diff --git a/.github/workflows/release-nightly.yml b/.github/workflows/release-nightly.yml deleted file mode 100644 index d16e226e54..0000000000 --- a/.github/workflows/release-nightly.yml +++ /dev/null @@ -1,75 +0,0 @@ -name: Release (golang.go-nightly) - -# Daily release on 15:00 UTC, monday-thursday. -# Or, trigger with workflow dispatch event. -on: - schedule: - - cron: "0 15 * * MON-THU" # 15 UTC, monday-thursday daily - workflow_dispatch: - -jobs: - release: - if: github.ref == 'refs/heads/master' && github.repository == 'golang/vscode-go' - - name: Release Nightly - runs-on: ubuntu-latest - environment: nightly - timeout-minutes: 20 - - steps: - - name: Clone repository - uses: actions/checkout@v4 - - - name: Setup Node - uses: actions/setup-node@v4 - with: - node-version: '18' - cache: 'npm' - - - name: Setup Go - uses: actions/setup-go@v4 - with: - go-version: '1.21' - check-latest: true - cache: true - - - name: Install dependencies - run: npm ci - - - name: Prepare Release - run: build/all.bash prepare_nightly - - - name: Version - run: | - echo "VSCODE_GO_VERSION=$(jq .version package.json | tr -d '"')" >> $GITHUB_ENV - - - name: Package Extension - run: npx vsce package -o "./go-nightly-${{ env.VSCODE_GO_VERSION }}.vsix" - - - name: Compile - run: npm run vscode:prepublish - - # TODO: use prerelease versions of tools (how? or master?) - - - name: Install Go tools (Modules mode) - run: | - go run ./tools/installtools/main.go - env: - GO111MODULE: on - EXT: "${{ matrix.os == 'windows-latest' && '.exe' || ''}}" - - - name: Run unit tests - run: npm run unit-test - - - name: Run tests - run: xvfb-run -a npm run test - env: - CODE_VERSION: 'insiders' - VSCODEGO_BEFORE_RELEASE_TESTS: true - - - name: Publish - if: github.ref == 'refs/heads/master' && github.repository == 'golang/vscode-go' - run: | - echo "publishing ${{ env.VSCODE_GO_VERSION }}" - ls *.vsix - npx vsce publish -i "./go-nightly-${{ env.VSCODE_GO_VERSION }}.vsix" -p "${{ secrets.VSCE_TOKEN }}" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index da3eaebf9b..0000000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,111 +0,0 @@ -name: Release (golang.go) - -# The new release workflow is triggered when a new tag on the release -# branch is pushed. -# -# Note: our canonical repository is in go.googlesource.com/vscode-go and tagging -# will be done in the canonical repository, and mirrored to the github repository. -# A typical workflow is: -# -# 1. A human operator creates a CL to merge the main dev branch to the 'release' branch. -# CI (GCB builder) will test the CL. -# 2. The CL is reviewed and merged. This triggers the "Long test workflow" (test-long.yml). -# 3. The human operator verifies the "Long test workflow" is green. -# Otherwise, fix (fix, cherry-pick, review, commit) on the 'release' branch. -# 4. When the 'release' branch reaches to the state ready for the release, -# the human operator will tag the commig from the canonical repository. -# (https://go-review.googlesource.com/admin/repos/vscode-go,tags) -# Stable versions should be in the format of 'vX.X.X' (e.g. v0.15.0) -# Release candidates should be in the format of 'vX.X.X-rc.X' (e.g. v0.15.0-rc.1) -# 5. The gopherbot will mirror the tag to the GitHub repo, and that push will trigger -# the 'Release (golang.go)' workflow specified in this file. -# - For stable version release (vX.X.X), check if the package.json has the matching version. -# - Packaging using 'vsce package' -# - Create a release in GitHub -# - Upload the vsix file as an asset of the release -# - For stable version release (vX.X.X), upload to the vscode market place - -on: - push: - tags: - - v* - -jobs: - release: - name: create release - runs-on: ubuntu-latest - if: github.repository == 'golang/vscode-go' - - steps: - - name: Clone repository - uses: actions/checkout@v4 - - - name: Setup Node - uses: actions/setup-node@v4 - with: - node-version: '18' - cache: 'npm' - - - name: get release version - id: release_version - run: | - TAGGED_VERSION="${GITHUB_REF/refs\/tags\/v/}" - - if [[ ! "${TAGGED_VERSION}" =~ ^[0-9]+\.[0-9]+\.[0-9]+.*$ ]]; then - echo "Invalid version tag '${TAGGED_VERSION}'" - exit 1 - fi - - echo "EXT_VERSION=${TAGGED_VERSION}" >> $GITHUB_ENV - WRITTEN_VERSION="$(cat package.json | jq '.version' -r)" - - if [[ "${TAGGED_VERSION}" == *"-"* ]]; then - if [[ ! "${TAGGED_VERSION}" == "${WRITTEN_VERSION}"-rc.* ]]; then - echo "Prerelease Tag and Version in package.json are not compatible: '${TAGGED_VERSION}' vs '${WRITTEN_VERSION}'" - exit 1 - fi - echo "EXT_ISPREVIEW=1" >> $GITHUB_ENV - else - if [[ "${TAGGED_VERSION}" != "${WRITTEN_VERSION}" ]]; then - echo "Release Tag and Version in package.json do not match: '${TAGGED_VERSION}' vs '${WRITTEN_VERSION}'" - exit 1 - fi - echo "EXT_ISPREVIEW=0" >> $GITHUB_ENV - fi - - - name: stamp version - run: | - cat package.json | jq --arg VER "${{ env.EXT_VERSION }}" '.version=$VER' > /tmp/package.json - cp /tmp/package.json ./package.json - npm ci - npm run vscode:prepublish - - - name: package extension - run: npx vsce package -o "./go-${{ env.EXT_VERSION }}.vsix" - - - name: create release - id: create_release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag_name: ${{ github.ref }} - release_name: Release ${{ env.EXT_VERSION }} - draft: false - prerelease: ${{env.EXT_ISPREVIEW == 1}} - - - name: upload release asset - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./go-${{ env.EXT_VERSION }}.vsix - asset_name: go-${{ env.EXT_VERSION }}.vsix - asset_content_type: application/zip - - - name: publish - if: env.EXT_ISPREVIEW != 1 && github.repository == 'golang/vscode-go' - run: npx vsce publish -i "./go-${{ env.EXT_VERSION }}.vsix" -p "${{ secrets.VSCE_TOKEN }}" - -# TODO: check if the commit is in green state. (test-long.yml results) diff --git a/.github/workflows/test-long-all.yml b/.github/workflows/test-long-all.yml index 3a5aca0fab..bee86cd0b8 100644 --- a/.github/workflows/test-long-all.yml +++ b/.github/workflows/test-long-all.yml @@ -28,6 +28,7 @@ jobs: with: node-version: '18' cache: 'npm' + cache-dependency-path: './extension/package-lock.json' - name: Setup Go uses: actions/setup-go@v4 @@ -38,29 +39,35 @@ jobs: - name: Install dependencies run: npm ci + working-directory: ./extension - name: Compile run: npm run vscode:prepublish + working-directory: ./extension - name: Install Go tools (Modules mode) run: | go version go run ./tools/installtools/main.go + working-directory: ./extension env: GO111MODULE: on EXT: "${{ matrix.os == 'windows-latest' && '.exe' || ''}}" - name: Run unit tests run: npm run unit-test + working-directory: ./extension - name: Run tests (Linux) run: xvfb-run -a npm run test + working-directory: ./extension if: ${{ matrix.os == 'ubuntu-latest' }} env: CODE_VERSION: ${{ matrix.version }} VSCODEGO_BEFORE_RELEASE_TESTS: true - name: Run tests (Windows/Mac) run: npm run test + working-directory: ./extension if: ${{ matrix.os != 'ubuntu-latest' }} env: CODE_VERSION: ${{ matrix.version }} @@ -68,4 +75,5 @@ jobs: - name: Lint check run: npm run lint + working-directory: ./extension if: ${{ matrix.os == 'ubuntu-latest' && matrix.version == 'stable' }} diff --git a/.github/workflows/test-long.yml b/.github/workflows/test-long.yml index d5b3d23710..aff6b13f26 100644 --- a/.github/workflows/test-long.yml +++ b/.github/workflows/test-long.yml @@ -27,6 +27,7 @@ jobs: with: node-version: '18' cache: 'npm' + cache-dependency-path: './extension/package-lock.json' - name: Setup Go uses: actions/setup-go@v4 @@ -37,32 +38,39 @@ jobs: - name: Install dependencies run: npm ci + working-directory: ./extension - name: Compile run: npm run vscode:prepublish + working-directory: ./extension - name: Install Go tools (Modules mode) run: | go version go run ./tools/installtools/main.go + working-directory: ./extension env: GO111MODULE: on EXT: "${{ matrix.os == 'windows-latest' && '.exe' || ''}}" - name: Run unit tests run: npm run unit-test + working-directory: ./extension - name: Run tests (Linux) run: xvfb-run -a npm run test + working-directory: ./extension if: ${{ matrix.os == 'ubuntu-latest' }} env: CODE_VERSION: ${{ matrix.version }} - name: Run tests (Windows/Mac) run: npm run test + working-directory: ./extension if: ${{ matrix.os != 'ubuntu-latest' }} env: CODE_VERSION: ${{ matrix.version }} - name: Lint check run: npm run lint + working-directory: ./extension if: ${{ matrix.os == 'ubuntu-latest' && matrix.version == 'stable' }} diff --git a/.github/workflows/test-smoke.yml b/.github/workflows/test-smoke.yml index b7f79093e4..c5f78fc876 100644 --- a/.github/workflows/test-smoke.yml +++ b/.github/workflows/test-smoke.yml @@ -26,6 +26,7 @@ jobs: with: node-version: '18' cache: 'npm' + cache-dependency-path: './extension/package-lock.json' - name: Setup Go uses: actions/setup-go@v4 @@ -36,32 +37,39 @@ jobs: - name: Install dependencies run: npm ci + working-directory: ./extension - name: Compile run: npm run vscode:prepublish + working-directory: ./extension - name: Install Go tools (Modules mode) run: | go version go run ./tools/installtools/main.go + working-directory: ./extension env: GO111MODULE: on EXT: "${{ matrix.os == 'windows-latest' && '.exe' || ''}}" - name: Run unit tests run: npm run unit-test + working-directory: ./extension - name: Run tests (Linux) run: xvfb-run -a npm run test + working-directory: ./extension if: ${{ matrix.os == 'ubuntu-latest' }} env: CODE_VERSION: ${{ matrix.version }} - name: Run tests (Windows/Mac) run: npm run test + working-directory: ./extension if: ${{ matrix.os != 'ubuntu-latest' }} env: CODE_VERSION: ${{ matrix.version }} - name: Lint check run: npm run lint + working-directory: ./extension if: ${{ matrix.os == 'ubuntu-latest' && matrix.version == 'stable' }} diff --git a/.github/workflows/wiki.yml b/.github/workflows/wiki.yml index 80fe35753a..b213ec5b87 100644 --- a/.github/workflows/wiki.yml +++ b/.github/workflows/wiki.yml @@ -43,7 +43,7 @@ jobs: - name: Push to wiki run: | cd vscode-go - go run ./tools/docs2wiki -w ./docs + go run -C extension ./tools/docs2wiki -w ../docs cd .. cd wiki rm -r ./* && cp -r ../vscode-go/docs/* . diff --git a/.gitignore b/.gitignore index e512f321a6..ea68ca1ecb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ +bin/ out/ dist/ node_modules/ .vscode-test/ .DS_Store -.user-data-dir-test/ \ No newline at end of file +.user-data-dir-test/ diff --git a/.prettierrc.js b/.prettierrc.js deleted file mode 100644 index ff15483392..0000000000 --- a/.prettierrc.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - ...require('gts/.prettierrc.json') -} diff --git a/.vscode/launch.json b/.vscode/launch.json index e6bfc34d40..e560dc7364 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -6,8 +6,8 @@ "type": "go", "request": "launch", "mode": "debug", - "program": "${workspaceFolder}/tools/generate.go", - "cwd": "${workspaceFolder}" + "program": "${workspaceFolder}/extension/tools/generate.go", + "cwd": "${workspaceFolder}/extension" }, { "name": "Launch Extension", @@ -20,7 +20,7 @@ "--disable-extensions" ], "outFiles": [ - "${workspaceFolder}/dist/**/*.js" + "${workspaceFolder}/extension/dist/**/*.js" ], "sourceMaps": true, "smartStep": true, @@ -28,21 +28,7 @@ "env": { "VSCODE_GO_IN_TEST": "" // Enable code }, - }, - { - "name": "Launch as server", - "type": "node", - "request": "launch", - "program": "${workspaceFolder}/dist/debugAdapter.js", - "args": [ - "--server=4711" - ], - "outFiles": [ - "${workspaceFolder}/dist/**/*.js" - ], - "sourceMaps": true, - "smartStep": true, - "preLaunchTask": "npm: bundle-dev" + "cwd": "${workspaceFolder}/extension" }, { "name": "Launch Extension Tests", @@ -53,9 +39,9 @@ "args": [ "--disable-extensions", "--profile-temp", - "--extensionDevelopmentPath=${workspaceFolder}", - "--extensionTestsPath=${workspaceFolder}/out/test/integration/index", - "--user-data-dir=${workspaceFolder}/.user-data-dir-test", + "--extensionDevelopmentPath=${workspaceFolder}/extension", + "--extensionTestsPath=${workspaceFolder}/extension/out/test/integration/index", + "--user-data-dir=${workspaceFolder}/extension/.user-data-dir-test", "--timeout", "999999" ], @@ -63,9 +49,13 @@ "VSCODE_GO_IN_TEST": "1", // Disable code that shouldn't be used in test "MOCHA_TIMEOUT": "999999", }, + "outFiles": [ + "${workspaceFolder}/extension/out/**/*.js" + ], "sourceMaps": true, "smartStep": true, "preLaunchTask": "npm: watch", + "cwd": "${workspaceFolder}/extension" }, { "name": "Launch Extension Tests with Gopls", @@ -76,41 +66,37 @@ "args": [ "--disable-extensions", "--profile-temp", - "--extensionDevelopmentPath=${workspaceFolder}", - "--extensionTestsPath=${workspaceFolder}/out/test/gopls/index", - "--user-data-dir=${workspaceFolder}/.user-data-dir-test", + "--extensionDevelopmentPath=${workspaceFolder}/extension", + "--extensionTestsPath=${workspaceFolder}/extension/out/test/gopls/index", + "--user-data-dir=${workspaceFolder}/extension/.user-data-dir-test", "--timeout", "999999", ], "env": { "VSCODE_GO_IN_TEST": "1" // Disable code that shouldn't be used in test }, + "outFiles": [ + "${workspaceFolder}/extension/out/**/*.js" + ], "sourceMaps": true, "preLaunchTask": "npm: watch", + "cwd": "${workspaceFolder}/extension" }, { "type": "node", "request": "launch", "name": "Launch Unit Tests", - "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha", + "program": "${workspaceFolder}/extension/node_modules/mocha/bin/_mocha", "args": [ "-u", "tdd", "--timeout", "5000", "--colors", - "${workspaceFolder}/out/test/unit" + "${workspaceFolder}/extension/out/test/unit" ], "internalConsoleOptions": "openOnSessionStart", "preLaunchTask": "npm: watch", + "cwd": "${workspaceFolder}/extension" }, - ], - "compounds": [ - { - "name": "Extension + Debug server", - "configurations": [ - "Launch Extension", - "Launch as server" - ] - } ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index 5fd2c96d96..2e93ae088d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,14 +1,19 @@ // Place your settings in this file to overwrite default and user settings. { "files.exclude": { - "out": true, - "typings": false + "**/out": true, + "**/.vscode-test": true, + "**/.user-data-dir-test": true, }, "search.exclude": { - "**/node_modules": true, - "**/bower_components": true, - "out/": true + "node_modules": true, + "out": true, + "dist": true, + ".vscode-test": true, + ".user-data-dir-test": true, }, "editor.insertSpaces": false, - "typescript.tsdk": "node_modules\\typescript\\lib", + "[yaml]": { + "editor.autoIndent": "advanced" + }, } diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 801a598c32..00d68da5e6 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -33,10 +33,10 @@ "tasks": [ { "type": "typescript", - "tsconfig": "./tsconfig.build.json", + "tsconfig": "extension/tsconfig.json", "problemMatcher": [ "$tsc" - ] + ], }, { "type": "npm", @@ -50,6 +50,7 @@ "kind": "build", "isDefault": true }, + "path": "extension" }, { "type": "npm", @@ -59,13 +60,15 @@ "isBackground": true, "presentation": { "reveal": "never" - } + }, + "path": "extension" }, { "type": "npm", "script": "bundle-dev", "group": "build", "problemMatcher": "$esbuild", + "path": "extension" } ] } diff --git a/README.md b/README.md index 5239f24ab1..15ca3d47e6 100644 --- a/README.md +++ b/README.md @@ -23,21 +23,17 @@ extension fits your needs and enhances your development experience. 1. Install the [VS Code Go extension]. -1. Open any directory or workspace containing Go code to automatically activate - the extension. The +1. Open any Go file or go.mod file to automatically activate the extension. The [Go status bar](https://github.com/golang/vscode-go/wiki/ui) appears in the - bottom left corner of the window and displays your Go version. + bottom right corner of the window and displays your Go version. -1. The extension depends on `go`, `gopls`, `dlv` and other optional tools. If - any of the dependencies are missing, the ⚠️ `Analysis Tools Missing` warning - is displayed. Click on the warning to download dependencies. - - See the - [tools documentation](https://github.com/golang/vscode-go/wiki/tools) for a - complete list of tools the extension depends on. +1. The extension depends on `go`, `gopls` (the Go language server), and optional + tools depending on your settings. If `gopls` is missing, the extension will + try to install it. The :zap: sign next to the Go version indicates + the language server is running, and you are ready to go.

- +
(Install Missing Tools)

@@ -52,7 +48,8 @@ You are ready to Go :-)    πŸŽ‰πŸŽ‰πŸŽ‰ and [advanced topics](https://github.com/golang/vscode-go/wiki/advanced) to customize the extension. * View the [tools documentation](https://github.com/golang/vscode-go/wiki/tools) - for a complete list of tools the VS Code Go extension depends on. + for a complete list of tools the VS Code Go extension depends on. You can + install additional tools and update them by using "Go: Install/Update Tools". * Solve issues with the [general troubleshooting](https://github.com/golang/vscode-go/wiki/troubleshooting) and [debugging troubleshooting](https://github.com/golang/vscode-go/wiki/debugging#troubleshooting) @@ -138,7 +135,7 @@ nightly build of this extension. Learn how to install it in by reading the VS Code Go extension relies on the [Go Telemetry](https://telemetry.go.dev) to learn insights about the performance and stability of the extension and the -language server (`gopls``). +language server (`gopls`). **Go Telemetry data uploading is disabled by default** and can be enabled with the following command: diff --git a/build/Dockerfile b/build/Dockerfile index c358d4534e..b1cac5a69a 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -6,7 +6,7 @@ ENV GOBIN /gobin # Install other Go tools tests depend on RUN mkdir -p /scratch/installtools -ADD tools/installtools/main.go /scratch/installtools/main.go +ADD extension/tools/installtools/main.go /scratch/installtools/main.go RUN go run /scratch/installtools/main.go FROM node:latest @@ -25,8 +25,17 @@ ENV DEBIAN_FRONTEND noninteractive # TODO(hyangah): remove this when the platform works with ipv6. ENV NODE_OPTIONS --dns-result-order=ipv4first +# Install xvfb jq RUN apt-get -qq update && apt-get install -qq -y libnss3 libgtk-3-dev libxss1 libasound2 xvfb libsecret-1-0 jq > /dev/null +# Install gh https://stackoverflow.com/a/69477930 +RUN apt update && apt install -y \ + curl \ + gpg +RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | gpg --dearmor -o /usr/share/keyrings/githubcli-archive-keyring.gpg; +RUN echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null; +RUN apt update && apt install -y gh; + USER node WORKDIR /workspace ENTRYPOINT ["build/all.bash"] \ No newline at end of file diff --git a/build/README.md b/build/README.md new file mode 100644 index 0000000000..a8b034efbe --- /dev/null +++ b/build/README.md @@ -0,0 +1,9 @@ +### Release process + +The golang.go-nightly extension is released daily during weekdays, based on the latest commit to the master branch. + +(Note: the release process is currently in GH workflow. We are in process of moving it to a GCB workflow.) + +* Dockerfile: defines the image containing tools and environments needed to build and test the extension. (e.g. Go, Node.js, jq, etc.) +* build-ci-image.yaml: defines the workflow to build the container image used for extension testing and releasing. +* release-nightly.yaml: defines the workflow that builds the nightly extension and runs tests. The built extension is pushed only after all tests pass. diff --git a/build/all.bash b/build/all.bash index cc9e72c901..f9f3ce83c0 100755 --- a/build/all.bash +++ b/build/all.bash @@ -1,4 +1,5 @@ -#!/bin/bash -e +#!/usr/bin/env bash +set -e # Copyright (C) Microsoft Corporation. All rights reserved. # Modification copyright 2020 The Go Authors. All rights reserved. @@ -36,32 +37,39 @@ setup_virtual_display() { go_binaries_info() { echo "**** Go version ****" go version -} - -run_test() { df -h | grep shm +} +run_doc_test() { echo "**** Run settings generator ****" - go run ./tools/generate.go -w=false -gopls=true - - echo "**** Run Go tests ****" - go test ./... + go run -C extension ./tools/generate.go -w=false -gopls=true +} +run_test() { + pushd . + cd "$(root_dir)/extension" echo "**** Test build ****" npm ci npm run compile + echo "**** Run Go tests ****" + go test ./... + echo "**** Run test ****" npm run unit-test npm test --silent + popd +} +run_lint() { + pushd . + cd "$(root_dir)/extension" + echo "**** Run lint ****" npm run lint + popd } - run_test_in_docker() { - which npm && npm version || echo "no npm" - which go && go version || echo "no go" echo "**** Building the docker image ***" docker build -t vscode-test-env ${GOVERSION:+ --build-arg GOVERSION="${GOVERSION}"} -f ./build/Dockerfile . @@ -75,10 +83,9 @@ prepare_nightly() { # on 2020/01/05 10:00 local VER=`git log -1 --format=%cd --date="format:%Y.%-m.%-d%H"` local COMMIT=`git log -1 --format=%H` - echo "**** Preparing nightly release : $VER ***" - + echo "**** Preparing nightly release : ${VER} (${COMMIT}) ***" # Update package.json - (cat package.json | jq --arg VER "${VER}" ' + (cat extension/package.json | jq --arg VER "${VER}" ' .version=$VER | .preview=true | .name="go-nightly" | @@ -86,18 +93,18 @@ prepare_nightly() { .publisher="golang" | .description="Rich Go language support for Visual Studio Code (Nightly)" | .contributes.configuration.properties."go.delveConfig".properties.hideSystemGoroutines.default=true -') > /tmp/package.json && mv /tmp/package.json package.json +') > /tmp/package.json && cp /tmp/package.json extension/package.json # Replace CHANGELOG.md with CHANGELOG.md + Release commit info. - printf "**Release ${VER} @ ${COMMIT}** \n\n" | cat - CHANGELOG.md > /tmp/CHANGELOG.md.new && mv /tmp/CHANGELOG.md.new CHANGELOG.md + printf "**Release ${VER} @ ${COMMIT}** \n\n" | cat - extension/CHANGELOG.md > /tmp/CHANGELOG.md.new && mv /tmp/CHANGELOG.md.new extension/CHANGELOG.md # Replace the heading of README.md with the heading for Go Nightly. sed '/^# Go for Visual Studio Code$/d' README.md | cat build/nightly/README.md - > /tmp/README.md.new && mv /tmp/README.md.new README.md # Replace src/const.ts with build/nightly/const.ts. - cp build/nightly/const.ts src/const.ts + cp build/nightly/const.ts extension/src/const.ts } main() { - cd "$(root_dir)" # always run from the script root. + cd "$(root_dir)" # always start to run from the extension source root. case "$1" in "help"|"-h"|"--help") usage @@ -113,11 +120,17 @@ main() { "ci") go_binaries_info setup_virtual_display + run_doc_test run_test + run_lint ;; "prepare_nightly") prepare_nightly ;; + "test_nightly") + setup_virtual_display + run_test + ;; *) usage exit 2 diff --git a/build/build-ci-image.yaml b/build/build-ci-image.yaml new file mode 100644 index 0000000000..f1c3bf3eee --- /dev/null +++ b/build/build-ci-image.yaml @@ -0,0 +1,14 @@ +# Usage: gcloud builds submit --config build/build-ci-image.yaml . +steps: +- name: 'gcr.io/cloud-builders/docker' + entrypoint: 'bash' + args: ['-c', 'docker pull us-docker.pkg.dev/$PROJECT_ID/vscode-go-docker-repo/ci-image:latest || exit 0'] +- name: 'gcr.io/cloud-builders/docker' + # https://cloud.google.com/build/docs/optimize-builds/speeding-up-builds + args: [ + 'build', + '-t', 'us-docker.pkg.dev/$PROJECT_ID/vscode-go-docker-repo/ci-image:latest', + '--cache-from', 'us-docker.pkg.dev/$PROJECT_ID/vscode-go-docker-repo/ci-image:latest', + '-f', 'build/Dockerfile', + '.'] +images: ['us-docker.pkg.dev/$PROJECT_ID/vscode-go-docker-repo/ci-image'] \ No newline at end of file diff --git a/build/release-nightly.yaml b/build/release-nightly.yaml index 10fd4fc9fc..ca6612616b 100644 --- a/build/release-nightly.yaml +++ b/build/release-nightly.yaml @@ -1,15 +1,84 @@ +# This workflow will be triggered daily. +# For local testing, run: +# gcloud builds submit --config release-nightly.yaml --no-source +# This will check out the vscode-go repo master branch and run the build from it. steps: -# TODO: check build/test status -# -# Install dependencies -- name: node - entrypoint: npm - args: ['ci'] -# Build .vsix -- name: node - entrypoint: npm - args: ['run', 'package'] + # TODO: check build/test status + - name: gcr.io/cloud-builders/git + args: + - clone + - '--branch=master' + - '--depth=1' + - 'https://go.googlesource.com/vscode-go' + - vscode-go + id: clone vscode-go repo + - name: gcr.io/cloud-builders/docker + args: + - '-R' + - '1000:1000' + - /workspace + - /builder/home + dir: / + id: adjust file permissions + entrypoint: chown + - name: us-docker.pkg.dev/$PROJECT_ID/vscode-go-docker-repo/ci-image + args: + - ci + dir: vscode-go/extension + id: install npm dependencies + entrypoint: npm + - name: us-docker.pkg.dev/$PROJECT_ID/vscode-go-docker-repo/ci-image + args: + - build/all.bash + - prepare_nightly + dir: vscode-go + id: prepare nightly release + entrypoint: bash + - name: us-docker.pkg.dev/$PROJECT_ID/vscode-go-docker-repo/ci-image + args: + - run + - package + dir: vscode-go/extension + id: build .vsix + entrypoint: npm + - name: ubuntu + args: + - '-c' + - ls -1 go-nightly-*.vsix | tee /workspace/vsix_name.txt + dir: vscode-go/extension + id: store the vsix file name + entrypoint: bash + - name: us-docker.pkg.dev/$PROJECT_ID/vscode-go-docker-repo/ci-image + env: + - IN_RELEASE_WORKFLOW=true + args: + - build/all.bash + - test_nightly + dir: vscode-go + id: run tests + entrypoint: bash + - name: us-docker.pkg.dev/$PROJECT_ID/vscode-go-docker-repo/ci-image + args: + - '-c' + - > + npx vsce publish -i $(cat /workspace/vsix_name.txt) -p $$VSCE_PAT + --baseContentUrl=https://github.com/golang/vscode-go + --baseImagesUrl=https://github.com/golang/vscode-go + dir: vscode-go/extension + id: publish nightly extension + entrypoint: bash + secretEnv: + - VSCE_PAT +timeout: 1800s +options: + machineType: E2_HIGHCPU_8 + substitutionOption: ALLOW_LOOSE artifacts: objects: - location: 'gs://$PROJECT_ID/nightly/$BUILD_ID' - paths: ['*.vsix'] \ No newline at end of file + location: 'gs://$PROJECT_ID/nightly' + paths: + - vscode-go/extension/*.vsix +availableSecrets: + secretManager: + - versionName: projects/$PROJECT_ID/secrets/$_VSCE_TOKEN/versions/latest + env: VSCE_PAT diff --git a/build/release.yaml b/build/release.yaml new file mode 100644 index 0000000000..2305d6862f --- /dev/null +++ b/build/release.yaml @@ -0,0 +1,65 @@ +# This workflow will be triggered when a new release tag (of the form vX.Y.Z) is +# pushed to the vscode-go repo.) +# For local testing, run: +# gcloud builds submit --config release.yaml --no-source --substitutions=_TAG_NAME="v0.40.1-rc.1",_GITHUB_TOKEN="alias1",_VSCE_TOKEN="alias2" +# +# WARNING: this will publish the extension. +# +# This will check out the vscode-go repo on the specified tag, build the extension, +# and publish it to the VS Code Marketplace and the GitHub Releases page if not published already. +steps: + # TODO: check build/test status + # TODO: configure failure notification https://cloud.google.com/build/docs/configuring-notifications/notifiers + - name: gcr.io/cloud-builders/git + args: + - clone + - '--branch=$TAG_NAME' + - '--single-branch' + - '--depth=1' + - 'https://go.googlesource.com/vscode-go' + - vscode-go + id: clone vscode-go repo + - name: gcr.io/cloud-builders/docker + args: + - '-R' + - '1000:1000' + - /workspace + - /builder/home + dir: / + id: adjust file permissions + entrypoint: chown + - name: us-docker.pkg.dev/$PROJECT_ID/vscode-go-docker-repo/ci-image + args: + - ci + dir: vscode-go/extension + id: install npm dependencies + entrypoint: npm + - name: us-docker.pkg.dev/$PROJECT_ID/vscode-go-docker-repo/ci-image + args: + - -c + - | + go run -C extension tools/release/release.go package && + go run -C extension tools/release/release.go publish + dir: vscode-go + id: package and publish the extension + entrypoint: bash + env: + - 'TAG_NAME=$TAG_NAME' + - 'COMMIT_SHA=$COMMIT_SHA' + secretEnv: + - VSCE_PAT + - GITHUB_TOKEN +timeout: 1800s +options: + substitutionOption: ALLOW_LOOSE +artifacts: + objects: + location: 'gs://$PROJECT_ID/releases/$TAG_NAME' + paths: + - vscode-go/extension/*.vsix +availableSecrets: + secretManager: + - versionName: projects/$PROJECT_ID/secrets/$_VSCE_TOKEN/versions/latest + env: VSCE_PAT + - versionName: projects/$PROJECT_ID/secrets/$_GITHUB_TOKEN/versions/latest + env: GITHUB_TOKEN diff --git a/doc.go b/doc.go new file mode 100644 index 0000000000..40621eb98b --- /dev/null +++ b/doc.go @@ -0,0 +1,8 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// VS Code Go is a Go extension for Visual Studio Code. +package vscodego + +// By adding this doc, pkg.go.dev will render README.md. diff --git a/docs/contributing.md b/docs/contributing.md index af6c65eb0d..e449c538f3 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -58,7 +58,7 @@ The debugging feature documentation has a dedicated section for tips for develop ```bash git clone https://go.googlesource.com/vscode-go - cd vscode-go + cd vscode-go/extension npm ci code . ``` @@ -79,10 +79,8 @@ If you make subsequent edits in the codebase, you can reload (`Ctrl+R` or `⌘+R ## Test -**note**: Unfortunately, VS Code test framework inherits your user settings when running tests [Issue 43](https://github.com/golang/vscode-go/issues/43). Make sure VS Code user settings do not contain any go related configuration, except `go.gopath` or `go.toolsGopath` in case you installed the tools for testing in a different `GOPATH`. - - 1. `export GOPATH=/path/to/gopath/for/test` +2. `cd extension` -- most extension development work is done in the `extension` directory. 2. `go run tools/installtools/main.go` -- this will install all tools in the `GOPATH/bin` built from master/main. 3. There are currently two different types of tests in this repo: - `npm run unit-test`: this runs unit tests defined in `test/unit`. They are light-weight tests that don't require `vscode` APIs. @@ -107,10 +105,7 @@ You can supply environment variables (e.g. `MOCHA_GREP`) by modifying the launch When you want to filter tests while debugging, utilize the `MOCAH_GREP` environment variable discussed previously - i.e., set the environment variable in the `env` property of the launch configuration. -#### (3) Another way to run all tests: -`build/all.bash test` is the script used by a CI (Linux). - -#### (4) Using different versions of tools. +#### (3) Using different versions of tools. The tests will pick tools found from `GOPATH/bin` first. So, install the versions you want there. ## Running/Debugging the Extension @@ -156,10 +151,9 @@ Or, if you use vscode for gopls development, you can configure `launch.json` of After making changes to the extension, you may want to test it end-to-end instead of running it in debug mode. To do this, you can sideload the extension. -1. Install the [vsce](https://code.visualstudio.com/api/working-with-extensions/publishing-extension#vsce) tool for packaging extensions (`npm install -g vsce`). -2. `cd` into your `vscode-go` directory. +1. `cd` into the `extension` directory. 3. Install all dependencies by running `npm ci`. -4. Run `vsce package`. This will generate a file with a `.vsix` extension in your current directory. +4. Run `npx vsce package`. This will generate a file with a `.vsix` extension in your current directory. ```bash npm install -g vsce @@ -194,10 +188,7 @@ you or a fellow contributor assigns the `Run-TryBot=+1` label in Gerrit, the tes for running Dockerized tests. `Kokoro` will post the result as a comment, and add its `TryBot-Result` vote after each test run completes. -To force a re-run of the Kokoro CI, - * Remove `TryBot-Result` vote (hover over the label, and click the trashcan icon). - * Reply in Gerrit with the comment "kokoro rerun". Make sure to keep the `Run-TryBot` +1 vote. - +To force a re-run of the Kokoro CI, add comment `kokoro rerun` to the CL. [#vscode-dev]: https://gophers.slack.com/archives/CUWGEKH5Z [Gophers Slack]: https://invite.slack.golangbridge.org/ diff --git a/docs/debugging-legacy.md b/docs/debugging-legacy.md index 6af77db32b..734b6c5e16 100644 --- a/docs/debugging-legacy.md +++ b/docs/debugging-legacy.md @@ -2,7 +2,7 @@ The Go extension historically used a small adapter program to work with the Go debugger, [Delve]. The extension transitioned to communicate with [Delve] directly but there are still cases you may -need to use the legacy debug adapter (e.g. remote debugging). This document explains how to use the +need to use the legacy debug adapter. This document explains how to use the ***legacy*** debug adapter. @@ -45,8 +45,6 @@ To opt in to use the legacy debug adapter (`legacy`) by default, add the followi ``` If you want to use the legacy mode for only a subset of your launch configurations, you can use [the `debugAdapter` attribute](#launchjson-attributes) to switch between `"dlv-dap"` and `"legacy"` mode. -For [Remote Debugging](#remote-debugging) (launch configuration with `"mode": "remote"` attribute), -the extension will use the `"legacy"` mode by default, so setting this attribute won't be necessary. Throughout this document, we assume that you opted in to use the legacy debug adapter. For debugging using the new debug adapter (default, `"dlv-dap"` mode), please see the documentation about [Debugging](https://github.com/golang/vscode-go/tree/master/docs/debugging-legacy.md). diff --git a/docs/debugging.md b/docs/debugging.md index 643e9a3573..044519f458 100644 --- a/docs/debugging.md +++ b/docs/debugging.md @@ -6,26 +6,8 @@ activities using [VS Code’s Debugging UI](https://code.visualstudio.com/docs/editor/debugging). These debugging features are possible by using -[Delve](https://github.com/go-delve/delve), the Go debugger. - -Previously, the Go extension communicated with Delve through a custom debug -adaptor program (`legacy` mode). Since -[`Delve`'s native debug adapter implementation](https://github.com/go-delve/delve/tree/master/service/dap) -is available, the Go extension is transitioning to deprecate the legacy debug -adapter in favor of direct communication with Delve via -[DAP](https://microsoft.github.io/debug-adapter-protocol/overview). - - - πŸ“£ **We are happy to announce that the new _`dlv-dap`_ mode of Delve - integration is enabled for _local_ _debugging_ by default. For - [_remote_ _debugging_](#remote-debugging) it is the default in - [Go Nightly](nightly.md) and is available with stable builds on demand with - `"debugAdapter": "dlv-dap"` attribute in `launch.json` or `settings.json`!** - -Many features and settings described in this document may be available only with -the new `dlv-dap` mode. For troubleshooting and configuring the legacy debug -adapter, see -[the legacy debug adapter documentation](https://github.com/golang/vscode-go/tree/master/docs/debugging-legacy.md). +[Delve](https://github.com/go-delve/delve), the Go debugger, and its +[native debug adapter implementation](https://github.com/go-delve/delve/tree/master/service/dap). ## Get started @@ -82,7 +64,9 @@ from the tree head. ### Switch to legacy debug adapter -Note: The extension still uses the legacy debug adapter for remote debugging. +Previously, the Go extension communicated with Delve through a custom debug +adaptor program (aka `legacy` mode). This legacy adapter is no longer maintained +and will be removed by the end of 2024 H2. If you need to use the legacy debug adapter for local debugging (`legacy` mode) by default, add the following in your VSCode settings. @@ -93,9 +77,6 @@ by default, add the following in your VSCode settings. } ``` -When `mode` is set to `remote` you must explicitly set `debugAdapter` to -`dlv-dap` to override the legacy adapter default. - If you want to switch to `legacy` for only a subset of your launch configurations, you can use [the `debugAdapter` attribute](#launchjson-attributes) to switch between @@ -809,8 +790,8 @@ with a running target. The [headless dlv server](https://github.com/go-delve/delve/tree/master/Documentation/api) -can now be used with both `"debugAdapter": "legacy"` (default value) and -`"debugAdapter": "dlv-dap"` (with Delve v1.7.3 or newer) as well as Delve's +can now be used with both `"debugAdapter": "dlv-dap"` (default) and +`"debugAdapter": "legacy"` (with Delve v1.7.3 or newer) as well as Delve's [command-line interface](https://github.com/go-delve/delve/tree/master/Documentation/cli) via `dlv connect`. The `--accept-multiclient` flag makes this a multi-use server that persists on `Disconnect` from a client and allows repeated connections from @@ -837,7 +818,6 @@ Connect to it with a remote attach configuration in your `launch.json`: { "name": "Connect to external session", "type": "go", - "debugAdapter": "dlv-dap", // `legacy` by default "request": "attach", "mode": "remote", "port": 12345, diff --git a/docs/features.md b/docs/features.md index a969315afd..08bbe02e19 100644 --- a/docs/features.md +++ b/docs/features.md @@ -248,9 +248,11 @@ Easily generate unit tests for your project by running one of the [`Go: Generate ### Fill struct literals -Use the [`Go: Fill struct`](commands.md#fill-struct) command to automatically fill a struct literal with its default values. +Use the [Code Action](https://code.visualstudio.com/docs/editor/refactoring#_code-actions-quick-fixes-and-refactorings) to automatically fill a struct literal with its default values. The Go language server provides this capability as a `refactor.rewrite` type code action. -
Fill struct literals
+
Fill struct literals
+ + **Note**: The old "Go: Fill struct" command was removed in v0.40.0 in favor of the Code Action. ## Diagnostics diff --git a/docs/go.mod b/docs/go.mod new file mode 100644 index 0000000000..0e86589558 --- /dev/null +++ b/docs/go.mod @@ -0,0 +1,3 @@ +module github.com/golang/vscode-go/docs + +go 1.21 diff --git a/docs/images/fillstruct.png b/docs/images/fillstruct.png new file mode 100644 index 0000000000..dc7233a329 Binary files /dev/null and b/docs/images/fillstruct.png differ diff --git a/docs/images/fillstructliterals.gif b/docs/images/fillstructliterals.gif deleted file mode 100644 index 9ea7fc2332..0000000000 Binary files a/docs/images/fillstructliterals.gif and /dev/null differ diff --git a/docs/images/gettingstarted.gif b/docs/images/gettingstarted.gif new file mode 100644 index 0000000000..4f066bd848 Binary files /dev/null and b/docs/images/gettingstarted.gif differ diff --git a/docs/images/goexplorer.png b/docs/images/goexplorer.png new file mode 100644 index 0000000000..3a08deb53c Binary files /dev/null and b/docs/images/goexplorer.png differ diff --git a/docs/images/gopls.png b/docs/images/gopls.png deleted file mode 100644 index ea8ab07291..0000000000 Binary files a/docs/images/gopls.png and /dev/null differ diff --git a/docs/images/gostatusbar.png b/docs/images/gostatusbar.png new file mode 100644 index 0000000000..94a0b8c48f Binary files /dev/null and b/docs/images/gostatusbar.png differ diff --git a/docs/images/languagestatusbar.png b/docs/images/languagestatusbar.png new file mode 100644 index 0000000000..39e5b42b0d Binary files /dev/null and b/docs/images/languagestatusbar.png differ diff --git a/docs/images/selectGoVersion.png b/docs/images/selectGoVersion.png deleted file mode 100644 index 85320dfb93..0000000000 Binary files a/docs/images/selectGoVersion.png and /dev/null differ diff --git a/docs/images/statusbarmenu.png b/docs/images/statusbarmenu.png deleted file mode 100644 index ae9d65a991..0000000000 Binary files a/docs/images/statusbarmenu.png and /dev/null differ diff --git a/docs/settings.md b/docs/settings.md index a9a6a63550..468bfb3a44 100644 --- a/docs/settings.md +++ b/docs/settings.md @@ -345,12 +345,10 @@ Specifies Lint tool name.
Allowed Options: `staticcheck`, `golint`, `golangci-lint`, `revive` Default: `"staticcheck"` -### `go.logging.level` +### `go.logging.level (deprecated)` -The logging level the extension logs at, defaults to 'error'
-Allowed Options: `off`, `error`, `info`, `verbose` +This setting is deprecated. Use 'Developer: Set Log Level...' command to control logging level instead. -Default: `"error"` ### `go.playground` The flags configured here will be passed through to command `goplay` @@ -723,7 +721,7 @@ Example Usage: ... "analyses": { "unreachable": false, // Disable the unreachable analyzer. - "unusedparams": true // Enable the unusedparams analyzer. + "unusedvariable": true // Enable the unusedvariable analyzer. } ... ``` @@ -748,7 +746,6 @@ Example Usage: | `errorsas` | report passing non-pointer or non-error values to errors.As
The errorsas analysis reports calls to errors.As where the type of the second argument is not a pointer to a type implementing error.
Default: `true` | | `fieldalignment` | find structs that would use less memory if their fields were sorted
This analyzer find structs that can be rearranged to use less memory, and provides a suggested edit with the most compact order.
Note that there are two different diagnostics reported. One checks struct size, and the other reports "pointer bytes" used. Pointer bytes is how many bytes of the object that the garbage collector has to potentially scan for pointers, for example:
struct { uint32; string }

have 16 pointer bytes because the garbage collector has to scan up through the string's inner pointer.
struct { string; *uint32 }

has 24 pointer bytes because it has to scan further through the *uint32.
struct { string; uint32 }

has 8 because it can stop immediately after the string pointer.
Be aware that the most compact order is not always the most efficient. In rare cases it may cause two variables each updated by its own goroutine to occupy the same CPU cache line, inducing a form of memory contention known as "false sharing" that slows down both goroutines.

Default: `false` | | `fillreturns` | suggest fixes for errors due to an incorrect number of return values
This checker provides suggested fixes for type errors of the type "wrong number of return values (want %d, got %d)". For example:
func m() (int, string, *bool, error) {
return
}

will turn into
func m() (int, string, *bool, error) {
return 0, "", nil, nil
}

This functionality is similar to https://github.com/sqs/goreturns.
Default: `true` | -| `fillstruct` | note incomplete struct initializations
This analyzer provides diagnostics for any struct literals that do not have any fields initialized. Because the suggested fix for this analysis is expensive to compute, callers should compute it separately, using the SuggestedFix function below.

Default: `true` | | `httpresponse` | check for mistakes using HTTP responses
A common mistake when using the net/http package is to defer a function call to close the http.Response Body before checking the error that determines whether the response is valid:
resp, err := http.Head(url)
defer resp.Body.Close()
if err != nil {
log.Fatal(err)
}
// (defer statement belongs here)

This checker helps uncover latent nil dereference bugs by reporting a diagnostic for such mistakes.
Default: `true` | | `ifaceassert` | detect impossible interface-to-interface type assertions
This checker flags type assertions v.(T) and corresponding type-switch cases in which the static type V of v is an interface that cannot possibly implement the target interface T. This occurs when V and T contain methods with the same name but different signatures. Example:
var v interface {
Read()
}
_ = v.(io.Reader)

The Read method in v has a different signature than the Read method in io.Reader, so this assertion cannot succeed.
Default: `true` | | `infertypeargs` | check for unnecessary type arguments in call expressions
Explicit type arguments may be omitted from call expressions if they can be inferred from function arguments, or from other type arguments:
func f[T any](T) {}


func _() {
f[string]("foo") // string could be inferred
}


Default: `true` | @@ -769,7 +766,7 @@ Example Usage: | `stdmethods` | check signature of methods of well-known interfaces
Sometimes a type may be intended to satisfy an interface but may fail to do so because of a mistake in its method signature. For example, the result of this WriteTo method should be (int64, error), not error, to satisfy io.WriterTo:
type myWriterTo struct{...}
func (myWriterTo) WriteTo(w io.Writer) error { ... }

This check ensures that each method whose name matches one of several well-known interface methods from the standard library has the correct signature for that interface.
Checked method names include:
Format GobEncode GobDecode MarshalJSON MarshalXML
Peek ReadByte ReadFrom ReadRune Scan Seek
UnmarshalJSON UnreadByte UnreadRune WriteByte
WriteTo

Default: `true` | | `stringintconv` | check for string(int) conversions
This checker flags conversions of the form string(x) where x is an integer (but not byte or rune) type. Such conversions are discouraged because they return the UTF-8 representation of the Unicode code point x, and not a decimal string representation of x as one might expect. Furthermore, if x denotes an invalid code point, the conversion cannot be statically rejected.
For conversions that intend on using the code point, consider replacing them with string(rune(x)). Otherwise, strconv.Itoa and its equivalents return the string representation of the value in the desired base.
Default: `true` | | `structtag` | check that struct field tags conform to reflect.StructTag.Get
Also report certain struct tags (json, xml) used with unexported fields.
Default: `true` | -| `stubmethods` | detect missing methods and fix with stub implementations
This analyzer detects type-checking errors due to missing methods in assignments from concrete types to interface types, and offers a suggested fix that will create a set of stub methods so that the concrete type satisfies the interface.
For example, this function will not compile because the value NegativeErr{} does not implement the "error" interface:
func sqrt(x float64) (float64, error) {
if x < 0 {
return 0, NegativeErr{} // error: missing method
}
...
}

type NegativeErr struct{}

This analyzer will suggest a fix to declare this method:
// Error implements error.Error.
func (NegativeErr) Error() string {
panic("unimplemented")
}

(At least, it appears to behave that way, but technically it doesn't use the SuggestedFix mechanism and the stub is created by logic in gopls's source.stub function.)
Default: `true` | +| `stubmethods` | detect missing methods and fix with stub implementations
This analyzer detects type-checking errors due to missing methods in assignments from concrete types to interface types, and offers a suggested fix that will create a set of stub methods so that the concrete type satisfies the interface.
For example, this function will not compile because the value NegativeErr{} does not implement the "error" interface:
func sqrt(x float64) (float64, error) {
if x < 0 {
return 0, NegativeErr{} // error: missing method
}
...
}

type NegativeErr struct{}

This analyzer will suggest a fix to declare this method:
// Error implements error.Error.
func (NegativeErr) Error() string {
panic("unimplemented")
}

(At least, it appears to behave that way, but technically it doesn't use the SuggestedFix mechanism and the stub is created by logic in gopls's golang.stub function.)
Default: `true` | | `testinggoroutine` | report calls to (*testing.T).Fatal from goroutines started by a test
Functions that abruptly terminate a test, such as the Fatal, Fatalf, FailNow, and Skip{,f,Now} methods of *testing.T, must be called from the test goroutine itself. This checker detects calls to these functions that occur within a goroutine started by the test. For example:
func TestFoo(t *testing.T) {
go func() {
t.Fatal("oops") // error: (*T).Fatal called from non-test goroutine
}()
}

Default: `true` | | `tests` | check for common mistaken usages of tests and examples
The tests checker walks Test, Benchmark, Fuzzing and Example functions checking malformed names, wrong signatures and examples documenting non-existent identifiers.
Please see the documentation for package testing in golang.org/pkg/testing for the conventions that are enforced for Tests, Benchmarks, and Examples.
Default: `true` | | `timeformat` | check for calls of (time.Time).Format or time.Parse with 2006-02-01
The timeformat checker looks for time formats with the 2006-02-01 (yyyy-dd-mm) format. Internationally, "yyyy-dd-mm" does not occur in common calendar date standards, and so it is more likely that 2006-01-02 (yyyy-mm-dd) was intended.
Default: `true` | @@ -777,7 +774,7 @@ Example Usage: | `unmarshal` | report passing non-pointer or non-interface values to unmarshal
The unmarshal analysis reports calls to functions such as json.Unmarshal in which the argument type is not a pointer or an interface.
Default: `true` | | `unreachable` | check for unreachable code
The unreachable analyzer finds statements that execution can never reach because they are preceded by an return statement, a call to panic, an infinite loop, or similar constructs.
Default: `true` | | `unsafeptr` | check for invalid conversions of uintptr to unsafe.Pointer
The unsafeptr analyzer reports likely incorrect uses of unsafe.Pointer to convert integers to pointers. A conversion from uintptr to unsafe.Pointer is invalid if it implies that there is a uintptr-typed word in memory that holds a pointer value, because that word will be invisible to stack copying and to the garbage collector.
Default: `true` | -| `unusedparams` | check for unused parameters of functions
The unusedparams analyzer checks functions to see if there are any parameters that are not being used.
To reduce false positives it ignores: - methods - parameters that do not have a name or have the name '_' (the blank identifier) - functions in test files - functions with empty bodies or those with just a return stmt
Default: `false` | +| `unusedparams` | check for unused parameters of functions
The unusedparams analyzer checks functions to see if there are any parameters that are not being used.
To ensure soundness, it ignores: - "address-taken" functions, that is, functions that are used as a value rather than being called directly; their signatures may be required to conform to a func type. - exported functions or methods, since they may be address-taken in another package. - unexported methods whose name matches an interface method declared in the same package, since the method's signature may be required to conform to the interface type. - functions with empty bodies, or containing just a call to panic. - parameters that are unnamed, or named "_", the blank identifier.
The analyzer suggests a fix of replacing the parameter name by "_", but in such cases a deeper fix can be obtained by invoking the "Refactor: remove unused parameter" code action, which will eliminate the parameter entirely, along with all corresponding arguments at call sites, while taking care to preserve any side effects in the argument expressions; see https://github.com/golang/tools/releases/tag/gopls%2Fv0.14.
Default: `true` | | `unusedresult` | check for unused results of calls to some functions
Some functions like fmt.Errorf return a result and have no side effects, so it is always a mistake to discard the result. Other functions may return an error that must not be ignored, or a cleanup operation that must be called. This analyzer reports calls to functions like these when the result of the call is ignored.
The set of functions may be controlled using flags.
Default: `true` | | `unusedvariable` | check for unused variables and suggest fixes
Default: `false` | | `unusedwrite` | checks for unused writes
The analyzer reports instances of writes to struct fields and arrays that are never read. Specifically, when a struct object or an array is copied, its elements are copied implicitly by the compiler, and any element write to this copy does nothing with the original object.
For example:
type T struct { x int }

func f(input []T) {
for i, v := range input { // v is a copy
v.x = i // unused write to field x
}
}

Another example is about non-pointer receiver:
type T struct { x int }

func (t T) f() {  // t is a copy
t.x = i // unused write to field x
}

Default: `false` | diff --git a/docs/tools.md b/docs/tools.md index 7f04a3f00f..5c93bcad05 100644 --- a/docs/tools.md +++ b/docs/tools.md @@ -35,6 +35,13 @@ This extension uses Delve for its debug/test functionalities. The extension curr For a comprehensive overview of how to debug your Go programs, please see the [debugging guide](./debugging.md). +### [`vscgo`](https://pkg.go.dev/github.com/golang/vscode-go/cmd/vscgo) + +This tool provides utilities needed by this extension but do not belong to the language server +or debug adapter server. Examples include dependency tools management, developer survey +configuration, and [Go telemetry collection](https://github.com/golang/vscode-go/issues/3121). +This tool is released with the extension and installed in the extension's directory. + ### [`goplay`](https://pkg.go.dev/github.com/haya14busa/goplay?tab=overview) This tool provides support for the [`Go: Run on Go Playground`](features.md#go-playground) command. diff --git a/docs/ui.md b/docs/ui.md index 9860221136..b9079be015 100644 --- a/docs/ui.md +++ b/docs/ui.md @@ -2,10 +2,15 @@ ## Using The Go Status Bar -The Go status bar appears in the lower left of the extension window. Clicking the Go status bar brings up a menu that provides easy access to see and update important information about your Go project. This includes information about the Go environment, the current Go version, the `gopls` trace, and about the current module. +The Go status bar appears in the lower right of the extension window, next to the Editor Language status bar item. Clicking the Go status bar brings up a menu that provides easy access to see and update important information about your Go project. This includes information about the Go environment, the current Go version, the `gopls` trace, and about the current module. -
vscode extension after Go status bar item is clicked
+
vscode extension after Go status bar item is clicked
+## Using The Language Status Bar + +The Language status bar shows status of dependency tools installation or availability of newly released Go versions. + +
Go language status bar
### Go Environment The `Go Locate Configured Go Tools` command will display the configured GOPATH, GOROOT, tool locations and the results of `go env` in the output window. @@ -14,12 +19,17 @@ The `Go Locate Configured Go Tools` command will display the configured GOPATH, You can view the current Go version by looking at the status bar item in the bottom left corner of VS Code. Clicking this button and selecting `Choose Go Environment` will present you with a menu from which you can select any version of Go that exists in your $HOME/sdk directory or on . This command is also available through the command pallette using `Go: Choose Go Environment`. -Previously, the `go.goroot` and `go.alternateTools` settings controlled the Go version used by VS Code Go. If you have configured these settings, they are no longer needed and should be deleted. +If you are using go1.21 or newer, you can control your Go version using the `GOTOOLCHAIN` environment variable. See https://go.dev/doc/toolchain for more information. To tell the extension to use a different `GOTOOLCHAIN`, use the `go.toolsEnvVars` setting or the Go explorer view. -
command pallete menu for selecting a new Go version
+``` +"go.toolsEnvVars": { + "GOTOOLCHAIN": "go1.21.0+auto" +} +``` +You will need to reload the window after updating this setting. We are working on improving the version switch workflow. -The "Clear Selection" option resets your Go version to the one found first in either `go.alternateTools`, `go.goroot` or your PATH. +Previously, the `go.goroot` and `go.alternateTools` settings controlled the Go version used by VS Code Go. If you have configured these settings, they are no longer needed and should be deleted. ### Installing a New Go Version @@ -31,9 +41,7 @@ Once the download completes, VS Code Go will make use of this new Go version. `gopls` is the official Go [language server](https://langserver.org/) developed by the Go team. It was developed in response to the release of Go modules, and it is the recommended approach when working with Go modules in VS Code. -When `gopls` is enabled, :zap: is displayed next to the Go version in the status bar and the `gopls` version is displayed in the menu. - -
command pallete menu for selecting a new Go version
+When `gopls` is enabled, :zap: is displayed next to the Go version in the Go status bar and the `gopls` version is displayed in the menu. Selecting `Open 'gopls' trace` will open the trace of the `gopls` server in the output window. Please include this trace when filing an issue related to the extension and `gopls` is enabled. @@ -47,4 +55,6 @@ More information about [using Go modules](https://go.dev/blog/using-go-modules ) The view displays the go environment variables (`go env`) that are applied to the file open in the editor. You can customize the list by "Go: Edit Workspace" command (pencil icon), and update modifiable environment variables through this view. -It displays required [tools](tools.md) and their location/version info, too. \ No newline at end of file +It displays required [tools](tools.md) and their location/version info, too. + +
Go explorer view
\ No newline at end of file diff --git a/.eslintignore b/extension/.eslintignore similarity index 100% rename from .eslintignore rename to extension/.eslintignore diff --git a/.eslintrc.json b/extension/.eslintrc.json similarity index 100% rename from .eslintrc.json rename to extension/.eslintrc.json diff --git a/extension/.prettierrc.js b/extension/.prettierrc.js new file mode 100644 index 0000000000..dcf982c304 --- /dev/null +++ b/extension/.prettierrc.js @@ -0,0 +1,3 @@ +module.exports = { + ...require('.prettierrc.json') +} diff --git a/.prettierrc.json b/extension/.prettierrc.json similarity index 100% rename from .prettierrc.json rename to extension/.prettierrc.json diff --git a/.vscodeignore b/extension/.vscodeignore similarity index 95% rename from .vscodeignore rename to extension/.vscodeignore index a6bbc5adfc..2d4285d4ef 100644 --- a/.vscodeignore +++ b/extension/.vscodeignore @@ -12,11 +12,11 @@ .vscode/ .vscode-test/ SECURITY.md +bin/ build/ codereview.cfg docs/ -go.mod -go.sum +go.* node_modules/ out/ src/ diff --git a/CHANGELOG.md b/extension/CHANGELOG.md similarity index 98% rename from CHANGELOG.md rename to extension/CHANGELOG.md index cdc23aac87..1af81c4e55 100644 --- a/CHANGELOG.md +++ b/extension/CHANGELOG.md @@ -1,3 +1,85 @@ +## v0.41.0 - 14 Feb, 2024 + +This release introduces significant updates to the extension's UI. +We also want to share the news that the [gopls v0.15 release](https://go.dev/s/gopls-v0.15) +enhances the multi-module workspace experience and improves build tag handling. + +For a detailed list of changes, refer to the complete [commit +history](https://github.com/golang/vscode-go/compare/v0.40.3...v0.41.0). + +### Changes + +#### Gopls v0.15.0 and Workspace Configuration +* The gopls v0.15 introduces a [significant change](https://go.dev/s/gopls-v0.15) + in its internal workspace data model. Known as ["zero configuration" + gopls](https://github.com/golang/go/issues/57979), `gopls` can automatically + determines workspace configurations such as Go module boundaries and necessary + GOOS/GOARCH build tags for open Go files. This eliminates the need for users + to align the VS Code workspace root folders with the Go module root folder. +* For more details and additional feature updates, refer to the [gopls v0.15.0 + release notes](https://go.dev/s/gopls-v0.15). The extension's + settings have been updated to align with gopls v0.15.0 settings. + +#### UI Updates +* A new [language status + bar](https://github.com/golang/vscode-go/wiki/ui#using-the-language-status-bar) + is added, visible when working on Go-related files. The [Go status + bar](https://github.com/golang/vscode-go/wiki/ui#using-the-go-status-bar), + which displays the selected Go version and the gopls status, is now located at + the bottom right of the window and is visible only when Go files are open. +* The "Go" and "Go Debug" output channels are now primarily used for logging + extension activities such as dependency tool installation, invocation, and + debug logging. Use the `"Developer: Set Log Level..."` command to adjust the + logging level. The `go.logging.level` setting is deprecated in favor of this + new logging mechanism. +* The `"Go: Locate Configured Go Tools"` command now opens an untitled file and + dumps the tools information there, instead of printing it in the "Go" output + channel. This change allows users to inspect and edit the output easily before + sharing it in their issue report. + +#### Debugging +* [Remote + debugging](https://github.com/golang/vscode-go/wiki/debugging#remote-debugging) + now defaults to using delve DAP. The legacy debug adapter will be removed in + the next release cycle. +* [Delve + 1.22.0](https://github.com/go-delve/delve/blob/master/CHANGELOG.md#1220-2023-12-29) + introduces new options to [display 'pprof' + labels](https://github.com/go-delve/delve/issues/3493) and [use concise symbol + and stack presentation](https://github.com/go-delve/delve/issues/3516). Update + delve to the latest version using the `"Go: Install/Update Tools"` command. + +#### Tools +* For new users, the extension will automatically install important tools + (`gopls` and an optionally selected extra lint tool such as `staticcheck` or + `golangci-lint`) if they are missing, using `go install` commands. Any + installation failures will be surfaced in the [language status + bar](https://github.com/golang/vscode-go/wiki/ui#using-the-go-status-bar) and + the "Go" output channel. +* The extension does not require `dlv` installation until the debug feature is + invoked. +* The extension now installs + [`vscgo`](https://pkg.go.dev/github.com/golang/vscode-go/cmd/vscgo), an + optional tool used to [update the Go telemetry + counters](https://github.com/golang/vscode-go/issues/3121). This tool is + installed in the extension's directory. + +#### Telemetry +* The Go telemetry now measures activation latency. ([CL + 549244](https://go-review.git.corp.google.com/c/vscode-go/+/549244)) + +### Fixes +* The extension now recognizes idx as a Web IDE. ([CL + 559895](https://go-review.googlesource.com/c/vscode-go/+/559895)) +* The deprecated `web-request` has been replaced with `node-fetch@v2`. ([Issue + 2995](https://github.com/golang/vscode-go/issues/2995)) + +### Development Process Updates +* The repository layout has been updated with the extension code moved to the + `extension/` directory. See [Issue + 3122](https://github.com/golang/vscode-go/issues/3122) for more details. +* The extension release workflow has been moved to Google Cloud Build. + ## v0.40.3 - 22 Jan, 2024 This is a point release to update the upcoming developer survey information @@ -477,7 +559,6 @@ A list of all issues and changes can be found in the [v0.28.1 milestone](https:/ ### Fixes - Skipped launch configuration adjustment to address build errors when debugging using externally launched delve DAP servers. (Issue [1793](https://github.com/golang/vscode-go/issues/1793)) -- Restore the fix for Issue [1729](https://github.com/golang/vscode-go/issues/1729) that was accidentally dropped during merge for release. ## v0.28.0 - 20 Sep, 2021 @@ -677,7 +758,6 @@ A list of all issues and changes can be found in the ## Code Health - Updated latest version of dlv-dap and gopls (v0.6.10) - ## v0.24.0 - 6th Apr, 2021 πŸ§ͺ We re-enabled the option to use `dlv dap` (Delve's native DAP implementation) instead of the old debug @@ -747,6 +827,12 @@ and the [changes since v0.22.1](https://github.com/golang/vscode-go/compare/v0.2 ## v0.23.0 - 4th Mar, 2021 +Delve DAP is a new debug adapter embedded in `dlv`, the Go debugger. +It is written in Go, understands Go's data types and runtime better, +and is under active development. In this release, we added back +access to Delve DAP. Delve DAP is still in the experimental stage +and we appreciate any feedback and bug reports! + A list of all issues and changes can be found in the [v0.23.0 milestone](https://github.com/golang/vscode-go/milestone/21?closed=1) and the [changes since v0.22.1](https://github.com/golang/vscode-go/compare/v0.22.1...v0.23.0) diff --git a/extension/LICENSE b/extension/LICENSE new file mode 100644 index 0000000000..bec3260395 --- /dev/null +++ b/extension/LICENSE @@ -0,0 +1,24 @@ +vscode-go + +The MIT License (MIT) + +Original Work Copyright (c) 2015-2020 Microsoft Corporation +Current Work and Modifications Copyright (c) 2020-present The Go Authors + +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/extension/doc.go b/extension/doc.go new file mode 100644 index 0000000000..58fc897b22 --- /dev/null +++ b/extension/doc.go @@ -0,0 +1,15 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package extension is a dummy package to configure +// dependency on the github.com/golang/vscode-go/vscgo tool. +package extension + +// Dummy command to add dependency on vscgo. + +import ( + // internal/vscgo is the implementation of + // the vscgo tool. + _ "github.com/golang/vscode-go/internal/vscgo" +) diff --git a/extension/go.mod b/extension/go.mod new file mode 100644 index 0000000000..2342a42ed0 --- /dev/null +++ b/extension/go.mod @@ -0,0 +1,46 @@ +module github.com/golang/vscode-go/extension + +go 1.21 + +require ( + github.com/golang/vscode-go v0.0.0-00010101000000-000000000000 + github.com/google/go-cmp v0.6.0 + github.com/stamblerre/work-stats v0.0.0-20221215212512-f2f2cf51e506 + golang.org/x/build v0.0.0-20240104151245-5535e355572c +) + +require ( + cloud.google.com/go/compute v1.23.0 // indirect + cloud.google.com/go/compute/metadata v0.2.3 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/google/go-github v17.0.0+incompatible // indirect + github.com/google/go-querystring v1.1.0 // indirect + github.com/google/s2a-go v0.1.4 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect + github.com/googleapis/gax-go/v2 v2.12.0 // indirect + github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect + github.com/stamblerre/sheets v0.0.0-20220322044539-54bdb620f700 // indirect + go.opencensus.io v0.24.0 // indirect + go4.org v0.0.0-20180809161055-417644f6feb5 // indirect + golang.org/x/crypto v0.16.0 // indirect + golang.org/x/exp v0.0.0-20230809094429-853ea248256d // indirect + golang.org/x/mod v0.14.0 // indirect + golang.org/x/net v0.19.0 // indirect + golang.org/x/oauth2 v0.15.0 // indirect + golang.org/x/sync v0.5.0 // indirect + golang.org/x/sys v0.16.0 // indirect + golang.org/x/telemetry v0.0.0-20240116212745-88e2d1c7f9a2 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + google.golang.org/api v0.136.0 // indirect + google.golang.org/appengine v1.6.8-0.20221117013220-504804fb50de // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577 // indirect + google.golang.org/grpc v1.58.3 // indirect + google.golang.org/protobuf v1.31.0 // indirect +) + +// For development, use the vscgo in the same repo. +// This go.mod file is excluded when packaging .vsix. +replace github.com/golang/vscode-go => ../ diff --git a/extension/go.sum b/extension/go.sum new file mode 100644 index 0000000000..4b2492ce1d --- /dev/null +++ b/extension/go.sum @@ -0,0 +1,223 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.110.7 h1:rJyC7nWRg2jWGZ4wSJ5nY65GTdYJkg0cd/uXb+ACI6o= +cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY= +cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +cloud.google.com/go/iam v1.1.2 h1:gacbrBdWcoVmGLozRuStX45YKvJtzIjJdAolzUs1sm4= +cloud.google.com/go/iam v1.1.2/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU= +cloud.google.com/go/secretmanager v1.11.1 h1:cLTCwAjFh9fKvU6F13Y4L9vPcx9yiWPyWXE4+zkuEQs= +cloud.google.com/go/secretmanager v1.11.1/go.mod h1:znq9JlXgTNdBeQk9TBW/FnR/W4uChEKGeqQWAJ8SXFw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= +github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/s2a-go v0.1.4 h1:1kZ/sQM3srePvKs3tXAvQzo66XfcReoqFpIpIccE7Oc= +github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.2.5 h1:UR4rDjcgpgEnqpIEvkiqTYKBCKLNmlge2eVjoZfySzM= +github.com/googleapis/enterprise-certificate-proxy v0.2.5/go.mod h1:RxW0N9901Cko1VOCW3SXCpWP+mlIEkk2tP7jnHy9a3w= +github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= +github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/stamblerre/sheets v0.0.0-20220322044539-54bdb620f700 h1:04VNnGQnE26PVIdxBjeJfCLS2W/5u8H8hFym+0EMf+s= +github.com/stamblerre/sheets v0.0.0-20220322044539-54bdb620f700/go.mod h1:XK977hNdUZpQFoSGTEDpbQicSofCnB1PT1CdOOf1lzs= +github.com/stamblerre/work-stats v0.0.0-20221215212512-f2f2cf51e506 h1:YQ1/WiCB8AV8giB+KO9CxheDJuD2Zl4su+vAQdv2ItQ= +github.com/stamblerre/work-stats v0.0.0-20221215212512-f2f2cf51e506/go.mod h1:G94Cv2VI3I+UtGIIah0eQE4OZBVZ3Z9r+XTmQfKlPk4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go4.org v0.0.0-20180809161055-417644f6feb5 h1:+hE86LblG4AyDgwMCLTE6FOlM9+qjHSYS+rKqxUVdsM= +go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= +golang.org/x/build v0.0.0-20240104151245-5535e355572c h1:rlI1VIwI7dfmvrRBxyCyhsp6YH9QjC5GgzPYGB+lO5g= +golang.org/x/build v0.0.0-20240104151245-5535e355572c/go.mod h1:dYD00ZPoQHK4GMm3QX05aTutZAk8hP43zHq62Wmljdk= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20230809094429-853ea248256d h1:wu5bD43Ana/nF1ZmaLr3lW/FQeJU8CcI+Ln7yWHViXE= +golang.org/x/exp v0.0.0-20230809094429-853ea248256d/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= +golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/telemetry v0.0.0-20240116212745-88e2d1c7f9a2 h1:0WVl+1Lj18W2TwhURTJmmBO/Lvh+5lio6kumGpZkEqo= +golang.org/x/telemetry v0.0.0-20240116212745-88e2d1c7f9a2/go.mod h1:ZthVHHkOi8rlMEsfFr3Ie42Ym1NonbFNNRKW3ci0UrU= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.136.0 h1:e/6enzUE1s4tGPa6Q3ZYShKTtvRc+1Jq0rrafhppmOs= +google.golang.org/api v0.136.0/go.mod h1:XtJfF+V2zgUxelOn5Zs3kECtluMxneJG8ZxUTlLNTPA= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.8-0.20221117013220-504804fb50de h1:MvEeYmzkzk0Rsw+ceqy28aIJN7Mum+4aYqBwCMqYNug= +google.golang.org/appengine v1.6.8-0.20221117013220-504804fb50de/go.mod h1:BbwiCY3WCmCUKOJTrX5NwgQzew1c32w3kxa6Sxvs0cQ= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20230807174057-1744710a1577 h1:Tyk/35yqszRCvaragTn5NnkY6IiKk/XvHzEWepo71N0= +google.golang.org/genproto v0.0.0-20230807174057-1744710a1577/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= +google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5 h1:nIgk/EEq3/YlnmVVXVnm14rC2oxgs1o0ong4sD/rd44= +google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5/go.mod h1:5DZzOUPCLYL3mNkQ0ms0F3EuUNZ7py1Bqeq6sxzI7/Q= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577 h1:wukfNtZmZUurLN/atp2hiIeTKn7QJWIQdHzqmsOnAOk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= +google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= +google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/languages/go.mod.language-configuration.json b/extension/languages/go.mod.language-configuration.json similarity index 100% rename from languages/go.mod.language-configuration.json rename to extension/languages/go.mod.language-configuration.json diff --git a/media/announce.png b/extension/media/announce.png similarity index 100% rename from media/announce.png rename to extension/media/announce.png diff --git a/media/codicon.css b/extension/media/codicon.css similarity index 100% rename from media/codicon.css rename to extension/media/codicon.css diff --git a/media/codicon.ttf b/extension/media/codicon.ttf similarity index 100% rename from media/codicon.ttf rename to extension/media/codicon.ttf diff --git a/media/go-logo-blue.png b/extension/media/go-logo-blue.png similarity index 100% rename from media/go-logo-blue.png rename to extension/media/go-logo-blue.png diff --git a/media/go-logo-white.svg b/extension/media/go-logo-white.svg similarity index 100% rename from media/go-logo-white.svg rename to extension/media/go-logo-white.svg diff --git a/media/gutter-blockblue.svg b/extension/media/gutter-blockblue.svg similarity index 100% rename from media/gutter-blockblue.svg rename to extension/media/gutter-blockblue.svg diff --git a/media/gutter-blockgreen.svg b/extension/media/gutter-blockgreen.svg similarity index 100% rename from media/gutter-blockgreen.svg rename to extension/media/gutter-blockgreen.svg diff --git a/media/gutter-blockred.svg b/extension/media/gutter-blockred.svg similarity index 100% rename from media/gutter-blockred.svg rename to extension/media/gutter-blockred.svg diff --git a/media/gutter-blockyellow.svg b/extension/media/gutter-blockyellow.svg similarity index 100% rename from media/gutter-blockyellow.svg rename to extension/media/gutter-blockyellow.svg diff --git a/media/gutter-slashblue.svg b/extension/media/gutter-slashblue.svg similarity index 100% rename from media/gutter-slashblue.svg rename to extension/media/gutter-slashblue.svg diff --git a/media/gutter-slashgreen.svg b/extension/media/gutter-slashgreen.svg similarity index 100% rename from media/gutter-slashgreen.svg rename to extension/media/gutter-slashgreen.svg diff --git a/media/gutter-slashred.svg b/extension/media/gutter-slashred.svg similarity index 100% rename from media/gutter-slashred.svg rename to extension/media/gutter-slashred.svg diff --git a/media/gutter-slashyellow.svg b/extension/media/gutter-slashyellow.svg similarity index 100% rename from media/gutter-slashyellow.svg rename to extension/media/gutter-slashyellow.svg diff --git a/media/gutter-vertblue.svg b/extension/media/gutter-vertblue.svg similarity index 100% rename from media/gutter-vertblue.svg rename to extension/media/gutter-vertblue.svg diff --git a/media/gutter-vertgreen.svg b/extension/media/gutter-vertgreen.svg similarity index 100% rename from media/gutter-vertgreen.svg rename to extension/media/gutter-vertgreen.svg diff --git a/media/gutter-vertred.svg b/extension/media/gutter-vertred.svg similarity index 100% rename from media/gutter-vertred.svg rename to extension/media/gutter-vertred.svg diff --git a/media/gutter-vertyellow.svg b/extension/media/gutter-vertyellow.svg similarity index 100% rename from media/gutter-vertyellow.svg rename to extension/media/gutter-vertyellow.svg diff --git a/media/reset.css b/extension/media/reset.css similarity index 100% rename from media/reset.css rename to extension/media/reset.css diff --git a/media/vscode.css b/extension/media/vscode.css similarity index 100% rename from media/vscode.css rename to extension/media/vscode.css diff --git a/media/welcome.css b/extension/media/welcome.css similarity index 100% rename from media/welcome.css rename to extension/media/welcome.css diff --git a/media/welcome.js b/extension/media/welcome.js similarity index 100% rename from media/welcome.js rename to extension/media/welcome.js diff --git a/package-lock.json b/extension/package-lock.json similarity index 93% rename from package-lock.json rename to extension/package-lock.json index 00bcb210d8..c7f428ab6e 100644 --- a/package-lock.json +++ b/extension/package-lock.json @@ -1,26 +1,26 @@ { "name": "go", - "version": "0.40.2", + "version": "0.41.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "go", - "version": "0.40.2", + "version": "0.41.0", "license": "MIT", "dependencies": { "diff": "4.0.2", "glob": "7.1.7", "json-rpc2": "2.0.0", "moment": "2.29.4", + "node-fetch": "2.7.0", "semver": "7.5.4", "tree-kill": "file:third_party/tree-kill", "vscode-debugadapter": "1.45.0", "vscode-debugprotocol": "1.45.0", "vscode-languageclient": "8.1.0", "vscode-languageserver-protocol": "3.17.3", - "vscode-uri": "3.0.3", - "web-request": "1.0.7" + "vscode-uri": "3.0.3" }, "devDependencies": { "@types/adm-zip": "0.4.33", @@ -28,12 +28,13 @@ "@types/glob": "7.1.3", "@types/mocha": "7.0.2", "@types/node": "13.13.46", + "@types/node-fetch": "2.6.9", "@types/semver": "7.3.4", "@types/sinon": "9.0.11", - "@types/vscode": "1.67.0", + "@types/vscode": "1.75.0", "@vscode/debugadapter-testsupport": "1.58.0", "@vscode/test-electron": "2.3.8", - "@vscode/vsce": "2.19.0", + "@vscode/vsce": "2.23.0", "adm-zip": "0.4.16", "esbuild": "0.17.10", "fs-extra": "9.1.0", @@ -679,6 +680,16 @@ "integrity": "sha512-dqpbzK/KDsOlEt+oyB3rv+u1IxlLFziZu/Z0adfRKoelkr+sTd6QcgiQC+HWq/vkYkHwG5ot2LxgV05aAjnhcg==", "dev": true }, + "node_modules/@types/node-fetch": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.9.tgz", + "integrity": "sha512-bQVlnMLFJ2d35DkPNjEPmd9ueO/rh5EiaZt2bhqiSarPjZIuIV6bPQVqcrEyvNo+AfTrRGVazle1tl597w3gfA==", + "dev": true, + "dependencies": { + "@types/node": "*", + "form-data": "^4.0.0" + } + }, "node_modules/@types/normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", @@ -707,9 +718,9 @@ "dev": true }, "node_modules/@types/vscode": { - "version": "1.67.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.67.0.tgz", - "integrity": "sha512-GH8BDf8cw9AC9080uneJfulhSa7KHSMI2s/CyKePXoGNos9J486w2V4YKoeNUqIEkW4hKoEAWp6/cXTwyGj47g==", + "version": "1.75.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.75.0.tgz", + "integrity": "sha512-SAr0PoOhJS6FUq5LjNr8C/StBKALZwDVm3+U4pjF/3iYkt3GioJOPV/oB1Sf1l7lROe4TgrMyL5N1yaEgTWycw==", "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { @@ -1031,15 +1042,16 @@ } }, "node_modules/@vscode/vsce": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-2.19.0.tgz", - "integrity": "sha512-dAlILxC5ggOutcvJY24jxz913wimGiUrHaPkk16Gm9/PGFbz1YezWtrXsTKUtJws4fIlpX2UIlVlVESWq8lkfQ==", + "version": "2.23.0", + "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-2.23.0.tgz", + "integrity": "sha512-Wf9yN8feZf4XmUW/erXyKQvCL577u72AQv4AI4Cwt5o5NyE49C5mpfw3pN78BJYYG3qnSIxwRo7JPvEurkQuNA==", "dev": true, "dependencies": { "azure-devops-node-api": "^11.0.1", "chalk": "^2.4.2", "cheerio": "^1.0.0-rc.9", - "commander": "^6.1.0", + "commander": "^6.2.1", + "find-yarn-workspace-root": "^2.0.0", "glob": "^7.0.6", "hosted-git-info": "^4.0.2", "jsonc-parser": "^3.2.0", @@ -1049,7 +1061,7 @@ "minimatch": "^3.0.3", "parse-semver": "^1.1.1", "read": "^1.0.7", - "semver": "^5.1.0", + "semver": "^7.5.2", "tmp": "^0.2.1", "typed-rest-client": "^1.8.4", "url-join": "^4.0.1", @@ -1117,15 +1129,6 @@ "node": ">=4" } }, - "node_modules/@vscode/vsce/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, "node_modules/@vscode/vsce/node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -1196,6 +1199,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -1304,26 +1308,11 @@ "node": ">=0.10.0" } }, - "node_modules/asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "engines": { - "node": ">=0.8" - } - }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true }, "node_modules/at-least-node": { "version": "1.0.0", @@ -1334,19 +1323,6 @@ "node": ">= 4.0.0" } }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" - }, "node_modules/azure-devops-node-api": { "version": "11.2.0", "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-11.2.0.tgz", @@ -1383,14 +1359,6 @@ ], "optional": true }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, "node_modules/better-curry": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/better-curry/-/better-curry-1.6.0.tgz", @@ -1550,11 +1518,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, "node_modules/chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -1703,6 +1666,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -1727,7 +1691,8 @@ "node_modules/core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true }, "node_modules/cross-spawn": { "version": "7.0.3", @@ -1771,17 +1736,6 @@ "url": "https://github.com/sponsors/fb55" } }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/debug": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", @@ -1864,7 +1818,8 @@ "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, "engines": { "node": ">=0.4.0" } @@ -1966,15 +1921,6 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -2450,11 +2396,6 @@ "node": ">=6" } }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, "node_modules/external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", @@ -2469,18 +2410,11 @@ "node": ">=4" } }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "engines": [ - "node >=0.6.0" - ] - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true }, "node_modules/fast-diff": { "version": "1.2.0", @@ -2507,7 +2441,8 @@ "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true }, "node_modules/fast-levenshtein": { "version": "2.0.6", @@ -2599,6 +2534,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/find-yarn-workspace-root": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", + "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", + "dev": true, + "dependencies": { + "micromatch": "^4.0.2" + } + }, "node_modules/flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", @@ -2627,25 +2571,18 @@ "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", "dev": true }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "engines": { - "node": "*" - } - }, "node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, "dependencies": { "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", + "combined-stream": "^1.0.8", "mime-types": "^2.1.12" }, "engines": { - "node": ">= 0.12" + "node": ">= 6" } }, "node_modules/fs-constants": { @@ -2748,14 +2685,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dependencies": { - "assert-plus": "^1.0.0" - } - }, "node_modules/github-from-package": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", @@ -2903,27 +2832,6 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/hard-rejection": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", @@ -3025,20 +2933,6 @@ "node": ">= 6" } }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, "node_modules/https-proxy-agent": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", @@ -3275,11 +3169,6 @@ "node": ">=8" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, "node_modules/is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", @@ -3304,22 +3193,12 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -3342,15 +3221,11 @@ "node": ">= 10" } }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -3358,11 +3233,6 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -3401,20 +3271,6 @@ "node >= 0.2.0" ] }, - "node_modules/jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, "node_modules/jszip": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", @@ -3681,19 +3537,21 @@ } }, "node_modules/mime-db": { - "version": "1.46.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz", - "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { - "version": "2.1.29", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz", - "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, "dependencies": { - "mime-db": "1.46.0" + "mime-db": "1.52.0" }, "engines": { "node": ">= 0.6" @@ -4014,6 +3872,25 @@ "dev": true, "optional": true }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/normalize-package-data": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.1.tgz", @@ -4062,14 +3939,6 @@ "url": "https://github.com/fb55/nth-check?sponsor=1" } }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "engines": { - "node": "*" - } - }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -4331,11 +4200,6 @@ "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", "dev": true }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -4414,11 +4278,6 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, - "node_modules/psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" - }, "node_modules/pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -4434,18 +4293,11 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, "engines": { "node": ">=6" } }, - "node_modules/qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", - "engines": { - "node": ">=0.6" - } - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -4679,37 +4531,6 @@ "url": "https://github.com/sponsors/mysticatea" } }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -4831,7 +4652,8 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true }, "node_modules/sax": { "version": "1.2.4", @@ -5015,30 +4837,6 @@ "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==", "dev": true }, - "node_modules/sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -5200,17 +4998,10 @@ "node": ">=8.0" } }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, "node_modules/tree-kill": { "resolved": "third_party/tree-kill", @@ -5259,6 +5050,8 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "optional": true, "dependencies": { "safe-buffer": "^5.0.1" }, @@ -5266,11 +5059,6 @@ "node": "*" } }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -5365,6 +5153,7 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, "dependencies": { "punycode": "^2.1.0" } @@ -5381,14 +5170,6 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, - "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "bin": { - "uuid": "bin/uuid" - } - }, "node_modules/v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", @@ -5405,19 +5186,6 @@ "spdx-expression-parse": "^3.0.0" } }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, "node_modules/vscode-debugadapter": { "version": "1.45.0", "resolved": "https://registry.npmjs.org/vscode-debugadapter/-/vscode-debugadapter-1.45.0.tgz", @@ -5491,13 +5259,10 @@ "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.3.tgz", "integrity": "sha512-EcswR2S8bpR7fD0YPeS7r2xXExrScVMxg4MedACaWHEtx9ftCF/qHG1xGkolzTPcEmjTavCQgbVzHUIdTMzFGA==" }, - "node_modules/web-request": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/web-request/-/web-request-1.0.7.tgz", - "integrity": "sha512-mVySwo0f8FFw77ZCEEjZ93g7SqAvWREj15FefhJgPkkylu7b185N/u3Oa92sNpMdhjcErGB7oGpOkAAIvflSjw==", - "dependencies": { - "request": "^2.69.0" - } + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "node_modules/websocket-driver": { "version": "0.7.4", @@ -5520,6 +5285,15 @@ "node": ">=0.8.0" } }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -6149,6 +5923,16 @@ "integrity": "sha512-dqpbzK/KDsOlEt+oyB3rv+u1IxlLFziZu/Z0adfRKoelkr+sTd6QcgiQC+HWq/vkYkHwG5ot2LxgV05aAjnhcg==", "dev": true }, + "@types/node-fetch": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.9.tgz", + "integrity": "sha512-bQVlnMLFJ2d35DkPNjEPmd9ueO/rh5EiaZt2bhqiSarPjZIuIV6bPQVqcrEyvNo+AfTrRGVazle1tl597w3gfA==", + "dev": true, + "requires": { + "@types/node": "*", + "form-data": "^4.0.0" + } + }, "@types/normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", @@ -6177,9 +5961,9 @@ "dev": true }, "@types/vscode": { - "version": "1.67.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.67.0.tgz", - "integrity": "sha512-GH8BDf8cw9AC9080uneJfulhSa7KHSMI2s/CyKePXoGNos9J486w2V4YKoeNUqIEkW4hKoEAWp6/cXTwyGj47g==", + "version": "1.75.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.75.0.tgz", + "integrity": "sha512-SAr0PoOhJS6FUq5LjNr8C/StBKALZwDVm3+U4pjF/3iYkt3GioJOPV/oB1Sf1l7lROe4TgrMyL5N1yaEgTWycw==", "dev": true }, "@typescript-eslint/eslint-plugin": { @@ -6372,15 +6156,16 @@ } }, "@vscode/vsce": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-2.19.0.tgz", - "integrity": "sha512-dAlILxC5ggOutcvJY24jxz913wimGiUrHaPkk16Gm9/PGFbz1YezWtrXsTKUtJws4fIlpX2UIlVlVESWq8lkfQ==", + "version": "2.23.0", + "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-2.23.0.tgz", + "integrity": "sha512-Wf9yN8feZf4XmUW/erXyKQvCL577u72AQv4AI4Cwt5o5NyE49C5mpfw3pN78BJYYG3qnSIxwRo7JPvEurkQuNA==", "dev": true, "requires": { "azure-devops-node-api": "^11.0.1", "chalk": "^2.4.2", "cheerio": "^1.0.0-rc.9", - "commander": "^6.1.0", + "commander": "^6.2.1", + "find-yarn-workspace-root": "^2.0.0", "glob": "^7.0.6", "hosted-git-info": "^4.0.2", "jsonc-parser": "^3.2.0", @@ -6391,7 +6176,7 @@ "minimatch": "^3.0.3", "parse-semver": "^1.1.1", "read": "^1.0.7", - "semver": "^5.1.0", + "semver": "^7.5.2", "tmp": "^0.2.1", "typed-rest-client": "^1.8.4", "url-join": "^4.0.1", @@ -6441,12 +6226,6 @@ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true - }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -6499,6 +6278,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -6572,23 +6352,11 @@ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true }, "at-least-node": { "version": "1.0.0", @@ -6596,16 +6364,6 @@ "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", "dev": true }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" - }, - "aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" - }, "azure-devops-node-api": { "version": "11.2.0", "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-11.2.0.tgz", @@ -6628,14 +6386,6 @@ "dev": true, "optional": true }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "requires": { - "tweetnacl": "^0.14.3" - } - }, "better-curry": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/better-curry/-/better-curry-1.6.0.tgz", @@ -6753,11 +6503,6 @@ "quick-lru": "^4.0.1" } }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, "chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -6871,6 +6616,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, "requires": { "delayed-stream": "~1.0.0" } @@ -6889,7 +6635,8 @@ "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true }, "cross-spawn": { "version": "7.0.3", @@ -6921,14 +6668,6 @@ "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", "dev": true }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "^1.0.0" - } - }, "debug": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", @@ -6987,7 +6726,8 @@ "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true }, "detect-libc": { "version": "2.0.1", @@ -7056,15 +6796,6 @@ "domhandler": "^5.0.1" } }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -7410,11 +7141,6 @@ "dev": true, "optional": true }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, "external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", @@ -7426,15 +7152,11 @@ "tmp": "^0.0.33" } }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" - }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true }, "fast-diff": { "version": "1.2.0", @@ -7458,7 +7180,8 @@ "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true }, "fast-levenshtein": { "version": "2.0.6", @@ -7529,6 +7252,15 @@ "path-exists": "^4.0.0" } }, + "find-yarn-workspace-root": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", + "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", + "dev": true, + "requires": { + "micromatch": "^4.0.2" + } + }, "flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", @@ -7551,18 +7283,14 @@ "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", "dev": true }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, "requires": { "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", + "combined-stream": "^1.0.8", "mime-types": "^2.1.12" } }, @@ -7638,14 +7366,6 @@ "integrity": "sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==", "dev": true }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "requires": { - "assert-plus": "^1.0.0" - } - }, "github-from-package": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", @@ -7749,20 +7469,6 @@ } } }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" - }, - "har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - } - }, "hard-rejection": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", @@ -7833,16 +7539,6 @@ "debug": "4" } }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, "https-proxy-agent": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", @@ -8014,11 +7710,6 @@ "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", "dev": true }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, "is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", @@ -8037,22 +7728,12 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, "json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -8072,15 +7753,11 @@ "object-assign": "^4.1.1" } }, - "json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -8088,11 +7765,6 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, "json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -8120,17 +7792,6 @@ "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" }, - "jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - } - }, "jszip": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", @@ -8340,16 +8001,18 @@ "dev": true }, "mime-db": { - "version": "1.46.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz", - "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==" + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true }, "mime-types": { - "version": "2.1.29", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz", - "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, "requires": { - "mime-db": "1.46.0" + "mime-db": "1.52.0" } }, "mimic-fn": { @@ -8591,6 +8254,14 @@ "dev": true, "optional": true }, + "node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "requires": { + "whatwg-url": "^5.0.0" + } + }, "normalize-package-data": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.1.tgz", @@ -8627,11 +8298,6 @@ "boolbase": "^1.0.0" } }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" - }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -8830,11 +8496,6 @@ "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", "dev": true }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, "picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -8889,11 +8550,6 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, - "psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" - }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -8908,12 +8564,8 @@ "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - }, - "qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==" + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true }, "queue-microtask": { "version": "1.2.3", @@ -9092,33 +8744,6 @@ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", "dev": true }, - "request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - } - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -9198,7 +8823,8 @@ "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true }, "sax": { "version": "1.2.4", @@ -9332,22 +8958,6 @@ "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==", "dev": true }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -9478,14 +9088,10 @@ "is-number": "^7.0.0" } }, - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, "tree-kill": { "version": "file:third_party/tree-kill" @@ -9521,15 +9127,12 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.0.1" } }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -9601,6 +9204,7 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, "requires": { "punycode": "^2.1.0" } @@ -9617,11 +9221,6 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - }, "v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", @@ -9638,16 +9237,6 @@ "spdx-expression-parse": "^3.0.0" } }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, "vscode-debugadapter": { "version": "1.45.0", "resolved": "https://registry.npmjs.org/vscode-debugadapter/-/vscode-debugadapter-1.45.0.tgz", @@ -9714,13 +9303,10 @@ "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.3.tgz", "integrity": "sha512-EcswR2S8bpR7fD0YPeS7r2xXExrScVMxg4MedACaWHEtx9ftCF/qHG1xGkolzTPcEmjTavCQgbVzHUIdTMzFGA==" }, - "web-request": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/web-request/-/web-request-1.0.7.tgz", - "integrity": "sha512-mVySwo0f8FFw77ZCEEjZ93g7SqAvWREj15FefhJgPkkylu7b185N/u3Oa92sNpMdhjcErGB7oGpOkAAIvflSjw==", - "requires": { - "request": "^2.69.0" - } + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "websocket-driver": { "version": "0.7.4", @@ -9737,6 +9323,15 @@ "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==" }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/extension/package.json similarity index 98% rename from package.json rename to extension/package.json index 21c2a6f55d..8c5ae26a17 100644 --- a/package.json +++ b/extension/package.json @@ -1,7 +1,7 @@ { "name": "go", "displayName": "Go", - "version": "0.40.2", + "version": "0.41.0", "publisher": "golang", "description": "Rich Go language support for Visual Studio Code", "author": { @@ -35,8 +35,8 @@ "gopls" ], "scripts": { - "clean": "rm -rf ./dist/* && rm -rf ./out/* && rm *.vsix", - "package": "npx vsce package", + "clean": "rm -rf ./dist/* && rm -rf ./out/* && rm -rf ./bin/* && rm *.vsix", + "package": "cp ../README.md ./README.md && npx vsce package --baseContentUrl https://github.com/golang/vscode-go/raw/HEAD --baseImagesUrl https://github.com/golang/vscode-go/raw/HEAD", "vscode:prepublish": "npm run compile", "bundle": "esbuild src/goMain.ts debugAdapter=src/debugAdapter/goDebug.ts --bundle --outdir=dist --external:vscode --format=cjs --platform=node", "bundle-dev": "npm run bundle -- --sourcemap", @@ -56,14 +56,14 @@ "glob": "7.1.7", "json-rpc2": "2.0.0", "moment": "2.29.4", + "node-fetch": "2.7.0", "semver": "7.5.4", "tree-kill": "file:third_party/tree-kill", "vscode-debugadapter": "1.45.0", "vscode-debugprotocol": "1.45.0", "vscode-languageclient": "8.1.0", "vscode-languageserver-protocol": "3.17.3", - "vscode-uri": "3.0.3", - "web-request": "1.0.7" + "vscode-uri": "3.0.3" }, "devDependencies": { "@types/adm-zip": "0.4.33", @@ -71,12 +71,13 @@ "@types/glob": "7.1.3", "@types/mocha": "7.0.2", "@types/node": "13.13.46", + "@types/node-fetch": "2.6.9", "@types/semver": "7.3.4", "@types/sinon": "9.0.11", - "@types/vscode": "1.67.0", + "@types/vscode": "1.75.0", "@vscode/debugadapter-testsupport": "1.58.0", "@vscode/test-electron": "2.3.8", - "@vscode/vsce": "2.19.0", + "@vscode/vsce": "2.23.0", "adm-zip": "0.4.16", "esbuild": "0.17.10", "fs-extra": "9.1.0", @@ -1512,14 +1513,7 @@ }, "go.logging.level": { "type": "string", - "default": "error", - "enum": [ - "off", - "error", - "info", - "verbose" - ], - "description": "The logging level the extension logs at, defaults to 'error'", + "deprecationMessage": "This setting is deprecated. Use 'Developer: Set Log Level...' command to control logging level instead.", "scope": "machine-overridable" }, "go.toolsManagement.go": { @@ -2101,7 +2095,7 @@ }, "ui.diagnostic.analyses": { "type": "object", - "markdownDescription": "analyses specify analyses that the user would like to enable or disable.\nA map of the names of analysis passes that should be enabled/disabled.\nA full list of analyzers that gopls uses can be found in\n[analyzers.md](https://github.com/golang/tools/blob/master/gopls/doc/analyzers.md).\n\nExample Usage:\n\n```json5\n...\n\"analyses\": {\n \"unreachable\": false, // Disable the unreachable analyzer.\n \"unusedparams\": true // Enable the unusedparams analyzer.\n}\n...\n```\n", + "markdownDescription": "analyses specify analyses that the user would like to enable or disable.\nA map of the names of analysis passes that should be enabled/disabled.\nA full list of analyzers that gopls uses can be found in\n[analyzers.md](https://github.com/golang/tools/blob/master/gopls/doc/analyzers.md).\n\nExample Usage:\n\n```json5\n...\n\"analyses\": {\n \"unreachable\": false, // Disable the unreachable analyzer.\n \"unusedvariable\": true // Enable the unusedvariable analyzer.\n}\n...\n```\n", "scope": "resource", "properties": { "appends": { @@ -2194,11 +2188,6 @@ "markdownDescription": "suggest fixes for errors due to an incorrect number of return values\n\nThis checker provides suggested fixes for type errors of the\ntype \"wrong number of return values (want %d, got %d)\". For example:\n\n\tfunc m() (int, string, *bool, error) {\n\t\treturn\n\t}\n\nwill turn into\n\n\tfunc m() (int, string, *bool, error) {\n\t\treturn 0, \"\", nil, nil\n\t}\n\nThis functionality is similar to https://github.com/sqs/goreturns.", "default": true }, - "fillstruct": { - "type": "boolean", - "markdownDescription": "note incomplete struct initializations\n\nThis analyzer provides diagnostics for any struct literals that do not have\nany fields initialized. Because the suggested fix for this analysis is\nexpensive to compute, callers should compute it separately, using the\nSuggestedFix function below.\n", - "default": true - }, "httpresponse": { "type": "boolean", "markdownDescription": "check for mistakes using HTTP responses\n\nA common mistake when using the net/http package is to defer a function\ncall to close the http.Response Body before checking the error that\ndetermines whether the response is valid:\n\n\tresp, err := http.Head(url)\n\tdefer resp.Body.Close()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\t// (defer statement belongs here)\n\nThis checker helps uncover latent nil dereference bugs by reporting a\ndiagnostic for such mistakes.", @@ -2301,7 +2290,7 @@ }, "stubmethods": { "type": "boolean", - "markdownDescription": "detect missing methods and fix with stub implementations\n\nThis analyzer detects type-checking errors due to missing methods\nin assignments from concrete types to interface types, and offers\na suggested fix that will create a set of stub methods so that\nthe concrete type satisfies the interface.\n\nFor example, this function will not compile because the value\nNegativeErr{} does not implement the \"error\" interface:\n\n\tfunc sqrt(x float64) (float64, error) {\n\t\tif x < 0 {\n\t\t\treturn 0, NegativeErr{} // error: missing method\n\t\t}\n\t\t...\n\t}\n\n\ttype NegativeErr struct{}\n\nThis analyzer will suggest a fix to declare this method:\n\n\t// Error implements error.Error.\n\tfunc (NegativeErr) Error() string {\n\t\tpanic(\"unimplemented\")\n\t}\n\n(At least, it appears to behave that way, but technically it\ndoesn't use the SuggestedFix mechanism and the stub is created by\nlogic in gopls's source.stub function.)", + "markdownDescription": "detect missing methods and fix with stub implementations\n\nThis analyzer detects type-checking errors due to missing methods\nin assignments from concrete types to interface types, and offers\na suggested fix that will create a set of stub methods so that\nthe concrete type satisfies the interface.\n\nFor example, this function will not compile because the value\nNegativeErr{} does not implement the \"error\" interface:\n\n\tfunc sqrt(x float64) (float64, error) {\n\t\tif x < 0 {\n\t\t\treturn 0, NegativeErr{} // error: missing method\n\t\t}\n\t\t...\n\t}\n\n\ttype NegativeErr struct{}\n\nThis analyzer will suggest a fix to declare this method:\n\n\t// Error implements error.Error.\n\tfunc (NegativeErr) Error() string {\n\t\tpanic(\"unimplemented\")\n\t}\n\n(At least, it appears to behave that way, but technically it\ndoesn't use the SuggestedFix mechanism and the stub is created by\nlogic in gopls's golang.stub function.)", "default": true }, "testinggoroutine": { @@ -2341,8 +2330,8 @@ }, "unusedparams": { "type": "boolean", - "markdownDescription": "check for unused parameters of functions\n\nThe unusedparams analyzer checks functions to see if there are\nany parameters that are not being used.\n\nTo reduce false positives it ignores:\n- methods\n- parameters that do not have a name or have the name '_' (the blank identifier)\n- functions in test files\n- functions with empty bodies or those with just a return stmt", - "default": false + "markdownDescription": "check for unused parameters of functions\n\nThe unusedparams analyzer checks functions to see if there are\nany parameters that are not being used.\n\nTo ensure soundness, it ignores:\n - \"address-taken\" functions, that is, functions that are used as\n a value rather than being called directly; their signatures may\n be required to conform to a func type.\n - exported functions or methods, since they may be address-taken\n in another package.\n - unexported methods whose name matches an interface method\n declared in the same package, since the method's signature\n may be required to conform to the interface type.\n - functions with empty bodies, or containing just a call to panic.\n - parameters that are unnamed, or named \"_\", the blank identifier.\n\nThe analyzer suggests a fix of replacing the parameter name by \"_\",\nbut in such cases a deeper fix can be obtained by invoking the\n\"Refactor: remove unused parameter\" code action, which will\neliminate the parameter entirely, along with all corresponding\narguments at call sites, while taking care to preserve any side\neffects in the argument expressions; see\nhttps://github.com/golang/tools/releases/tag/gopls%2Fv0.14.", + "default": true }, "unusedresult": { "type": "boolean", diff --git a/snippets/go.json b/extension/snippets/go.json similarity index 100% rename from snippets/go.json rename to extension/snippets/go.json diff --git a/src/commands/applyCoverprofile.ts b/extension/src/commands/applyCoverprofile.ts similarity index 100% rename from src/commands/applyCoverprofile.ts rename to extension/src/commands/applyCoverprofile.ts diff --git a/extension/src/commands/getConfiguredGoTools.ts b/extension/src/commands/getConfiguredGoTools.ts new file mode 100644 index 0000000000..88a412bbb0 --- /dev/null +++ b/extension/src/commands/getConfiguredGoTools.ts @@ -0,0 +1,101 @@ +/*--------------------------------------------------------- + * Copyright 2022 The Go Authors. All rights reserved. + * Licensed under the MIT License. See LICENSE in the project root for license information. + *--------------------------------------------------------*/ + +import * as vscode from 'vscode'; +import path from 'path'; + +import { CommandFactory } from '.'; +import { getGoConfig, getGoplsConfig } from '../config'; +import { inspectGoToolVersion } from '../goInstallTools'; +import { getConfiguredTools } from '../goTools'; +import { getBinPath, getCurrentGoPath, getGoEnv, getGoVersion, getToolsGopath } from '../util'; +import { getEnvPath, initialEnvPath, getCurrentGoRoot } from '../utils/pathUtils'; + +export const getConfiguredGoTools: CommandFactory = () => { + return async () => { + // create an untitled markdown document. + const buf = []; + // Tool's path search is done by getBinPathWithPreferredGopath + // which searches places in the following order + // 1) absolute path for the alternateTool + // 2) GOBIN + // 3) toolsGopath + // 4) gopath + // 5) GOROOT + // 6) PATH + buf.push('# Tools Configuration\n'); + buf.push('\n## Environment\n'); + buf.push('GOBIN: ' + process.env['GOBIN']); + buf.push('toolsGopath: ' + getToolsGopath()); + buf.push('gopath: ' + getCurrentGoPath()); + buf.push('GOROOT: ' + getCurrentGoRoot()); + const currentEnvPath = getEnvPath(); + buf.push('PATH: ' + currentEnvPath); + if (currentEnvPath !== initialEnvPath) { + buf.push(`PATH (vscode launched with): ${initialEnvPath}`); + } + + buf.push('\n## Tools\n'); + try { + const goVersion = await getGoVersion(); + const allTools = getConfiguredTools(getGoConfig(), getGoplsConfig()); + const goVersionTooOld = goVersion?.lt('1.18') || false; + + buf.push(`\tgo:\t${goVersion?.binaryPath}: ${goVersion?.version}`); + const toolsInfo = await Promise.all( + allTools.map(async (tool) => { + const toolPath = getBinPath(tool.name); + // TODO(hyangah): print alternate tool info if set. + if (!path.isAbsolute(toolPath)) { + // getBinPath returns the absolute path is the tool exists. + // (See getBinPathWithPreferredGopath which is called underneath) + return `\t${tool.name}:\tnot installed`; + } + if (goVersionTooOld) { + return `\t${tool.name}:\t${toolPath}: unknown version`; + } + const { goVersion, moduleVersion, debugInfo } = await inspectGoToolVersion(toolPath); + if (goVersion || moduleVersion) { + return `\t${tool.name}:\t${toolPath}\t(version: ${moduleVersion} built with go: ${goVersion})`; + } else { + return `\t${tool.name}:\t${toolPath}\t(version: unknown - ${debugInfo})`; + } + }) + ); + toolsInfo.forEach((info) => { + buf.push(info); + }); + } catch (e) { + buf.push(`failed to get tools info: ${e}`); + } + + let folders = vscode.workspace.workspaceFolders?.map<{ name: string; path?: string }>((folder) => { + return { name: folder.name, path: folder.uri.fsPath }; + }); + if (!folders) { + folders = [{ name: 'no folder', path: undefined }]; + } + + buf.push('\n## Go env\n'); + for (const folder of folders) { + buf.push(`Workspace Folder (${folder.name}): ${folder.path}\n`); + try { + const out = await getGoEnv(folder.path); + // Append '\t' to the beginning of every line (^) of 'out'. + // 'g' = 'global matching', and 'm' = 'multi-line matching' + buf.push(out.replace(/^/gm, '\t')); + } catch (e) { + buf.push(`failed to run 'go env': ${e}`); + } + } + + // create a new untitled document + const doc = await vscode.workspace.openTextDocument({ + content: buf.join('\n'), + language: 'markdown' + }); + await vscode.window.showTextDocument(doc); + }; +}; diff --git a/src/commands/getCurrentGoPath.ts b/extension/src/commands/getCurrentGoPath.ts similarity index 100% rename from src/commands/getCurrentGoPath.ts rename to extension/src/commands/getCurrentGoPath.ts diff --git a/src/commands/getCurrentGoRoot.ts b/extension/src/commands/getCurrentGoRoot.ts similarity index 100% rename from src/commands/getCurrentGoRoot.ts rename to extension/src/commands/getCurrentGoRoot.ts diff --git a/src/commands/index.ts b/extension/src/commands/index.ts similarity index 100% rename from src/commands/index.ts rename to extension/src/commands/index.ts diff --git a/src/commands/installTools.ts b/extension/src/commands/installTools.ts similarity index 100% rename from src/commands/installTools.ts rename to extension/src/commands/installTools.ts diff --git a/src/commands/runBuilds.ts b/extension/src/commands/runBuilds.ts similarity index 100% rename from src/commands/runBuilds.ts rename to extension/src/commands/runBuilds.ts diff --git a/src/commands/showCommands.ts b/extension/src/commands/showCommands.ts similarity index 100% rename from src/commands/showCommands.ts rename to extension/src/commands/showCommands.ts diff --git a/src/commands/startDebugSession.ts b/extension/src/commands/startDebugSession.ts similarity index 100% rename from src/commands/startDebugSession.ts rename to extension/src/commands/startDebugSession.ts diff --git a/src/commands/startLanguageServer.ts b/extension/src/commands/startLanguageServer.ts similarity index 95% rename from src/commands/startLanguageServer.ts rename to extension/src/commands/startLanguageServer.ts index f01d1f97c4..350b1da15e 100644 --- a/src/commands/startLanguageServer.ts +++ b/extension/src/commands/startLanguageServer.ts @@ -88,13 +88,13 @@ export const startLanguageServer: CommandFactory = (ctx, goCtx) => { goCtx.serverInfo?.Commands ); - updateStatus(goCtx, goConfig, true); console.log(`Server: ${JSON.stringify(goCtx.serverInfo, null, 2)}`); } catch (e) { const msg = `Error starting language server: ${e}`; console.log(msg); goCtx.serverOutputChannel?.append(msg); } finally { + updateStatus(goCtx, goConfig, true); unlock(); } }; @@ -103,26 +103,26 @@ export const startLanguageServer: CommandFactory = (ctx, goCtx) => { function updateStatus(goCtx: GoExtensionContext, goConfig: vscode.WorkspaceConfiguration, didStart: boolean) { goCtx.languageServerIsRunning = didStart; vscode.commands.executeCommand('setContext', 'go.goplsIsRunning', didStart); - updateLanguageServerIconGoStatusBar(didStart, goConfig['useLanguageServer'] === true); + updateLanguageServerIconGoStatusBar(goCtx.languageClient, goConfig['useLanguageServer'] === true); } function shouldActivateLanguageFeatures() { for (const folder of vscode.workspace.workspaceFolders || []) { switch (folder.uri.scheme) { case 'vsls': - outputChannel.appendLine( + outputChannel.error( 'Language service on the guest side is disabled. ' + 'The server-side language service will provide the language features.' ); return; case 'ssh': - outputChannel.appendLine('The language server is not supported for SSH. Disabling it.'); + outputChannel.error('The language server is not supported for SSH. Disabling it.'); return; } } const schemes = vscode.workspace.workspaceFolders?.map((folder) => folder.uri.scheme); if (schemes && schemes.length > 0 && !schemes.includes('file') && !schemes.includes('untitled')) { - outputChannel.appendLine( + outputChannel.error( `None of the folders in this workspace ${schemes.join( ',' )} are the types the language server recognizes. Disabling the language features.` diff --git a/src/commands/toggleGCDetails.ts b/extension/src/commands/toggleGCDetails.ts similarity index 100% rename from src/commands/toggleGCDetails.ts rename to extension/src/commands/toggleGCDetails.ts diff --git a/src/config.ts b/extension/src/config.ts similarity index 97% rename from src/config.ts rename to extension/src/config.ts index 48cb530078..7b3ab06920 100644 --- a/src/config.ts +++ b/extension/src/config.ts @@ -46,6 +46,7 @@ export class ExtensionInfo { this.isPreview = !!packageJSON?.preview; this.isInCloudIDE = process.env.CLOUD_SHELL === 'true' || + process.env.MONOSPACE_ENV === 'true' || process.env.CODESPACES === 'true' || !!process.env.GITPOD_WORKSPACE_ID; } diff --git a/src/const.ts b/extension/src/const.ts similarity index 100% rename from src/const.ts rename to extension/src/const.ts diff --git a/src/context.ts b/extension/src/context.ts similarity index 100% rename from src/context.ts rename to extension/src/context.ts diff --git a/src/debugAdapter/README.md b/extension/src/debugAdapter/README.md similarity index 100% rename from src/debugAdapter/README.md rename to extension/src/debugAdapter/README.md diff --git a/src/debugAdapter/goDebug.ts b/extension/src/debugAdapter/goDebug.ts similarity index 99% rename from src/debugAdapter/goDebug.ts rename to extension/src/debugAdapter/goDebug.ts index cf1eb3e17f..526f185cb2 100644 --- a/src/debugAdapter/goDebug.ts +++ b/extension/src/debugAdapter/goDebug.ts @@ -1628,7 +1628,9 @@ export class GoDebugSession extends LoggingDebugSession { response, 2007, 'Unable to list global vars: "{e}"', - { e: listPkgVarsErr.toString() } + { + e: listPkgVarsErr.toString() + } ); } const globals = this.delve?.isApiV1 @@ -2088,7 +2090,9 @@ export class GoDebugSession extends LoggingDebugSession { response, 2001, 'Failed to get remote server version: "{e}"', - { e: err.toString() } + { + e: err.toString() + } ); } const clientVersion = this.delve?.isApiV1 ? 1 : 2; diff --git a/src/diffUtils.ts b/extension/src/diffUtils.ts similarity index 100% rename from src/diffUtils.ts rename to extension/src/diffUtils.ts diff --git a/src/export.d.ts b/extension/src/export.d.ts similarity index 100% rename from src/export.d.ts rename to extension/src/export.d.ts diff --git a/src/extensionAPI.ts b/extension/src/extensionAPI.ts similarity index 100% rename from src/extensionAPI.ts rename to extension/src/extensionAPI.ts diff --git a/src/goBaseCodelens.ts b/extension/src/goBaseCodelens.ts similarity index 100% rename from src/goBaseCodelens.ts rename to extension/src/goBaseCodelens.ts diff --git a/src/goBrowsePackage.ts b/extension/src/goBrowsePackage.ts similarity index 100% rename from src/goBrowsePackage.ts rename to extension/src/goBrowsePackage.ts diff --git a/src/goBuild.ts b/extension/src/goBuild.ts similarity index 98% rename from src/goBuild.ts rename to extension/src/goBuild.ts index 5f0462ebb2..5df6d00dec 100644 --- a/src/goBuild.ts +++ b/extension/src/goBuild.ts @@ -45,7 +45,6 @@ export function buildCode(buildWorkspace?: boolean): CommandFactory { const documentUri = editor?.document.uri; const goConfig = getGoConfig(documentUri); - outputChannel.clear(); // Ensures stale output from build on save is cleared diagnosticsStatusBarItem.show(); diagnosticsStatusBarItem.text = 'Building...'; @@ -156,7 +155,7 @@ export async function goBuild( if (currentGoWorkspace && !isMod) { importPath = cwd.substr(currentGoWorkspace.length + 1); } else { - outputChannel.appendLine( + outputChannel.error( `Not able to determine import path of current package by using cwd: ${cwd} and Go workspace: ${currentGoWorkspace}` ); } diff --git a/src/goCheck.ts b/extension/src/goCheck.ts similarity index 98% rename from src/goCheck.ts rename to extension/src/goCheck.ts index c71574b820..3231649443 100644 --- a/src/goCheck.ts +++ b/extension/src/goCheck.ts @@ -61,7 +61,7 @@ export function check( goConfig: vscode.WorkspaceConfiguration ): Promise { diagnosticsStatusBarItem.hide(); - outputChannel.clear(); + outputChannel.appendLine('Running checks...'); const runningToolsPromises = []; const cwd = path.dirname(fileUri.fsPath); diff --git a/src/goCover.ts b/extension/src/goCover.ts similarity index 100% rename from src/goCover.ts rename to extension/src/goCover.ts diff --git a/src/goDebugConfiguration.ts b/extension/src/goDebugConfiguration.ts similarity index 94% rename from src/goDebugConfiguration.ts rename to extension/src/goDebugConfiguration.ts index 1d1a1baba2..caebceaccf 100644 --- a/src/goDebugConfiguration.ts +++ b/extension/src/goDebugConfiguration.ts @@ -183,25 +183,36 @@ export class GoDebugConfigurationProvider implements vscode.DebugConfigurationPr } } // If neither launch.json nor settings.json gave us the debugAdapter value, we go with the default - // from package.json (dlv-dap) unless this is remote attach with a stable release. + // from package.json (dlv-dap). if (!debugConfiguration['debugAdapter']) { debugConfiguration['debugAdapter'] = defaultConfig.debugAdapter.default; - if (debugConfiguration['mode'] === 'remote' && !extensionInfo.isPreview) { - debugConfiguration['debugAdapter'] = 'legacy'; - } - } - if (debugConfiguration['debugAdapter'] === 'dlv-dap') { - if (debugConfiguration['mode'] === 'remote') { - // This needs to use dlv at version 'v1.7.3-0.20211026171155-b48ceec161d5' or later, - // but we have no way of detectng that with an external server ahead of time. - // If an earlier version is used, the attach will fail with warning about versions. - } else if (debugConfiguration['port']) { + if ( + debugConfiguration.request === 'attach' && + debugConfiguration['mode'] === 'remote' && + !extensionInfo.isPreview + ) { this.showWarning( - 'ignorePortUsedInDlvDapWarning', - "`port` with 'dlv-dap' debugAdapter connects to [an external `dlv dap` server](https://github.com/golang/vscode-go/blob/master/docs/debugging.md#running-debugee-externally) to launch a program or attach to a process. Remove 'host' and 'port' from your launch.json if you have not launched a 'dlv dap' server." + 'ignoreDefaultDebugAdapterChangeWarning', + "We are using the 'dlv-dap' integration for remote debugging by default. Please comment on [issue 3096](https://github.com/golang/vscode-go/issues/3096) if this impacts your workflows." ); } } + if (debugConfiguration['debugAdapter'] === 'legacy') { + this.showWarning( + 'ignoreLegacyDADeprecationWarning', + 'Legacy debug adapter is deprecated. Please comment on [issue 3096](https://github.com/golang/vscode-go/issues/3096) if this impacts your workflows.' + ); + } + if ( + debugConfiguration['debugAdapter'] === 'dlv-dap' && + debugConfiguration.request === 'launch' && + debugConfiguration['port'] + ) { + this.showWarning( + 'ignorePortUsedInDlvDapWarning', + "`port` with 'dlv-dap' debugAdapter connects to [a `dlv dap` server](https://github.com/golang/vscode-go/wiki/debugging#run-debugee-externally) to launch a program or attach to a process. Remove 'host'/'port' from your launch.json configuration if you have not launched a 'dlv dap' server." + ); + } const debugAdapter = debugConfiguration['debugAdapter'] === 'dlv-dap' ? 'dlv-dap' : 'dlv'; @@ -311,7 +322,7 @@ export class GoDebugConfigurationProvider implements vscode.DebugConfigurationPr const toolsManagementConfig = getGoConfig()['toolsManagement']; if (toolsManagementConfig && toolsManagementConfig['autoUpdate'] === true) { const goVersion = await getGoVersion(); - await installTools([tool], goVersion, true); + await installTools([tool], goVersion, { silent: true }); } else { await promptForUpdatingTool(tool.name); } diff --git a/src/goDebugFactory.ts b/extension/src/goDebugFactory.ts similarity index 94% rename from src/goDebugFactory.ts rename to extension/src/goDebugFactory.ts index e57169eeb5..85542b0c2d 100644 --- a/src/goDebugFactory.ts +++ b/extension/src/goDebugFactory.ts @@ -12,7 +12,6 @@ import getPort = require('get-port'); import path = require('path'); import * as fs from 'fs'; import * as net from 'net'; -import { Logger, logVerbose, TimestampedLogger } from './goLogging'; import { DebugProtocol } from 'vscode-debugprotocol'; import { getWorkspaceFolderPath } from './util'; import { getEnvPath, getBinPathFromEnvVar } from './utils/pathUtils'; @@ -20,7 +19,7 @@ import { GoExtensionContext } from './context'; import { createRegisterCommand } from './commands'; export function activate(ctx: vscode.ExtensionContext, goCtx: GoExtensionContext) { - const debugOutputChannel = vscode.window.createOutputChannel('Go Debug'); + const debugOutputChannel = vscode.window.createOutputChannel('Go Debug', { log: true }); ctx.subscriptions.push(debugOutputChannel); const factory = new GoDebugAdapterDescriptorFactory(debugOutputChannel); @@ -40,7 +39,7 @@ export function activate(ctx: vscode.ExtensionContext, goCtx: GoExtensionContext } class GoDebugAdapterDescriptorFactory implements vscode.DebugAdapterDescriptorFactory { - constructor(private outputChannel?: vscode.OutputChannel) {} + constructor(private outputChannel: vscode.LogOutputChannel) {} public createDebugAdapterDescriptor( session: vscode.DebugSession, @@ -59,11 +58,11 @@ class GoDebugAdapterDescriptorFactory implements vscode.DebugAdapterDescriptorFa private async createDebugAdapterDescriptorDlvDap( configuration: vscode.DebugConfiguration ): Promise> { - const logger = new TimestampedLogger(configuration.trace, this.outputChannel); - logger.debug(`Config: ${JSON.stringify(configuration)}\n`); + const logger = this.outputChannel; + logger.debug(`Config: ${JSON.stringify(configuration)}`); if (configuration.port) { const host = configuration.host ?? '127.0.0.1'; - logger.info(`Connecting to DAP server at ${host}:${configuration.port}\n`); + logger.info(`Connecting to DAP server at ${host}:${configuration.port}`); return new vscode.DebugAdapterServer(configuration.port, host); } const d = new DelveDAPOutputAdapter(configuration, logger); @@ -72,28 +71,24 @@ class GoDebugAdapterDescriptorFactory implements vscode.DebugAdapterDescriptorFa } class GoDebugAdapterTrackerFactory implements vscode.DebugAdapterTrackerFactory { - constructor(private outputChannel: vscode.OutputChannel) {} + constructor(private outputChannel: vscode.LogOutputChannel) {} createDebugAdapterTracker(session: vscode.DebugSession) { - const level = session.configuration?.trace; - if (!level || level === 'off') { - return null; - } - const logger = new TimestampedLogger(session.configuration?.trace || 'off', this.outputChannel); + const logger = this.outputChannel; let requestsSent = 0; let responsesReceived = 0; return { onWillStartSession: () => - logger.debug(`session ${session.id} will start with ${JSON.stringify(session.configuration)}\n`), + logger.debug(`session ${session.id} will start with ${JSON.stringify(session.configuration)}`), onWillReceiveMessage: (message: any) => { - logger.trace(`client -> ${JSON.stringify(message)}\n`); + logger.trace(`client -> ${JSON.stringify(message)}`); requestsSent++; }, onDidSendMessage: (message: any) => { - logger.trace(`client <- ${JSON.stringify(message)}\n`); + logger.trace(`client <- ${JSON.stringify(message)}`); responsesReceived++; }, - onError: (error: Error) => logger.error(`error: ${error}\n`), + onError: (error: Error) => logger.error(`error: ${error}`), onWillStopSession: () => { if ( session.configuration.debugAdapter === 'dlv-dap' && @@ -109,7 +104,7 @@ class GoDebugAdapterTrackerFactory implements vscode.DebugAdapterTrackerFactory logger.debug(`session ${session.id} will stop\n`); }, onExit: (code: number | undefined, signal: string | undefined) => - logger.info(`debug adapter exited: (code: ${code}, signal: ${signal})\n`) + logger.info(`debug adapter exited: (code: ${code}, signal: ${signal})`) }; } @@ -118,6 +113,8 @@ class GoDebugAdapterTrackerFactory implements vscode.DebugAdapterTrackerFactory const TWO_CRLF = '\r\n\r\n'; +type ILogger = Pick; + // Proxies DebugProtocolMessage exchanges between VSCode and a remote // process or server connected through a duplex stream, after its // start method is called. @@ -126,10 +123,10 @@ export class ProxyDebugAdapter implements vscode.DebugAdapter { // connection from/to server (= dlv dap) private readable?: stream.Readable; private writable?: stream.Writable; - protected logger?: Logger; + protected logger: ILogger; private terminated = false; - constructor(logger: Logger) { + constructor(logger: ILogger) { this.logger = logger; this.onDidSendMessage = this.messageEmitter.event; } @@ -240,7 +237,7 @@ export class ProxyDebugAdapter implements vscode.DebugAdapter { // VSCode and a dlv dap process spawned and managed by this adapter. // It turns the process's stdout/stderrr into OutputEvent. export class DelveDAPOutputAdapter extends ProxyDebugAdapter { - constructor(private configuration: vscode.DebugConfiguration, logger: Logger) { + constructor(private configuration: vscode.DebugConfiguration, logger: ILogger) { super(logger); } @@ -252,7 +249,7 @@ export class DelveDAPOutputAdapter extends ProxyDebugAdapter { protected sendMessageToClient(message: vscode.DebugProtocolMessage) { const m = message as any; if (m.type === 'request') { - logVerbose(`do not forward reverse request: dropping ${JSON.stringify(m)}`); + this.logger.debug(`do not forward reverse request: dropping ${JSON.stringify(m)}`); return; } @@ -262,7 +259,7 @@ export class DelveDAPOutputAdapter extends ProxyDebugAdapter { protected async sendMessageToServer(message: vscode.DebugProtocolMessage): Promise { const m = message as any; if (m.type === 'response') { - logVerbose(`do not forward reverse request response: dropping ${JSON.stringify(m)}`); + this.logger.debug(`do not forward reverse request response: dropping ${JSON.stringify(m)}`); return; } @@ -353,7 +350,7 @@ export class DelveDAPOutputAdapter extends ProxyDebugAdapter { } catch (err) { return { connected: false, reason: err }; } - this.logger?.debug(`Running dlv dap server: pid=${this.dlvDapServer?.pid}\n`); + this.logger?.debug(`Running dlv dap server: pid=${this.dlvDapServer?.pid}`); return { connected: true }; } @@ -372,7 +369,7 @@ export class DelveDAPOutputAdapter extends ProxyDebugAdapter { // may not appear in the DEBUG CONSOLE. For easier debugging, log // the messages through the logger that prints to Go Debug output // channel. - this.logger?.info(msg); + this.logger?.trace(msg); }; // If a port has been specified, assume there is an already @@ -437,7 +434,7 @@ export class DelveDAPOutputAdapter extends ProxyDebugAdapter { try { const port = await getPort(); - const rendezvousServerPromise = waitForDAPServer(port, 30_000); + const rendezvousServerPromise = waitForDAPServer(port, 30_000, this.logger); dlvArgs.push(`--client-addr=:${port}`); @@ -470,7 +467,7 @@ function getSudo(): string | null { return sudoPath; } -function waitForDAPServer(port: number, timeoutMs: number): Promise { +function waitForDAPServer(port: number, timeoutMs: number, logger: ILogger): Promise { return new Promise((resolve, reject) => { // eslint-disable-next-line prefer-const let s: net.Server | undefined; @@ -482,7 +479,7 @@ function waitForDAPServer(port: number, timeoutMs: number): Promise }, timeoutMs); s = net.createServer({ pauseOnConnect: true }, (socket) => { - logVerbose( + logger.debug( `connected: ${port} (remote: ${socket.remoteAddress}:${socket.remotePort} local: ${socket.localAddress}:${socket.localPort})` ); clearTimeout(timeoutToken); @@ -491,7 +488,7 @@ function waitForDAPServer(port: number, timeoutMs: number): Promise resolve(socket); }); s.on('error', (err) => { - logVerbose(`connection error ${err}`); + logger.error(`connection error ${err}`); reject(err); }); s.maxConnections = 1; diff --git a/src/goDeveloperSurvey.ts b/extension/src/goDeveloperSurvey.ts similarity index 100% rename from src/goDeveloperSurvey.ts rename to extension/src/goDeveloperSurvey.ts diff --git a/src/goDocumentSymbols.ts b/extension/src/goDocumentSymbols.ts similarity index 100% rename from src/goDocumentSymbols.ts rename to extension/src/goDocumentSymbols.ts diff --git a/src/goEnv.ts b/extension/src/goEnv.ts similarity index 95% rename from src/goEnv.ts rename to extension/src/goEnv.ts index f416fe8b8f..138dcac760 100644 --- a/src/goEnv.ts +++ b/extension/src/goEnv.ts @@ -8,9 +8,9 @@ import vscode = require('vscode'); import { getGoConfig } from './config'; import { getCurrentGoPath, getToolsGopath, resolvePath, substituteEnv } from './util'; -import { logVerbose } from './goLogging'; import { dirExists } from './utils/pathUtils'; import { getFromGlobalState, updateGlobalState } from './stateUtils'; +import { outputChannel } from './goStatus'; // toolInstallationEnvironment returns the environment in which tools should // be installed. It always returns a new object. @@ -67,7 +67,7 @@ export function toolExecutionEnvironment(uri?: vscode.Uri, addProcessEnv = true) // Remove json flag (-json or --json=) from GOFLAGS because it will effect to result format of the execution if (env['GOFLAGS'] && env['GOFLAGS'].includes('-json')) { env['GOFLAGS'] = env['GOFLAGS'].replace(/(^|\s+)-?-json[^\s]*/g, ''); - logVerbose(`removed -json from GOFLAGS: ${env['GOFLAGS']}`); + outputChannel.debug(`removed -json from GOFLAGS: ${env['GOFLAGS']}`); } return env; } @@ -127,7 +127,9 @@ export async function setGOROOTEnvVar(configGOROOT: string) { }); } - logVerbose(`setting GOROOT = ${goroot} (old value: ${currentGOROOT}) because "go.goroot": "${configGOROOT}"`); + outputChannel.debug( + `setting GOROOT = ${goroot} (old value: ${currentGOROOT}) because "go.goroot": "${configGOROOT}"` + ); if (goroot) { process.env['GOROOT'] = goroot; } else { diff --git a/src/goEnvironmentStatus.ts b/extension/src/goEnvironmentStatus.ts similarity index 85% rename from src/goEnvironmentStatus.ts rename to extension/src/goEnvironmentStatus.ts index bbeb5b1aa5..48256a3fcc 100644 --- a/src/goEnvironmentStatus.ts +++ b/extension/src/goEnvironmentStatus.ts @@ -15,7 +15,6 @@ import path = require('path'); import { promisify } from 'util'; import { getGoConfig, extensionInfo } from './config'; import { toolInstallationEnvironment } from './goEnv'; -import { logVerbose } from './goLogging'; import { addGoStatus, goEnvStatusbarItem, outputChannel, removeGoStatus } from './goStatus'; import { getFromGlobalState, getFromWorkspaceState, updateGlobalState, updateWorkspaceState } from './stateUtils'; import { getBinPath, getCheckForToolsUpdatesConfig, getGoVersion, GoVersion } from './util'; @@ -28,9 +27,9 @@ import { dirExists } from './utils/pathUtils'; import vscode = require('vscode'); -import WebRequest = require('web-request'); import { installTool } from './goInstallTools'; import { CommandFactory } from './commands'; +import fetch from 'node-fetch'; export class GoEnvironmentOption implements vscode.QuickPickItem { readonly description: string; @@ -218,8 +217,6 @@ async function downloadGo(goOption: GoEnvironmentOption): Promise { - outputChannel.clear(); - outputChannel.show(); outputChannel.appendLine(`go install ${goOption.binpath}@latest`); const result = await installTool({ name: newExecutableName, @@ -229,7 +226,7 @@ async function downloadGo(goOption: GoEnvironmentOption): Promiseprocess.env[pathEnvVar]; } - logVerbose(`addGoRuntimeBase(${newGoRuntimeBase}) when PATH=${defaultPathEnv}`); + outputChannel.debug(`addGoRuntimeBase(${newGoRuntimeBase}) when PATH=${defaultPathEnv}`); // calling this multiple times will override the previous value. // environmentVariableCollection.clear(); @@ -356,7 +353,7 @@ export function clearGoRuntimeBaseFromPATH() { } const pathEnvVar = pathEnvVarName(); if (!pathEnvVar) { - logVerbose("couldn't find PATH property in process.env"); + outputChannel.debug("couldn't find PATH property in process.env"); return; } environmentVariableCollection?.delete(pathEnvVar); @@ -418,15 +415,15 @@ export function getGoEnvironmentStatusbarItem(): vscode.StatusBarItem { export function formatGoVersion(version?: GoVersion): string { if (!version || !version.isValid()) { - return 'Go (unknown)'; + return '(unknown)'; } const versionStr = version.format(true); const versionWords = versionStr.split(' '); if (versionWords.length > 1 && versionWords[0] === 'devel') { // go devel +hash or go devel go1.17-hash - return versionWords[1].startsWith('go') ? `Go ${versionWords[1].slice(2)}` : `Go ${versionWords[1]}`; + return versionWords[1].startsWith('go') ? `${versionWords[1].slice(2)}` : `${versionWords[1]}`; } else { - return `Go ${versionWords[0]}`; + return `${versionWords[0]}`; } } @@ -468,10 +465,12 @@ interface GoVersionWebResult { } async function fetchDownloadableGoVersions(): Promise { + // TODO: use `go list -m --versions -json go` when go1.20+ is the minimum supported version. // fetch information about what Go versions are available to install let webResults; try { - webResults = await WebRequest.json('https://go.dev/dl/?mode=json'); + const response = await fetch('https://go.dev/dl/?mode=json'); + webResults = (await response.json()) as GoVersionWebResult[]; } catch (error) { return []; } @@ -511,24 +510,20 @@ export async function getLatestGoVersions(): Promise { goVersions: results }); } catch (e) { - // hardcode the latest versions of Go in case golang.dl is unavailable - // TODO(hyangah): consider to remove these hardcoded versions and instead - // show error notification if necessary. - results = [ - new GoEnvironmentOption('golang.org/dl/go1.17.6', 'Go 1.17.6', false), - new GoEnvironmentOption('golang.org/dl/go1.16.13', 'Go 1.16.13', false) - ]; + results = []; } } return results; } -const STATUS_BAR_ITEM_NAME = 'Go Notification'; +const STATUS_BAR_ITEM_NAME = 'Go Update Notification'; const dismissedGoVersionUpdatesKey = 'dismissedGoVersionUpdates'; -export async function offerToInstallLatestGoVersion() { +export async function offerToInstallLatestGoVersion(ctx: Pick) { if (extensionInfo.isInCloudIDE) { + // TODO: As we use the language status bar, the notification is less visible + // and we can consider to remove this condition check. return; } const goConfig = getGoConfig(); @@ -555,59 +550,66 @@ export async function offerToInstallLatestGoVersion() { // notify user that there is a newer version of Go available if (options.length > 0) { - addGoStatus( - STATUS_BAR_ITEM_NAME, - 'Go Update Available', - 'go.promptforgoinstall', - 'A newer version of Go is available' - ); - vscode.commands.registerCommand('go.promptforgoinstall', () => { - const download = { - title: 'Download', - async command() { - await vscode.env.openExternal(vscode.Uri.parse('https://go.dev/dl/')); - } - }; - - const neverAgain = { - title: "Don't Show Again", - async command() { - // mark these versions as seen - dismissedOptions = await getFromGlobalState(dismissedGoVersionUpdatesKey); - if (!dismissedOptions) { - dismissedOptions = []; + const versionsText = options.map((x) => x.label).join(', '); + const statusBarItem = addGoStatus(STATUS_BAR_ITEM_NAME); + statusBarItem.name = STATUS_BAR_ITEM_NAME; + statusBarItem.text = 'New Go version is available'; + statusBarItem.detail = versionsText; + statusBarItem.command = { + title: 'Upgrade', + command: 'go.promptforgoinstall', + arguments: [options], + tooltip: 'Upgrade or silence notification' + }; + // TODO: Error level is more visible. Consider to make it configurable? + statusBarItem.severity = vscode.LanguageStatusSeverity.Warning; + + ctx.subscriptions.push( + vscode.commands.registerCommand('go.promptforgoinstall', () => { + const download = { + title: 'Download', + async command() { + await vscode.env.openExternal(vscode.Uri.parse('https://go.dev/dl/')); } - options.forEach((version) => { - dismissedOptions.push(version); - }); - await updateGlobalState(dismissedGoVersionUpdatesKey, dismissedOptions); + }; + + const neverAgain = { + title: "Don't Show Again", + async command() { + // mark these versions as seen + dismissedOptions = await getFromGlobalState(dismissedGoVersionUpdatesKey); + if (!dismissedOptions) { + dismissedOptions = []; + } + options.forEach((version) => { + dismissedOptions.push(version); + }); + await updateGlobalState(dismissedGoVersionUpdatesKey, dismissedOptions); + } + }; + + let versionsText: string; + if (options.length > 1) { + versionsText = `${options + .map((x) => x.label) + .reduce((prev, next) => { + return prev + ' and ' + next; + })} are available`; + } else { + versionsText = `${options[0].label} is available`; } - }; - - let versionsText: string; - if (options.length > 1) { - versionsText = `${options - .map((x) => x.label) - .reduce((prev, next) => { - return prev + ' and ' + next; - })} are available`; - } else { - versionsText = `${options[0].label} is available`; - } - vscode.window - .showInformationMessage( - `${versionsText}. You are currently using ${formatGoVersion(currentVersion)}.`, - download, - neverAgain - ) - .then((selection) => { - // TODO: should we removeGoStatus if user has closed the notification - // without any action? It's kind of a feature now - without selecting - // neverAgain, user can hide this statusbar item. - removeGoStatus(STATUS_BAR_ITEM_NAME); - selection?.command(); - }); - }); + vscode.window + .showInformationMessage( + `${versionsText}. You are currently using ${formatGoVersion(currentVersion)}.`, + download, + neverAgain + ) + .then((selection) => { + selection?.command(); + removeGoStatus(STATUS_BAR_ITEM_NAME); + }); + }) + ); } } diff --git a/src/goExplorer.ts b/extension/src/goExplorer.ts similarity index 100% rename from src/goExplorer.ts rename to extension/src/goExplorer.ts diff --git a/src/goGenerateTests.ts b/extension/src/goGenerateTests.ts similarity index 99% rename from src/goGenerateTests.ts rename to extension/src/goGenerateTests.ts index d2ee0ad3af..00cb913987 100644 --- a/src/goGenerateTests.ts +++ b/extension/src/goGenerateTests.ts @@ -202,8 +202,7 @@ function generateTests( return resolve(false); } if (err) { - console.log(err); - outputChannel.appendLine(err.message); + outputChannel.error(err.message); return reject('Cannot generate test due to errors'); } diff --git a/src/goGetPackage.ts b/extension/src/goGetPackage.ts similarity index 95% rename from src/goGetPackage.ts rename to extension/src/goGetPackage.ts index 46bb542b0f..0d27eec71d 100644 --- a/src/goGetPackage.ts +++ b/extension/src/goGetPackage.ts @@ -35,9 +35,7 @@ export const goGetPackage: CommandFactory = (ctx, goCtx) => () => { cp.execFile(goRuntimePath, ['get', '-v', importPath], { env }, (err, stdout, stderr) => { // go get -v uses stderr to write output regardless of success or failure if (stderr !== '') { - outputChannel.show(); - outputChannel.clear(); - outputChannel.appendLine(stderr); + outputChannel.error(stderr); buildCode(false)(ctx, goCtx)(); return; } diff --git a/src/goImpl.ts b/extension/src/goImpl.ts similarity index 100% rename from src/goImpl.ts rename to extension/src/goImpl.ts diff --git a/src/goImport.ts b/extension/src/goImport.ts similarity index 100% rename from src/goImport.ts rename to extension/src/goImport.ts diff --git a/src/goInstall.ts b/extension/src/goInstall.ts similarity index 94% rename from src/goInstall.ts rename to extension/src/goInstall.ts index 2e006c8909..52aab35631 100644 --- a/src/goInstall.ts +++ b/extension/src/goInstall.ts @@ -58,11 +58,13 @@ export const installCurrentPackage: CommandFactory = () => async () => { const importPath = currentGoWorkspace && !isMod ? cwd.substr(currentGoWorkspace.length + 1) : '.'; args.push(importPath); - outputChannel.clear(); - outputChannel.show(); outputChannel.appendLine(`Installing ${importPath === '.' ? 'current package' : importPath}`); cp.execFile(goRuntimePath, args, { env, cwd }, (err, stdout, stderr) => { - outputChannel.appendLine(err ? `Installation failed: ${stderr}` : 'Installation successful'); + if (err) { + outputChannel.error(`Installation failed: ${stderr}`); + } else { + outputChannel.appendLine('Installation successful'); + } }); }; diff --git a/src/goInstallTools.ts b/extension/src/goInstallTools.ts similarity index 77% rename from src/goInstallTools.ts rename to extension/src/goInstallTools.ts index 09be365e8e..8d570c7949 100644 --- a/src/goInstallTools.ts +++ b/extension/src/goInstallTools.ts @@ -16,7 +16,6 @@ import { ConfigurationTarget } from 'vscode'; import { extensionInfo, getGoConfig, getGoplsConfig } from './config'; import { toolExecutionEnvironment, toolInstallationEnvironment } from './goEnv'; import { addGoRuntimeBaseToPATH, clearGoRuntimeBaseFromPATH } from './goEnvironmentStatus'; -import { logVerbose, logError } from './goLogging'; import { GoExtensionContext } from './context'; import { addGoStatus, initGoStatusBar, outputChannel, removeGoStatus } from './goStatus'; import { containsTool, getConfiguredTools, getImportPathWithVersion, getTool, Tool, ToolAtVersion } from './goTools'; @@ -30,10 +29,18 @@ import { GoVersion, rmdirRecursive } from './util'; -import { getEnvPath, getCurrentGoRoot, setCurrentGoRoot } from './utils/pathUtils'; +import { + getEnvPath, + getCurrentGoRoot, + setCurrentGoRoot, + correctBinname, + executableFileExists +} from './utils/pathUtils'; import util = require('util'); import vscode = require('vscode'); import { RestartReason } from './language/goLanguageServer'; +import { telemetryReporter } from './goTelemetry'; +import { allToolsInformation } from './goToolsInformation'; const STATUS_BAR_ITEM_NAME = 'Go Tools'; @@ -43,6 +50,16 @@ const declinedUpdates: Tool[] = []; // declinedUpdates tracks the tools that the user has declined to install. const declinedInstalls: Tool[] = []; +export interface IToolsManager { + getMissingTools(filter: (tool: Tool) => boolean): Promise; + installTool(tool: Tool, goVersion: GoVersion, env: NodeJS.Dict): Promise; +} + +const defaultToolsManager: IToolsManager = { + getMissingTools, + installTool: installToolWithGo +}; + export async function installAllTools(updateExistingToolsOnly = false) { const goVersion = await getGoVersion(); let allTools = getConfiguredTools(getGoConfig(), getGoplsConfig()); @@ -88,28 +105,31 @@ export async function installAllTools(updateExistingToolsOnly = false) { ); } -export async function getGoForInstall(goVersion: GoVersion, silent?: boolean): Promise { +async function getGoForInstall(goVersion: GoVersion, silent?: boolean): Promise { const configured = getGoConfig().get('toolsManagement.go'); if (!configured) { - return goVersion; + return goVersion; // use the default. } try { const go = await getGoVersion(configured); if (go) return go; } catch (e) { - logError(`getGoForInstall failed to run 'go version' with the configured go for tool install: ${e}`); - } finally { if (!silent) { - outputChannel.appendLine( - `Ignoring misconfigured 'go.toolsManagement.go' (${configured}). Provide a valid path to the Go command.` + outputChannel.error( + `failed to run "go version" with "${configured}". Provide a valid path to the Go binary` ); } } - return goVersion; } +interface installToolsOptions { + silent?: boolean; + skipRestartGopls?: boolean; + toolsManager?: IToolsManager; +} + /** * Installs given array of missing tools. If no input is given, the all tools are installed * @@ -122,12 +142,12 @@ export async function getGoForInstall(goVersion: GoVersion, silent?: boolean): P export async function installTools( missing: ToolAtVersion[], goVersion: GoVersion, - silent?: boolean + options?: installToolsOptions ): Promise<{ tool: ToolAtVersion; reason: string }[]> { if (!missing) { return []; } - + const { silent, skipRestartGopls } = options || {}; if (!silent) { outputChannel.show(); } @@ -177,11 +197,12 @@ export async function installTools( outputChannel.appendLine(''); // Blank line for spacing. const failures: { tool: ToolAtVersion; reason: string }[] = []; + const tm = options?.toolsManager ?? defaultToolsManager; for (const tool of missing) { - const failed = await installToolWithGo(tool, goForInstall, envForTools); + const failed = await tm.installTool(tool, goForInstall, envForTools); if (failed) { failures.push({ tool, reason: failed }); - } else if (tool.name === 'gopls') { + } else if (tool.name === 'gopls' && !skipRestartGopls) { // Restart the language server if a new binary has been installed. vscode.commands.executeCommand('go.languageserver.restart', RestartReason.INSTALLATION); } @@ -202,6 +223,10 @@ export async function installTools( outputChannel.appendLine(`${failure.tool.name}: ${failure.reason} `); } } + if (missing.some((tool) => tool.isImportant)) { + // if we just installed important tools, update the status bar. + updateImportantToolsStatus(tm); + } return failures; } @@ -267,7 +292,7 @@ async function installToolWithGoInstall(goVersion: GoVersion, env: NodeJS.Dict const { binPath, why } = getBinPathWithExplanation('go', false); const goRuntimePath = binPath; - logVerbose(`updateGoVarsFromConfig: found 'go' in ${goRuntimePath}`); + outputChannel.debug(`updateGoVarsFromConfig: found 'go' in ${goRuntimePath}`); if (!goRuntimePath || !path.isAbsolute(goRuntimePath)) { // getBinPath returns the absolute path to the tool if it exists. // Otherwise, it may return the tool name (e.g. 'go'). @@ -458,9 +483,10 @@ export function updateGoVarsFromConfig(goCtx: GoExtensionContext): Promise outputChannel.append(`'${goRuntimePath} env': ${stderr}`); outputChannel.show(); } - logVerbose(`${goRuntimePath} env ...:\n${stdout}`); + outputChannel.trace(`${goRuntimePath} env ...:\n${stdout}`); const envOutput = JSON.parse(stdout); if (envOutput.GOROOT && envOutput.GOROOT.trim()) { + outputChannel.debug('setCurrentGOROOT:', envOutput.GOROOT); setCurrentGoRoot(envOutput.GOROOT.trim()); delete envOutput.GOROOT; } @@ -489,60 +515,107 @@ export function updateGoVarsFromConfig(goCtx: GoExtensionContext): Promise }); } -let alreadyOfferedToInstallTools = false; +// maybeInstallImportantTools checks whether important tools are installed, +// and tries to auto-install them if missing. +export async function maybeInstallImportantTools( + alternateTools: { [key: string]: string } | undefined, + tm: IToolsManager = defaultToolsManager +): Promise { + const statusBarItem = addGoStatus(STATUS_BAR_ITEM_NAME); + statusBarItem.name = STATUS_BAR_ITEM_NAME; + statusBarItem.text = 'Analysis tools'; -export async function offerToInstallTools() { - if (alreadyOfferedToInstallTools) { - return; + try { + statusBarItem.busy = true; + let missing = await tm.getMissingTools((tool: Tool) => { + return tool.isImportant; + }); // expect gopls and a linter. + + // Initial install. + if (missing.length > 0) { + outputChannel.show(); // Best effort: make it visible so users can see the progress. + statusBarItem.detail = missing.map((tool) => tool.name).join(', '); + const goVersion = await getGoVersion(); + // filter out tools with 'alternateTools' setting. updateImportantToolsStatus will + // recompute missing tools and recognize tools still missing. + if (alternateTools) { + missing = missing + .map((tool) => { + if (alternateTools[tool.name]) { + outputChannel.appendLine( + `skip installing ${ + tool.name + } because the 'alternateTools' setting is configured to use ${ + alternateTools[tool.name] + } instead.` + ); + } + return tool; + }) + .filter((tool) => !alternateTools[tool.name]); + } + await installTools(missing, goVersion, { toolsManager: tm, skipRestartGopls: true }); + // installTools will update ImportantToolsStatus. + } else { + // no essential tools to be installed. + await updateImportantToolsStatus(tm); + } + } catch (e) { + outputChannel.appendLine('install missing tools failed - ' + JSON.stringify(e)); + } finally { + statusBarItem.busy = false; } - alreadyOfferedToInstallTools = true; + return statusBarItem; +} - const goVersion = await getGoVersion(); - let missing = await getMissingTools(); - missing = missing.filter((x) => x.isImportant); - if (missing.length > 0) { - addGoStatus( - STATUS_BAR_ITEM_NAME, - 'Analysis Tools Missing', - 'go.promptforinstall', - 'Not all Go tools are available on the GOPATH' - ); - vscode.commands.registerCommand('go.promptforinstall', () => { - const installItem = { - title: 'Install', - async command() { - removeGoStatus(STATUS_BAR_ITEM_NAME); - await installTools(missing, goVersion); - } - }; - const showItem = { - title: 'Show', - command() { - outputChannel.clear(); - outputChannel.show(); - outputChannel.appendLine('Below tools are needed for the basic features of the Go extension.'); - missing.forEach((x) => outputChannel.appendLine(` ${x.name}`)); - } - }; - vscode.window - .showInformationMessage( - 'Failed to find some of the Go analysis tools. Would you like to install them?', - installItem, - showItem - ) - .then((selection) => { - if (selection) { - selection.command(); - } else { - removeGoStatus(STATUS_BAR_ITEM_NAME); - } - }); - }); +async function updateImportantToolsStatus(tm: IToolsManager = defaultToolsManager): Promise { + const statusBarItem = addGoStatus(STATUS_BAR_ITEM_NAME); + let missing: Tool[] | null = null; + try { + missing = await tm.getMissingTools((tool: Tool) => { + return tool.isImportant; + }); // expect gopls and a linter. + } catch (e) { + // ignore. + } + + if (missing === null) { + statusBarItem.severity = vscode.LanguageStatusSeverity.Error; + statusBarItem.detail = 'failed to compute missing tools'; + statusBarItem.command = { + command: 'go.tools.install', + title: 'Retry', + tooltip: 'Install/Update Tools' + }; + return; + } else if (missing.length === 0) { + statusBarItem.severity = vscode.LanguageStatusSeverity.Information; + statusBarItem.detail = 'no missing tools'; + statusBarItem.command = { + command: 'go.tools.install', + title: 'Update', + tooltip: 'Install/Update Tools' + }; + return; + } else { + statusBarItem.severity = vscode.LanguageStatusSeverity.Error; + statusBarItem.detail = `missing ${missing.map((tool) => tool.name).join(',')}`; + statusBarItem.command = { + command: 'go.tools.install', + arguments: missing.map((tool) => tool.name), + title: 'Install missing tools', + tooltip: `Install ${missing.join(',')}` + }; } } -function getMissingTools(): Promise { - const keys = getConfiguredTools(getGoConfig(), getGoplsConfig()); +// getMissingTools returns missing tools. +// If matcher is provided, only the tools that match the filter will be checked. +function getMissingTools(matcher?: (value: Tool) => boolean): Promise { + let keys = getConfiguredTools(getGoConfig(), getGoplsConfig()); + if (matcher) { + keys = keys.filter(matcher); + } return Promise.all( keys.map( (tool) => @@ -599,7 +672,10 @@ export async function latestToolVersion(tool: Tool, includePrerelease?: boolean) const { stdout } = await execFile( goCmd, ['list', '-m', '--versions', '-json', `${tool.modulePath}@${version}`], - { env, cwd: tmpDir } + { + env, + cwd: tmpDir + } ); const m = JSON.parse(stdout); // Versions field is a list of all known versions of the module, @@ -706,7 +782,7 @@ export async function suggestUpdates() { // without prompting. const toolsManagementConfig = getGoConfig()['toolsManagement']; if (toolsManagementConfig && toolsManagementConfig['autoUpdate'] === true) { - installTools(toolsToUpdate, configuredGoVersion, true); + installTools(toolsToUpdate, configuredGoVersion, { silent: true }); } else { const updateToolsCmdText = 'Update tools'; const selected = await vscode.window.showWarningMessage( @@ -781,3 +857,48 @@ export async function listOutdatedTools(configuredGoVersion: GoVersion | undefin ); return oldTools.filter((tool): tool is Tool => !!tool); } + +// maybeInstallVSCGO is a special program released and installed with the Go extension. +// Unlike other tools, it is installed under the extension path (which is cleared +// when a new version is installed). +export async function maybeInstallVSCGO( + extensionMode: vscode.ExtensionMode, + extensionId: string, + extensionVersion: string, + extensionPath: string, + isPreview: boolean +): Promise { + // golang.go stable, golang.go-nightly stable -> install once per version. + // golang.go dev through launch.json -> install every time. + const progPath = path.join(extensionPath, 'bin', correctBinname('vscgo')); + + if (extensionMode === vscode.ExtensionMode.Production && executableFileExists(progPath)) { + return progPath; // reuse existing executable. + } + telemetryReporter.add('vscgo_install', 1); + const mkdir = util.promisify(fs.mkdir); + await mkdir(path.dirname(progPath), { recursive: true }); + const execFile = util.promisify(cp.execFile); + + const cwd = path.join(extensionPath); + const env = toolExecutionEnvironment(); + env['GOBIN'] = path.dirname(progPath); + + const importPath = allToolsInformation['vscgo'].importPath; + const version = + extensionMode !== vscode.ExtensionMode.Production + ? '' + : extensionId !== 'golang.go' || isPreview + ? '@master' + : `@v${extensionVersion}`; + // build from source acquired from the module proxy if this is a non-preview version. + try { + const args = ['install', `${importPath}${version}`]; + console.log(`installing vscgo: ${args.join(' ')}`); + await execFile(getBinPath('go'), args, { cwd, env }); + return progPath; + } catch (e) { + telemetryReporter.add('vscgo_install_fail', 1); + return Promise.reject(`failed to install vscgo - ${e}`); + } +} diff --git a/src/goLint.ts b/extension/src/goLint.ts similarity index 98% rename from src/goLint.ts rename to extension/src/goLint.ts index 4f2c5c5e8f..b9d64503f9 100644 --- a/src/goLint.ts +++ b/extension/src/goLint.ts @@ -35,7 +35,7 @@ export function lintCode(scope?: string): CommandFactory { const goConfig = getGoConfig(documentUri); const goplsConfig = getGoplsConfig(documentUri); - outputChannel.clear(); // Ensures stale output from lint on save is cleared + outputChannel.appendLine('Linting...'); diagnosticsStatusBarItem.show(); diagnosticsStatusBarItem.text = 'Linting...'; diff --git a/src/goMain.ts b/extension/src/goMain.ts similarity index 91% rename from src/goMain.ts rename to extension/src/goMain.ts index 1b6eb9588d..b1221e4bbb 100644 --- a/src/goMain.ts +++ b/extension/src/goMain.ts @@ -8,7 +8,7 @@ 'use strict'; -import { getGoConfig } from './config'; +import { extensionInfo, getGoConfig } from './config'; import { browsePackages } from './goBrowsePackage'; import { buildCode } from './goBuild'; import { notifyIfGeneratedFile, removeTestStatus } from './goCheck'; @@ -32,12 +32,17 @@ import * as goGenerateTests from './goGenerateTests'; import { goGetPackage } from './goGetPackage'; import { addImport, addImportToWorkspace } from './goImport'; import { installCurrentPackage } from './goInstall'; -import { offerToInstallTools, promptForMissingTool, updateGoVarsFromConfig, suggestUpdates } from './goInstallTools'; +import { + promptForMissingTool, + updateGoVarsFromConfig, + suggestUpdates, + maybeInstallVSCGO, + maybeInstallImportantTools +} from './goInstallTools'; import { RestartReason, showServerOutputChannel, watchLanguageServerConfiguration } from './language/goLanguageServer'; import { lintCode } from './goLint'; -import { setLogConfig } from './goLogging'; import { GO_MODE } from './goMode'; -import { GO111MODULE, goModInit, isModSupported } from './goModules'; +import { GO111MODULE, goModInit } from './goModules'; import { playgroundCommand } from './goPlayground'; import { GoRunTestCodeLensProvider } from './goRunTestCodelens'; import { disposeGoStatusBar, expandGoStatusBar, outputChannel, updateGoStatusBar } from './goStatus'; @@ -52,7 +57,7 @@ import { updateGlobalState } from './stateUtils'; import { cancelRunningTests, showTestOutput } from './testUtils'; -import { cleanupTempDir, getBinPath, getToolsGopath, isGoPathSet } from './util'; +import { cleanupTempDir, getBinPath, getToolsGopath } from './util'; import { clearCacheForTools } from './utils/pathUtils'; import { WelcomePanel } from './welcome'; import vscode = require('vscode'); @@ -67,6 +72,7 @@ import { GoExtensionContext } from './context'; import * as commands from './commands'; import { toggleVulncheckCommandFactory } from './goVulncheck'; import { GoTaskProvider } from './goTaskProvider'; +import { telemetryReporter } from './goTelemetry'; const goCtx: GoExtensionContext = {}; @@ -76,13 +82,12 @@ export async function activate(ctx: vscode.ExtensionContext): Promise telemetryReporter.setTool(path)) + .catch((reason) => console.error(reason)); const registerCommand = commands.createRegisterCommand(ctx, goCtx); registerCommand('go.languageserver.restart', commands.startLanguageServer); registerCommand('go.languageserver.maintain', commands.startGoplsMaintainerInterface); + await maybeInstallImportantTools(cfg.get('alternateTools')); await commands.startLanguageServer(ctx, goCtx)(RestartReason.ACTIVATION); + suggestUpdates(); + offerToInstallLatestGoVersion(ctx); + initCoverageDecorators(ctx); registerCommand('go.builds.run', commands.runBuilds); @@ -201,16 +217,35 @@ export async function activate(ctx: vscode.ExtensionContext): Promise vscode.languages.match(selector, document)); } + +export const GoDocumentSelector = [ + // gopls handles only file URIs. + { language: 'go', scheme: 'file' }, + { language: 'go.mod', scheme: 'file' }, + { language: 'go.sum', scheme: 'file' }, + { language: 'go.work', scheme: 'file' }, + { language: 'gotmpl', scheme: 'file' } +]; diff --git a/src/goModifytags.ts b/extension/src/goModifytags.ts similarity index 100% rename from src/goModifytags.ts rename to extension/src/goModifytags.ts diff --git a/src/goModules.ts b/extension/src/goModules.ts similarity index 98% rename from src/goModules.ts rename to extension/src/goModules.ts index 822846cb7f..313f7e11e8 100644 --- a/src/goModules.ts +++ b/extension/src/goModules.ts @@ -127,8 +127,6 @@ export async function getCurrentPackage(cwd: string): Promise { } export const goModInit: CommandFactory = () => async () => { - outputChannel.clear(); - const moduleName = await vscode.window.showInputBox({ prompt: 'Enter module name', value: '', @@ -149,7 +147,7 @@ export const goModInit: CommandFactory = () => async () => { outputChannel.appendLine('Module successfully initialized. You are ready to Go :)'); vscode.commands.executeCommand('vscode.open', vscode.Uri.file(path.join(cwd, 'go.mod'))); } catch (e) { - outputChannel.appendLine((e as Error).message); + outputChannel.error((e as Error).message); outputChannel.show(); vscode.window.showErrorMessage( `Error running "${goRuntimePath} mod init ${moduleName}": See Go output channel for details` diff --git a/src/goPackages.ts b/extension/src/goPackages.ts similarity index 100% rename from src/goPackages.ts rename to extension/src/goPackages.ts diff --git a/src/goPlayground.ts b/extension/src/goPlayground.ts similarity index 100% rename from src/goPlayground.ts rename to extension/src/goPlayground.ts diff --git a/src/goRunTestCodelens.ts b/extension/src/goRunTestCodelens.ts similarity index 100% rename from src/goRunTestCodelens.ts rename to extension/src/goRunTestCodelens.ts diff --git a/src/goStatus.ts b/extension/src/goStatus.ts similarity index 70% rename from src/goStatus.ts rename to extension/src/goStatus.ts index 6ce338b514..91c57b6c23 100644 --- a/src/goStatus.ts +++ b/extension/src/goStatus.ts @@ -11,14 +11,15 @@ import vscode = require('vscode'); import vscodeUri = require('vscode-uri'); import { getGoConfig } from './config'; import { formatGoVersion, GoEnvironmentOption, terminalCreationListener } from './goEnvironmentStatus'; -import { isGoFile } from './goMode'; -import { isModSupported, runGoEnv } from './goModules'; +import { GoDocumentSelector, isGoFile } from './goMode'; +import { runGoEnv } from './goModules'; import { allToolsInformation } from './goToolsInformation'; import { getGoVersion } from './util'; import { GoExtensionContext } from './context'; import { CommandFactory } from './commands'; +import { LanguageClient, State } from 'vscode-languageclient/node'; -export const outputChannel = vscode.window.createOutputChannel('Go'); +export const outputChannel = vscode.window.createOutputChannel('Go', { log: true }); const STATUS_BAR_ITEM_NAME = 'Go Diagnostics'; export const diagnosticsStatusBarItem = vscode.window.createStatusBarItem( @@ -32,28 +33,39 @@ export let goEnvStatusbarItem: vscode.StatusBarItem; let gomod: string; let gowork: string; -export const languageServerIcon = '$(zap)'; -export const languageServerErrorIcon = '$(warning)'; +const languageServerIcon = '$(zap)'; +const languageServerErrorIcon = '$(warning)'; +const languageServerStartingIcon = '$(sync~spin)'; export async function updateGoStatusBar(editor: vscode.TextEditor | undefined) { + if (!editor) { + return; + } + if (isGoFile(editor.document)) { + showGoStatusBar(); + return; + } + if (editor.document.languageId?.toLowerCase() !== 'log') { + goEnvStatusbarItem.hide(); + } +} + +export const expandGoStatusBar: CommandFactory = (ctx, goCtx) => async () => { // Only update the module path if we are in a Go file. // This allows the user to open output windows without losing // the go.mod information in the status bar. + const editor = vscode.window.activeTextEditor; if (!!editor && isGoFile(editor.document)) { - const isMod = await isModSupported(editor.document.uri); - if (isMod) { - runGoEnv(vscodeUri.Utils.dirname(editor.document.uri), ['GOMOD', 'GOWORK']).then((p) => { - gomod = p['GOMOD'] === '/dev/null' || p['GOMOD'] === 'NUL' ? '' : p['GOMOD']; - gowork = p['GOWORK']; - }); - } else { - gomod = ''; - gowork = ''; + const cwd = vscodeUri.Utils.dirname(editor.document.uri); + try { + const p = await runGoEnv(cwd, ['GOMOD', 'GOWORK']); + gomod = p['GOMOD'] === '/dev/null' || p['GOMOD'] === 'NUL' ? '' : p['GOMOD']; + gowork = p['GOWORK']; + } catch (e) { + outputChannel.debug(`failed to run go env from ${cwd} - ${e}`); } } -} -export const expandGoStatusBar: CommandFactory = (ctx, goCtx) => async () => { const { languageServerIsRunning, serverOutputChannel } = goCtx; const options = [ { label: 'Locate Configured Go Tools', description: 'display go env' }, @@ -66,7 +78,7 @@ export const expandGoStatusBar: CommandFactory = (ctx, goCtx) => async () => { const goplsIsRunning = languageServerIsRunning && cfg && cfg.serverName === 'gopls'; if (goplsIsRunning) { const goplsVersion = cfg.version; - options.push({ label: `${languageServerIcon}Open 'gopls' trace`, description: `${goplsVersion?.version}` }); + options.push({ label: `${languageServerIcon} Open 'gopls' trace`, description: `${goplsVersion?.version}` }); } // In case gopls still need to be installed, cfg.serverName will be empty. if (!goplsIsRunning && goConfig.get('useLanguageServer') === true && cfg?.serverName === '') { @@ -120,13 +132,13 @@ export const expandGoStatusBar: CommandFactory = (ctx, goCtx) => async () => { * Initialize the status bar item with current Go binary */ export async function initGoStatusBar(goCtx: GoExtensionContext) { - const { languageServerIsRunning } = goCtx; + const { languageClient } = goCtx; if (!goEnvStatusbarItem) { const STATUS_BAR_ITEM_NAME = 'Go'; goEnvStatusbarItem = vscode.window.createStatusBarItem( STATUS_BAR_ITEM_NAME, - vscode.StatusBarAlignment.Left, - 50 + vscode.StatusBarAlignment.Right, + 100.09999 // place the item right after the language status item https://github.com/microsoft/vscode-python/issues/18040#issuecomment-992567670. ); goEnvStatusbarItem.name = STATUS_BAR_ITEM_NAME; } @@ -141,12 +153,13 @@ export async function initGoStatusBar(goCtx: GoExtensionContext) { // Assume if it is configured it is already running, since the // icon will be updated on an attempt to start. const goConfig = getGoConfig(); - updateLanguageServerIconGoStatusBar(!!languageServerIsRunning, goConfig['useLanguageServer'] === true); - - showGoStatusBar(); + updateLanguageServerIconGoStatusBar(languageClient, goConfig['useLanguageServer'] === true); + if (vscode.window.visibleTextEditors.some((editor) => !!editor && isGoFile(editor.document))) { + showGoStatusBar(); + } } -export function updateLanguageServerIconGoStatusBar(started: boolean, enabled: boolean) { +export function updateLanguageServerIconGoStatusBar(languageClient: LanguageClient | undefined, enabled: boolean) { if (!goEnvStatusbarItem) { return; } @@ -154,20 +167,31 @@ export function updateLanguageServerIconGoStatusBar(started: boolean, enabled: b // Split the existing goEnvStatusbarItem.text into the version string part and // the gopls icon part. let text = goEnvStatusbarItem.text; - let icon = ''; if (text.endsWith(languageServerIcon)) { text = text.substring(0, text.length - languageServerIcon.length); } else if (text.endsWith(languageServerErrorIcon)) { text = text.substring(0, text.length - languageServerErrorIcon.length); + } else if (text.endsWith(languageServerStartingIcon)) { + text = text.substring(0, text.length - languageServerStartingIcon.length); } - - if (started && enabled) { + let color = undefined; + let icon = ''; + if (!enabled || !languageClient) { + icon = ''; + color = new vscode.ThemeColor('statusBarItem.warningBackground'); + } else if (languageClient.state === State.Starting) { + icon = languageServerStartingIcon; + color = undefined; + } else if (languageClient.state === State.Running) { icon = languageServerIcon; - } else if (!started && enabled) { + color = undefined; + } else if (languageClient.state === State.Stopped) { icon = languageServerErrorIcon; + color = new vscode.ThemeColor('statusBarItem.errorBackground'); } goEnvStatusbarItem.text = text + icon; + goEnvStatusbarItem.backgroundColor = color; } /** @@ -199,7 +223,7 @@ export function showGoStatusBar() { } // status bar item to show warning messages such as missing analysis tools. -const statusBarEntries = new Map(); +const statusBarEntries = new Map(); export function removeGoStatus(name: string) { const statusBarEntry = statusBarEntries.get(name); @@ -209,16 +233,11 @@ export function removeGoStatus(name: string) { } } -export function addGoStatus(name: string, message: string, command: string, tooltip?: string) { +export function addGoStatus(name: string): vscode.LanguageStatusItem { let statusBarEntry = statusBarEntries.get(name); if (!statusBarEntry) { - statusBarEntry = vscode.window.createStatusBarItem(name, vscode.StatusBarAlignment.Right, Number.MIN_VALUE); + statusBarEntry = vscode.languages.createLanguageStatusItem(name, GoDocumentSelector); statusBarEntries.set(name, statusBarEntry); - - statusBarEntry.name = name; } - statusBarEntry.text = `$(alert) ${message}`; - statusBarEntry.command = command; - statusBarEntry.tooltip = tooltip; - statusBarEntry.show(); + return statusBarEntry; } diff --git a/src/goSurvey.ts b/extension/src/goSurvey.ts similarity index 100% rename from src/goSurvey.ts rename to extension/src/goSurvey.ts diff --git a/src/goTaskProvider.ts b/extension/src/goTaskProvider.ts similarity index 100% rename from src/goTaskProvider.ts rename to extension/src/goTaskProvider.ts diff --git a/extension/src/goTelemetry.ts b/extension/src/goTelemetry.ts new file mode 100644 index 0000000000..58cdec9d38 --- /dev/null +++ b/extension/src/goTelemetry.ts @@ -0,0 +1,200 @@ +/*--------------------------------------------------------- + * Copyright 2023 The Go Authors. All rights reserved. + * Licensed under the MIT License. See LICENSE in the project root for license information. + *--------------------------------------------------------*/ + +import * as vscode from 'vscode'; + +import { createHash } from 'crypto'; +import { ExecuteCommandRequest } from 'vscode-languageserver-protocol'; +import { daysBetween } from './goSurvey'; +import { LanguageClient } from 'vscode-languageclient/node'; +import * as cp from 'child_process'; +import { getWorkspaceFolderPath } from './util'; +import { toolExecutionEnvironment } from './goEnv'; + +// Name of the prompt telemetry command. This is also used to determine if the gopls instance supports telemetry. +// Exported for testing. +export const GOPLS_MAYBE_PROMPT_FOR_TELEMETRY = 'gopls.maybe_prompt_for_telemetry'; + +// Key for the global state that holds the very first time the telemetry-enabled gopls was observed. +// Exported for testing. +export const TELEMETRY_START_TIME_KEY = 'telemetryStartTime'; + +enum ReporterState { + NOT_INITIALIZED, + IDLE, + STARTING, + RUNNING +} + +// exported for testing. +export class TelemetryReporter implements vscode.Disposable { + private _state = ReporterState.NOT_INITIALIZED; + private _counters: { [key: string]: number } = {}; + private _flushTimer: NodeJS.Timeout | undefined; + private _tool = ''; + constructor(flushIntervalMs = 60_000, private counterFile: string = '') { + if (flushIntervalMs > 0) { + // periodically call flush. + this._flushTimer = setInterval(this.flush.bind(this), flushIntervalMs); + } + } + + public setTool(tool: string) { + // allow only once. + if (tool === '' || this._state !== ReporterState.NOT_INITIALIZED) { + return; + } + this._state = ReporterState.IDLE; + this._tool = tool; + } + + public add(key: string, value: number) { + if (value <= 0) { + return; + } + key = key.replace(/[\s\n]/g, '_'); + this._counters[key] = (this._counters[key] || 0) + value; + } + + // flush is called periodically (by the callback set up in the constructor) + // or when the extension is deactivated (with force=true). + public async flush(force = false) { + // If flush runs with force=true, ignore the state and skip state update. + if (!force && this._state !== ReporterState.IDLE) { + // vscgo is not installed yet or is running. flush next time. + return 0; + } + if (!force) { + this._state = ReporterState.STARTING; + } + try { + await this.writeGoTelemetry(); + } catch (e) { + console.log(`failed to flush telemetry data: ${e}`); + } finally { + if (!force) { + this._state = ReporterState.IDLE; + } + } + } + + private writeGoTelemetry() { + const data = Object.entries(this._counters); + if (data.length === 0) { + return; + } + this._counters = {}; + + let stderr = ''; + return new Promise((resolve, reject) => { + const env = toolExecutionEnvironment(); + if (this.counterFile !== '') { + env['TELEMETRY_COUNTER_FILE'] = this.counterFile; + } + const p = cp.spawn(this._tool, ['inc_counters'], { + cwd: getWorkspaceFolderPath(), + env + }); + + p.stderr.on('data', (data) => { + stderr += data; + }); + + // 'close' fires after exit or error when the subprocess closes all stdio. + p.on('close', (exitCode, signal) => { + if (exitCode > 0) { + reject(`exited with code=${exitCode} signal=${signal} stderr=${stderr}`); + } else { + resolve(exitCode); + } + }); + // Stream key/value to the vscgo process. + data.forEach(([key, value]) => { + p.stdin.write(`${key} ${value}\n`); + }); + p.stdin.end(); + }); + } + + public async dispose() { + if (this._flushTimer) { + clearInterval(this._flushTimer); + } + this._flushTimer = undefined; + await this.flush(true); // flush any remaining data in buffer. + } +} + +// global telemetryReporter instance. +export const telemetryReporter = new TelemetryReporter(); + +// TODO(hyangah): consolidate the list of all the telemetries and bucketting functions. + +export function addTelemetryEvent(name: string, count: number) { + telemetryReporter.add(name, count); +} + +// Go extension delegates most of the telemetry logic to gopls. +// TelemetryService provides API to interact with gopls's telemetry. +export class TelemetryService { + private active = false; + constructor( + private languageClient: Pick | undefined, + private globalState: vscode.Memento, + commands: string[] = [] + ) { + if (!languageClient || !commands.includes(GOPLS_MAYBE_PROMPT_FOR_TELEMETRY)) { + // we are not backed by the gopls version that supports telemetry. + return; + } + + this.active = true; + // record the first time we see the gopls with telemetry support. + // The timestamp will be used to avoid prompting too early. + const telemetryStartTime = globalState.get(TELEMETRY_START_TIME_KEY); + if (!telemetryStartTime) { + globalState.update(TELEMETRY_START_TIME_KEY, new Date()); + } + } + + async promptForTelemetry( + isPreviewExtension: boolean, + isVSCodeTelemetryEnabled: boolean = vscode.env.isTelemetryEnabled, + samplingInterval = 1 /* prompt N out of 1000. 1 = 0.1% */ + ) { + if (!this.active) return; + + // Do not prompt yet if the user disabled vscode's telemetry. + // TODO(hyangah): remove this condition after we roll out to 100%. It's possible + // users who don't want vscode's telemetry are still willing to opt in. + if (!isVSCodeTelemetryEnabled) return; + + // Allow at least 7days for gopls to collect some data. + const now = new Date(); + const telemetryStartTime = this.globalState.get(TELEMETRY_START_TIME_KEY, now); + if (daysBetween(telemetryStartTime, now) < 7) { + return; + } + + // For official extension users, prompt only N out of 1000. + if (!isPreviewExtension && this.hashMachineID() % 1000 >= samplingInterval) { + return; + } + + try { + await this.languageClient?.sendRequest(ExecuteCommandRequest.type, { + command: GOPLS_MAYBE_PROMPT_FOR_TELEMETRY + }); + } catch (e) { + console.log(`failed to send telemetry request: ${e}`); + } + } + + // exported for testing. + public hashMachineID(salt?: string): number { + const hash = createHash('md5').update(`${vscode.env.machineId}${salt}`).digest('hex'); + return parseInt(hash.substring(0, 8), 16); + } +} diff --git a/src/goTest.ts b/extension/src/goTest.ts similarity index 100% rename from src/goTest.ts rename to extension/src/goTest.ts diff --git a/src/goTest/explore.ts b/extension/src/goTest/explore.ts similarity index 96% rename from src/goTest/explore.ts rename to extension/src/goTest/explore.ts index bb5e009bf2..e6901b2151 100644 --- a/src/goTest/explore.ts +++ b/extension/src/goTest/explore.ts @@ -141,7 +141,7 @@ export class GoTestExplorer { await inst.didChangeConfiguration(x); } catch (error) { if (isInTest()) throw error; - else outputChannel.appendLine(`Failed while handling 'onDidChangeConfiguration': ${error}`); + else outputChannel.error(`Failed while handling 'onDidChangeConfiguration': ${error}`); } }) ); @@ -152,7 +152,7 @@ export class GoTestExplorer { await inst.didOpenTextDocument(x); } catch (error) { if (isInTest()) throw error; - else outputChannel.appendLine(`Failed while handling 'onDidOpenTextDocument': ${error}`); + else outputChannel.error(`Failed while handling 'onDidOpenTextDocument': ${error}`); } }) ); @@ -163,7 +163,7 @@ export class GoTestExplorer { await inst.didChangeTextDocument(x); } catch (error) { if (isInTest()) throw error; - else outputChannel.appendLine(`Failed while handling 'onDidChangeTextDocument': ${error}`); + else outputChannel.error(`Failed while handling 'onDidChangeTextDocument': ${error}`); } }) ); diff --git a/src/goTest/profile.ts b/extension/src/goTest/profile.ts similarity index 100% rename from src/goTest/profile.ts rename to extension/src/goTest/profile.ts diff --git a/src/goTest/resolve.ts b/extension/src/goTest/resolve.ts similarity index 99% rename from src/goTest/resolve.ts rename to extension/src/goTest/resolve.ts index 5bcc91c999..46362d6b02 100644 --- a/src/goTest/resolve.ts +++ b/extension/src/goTest/resolve.ts @@ -57,8 +57,7 @@ export class GoTestResolver { if (isInTest()) throw error; const m = 'Failed to resolve tests'; - outputChannel.appendLine(`${m}: ${error}`); - await vscode.window.showErrorMessage(m); + outputChannel.error(`${m}: ${error}`); } }; } diff --git a/src/goTest/run.ts b/extension/src/goTest/run.ts similarity index 99% rename from src/goTest/run.ts rename to extension/src/goTest/run.ts index 697a481e24..eb0f03e065 100644 --- a/src/goTest/run.ts +++ b/extension/src/goTest/run.ts @@ -92,7 +92,7 @@ export class GoTestRunner { await this.run(request, token); } catch (error) { const m = 'Failed to execute tests'; - outputChannel.appendLine(`${m}: ${error}`); + outputChannel.error(`${m}: ${error}`); await vscode.window.showErrorMessage(m); } }, @@ -107,7 +107,7 @@ export class GoTestRunner { await this.debug(request, token); } catch (error) { const m = 'Failed to debug tests'; - outputChannel.appendLine(`${m}: ${error}`); + outputChannel.error(`${m}: ${error}`); await vscode.window.showErrorMessage(m); } }, @@ -122,7 +122,7 @@ export class GoTestRunner { await this.run(request, token, this.profiler.options); } catch (error) { const m = 'Failed to execute tests'; - outputChannel.appendLine(`${m}: ${error}`); + outputChannel.error(`${m}: ${error}`); await vscode.window.showErrorMessage(m); } }, @@ -333,7 +333,7 @@ export class GoTestRunner { // https://github.com/golang/go/issues/39904 if (subItems.length > 0 && Object.keys(tests).length + Object.keys(benchmarks).length > 1) { - outputChannel.appendLine( + outputChannel.error( `The following tests in ${pkg.uri} failed to run, as go test will only run a sub-test or sub-benchmark if it is by itself:` ); Object.keys(tests) diff --git a/src/goTest/test-explorer.md b/extension/src/goTest/test-explorer.md similarity index 100% rename from src/goTest/test-explorer.md rename to extension/src/goTest/test-explorer.md diff --git a/src/goTest/test_events.md b/extension/src/goTest/test_events.md similarity index 100% rename from src/goTest/test_events.md rename to extension/src/goTest/test_events.md diff --git a/src/goTest/utils.ts b/extension/src/goTest/utils.ts similarity index 100% rename from src/goTest/utils.ts rename to extension/src/goTest/utils.ts diff --git a/src/goTest/walk.ts b/extension/src/goTest/walk.ts similarity index 100% rename from src/goTest/walk.ts rename to extension/src/goTest/walk.ts diff --git a/src/goTools.ts b/extension/src/goTools.ts similarity index 100% rename from src/goTools.ts rename to extension/src/goTools.ts diff --git a/src/goToolsInformation.ts b/extension/src/goToolsInformation.ts similarity index 85% rename from src/goToolsInformation.ts rename to extension/src/goToolsInformation.ts index 51f0ba5a32..32c4261a85 100644 --- a/src/goToolsInformation.ts +++ b/extension/src/goToolsInformation.ts @@ -103,20 +103,29 @@ export const allToolsInformation: { [key: string]: Tool } = { description: 'Language Server from Google', usePrereleaseInPreviewMode: true, minimumGoVersion: semver.coerce('1.18'), - latestVersion: semver.parse('v0.14.1'), - latestVersionTimestamp: moment('2023-10-26', 'YYYY-MM-DD'), - latestPrereleaseVersion: semver.parse('v0.14.1'), - latestPrereleaseVersionTimestamp: moment('2023-10-26', 'YYYY-MM-DD') + latestVersion: semver.parse('v0.14.2'), + latestVersionTimestamp: moment('2023-11-14', 'YYYY-MM-DD'), + latestPrereleaseVersion: semver.parse('v0.14.2'), + latestPrereleaseVersionTimestamp: moment('2023-11-14', 'YYYY-MM-DD') }, 'dlv': { name: 'dlv', importPath: 'github.com/go-delve/delve/cmd/dlv', modulePath: 'github.com/go-delve/delve', replacedByGopls: false, - isImportant: true, + isImportant: false, description: 'Go debugger (Delve)', latestVersion: semver.parse('v1.8.3'), latestVersionTimestamp: moment('2022-04-26', 'YYYY-MM-DD'), minimumGoVersion: semver.coerce('1.18') + }, + 'vscgo': { + name: 'vscgo', + importPath: 'github.com/golang/vscode-go/vscgo', + modulePath: 'github.com/golang/vscode-go/vscgo', + replacedByGopls: false, + isImportant: false, // TODO: set to true when we need it + description: 'VS Code Go helper program', + minimumGoVersion: semver.coerce('1.18') } }; diff --git a/src/goVet.ts b/extension/src/goVet.ts similarity index 98% rename from src/goVet.ts rename to extension/src/goVet.ts index c7efb70a4d..b7965f4f19 100644 --- a/src/goVet.ts +++ b/extension/src/goVet.ts @@ -38,7 +38,7 @@ export function vetCode(vetWorkspace?: boolean): CommandFactory { const documentUri = editor?.document.uri; const goConfig = getGoConfig(documentUri); - outputChannel.clear(); // Ensures stale output from vet on save is cleared + outputChannel.appendLine('Vetting...'); diagnosticsStatusBarItem.show(); diagnosticsStatusBarItem.text = 'Vetting...'; diff --git a/src/goVulncheck.ts b/extension/src/goVulncheck.ts similarity index 100% rename from src/goVulncheck.ts rename to extension/src/goVulncheck.ts diff --git a/src/language/goLanguageServer.ts b/extension/src/language/goLanguageServer.ts similarity index 98% rename from src/language/goLanguageServer.ts rename to extension/src/language/goLanguageServer.ts index bed2024e50..9f5352f0d6 100644 --- a/src/language/goLanguageServer.ts +++ b/extension/src/language/goLanguageServer.ts @@ -51,7 +51,7 @@ import { removeDuplicateDiagnostics } from '../util'; import { getToolFromToolPath } from '../utils/pathUtils'; -import WebRequest = require('web-request'); +import fetch from 'node-fetch'; import { CompletionItemKind, FoldingContext } from 'vscode'; import { ProvideFoldingRangeSignature } from 'vscode-languageclient/lib/common/foldingRange'; import { daysBetween, getStateConfig, maybePromptForGoplsSurvey, timeDay, timeMinute } from '../goSurvey'; @@ -62,6 +62,7 @@ import { URI } from 'vscode-uri'; import { IVulncheckTerminal, VulncheckReport, VulncheckTerminal, writeVulns } from '../goVulncheck'; import { createHash } from 'crypto'; import { GoExtensionContext } from '../context'; +import { GoDocumentSelector } from '../goMode'; export interface LanguageServerConfig { serverName: string; @@ -174,7 +175,7 @@ export function scheduleGoplsSuggestions(goCtx: GoExtensionContext) { if (extensionInfo.isPreview || (await okForStagedRollout(tool, versionToUpdate, hashMachineID))) { const goVersion = await getGoVersion(); const toolVersion = { ...tool, version: versionToUpdate }; // ToolWithVersion - await installTools([toolVersion], goVersion, true); + await installTools([toolVersion], goVersion, { silent: true }); } else { console.log(`gopls ${versionToUpdate} is too new, try to update later`); } @@ -397,19 +398,10 @@ export async function buildLanguageClient( await getLocalGoplsVersion(cfg); // populate and cache cfg.version const goplsWorkspaceConfig = await adjustGoplsWorkspaceConfiguration(cfg, getGoplsConfig(), 'gopls', undefined); - const documentSelector = [ - // gopls handles only file URIs. - { language: 'go', scheme: 'file' }, - { language: 'go.mod', scheme: 'file' }, - { language: 'go.sum', scheme: 'file' }, - { language: 'go.work', scheme: 'file' }, - { language: 'gotmpl', scheme: 'file' } - ]; - // when initialization is failed after the connection is established, // we want to handle the connection close error case specially. Capture the error // in initializationFailedHandler and handle it in the connectionCloseHandler. - let initializationError: WebRequest.ResponseError | undefined = undefined; + let initializationError: ResponseError | undefined = undefined; let govulncheckTerminal: IVulncheckTerminal | undefined; const pendingVulncheckProgressToken = new Map(); @@ -425,7 +417,7 @@ export async function buildLanguageClient( } as ServerOptions, { initializationOptions: goplsWorkspaceConfig, - documentSelector, + documentSelector: GoDocumentSelector, uriConverters: { // Apply file:/// scheme to all file paths. code2Protocol: (uri: vscode.Uri): string => @@ -435,7 +427,7 @@ export async function buildLanguageClient( outputChannel: cfg.outputChannel, traceOutputChannel: cfg.traceOutputChannel, revealOutputChannelOn: RevealOutputChannelOn.Never, - initializationFailedHandler: (error: WebRequest.ResponseError): boolean => { + initializationFailedHandler: (error: ResponseError): boolean => { initializationError = error; return false; }, @@ -474,6 +466,7 @@ export async function buildLanguageClient( const { crashCount = 0 } = goCtx; goCtx.crashCount = crashCount + 1; if (goCtx.crashCount < 5) { + updateLanguageServerIconGoStatusBar(c, true); return { message: '', // suppresses error popups action: CloseAction.Restart @@ -485,7 +478,7 @@ export async function buildLanguageClient( 'The connection to gopls has been closed. The gopls server may have crashed.', errorKind.crash ); - updateLanguageServerIconGoStatusBar(false, true); + updateLanguageServerIconGoStatusBar(c, true); return { message: '', // suppresses error popups - there will be other popups. action: CloseAction.DoNotRestart @@ -1287,9 +1280,8 @@ async function goProxyRequest(tool: Tool, endpoint: string): Promise { const url = `${proxy}/${tool.importPath}/@v/${endpoint}`; let data: string; try { - data = await WebRequest.json(url, { - throwResponseError: true - }); + const response = await fetch(url); + data = await response.text(); } catch (e) { console.log(`Error sending request to ${proxy}: ${e}`); return null; @@ -1312,7 +1304,7 @@ export async function suggestGoplsIssueReport( cfg: LanguageServerConfig, // config used when starting this gopls. msg: string, reason: errorKind, - initializationError?: WebRequest.ResponseError + initializationError?: ResponseError ) { const issueTime = new Date(); diff --git a/src/language/legacy/goFormat.ts b/extension/src/language/legacy/goFormat.ts similarity index 100% rename from src/language/legacy/goFormat.ts rename to extension/src/language/legacy/goFormat.ts diff --git a/src/language/registerDefaultProviders.ts b/extension/src/language/registerDefaultProviders.ts similarity index 100% rename from src/language/registerDefaultProviders.ts rename to extension/src/language/registerDefaultProviders.ts diff --git a/src/pickProcess.ts b/extension/src/pickProcess.ts similarity index 100% rename from src/pickProcess.ts rename to extension/src/pickProcess.ts diff --git a/src/stateUtils.ts b/extension/src/stateUtils.ts similarity index 100% rename from src/stateUtils.ts rename to extension/src/stateUtils.ts diff --git a/src/subTestUtils.ts b/extension/src/subTestUtils.ts similarity index 100% rename from src/subTestUtils.ts rename to extension/src/subTestUtils.ts diff --git a/src/testUtils.ts b/extension/src/testUtils.ts similarity index 100% rename from src/testUtils.ts rename to extension/src/testUtils.ts diff --git a/src/util.ts b/extension/src/util.ts similarity index 99% rename from src/util.ts rename to extension/src/util.ts index 7c4318c53e..dfc4c3f7bd 100644 --- a/src/util.ts +++ b/extension/src/util.ts @@ -533,8 +533,8 @@ export function runTool( return resolve([]); } if (err && stderr && !useStdErr) { - outputChannel.appendLine(['Error while running tool:', cmd, ...args].join(' ')); - outputChannel.appendLine(stderr); + outputChannel.error(['Error while running tool:', cmd, ...args].join(' ')); + outputChannel.error(stderr); return resolve([]); } const lines = (useStdErr ? stderr : stdout).toString().split('\n'); @@ -575,7 +575,7 @@ export function runTool( outputChannel.appendLine(`${filePath}:${line}:${col ?? ''} ${msg}`); } if (!atLeastSingleMatch && unexpectedOutput && vscode.window.activeTextEditor) { - outputChannel.appendLine(stderr); + outputChannel.error(stderr); if (err) { ret.push({ file: vscode.window.activeTextEditor.document.fileName, diff --git a/src/utils/README.md b/extension/src/utils/README.md similarity index 100% rename from src/utils/README.md rename to extension/src/utils/README.md diff --git a/src/utils/argsUtil.ts b/extension/src/utils/argsUtil.ts similarity index 100% rename from src/utils/argsUtil.ts rename to extension/src/utils/argsUtil.ts diff --git a/src/utils/envUtils.ts b/extension/src/utils/envUtils.ts similarity index 100% rename from src/utils/envUtils.ts rename to extension/src/utils/envUtils.ts diff --git a/src/utils/lsofProcessParser.ts b/extension/src/utils/lsofProcessParser.ts similarity index 100% rename from src/utils/lsofProcessParser.ts rename to extension/src/utils/lsofProcessParser.ts diff --git a/src/utils/mutex.ts b/extension/src/utils/mutex.ts similarity index 100% rename from src/utils/mutex.ts rename to extension/src/utils/mutex.ts diff --git a/src/utils/pathUtils.ts b/extension/src/utils/pathUtils.ts similarity index 99% rename from src/utils/pathUtils.ts rename to extension/src/utils/pathUtils.ts index d42ac2c165..b3ce43b9ab 100644 --- a/src/utils/pathUtils.ts +++ b/extension/src/utils/pathUtils.ts @@ -13,7 +13,6 @@ import fs = require('fs'); import os = require('os'); import path = require('path'); import { promisify } from 'util'; -import { logVerbose } from '../goLogging'; let binPathCache: { [bin: string]: string } = {}; @@ -142,7 +141,6 @@ export function getCurrentGoRoot(): string { } export function setCurrentGoRoot(goroot: string) { - logVerbose(`setCurrentGoRoot(${goroot})`); currentGoRoot = goroot; } diff --git a/src/utils/processUtils.ts b/extension/src/utils/processUtils.ts similarity index 100% rename from src/utils/processUtils.ts rename to extension/src/utils/processUtils.ts diff --git a/src/utils/psProcessParser.ts b/extension/src/utils/psProcessParser.ts similarity index 100% rename from src/utils/psProcessParser.ts rename to extension/src/utils/psProcessParser.ts diff --git a/src/utils/randomDayutils.ts b/extension/src/utils/randomDayutils.ts similarity index 100% rename from src/utils/randomDayutils.ts rename to extension/src/utils/randomDayutils.ts diff --git a/src/utils/wmicProcessParser.ts b/extension/src/utils/wmicProcessParser.ts similarity index 100% rename from src/utils/wmicProcessParser.ts rename to extension/src/utils/wmicProcessParser.ts diff --git a/src/welcome.ts b/extension/src/welcome.ts similarity index 100% rename from src/welcome.ts rename to extension/src/welcome.ts diff --git a/syntaxes/go.mod.tmGrammar.json b/extension/syntaxes/go.mod.tmGrammar.json similarity index 100% rename from syntaxes/go.mod.tmGrammar.json rename to extension/syntaxes/go.mod.tmGrammar.json diff --git a/syntaxes/go.sum.tmGrammar.json b/extension/syntaxes/go.sum.tmGrammar.json similarity index 100% rename from syntaxes/go.sum.tmGrammar.json rename to extension/syntaxes/go.sum.tmGrammar.json diff --git a/test/gopls/codelens.test.ts b/extension/test/gopls/codelens.test.ts similarity index 100% rename from test/gopls/codelens.test.ts rename to extension/test/gopls/codelens.test.ts diff --git a/test/gopls/configuration.test.ts b/extension/test/gopls/configuration.test.ts similarity index 100% rename from test/gopls/configuration.test.ts rename to extension/test/gopls/configuration.test.ts diff --git a/test/gopls/extension.test.ts b/extension/test/gopls/extension.test.ts similarity index 100% rename from test/gopls/extension.test.ts rename to extension/test/gopls/extension.test.ts diff --git a/test/gopls/goTest.explore.test.ts b/extension/test/gopls/goTest.explore.test.ts similarity index 100% rename from test/gopls/goTest.explore.test.ts rename to extension/test/gopls/goTest.explore.test.ts diff --git a/test/gopls/goTest.resolve.test.ts b/extension/test/gopls/goTest.resolve.test.ts similarity index 100% rename from test/gopls/goTest.resolve.test.ts rename to extension/test/gopls/goTest.resolve.test.ts diff --git a/test/gopls/goTest.run.test.ts b/extension/test/gopls/goTest.run.test.ts similarity index 100% rename from test/gopls/goTest.run.test.ts rename to extension/test/gopls/goTest.run.test.ts diff --git a/test/gopls/goTest.utils.ts b/extension/test/gopls/goTest.utils.ts similarity index 100% rename from test/gopls/goTest.utils.ts rename to extension/test/gopls/goTest.utils.ts diff --git a/test/gopls/goplsTestEnv.utils.ts b/extension/test/gopls/goplsTestEnv.utils.ts similarity index 100% rename from test/gopls/goplsTestEnv.utils.ts rename to extension/test/gopls/goplsTestEnv.utils.ts diff --git a/test/gopls/index.ts b/extension/test/gopls/index.ts similarity index 100% rename from test/gopls/index.ts rename to extension/test/gopls/index.ts diff --git a/test/gopls/report.test.ts b/extension/test/gopls/report.test.ts similarity index 100% rename from test/gopls/report.test.ts rename to extension/test/gopls/report.test.ts diff --git a/test/gopls/survey.test.ts b/extension/test/gopls/survey.test.ts similarity index 100% rename from test/gopls/survey.test.ts rename to extension/test/gopls/survey.test.ts diff --git a/test/gopls/telemetry.test.ts b/extension/test/gopls/telemetry.test.ts similarity index 61% rename from test/gopls/telemetry.test.ts rename to extension/test/gopls/telemetry.test.ts index d7a15c6ae5..6f409d1938 100644 --- a/test/gopls/telemetry.test.ts +++ b/extension/test/gopls/telemetry.test.ts @@ -6,8 +6,22 @@ import * as sinon from 'sinon'; import { describe, it } from 'mocha'; -import { GOPLS_MAYBE_PROMPT_FOR_TELEMETRY, TELEMETRY_START_TIME_KEY, TelemetryService } from '../../src/goTelemetry'; +import { + GOPLS_MAYBE_PROMPT_FOR_TELEMETRY, + TELEMETRY_START_TIME_KEY, + TelemetryReporter, + TelemetryService +} from '../../src/goTelemetry'; import { MockMemento } from '../mocks/MockMemento'; +import { maybeInstallVSCGO } from '../../src/goInstallTools'; +import assert from 'assert'; +import path from 'path'; +import * as fs from 'fs-extra'; +import os = require('os'); +import { rmdirRecursive } from '../../src/util'; +import { extensionId } from '../../src/const'; +import { executableFileExists, fileExists } from '../../src/utils/pathUtils'; +import { ExtensionMode } from 'vscode'; describe('# prompt for telemetry', () => { it( @@ -157,3 +171,69 @@ function testTelemetryPrompt(tc: testCase, wantPrompt: boolean) { } }; } + +describe('# telemetry reporter using vscgo', async function () { + if (os.platform() === 'win32') { + this.timeout(10000); // go install is slow on windows builder. + } + // installVSCGO expects + // {extensionPath}/vscgo: vscgo source code for testing. + // {extensionPath}/bin: where compiled vscgo will be stored. + // During testing, extensionDevelopmentPath is the root of the extension. + // __dirname = out/test/gopls. + const extensionDevelopmentPath = path.resolve(__dirname, '../../..'); + const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'telemetryReporter')); + const counterfile = path.join(tmpDir, 'counterfile.txt'); + const sut = new TelemetryReporter(0, counterfile); + let vscgo: string; + + suiteSetup(async () => { + try { + vscgo = await maybeInstallVSCGO( + ExtensionMode.Test, + extensionId, + '', + extensionDevelopmentPath, + true /*isPreview*/ + ); + } catch (e) { + assert.fail(`failed to install vscgo needed for testing: ${e}`); + } + }); + suiteTeardown(() => { + rmdirRecursive(tmpDir); + if (executableFileExists(vscgo)) { + fs.unlink(vscgo); + } + }); + + teardown(() => { + if (fileExists(counterfile)) { + fs.unlink(counterfile); + } + }); + + it('add succeeds before telemetryReporter.setTool runs', () => { + sut.add('hello', 1); + sut.add('world', 2); + }); + + it('flush is noop before setTool', async () => { + await sut.flush(); + assert(!fileExists(counterfile), 'counterfile exists'); + }); + + it('flush writes accumulated counters after setTool', async () => { + sut.setTool(vscgo); + await sut.flush(); + const readAll = fs.readFileSync(counterfile).toString(); + assert(readAll.includes('hello 1\n') && readAll.includes('world 2\n'), readAll); + }); + + it('dispose triggers flush', async () => { + sut.add('bye', 3); + await sut.dispose(); + const readAll = fs.readFileSync(counterfile).toString(); + assert(readAll.includes('bye 3\n'), readAll); + }); +}); diff --git a/test/gopls/testdata/src/workspace/.gitignore b/extension/test/gopls/testdata/src/workspace/.gitignore similarity index 100% rename from test/gopls/testdata/src/workspace/.gitignore rename to extension/test/gopls/testdata/src/workspace/.gitignore diff --git a/test/gopls/testdata/src/workspace/.vscode/settings.json b/extension/test/gopls/testdata/src/workspace/.vscode/settings.json similarity index 100% rename from test/gopls/testdata/src/workspace/.vscode/settings.json rename to extension/test/gopls/testdata/src/workspace/.vscode/settings.json diff --git a/test/gopls/update.test.ts b/extension/test/gopls/update.test.ts similarity index 100% rename from test/gopls/update.test.ts rename to extension/test/gopls/update.test.ts diff --git a/test/gopls/vulncheck.test.ts b/extension/test/gopls/vulncheck.test.ts similarity index 100% rename from test/gopls/vulncheck.test.ts rename to extension/test/gopls/vulncheck.test.ts diff --git a/test/integration/coverage.test.ts b/extension/test/integration/coverage.test.ts similarity index 100% rename from test/integration/coverage.test.ts rename to extension/test/integration/coverage.test.ts diff --git a/test/integration/extension.test.ts b/extension/test/integration/extension.test.ts similarity index 100% rename from test/integration/extension.test.ts rename to extension/test/integration/extension.test.ts diff --git a/test/integration/goDebug.test.ts b/extension/test/integration/goDebug.test.ts similarity index 99% rename from test/integration/goDebug.test.ts rename to extension/test/integration/goDebug.test.ts index a9537ddc93..6c86635bdf 100644 --- a/test/integration/goDebug.test.ts +++ b/extension/test/integration/goDebug.test.ts @@ -24,7 +24,6 @@ import { getBinPath, rmdirRecursive } from '../../src/util'; import { killProcessTree } from '../../src/utils/processUtils'; import getPort = require('get-port'); import util = require('util'); -import { TimestampedLogger } from '../../src/goLogging'; import { affectedByIssue832 } from './testutils'; // For debugging test and streaming the trace instead of buffering, set this. @@ -43,9 +42,10 @@ const testAll = (ctx: Mocha.Context, isDlvDap: boolean, withConsole?: string) => name: 'Attach', type: 'go', request: 'attach', - mode: 'remote', // This implies debugAdapter = legacy. + mode: 'remote', host: '127.0.0.1', - port: 3456 + port: 3456, + debugAdapter: isDlvDap ? undefined : 'legacy' }; let dc: DebugClient; @@ -2100,7 +2100,21 @@ class DelveDAPDebugAdapterOnSocket extends proxy.DelveDAPOutputAdapter { } private constructor(config: DebugConfiguration) { - super(config, new TimestampedLogger('error', undefined, PRINT_TO_CONSOLE)); + const logger = { + trace: (msg: string) => { + console.log(msg); + }, + debug: (msg: string) => { + console.log(msg); + }, + info: (msg: string) => { + console.log(msg); + }, + error: (msg: string) => { + console.error(msg); + } + }; + super(config, logger); } private static TWO_CRLF = '\r\n\r\n'; diff --git a/test/integration/goDebugConfiguration.test.ts b/extension/test/integration/goDebugConfiguration.test.ts similarity index 98% rename from test/integration/goDebugConfiguration.test.ts rename to extension/test/integration/goDebugConfiguration.test.ts index 75ea818966..3d6bff60f1 100644 --- a/test/integration/goDebugConfiguration.test.ts +++ b/extension/test/integration/goDebugConfiguration.test.ts @@ -951,7 +951,7 @@ suite('Debug Configuration Default DebugAdapter', () => { assert.strictEqual(resolvedConfig['debugAdapter'], 'dlv-dap'); }); - test("default debugAdapter for remote mode should be 'legacy' when not in Preview mode", async () => { + test("default debugAdapter for remote mode should be 'dlv-dap'", async () => { const config = { name: 'Attach', type: 'go', @@ -961,24 +961,24 @@ suite('Debug Configuration Default DebugAdapter', () => { cwd: '/path' }; - const want = extensionInfo.isPreview ? 'dlv-dap' : 'legacy'; + const want = 'dlv-dap'; await debugConfigProvider.resolveDebugConfiguration(undefined, config); const resolvedConfig = config as any; assert.strictEqual(resolvedConfig['debugAdapter'], want); }); - test('debugAdapter=dlv-dap is allowed with remote mode', async () => { + test('debugAdapter=legacy is allowed with remote mode', async () => { const config = { name: 'Attach', type: 'go', request: 'attach', mode: 'remote', - debugAdapter: 'dlv-dap', + debugAdapter: 'legacy', program: '/path/to/main_test.go', cwd: '/path' }; - const want = 'dlv-dap'; // If requested, dlv-dap is preserved. + const want = 'legacy'; // If requested, legacy is preserved. await debugConfigProvider.resolveDebugConfiguration(undefined, config); const resolvedConfig = config as any; assert.strictEqual(resolvedConfig['debugAdapter'], want); diff --git a/test/integration/goExplorer.test.ts b/extension/test/integration/goExplorer.test.ts similarity index 100% rename from test/integration/goExplorer.test.ts rename to extension/test/integration/goExplorer.test.ts diff --git a/test/integration/goTask.test.ts b/extension/test/integration/goTask.test.ts similarity index 100% rename from test/integration/goTask.test.ts rename to extension/test/integration/goTask.test.ts diff --git a/test/integration/goversion.test.ts b/extension/test/integration/goversion.test.ts similarity index 80% rename from test/integration/goversion.test.ts rename to extension/test/integration/goversion.test.ts index 6ff375de0a..39e1710179 100644 --- a/test/integration/goversion.test.ts +++ b/extension/test/integration/goversion.test.ts @@ -13,17 +13,14 @@ import * as vscode from 'vscode'; import { getLatestGoVersions, GoEnvironmentOption, latestGoVersionKey } from '../../src/goEnvironmentStatus'; import { getGlobalState, setGlobalState, updateGlobalState } from '../../src/stateUtils'; import { MockMemento } from '../mocks/MockMemento'; +import * as fetchModule from 'node-fetch'; import moment = require('moment'); -import semver = require('semver'); -import WebRequest = require('web-request'); describe('#getLatestGoVersion()', function () { this.timeout(40000); let sandbox: sinon.SinonSandbox | undefined; let defaultMemento: vscode.Memento; - const webrequest = sinon.mock(WebRequest); - const mmnt = sinon.mock(moment); const now = 100000000; const oneday = 60 * 60 * 24 * 1000; // 24 hours in milliseconds @@ -39,20 +36,16 @@ describe('#getLatestGoVersion()', function () { sandbox = sinon.createSandbox(); setGlobalState(new MockMemento()); - webrequest - .expects('json') + const responseJSON = JSON.stringify([ + { version: 'go1.15.1', stable: true }, + { version: 'go1.14.2', stable: true } + ]); + const fetchMock = sandbox.mock(fetchModule); + fetchMock.expects('default') .withArgs('https://go.dev/dl/?mode=json') - .returns([ - { - version: 'go1.15.1', - stable: true - }, - { - version: 'go1.14.2', - stable: true - } - ]); - + .returns(Promise.resolve( + new fetchModule.Response(responseJSON))); + const mmnt = sandbox.mock(moment); mmnt.expects('now').returns(now); }); @@ -69,8 +62,8 @@ describe('#getLatestGoVersion()', function () { assert.strictEqual(results.length, want.length); for (let i = 0; i < results.length; i++) { - assert(results[i].label === want[i].label); - assert(results[i].binpath === want[i].binpath); + assert.strictEqual(results[i].label, want[i].label); + assert.strictEqual(results[i].binpath, want[i].binpath); } }); @@ -96,8 +89,8 @@ describe('#getLatestGoVersion()', function () { // check results assert.strictEqual(results.length, want.length); for (let i = 0; i < results.length; i++) { - assert(results[i].label === want[i].label); - assert(results[i].binpath === want[i].binpath); + assert.strictEqual(results[i].label, want[i].label); + assert.strictEqual(results[i].binpath, want[i].binpath); } }); @@ -116,10 +109,10 @@ describe('#getLatestGoVersion()', function () { ]; // check results - assert(results.length === want.length); + assert.strictEqual(results.length, want.length); for (let i = 0; i < results.length; i++) { - assert(results[i].label === want[i].label); - assert(results[i].binpath === want[i].binpath); + assert.strictEqual(results[i].label, want[i].label); + assert.strictEqual(results[i].binpath, want[i].binpath); } }); }); diff --git a/test/integration/index.ts b/extension/test/integration/index.ts similarity index 100% rename from test/integration/index.ts rename to extension/test/integration/index.ts diff --git a/test/integration/install.test.ts b/extension/test/integration/install.test.ts similarity index 80% rename from test/integration/install.test.ts rename to extension/test/integration/install.test.ts index 8b30501be0..ce435cf65d 100644 --- a/test/integration/install.test.ts +++ b/extension/test/integration/install.test.ts @@ -7,8 +7,8 @@ import AdmZip = require('adm-zip'); import assert from 'assert'; import * as config from '../../src/config'; -import { inspectGoToolVersion, installTools } from '../../src/goInstallTools'; -import { getConfiguredTools, getTool, getToolAtVersion } from '../../src/goTools'; +import { inspectGoToolVersion, installTools, maybeInstallImportantTools } from '../../src/goInstallTools'; +import { Tool, getConfiguredTools, getTool, getToolAtVersion } from '../../src/goTools'; import { getBinPath, getGoVersion, GoVersion, rmdirRecursive } from '../../src/util'; import { correctBinname } from '../../src/utils/pathUtils'; import cp = require('child_process'); @@ -379,3 +379,97 @@ suite('listOutdatedTools', () => { assert.deepStrictEqual(x, ['dlv']); }); }); + +suite('maybeInstallImportantTools tests', () => { + let sandbox: sinon.SinonSandbox; + + setup(() => { + sandbox = sinon.createSandbox(); + }); + + teardown(async () => sandbox.restore()); + + // runTest actually executes the logic of the test using a fake proxy. + async function runTest( + toolsManager: goInstallTools.IToolsManager, + alternateToolsCfg: { [key: string]: string } = {}, + wantMissingTools: string[] = [] + ) { + // maybeInstallImportantTools shouldn't trigger gopls restart. + // The caller ('activate') will explicitly start it. + sandbox + .stub(vscode.commands, 'executeCommand') + .withArgs('go.languageserver.restart') + .throws(new Error('gopls shouldn not be restarted')); + + try { + const statusBarItem = await maybeInstallImportantTools(alternateToolsCfg, toolsManager); + assert.strictEqual(statusBarItem.busy, false); + assert.strictEqual( + statusBarItem.severity, + wantMissingTools && wantMissingTools.length > 0 + ? vscode.LanguageStatusSeverity.Error + : vscode.LanguageStatusSeverity.Information, + statusBarItem.text + ); + if (wantMissingTools && wantMissingTools.length > 0) { + assert.strictEqual(statusBarItem.command?.title, 'Install missing tools'); + for (const tool of wantMissingTools) { + assert(statusBarItem.detail!.includes(tool), statusBarItem.detail + ' does not contain ' + tool); + } + } else { + assert.strictEqual(statusBarItem.command?.title, 'Update'); + assert.strictEqual(statusBarItem.detail, 'no missing tools'); + } + } catch (e) { + assert.fail(`maybeInstallImportantTools failed: ${e}`); + } + } + + test('Successfully install gopls & linter', async () => { + await runTest( + toolsManagerForTest(), + {}, // emtpry alternateTools. + [] // no missing tools after run. + ); + }); + + test('Do not install alternate tools', async () => { + await runTest(toolsManagerForTest(), { gopls: 'fork.example.com/gopls' }, ['gopls']); + }); + + test('Recover when installation fails', async () => { + const tm = toolsManagerForTest(); + tm.installTool = () => { + return Promise.resolve('failed'); + }; + await runTest(tm, {}, ['gopls', 'staticcheck']); + }); + + test('Recover when installation crashes', async () => { + const tm = toolsManagerForTest(); + tm.installTool = () => { + throw new Error('crash'); + }; + await runTest(tm, {}, ['gopls', 'staticcheck']); + }); + + function toolsManagerForTest() { + const installed: string[] = []; + const toolsManager: goInstallTools.IToolsManager = { + getMissingTools: function (matcher: (tool: Tool) => boolean): Promise { + let tools = getConfiguredTools(config.getGoConfig(), {}); + // apply user's filter; + tools = matcher ? tools.filter(matcher) : tools; + // remove tools that are installed. + tools = tools.filter((tool) => !installed.includes(tool.name)); + return Promise.resolve(tools); + }, + installTool: function (tool: Tool): Promise { + installed.push(tool.name); + return Promise.resolve(undefined); // no error. + } + }; + return toolsManager; + } +}); diff --git a/test/integration/pickProcess.test.ts b/extension/test/integration/pickProcess.test.ts similarity index 100% rename from test/integration/pickProcess.test.ts rename to extension/test/integration/pickProcess.test.ts diff --git a/test/integration/stateUtils.test.ts b/extension/test/integration/stateUtils.test.ts similarity index 100% rename from test/integration/stateUtils.test.ts rename to extension/test/integration/stateUtils.test.ts diff --git a/test/integration/statusbar.test.ts b/extension/test/integration/statusbar.test.ts similarity index 100% rename from test/integration/statusbar.test.ts rename to extension/test/integration/statusbar.test.ts diff --git a/test/integration/test.test.ts b/extension/test/integration/test.test.ts similarity index 100% rename from test/integration/test.test.ts rename to extension/test/integration/test.test.ts diff --git a/test/integration/testutils.ts b/extension/test/integration/testutils.ts similarity index 100% rename from test/integration/testutils.ts rename to extension/test/integration/testutils.ts diff --git a/test/integration/utils.test.ts b/extension/test/integration/utils.test.ts similarity index 100% rename from test/integration/utils.test.ts rename to extension/test/integration/utils.test.ts diff --git a/test/integration/welcome.test.ts b/extension/test/integration/welcome.test.ts similarity index 100% rename from test/integration/welcome.test.ts rename to extension/test/integration/welcome.test.ts diff --git a/test/mocks/MockCfg.ts b/extension/test/mocks/MockCfg.ts similarity index 100% rename from test/mocks/MockCfg.ts rename to extension/test/mocks/MockCfg.ts diff --git a/test/mocks/MockContext.ts b/extension/test/mocks/MockContext.ts similarity index 100% rename from test/mocks/MockContext.ts rename to extension/test/mocks/MockContext.ts diff --git a/test/mocks/MockMemento.ts b/extension/test/mocks/MockMemento.ts similarity index 100% rename from test/mocks/MockMemento.ts rename to extension/test/mocks/MockMemento.ts diff --git a/test/mocks/MockTest.ts b/extension/test/mocks/MockTest.ts similarity index 98% rename from test/mocks/MockTest.ts rename to extension/test/mocks/MockTest.ts index 86c146e28e..bcbb861329 100644 --- a/test/mocks/MockTest.ts +++ b/extension/test/mocks/MockTest.ts @@ -33,6 +33,10 @@ type TestRunHandler = (request: TestRunRequest, token: CancellationToken) => The class MockTestCollection implements TestItemCollection { constructor(private item: MockTestItem | MockTestController) {} + [Symbol.iterator](): Iterator<[id: string, testItem: TestItem], any, undefined> { + throw new Error('Method not implemented.'); + } + private readonly m = new Map(); get size() { diff --git a/test/runTest.ts b/extension/test/runTest.ts similarity index 100% rename from test/runTest.ts rename to extension/test/runTest.ts diff --git a/test/testdata/baseTest/go.mod b/extension/test/testdata/baseTest/go.mod similarity index 100% rename from test/testdata/baseTest/go.mod rename to extension/test/testdata/baseTest/go.mod diff --git a/test/testdata/baseTest/sample_test.go b/extension/test/testdata/baseTest/sample_test.go similarity index 100% rename from test/testdata/baseTest/sample_test.go rename to extension/test/testdata/baseTest/sample_test.go diff --git a/test/testdata/baseTest/test.go b/extension/test/testdata/baseTest/test.go similarity index 100% rename from test/testdata/baseTest/test.go rename to extension/test/testdata/baseTest/test.go diff --git a/test/testdata/buildTags/go.mod b/extension/test/testdata/buildTags/go.mod similarity index 100% rename from test/testdata/buildTags/go.mod rename to extension/test/testdata/buildTags/go.mod diff --git a/test/testdata/buildTags/hello.go b/extension/test/testdata/buildTags/hello.go similarity index 100% rename from test/testdata/buildTags/hello.go rename to extension/test/testdata/buildTags/hello.go diff --git a/test/testdata/codelens/codelens2_test.go b/extension/test/testdata/codelens/codelens2_test.go similarity index 100% rename from test/testdata/codelens/codelens2_test.go rename to extension/test/testdata/codelens/codelens2_test.go diff --git a/test/testdata/codelens/codelens_benchmark_test.go b/extension/test/testdata/codelens/codelens_benchmark_test.go similarity index 100% rename from test/testdata/codelens/codelens_benchmark_test.go rename to extension/test/testdata/codelens/codelens_benchmark_test.go diff --git a/test/testdata/codelens/codelens_go118_test.go b/extension/test/testdata/codelens/codelens_go118_test.go similarity index 100% rename from test/testdata/codelens/codelens_go118_test.go rename to extension/test/testdata/codelens/codelens_go118_test.go diff --git a/test/testdata/codelens/codelens_test.go b/extension/test/testdata/codelens/codelens_test.go similarity index 100% rename from test/testdata/codelens/codelens_test.go rename to extension/test/testdata/codelens/codelens_test.go diff --git a/test/testdata/codelens/go.mod b/extension/test/testdata/codelens/go.mod similarity index 100% rename from test/testdata/codelens/go.mod rename to extension/test/testdata/codelens/go.mod diff --git a/test/testdata/codelens/testmain/testmain_test.go b/extension/test/testdata/codelens/testmain/testmain_test.go similarity index 100% rename from test/testdata/codelens/testmain/testmain_test.go rename to extension/test/testdata/codelens/testmain/testmain_test.go diff --git a/test/testdata/completions/exportedMemberDocs.go b/extension/test/testdata/completions/exportedMemberDocs.go similarity index 100% rename from test/testdata/completions/exportedMemberDocs.go rename to extension/test/testdata/completions/exportedMemberDocs.go diff --git a/test/testdata/completions/go.mod b/extension/test/testdata/completions/go.mod similarity index 100% rename from test/testdata/completions/go.mod rename to extension/test/testdata/completions/go.mod diff --git a/test/testdata/completions/nosnippets.go b/extension/test/testdata/completions/nosnippets.go similarity index 100% rename from test/testdata/completions/nosnippets.go rename to extension/test/testdata/completions/nosnippets.go diff --git a/test/testdata/completions/snippets.go b/extension/test/testdata/completions/snippets.go similarity index 100% rename from test/testdata/completions/snippets.go rename to extension/test/testdata/completions/snippets.go diff --git a/test/testdata/completions/unimportedMultiplePkgs.go b/extension/test/testdata/completions/unimportedMultiplePkgs.go similarity index 100% rename from test/testdata/completions/unimportedMultiplePkgs.go rename to extension/test/testdata/completions/unimportedMultiplePkgs.go diff --git a/test/testdata/completions/unimportedPkgs.go b/extension/test/testdata/completions/unimportedPkgs.go similarity index 100% rename from test/testdata/completions/unimportedPkgs.go rename to extension/test/testdata/completions/unimportedPkgs.go diff --git a/test/testdata/condbp/condbp.go b/extension/test/testdata/condbp/condbp.go similarity index 100% rename from test/testdata/condbp/condbp.go rename to extension/test/testdata/condbp/condbp.go diff --git a/test/testdata/condbp/go.mod b/extension/test/testdata/condbp/go.mod similarity index 100% rename from test/testdata/condbp/go.mod rename to extension/test/testdata/condbp/go.mod diff --git a/test/testdata/coverage/a/a.go b/extension/test/testdata/coverage/a/a.go similarity index 100% rename from test/testdata/coverage/a/a.go rename to extension/test/testdata/coverage/a/a.go diff --git a/test/testdata/coverage/b/b.go b/extension/test/testdata/coverage/b/b.go similarity index 100% rename from test/testdata/coverage/b/b.go rename to extension/test/testdata/coverage/b/b.go diff --git a/test/testdata/coverage/cover.out b/extension/test/testdata/coverage/cover.out similarity index 100% rename from test/testdata/coverage/cover.out rename to extension/test/testdata/coverage/cover.out diff --git a/test/testdata/coverage/go.mod b/extension/test/testdata/coverage/go.mod similarity index 100% rename from test/testdata/coverage/go.mod rename to extension/test/testdata/coverage/go.mod diff --git a/test/testdata/cwdTest/cwdTest/go.mod b/extension/test/testdata/cwdTest/cwdTest/go.mod similarity index 100% rename from test/testdata/cwdTest/cwdTest/go.mod rename to extension/test/testdata/cwdTest/cwdTest/go.mod diff --git a/test/testdata/cwdTest/cwdTest/hello.txt b/extension/test/testdata/cwdTest/cwdTest/hello.txt similarity index 100% rename from test/testdata/cwdTest/cwdTest/hello.txt rename to extension/test/testdata/cwdTest/cwdTest/hello.txt diff --git a/test/testdata/cwdTest/cwdTest/main.go b/extension/test/testdata/cwdTest/cwdTest/main.go similarity index 100% rename from test/testdata/cwdTest/cwdTest/main.go rename to extension/test/testdata/cwdTest/cwdTest/main.go diff --git a/test/testdata/cwdTest/hello.txt b/extension/test/testdata/cwdTest/hello.txt similarity index 100% rename from test/testdata/cwdTest/hello.txt rename to extension/test/testdata/cwdTest/hello.txt diff --git a/test/testdata/diffTestData/file1.go b/extension/test/testdata/diffTestData/file1.go similarity index 100% rename from test/testdata/diffTestData/file1.go rename to extension/test/testdata/diffTestData/file1.go diff --git a/test/testdata/diffTestData/file2.go b/extension/test/testdata/diffTestData/file2.go similarity index 100% rename from test/testdata/diffTestData/file2.go rename to extension/test/testdata/diffTestData/file2.go diff --git a/test/testdata/diffTestData/go.mod b/extension/test/testdata/diffTestData/go.mod similarity index 100% rename from test/testdata/diffTestData/go.mod rename to extension/test/testdata/diffTestData/go.mod diff --git a/test/testdata/envTest/main.go b/extension/test/testdata/envTest/main.go similarity index 100% rename from test/testdata/envTest/main.go rename to extension/test/testdata/envTest/main.go diff --git a/test/testdata/errorsTest/errors.go b/extension/test/testdata/errorsTest/errors.go similarity index 100% rename from test/testdata/errorsTest/errors.go rename to extension/test/testdata/errorsTest/errors.go diff --git a/test/testdata/errorsTest/go.mod b/extension/test/testdata/errorsTest/go.mod similarity index 100% rename from test/testdata/errorsTest/go.mod rename to extension/test/testdata/errorsTest/go.mod diff --git a/test/testdata/generatetests/generatetests.go b/extension/test/testdata/generatetests/generatetests.go similarity index 100% rename from test/testdata/generatetests/generatetests.go rename to extension/test/testdata/generatetests/generatetests.go diff --git a/test/testdata/generatetests/go.mod b/extension/test/testdata/generatetests/go.mod similarity index 100% rename from test/testdata/generatetests/go.mod rename to extension/test/testdata/generatetests/go.mod diff --git a/test/testdata/goTestTest/a_test.go b/extension/test/testdata/goTestTest/a_test.go similarity index 100% rename from test/testdata/goTestTest/a_test.go rename to extension/test/testdata/goTestTest/a_test.go diff --git a/test/testdata/goTestTest/b/b_test.go b/extension/test/testdata/goTestTest/b/b_test.go similarity index 100% rename from test/testdata/goTestTest/b/b_test.go rename to extension/test/testdata/goTestTest/b/b_test.go diff --git a/test/testdata/goTestTest/go.mod b/extension/test/testdata/goTestTest/go.mod similarity index 100% rename from test/testdata/goTestTest/go.mod rename to extension/test/testdata/goTestTest/go.mod diff --git a/test/testdata/gogetdocTestData/format.go b/extension/test/testdata/gogetdocTestData/format.go similarity index 100% rename from test/testdata/gogetdocTestData/format.go rename to extension/test/testdata/gogetdocTestData/format.go diff --git a/test/testdata/gogetdocTestData/go.mod b/extension/test/testdata/gogetdocTestData/go.mod similarity index 100% rename from test/testdata/gogetdocTestData/go.mod rename to extension/test/testdata/gogetdocTestData/go.mod diff --git a/test/testdata/gogetdocTestData/test.go b/extension/test/testdata/gogetdocTestData/test.go similarity index 100% rename from test/testdata/gogetdocTestData/test.go rename to extension/test/testdata/gogetdocTestData/test.go diff --git a/test/testdata/goroutineTest/go.mod b/extension/test/testdata/goroutineTest/go.mod similarity index 100% rename from test/testdata/goroutineTest/go.mod rename to extension/test/testdata/goroutineTest/go.mod diff --git a/test/testdata/goroutineTest/main.go b/extension/test/testdata/goroutineTest/main.go similarity index 100% rename from test/testdata/goroutineTest/main.go rename to extension/test/testdata/goroutineTest/main.go diff --git a/test/testdata/helloWorldServer/go.mod b/extension/test/testdata/helloWorldServer/go.mod similarity index 100% rename from test/testdata/helloWorldServer/go.mod rename to extension/test/testdata/helloWorldServer/go.mod diff --git a/test/testdata/helloWorldServer/main.go b/extension/test/testdata/helloWorldServer/main.go similarity index 100% rename from test/testdata/helloWorldServer/main.go rename to extension/test/testdata/helloWorldServer/main.go diff --git a/test/testdata/importTest/cgoImports.go b/extension/test/testdata/importTest/cgoImports.go similarity index 100% rename from test/testdata/importTest/cgoImports.go rename to extension/test/testdata/importTest/cgoImports.go diff --git a/test/testdata/importTest/go.mod b/extension/test/testdata/importTest/go.mod similarity index 100% rename from test/testdata/importTest/go.mod rename to extension/test/testdata/importTest/go.mod diff --git a/test/testdata/importTest/groupImports.go b/extension/test/testdata/importTest/groupImports.go similarity index 100% rename from test/testdata/importTest/groupImports.go rename to extension/test/testdata/importTest/groupImports.go diff --git a/test/testdata/importTest/noimports.go b/extension/test/testdata/importTest/noimports.go similarity index 100% rename from test/testdata/importTest/noimports.go rename to extension/test/testdata/importTest/noimports.go diff --git a/test/testdata/importTest/singleImports.go b/extension/test/testdata/importTest/singleImports.go similarity index 100% rename from test/testdata/importTest/singleImports.go rename to extension/test/testdata/importTest/singleImports.go diff --git a/test/testdata/linterTest/go.mod b/extension/test/testdata/linterTest/go.mod similarity index 100% rename from test/testdata/linterTest/go.mod rename to extension/test/testdata/linterTest/go.mod diff --git a/test/testdata/linterTest/linter_1.go b/extension/test/testdata/linterTest/linter_1.go similarity index 100% rename from test/testdata/linterTest/linter_1.go rename to extension/test/testdata/linterTest/linter_1.go diff --git a/test/testdata/linterTest/linter_2.go b/extension/test/testdata/linterTest/linter_2.go similarity index 100% rename from test/testdata/linterTest/linter_2.go rename to extension/test/testdata/linterTest/linter_2.go diff --git a/test/testdata/loop/go.mod b/extension/test/testdata/loop/go.mod similarity index 100% rename from test/testdata/loop/go.mod rename to extension/test/testdata/loop/go.mod diff --git a/test/testdata/loop/loop.go b/extension/test/testdata/loop/loop.go similarity index 100% rename from test/testdata/loop/loop.go rename to extension/test/testdata/loop/loop.go diff --git a/test/testdata/outlineTest/go.mod b/extension/test/testdata/outlineTest/go.mod similarity index 100% rename from test/testdata/outlineTest/go.mod rename to extension/test/testdata/outlineTest/go.mod diff --git a/test/testdata/outlineTest/test.go b/extension/test/testdata/outlineTest/test.go similarity index 100% rename from test/testdata/outlineTest/test.go rename to extension/test/testdata/outlineTest/test.go diff --git a/test/testdata/panic/go.mod b/extension/test/testdata/panic/go.mod similarity index 100% rename from test/testdata/panic/go.mod rename to extension/test/testdata/panic/go.mod diff --git a/test/testdata/panic/panic.go b/extension/test/testdata/panic/panic.go similarity index 100% rename from test/testdata/panic/panic.go rename to extension/test/testdata/panic/panic.go diff --git a/test/testdata/runtimeError/go.mod b/extension/test/testdata/runtimeError/go.mod similarity index 100% rename from test/testdata/runtimeError/go.mod rename to extension/test/testdata/runtimeError/go.mod diff --git a/test/testdata/runtimeError/oops.go b/extension/test/testdata/runtimeError/oops.go similarity index 100% rename from test/testdata/runtimeError/oops.go rename to extension/test/testdata/runtimeError/oops.go diff --git a/test/testdata/sleep/go.mod b/extension/test/testdata/sleep/go.mod similarity index 100% rename from test/testdata/sleep/go.mod rename to extension/test/testdata/sleep/go.mod diff --git a/test/testdata/sleep/sleep.go b/extension/test/testdata/sleep/sleep.go similarity index 100% rename from test/testdata/sleep/sleep.go rename to extension/test/testdata/sleep/sleep.go diff --git a/test/testdata/stretchrTestSuite/go.mod b/extension/test/testdata/stretchrTestSuite/go.mod similarity index 100% rename from test/testdata/stretchrTestSuite/go.mod rename to extension/test/testdata/stretchrTestSuite/go.mod diff --git a/test/testdata/stretchrTestSuite/go.sum b/extension/test/testdata/stretchrTestSuite/go.sum similarity index 100% rename from test/testdata/stretchrTestSuite/go.sum rename to extension/test/testdata/stretchrTestSuite/go.sum diff --git a/test/testdata/stretchrTestSuite/suite_test.go b/extension/test/testdata/stretchrTestSuite/suite_test.go similarity index 100% rename from test/testdata/stretchrTestSuite/suite_test.go rename to extension/test/testdata/stretchrTestSuite/suite_test.go diff --git a/test/testdata/subTest/go.mod b/extension/test/testdata/subTest/go.mod similarity index 100% rename from test/testdata/subTest/go.mod rename to extension/test/testdata/subTest/go.mod diff --git a/test/testdata/subTest/sub_test.go b/extension/test/testdata/subTest/sub_test.go similarity index 100% rename from test/testdata/subTest/sub_test.go rename to extension/test/testdata/subTest/sub_test.go diff --git a/test/testdata/testTags/go.mod b/extension/test/testdata/testTags/go.mod similarity index 100% rename from test/testdata/testTags/go.mod rename to extension/test/testdata/testTags/go.mod diff --git a/test/testdata/testTags/hello_test.go b/extension/test/testdata/testTags/hello_test.go similarity index 100% rename from test/testdata/testTags/hello_test.go rename to extension/test/testdata/testTags/hello_test.go diff --git a/test/testdata/vendoring/main.go b/extension/test/testdata/vendoring/main.go similarity index 100% rename from test/testdata/vendoring/main.go rename to extension/test/testdata/vendoring/main.go diff --git a/test/testdata/vendoring/vendor/example/vendorpls/lib.go b/extension/test/testdata/vendoring/vendor/example/vendorpls/lib.go similarity index 100% rename from test/testdata/vendoring/vendor/example/vendorpls/lib.go rename to extension/test/testdata/vendoring/vendor/example/vendorpls/lib.go diff --git a/test/testdata/vuln/go.work b/extension/test/testdata/vuln/go.work similarity index 100% rename from test/testdata/vuln/go.work rename to extension/test/testdata/vuln/go.work diff --git a/test/testdata/vuln/mod1/go.mod b/extension/test/testdata/vuln/mod1/go.mod similarity index 100% rename from test/testdata/vuln/mod1/go.mod rename to extension/test/testdata/vuln/mod1/go.mod diff --git a/test/testdata/vuln/mod1/go.sum b/extension/test/testdata/vuln/mod1/go.sum similarity index 100% rename from test/testdata/vuln/mod1/go.sum rename to extension/test/testdata/vuln/mod1/go.sum diff --git a/test/testdata/vuln/mod1/test.go b/extension/test/testdata/vuln/mod1/test.go similarity index 100% rename from test/testdata/vuln/mod1/test.go rename to extension/test/testdata/vuln/mod1/test.go diff --git a/test/testdata/vuln/mod2/go.mod b/extension/test/testdata/vuln/mod2/go.mod similarity index 100% rename from test/testdata/vuln/mod2/go.mod rename to extension/test/testdata/vuln/mod2/go.mod diff --git a/test/testdata/vuln/mod2/test.go b/extension/test/testdata/vuln/mod2/test.go similarity index 100% rename from test/testdata/vuln/mod2/test.go rename to extension/test/testdata/vuln/mod2/test.go diff --git a/test/testdata/vuln/vulndb/GO-1970-FMT.json b/extension/test/testdata/vuln/vulndb/GO-1970-FMT.json similarity index 100% rename from test/testdata/vuln/vulndb/GO-1970-FMT.json rename to extension/test/testdata/vuln/vulndb/GO-1970-FMT.json diff --git a/test/testdata/vuln/vulndb/GO-1970-TEXT.json b/extension/test/testdata/vuln/vulndb/GO-1970-TEXT.json similarity index 100% rename from test/testdata/vuln/vulndb/GO-1970-TEXT.json rename to extension/test/testdata/vuln/vulndb/GO-1970-TEXT.json diff --git a/test/unit/calendartest.ts b/extension/test/unit/calendartest.ts similarity index 100% rename from test/unit/calendartest.ts rename to extension/test/unit/calendartest.ts diff --git a/test/unit/mutex.test.ts b/extension/test/unit/mutex.test.ts similarity index 100% rename from test/unit/mutex.test.ts rename to extension/test/unit/mutex.test.ts diff --git a/test/unit/subTestUtils.test.ts b/extension/test/unit/subTestUtils.test.ts similarity index 100% rename from test/unit/subTestUtils.test.ts rename to extension/test/unit/subTestUtils.test.ts diff --git a/test/unit/util.test.ts b/extension/test/unit/util.test.ts similarity index 100% rename from test/unit/util.test.ts rename to extension/test/unit/util.test.ts diff --git a/third_party/README.md b/extension/third_party/README.md similarity index 100% rename from third_party/README.md rename to extension/third_party/README.md diff --git a/third_party/tree-kill/LICENSE b/extension/third_party/tree-kill/LICENSE similarity index 100% rename from third_party/tree-kill/LICENSE rename to extension/third_party/tree-kill/LICENSE diff --git a/third_party/tree-kill/README.md b/extension/third_party/tree-kill/README.md similarity index 100% rename from third_party/tree-kill/README.md rename to extension/third_party/tree-kill/README.md diff --git a/third_party/tree-kill/index.d.ts b/extension/third_party/tree-kill/index.d.ts similarity index 100% rename from third_party/tree-kill/index.d.ts rename to extension/third_party/tree-kill/index.d.ts diff --git a/third_party/tree-kill/index.js b/extension/third_party/tree-kill/index.js similarity index 100% rename from third_party/tree-kill/index.js rename to extension/third_party/tree-kill/index.js diff --git a/third_party/tree-kill/package.json b/extension/third_party/tree-kill/package.json similarity index 100% rename from third_party/tree-kill/package.json rename to extension/third_party/tree-kill/package.json diff --git a/tools/allTools.ts.in b/extension/tools/allTools.ts.in similarity index 91% rename from tools/allTools.ts.in rename to extension/tools/allTools.ts.in index 016b1bfb1c..7cc53113d0 100644 --- a/tools/allTools.ts.in +++ b/extension/tools/allTools.ts.in @@ -111,10 +111,19 @@ export const allToolsInformation: { [key: string]: Tool } = { importPath: 'github.com/go-delve/delve/cmd/dlv', modulePath: 'github.com/go-delve/delve', replacedByGopls: false, - isImportant: true, + isImportant: false, description: 'Go debugger (Delve)', latestVersion: semver.parse('v1.8.3'), latestVersionTimestamp: moment('2022-04-26', 'YYYY-MM-DD'), minimumGoVersion: semver.coerce('1.18') + }, + 'vscgo': { + name: 'vscgo', + importPath: 'github.com/golang/vscode-go/vscgo', + modulePath: 'github.com/golang/vscode-go/vscgo', + replacedByGopls: false, + isImportant: false, // TODO: set to true when we need it + description: 'VS Code Go helper program', + minimumGoVersion: semver.coerce('1.18') } }; \ No newline at end of file diff --git a/tools/docs2wiki/main.go b/extension/tools/docs2wiki/main.go similarity index 100% rename from tools/docs2wiki/main.go rename to extension/tools/docs2wiki/main.go diff --git a/tools/docs2wiki/main_test.go b/extension/tools/docs2wiki/main_test.go similarity index 100% rename from tools/docs2wiki/main_test.go rename to extension/tools/docs2wiki/main_test.go diff --git a/tools/generate.go b/extension/tools/generate.go similarity index 98% rename from tools/generate.go rename to extension/tools/generate.go index d806abe3cf..725dafa58c 100644 --- a/tools/generate.go +++ b/extension/tools/generate.go @@ -28,7 +28,7 @@ import ( "sort" "strings" - "github.com/golang/vscode-go/tools/goplssetting" + "github.com/golang/vscode-go/extension/tools/goplssetting" ) var ( @@ -52,7 +52,7 @@ func checkAndWrite(filename string, oldContent, newContent []byte) { } fmt.Printf("updated %s\n", filename) } else { - base := filepath.Join("docs", filepath.Base(filename)) + base := filepath.Join("..", "docs", filepath.Base(filename)) fmt.Printf(`%s have changed in the package.json, but documentation in %s was not updated. To update the settings, run "go run tools/generate.go -w". `, strings.TrimSuffix(base, ".md"), base) @@ -180,7 +180,7 @@ func main() { b.WriteString("\n\n") } } - rewrite(filepath.Join(dir, "docs", "commands.md"), b.Bytes()) + rewrite(filepath.Join(dir, "..", "docs", "commands.md"), b.Bytes()) // Clear so that we can rewrite settings.md. b.Reset() @@ -218,11 +218,11 @@ func main() { b.WriteString("## Settings for `gopls`\n\n") writeGoplsSettingsSection(b, goplsProperty) - rewrite(filepath.Join(dir, "docs", "settings.md"), b.Bytes()) + rewrite(filepath.Join(dir, "..", "docs", "settings.md"), b.Bytes()) b.Reset() generateDebugConfigTable(b, pkgJSON) - rewriteDebugDoc(filepath.Join(dir, "docs", "debugging.md"), b.Bytes()) + rewriteDebugDoc(filepath.Join(dir, "..", "docs", "debugging.md"), b.Bytes()) // Only update the latest tool versions if the flag is set. if !*updateLatestToolVersionsFlag { diff --git a/tools/goplssetting/goplssetting.go b/extension/tools/goplssetting/goplssetting.go similarity index 100% rename from tools/goplssetting/goplssetting.go rename to extension/tools/goplssetting/goplssetting.go diff --git a/tools/goplssetting/goplssetting_test.go b/extension/tools/goplssetting/goplssetting_test.go similarity index 100% rename from tools/goplssetting/goplssetting_test.go rename to extension/tools/goplssetting/goplssetting_test.go diff --git a/tools/installtools/main.go b/extension/tools/installtools/main.go similarity index 100% rename from tools/installtools/main.go rename to extension/tools/installtools/main.go diff --git a/tools/installtools/main_test.go b/extension/tools/installtools/main_test.go similarity index 100% rename from tools/installtools/main_test.go rename to extension/tools/installtools/main_test.go diff --git a/tools/license.sh b/extension/tools/license.sh similarity index 100% rename from tools/license.sh rename to extension/tools/license.sh diff --git a/extension/tools/release/release.go b/extension/tools/release/release.go new file mode 100644 index 0000000000..4c12fd3e17 --- /dev/null +++ b/extension/tools/release/release.go @@ -0,0 +1,244 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This script is used to build and publish VS Code Go extension. +// The script should be run from the root of the repository where package.json is located. +// +// The script requires the following environment variables to be set: +// +// TAG_NAME: the name of the tag to be released. +// COMMIT_SHA: the commit SHA to be released (optional. if not set, it will be retrieved from git) +// VSCE_PAT: the Personal Access Token for the VS Code Marketplace. +// GITHUB_TOKEN: the GitHub token for the Go repository. +// +// This script requires the following tools to be installed: +// +// jq, npx, gh, git +// +// Usage: +// +// // package the extension (based on TAG_NAME). +// go run build/release.go package +// // publish the extension. +// go run build/release.go publish +package main + +import ( + "bytes" + "flag" + "fmt" + "os" + "os/exec" + "path/filepath" + "regexp" + "strings" +) + +var flagN = flag.Bool("n", false, "print the underlying commands but do not run them") + +func main() { + flag.Parse() + if flag.NArg() != 1 { + usage() + os.Exit(1) + } + cmd := flag.Arg(0) + + checkWD() + requireTools("jq", "npx", "gh", "git") + requireEnvVars("TAG_NAME") + + tagName, version, isRC := releaseVersionInfo() + vsix := fmt.Sprintf("go-%s.vsix", version) + + switch cmd { + case "package": + buildPackage(version, tagName, vsix) + case "publish": + requireEnvVars("VSCE_PAT", "GITHUB_TOKEN") + publish(tagName, vsix, isRC) + default: + usage() + os.Exit(1) + } +} + +func usage() { + fmt.Fprintf(os.Stderr, "Usage: %s [package|publish]\n\n", os.Args[0]) + fmt.Fprintln(os.Stderr, "Flags:") + flag.PrintDefaults() +} + +func fatalf(format string, args ...any) { + fmt.Fprintf(os.Stderr, format, args...) + fmt.Fprintf(os.Stderr, "\n") + os.Exit(1) +} + +func requireTools(tools ...string) { + for _, tool := range tools { + if _, err := exec.LookPath(tool); err != nil { + fatalf("required tool %q not found", tool) + } + } +} + +func requireEnvVars(vars ...string) { + for _, v := range vars { + if os.Getenv(v) == "" { + fatalf("required environment variable %q not set", v) + } + } +} + +// checkWD checks if the working directory is the extension directory where package.json is located. +func checkWD() { + wd, err := os.Getwd() + if err != nil { + fatalf("failed to get working directory") + } + // check if package.json is in the working directory + if _, err := os.Stat("package.json"); os.IsNotExist(err) { + fatalf("package.json not found in working directory %q", wd) + } +} + +// releaseVersionInfo computes the version and label information for this release. +// It requires the TAG_NAME environment variable to be set and the tag matches the version info embedded in package.json. +func releaseVersionInfo() (tagName, version string, isPrerelease bool) { + tagName = os.Getenv("TAG_NAME") + if tagName == "" { + fatalf("TAG_NAME environment variable is not set") + } + // versionTag should be of the form vMajor.Minor.Patch[-rc.N]. + // e.g. v1.1.0-rc.1, v1.1.0 + // The MajorMinorPatch part should match the version in package.json. + // The optional `-rc.N` part is captured as the `Label` group + // and the validity is checked below. + versionTagRE := regexp.MustCompile(`^v(?P\d+\.\d+\.\d+)(?P