diff --git a/.custom-gcl.reference.yml b/.custom-gcl.reference.yml new file mode 100644 index 000000000000..08d7dfc681ec --- /dev/null +++ b/.custom-gcl.reference.yml @@ -0,0 +1,37 @@ +# The golangci-lint version used to build the custom binary. +# Require. +version: v1.56.2 + +# The name of the custom binary. +# Optional. +# Default: custom-gcl +name: custom-golangci-lint + +# The directory path used to store the custom binary. +# Optional. +# Default: . +destination: ./my/path/ + +# The list of the plugins to integrate inside the custom binary. +plugins: + # a plugin from a Go proxy + - module: 'github.com/example/plugin3' + version: v1.2.3 + + # a plugin from a Go proxy (with a specific import path) + - module: 'github.com/example/plugin4' + import: 'github.com/example/plugin4/foo' + version: v1.0.0 + + # a plugin from local source (with absolute path) + - module: 'github.com/example/plugin2' + path: /my/local/path/plugin2 + + # a plugin from local source (with relative path) + - module: 'github.com/example/plugin1' + path: ./my/local/path/plugin1 + + # a plugin from local source (with absolute path and a specific import path) + - module: 'github.com/example/plugin2' + import: 'github.com/example/plugin4/foo' + path: /my/local/path/plugin2 diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 8861771c2687..42e74a3931b4 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1 +1 @@ -See [contibuting quick start](https://golangci-lint.run/contributing/quick-start/) on our website. +See [contributing quick start](https://golangci-lint.run/contributing/quick-start/) on our website. diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 8b58bf4da0e5..0bad078aa8b6 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -11,7 +11,7 @@ body: required: true - label: Yes, I've searched similar issues on GitHub and didn't find any. required: true - - label: Yes, I've included all information below (version, config, etc.). + - label: Yes, I've read the typecheck section of the FAQ (https://golangci-lint.run/usage/faq/#why-do-you-have-typecheck-errors). required: true - label: Yes, I've tried with the standalone linter if available (e.g., gocritic, go vet, etc.). (https://golangci-lint.run/usage/linters/) required: true @@ -43,13 +43,12 @@ body: - type: textarea id: config attributes: - label: Configuration file + label: Configuration value: |-
```console - $ cat .golangci.yml - # paste output here + # paste configuration file or CLI flags here ```
@@ -92,7 +91,8 @@ body: - type: textarea id: code-example attributes: - label: Code example or link to a public repository + label: A minimal reproducible example or link to a public repository + description: if your problem is related to a private repository, a minimal reproducible example is required. value: |-
@@ -103,3 +103,11 @@ body:
validations: required: true + + - type: checkboxes + id: validation + attributes: + label: Validation + options: + - label: Yes, I've included all information above (version, config, etc.). + required: true diff --git a/.github/contributors/generate.ts b/.github/contributors/generate.ts index 67aa03faf46d..beef913ba7ff 100644 --- a/.github/contributors/generate.ts +++ b/.github/contributors/generate.ts @@ -124,6 +124,7 @@ const main = async () => { fossabot: true, golangcibot: true, kortschak: true, + "golangci-releaser": true, } const res: DataJSON = { diff --git a/.github/contributors/package-lock.json b/.github/contributors/package-lock.json index d6009e8db2b2..c14723a8d966 100644 --- a/.github/contributors/package-lock.json +++ b/.github/contributors/package-lock.json @@ -699,9 +699,9 @@ } }, "node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "bin": { "semver": "bin/semver" } @@ -1405,9 +1405,9 @@ } }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" }, "shebang-command": { "version": "1.2.0", diff --git a/.github/peril/package-lock.json b/.github/peril/package-lock.json index 8f5ef1642f7e..038ea0226242 100644 --- a/.github/peril/package-lock.json +++ b/.github/peril/package-lock.json @@ -84,23 +84,6 @@ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==" }, - "@babel/helper-function-name": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", - "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", - "requires": { - "@babel/template": "^7.18.10", - "@babel/types": "^7.19.0" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", - "requires": { - "@babel/types": "^7.18.6" - } - }, "@babel/helper-module-imports": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", @@ -354,20 +337,180 @@ } }, "@babel/traverse": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.1.tgz", - "integrity": "sha512-0j/ZfZMxKukDaag2PtOPDbwuELqIar6lLskVPPJDjXMXjfLb1Obo/1yjxIGqqAJrmfaTIY3z2wFLAQ7qSkLsuA==", - "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.19.0", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.19.1", - "@babel/types": "^7.19.0", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "requires": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", "debug": "^4.1.0", "globals": "^11.1.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "requires": { + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" + } + }, + "@babel/generator": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "requires": { + "@babel/types": "^7.23.0", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + } + }, + "@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==" + }, + "@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "requires": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==" + }, + "@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==" + }, + "@babel/highlight": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "requires": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==" + }, + "@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "requires": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + } + }, + "@babel/types": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "requires": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + } + }, + "@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/trace-mapping": { + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } } }, "@babel/types": { @@ -1687,9 +1830,9 @@ }, "dependencies": { "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "requires": { "lru-cache": "^6.0.0" } @@ -2061,9 +2204,9 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" }, "shebang-command": { "version": "2.0.0", diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index e27022d109ec..768f03ce434e 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -33,11 +33,11 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -46,4 +46,4 @@ jobs: # queries: ./path/to/local/query, your-org/your-repo/queries@main - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml new file mode 100644 index 000000000000..cd55da314412 --- /dev/null +++ b/.github/workflows/documentation.yml @@ -0,0 +1,63 @@ +name: Documentation + +on: + push: + branches: + - master + +jobs: + + doc: + name: Build and deploy documentation + runs-on: ubuntu-latest + env: + GO_VERSION: '1.22' + NODE_VERSION: '20.x' + CGO_ENABLED: 0 + + steps: + - name: Check out code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Go ${{ env.GO_VERSION }} + uses: actions/setup-go@v5 + with: + go-version: ${{ env.GO_VERSION }} + + - name: Cache Go modules + uses: actions/cache@v4 + with: + # In order: + # * Module download cache + # * Build cache (Linux) + path: | + ~/go/pkg/mod + ~/.cache/go-build + key: docs-${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + docs-${{ runner.os }}-go- + + - run: go mod download + + - name: Use Node.js ${{ env.NODE_VERSION }} + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: npm + cache-dependency-path: docs/package-lock.json + + - run: npm install --legacy-peer-deps + working-directory: ./docs + + - name: Build Documentation + run: npm run build + working-directory: ./docs + + - name: Deploy to GitHub Pages + uses: peaceiris/actions-gh-pages@v3 + with: + publish_dir: docs/public + force_orphan: true + github_token: ${{ secrets.GOLANGCI_LINT_TOKEN }} diff --git a/.github/workflows/post-release.yml b/.github/workflows/post-release.yml index 1da84e0cd31a..65435055ef02 100644 --- a/.github/workflows/post-release.yml +++ b/.github/workflows/post-release.yml @@ -1,47 +1,82 @@ -name: "Publish release documentation" +name: "Post release" on: release: types: - published jobs: - update-docs-and-assets: + update-docs: + name: "Update readme" + continue-on-error: true runs-on: ubuntu-latest env: GITHUB_TOKEN: ${{ secrets.GOLANGCI_LINT_TOKEN }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v5 with: # https://github.com/actions/setup-go#supported-version-syntax # ex: # - 1.18beta1 -> 1.18.0-beta.1 # - 1.18rc1 -> 1.18.0-rc.1 - go-version: '1.20' - - - name: Update GitHub action config - run: make assets/github-action-config.json - - - uses: actions/setup-node@v3 + go-version: '1.22' + - uses: actions/setup-node@v4 with: node-version: "15" check-latest: true + - name: npm install working-directory: .github/contributors run: npm install + - name: Update Contributors list - run: make update_contributors_list # may take 15 min + run: make update_contributors_list # may take more than 1 hour + + - name: Create Pull Request + uses: peter-evans/create-pull-request@v6 + with: + base: master + token: ${{ secrets.GOLANGCI_LINT_TOKEN }} + branch-suffix: timestamp + title: "docs: update documentation" + team-reviewers: golangci/team + delete-branch: true + + update-assets: + name: "Update assets" + runs-on: ubuntu-latest + env: + GITHUB_TOKEN: ${{ secrets.GOLANGCI_LINT_TOKEN }} + steps: + - uses: actions/checkout@v4 + - name: Install Go + uses: actions/setup-go@v5 + with: + # https://github.com/actions/setup-go#supported-version-syntax + # ex: + # - 1.18beta1 -> 1.18.0-beta.1 + # - 1.18rc1 -> 1.18.0-rc.1 + go-version: '1.22' + + - name: Update GitHub action config + run: make assets/github-action-config.json + + - name: Update reference files + run: cp .golangci.next.reference.yml .golangci.reference.yml + + - name: Update JSON schema files + run: cp jsonschema/golangci.next.jsonschema.json jsonschema/golangci.jsonschema.json - - name: Update netlify state hash - run: make update_netlify_state + - name: Update information + run: make website_dump_info - name: Create Pull Request - uses: peter-evans/create-pull-request@v4 + uses: peter-evans/create-pull-request@v6 with: base: master token: ${{ secrets.GOLANGCI_LINT_TOKEN }} branch-suffix: timestamp - title: "docs: Update documentation and assets" + title: "docs: update assets" team-reviewers: golangci/team delete-branch: true diff --git a/.github/workflows/pr-documentation.yml b/.github/workflows/pr-documentation.yml new file mode 100644 index 000000000000..c5d525bc4317 --- /dev/null +++ b/.github/workflows/pr-documentation.yml @@ -0,0 +1,54 @@ +name: Check Documentation + +on: + pull_request: + +jobs: + + doc: + name: Build documentation + runs-on: ubuntu-latest + env: + GO_VERSION: '1.22' + NODE_VERSION: '20.x' + CGO_ENABLED: 0 + + steps: + - name: Check out code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Go ${{ env.GO_VERSION }} + uses: actions/setup-go@v5 + with: + go-version: ${{ env.GO_VERSION }} + + - name: Cache Go modules + uses: actions/cache@v4 + with: + # In order: + # * Module download cache + # * Build cache (Linux) + path: | + ~/go/pkg/mod + ~/.cache/go-build + key: docs-${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + docs-${{ runner.os }}-go- + + - run: go mod download + + - name: Use Node.js ${{ env.NODE_VERSION }} + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: npm + cache-dependency-path: docs/package-lock.json + + - run: npm install --legacy-peer-deps + working-directory: ./docs + + - name: Build Documentation + run: npm run build + working-directory: ./docs diff --git a/.github/workflows/pr-extra.yml b/.github/workflows/pr-extra.yml index 221e4aa82f70..8cdd913be9e9 100644 --- a/.github/workflows/pr-extra.yml +++ b/.github/workflows/pr-extra.yml @@ -10,15 +10,15 @@ jobs: name: Vulnerability scanner runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-go@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 with: # https://github.com/actions/setup-go#supported-version-syntax # ex: # - 1.18beta1 -> 1.18.0-beta.1 # - 1.18rc1 -> 1.18.0-rc.1 - go-version: '1.20' + go-version: '1.22' - name: Run go list run: go list -json -m all > go.list - name: Nancy - uses: sonatype-nexus-community/nancy-github-action@v1.0.2 + uses: sonatype-nexus-community/nancy-github-action@v1.0.3 diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index c42696f8c060..66a0c847e9a2 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -6,7 +6,7 @@ on: pull_request: env: - GO_VERSION: '1.20' + GO_VERSION: '1.22' jobs: # Check if there is any dirty change for go mod tidy @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Install Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v5 with: # https://github.com/actions/setup-go#supported-version-syntax # ex: @@ -22,20 +22,21 @@ jobs: # - 1.18rc1 -> 1.18.0-rc.1 go-version: ${{ env.GO_VERSION }} - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Check go mod run: | go mod tidy git diff --exit-code go.mod + git diff --exit-code go.sum # We already run the current golangci-lint in tests, but here we test # our GitHub action with the latest stable golangci-lint. golangci-lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v5 with: # https://github.com/actions/setup-go#supported-version-syntax # ex: @@ -43,7 +44,7 @@ jobs: # - 1.18rc1 -> 1.18.0-rc.1 go-version: ${{ env.GO_VERSION }} - name: lint - uses: golangci/golangci-lint-action@v3.4.0 + uses: golangci/golangci-lint-action@v4.0.0 with: version: latest # skip cache because of flaky behaviors @@ -54,9 +55,9 @@ jobs: needs: golangci-lint # run after golangci-lint action to not produce duplicated errors runs-on: windows-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v5 with: # https://github.com/actions/setup-go#supported-version-syntax # ex: @@ -70,9 +71,9 @@ jobs: needs: golangci-lint # run after golangci-lint action to not produce duplicated errors runs-on: macos-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v5 with: # https://github.com/actions/setup-go#supported-version-syntax # ex: @@ -88,19 +89,19 @@ jobs: strategy: matrix: golang: - - 1.19 - - '1.20' + - '1.21' + - '1.22' steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v5 with: # https://github.com/actions/setup-go#supported-version-syntax # ex: # - 1.18beta1 -> 1.18.0-beta.1 # - 1.18rc1 -> 1.18.0-rc.1 go-version: ${{ matrix.golang }} - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ matrix.golang }}-${{ hashFiles('**/go.sum') }} @@ -112,15 +113,12 @@ jobs: check_generated: needs: golangci-lint # run after golangci-lint action to not produce duplicated errors runs-on: ubuntu-latest - env: - # needed for github-action-config.json generation - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Unshallow run: git fetch --prune --unshallow - name: Install Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v5 with: # https://github.com/actions/setup-go#supported-version-syntax # ex: @@ -129,3 +127,6 @@ jobs: go-version: ${{ env.GO_VERSION }} - name: Check generated files are up to date run: make fast_check_generated + env: + # needed for github-action-config.json generation + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/tag.yml b/.github/workflows/tag.yml index 99beb6ab8100..48c348ec1489 100644 --- a/.github/workflows/tag.yml +++ b/.github/workflows/tag.yml @@ -7,94 +7,32 @@ on: jobs: release: runs-on: ubuntu-latest - env: - GITHUB_TOKEN: ${{ secrets.GOLANGCI_LINT_TOKEN }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v5 with: # https://github.com/actions/setup-go#supported-version-syntax # ex: # - 1.18beta1 -> 1.18.0-beta.1 # - 1.18rc1 -> 1.18.0-rc.1 - go-version: '1.20' + go-version: '1.22' - name: Unshallow run: git fetch --prune --unshallow - - name: Create release - uses: goreleaser/goreleaser-action@v4 - with: - version: latest - args: release --rm-dist - env: - GITHUB_TOKEN: ${{ secrets.GOLANGCI_LINT_TOKEN }} - - docker-release: - needs: release - runs-on: ubuntu-latest - strategy: - matrix: - target: - - Dockerfile: build/Dockerfile - - Dockerfile: build/alpine.Dockerfile - steps: - - uses: actions/checkout@v3 - - - name: Install Go - uses: actions/setup-go@v3 - with: - # https://github.com/actions/setup-go#supported-version-syntax - # ex: - # - 1.18beta1 -> 1.18.0-beta.1 - # - 1.18rc1 -> 1.18.0-rc.1 - go-version: '1.20' - - - name: Unshallow - run: git fetch --prune --unshallow - - - name: Prepare - id: prepare - run: | - TAG=${GITHUB_REF#refs/tags/} - MAJOR=${TAG%.*} - SHORT_COMMIT=${GITHUB_SHA::8} - DATE=$(date '+%Y-%m-%dT%H:%M:%SZ') - echo tag_name=${TAG} >> $GITHUB_OUTPUT - echo major_tag=${MAJOR} >> $GITHUB_OUTPUT - echo short_commit=${SHORT_COMMIT} >> $GITHUB_OUTPUT - echo date=${DATE} >> $GITHUB_OUTPUT - if [[ ${{ matrix.target.Dockerfile }} == *"alpine"* ]]; then - echo full_tag_name=${TAG}-alpine >> $GITHUB_OUTPUT - echo full_major_tag=${MAJOR}-alpine >> $GITHUB_OUTPUT - echo latest_tag=latest-alpine >> $GITHUB_OUTPUT - else - echo full_tag_name=${TAG} >> $GITHUB_OUTPUT - echo full_major_tag=${MAJOR} >> $GITHUB_OUTPUT - echo latest_tag=latest >> $GITHUB_OUTPUT - fi - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 - name: Login do docker.io run: docker login -u golangci -p ${{ secrets.GOLANGCI_LINT_DOCKER_TOKEN }} - - name: Build and publish ${{ matrix.target.Dockerfile }} - uses: docker/build-push-action@v4 + - name: Create release + uses: goreleaser/goreleaser-action@v5 with: - context: . - file: ${{ matrix.target.Dockerfile }} - platforms: linux/amd64,linux/arm64 - push: true - build-args: | - VERSION=${{ steps.prepare.outputs.tag_name }} - SHORT_COMMIT=${{ steps.prepare.outputs.short_commit }} - DATE=${{ steps.prepare.outputs.date }} - tags: | - golangci/golangci-lint:${{ steps.prepare.outputs.full_tag_name }} - golangci/golangci-lint:${{ steps.prepare.outputs.full_major_tag }} - golangci/golangci-lint:${{ steps.prepare.outputs.latest_tag }} + version: latest + args: release --clean --timeout=90m + env: + GITHUB_TOKEN: ${{ secrets.GOLANGCI_LINT_TOKEN }} diff --git a/.gitignore b/.gitignore index d4e674623359..827702fbb926 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ /.vscode/ /dist/ /golangci-lint +/golangci-lint.exe /test/path /tools/Dracula.itermcolors /tools/dist/ @@ -17,3 +18,7 @@ /vendor/ coverage.out coverage.xml +/custom-golangci-lint +/custom-gcl +.custom-gcl.yml +.custom-gcl.yaml diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml new file mode 100644 index 000000000000..85916490ff04 --- /dev/null +++ b/.golangci.next.reference.yml @@ -0,0 +1,2916 @@ +# This file contains all available configuration options +# with their default values (in comments). +# +# This file is not a configuration example, +# it contains the exhaustive configuration with explanations of the options. + +# Options for analysis running. +run: + # Number of operating system threads (`GOMAXPROCS`) that can execute golangci-lint simultaneously. + # If it is explicitly set to 0 (i.e. not the default) then golangci-lint will automatically set the value to match Linux container CPU quota. + # Default: the number of logical CPUs in the machine + concurrency: 4 + + # Timeout for analysis, e.g. 30s, 5m. + # Default: 1m + timeout: 5m + + # Exit code when at least one issue was found. + # Default: 1 + issues-exit-code: 2 + + # Include test files or not. + # Default: true + tests: false + + # List of build tags, all linters use it. + # Default: [] + build-tags: + - mytag + + # Which dirs to skip: issues from them won't be reported. + # Can use regexp here: `generated.*`, regexp is applied on full path, + # including the path prefix if one is set. + # Default dirs are skipped independently of this option's value (see skip-dirs-use-default). + # "/" will be replaced by current OS file path separator to properly work on Windows. + # Default: [] + skip-dirs: + - src/external_libs + - autogenerated_by_my_lib + + # Enables skipping of directories: + # - vendor$, third_party$, testdata$, examples$, Godeps$, builtin$ + # Default: true + skip-dirs-use-default: false + + # Which files to skip: they will be analyzed, but issues from them won't be reported. + # There is no need to include all autogenerated files, + # we confidently recognize autogenerated files. + # If it's not, please let us know. + # "/" will be replaced by current OS file path separator to properly work on Windows. + # Default: [] + skip-files: + - ".*\\.my\\.go$" + - lib/bad.go + + # If set, we pass it to "go list -mod={option}". From "go help modules": + # If invoked with -mod=readonly, the go command is disallowed from the implicit + # automatic updating of go.mod described above. Instead, it fails when any changes + # to go.mod are needed. This setting is most useful to check that go.mod does + # not need updates, such as in a continuous integration and testing system. + # If invoked with -mod=vendor, the go command assumes that the vendor + # directory holds the correct copies of dependencies and ignores + # the dependency descriptions in go.mod. + # + # Allowed values: readonly|vendor|mod + # Default: "" + modules-download-mode: readonly + + # Allow multiple parallel golangci-lint instances running. + # If false, golangci-lint acquires file lock on start. + # Default: false + allow-parallel-runners: true + + # Allow multiple golangci-lint instances running, but serialize them around a lock. + # If false, golangci-lint exits with an error if it fails to acquire file lock on start. + # Default: false + allow-serial-runners: true + + # Define the Go version limit. + # Mainly related to generics support since go1.18. + # Default: use Go version from the go.mod file, fallback on the env var `GOVERSION`, fallback on 1.17 + go: '1.19' + + +# output configuration options +output: + # Format: colored-line-number|line-number|json|colored-tab|tab|checkstyle|code-climate|junit-xml|github-actions|teamcity + # + # Multiple can be specified by separating them by comma, output can be provided + # for each of them by separating format name and path by colon symbol. + # Output path can be either `stdout`, `stderr` or path to the file to write to. + # Example: "checkstyle:report.xml,json:stdout,colored-line-number" + # + # Default: colored-line-number + format: json + + # Print lines of code with issue. + # Default: true + print-issued-lines: false + + # Print linter name in the end of issue text. + # Default: true + print-linter-name: false + + # Make issues output unique by line. + # Default: true + uniq-by-line: false + + # Add a prefix to the output file references. + # Default: "" + path-prefix: "" + + # Sort results by the order defined in `sort-order`. + # Default: false + sort-results: true + + # Order to use when sorting results. + # Require `sort-results` to `true`. + # Possible values: `file`, `linter`, and `severity`. + # + # If the severity values are inside the following list, they are ordered in this order: + # 1. error + # 2. warning + # 3. high + # 4. medium + # 5. low + # Either they are sorted alphabetically. + # + # Default: ["file"] + sort-order: + - linter + - severity + - file # filepath, line, and column. + + # Show statistics per linter. + # Default: false + show-stats: true + + +# All available settings of specific linters. +linters-settings: + asasalint: + # To specify a set of function names to exclude. + # The values are merged with the builtin exclusions. + # The builtin exclusions can be disabled by setting `use-builtin-exclusions` to `false`. + # Default: ["^(fmt|log|logger|t|)\.(Print|Fprint|Sprint|Fatal|Panic|Error|Warn|Warning|Info|Debug|Log)(|f|ln)$"] + exclude: + - Append + - \.Wrapf + # To enable/disable the asasalint builtin exclusions of function names. + # See the default value of `exclude` to get the builtin exclusions. + # Default: true + use-builtin-exclusions: false + # Ignore *_test.go files. + # Default: false + ignore-test: true + + bidichk: + # The following configurations check for all mentioned invisible unicode runes. + # All runes are enabled by default. + left-to-right-embedding: false + right-to-left-embedding: false + pop-directional-formatting: false + left-to-right-override: false + right-to-left-override: false + left-to-right-isolate: false + right-to-left-isolate: false + first-strong-isolate: false + pop-directional-isolate: false + + copyloopvar: + # If true, ignore aliasing of loop variables. + # Default: false + ignore-alias: true + + cyclop: + # The maximal code complexity to report. + # Default: 10 + max-complexity: 10 + # The maximal average package complexity. + # If it's higher than 0.0 (float) the check is enabled + # Default: 0.0 + package-average: 0.5 + # Should ignore tests. + # Default: false + skip-tests: true + + decorder: + # Required order of `type`, `const`, `var` and `func` declarations inside a file. + # Default: types before constants before variables before functions. + dec-order: + - type + - const + - var + - func + + # If true, underscore vars (vars with "_" as the name) will be ignored at all checks + # Default: false (underscore vars are not ignored) + ignore-underscore-vars: false + + # If true, order of declarations is not checked at all. + # Default: true (disabled) + disable-dec-order-check: false + + # If true, `init` func can be anywhere in file (does not have to be declared before all other functions). + # Default: true (disabled) + disable-init-func-first-check: false + + # If true, multiple global `type`, `const` and `var` declarations are allowed. + # Default: true (disabled) + disable-dec-num-check: false + + # If true, type declarations will be ignored for dec num check + # Default: false (type statements are not ignored) + disable-type-dec-num-check: false + + # If true, const declarations will be ignored for dec num check + # Default: false (const statements are not ignored) + disable-const-dec-num-check: false + + # If true, var declarations will be ignored for dec num check + # Default: false (var statements are not ignored) + disable-var-dec-num-check: false + + depguard: + # Rules to apply. + # + # Variables: + # - File Variables + # you can still use and exclamation mark ! in front of a variable to say not to use it. + # Example !$test will match any file that is not a go test file. + # + # `$all` - matches all go files + # `$test` - matches all go test files + # + # - Package Variables + # + # `$gostd` - matches all of go's standard library (Pulled from `GOROOT`) + # + # Default: Only allow $gostd in all files. + rules: + # Name of a rule. + main: + # Used to determine the package matching priority. + # There are three different modes: `original`, `strict`, and `lax`. + # Default: "original" + list-mode: lax + # List of file globs that will match this list of settings to compare against. + # Default: $all + files: + - "!**/*_a _file.go" + # List of allowed packages. + allow: + - $gostd + - github.com/OpenPeeDeeP + # Packages that are not allowed where the value is a suggestion. + deny: + - pkg: "github.com/sirupsen/logrus" + desc: not allowed + - pkg: "github.com/pkg/errors" + desc: Should be replaced by standard lib errors package + + dogsled: + # Checks assignments with too many blank identifiers. + # Default: 2 + max-blank-identifiers: 3 + + dupl: + # Tokens count to trigger issue. + # Default: 150 + threshold: 100 + + dupword: + # Keywords for detecting duplicate words. + # If this list is not empty, only the words defined in this list will be detected. + # Default: [] + keywords: + - "the" + - "and" + - "a" + # Keywords used to ignore detection. + # Default: [] + ignore: + - "0C0C" + + errcheck: + # Report about not checking of errors in type assertions: `a := b.(MyStruct)`. + # Such cases aren't reported by default. + # Default: false + check-type-assertions: true + + # report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`. + # Such cases aren't reported by default. + # Default: false + check-blank: true + + # DEPRECATED comma-separated list of pairs of the form pkg:regex + # + # the regex is used to ignore names within pkg. (default "fmt:.*"). + # see https://github.com/kisielk/errcheck#the-deprecated-method for details + ignore: fmt:.*,io/ioutil:^Read.* + + # To disable the errcheck built-in exclude list. + # See `-excludeonly` option in https://github.com/kisielk/errcheck#excluding-functions for details. + # Default: false + disable-default-exclusions: true + + # DEPRECATED use exclude-functions instead. + # + # Path to a file containing a list of functions to exclude from checking. + # See https://github.com/kisielk/errcheck#excluding-functions for details. + exclude: /path/to/file.txt + + # List of functions to exclude from checking, where each entry is a single function to exclude. + # See https://github.com/kisielk/errcheck#excluding-functions for details. + exclude-functions: + - io/ioutil.ReadFile + - io.Copy(*bytes.Buffer) + - io.Copy(os.Stdout) + + errchkjson: + # With check-error-free-encoding set to true, errchkjson does warn about errors + # from json encoding functions that are safe to be ignored, + # because they are not possible to happen. + # + # if check-error-free-encoding is set to true and errcheck linter is enabled, + # it is recommended to add the following exceptions to prevent from false positives: + # + # linters-settings: + # errcheck: + # exclude-functions: + # - encoding/json.Marshal + # - encoding/json.MarshalIndent + # + # Default: false + check-error-free-encoding: true + + # Issue on struct encoding that doesn't have exported fields. + # Default: false + report-no-exported: false + + errorlint: + # Check whether fmt.Errorf uses the %w verb for formatting errors. + # See the https://github.com/polyfloyd/go-errorlint for caveats. + # Default: true + errorf: false + # Permit more than 1 %w verb, valid per Go 1.20 (Requires errorf:true) + # Default: true + errorf-multi: false + # Check for plain type assertions and type switches. + # Default: true + asserts: false + # Check for plain error comparisons. + # Default: true + comparison: false + + exhaustive: + # Program elements to check for exhaustiveness. + # Default: [ switch ] + check: + - switch + - map + # Check switch statements in generated files also. + # Default: false + check-generated: true + # Presence of "default" case in switch statements satisfies exhaustiveness, + # even if all enum members are not listed. + # Default: false + default-signifies-exhaustive: true + # Enum members matching the supplied regex do not have to be listed in + # switch statements to satisfy exhaustiveness. + # Default: "" + ignore-enum-members: "Example.+" + # Enum types matching the supplied regex do not have to be listed in + # switch statements to satisfy exhaustiveness. + # Default: "" + ignore-enum-types: "Example.+" + # Consider enums only in package scopes, not in inner scopes. + # Default: false + package-scope-only: true + # Only run exhaustive check on switches with "//exhaustive:enforce" comment. + # Default: false + explicit-exhaustive-switch: true + # Only run exhaustive check on map literals with "//exhaustive:enforce" comment. + # Default: false + explicit-exhaustive-map: true + # Switch statement requires default case even if exhaustive. + # Default: false + default-case-required: true + + exhaustruct: + # List of regular expressions to match struct packages and their names. + # Regular expressions must match complete canonical struct package/name/structname. + # If this list is empty, all structs are tested. + # Default: [] + include: + - '.+\.Test' + - 'example\.com/package\.ExampleStruct[\d]{1,2}' + # List of regular expressions to exclude struct packages and their names from checks. + # Regular expressions must match complete canonical struct package/name/structname. + # Default: [] + exclude: + - '.+/cobra\.Command$' + + forbidigo: + # Forbid the following identifiers (list of regexp). + # Default: ["^(fmt\\.Print(|f|ln)|print|println)$"] + forbid: + # Builtin function: + - ^print.*$ + # Optional message that gets included in error reports. + - p: ^fmt\.Print.*$ + msg: Do not commit print statements. + # Alternatively, put messages at the end of the regex, surrounded by `(# )?` + # Escape any special characters. Those messages get included in error reports. + - 'fmt\.Print.*(# Do not commit print statements\.)?' + # Forbid spew Dump, whether it is called as function or method. + # Depends on analyze-types below. + - ^spew\.(ConfigState\.)?Dump$ + # The package name might be ambiguous. + # The full import path can be used as additional criteria. + # Depends on analyze-types below. + - p: ^v1.Dump$ + pkg: ^example.com/pkg/api/v1$ + # Exclude godoc examples from forbidigo checks. + # Default: true + exclude-godoc-examples: false + # Instead of matching the literal source code, + # use type information to replace expressions with strings that contain the package name + # and (for methods and fields) the type name. + # This makes it possible to handle import renaming and forbid struct fields and methods. + # Default: false + analyze-types: true + + funlen: + # Checks the number of lines in a function. + # If lower than 0, disable the check. + # Default: 60 + lines: -1 + # Checks the number of statements in a function. + # If lower than 0, disable the check. + # Default: 40 + statements: -1 + # Ignore comments when counting lines. + # Default false + ignore-comments: true + + gci: + # DEPRECATED: use `sections` and `prefix(github.com/org/project)` instead. + local-prefixes: github.com/org/project + + # Section configuration to compare against. + # Section names are case-insensitive and may contain parameters in (). + # The default order of sections is `standard > default > custom > blank > dot > alias`, + # If `custom-order` is `true`, it follows the order of `sections` option. + # Default: ["standard", "default"] + sections: + - standard # Standard section: captures all standard packages. + - default # Default section: contains all imports that could not be matched to another section type. + - prefix(github.com/org/project) # Custom section: groups all imports with the specified Prefix. + - blank # Blank section: contains all blank imports. This section is not present unless explicitly enabled. + - dot # Dot section: contains all dot imports. This section is not present unless explicitly enabled. + - alias # Alias section: contains all alias imports. This section is not present unless explicitly enabled. + + # Skip generated files. + # Default: true + skip-generated: false + + # Enable custom order of sections. + # If `true`, make the section order the same as the order of `sections`. + # Default: false + custom-order: true + + ginkgolinter: + # Suppress the wrong length assertion warning. + # Default: false + suppress-len-assertion: true + + # Suppress the wrong nil assertion warning. + # Default: false + suppress-nil-assertion: true + + # Suppress the wrong error assertion warning. + # Default: false + suppress-err-assertion: true + + # Suppress the wrong comparison assertion warning. + # Default: false + suppress-compare-assertion: true + + # Suppress the function all in async assertion warning. + # Default: false + suppress-async-assertion: true + + # Suppress warning for comparing values from different types, like int32 and uint32 + # Default: false + suppress-type-compare-assertion: true + + # Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt + # Default: false + forbid-focus-container: true + + # Don't trigger warnings for HaveLen(0) + # Default: false + allow-havelen-zero: true + + gocognit: + # Minimal code complexity to report. + # Default: 30 (but we recommend 10-20) + min-complexity: 10 + + goconst: + # Minimal length of string constant. + # Default: 3 + min-len: 2 + # Minimum occurrences of constant string count to trigger issue. + # Default: 3 + min-occurrences: 2 + # Ignore test files. + # Default: false + ignore-tests: true + # Look for existing constants matching the values. + # Default: true + match-constant: false + # Search also for duplicated numbers. + # Default: false + numbers: true + # Minimum value, only works with goconst.numbers + # Default: 3 + min: 2 + # Maximum value, only works with goconst.numbers + # Default: 3 + max: 2 + # Ignore when constant is not used as function argument. + # Default: true + ignore-calls: false + # Exclude strings matching the given regular expression. + # Default: "" + ignore-strings: 'foo.+' + + gocritic: + # Disable all checks. + # Default: false + disable-all: true + # Which checks should be enabled in addition to default checks; can't be combined with 'disabled-checks'. + # By default, list of stable checks is used (https://go-critic.github.io/overview#checks-overview): + # appendAssign, argOrder, assignOp, badCall, badCond, captLocal, caseOrder, codegenComment, commentFormatting, + # defaultCaseOrder, deprecatedComment, dupArg, dupBranchBody, dupCase, dupSubExpr, elseif, exitAfterDefer, + # flagDeref, flagName, ifElseChain, mapKey, newDeref, offBy1, regexpMust, singleCaseSwitch, sloppyLen, + # sloppyTypeAssert, switchTrue, typeSwitchVar, underef, unlambda, unslice, valSwap, wrapperFunc + # To see which checks are enabled run `GL_DEBUG=gocritic golangci-lint run --enable=gocritic`. + enabled-checks: + - nestingReduce + - unnamedResult + - ruleguard + - truncateCmp + + # Enable all checks. + # Default: false + enable-all: true + # Which checks should be disabled; can't be combined with 'enabled-checks'. + # Default: [] + disabled-checks: + - regexpMust + + # Enable multiple checks by tags in addition to default checks. + # Run `GL_DEBUG=gocritic golangci-lint run --enable=gocritic` to see all tags and checks. + # See https://github.com/go-critic/go-critic#usage -> section "Tags". + # Default: [] + enabled-tags: + - diagnostic + - style + - performance + - experimental + - opinionated + disabled-tags: + - diagnostic + - style + - performance + - experimental + - opinionated + + # Settings passed to gocritic. + # The settings key is the name of a supported gocritic checker. + # The list of supported checkers can be find in https://go-critic.github.io/overview. + settings: + # Must be valid enabled check name. + captLocal: + # Whether to restrict checker to params only. + # Default: true + paramsOnly: false + commentedOutCode: + # Min length of the comment that triggers a warning. + # Default: 15 + minLength: 50 + elseif: + # Whether to skip balanced if-else pairs. + # Default: true + skipBalanced: false + hugeParam: + # Size in bytes that makes the warning trigger. + # Default: 80 + sizeThreshold: 70 + ifElseChain: + # Min number of if-else blocks that makes the warning trigger. + # Default: 2 + minThreshold: 4 + nestingReduce: + # Min number of statements inside a branch to trigger a warning. + # Default: 5 + bodyWidth: 4 + rangeExprCopy: + # Size in bytes that makes the warning trigger. + # Default: 512 + sizeThreshold: 516 + # Whether to check test functions + # Default: true + skipTestFuncs: false + rangeValCopy: + # Size in bytes that makes the warning trigger. + # Default: 128 + sizeThreshold: 32 + # Whether to check test functions. + # Default: true + skipTestFuncs: false + ruleguard: + # Enable debug to identify which 'Where' condition was rejected. + # The value of the parameter is the name of a function in a ruleguard file. + # + # When a rule is evaluated: + # If: + # The Match() clause is accepted; and + # One of the conditions in the Where() clause is rejected, + # Then: + # ruleguard prints the specific Where() condition that was rejected. + # + # The option is passed to the ruleguard 'debug-group' argument. + # Default: "" + debug: 'emptyDecl' + # Deprecated, use 'failOn' param. + # If set to true, identical to failOn='all', otherwise failOn='' + failOnError: false + # Determines the behavior when an error occurs while parsing ruleguard files. + # If flag is not set, log error and skip rule files that contain an error. + # If flag is set, the value must be a comma-separated list of error conditions. + # - 'all': fail on all errors. + # - 'import': ruleguard rule imports a package that cannot be found. + # - 'dsl': gorule file does not comply with the ruleguard DSL. + # Default: "" + failOn: dsl + # Comma-separated list of file paths containing ruleguard rules. + # If a path is relative, it is relative to the directory where the golangci-lint command is executed. + # The special '${configDir}' variable is substituted with the absolute directory containing the golangci config file. + # Glob patterns such as 'rules-*.go' may be specified. + # Default: "" + rules: '${configDir}/ruleguard/rules-*.go,${configDir}/myrule1.go' + # Comma-separated list of enabled groups or skip empty to enable everything. + # Tags can be defined with # character prefix. + # Default: "" + enable: "myGroupName,#myTagName" + # Comma-separated list of disabled groups or skip empty to enable everything. + # Tags can be defined with # character prefix. + # Default: "" + disable: "myGroupName,#myTagName" + tooManyResultsChecker: + # Maximum number of results. + # Default: 5 + maxResults: 10 + truncateCmp: + # Whether to skip int/uint/uintptr types. + # Default: true + skipArchDependent: false + underef: + # Whether to skip (*x).method() calls where x is a pointer receiver. + # Default: true + skipRecvDeref: false + unnamedResult: + # Whether to check exported functions. + # Default: false + checkExported: true + + gocyclo: + # Minimal code complexity to report. + # Default: 30 (but we recommend 10-20) + min-complexity: 10 + + godot: + # Comments to be checked: `declarations`, `toplevel`, or `all`. + # Default: declarations + scope: toplevel + # List of regexps for excluding particular comment lines from check. + # Default: [] + exclude: + # Exclude todo and fixme comments. + - "^fixme:" + - "^todo:" + # Check that each sentence ends with a period. + # Default: true + period: false + # Check that each sentence starts with a capital letter. + # Default: false + capital: true + + godox: + # Report any comments starting with keywords, this is useful for TODO or FIXME comments that + # might be left in the code accidentally and should be resolved before merging. + # Default: ["TODO", "BUG", "FIXME"] + keywords: + - NOTE + - OPTIMIZE # marks code that should be optimized before merging + - HACK # marks hack-around that should be removed before merging + + gofmt: + # Simplify code: gofmt with `-s` option. + # Default: true + simplify: false + # Apply the rewrite rules to the source before reformatting. + # https://pkg.go.dev/cmd/gofmt + # Default: [] + rewrite-rules: + - pattern: 'interface{}' + replacement: 'any' + - pattern: 'a[b:len(a)]' + replacement: 'a[b:]' + + gofumpt: + # Deprecated: use the global `run.go` instead. + lang-version: "1.17" + + # Module path which contains the source code being formatted. + # Default: "" + module-path: github.com/org/project + + # Choose whether to use the extra rules. + # Default: false + extra-rules: true + + goheader: + # Supports two types 'const` and `regexp`. + # Values can be used recursively. + # Default: {} + values: + const: + # Define here const type values in format k:v. + # For example: + COMPANY: MY COMPANY + regexp: + # Define here regexp type values. + # for example: + AUTHOR: .*@mycompany\.com + # The template use for checking. + # Default: "" + template: |- + # Put here copyright header template for source code files + # For example: + # Note: {{ YEAR }} is a builtin value that returns the year relative to the current machine time. + # + # {{ AUTHOR }} {{ COMPANY }} {{ YEAR }} + # SPDX-License-Identifier: Apache-2.0 + + # Licensed under the Apache License, Version 2.0 (the "License"); + # you may not use this file except in compliance with the License. + # You may obtain a copy of the License at: + + # http://www.apache.org/licenses/LICENSE-2.0 + + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. + # As alternative of directive 'template', you may put the path to file with the template source. + # Useful if you need to load the template from a specific file. + # Default: "" + template-path: /path/to/my/template.tmpl + + goimports: + # A comma-separated list of prefixes, which, if set, checks import paths + # with the given prefixes are grouped after 3rd-party packages. + # Default: "" + local-prefixes: github.com/org/project + + gomnd: + # List of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description. + # Default: ["argument", "case", "condition", "operation", "return", "assign"] + checks: + - argument + - case + - condition + - operation + - return + - assign + # List of numbers to exclude from analysis. + # The numbers should be written as string. + # Values always ignored: "1", "1.0", "0" and "0.0" + # Default: [] + ignored-numbers: + - '0666' + - '0755' + - '42' + # List of file patterns to exclude from analysis. + # Values always ignored: `.+_test.go` + # Default: [] + ignored-files: + - 'magic1_.+\.go$' + # List of function patterns to exclude from analysis. + # Following functions are always ignored: `time.Date`, + # `strconv.FormatInt`, `strconv.FormatUint`, `strconv.FormatFloat`, + # `strconv.ParseInt`, `strconv.ParseUint`, `strconv.ParseFloat`. + # Default: [] + ignored-functions: + - '^math\.' + - '^http\.StatusText$' + + gomoddirectives: + # Allow local `replace` directives. + # Default: false + replace-local: false + # List of allowed `replace` directives. + # Default: [] + replace-allow-list: + - launchpad.net/gocheck + # Allow to not explain why the version has been retracted in the `retract` directives. + # Default: false + retract-allow-no-explanation: false + # Forbid the use of the `exclude` directives. + # Default: false + exclude-forbidden: false + + gomodguard: + allowed: + # List of allowed modules. + # Default: [] + modules: + - gopkg.in/yaml.v2 + # List of allowed module domains. + # Default: [] + domains: + - golang.org + blocked: + # List of blocked modules. + # Default: [] + modules: + # Blocked module. + - github.com/uudashr/go-module: + # Recommended modules that should be used instead. (Optional) + recommendations: + - golang.org/x/mod + # Reason why the recommended module should be used. (Optional) + reason: "`mod` is the official go.mod parser library." + # List of blocked module version constraints. + # Default: [] + versions: + # Blocked module with version constraint. + - github.com/mitchellh/go-homedir: + # Version constraint, see https://github.com/Masterminds/semver#basic-comparisons. + version: "< 1.1.0" + # Reason why the version constraint exists. (Optional) + reason: "testing if blocked version constraint works." + # Set to true to raise lint issues for packages that are loaded from a local path via replace directive. + # Default: false + local_replace_directives: false + + gosimple: + # Deprecated: use the global `run.go` instead. + go: "1.15" + # Sxxxx checks in https://staticcheck.io/docs/configuration/options/#checks + # Default: ["*"] + checks: [ "all" ] + + gosec: + # To select a subset of rules to run. + # Available rules: https://github.com/securego/gosec#available-rules + # Default: [] - means include all rules + includes: + - G101 # Look for hard coded credentials + - G102 # Bind to all interfaces + - G103 # Audit the use of unsafe block + - G104 # Audit errors not checked + - G106 # Audit the use of ssh.InsecureIgnoreHostKey + - G107 # Url provided to HTTP request as taint input + - G108 # Profiling endpoint automatically exposed on /debug/pprof + - G109 # Potential Integer overflow made by strconv.Atoi result conversion to int16/32 + - G110 # Potential DoS vulnerability via decompression bomb + - G111 # Potential directory traversal + - G112 # Potential slowloris attack + - G113 # Usage of Rat.SetString in math/big with an overflow (CVE-2022-23772) + - G114 # Use of net/http serve function that has no support for setting timeouts + - G201 # SQL query construction using format string + - G202 # SQL query construction using string concatenation + - G203 # Use of unescaped data in HTML templates + - G204 # Audit use of command execution + - G301 # Poor file permissions used when creating a directory + - G302 # Poor file permissions used with chmod + - G303 # Creating tempfile using a predictable path + - G304 # File path provided as taint input + - G305 # File traversal when extracting zip/tar archive + - G306 # Poor file permissions used when writing to a new file + - G307 # Poor file permissions used when creating a file with os.Create + - G401 # Detect the usage of DES, RC4, MD5 or SHA1 + - G402 # Look for bad TLS connection settings + - G403 # Ensure minimum RSA key length of 2048 bits + - G404 # Insecure random number source (rand) + - G501 # Import blocklist: crypto/md5 + - G502 # Import blocklist: crypto/des + - G503 # Import blocklist: crypto/rc4 + - G504 # Import blocklist: net/http/cgi + - G505 # Import blocklist: crypto/sha1 + - G601 # Implicit memory aliasing of items from a range statement + - G602 # Slice access out of bounds + + # To specify a set of rules to explicitly exclude. + # Available rules: https://github.com/securego/gosec#available-rules + # Default: [] + excludes: + - G101 # Look for hard coded credentials + - G102 # Bind to all interfaces + - G103 # Audit the use of unsafe block + - G104 # Audit errors not checked + - G106 # Audit the use of ssh.InsecureIgnoreHostKey + - G107 # Url provided to HTTP request as taint input + - G108 # Profiling endpoint automatically exposed on /debug/pprof + - G109 # Potential Integer overflow made by strconv.Atoi result conversion to int16/32 + - G110 # Potential DoS vulnerability via decompression bomb + - G111 # Potential directory traversal + - G112 # Potential slowloris attack + - G113 # Usage of Rat.SetString in math/big with an overflow (CVE-2022-23772) + - G114 # Use of net/http serve function that has no support for setting timeouts + - G201 # SQL query construction using format string + - G202 # SQL query construction using string concatenation + - G203 # Use of unescaped data in HTML templates + - G204 # Audit use of command execution + - G301 # Poor file permissions used when creating a directory + - G302 # Poor file permissions used with chmod + - G303 # Creating tempfile using a predictable path + - G304 # File path provided as taint input + - G305 # File traversal when extracting zip/tar archive + - G306 # Poor file permissions used when writing to a new file + - G307 # Poor file permissions used when creating a file with os.Create + - G401 # Detect the usage of DES, RC4, MD5 or SHA1 + - G402 # Look for bad TLS connection settings + - G403 # Ensure minimum RSA key length of 2048 bits + - G404 # Insecure random number source (rand) + - G501 # Import blocklist: crypto/md5 + - G502 # Import blocklist: crypto/des + - G503 # Import blocklist: crypto/rc4 + - G504 # Import blocklist: net/http/cgi + - G505 # Import blocklist: crypto/sha1 + - G601 # Implicit memory aliasing of items from a range statement + - G602 # Slice access out of bounds + + # Exclude generated files + # Default: false + exclude-generated: true + + # Filter out the issues with a lower severity than the given value. + # Valid options are: low, medium, high. + # Default: low + severity: medium + + # Filter out the issues with a lower confidence than the given value. + # Valid options are: low, medium, high. + # Default: low + confidence: medium + + # Concurrency value. + # Default: the number of logical CPUs usable by the current process. + concurrency: 12 + + # To specify the configuration of rules. + config: + # Globals are applicable to all rules. + global: + # If true, ignore #nosec in comments (and an alternative as well). + # Default: false + nosec: true + # Add an alternative comment prefix to #nosec (both will work at the same time). + # Default: "" + "#nosec": "#my-custom-nosec" + # Define whether nosec issues are counted as finding or not. + # Default: false + show-ignored: true + # Audit mode enables addition checks that for normal code analysis might be too nosy. + # Default: false + audit: true + G101: + # Regexp pattern for variables and constants to find. + # Default: "(?i)passwd|pass|password|pwd|secret|token|pw|apiKey|bearer|cred" + pattern: "(?i)example" + # If true, complain about all cases (even with low entropy). + # Default: false + ignore_entropy: false + # Maximum allowed entropy of the string. + # Default: "80.0" + entropy_threshold: "80.0" + # Maximum allowed value of entropy/string length. + # Is taken into account if entropy >= entropy_threshold/2. + # Default: "3.0" + per_char_threshold: "3.0" + # Calculate entropy for first N chars of the string. + # Default: "16" + truncate: "32" + # Additional functions to ignore while checking unhandled errors. + # Following functions always ignored: + # bytes.Buffer: + # - Write + # - WriteByte + # - WriteRune + # - WriteString + # fmt: + # - Print + # - Printf + # - Println + # - Fprint + # - Fprintf + # - Fprintln + # strings.Builder: + # - Write + # - WriteByte + # - WriteRune + # - WriteString + # io.PipeWriter: + # - CloseWithError + # hash.Hash: + # - Write + # os: + # - Unsetenv + # Default: {} + G104: + fmt: + - Fscanf + G111: + # Regexp pattern to find potential directory traversal. + # Default: "http\\.Dir\\(\"\\/\"\\)|http\\.Dir\\('\\/'\\)" + pattern: "custom\\.Dir\\(\\)" + # Maximum allowed permissions mode for os.Mkdir and os.MkdirAll + # Default: "0750" + G301: "0750" + # Maximum allowed permissions mode for os.OpenFile and os.Chmod + # Default: "0600" + G302: "0600" + # Maximum allowed permissions mode for os.WriteFile and ioutil.WriteFile + # Default: "0600" + G306: "0600" + + gosmopolitan: + # Allow and ignore `time.Local` usages. + # + # Default: false + allow-time-local: true + # List of fully qualified names in the `full/pkg/path.name` form, to act as "i18n escape hatches". + # String literals inside call-like expressions to, or struct literals of those names, + # are exempt from the writing system check. + # + # Default: [] + escape-hatches: + - 'github.com/nicksnyder/go-i18n/v2/i18n.Message' + - 'example.com/your/project/i18n/markers.Raw' + - 'example.com/your/project/i18n/markers.OK' + - 'example.com/your/project/i18n/markers.TODO' + - 'command-line-arguments.Simple' + # Ignore test files. + # + # Default: true + ignore-tests: false + # List of Unicode scripts to watch for any usage in string literals. + # https://pkg.go.dev/unicode#pkg-variables + # + # Default: ["Han"] + watch-for-scripts: + - Devanagari + - Han + - Hangul + - Hiragana + - Katakana + + govet: + # Report about shadowed variables. + # Default: false + check-shadowing: true + + # Settings per analyzer. + settings: + # Analyzer name, run `go tool vet help` to see all analyzers. + printf: + # Comma-separated list of print function names to check (in addition to default, see `go tool vet help printf`). + # Default: [] + funcs: + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf + shadow: + # Whether to be strict about shadowing; can be noisy. + # Default: false + strict: true + unusedresult: + # Comma-separated list of functions whose results must be used + # (in addition to default: + # context.WithCancel, context.WithDeadline, context.WithTimeout, context.WithValue, errors.New, fmt.Errorf, + # fmt.Sprint, fmt.Sprintf, sort.Reverse + # ). + # Default: [] + funcs: + - pkg.MyFunc + # Comma-separated list of names of methods of type func() string whose results must be used + # (in addition to default Error,String) + # Default: [] + stringmethods: + - MyMethod + + # Disable all analyzers. + # Default: false + disable-all: true + # Enable analyzers by name. + # (in addition to default: + # appends, asmdecl, assign, atomic, bools, buildtag, cgocall, composites, copylocks, defers, directive, errorsas, + # framepointer, httpresponse, ifaceassert, loopclosure, lostcancel, nilfunc, printf, shift, sigchanyzer, slog, + # stdmethods, stringintconv, structtag, testinggoroutine, tests, timeformat, unmarshal, unreachable, unsafeptr, + # unusedresult + # ). + # Run `GL_DEBUG=govet golangci-lint run --enable=govet` to see default, all available analyzers, and enabled analyzers. + # Default: [] + enable: + - appends + - asmdecl + - assign + - atomic + - atomicalign + - bools + - buildtag + - cgocall + - composites + - copylocks + - deepequalerrors + - defers + - directive + - errorsas + - fieldalignment + - findcall + - framepointer + - httpresponse + - ifaceassert + - loopclosure + - lostcancel + - nilfunc + - nilness + - printf + - reflectvaluecompare + - shadow + - shift + - sigchanyzer + - slog + - sortslice + - stdmethods + - stringintconv + - structtag + - testinggoroutine + - tests + - unmarshal + - unreachable + - unsafeptr + - unusedresult + - unusedwrite + + # Enable all analyzers. + # Default: false + enable-all: true + # Disable analyzers by name. + # (in addition to default + # atomicalign, deepequalerrors, fieldalignment, findcall, nilness, reflectvaluecompare, shadow, sortslice, + # timeformat, unusedwrite + # ). + # Run `GL_DEBUG=govet golangci-lint run --enable=govet` to see default, all available analyzers, and enabled analyzers. + # Default: [] + disable: + - appends + - asmdecl + - assign + - atomic + - atomicalign + - bools + - buildtag + - cgocall + - composites + - copylocks + - deepequalerrors + - defers + - directive + - errorsas + - fieldalignment + - findcall + - framepointer + - httpresponse + - ifaceassert + - loopclosure + - lostcancel + - nilfunc + - nilness + - printf + - reflectvaluecompare + - shadow + - shift + - sigchanyzer + - slog + - sortslice + - stdmethods + - stringintconv + - structtag + - testinggoroutine + - tests + - unmarshal + - unreachable + - unsafeptr + - unusedresult + - unusedwrite + + grouper: + # Require the use of a single global 'const' declaration only. + # Default: false + const-require-single-const: true + # Require the use of grouped global 'const' declarations. + # Default: false + const-require-grouping: true + + # Require the use of a single 'import' declaration only. + # Default: false + import-require-single-import: true + # Require the use of grouped 'import' declarations. + # Default: false + import-require-grouping: true + + # Require the use of a single global 'type' declaration only. + # Default: false + type-require-single-type: true + # Require the use of grouped global 'type' declarations. + # Default: false + type-require-grouping: true + + # Require the use of a single global 'var' declaration only. + # Default: false + var-require-single-var: true + # Require the use of grouped global 'var' declarations. + # Default: false + var-require-grouping: true + + importas: + # Do not allow unaliased imports of aliased packages. + # Default: false + no-unaliased: true + # Do not allow non-required aliases. + # Default: false + no-extra-aliases: true + # List of aliases + # Default: [] + alias: + # Using `servingv1` alias for `knative.dev/serving/pkg/apis/serving/v1` package. + - pkg: knative.dev/serving/pkg/apis/serving/v1 + alias: servingv1 + # Using `autoscalingv1alpha1` alias for `knative.dev/serving/pkg/apis/autoscaling/v1alpha1` package. + - pkg: knative.dev/serving/pkg/apis/autoscaling/v1alpha1 + alias: autoscalingv1alpha1 + # You can specify the package path by regular expression, + # and alias by regular expression expansion syntax like below. + # see https://github.com/julz/importas#use-regular-expression for details + - pkg: knative.dev/serving/pkg/apis/(\w+)/(v[\w\d]+) + alias: $1$2 + + inamedparam: + # Skips check for interface methods with only a single parameter. + # Default: false + skip-single-param: true + + interfacebloat: + # The maximum number of methods allowed for an interface. + # Default: 10 + max: 5 + + ireturn: + # ireturn does not allow using `allow` and `reject` settings at the same time. + # Both settings are lists of the keywords and regular expressions matched to interface or package names. + # keywords: + # - `empty` for `interface{}` + # - `error` for errors + # - `stdlib` for standard library + # - `anon` for anonymous interfaces + # - `generic` for generic interfaces added in go 1.18 + + # By default, it allows using errors, empty interfaces, anonymous interfaces, + # and interfaces provided by the standard library. + allow: + - anon + - error + - empty + - stdlib + # You can specify idiomatic endings for interface + - (or|er)$ + + # reject-list of interfaces + reject: + - github.com\/user\/package\/v4\.Type + + lll: + # Max line length, lines longer will be reported. + # '\t' is counted as 1 character by default, and can be changed with the tab-width option. + # Default: 120. + line-length: 120 + # Tab width in spaces. + # Default: 1 + tab-width: 1 + + loggercheck: + # Allow check for the github.com/go-kit/log library. + # Default: true + kitlog: false + # Allow check for the k8s.io/klog/v2 library. + # Default: true + klog: false + # Allow check for the github.com/go-logr/logr library. + # Default: true + logr: false + # Allow check for the "sugar logger" from go.uber.org/zap library. + # Default: true + zap: false + # Require all logging keys to be inlined constant strings. + # Default: false + require-string-key: true + # Require printf-like format specifier (%s, %d for example) not present. + # Default: false + no-printf-like: true + # List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers. + # For example: https://github.com/timonwong/loggercheck/blob/7395ab86595781e33f7afba27ad7b55e6956ebcd/testdata/custom-rules.txt + # Default: empty + rules: + - k8s.io/klog/v2.InfoS # package level exported functions + - (github.com/go-logr/logr.Logger).Error # "Methods" + - (*go.uber.org/zap.SugaredLogger).With # Also "Methods", but with a pointer receiver + + maintidx: + # Show functions with maintainability index lower than N. + # A high index indicates better maintainability (it's kind of the opposite of complexity). + # Default: 20 + under: 100 + + makezero: + # Allow only slices initialized with a length of zero. + # Default: false + always: true + + misspell: + # Correct spellings using locale preferences for US or UK. + # Setting locale to US will correct the British spelling of 'colour' to 'color'. + # Default is to use a neutral variety of English. + locale: US + # Typos to ignore. + # Should be in lower case. + # Default: [] + ignore-words: + - someword + # Extra word corrections. + # `typo` and `correction` should only contain letters. + # The words are case-insensitive. + # Default: [] + extra-words: + - typo: "iff" + correction: "if" + - typo: "cancelation" + correction: "cancellation" + # Mode of the analysis: + # - default: checks all the file content. + # - restricted: checks only comments. + # Default: "" + mode: restricted + + musttag: + # A set of custom functions to check in addition to the builtin ones. + # Default: json, xml, gopkg.in/yaml.v3, BurntSushi/toml, mitchellh/mapstructure, jmoiron/sqlx + functions: + # The full name of the function, including the package. + - name: github.com/hashicorp/hcl/v2/hclsimple.DecodeFile + # The struct tag whose presence should be ensured. + tag: hcl + # The position of the argument to check. + arg-pos: 2 + + nakedret: + # Make an issue if func has more lines of code than this setting, and it has naked returns. + # Default: 30 + max-func-lines: 31 + + nestif: + # Minimal complexity of if statements to report. + # Default: 5 + min-complexity: 4 + + nilnil: + # Checks that there is no simultaneous return of `nil` error and an invalid value. + # Default: ["ptr", "func", "iface", "map", "chan"] + checked-types: + - ptr + - func + - iface + - map + - chan + + nlreturn: + # Size of the block (including return statement that is still "OK") + # so no return split required. + # Default: 1 + block-size: 2 + + nolintlint: + # Disable to ensure that all nolint directives actually have an effect. + # Default: false + allow-unused: true + # Exclude following linters from requiring an explanation. + # Default: [] + allow-no-explanation: [ ] + # Enable to require an explanation of nonzero length after each nolint directive. + # Default: false + require-explanation: true + # Enable to require nolint directives to mention the specific linter being suppressed. + # Default: false + require-specific: true + + nonamedreturns: + # Report named error if it is assigned inside defer. + # Default: false + report-error-in-defer: true + + paralleltest: + # Ignore missing calls to `t.Parallel()` and only report incorrect uses of it. + # Default: false + ignore-missing: true + # Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are + # still required to have `t.Parallel`, but subtests are allowed to skip it. + # Default: false + ignore-missing-subtests: true + + perfsprint: + # Optimizes even if it requires an int or uint type cast. + # Default: true + int-conversion: false + # Optimizes into `err.Error()` even if it is only equivalent for non-nil errors. + # Default: false + err-error: true + # Optimizes `fmt.Errorf`. + # Default: true + errorf: false + # Optimizes `fmt.Sprintf` with only one argument. + # Default: true + sprintf1: false + # Optimizes into strings concatenation. + # Default: true + strconcat: false + + prealloc: + # IMPORTANT: we don't recommend using this linter before doing performance profiling. + # For most programs usage of prealloc will be a premature optimization. + + # Report pre-allocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them. + # Default: true + simple: false + # Report pre-allocation suggestions on range loops. + # Default: true + range-loops: false + # Report pre-allocation suggestions on for loops. + # Default: false + for-loops: true + + predeclared: + # Comma-separated list of predeclared identifiers to not report on. + # Default: "" + ignore: "new,int" + # Include method names and field names (i.e., qualified names) in checks. + # Default: false + q: true + + promlinter: + # Promlinter cannot infer all metrics name in static analysis. + # Enable strict mode will also include the errors caused by failing to parse the args. + # Default: false + strict: true + # Please refer to https://github.com/yeya24/promlinter#usage for detailed usage. + # Default: [] + disabled-linters: + - Help + - MetricUnits + - Counter + - HistogramSummaryReserved + - MetricTypeInName + - ReservedChars + - CamelCase + - UnitAbbreviations + + protogetter: + # Skip files generated by specified generators from the checking. + # Checks only the file's initial comment, which must follow the format: "// Code generated by ". + # Files generated by protoc-gen-go, protoc-gen-go-grpc, and protoc-gen-grpc-gateway are always excluded automatically. + # Default: [] + skip-generated-by: ["protoc-gen-go-my-own-generator"] + # Skip files matching the specified glob pattern from the checking. + # Default: [] + skip-files: + - "*.pb.go" + - "*/vendor/*" + - "/full/path/to/file.go" + # Skip any generated files from the checking. + # Default: false + skip-any-generated: true + # Skip first argument of append function. + # Default: false + replace-first-arg-in-append: true + + reassign: + # Patterns for global variable names that are checked for reassignment. + # See https://github.com/curioswitch/go-reassign#usage + # Default: ["EOF", "Err.*"] + patterns: + - ".*" + + revive: + # Maximum number of open files at the same time. + # See https://github.com/mgechev/revive#command-line-flags + # Defaults to unlimited. + max-open-files: 2048 + + # When set to false, ignores files with "GENERATED" header, similar to golint. + # See https://github.com/mgechev/revive#available-rules for details. + # Default: false + ignore-generated-header: true + + # Sets the default severity. + # See https://github.com/mgechev/revive#configuration + # Default: warning + severity: error + + # Enable all available rules. + # Default: false + enable-all-rules: true + + # Sets the default failure confidence. + # This means that linting errors with less than 0.8 confidence will be ignored. + # Default: 0.8 + confidence: 0.1 + + rules: + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#add-constant + - name: add-constant + severity: warning + disabled: false + exclude: [""] + arguments: + - maxLitCount: "3" + allowStrs: '""' + allowInts: "0,1,2" + allowFloats: "0.0,0.,1.0,1.,2.0,2." + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#argument-limit + - name: argument-limit + severity: warning + disabled: false + exclude: [""] + arguments: [ 4 ] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#atomic + - name: atomic + severity: warning + exclude: [""] + disabled: false + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#banned-characters + - name: banned-characters + severity: warning + disabled: false + exclude: [""] + arguments: [ "Ω","Σ","σ", "7" ] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#bare-return + - name: bare-return + severity: warning + exclude: [""] + disabled: false + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#blank-imports + - name: blank-imports + severity: warning + exclude: [""] + disabled: false + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#bool-literal-in-expr + - name: bool-literal-in-expr + severity: warning + exclude: [""] + disabled: false + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#call-to-gc + - name: call-to-gc + severity: warning + exclude: [""] + disabled: false + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#cognitive-complexity + - name: cognitive-complexity + severity: warning + disabled: false + exclude: [""] + arguments: [ 7 ] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#comment-spacings + - name: comment-spacings + severity: warning + disabled: false + exclude: [""] + arguments: + - mypragma + - otherpragma + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#confusing-naming + - name: confusing-naming + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#confusing-results + - name: confusing-results + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#constant-logical-expr + - name: constant-logical-expr + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#context-as-argument + - name: context-as-argument + severity: warning + disabled: false + exclude: [""] + arguments: + - allowTypesBefore: "*testing.T,*github.com/user/repo/testing.Harness" + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#context-keys-type + - name: context-keys-type + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#cyclomatic + - name: cyclomatic + severity: warning + disabled: false + exclude: [""] + arguments: [ 3 ] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#datarace + - name: datarace + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#deep-exit + - name: deep-exit + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#defer + - name: defer + severity: warning + disabled: false + exclude: [""] + arguments: + - [ "call-chain", "loop" ] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#dot-imports + - name: dot-imports + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#duplicated-imports + - name: duplicated-imports + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#early-return + - name: early-return + severity: warning + disabled: false + exclude: [""] + arguments: + - "preserveScope" + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#empty-block + - name: empty-block + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#empty-lines + - name: empty-lines + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#enforce-map-style + - name: enforce-map-style + severity: warning + disabled: false + exclude: [""] + arguments: + - "make" + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#enforce-repeated-arg-type-style + - name: enforce-repeated-arg-type-style + severity: warning + disabled: false + exclude: [""] + arguments: + - "short" + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#enforce-slice-style + - name: enforce-slice-style + severity: warning + disabled: false + exclude: [""] + arguments: + - "make" + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#error-naming + - name: error-naming + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#error-return + - name: error-return + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#error-strings + - name: error-strings + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#errorf + - name: errorf + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#exported + - name: exported + severity: warning + disabled: false + exclude: [""] + arguments: + - "preserveScope" + - "checkPrivateReceivers" + - "sayRepetitiveInsteadOfStutters" + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#file-header + - name: file-header + severity: warning + disabled: false + exclude: [""] + arguments: + - This is the text that must appear at the top of source files. + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#flag-parameter + - name: flag-parameter + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#function-result-limit + - name: function-result-limit + severity: warning + disabled: false + exclude: [""] + arguments: [ 2 ] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#function-length + - name: function-length + severity: warning + disabled: false + exclude: [""] + arguments: [ 10, 0 ] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#get-return + - name: get-return + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#identical-branches + - name: identical-branches + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#if-return + - name: if-return + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#increment-decrement + - name: increment-decrement + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#indent-error-flow + - name: indent-error-flow + severity: warning + disabled: false + exclude: [""] + arguments: + - "preserveScope" + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#import-alias-naming + - name: import-alias-naming + severity: warning + disabled: false + exclude: [""] + arguments: + - "^[a-z][a-z0-9]{0,}$" + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#imports-blocklist + - name: imports-blocklist + severity: warning + disabled: false + exclude: [""] + arguments: + - "crypto/md5" + - "crypto/sha1" + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#import-shadowing + - name: import-shadowing + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#line-length-limit + - name: line-length-limit + severity: warning + disabled: false + exclude: [""] + arguments: [ 80 ] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#max-control-nesting + - name: max-control-nesting + severity: warning + disabled: false + exclude: [""] + arguments: [ 3 ] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#max-public-structs + - name: max-public-structs + severity: warning + disabled: false + exclude: [""] + arguments: [ 3 ] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#modifies-parameter + - name: modifies-parameter + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#modifies-value-receiver + - name: modifies-value-receiver + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#nested-structs + - name: nested-structs + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#optimize-operands-order + - name: optimize-operands-order + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#package-comments + - name: package-comments + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#range + - name: range + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#range-val-in-closure + - name: range-val-in-closure + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#range-val-address + - name: range-val-address + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#receiver-naming + - name: receiver-naming + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#redundant-import-alias + - name: redundant-import-alias + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#redefines-builtin-id + - name: redefines-builtin-id + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#string-of-int + - name: string-of-int + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#string-format + - name: string-format + severity: warning + disabled: false + exclude: [""] + arguments: + - - 'core.WriteError[1].Message' + - '/^([^A-Z]|$)/' + - must not start with a capital letter + - - 'fmt.Errorf[0]' + - '/(^|[^\.!?])$/' + - must not end in punctuation + - - panic + - '/^[^\n]*$/' + - must not contain line breaks + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#struct-tag + - name: struct-tag + arguments: + - "json,inline" + - "bson,outline,gnu" + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#superfluous-else + - name: superfluous-else + severity: warning + disabled: false + exclude: [""] + arguments: + - "preserveScope" + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#time-equal + - name: time-equal + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#time-naming + - name: time-naming + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#var-naming + - name: var-naming + severity: warning + disabled: false + exclude: [""] + arguments: + - [ "ID" ] # AllowList + - [ "VM" ] # DenyList + - - upperCaseConst: true + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#var-declaration + - name: var-declaration + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unconditional-recursion + - name: unconditional-recursion + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unexported-naming + - name: unexported-naming + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unexported-return + - name: unexported-return + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unhandled-error + - name: unhandled-error + severity: warning + disabled: false + exclude: [""] + arguments: + - "fmt.Printf" + - "myFunction" + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unnecessary-stmt + - name: unnecessary-stmt + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unreachable-code + - name: unreachable-code + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unused-parameter + - name: unused-parameter + severity: warning + disabled: false + exclude: [""] + arguments: + - allowRegex: "^_" + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unused-receiver + - name: unused-receiver + severity: warning + disabled: false + exclude: [""] + arguments: + - allowRegex: "^_" + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#useless-break + - name: useless-break + severity: warning + disabled: false + exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#waitgroup-by-value + - name: waitgroup-by-value + severity: warning + disabled: false + exclude: [""] + + rowserrcheck: + # database/sql is always checked + # Default: [] + packages: + - github.com/jmoiron/sqlx + + sloglint: + # Enforce not mixing key-value pairs and attributes. + # Default: true + no-mixed-args: false + # Enforce using key-value pairs only (overrides no-mixed-args, incompatible with attr-only). + # Default: false + kv-only: true + # Enforce using attributes only (overrides no-mixed-args, incompatible with kv-only). + # Default: false + attr-only: true + # Enforce using methods that accept a context. + # Default: false + context-only: true + # Enforce using static values for log messages. + # Default: false + static-msg: true + # Enforce using constants instead of raw keys. + # Default: false + no-raw-keys: true + # Enforce a single key naming convention. + # Values: snake, kebab, camel, pascal + # Default: "" + key-naming-case: snake + # Enforce putting arguments on separate lines. + # Default: false + args-on-sep-lines: true + + spancheck: + # Checks to enable. + # Options include: + # - `end`: check that `span.End()` is called + # - `record-error`: check that `span.RecordError(err)` is called when an error is returned + # - `set-status`: check that `span.SetStatus(codes.Error, msg)` is called when an error is returned + # Default: ["end"] + checks: + - end + - record-error + - set-status + # A list of regexes for function signatures that silence `record-error` and `set-status` reports + # if found in the call path to a returned error. + # https://github.com/jjti/go-spancheck#ignore-check-signatures + # Default: [] + ignore-check-signatures: + - "telemetry.RecordError" + + staticcheck: + # Deprecated: use the global `run.go` instead. + go: "1.15" + # SAxxxx checks in https://staticcheck.io/docs/configuration/options/#checks + # Default: ["*"] + checks: [ "all" ] + + stylecheck: + # Deprecated: use the global `run.go` instead. + go: "1.15" + # STxxxx checks in https://staticcheck.io/docs/configuration/options/#checks + # Default: ["*"] + checks: [ "all", "-ST1000", "-ST1003", "-ST1016", "-ST1020", "-ST1021", "-ST1022" ] + # https://staticcheck.io/docs/configuration/options/#dot_import_whitelist + # Default: ["github.com/mmcloughlin/avo/build", "github.com/mmcloughlin/avo/operand", "github.com/mmcloughlin/avo/reg"] + dot-import-whitelist: + - fmt + # https://staticcheck.io/docs/configuration/options/#initialisms + # Default: ["ACL", "API", "ASCII", "CPU", "CSS", "DNS", "EOF", "GUID", "HTML", "HTTP", "HTTPS", "ID", "IP", "JSON", "QPS", "RAM", "RPC", "SLA", "SMTP", "SQL", "SSH", "TCP", "TLS", "TTL", "UDP", "UI", "GID", "UID", "UUID", "URI", "URL", "UTF8", "VM", "XML", "XMPP", "XSRF", "XSS", "SIP", "RTP", "AMQP", "DB", "TS"] + initialisms: [ "ACL", "API", "ASCII", "CPU", "CSS", "DNS", "EOF", "GUID", "HTML", "HTTP", "HTTPS", "ID", "IP", "JSON", "QPS", "RAM", "RPC", "SLA", "SMTP", "SQL", "SSH", "TCP", "TLS", "TTL", "UDP", "UI", "GID", "UID", "UUID", "URI", "URL", "UTF8", "VM", "XML", "XMPP", "XSRF", "XSS", "SIP", "RTP", "AMQP", "DB", "TS" ] + # https://staticcheck.io/docs/configuration/options/#http_status_code_whitelist + # Default: ["200", "400", "404", "500"] + http-status-code-whitelist: [ "200", "400", "404", "500" ] + + tagalign: + # Align and sort can be used together or separately. + # + # Whether enable align. If true, the struct tags will be aligned. + # e.g.: + # type FooBar struct { + # Bar string `json:"bar" validate:"required"` + # FooFoo int8 `json:"foo_foo" validate:"required"` + # } + # will be formatted to: + # type FooBar struct { + # Bar string `json:"bar" validate:"required"` + # FooFoo int8 `json:"foo_foo" validate:"required"` + # } + # Default: true. + align: false + # Whether enable tags sort. + # If true, the tags will be sorted by name in ascending order. + # e.g.: `xml:"bar" json:"bar" validate:"required"` -> `json:"bar" validate:"required" xml:"bar"` + # Default: true + sort: false + # Specify the order of tags, the other tags will be sorted by name. + # This option will be ignored if `sort` is false. + # Default: [] + order: + - json + - yaml + - yml + - toml + - mapstructure + - binding + - validate + # Whether enable strict style. + # In this style, the tags will be sorted and aligned in the dictionary order, + # and the tags with the same name will be aligned together. + # Note: This option will be ignored if 'align' or 'sort' is false. + # Default: false + strict: true + + tagliatelle: + # Check the struct tag name case. + case: + # Use the struct field name to check the name of the struct tag. + # Default: false + use-field-name: true + # `camel` is used for `json` and `yaml`, and `header` is used for `header` (can be overridden) + # Default: {} + rules: + # Any struct tag type can be used. + # Support string case: `camel`, `pascal`, `kebab`, `snake`, `upperSnake`, `goCamel`, `goPascal`, `goKebab`, `goSnake`, `upper`, `lower`, `header` + json: camel + yaml: camel + xml: camel + bson: camel + avro: snake + mapstructure: kebab + env: upperSnake + envconfig: upperSnake + + tenv: + # The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures. + # Otherwise, only methods that take `*testing.T`, `*testing.B`, and `testing.TB` as arguments are checked. + # Default: false + all: false + + testifylint: + # Enable all checkers (https://github.com/Antonboom/testifylint#checkers). + # Default: false + enable-all: true + # Disable checkers by name + # (in addition to default + # suite-thelper + # ). + disable: + - blank-import + - bool-compare + - compares + - empty + - error-is-as + - error-nil + - expected-actual + - go-require + - float-compare + - len + - nil-compare + - require-error + - suite-dont-use-pkg + - suite-extra-assert-call + - suite-thelper + - useless-assert + + # Disable all checkers (https://github.com/Antonboom/testifylint#checkers). + # Default: false + disable-all: true + # Enable checkers by name + # (in addition to default + # blank-import, bool-compare, compares, empty, error-is-as, error-nil, expected-actual, go-require, float-compare, + # len, nil-compare, require-error, suite-dont-use-pkg, suite-extra-assert-call, useless-assert + # ). + enable: + - blank-import + - bool-compare + - compares + - empty + - error-is-as + - error-nil + - expected-actual + - go-require + - float-compare + - len + - nil-compare + - require-error + - suite-dont-use-pkg + - suite-extra-assert-call + - suite-thelper + - useless-assert + + bool-compare: + # To ignore user defined types (over builtin bool). + # Default: false + ignore-custom-types: true + expected-actual: + # Regexp for expected variable name. + # Default: (^(exp(ected)?|want(ed)?)([A-Z]\w*)?$)|(^(\w*[a-z])?(Exp(ected)?|Want(ed)?)$) + pattern: ^expected + require-error: + # Regexp for assertions to analyze. If defined, then only matched error assertions will be reported. + # Default: "" + fn-pattern: ^(Errorf?|NoErrorf?)$ + suite-extra-assert-call: + # To require or remove extra Assert() call? + # Default: remove + mode: require + + testpackage: + # Regexp pattern to skip files. + # Default: "(export|internal)_test\\.go" + skip-regexp: (export|internal)_test\.go + # List of packages that don't end with _test that tests are allowed to be in. + # Default: "main" + allow-packages: + - example + - main + + thelper: + test: + # Check *testing.T is first param (or after context.Context) of helper function. + # Default: true + first: false + # Check *testing.T param has name t. + # Default: true + name: false + # Check t.Helper() begins helper function. + # Default: true + begin: false + benchmark: + # Check *testing.B is first param (or after context.Context) of helper function. + # Default: true + first: false + # Check *testing.B param has name b. + # Default: true + name: false + # Check b.Helper() begins helper function. + # Default: true + begin: false + tb: + # Check *testing.TB is first param (or after context.Context) of helper function. + # Default: true + first: false + # Check *testing.TB param has name tb. + # Default: true + name: false + # Check tb.Helper() begins helper function. + # Default: true + begin: false + fuzz: + # Check *testing.F is first param (or after context.Context) of helper function. + # Default: true + first: false + # Check *testing.F param has name f. + # Default: true + name: false + # Check f.Helper() begins helper function. + # Default: true + begin: false + + usestdlibvars: + # Suggest the use of http.MethodXX. + # Default: true + http-method: false + # Suggest the use of http.StatusXX. + # Default: true + http-status-code: false + # Suggest the use of time.Weekday.String(). + # Default: true + time-weekday: true + # Suggest the use of time.Month.String(). + # Default: false + time-month: true + # Suggest the use of time.Layout. + # Default: false + time-layout: true + # Suggest the use of crypto.Hash.String(). + # Default: false + crypto-hash: true + # Suggest the use of rpc.DefaultXXPath. + # Default: false + default-rpc-path: true + # DEPRECATED Suggest the use of os.DevNull. + # Default: false + os-dev-null: true + # Suggest the use of sql.LevelXX.String(). + # Default: false + sql-isolation-level: true + # Suggest the use of tls.SignatureScheme.String(). + # Default: false + tls-signature-scheme: true + # Suggest the use of constant.Kind.String(). + # Default: false + constant-kind: true + # DEPRECATED Suggest the use of syslog.Priority. + # Default: false + syslog-priority: true + + unconvert: + # Remove conversions that force intermediate rounding. + # Default: false + fast-math: true + # Be more conservative (experimental). + # Default: false + safe: true + + unparam: + # Inspect exported functions. + # + # Set to true if no external program/library imports your code. + # XXX: if you enable this setting, unparam will report a lot of false-positives in text editors: + # if it's called for subdir of a project it can't find external interfaces. All text editor integrations + # with golangci-lint call it on a directory with the changed file. + # + # Default: false + check-exported: true + + unused: + # Mark all struct fields that have been written to as used. + # Default: true + field-writes-are-uses: false + # Treat IncDec statement (e.g. `i++` or `i--`) as both read and write operation instead of just write. + # Default: false + post-statements-are-reads: true + # Mark all exported identifiers as used. + # Default: true + exported-is-used: false + # Mark all exported fields as used. + # default: true + exported-fields-are-used: false + # Mark all function parameters as used. + # default: true + parameters-are-used: false + # Mark all local variables as used. + # default: true + local-variables-are-used: false + # Mark all identifiers inside generated files as used. + # Default: true + generated-is-used: false + + varnamelen: + # The longest distance, in source lines, that is being considered a "small scope". + # Variables used in at most this many lines will be ignored. + # Default: 5 + max-distance: 6 + # The minimum length of a variable's name that is considered "long". + # Variable names that are at least this long will be ignored. + # Default: 3 + min-name-length: 2 + # Check method receivers. + # Default: false + check-receiver: true + # Check named return values. + # Default: false + check-return: true + # Check type parameters. + # Default: false + check-type-param: true + # Ignore "ok" variables that hold the bool return value of a type assertion. + # Default: false + ignore-type-assert-ok: true + # Ignore "ok" variables that hold the bool return value of a map index. + # Default: false + ignore-map-index-ok: true + # Ignore "ok" variables that hold the bool return value of a channel receive. + # Default: false + ignore-chan-recv-ok: true + # Optional list of variable names that should be ignored completely. + # Default: [] + ignore-names: + - err + # Optional list of variable declarations that should be ignored completely. + # Entries must be in one of the following forms (see below for examples): + # - for variables, parameters, named return values, method receivers, or type parameters: + # ( can also be a pointer/slice/map/chan/...) + # - for constants: const + # + # Default: [] + ignore-decls: + - c echo.Context + - t testing.T + - f *foo.Bar + - e error + - i int + - const C + - T any + - m map[string]int + + whitespace: + # Enforces newlines (or comments) after every multi-line if statement. + # Default: false + multi-if: true + # Enforces newlines (or comments) after every multi-line function signature. + # Default: false + multi-func: true + + wrapcheck: + # An array of strings that specify substrings of signatures to ignore. + # If this set, it will override the default set of ignored signatures. + # See https://github.com/tomarrell/wrapcheck#configuration for more information. + # Default: [".Errorf(", "errors.New(", "errors.Unwrap(", "errors.Join(", ".Wrap(", ".Wrapf(", ".WithMessage(", ".WithMessagef(", ".WithStack("] + ignoreSigs: + - .Errorf( + - errors.New( + - errors.Unwrap( + - errors.Join( + - .Wrap( + - .Wrapf( + - .WithMessage( + - .WithMessagef( + - .WithStack( + # An array of strings that specify regular expressions of signatures to ignore. + # Default: [] + ignoreSigRegexps: + - \.New.*Error\( + # An array of strings that specify globs of packages to ignore. + # Default: [] + ignorePackageGlobs: + - encoding/* + - github.com/pkg/* + # An array of strings that specify regular expressions of interfaces to ignore. + # Default: [] + ignoreInterfaceRegexps: + - ^(?i)c(?-i)ach(ing|e) + + wsl: + # See https://github.com/bombsimon/wsl/blob/master/doc/configuration.md for documentation of available settings. + # These are the defaults for `golangci-lint`. + + # Do strict checking when assigning from append (x = append(x, y)). If + # this is set to true - the append call must append either a variable + # assigned, called or used on the line above. + strict-append: true + + # Allows assignments to be cuddled with variables used in calls on + # line above and calls to be cuddled with assignments of variables + # used in call on line above. + allow-assign-and-call: true + + # Allows assignments to be cuddled with anything. + allow-assign-and-anything: false + + # Allows cuddling to assignments even if they span over multiple lines. + allow-multiline-assign: true + + # If the number of lines in a case block is equal to or lager than this + # number, the case *must* end white a newline. + force-case-trailing-whitespace: 0 + + # Allow blocks to end with comments. + allow-trailing-comment: false + + # Allow multiple comments in the beginning of a block separated with newline. + allow-separated-leading-comment: false + + # Allow multiple var/declaration statements to be cuddled. + allow-cuddle-declarations: false + + # A list of call idents that everything can be cuddled with. + # Defaults to calls looking like locks. + allow-cuddle-with-calls: [ "Lock", "RLock" ] + + # AllowCuddleWithRHS is a list of right hand side variables that is allowed + # to be cuddled with anything. Defaults to assignments or calls looking + # like unlocks. + allow-cuddle-with-rhs: [ "Unlock", "RUnlock" ] + + # Causes an error when an If statement that checks an error variable doesn't + # cuddle with the assignment of that variable. + force-err-cuddling: false + + # When force-err-cuddling is enabled this is a list of names + # used for error variables to check for in the conditional. + error-variable-names: [ "err" ] + + # Causes an error if a short declaration (:=) cuddles with anything other than + # another short declaration. + # This logic overrides force-err-cuddling among others. + force-short-decl-cuddling: false + + # The custom section can be used to define linter plugins to be loaded at runtime. + # See README documentation for more info. + custom: + # Each custom linter should have a unique name. + example: + # The plugin type. + # It can be `goplugin` or `module`. + # Default: goplugin + type: module + # The path to the plugin *.so. Can be absolute or local. + # Required for each custom linter. + path: /path/to/example.so + # The description of the linter. + # Optional. + description: This is an example usage of a plugin linter. + # Intended to point to the repo location of the linter. + # Optional. + original-url: github.com/golangci/example-linter + # Plugins settings/configuration. + # Only work with plugin based on `linterdb.PluginConstructor`. + # Optional. + settings: + foo: bar + + +linters: + # Disable all linters. + # Default: false + disable-all: true + # Enable specific linter + # https://golangci-lint.run/usage/linters/#enabled-by-default + enable: + - asasalint + - asciicheck + - bidichk + - bodyclose + - containedctx + - contextcheck + - copyloopvar + - cyclop + - decorder + - depguard + - dogsled + - dupl + - dupword + - durationcheck + - errcheck + - errchkjson + - errname + - errorlint + - execinquery + - exhaustive + - exhaustruct + - exportloopref + - forbidigo + - forcetypeassert + - funlen + - gci + - ginkgolinter + - gocheckcompilerdirectives + - gochecknoglobals + - gochecknoinits + - gochecksumtype + - gocognit + - goconst + - gocritic + - gocyclo + - godot + - godox + - goerr113 + - gofmt + - gofumpt + - goheader + - goimports + - gomnd + - gomoddirectives + - gomodguard + - goprintffuncname + - gosec + - gosimple + - gosmopolitan + - govet + - grouper + - importas + - inamedparam + - ineffassign + - interfacebloat + - intrange + - ireturn + - lll + - loggercheck + - maintidx + - makezero + - mirror + - misspell + - musttag + - nakedret + - nestif + - nilerr + - nilnil + - nlreturn + - noctx + - nolintlint + - nonamedreturns + - nosprintfhostport + - paralleltest + - perfsprint + - prealloc + - predeclared + - promlinter + - protogetter + - reassign + - revive + - rowserrcheck + - sloglint + - spancheck + - sqlclosecheck + - staticcheck + - stylecheck + - tagalign + - tagliatelle + - tenv + - testableexamples + - testifylint + - testpackage + - thelper + - tparallel + - typecheck + - unconvert + - unparam + - unused + - usestdlibvars + - varnamelen + - wastedassign + - whitespace + - wrapcheck + - wsl + - zerologlint + + # Enable all available linters. + # Default: false + enable-all: true + # Disable specific linter + # https://golangci-lint.run/usage/linters/#disabled-by-default + disable: + - asasalint + - asciicheck + - bidichk + - bodyclose + - containedctx + - contextcheck + - copyloopvar + - cyclop + - decorder + - depguard + - dogsled + - dupl + - dupword + - durationcheck + - errcheck + - errchkjson + - errname + - errorlint + - execinquery + - exhaustive + - exhaustruct + - exportloopref + - forbidigo + - forcetypeassert + - funlen + - gci + - ginkgolinter + - gocheckcompilerdirectives + - gochecknoglobals + - gochecknoinits + - gochecksumtype + - gocognit + - goconst + - gocritic + - gocyclo + - godot + - godox + - goerr113 + - gofmt + - gofumpt + - goheader + - goimports + - gomnd + - gomoddirectives + - gomodguard + - goprintffuncname + - gosec + - gosimple + - gosmopolitan + - govet + - grouper + - importas + - inamedparam + - ineffassign + - interfacebloat + - intrange + - ireturn + - lll + - loggercheck + - maintidx + - makezero + - mirror + - misspell + - musttag + - nakedret + - nestif + - nilerr + - nilnil + - nlreturn + - noctx + - nolintlint + - nonamedreturns + - nosprintfhostport + - paralleltest + - perfsprint + - prealloc + - predeclared + - promlinter + - protogetter + - reassign + - revive + - rowserrcheck + - sloglint + - spancheck + - sqlclosecheck + - staticcheck + - stylecheck + - tagalign + - tagliatelle + - tenv + - testableexamples + - testifylint + - testpackage + - thelper + - tparallel + - typecheck + - unconvert + - unparam + - unused + - usestdlibvars + - varnamelen + - wastedassign + - whitespace + - wrapcheck + - wsl + - zerologlint + - deadcode # Deprecated + - exhaustivestruct # Deprecated + - golint # Deprecated + - ifshort # Deprecated + - interfacer # Deprecated + - maligned # Deprecated + - nosnakecase # Deprecated + - scopelint # Deprecated + - structcheck # Deprecated + - varcheck # Deprecated + + # Enable presets. + # https://golangci-lint.run/usage/linters + # Default: [] + presets: + - bugs + - comment + - complexity + - error + - format + - import + - metalinter + - module + - performance + - sql + - style + - test + - unused + + # Enable only fast linters from enabled linters set (first run won't be fast) + # Default: false + fast: true + + +issues: + # List of regexps of issue texts to exclude. + # + # But independently of this option we use default exclude patterns, + # it can be disabled by `exclude-use-default: false`. + # To list all excluded by default patterns execute `golangci-lint run --help` + # + # Default: https://golangci-lint.run/usage/false-positives/#default-exclusions + exclude: + - abcdef + + # Excluding configuration per-path, per-linter, per-text and per-source + exclude-rules: + # Exclude some linters from running on tests files. + - path: _test\.go + linters: + - gocyclo + - errcheck + - dupl + - gosec + + # Run some linter only for test files by excluding its issues for everything else. + - path-except: _test\.go + linters: + - forbidigo + + # Exclude known linters from partially hard-vendored code, + # which is impossible to exclude via `nolint` comments. + # `/` will be replaced by current OS file path separator to properly work on Windows. + - path: internal/hmac/ + text: "weak cryptographic primitive" + linters: + - gosec + + # Exclude some `staticcheck` messages. + - linters: + - staticcheck + text: "SA9003:" + + # Exclude `lll` issues for long lines with `go:generate`. + - linters: + - lll + source: "^//go:generate " + + # Independently of option `exclude` we use default exclude patterns, + # it can be disabled by this option. + # To list all excluded by default patterns execute `golangci-lint run --help`. + # Default: true + exclude-use-default: false + + # If set to true exclude and exclude-rules regular expressions become case-sensitive. + # Default: false + exclude-case-sensitive: false + + # To follow strictly the Go generated file convention. + # + # If set to true, source files that have lines matching only the following regular expression will be excluded: + # `^// Code generated .* DO NOT EDIT\.$` + # This line must appear before the first non-comment, non-blank text in the file. + # https://go.dev/s/generatedcode + # + # By default, a lax pattern is applied: + # sources are excluded if they contain lines `autogenerated file`, `code generated`, `do not edit`, etc. + # Default: false + exclude-generated-strict: true + + # The list of ids of default excludes to include or disable. + # https://golangci-lint.run/usage/false-positives/#default-exclusions + # Default: [] + include: + - EXC0001 + - EXC0002 + - EXC0003 + - EXC0004 + - EXC0005 + - EXC0006 + - EXC0007 + - EXC0008 + - EXC0009 + - EXC0010 + - EXC0011 + - EXC0012 + - EXC0013 + - EXC0014 + - EXC0015 + + # Maximum issues count per one linter. + # Set to 0 to disable. + # Default: 50 + max-issues-per-linter: 0 + + # Maximum count of issues with the same text. + # Set to 0 to disable. + # Default: 3 + max-same-issues: 0 + + # Show only new issues: if there are unstaged changes or untracked files, + # only those changes are analyzed, else only changes in HEAD~ are analyzed. + # It's a super-useful option for integration of golangci-lint into existing large codebase. + # It's not practical to fix all existing issues at the moment of integration: + # much better don't allow issues in new code. + # + # Default: false + new: true + + # Show only new issues created after git revision `REV`. + # Default: "" + new-from-rev: HEAD + + # Show only new issues created in git patch with set file path. + # Default: "" + new-from-patch: path/to/patch/file + + # Fix found issues (if it's supported by the linter). + # Default: false + fix: true + + # Show issues in any part of update files (requires new-from-rev or new-from-patch). + # Default: false + whole-files: true + +severity: + # Set the default severity for issues. + # + # If severity rules are defined and the issues do not match or no severity is provided to the rule + # this will be the default severity applied. + # Severities should match the supported severity names of the selected out format. + # - Code climate: https://docs.codeclimate.com/docs/issues#issue-severity + # - Checkstyle: https://checkstyle.sourceforge.io/property_types.html#SeverityLevel + # - GitHub: https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message + # - TeamCity: https://www.jetbrains.com/help/teamcity/service-messages.html#Inspection+Instance + # + # `@linter` can be used as severity value to keep the severity from linters (e.g. revive, gosec, ...) + # + # Default: "" + default-severity: error + + # If set to true `severity-rules` regular expressions become case-sensitive. + # Default: false + case-sensitive: true + + # When a list of severity rules are provided, severity information will be added to lint issues. + # Severity rules have the same filtering capability as exclude rules + # except you are allowed to specify one matcher per severity rule. + # + # `@linter` can be used as severity value to keep the severity from linters (e.g. revive, gosec, ...) + # + # Only affects out formats that support setting severity information. + # + # Default: [] + rules: + - linters: + - dupl + severity: info diff --git a/.golangci.reference.yml b/.golangci.reference.yml index 7de210b98ba4..03e6fa406015 100644 --- a/.golangci.reference.yml +++ b/.golangci.reference.yml @@ -6,7 +6,8 @@ # Options for analysis running. run: - # The default concurrency value is the number of available CPU. + # Number of CPUs to use when running golangci-lint. + # Default: the number of logical CPUs in the machine concurrency: 4 # Timeout for analysis, e.g. 30s, 5m. @@ -22,15 +23,16 @@ run: tests: false # List of build tags, all linters use it. - # Default: []. + # Default: [] build-tags: - mytag # Which dirs to skip: issues from them won't be reported. - # Can use regexp here: `generated.*`, regexp is applied on full path. - # Default value is empty list, - # but default dirs are skipped independently of this option's value (see skip-dirs-use-default). + # Can use regexp here: `generated.*`, regexp is applied on full path, + # including the path prefix if one is set. + # Default dirs are skipped independently of this option's value (see skip-dirs-use-default). # "/" will be replaced by current OS file path separator to properly work on Windows. + # Default: [] skip-dirs: - src/external_libs - autogenerated_by_my_lib @@ -41,16 +43,16 @@ run: skip-dirs-use-default: false # Which files to skip: they will be analyzed, but issues from them won't be reported. - # Default value is empty list, - # but there is no need to include all autogenerated files, + # There is no need to include all autogenerated files, # we confidently recognize autogenerated files. - # If it's not please let us know. + # If it's not, please let us know. # "/" will be replaced by current OS file path separator to properly work on Windows. + # Default: [] skip-files: - ".*\\.my\\.go$" - lib/bad.go - # If set we pass it to "go list -mod={option}". From "go help modules": + # If set, we pass it to "go list -mod={option}". From "go help modules": # If invoked with -mod=readonly, the go command is disallowed from the implicit # automatic updating of go.mod described above. Instead, it fails when any changes # to go.mod are needed. This setting is most useful to check that go.mod does @@ -60,22 +62,32 @@ run: # the dependency descriptions in go.mod. # # Allowed values: readonly|vendor|mod - # By default, it isn't set. + # Default: "" modules-download-mode: readonly # Allow multiple parallel golangci-lint instances running. - # If false (default) - golangci-lint acquires file lock on start. - allow-parallel-runners: false + # If false, golangci-lint acquires file lock on start. + # Default: false + allow-parallel-runners: true + + # Allow multiple golangci-lint instances running, but serialize them around a lock. + # If false, golangci-lint exits with an error if it fails to acquire file lock on start. + # Default: false + allow-serial-runners: true # Define the Go version limit. # Mainly related to generics support since go1.18. - # Default: use Go version from the go.mod file, fallback on the env var `GOVERSION`, fallback on 1.18 + # Default: use Go version from the go.mod file, fallback on the env var `GOVERSION`, fallback on 1.17 go: '1.19' + # Show statistics per linter. + # Default: false + show-stats: true + # output configuration options output: - # Format: colored-line-number|line-number|json|tab|checkstyle|code-climate|junit-xml|github-actions + # Format: colored-line-number|line-number|json|colored-tab|tab|checkstyle|code-climate|junit-xml|github-actions|teamcity # # Multiple can be specified by separating them by comma, output can be provided # for each of them by separating format name and path by colon symbol. @@ -98,11 +110,12 @@ output: uniq-by-line: false # Add a prefix to the output file references. - # Default is no prefix. + # Default: "" path-prefix: "" # Sort results by: filepath, line and column. - sort-results: false + # Default: false + sort-results: true # All available settings of specific linters. @@ -157,6 +170,10 @@ linters-settings: - var - func + # If true, underscore vars (vars with "_" as the name) will be ignored at all checks + # Default: false (underscore vars are not ignored) + ignore-underscore-vars: false + # If true, order of declarations is not checked at all. # Default: true (disabled) disable-dec-order-check: false @@ -169,50 +186,55 @@ linters-settings: # Default: true (disabled) disable-dec-num-check: false - depguard: - # Kind of list is passed in. - # Allowed values: allowlist|denylist - # Default: denylist - list-type: allowlist + # If true, type declarations will be ignored for dec num check + # Default: false (type statements are not ignored) + disable-type-dec-num-check: false - # Check the list against standard lib. - # Default: false - include-go-root: true + # If true, const declarations will be ignored for dec num check + # Default: false (const statements are not ignored) + disable-const-dec-num-check: false - # A list of packages for the list type specified. - # Can accept both string prefixes and string glob patterns. - # Default: [] - packages: - - github.com/sirupsen/logrus - - allow/**/pkg + # If true, var declarations will be ignored for dec num check + # Default: false (var statements are not ignored) + disable-var-dec-num-check: false - # A list of packages for the list type specified. - # Specify an error message to output when a denied package is used. - # Default: [] - packages-with-error-message: - - github.com/sirupsen/logrus: 'logging is allowed only by logutils.Log' - - # Specify rules by which the linter ignores certain files for consideration. - # Can accept both string prefixes and string glob patterns. - # The ! character in front of the rule is a special character - # which signals that the linter should negate the rule. - # This allows for more precise control, but it is only available for glob patterns. - # Default: [] - ignore-file-rules: - - "ignore/**/*.go" - - "!**/*_test.go" - - # Create additional guards that follow the same configuration pattern. - # Results from all guards are aggregated together. - additional-guards: - - list-type: denylist - include-go-root: false - packages: - - github.com/stretchr/testify - # Specify rules by which the linter ignores certain files for consideration. - ignore-file-rules: - - "**/*_test.go" - - "**/mock/**/*.go" + depguard: + # Rules to apply. + # + # Variables: + # - File Variables + # you can still use and exclamation mark ! in front of a variable to say not to use it. + # Example !$test will match any file that is not a go test file. + # + # `$all` - matches all go files + # `$test` - matches all go test files + # + # - Package Variables + # + # `$gostd` - matches all of go's standard library (Pulled from `GOROOT`) + # + # Default: Only allow $gostd in all files. + rules: + # Name of a rule. + main: + # Used to determine the package matching priority. + # There are three different modes: `original`, `strict`, and `lax`. + # Default: "original" + list-mode: lax + # List of file globs that will match this list of settings to compare against. + # Default: $all + files: + - "!**/*_a _file.go" + # List of allowed packages. + allow: + - $gostd + - github.com/OpenPeeDeeP + # Packages that are not allowed where the value is a suggestion. + deny: + - pkg: "github.com/sirupsen/logrus" + desc: not allowed + - pkg: "github.com/pkg/errors" + desc: Should be replaced by standard lib errors package dogsled: # Checks assignments with too many blank identifiers. @@ -229,9 +251,13 @@ linters-settings: # If this list is not empty, only the words defined in this list will be detected. # Default: [] keywords: - - "the" - - "and" - - "a" + - "the" + - "and" + - "a" + # Keywords used to ignore detection. + # Default: [] + ignore: + - "0C0C" errcheck: # Report about not checking of errors in type assertions: `a := b.(MyStruct)`. @@ -294,6 +320,9 @@ linters-settings: # See the https://github.com/polyfloyd/go-errorlint for caveats. # Default: true errorf: false + # Permit more than 1 %w verb, valid per Go 1.20 (Requires errorf:true) + # Default: true + errorf-multi: false # Check for plain type assertions and type switches. # Default: true asserts: false @@ -331,6 +360,9 @@ linters-settings: # Only run exhaustive check on map literals with "//exhaustive:enforce" comment. # Default: false explicit-exhaustive-map: true + # Switch statement requires default case even if exhaustive. + # Default: false + default-case-required: true exhaustivestruct: # Struct Patterns is list of expressions to match struct packages and names. @@ -343,29 +375,48 @@ linters-settings: - 'example.com/package.ExampleStruct' exhaustruct: - # List of regular expressions to match struct packages and names. + # List of regular expressions to match struct packages and their names. + # Regular expressions must match complete canonical struct package/name/structname. # If this list is empty, all structs are tested. # Default: [] include: - - '.*\.Test' + - '.+\.Test' - 'example\.com/package\.ExampleStruct[\d]{1,2}' - # List of regular expressions to exclude struct packages and names from check. + # List of regular expressions to exclude struct packages and their names from checks. + # Regular expressions must match complete canonical struct package/name/structname. # Default: [] exclude: - - 'cobra\.Command$' + - '.+/cobra\.Command$' forbidigo: # Forbid the following identifiers (list of regexp). # Default: ["^(fmt\\.Print(|f|ln)|print|println)$"] forbid: + # Builtin function: - ^print.*$ - - 'fmt\.Print.*' - # Optionally put comments at the end of the regex, surrounded by `(# )?` - # Escape any special characters. + # Optional message that gets included in error reports. + - p: ^fmt\.Print.*$ + msg: Do not commit print statements. + # Alternatively, put messages at the end of the regex, surrounded by `(# )?` + # Escape any special characters. Those messages get included in error reports. - 'fmt\.Print.*(# Do not commit print statements\.)?' + # Forbid spew Dump, whether it is called as function or method. + # Depends on analyze-types below. + - ^spew\.(ConfigState\.)?Dump$ + # The package name might be ambiguous. + # The full import path can be used as additional criteria. + # Depends on analyze-types below. + - p: ^v1.Dump$ + pkg: ^example.com/pkg/api/v1$ # Exclude godoc examples from forbidigo checks. # Default: true - exclude_godoc_examples: false + exclude-godoc-examples: false + # Instead of matching the literal source code, + # use type information to replace expressions with strings that contain the package name + # and (for methods and fields) the type name. + # This makes it possible to handle import renaming and forbid struct fields and methods. + # Default: false + analyze-types: true funlen: # Checks the number of lines in a function. @@ -376,6 +427,9 @@ linters-settings: # If lower than 0, disable the check. # Default: 40 statements: -1 + # Ignore comments when counting lines. + # Default false + ignore-comments: true gci: # DEPRECATED: use `sections` and `prefix(github.com/org/project)` instead. @@ -383,7 +437,7 @@ linters-settings: # Section configuration to compare against. # Section names are case-insensitive and may contain parameters in (). - # The default order of sections is `standard > default > custom > blank > dot`, + # The default order of sections is `standard > default > custom > blank > dot > alias`, # If `custom-order` is `true`, it follows the order of `sections` option. # Default: ["standard", "default"] sections: @@ -392,6 +446,7 @@ linters-settings: - prefix(github.com/org/project) # Custom section: groups all imports with the specified Prefix. - blank # Blank section: contains all blank imports. This section is not present unless explicitly enabled. - dot # Dot section: contains all dot imports. This section is not present unless explicitly enabled. + - alias # Alias section: contains all alias imports. This section is not present unless explicitly enabled. # Skip generated files. # Default: true @@ -415,6 +470,26 @@ linters-settings: # Default: false suppress-err-assertion: true + # Suppress the wrong comparison assertion warning. + # Default: false + suppress-compare-assertion: true + + # Suppress the function all in async assertion warning. + # Default: false + suppress-async-assertion: true + + # Suppress warning for comparing values from different types, like int32 and uint32 + # Default: false + suppress-type-compare-assertion: true + + # Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt + # Default: false + forbid-focus-container: true + + # Don't trigger warnings for HaveLen(0) + # Default: false + allow-havelen-zero: true + gocognit: # Minimal code complexity to report. # Default: 30 (but we recommend 10-20) @@ -445,12 +520,21 @@ linters-settings: # Ignore when constant is not used as function argument. # Default: true ignore-calls: false + # Exclude strings matching the given regular expression. + # Default: "" + ignore-strings: 'foo.+' gocritic: - # Which checks should be enabled; can't be combined with 'disabled-checks'. - # See https://go-critic.github.io/overview#checks-overview. - # To check which checks are enabled run `GL_DEBUG=gocritic golangci-lint run`. - # By default, list of stable checks is used. + # Disable all checks. + # Default: false + disable-all: true + # Which checks should be enabled in addition to default checks; can't be combined with 'disabled-checks'. + # By default, list of stable checks is used (https://go-critic.github.io/overview#checks-overview): + # appendAssign, argOrder, assignOp, badCall, badCond, captLocal, caseOrder, codegenComment, commentFormatting, + # defaultCaseOrder, deprecatedComment, dupArg, dupBranchBody, dupCase, dupSubExpr, elseif, exitAfterDefer, + # flagDeref, flagName, ifElseChain, mapKey, newDeref, offBy1, regexpMust, singleCaseSwitch, sloppyLen, + # sloppyTypeAssert, switchTrue, typeSwitchVar, underef, unlambda, unslice, valSwap, wrapperFunc + # To see which checks are enabled run `GL_DEBUG=gocritic golangci-lint run --enable=gocritic`. enabled-checks: - nestingReduce - unnamedResult @@ -462,7 +546,8 @@ linters-settings: disabled-checks: - regexpMust - # Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks. + # Enable multiple checks by tags in addition to default checks. + # Run `GL_DEBUG=gocritic golangci-lint run --enable=gocritic` to see all tags and checks. # See https://github.com/go-critic/go-critic#usage -> section "Tags". # Default: [] enabled-tags: @@ -487,6 +572,10 @@ linters-settings: # Whether to restrict checker to params only. # Default: true paramsOnly: false + commentedOutCode: + # Min length of the comment that triggers a warning. + # Default: 15 + minLength: 50 elseif: # Whether to skip balanced if-else pairs. # Default: true @@ -495,6 +584,10 @@ linters-settings: # Size in bytes that makes the warning trigger. # Default: 80 sizeThreshold: 70 + ifElseChain: + # Min number of if-else blocks that makes the warning trigger. + # Default: 2 + minThreshold: 4 nestingReduce: # Min number of statements inside a branch to trigger a warning. # Default: 5 @@ -524,7 +617,7 @@ linters-settings: # Then: # ruleguard prints the specific Where() condition that was rejected. # - # The flag is passed to the ruleguard 'debug-group' argument. + # The option is passed to the ruleguard 'debug-group' argument. # Default: "" debug: 'emptyDecl' # Deprecated, use 'failOn' param. @@ -614,8 +707,6 @@ linters-settings: replacement: 'a[b:]' gofumpt: - # Select the Go version to target. - # Default: "1.15" # Deprecated: use the global `run.go` instead. lang-version: "1.17" @@ -699,15 +790,15 @@ linters-settings: # Values always ignored: `.+_test.go` # Default: [] ignored-files: - - 'magic1_.*.go' + - 'magic1_.+\.go$' # List of function patterns to exclude from analysis. # Following functions are always ignored: `time.Date`, # `strconv.FormatInt`, `strconv.FormatUint`, `strconv.FormatFloat`, # `strconv.ParseInt`, `strconv.ParseUint`, `strconv.ParseFloat`. # Default: [] ignored-functions: - - 'math.*' - - 'http.StatusText' + - '^math\.' + - '^http\.StatusText$' gomoddirectives: # Allow local `replace` directives. @@ -759,8 +850,6 @@ linters-settings: local_replace_directives: false gosimple: - # Select the Go version to target. - # Default: 1.13 # Deprecated: use the global `run.go` instead. go: "1.15" # Sxxxx checks in https://staticcheck.io/docs/configuration/options/#checks @@ -795,7 +884,7 @@ linters-settings: - G304 # File path provided as taint input - G305 # File traversal when extracting zip/tar archive - G306 # Poor file permissions used when writing to a new file - - G307 # Deferring a method which returns an error + - G307 # Poor file permissions used when creating a file with os.Create - G401 # Detect the usage of DES, RC4, MD5 or SHA1 - G402 # Look for bad TLS connection settings - G403 # Ensure minimum RSA key length of 2048 bits @@ -806,6 +895,7 @@ linters-settings: - G504 # Import blocklist: net/http/cgi - G505 # Import blocklist: crypto/sha1 - G601 # Implicit memory aliasing of items from a range statement + - G602 # Slice access out of bounds # To specify a set of rules to explicitly exclude. # Available rules: https://github.com/securego/gosec#available-rules @@ -834,7 +924,7 @@ linters-settings: - G304 # File path provided as taint input - G305 # File traversal when extracting zip/tar archive - G306 # Poor file permissions used when writing to a new file - - G307 # Deferring a method which returns an error + - G307 # Poor file permissions used when creating a file with os.Create - G401 # Detect the usage of DES, RC4, MD5 or SHA1 - G402 # Look for bad TLS connection settings - G403 # Ensure minimum RSA key length of 2048 bits @@ -845,6 +935,7 @@ linters-settings: - G504 # Import blocklist: net/http/cgi - G505 # Import blocklist: crypto/sha1 - G601 # Implicit memory aliasing of items from a range statement + - G602 # Slice access out of bounds # Exclude generated files # Default: false @@ -940,6 +1031,37 @@ linters-settings: # Default: "0600" G306: "0600" + gosmopolitan: + # Allow and ignore `time.Local` usages. + # + # Default: false + allow-time-local: true + # List of fully qualified names in the `full/pkg/path.name` form, to act as "i18n escape hatches". + # String literals inside call-like expressions to, or struct literals of those names, + # are exempt from the writing system check. + # + # Default: [] + escape-hatches: + - 'github.com/nicksnyder/go-i18n/v2/i18n.Message' + - 'example.com/your/project/i18n/markers.Raw' + - 'example.com/your/project/i18n/markers.OK' + - 'example.com/your/project/i18n/markers.TODO' + - 'command-line-arguments.Simple' + # Ignore test files. + # + # Default: true + ignore-tests: false + # List of Unicode scripts to watch for any usage in string literals. + # https://pkg.go.dev/unicode#pkg-variables + # + # Default: ["Han"] + watch-for-scripts: + - Devanagari + - Han + - Hangul + - Hiragana + - Katakana + govet: # Report about shadowed variables. # Default: false @@ -962,24 +1084,33 @@ linters-settings: strict: true unusedresult: # Comma-separated list of functions whose results must be used - # (in addition to defaults context.WithCancel,context.WithDeadline,context.WithTimeout,context.WithValue, - # errors.New,fmt.Errorf,fmt.Sprint,fmt.Sprintf,sort.Reverse) - # Default [] + # (in addition to default: + # context.WithCancel, context.WithDeadline, context.WithTimeout, context.WithValue, errors.New, fmt.Errorf, + # fmt.Sprint, fmt.Sprintf, sort.Reverse + # ). + # Default: [] funcs: - pkg.MyFunc # Comma-separated list of names of methods of type func() string whose results must be used # (in addition to default Error,String) - # Default [] + # Default: [] stringmethods: - MyMethod # Disable all analyzers. # Default: false disable-all: true - # Enable analyzers by name (in addition to default). + # Enable analyzers by name. + # (in addition to default: + # appends, asmdecl, assign, atomic, bools, buildtag, cgocall, composites, copylocks, defers, directive, errorsas, + # framepointer, httpresponse, ifaceassert, loopclosure, lostcancel, nilfunc, printf, shift, sigchanyzer, slog, + # stdmethods, stringintconv, structtag, testinggoroutine, tests, timeformat, unmarshal, unreachable, unsafeptr, + # unusedresult + # ). # Run `go tool vet help` to see all analyzers. # Default: [] enable: + - appends - asmdecl - assign - atomic @@ -990,6 +1121,8 @@ linters-settings: - composites - copylocks - deepequalerrors + - defers + - directive - errorsas - fieldalignment - findcall @@ -1005,6 +1138,7 @@ linters-settings: - shadow - shift - sigchanyzer + - slog - sortslice - stdmethods - stringintconv @@ -1021,9 +1155,14 @@ linters-settings: # Default: false enable-all: true # Disable analyzers by name. + # (in addition to default + # atomicalign, deepequalerrors, fieldalignment, findcall, nilness, reflectvaluecompare, shadow, sortslice, + # timeformat, unusedwrite + # ). # Run `go tool vet help` to see all analyzers. # Default: [] disable: + - appends - asmdecl - assign - atomic @@ -1034,6 +1173,8 @@ linters-settings: - composites - copylocks - deepequalerrors + - defers + - directive - errorsas - fieldalignment - findcall @@ -1049,6 +1190,7 @@ linters-settings: - shadow - shift - sigchanyzer + - slog - sortslice - stdmethods - stringintconv @@ -1121,19 +1263,25 @@ linters-settings: - pkg: knative.dev/serving/pkg/apis/(\w+)/(v[\w\d]+) alias: $1$2 + inamedparam: + # Skips check for interface methods with only a single parameter. + # Default: false + skip-single-param: true + interfacebloat: # The maximum number of methods allowed for an interface. # Default: 10 max: 5 ireturn: - # ireturn allows using `allow` and `reject` settings at the same time. + # ireturn does not allow using `allow` and `reject` settings at the same time. # Both settings are lists of the keywords and regular expressions matched to interface or package names. # keywords: # - `empty` for `interface{}` # - `error` for errors # - `stdlib` for standard library # - `anon` for anonymous interfaces + # - `generic` for generic interfaces added in go 1.18 # By default, it allows using errors, empty interfaces, anonymous interfaces, # and interfaces provided by the standard library. @@ -1184,6 +1332,7 @@ linters-settings: - k8s.io/klog/v2.InfoS # package level exported functions - (github.com/go-logr/logr.Logger).Error # "Methods" - (*go.uber.org/zap.SugaredLogger).With # Also "Methods", but with a pointer receiver + maintidx: # Show functions with maintainability index lower than N. # A high index indicates better maintainability (it's kind of the opposite of complexity). @@ -1208,17 +1357,22 @@ linters-settings: # Default: [] ignore-words: - someword + # Mode of the analysis: + # - default: checks all the file content. + # - restricted: checks only comments. + # Default: "" + mode: restricted musttag: # A set of custom functions to check in addition to the builtin ones. - # Default: json, xml, gopkg.in/yaml.v3, BurntSushi/toml, mitchellh/mapstructure + # Default: json, xml, gopkg.in/yaml.v3, BurntSushi/toml, mitchellh/mapstructure, jmoiron/sqlx functions: - # The full name of the function, including the package. - - name: github.com/jmoiron/sqlx.Get + # The full name of the function, including the package. + - name: github.com/hashicorp/hcl/v2/hclsimple.DecodeFile # The struct tag whose presence should be ensured. - tag: db + tag: hcl # The position of the argument to check. - arg-pos: 1 + arg-pos: 2 nakedret: # Make an issue if func has more lines of code than this setting, and it has naked returns. @@ -1269,6 +1423,24 @@ linters-settings: # Ignore missing calls to `t.Parallel()` and only report incorrect uses of it. # Default: false ignore-missing: true + # Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are + # still required to have `t.Parallel`, but subtests are allowed to skip it. + # Default: false + ignore-missing-subtests: true + + perfsprint: + # Optimizes even if it requires an int or uint type cast. + # Default: true + int-conversion: false + # Optimizes into `err.Error()` even if it is only equivalent for non-nil errors. + # Default: false + err-error: true + # Optimizes `fmt.Errorf`. + # Default: true + errorf: false + # Optimizes `fmt.Sprintf` with only one argument. + # Default: true + sprintf1: false prealloc: # IMPORTANT: we don't recommend using this linter before doing performance profiling. @@ -1309,6 +1481,25 @@ linters-settings: - CamelCase - UnitAbbreviations + protogetter: + # Skip files generated by specified generators from the checking. + # Checks only the file's initial comment, which must follow the format: "// Code generated by ". + # Files generated by protoc-gen-go, protoc-gen-go-grpc, and protoc-gen-grpc-gateway are always excluded automatically. + # Default: [] + skip-generated-by: ["protoc-gen-go-my-own-generator"] + # Skip files matching the specified glob pattern from the checking. + # Default: [] + skip-files: + - "*.pb.go" + - "*/vendor/*" + - "/full/path/to/file.go" + # Skip any generated files from the checking. + # Default: false + skip-any-generated: true + # Skip first argument of append function. + # Default: false + replace-first-arg-in-append: true + reassign: # Patterns for global variable names that are checked for reassignment. # See https://github.com/curioswitch/go-reassign#usage @@ -1446,6 +1637,8 @@ linters-settings: - name: early-return severity: warning disabled: false + arguments: + - "preserveScope" # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#empty-block - name: empty-block severity: warning @@ -1454,6 +1647,24 @@ linters-settings: - name: empty-lines severity: warning disabled: false + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#enforce-map-style + - name: enforce-map-style + severity: warning + disabled: false + arguments: + - "make" + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#enforce-repeated-arg-type-style + - name: enforce-repeated-arg-type-style + severity: warning + disabled: false + arguments: + - "short" + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#enforce-slice-style + - name: enforce-slice-style + severity: warning + disabled: false + arguments: + - "make" # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#error-naming - name: error-naming severity: warning @@ -1475,6 +1686,7 @@ linters-settings: severity: warning disabled: false arguments: + - "preserveScope" - "checkPrivateReceivers" - "sayRepetitiveInsteadOfStutters" # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#file-header @@ -1517,8 +1729,16 @@ linters-settings: - name: indent-error-flow severity: warning disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#imports-blacklist - - name: imports-blacklist + arguments: + - "preserveScope" + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#import-alias-naming + - name: import-alias-naming + severity: warning + disabled: false + arguments: + - "^[a-z][a-z0-9]{0,}$" + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#imports-blocklist + - name: imports-blocklist severity: warning disabled: false arguments: @@ -1533,6 +1753,11 @@ linters-settings: severity: warning disabled: false arguments: [ 80 ] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#max-control-nesting + - name: max-control-nesting + severity: warning + disabled: false + arguments: [ 3 ] # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#max-public-structs - name: max-public-structs severity: warning @@ -1574,6 +1799,10 @@ linters-settings: - name: receiver-naming severity: warning disabled: false + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#redundant-import-alias + - name: redundant-import-alias + severity: warning + disabled: false # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#redefines-builtin-id - name: redefines-builtin-id severity: warning @@ -1598,12 +1827,17 @@ linters-settings: - must not contain line breaks # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#struct-tag - name: struct-tag + arguments: + - "json,inline" + - "bson,outline,gnu" severity: warning disabled: false # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#superfluous-else - name: superfluous-else severity: warning disabled: false + arguments: + - "preserveScope" # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#time-equal - name: time-equal severity: warning @@ -1619,6 +1853,7 @@ linters-settings: arguments: - [ "ID" ] # AllowList - [ "VM" ] # DenyList + - - upperCaseConst: true # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#var-declaration - name: var-declaration severity: warning @@ -1654,10 +1889,14 @@ linters-settings: - name: unused-parameter severity: warning disabled: false + arguments: + - allowRegex: "^_" # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unused-receiver - name: unused-receiver severity: warning disabled: false + arguments: + - allowRegex: "^_" # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#useless-break - name: useless-break severity: warning @@ -1673,9 +1912,52 @@ linters-settings: packages: - github.com/jmoiron/sqlx + sloglint: + # Enforce not mixing key-value pairs and attributes. + # Default: true + no-mixed-args: false + # Enforce using key-value pairs only (overrides no-mixed-args, incompatible with attr-only). + # Default: false + kv-only: true + # Enforce using attributes only (overrides no-mixed-args, incompatible with kv-only). + # Default: false + attr-only: true + # Enforce using methods that accept a context. + # Default: false + context-only: true + # Enforce using static values for log messages. + # Default: false + static-msg: true + # Enforce using constants instead of raw keys. + # Default: false + no-raw-keys: true + # Enforce a single key naming convention. + # Values: snake, kebab, camel, pascal + # Default: "" + key-naming-case: snake + # Enforce putting arguments on separate lines. + # Default: false + args-on-sep-lines: true + + spancheck: + # Checks to enable. + # Options include: + # - `end`: check that `span.End()` is called + # - `record-error`: check that `span.RecordError(err)` is called when an error is returned + # - `set-status`: check that `span.SetStatus(codes.Error, msg)` is called when an error is returned + # Default: ["end"] + checks: + - end + - record-error + - set-status + # A list of regexes for function signatures that silence `record-error` and `set-status` reports + # if found in the call path to a returned error. + # https://github.com/jjti/go-spancheck#ignore-check-signatures + # Default: [] + ignore-check-signatures: + - "telemetry.RecordError" + staticcheck: - # Select the Go version to target. - # Default: "1.13" # Deprecated: use the global `run.go` instead. go: "1.15" # SAxxxx checks in https://staticcheck.io/docs/configuration/options/#checks @@ -1683,8 +1965,6 @@ linters-settings: checks: [ "all" ] stylecheck: - # Select the Go version to target. - # Default: 1.13 # Deprecated: use the global `run.go` instead. go: "1.15" # STxxxx checks in https://staticcheck.io/docs/configuration/options/#checks @@ -1701,6 +1981,45 @@ linters-settings: # Default: ["200", "400", "404", "500"] http-status-code-whitelist: [ "200", "400", "404", "500" ] + tagalign: + # Align and sort can be used together or separately. + # + # Whether enable align. If true, the struct tags will be aligned. + # e.g.: + # type FooBar struct { + # Bar string `json:"bar" validate:"required"` + # FooFoo int8 `json:"foo_foo" validate:"required"` + # } + # will be formatted to: + # type FooBar struct { + # Bar string `json:"bar" validate:"required"` + # FooFoo int8 `json:"foo_foo" validate:"required"` + # } + # Default: true. + align: false + # Whether enable tags sort. + # If true, the tags will be sorted by name in ascending order. + # e.g.: `xml:"bar" json:"bar" validate:"required"` -> `json:"bar" validate:"required" xml:"bar"` + # Default: true + sort: false + # Specify the order of tags, the other tags will be sorted by name. + # This option will be ignored if `sort` is false. + # Default: [] + order: + - json + - yaml + - yml + - toml + - mapstructure + - binding + - validate + # Whether enable strict style. + # In this style, the tags will be sorted and aligned in the dictionary order, + # and the tags with the same name will be aligned together. + # Note: This option will be ignored if 'align' or 'sort' is false. + # Default: false + strict: true + tagliatelle: # Check the struct tag name case. case: @@ -1711,13 +2030,15 @@ linters-settings: # Default: {} rules: # Any struct tag type can be used. - # Support string case: `camel`, `pascal`, `kebab`, `snake`, `goCamel`, `goPascal`, `goKebab`, `goSnake`, `upper`, `lower`, `header` + # Support string case: `camel`, `pascal`, `kebab`, `snake`, `upperSnake`, `goCamel`, `goPascal`, `goKebab`, `goSnake`, `upper`, `lower`, `header` json: camel yaml: camel xml: camel bson: camel avro: snake mapstructure: kebab + env: upperSnake + envconfig: upperSnake tenv: # The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures. @@ -1725,6 +2046,71 @@ linters-settings: # Default: false all: false + testifylint: + # Enable all checkers (https://github.com/Antonboom/testifylint#checkers). + # Default: false + enable-all: true + # Disable checkers by name + # (in addition to default + # suite-thelper + # ). + disable: + - blank-import + - bool-compare + - compares + - empty + - error-is-as + - error-nil + - expected-actual + - go-require + - float-compare + - len + - nil-compare + - require-error + - suite-dont-use-pkg + - suite-extra-assert-call + - suite-thelper + - useless-assert + + # Disable all checkers (https://github.com/Antonboom/testifylint#checkers). + # Default: false + disable-all: true + # Enable checkers by name + # (in addition to default + # blank-import, bool-compare, compares, empty, error-is-as, error-nil, expected-actual, go-require, float-compare, + # len, nil-compare, require-error, suite-dont-use-pkg, suite-extra-assert-call, useless-assert + # ). + enable: + - blank-import + - bool-compare + - compares + - empty + - error-is-as + - error-nil + - expected-actual + - go-require + - float-compare + - len + - nil-compare + - require-error + - suite-dont-use-pkg + - suite-extra-assert-call + - suite-thelper + - useless-assert + + expected-actual: + # Regexp for expected variable name. + # Default: (^(exp(ected)?|want(ed)?)([A-Z]\w*)?$)|(^(\w*[a-z])?(Exp(ected)?|Want(ed)?)$) + pattern: ^expected + require-error: + # Regexp for assertions to analyze. If defined, then only matched error assertions will be reported. + # Default: "" + fn-pattern: ^(Errorf?|NoErrorf?)$ + suite-extra-assert-call: + # To require or remove extra Assert() call? + # Default: remove + mode: require + testpackage: # Regexp pattern to skip files. # Default: "(export|internal)_test\\.go" @@ -1826,6 +2212,29 @@ linters-settings: # Default: false check-exported: true + unused: + # Mark all struct fields that have been written to as used. + # Default: true + field-writes-are-uses: false + # Treat IncDec statement (e.g. `i++` or `i--`) as both read and write operation instead of just write. + # Default: false + post-statements-are-reads: true + # Mark all exported identifiers as used. + # Default: true + exported-is-used: false + # Mark all exported fields as used. + # default: true + exported-fields-are-used: false + # Mark all function parameters as used. + # default: true + parameters-are-used: false + # Mark all local variables as used. + # default: true + local-variables-are-used: false + # Mark all identifiers inside generated files as used. + # Default: true + generated-is-used: false + varcheck: # Check usage of exported fields and variables. # Default: false @@ -1891,11 +2300,12 @@ linters-settings: # An array of strings that specify substrings of signatures to ignore. # If this set, it will override the default set of ignored signatures. # See https://github.com/tomarrell/wrapcheck#configuration for more information. - # Default: [".Errorf(", "errors.New(", "errors.Unwrap(", ".Wrap(", ".Wrapf(", ".WithMessage(", ".WithMessagef(", ".WithStack("] + # Default: [".Errorf(", "errors.New(", "errors.Unwrap(", "errors.Join(", ".Wrap(", ".Wrapf(", ".WithMessage(", ".WithMessagef(", ".WithStack("] ignoreSigs: - .Errorf( - errors.New( - errors.Unwrap( + - errors.Join( - .Wrap( - .Wrapf( - .WithMessage( @@ -2024,6 +2434,7 @@ linters: - gocheckcompilerdirectives - gochecknoglobals - gochecknoinits + - gochecksumtype - gocognit - goconst - gocritic @@ -2042,10 +2453,12 @@ linters: - goprintffuncname - gosec - gosimple + - gosmopolitan - govet - grouper - ifshort - importas + - inamedparam - ineffassign - interfacebloat - interfacer @@ -2055,6 +2468,7 @@ linters: - maintidx - makezero - maligned + - mirror - misspell - musttag - nakedret @@ -2068,20 +2482,26 @@ linters: - nosnakecase - nosprintfhostport - paralleltest + - perfsprint - prealloc - predeclared - promlinter + - protogetter - reassign - revive - rowserrcheck - scopelint + - sloglint + - spancheck - sqlclosecheck - staticcheck - structcheck - stylecheck + - tagalign - tagliatelle - tenv - testableexamples + - testifylint - testpackage - thelper - tparallel @@ -2096,6 +2516,7 @@ linters: - whitespace - wrapcheck - wsl + - zerologlint # Enable all available linters. # Default: false @@ -2134,6 +2555,7 @@ linters: - gocheckcompilerdirectives - gochecknoglobals - gochecknoinits + - gochecksumtype - gocognit - goconst - gocritic @@ -2152,10 +2574,12 @@ linters: - goprintffuncname - gosec - gosimple + - gosmopolitan - govet - grouper - ifshort - importas + - inamedparam - ineffassign - interfacebloat - interfacer @@ -2165,6 +2589,7 @@ linters: - maintidx - makezero - maligned + - mirror - misspell - musttag - nakedret @@ -2178,20 +2603,26 @@ linters: - nosnakecase - nosprintfhostport - paralleltest + - perfsprint - prealloc - predeclared - promlinter + - protogetter - reassign - revive - rowserrcheck - scopelint + - sloglint + - spancheck - sqlclosecheck - staticcheck - structcheck - stylecheck + - tagalign - tagliatelle - tenv - testableexamples + - testifylint - testpackage - thelper - tparallel @@ -2206,9 +2637,11 @@ linters: - whitespace - wrapcheck - wsl + - zerologlint # Enable presets. # https://golangci-lint.run/usage/linters + # Default: [] presets: - bugs - comment @@ -2224,7 +2657,7 @@ linters: - test - unused - # Run only fast linters from enabled linters set (first run won't be fast) + # Enable only fast linters from enabled linters set (first run won't be fast) # Default: false fast: true @@ -2250,6 +2683,11 @@ issues: - dupl - gosec + # Run some linter only for test files by excluding its issues for everything else. + - path-except: _test\.go + linters: + - forbidigo + # Exclude known linters from partially hard-vendored code, # which is impossible to exclude via `nolint` comments. # `/` will be replaced by current OS file path separator to properly work on Windows. @@ -2271,7 +2709,7 @@ issues: # Independently of option `exclude` we use default exclude patterns, # it can be disabled by this option. # To list all excluded by default patterns execute `golangci-lint run --help`. - # Default: true. + # Default: true exclude-use-default: false # If set to true exclude and exclude-rules regular expressions become case-sensitive. @@ -2314,18 +2752,24 @@ issues: # It's not practical to fix all existing issues at the moment of integration: # much better don't allow issues in new code. # - # Default: false. + # Default: false new: true # Show only new issues created after git revision `REV`. + # Default: "" new-from-rev: HEAD # Show only new issues created in git patch with set file path. + # Default: "" new-from-patch: path/to/patch/file # Fix found issues (if it's supported by the linter). + # Default: false fix: true + # Show issues in any part of update files (requires new-from-rev or new-from-patch). + # Default: false + whole-files: true severity: # Set the default severity for issues. @@ -2336,8 +2780,9 @@ severity: # - Code climate: https://docs.codeclimate.com/docs/issues#issue-severity # - Checkstyle: https://checkstyle.sourceforge.io/property_types.html#SeverityLevel # - GitHub: https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message + # - TeamCity: https://www.jetbrains.com/help/teamcity/service-messages.html#Inspection+Instance # - # Default value is an empty string. + # Default: "" default-severity: error # If set to true `severity-rules` regular expressions become case-sensitive. diff --git a/.golangci.yml b/.golangci.yml index a755b257836b..c9700f77a79b 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,16 +1,33 @@ +# This configuration file is not a recommendation. +# +# We intentionally use a limited set of linters. +# This configuration file is used with different version of golangci-lint to avoid regressions: +# the linters can change between version, +# their configuration may be not compatible or their reports can be different, +# and this can break some of our tests. +# Also, some linters are not relevant for the project (e.g. linters related to SQL). +# +# We have specific constraints, so we use a specific configuration. +# +# See the file `.golangci.reference.yml` to have a list of all available configuration options. + linters-settings: depguard: - list-type: denylist - packages: - # logging is allowed only by logutils.Log, logrus - # is allowed to use only in logutils package - - github.com/sirupsen/logrus - packages-with-error-message: - - github.com/sirupsen/logrus: "logging is allowed only by logutils.Log" + rules: + logger: + deny: + # logging is allowed only by logutils.Log, + # logrus is allowed to use only in logutils package. + - pkg: "github.com/sirupsen/logrus" + desc: logging is allowed only by logutils.Log. + - pkg: "github.com/pkg/errors" + desc: Should be replaced by standard lib errors package. + - pkg: "github.com/instana/testify" + desc: It's a fork of github.com/stretchr/testify. dupl: threshold: 100 funlen: - lines: 100 + lines: -1 # the number of lines (code + empty lines) is not a right metric and leads to code without empty line or one-liner. statements: 50 goconst: min-len: 2 @@ -29,6 +46,13 @@ linters-settings: - whyNoLint gocyclo: min-complexity: 15 + godox: + keywords: + - FIXME + gofmt: + rewrite-rules: + - pattern: 'interface{}' + replacement: 'any' goimports: local-prefixes: github.com/golangci/golangci-lint gomnd: @@ -45,9 +69,7 @@ linters-settings: - '3' ignored-functions: - strings.SplitN - govet: - check-shadowing: true settings: printf: funcs: @@ -55,6 +77,11 @@ linters-settings: - (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf - (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf - (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf + enable: + - nilness + - shadow + errorlint: + asserts: false lll: line-length: 140 misspell: @@ -63,6 +90,11 @@ linters-settings: allow-unused: false # report any unused nolint directives require-explanation: false # don't require an explanation for nolint directives require-specific: false # don't require nolint directives to be specific about which linter is being skipped + revive: + rules: + - name: unexported-return + disabled: true + - name: unused-parameter linters: disable-all: true @@ -72,12 +104,15 @@ linters: - dogsled - dupl - errcheck + - errorlint - exportloopref - funlen + - gocheckcompilerdirectives - gochecknoinits - goconst - gocritic - gocyclo + - godox - gofmt - goimports - gomnd @@ -91,6 +126,7 @@ linters: - nakedret - noctx - nolintlint + - revive - staticcheck - stylecheck - typecheck @@ -99,21 +135,9 @@ linters: - unused - whitespace - # don't enable: - # - asciicheck - # - scopelint - # - gochecknoglobals - # - gocognit - # - godot - # - godox - # - goerr113 - # - interfacer - # - maligned - # - nestif - # - prealloc - # - testpackage - # - revive - # - wsl + # This list of linters is not a recommendation (same thing for all this configuration file). + # We intentionally use a limited set of linters. + # See the comment on top of this file. issues: # Excluding configuration per-path, per-linter, per-text and per-source @@ -123,20 +147,31 @@ issues: - gomnd - path: pkg/golinters/errcheck.go + linters: [staticcheck] text: "SA1019: errCfg.Exclude is deprecated: use ExcludeFunctions instead" - path: pkg/commands/run.go + linters: [staticcheck] text: "SA1019: lsc.Errcheck.Exclude is deprecated: use ExcludeFunctions instead" - path: pkg/commands/run.go - text: "SA1019: e.cfg.Run.Deadline is deprecated: Deadline exists for historical compatibility and should not be used." + linters: [staticcheck] + text: "SA1019: c.cfg.Run.ShowStats is deprecated: use Output.ShowStats instead." - path: pkg/golinters/gofumpt.go + linters: [staticcheck] text: "SA1019: settings.LangVersion is deprecated: use the global `run.go` instead." - path: pkg/golinters/staticcheck_common.go + linters: [staticcheck] text: "SA1019: settings.GoVersion is deprecated: use the global `run.go` instead." - path: pkg/lint/lintersdb/manager.go + linters: [staticcheck] text: "SA1019: (.+).(GoVersion|LangVersion) is deprecated: use the global `run.go` instead." + - path: pkg/golinters/unused.go + linters: [gocritic] text: "rangeValCopy: each iteration copies 160 bytes \\(consider pointers or indexing\\)" + - path: test/(fix|linters)_test.go + linters: [gocritic] + text: "string `gocritic.go` has 3 occurrences, make it a constant" run: timeout: 5m diff --git a/.goreleaser.yml b/.goreleaser.yml index 5b498d900682..36d129b8ea76 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -14,6 +14,7 @@ builds: - linux - freebsd - netbsd + - illumos goarch: - amd64 - arm64 @@ -73,8 +74,12 @@ changelog: - Merge pull request - Merge branch +source: + enabled: true + name_template: '{{ .ProjectName }}-{{ .Version }}-source' + brews: - - tap: + - repository: owner: golangci name: homebrew-tap folder: Formula @@ -101,6 +106,147 @@ nfpms: maintainer: "golangci-lint Team " description: Fast linters Runner for Go license: GPLv3 + section: golang formats: - deb - rpm + umask: 0o022 + overrides: + deb: + contents: + - src: LICENSE + dst: /usr/share/doc/golangci-lint/copyright + - src: README.md + dst: /usr/share/doc/golangci-lint/README.md + recommends: + - golang-go + rpm: + contents: + - src: LICENSE + dst: /usr/share/doc/golangci-lint/LICENSE + type: license + - src: README.md + dst: /usr/share/doc/golangci-lint/README.md + type: readme + recommends: + - /usr/bin/go + rpm: + group: Development/Tools + +docker_manifests: + # basic + - name_template: 'golangci/golangci-lint:latest' + image_templates: + - 'golangci/golangci-lint:{{ .Tag }}-amd64' + - 'golangci/golangci-lint:{{ .Tag }}-arm64' + + - name_template: 'golangci/golangci-lint:v{{ .Major }}.{{ .Minor }}' + image_templates: + - 'golangci/golangci-lint:v{{ .Major }}.{{ .Minor }}-amd64' + - 'golangci/golangci-lint:v{{ .Major }}.{{ .Minor }}-arm64' + + - name_template: 'golangci/golangci-lint:{{ .Tag }}' + image_templates: + - 'golangci/golangci-lint:{{ .Tag }}-amd64' + - 'golangci/golangci-lint:{{ .Tag }}-arm64' + + # alpine + - name_template: 'golangci/golangci-lint:latest-alpine' + image_templates: + - 'golangci/golangci-lint:{{ .Tag }}-alpine-amd64' + - 'golangci/golangci-lint:{{ .Tag }}-alpine-arm64' + + - name_template: 'golangci/golangci-lint:v{{ .Major }}.{{ .Minor }}-alpine' + image_templates: + - 'golangci/golangci-lint:v{{ .Major }}.{{ .Minor }}-alpine-amd64' + - 'golangci/golangci-lint:v{{ .Major }}.{{ .Minor }}-alpine-arm64' + + - name_template: 'golangci/golangci-lint:{{ .Tag }}-alpine' + image_templates: + - 'golangci/golangci-lint:{{ .Tag }}-alpine-amd64' + - 'golangci/golangci-lint:{{ .Tag }}-alpine-arm64' + +dockers: + - use: buildx + goos: linux + goarch: amd64 + dockerfile: build/buildx.Dockerfile + image_templates: + - 'golangci/golangci-lint:latest-amd64' + - 'golangci/golangci-lint:{{ .Tag }}-amd64' + - 'golangci/golangci-lint:v{{ .Major }}.{{ .Minor }}-amd64' + build_flag_templates: + - '--pull' + # https://github.com/opencontainers/image-spec/blob/main/annotations.md#pre-defined-annotation-keys + - '--label=org.opencontainers.image.title={{.ProjectName}}' + - '--label=org.opencontainers.image.description=Fast linters Runner for Go' + - '--label=org.opencontainers.image.source={{.GitURL}}' + - '--label=org.opencontainers.image.url={{.GitURL}}' + - '--label=org.opencontainers.image.documentation=https://golangci-lint.run' + - '--label=org.opencontainers.image.created={{.Date}}' + - '--label=org.opencontainers.image.revision={{.FullCommit}}' + - '--label=org.opencontainers.image.version={{.Version}}' + - '--platform=linux/amd64' + + - use: buildx + goos: linux + goarch: arm64 + dockerfile: build/buildx.Dockerfile + image_templates: + - 'golangci/golangci-lint:latest-arm64' + - 'golangci/golangci-lint:{{ .Tag }}-arm64' + - 'golangci/golangci-lint:v{{ .Major }}.{{ .Minor }}-arm64' + build_flag_templates: + - '--pull' + # https://github.com/opencontainers/image-spec/blob/main/annotations.md#pre-defined-annotation-keys + - '--label=org.opencontainers.image.title={{.ProjectName}}' + - '--label=org.opencontainers.image.description=Fast linters Runner for Go' + - '--label=org.opencontainers.image.source={{.GitURL}}' + - '--label=org.opencontainers.image.url={{.GitURL}}' + - '--label=org.opencontainers.image.documentation=https://golangci-lint.run' + - '--label=org.opencontainers.image.created={{.Date}}' + - '--label=org.opencontainers.image.revision={{.FullCommit}}' + - '--label=org.opencontainers.image.version={{.Version}}' + - '--platform=linux/arm64' + + - use: buildx + goos: linux + goarch: amd64 + dockerfile: build/buildx-alpine.Dockerfile + image_templates: + - 'golangci/golangci-lint:latest-alpine-amd64' + - 'golangci/golangci-lint:{{ .Tag }}-alpine-amd64' + - 'golangci/golangci-lint:v{{ .Major }}.{{ .Minor }}-alpine-amd64' + build_flag_templates: + - '--pull' + # https://github.com/opencontainers/image-spec/blob/main/annotations.md#pre-defined-annotation-keys + - '--label=org.opencontainers.image.title={{.ProjectName}}' + - '--label=org.opencontainers.image.description=Fast linters Runner for Go' + - '--label=org.opencontainers.image.source={{.GitURL}}' + - '--label=org.opencontainers.image.url={{.GitURL}}' + - '--label=org.opencontainers.image.documentation=https://golangci-lint.run' + - '--label=org.opencontainers.image.created={{.Date}}' + - '--label=org.opencontainers.image.revision={{.FullCommit}}' + - '--label=org.opencontainers.image.version={{.Version}}' + - '--platform=linux/amd64' + + - use: buildx + goos: linux + goarch: arm64 + dockerfile: build/buildx-alpine.Dockerfile + image_templates: + - 'golangci/golangci-lint:latest-alpine-arm64' + - 'golangci/golangci-lint:{{ .Tag }}-alpine-arm64' + - 'golangci/golangci-lint:v{{ .Major }}.{{ .Minor }}-alpine-arm64' + build_flag_templates: + - '--pull' + # https://github.com/opencontainers/image-spec/blob/main/annotations.md#pre-defined-annotation-keys + - '--label=org.opencontainers.image.title={{.ProjectName}}' + - '--label=org.opencontainers.image.description=Fast linters Runner for Go' + - '--label=org.opencontainers.image.source={{.GitURL}}' + - '--label=org.opencontainers.image.url={{.GitURL}}' + - '--label=org.opencontainers.image.documentation=https://golangci-lint.run' + - '--label=org.opencontainers.image.created={{.Date}}' + - '--label=org.opencontainers.image.revision={{.FullCommit}}' + - '--label=org.opencontainers.image.version={{.Version}}' + - '--platform=linux/arm64' diff --git a/.nancy-ignore b/.nancy-ignore index 8496832e9804..e651eb9706b4 100644 --- a/.nancy-ignore +++ b/.nancy-ignore @@ -18,3 +18,19 @@ CVE-2021-41803 # Skip for indirect dependencies golang/github.com/valyala/fasthttp@v1.30.0 CVE-2022-21221 + +# Skip for indirect dependencies golang/golang.org/x/net +CVE-2022-41723 +CVE-2023-3978 + +# Skip for indirect dependencies golang/google.golang.org/grpc@v1.46.2 +CVE-2023-32731 + +# Skip for indirect dependencies golang/golang.org/x/crypto@v0.14.0 +CVE-2023-48795 + +# Skip for indirect dependencies github.com/jackc/pgproto3 - github.com/jackc/pgx +CVE-2024-27304 + +# Skip for indirect dependencies golang/google.golang.org/protobuf +CVE-2024-24786 diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml index 92a01f441216..2e622bc5df3c 100644 --- a/.pre-commit-hooks.yaml +++ b/.pre-commit-hooks.yaml @@ -1,7 +1,16 @@ - id: golangci-lint name: golangci-lint - description: Fast linters runner for Go. + description: Fast linters runner for Go. Note that only modified files are linted, so linters like 'unused' that need to scan all files won't work as expected. + entry: golangci-lint run --new-from-rev HEAD --fix + types: [go] + language: golang + require_serial: true + pass_filenames: false +- id: golangci-lint-full + name: golangci-lint-full + description: Fast linters runner for Go. Runs on all files in the repo. Use this hook if you use pre-commit in CI. entry: golangci-lint run --fix types: [go] language: golang + require_serial: true pass_filenames: false diff --git a/CHANGELOG.md b/CHANGELOG.md index 014c847a2127..fb24ac84aafc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,360 @@ -Follow the news and releases on our [twitter](https://twitter.com/golangci) and our [blog](https://medium.com/golangci). +Follow the news and releases on [Mastodon](https://fosstodon.org/@golangcilint) and on [Twitter](https://twitter.com/golangci). + There is the most valuable changes log: +### v1.56.2 + +1. updated linters + * `go-critic`: from 0.11.0 to 0.11.1 + * `gosec`: from 2.18.2 to 2.19.0 + * `testifylint`: from 1.1.1 to 1.1.2 + * `usestdlibvars`: from 1.24.0 to 1.25.0 + * `wsl`: from 4.2.0 to 4.2.1 +2. misc. + * Fix missing version in Docker image +3. Documentation + * Explain the limitation of new-from-rev and new-from-patch + +### v1.56.1 + +1. updated linters + * `errcheck`: from 1.6.3 to 1.7.0 + * `govet`: disable `loopclosure` with go1.22 + * `revive`: from 1.3.6 to 1.3.7 + * `testifylint`: from 1.1.0 to 1.1.1 + +### v1.56.0 + +1. new linters + * feat: add `spancheck` linter https://github.com/jjti/go-spancheck +2. updated linters + * `depguard`: from 2.1.0 to 2.2.0 + * `exhaustive`: from 0.11.0 to 0.12.0 + * `exhaustruct`: from 3.1.0 to 3.2.0 + * `gci`: from 0.11.2 to 0.12.1 + * `ginkgolinter`: from 0.14.1 to 0.15.2 + * `go-check-sumtype`: from 0.1.3 to 0.1.4 + * `go-critic`: from 0.9.0 to 0.11.0 + * `go-errorlint`: from 1.4.5 to 1.4.8 + * `go-spancheck`: from 0.4.2 to 0.5.2 + * `goconst`: from 1.6.0 to 1.7.0 + * `godot`: from 1.4.15 to 1.4.16 + * `gofumpt`: from 0.5.0 to 0.6.0 + * `inamedparam`: from 0.1.2 to 0.1.3 + * `ineffassign`: from 0.0.0-20230610083614-0e73809eb601 to 0.1.0 + * `ireturn`: from 0.2.2 to 0.3.0 + * `misspell`: add mode option + * `musttag`: from v0.7.2 to v0.8.0 + * `paralleltest`: from 1.0.8 to 1.0.9 + * `perfsprint`: from 0.2.0 to 0.6.0 + * `protogetter`: from 0.2.3 to 0.3.4 + * `revive`: from 1.3.4 to 1.3.6 + * `sloglint`: add static-msg option + * `sloglint`: from 0.1.2 to 0.4.0 + * `testifylint`: from 0.2.3 to 1.1.0 + * `unparam`: from 20221223090309-7455f1af531d to 20240104100049-c549a3470d14 + * `whitespace`: update after moving to the `analysis` package + * `wsl`: from 3.4.0 to 4.2.0 + * `zerologlint`: from 0.1.3 to 0.1.5 +3. misc. + * 🎉 go1.22 support + * Implement stats per linter with a flag + * fix: make versioning inside Docker image consistent with binaries + * fix: parse Go RC version +4. Documentation + * Add missing fields to .golangci.reference.yml + * Fix noctx description + * Improve .golangci.reference.yml defaults + * Improve typecheck FAQ + * Note that `exhaustruct` struct regular expressions are expected to match the entire `package/name/structname` + * Adjust wrapcheck ignoreSigs to new defaults + +**Important** + +`testifylint` has [breaking changes](https://github.com/Antonboom/testifylint/releases/tag/v1.0.0) about enabling/disabling checks: + +- If you were using the option `enable` with a filtered list of checks, you should either add `disable-all: true` (1) or use `disable` field (2). + + ```yml + # Example (1) + testifylint: + disable-all: true + enable: + - bool-compare + - compares + - empty + - error-is-as + - error-nil + - expected-actual + - go-require + - float-compare + - len + - nil-compare + - require-error + # - suite-dont-use-pkg + - suite-extra-assert-call + - suite-thelper + ``` + + ```yml + # Example (2) + testifylint: + disable: + - suite-dont-use-pkg + ``` + +### v1.55.2 + +1. updated linters + * `ireturn`: from 0.2.1 to 0.2.2 + * `ginkgolinter`: from 0.14.0 to 0.14.1 + +### v1.55.1 + +1. updated linters + * `gosec`: from 2.18.1 to 2.18.2 +2. misc. + * `revgrep`: from v0.5.0 to v0.5.2 (support git < 2.41.0) + * output: convert backslashes to forward slashes for GitHub Action annotations printer + +### v1.55.0 + +1. new linters + * `gochecksumtype`: https://github.com/alecthomas/go-check-sumtype + * `inamedparam`: https://github.com/macabu/inamedparam + * `perfsprint`: https://github.com/catenacyber/perfsprint + * `protogetter`: https://github.com/ghostiam/protogetter + * `sloglint`: https://github.com/go-simpler/sloglint + * `testifylint`: https://github.com/Antonboom/testifylint +2. updated linters + * `bidichk`: from 0.2.4 to 0.2.7 + * `decorder`: from 0.4.0 to 0.4.1 + * `dupword`: from 0.0.12 to 0.0.13 + * `errchkjson`: from 0.3.1 to 0.3.6 + * `gci`: from 0.11.0 to 0.11.2 + * `ginkgolinter`: from 0.13.5 to 0.14.0 + * `go-errorlint`: from 1.4.4 to 1.4.5 + * `gocognit`: from 1.0.7 to 1.1.0 + * `goconst`: from 1.5.1 to 1.6.0 + * `godot`: from 1.4.14 to 1.4.15 + * `gofmt`: update to HEAD + * `goimports`: update to HEAD + * `gosec`: from 2.17.0 to 2.18.1 + * `gosmopolitan`: from 1.2.1 to 1.2.2 + * `govet`: add `appends` analyzer + * `ireturn`: from 0.2.0 to 0.2.1 + * `protogetter`: from 0.2.2 to 0.2.3 + * `revgrep`: from 745bb2f7c2e6 to v0.5.0 + * `revive`: from 1.3.2 to 1.3.4 + * `sqlclosecheck`: from 0.4.0 to 0.5.1 + * `staticcheck`: from 0.4.5 to 0.4.6 + * `tagalign`: from 1.3.2 to 1.3.3 + * `unused`: support passing in options +3. misc. + * Add a pre-commit hook to check all files +4. Documentation + * add source options to exclude-rules docs + * `gosec`: add G602 to includes/excludes inside .golangci.reference.yml + +### v1.54.2 + +1. updated linters: + * `errname`: from 0.1.10 to 0.1.12 + * `ginkgolinter`: from 0.13.3 to 0.13.5 + * `go-errorlint`: from 1.4.3 to 1.4.4 + * `godot`: from 1.4.11 to 1.4.14 + * `gosec`: from 2.16.0 to 2.17.0 + * `musttag`: from 0.7.1 to 0.7.2 + * `nilnil`: from 0.1.5 to 0.1.7 + * `staticcheck`: from 0.4.3 to 0.4.5 + * `usestdlibvars`: from 1.23.0 to 1.24.0 + * `govet`: add missing `directive` and `slog` passes + +### v1.54.1 + +1. updated linters: + * `go-critic`: from 0.8.2 to 0.9.0 +2. misc. + * plugin: temporarily hide warning about using plugins using the old API + +### v1.54.0 + +1. updated linters: + * `decorder`: from 0.2.3 to 0.4.0 + * `dupword`: from 0.0.11 to 0.0.12 + * `errorlint`: from 1.4.2 to 1.4.3 + * `exhaustruct`: from 2.3.0 to 3.1.0 + * `forbidigo`: from 1.5.3 to 1.6.0 + * `funlen`: from 0.0.3 to 0.1.0 + * `gci`: from 0.10.1 to 0.11.0 + * `ginkgolinter`: from 0.12.1 to 0.13.3 + * `go-critic`: from 0.8.1 to 0.8.2 + * `go-errorlint`: from 1.4.2 to 1.4.3 + * `go-exhaustruct`: from 2.3.0 to 3.1.0 + * `gocognit`: from 1.0.6 to 1.0.7 + * `gocritic`: from 0.8.1 to 0.8.2 + * `gofmt`: autofix missing newline at EOF + * `misspell`: 0.4.0 to 0.4.1 + * `musttag`: from 0.7.0 to 0.7.1 + * `paralleltest`: from 1.0.7 to 1.0.8 + * `tagalign`: from 1.2.2 to 1.3.2 + * `typecheck`: explain it and remove it from the linter list + * `zerologlint`: from 0.1.2 to 0.1.3 +2. misc. + * 🎉 go1.21 support + * plugin: include custom linters in `enable-all` + * plugin: allow to use settings for plugins +3. Documentation + * Add linter descriptions. + +**Important** + +`ruleguard` (a "rule" inside `gocritic`) was disabled in this release (v1.54.0) and was enabled again in the next release (v1.54.1). + +`exhaustruct` has breaking changes with regular expressions, more details [here](https://github.com/GaijinEntertainment/go-exhaustruct/releases/tag/v3.0.0). + +### v1.53.3 + +1. updated linters: + * `cyclop`: from 1.2.0 to 1.2.1 + * `exhaustive`: from 0.10.0 to 0.11.0 + * `forbidigo`: from 1.5.1 to 1.5.3 + * `ginkgolinter`: from 0.12.2 to 0.12.1 + * `ineffassign`: bump to HEAD + * `nakedret`: from 2.0.1 to 2.0.2 + * `zerologlint`: from 0.1.1 to 0.1.2 +2. misc. + * codeclimate: reduce memory allocation + * support illumos/amd64 + +### v1.53.2 + +1. updated linters + * `depguard`: from v2.0.1 to 2.1.0 +2. misc. + * `depguard`: throw error only when the linter is called + +### v1.53.1 + +1. misc. + * `depguard`: fix GOROOT detection + * `importas`: fix duplication detection when aliases use regular expression replacement pattern + +### v1.53.0 + +1. new linters + * `gosmopolitan`: https://github.com/xen0n/gosmopolitan + * `mirror`: https://github.com/butuzov/mirror + * `tagalign`: https://github.com/4meepo/tagalign + * `zerologlint`: https://github.com/ykadowak/zerologlint +2. updated linters + * `bodyclose`: bump to HEAD + * `containedctx`: from 1.0.2 to 1.0.3 + * `depguard`: migrate to v2 + * `errname`: from 0.1.9 to 0.1.10 + * `exhaustive`: from 0.9.5 to 0.10.0 + * `forbidigo`: better support for configuring complex rules + * `gci`: improve error message + * `ginkgolinter`: add suppress-async-assertion option + * `ginkgolinter`: from 0.9.0 to 0.12.0 + * `go-critic`: from 0.7.0 to 0.8.1 + * `go-errorlint`: from 1.4.0 to 1.4.2 + * `gofumpt`: from 0.4.0 to 0.5.0 + * `gosec`: convert global settings as map with proper key type + * `gosec`: from 2.15.0 to 2.16.0 + * `importas`: detect duplicate alias or package in the configuration + * `importas`: fix typo in logs + * `ireturn`: from 0.1.1 to 0.2.0 + * `musttag`: from 0.5.0 to 0.7.0 + * `nakedret`: to 2.0.1 + * `nilnil`: from 0.1.3 to 0.1.5 + * `paralleltest`: from 1.0.6 to 1.0.7 + * `revive`: from 1.3.1 to 1.3.2 + * `tagliatelle`: from 0.4.0 to 0.5.0 + * `usestdlibvars`: fix configuration +3. misc. + * `golang.org/x/tools`: from 0.7.0 to 0.9.2 + * add loongarch64 to the install script + * output: add colored-tab + * remove warning when the config file is explicitly stdin + * rules: support inverted path match +4. Documentation + * `mnd`: clarify ignore usage examples to be regexps + * `tagliatelle`: update documentation + * improve features section + * update supported Go versions FAQ + +### v1.52.2 + +1. updated linters + * `tparallel`: from 0.3.0 to 0.3.1 +2. misc. + * fix: pre-commit `require_serial` and `pass_filenames` + +### v1.52.1 + +1. misc. + * fix: improve panic management + * fix: the combination of --fix and --path-prefix + +### v1.52.0 + +1. updated linters + * `asciicheck`: from 0.1.1 to 0.2.0 + * `bidichk`: from 0.2.3 to 0.2.4 + * `contextcheck`: from 1.1.3 to 1.1.4 + * `dupword`: from 0.0.9 to 0.0.11 + * `durationcheck`: from 0.0.9 to 0.0.10 + * `errchkjson`: from 0.3.0 to 0.3.1 + * `errname`: from 0.1.7 to 0.1.9 + * `forbidigo`: from 1.4.0 to 1.5.1 + * `gci`: from 0.9.1 to 0.10.1 + * `ginkgolinter`: from 0.8.1 to 0.9.0 + * `go-critic`: from 0.6.7 to 0.7.0 + * `go-errorlint`: from 1.1.0 to 1.4.0 + * `godox`: bump to HEAD + * `lll`: skip go command + * `loggercheck`: from 0.9.3 to 0.9.4 + * `musttag`: from 0.4.5 to 0.5.0 + * `nilnil`: from 0.1.1 to 0.1.3 + * `noctx`: from 0.0.1 to 0.0.2 + * `revive`: from 1.2.5 to 1.3.1 + * `rowserrcheck`: remove limitation related to generics support + * `staticcheck`: from 0.4.2 to 0.4.3 + * `testpackage`: from 1.1.0 to 1.1.1 + * `tparallel`: from 0.2.1 to 0.3.0 + * `wastedassign`: remove limitation related to generics support + * `wrapcheck`: from 2.8.0 to 2.8.1 +2. misc. + * Add TeamCity output format + * Consider path prefix when matching path patterns + * Add Go version to version information +3. Documentation + * Add Tekton in Trusted By page + * Clarify that custom linters are not enabled by default + * Remove description for deprecated "go" option + +### v1.51.2 + +1. updated linters + * `forbidigo`: from 1.3.0 to 1.4.0 + * `gci`: from 0.9.0 to 0.9.1 + * `go-critic`: from 0.6.5 to 0.6.7 + * `go-errorlint`: from 1.0.6 to 1.1.0 + * `gosec`: from 2.14.0 to 2.15.0 + * `musttag`: from 0.4.4 to 0.4.5 + * `staticcheck`: from 0.4.0 to 0.4.2 + * `tools`: from 0.5.0 to 0.6.0 + * `usestdlibvars`: from 1.21.1 to 1.23.0 + * `wsl`: from 3.3.0 to 3.4.0 + * `govet`: enable `timeformat` by default +2. misc. + * fix: cache status size calculation + * add new source archive +3. Documentation + * Improve installation section + * Replace links to godoc.org with pkg.go.dev + ### v1.51.1 1. updated linters @@ -16,7 +370,7 @@ There is the most valuable changes log: 1. new linters * `ginkgolinter`: https://github.com/nunnatsa/ginkgolinter - * `musttag`: https://github.com/junk1tm/musttag + * `musttag`: https://github.com/tmzane/musttag * `gocheckcompilerdirectives`: https://github.com/leighmcculloch/gocheckcompilerdirectives 2. updated linters * `bodyclose`: to HEAD diff --git a/Makefile b/Makefile index 92f3580e74a4..823bf8234be6 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,6 @@ clean: rm -f $(BINARY) rm -f test/path rm -f tools/Dracula.itermcolors - rm -f tools/goreleaser rm -f tools/svg-term rm -rf tools/node_modules .PHONY: clean @@ -62,23 +61,11 @@ fast_check_generated: git checkout -- go.mod go.sum # can differ between go1.16 and go1.17 git diff --exit-code # check no changes -release: .goreleaser.yml tools/goreleaser - ./tools/goreleaser -.PHONY: release - -snapshot: .goreleaser.yml tools/goreleaser - ./tools/goreleaser --snapshot --rm-dist -.PHONY: snapshot - # Non-PHONY targets (real files) $(BINARY): FORCE go build -o $@ ./cmd/golangci-lint -tools/goreleaser: export GOFLAGS = -mod=readonly -tools/goreleaser: tools/go.mod tools/go.sum - cd tools && go build github.com/goreleaser/goreleaser - # TODO: migrate to docs/ tools/svg-term: tools/package.json tools/package-lock.json cd tools && npm ci @@ -101,12 +88,18 @@ go.mod: FORCE go mod verify go.sum: go.mod -expand_website_templates: - go run ./scripts/expand_website_templates/main.go -.PHONY: expand_website_templates +website_copy_jsonschema: + cp -r ./jsonschema ./docs/static +.PHONY: website_copy_jsonschema + +website_expand_templates: + go run ./scripts/website/expand_templates/ +.PHONY: website_expand_templates + +website_dump_info: + go run ./scripts/website/dump_info/ +.PHONY: website_dump_info update_contributors_list: cd .github/contributors && npm run all -update_netlify_state: - go run ./scripts/expand_website_templates/main.go -only-state diff --git a/README.md b/README.md index a9ff77b3e540..041878518b90 100644 --- a/README.md +++ b/README.md @@ -6,13 +6,13 @@ --- -`golangci-lint` is a fast Go linters runner. It runs linters in parallel, uses caching, supports `yaml` config, has integrations -with all major IDE and has dozens of linters included. +`golangci-lint` is a fast Go linters runner. It runs linters in parallel, uses caching, supports YAML configuration, +integrates with all major IDEs, and includes over a hundred linters. ## Install `golangci-lint` -- [On my machine](https://golangci-lint.run/usage/install/#local-installation); -- [On CI/CD systems](https://golangci-lint.run/usage/install/#ci-installation). +- [On my machine](https://golangci-lint.run/welcome/install/#local-installation); +- [On CI/CD systems](https://golangci-lint.run/welcome/install/#ci-installation). ## Documentation @@ -54,7 +54,7 @@ The Core Team has the following responsibilities: - + @@ -64,185 +64,221 @@ The Core Team has the following responsibilities:

Ludovic Fernandez

Ludovic Fernandez

Denis Isaev

Aleksandr Razumov
- - + + + - - + + + - - + - - + - - - + + + + + - - + + + - - + + - - - + + + + + - - - - -

Sergey Vilgelm

Tam Mach

Sergey Vilgelm

Simon Sawert

Tam Mach

Trevor Pounds

Oleksandr Redko

Loong Dai

Kamil Samigullin

Oleg Butuzov

Oleg Butuzov

Kamil Samigullin

Anton Telyshev

Sascha Grunert

@iwankgb

Andrew Shannon Brown

@golangci-releaser

Andrew Shannon Brown

Marat Reymers

sivchari

Pierre Durand

sivchari

Sebastien Rosset

Ryan Currah

Sasha Melentyev

@leonklingele

Ryan Currah

Pierre Durand

Sebastien Rosset

Sasha Melentyev

Patrick Ohly

Denis Tingaikin

David Lobe

Alexey Palazhchenko

Alexey Palazhchenko

David Lobe

Ville Skyttä

Duco van Amstel

Nishanth Shanmugham

Kensei Nakada

Nishanth Shanmugham

Kensei Nakada

Melvin

quasilyte

Denis Krivak

Anton Telyshev

quasilyte

Denis Krivak

Alec Thomas

Mitsuo HEIJO

Maik Schreiber

Nahshon Unna Tsameret

Steve Coffman

Matouš Dzivjak

Alec Thomas

Mateusz Gozdek

Will Dixon

Mitsuo Heijo
-And 381 more our team members +And 461 more our team members + + + + + + + + - - + + + - - - + - + + + - + + - - + - + + - - - + + - - - + - + - - + + + + - - - + + + + + - - + + + + - - + + + + + + + + - + - - + + + + + + + + + + - - - - - - - - + + + + + + - + + + - + + + - + + + + - + + + + + - - - - - + + + + + - - - - + + + + - + @@ -252,358 +288,424 @@ The Core Team has the following responsibilities: - - + + - - - - + + + - + + - + + + + - - - + + - + + + + + - - - + + + + - + + + - + + + - - - + + - - + + + - - + + - + + + + + - - - + - - - - + + + + - - - - - + + + + + + + + - + + + - - - - + + + + + + + + + + + + + - - - + + + + - + - + - + - + - + - + - + + - - + + - - - - + + - - + + + + + - - - - + + + - + - - + + - + - + - - + + + + - - - - + + + + - - + + + + - - + + - - - - - - + + + + + + - + + + + - - - - - - + + + - - - + + + + + + + + + - + - - - + + + + + + + + + + + + - + - - - + + + + - + + + + - - + + + + - - - + - + + + - - + + + + + + + + + + + - - - + + + - + - - + - + + - - - - - - + + - + + + + + - + + + +

Matouš Dzivjak

Will Dixon

Mateusz Gozdek

Peter Mescalchin

Mateus Oliveira

Michael Mulligan

Nuruddin Ashr

Tom

Joe Wilner

Oleksandr Redko

Soichiro Kashima

Peter Mescalchin

Lucas Bremgartner

@alingse

Oleg Kovalov

Florian Bosdorff

Ville Skyttä

Kir Kolyshkin

Tim Heckman

@alingse

Tim Heckman

James

Colin Arnott

Anton Zinovyev

Anton Zinovyev

Luke T. Shumaker

Steven Hartland

Luke Shumaker

Aleksey Bakin

Márk Sági-Kazár

Rski

Ryan Boehning

Gustavo Bazan

Florian Bosdorff

Eugene Simonov

Rski

Timon Wong

Timon Wong

ferhat elmas

Nate Finch

Aliaksandr Mianzhynski

Aleksey Bakin

Steven Hartland

Leigh McCulloch

Aneesh Agrawal

Leigh McCulloch

sonatard

ZhangYunHao

Aneesh Agrawal

Vladimir Evgrafov

Nahshon Unna Tsameret

Vladimir Evgrafov

gaojingyu

@odidev

Denis Limarev

Denis Limarev

NiseVoid

Christian Mehlmauer

Sean DuBois

Viktoras

Fabian Holler

Yifei Liu

Agniva De Sarker

Nate Finch

SystemGlitch

Henrik Johansson

Adam Shannon

Ilia Sergunin

SystemGlitch

Henrik Johansson

Florent Viel

Tom Arrell

Choko

John Starich

Koichi Shiraishi

Bart

Neha Viswanathan

David Braley

Neha Viswanathan

Lukas Malkmus

David Braley

Vladislav Fursov

Chris Bandy

Patrick Kuca

Viacheslav Poturaev

Lukas Malkmus

Zik

Catena cyber

@Abirdcfly

Hendry Wiranto

Mitar

Zik Aeroh

Paweł Żak

sylvia

Robert Liebowitz

Robert Liebowitz

Zeal Wierslee

Tim Kral

Hiroyuki Yagihashi

Florent Viel

Hiroyuki Yagihashi

Kyoh

Jiangnan Jia

Kunwardeep

Pierre R

Stephan Renatus

Adam Jones

Martin Desrumaux

tdakkota

Ivan

Carlos Henrique Guardão Gandarez

@kyoh86

Ivan

tdakkota

Diego Pontoriero

Daniel Helfand

Benjamin Wang

Adam Jones

Faisal Alam

Benjamin Wang

Craig Silverstein

Faisal Alam

Alex Collins

Ryo Nakao

Ryan Olds

Matheus Macabu

Tommy Mühle

Sebastiaan van Stijn

@Dominik-K

Sam Zaydel

Hans Wernetti

Carlos Alexandro Becker

Craig Silverstein

Dominik K.

Joshua Timmons

Sindre Røkenes Myren

Bartłomiej Klimczak

ferhat elmas

Fata Nugraha

M. Ángel Jimeno

Jan Oopkaup

Chris Drew

Teiva Harsanyi

Teiva Harsanyi

Brian Flad

Chris Suszynski

@chenfeining

Kailun Qin

Misha Gusarov

Chris Suszynski

Kailun Qin

@Abirdcfly

Ariel Mashraki

Shulhan

Ariel Mashraki

Shulhan

Oscar

Denis Isaev

Dreamacro

Tom Payne

@fsouza

Dreamacro

Tom Payne

Jiangnan Jia

@fsouza

Siarhei Navatski

Chris Halbert

Koya IWAMURA

Hiroki Suezawa

Lauris BH

Sean McGinnis

Fabrice

Christoph Blecker

Mateusz Bilski

Mateusz Bilski

Jakub Chábek

Ben Ye

lufe

Cory LaNou

Vitaly Isaev

Sindre Røkenes Myren

Pete Wagner

Renato Suero

Buyanov Vladimir

Sven Anderson

Sven Anderson

Ben Wells

Ben Wells

Jonathan Chappelow

Siarhei Navatski

Yuki Okushi

Sean McGinnis

Yuki Okushi

hbc

WÁNG Xuěruì

Eric Wohltman

Borja Clemente

Borja Clemente

Ethan Reesor

Ethan Reesor

Mattias de Zalenski

@AlduLonghi

Justin Fuller

masibw

Sonia Hamilton

@black-06

Gianguido Sorà

Derek Perkins

Carlos Henrique Guardão Gandarez

Oksana Grishchenko

Derek Perkins

Oksana Grishchenko

Berezhnoy Pavel

Henry

Son Luong Ngoc

Henry

Aofei Sheng

jessetang

Maksym Pavlenko

Ivan Prisyazhnyy

@ngehrsitz

John Reese

John Reese

Matthew Gabeler-Lee

Matthew Dowdell

James Lucktaylor

Dale Hui

Ondrej Fabry

Ondrej Fabry

Aris Tzoumas

Gabor Javorszky

hori-ryota

Kishan B

proton

Adam Bouqdib

Roman Chaliy

proton

Eric Jain

Ghvst Code

Son Luong Ngoc

Markus

Sebastian Spaink

Markus

Sebastian Spaink

Andrew Lavery

Mark Fine

Tariq Ibrahim

Mark Fine

Rory Prendergast

Tariq

Peter Štibraný

kaixiang zhong

@ced42

David Bariod

Stephen Benjamin

@kkHAIKE

Stephen Benjamin

@kkHAIKE

Hsing-Yu (David) Chen

WÁNG Xuěruì

Batuhan Apaydın

Mostafa Moradian

过客龙门

Eldar Rakhimberdin

Toon Schoenmakers

Cezar Sá Espinola

Ben Paxton

Connor Adams

Draven

Draven

David Cuadrado

Max Riveiro

Martins Irbe

Craig Furman

Yilong Li

Rodrigo Brito

Martins Irbe

Yilong Li

Rodrigo Brito

@techknowlogick

takaya

Craig Furman

@ttys3

Mark Sart

Joshua Rubin

Danil Ovchinnikov

Rafael Franco

Tom

Mark Sart

Joshua Rubin

Danil Ovchinnikov

Rafael Franco

Ksenia Rogova

Paul Vaughan

Linus Arver

Glen Mailer

Ian Howell

Chris K

Chris K

Grigory Zubankov

@xxpxxxxp

subham sarkar

Ryan Leung

Subham

smantic

Ryan Leung

Donal Byrne

Marko

Yusuke Kadowaki

Olli Raula

@CfirTsabari

Jared Allard

Navneeth Jayendran

Navneeth Jayendran

Marko

Chris Lewis

Muhammad Ikhsan

Anton Braer

Jaegoo Kim

David Gleich

yuqengo

David Gleich

Fata Nugraha

Misha Gusarov

Dejan Benedik

Craig Rodrigues

Askari

David Beitey

Dan Richelson

Denis Titusov

Terdunov Vyacheslav

Sean Chittenden

Sean Chittenden

Hui Zhu

@Harsimran1

rinsuki

rinsuki

Anton Antonov

@hn8

Kevin Gillette

Milas Bowman

Milas Bowman

@credativ-dar

☃ Elliot Shepherd

@nvartolomei

Nicolae Vartolomei

Martin Etmajer

Fisher Xu

Matthew Poer

Cody Ley-Han

Cody Ley-Han

@darklore

@to6ka

@evalexpr

Jonathan Wilkins

Collin Kreklow

Marcin Owsiany

C.J. Jameson

Jacek

Stephen Brown II

Jacek

paul fisher

@ofw

Rafik Draoui

Miles Delahunty

Anton Kachurin

Nico Ismaili

Benjamin Kane

Nico Ismaili

Benjamin Kane

@trajan0x

Philip Linell

Herman van Zyl

Koya IWAMURA

Jongwoo Han

Ryo Sato

Eric Zimanyi

Jongwoo Han

Yury Gargay

@bbernays

Boban Acimovic

Ryo Sato

Eric Zimanyi

Ben Bernays

Boban Acimovic

Viktor Alenkov

Dima

David Hill

Troy Ronda

Jared Allard

Viktor Alenkov

Anton Braer

Troy Ronda

Andrey Grazhdankov

mfreeman451

Florian Gessner

Osamu TONOMORI

Osamu TONOMORI

Bo Liu

Steven Allen

Colin Arnott

Eran Levy

Colin Arnott

Eran Levy

Roman Leventov

Hugo

Hugo

Mathias Weber

Naveen

Naveen

@maxsond

mattu

Maksim Meshkov

Maksim Meshkov

@raffepaffe

Abhinav Gupta

Brandur Leach

Michael

Evgeniy Kulikov

Chris Nesbitt-Smith

Daniel Caballero

Igor Zibarev

Carlton Henderson

Shintaro Ikeda

Daniel Caballero

Igor Zibarev

Carl Henderson

Shintaro Anazawa

Matt Braymer-Hayes

Arjen van der Ende

Adam Bouqdib

Tomas Dabasinskas

Pete Davison

Tomas Dabašinskas

@xuri

Charl Matthee

Sriram Venkatesh

Peter Schuller

David Golub

Alexander Morozov

Pastoh

Liam White

Alex Dupre

Juanito

Jinming Yue

@wxdao

Kévin Dunglas

Sijie Yang

Stephen

Thang Minh Vu

Julia Ogris

Sijie Yang

Stephen

Thang Minh Vu

Julia Ogris

Greg Curtis

@ac-rappi

Dudás Ádám

Abhishek | अभिषेक

Daniele

Takumasa Sakao

Takumasa Sakao

Ben Drucker

Matthew Cobbing

@Darlez

Kirill Danshin

Stephen Brown II

Matthew Cobbing

@Darlez

Kirill Danshin

mook

Kyungmin Bae

Dylan Arbour

Cory Miller

Ben Brown

Dor

sink

João Freitas

nick

@andreykuchin

Irina

nick

David Bendory

@znley

Jonathan Colby

Justin Robertson

Caleb Xu

Tobias

@andreykuchin

Irina

Petr Pučil

Aaron Bennett

阿杰鲁

zaunist

Daniil Suvorov

Alexandre Vilain

Thirukumaran Vaseeharan

Alessio Treglia

Yuki Watanabe

Aisuko

Tung Leo

Kunal Singh

Rui Chen

Alexandre Vilain

Federico Guerinoni

Matias Lahti

Thirukumaran Vaseeharan

Alessio Treglia

Alay Patel

Martin Hutchinson

Martin Hutchinson

Emanuel Bennici

Mayo

Matias Lahti

Sebastian Crane

Alexander Else

smantic

@connorszczepaniak-wk

Sebastian Crane

Alexander Else

@vladopajic

Lucas Ramage

@oxr463

Trim21

@oliverpool

Christian Clauss

Johanan Liebermann

Korjavin Ivan

Eng Zer Jun

Mateus Esdras

Devin Gunay

Hilário Coelho

Thomas Cave

Tibo Delor

@chainchad

Francois Parquet

Robert Kopaczewski

Marc Tudurí

Marc Tudurí

@opennota

@pohang

Cyrille Meichel

Cyrille Meichel

neglect-yp

Felix

Felix

Adrien

Joe Bergevin

Axetroy

Joe Bergevin

Guillaume JG

cnmade

Evan Cordell

靳灿奇

Nassos Kat

hitzhangjie

Jesse Donat

Oleg Shparber

Tomi Juntunen

Miel Donkers

Ryosei Karaki

Marccio Silva

KADOTA, Kyohei

Conor Evans

Anirudh Sylendranath

Anirudh Sylendranath

@jumpeiMano

Federico Guerinoni

Alex Rodin

Oliver Gugger

Bryan Andrews

David Beitey

@TomerJLevy

Thomas Gorham

Wei Jian Gan

Wei Jian Gan

Tamás Gulácsi

Jack Wilsdon

Michał Suchwałko

Alexander Apalikov

Domas Tamašauskas

Stéphane Chausson

neo_sli

neo_sli

@srdhoni

@derekhuizhang

le0tk0k

takaokanbe

Sean Schneeweiss

@connorszczepaniak-wk

pprzekwas

madflow

Arman Tarkhanian

@madflow

Axetroy

Arman Tarkhanian

John Adler

@licraft2019

@mlueckest

Malte Ehrlen

@golangaccount

Tyler Dorn

Dor

Enmanuel Moreira

@eiffel-fl

Sylvain Rabot

Thomas Bonfort

Piotr Persona

Han Gyoung-Su

Harry Tennent

Kamyar Mirzavaziri

@w1ck3dg0ph3r

Matthieu MOREL

Richard Yuh

Thomas Bonfort

Matthieu MOREL

Egor Kovetskiy

Jared Szechy

Wilhelm Ågren
diff --git a/assets/cli-help.json b/assets/cli-help.json new file mode 100644 index 000000000000..55d66d5ed021 --- /dev/null +++ b/assets/cli-help.json @@ -0,0 +1,5 @@ +{ + "enable": "Enabled by default linters:\nerrcheck: errcheck is a program for checking for unchecked errors in Go code. These unchecked errors can be critical bugs in some cases [fast: false, auto-fix: false]\ngosimple (megacheck): Linter for Go source code that specializes in simplifying code [fast: false, auto-fix: false]\ngovet (vet, vetshadow): Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string [fast: false, auto-fix: false]\nineffassign: Detects when assignments to existing variables are not used [fast: true, auto-fix: false]\nstaticcheck (megacheck): It's a set of rules from staticcheck. It's not the same thing as the staticcheck binary. The author of staticcheck doesn't support or approve the use of staticcheck as a library inside golangci-lint. [fast: false, auto-fix: false]\nunused (megacheck): Checks Go code for unused constants, variables, functions and types [fast: false, auto-fix: false]", + "disable": "Disabled by default linters:\nasasalint: check for pass []any as any in variadic func(...any) [fast: false, auto-fix: false]\nasciicheck: checks that all code identifiers does not have non-ASCII symbols in the name [fast: true, auto-fix: false]\nbidichk: Checks for dangerous unicode character sequences [fast: true, auto-fix: false]\nbodyclose: checks whether HTTP response body is closed successfully [fast: false, auto-fix: false]\ncontainedctx: containedctx is a linter that detects struct contained context.Context field [fast: false, auto-fix: false]\ncontextcheck: check whether the function uses a non-inherited context [fast: false, auto-fix: false]\ncyclop: checks function and package cyclomatic complexity [fast: false, auto-fix: false]\ndeadcode [deprecated]: Finds unused code [fast: false, auto-fix: false]\ndecorder: check declaration order and count of types, constants, variables and functions [fast: true, auto-fix: false]\ndepguard: Go linter that checks if package imports are in a list of acceptable packages [fast: true, auto-fix: false]\ndogsled: Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) [fast: true, auto-fix: false]\ndupl: Tool for code clone detection [fast: true, auto-fix: false]\ndupword: checks for duplicate words in the source code [fast: true, auto-fix: true]\ndurationcheck: check for two durations multiplied together [fast: false, auto-fix: false]\nerrchkjson: Checks types passed to the json encoding functions. Reports unsupported types and reports occations, where the check for the returned error can be omitted. [fast: false, auto-fix: false]\nerrname: Checks that sentinel errors are prefixed with the `Err` and error types are suffixed with the `Error`. [fast: false, auto-fix: false]\nerrorlint: errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13. [fast: false, auto-fix: false]\nexecinquery: execinquery is a linter about query string checker in Query function which reads your Go src files and warning it finds [fast: false, auto-fix: false]\nexhaustive: check exhaustiveness of enum switch statements [fast: false, auto-fix: false]\nexhaustivestruct [deprecated]: Checks if all struct's fields are initialized [fast: false, auto-fix: false]\nexhaustruct: Checks if all structure fields are initialized [fast: false, auto-fix: false]\nexportloopref: checks for pointers to enclosing loop variables [fast: false, auto-fix: false]\nforbidigo: Forbids identifiers [fast: false, auto-fix: false]\nforcetypeassert: finds forced type assertions [fast: true, auto-fix: false]\nfunlen: Tool for detection of long functions [fast: true, auto-fix: false]\ngci: Gci controls Go package import order and makes it always deterministic. [fast: true, auto-fix: false]\nginkgolinter: enforces standards of using ginkgo and gomega [fast: false, auto-fix: false]\ngocheckcompilerdirectives: Checks that go compiler directive comments (//go:) are valid. [fast: true, auto-fix: false]\ngochecknoglobals: check that no global variables exist [fast: false, auto-fix: false]\ngochecknoinits: Checks that no init functions are present in Go code [fast: true, auto-fix: false]\ngochecksumtype: Run exhaustiveness checks on Go \"sum types\" [fast: false, auto-fix: false]\ngocognit: Computes and checks the cognitive complexity of functions [fast: true, auto-fix: false]\ngoconst: Finds repeated strings that could be replaced by a constant [fast: true, auto-fix: false]\ngocritic: Provides diagnostics that check for bugs, performance and style issues. [fast: false, auto-fix: false]\ngocyclo: Computes and checks the cyclomatic complexity of functions [fast: true, auto-fix: false]\ngodot: Check if comments end in a period [fast: true, auto-fix: true]\ngodox: Tool for detection of FIXME, TODO and other comment keywords [fast: true, auto-fix: false]\ngoerr113: Go linter to check the errors handling expressions [fast: false, auto-fix: false]\ngofmt: Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification [fast: true, auto-fix: true]\ngofumpt: Gofumpt checks whether code was gofumpt-ed. [fast: true, auto-fix: true]\ngoheader: Checks is file header matches to pattern [fast: true, auto-fix: false]\ngoimports: Check import statements are formatted according to the 'goimport' command. Reformat imports in autofix mode. [fast: true, auto-fix: true]\ngolint [deprecated]: Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes [fast: false, auto-fix: false]\ngomnd: An analyzer to detect magic numbers. [fast: true, auto-fix: false]\ngomoddirectives: Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod. [fast: true, auto-fix: false]\ngomodguard: Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. [fast: true, auto-fix: false]\ngoprintffuncname: Checks that printf-like functions are named with `f` at the end. [fast: true, auto-fix: false]\ngosec (gas): Inspects source code for security problems [fast: false, auto-fix: false]\ngosmopolitan: Report certain i18n/l10n anti-patterns in your Go codebase [fast: false, auto-fix: false]\ngrouper: Analyze expression groups. [fast: true, auto-fix: false]\nifshort [deprecated]: Checks that your code uses short syntax for if-statements whenever possible. [fast: true, auto-fix: false]\nimportas: Enforces consistent import aliases [fast: false, auto-fix: false]\ninamedparam: reports interfaces with unnamed method parameters [fast: true, auto-fix: false]\ninterfacebloat: A linter that checks the number of methods inside an interface. [fast: true, auto-fix: false]\ninterfacer [deprecated]: Linter that suggests narrower interface types [fast: false, auto-fix: false]\nireturn: Accept Interfaces, Return Concrete Types [fast: false, auto-fix: false]\nlll: Reports long lines [fast: true, auto-fix: false]\nloggercheck (logrlint): Checks key value pairs for common logger libraries (kitlog,klog,logr,zap). [fast: false, auto-fix: false]\nmaintidx: maintidx measures the maintainability index of each function. [fast: true, auto-fix: false]\nmakezero: Finds slice declarations with non-zero initial length [fast: false, auto-fix: false]\nmaligned [deprecated]: Tool to detect Go structs that would take less memory if their fields were sorted [fast: false, auto-fix: false]\nmirror: reports wrong mirror patterns of bytes/strings usage [fast: false, auto-fix: false]\nmisspell: Finds commonly misspelled English words [fast: true, auto-fix: true]\nmusttag: enforce field tags in (un)marshaled structs [fast: false, auto-fix: false]\nnakedret: Checks that functions with naked returns are not longer than a maximum size (can be zero). [fast: true, auto-fix: false]\nnestif: Reports deeply nested if statements [fast: true, auto-fix: false]\nnilerr: Finds the code that returns nil even if it checks that the error is not nil. [fast: false, auto-fix: false]\nnilnil: Checks that there is no simultaneous return of `nil` error and an invalid value. [fast: false, auto-fix: false]\nnlreturn: nlreturn checks for a new line before return and branch statements to increase code clarity [fast: true, auto-fix: false]\nnoctx: Finds sending http request without context.Context [fast: false, auto-fix: false]\nnolintlint: Reports ill-formed or insufficient nolint directives [fast: true, auto-fix: false]\nnonamedreturns: Reports all named returns [fast: false, auto-fix: false]\nnosnakecase [deprecated]: nosnakecase is a linter that detects snake case of variable naming and function name. [fast: true, auto-fix: false]\nnosprintfhostport: Checks for misuse of Sprintf to construct a host with port in a URL. [fast: true, auto-fix: false]\nparalleltest: Detects missing usage of t.Parallel() method in your Go test [fast: false, auto-fix: false]\nperfsprint: Checks that fmt.Sprintf can be replaced with a faster alternative. [fast: false, auto-fix: false]\nprealloc: Finds slice declarations that could potentially be pre-allocated [fast: true, auto-fix: false]\npredeclared: find code that shadows one of Go's predeclared identifiers [fast: true, auto-fix: false]\npromlinter: Check Prometheus metrics naming via promlint [fast: true, auto-fix: false]\nprotogetter: Reports direct reads from proto message fields when getters should be used [fast: false, auto-fix: true]\nreassign: Checks that package variables are not reassigned [fast: false, auto-fix: false]\nrevive: Fast, configurable, extensible, flexible, and beautiful linter for Go. Drop-in replacement of golint. [fast: false, auto-fix: false]\nrowserrcheck: checks whether Rows.Err of rows is checked successfully [fast: false, auto-fix: false]\nscopelint [deprecated]: Scopelint checks for unpinned variables in go programs [fast: true, auto-fix: false]\nsloglint: ensure consistent code style when using log/slog [fast: false, auto-fix: false]\nspancheck: Checks for mistakes with OpenTelemetry/Census spans. [fast: false, auto-fix: false]\nsqlclosecheck: Checks that sql.Rows, sql.Stmt, sqlx.NamedStmt, pgx.Query are closed. [fast: false, auto-fix: false]\nstructcheck [deprecated]: Finds unused struct fields [fast: false, auto-fix: false]\nstylecheck: Stylecheck is a replacement for golint [fast: false, auto-fix: false]\ntagalign: check that struct tags are well aligned [fast: true, auto-fix: true]\ntagliatelle: Checks the struct tags. [fast: true, auto-fix: false]\ntenv: tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17 [fast: false, auto-fix: false]\ntestableexamples: linter checks if examples are testable (have an expected output) [fast: true, auto-fix: false]\ntestifylint: Checks usage of github.com/stretchr/testify. [fast: false, auto-fix: false]\ntestpackage: linter that makes you use a separate _test package [fast: true, auto-fix: false]\nthelper: thelper detects tests helpers which is not start with t.Helper() method. [fast: false, auto-fix: false]\ntparallel: tparallel detects inappropriate usage of t.Parallel() method in your Go test codes. [fast: false, auto-fix: false]\nunconvert: Remove unnecessary type conversions [fast: false, auto-fix: false]\nunparam: Reports unused function parameters [fast: false, auto-fix: false]\nusestdlibvars: A linter that detect the possibility to use variables/constants from the Go standard library. [fast: true, auto-fix: false]\nvarcheck [deprecated]: Finds unused global variables and constants [fast: false, auto-fix: false]\nvarnamelen: checks that the length of a variable's name matches its scope [fast: false, auto-fix: false]\nwastedassign: Finds wasted assignment statements [fast: false, auto-fix: false]\nwhitespace: Whitespace is a linter that checks for unnecessary newlines at the start and end of functions, if, for, etc. [fast: true, auto-fix: true]\nwrapcheck: Checks that errors returned from external packages are wrapped [fast: false, auto-fix: false]\nwsl: add or remove empty lines [fast: true, auto-fix: false]\nzerologlint: Detects the wrong usage of `zerolog` that a user forgets to dispatch with `Send` or `Msg` [fast: false, auto-fix: false]", + "help": "Usage:\n golangci-lint run [flags]\n\nFlags:\n -c, --config PATH Read config from file path PATH\n --no-config Don't read config file\n --out-format string Format of output: colored-line-number|line-number|json|tab|checkstyle|code-climate|html|junit-xml|github-actions|teamcity (default \"colored-line-number\")\n --print-issued-lines Print lines of code with issue (default true)\n --print-linter-name Print linter name in issue line (default true)\n --uniq-by-line Make issues output unique by line (default true)\n --sort-results Sort linter results\n --path-prefix string Path prefix to add to output\n --modules-download-mode string Modules download mode. If not empty, passed as -mod=\u003cmode\u003e to go tools\n --issues-exit-code int Exit code when issues were found (default 1)\n --go string Targeted Go version\n --build-tags strings Build tags\n --timeout duration Timeout for total work (default 1m0s)\n --tests Analyze tests (*_test.go) (default true)\n --print-resources-usage Print avg and max memory usage of golangci-lint and total time\n --skip-dirs strings Regexps of directories to skip\n --skip-dirs-use-default Use or not use default excluded directories:\n - (^|/)vendor($|/)\n - (^|/)third_party($|/)\n - (^|/)testdata($|/)\n - (^|/)examples($|/)\n - (^|/)Godeps($|/)\n - (^|/)builtin($|/)\n (default true)\n --skip-files strings Regexps of files to skip\n --allow-parallel-runners Allow multiple parallel golangci-lint instances running. If false (default) - golangci-lint acquires file lock on start.\n --allow-serial-runners Allow multiple golangci-lint instances running, but serialize them around a lock. If false (default) - golangci-lint exits with an error if it fails to acquire file lock on start.\n --show-stats Show statistics per linter\n -D, --disable strings Disable specific linter\n --disable-all Disable all linters\n -E, --enable strings Enable specific linter\n --enable-all Enable all linters\n --fast Enable only fast linters from enabled linters set (first run won't be fast)\n -p, --presets strings Enable presets (bugs|comment|complexity|error|format|import|metalinter|module|performance|sql|style|test|unused) of linters. Run 'golangci-lint help linters' to see them. This option implies option --disable-all\n -e, --exclude strings Exclude issue by regexp\n --exclude-use-default Use or not use default excludes:\n # EXC0001 errcheck: Almost all programs ignore errors on these functions and in most cases it's ok\n - Error return value of .((os\\.)?std(out|err)\\..*|.*Close|.*Flush|os\\.Remove(All)?|.*print(f|ln)?|os\\.(Un)?Setenv). is not checked\n \n # EXC0002 golint: Annoying issue about not having a comment. The rare codebase has such comments\n - (comment on exported (method|function|type|const)|should have( a package)? comment|comment should be of the form)\n \n # EXC0003 golint: False positive when tests are defined in package 'test'\n - func name will be used as test\\.Test.* by other packages, and that stutters; consider calling this\n \n # EXC0004 govet: Common false positives\n - (possible misuse of unsafe.Pointer|should have signature)\n \n # EXC0005 staticcheck: Developers tend to write in C-style with an explicit 'break' in a 'switch', so it's ok to ignore\n - ineffective break statement. Did you mean to break out of the outer loop\n \n # EXC0006 gosec: Too many false-positives on 'unsafe' usage\n - Use of unsafe calls should be audited\n \n # EXC0007 gosec: Too many false-positives for parametrized shell calls\n - Subprocess launch(ed with variable|ing should be audited)\n \n # EXC0008 gosec: Duplicated errcheck checks\n - (G104)\n \n # EXC0009 gosec: Too many issues in popular repos\n - (Expect directory permissions to be 0750 or less|Expect file permissions to be 0600 or less)\n \n # EXC0010 gosec: False positive is triggered by 'src, err := ioutil.ReadFile(filename)'\n - Potential file inclusion via variable\n \n # EXC0011 stylecheck: Annoying issue about not having a comment. The rare codebase has such comments\n - (comment on exported (method|function|type|const)|should have( a package)? comment|comment should be of the form)\n \n # EXC0012 revive: Annoying issue about not having a comment. The rare codebase has such comments\n - exported (.+) should have comment( \\(or a comment on this block\\))? or be unexported\n \n # EXC0013 revive: Annoying issue about not having a comment. The rare codebase has such comments\n - package comment should be of the form \"(.+)...\n \n # EXC0014 revive: Annoying issue about not having a comment. The rare codebase has such comments\n - comment on exported (.+) should be of the form \"(.+)...\"\n \n # EXC0015 revive: Annoying issue about not having a comment. The rare codebase has such comments\n - should have a package comment\n (default true)\n --exclude-case-sensitive If set to true exclude and exclude rules regular expressions are case sensitive\n --max-issues-per-linter int Maximum issues count per one linter. Set to 0 to disable (default 50)\n --max-same-issues int Maximum count of issues with the same text. Set to 0 to disable (default 3)\n -n, --new Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.\n It's a super-useful option for integration of golangci-lint into existing large codebase.\n It's not practical to fix all existing issues at the moment of integration: much better to not allow issues in new code.\n For CI setups, prefer --new-from-rev=HEAD~, as --new can skip linting the current patch if any scripts generate unstaged files before golangci-lint runs.\n --new-from-rev REV Show only new issues created after git revision REV\n --new-from-patch PATH Show only new issues created in git patch with file path PATH\n --whole-files Show issues in any part of update files (requires new-from-rev or new-from-patch)\n --fix Fix found issues (if it's supported by the linter)\n -h, --help help for run\n\nGlobal Flags:\n --color string Use color when printing; can be 'always', 'auto', or 'never' (default \"auto\")\n -j, --concurrency int Number of CPUs to use (Default: number of logical CPUs) (default 8)\n --cpu-profile-path string Path to CPU profile output file\n --mem-profile-path string Path to memory profile output file\n --trace-path string Path to trace output file\n -v, --verbose Verbose output\n --version Print version\n" +} diff --git a/assets/default-exclusions.json b/assets/default-exclusions.json new file mode 100644 index 000000000000..93f096dd6c5f --- /dev/null +++ b/assets/default-exclusions.json @@ -0,0 +1,92 @@ +[ + { + "id": "EXC0001", + "pattern": "Error return value of .((os\\.)?std(out|err)\\..*|.*Close|.*Flush|os\\.Remove(All)?|.*print(f|ln)?|os\\.(Un)?Setenv). is not checked", + "linter": "errcheck", + "why": "Almost all programs ignore errors on these functions and in most cases it's ok" + }, + { + "id": "EXC0002", + "pattern": "(comment on exported (method|function|type|const)|should have( a package)? comment|comment should be of the form)", + "linter": "golint", + "why": "Annoying issue about not having a comment. The rare codebase has such comments" + }, + { + "id": "EXC0003", + "pattern": "func name will be used as test\\.Test.* by other packages, and that stutters; consider calling this", + "linter": "golint", + "why": "False positive when tests are defined in package 'test'" + }, + { + "id": "EXC0004", + "pattern": "(possible misuse of unsafe.Pointer|should have signature)", + "linter": "govet", + "why": "Common false positives" + }, + { + "id": "EXC0005", + "pattern": "ineffective break statement. Did you mean to break out of the outer loop", + "linter": "staticcheck", + "why": "Developers tend to write in C-style with an explicit 'break' in a 'switch', so it's ok to ignore" + }, + { + "id": "EXC0006", + "pattern": "Use of unsafe calls should be audited", + "linter": "gosec", + "why": "Too many false-positives on 'unsafe' usage" + }, + { + "id": "EXC0007", + "pattern": "Subprocess launch(ed with variable|ing should be audited)", + "linter": "gosec", + "why": "Too many false-positives for parametrized shell calls" + }, + { + "id": "EXC0008", + "pattern": "(G104)", + "linter": "gosec", + "why": "Duplicated errcheck checks" + }, + { + "id": "EXC0009", + "pattern": "(Expect directory permissions to be 0750 or less|Expect file permissions to be 0600 or less)", + "linter": "gosec", + "why": "Too many issues in popular repos" + }, + { + "id": "EXC0010", + "pattern": "Potential file inclusion via variable", + "linter": "gosec", + "why": "False positive is triggered by 'src, err := ioutil.ReadFile(filename)'" + }, + { + "id": "EXC0011", + "pattern": "(comment on exported (method|function|type|const)|should have( a package)? comment|comment should be of the form)", + "linter": "stylecheck", + "why": "Annoying issue about not having a comment. The rare codebase has such comments" + }, + { + "id": "EXC0012", + "pattern": "exported (.+) should have comment( \\(or a comment on this block\\))? or be unexported", + "linter": "revive", + "why": "Annoying issue about not having a comment. The rare codebase has such comments" + }, + { + "id": "EXC0013", + "pattern": "package comment should be of the form \"(.+)...", + "linter": "revive", + "why": "Annoying issue about not having a comment. The rare codebase has such comments" + }, + { + "id": "EXC0014", + "pattern": "comment on exported (.+) should be of the form \"(.+)...\"", + "linter": "revive", + "why": "Annoying issue about not having a comment. The rare codebase has such comments" + }, + { + "id": "EXC0015", + "pattern": "should have a package comment", + "linter": "revive", + "why": "Annoying issue about not having a comment. The rare codebase has such comments" + } +] diff --git a/assets/github-action-config.json b/assets/github-action-config.json index ce268e86a757..f2a5227b446c 100644 --- a/assets/github-action-config.json +++ b/assets/github-action-config.json @@ -1,8 +1,8 @@ { "MinorVersionToConfig": { "latest": { - "TargetVersion": "v1.51.1", - "AssetURL": "https://github.com/golangci/golangci-lint/releases/download/v1.51.1/golangci-lint-1.51.1-linux-amd64.tar.gz" + "TargetVersion": "v1.56.2", + "AssetURL": "https://github.com/golangci/golangci-lint/releases/download/v1.56.2/golangci-lint-1.56.2-linux-amd64.tar.gz" }, "v1.10": { "Error": "golangci-lint version 'v1.10' isn't supported: we support only v1.14.0 and later versions" @@ -174,8 +174,28 @@ "AssetURL": "https://github.com/golangci/golangci-lint/releases/download/v1.50.1/golangci-lint-1.50.1-linux-amd64.tar.gz" }, "v1.51": { - "TargetVersion": "v1.51.1", - "AssetURL": "https://github.com/golangci/golangci-lint/releases/download/v1.51.1/golangci-lint-1.51.1-linux-amd64.tar.gz" + "TargetVersion": "v1.51.2", + "AssetURL": "https://github.com/golangci/golangci-lint/releases/download/v1.51.2/golangci-lint-1.51.2-linux-amd64.tar.gz" + }, + "v1.52": { + "TargetVersion": "v1.52.2", + "AssetURL": "https://github.com/golangci/golangci-lint/releases/download/v1.52.2/golangci-lint-1.52.2-linux-amd64.tar.gz" + }, + "v1.53": { + "TargetVersion": "v1.53.3", + "AssetURL": "https://github.com/golangci/golangci-lint/releases/download/v1.53.3/golangci-lint-1.53.3-linux-amd64.tar.gz" + }, + "v1.54": { + "TargetVersion": "v1.54.2", + "AssetURL": "https://github.com/golangci/golangci-lint/releases/download/v1.54.2/golangci-lint-1.54.2-linux-amd64.tar.gz" + }, + "v1.55": { + "TargetVersion": "v1.55.2", + "AssetURL": "https://github.com/golangci/golangci-lint/releases/download/v1.55.2/golangci-lint-1.55.2-linux-amd64.tar.gz" + }, + "v1.56": { + "TargetVersion": "v1.56.2", + "AssetURL": "https://github.com/golangci/golangci-lint/releases/download/v1.56.2/golangci-lint-1.56.2-linux-amd64.tar.gz" }, "v1.6": { "Error": "golangci-lint version 'v1.6' isn't supported: we support only v1.14.0 and later versions" diff --git a/assets/linters-info.json b/assets/linters-info.json new file mode 100644 index 000000000000..eab346ceed01 --- /dev/null +++ b/assets/linters-info.json @@ -0,0 +1,1600 @@ +[ + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "bugs" + ], + "originalURL": "https://github.com/alingse/asasalint", + "internal": false, + "isSlow": true, + "since": "1.47.0", + "name": "asasalint", + "desc": "check for pass []any as any in variadic func(...any)" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "bugs", + "style" + ], + "originalURL": "https://github.com/tdakkota/asciicheck", + "internal": false, + "isSlow": false, + "since": "v1.26.0", + "name": "asciicheck", + "desc": "checks that all code identifiers does not have non-ASCII symbols in the name" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "bugs" + ], + "originalURL": "https://github.com/breml/bidichk", + "internal": false, + "isSlow": false, + "since": "1.43.0", + "name": "bidichk", + "desc": "Checks for dangerous unicode character sequences" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "performance", + "bugs" + ], + "originalURL": "https://github.com/timakin/bodyclose", + "internal": false, + "isSlow": true, + "since": "v1.18.0", + "name": "bodyclose", + "desc": "checks whether HTTP response body is closed successfully" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/sivchari/containedctx", + "internal": false, + "isSlow": true, + "since": "1.44.0", + "name": "containedctx", + "desc": "containedctx is a linter that detects struct contained context.Context field" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "bugs" + ], + "originalURL": "https://github.com/kkHAIKE/contextcheck", + "internal": false, + "isSlow": true, + "since": "v1.43.0", + "name": "contextcheck", + "desc": "check whether the function uses a non-inherited context" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "complexity" + ], + "originalURL": "https://github.com/bkielbasa/cyclop", + "internal": false, + "isSlow": true, + "since": "v1.37.0", + "name": "cyclop", + "desc": "checks function and package cyclomatic complexity" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "format", + "style" + ], + "originalURL": "https://gitlab.com/bosi/decorder", + "internal": false, + "isSlow": false, + "since": "v1.44.0", + "name": "decorder", + "desc": "check declaration order and count of types, constants, variables and functions" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "unused" + ], + "originalURL": "https://github.com/remyoudompheng/go-misc/tree/master/deadcode", + "internal": false, + "isSlow": true, + "since": "v1.0.0", + "deprecation": { + "since": "v1.49.0", + "message": "The owner seems to have abandoned the linter.", + "replacement": "unused" + }, + "name": "deadcode", + "desc": "Finds unused code" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style", + "import", + "module" + ], + "originalURL": "https://github.com/OpenPeeDeeP/depguard", + "internal": false, + "isSlow": false, + "since": "v1.4.0", + "name": "depguard", + "desc": "Go linter that checks if package imports are in a list of acceptable packages" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/alexkohler/dogsled", + "internal": false, + "isSlow": false, + "since": "v1.19.0", + "name": "dogsled", + "desc": "Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f())" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/mibk/dupl", + "internal": false, + "isSlow": false, + "since": "v1.0.0", + "name": "dupl", + "desc": "Tool for code clone detection" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "comment" + ], + "originalURL": "https://github.com/Abirdcfly/dupword", + "internal": false, + "canAutoFix": true, + "isSlow": false, + "since": "1.50.0", + "name": "dupword", + "desc": "checks for duplicate words in the source code" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "bugs" + ], + "originalURL": "https://github.com/charithe/durationcheck", + "internal": false, + "isSlow": true, + "since": "v1.37.0", + "name": "durationcheck", + "desc": "check for two durations multiplied together" + }, + { + "linter": {}, + "enabledByDefault": true, + "loadMode": 575, + "inPresets": [ + "bugs", + "error" + ], + "originalURL": "https://github.com/kisielk/errcheck", + "internal": false, + "isSlow": true, + "since": "v1.0.0", + "name": "errcheck", + "desc": "errcheck is a program for checking for unchecked errors in Go code. These unchecked errors can be critical bugs in some cases" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "bugs" + ], + "originalURL": "https://github.com/breml/errchkjson", + "internal": false, + "isSlow": true, + "since": "1.44.0", + "name": "errchkjson", + "desc": "Checks types passed to the json encoding functions. Reports unsupported types and reports occations, where the check for the returned error can be omitted." + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/Antonboom/errname", + "internal": false, + "isSlow": true, + "since": "v1.42.0", + "name": "errname", + "desc": "Checks that sentinel errors are prefixed with the `Err` and error types are suffixed with the `Error`." + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "bugs", + "error" + ], + "originalURL": "https://github.com/polyfloyd/go-errorlint", + "internal": false, + "isSlow": true, + "since": "v1.32.0", + "name": "errorlint", + "desc": "errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13." + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "sql" + ], + "originalURL": "https://github.com/lufeee/execinquery", + "internal": false, + "isSlow": true, + "since": "v1.46.0", + "name": "execinquery", + "desc": "execinquery is a linter about query string checker in Query function which reads your Go src files and warning it finds" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "bugs" + ], + "originalURL": "https://github.com/nishanths/exhaustive", + "internal": false, + "isSlow": true, + "since": " v1.28.0", + "name": "exhaustive", + "desc": "check exhaustiveness of enum switch statements" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "style", + "test" + ], + "originalURL": "https://github.com/mbilski/exhaustivestruct", + "internal": false, + "isSlow": true, + "since": "v1.32.0", + "deprecation": { + "since": "v1.46.0", + "message": "The owner seems to have abandoned the linter.", + "replacement": "exhaustruct" + }, + "name": "exhaustivestruct", + "desc": "Checks if all struct's fields are initialized" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "style", + "test" + ], + "originalURL": "https://github.com/GaijinEntertainment/go-exhaustruct", + "internal": false, + "isSlow": true, + "since": "v1.46.0", + "name": "exhaustruct", + "desc": "Checks if all structure fields are initialized" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "bugs" + ], + "originalURL": "https://github.com/kyoh86/exportloopref", + "internal": false, + "isSlow": true, + "since": "v1.28.0", + "name": "exportloopref", + "desc": "checks for pointers to enclosing loop variables" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/ashanbrown/forbidigo", + "internal": false, + "isSlow": true, + "since": "v1.34.0", + "name": "forbidigo", + "desc": "Forbids identifiers" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/gostaticanalysis/forcetypeassert", + "internal": false, + "isSlow": false, + "since": "v1.38.0", + "name": "forcetypeassert", + "desc": "finds forced type assertions" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "complexity" + ], + "originalURL": "https://github.com/ultraware/funlen", + "internal": false, + "isSlow": false, + "since": "v1.18.0", + "name": "funlen", + "desc": "Tool for detection of long functions" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "format", + "import" + ], + "originalURL": "https://github.com/daixiang0/gci", + "internal": false, + "isSlow": false, + "since": "v1.30.0", + "name": "gci", + "desc": "Gci controls Go package import order and makes it always deterministic." + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/nunnatsa/ginkgolinter", + "internal": false, + "isSlow": true, + "since": "v1.51.0", + "name": "ginkgolinter", + "desc": "enforces standards of using ginkgo and gomega" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "bugs" + ], + "originalURL": "https://github.com/leighmcculloch/gocheckcompilerdirectives", + "internal": false, + "isSlow": false, + "since": "v1.51.0", + "name": "gocheckcompilerdirectives", + "desc": "Checks that go compiler directive comments (//go:) are valid." + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/leighmcculloch/gochecknoglobals", + "internal": false, + "isSlow": true, + "since": "v1.12.0", + "name": "gochecknoglobals", + "desc": "check that no global variables exist\n\nThis analyzer checks for global variables and errors on any found.\n\nA global variable is a variable declared in package scope and that can be read\nand written to by any function within the package. Global variables can cause\nside effects which are difficult to keep track of. A code in one function may\nchange the variables state while another unrelated chunk of code may be\neffected by it." + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style" + ], + "internal": false, + "isSlow": false, + "since": "v1.12.0", + "name": "gochecknoinits", + "desc": "Checks that no init functions are present in Go code" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "bugs" + ], + "originalURL": "https://github.com/alecthomas/go-check-sumtype", + "internal": false, + "isSlow": true, + "since": "v1.55.0", + "name": "gochecksumtype", + "desc": "Run exhaustiveness checks on Go \"sum types\"" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "complexity" + ], + "originalURL": "https://github.com/uudashr/gocognit", + "internal": false, + "isSlow": false, + "since": "v1.20.0", + "name": "gocognit", + "desc": "Computes and checks the cognitive complexity of functions" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/jgautheron/goconst", + "internal": false, + "isSlow": false, + "since": "v1.0.0", + "name": "goconst", + "desc": "Finds repeated strings that could be replaced by a constant" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "style", + "metalinter" + ], + "originalURL": "https://github.com/go-critic/go-critic", + "internal": false, + "isSlow": true, + "since": "v1.12.0", + "name": "gocritic", + "desc": "Provides diagnostics that check for bugs, performance and style issues.\nExtensible without recompilation through dynamic rules.\nDynamic rules are written declaratively with AST patterns, filters, report message and optional suggestion." + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "complexity" + ], + "originalURL": "https://github.com/fzipp/gocyclo", + "internal": false, + "isSlow": false, + "since": "v1.0.0", + "name": "gocyclo", + "desc": "Computes and checks the cyclomatic complexity of functions" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style", + "comment" + ], + "originalURL": "https://github.com/tetafro/godot", + "internal": false, + "canAutoFix": true, + "isSlow": false, + "since": "v1.25.0", + "name": "godot", + "desc": "Check if comments end in a period" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style", + "comment" + ], + "originalURL": "https://github.com/matoous/godox", + "internal": false, + "isSlow": false, + "since": "v1.19.0", + "name": "godox", + "desc": "Tool for detection of FIXME, TODO and other comment keywords" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "style", + "error" + ], + "originalURL": "https://github.com/Djarvur/go-err113", + "internal": false, + "isSlow": true, + "since": "v1.26.0", + "name": "goerr113", + "desc": "Go linter to check the errors handling expressions" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "format" + ], + "originalURL": "https://pkg.go.dev/cmd/gofmt", + "internal": false, + "canAutoFix": true, + "isSlow": false, + "since": "v1.0.0", + "name": "gofmt", + "desc": "Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "format" + ], + "originalURL": "https://github.com/mvdan/gofumpt", + "internal": false, + "canAutoFix": true, + "isSlow": false, + "since": "v1.28.0", + "name": "gofumpt", + "desc": "Gofumpt checks whether code was gofumpt-ed." + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/denis-tingaikin/go-header", + "internal": false, + "isSlow": false, + "since": "v1.28.0", + "name": "goheader", + "desc": "Checks is file header matches to pattern" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "format", + "import" + ], + "originalURL": "https://pkg.go.dev/golang.org/x/tools/cmd/goimports", + "internal": false, + "canAutoFix": true, + "isSlow": false, + "since": "v1.20.0", + "name": "goimports", + "desc": "Check import statements are formatted according to the 'goimport' command. Reformat imports in autofix mode." + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/golang/lint", + "internal": false, + "isSlow": true, + "since": "v1.0.0", + "deprecation": { + "since": "v1.41.0", + "message": "The repository of the linter has been archived by the owner.", + "replacement": "revive" + }, + "name": "golint", + "desc": "Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/tommy-muehle/go-mnd", + "internal": false, + "isSlow": false, + "since": "v1.22.0", + "name": "gomnd", + "desc": "An analyzer to detect magic numbers." + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style", + "module" + ], + "originalURL": "https://github.com/ldez/gomoddirectives", + "internal": false, + "isSlow": false, + "since": "v1.39.0", + "name": "gomoddirectives", + "desc": "Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod." + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style", + "import", + "module" + ], + "originalURL": "https://github.com/ryancurrah/gomodguard", + "internal": false, + "isSlow": false, + "since": "v1.25.0", + "name": "gomodguard", + "desc": "Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations." + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/jirfag/go-printf-func-name", + "internal": false, + "isSlow": false, + "since": "v1.23.0", + "name": "goprintffuncname", + "desc": "Checks that printf-like functions are named with `f` at the end." + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "bugs" + ], + "alternativeNames": [ + "gas" + ], + "originalURL": "https://github.com/securego/gosec", + "internal": false, + "isSlow": true, + "since": "v1.0.0", + "name": "gosec", + "desc": "Inspects source code for security problems" + }, + { + "linter": {}, + "enabledByDefault": true, + "loadMode": 575, + "inPresets": [ + "style" + ], + "alternativeNames": [ + "megacheck" + ], + "originalURL": "https://github.com/dominikh/go-tools/tree/master/simple", + "internal": false, + "isSlow": true, + "since": "v1.20.0", + "name": "gosimple", + "desc": "Linter for Go source code that specializes in simplifying code" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "bugs" + ], + "originalURL": "https://github.com/xen0n/gosmopolitan", + "internal": false, + "isSlow": true, + "since": "v1.53.0", + "name": "gosmopolitan", + "desc": "Report certain i18n/l10n anti-patterns in your Go codebase" + }, + { + "linter": {}, + "enabledByDefault": true, + "loadMode": 575, + "inPresets": [ + "bugs", + "metalinter" + ], + "alternativeNames": [ + "vet", + "vetshadow" + ], + "originalURL": "https://pkg.go.dev/cmd/vet", + "internal": false, + "isSlow": true, + "since": "v1.0.0", + "name": "govet", + "desc": "Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/leonklingele/grouper", + "internal": false, + "isSlow": false, + "since": "v1.44.0", + "name": "grouper", + "desc": "Analyze expression groups." + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/esimonov/ifshort", + "internal": false, + "isSlow": false, + "since": "v1.36.0", + "deprecation": { + "since": "v1.48.0", + "message": "The repository of the linter has been deprecated by the owner." + }, + "name": "ifshort", + "desc": "Checks that your code uses short syntax for if-statements whenever possible." + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/julz/importas", + "internal": false, + "isSlow": true, + "since": "v1.38.0", + "name": "importas", + "desc": "Enforces consistent import aliases" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/macabu/inamedparam", + "internal": false, + "isSlow": false, + "since": "v1.55.0", + "name": "inamedparam", + "desc": "reports interfaces with unnamed method parameters" + }, + { + "linter": {}, + "enabledByDefault": true, + "loadMode": 7, + "inPresets": [ + "unused" + ], + "originalURL": "https://github.com/gordonklaus/ineffassign", + "internal": false, + "isSlow": false, + "since": "v1.0.0", + "name": "ineffassign", + "desc": "Detects when assignments to existing variables are not used" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/sashamelentyev/interfacebloat", + "internal": false, + "isSlow": false, + "since": "v1.49.0", + "name": "interfacebloat", + "desc": "A linter that checks the number of methods inside an interface." + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/mvdan/interfacer", + "internal": false, + "isSlow": true, + "since": "v1.0.0", + "deprecation": { + "since": "v1.38.0", + "message": "The repository of the linter has been archived by the owner." + }, + "name": "interfacer", + "desc": "Linter that suggests narrower interface types" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/butuzov/ireturn", + "internal": false, + "isSlow": true, + "since": "v1.43.0", + "name": "ireturn", + "desc": "Accept Interfaces, Return Concrete Types" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style" + ], + "internal": false, + "isSlow": false, + "since": "v1.8.0", + "name": "lll", + "desc": "Reports long lines" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "style", + "bugs" + ], + "alternativeNames": [ + "logrlint" + ], + "originalURL": "https://github.com/timonwong/loggercheck", + "internal": false, + "isSlow": true, + "since": "v1.49.0", + "name": "loggercheck", + "desc": "Checks key value pairs for common logger libraries (kitlog,klog,logr,zap)." + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "complexity" + ], + "originalURL": "https://github.com/yagipy/maintidx", + "internal": false, + "isSlow": false, + "since": "v1.44.0", + "name": "maintidx", + "desc": "maintidx measures the maintainability index of each function." + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "style", + "bugs" + ], + "originalURL": "https://github.com/ashanbrown/makezero", + "internal": false, + "isSlow": true, + "since": "v1.34.0", + "name": "makezero", + "desc": "Finds slice declarations with non-zero initial length" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "performance" + ], + "originalURL": "https://github.com/mdempsky/maligned", + "internal": false, + "isSlow": true, + "since": "v1.0.0", + "deprecation": { + "since": "v1.38.0", + "message": "The repository of the linter has been archived by the owner.", + "replacement": "govet 'fieldalignment'" + }, + "name": "maligned", + "desc": "Tool to detect Go structs that would take less memory if their fields were sorted" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/butuzov/mirror", + "internal": false, + "isSlow": true, + "since": "v1.53.0", + "name": "mirror", + "desc": "reports wrong mirror patterns of bytes/strings usage" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style", + "comment" + ], + "originalURL": "https://github.com/client9/misspell", + "internal": false, + "canAutoFix": true, + "isSlow": false, + "since": "v1.8.0", + "name": "misspell", + "desc": "Finds commonly misspelled English words" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "style", + "bugs" + ], + "originalURL": "https://github.com/go-simpler/musttag", + "internal": false, + "isSlow": true, + "since": "v1.51.0", + "name": "musttag", + "desc": "enforce field tags in (un)marshaled structs" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/alexkohler/nakedret", + "internal": false, + "isSlow": false, + "since": "v1.19.0", + "name": "nakedret", + "desc": "Checks that functions with naked returns are not longer than a maximum size (can be zero)." + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "complexity" + ], + "originalURL": "https://github.com/nakabonne/nestif", + "internal": false, + "isSlow": false, + "since": "v1.25.0", + "name": "nestif", + "desc": "Reports deeply nested if statements" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "bugs" + ], + "originalURL": "https://github.com/gostaticanalysis/nilerr", + "internal": false, + "isSlow": true, + "since": "v1.38.0", + "name": "nilerr", + "desc": "Finds the code that returns nil even if it checks that the error is not nil." + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/Antonboom/nilnil", + "internal": false, + "isSlow": true, + "since": "v1.43.0", + "name": "nilnil", + "desc": "Checks that there is no simultaneous return of `nil` error and an invalid value." + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/ssgreg/nlreturn", + "internal": false, + "isSlow": false, + "since": "v1.30.0", + "name": "nlreturn", + "desc": "nlreturn checks for a new line before return and branch statements to increase code clarity" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "performance", + "bugs" + ], + "originalURL": "https://github.com/sonatard/noctx", + "internal": false, + "isSlow": true, + "since": "v1.28.0", + "name": "noctx", + "desc": "Finds sending http request without context.Context" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/firefart/nonamedreturns", + "internal": false, + "isSlow": true, + "since": "v1.46.0", + "name": "nonamedreturns", + "desc": "Reports all named returns" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/sivchari/nosnakecase", + "internal": false, + "isSlow": false, + "since": "v1.47.0", + "deprecation": { + "since": "v1.48.1", + "message": "The repository of the linter has been deprecated by the owner.", + "replacement": "revive(var-naming)" + }, + "name": "nosnakecase", + "desc": "nosnakecase is a linter that detects snake case of variable naming and function name." + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/stbenjam/no-sprintf-host-port", + "internal": false, + "isSlow": false, + "since": "v1.46.0", + "name": "nosprintfhostport", + "desc": "Checks for misuse of Sprintf to construct a host with port in a URL." + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "style", + "test" + ], + "originalURL": "https://github.com/kunwardeep/paralleltest", + "internal": false, + "isSlow": true, + "since": "v1.33.0", + "name": "paralleltest", + "desc": "Detects missing usage of t.Parallel() method in your Go test" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "performance" + ], + "originalURL": "https://github.com/catenacyber/perfsprint", + "internal": false, + "isSlow": true, + "since": "v1.55.0", + "name": "perfsprint", + "desc": "Checks that fmt.Sprintf can be replaced with a faster alternative." + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "performance" + ], + "originalURL": "https://github.com/alexkohler/prealloc", + "internal": false, + "isSlow": false, + "since": "v1.19.0", + "name": "prealloc", + "desc": "Finds slice declarations that could potentially be pre-allocated" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/nishanths/predeclared", + "internal": false, + "isSlow": false, + "since": "v1.35.0", + "name": "predeclared", + "desc": "find code that shadows one of Go's predeclared identifiers" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/yeya24/promlinter", + "internal": false, + "isSlow": false, + "since": "v1.40.0", + "name": "promlinter", + "desc": "Check Prometheus metrics naming via promlint" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "bugs" + ], + "originalURL": "https://github.com/ghostiam/protogetter", + "internal": false, + "canAutoFix": true, + "isSlow": true, + "since": "v1.55.0", + "name": "protogetter", + "desc": "Reports direct reads from proto message fields when getters should be used" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "bugs" + ], + "originalURL": "https://github.com/curioswitch/go-reassign", + "internal": false, + "isSlow": true, + "since": "1.49.0", + "name": "reassign", + "desc": "Checks that package variables are not reassigned" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style", + "metalinter" + ], + "originalURL": "https://github.com/mgechev/revive", + "internal": false, + "isSlow": true, + "since": "v1.37.0", + "name": "revive", + "desc": "Fast, configurable, extensible, flexible, and beautiful linter for Go. Drop-in replacement of golint." + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "bugs", + "sql" + ], + "originalURL": "https://github.com/jingyugao/rowserrcheck", + "internal": false, + "isSlow": true, + "since": "v1.23.0", + "name": "rowserrcheck", + "desc": "checks whether Rows.Err of rows is checked successfully" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "style", + "format" + ], + "originalURL": "https://github.com/go-simpler/sloglint", + "internal": false, + "isSlow": true, + "since": "v1.55.0", + "name": "sloglint", + "desc": "ensure consistent code style when using log/slog" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "bugs" + ], + "originalURL": "https://github.com/kyoh86/scopelint", + "internal": false, + "isSlow": false, + "since": "v1.12.0", + "deprecation": { + "since": "v1.39.0", + "message": "The repository of the linter has been deprecated by the owner.", + "replacement": "exportloopref" + }, + "name": "scopelint", + "desc": "Scopelint checks for unpinned variables in go programs" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "bugs", + "sql" + ], + "originalURL": "https://github.com/ryanrolds/sqlclosecheck", + "internal": false, + "isSlow": true, + "since": "v1.28.0", + "name": "sqlclosecheck", + "desc": "Checks that sql.Rows, sql.Stmt, sqlx.NamedStmt, pgx.Query are closed." + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "bugs" + ], + "originalURL": "https://github.com/jjti/go-spancheck", + "internal": false, + "isSlow": true, + "since": "v1.56.0", + "name": "spancheck", + "desc": "Checks for mistakes with OpenTelemetry/Census spans." + }, + { + "linter": {}, + "enabledByDefault": true, + "loadMode": 575, + "inPresets": [ + "bugs", + "metalinter" + ], + "alternativeNames": [ + "megacheck" + ], + "originalURL": "https://staticcheck.io/", + "internal": false, + "isSlow": true, + "since": "v1.0.0", + "name": "staticcheck", + "desc": "It's a set of rules from staticcheck. It's not the same thing as the staticcheck binary. The author of staticcheck doesn't support or approve the use of staticcheck as a library inside golangci-lint." + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "unused" + ], + "originalURL": "https://github.com/opennota/check", + "internal": false, + "isSlow": true, + "since": "v1.0.0", + "deprecation": { + "since": "v1.49.0", + "message": "The owner seems to have abandoned the linter.", + "replacement": "unused" + }, + "name": "structcheck", + "desc": "Finds unused struct fields" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/dominikh/go-tools/tree/master/stylecheck", + "internal": false, + "isSlow": true, + "since": "v1.20.0", + "name": "stylecheck", + "desc": "Stylecheck is a replacement for golint" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style", + "format" + ], + "originalURL": "https://github.com/4meepo/tagalign", + "internal": false, + "canAutoFix": true, + "isSlow": false, + "since": "v1.53.0", + "name": "tagalign", + "desc": "check that struct tags are well aligned" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/ldez/tagliatelle", + "internal": false, + "isSlow": false, + "since": "v1.40.0", + "name": "tagliatelle", + "desc": "Checks the struct tags." + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/sivchari/tenv", + "internal": false, + "isSlow": true, + "since": "v1.43.0", + "name": "tenv", + "desc": "tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "test" + ], + "originalURL": "https://github.com/maratori/testableexamples", + "internal": false, + "isSlow": false, + "since": "v1.50.0", + "name": "testableexamples", + "desc": "linter checks if examples are testable (have an expected output)" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "test", + "bugs" + ], + "originalURL": "https://github.com/Antonboom/testifylint", + "internal": false, + "isSlow": true, + "since": "v1.55.0", + "name": "testifylint", + "desc": "Checks usage of github.com/stretchr/testify." + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style", + "test" + ], + "originalURL": "https://github.com/maratori/testpackage", + "internal": false, + "isSlow": false, + "since": "v1.25.0", + "name": "testpackage", + "desc": "linter that makes you use a separate _test package" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/kulti/thelper", + "internal": false, + "isSlow": true, + "since": "v1.34.0", + "name": "thelper", + "desc": "thelper detects tests helpers which is not start with t.Helper() method." + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "style", + "test" + ], + "originalURL": "https://github.com/moricho/tparallel", + "internal": false, + "isSlow": true, + "since": "v1.32.0", + "name": "tparallel", + "desc": "tparallel detects inappropriate usage of t.Parallel() method in your Go test codes." + }, + { + "linter": {}, + "enabledByDefault": true, + "loadMode": 575, + "inPresets": [ + "bugs" + ], + "internal": true, + "isSlow": true, + "since": "v1.3.0", + "name": "typecheck", + "desc": "Like the front-end of a Go compiler, parses and type-checks Go code" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/mdempsky/unconvert", + "internal": false, + "isSlow": true, + "since": "v1.0.0", + "name": "unconvert", + "desc": "Remove unnecessary type conversions" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "unused" + ], + "originalURL": "https://github.com/mvdan/unparam", + "internal": false, + "isSlow": true, + "since": "v1.9.0", + "name": "unparam", + "desc": "Reports unused function parameters" + }, + { + "linter": {}, + "enabledByDefault": true, + "loadMode": 575, + "inPresets": [ + "unused" + ], + "alternativeNames": [ + "megacheck" + ], + "originalURL": "https://github.com/dominikh/go-tools/tree/master/unused", + "internal": false, + "isSlow": true, + "doesChangeTypes": true, + "since": "v1.20.0", + "name": "unused", + "desc": "Checks Go code for unused constants, variables, functions and types" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/sashamelentyev/usestdlibvars", + "internal": false, + "isSlow": false, + "since": "v1.48.0", + "name": "usestdlibvars", + "desc": "A linter that detect the possibility to use variables/constants from the Go standard library." + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "unused" + ], + "originalURL": "https://github.com/opennota/check", + "internal": false, + "isSlow": true, + "since": "v1.0.0", + "deprecation": { + "since": "v1.49.0", + "message": "The owner seems to have abandoned the linter.", + "replacement": "unused" + }, + "name": "varcheck", + "desc": "Finds unused global variables and constants" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/blizzy78/varnamelen", + "internal": false, + "isSlow": true, + "since": "v1.43.0", + "name": "varnamelen", + "desc": "checks that the length of a variable's name matches its scope" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/sanposhiho/wastedassign", + "internal": false, + "isSlow": true, + "since": "v1.38.0", + "name": "wastedassign", + "desc": "Finds wasted assignment statements" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/ultraware/whitespace", + "internal": false, + "canAutoFix": true, + "isSlow": false, + "since": "v1.19.0", + "name": "whitespace", + "desc": "Whitespace is a linter that checks for unnecessary newlines at the start and end of functions, if, for, etc." + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "style", + "error" + ], + "originalURL": "https://github.com/tomarrell/wrapcheck", + "internal": false, + "isSlow": true, + "since": "v1.32.0", + "name": "wrapcheck", + "desc": "Checks that errors returned from external packages are wrapped" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/bombsimon/wsl", + "internal": false, + "isSlow": false, + "since": "v1.20.0", + "name": "wsl", + "desc": "add or remove empty lines" + }, + { + "linter": {}, + "loadMode": 575, + "inPresets": [ + "bugs" + ], + "originalURL": "https://github.com/ykadowak/zerologlint", + "internal": false, + "isSlow": true, + "since": "v1.53.0", + "name": "zerologlint", + "desc": "Detects the wrong usage of `zerolog` that a user forgets to dispatch with `Send` or `Msg`" + }, + { + "linter": {}, + "loadMode": 7, + "inPresets": [ + "style" + ], + "originalURL": "https://github.com/golangci/golangci-lint/blob/master/pkg/golinters/nolintlint/README.md", + "internal": false, + "isSlow": false, + "since": "v1.26.0", + "name": "nolintlint", + "desc": "Reports ill-formed or insufficient nolint directives" + } +] diff --git a/build/Dockerfile b/build/Dockerfile deleted file mode 100644 index 3488446b7c71..000000000000 --- a/build/Dockerfile +++ /dev/null @@ -1,18 +0,0 @@ -# stage 1 building the code -FROM golang:1.20 as builder - -ARG VERSION -ARG SHORT_COMMIT -ARG DATE - -COPY / /golangci -WORKDIR /golangci -RUN CGO_ENABLED=0 go build -trimpath -ldflags "-s -w -X main.version=$VERSION -X main.commit=$SHORT_COMMIT -X main.date=$DATE" -o golangci-lint ./cmd/golangci-lint/main.go - -# stage 2 -FROM golang:1.20 -# related to https://github.com/golangci/golangci-lint/issues/3107 -ENV GOROOT /usr/local/go -# don't place it into $GOPATH/bin because Drone mounts $GOPATH as volume -COPY --from=builder /golangci/golangci-lint /usr/bin/ -CMD ["golangci-lint"] diff --git a/build/alpine.Dockerfile b/build/alpine.Dockerfile deleted file mode 100644 index 5eeb76228de2..000000000000 --- a/build/alpine.Dockerfile +++ /dev/null @@ -1,27 +0,0 @@ -# stage 1 building the code -FROM golang:1.20-alpine as builder - -ARG VERSION -ARG SHORT_COMMIT -ARG DATE - -COPY / /golangci -WORKDIR /golangci - -# gcc is required to support cgo; -# git and mercurial are needed most times for go get`, etc. -# See https://github.com/docker-library/golang/issues/80 -RUN apk --no-cache add gcc musl-dev git mercurial -RUN CGO_ENABLED=0 go build -trimpath -ldflags "-s -w -X main.version=$VERSION -X main.commit=$SHORT_COMMIT -X main.date=$DATE" -o golangci-lint ./cmd/golangci-lint/main.go - -# stage 2 -FROM golang:1.20-alpine -# related to https://github.com/golangci/golangci-lint/issues/3107 -ENV GOROOT /usr/local/go -# gcc is required to support cgo; -# git and mercurial are needed most times for go get`, etc. -# See https://github.com/docker-library/golang/issues/80 -RUN apk --no-cache add gcc musl-dev git mercurial -# don't place it into $GOPATH/bin because Drone mounts $GOPATH as volume -COPY --from=builder /golangci/golangci-lint /usr/bin/ -CMD ["golangci-lint"] diff --git a/build/buildx-alpine.Dockerfile b/build/buildx-alpine.Dockerfile new file mode 100644 index 000000000000..e0e426cb17dc --- /dev/null +++ b/build/buildx-alpine.Dockerfile @@ -0,0 +1,16 @@ +# syntax=docker/dockerfile:1.4 +FROM golang:1.22-alpine + +# related to https://github.com/golangci/golangci-lint/issues/3107 +ENV GOROOT /usr/local/go + +# gcc is required to support cgo; +# git and mercurial are needed most times for go get`, etc. +# See https://github.com/docker-library/golang/issues/80 +RUN apk --no-cache add gcc musl-dev git mercurial + +# Set all directories as safe +RUN git config --global --add safe.directory '*' + +COPY golangci-lint /usr/bin/ +CMD ["golangci-lint"] diff --git a/build/buildx.Dockerfile b/build/buildx.Dockerfile new file mode 100644 index 000000000000..0e585067f2d1 --- /dev/null +++ b/build/buildx.Dockerfile @@ -0,0 +1,11 @@ +# syntax=docker/dockerfile:1.4 +FROM golang:1.22 + +# related to https://github.com/golangci/golangci-lint/issues/3107 +ENV GOROOT /usr/local/go + +# Set all directories as safe +RUN git config --global --add safe.directory '*' + +COPY golangci-lint /usr/bin/ +CMD ["golangci-lint"] diff --git a/cmd/golangci-lint/main.go b/cmd/golangci-lint/main.go index 282d794b8209..413e071d65f2 100644 --- a/cmd/golangci-lint/main.go +++ b/cmd/golangci-lint/main.go @@ -3,23 +3,79 @@ package main import ( "fmt" "os" + "runtime/debug" "github.com/golangci/golangci-lint/pkg/commands" "github.com/golangci/golangci-lint/pkg/exitcodes" ) var ( + goVersion = "unknown" + // Populated by goreleaser during build - version = "master" + version = "unknown" commit = "?" date = "" ) func main() { - e := commands.NewExecutor(version, commit, date) + info := createBuildInfo() - if err := e.Execute(); err != nil { - fmt.Fprintf(os.Stderr, "failed executing command with error %v\n", err) + if err := commands.Execute(info); err != nil { + _, _ = fmt.Fprintf(os.Stderr, "Failed executing command with error: %v\n", err) os.Exit(exitcodes.Failure) } } + +func createBuildInfo() commands.BuildInfo { + info := commands.BuildInfo{ + Commit: commit, + Version: version, + GoVersion: goVersion, + Date: date, + } + + buildInfo, available := debug.ReadBuildInfo() + if !available { + return info + } + + info.GoVersion = buildInfo.GoVersion + + if date != "" { + return info + } + + info.Version = buildInfo.Main.Version + + var revision string + var modified string + for _, setting := range buildInfo.Settings { + // The `vcs.xxx` information is only available with `go build`. + // This information is not available with `go install` or `go run`. + switch setting.Key { + case "vcs.time": + info.Date = setting.Value + case "vcs.revision": + revision = setting.Value + case "vcs.modified": + modified = setting.Value + } + } + + if revision == "" { + revision = "unknown" + } + + if modified == "" { + modified = "?" + } + + if info.Date == "" { + info.Date = "(unknown)" + } + + info.Commit = fmt.Sprintf("(%s, modified: %s, mod sum: %q)", revision, modified, buildInfo.Main.Sum) + + return info +} diff --git a/cmd/golangci-lint/mod_version.go b/cmd/golangci-lint/mod_version.go deleted file mode 100644 index 119a8a60dbb6..000000000000 --- a/cmd/golangci-lint/mod_version.go +++ /dev/null @@ -1,17 +0,0 @@ -package main - -import ( - "fmt" - "runtime/debug" -) - -//nolint:gochecknoinits -func init() { - if info, available := debug.ReadBuildInfo(); available { - if date == "" { - version = info.Main.Version - commit = fmt.Sprintf("(unknown, mod sum: %q)", info.Main.Sum) - date = "(unknown)" - } - } -} diff --git a/cmd/golangci-lint/plugins.go b/cmd/golangci-lint/plugins.go new file mode 100644 index 000000000000..541ff7624271 --- /dev/null +++ b/cmd/golangci-lint/plugins.go @@ -0,0 +1,3 @@ +package main + +// This file is used to declare module plugins. diff --git a/docs/.gitignore b/docs/.gitignore index f81327511eeb..2433561c61cd 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -67,3 +67,5 @@ yarn-error.log .pnp.js # Yarn Integrity file .yarn-integrity + +/static/jsonschema/ diff --git a/docs/gatsby-node.js b/docs/gatsby-node.js index d971b6a72dfc..ab45dd5ac465 100644 --- a/docs/gatsby-node.js +++ b/docs/gatsby-node.js @@ -165,7 +165,7 @@ exports.onPreBootstrap = ({ store, reporter }, themeOptions) => { dirs.forEach((dir) => { if (!fs.existsSync(dir)) { - reporter.success(`docs: intialized the ${dir} directory`); + reporter.success(`docs: initialized the ${dir} directory`); fs.mkdirSync(dir); } }); diff --git a/docs/package-lock.json b/docs/package-lock.json index 5e528327ab4b..ab9836ffc77e 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -9,11 +9,11 @@ "version": "1.0.0", "license": "MIT", "dependencies": { - "@emotion/react": "^11.10.4", + "@emotion/react": "^11.11.0", "@emotion/styled": "^11.10.0", "@mdx-js/mdx": "^1.6.22", "@mdx-js/react": "^1.6.16", - "gatsby": "^4.25.0", + "gatsby": "^4.25.7", "gatsby-alias-imports": "^1.0.6", "gatsby-plugin-canonical-urls": "^4.25.0", "gatsby-plugin-catch-links": "^4.21.0", @@ -25,20 +25,20 @@ "gatsby-plugin-react-helmet": "^5.21.0", "gatsby-plugin-react-svg": "^3.1.0", "gatsby-plugin-robots-txt": "^1.7.1", - "gatsby-plugin-sharp": "^4.24.0", + "gatsby-plugin-sharp": "^4.25.1", "gatsby-plugin-sitemap": "^5.24.0", "gatsby-remark-autolink-headers": "^5.24.0", "gatsby-remark-copy-linked-files": "^5.24.0", "gatsby-remark-external-links": "^0.0.4", "gatsby-remark-images": "^6.25.0", "gatsby-remark-mermaid": "^2.1.0", - "gatsby-remark-responsive-iframe": "^5.24.0", + "gatsby-remark-responsive-iframe": "^5.25.0", "gatsby-source-filesystem": "^4.22.0", "gatsby-transformer-remark": "^5.25.1", "gatsby-transformer-sharp": "^4.21.0", - "gatsby-transformer-yaml": "^4.21.0", + "gatsby-transformer-yaml": "^4.25.0", "polished": "^4.2.2", - "postcss": "^8.4.20", + "postcss": "^8.4.31", "prism-react-renderer": "^1.3.5", "prop-types": "^15.8.1", "puppeteer": "^13.7.0", @@ -55,11 +55,12 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", "dependencies": { - "@babel/highlight": "^7.18.6" + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" }, "engines": { "node": ">=6.9.0" @@ -103,9 +104,9 @@ } }, "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" } @@ -136,20 +137,21 @@ } }, "node_modules/@babel/eslint-parser/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" } }, "node_modules/@babel/generator": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.5.tgz", - "integrity": "sha512-jl7JY2Ykn9S0yj4DQP82sYvPU+T3g0HFcWTqDLqiuA9tGRNIj9VfbtXGAYTTkyNEnQk1jkMGOdYka8aG/lulCA==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", "dependencies": { - "@babel/types": "^7.20.5", + "@babel/types": "^7.23.0", "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" }, "engines": { @@ -197,9 +199,9 @@ } }, "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" } @@ -263,17 +265,17 @@ "integrity": "sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ==" }, "node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "engines": { "node": ">=6.9.0" } @@ -290,23 +292,23 @@ } }, "node_modules/@babel/helper-function-name": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", - "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dependencies": { - "@babel/template": "^7.18.10", - "@babel/types": "^7.19.0" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -419,28 +421,28 @@ } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "engines": { "node": ">=6.9.0" } @@ -481,12 +483,12 @@ } }, "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, "engines": { @@ -494,9 +496,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.5.tgz", - "integrity": "sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", "bin": { "parser": "bin/babel-parser.js" }, @@ -1855,9 +1857,9 @@ } }, "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" } @@ -2155,9 +2157,9 @@ } }, "node_modules/@babel/preset-env/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" } @@ -2252,31 +2254,31 @@ } }, "node_modules/@babel/template": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", - "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.18.10", - "@babel/types": "^7.18.10" + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.5.tgz", - "integrity": "sha512-WM5ZNN3JITQIq9tFZaw1ojLU3WgWdtkxnhM1AegMS+PvHjkM5IXjmYEGY7yukz5XS4sJyEf2VzWjI8uAavhxBQ==", - "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.5", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.20.5", - "@babel/types": "^7.20.5", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -2285,12 +2287,12 @@ } }, "node_modules/@babel/types": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.5.tgz", - "integrity": "sha512-c9fst/h2/dcF7H+MJKZ2T0KjEQ8hY/BNnDk/H3XY8C4Aw/eWQXWn/lWntHF9ooUBnGmEvbfGrTgLWc+um0YDUg==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", "dependencies": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, "engines": { @@ -2311,25 +2313,21 @@ } }, "node_modules/@emotion/babel-plugin": { - "version": "11.10.2", - "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.10.2.tgz", - "integrity": "sha512-xNQ57njWTFVfPAc3cjfuaPdsgLp5QOSuRsj9MA6ndEhH/AzuZM86qIQzt6rq+aGBwj3n5/TkLmU5lhAfdRmogA==", + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", + "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", "dependencies": { "@babel/helper-module-imports": "^7.16.7", - "@babel/plugin-syntax-jsx": "^7.17.12", "@babel/runtime": "^7.18.3", - "@emotion/hash": "^0.9.0", - "@emotion/memoize": "^0.8.0", - "@emotion/serialize": "^1.1.0", + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/serialize": "^1.1.2", "babel-plugin-macros": "^3.1.0", "convert-source-map": "^1.5.0", "escape-string-regexp": "^4.0.0", "find-root": "^1.1.0", "source-map": "^0.5.7", - "stylis": "4.0.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "stylis": "4.2.0" } }, "node_modules/@emotion/babel-plugin-jsx-pragmatic": { @@ -2369,21 +2367,21 @@ } }, "node_modules/@emotion/cache": { - "version": "11.10.3", - "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.10.3.tgz", - "integrity": "sha512-Psmp/7ovAa8appWh3g51goxu/z3iVms7JXOreq136D8Bbn6dYraPnmL6mdM8GThEx9vwSn92Fz+mGSjBzN8UPQ==", + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz", + "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==", "dependencies": { - "@emotion/memoize": "^0.8.0", - "@emotion/sheet": "^1.2.0", - "@emotion/utils": "^1.2.0", - "@emotion/weak-memoize": "^0.3.0", - "stylis": "4.0.13" + "@emotion/memoize": "^0.8.1", + "@emotion/sheet": "^1.2.2", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "stylis": "4.2.0" } }, "node_modules/@emotion/hash": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.0.tgz", - "integrity": "sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ==" + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" }, "node_modules/@emotion/is-prop-valid": { "version": "1.2.0", @@ -2394,53 +2392,49 @@ } }, "node_modules/@emotion/memoize": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz", - "integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA==" + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" }, "node_modules/@emotion/react": { - "version": "11.10.4", - "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.10.4.tgz", - "integrity": "sha512-j0AkMpr6BL8gldJZ6XQsQ8DnS9TxEQu1R+OGmDZiWjBAJtCcbt0tS3I/YffoqHXxH6MjgI7KdMbYKw3MEiU9eA==", + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.0.tgz", + "integrity": "sha512-ZSK3ZJsNkwfjT3JpDAWJZlrGD81Z3ytNDsxw1LKq1o+xkmO5pnWfr6gmCC8gHEFf3nSSX/09YrG67jybNPxSUw==", "dependencies": { "@babel/runtime": "^7.18.3", - "@emotion/babel-plugin": "^11.10.0", - "@emotion/cache": "^11.10.0", - "@emotion/serialize": "^1.1.0", - "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0", - "@emotion/utils": "^1.2.0", - "@emotion/weak-memoize": "^0.3.0", + "@emotion/babel-plugin": "^11.11.0", + "@emotion/cache": "^11.11.0", + "@emotion/serialize": "^1.1.2", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", "hoist-non-react-statics": "^3.3.1" }, "peerDependencies": { - "@babel/core": "^7.0.0", "react": ">=16.8.0" }, "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, "@types/react": { "optional": true } } }, "node_modules/@emotion/serialize": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.0.tgz", - "integrity": "sha512-F1ZZZW51T/fx+wKbVlwsfchr5q97iW8brAnXmsskz4d0hVB4O3M/SiA3SaeH06x02lSNzkkQv+n3AX3kCXKSFA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.2.tgz", + "integrity": "sha512-zR6a/fkFP4EAcCMQtLOhIgpprZOwNmCldtpaISpvz348+DP4Mz8ZoKaGGCQpbzepNIUWbq4w6hNZkwDyKoS+HA==", "dependencies": { - "@emotion/hash": "^0.9.0", - "@emotion/memoize": "^0.8.0", - "@emotion/unitless": "^0.8.0", - "@emotion/utils": "^1.2.0", + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/unitless": "^0.8.1", + "@emotion/utils": "^1.2.1", "csstype": "^3.0.2" } }, "node_modules/@emotion/sheet": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.0.tgz", - "integrity": "sha512-OiTkRgpxescko+M51tZsMq7Puu/KP55wMT8BgpcXVG2hqXc0Vo0mfymJ/Uj24Hp0i083ji/o0aLddh08UEjq8w==" + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", + "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" }, "node_modules/@emotion/styled": { "version": "11.10.0", @@ -2468,27 +2462,27 @@ } }, "node_modules/@emotion/unitless": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.0.tgz", - "integrity": "sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw==" + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" }, "node_modules/@emotion/use-insertion-effect-with-fallbacks": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.0.tgz", - "integrity": "sha512-1eEgUGmkaljiBnRMTdksDV1W4kUnmwgp7X9G8B++9GYwl1lUdqSndSriIrTJ0N7LQaoauY9JJ2yhiOYK5+NI4A==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", + "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", "peerDependencies": { "react": ">=16.8.0" } }, "node_modules/@emotion/utils": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.0.tgz", - "integrity": "sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", + "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" }, "node_modules/@emotion/weak-memoize": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz", - "integrity": "sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg==" + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", + "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" }, "node_modules/@eslint/eslintrc": { "version": "0.4.3", @@ -3028,12 +3022,12 @@ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz", - "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==", + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, "node_modules/@lezer/common": { @@ -3236,6 +3230,78 @@ "node": ">=12.0.0" } }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.2.tgz", + "integrity": "sha512-9bfjwDxIDWmmOKusUcqdS4Rw+SETlp9Dy39Xui9BEGEk19dDwH0jhipwFzEff/pFg95NKymc6TOTbRKcWeRqyQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.2.tgz", + "integrity": "sha512-lwriRAHm1Yg4iDf23Oxm9n/t5Zpw1lVnxYU3HnJPTi2lJRkKTrps1KVgvL6m7WvmhYVt/FIsssWay+k45QHeuw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.2.tgz", + "integrity": "sha512-MOI9Dlfrpi2Cuc7i5dXdxPbFIgbDBGgKR5F2yWEa6FVEtSWncfVNKW5AKjImAQ6CZlBK9tympdsZJ2xThBiWWA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.2.tgz", + "integrity": "sha512-FU20Bo66/f7He9Fp9sP2zaJ1Q8L9uLPZQDub/WlUip78JlPeMbVL8546HbZfcW9LNciEXc8d+tThSJjSC+tmsg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.2.tgz", + "integrity": "sha512-gsWNDCklNy7Ajk0vBBf9jEx04RUxuDQfBse918Ww+Qb9HCPoGzS+XJTLe96iN3BVK7grnLiYghP/M4L8VsaHeA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.2.tgz", + "integrity": "sha512-O+6Gs8UeDbyFpbSh2CPEz/UOrrdWPTBYNblZK5CxxLisYt4kGX3Sc+czffFonyjiGSq3jWLwJS/CCJc7tBr4sQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -4232,6 +4298,11 @@ "node": ">=8" } }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" + }, "node_modules/@swc/helpers": { "version": "0.4.14", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", @@ -4301,11 +4372,6 @@ "resolved": "https://registry.npmjs.org/@types/common-tags/-/common-tags-1.8.1.tgz", "integrity": "sha512-20R/mDpKSPWdJs5TOpz3e7zqbeCNuMCPhV7Yndk9KU2Rbij2r5W4RzwDPkzC+2lzUqXYu9rFzTktCBnDjHuNQg==" }, - "node_modules/@types/component-emitter": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", - "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==" - }, "node_modules/@types/configstore": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/@types/configstore/-/configstore-2.1.1.tgz", @@ -4317,9 +4383,12 @@ "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" }, "node_modules/@types/cors": { - "version": "2.8.12", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", - "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==" + "version": "2.8.13", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", + "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", + "dependencies": { + "@types/node": "*" + } }, "node_modules/@types/debug": { "version": "0.0.30", @@ -4345,9 +4414,9 @@ } }, "node_modules/@types/estree": { - "version": "0.0.50", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz", - "integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==" + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==" }, "node_modules/@types/get-port": { "version": "3.2.0", @@ -4597,9 +4666,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -4714,9 +4783,9 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -5446,9 +5515,9 @@ } }, "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" } @@ -5576,11 +5645,6 @@ "babylon": "bin/babylon.js" } }, - "node_modules/backo2": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", - "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" - }, "node_modules/bail": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", @@ -5599,14 +5663,6 @@ "safe-buffer": "^5.0.1" } }, - "node_modules/base64-arraybuffer": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz", - "integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI=", - "engines": { - "node": ">= 0.6.0" - } - }, "node_modules/base64-js": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", @@ -6831,11 +6887,6 @@ "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" - }, "node_modules/compressible": { "version": "2.0.18", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", @@ -7229,9 +7280,9 @@ } }, "node_modules/css-loader/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -8680,54 +8731,49 @@ } }, "node_modules/engine.io": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-4.1.2.tgz", - "integrity": "sha512-t5z6zjXuVLhXDMiFJPYsPOWEER8B0tIsD3ETgw19S1yg9zryvUfY3Vhtk3Gf4sihw/bQGIqQ//gjvVlu+Ca0bQ==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.2.1.tgz", + "integrity": "sha512-ECceEFcAaNRybd3lsGQKas3ZlMVjN3cyWwMP25D2i0zWfyiytVbTpRPa34qrr+FHddtpBVOmq4H/DCv1O0lZRA==", "dependencies": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", "accepts": "~1.3.4", "base64id": "2.0.0", "cookie": "~0.4.1", "cors": "~2.8.5", "debug": "~4.3.1", - "engine.io-parser": "~4.0.0", - "ws": "~7.4.2" + "engine.io-parser": "~5.0.3", + "ws": "~8.2.3" }, "engines": { "node": ">=10.0.0" } }, "node_modules/engine.io-client": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-4.1.4.tgz", - "integrity": "sha512-843fqAdKeUMFqKi1sSjnR11tJ4wi8sIefu6+JC1OzkkJBmjtc/gM/rZ53tJfu5Iae/3gApm5veoS+v+gtT0+Fg==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.2.3.tgz", + "integrity": "sha512-aXPtgF1JS3RuuKcpSrBtimSjYvrbhKW9froICH4s0F3XQWLxsKNxqzG39nnvQZQnva4CMvUK63T7shevxRyYHw==", "dependencies": { - "base64-arraybuffer": "0.1.4", - "component-emitter": "~1.3.0", + "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1", - "engine.io-parser": "~4.0.1", - "has-cors": "1.1.0", - "parseqs": "0.0.6", - "parseuri": "0.0.6", - "ws": "~7.4.2", - "xmlhttprequest-ssl": "~1.6.2", - "yeast": "0.1.2" + "engine.io-parser": "~5.0.3", + "ws": "~8.2.3", + "xmlhttprequest-ssl": "~2.0.0" } }, "node_modules/engine.io-parser": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-4.0.3.tgz", - "integrity": "sha512-xEAAY0msNnESNPc00e19y5heTPX4y/TJ36gr8t1voOaNmTojP9b3oK3BbJLFufW2XFPQaaijpFewm2g2Um3uqA==", - "dependencies": { - "base64-arraybuffer": "0.1.4" - }, + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.7.tgz", + "integrity": "sha512-P+jDFbvK6lE3n1OL+q9KuzdOFWkkZ/cMV9gol/SbVfpyqfvrfrFTOFJ6fQm2VC3PZHlU3QPhVwmbsCnauHF2MQ==", "engines": { - "node": ">=8.0.0" + "node": ">=10.0.0" } }, "node_modules/enhanced-resolve": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz", - "integrity": "sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA==", + "version": "5.12.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", + "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -8855,20 +8901,20 @@ } }, "node_modules/es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "version": "0.10.63", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.63.tgz", + "integrity": "sha512-hUCZd2Byj/mNKjfP9jXrdVZ62B8KuA/VoK7X8nUh5qT+AxDmcbvZz041oDVZdbIN1qW6XY9VDNwzkvKnZvK2TQ==", + "hasInstallScript": true, "dependencies": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "esniff": "^2.0.1", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" } }, - "node_modules/es5-ext/node_modules/next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" - }, "node_modules/es6-iterator": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", @@ -9227,9 +9273,9 @@ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, "node_modules/eslint-plugin-jsx-a11y/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" } @@ -9296,9 +9342,9 @@ } }, "node_modules/eslint-plugin-react/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" } @@ -9578,9 +9624,9 @@ } }, "node_modules/eslint/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -9646,6 +9692,25 @@ "node": ">= 8" } }, + "node_modules/esniff": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", + "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "event-emitter": "^0.3.5", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esniff/node_modules/type": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" + }, "node_modules/espree": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", @@ -10401,9 +10466,9 @@ "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" }, "node_modules/follow-redirects": { - "version": "1.14.8", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", - "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", @@ -10553,9 +10618,9 @@ } }, "node_modules/fork-ts-checker-webpack-plugin/node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -10695,9 +10760,9 @@ } }, "node_modules/gatsby": { - "version": "4.25.0", - "resolved": "https://registry.npmjs.org/gatsby/-/gatsby-4.25.0.tgz", - "integrity": "sha512-zR/u0X60Ww250XqHGytAVFDfFJUpDzMnbPHQ7uAqr6zLgU03DBKyjqKiRpFsGx7L7ENj61hdorjz12IiNj6DIw==", + "version": "4.25.7", + "resolved": "https://registry.npmjs.org/gatsby/-/gatsby-4.25.7.tgz", + "integrity": "sha512-kspM1XokxDw2YqC2hkPKQTfWSNSq/AnY8PNYSrUM+MCsyIKFuGqSVchNonZN1g8/nCoh4jQpBYXH5Uw2Hrs6Sw==", "hasInstallScript": true, "dependencies": { "@babel/code-frame": "^7.14.0", @@ -10786,7 +10851,7 @@ "gatsby-legacy-polyfills": "^2.25.0", "gatsby-link": "^4.25.0", "gatsby-page-utils": "^2.25.0", - "gatsby-parcel-config": "^0.16.0", + "gatsby-parcel-config": "0.16.0", "gatsby-plugin-page-creator": "^4.25.0", "gatsby-plugin-typescript": "^4.25.0", "gatsby-plugin-utils": "^3.19.0", @@ -10845,8 +10910,8 @@ "shallow-compare": "^1.2.2", "signal-exit": "^3.0.5", "slugify": "^1.6.1", - "socket.io": "3.1.2", - "socket.io-client": "3.1.3", + "socket.io": "4.5.4", + "socket.io-client": "4.5.4", "st": "^2.0.0", "stack-trace": "^0.0.10", "string-similarity": "^1.2.2", @@ -10864,7 +10929,7 @@ "webpack-stats-plugin": "^1.0.3", "webpack-virtual-modules": "^0.3.2", "xstate": "4.32.1", - "yaml-loader": "^0.6.0" + "yaml-loader": "^0.8.0" }, "bin": { "gatsby": "cli.js" @@ -11038,9 +11103,9 @@ } }, "node_modules/gatsby-cli/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -11320,9 +11385,9 @@ } }, "node_modules/gatsby-plugin-manifest/node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -11817,25 +11882,22 @@ } }, "node_modules/gatsby-plugin-sharp": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/gatsby-plugin-sharp/-/gatsby-plugin-sharp-4.24.0.tgz", - "integrity": "sha512-wVs8F9zLeiLf02yLi8vjse1vqSrZsx2u3RsMhoSv1bEinyaI5bcoLZ7mMJCsEeZe2G9mvNrPi4Ymhh/YzgxYCg==", + "version": "4.25.1", + "resolved": "https://registry.npmjs.org/gatsby-plugin-sharp/-/gatsby-plugin-sharp-4.25.1.tgz", + "integrity": "sha512-cGRb8lmwJkzwT1Qze0R+VL+55BIb9weM17m+dUf6gs5Z++lQltqge+L8a1qWWsGL6KfLQN7+bIqjhmTTscIPMQ==", "dependencies": { "@babel/runtime": "^7.15.4", - "@gatsbyjs/potrace": "^2.3.0", "async": "^3.2.4", "bluebird": "^3.7.2", "debug": "^4.3.4", "filenamify": "^4.3.0", "fs-extra": "^10.1.0", - "gatsby-core-utils": "^3.24.0", - "gatsby-plugin-utils": "^3.18.0", + "gatsby-core-utils": "^3.25.0", + "gatsby-plugin-utils": "^3.19.0", "lodash": "^4.17.21", - "mini-svg-data-uri": "^1.4.4", "probe-image-size": "^7.2.3", "semver": "^7.3.7", - "sharp": "^0.30.7", - "svgo": "^2.8.0" + "sharp": "^0.30.7" }, "engines": { "node": ">=14.15.0" @@ -11874,9 +11936,9 @@ } }, "node_modules/gatsby-plugin-sharp/node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -12483,9 +12545,9 @@ } }, "node_modules/gatsby-remark-responsive-iframe": { - "version": "5.24.0", - "resolved": "https://registry.npmjs.org/gatsby-remark-responsive-iframe/-/gatsby-remark-responsive-iframe-5.24.0.tgz", - "integrity": "sha512-gfLeeRol5Y35vuSxwVr9nRwGylZQmty4BmwzFJJkUwdUa0lI1P8X0Nhu9OY4WEnzLF4aeTMDUECnfsVzXi0/Tw==", + "version": "5.25.0", + "resolved": "https://registry.npmjs.org/gatsby-remark-responsive-iframe/-/gatsby-remark-responsive-iframe-5.25.0.tgz", + "integrity": "sha512-K2a0k0Q2umJA1lDtSoq3MM4QB1OGdAMSIbFtS/P9dXjg8rHDvnZGach6iDB8dF3fpjpl7LH3tr/DYAZBPHTqog==", "dependencies": { "@babel/runtime": "^7.15.4", "cheerio": "^1.0.0-rc.10", @@ -13052,9 +13114,9 @@ } }, "node_modules/gatsby-transformer-sharp/node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -13074,9 +13136,9 @@ } }, "node_modules/gatsby-transformer-yaml": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/gatsby-transformer-yaml/-/gatsby-transformer-yaml-4.21.0.tgz", - "integrity": "sha512-zq1ZDhGLZvPjCckz1jyBQqYU8Dj1dr0BCHGoZK4s/HmKVjoP2PCTbEGvUOXJv/3rzcZ4TPZczLC9McpLFhtRvA==", + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/gatsby-transformer-yaml/-/gatsby-transformer-yaml-4.25.0.tgz", + "integrity": "sha512-upmV5yAqvyDE7WvpMtG0LWlTLHk1lFivP82iL9iwKHRf/bn21iAafiFADyh0RCENnXbK0xxY4mM8UDvAXu3v3g==", "dependencies": { "@babel/runtime": "^7.15.4", "js-yaml": "^3.14.1", @@ -13476,9 +13538,9 @@ } }, "node_modules/gatsby/node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -14088,11 +14150,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-cors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", - "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" - }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -15276,6 +15333,11 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, + "node_modules/javascript-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-2.1.0.tgz", + "integrity": "sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==" + }, "node_modules/jest-worker": { "version": "26.6.2", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", @@ -15381,6 +15443,11 @@ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -15834,9 +15901,9 @@ } }, "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" } @@ -16962,14 +17029,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/mini-svg-data-uri": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", - "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==", - "bin": { - "mini-svg-data-uri": "cli.js" - } - }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -17055,22 +17114,43 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/msgpackr": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.5.4.tgz", - "integrity": "sha512-Z7w5Jg+2Q9z9gJxeM68d7tSuWZZGnFIRhZnyqcZCa/1dKkhOCNvR1TUV3zzJ3+vj78vlwKRzUgVDlW4jiSOeDA==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.10.1.tgz", + "integrity": "sha512-r5VRLv9qouXuLiIBrLpl2d5ZvPt8svdQTl5/vMvE4nzDMyEX4sgW5yWhuBBj5UmgwOTWj8CIdSXn5sAfsHAWIQ==", "optionalDependencies": { - "msgpackr-extract": "^1.0.14" + "msgpackr-extract": "^3.0.2" } }, "node_modules/msgpackr-extract": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-1.0.16.tgz", - "integrity": "sha512-fxdRfQUxPrL/TizyfYfMn09dK58e+d65bRD/fcaVH4052vj30QOzzqxcQIS7B0NsqlypEQ/6Du3QmP2DhWFfCA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.2.tgz", + "integrity": "sha512-SdzXp4kD/Qf8agZ9+iTu6eql0m3kWm1A2y1hkpTeVNENutaB0BwHlSvAIaMxwntmRUAUjon2V4L8Z/njd0Ct8A==", "hasInstallScript": true, "optional": true, "dependencies": { - "nan": "^2.14.2", - "node-gyp-build": "^4.2.3" + "node-gyp-build-optional-packages": "5.0.7" + }, + "bin": { + "download-msgpackr-prebuilds": "bin/download-prebuilds.js" + }, + "optionalDependencies": { + "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.2", + "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.2", + "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.2", + "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.2", + "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.2", + "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.2" + } + }, + "node_modules/msgpackr-extract/node_modules/node-gyp-build-optional-packages": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.0.7.tgz", + "integrity": "sha512-YlCCc6Wffkx0kHkmam79GKvDQ6x+QZkMjFGrIMxgFNILFvGSbCp2fCBC55pGTT9gVaz8Na5CLmxt/urtzRv36w==", + "optional": true, + "bin": { + "node-gyp-build-optional-packages": "bin.js", + "node-gyp-build-optional-packages-optional": "optional.js", + "node-gyp-build-optional-packages-test": "build-test.js" } }, "node_modules/multer": { @@ -17105,16 +17185,16 @@ "thenify-all": "^1.0.0" } }, - "node_modules/nan": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", - "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==", - "optional": true - }, "node_modules/nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -17204,9 +17284,9 @@ } }, "node_modules/node-abi/node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -17815,9 +17895,9 @@ } }, "node_modules/package-json/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" } @@ -17936,16 +18016,6 @@ "parse5": "^6.0.1" } }, - "node_modules/parseqs": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz", - "integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==" - }, - "node_modules/parseuri": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz", - "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==" - }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -18200,9 +18270,9 @@ } }, "node_modules/postcss": { - "version": "8.4.20", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.20.tgz", - "integrity": "sha512-6Q04AXR1212bXr5fh03u8aAwbLxAQNGQ/Q1LNa0VfOI06ZAlhPHtQvE4OIdpj4kLThXilalPnmDSOD65DcHt+g==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "funding": [ { "type": "opencollective", @@ -18211,10 +18281,14 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "nanoid": "^3.3.4", + "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -18259,9 +18333,9 @@ } }, "node_modules/postcss-loader/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -20216,9 +20290,9 @@ } }, "node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "bin": { "semver": "bin/semver" } @@ -20235,9 +20309,9 @@ } }, "node_modules/semver-diff/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" } @@ -20408,9 +20482,9 @@ } }, "node_modules/sharp/node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -20648,53 +20722,46 @@ } }, "node_modules/socket.io": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-3.1.2.tgz", - "integrity": "sha512-JubKZnTQ4Z8G4IZWtaAZSiRP3I/inpy8c/Bsx2jrwGrTbKeVU5xd6qkKMHpChYeM3dWZSO0QACiGK+obhBNwYw==", + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.5.4.tgz", + "integrity": "sha512-m3GC94iK9MfIEeIBfbhJs5BqFibMtkRk8ZpKwG2QwxV0m/eEhPIV4ara6XCF1LWNAus7z58RodiZlAH71U3EhQ==", "dependencies": { - "@types/cookie": "^0.4.0", - "@types/cors": "^2.8.8", - "@types/node": ">=10.0.0", "accepts": "~1.3.4", "base64id": "~2.0.0", - "debug": "~4.3.1", - "engine.io": "~4.1.0", - "socket.io-adapter": "~2.1.0", - "socket.io-parser": "~4.0.3" + "debug": "~4.3.2", + "engine.io": "~6.2.1", + "socket.io-adapter": "~2.4.0", + "socket.io-parser": "~4.2.1" }, "engines": { "node": ">=10.0.0" } }, "node_modules/socket.io-adapter": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.1.0.tgz", - "integrity": "sha512-+vDov/aTsLjViYTwS9fPy5pEtTkrbEKsw2M+oVSoFGw6OD1IpvlV1VPhUzNbofCQ8oyMbdYJqDtGdmHQK6TdPg==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.4.0.tgz", + "integrity": "sha512-W4N+o69rkMEGVuk2D/cvca3uYsvGlMwsySWV447y99gUPghxq42BxqLNMndb+a1mm/5/7NeXVQS7RLa2XyXvYg==" }, "node_modules/socket.io-client": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-3.1.3.tgz", - "integrity": "sha512-4sIGOGOmCg3AOgGi7EEr6ZkTZRkrXwub70bBB/F0JSkMOUFpA77WsL87o34DffQQ31PkbMUIadGOk+3tx1KGbw==", + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.5.4.tgz", + "integrity": "sha512-ZpKteoA06RzkD32IbqILZ+Cnst4xewU7ZYK12aS1mzHftFFjpoMz69IuhP/nL25pJfao/amoPI527KnuhFm01g==", "dependencies": { - "@types/component-emitter": "^1.2.10", - "backo2": "~1.0.2", - "component-emitter": "~1.3.0", - "debug": "~4.3.1", - "engine.io-client": "~4.1.0", - "parseuri": "0.0.6", - "socket.io-parser": "~4.0.4" + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.2.3", + "socket.io-parser": "~4.2.1" }, "engines": { "node": ">=10.0.0" } }, "node_modules/socket.io-parser": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.5.tgz", - "integrity": "sha512-sNjbT9dX63nqUFIOv95tTVm6elyIU4RvB1m8dOeZt+IgWwcWklFDOdmGcfo3zSiRsnR/3pJkjY5lfoGqEe4Eig==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", "dependencies": { - "@types/component-emitter": "^1.2.10", - "component-emitter": "~1.3.0", + "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1" }, "engines": { @@ -21193,9 +21260,9 @@ } }, "node_modules/stylis": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.0.13.tgz", - "integrity": "sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag==" + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" }, "node_modules/sucrase": { "version": "3.21.0", @@ -22520,9 +22587,9 @@ } }, "node_modules/update-notifier/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -22755,9 +22822,9 @@ } }, "node_modules/watchpack": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", - "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -22787,33 +22854,33 @@ "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" }, "node_modules/webpack": { - "version": "5.68.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.68.0.tgz", - "integrity": "sha512-zUcqaUO0772UuuW2bzaES2Zjlm/y3kRBQDVFVCge+s2Y8mwuUTdperGaAv65/NtRL/1zanpSJOq/MD8u61vo6g==", + "version": "5.76.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.1.tgz", + "integrity": "sha512-4+YIK4Abzv8172/SGqObnUjaIHjLEuUasz9EwQj/9xmPPkYJy2Mh03Q/lJfSD3YLzbxy5FeTq5Uw0323Oh6SJQ==", "dependencies": { - "@types/eslint-scope": "^3.7.0", - "@types/estree": "^0.0.50", + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", "@webassemblyjs/ast": "1.11.1", "@webassemblyjs/wasm-edit": "1.11.1", "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.4.1", + "acorn": "^8.7.1", "acorn-import-assertions": "^1.7.6", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.8.3", + "enhanced-resolve": "^5.10.0", "es-module-lexer": "^0.9.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.9", - "json-parse-better-errors": "^1.0.2", + "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", "schema-utils": "^3.1.0", "tapable": "^2.1.1", "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.3.1", + "watchpack": "^2.4.0", "webpack-sources": "^3.2.3" }, "bin": { @@ -23041,9 +23108,9 @@ } }, "node_modules/webpack/node_modules/acorn": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", - "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", "bin": { "acorn": "bin/acorn" }, @@ -23149,9 +23216,9 @@ "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==" }, "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", + "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", "engines": { "node": ">=0.10.0" } @@ -23368,11 +23435,11 @@ } }, "node_modules/ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", "engines": { - "node": ">=8.3.0" + "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", @@ -23401,9 +23468,9 @@ } }, "node_modules/xmlhttprequest-ssl": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.6.3.tgz", - "integrity": "sha512-3XfeQE/wNkvrIktn2Kf0869fC0BN6UpydVasGIeSm2B1Llihf7/0UfZM+eCkOw3P7bP4+qPgqhm7ZoxuJtFU0Q==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", + "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==", "engines": { "node": ">=0.4.0" } @@ -23464,15 +23531,37 @@ } }, "node_modules/yaml-loader": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/yaml-loader/-/yaml-loader-0.6.0.tgz", - "integrity": "sha512-1bNiLelumURyj+zvVHOv8Y3dpCri0F2S+DCcmps0pA1zWRLjS+FhZQg4o3aUUDYESh73+pKZNI18bj7stpReow==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/yaml-loader/-/yaml-loader-0.8.0.tgz", + "integrity": "sha512-LjeKnTzVBKWiQBeE2L9ssl6WprqaUIxCSNs5tle8PaDydgu3wVFXTbMfsvF2MSErpy9TDVa092n4q6adYwJaWg==", "dependencies": { - "loader-utils": "^1.4.0", - "yaml": "^1.8.3" + "javascript-stringify": "^2.0.1", + "loader-utils": "^2.0.0", + "yaml": "^2.0.0" }, "engines": { - "node": ">= 6" + "node": ">= 12.13" + } + }, + "node_modules/yaml-loader/node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/yaml-loader/node_modules/yaml": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", + "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==", + "engines": { + "node": ">= 14" } }, "node_modules/yargs": { @@ -23517,11 +23606,6 @@ "fd-slicer": "~1.1.0" } }, - "node_modules/yeast": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", - "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -23583,11 +23667,12 @@ }, "dependencies": { "@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", "requires": { - "@babel/highlight": "^7.18.6" + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" } }, "@babel/compat-data": { @@ -23618,9 +23703,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, @@ -23640,19 +23725,20 @@ "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==" }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, "@babel/generator": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.5.tgz", - "integrity": "sha512-jl7JY2Ykn9S0yj4DQP82sYvPU+T3g0HFcWTqDLqiuA9tGRNIj9VfbtXGAYTTkyNEnQk1jkMGOdYka8aG/lulCA==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", "requires": { - "@babel/types": "^7.20.5", + "@babel/types": "^7.23.0", "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" } }, @@ -23685,9 +23771,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, @@ -23735,16 +23821,16 @@ "integrity": "sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ==" }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, "@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==" + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==" }, "@babel/helper-explode-assignable-expression": { "version": "7.14.5", @@ -23755,20 +23841,20 @@ } }, "@babel/helper-function-name": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", - "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "requires": { - "@babel/template": "^7.18.10", - "@babel/types": "^7.19.0" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" } }, "@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "requires": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" } }, "@babel/helper-member-expression-to-functions": { @@ -23854,22 +23940,22 @@ } }, "@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "requires": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" } }, "@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==" + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==" }, "@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==" + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==" }, "@babel/helper-validator-option": { "version": "7.18.6", @@ -23898,19 +23984,19 @@ } }, "@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", "requires": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", "js-tokens": "^4.0.0" } }, "@babel/parser": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.5.tgz", - "integrity": "sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA==" + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==" }, "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { "version": "7.15.4", @@ -24869,9 +24955,9 @@ } }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, @@ -25097,9 +25183,9 @@ } }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, @@ -25170,39 +25256,39 @@ } }, "@babel/template": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", - "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.18.10", - "@babel/types": "^7.18.10" + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" } }, "@babel/traverse": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.5.tgz", - "integrity": "sha512-WM5ZNN3JITQIq9tFZaw1ojLU3WgWdtkxnhM1AegMS+PvHjkM5IXjmYEGY7yukz5XS4sJyEf2VzWjI8uAavhxBQ==", - "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.5", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.20.5", - "@babel/types": "^7.20.5", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "requires": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", "debug": "^4.1.0", "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.5.tgz", - "integrity": "sha512-c9fst/h2/dcF7H+MJKZ2T0KjEQ8hY/BNnDk/H3XY8C4Aw/eWQXWn/lWntHF9ooUBnGmEvbfGrTgLWc+um0YDUg==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", "requires": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" } }, @@ -25217,22 +25303,21 @@ "integrity": "sha512-qnikpQgi30AS01aFlNQV6l8/qdZIcP76mp90ti+u4rucXHsn4afSKivQXApqxvrQG9+Ibv45STyvHizvxef/7A==" }, "@emotion/babel-plugin": { - "version": "11.10.2", - "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.10.2.tgz", - "integrity": "sha512-xNQ57njWTFVfPAc3cjfuaPdsgLp5QOSuRsj9MA6ndEhH/AzuZM86qIQzt6rq+aGBwj3n5/TkLmU5lhAfdRmogA==", + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", + "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", "requires": { "@babel/helper-module-imports": "^7.16.7", - "@babel/plugin-syntax-jsx": "^7.17.12", "@babel/runtime": "^7.18.3", - "@emotion/hash": "^0.9.0", - "@emotion/memoize": "^0.8.0", - "@emotion/serialize": "^1.1.0", + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/serialize": "^1.1.2", "babel-plugin-macros": "^3.1.0", "convert-source-map": "^1.5.0", "escape-string-regexp": "^4.0.0", "find-root": "^1.1.0", "source-map": "^0.5.7", - "stylis": "4.0.13" + "stylis": "4.2.0" }, "dependencies": { "escape-string-regexp": { @@ -25262,21 +25347,21 @@ } }, "@emotion/cache": { - "version": "11.10.3", - "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.10.3.tgz", - "integrity": "sha512-Psmp/7ovAa8appWh3g51goxu/z3iVms7JXOreq136D8Bbn6dYraPnmL6mdM8GThEx9vwSn92Fz+mGSjBzN8UPQ==", + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz", + "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==", "requires": { - "@emotion/memoize": "^0.8.0", - "@emotion/sheet": "^1.2.0", - "@emotion/utils": "^1.2.0", - "@emotion/weak-memoize": "^0.3.0", - "stylis": "4.0.13" + "@emotion/memoize": "^0.8.1", + "@emotion/sheet": "^1.2.2", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "stylis": "4.2.0" } }, "@emotion/hash": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.0.tgz", - "integrity": "sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ==" + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" }, "@emotion/is-prop-valid": { "version": "1.2.0", @@ -25287,41 +25372,41 @@ } }, "@emotion/memoize": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz", - "integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA==" + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" }, "@emotion/react": { - "version": "11.10.4", - "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.10.4.tgz", - "integrity": "sha512-j0AkMpr6BL8gldJZ6XQsQ8DnS9TxEQu1R+OGmDZiWjBAJtCcbt0tS3I/YffoqHXxH6MjgI7KdMbYKw3MEiU9eA==", + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.0.tgz", + "integrity": "sha512-ZSK3ZJsNkwfjT3JpDAWJZlrGD81Z3ytNDsxw1LKq1o+xkmO5pnWfr6gmCC8gHEFf3nSSX/09YrG67jybNPxSUw==", "requires": { "@babel/runtime": "^7.18.3", - "@emotion/babel-plugin": "^11.10.0", - "@emotion/cache": "^11.10.0", - "@emotion/serialize": "^1.1.0", - "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0", - "@emotion/utils": "^1.2.0", - "@emotion/weak-memoize": "^0.3.0", + "@emotion/babel-plugin": "^11.11.0", + "@emotion/cache": "^11.11.0", + "@emotion/serialize": "^1.1.2", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", "hoist-non-react-statics": "^3.3.1" } }, "@emotion/serialize": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.0.tgz", - "integrity": "sha512-F1ZZZW51T/fx+wKbVlwsfchr5q97iW8brAnXmsskz4d0hVB4O3M/SiA3SaeH06x02lSNzkkQv+n3AX3kCXKSFA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.2.tgz", + "integrity": "sha512-zR6a/fkFP4EAcCMQtLOhIgpprZOwNmCldtpaISpvz348+DP4Mz8ZoKaGGCQpbzepNIUWbq4w6hNZkwDyKoS+HA==", "requires": { - "@emotion/hash": "^0.9.0", - "@emotion/memoize": "^0.8.0", - "@emotion/unitless": "^0.8.0", - "@emotion/utils": "^1.2.0", + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/unitless": "^0.8.1", + "@emotion/utils": "^1.2.1", "csstype": "^3.0.2" } }, "@emotion/sheet": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.0.tgz", - "integrity": "sha512-OiTkRgpxescko+M51tZsMq7Puu/KP55wMT8BgpcXVG2hqXc0Vo0mfymJ/Uj24Hp0i083ji/o0aLddh08UEjq8w==" + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", + "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" }, "@emotion/styled": { "version": "11.10.0", @@ -25336,25 +25421,25 @@ } }, "@emotion/unitless": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.0.tgz", - "integrity": "sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw==" + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" }, "@emotion/use-insertion-effect-with-fallbacks": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.0.tgz", - "integrity": "sha512-1eEgUGmkaljiBnRMTdksDV1W4kUnmwgp7X9G8B++9GYwl1lUdqSndSriIrTJ0N7LQaoauY9JJ2yhiOYK5+NI4A==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", + "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", "requires": {} }, "@emotion/utils": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.0.tgz", - "integrity": "sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", + "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" }, "@emotion/weak-memoize": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz", - "integrity": "sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg==" + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", + "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" }, "@eslint/eslintrc": { "version": "0.4.3", @@ -25830,12 +25915,12 @@ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" }, "@jridgewell/trace-mapping": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz", - "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==", + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, "@lezer/common": { @@ -25998,6 +26083,42 @@ "json5": "^2.2.1" } }, + "@msgpackr-extract/msgpackr-extract-darwin-arm64": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.2.tgz", + "integrity": "sha512-9bfjwDxIDWmmOKusUcqdS4Rw+SETlp9Dy39Xui9BEGEk19dDwH0jhipwFzEff/pFg95NKymc6TOTbRKcWeRqyQ==", + "optional": true + }, + "@msgpackr-extract/msgpackr-extract-darwin-x64": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.2.tgz", + "integrity": "sha512-lwriRAHm1Yg4iDf23Oxm9n/t5Zpw1lVnxYU3HnJPTi2lJRkKTrps1KVgvL6m7WvmhYVt/FIsssWay+k45QHeuw==", + "optional": true + }, + "@msgpackr-extract/msgpackr-extract-linux-arm": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.2.tgz", + "integrity": "sha512-MOI9Dlfrpi2Cuc7i5dXdxPbFIgbDBGgKR5F2yWEa6FVEtSWncfVNKW5AKjImAQ6CZlBK9tympdsZJ2xThBiWWA==", + "optional": true + }, + "@msgpackr-extract/msgpackr-extract-linux-arm64": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.2.tgz", + "integrity": "sha512-FU20Bo66/f7He9Fp9sP2zaJ1Q8L9uLPZQDub/WlUip78JlPeMbVL8546HbZfcW9LNciEXc8d+tThSJjSC+tmsg==", + "optional": true + }, + "@msgpackr-extract/msgpackr-extract-linux-x64": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.2.tgz", + "integrity": "sha512-gsWNDCklNy7Ajk0vBBf9jEx04RUxuDQfBse918Ww+Qb9HCPoGzS+XJTLe96iN3BVK7grnLiYghP/M4L8VsaHeA==", + "optional": true + }, + "@msgpackr-extract/msgpackr-extract-win32-x64": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.2.tgz", + "integrity": "sha512-O+6Gs8UeDbyFpbSh2CPEz/UOrrdWPTBYNblZK5CxxLisYt4kGX3Sc+czffFonyjiGSq3jWLwJS/CCJc7tBr4sQ==", + "optional": true + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -26638,6 +26759,11 @@ } } }, + "@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" + }, "@swc/helpers": { "version": "0.4.14", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", @@ -26700,11 +26826,6 @@ "resolved": "https://registry.npmjs.org/@types/common-tags/-/common-tags-1.8.1.tgz", "integrity": "sha512-20R/mDpKSPWdJs5TOpz3e7zqbeCNuMCPhV7Yndk9KU2Rbij2r5W4RzwDPkzC+2lzUqXYu9rFzTktCBnDjHuNQg==" }, - "@types/component-emitter": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", - "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==" - }, "@types/configstore": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/@types/configstore/-/configstore-2.1.1.tgz", @@ -26716,9 +26837,12 @@ "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" }, "@types/cors": { - "version": "2.8.12", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", - "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==" + "version": "2.8.13", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", + "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", + "requires": { + "@types/node": "*" + } }, "@types/debug": { "version": "0.0.30", @@ -26744,9 +26868,9 @@ } }, "@types/estree": { - "version": "0.0.50", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz", - "integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==" + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==" }, "@types/get-port": { "version": "3.2.0", @@ -26980,9 +27104,9 @@ }, "dependencies": { "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "requires": { "lru-cache": "^6.0.0" } @@ -27042,9 +27166,9 @@ }, "dependencies": { "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "requires": { "lru-cache": "^6.0.0" } @@ -27619,9 +27743,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, @@ -27731,11 +27855,6 @@ "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" }, - "backo2": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", - "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" - }, "bail": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", @@ -27754,11 +27873,6 @@ "safe-buffer": "^5.0.1" } }, - "base64-arraybuffer": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz", - "integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI=" - }, "base64-js": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", @@ -28771,11 +28885,6 @@ "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" - }, "compressible": { "version": "2.0.18", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", @@ -29067,9 +29176,9 @@ } }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "requires": { "lru-cache": "^6.0.0" } @@ -30165,48 +30274,43 @@ } }, "engine.io": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-4.1.2.tgz", - "integrity": "sha512-t5z6zjXuVLhXDMiFJPYsPOWEER8B0tIsD3ETgw19S1yg9zryvUfY3Vhtk3Gf4sihw/bQGIqQ//gjvVlu+Ca0bQ==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.2.1.tgz", + "integrity": "sha512-ECceEFcAaNRybd3lsGQKas3ZlMVjN3cyWwMP25D2i0zWfyiytVbTpRPa34qrr+FHddtpBVOmq4H/DCv1O0lZRA==", "requires": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", "accepts": "~1.3.4", "base64id": "2.0.0", "cookie": "~0.4.1", "cors": "~2.8.5", "debug": "~4.3.1", - "engine.io-parser": "~4.0.0", - "ws": "~7.4.2" + "engine.io-parser": "~5.0.3", + "ws": "~8.2.3" } }, "engine.io-client": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-4.1.4.tgz", - "integrity": "sha512-843fqAdKeUMFqKi1sSjnR11tJ4wi8sIefu6+JC1OzkkJBmjtc/gM/rZ53tJfu5Iae/3gApm5veoS+v+gtT0+Fg==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.2.3.tgz", + "integrity": "sha512-aXPtgF1JS3RuuKcpSrBtimSjYvrbhKW9froICH4s0F3XQWLxsKNxqzG39nnvQZQnva4CMvUK63T7shevxRyYHw==", "requires": { - "base64-arraybuffer": "0.1.4", - "component-emitter": "~1.3.0", + "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1", - "engine.io-parser": "~4.0.1", - "has-cors": "1.1.0", - "parseqs": "0.0.6", - "parseuri": "0.0.6", - "ws": "~7.4.2", - "xmlhttprequest-ssl": "~1.6.2", - "yeast": "0.1.2" + "engine.io-parser": "~5.0.3", + "ws": "~8.2.3", + "xmlhttprequest-ssl": "~2.0.0" } }, "engine.io-parser": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-4.0.3.tgz", - "integrity": "sha512-xEAAY0msNnESNPc00e19y5heTPX4y/TJ36gr8t1voOaNmTojP9b3oK3BbJLFufW2XFPQaaijpFewm2g2Um3uqA==", - "requires": { - "base64-arraybuffer": "0.1.4" - } + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.7.tgz", + "integrity": "sha512-P+jDFbvK6lE3n1OL+q9KuzdOFWkkZ/cMV9gol/SbVfpyqfvrfrFTOFJ6fQm2VC3PZHlU3QPhVwmbsCnauHF2MQ==" }, "enhanced-resolve": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz", - "integrity": "sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA==", + "version": "5.12.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", + "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", "requires": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -30312,20 +30416,14 @@ } }, "es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "version": "0.10.63", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.63.tgz", + "integrity": "sha512-hUCZd2Byj/mNKjfP9jXrdVZ62B8KuA/VoK7X8nUh5qT+AxDmcbvZz041oDVZdbIN1qW6XY9VDNwzkvKnZvK2TQ==", "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" - }, - "dependencies": { - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" - } + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "esniff": "^2.0.1", + "next-tick": "^1.1.0" } }, "es6-iterator": { @@ -30527,9 +30625,9 @@ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "requires": { "lru-cache": "^6.0.0" } @@ -30745,9 +30843,9 @@ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, @@ -30790,9 +30888,9 @@ } }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, @@ -30886,6 +30984,24 @@ } } }, + "esniff": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", + "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", + "requires": { + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "event-emitter": "^0.3.5", + "type": "^2.7.2" + }, + "dependencies": { + "type": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" + } + } + }, "espree": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", @@ -31468,9 +31584,9 @@ "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" }, "follow-redirects": { - "version": "1.14.8", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", - "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==" + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==" }, "fork-ts-checker-webpack-plugin": { "version": "6.5.2", @@ -31558,9 +31674,9 @@ } }, "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "requires": { "lru-cache": "^6.0.0" } @@ -31658,9 +31774,9 @@ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" }, "gatsby": { - "version": "4.25.0", - "resolved": "https://registry.npmjs.org/gatsby/-/gatsby-4.25.0.tgz", - "integrity": "sha512-zR/u0X60Ww250XqHGytAVFDfFJUpDzMnbPHQ7uAqr6zLgU03DBKyjqKiRpFsGx7L7ENj61hdorjz12IiNj6DIw==", + "version": "4.25.7", + "resolved": "https://registry.npmjs.org/gatsby/-/gatsby-4.25.7.tgz", + "integrity": "sha512-kspM1XokxDw2YqC2hkPKQTfWSNSq/AnY8PNYSrUM+MCsyIKFuGqSVchNonZN1g8/nCoh4jQpBYXH5Uw2Hrs6Sw==", "requires": { "@babel/code-frame": "^7.14.0", "@babel/core": "^7.15.5", @@ -31748,7 +31864,7 @@ "gatsby-legacy-polyfills": "^2.25.0", "gatsby-link": "^4.25.0", "gatsby-page-utils": "^2.25.0", - "gatsby-parcel-config": "^0.16.0", + "gatsby-parcel-config": "0.16.0", "gatsby-plugin-page-creator": "^4.25.0", "gatsby-plugin-typescript": "^4.25.0", "gatsby-plugin-utils": "^3.19.0", @@ -31808,8 +31924,8 @@ "shallow-compare": "^1.2.2", "signal-exit": "^3.0.5", "slugify": "^1.6.1", - "socket.io": "3.1.2", - "socket.io-client": "3.1.3", + "socket.io": "4.5.4", + "socket.io-client": "4.5.4", "st": "^2.0.0", "stack-trace": "^0.0.10", "string-similarity": "^1.2.2", @@ -31827,7 +31943,7 @@ "webpack-stats-plugin": "^1.0.3", "webpack-virtual-modules": "^0.3.2", "xstate": "4.32.1", - "yaml-loader": "^0.6.0" + "yaml-loader": "^0.8.0" }, "dependencies": { "@babel/helper-plugin-utils": { @@ -32061,9 +32177,9 @@ } }, "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "requires": { "lru-cache": "^6.0.0" } @@ -32227,9 +32343,9 @@ } }, "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "requires": { "lru-cache": "^6.0.0" } @@ -32428,9 +32544,9 @@ }, "dependencies": { "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "requires": { "lru-cache": "^6.0.0" } @@ -32807,25 +32923,22 @@ } }, "gatsby-plugin-sharp": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/gatsby-plugin-sharp/-/gatsby-plugin-sharp-4.24.0.tgz", - "integrity": "sha512-wVs8F9zLeiLf02yLi8vjse1vqSrZsx2u3RsMhoSv1bEinyaI5bcoLZ7mMJCsEeZe2G9mvNrPi4Ymhh/YzgxYCg==", + "version": "4.25.1", + "resolved": "https://registry.npmjs.org/gatsby-plugin-sharp/-/gatsby-plugin-sharp-4.25.1.tgz", + "integrity": "sha512-cGRb8lmwJkzwT1Qze0R+VL+55BIb9weM17m+dUf6gs5Z++lQltqge+L8a1qWWsGL6KfLQN7+bIqjhmTTscIPMQ==", "requires": { "@babel/runtime": "^7.15.4", - "@gatsbyjs/potrace": "^2.3.0", "async": "^3.2.4", "bluebird": "^3.7.2", "debug": "^4.3.4", "filenamify": "^4.3.0", "fs-extra": "^10.1.0", - "gatsby-core-utils": "^3.24.0", - "gatsby-plugin-utils": "^3.18.0", + "gatsby-core-utils": "^3.25.0", + "gatsby-plugin-utils": "^3.19.0", "lodash": "^4.17.21", - "mini-svg-data-uri": "^1.4.4", "probe-image-size": "^7.2.3", "semver": "^7.3.7", - "sharp": "^0.30.7", - "svgo": "^2.8.0" + "sharp": "^0.30.7" }, "dependencies": { "async": { @@ -32853,9 +32966,9 @@ } }, "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "requires": { "lru-cache": "^6.0.0" } @@ -33291,9 +33404,9 @@ } }, "gatsby-remark-responsive-iframe": { - "version": "5.24.0", - "resolved": "https://registry.npmjs.org/gatsby-remark-responsive-iframe/-/gatsby-remark-responsive-iframe-5.24.0.tgz", - "integrity": "sha512-gfLeeRol5Y35vuSxwVr9nRwGylZQmty4BmwzFJJkUwdUa0lI1P8X0Nhu9OY4WEnzLF4aeTMDUECnfsVzXi0/Tw==", + "version": "5.25.0", + "resolved": "https://registry.npmjs.org/gatsby-remark-responsive-iframe/-/gatsby-remark-responsive-iframe-5.25.0.tgz", + "integrity": "sha512-K2a0k0Q2umJA1lDtSoq3MM4QB1OGdAMSIbFtS/P9dXjg8rHDvnZGach6iDB8dF3fpjpl7LH3tr/DYAZBPHTqog==", "requires": { "@babel/runtime": "^7.15.4", "cheerio": "^1.0.0-rc.10", @@ -33711,9 +33824,9 @@ } }, "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "requires": { "lru-cache": "^6.0.0" } @@ -33726,9 +33839,9 @@ } }, "gatsby-transformer-yaml": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/gatsby-transformer-yaml/-/gatsby-transformer-yaml-4.21.0.tgz", - "integrity": "sha512-zq1ZDhGLZvPjCckz1jyBQqYU8Dj1dr0BCHGoZK4s/HmKVjoP2PCTbEGvUOXJv/3rzcZ4TPZczLC9McpLFhtRvA==", + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/gatsby-transformer-yaml/-/gatsby-transformer-yaml-4.25.0.tgz", + "integrity": "sha512-upmV5yAqvyDE7WvpMtG0LWlTLHk1lFivP82iL9iwKHRf/bn21iAafiFADyh0RCENnXbK0xxY4mM8UDvAXu3v3g==", "requires": { "@babel/runtime": "^7.15.4", "js-yaml": "^3.14.1", @@ -34160,11 +34273,6 @@ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==" }, - "has-cors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", - "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -35034,6 +35142,11 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, + "javascript-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-2.1.0.tgz", + "integrity": "sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==" + }, "jest-worker": { "version": "26.6.2", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", @@ -35125,6 +35238,11 @@ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -35530,9 +35648,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, @@ -36371,11 +36489,6 @@ } } }, - "mini-svg-data-uri": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", - "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==" - }, "minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -36445,21 +36558,34 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "msgpackr": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.5.4.tgz", - "integrity": "sha512-Z7w5Jg+2Q9z9gJxeM68d7tSuWZZGnFIRhZnyqcZCa/1dKkhOCNvR1TUV3zzJ3+vj78vlwKRzUgVDlW4jiSOeDA==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.10.1.tgz", + "integrity": "sha512-r5VRLv9qouXuLiIBrLpl2d5ZvPt8svdQTl5/vMvE4nzDMyEX4sgW5yWhuBBj5UmgwOTWj8CIdSXn5sAfsHAWIQ==", "requires": { - "msgpackr-extract": "^1.0.14" + "msgpackr-extract": "^3.0.2" } }, "msgpackr-extract": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-1.0.16.tgz", - "integrity": "sha512-fxdRfQUxPrL/TizyfYfMn09dK58e+d65bRD/fcaVH4052vj30QOzzqxcQIS7B0NsqlypEQ/6Du3QmP2DhWFfCA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.2.tgz", + "integrity": "sha512-SdzXp4kD/Qf8agZ9+iTu6eql0m3kWm1A2y1hkpTeVNENutaB0BwHlSvAIaMxwntmRUAUjon2V4L8Z/njd0Ct8A==", "optional": true, "requires": { - "nan": "^2.14.2", - "node-gyp-build": "^4.2.3" + "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.2", + "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.2", + "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.2", + "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.2", + "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.2", + "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.2", + "node-gyp-build-optional-packages": "5.0.7" + }, + "dependencies": { + "node-gyp-build-optional-packages": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.0.7.tgz", + "integrity": "sha512-YlCCc6Wffkx0kHkmam79GKvDQ6x+QZkMjFGrIMxgFNILFvGSbCp2fCBC55pGTT9gVaz8Na5CLmxt/urtzRv36w==", + "optional": true + } } }, "multer": { @@ -36491,16 +36617,10 @@ "thenify-all": "^1.0.0" } }, - "nan": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", - "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==", - "optional": true - }, "nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==" + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==" }, "napi-build-utils": { "version": "1.0.2", @@ -36574,9 +36694,9 @@ }, "dependencies": { "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "requires": { "lru-cache": "^6.0.0" } @@ -37004,9 +37124,9 @@ } }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, @@ -37115,16 +37235,6 @@ "parse5": "^6.0.1" } }, - "parseqs": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz", - "integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==" - }, - "parseuri": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz", - "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==" - }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -37325,11 +37435,11 @@ } }, "postcss": { - "version": "8.4.20", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.20.tgz", - "integrity": "sha512-6Q04AXR1212bXr5fh03u8aAwbLxAQNGQ/Q1LNa0VfOI06ZAlhPHtQvE4OIdpj4kLThXilalPnmDSOD65DcHt+g==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "requires": { - "nanoid": "^3.3.4", + "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } @@ -37357,9 +37467,9 @@ } }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "requires": { "lru-cache": "^6.0.0" } @@ -38883,9 +38993,9 @@ } }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" }, "semver-diff": { "version": "3.1.1", @@ -38896,9 +39006,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, @@ -39041,9 +39151,9 @@ "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" }, "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "requires": { "lru-cache": "^6.0.0" } @@ -39208,47 +39318,40 @@ } }, "socket.io": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-3.1.2.tgz", - "integrity": "sha512-JubKZnTQ4Z8G4IZWtaAZSiRP3I/inpy8c/Bsx2jrwGrTbKeVU5xd6qkKMHpChYeM3dWZSO0QACiGK+obhBNwYw==", + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.5.4.tgz", + "integrity": "sha512-m3GC94iK9MfIEeIBfbhJs5BqFibMtkRk8ZpKwG2QwxV0m/eEhPIV4ara6XCF1LWNAus7z58RodiZlAH71U3EhQ==", "requires": { - "@types/cookie": "^0.4.0", - "@types/cors": "^2.8.8", - "@types/node": ">=10.0.0", "accepts": "~1.3.4", "base64id": "~2.0.0", - "debug": "~4.3.1", - "engine.io": "~4.1.0", - "socket.io-adapter": "~2.1.0", - "socket.io-parser": "~4.0.3" + "debug": "~4.3.2", + "engine.io": "~6.2.1", + "socket.io-adapter": "~2.4.0", + "socket.io-parser": "~4.2.1" } }, "socket.io-adapter": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.1.0.tgz", - "integrity": "sha512-+vDov/aTsLjViYTwS9fPy5pEtTkrbEKsw2M+oVSoFGw6OD1IpvlV1VPhUzNbofCQ8oyMbdYJqDtGdmHQK6TdPg==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.4.0.tgz", + "integrity": "sha512-W4N+o69rkMEGVuk2D/cvca3uYsvGlMwsySWV447y99gUPghxq42BxqLNMndb+a1mm/5/7NeXVQS7RLa2XyXvYg==" }, "socket.io-client": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-3.1.3.tgz", - "integrity": "sha512-4sIGOGOmCg3AOgGi7EEr6ZkTZRkrXwub70bBB/F0JSkMOUFpA77WsL87o34DffQQ31PkbMUIadGOk+3tx1KGbw==", + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.5.4.tgz", + "integrity": "sha512-ZpKteoA06RzkD32IbqILZ+Cnst4xewU7ZYK12aS1mzHftFFjpoMz69IuhP/nL25pJfao/amoPI527KnuhFm01g==", "requires": { - "@types/component-emitter": "^1.2.10", - "backo2": "~1.0.2", - "component-emitter": "~1.3.0", - "debug": "~4.3.1", - "engine.io-client": "~4.1.0", - "parseuri": "0.0.6", - "socket.io-parser": "~4.0.4" + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.2.3", + "socket.io-parser": "~4.2.1" } }, "socket.io-parser": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.5.tgz", - "integrity": "sha512-sNjbT9dX63nqUFIOv95tTVm6elyIU4RvB1m8dOeZt+IgWwcWklFDOdmGcfo3zSiRsnR/3pJkjY5lfoGqEe4Eig==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", "requires": { - "@types/component-emitter": "^1.2.10", - "component-emitter": "~1.3.0", + "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1" } }, @@ -39657,9 +39760,9 @@ } }, "stylis": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.0.13.tgz", - "integrity": "sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag==" + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" }, "sucrase": { "version": "3.21.0", @@ -40687,9 +40790,9 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "requires": { "lru-cache": "^6.0.0" } @@ -40873,9 +40976,9 @@ } }, "watchpack": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", - "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", "requires": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -40902,40 +41005,40 @@ "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" }, "webpack": { - "version": "5.68.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.68.0.tgz", - "integrity": "sha512-zUcqaUO0772UuuW2bzaES2Zjlm/y3kRBQDVFVCge+s2Y8mwuUTdperGaAv65/NtRL/1zanpSJOq/MD8u61vo6g==", + "version": "5.76.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.1.tgz", + "integrity": "sha512-4+YIK4Abzv8172/SGqObnUjaIHjLEuUasz9EwQj/9xmPPkYJy2Mh03Q/lJfSD3YLzbxy5FeTq5Uw0323Oh6SJQ==", "requires": { - "@types/eslint-scope": "^3.7.0", - "@types/estree": "^0.0.50", + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", "@webassemblyjs/ast": "1.11.1", "@webassemblyjs/wasm-edit": "1.11.1", "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.4.1", + "acorn": "^8.7.1", "acorn-import-assertions": "^1.7.6", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.8.3", + "enhanced-resolve": "^5.10.0", "es-module-lexer": "^0.9.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.9", - "json-parse-better-errors": "^1.0.2", + "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", "schema-utils": "^3.1.0", "tapable": "^2.1.1", "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.3.1", + "watchpack": "^2.4.0", "webpack-sources": "^3.2.3" }, "dependencies": { "acorn": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", - "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==" + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==" }, "acorn-import-assertions": { "version": "1.8.0", @@ -41169,9 +41272,9 @@ "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==" }, "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", + "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==" }, "workbox-background-sync": { "version": "4.3.1", @@ -41374,9 +41477,9 @@ } }, "ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", "requires": {} }, "x-is-string": { @@ -41390,9 +41493,9 @@ "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==" }, "xmlhttprequest-ssl": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.6.3.tgz", - "integrity": "sha512-3XfeQE/wNkvrIktn2Kf0869fC0BN6UpydVasGIeSm2B1Llihf7/0UfZM+eCkOw3P7bP4+qPgqhm7ZoxuJtFU0Q==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", + "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==" }, "xss": { "version": "1.0.8", @@ -41434,12 +41537,30 @@ "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==" }, "yaml-loader": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/yaml-loader/-/yaml-loader-0.6.0.tgz", - "integrity": "sha512-1bNiLelumURyj+zvVHOv8Y3dpCri0F2S+DCcmps0pA1zWRLjS+FhZQg4o3aUUDYESh73+pKZNI18bj7stpReow==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/yaml-loader/-/yaml-loader-0.8.0.tgz", + "integrity": "sha512-LjeKnTzVBKWiQBeE2L9ssl6WprqaUIxCSNs5tle8PaDydgu3wVFXTbMfsvF2MSErpy9TDVa092n4q6adYwJaWg==", "requires": { - "loader-utils": "^1.4.0", - "yaml": "^1.8.3" + "javascript-stringify": "^2.0.1", + "loader-utils": "^2.0.0", + "yaml": "^2.0.0" + }, + "dependencies": { + "loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "yaml": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", + "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==" + } } }, "yargs": { @@ -41478,11 +41599,6 @@ "fd-slicer": "~1.1.0" } }, - "yeast": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", - "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" - }, "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/docs/package.json b/docs/package.json index 5cf838702791..e062f6224bac 100644 --- a/docs/package.json +++ b/docs/package.json @@ -6,11 +6,11 @@ "author": "", "license": "MIT", "dependencies": { - "@emotion/react": "^11.10.4", + "@emotion/react": "^11.11.0", "@emotion/styled": "^11.10.0", "@mdx-js/mdx": "^1.6.22", "@mdx-js/react": "^1.6.16", - "gatsby": "^4.25.0", + "gatsby": "^4.25.7", "gatsby-alias-imports": "^1.0.6", "gatsby-plugin-canonical-urls": "^4.25.0", "gatsby-plugin-catch-links": "^4.21.0", @@ -22,20 +22,20 @@ "gatsby-plugin-react-helmet": "^5.21.0", "gatsby-plugin-react-svg": "^3.1.0", "gatsby-plugin-robots-txt": "^1.7.1", - "gatsby-plugin-sharp": "^4.24.0", + "gatsby-plugin-sharp": "^4.25.1", "gatsby-plugin-sitemap": "^5.24.0", "gatsby-remark-autolink-headers": "^5.24.0", "gatsby-remark-copy-linked-files": "^5.24.0", "gatsby-remark-external-links": "^0.0.4", "gatsby-remark-images": "^6.25.0", "gatsby-remark-mermaid": "^2.1.0", - "gatsby-remark-responsive-iframe": "^5.24.0", + "gatsby-remark-responsive-iframe": "^5.25.0", "gatsby-source-filesystem": "^4.22.0", "gatsby-transformer-remark": "^5.25.1", "gatsby-transformer-sharp": "^4.21.0", - "gatsby-transformer-yaml": "^4.21.0", + "gatsby-transformer-yaml": "^4.25.0", "polished": "^4.2.2", - "postcss": "^8.4.20", + "postcss": "^8.4.31", "prism-react-renderer": "^1.3.5", "prop-types": "^15.8.1", "puppeteer": "^13.7.0", @@ -51,7 +51,7 @@ "gatsby-plugin-netlify": "^5.1.0" }, "scripts": { - "build": "make -C .. expand_website_templates && gatsby build", + "build": "make -C .. website_expand_templates website_copy_jsonschema && gatsby build", "start": "gatsby develop", "serve": "gatsby serve", "clean": "gatsby clean" diff --git a/docs/src/config/sidebar.yml b/docs/src/config/sidebar.yml index b034cdb4c1b2..93030648c859 100644 --- a/docs/src/config/sidebar.yml +++ b/docs/src/config/sidebar.yml @@ -2,32 +2,36 @@ - label: "Introduction" link: "/" -- label: Usage +- label: Welcome items: - label: "Install" - link: "/usage/install/" + link: "/welcome/install/" - label: "Quick Start" - link: "/usage/quick-start/" + link: "/welcome/quick-start/" - label: "Integrations" - link: "/usage/integrations/" - - label: "Linters" - link: "/usage/linters/" + link: "/welcome/integrations/" + - label: "FAQ" + link: "/welcome/faq/" +- label: Usage + items: - label: "Configuration" link: "/usage/configuration/" + - label: "Linters" + link: "/usage/linters/" - label: "False Positives" link: "/usage/false-positives/" - - label: "Performance" - link: "/usage/performance/" - - label: "FAQ" - link: "/usage/faq/" - label: Product items: - - label: "Roadmap" - link: "/product/roadmap/" - label: "Thanks" link: "/product/thanks/" - label: "Trusted By" link: "/product/trusted-by/" + - label: "Changelog" + link: "/product/changelog/" + - label: "Roadmap" + link: "/product/roadmap/" + - label: "Performance" + link: "/product/performance/" - label: "GitHub" link: "https://github.com/golangci/golangci-lint" - label: Contributing @@ -46,3 +50,10 @@ link: /contributing/faq/ - label: This Website link: /contributing/website/ +- label: Plugins + items: + - label: Module Plugin System + link: /plugins/module-plugins/ + - label: Go Plugin System + link: /plugins/go-plugins/ + diff --git a/docs/src/docs/contributing/architecture.mdx b/docs/src/docs/contributing/architecture.mdx index 5a48b3d3e340..ad4dc3fd2481 100644 --- a/docs/src/docs/contributing/architecture.mdx +++ b/docs/src/docs/contributing/architecture.mdx @@ -24,88 +24,16 @@ graph LR ## Init -The execution starts here: +The configuration is loaded from file and flags by `config.Loader` inside `PersistentPreRun` (or `PreRun`) of the commands that require configuration. -```go title=cmd/golangci-lint/main.go -func main() { - e := commands.NewExecutor(version, commit, date) - - if err := e.Execute(); err != nil { - fmt.Fprintf(os.Stderr, "failed executing command with error %v\n", err) - os.Exit(exitcodes.Failure) - } -} -``` - -The **executer** is our abstraction: - -```go title=pkg/commands/executor.go -type Executor struct { - rootCmd *cobra.Command - runCmd *cobra.Command - lintersCmd *cobra.Command - - exitCode int - - cfg *config.Config - log logutils.Log - reportData report.Data - DBManager *lintersdb.Manager - EnabledLintersSet *lintersdb.EnabledSet - contextLoader *lint.ContextLoader - goenv *goutil.Env - fileCache *fsutils.FileCache - lineCache *fsutils.LineCache - pkgCache *pkgcache.Cache - debugf logutils.DebugFunc - sw *timeutils.Stopwatch - - loadGuard *load.Guard - flock *flock.Flock -} -``` - -We use dependency injection and all root dependencies are stored in this executor. - -In the function `NewExecutor` we do the following: - -1. init dependencies -2. init [cobra](https://github.com/spf13/cobra) commands -3. parse config file using [viper](https://github.com/spf13/viper) and merge it with command line args. - -The following execution is controlled by `cobra`. If a user executes `golangci-lint run` -then `cobra` executes `e.runCmd`. - -Different `cobra` commands have different runners, e.g. a `run` command is configured in the following way: - -```go title=pkg/commands/run.go -func (e *Executor) initRun() { - e.runCmd = &cobra.Command{ - Use: "run", - Short: welcomeMessage, - Run: e.executeRun, - PreRun: func(_ *cobra.Command, _ []string) { - if ok := e.acquireFileLock(); !ok { - e.log.Fatalf("Parallel golangci-lint is running") - } - }, - PostRun: func(_ *cobra.Command, _ []string) { - e.releaseFileLock() - }, - } - e.rootCmd.AddCommand(e.runCmd) - e.runCmd.SetOutput(logutils.StdOut) // use custom output to properly color it in Windows terminals - e.initRunConfiguration(e.runCmd) -} -``` - -The primary execution function of the `run` command is `executeRun`. +The linter database (`linterdb.Manager`) is fill based on the configuration: +- The linters ("internals" and plugins) are built by `linterdb.LinterBuilder` and `linterdb.PluginBuilder` builders. +- The configuration is validated by `linterdb.Validator`. ## Load Packages Loading packages is listing all packages and their recursive dependencies for analysis. -Also, depending on the enabled linters set some parsing of the source code can be performed -at this step. +Also, depending on the enabled linters set some parsing of the source code can be performed at this step. Packages loading starts here: @@ -114,13 +42,13 @@ func (cl *ContextLoader) Load(ctx context.Context, linters []*linter.Config) (*l loadMode := cl.findLoadMode(linters) pkgs, err := cl.loadPackages(ctx, loadMode) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to load packages: %w", err) } - // ... - ret := &linter.Context{ - // ... - } + // ... + ret := &linter.Context{ + // ... + } return ret, nil } ``` @@ -142,10 +70,11 @@ func (lc *Config) WithLoadFiles() *Config { If a linter uses `go/analysis` and needs type information, we need to extract more data by `go/packages`: -```go title=/pkg/lint/linter/config.go +```go title=pkg/lint/linter/config.go func (lc *Config) WithLoadForGoAnalysis() *Config { lc = lc.WithLoadFiles() - lc.LoadMode |= packages.NeedImports | packages.NeedDeps | packages.NeedExportsFile | packages.NeedTypesSizes + lc.LoadMode |= packages.NeedImports | packages.NeedDeps | packages.NeedExportFile | packages.NeedTypesSizes + lc.IsSlow = true return lc } ``` @@ -157,41 +86,44 @@ and outputs list of packages and requested information about them: filenames, ty First, we need to find all enabled linters. All linters are registered here: -```go title=pkg/lint/lintersdb/manager.go -func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { - // ... - lcs := []*linter.Config{ +```go title=pkg/lint/lintersdb/builder_linter.go +func (b LinterBuilder) Build(cfg *config.Config) []*linter.Config { + // ... + return []*linter.Config{ + // ... + linter.NewConfig(golinters.NewBodyclose()). + WithSince("v1.18.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetPerformance, linter.PresetBugs). + WithURL("https://github.com/timakin/bodyclose"), + // ... linter.NewConfig(golinters.NewGovet(govetCfg)). + WithEnabledByDefault(). + WithSince("v1.0.0"). WithLoadForGoAnalysis(). - WithPresets(linter.PresetBugs). + WithPresets(linter.PresetBugs, linter.PresetMetaLinter). WithAlternativeNames("vet", "vetshadow"). WithURL("https://pkg.go.dev/cmd/vet"), - linter.NewConfig(golinters.NewBodyclose()). - WithLoadForGoAnalysis(). - WithPresets(linter.PresetPerformance, linter.PresetBugs). - WithURL("https://github.com/timakin/bodyclose"), - // ... - } - // ... + // ... + } } ``` We filter requested in config and command-line linters in `EnabledSet`: -```go title=pkg/lint/lintersdb/enabled_set.go -func (es EnabledSet) GetEnabledLintersMap() (map[string]*linter.Config, error) +```go title=pkg/lint/lintersdb/manager.go +func (m *Manager) GetEnabledLintersMap() (map[string]*linter.Config, error) ``` We merge enabled linters into one `MetaLinter` to improve execution time if we can: -```go title=pkg/lint/lintersdb/enabled_set.go -// GetOptimizedLinters returns enabled linters after optimization (merging) of multiple linters -// into a fewer number of linters. E.g. some go/analysis linters can be optimized into -// one metalinter for data reuse and speed up. -func (es EnabledSet) GetOptimizedLinters() ([]*linter.Config, error) { - // ... - es.combineGoAnalysisLinters(resultLintersSet) - // ... +```go titlepkg/lint/lintersdb/manager.go +// GetOptimizedLinters returns enabled linters after optimization (merging) of multiple linters into a fewer number of linters. +// E.g. some go/analysis linters can be optimized into one metalinter for data reuse and speed up. +func (m *Manager) GetOptimizedLinters() ([]*linter.Config, error) { + // ... + m.combineGoAnalysisLinters(resultLintersSet) + // ... } ``` @@ -207,9 +139,11 @@ type MetaLinter struct { Currently, all linters except `unused` can be merged into this meta linter. The `unused` isn't merged because it has high memory usage. -Linters execution starts in `runAnalyzers`. It's the most complex part of the `golangci-lint`. -We use custom [go/analysis](https://pkg.go.dev/golang.org/x/tools/go/analysis) runner there. It runs as much as it can in parallel. It lazy-loads as much as it can -to reduce memory usage. Also, it sets all heavyweight data to `nil` as becomes unneeded to save memory. +Linters execution starts in `runAnalyzers`. +It's the most complex part of the `golangci-lint`. +We use custom [go/analysis](https://pkg.go.dev/golang.org/x/tools/go/analysis) runner there. +It runs as much as it can in parallel. It lazy-loads as much as it can to reduce memory usage. +Also, it sets all heavyweight data to `nil` as becomes unneeded to save memory. We don't use existing [multichecker](https://pkg.go.dev/golang.org/x/tools/go/analysis/multichecker) because it doesn't use caching and doesn't have some important performance optimizations. @@ -221,6 +155,8 @@ type Issue struct { FromLinter string Text string + Severity string + // Source lines of a code with the issue to show SourceLines []string @@ -250,8 +186,10 @@ We have an abstraction of `result.Processor` to postprocess found issues: ```sh $ tree -L 1 ./pkg/result/processors/ ./pkg/result/processors/ +./pkg/result/processors/ ├── autogenerated_exclude.go ├── autogenerated_exclude_test.go +├── base_rule.go ├── cgo.go ├── diff.go ├── exclude.go @@ -262,6 +200,7 @@ $ tree -L 1 ./pkg/result/processors/ ├── fixer.go ├── identifier_marker.go ├── identifier_marker_test.go +├── issues.go ├── max_from_linter.go ├── max_from_linter_test.go ├── max_per_file_from_linter.go @@ -270,17 +209,23 @@ $ tree -L 1 ./pkg/result/processors/ ├── max_same_issues_test.go ├── nolint.go ├── nolint_test.go +├── path_prefixer.go +├── path_prefixer_test.go ├── path_prettifier.go ├── path_shortener.go ├── processor.go +├── processor_test.go +├── severity_rules.go +├── severity_rules_test.go ├── skip_dirs.go ├── skip_files.go ├── skip_files_test.go +├── sort_results.go +├── sort_results_test.go ├── source_code.go ├── testdata ├── uniq_by_line.go -├── uniq_by_line_test.go -└── utils.go +└── uniq_by_line_test.go ``` The abstraction is simple: @@ -303,14 +248,24 @@ We have an abstraction for printing found issues. $ tree -L 1 ./pkg/printers/ ./pkg/printers/ ├── checkstyle.go +├── checkstyle_test.go ├── codeclimate.go +├── codeclimate_test.go ├── github.go ├── github_test.go +├── html.go +├── html_test.go ├── json.go +├── json_test.go ├── junitxml.go +├── junitxml_test.go ├── printer.go ├── tab.go -└── text.go +├── tab_test.go +├── teamcity.go +├── teamcity_test.go +├── text.go +└── text_test.go ``` Needed printer is selected by command line option `--out-format`. diff --git a/docs/src/docs/contributing/faq.mdx b/docs/src/docs/contributing/faq.mdx index 9ed95b77dba2..1da0c75a0535 100644 --- a/docs/src/docs/contributing/faq.mdx +++ b/docs/src/docs/contributing/faq.mdx @@ -2,10 +2,6 @@ title: Contributing FAQ --- -## How to write a custom linter - -See [there](/contributing/new-linters#how-to-write-a-custom-linter). - ## How to add a new open-source linter to `golangci-lint` See [there](/contributing/new-linters#how-to-add-a-public-linter-to-golangci-lint). @@ -16,7 +12,7 @@ See [there](/contributing/new-linters#how-to-add-a-private-linter-to-golangci-li ## How to update existing linter -Just update it's version in `go.mod`. +Just update its version in `go.mod`. ## How to add configuration option to existing linter diff --git a/docs/src/docs/contributing/new-linters.mdx b/docs/src/docs/contributing/new-linters.mdx index 55f5c4a065ee..2bdb1ca6be4e 100644 --- a/docs/src/docs/contributing/new-linters.mdx +++ b/docs/src/docs/contributing/new-linters.mdx @@ -2,28 +2,34 @@ title: New linters --- -## How to write a custom linter +## How to write a linter -Use `go/analysis` and take a look at [this tutorial](https://disaev.me/p/writing-useful-go-analysis-linter/): it shows how to write `go/analysis` linter -from scratch and integrate it into `golangci-lint`. +Use `go/analysis` and take a look at [this tutorial](https://disaev.me/p/writing-useful-go-analysis-linter/): +it shows how to write `go/analysis` linter from scratch and integrate it into `golangci-lint`. ## How to add a public linter to `golangci-lint` You need to implement a new linter using `go/analysis` API. -We don't accept not `go/analysis` linters. +We don't accept non `go/analysis` linters. After that: 1. Implement functional tests for the linter: - Add one file into directory [`test/testdata`](https://github.com/golangci/golangci-lint/tree/master/test/testdata). - - Run `T=yourlintername.go make test_linters` to ensure that test fails. - - Run `go run ./cmd/golangci-lint/ run --no-config --disable-all --enable=yourlintername ./test/testdata/yourlintername.go` + - Run the test to ensure that test fails: + ```bash + T=yourlintername.go make test_linters + ``` + - Run: + ```bash + go run ./cmd/golangci-lint/ run --no-config --disable-all --enable=yourlintername ./test/testdata/yourlintername.go + ``` 2. Add a new file `pkg/golinters/{yourlintername}.go`. Look at other linters in this directory. Implement linter integration and check that test passes. 3. Add the new struct for the linter (which you've implemented in `pkg/golinters/{yourlintername}.go`) to the - list of all supported linters in [`pkg/lint/lintersdb/manager.go`](https://github.com/golangci/golangci-lint/blob/master/pkg/lint/lintersdb/manager.go) - to the function `GetAllSupportedLinterConfigs`. + list of all supported linters in [`pkg/lint/lintersdb/builder_linter.go`](https://github.com/golangci/golangci-lint/blob/master/pkg/lint/lintersdb/builder_linter.go) + to the method `LinterBuilder.Build`. - Add `WithSince("next_version")`, where `next_version` must be replaced by the next minor version. (ex: v1.2.0 if the current version is v1.1.0) 4. Find out what options do you need to configure for the linter. For example, `nakedret` has only 1 option: [`max-func-lines`](https://github.com/golangci/golangci-lint/blob/master/.golangci.reference.yml). @@ -33,59 +39,14 @@ After that: if you think that this project needs not default values. - [config struct](https://github.com/golangci/golangci-lint/blob/master/pkg/config/config.go) - don't forget about `mapstructure` tag for proper configuration files parsing by [pflag](https://github.com/spf13/pflag). -5. Take a look at the example of [Pull Request with new linter support](https://github.com/golangci/golangci-lint/pulls?q=is%3Apr+is%3Amerged+label%3A%22linter%3A+new%22). +5. Take a look at the example of [pull requests with new linter support](https://github.com/golangci/golangci-lint/pulls?q=is%3Apr+is%3Amerged+label%3A%22linter%3A+new%22). ## How to add a private linter to `golangci-lint` Some people and organizations may choose to have custom-made linters run as a part of `golangci-lint`. Typically, these linters can't be open-sourced or too specific. -Such linters can be added through Go's plugin library. -For a private linter (which acts as a plugin) to work properly, -the plugin as well as the golangci-lint binary needs to be built for the same environment. `CGO_ENABLED` is another requirement. -This means that `golangci-lint` needs to be built for whatever machine you intend to run it on -(cloning the golangci-lint repository and running a `CGO_ENABLED=1 make build` should do the trick for your machine). +Such linters can be added through 2 plugin systems: -### Configure a Plugin - -If you already have a linter plugin available, you can follow these steps to define it's usage in a projects -`.golangci.yml` file. An example linter can be found at [here](https://github.com/golangci/example-plugin-linter). If you're looking for -instructions on how to configure your own custom linter, they can be found further down. - -1. If the project you want to lint does not have one already, copy the [.golangci.yml](https://github.com/golangci/golangci-lint/blob/master/.golangci.yml) to the root directory. -2. Adjust the yaml to appropriate `linters-settings:custom` entries as so: - -```yaml -linters-settings: - custom: - example: - path: /example.so - description: The description of the linter - original-url: github.com/golangci/example-linter -``` - -That is all the configuration that is required to run a custom linter in your project. Custom linters are enabled by default, -but abide by the same rules as other linters. If the disable all option is specified either on command line or in -`.golangci.yml` files `linters:disable-all: true`, custom linters will be disabled; they can be re-enabled by adding them -to the `linters:enable` list, or providing the enabled option on the command line, `golangci-lint run -Eexample`. - -### Create a Plugin - -Your linter must implement one or more `golang.org/x/tools/go/analysis.Analyzer` structs. -Your project should also use `go.mod`. All versions of libraries that overlap `golangci-lint` (including replaced -libraries) MUST be set to the same version as `golangci-lint`. You can see the versions by running `go version -m golangci-lint`. - -You'll also need to create a go file like `plugin/example.go`. This MUST be in the package `main`, and define a -variable of name `AnalyzerPlugin`. The `AnalyzerPlugin` instance MUST implement the following interface: - -```go -type AnalyzerPlugin interface { - GetAnalyzers() []*analysis.Analyzer -} -``` - -The type of `AnalyzerPlugin` is not important, but is by convention `type analyzerPlugin struct {}`. See -[plugin/example.go](https://github.com/golangci/example-plugin-linter/blob/master/plugin/example.go) for more info. - -To build the plugin, from the root project directory, run `go build -buildmode=plugin plugin/example.go`. This will create a plugin `*.so` -file that can be copied into your project or another well known location for usage in golangci-lint. +1. [Go Plugin System](/plugins/module-plugins) +2. [Module Plugin System](/plugins/go-plugins) diff --git a/docs/src/docs/contributing/website.mdx b/docs/src/docs/contributing/website.mdx index b56757850ff7..aaf68a2e0e50 100644 --- a/docs/src/docs/contributing/website.mdx +++ b/docs/src/docs/contributing/website.mdx @@ -4,8 +4,7 @@ title: Website architecture ## Technology -We use [Gatsby](https://www.gatsbyjs.org/) for static site generation because sites built with it -are very fast. +We use [Gatsby](https://www.gatsbyjs.org/) for static site generation because sites built with it are very fast. This framework uses React and JavaScript/TypeScript. @@ -15,10 +14,9 @@ The website lives in `docs/` directory of [golangci-lint repository](https://git ## Theme -Initially the site is based on [@rocketseat](https://rocketdocs.netlify.app/) theme. -Later we've merged it's code into `src/@rocketseat` because we needed too much changes -and [gatsby shadowing](https://www.gatsbyjs.org/docs/themes/shadowing/) doesn't -allow shadowing `gatsby-node.js` or `gatsby-config.js`. +Initially the site is based on [@rocketseat](https://github.com/jpedroschmitz/rocketdocs) theme. +Later we've merged its code into `src/@rocketseat` because we needed too much changes +and [gatsby shadowing](https://www.gatsbyjs.org/docs/themes/shadowing/) doesn't allow shadowing `gatsby-node.js` or `gatsby-config.js`. ## Navigation @@ -31,29 +29,24 @@ allowing to use `React` components. ## Templating -We use templates like `{.SomeField}` inside our `mdx` files. There templates are expanded -by running `make expand_website_templates` in the root of the repository. -It runs script `scripts/expand_website_templates/main.go` that rewrites `mdx` files with replaced templates. - -## CDN and DNS - -We use [CloudFlare](https://www.cloudflare.com/) for CDN, proxying and DNS management. +We use templates like `{.SomeField}` inside our `mdx` files. +There templates are expanded by running `make website_expand_templates` in the root of the repository. +It runs script `scripts/website/expand_templates/` that rewrites `mdx` files with replaced templates. ## Hosting -We use [Netlify](https://www.netlify.com/) as static website hosting and CD. -It's integrated into our pull requests: if `docs/` directory has changes Netlify -will trigger website rebuild and deploy it's preview for a branch. You can view -it to ensure that everything ok. +We use GitHub Pages as static website hosting and CD. -Netlify deploys the website to production after merging anything to a `master` branch. +GitHub deploys the website to production after merging anything to a `master` branch. ## Local Testing +Install Node.js (v20 or newer). + Run: ```sh -npm install +npm install --legacy-peer-deps npm run start ``` @@ -61,16 +54,10 @@ And navigate to `http://localhost:8000` after successful Gatsby build. There is no need to restart Gatsby server almost for all changes: it supports hot reload. Also, there is no need to refresh a webpage: hot reload updates changed content on the open page. -## Trigger Website Rebuild +## Website Build -Currently, Netlify triggers rebuild only if anything has changes in `docs/` directory. -But we can add a new linter and need to change a documentation to list the linter. - -To do it run +To do it run: ```sh -go run ./scripts/expand_website_templates/main.go -only-state +go run ./scripts/website/expand_templates/ ``` - -It saves a hash of template replacements (that include all linters, configs, etc) -into `docs/template_data.state`. diff --git a/docs/src/docs/contributing/workflow.mdx b/docs/src/docs/contributing/workflow.mdx index a6e8531a6d66..79df46701e69 100644 --- a/docs/src/docs/contributing/workflow.mdx +++ b/docs/src/docs/contributing/workflow.mdx @@ -4,10 +4,9 @@ title: Contributing Workflow # Contributing -By participating to this project, you agree to abide our [code of -conduct](https://github.com/golangci/golangci-lint/blob/master/CODE_OF_CONDUCT.md). +By participating in this project, you agree to abide our [code of conduct](https://github.com/golangci/golangci-lint/blob/master/CODE_OF_CONDUCT.md). -## Setup your machine +## Set up your machine `golangci-lint` is written in [Go](https://go.dev). @@ -46,14 +45,13 @@ Push your branch to your `golangci-lint` fork and open a pull request against th ## Pull request checks -First, please, accept [CLA](https://gist.github.com/jirfag/26a39fd375da84b2d5ad4296fecb0668) - [cla assistant](https://cla-assistant.io/) will -make a comment on the pull request about it. +First, please, accept [CLA](https://gist.github.com/jirfag/26a39fd375da84b2d5ad4296fecb0668) - [cla assistant](https://cla-assistant.io/) will make a comment on the pull request about it. Also, we run a few checks in CI by using GitHub actions, you can see them [here](https://github.com/golangci/golangci-lint/blob/master/.github/workflows/pr.yml). ## New releases -First, see [our versioning policy](/usage/install/#versioning-policy). +First, see [our versioning policy](/product/roadmap/#versioning-policy). To make a new release create a tag `vx.y.z`. Don't forget to add zero patch version for a new minor release, e.g. `v1.99.0`. A GitHub action [workflow](https://github.com/golangci/golangci-lint/blob/master/.github/workflows/tag.yml) will start building and publishing release after that. @@ -61,19 +59,11 @@ A GitHub action [workflow](https://github.com/golangci/golangci-lint/blob/master After making a release you need to update: 1. GitHub [action config](https://github.com/golangci/golangci-lint/blob/master/assets/github-action-config.json) by running: - ```sh make assets/github-action-config.json ``` -2. The latest netlify state (e.g. docs/template_date.state): - -```sh -make update_netlify_state -``` - -3. Contributors list - +2. Contributors list: ```sh make update_contributors_list # may take 15 min ``` diff --git a/docs/src/docs/index.mdx b/docs/src/docs/index.mdx index 537e1e87c4a9..5a862ec576b1 100644 --- a/docs/src/docs/index.mdx +++ b/docs/src/docs/index.mdx @@ -20,14 +20,14 @@ Follow the news and releases on our twitter warning message +- v1.1.0 -> error message +- v1.2.0 -> linter removed + +The deprecated linters are removed from presets immediately when they are deprecated (phase 1). + +We will provide clear information about those changes on different supports: changelog, logs, social network, etc. + +We consider the removal of a linter as non-breaking changes for golangci-lint itself. +No major version will be created when a linter is removed. ## Future Plans diff --git a/docs/src/docs/product/trusted-by.mdx b/docs/src/docs/product/trusted-by.mdx index 2574591ee379..e7a7c399a1fc 100644 --- a/docs/src/docs/product/trusted-by.mdx +++ b/docs/src/docs/product/trusted-by.mdx @@ -20,6 +20,7 @@ The following companies/products use `golangci-lint`: - [ScyllaDB](https://github.com/scylladb/gocqlx) - [Serverless](https://github.com/serverless/event-gateway) - [SoundCloud](https://github.com/soundcloud/periskop) +- [Tekton](http://tekton.dev/) - [The New York Times](https://github.com/NYTimes/encoding-wrapper) - [WooCart](https://github.com/woocart/gsutil) - [Xiaomi](https://github.com/XiaoMi/soar) diff --git a/docs/src/docs/usage/configuration.mdx b/docs/src/docs/usage/configuration.mdx index d3bdfd3e107e..969c0bc62387 100644 --- a/docs/src/docs/usage/configuration.mdx +++ b/docs/src/docs/usage/configuration.mdx @@ -29,7 +29,9 @@ Config options inside the file are identical to command-line options. You can configure specific linters' options only within the config file (not the command-line). There is a [`.golangci.reference.yml`](https://github.com/golangci/golangci-lint/blob/master/.golangci.reference.yml) file with all supported options, their description, and default values. -This file is a neither a working example nor recommended configuration, it's just a reference to display all the configuration options. +This file is neither a working example nor a recommended configuration, it's just a reference to display all the configuration options. + +The configuration file can be validated with the JSON Schema: https://golangci-lint.run/jsonschema/golangci.jsonschema.json { .ConfigurationExample } diff --git a/docs/src/docs/usage/false-positives.mdx b/docs/src/docs/usage/false-positives.mdx index 354aee9f67fa..f72882872a36 100644 --- a/docs/src/docs/usage/false-positives.mdx +++ b/docs/src/docs/usage/false-positives.mdx @@ -53,6 +53,16 @@ issues: text: "mnd: Magic number: 9" ``` +In the following example, all the reports from the linters (`linters`) that originated from the source (`source`) are excluded: + +```yml +issues: + exclude-rules: + - linters: + - lll + source: "^//go:generate " +``` + In the following example, all the reports that contains the text (`text`) in the path (`path`) are excluded: ```yml @@ -66,6 +76,10 @@ issues: Exclude issues in path by `run.skip-dirs`, `run.skip-files` or `issues.exclude-rules` config options. +Beware that the paths that get matched here are relative to the current working directory. +When the configuration contains path patterns that check for specific directories, +the `--path-prefix` parameter can be used to extend the paths before matching. + In the following example, all the reports from the linters (`linters`) that concerns the path (`path`) are excluded: ```yml @@ -77,6 +91,18 @@ issues: - goconst ``` +The opposite, excluding reports **except** for specific paths, is also possible. +In the following example, only test files get checked: + +```yml +issues: + exclude-rules: + - path-except: '(.+)_test\.go' + linters: + - funlen + - goconst +``` + In the following example, all the reports related to the files (`skip-files`) are excluded: ```yml diff --git a/docs/src/docs/usage/faq.mdx b/docs/src/docs/usage/faq.mdx deleted file mode 100644 index f374d706fee7..000000000000 --- a/docs/src/docs/usage/faq.mdx +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: FAQ ---- - -## How do you add a custom linter? - -You can integrate it yourself, see this [manual](/contributing/new-linters/). -Or you can create a [GitHub Issue](https://github.com/golangci/golangci-lint/issues/new) and we will integrate when time permits. - -## How to integrate `golangci-lint` into large project with thousands of issues - -We are sure that every project can easily integrate `golangci-lint`, even the large one. The idea is to not fix all existing issues. Fix only newly added issue: issues in new code. To do this setup CI (or better use [GolangCI](https://golangci.com)) to run `golangci-lint` with option `--new-from-rev=HEAD~1`. Also, take a look at option `--new`, but consider that CI scripts that generate unstaged files will make `--new` only point out issues in those files and not in the last commit. In that regard `--new-from-rev=HEAD~1` is safer. -By doing this you won't create new issues in your code and can choose fix existing issues (or not). - -## How to use `golangci-lint` in CI - -Run `golangci-lint` in CI and check the exit code. If it's non-zero - fail the build. - -See [how to properly install `golangci-lint` in CI](/usage/install#ci-installation) - -## Which Go versions are supported - -The same as the Go team (the 2 last minor versions) - -go1.18+ is officially supported, with some [limitations](https://github.com/golangci/golangci-lint/issues/2649), since golangci-lint v1.45.0. - -## `golangci-lint` doesn't work - -1. Please, ensure you are using the latest binary release. -2. Run it with `-v` option and check the output. -3. If it doesn't help create a [GitHub issue](https://github.com/golangci/golangci-lint/issues/new) with the output from the error and #2 above. - -## Why running with `--fast` is slow on the first run - -Because the first run caches type information. All subsequent runs will be fast. -Usually this options is used during development on local machine and compilation was already performed. diff --git a/docs/src/docs/usage/install/annotations.png b/docs/src/docs/welcome/annotations.png similarity index 100% rename from docs/src/docs/usage/install/annotations.png rename to docs/src/docs/welcome/annotations.png diff --git a/docs/src/docs/welcome/faq.mdx b/docs/src/docs/welcome/faq.mdx new file mode 100644 index 000000000000..53725a244945 --- /dev/null +++ b/docs/src/docs/welcome/faq.mdx @@ -0,0 +1,79 @@ +--- +title: FAQ +--- + +## Which Go versions are supported + +The same as the Go team (the 2 latest minor versions). + +## How to use `golangci-lint` in CI + +Run `golangci-lint` in CI and check the exit code. If it's non-zero - fail the build. + +See [how to properly install `golangci-lint` in CI](/welcome/install/#ci-installation) + +## `golangci-lint` doesn't work + +1. Please, ensure you are using the latest binary release. +2. Run it with `-v` option and check the output. +3. If it doesn't help create a [GitHub issue](https://github.com/golangci/golangci-lint/issues/new) with the output from the error and #2 above. + +## Why do you have `typecheck` errors? + +`typecheck` is like a front-end for the Go compiler errors. +Compilation errors are identified/labeled as reports of `typecheck` but they are not produced by a linter called `typecheck`. + +`typecheck` is not a linter, it doesn't perform any analysis, +it's just a way to identify, parse, and display compiling errors (produced by the `types.Checker`) and some linter errors. + +It cannot be disabled because of that. + +Of course, this is just as good as the compiler itself and a lot of compilation issues will not properly show where in the code your error lies. + +As a consequence, the code to analyze should compile. +It means that if you try to run an analysis on a single file or a group of files or a package or a group of packages, +with dependencies on other files or packages of your project, as it doesn't compile (because of the missing pieces of code), +it also cannot be analyzed. + +If there are `typecheck` errors, golangci-lint will not able to produce other reports because that kind of error doesn't allow it to perform any analysis. + +How to troubleshoot: + +- [ ] Ensure the version of `golangci-lint` is built with a compatible version of Go. +- [ ] Ensure dependencies are up-to-date with `go mod tidy`. +- [ ] Ensure building works with `go run ./...`/`go build ./...` - whole package. +- [ ] Ensure you are not running an analysis on code that depends on files/packages outside the scope of the analyzed elements. +- [ ] If using CGO, ensure all require system libraries are installed. + +## Why running with `--fast` is slow on the first run + +Because the first run caches type information. All subsequent runs will be fast. +Usually this options is used during development on local machine and compilation was already performed. + +## How do you add a custom linter? + +You can integrate it yourself, see this [manual](/contributing/new-linters/). +Or you can create a [GitHub Issue](https://github.com/golangci/golangci-lint/issues/new) and we will integrate when time permits. + +## How to integrate `golangci-lint` into large project with thousands of issues + +We are sure that every project can easily integrate `golangci-lint`, even the large one. + +The idea is to not fix all existing issues. Fix only newly added issue: issues in new code. +To do this setup CI to run `golangci-lint` with option `--new-from-rev=HEAD~1`. + +Also, take a look at option `--new`, but consider that CI scripts that generate unstaged files will make `--new` only point out issues in those files and not in the last commit. +In that regard `--new-from-rev=HEAD~1` is safer. + +By doing this you won't create new issues in your code and can choose fix existing issues (or not). + +## Why `--new-from-rev` or `--new-from-patch` don't seem to be working in some cases? + +The options `--new-from-rev` and `--new-from-patch` work by comparing `git diff` output and issues. + +If an issue is not reported as the same line as the changes then the issue will be skipped. +This is the line of the issue is not inside the lines changed. + +To fix that you have to use the option `--whole-files`. + +The side effect is the issues inside file that contains changes but not directly related to the changes themselves will be reported. diff --git a/docs/src/docs/usage/install/index.mdx b/docs/src/docs/welcome/install.mdx similarity index 64% rename from docs/src/docs/usage/install/index.mdx rename to docs/src/docs/welcome/install.mdx index f101068f18c9..67d15c6ba6f0 100644 --- a/docs/src/docs/usage/install/index.mdx +++ b/docs/src/docs/welcome/install.mdx @@ -44,30 +44,16 @@ and is constantly being improved. For any problems with `golangci-lint`, check o ## Local Installation -### macOS - -You can install a binary release on macOS using [brew](https://brew.sh/): +### Binaries ```sh -brew install golangci-lint -brew upgrade golangci-lint -``` - -Note: Previously we used a [homebrew tap](https://github.com/golangci/homebrew-tap). We recommend using official formula instead of the tap, but sometimes the most recent release -isn't immediately available via homebrew core due to manual updates that need to occur from homebrew core maintainers. In this case, the tap formula, which is updated automatically, -can be used to install the latest version of `golangci-lint`: +# binary will be $(go env GOPATH)/bin/golangci-lint +curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin {.LatestVersion} -```sh -brew tap golangci/tap -brew install golangci/tap/golangci-lint +golangci-lint --version ``` -It can also be installed through [macports](https://www.macports.org/) -The macports installation mode is community driven, and not officially maintained by golangci team. - -```sh -sudo port install golangci-lint -``` +On Windows, you can run the above commands with Git Bash, which comes with [Git for Windows](https://git-scm.com/download/win). ### Docker @@ -85,16 +71,33 @@ Colored output: docker run -t --rm -v $(pwd):/app -w /app golangci/golangci-lint:{.LatestVersion} golangci-lint run -v ``` -### Linux and Windows +### macOS + +Note: brew can use a non-expected version of Go to build the binary, +so we recommend either using our binaries or be sure of the version of Go used to build. + +You can install a binary release on macOS using [brew](https://brew.sh/): ```sh -# binary will be $(go env GOPATH)/bin/golangci-lint -curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin {.LatestVersion} +brew install golangci-lint +brew upgrade golangci-lint +``` -golangci-lint --version +Note: Previously we used a [homebrew tap](https://github.com/golangci/homebrew-tap). We recommend using official formula instead of the tap, but sometimes the most recent release +isn't immediately available via homebrew core due to manual updates that need to occur from homebrew core maintainers. In this case, the tap formula, which is updated automatically, +can be used to install the latest version of `golangci-lint`: + +```sh +brew tap golangci/tap +brew install golangci/tap/golangci-lint ``` -On Windows, you can run the above commands with Git Bash, which comes with [Git for Windows](https://git-scm.com/download/win). +It can also be installed through [macports](https://www.macports.org/) +The macports installation mode is community driven, and not officially maintained by golangci team. + +```sh +sudo port install golangci-lint +``` ### Install from Source @@ -105,12 +108,11 @@ Note: such `go install`/`go get` installation aren't guaranteed to work. We reco `go install`/`go get` installation isn't recommended because of the following points: -1. some users use `-u` flag for `go get`, which upgrades our dependencies. Resulting configuration wasn't tested and isn't guaranteed to work. +1. Some users use `-u` flag for `go get`, which upgrades our dependencies. Resulting configuration wasn't tested and isn't guaranteed to work. 2. [`go.mod`](https://github.com/golangci/golangci-lint/blob/master/go.mod) replacement directive doesn't apply. It means a user will be using patched version of `golangci-lint` if we use such replacements. -3. it's stability depends on a user's Go version (e.g. on [this compiler Go <= 1.12 bug](https://github.com/golang/go/issues/29612)). -4. we've encountered a lot of issues with Go modules hashes. -5. it allows installation from `master` branch which can't be considered stable. -6. it's slower than binary installation +3. We've encountered a lot of issues with Go modules hashes. +4. It allows installation from `master` branch which can't be considered stable. +5. It's slower than binary installation.
@@ -122,33 +124,6 @@ go install github.com/golangci/golangci-lint/cmd/golangci-lint@{.LatestVersion} -## Versioning Policy - -`golangci-lint` follows [semantic versioning](https://semver.org). However, due to the nature of `golangci-lint` as a code quality tool, -it's not always clear when a minor or major version bump occurs. To help clarify this for everyone, we've defined the following semantic versioning policy: - -- Patch release (intended to not break your lint build) - - A patch version update in a specific linter that results in `golangci-lint` reporting fewer errors. - - A bug fix to the CLI or core (packages loading, runner, postprocessors, etc). - - Improvements to documentation. - - Non-user-facing changes such as refactoring code, adding, deleting, or modifying tests, and increasing test coverage. - - Re-releasing after a failed release (i.e., publishing a release that doesn't work for anyone). -- Minor release (might break your lint build because of newly found issues) - - A major or minor version update of a specific linter that results in `golangci-lint` reporting more errors. - - A new linter is added. - - An existing configuration option or linter is deprecated. - - A new CLI command is created. - - Backward incompatible change of configuration with extremely low impact, e.g. adding validation of a list of enabled `go-critic` checkers. -- Major release (likely to break your lint build) - - Backward incompatible change of configuration with huge impact, e.g. removing excluding issues about missed comments from `golint` by default. - - A linter is removed. - -According to our policy, any minor update may report more errors than the previous release (ex: from a bug fix). -As such, we recommend using the fixed minor version and fixed or the latest patch version to guarantee the results of your builds. - -For example, in our [GitHub Action](https://github.com/golangci/golangci-lint-action) we require users to explicitly set the minor version of `golangci-lint` -and we always use the latest patch version. - ## Next -[Quick Start: how to use `golangci-lint`](/usage/quick-start). +[Quick Start: how to use `golangci-lint`](/welcome/quick-start/). diff --git a/docs/src/docs/usage/integrations.mdx b/docs/src/docs/welcome/integrations.mdx similarity index 98% rename from docs/src/docs/usage/integrations.mdx rename to docs/src/docs/welcome/integrations.mdx index 1f347349323a..55acb3c46fa6 100644 --- a/docs/src/docs/usage/integrations.mdx +++ b/docs/src/docs/welcome/integrations.mdx @@ -80,4 +80,4 @@ See the instructions on `golangci-lint completion --help` (replace ## CI Integration -See our [GitHub Action](/usage/install#github-actions). +See our [GitHub Action](/welcome/install/#github-actions). diff --git a/docs/src/docs/usage/quick-start.mdx b/docs/src/docs/welcome/quick-start.mdx similarity index 71% rename from docs/src/docs/usage/quick-start.mdx rename to docs/src/docs/welcome/quick-start.mdx index 2894998c0fc8..e5b1139f7aac 100644 --- a/docs/src/docs/usage/quick-start.mdx +++ b/docs/src/docs/welcome/quick-start.mdx @@ -22,23 +22,17 @@ golangci-lint run dir1 dir2/... dir3/file1.go Directories are NOT analyzed recursively. To analyze them recursively append `/...` to their path. -GolangCI-Lint can be used with zero configuration. By default the following linters are enabled: +GolangCI-Lint can be used with zero configuration. By default, the following linters are enabled: ```sh $ golangci-lint help linters {.LintersCommandOutputEnabledOnly} ``` -and the following linters are disabled by default: - -```sh -$ golangci-lint help linters -... -{.LintersCommandOutputDisabledOnly} -``` - Pass `-E/--enable` to enable linter and `-D/--disable` to disable: ```sh golangci-lint run --disable-all -E errcheck ``` + +More information about available linters can be found in the [linters page](/usage/linters/). diff --git a/docs/static/CNAME b/docs/static/CNAME new file mode 100644 index 000000000000..6c92bff7c490 --- /dev/null +++ b/docs/static/CNAME @@ -0,0 +1 @@ +golangci-lint.run diff --git a/docs/template_data.state b/docs/template_data.state deleted file mode 100755 index 57685585ca6f..000000000000 --- a/docs/template_data.state +++ /dev/null @@ -1,2 +0,0 @@ -This file stores hash of website templates to trigger Netlify rebuild when something changes, e.g. new linter is added. -f64a216efd5eaeba6d52b81db65fb6c14bac6fbb143060d5f3f596c43fcea0c5 \ No newline at end of file diff --git a/go.mod b/go.mod index ca6d8c9fddef..d91b709b5def 100644 --- a/go.mod +++ b/go.mod @@ -1,156 +1,163 @@ module github.com/golangci/golangci-lint -go 1.19 +go 1.21 require ( 4d63.com/gocheckcompilerdirectives v1.2.1 4d63.com/gochecknoglobals v0.2.1 - github.com/Abirdcfly/dupword v0.0.9 - github.com/Antonboom/errname v0.1.7 - github.com/Antonboom/nilnil v0.1.1 - github.com/BurntSushi/toml v1.2.1 + github.com/4meepo/tagalign v1.3.3 + github.com/Abirdcfly/dupword v0.0.14 + github.com/Antonboom/errname v0.1.12 + github.com/Antonboom/nilnil v0.1.7 + github.com/Antonboom/testifylint v1.2.0 + github.com/BurntSushi/toml v1.3.2 github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 - github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0 - github.com/OpenPeeDeeP/depguard v1.1.1 + github.com/GaijinEntertainment/go-exhaustruct/v3 v3.2.0 + github.com/OpenPeeDeeP/depguard/v2 v2.2.0 + github.com/alecthomas/go-check-sumtype v0.1.4 + github.com/alexkohler/nakedret/v2 v2.0.2 github.com/alexkohler/prealloc v1.0.0 github.com/alingse/asasalint v0.0.11 - github.com/ashanbrown/forbidigo v1.4.0 + github.com/ashanbrown/forbidigo v1.6.0 github.com/ashanbrown/makezero v1.1.1 - github.com/bkielbasa/cyclop v1.2.0 + github.com/bkielbasa/cyclop v1.2.1 github.com/blizzy78/varnamelen v0.8.0 - github.com/bombsimon/wsl/v3 v3.4.0 - github.com/breml/bidichk v0.2.3 - github.com/breml/errchkjson v0.3.0 - github.com/butuzov/ireturn v0.1.1 - github.com/charithe/durationcheck v0.0.9 + github.com/bombsimon/wsl/v4 v4.2.1 + github.com/breml/bidichk v0.2.7 + github.com/breml/errchkjson v0.3.6 + github.com/butuzov/ireturn v0.3.0 + github.com/butuzov/mirror v1.1.0 + github.com/catenacyber/perfsprint v0.7.1 + github.com/charithe/durationcheck v0.0.10 + github.com/ckaznocha/intrange v0.1.0 github.com/curioswitch/go-reassign v0.2.0 - github.com/daixiang0/gci v0.9.1 - github.com/denis-tingaikin/go-header v0.4.3 - github.com/esimonov/ifshort v1.0.4 - github.com/fatih/color v1.14.1 + github.com/daixiang0/gci v0.12.3 + github.com/denis-tingaikin/go-header v0.5.0 + github.com/fatih/color v1.16.0 github.com/firefart/nonamedreturns v1.0.4 github.com/fzipp/gocyclo v0.6.0 - github.com/go-critic/go-critic v0.6.5 + github.com/ghostiam/protogetter v0.3.4 + github.com/go-critic/go-critic v0.11.2 + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 github.com/go-xmlfmt/xmlfmt v1.1.2 github.com/gofrs/flock v0.8.1 - github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a - github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe - github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2 - github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 - github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca - github.com/golangci/misspell v0.4.0 - github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6 - github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 - github.com/gordonklaus/ineffassign v0.0.0-20230107090616-13ace0543b28 + github.com/golangci/gofmt v0.0.0-20231018234816-f50ced29576e + github.com/golangci/misspell v0.4.1 + github.com/golangci/plugin-module-register v0.1.0 + github.com/golangci/revgrep v0.5.2 + github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed + github.com/gordonklaus/ineffassign v0.1.0 github.com/gostaticanalysis/forcetypeassert v0.1.0 github.com/gostaticanalysis/nilerr v0.1.1 - github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/go-version v1.6.0 github.com/hexops/gotextdiff v1.0.3 - github.com/jgautheron/goconst v1.5.1 + github.com/jgautheron/goconst v1.7.0 github.com/jingyugao/rowserrcheck v1.1.1 github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af + github.com/jjti/go-spancheck v0.5.3 github.com/julz/importas v0.1.0 - github.com/junk1tm/musttag v0.4.4 - github.com/kisielk/errcheck v1.6.3 - github.com/kkHAIKE/contextcheck v1.1.3 + github.com/karamaru-alpha/copyloopvar v1.0.8 + github.com/kisielk/errcheck v1.7.0 + github.com/kkHAIKE/contextcheck v1.1.4 github.com/kulti/thelper v0.6.3 - github.com/kunwardeep/paralleltest v1.0.6 + github.com/kunwardeep/paralleltest v1.0.10 github.com/kyoh86/exportloopref v0.1.11 github.com/ldez/gomoddirectives v0.2.3 - github.com/ldez/tagliatelle v0.4.0 + github.com/ldez/tagliatelle v0.5.0 github.com/leonklingele/grouper v1.1.1 github.com/lufeee/execinquery v1.2.1 + github.com/macabu/inamedparam v0.1.3 github.com/maratori/testableexamples v1.0.0 - github.com/maratori/testpackage v1.1.0 - github.com/matoous/godox v0.0.0-20210227103229-6504466cf951 // v1.0 + github.com/maratori/testpackage v1.1.1 + github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26 github.com/mattn/go-colorable v0.1.13 - github.com/mbilski/exhaustivestruct v1.2.0 - github.com/mgechev/revive v1.2.5 + github.com/mgechev/revive v1.3.7 github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/go-ps v1.0.0 - github.com/moricho/tparallel v0.2.1 + github.com/moricho/tparallel v0.3.1 github.com/nakabonne/nestif v0.3.1 - github.com/nishanths/exhaustive v0.9.5 + github.com/nishanths/exhaustive v0.12.0 github.com/nishanths/predeclared v0.2.2 - github.com/nunnatsa/ginkgolinter v0.8.1 - github.com/pkg/errors v0.9.1 - github.com/polyfloyd/go-errorlint v1.1.0 + github.com/nunnatsa/ginkgolinter v0.15.2 + github.com/polyfloyd/go-errorlint v1.4.8 github.com/quasilyte/go-ruleguard/dsl v0.3.22 github.com/ryancurrah/gomodguard v1.3.0 - github.com/ryanrolds/sqlclosecheck v0.4.0 + github.com/ryanrolds/sqlclosecheck v0.5.1 github.com/sanposhiho/wastedassign/v2 v2.0.7 github.com/sashamelentyev/interfacebloat v1.1.0 - github.com/sashamelentyev/usestdlibvars v1.22.0 - github.com/securego/gosec/v2 v2.15.0 + github.com/sashamelentyev/usestdlibvars v1.25.0 + github.com/securego/gosec/v2 v2.19.0 github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c - github.com/shirou/gopsutil/v3 v3.23.1 - github.com/sirupsen/logrus v1.9.0 - github.com/sivchari/containedctx v1.0.2 + github.com/shirou/gopsutil/v3 v3.24.2 + github.com/sirupsen/logrus v1.9.3 + github.com/sivchari/containedctx v1.0.3 github.com/sivchari/tenv v1.7.1 - github.com/sonatard/noctx v0.0.1 + github.com/sonatard/noctx v0.0.2 github.com/sourcegraph/go-diff v0.7.0 - github.com/spf13/cobra v1.6.1 + github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.12.0 github.com/ssgreg/nlreturn/v2 v2.2.1 github.com/stbenjam/no-sprintf-host-port v0.1.1 - github.com/stretchr/testify v1.8.1 - github.com/tdakkota/asciicheck v0.1.1 - github.com/tetafro/godot v1.4.11 - github.com/timakin/bodyclose v0.0.0-20221125081123-e39cf3fc478e - github.com/timonwong/loggercheck v0.9.3 - github.com/tomarrell/wrapcheck/v2 v2.8.0 + github.com/stretchr/testify v1.9.0 + github.com/tdakkota/asciicheck v0.2.0 + github.com/tetafro/godot v1.4.16 + github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966 + github.com/timonwong/loggercheck v0.9.4 + github.com/tomarrell/wrapcheck/v2 v2.8.3 github.com/tommy-muehle/go-mnd/v2 v2.5.1 - github.com/ultraware/funlen v0.0.3 - github.com/ultraware/whitespace v0.0.5 - github.com/uudashr/gocognit v1.0.6 + github.com/ultraware/funlen v0.1.0 + github.com/ultraware/whitespace v0.1.0 + github.com/uudashr/gocognit v1.1.2 github.com/valyala/quicktemplate v1.7.0 + github.com/xen0n/gosmopolitan v1.2.2 github.com/yagipy/maintidx v1.0.0 github.com/yeya24/promlinter v0.2.0 - gitlab.com/bosi/decorder v0.2.3 - golang.org/x/tools v0.6.0 + github.com/ykadowak/zerologlint v0.1.5 + gitlab.com/bosi/decorder v0.4.1 + go-simpler.org/musttag v0.9.0 + go-simpler.org/sloglint v0.4.0 + go.uber.org/automaxprocs v1.5.3 + golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc + golang.org/x/tools v0.19.0 gopkg.in/yaml.v3 v3.0.1 - honnef.co/go/tools v0.4.1 - mvdan.cc/gofumpt v0.4.0 - mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed - mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d + honnef.co/go/tools v0.4.7 + mvdan.cc/gofumpt v0.6.0 + mvdan.cc/unparam v0.0.0-20240104100049-c549a3470d14 ) require ( github.com/Masterminds/semver v1.5.0 // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/ccojocar/zxcvbn-go v1.0.2 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect - github.com/chavacava/garif v0.0.0-20221024190013-b3ef35877348 // indirect + github.com/chavacava/garif v0.1.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/ettle/strcase v0.1.1 // indirect + github.com/ettle/strcase v0.2.0 // indirect github.com/fatih/structtag v1.2.0 // indirect github.com/fsnotify/fsnotify v1.5.4 // indirect github.com/go-ole/go-ole v1.2.6 // indirect - github.com/go-toolsmith/astcast v1.0.0 // indirect - github.com/go-toolsmith/astcopy v1.0.3 // indirect - github.com/go-toolsmith/astequal v1.0.3 // indirect - github.com/go-toolsmith/astfmt v1.0.0 // indirect - github.com/go-toolsmith/astp v1.0.0 // indirect - github.com/go-toolsmith/strparse v1.0.0 // indirect - github.com/go-toolsmith/typep v1.0.2 // indirect + github.com/go-toolsmith/astcast v1.1.0 // indirect + github.com/go-toolsmith/astcopy v1.1.0 // indirect + github.com/go-toolsmith/astequal v1.2.0 // indirect + github.com/go-toolsmith/astfmt v1.1.0 // indirect + github.com/go-toolsmith/astp v1.1.0 // indirect + github.com/go-toolsmith/strparse v1.1.0 // indirect + github.com/go-toolsmith/typep v1.1.0 // indirect github.com/gobwas/glob v0.2.3 // indirect - github.com/golang/protobuf v1.5.2 // indirect - github.com/google/go-cmp v0.5.9 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/gostaticanalysis/analysisutil v0.7.1 // indirect github.com/gostaticanalysis/comment v1.4.2 // indirect - github.com/hashicorp/errwrap v1.0.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/inconshreveable/mousetrap v1.0.1 // indirect - github.com/kisielk/gotool v1.0.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.6 // indirect - github.com/mattn/go-isatty v0.0.17 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.0.5 // indirect @@ -160,32 +167,30 @@ require ( github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect - github.com/quasilyte/go-ruleguard v0.3.18 // indirect - github.com/quasilyte/gogrep v0.0.0-20220828223005-86e4605de09f // indirect - github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95 // indirect + github.com/quasilyte/go-ruleguard v0.4.2 // indirect + github.com/quasilyte/gogrep v0.5.0 // indirect + github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect - github.com/sivchari/nosnakecase v1.7.0 - github.com/spf13/afero v1.8.2 // indirect + github.com/shoenig/go-m1cpu v0.1.6 // indirect + github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.5.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect - github.com/stretchr/objx v0.5.0 // indirect + github.com/stretchr/objx v0.5.2 // indirect github.com/subosito/gotenv v1.4.1 // indirect github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c // indirect - github.com/tklauser/go-sysconf v0.3.11 // indirect - github.com/tklauser/numcpus v0.6.0 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect - github.com/yusufpapurcu/wmi v1.2.2 // indirect + github.com/yusufpapurcu/wmi v1.2.4 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect - go.uber.org/zap v1.17.0 // indirect - golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect - golang.org/x/exp/typeparams v0.0.0-20221208152030-732eee02a75a // indirect - golang.org/x/mod v0.8.0 // indirect - golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.5.0 // indirect - golang.org/x/text v0.6.0 // indirect - google.golang.org/protobuf v1.28.0 // indirect + go.uber.org/zap v1.24.0 // indirect + golang.org/x/exp/typeparams v0.0.0-20240213143201-ec583247a57a // indirect + golang.org/x/mod v0.16.0 // indirect + golang.org/x/sync v0.6.0 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b // indirect ) diff --git a/go.sum b/go.sum index b48c135cb6b2..ce18f429b272 100644 --- a/go.sum +++ b/go.sum @@ -7,7 +7,6 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= @@ -18,9 +17,6 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -38,106 +34,123 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/Abirdcfly/dupword v0.0.9 h1:MxprGjKq3yDBICXDgEEsyGirIXfMYXkLNT/agPsE1tk= -github.com/Abirdcfly/dupword v0.0.9/go.mod h1:PzmHVLLZ27MvHSzV7eFmMXSFArWXZPZmfuuziuUrf2g= -github.com/Antonboom/errname v0.1.7 h1:mBBDKvEYwPl4WFFNwec1CZO096G6vzK9vvDQzAwkako= -github.com/Antonboom/errname v0.1.7/go.mod h1:g0ONh16msHIPgJSGsecu1G/dcF2hlYR/0SddnIAGavU= -github.com/Antonboom/nilnil v0.1.1 h1:PHhrh5ANKFWRBh7TdYmyyq2gyT2lotnvFvvFbylF81Q= -github.com/Antonboom/nilnil v0.1.1/go.mod h1:L1jBqoWM7AOeTD+tSquifKSesRHs4ZdaxvZR+xdJEaI= +github.com/4meepo/tagalign v1.3.3 h1:ZsOxcwGD/jP4U/aw7qeWu58i7dwYemfy5Y+IF1ACoNw= +github.com/4meepo/tagalign v1.3.3/go.mod h1:Q9c1rYMZJc9dPRkbQPpcBNCLEmY2njbAsXhQOZFE2dE= +github.com/Abirdcfly/dupword v0.0.14 h1:3U4ulkc8EUo+CaT105/GJ1BQwtgyj6+VaBVbAX11Ba8= +github.com/Abirdcfly/dupword v0.0.14/go.mod h1:VKDAbxdY8YbKUByLGg8EETzYSuC4crm9WwI6Y3S0cLI= +github.com/Antonboom/errname v0.1.12 h1:oh9ak2zUtsLp5oaEd/erjB4GPu9w19NyoIskZClDcQY= +github.com/Antonboom/errname v0.1.12/go.mod h1:bK7todrzvlaZoQagP1orKzWXv59X/x0W0Io2XT1Ssro= +github.com/Antonboom/nilnil v0.1.7 h1:ofgL+BA7vlA1K2wNQOsHzLJ2Pw5B5DpWRLdDAVvvTow= +github.com/Antonboom/nilnil v0.1.7/go.mod h1:TP+ScQWVEq0eSIxqU8CbdT5DFWoHp0MbP+KMUO1BKYQ= +github.com/Antonboom/testifylint v1.2.0 h1:015bxD8zc5iY8QwTp4+RG9I4kIbqwvGX9TrBbb7jGdM= +github.com/Antonboom/testifylint v1.2.0/go.mod h1:rkmEqjqVnHDRNsinyN6fPSLnoajzFwsCcguJgwADBkw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= -github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rWPdisA5ynNEsoARbiCBOyGcJM4/OzsM= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= -github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0 h1:+r1rSv4gvYn0wmRjC8X7IAzX8QezqtFV9m0MUHFJgts= -github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0/go.mod h1:b3g59n2Y+T5xmcxJL+UEG2f8cQploZm1mR/v6BW0mU0= +github.com/GaijinEntertainment/go-exhaustruct/v3 v3.2.0 h1:sATXp1x6/axKxz2Gjxv8MALP0bXaNRfQinEwyfMcx8c= +github.com/GaijinEntertainment/go-exhaustruct/v3 v3.2.0/go.mod h1:Nl76DrGNJTA1KJ0LePKBw/vznBX1EHbAZX8mwjR82nI= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/OpenPeeDeeP/depguard v1.1.1 h1:TSUznLjvp/4IUP+OQ0t/4jF4QUyxIcVX8YnghZdunyA= -github.com/OpenPeeDeeP/depguard v1.1.1/go.mod h1:JtAMzWkmFEzDPyAd+W0NHl1lvpQKTvT9jnRVsohBKpc= +github.com/OpenPeeDeeP/depguard/v2 v2.2.0 h1:vDfG60vDtIuf0MEOhmLlLLSzqaRM8EMcgJPdp74zmpA= +github.com/OpenPeeDeeP/depguard/v2 v2.2.0/go.mod h1:CIzddKRvLBC4Au5aYP/i3nyaWQ+ClszLIuVocRiCYFQ= +github.com/alecthomas/assert/v2 v2.2.2 h1:Z/iVC0xZfWTaFNE6bA3z07T86hd45Xe2eLt6WVy2bbk= +github.com/alecthomas/assert/v2 v2.2.2/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ= +github.com/alecthomas/go-check-sumtype v0.1.4 h1:WCvlB3l5Vq5dZQTFmodqL2g68uHiSwwlWcT5a2FGK0c= +github.com/alecthomas/go-check-sumtype v0.1.4/go.mod h1:WyYPfhfkdhyrdaligV6svFopZV8Lqdzn5pyVBaV6jhQ= +github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk= +github.com/alecthomas/repr v0.2.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/alexkohler/nakedret/v2 v2.0.2 h1:qnXuZNvv3/AxkAb22q/sEsEpcA99YxLFACDtEw9TPxE= +github.com/alexkohler/nakedret/v2 v2.0.2/go.mod h1:2b8Gkk0GsOrqQv/gPWjNLDSKwG8I5moSXG1K4VIBcTQ= github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pOcUuw= github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw= github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= -github.com/ashanbrown/forbidigo v1.4.0 h1:spdPbupaSqtWORq1Q4eHBoPBmHtwVyLKwaedbSLc5Sw= -github.com/ashanbrown/forbidigo v1.4.0/go.mod h1:IvgwB5Y4fzqSAj/WVXKWigoTkB0dzI2FBbpKWuh7ph8= +github.com/ashanbrown/forbidigo v1.6.0 h1:D3aewfM37Yb3pxHujIPSpTf6oQk9sc9WZi8gerOIVIY= +github.com/ashanbrown/forbidigo v1.6.0/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU= github.com/ashanbrown/makezero v1.1.1 h1:iCQ87C0V0vSyO+M9E/FZYbu65auqH0lnsOkf5FcB28s= github.com/ashanbrown/makezero v1.1.1/go.mod h1:i1bJLCRSCHOcOa9Y6MyF2FTfMZMFdHvxKHxgO5Z1axI= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bkielbasa/cyclop v1.2.0 h1:7Jmnh0yL2DjKfw28p86YTd/B4lRGcNuu12sKE35sM7A= -github.com/bkielbasa/cyclop v1.2.0/go.mod h1:qOI0yy6A7dYC4Zgsa72Ppm9kONl0RoIlPbzot9mhmeI= +github.com/bkielbasa/cyclop v1.2.1 h1:AeF71HZDob1P2/pRm1so9cd1alZnrpyc4q2uP2l0gJY= +github.com/bkielbasa/cyclop v1.2.1/go.mod h1:K/dT/M0FPAiYjBgQGau7tz+3TMh4FWAEqlMhzFWCrgM= github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ089M= github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= -github.com/bombsimon/wsl/v3 v3.4.0 h1:RkSxjT3tmlptwfgEgTgU+KYKLI35p/tviNXNXiL2aNU= -github.com/bombsimon/wsl/v3 v3.4.0/go.mod h1:KkIB+TXkqy6MvK9BDZVbZxKNYsE1/oLRJbIFtf14qqo= -github.com/breml/bidichk v0.2.3 h1:qe6ggxpTfA8E75hdjWPZ581sY3a2lnl0IRxLQFelECI= -github.com/breml/bidichk v0.2.3/go.mod h1:8u2C6DnAy0g2cEq+k/A2+tr9O1s+vHGxWn0LTc70T2A= -github.com/breml/errchkjson v0.3.0 h1:YdDqhfqMT+I1vIxPSas44P+9Z9HzJwCeAzjB8PxP1xw= -github.com/breml/errchkjson v0.3.0/go.mod h1:9Cogkyv9gcT8HREpzi3TiqBxCqDzo8awa92zSDFcofU= -github.com/butuzov/ireturn v0.1.1 h1:QvrO2QF2+/Cx1WA/vETCIYBKtRjc30vesdoPUNo1EbY= -github.com/butuzov/ireturn v0.1.1/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacMsOEFPoc= +github.com/bombsimon/wsl/v4 v4.2.1 h1:Cxg6u+XDWff75SIFFmNsqnIOgob+Q9hG6y/ioKbRFiM= +github.com/bombsimon/wsl/v4 v4.2.1/go.mod h1:Xu/kDxGZTofQcDGCtQe9KCzhHphIe0fDuyWTxER9Feo= +github.com/breml/bidichk v0.2.7 h1:dAkKQPLl/Qrk7hnP6P+E0xOodrq8Us7+U0o4UBOAlQY= +github.com/breml/bidichk v0.2.7/go.mod h1:YodjipAGI9fGcYM7II6wFvGhdMYsC5pHDlGzqvEW3tQ= +github.com/breml/errchkjson v0.3.6 h1:VLhVkqSBH96AvXEyclMR37rZslRrY2kcyq+31HCsVrA= +github.com/breml/errchkjson v0.3.6/go.mod h1:jhSDoFheAF2RSDOlCfhHO9KqhZgAYLyvHe7bRCX8f/U= +github.com/butuzov/ireturn v0.3.0 h1:hTjMqWw3y5JC3kpnC5vXmFJAWI/m31jaCYQqzkS6PL0= +github.com/butuzov/ireturn v0.3.0/go.mod h1:A09nIiwiqzN/IoVo9ogpa0Hzi9fex1kd9PSD6edP5ZA= +github.com/butuzov/mirror v1.1.0 h1:ZqX54gBVMXu78QLoiqdwpl2mgmoOJTk7s4p4o+0avZI= +github.com/butuzov/mirror v1.1.0/go.mod h1:8Q0BdQU6rC6WILDiBM60DBfvV78OLJmMmixe7GF45AE= +github.com/catenacyber/perfsprint v0.7.1 h1:PGW5G/Kxn+YrN04cRAZKC+ZuvlVwolYMrIyyTJ/rMmc= +github.com/catenacyber/perfsprint v0.7.1/go.mod h1:/wclWYompEyjUD2FuIIDVKNkqz7IgBIWXIH3V0Zol50= +github.com/ccojocar/zxcvbn-go v1.0.2 h1:na/czXU8RrhXO4EZme6eQJLR4PzcGsahsBOAwU6I3Vg= +github.com/ccojocar/zxcvbn-go v1.0.2/go.mod h1:g1qkXtUSvHP8lhHp5GrSmTz6uWALGRMQdw6Qnz/hi60= 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/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/charithe/durationcheck v0.0.9 h1:mPP4ucLrf/rKZiIG/a9IPXHGlh8p4CzgpyTy6EEutYk= -github.com/charithe/durationcheck v0.0.9/go.mod h1:SSbRIBVfMjCi/kEB6K65XEA83D6prSM8ap1UCpNKtgg= -github.com/chavacava/garif v0.0.0-20221024190013-b3ef35877348 h1:cy5GCEZLUCshCGCRRUjxHrDUqkB4l5cuUt3ShEckQEo= -github.com/chavacava/garif v0.0.0-20221024190013-b3ef35877348/go.mod h1:f/miWtG3SSuTxKsNK3o58H1xl+XV6ZIfbC6p7lPPB8U= +github.com/charithe/durationcheck v0.0.10 h1:wgw73BiocdBDQPik+zcEoBG/ob8uyBHf2iyoHGPf5w4= +github.com/charithe/durationcheck v0.0.10/go.mod h1:bCWXb7gYRysD1CU3C+u4ceO49LoGOY1C1L6uouGNreQ= +github.com/chavacava/garif v0.1.0 h1:2JHa3hbYf5D9dsgseMKAmc/MZ109otzgNFk5s87H9Pc= +github.com/chavacava/garif v0.1.0/go.mod h1:XMyYCkEL58DF0oyW4qDjjnPWONs2HBqYKI+UIPD+Gww= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/ckaznocha/intrange v0.1.0 h1:ZiGBhvrdsKpoEfzh9CjBfDSZof6QB0ORY5tXasUtiew= +github.com/ckaznocha/intrange v0.1.0/go.mod h1:Vwa9Ekex2BrEQMg6zlrWwbs/FtYw7eS5838Q7UjK7TQ= 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-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/cristalhq/acmd v0.8.1/go.mod h1:LG5oa43pE/BbxtfMoImHCQN++0Su7dzipdgBjMCBVDQ= github.com/curioswitch/go-reassign v0.2.0 h1:G9UZyOcpk/d7Gd6mqYgd8XYWFMw/znxwGDUstnC9DIo= github.com/curioswitch/go-reassign v0.2.0/go.mod h1:x6OpXuWvgfQaMGks2BZybTngWjT84hqJfKoO8Tt/Roc= -github.com/daixiang0/gci v0.9.1 h1:jBrwBmBZTDsGsXiaCTLIe9diotp1X4X64zodFrh7l+c= -github.com/daixiang0/gci v0.9.1/go.mod h1:EpVfrztufwVgQRXjnX4zuNinEpLj5OmMjtu/+MB0V0c= +github.com/daixiang0/gci v0.12.3 h1:yOZI7VAxAGPQmkb1eqt5g/11SUlwoat1fSblGLmdiQc= +github.com/daixiang0/gci v0.12.3/go.mod h1:xtHP9N7AHdNvtRNfcx9gwTDfw7FRJx4bZUsiEfiNNAI= 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/denis-tingaikin/go-header v0.4.3 h1:tEaZKAlqql6SKCY++utLmkPLd6K8IBM20Ha7UVm+mtU= -github.com/denis-tingaikin/go-header v0.4.3/go.mod h1:0wOCWuN71D5qIgE2nz9KrKmuYBAC2Mra5RassOIQ2/c= +github.com/denis-tingaikin/go-header v0.5.0 h1:SRdnP5ZKvcO9KKRP1KJrhFR3RrlGuD+42t4429eC9k8= +github.com/denis-tingaikin/go-header v0.5.0/go.mod h1:mMenU5bWrok6Wl2UsZjy+1okegmwQ3UgWl4V1D8gjlY= 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.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/esimonov/ifshort v1.0.4 h1:6SID4yGWfRae/M7hkVDVVyppy8q/v9OuxNdmjLQStBA= -github.com/esimonov/ifshort v1.0.4/go.mod h1:Pe8zjlRrJ80+q2CxHLfEOfTwxCZ4O+MuhcHcfgNWTk0= -github.com/ettle/strcase v0.1.1 h1:htFueZyVeE1XNnMEfbqp5r67qAN/4r6ya1ysq8Q+Zcw= -github.com/ettle/strcase v0.1.1/go.mod h1:hzDLsPC7/lwKyBOywSHEP89nt2pDgdy+No1NBA9o9VY= -github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= -github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= +github.com/ettle/strcase v0.2.0 h1:fGNiVF21fHXpX1niBgk0aROov1LagYsOwV/xqKDKR/Q= +github.com/ettle/strcase v0.2.0/go.mod h1:DajmHElDSaX76ITe3/VHVyMin4LWSJN5Z909Wp+ED1A= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/firefart/nonamedreturns v1.0.4 h1:abzI1p7mAEPYuR4A+VLKn4eNDOycjYo2phmY9sfv40Y= github.com/firefart/nonamedreturns v1.0.4/go.mod h1:TDhe/tjI1BXo48CmYbUduTV7BdIga8MAO/xbKdcVsGI= -github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= -github.com/go-critic/go-critic v0.6.5 h1:fDaR/5GWURljXwF8Eh31T2GZNz9X4jeboS912mWF8Uo= -github.com/go-critic/go-critic v0.6.5/go.mod h1:ezfP/Lh7MA6dBNn4c6ab5ALv3sKnZVLx37tr00uuaOY= +github.com/ghostiam/protogetter v0.3.4 h1:5SZ+lZSNmNkSbGVSF9hUHhv/b7ELF9Rwchoq7btYo6c= +github.com/ghostiam/protogetter v0.3.4/go.mod h1:A0JgIhs0fgVnotGinjQiKaFVG3waItLJNwPmcMzDnvk= +github.com/go-critic/go-critic v0.11.2 h1:81xH/2muBphEgPtcwH1p6QD+KzXl2tMSi3hXjBSxDnM= +github.com/go-critic/go-critic v0.11.2/go.mod h1:OePaicfjsf+KPy33yq4gzv6CO7TEQ9Rom6ns1KsJnl8= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -147,29 +160,34 @@ github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vb github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= +github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-toolsmith/astcast v1.0.0 h1:JojxlmI6STnFVG9yOImLeGREv8W2ocNUM+iOhR6jE7g= -github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= -github.com/go-toolsmith/astcopy v1.0.2/go.mod h1:4TcEdbElGc9twQEYpVo/aieIXfHhiuLh4aLAck6dO7Y= -github.com/go-toolsmith/astcopy v1.0.3 h1:r0bgSRlMOAgO+BdQnVAcpMSMkrQCnV6ZJmIkrJgcJj0= -github.com/go-toolsmith/astcopy v1.0.3/go.mod h1:4TcEdbElGc9twQEYpVo/aieIXfHhiuLh4aLAck6dO7Y= -github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= -github.com/go-toolsmith/astequal v1.0.2/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= -github.com/go-toolsmith/astequal v1.0.3 h1:+LVdyRatFS+XO78SGV4I3TCEA0AC7fKEGma+fH+674o= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/go-toolsmith/astcast v1.1.0 h1:+JN9xZV1A+Re+95pgnMgDboWNVnIMMQXwfBwLRPgSC8= +github.com/go-toolsmith/astcast v1.1.0/go.mod h1:qdcuFWeGGS2xX5bLM/c3U9lewg7+Zu4mr+xPwZIB4ZU= +github.com/go-toolsmith/astcopy v1.1.0 h1:YGwBN0WM+ekI/6SS6+52zLDEf8Yvp3n2seZITCUBt5s= +github.com/go-toolsmith/astcopy v1.1.0/go.mod h1:hXM6gan18VA1T/daUEHCFcYiW8Ai1tIwIzHY6srfEAw= github.com/go-toolsmith/astequal v1.0.3/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= -github.com/go-toolsmith/astfmt v1.0.0 h1:A0vDDXt+vsvLEdbMFJAUBI/uTbRw1ffOPnxsILnFL6k= -github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw= -github.com/go-toolsmith/astp v1.0.0 h1:alXE75TXgcmupDsMK1fRAy0YUzLzqPVvBKoyWV+KPXg= -github.com/go-toolsmith/astp v1.0.0/go.mod h1:RSyrtpVlfTFGDYRbrjyWP1pYu//tSFcvdYrA8meBmLI= -github.com/go-toolsmith/pkgload v1.0.2-0.20220101231613-e814995d17c5 h1:eD9POs68PHkwrx7hAB78z1cb6PfGq/jyWn3wJywsH1o= -github.com/go-toolsmith/pkgload v1.0.2-0.20220101231613-e814995d17c5/go.mod h1:3NAwwmD4uY/yggRxoEjk/S00MIV3A+H7rrE3i87eYxM= -github.com/go-toolsmith/strparse v1.0.0 h1:Vcw78DnpCAKlM20kSbAyO4mPfJn/lyYA4BJUDxe2Jb4= +github.com/go-toolsmith/astequal v1.1.0/go.mod h1:sedf7VIdCL22LD8qIvv7Nn9MuWJruQA/ysswh64lffQ= +github.com/go-toolsmith/astequal v1.2.0 h1:3Fs3CYZ1k9Vo4FzFhwwewC3CHISHDnVUPC4x0bI2+Cw= +github.com/go-toolsmith/astequal v1.2.0/go.mod h1:c8NZ3+kSFtFY/8lPso4v8LuJjdJiUFVnSuU3s0qrrDY= +github.com/go-toolsmith/astfmt v1.1.0 h1:iJVPDPp6/7AaeLJEruMsBUlOYCmvg0MoCfJprsOmcco= +github.com/go-toolsmith/astfmt v1.1.0/go.mod h1:OrcLlRwu0CuiIBp/8b5PYF9ktGVZUjlNMV634mhwuQ4= +github.com/go-toolsmith/astp v1.1.0 h1:dXPuCl6u2llURjdPLLDxJeZInAeZ0/eZwFJmqZMnpQA= +github.com/go-toolsmith/astp v1.1.0/go.mod h1:0T1xFGz9hicKs8Z5MfAqSUitoUYS30pDMsRVIDHs8CA= +github.com/go-toolsmith/pkgload v1.2.2 h1:0CtmHq/02QhxcF7E9N5LIFcYFsMR5rdovfqTtRKkgIk= +github.com/go-toolsmith/pkgload v1.2.2/go.mod h1:R2hxLNRKuAsiXCo2i5J6ZQPhnPMOVtU+f0arbFPWCus= github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= -github.com/go-toolsmith/typep v1.0.2 h1:8xdsa1+FSIH/RhEkgnD1j2CJOy5mNllW1Q9tRiYwvlk= -github.com/go-toolsmith/typep v1.0.2/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= +github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQiyP2Bvw= +github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= +github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus= +github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-xmlfmt/xmlfmt v1.1.2 h1:Nea7b4icn8s57fTx1M5AI4qQT5HEM3rVUO8MuE6g80U= github.com/go-xmlfmt/xmlfmt v1.1.2/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= @@ -203,27 +221,22 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD 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 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= 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/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 h1:23T5iq8rbUYlhpt5DB4XJkc6BU31uODLD1o1gKvZmD0= -github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4= github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM= github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= -github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe h1:6RGUuS7EGotKx6J5HIP8ZtyMdiDscjMLfRBSPuzVVeo= -github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe/go.mod h1:gjqyPShc/m8pEMpk0a3SeagVb0kaqvhscv+i9jI5ZhQ= -github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2 h1:amWTbTGqOZ71ruzrdA+Nx5WA3tV1N0goTspwmKCQvBY= -github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2/go.mod h1:9wOXstvyDRshQ9LggQuzBCGysxs3b6Uo/1MvYCR2NMs= -github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 h1:MfyDlzVjl1hoaPzPD4Gpb/QgoRfSBR0jdhwGyAWwMSA= -github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= -github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA= -github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o= -github.com/golangci/misspell v0.4.0 h1:KtVB/hTK4bbL/S6bs64rYyk8adjmh1BygbBiaAiX+a0= -github.com/golangci/misspell v0.4.0/go.mod h1:W6O/bwV6lGDxUCChm2ykw9NQdd5bYd1Xkjo88UcWyJc= -github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6 h1:DIPQnGy2Gv2FSA4B/hh8Q7xx3B7AIDk3DAMeHclH1vQ= -github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6/go.mod h1:0AKcRCkMoKvUvlf89F6O7H2LYdhr1zBh736mBItOdRs= -github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSWhqsYNgcuWO2kFlpdOZbP0+yRjmvPGys= -github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= +github.com/golangci/gofmt v0.0.0-20231018234816-f50ced29576e h1:ULcKCDV1LOZPFxGZaA6TlQbiM3J2GCPnkx/bGF6sX/g= +github.com/golangci/gofmt v0.0.0-20231018234816-f50ced29576e/go.mod h1:Pm5KhLPA8gSnQwrQ6ukebRcapGb/BG9iUkdaiCcGHJM= +github.com/golangci/misspell v0.4.1 h1:+y73iSicVy2PqyX7kmUefHusENlrP9YwuHZHPLGQj/g= +github.com/golangci/misspell v0.4.1/go.mod h1:9mAN1quEo3DlpbaIKKyEvRxK1pwqR9s/Sea1bJCtlNI= +github.com/golangci/plugin-module-register v0.1.0 h1:py0VsgNTwBNC5IqhcWFvMZpcKjaSGmyO8TqIJ+0KnEE= +github.com/golangci/plugin-module-register v0.1.0/go.mod h1:TTpqoB6KkwOJMV8u7+NyXMrkwwESJLOkfl9TxR1DGFc= +github.com/golangci/revgrep v0.5.2 h1:EndcWoRhcnfj2NHQ+28hyuXpLMF+dQmCN+YaeeIl4FU= +github.com/golangci/revgrep v0.5.2/go.mod h1:bjAMA+Sh/QUfTDcHzxfyHxr4xKvllVr/0sCv2e7jJHA= +github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed h1:IURFTjxeTfNFP0hTEi1YKjB/ub8zkpaOqFFMApi2EAs= +github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed/go.mod h1:XLXN8bNw4CGRPaqgl3bv/lhz7bsGPh4/xSaMTbo2vkQ= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -238,12 +251,12 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +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/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -251,21 +264,15 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= -github.com/gordonklaus/ineffassign v0.0.0-20230107090616-13ace0543b28 h1:9alfqbrhuD+9fLZ4iaAVwhlp5PEhmnBt7yvK2Oy5C1U= -github.com/gordonklaus/ineffassign v0.0.0-20230107090616-13ace0543b28/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= -github.com/gostaticanalysis/analysisutil v0.0.3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= -github.com/gostaticanalysis/analysisutil v0.1.0/go.mod h1:dMhHRU9KTiDcuLGdy87/2gTR8WruwYZrKdRq9m1O6uw= +github.com/gordonklaus/ineffassign v0.1.0 h1:y2Gd/9I7MdY1oEIt+n+rowjBNDcLQq3RsH5hwJd0f9s= +github.com/gordonklaus/ineffassign v0.1.0/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= github.com/gostaticanalysis/analysisutil v0.7.1 h1:ZMCjoue3DtDWQ5WyU16YbjbQEQ3VuzwxALrpYd+HeKk= github.com/gostaticanalysis/analysisutil v0.7.1/go.mod h1:v21E3hY37WKMGSnbsw2S/ojApNWb6C1//mXO48CXbVc= -github.com/gostaticanalysis/comment v1.3.0/go.mod h1:xMicKDx7XRXYdVwY9f9wQpDJVnqWxw9wCauCMKp+IBI= github.com/gostaticanalysis/comment v1.4.1/go.mod h1:ih6ZxzTHLdadaiSnF5WY3dxUoXfXAlTaRzuaNDlSado= github.com/gostaticanalysis/comment v1.4.2 h1:hlnx5+S2fY9Zo9ePo4AhgYsYHbM2+eAv8m/s1JiCd6Q= github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM= @@ -275,10 +282,7 @@ github.com/gostaticanalysis/nilerr v0.1.1 h1:ThE+hJP0fEp4zWLkWHWcRyI2Od0p7DlgYG3 github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= github.com/gostaticanalysis/testutil v0.4.0 h1:nhdCmubdmDF6VEatUNjgUZBJKWRqugoISdUv3PPQgHY= -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/gostaticanalysis/testutil v0.4.0/go.mod h1:bLIoPefWXrRi/ssLFWX1dx7Repi5x3CuviD3dgAZaBU= github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= @@ -289,15 +293,16 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= -github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/jgautheron/goconst v1.5.1 h1:HxVbL1MhydKs8R8n/HE5NPvzfaYmQJA3o879lE4+WcM= -github.com/jgautheron/goconst v1.5.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jgautheron/goconst v1.7.0 h1:cEqH+YBKLsECnRSd4F4TK5ri8t/aXtt/qoL0Ft252B0= +github.com/jgautheron/goconst v1.7.0/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af h1:KA9BjwUk7KlCh6S9EAGWBt1oExIUv9WyNCiRz5amv48= github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= +github.com/jjti/go-spancheck v0.5.3 h1:vfq4s2IB8T3HvbpiwDTYgVPj1Ze/ZSXrTtaZRTc7CuM= +github.com/jjti/go-spancheck v0.5.3/go.mod h1:eQdOX1k3T+nAKvZDyLC3Eby0La4dZ+I19iOl5NzSPFE= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -309,64 +314,64 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/julz/importas v0.1.0 h1:F78HnrsjY3cR7j0etXy5+TU1Zuy7Xt08X/1aJnH5xXY= github.com/julz/importas v0.1.0/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0= -github.com/junk1tm/musttag v0.4.4 h1:VK4L7v7lvWAhKDDx0cUJgbb0UBNipYinv8pPeHJzH9Q= -github.com/junk1tm/musttag v0.4.4/go.mod h1:XkcL/9O6RmD88JBXb+I15nYRl9W4ExhgQeCBEhfMC8U= -github.com/kisielk/errcheck v1.6.3 h1:dEKh+GLHcWm2oN34nMvDzn1sqI0i0WxPvrgiJA5JuM8= -github.com/kisielk/errcheck v1.6.3/go.mod h1:nXw/i/MfnvRHqXa7XXmQMUB0oNFGuBrNI8d8NLy0LPw= -github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= +github.com/karamaru-alpha/copyloopvar v1.0.8 h1:gieLARwuByhEMxRwM3GRS/juJqFbLraftXIKDDNJ50Q= +github.com/karamaru-alpha/copyloopvar v1.0.8/go.mod h1:u7CIfztblY0jZLOQZgH3oYsJzpC2A7S6u/lfgSXHy0k= +github.com/kisielk/errcheck v1.7.0 h1:+SbscKmWJ5mOK/bO1zS60F5I9WwZDWOfRsC4RwfwRV0= +github.com/kisielk/errcheck v1.7.0/go.mod h1:1kLL+jV4e+CFfueBmI1dSK2ADDyQnlrnrY/FqKluHJQ= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kkHAIKE/contextcheck v1.1.3 h1:l4pNvrb8JSwRd51ojtcOxOeHJzHek+MtOyXbaR0uvmw= -github.com/kkHAIKE/contextcheck v1.1.3/go.mod h1:PG/cwd6c0705/LM0KTr1acO2gORUxkSVWyLJOFW5qoo= +github.com/kkHAIKE/contextcheck v1.1.4 h1:B6zAaLhOEEcjvUgIYEqystmnFk1Oemn8bvJhbt0GMb8= +github.com/kkHAIKE/contextcheck v1.1.4/go.mod h1:1+i/gWqokIa+dm31mqGLZhZJ7Uh44DJGZVmr6QRBNJg= github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kulti/thelper v0.6.3 h1:ElhKf+AlItIu+xGnI990no4cE2+XaSu1ULymV2Yulxs= github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I= -github.com/kunwardeep/paralleltest v1.0.6 h1:FCKYMF1OF2+RveWlABsdnmsvJrei5aoyZoaGS+Ugg8g= -github.com/kunwardeep/paralleltest v1.0.6/go.mod h1:Y0Y0XISdZM5IKm3TREQMZ6iteqn1YuwCsJO/0kL9Zes= +github.com/kunwardeep/paralleltest v1.0.10 h1:wrodoaKYzS2mdNVnc4/w31YaXFtsc21PCTdvWJ/lDDs= +github.com/kunwardeep/paralleltest v1.0.10/go.mod h1:2C7s65hONVqY7Q5Efj5aLzRCNLjw2h4eMc9EcypGjcY= github.com/kyoh86/exportloopref v0.1.11 h1:1Z0bcmTypkL3Q4k+IDHMWTcnCliEZcaPiIe0/ymEyhQ= github.com/kyoh86/exportloopref v0.1.11/go.mod h1:qkV4UF1zGl6EkF1ox8L5t9SwyeBAZ3qLMd6up458uqA= github.com/ldez/gomoddirectives v0.2.3 h1:y7MBaisZVDYmKvt9/l1mjNCiSA1BVn34U0ObUcJwlhA= github.com/ldez/gomoddirectives v0.2.3/go.mod h1:cpgBogWITnCfRq2qGoDkKMEVSaarhdBr6g8G04uz6d0= -github.com/ldez/tagliatelle v0.4.0 h1:sylp7d9kh6AdXN2DpVGHBRb5guTVAgOxqNGhbqc4b1c= -github.com/ldez/tagliatelle v0.4.0/go.mod h1:mNtTfrHy2haaBAw+VT7IBV6VXBThS7TCreYWbBcJ87I= +github.com/ldez/tagliatelle v0.5.0 h1:epgfuYt9v0CG3fms0pEgIMNPuFf/LpPIfjk4kyqSioo= +github.com/ldez/tagliatelle v0.5.0/go.mod h1:rj1HmWiL1MiKQuOONhd09iySTEkUuE/8+5jtPYz9xa4= github.com/leonklingele/grouper v1.1.1 h1:suWXRU57D4/Enn6pXR0QVqqWWrnJ9Osrz+5rjt8ivzU= github.com/leonklingele/grouper v1.1.1/go.mod h1:uk3I3uDfi9B6PeUjsCKi6ndcf63Uy7snXgR4yDYQVDY= github.com/lufeee/execinquery v1.2.1 h1:hf0Ems4SHcUGBxpGN7Jz78z1ppVkP/837ZlETPCEtOM= github.com/lufeee/execinquery v1.2.1/go.mod h1:EC7DrEKView09ocscGHC+apXMIaorh4xqSxS/dy8SbM= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/macabu/inamedparam v0.1.3 h1:2tk/phHkMlEL/1GNe/Yf6kkR/hkcUdAEY3L0hjYV1Mk= +github.com/macabu/inamedparam v0.1.3/go.mod h1:93FLICAIk/quk7eaPPQvbzihUdn/QkGDwIZEoLtpH6I= github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI= github.com/maratori/testableexamples v1.0.0/go.mod h1:4rhjL1n20TUTT4vdh3RDqSizKLyXp7K2u6HgraZCGzE= -github.com/maratori/testpackage v1.1.0 h1:GJY4wlzQhuBusMF1oahQCBtUV/AQ/k69IZ68vxaac2Q= -github.com/maratori/testpackage v1.1.0/go.mod h1:PeAhzU8qkCwdGEMTEupsHJNlQu2gZopMC6RjbhmHeDc= -github.com/matoous/godox v0.0.0-20210227103229-6504466cf951 h1:pWxk9e//NbPwfxat7RXkts09K+dEBJWakUWwICVqYbA= -github.com/matoous/godox v0.0.0-20210227103229-6504466cf951/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= +github.com/maratori/testpackage v1.1.1 h1:S58XVV5AD7HADMmD0fNnziNHqKvSdDuEKdPD1rNTU04= +github.com/maratori/testpackage v1.1.1/go.mod h1:s4gRK/ym6AMrqpOa/kEbQTV4Q4jb7WeLZzVhVVVOQMc= +github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26 h1:gWg6ZQ4JhDfJPqlo2srm/LN17lpybq15AryXIRcWYLE= +github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mbilski/exhaustivestruct v1.2.0 h1:wCBmUnSYufAHO6J4AVWY6ff+oxWxsVFrwgOdMUQePUo= -github.com/mbilski/exhaustivestruct v1.2.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc= -github.com/mgechev/revive v1.2.5 h1:UF9AR8pOAuwNmhXj2odp4mxv9Nx2qUIwVz8ZsU+Mbec= -github.com/mgechev/revive v1.2.5/go.mod h1:nFOXent79jMTISAfOAasKfy0Z2Ejq0WX7Qn/KAdYopI= +github.com/mgechev/revive v1.3.7 h1:502QY0vQGe9KtYJ9FpxMz9rL+Fc/P13CI5POL4uHCcE= +github.com/mgechev/revive v1.3.7/go.mod h1:RJ16jUbF0OWC3co/+XTxmFNgEpUPwnnA0BRllX2aDNA= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc= @@ -378,27 +383,27 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/moricho/tparallel v0.2.1 h1:95FytivzT6rYzdJLdtfn6m1bfFJylOJK41+lgv/EHf4= -github.com/moricho/tparallel v0.2.1/go.mod h1:fXEIZxG2vdfl0ZF8b42f5a78EhjjD5mX8qUplsoSU4k= +github.com/moricho/tparallel v0.3.1 h1:fQKD4U1wRMAYNngDonW5XupoB/ZGJHdpzrWqgyg9krA= +github.com/moricho/tparallel v0.3.1/go.mod h1:leENX2cUv7Sv2qDgdi0D0fCftN8fRC67Bcn8pqzeYNI= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81U= github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4Ngq6aY7OE= -github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 h1:4kuARK6Y6FxaNu/BnU2OAaLF86eTVhP2hjTB6iMvItA= -github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354/go.mod h1:KSVJerMDfblTH7p5MZaTt+8zaT2iEk3AkVb9PQdZuE8= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/nishanths/exhaustive v0.9.5 h1:TzssWan6orBiLYVqewCG8faud9qlFntJE30ACpzmGME= -github.com/nishanths/exhaustive v0.9.5/go.mod h1:IbwrGdVMizvDcIxPYGVdQn5BqWJaOwpCvg4RGb8r/TA= +github.com/nishanths/exhaustive v0.12.0 h1:vIY9sALmw6T/yxiASewa4TQcFsVYZQQRUQJhKRf3Swg= +github.com/nishanths/exhaustive v0.12.0/go.mod h1:mEZ95wPIZW+x8kC4TgC+9YCUgiST7ecevsVDTgc2obs= github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk= github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= -github.com/nunnatsa/ginkgolinter v0.8.1 h1:/y4o/0hV+ruUHj4xXh89xlFjoaitnI4LnkpuYs02q1c= -github.com/nunnatsa/ginkgolinter v0.8.1/go.mod h1:FYYLtszIdmzCH8XMaMPyxPVXZ7VCaIm55bA+gugx+14= +github.com/nunnatsa/ginkgolinter v0.15.2 h1:N2ORxUxPU56R9gsfLIlVVvCv/V/VVou5qVI1oBKBNHg= +github.com/nunnatsa/ginkgolinter v0.15.2/go.mod h1:oYxE7dt1vZI8cK2rZOs3RgTaBN2vggkqnENmoJ8kVvc= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/onsi/ginkgo/v2 v2.8.0 h1:pAM+oBNPrpXRs+E/8spkeGx9QgekbRVyr74EUvRVOUI= -github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q= -github.com/otiai10/copy v1.2.0 h1:HvG945u96iNadPoG2/Ja2+AUJeW5YuFQMixq9yirC+k= +github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY= +github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM= +github.com/onsi/gomega v1.31.1 h1:KYppCUK+bUgAZwHOu7EXVBKyQA6ILvOESHkn/tgoqvo= +github.com/onsi/gomega v1.31.1/go.mod h1:y40C95dwAD1Nz36SsEnxvfFe8FFfNxzI5eJ0EYGyAy0= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= +github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= +github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= @@ -411,13 +416,14 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/polyfloyd/go-errorlint v1.1.0 h1:VKoEFg5yxSgJ2yFPVhxW7oGz+f8/OVcuMeNvcPIi6Eg= -github.com/polyfloyd/go-errorlint v1.1.0/go.mod h1:Uss7Bc/izYG0leCMRx3WVlrpqWedSZk7V/FUQW6VJ6U= +github.com/polyfloyd/go-errorlint v1.4.8 h1:jiEjKDH33ouFktyez7sckv6pHWif9B7SuS8cutDXFHw= +github.com/polyfloyd/go-errorlint v1.4.8/go.mod h1:NNCxFcFjZcw3xNjVdCchERkEM6Oz7wta2XJVxRftwO4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= +github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= @@ -440,63 +446,61 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/quasilyte/go-ruleguard v0.3.1-0.20210203134552-1b5a410e1cc8/go.mod h1:KsAh3x0e7Fkpgs+Q9pNLS5XpFSvYCEVl5gP9Pp1xp30= -github.com/quasilyte/go-ruleguard v0.3.18 h1:sd+abO1PEI9fkYennwzHn9kl3nqP6M5vE7FiOzZ+5CE= -github.com/quasilyte/go-ruleguard v0.3.18/go.mod h1:lOIzcYlgxrQ2sGJ735EHXmf/e9MJ516j16K/Ifcttvs= -github.com/quasilyte/go-ruleguard/dsl v0.3.0/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= -github.com/quasilyte/go-ruleguard/dsl v0.3.21/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= +github.com/quasilyte/go-ruleguard v0.4.2 h1:htXcXDK6/rO12kiTHKfHuqR4kr3Y4M0J0rOL6CH/BYs= +github.com/quasilyte/go-ruleguard v0.4.2/go.mod h1:GJLgqsLeo4qgavUoL8JeGFNS7qcisx3awV/w9eWTmNI= github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE= github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= -github.com/quasilyte/go-ruleguard/rules v0.0.0-20201231183845-9e62ed36efe1/go.mod h1:7JTjp89EGyU1d6XfBiXihJNG37wB2VRkd125Q1u7Plc= -github.com/quasilyte/go-ruleguard/rules v0.0.0-20211022131956-028d6511ab71/go.mod h1:4cgAphtvu7Ftv7vOT2ZOYhC6CvBxZixcasr8qIOTA50= -github.com/quasilyte/gogrep v0.0.0-20220828223005-86e4605de09f h1:6Gtn2i04RD0gVyYf2/IUMTIs+qYleBt4zxDqkLTcu4U= -github.com/quasilyte/gogrep v0.0.0-20220828223005-86e4605de09f/go.mod h1:Cm9lpz9NZjEoL1tgZ2OgeUKPIxL1meE7eo60Z6Sk+Ng= -github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95 h1:L8QM9bvf68pVdQ3bCFZMDmnt9yqcMBro1pC7F+IPYMY= -github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= +github.com/quasilyte/gogrep v0.5.0 h1:eTKODPXbI8ffJMN+W2aE0+oL0z/nh8/5eNdiO34SOAo= +github.com/quasilyte/gogrep v0.5.0/go.mod h1:Cm9lpz9NZjEoL1tgZ2OgeUKPIxL1meE7eo60Z6Sk+Ng= +github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 h1:TCg2WBOl980XxGFEZSS6KlBGIV0diGdySzxATTWoqaU= +github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4lu7Gd+PU1fV2/qnDNfzT635KRSObncs= github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryancurrah/gomodguard v1.3.0 h1:q15RT/pd6UggBXVBuLps8BXRvl5GPBcwVA7BJHMLuTw= github.com/ryancurrah/gomodguard v1.3.0/go.mod h1:ggBxb3luypPEzqVtq33ee7YSN35V28XeGnid8dnni50= -github.com/ryanrolds/sqlclosecheck v0.4.0 h1:i8SX60Rppc1wRuyQjMciLqIzV3xnoHB7/tXbr6RGYNI= -github.com/ryanrolds/sqlclosecheck v0.4.0/go.mod h1:TBRRjzL31JONc9i4XMinicuo+s+E8yKZ5FN8X3G6CKQ= +github.com/ryanrolds/sqlclosecheck v0.5.1 h1:dibWW826u0P8jNLsLN+En7+RqWWTYrjCB9fJfSfdyCU= +github.com/ryanrolds/sqlclosecheck v0.5.1/go.mod h1:2g3dUjoS6AL4huFdv6wn55WpLIDjY7ZgUR4J8HOO/XQ= github.com/sanposhiho/wastedassign/v2 v2.0.7 h1:J+6nrY4VW+gC9xFzUc+XjPD3g3wF3je/NsJFwFK7Uxc= github.com/sanposhiho/wastedassign/v2 v2.0.7/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw= github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= -github.com/sashamelentyev/usestdlibvars v1.22.0 h1:7ZyG1CVpjH5O3gvuuVoOZ0xYZKm0aaIILMRAVLKYN0k= -github.com/sashamelentyev/usestdlibvars v1.22.0/go.mod h1:1T21P9pG3rMZnbTP4IBuKSGgU4UfUCsz7u129/5PMMM= -github.com/securego/gosec/v2 v2.15.0 h1:v4Ym7FF58/jlykYmmhZ7mTm7FQvN/setNm++0fgIAtw= -github.com/securego/gosec/v2 v2.15.0/go.mod h1:VOjTrZOkUtSDt2QLSJmQBMWnvwiQPEjg0l+5juIqGk8= +github.com/sashamelentyev/usestdlibvars v1.25.0 h1:IK8SI2QyFzy/2OD2PYnhy84dpfNo9qADrRt6LH8vSzU= +github.com/sashamelentyev/usestdlibvars v1.25.0/go.mod h1:9nl0jgOfHKWNFS43Ojw0i7aRoS4j6EBye3YBhmAIRF8= +github.com/securego/gosec/v2 v2.19.0 h1:gl5xMkOI0/E6Hxx0XCY2XujA3V7SNSefA8sC+3f1gnk= +github.com/securego/gosec/v2 v2.19.0/go.mod h1:hOkDcHz9J/XIgIlPDXalxjeVYsHxoWUc5zJSHxcB8YM= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c h1:W65qqJCIOVP4jpqPQ0YvHYKwcMEMVWIzWC5iNQQfBTU= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs= -github.com/shirou/gopsutil/v3 v3.23.1 h1:a9KKO+kGLKEvcPIs4W62v0nu3sciVDOOOPUD0Hz7z/4= -github.com/shirou/gopsutil/v3 v3.23.1/go.mod h1:NN6mnm5/0k8jw4cBfCnJtr5L7ErOTg18tMNpgFkn0hA= +github.com/shirou/gopsutil/v3 v3.24.2 h1:kcR0erMbLg5/3LcInpw0X/rrPSqq4CDPyI6A6ZRC18Y= +github.com/shirou/gopsutil/v3 v3.24.2/go.mod h1:tSg/594BcA+8UdQU2XcW803GWYgdtauFFPgJCJKZlVk= +github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= +github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= +github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= +github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/sivchari/containedctx v1.0.2 h1:0hLQKpgC53OVF1VT7CeoFHk9YKstur1XOgfYIc1yrHI= -github.com/sivchari/containedctx v1.0.2/go.mod h1:PwZOeqm4/DLoJOqMSIJs3aKqXRX4YO+uXww087KZ7Bw= -github.com/sivchari/nosnakecase v1.7.0 h1:7QkpWIRMe8x25gckkFd2A5Pi6Ymo0qgr4JrhGt95do8= -github.com/sivchari/nosnakecase v1.7.0/go.mod h1:CwDzrzPea40/GB6uynrNLiorAlgFRvRbFSgJx2Gs+QY= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sivchari/containedctx v1.0.3 h1:x+etemjbsh2fB5ewm5FeLNi5bUjK0V8n0RB+Wwfd0XE= +github.com/sivchari/containedctx v1.0.3/go.mod h1:c1RDvCbnJLtH4lLcYD/GqwiBSSf4F5Qk0xld2rBqzJ4= github.com/sivchari/tenv v1.7.1 h1:PSpuD4bu6fSmtWMxSGWcvqUUgIn7k3yOJhOIzVWn8Ak= github.com/sivchari/tenv v1.7.1/go.mod h1:64yStXKSOxDfX47NlhVwND4dHwfZDdbp2Lyl018Icvg= -github.com/sonatard/noctx v0.0.1 h1:VC1Qhl6Oxx9vvWo3UDgrGXYCeKCe3Wbw7qAWL6FrmTY= -github.com/sonatard/noctx v0.0.1/go.mod h1:9D2D/EoULe8Yy2joDHJj7bv3sZoq9AaSb8B4lqBjiZI= +github.com/sonatard/noctx v0.0.2 h1:L7Dz4De2zDQhW8S0t+KUjY0MAQJd6SgVwhzNIc4ok00= +github.com/sonatard/noctx v0.0.2/go.mod h1:kzFz+CzWSjQ2OzIm46uJZoXuBpa2+0y3T36U18dWqIo= github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCpA8G0= github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= -github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo= -github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= -github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= -github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= +github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -510,9 +514,9 @@ github.com/stbenjam/no-sprintf-host-port v0.1.1/go.mod h1:TLhvtIvONRzdmkFiio4O8L github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/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 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -520,48 +524,53 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 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 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c h1:+aPplBwWcHBo6q9xrfWdMrT9o4kltkmmvpemgIjep/8= github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c/go.mod h1:SbErYREK7xXdsRiigaQiQkI9McGRzYMvlKYaP3Nimdk= -github.com/tdakkota/asciicheck v0.1.1 h1:PKzG7JUTUmVspQTDqtkX9eSiLGossXTybutHwTXuO0A= -github.com/tdakkota/asciicheck v0.1.1/go.mod h1:yHp0ai0Z9gUljN3o0xMhYJnH/IcvkdTBOX2fmJ93JEM= +github.com/tdakkota/asciicheck v0.2.0 h1:o8jvnUANo0qXtnslk2d3nMKTFNlOnJjRrNcj0j9qkHM= +github.com/tdakkota/asciicheck v0.2.0/go.mod h1:Qb7Y9EgjCLJGup51gDHFzbI08/gbGhL/UVhYIPWG2rg= github.com/tenntenn/modver v1.0.1 h1:2klLppGhDgzJrScMpkj9Ujy3rXPUspSjAcev9tSEBgA= github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 h1:f+jULpRQGxTSkNYKJ51yaw6ChIqO+Je8UqsTKN/cDag= github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= -github.com/tetafro/godot v1.4.11 h1:BVoBIqAf/2QdbFmSwAWnaIqDivZdOV0ZRwEm6jivLKw= -github.com/tetafro/godot v1.4.11/go.mod h1:LR3CJpxDVGlYOWn3ZZg1PgNZdTUvzsZWu8xaEohUpn8= -github.com/timakin/bodyclose v0.0.0-20221125081123-e39cf3fc478e h1:MV6KaVu/hzByHP0UvJ4HcMGE/8a6A4Rggc/0wx2AvJo= -github.com/timakin/bodyclose v0.0.0-20221125081123-e39cf3fc478e/go.mod h1:27bSVNWSBOHm+qRp1T9qzaIpsWEP6TbUnei/43HK+PQ= -github.com/timonwong/loggercheck v0.9.3 h1:ecACo9fNiHxX4/Bc02rW2+kaJIAMAes7qJ7JKxt0EZI= -github.com/timonwong/loggercheck v0.9.3/go.mod h1:wUqnk9yAOIKtGA39l1KLE9Iz0QiTocu/YZoOf+OzFdw= -github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM= -github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI= -github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms= -github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4= -github.com/tomarrell/wrapcheck/v2 v2.8.0 h1:qDzbir0xmoE+aNxGCPrn+rUSxAX+nG6vREgbbXAR81I= -github.com/tomarrell/wrapcheck/v2 v2.8.0/go.mod h1:ao7l5p0aOlUNJKI0qVwB4Yjlqutd0IvAB9Rdwyilxvg= +github.com/tetafro/godot v1.4.16 h1:4ChfhveiNLk4NveAZ9Pu2AN8QZ2nkUGFuadM9lrr5D0= +github.com/tetafro/godot v1.4.16/go.mod h1:2oVxTBSftRTh4+MVfUaUXR6bn2GDXCaMcOG4Dk3rfio= +github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966 h1:quvGphlmUVU+nhpFa4gg4yJyTRJ13reZMDHrKwYw53M= +github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966/go.mod h1:27bSVNWSBOHm+qRp1T9qzaIpsWEP6TbUnei/43HK+PQ= +github.com/timonwong/loggercheck v0.9.4 h1:HKKhqrjcVj8sxL7K77beXh0adEm6DLjV/QOGeMXEVi4= +github.com/timonwong/loggercheck v0.9.4/go.mod h1:caz4zlPcgvpEkXgVnAJGowHAMW2NwHaNlpS8xDbVhTg= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/tomarrell/wrapcheck/v2 v2.8.3 h1:5ov+Cbhlgi7s/a42BprYoxsr73CbdMUTzE3bRDFASUs= +github.com/tomarrell/wrapcheck/v2 v2.8.3/go.mod h1:g9vNIyhb5/9TQgumxQyOEqDHsmGYcGsVMOx/xGkqdMo= github.com/tommy-muehle/go-mnd/v2 v2.5.1 h1:NowYhSdyE/1zwK9QCLeRb6USWdoif80Ie+v+yU8u1Zw= github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= -github.com/ultraware/funlen v0.0.3 h1:5ylVWm8wsNwH5aWo9438pwvsK0QiqVuUrt9bn7S/iLA= -github.com/ultraware/funlen v0.0.3/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= -github.com/ultraware/whitespace v0.0.5 h1:hh+/cpIcopyMYbZNVov9iSxvJU3OYQg78Sfaqzi/CzI= -github.com/ultraware/whitespace v0.0.5/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= -github.com/uudashr/gocognit v1.0.6 h1:2Cgi6MweCsdB6kpcVQp7EW4U23iBFQWfTXiWlyp842Y= -github.com/uudashr/gocognit v1.0.6/go.mod h1:nAIUuVBnYU7pcninia3BHOvQkpQCeO76Uscky5BOwcY= +github.com/ultraware/funlen v0.1.0 h1:BuqclbkY6pO+cvxoq7OsktIXZpgBSkYTQtmwhAK81vI= +github.com/ultraware/funlen v0.1.0/go.mod h1:XJqmOQja6DpxarLj6Jj1U7JuoS8PvL4nEqDaQhy22p4= +github.com/ultraware/whitespace v0.1.0 h1:O1HKYoh0kIeqE8sFqZf1o0qbORXUCOQFrlaQyZsczZw= +github.com/ultraware/whitespace v0.1.0/go.mod h1:/se4r3beMFNmewJ4Xmz0nMQ941GJt+qmSHGP9emHYe0= +github.com/uudashr/gocognit v1.1.2 h1:l6BAEKJqQH2UpKAPKdMfZf5kE4W/2xk8pfU1OVLvniI= +github.com/uudashr/gocognit v1.1.2/go.mod h1:aAVdLURqcanke8h3vg35BC++eseDm66Z7KmchI5et4k= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.30.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus= github.com/valyala/quicktemplate v1.7.0 h1:LUPTJmlVcb46OOUY3IeD9DojFpAVbsG+5WFTcjMJzCM= github.com/valyala/quicktemplate v1.7.0/go.mod h1:sqKJnoaOF88V07vkO+9FL8fb9uZg/VPSJnLYn+LmLk8= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +github.com/xen0n/gosmopolitan v1.2.2 h1:/p2KTnMzwRexIW8GlKawsTWOxn7UHA+jCMF/V8HHtvU= +github.com/xen0n/gosmopolitan v1.2.2/go.mod h1:7XX7Mj61uLYrj0qmeN0zi7XDon9JRAEhYQqAPLVNTeg= github.com/yagipy/maintidx v1.0.0 h1:h5NvIsCz+nRDapQ0exNv4aJ0yXSI0420omVANTv3GJM= github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk= github.com/yeya24/promlinter v0.2.0 h1:xFKDQ82orCU5jQujdaD8stOHiv8UN68BSdn2a8u8Y3o= github.com/yeya24/promlinter v0.2.0/go.mod h1:u54lkmBOZrpEbQQ6gox2zWKKLKu2SGe+2KOiextY+IA= +github.com/ykadowak/zerologlint v0.1.5 h1:Gy/fMz1dFQN9JZTPjv1hxEk+sRWm05row04Yoolgdiw= +github.com/ykadowak/zerologlint v0.1.5/go.mod h1:KaUskqF3e/v59oPmdq1U1DnKcuHokl2/K1U4pmIELKg= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -569,32 +578,39 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= -github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -gitlab.com/bosi/decorder v0.2.3 h1:gX4/RgK16ijY8V+BRQHAySfQAb354T7/xQpDB2n10P0= -gitlab.com/bosi/decorder v0.2.3/go.mod h1:9K1RB5+VPNQYtXtTDAzd2OEftsZb1oV0IrJrzChSdGE= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +gitlab.com/bosi/decorder v0.4.1 h1:VdsdfxhstabyhZovHafFw+9eJ6eU0d2CkFNJcZz/NU4= +gitlab.com/bosi/decorder v0.4.1/go.mod h1:jecSqWUew6Yle1pCr2eLWTensJMmsxHsBwt+PVbkAqA= +go-simpler.org/assert v0.7.0 h1:OzWWZqfNxt8cLS+MlUp6Tgk1HjPkmgdKBq9qvy8lZsA= +go-simpler.org/assert v0.7.0/go.mod h1:74Eqh5eI6vCK6Y5l3PI8ZYFXG4Sa+tkr70OIPJAUr28= +go-simpler.org/musttag v0.9.0 h1:Dzt6/tyP9ONr5g9h9P3cnYWCxeBFRkd0uJL/w+1Mxos= +go-simpler.org/musttag v0.9.0/go.mod h1:gA9nThnalvNSKpEoyp3Ko4/vCX2xTpqKoUtNqXOnVR4= +go-simpler.org/sloglint v0.4.0 h1:UVJuUJo63iNQNFEOtZ6o1xAgagVg/giVLLvG9nNLobI= +go-simpler.org/sloglint v0.4.0/go.mod h1:v6zJ++j/thFPhefs2wEXoCKwT10yo5nkBDYRCXyqgNQ= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8= +go.uber.org/automaxprocs v1.5.3/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0= +go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -606,12 +622,12 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= +golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc h1:ao2WRsKSzW6KuUY9IWPwWahcHCgR0s52IfwutMfEbdM= +golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/exp/typeparams v0.0.0-20220827204233-334a2380cb91/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/exp/typeparams v0.0.0-20221208152030-732eee02a75a h1:Jw5wfR+h9mnIYH+OtGT2im5wV1YGGDora5vTv/aa5bE= -golang.org/x/exp/typeparams v0.0.0-20221208152030-732eee02a75a/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp/typeparams v0.0.0-20240213143201-ec583247a57a h1:rrd/FiSCWtI24jk057yBSfEfHrzzjXva1VkDNWRXMag= +golang.org/x/exp/typeparams v0.0.0-20240213143201-ec583247a57a/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -624,7 +640,6 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -633,7 +648,6 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= @@ -641,8 +655,9 @@ golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic= +golang.org/x/mod v0.16.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-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -672,9 +687,6 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -683,18 +695,15 @@ golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= -golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= +golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 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= @@ -708,8 +717,9 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/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.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.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-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -742,18 +752,13 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/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-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -769,38 +774,39 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/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.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +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.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 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-20190307163923-6a08e3108db3/go.mod h1:25r3+/G6/xytQM8iWZKq3Hn0kr0rgFKPUNVEL/dr3z4= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190321232350-e250d351ecad/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -823,7 +829,6 @@ golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117220505-0cba7a3a9ee9/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= @@ -836,44 +841,31 @@ golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjs golang.org/x/tools v0.0.0-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200414032229-332987a829c3/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200624225443-88f3c62a19ff/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200812195022-5ae4c3c160a0/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200831203904-5a2aa26beb65/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201001104356-43ebab892c4c/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201230224404-63754364767c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= golang.org/x/tools v0.1.1-0.20210302220138-2ac05c832e1a/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.9-0.20211228192929-ee1ca4ffc4da/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= -golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= -golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw= +golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -894,16 +886,12 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= 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.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -933,13 +921,6 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -952,10 +933,6 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 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= @@ -968,13 +945,13 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj 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.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= @@ -982,12 +959,10 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 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= @@ -997,16 +972,12 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.4.1 h1:HPeloSr0mLOEMOkhT9Au5aeki44kvP6ka3v1xIsM6Zo= -honnef.co/go/tools v0.4.1/go.mod h1:36ZgoUOrqOk1GxwHhyryEkq8FQWkUO2xGuSMhUCcdvA= -mvdan.cc/gofumpt v0.4.0 h1:JVf4NN1mIpHogBj7ABpgOyZc65/UUOkKQFkoURsz4MM= -mvdan.cc/gofumpt v0.4.0/go.mod h1:PljLOHDeZqgS8opHRKLzp2It2VBuSdteAgqUfzMTxlQ= -mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I= -mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= -mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo= -mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= -mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d h1:3rvTIIM22r9pvXk+q3swxUQAQOxksVMGK7sml4nG57w= -mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d/go.mod h1:IeHQjmn6TOD+e4Z3RFiZMMsLVL+A96Nvptar8Fj71is= +honnef.co/go/tools v0.4.7 h1:9MDAWxMoSnB6QoSqiVr7P5mtkT9pOc1kSxchzPCnqJs= +honnef.co/go/tools v0.4.7/go.mod h1:+rnGS1THNh8zMwnd2oVOTL9QF6vmfyG6ZXBULae2uc0= +mvdan.cc/gofumpt v0.6.0 h1:G3QvahNDmpD+Aek/bNOLrFR2XC6ZAdo62dZu65gmwGo= +mvdan.cc/gofumpt v0.6.0/go.mod h1:4L0wf+kgIPZtcCWXynNS2e6bhmj73umwnuXSZarixzA= +mvdan.cc/unparam v0.0.0-20240104100049-c549a3470d14 h1:zCr3iRRgdk5eIikZNDphGcM6KGVTx3Yu+/Uu9Es254w= +mvdan.cc/unparam v0.0.0-20240104100049-c549a3470d14/go.mod h1:ZzZjEpJDOmx8TdVU6umamY3Xy0UAQUI2DHbf05USVbI= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/install.sh b/install.sh old mode 100644 new mode 100755 index 291c47ac5df4..e4728903490b --- a/install.sh +++ b/install.sh @@ -6,16 +6,13 @@ usage() { cat <] [-d] [] -b sets bindir or installation directory, Defaults to ./bin -d turns on debug logging - [tag] is a tag from + is a tag from https://github.com/golangci/golangci-lint/releases If tag is missing, then the latest will be used. - Generated by godownloader - https://github.com/goreleaser/godownloader - EOF exit 2 } @@ -77,6 +74,7 @@ get_binaries() { freebsd/mips64le) BINARIES="golangci-lint" ;; freebsd/ppc64le) BINARIES="golangci-lint" ;; freebsd/s390x) BINARIES="golangci-lint" ;; + illumos/amd64) BINARIES="golangci-lint" ;; linux/386) BINARIES="golangci-lint" ;; linux/amd64) BINARIES="golangci-lint" ;; linux/arm64) BINARIES="golangci-lint" ;; @@ -87,6 +85,7 @@ get_binaries() { linux/ppc64le) BINARIES="golangci-lint" ;; linux/s390x) BINARIES="golangci-lint" ;; linux/riscv64) BINARIES="golangci-lint" ;; + linux/loong64) BINARIES="golangci-lint" ;; netbsd/386) BINARIES="golangci-lint" ;; netbsd/amd64) BINARIES="golangci-lint" ;; netbsd/armv6) BINARIES="golangci-lint" ;; @@ -201,6 +200,7 @@ uname_os() { mingw*) os="windows" ;; cygwin*) os="windows" ;; win*) os="windows" ;; + sunos) [ $(uname -o) == "illumos" ] && os=illumos ;; esac echo "$os" } @@ -211,10 +211,12 @@ uname_arch() { x86) arch="386" ;; i686) arch="386" ;; i386) arch="386" ;; + i86pc) arch="amd64" ;; aarch64) arch="arm64" ;; armv5*) arch="armv5" ;; armv6*) arch="armv6" ;; armv7*) arch="armv7" ;; + loongarch64) arch="loong64" ;; esac echo ${arch} } @@ -224,6 +226,7 @@ uname_os_check() { darwin) return 0 ;; dragonfly) return 0 ;; freebsd) return 0 ;; + illumos) return 0;; linux) return 0 ;; android) return 0 ;; nacl) return 0 ;; @@ -254,6 +257,7 @@ uname_arch_check() { s390x) return 0 ;; riscv64) return 0 ;; amd64p32) return 0 ;; + loong64) return 0 ;; esac log_crit "uname_arch_check '$(uname -m)' got converted to '$arch' which is not a GOARCH value." return 1 diff --git a/internal/cache/cache.go b/internal/cache/cache.go index e9638c8e16f2..299fd5279021 100644 --- a/internal/cache/cache.go +++ b/internal/cache/cache.go @@ -12,6 +12,7 @@ import ( "bytes" "crypto/sha256" "encoding/hex" + "errors" "fmt" "io" "os" @@ -20,8 +21,6 @@ import ( "strings" "time" - "github.com/pkg/errors" - "github.com/golangci/golangci-lint/internal/renameio" "github.com/golangci/golangci-lint/internal/robustio" ) @@ -80,7 +79,7 @@ func (c *Cache) fileName(id [HashSize]byte, key string) string { var errMissing = errors.New("cache entry not found") func IsErrMissing(err error) bool { - return errors.Cause(err) == errMissing + return errors.Is(err, errMissing) } const ( @@ -169,10 +168,10 @@ func (c *Cache) get(id ActionID) (Entry, error) { etime := entry[1 : 1+20] var buf [HashSize]byte if _, err = hex.Decode(buf[:], eid); err != nil || buf != id { - return failed(errors.Wrapf(err, "failed to hex decode eid data in %s", fileName)) + return failed(fmt.Errorf("failed to hex decode eid data in %s: %w", fileName, err)) } if _, err = hex.Decode(buf[:], eout); err != nil { - return failed(errors.Wrapf(err, "failed to hex decode eout data in %s", fileName)) + return failed(fmt.Errorf("failed to hex decode eout data in %s: %w", fileName, err)) } i := 0 for i < len(esize) && esize[i] == ' ' { @@ -192,7 +191,7 @@ func (c *Cache) get(id ActionID) (Entry, error) { } if err = c.used(fileName); err != nil { - return failed(errors.Wrapf(err, "failed to mark %s as used", fileName)) + return failed(fmt.Errorf("failed to mark %s as used: %w", fileName, err)) } return Entry{buf, size, time.Unix(0, tm)}, nil @@ -264,7 +263,7 @@ func (c *Cache) used(file string) error { if os.IsNotExist(err) { return errMissing } - return errors.Wrapf(err, "failed to stat file %s", file) + return fmt.Errorf("failed to stat file %s: %w", file, err) } if c.now().Sub(info.ModTime()) < mtimeInterval { @@ -272,7 +271,7 @@ func (c *Cache) used(file string) error { } if err := os.Chtimes(file, c.now(), c.now()); err != nil { - return errors.Wrapf(err, "failed to change time of file %s", file) + return fmt.Errorf("failed to change time of file %s: %w", file, err) } return nil @@ -385,7 +384,7 @@ func (c *Cache) putIndexEntry(id ActionID, out OutputID, size int64, allowVerify return err } if err = os.Chtimes(file, c.now(), c.now()); err != nil { // mainly for tests - return errors.Wrapf(err, "failed to change time of file %s", file) + return fmt.Errorf("failed to change time of file %s: %w", file, err) } return nil @@ -443,7 +442,7 @@ func (c *Cache) copyFile(file io.ReadSeeker, out OutputID, size int64) error { if f, openErr := os.Open(name); openErr == nil { h := sha256.New() if _, copyErr := io.Copy(h, f); copyErr != nil { - return errors.Wrap(copyErr, "failed to copy to sha256") + return fmt.Errorf("failed to copy to sha256: %w", copyErr) } f.Close() @@ -519,7 +518,7 @@ func (c *Cache) copyFile(file io.ReadSeeker, out OutputID, size int64) error { return err } if err = os.Chtimes(name, c.now(), c.now()); err != nil { // mainly for tests - return errors.Wrapf(err, "failed to change time of file %s", name) + return fmt.Errorf("failed to change time of file %s: %w", name, err) } return nil diff --git a/internal/errorutil/errors.go b/internal/errorutil/errors.go index 5cb86d669882..c8a3a0357e7c 100644 --- a/internal/errorutil/errors.go +++ b/internal/errorutil/errors.go @@ -6,11 +6,11 @@ import ( // PanicError can be used to not print stacktrace twice type PanicError struct { - recovered interface{} + recovered any stack []byte } -func NewPanicError(recovered interface{}, stack []byte) *PanicError { +func NewPanicError(recovered any, stack []byte) *PanicError { return &PanicError{recovered: recovered, stack: stack} } diff --git a/internal/pkgcache/pkgcache.go b/internal/pkgcache/pkgcache.go index 83e607387543..3b3422eb7a8c 100644 --- a/internal/pkgcache/pkgcache.go +++ b/internal/pkgcache/pkgcache.go @@ -4,12 +4,12 @@ import ( "bytes" "encoding/gob" "encoding/hex" + "errors" "fmt" "runtime" "sort" "sync" - "github.com/pkg/errors" "golang.org/x/tools/go/packages" "github.com/golangci/golangci-lint/internal/cache" @@ -54,14 +54,14 @@ func (c *Cache) Trim() { }) } -func (c *Cache) Put(pkg *packages.Package, mode HashMode, key string, data interface{}) error { +func (c *Cache) Put(pkg *packages.Package, mode HashMode, key string, data any) error { var err error buf := &bytes.Buffer{} c.sw.TrackStage("gob", func() { err = gob.NewEncoder(buf).Encode(data) }) if err != nil { - return errors.Wrap(err, "failed to gob encode") + return fmt.Errorf("failed to gob encode: %w", err) } var aID cache.ActionID @@ -71,13 +71,13 @@ func (c *Cache) Put(pkg *packages.Package, mode HashMode, key string, data inter if err == nil { subkey, subkeyErr := cache.Subkey(aID, key) if subkeyErr != nil { - err = errors.Wrap(subkeyErr, "failed to build subkey") + err = fmt.Errorf("failed to build subkey: %w", subkeyErr) } aID = subkey } }) if err != nil { - return errors.Wrapf(err, "failed to calculate package %s action id", pkg.Name) + return fmt.Errorf("failed to calculate package %s action id: %w", pkg.Name, err) } c.ioSem <- struct{}{} c.sw.TrackStage("cache io", func() { @@ -85,7 +85,7 @@ func (c *Cache) Put(pkg *packages.Package, mode HashMode, key string, data inter }) <-c.ioSem if err != nil { - return errors.Wrapf(err, "failed to save data to low-level cache by key %s for package %s", key, pkg.Name) + return fmt.Errorf("failed to save data to low-level cache by key %s for package %s: %w", key, pkg.Name, err) } return nil @@ -93,7 +93,7 @@ func (c *Cache) Put(pkg *packages.Package, mode HashMode, key string, data inter var ErrMissing = errors.New("missing data") -func (c *Cache) Get(pkg *packages.Package, mode HashMode, key string, data interface{}) error { +func (c *Cache) Get(pkg *packages.Package, mode HashMode, key string, data any) error { var aID cache.ActionID var err error c.sw.TrackStage("key build", func() { @@ -101,13 +101,13 @@ func (c *Cache) Get(pkg *packages.Package, mode HashMode, key string, data inter if err == nil { subkey, subkeyErr := cache.Subkey(aID, key) if subkeyErr != nil { - err = errors.Wrap(subkeyErr, "failed to build subkey") + err = fmt.Errorf("failed to build subkey: %w", subkeyErr) } aID = subkey } }) if err != nil { - return errors.Wrapf(err, "failed to calculate package %s action id", pkg.Name) + return fmt.Errorf("failed to calculate package %s action id: %w", pkg.Name, err) } var b []byte @@ -120,14 +120,14 @@ func (c *Cache) Get(pkg *packages.Package, mode HashMode, key string, data inter if cache.IsErrMissing(err) { return ErrMissing } - return errors.Wrapf(err, "failed to get data from low-level cache by key %s for package %s", key, pkg.Name) + return fmt.Errorf("failed to get data from low-level cache by key %s for package %s: %w", key, pkg.Name, err) } c.sw.TrackStage("gob", func() { err = gob.NewDecoder(bytes.NewReader(b)).Decode(data) }) if err != nil { - return errors.Wrap(err, "failed to gob decode") + return fmt.Errorf("failed to gob decode: %w", err) } return nil @@ -136,12 +136,12 @@ func (c *Cache) Get(pkg *packages.Package, mode HashMode, key string, data inter func (c *Cache) pkgActionID(pkg *packages.Package, mode HashMode) (cache.ActionID, error) { hash, err := c.packageHash(pkg, mode) if err != nil { - return cache.ActionID{}, errors.Wrap(err, "failed to get package hash") + return cache.ActionID{}, fmt.Errorf("failed to get package hash: %w", err) } key, err := cache.NewHash("action ID") if err != nil { - return cache.ActionID{}, errors.Wrap(err, "failed to make a hash") + return cache.ActionID{}, fmt.Errorf("failed to make a hash: %w", err) } fmt.Fprintf(key, "pkgpath %s\n", pkg.PkgPath) fmt.Fprintf(key, "pkghash %s\n", hash) @@ -167,7 +167,7 @@ func (c *Cache) packageHash(pkg *packages.Package, mode HashMode) (string, error key, err := cache.NewHash("package hash") if err != nil { - return "", errors.Wrap(err, "failed to make a hash") + return "", fmt.Errorf("failed to make a hash: %w", err) } fmt.Fprintf(key, "pkgpath %s\n", pkg.PkgPath) @@ -176,7 +176,7 @@ func (c *Cache) packageHash(pkg *packages.Package, mode HashMode) (string, error h, fErr := cache.FileHash(f) <-c.ioSem if fErr != nil { - return "", errors.Wrapf(fErr, "failed to calculate file %s hash", f) + return "", fmt.Errorf("failed to calculate file %s hash: %w", f, fErr) } fmt.Fprintf(key, "file %s %x\n", f, h) } @@ -199,7 +199,7 @@ func (c *Cache) packageHash(pkg *packages.Package, mode HashMode) (string, error depHash, depErr := c.packageHash(dep, depMode) if depErr != nil { - return errors.Wrapf(depErr, "failed to calculate hash for dependency %s with mode %d", dep.Name, depMode) + return fmt.Errorf("failed to calculate hash for dependency %s with mode %d: %w", dep.Name, depMode, depErr) } fmt.Fprintf(key, "import %s %s\n", dep.PkgPath, depHash) diff --git a/jsonschema/custom-gcl.jsonschema.json b/jsonschema/custom-gcl.jsonschema.json new file mode 100644 index 000000000000..71ea3e98df65 --- /dev/null +++ b/jsonschema/custom-gcl.jsonschema.json @@ -0,0 +1,76 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$ref": "#/$defs/Configuration", + "$defs": { + "Configuration": { + "properties": { + "version": { + "type": "string", + "description": "golangci-lint version." + }, + "name": { + "type": "string", + "description": "Name of the binary." + }, + "destination": { + "type": "string", + "description": "Destination is the path to a directory to store the binary." + }, + "plugins": { + "items": { + "$ref": "#/$defs/Plugin" + }, + "type": "array", + "description": "Plugins information." + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "version" + ], + "description": "Configuration represents the configuration file." + }, + "Plugin": { + "oneOf": [ + { + "required": [ + "version" + ], + "title": "version" + }, + { + "required": [ + "path" + ], + "title": "path" + } + ], + "properties": { + "module": { + "type": "string", + "description": "Module name." + }, + "import": { + "type": "string", + "description": "Import to use." + }, + "version": { + "type": "string", + "description": "Version of the module.\nOnly for module available through a Go proxy." + }, + "path": { + "type": "string", + "description": "Path to the local module.\nOnly for local module." + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "module" + ], + "description": "Plugin represents information about a plugin." + } + }, + "description": "mygcl configuration definition file" +} \ No newline at end of file diff --git a/jsonschema/golangci.jsonschema.json b/jsonschema/golangci.jsonschema.json new file mode 100644 index 000000000000..0355f9b804ce --- /dev/null +++ b/jsonschema/golangci.jsonschema.json @@ -0,0 +1,3462 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://json.schemastore.org/golangci-lint.json", + "definitions": { + "gocritic-checks": { + "enum": [ + "appendAssign", + "appendCombine", + "argOrder", + "assignOp", + "badCall", + "badCond", + "badLock", + "badRegexp", + "badSorting", + "boolExprSimplify", + "builtinShadow", + "builtinShadowDecl", + "captLocal", + "caseOrder", + "codegenComment", + "commentedOutCode", + "commentedOutImport", + "commentFormatting", + "defaultCaseOrder", + "deferUnlambda", + "deferInLoop", + "deprecatedComment", + "docStub", + "dupArg", + "dupBranchBody", + "dupCase", + "dupImport", + "dupSubExpr", + "dynamicFmtString", + "elseif", + "emptyDecl", + "emptyFallthrough", + "emptyStringTest", + "equalFold", + "evalOrder", + "exitAfterDefer", + "exposedSyncMutex", + "externalErrorReassign", + "filepathJoin", + "flagDeref", + "flagName", + "hexLiteral", + "httpNoBody", + "hugeParam", + "ifElseChain", + "importShadow", + "indexAlloc", + "initClause", + "ioutilDeprecated", + "mapKey", + "methodExprCall", + "nestingReduce", + "newDeref", + "nilValReturn", + "octalLiteral", + "offBy1", + "paramTypeCombine", + "preferDecodeRune", + "preferFilepathJoin", + "preferFprint", + "preferStringWriter", + "preferWriteByte", + "ptrToRefParam", + "rangeExprCopy", + "rangeValCopy", + "redundantSprint", + "regexpMust", + "regexpPattern", + "regexpSimplify", + "returnAfterHttpError", + "ruleguard", + "singleCaseSwitch", + "sliceClear", + "sloppyLen", + "sloppyReassign", + "sloppyTypeAssert", + "sortSlice", + "sprintfQuotedString", + "sqlQuery", + "stringConcatSimplify", + "stringsCompare", + "stringXbytes", + "suspiciousSorting", + "switchTrue", + "syncMapLoadAndDelete", + "timeCmpSimplify", + "timeExprSimplify", + "tooManyResultsChecker", + "truncateCmp", + "typeAssertChain", + "typeDefFirst", + "typeSwitchVar", + "typeUnparen", + "uncheckedInlineErr", + "underef", + "unlabelStmt", + "unlambda", + "unnamedResult", + "unnecessaryBlock", + "unnecessaryDefer", + "unslice", + "valSwap", + "weakCond", + "whyNoLint", + "wrapperFunc", + "yodaStyleExpr" + ] + }, + "gocritic-tags": { + "enum": [ + "diagnostic", + "style", + "performance", + "experimental", + "opinionated", + "security" + ] + }, + "gosec-rules": { + "enum": [ + "G101", + "G102", + "G103", + "G104", + "G106", + "G107", + "G108", + "G109", + "G110", + "G111", + "G112", + "G113", + "G114", + "G201", + "G202", + "G203", + "G204", + "G301", + "G302", + "G303", + "G304", + "G305", + "G306", + "G307", + "G401", + "G402", + "G403", + "G404", + "G501", + "G502", + "G503", + "G504", + "G505", + "G601", + "G602" + ] + }, + "govet-analyzers": { + "enum": [ + "appends", + "asmdecl", + "assign", + "atomic", + "atomicalign", + "bools", + "buildtag", + "cgocall", + "composites", + "copylocks", + "deepequalerrors", + "defers", + "directive", + "errorsas", + "fieldalignment", + "findcall", + "framepointer", + "httpresponse", + "ifaceassert", + "loopclosure", + "lostcancel", + "nilfunc", + "nilness", + "printf", + "reflectvaluecompare", + "shadow", + "shift", + "sigchanyzer", + "slog", + "sortslice", + "stdmethods", + "stringintconv", + "structtag", + "testinggoroutine", + "tests", + "unmarshal", + "unreachable", + "unsafeptr", + "unusedresult", + "unusedwrite" + ] + }, + "linters": { + "$comment": "anyOf with enum is used to allow auto completion of non-custom linters", + "description": "Linters usable.", + "anyOf": [ + { + "enum": [ + "asasalint", + "asciicheck", + "bidichk", + "bodyclose", + "containedctx", + "contextcheck", + "cyclop", + "deadcode", + "decorder", + "depguard", + "dogsled", + "dupl", + "dupword", + "durationcheck", + "errcheck", + "errchkjson", + "errname", + "errorlint", + "execinquery", + "exhaustive", + "exhaustivestruct", + "exhaustruct", + "exportloopref", + "forbidigo", + "forcetypeassert", + "funlen", + "gci", + "ginkgolinter", + "gocheckcompilerdirectives", + "gochecknoglobals", + "gochecknoinits", + "gochecksumtype", + "gocognit", + "goconst", + "gocritic", + "gocyclo", + "godot", + "godox", + "goerr113", + "gofmt", + "gofumpt", + "goheader", + "goimports", + "golint", + "gomnd", + "gomoddirectives", + "gomodguard", + "goprintffuncname", + "gosec", + "gosimple", + "gosmopolitan", + "govet", + "grouper", + "ifshort", + "importas", + "inamedparam", + "ineffassign", + "interfacebloat", + "interfacer", + "ireturn", + "lll", + "loggercheck", + "maintidx", + "makezero", + "maligned", + "mirror", + "misspell", + "musttag", + "nakedret", + "nestif", + "nilerr", + "nilnil", + "nlreturn", + "noctx", + "nolintlint", + "nonamedreturns", + "nosnakecase", + "nosprintfhostport", + "paralleltest", + "perfsprint", + "prealloc", + "predeclared", + "promlinter", + "protogetter", + "reassign", + "revive", + "rowserrcheck", + "scopelint", + "sloglint", + "sqlclosecheck", + "staticcheck", + "structcheck", + "stylecheck", + "tagalign", + "tagliatelle", + "tenv", + "testableexamples", + "testifylint", + "testpackage", + "thelper", + "tparallel", + "typecheck", + "unconvert", + "unparam", + "unused", + "usestdlibvars", + "varcheck", + "varnamelen", + "wastedassign", + "whitespace", + "wrapcheck", + "wsl", + "zerologlint" + ] + }, + { + "type": "string" + } + ] + }, + "issue-match-path": { + "type": "object", + "properties": { + "path": { + "type": "string" + }, + "severity": { + "$comment": "This is here only to allow `additionalProperties: false`." + } + }, + "additionalProperties": false + }, + "issue-match-linters": { + "type": "object", + "properties": { + "linters": { + "type": "array", + "items": { + "$ref": "#/definitions/linters" + } + }, + "severity": { + "$comment": "This is here only to allow `additionalProperties: false`." + } + }, + "additionalProperties": false + }, + "issue-match-source": { + "type": "object", + "properties": { + "source": { + "type": "string" + }, + "severity": { + "$comment": "This is here only to allow `additionalProperties: false`." + } + }, + "additionalProperties": false + }, + "issue-match-text": { + "type": "object", + "properties": { + "text": { + "type": "string" + }, + "severity": { + "$comment": "This is here only to allow `additionalProperties: false`." + } + }, + "additionalProperties": false + } + }, + "properties": { + "run": { + "description": "Options for analysis running,", + "type": "object", + "properties": { + "concurrency": { + "description": "Number of concurrent runners. Defaults to the number of available CPU cores.", + "type": "integer", + "minimum": 1, + "examples": [4] + }, + "timeout": { + "description": "Timeout for the analysis.", + "type": "string", + "pattern": "^\\d*[sm]$", + "default": "1m", + "examples": ["30s", "5m"] + }, + "issues-exit-code": { + "description": "Exit code when at least one issue was found.", + "type": "integer", + "default": 1 + }, + "tests": { + "description": "Enable inclusion of test files.", + "type": "boolean", + "default": true + }, + "build-tags": { + "description": "List of build tags to pass to all linters.", + "type": "array", + "items": { + "type": "string" + }, + "default": [], + "examples": [["mytag"]] + }, + "skip-dirs": { + "description": "Which directories to skip: issues from them won't be reported.", + "type": "array", + "items": { + "description": "You can use regexp here. The regexp is applied on the full path.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.", + "type": "string", + "examples": ["generated.*"] + }, + "default": [], + "examples": [["src/external_libs", "autogenerated_by_my_lib"]] + }, + "skip-dirs-use-default": { + "description": "Enable skipping of directories \"vendor\", \"third_party\", \"testdata\", \"examples\", \"Godeps\", and \"builtin\".", + "type": "boolean", + "default": true + }, + "skip-files": { + "description": "Which files to skip: they will be analyzed, but issues from them will not be reported.", + "type": "array", + "items": { + "description": "You can use regexp here. There is no need to include all autogenerated files, we confidently recognize them. If that is not the case, please let us know.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.", + "type": "string", + "examples": [".*\\.my\\.go$"] + }, + "default": [], + "examples": [[".*\\.my\\.go$", "lib/bad.go"]] + }, + "modules-download-mode": { + "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.", + "enum": ["mod", "readonly", "vendor"] + }, + "allow-parallel-runners": { + "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.", + "type": "boolean", + "default": false + }, + "allow-serial-runners": { + "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.", + "type": "boolean", + "default": false + }, + "print-resources-usage": { + "description": "Print avg and max memory usage of golangci-lint and total time.", + "type": "boolean", + "default": false + }, + "show-stats": { + "description": "Show statistics per linter.", + "type": "boolean", + "default": false + }, + "go": { + "description": "Targeted Go version.", + "type": "string", + "default": "1.17" + } + }, + "additionalProperties": false + }, + "output": { + "description": "Output configuration options.", + "type": "object", + "properties": { + "format": { + "description": "Output format to use.", + "pattern": "^(,?(colored-line-number|line-number|json|colored-tab|tab|checkstyle|code-climate|junit-xml|github-actions|teamcity)(:[^,]+)?)+$", + "default": "colored-line-number", + "examples": [ + "colored-line-number", + "checkstyle:report.json,colored-line-number", + "line-number:golangci-lint.out,colored-line-number:stdout" + ] + }, + "print-issued-lines": { + "description": "Print lines of code with issue.", + "type": "boolean", + "default": true + }, + "print-linter-name": { + "description": "Print linter name in the end of issue text.", + "type": "boolean", + "default": true + }, + "uniq-by-line": { + "description": "Make issues output unique by line.", + "type": "boolean", + "default": true + }, + "path-prefix": { + "description": "Add a prefix to the output file references.", + "type": "string", + "default": "" + }, + "sort-results": { + "description": "Sort results by: filepath, line and column.", + "type": "boolean", + "default": true + } + }, + "additionalProperties": false + }, + "linters-settings": { + "description": "All available settings of specific linters.", + "type": "object", + "properties": { + "dupword": { + "type": "object", + "additionalProperties": false, + "properties": { + "keywords": { + "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.", + "type": "array", + "uniqueItems": true, + "items": { + "type": "string", + "examples": ["the", "and", "a"] + } + }, + "ignore": { + "description": "Keywords used to ignore detection.", + "type": "array", + "uniqueItems": true, + "items": { + "type": "string", + "examples": ["0C0C"] + } + } + } + }, + "asasalint": { + "type": "object", + "additionalProperties": false, + "properties": { + "exclude": { + "description": "To specify a set of function names to exclude.", + "type": "array", + "uniqueItems": true, + "items": { + "type": "string", + "examples": ["\\.Wrapf"] + } + }, + "use-builtin-exclusions": { + "description": "To enable/disable the asasalint builtin exclusions of function names.", + "type": "boolean", + "default": true + }, + "ignore-test": { + "description": "Ignore *_test.go files.", + "type": "boolean", + "default": false + } + } + }, + "bidichk": { + "type": "object", + "additionalProperties": false, + "properties": { + "left-to-right-embedding": { + "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING", + "type": "boolean", + "default": false + }, + "right-to-left-embedding": { + "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING", + "type": "boolean", + "default": false + }, + "pop-directional-formatting": { + "description": "Disallow: POP-DIRECTIONAL-FORMATTING", + "type": "boolean", + "default": false + }, + "left-to-right-override": { + "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE", + "type": "boolean", + "default": false + }, + "right-to-left-override": { + "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE", + "type": "boolean", + "default": false + }, + "left-to-right-isolate": { + "description": "Disallow: LEFT-TO-RIGHT-ISOLATE", + "type": "boolean", + "default": false + }, + "right-to-left-isolate": { + "description": "Disallow: RIGHT-TO-LEFT-ISOLATE", + "type": "boolean", + "default": false + }, + "first-strong-isolate": { + "description": "Disallow: FIRST-STRONG-ISOLATE", + "type": "boolean", + "default": false + }, + "pop-directional-isolate": { + "description": "Disallow: POP-DIRECTIONAL-ISOLATE", + "type": "boolean", + "default": false + } + } + }, + "cyclop": { + "type": "object", + "additionalProperties": false, + "properties": { + "skip-tests": { + "description": "Should the linter execute on test files as well", + "type": "boolean", + "default": false + }, + "max-complexity": { + "description": "Max complexity the function can have", + "type": "integer", + "default": 10, + "minimum": 0 + }, + "package-average": { + "description": "Max average complexity in package", + "type": "number", + "default": 0, + "minimum": 0 + } + } + }, + "decorder": { + "type": "object", + "additionalProperties": false, + "properties": { + "dec-order": { + "type": "array", + "default": [["type", "const", "var", "func"]], + "items": { + "enum": ["type", "const", "var", "func"] + } + }, + "ignore-underscore-vars": { + "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks", + "default": true, + "type": "boolean" + }, + "disable-dec-order-check": { + "description": "Order of declarations is not checked", + "default": true, + "type": "boolean" + }, + "disable-init-func-first-check": { + "description": "Allow init func to be anywhere in file", + "default": true, + "type": "boolean" + }, + "disable-dec-num-check": { + "description": "Multiple global type, const and var declarations are allowed", + "default": true, + "type": "boolean" + }, + "disable-type-dec-num-check": { + "description": "Type declarations will be ignored for dec num check", + "default": true, + "type": "boolean" + }, + "disable-const-dec-num-check": { + "description": "Const declarations will be ignored for dec num check", + "default": true, + "type": "boolean" + }, + "disable-var-dec-num-check": { + "description": "Var declarations will be ignored for dec num check", + "default": true, + "type": "boolean" + } + } + }, + "depguard": { + "type": "object", + "additionalProperties": false, + "properties": { + "rules": { + "description": "Rules to apply.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^[^.]+$": { + "description": "Name of a rule.", + "additionalProperties": false, + "type": "object", + "properties": { + "list-mode": { + "description": "Used to determine the package matching priority.", + "enum": ["original", "strict", "lax"], + "default": "original" + }, + "files": { + "description": "List of file globs that will match this list of settings to compare against.", + "additionalProperties": false, + "type": "array", + "items": { + "type": "string" + } + }, + "allow": { + "description": "List of allowed packages.", + "additionalProperties": false, + "type": "array", + "items": { + "type": "string" + } + }, + "deny": { + "description": "Packages that are not allowed where the value is a suggestion.", + "additionalProperties": false, + "type": "array", + "items": { + "additionalProperties": false, + "type": "object", + "properties": { + "desc": { + "description": "Description", + "type": "string" + }, + "pkg": { + "description": "Package", + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "dogsled": { + "type": "object", + "additionalProperties": false, + "properties": { + "max-blank-identifiers": { + "description": "Check assignments with too many blank identifiers.", + "type": "integer", + "default": 2, + "minimum": 0 + } + } + }, + "dupl": { + "type": "object", + "additionalProperties": false, + "properties": { + "threshold": { + "description": "Tokens count to trigger issue.", + "type": "integer", + "default": 150, + "minimum": 0 + } + } + }, + "errcheck": { + "type": "object", + "additionalProperties": false, + "properties": { + "check-type-assertions": { + "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`", + "type": "boolean", + "default": false + }, + "check-blank": { + "description": "Report about assignment of errors to blank identifier", + "type": "boolean", + "default": false + }, + "ignore": { + "description": "DEPRECATED: use `exclude-functions` instead. Comma-separated list of pairs of the form \"pkg:regex\".", + "type": "string", + "default": "fmt:.*" + }, + "exclude": { + "description": "DEPRECATED: use `exclude-functions` instead. Path to a file containing a list of functions to exclude from checking.", + "type": "string", + "examples": ["/path/to/file.txt"] + }, + "exclude-functions": { + "description": "List of functions to exclude from checking, where each entry is a single function to exclude", + "type": "array", + "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"], + "items": { + "type": "string" + } + }, + "disable-default-exclusions": { + "description": "To disable the errcheck built-in exclude list", + "type": "boolean", + "default": false + } + } + }, + "errchkjson": { + "type": "object", + "additionalProperties": false, + "properties": { + "check-error-free-encoding": { + "type": "boolean", + "default": false + }, + "report-no-exported": { + "description": "Issue on struct that doesn't have exported fields.", + "type": "boolean", + "default": false + } + } + }, + "errorlint": { + "type": "object", + "additionalProperties": false, + "properties": { + "errorf": { + "description": "Check whether fmt.Errorf uses the %w verb for formatting errors", + "type": "boolean", + "default": true + }, + "errorf-multi": { + "description": "Permit more than 1 %w verb, valid per Go 1.20", + "type": "boolean", + "default": true + }, + "asserts": { + "description": "Check for plain type assertions and type switches.", + "type": "boolean", + "default": true + }, + "comparison": { + "description": "Check for plain error comparisons", + "type": "boolean", + "default": true + } + } + }, + "exhaustive": { + "type": "object", + "additionalProperties": false, + "properties": { + "check": { + "description": "Program elements to check for exhaustiveness.", + "type": "array", + "uniqueItems": true, + "items": { + "type": "string", + "examples": ["switch", "map"] + } + }, + "check-generated": { + "description": "Check switch statements in generated files", + "type": "boolean", + "default": false + }, + "explicit-exhaustive-switch": { + "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.", + "type": "boolean", + "default": false + }, + "explicit-exhaustive-map": { + "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.", + "type": "boolean", + "default": false + }, + "default-case-required": { + "description": "Switch statement requires default case even if exhaustive.", + "type": "boolean", + "default": false + }, + "default-signifies-exhaustive": { + "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.", + "type": "boolean", + "default": false + }, + "ignore-enum-members": { + "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness", + "type": "string" + }, + "ignore-enum-types": { + "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.", + "type": "string" + }, + "package-scope-only": { + "description": "Consider enums only in package scopes, not in inner scopes.", + "type": "boolean", + "default": false + } + } + }, + "exhaustivestruct": { + "type": "object", + "additionalProperties": false, + "properties": { + "struct-patterns": { + "description": "Struct Patterns is list of expressions to match struct packages (written using `path` matching syntax)", + "type": "array", + "examples": ["^print.*$"], + "items": { + "type": "string" + } + } + } + }, + "exhaustruct": { + "type": "object", + "additionalProperties": false, + "properties": { + "include": { + "description": "List of regular expressions to match struct packages and names.", + "type": "array", + "examples": [".*\\.Test"], + "items": { + "type": "string" + } + }, + "exclude": { + "description": "List of regular expressions to exclude struct packages and names from check.", + "type": "array", + "examples": ["cobra\\.Command$"], + "items": { + "type": "string" + } + } + } + }, + "forbidigo": { + "type": "object", + "additionalProperties": false, + "properties": { + "exclude-godoc-examples": { + "description": "Exclude code in godoc examples.", + "type": "boolean", + "default": true + }, + "analyze-types": { + "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.", + "type": "boolean", + "default": true + }, + "forbid": { + "description": "List of identifiers to forbid (written using `regexp`)", + "type": "array", + "examples": ["^print.*$"], + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "p": { + "description": "Pattern", + "type": "string" + }, + "pkg": { + "description": "Package", + "type": "string" + }, + "msg": { + "description": "Message", + "type": "string" + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "funlen": { + "type": "object", + "additionalProperties": false, + "properties": { + "lines": { + "description": "Limit lines number per function.", + "type": "integer", + "default": 60 + }, + "statements": { + "description": "Limit statements number per function.", + "type": "integer", + "default": 40 + }, + "ignore-comments": { + "description": "Ignore comments when counting lines.", + "type": "boolean", + "default": false + } + } + }, + "gci": { + "type": "object", + "additionalProperties": false, + "properties": { + "local-prefixes": { + "description": "DEPRECATED: use 'sections' and 'prefix(github.com/org/project)' instead.", + "type": "string", + "examples": ["github.com/org/project"] + }, + "sections": { + "description": "Section configuration to compare against.", + "type": "array", + "items": { + "type": "string" + }, + "default": ["standard", "default"] + }, + "skip-generated": { + "description": "Skip generated files.", + "type": "boolean", + "default": true + }, + "custom-order": { + "description": "Enable custom order of sections.", + "type": "boolean", + "default": false + } + } + }, + "ginkgolinter": { + "type": "object", + "additionalProperties": false, + "properties": { + "suppress-len-assertion": { + "description": "Suppress the wrong length assertion warning.", + "type": "boolean", + "default": false + }, + "suppress-nil-assertion": { + "description": "Suppress the wrong nil assertion warning.", + "type": "boolean", + "default": false + }, + "suppress-err-assertion": { + "description": "Suppress the wrong error assertion warning.", + "type": "boolean", + "default": false + }, + "suppress-compare-assertion": { + "description": "Suppress the wrong comparison assertion warning.", + "type": "boolean", + "default": false + }, + "suppress-async-assertion": { + "description": "Suppress the function all in async assertion warning.", + "type": "boolean", + "default": false + }, + "suppress-type-compare-assertion": { + "description": "Suppress warning for comparing values from different types, like int32 and uint32.", + "type": "boolean", + "default": false + }, + "forbid-focus-container": { + "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.", + "type": "boolean", + "default": false + }, + "allow-havelen-zero": { + "description": "Don't trigger warnings for HaveLen(0).", + "type": "boolean", + "default": false + } + } + }, + "gocognit": { + "type": "object", + "additionalProperties": false, + "properties": { + "min-complexity": { + "description": "Minimal code complexity to report (we recommend 10-20).", + "type": "integer", + "default": 30 + } + } + }, + "goconst": { + "type": "object", + "additionalProperties": false, + "properties": { + "match-constant": { + "description": "Look for existing constants matching the values", + "type": "boolean", + "default": true + }, + "min-len": { + "description": "Minimum length of string constant.", + "type": "integer", + "default": 3 + }, + "min-occurrences": { + "description": "Minimum occurrences count to trigger.", + "type": "integer", + "default": 3 + }, + "ignore-tests": { + "description": "Ignore test files.", + "type": "boolean", + "default": false + }, + "ignore-calls": { + "description": "Ignore when constant is not used as function argument", + "type": "boolean", + "default": true + }, + "ignore-strings": { + "description": "Exclude strings matching the given regular expression", + "type": "string" + }, + "numbers": { + "description": "Search also for duplicated numbers.", + "type": "boolean", + "default": false + }, + "min": { + "description": "Minimum value, only works with `numbers`", + "type": "integer", + "default": 3 + }, + "max": { + "description": "Maximum value, only works with `numbers`", + "type": "integer", + "default": 3 + } + } + }, + "gocritic": { + "type": "object", + "properties": { + "enabled-checks": { + "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.", + "type": "array", + "items": { + "$ref": "#/definitions/gocritic-checks" + } + }, + "disabled-checks": { + "description": "Which checks should be disabled.", + "type": "array", + "items": { + "$ref": "#/definitions/gocritic-checks" + }, + "default": [] + }, + "enabled-tags": { + "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.", + "type": "array", + "items": { + "$ref": "#/definitions/gocritic-tags" + } + }, + "disabled-tags": { + "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.", + "type": "array", + "items": { + "$ref": "#/definitions/gocritic-tags" + } + }, + "settings": { + "description": "Settings passed to gocritic. Properties must be valid and enabled check names.", + "type": "object", + "propertyNames": { + "$ref": "#/definitions/gocritic-checks" + } + } + } + }, + "gocyclo": { + "type": "object", + "additionalProperties": false, + "properties": { + "min-complexity": { + "description": "Minimum code complexity to report (we recommend 10-20).", + "type": "integer", + "default": 30 + } + } + }, + "godot": { + "type": "object", + "additionalProperties": false, + "properties": { + "scope": { + "description": "Comments to be checked.", + "enum": ["declarations", "toplevel", "all"], + "default": "declarations" + }, + "exclude": { + "description": "List of regexps for excluding particular comment lines from check.", + "type": "array", + "items": { + "type": "string" + } + }, + "period": { + "description": "Check that each sentence ends with a period.", + "type": "boolean", + "default": true + }, + "capital": { + "description": "Check that each sentence starts with a capital letter.", + "type": "boolean", + "default": false + }, + "check-all": { + "description": "DEPRECATED: Check all top-level comments, not only declarations.", + "type": "boolean", + "default": false + } + } + }, + "godox": { + "type": "object", + "additionalProperties": false, + "properties": { + "keywords": { + "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.", + "type": "array", + "items": { + "type": "string" + }, + "default": ["TODO", "BUG", "FIXME"] + } + } + }, + "gofmt": { + "type": "object", + "additionalProperties": false, + "properties": { + "simplify": { + "description": "Simplify code.", + "type": "boolean", + "default": true + }, + "rewrite-rules": { + "description": "Apply the rewrite rules to the source before reformatting.", + "type": "array", + "items": { + "type": "object", + "properties": { + "pattern": { + "type": "string" + }, + "replacement": { + "type": "string" + } + }, + "additionalProperties": false + } + } + } + }, + "interfacebloat": { + "type": "object", + "additionalProperties": false, + "properties": { + "max": { + "description": "The maximum number of methods allowed for an interface.", + "type": "integer" + } + } + }, + "gofumpt": { + "type": "object", + "additionalProperties": false, + "properties": { + "extra-rules": { + "description": "Choose whether or not to use the extra rules that are disabled by default.", + "type": "boolean", + "default": false + }, + "lang-version": { + "description": "Select the Go version to target.", + "type": "string", + "default": "1.15" + }, + "module-path": { + "description": " Module path which contains the source code being formatted.", + "type": "string" + } + } + }, + "goheader": { + "type": "object", + "allOf": [ + { + "properties": { + "values": { + "type": "object", + "properties": { + "const": { + "description": "Constants to use in the template.", + "type": "object", + "patternProperties": { + "^.+$": { + "description": "Value for the constant.", + "type": "string" + } + }, + "additionalProperties": false, + "examples": [ + { + "YEAR": "2030", + "COMPANY": "MY FUTURISTIC COMPANY" + } + ] + }, + "regexp": { + "description": "Regular expressions to use in your template.", + "type": "object", + "patternProperties": { + "^.+$": { + "type": "string" + } + }, + "additionalProperties": false, + "examples": [ + { + "AUTHOR": ".*@mycompany\\.com" + } + ] + } + } + } + } + }, + { + "oneOf": [ + { + "properties": { + "template": { + "description": "Template to put on top of every file.", + "type": "string", + "examples": [ + "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License." + ] + } + }, + "required": ["template"] + }, + { + "properties": { + "template-path": { + "description": "Path to the file containing the template source.", + "type": "string", + "examples": ["my_header_template.txt"] + } + }, + "required": ["template-path"] + } + ] + } + ] + }, + "goimports": { + "type": "object", + "additionalProperties": false, + "properties": { + "local-prefixes": { + "description": "Put imports beginning with prefix after 3rd-party packages. It is a comma-separated list of prefixes.", + "type": "string", + "examples": ["github.com/org/project"] + } + } + }, + "golint": { + "type": "object", + "additionalProperties": false, + "properties": { + "min-confidence": { + "description": "Minimum confidence for issues.", + "type": "number", + "minimum": 0, + "exclusiveMaximum": 1 + } + } + }, + "gomnd": { + "type": "object", + "additionalProperties": false, + "properties": { + "settings": { + "type": "object", + "properties": { + "mnd": { + "type": "object", + "properties": { + "ignored-files": { + "description": "Comma-separated list of file patterns to exclude from the analysis.", + "examples": ["magic1_.*.go"], + "type": "string" + }, + "ignored-functions": { + "description": "Comma-separated list of function patterns to exclude from the analysis.", + "examples": ["math.*,http.StatusText,make"], + "type": "string" + }, + "ignored-numbers": { + "description": "Comma-separated list of numbers to exclude from the analysis.", + "examples": ["1000,1234_567_890,3.14159264"], + "type": "string" + }, + "checks": { + "description": "The list of enabled checks.", + "type": "array", + "items": { + "enum": [ + "argument", + "case", + "condition", + "operation", + "return", + "assign" + ] + } + } + } + } + } + }, + "ignored-files": { + "description": "List of file patterns to exclude from analysis.", + "examples": [["magic1_.*.go"]], + "type": "array", + "items": { + "type": "string" + } + }, + "ignored-functions": { + "description": "Comma-separated list of function patterns to exclude from the analysis.", + "examples": [["math.*", "http.StatusText", "make"]], + "type": "array", + "items": { + "type": "string" + } + }, + "ignored-numbers": { + "description": "List of numbers to exclude from analysis.", + "examples": [["1000", "1234_567_890", "3.14159264"]], + "type": "array", + "items": { + "type": "string" + } + }, + "checks": { + "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.", + "type": "array", + "items": { + "enum": [ + "argument", + "case", + "condition", + "operation", + "return", + "assign" + ] + } + } + } + }, + "gomoddirectives": { + "type": "object", + "additionalProperties": false, + "properties": { + "replace-local": { + "description": "Allow local `replace` directives.", + "type": "boolean", + "default": true + }, + "replace-allow-list": { + "description": "List of allowed `replace` directives.", + "type": "array", + "items": { + "type": "string" + } + }, + "retract-allow-no-explanation": { + "description": "Allow to not explain why the version has been retracted in the `retract` directives.", + "type": "boolean", + "default": true + }, + "exclude-forbidden": { + "description": "Forbid the use of the `exclude` directives.", + "type": "boolean", + "default": true + } + } + }, + "gomodguard": { + "type": "object", + "additionalProperties": false, + "properties": { + "allowed": { + "type": "object", + "properties": { + "modules": { + "description": "List of allowed modules.", + "type": "array", + "items": { + "type": "string", + "examples": ["gopkg.in/yaml.v2"] + } + }, + "domains": { + "description": "List of allowed module domains.", + "type": "array", + "items": { + "type": "string", + "examples": ["golang.org"] + } + } + } + }, + "blocked": { + "type": "object", + "properties": { + "modules": { + "description": "List of blocked modules.", + "type": "array", + "items": { + "type": "object", + "patternProperties": { + "^.+$": { + "type": "object", + "properties": { + "recommendations": { + "description": "Recommended modules that should be used instead.", + "type": "array", + "items": { + "type": "string" + } + }, + "reason": { + "description": "Reason why the recommended module should be used.", + "type": "string" + } + } + } + }, + "additionalProperties": false + } + }, + "versions": { + "description": "List of blocked module version constraints.", + "type": "array", + "items": { + "type": "object", + "patternProperties": { + "^.*$": { + "type": "object", + "properties": { + "version": { + "description": "Version constraint.", + "type": "string" + }, + "reason": { + "description": "Reason why the version constraint exists.", + "type": "string" + } + }, + "required": ["reason"] + } + } + } + }, + "local_replace_directives": { + "description": "Raise lint issues if loading local path with replace directive", + "type": "boolean", + "default": true + } + } + } + } + }, + "gosimple": { + "type": "object", + "additionalProperties": false, + "properties": { + "go": { + "description": "Targeted Go version", + "type": "string", + "default": "1.13" + }, + "checks": { + "type": "array", + "items": { + "anyOf": [ + { + "enum": ["all"] + }, + { + "type": "string" + } + ] + } + } + } + }, + "gosec": { + "type": "object", + "additionalProperties": false, + "properties": { + "includes": { + "type": "array", + "description": "To select a subset of rules to run", + "examples": [["G401"]], + "items": { + "$ref": "#/definitions/gosec-rules" + } + }, + "excludes": { + "type": "array", + "description": "To specify a set of rules to explicitly exclude", + "examples": [["G401"]], + "items": { + "$ref": "#/definitions/gosec-rules" + } + }, + "exclude-generated": { + "description": "Exclude generated files", + "type": "boolean", + "default": false + }, + "severity": { + "description": "Filter out the issues with a lower severity than the given value", + "type": "string", + "enum": ["low", "medium", "high"], + "default": "low" + }, + "confidence": { + "description": "Filter out the issues with a lower confidence than the given value", + "type": "string", + "enum": ["low", "medium", "high"], + "default": "low" + }, + "config": { + "description": "To specify the configuration of rules", + "type": "object" + }, + "concurrency": { + "description": "Concurrency value", + "type": "integer" + } + } + }, + "gosmopolitan": { + "type": "object", + "additionalProperties": false, + "properties": { + "allow-time-local": { + "description": "Allow and ignore `time.Local` usages.", + "type": "boolean", + "default": false + }, + "escape-hatches": { + "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".", + "type": "array", + "items": { + "type": "string" + } + }, + "ignore-tests": { + "description": "Ignore test files.", + "type": "boolean", + "default": false + }, + "watch-for-scripts": { + "description": "List of Unicode scripts to watch for any usage in string literals.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "govet": { + "type": "object", + "additionalProperties": false, + "properties": { + "check-shadowing": { + "description": "Report shadowed variables.", + "type": "boolean", + "default": true + }, + "settings": { + "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.", + "type": "object", + "propertyNames": { + "$ref": "#/definitions/govet-analyzers" + }, + "patternProperties": { + "^.*$": { + "description": "Run `go tool vet help ` to see all settings.", + "type": "object" + } + } + }, + "enable": { + "description": "Enable analyzers by name.", + "type": "array", + "items": { + "$ref": "#/definitions/govet-analyzers" + } + }, + "disable": { + "description": "Disable analyzers by name.", + "type": "array", + "items": { + "$ref": "#/definitions/govet-analyzers" + } + }, + "enable-all": { + "description": "Enable all analyzers.", + "type": "boolean", + "default": false + }, + "disable-all": { + "description": "Disable all analyzers.", + "type": "boolean", + "default": false + } + } + }, + "grouper": { + "type": "object", + "additionalProperties": false, + "properties": { + "const-require-single-const": { + "type": "boolean", + "default": false + }, + "const-require-grouping": { + "type": "boolean", + "default": false + }, + "import-require-single-import": { + "type": "boolean", + "default": false + }, + "import-require-grouping": { + "type": "boolean", + "default": false + }, + "type-require-single-type": { + "type": "boolean", + "default": false + }, + "type-require-grouping": { + "type": "boolean", + "default": false + }, + "var-require-single-var": { + "type": "boolean", + "default": false + }, + "var-require-grouping": { + "type": "boolean", + "default": false + } + } + }, + "ifshort": { + "type": "object", + "additionalProperties": false, + "properties": { + "max-decl-lines": { + "description": "maximum length of variable declaration measured in numbers of lines, after which the linter won't suggest using short syntax. Has precedence over max-decl-chars", + "type": "integer", + "minimum": 1, + "default": 1 + }, + "max-decl-chars": { + "description": "maximum length of variable declaration measured in number of characters, after which the linter won't suggest using short syntax.", + "type": "integer", + "minimum": 1, + "default": 30 + } + } + }, + "importas": { + "type": "object", + "additionalProperties": false, + "properties": { + "no-unaliased": { + "description": "Do not allow unaliased imports of aliased packages.", + "type": "boolean", + "default": false + }, + "no-extra-aliases": { + "description": "Do not allow non-required aliases.", + "type": "boolean", + "default": false + }, + "alias": { + "description": "List of aliases", + "type": "array", + "items": { + "type": "object", + "properties": { + "pkg": { + "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1", + "type": "string" + }, + "alias": { + "description": "Package alias e.g. autoscalingv1alpha1", + "type": "string" + } + }, + "required": ["pkg", "alias"] + } + } + } + }, + "inamedparam": { + "type": "object", + "additionalProperties": false, + "properties": { + "skip-single-param": { + "description": "Skips check for interface methods with only a single parameter.", + "type": "boolean", + "default": false + } + } + }, + "ireturn": { + "type": "object", + "additionalProperties": false, + "description": "Use either `reject` or `allow` properties for interfaces matching.", + "properties": { + "allow": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "enum": ["anon", "error", "empty", "stdlib"] + } + ] + } + }, + "reject": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "enum": ["anon", "error", "empty", "stdlib"] + } + ] + } + } + }, + "anyOf": [ + { + "not": { + "properties": { + "allow": { + "const": "reject" + } + } + }, + "required": ["allow"] + }, + { + "required": ["reject"] + } + ] + }, + "lll": { + "type": "object", + "additionalProperties": false, + "properties": { + "tab-width": { + "description": "Width of \"\\t\" in spaces.", + "type": "integer", + "minimum": 0, + "default": 1 + }, + "line-length": { + "description": "Maximum allowed line length, lines longer will be reported.", + "type": "integer", + "minimum": 1, + "default": 120 + } + } + }, + "maintidx": { + "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022", + "type": "object", + "additionalProperties": false, + "properties": { + "under": { + "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)", + "type": "number", + "default": 20 + } + } + }, + "makezero": { + "type": "object", + "additionalProperties": false, + "properties": { + "always": { + "description": "Allow only slices initialized with a length of zero.", + "type": "boolean", + "default": false + } + } + }, + "loggercheck": { + "type": "object", + "additionalProperties": false, + "properties": { + "kitlog": { + "description": "Allow check for the github.com/go-kit/log library.", + "type": "boolean", + "default": true + }, + "klog": { + "description": "Allow check for the k8s.io/klog/v2 library.", + "type": "boolean", + "default": true + }, + "logr": { + "description": "Allow check for the github.com/go-logr/logr library.", + "type": "boolean", + "default": true + }, + "zap": { + "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.", + "type": "boolean", + "default": true + }, + "require-string-key": { + "description": "Require all logging keys to be inlined constant strings.", + "type": "boolean", + "default": false + }, + "no-printf-like": { + "description": "Require printf-like format specifier (%s, %d for example) not present.", + "type": "boolean", + "default": false + }, + "rules": { + "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "maligned": { + "type": "object", + "additionalProperties": false, + "properties": { + "suggest-new": { + "description": "Whether to print struct with more effective memory layout.", + "type": "boolean", + "default": false + } + } + }, + "misspell": { + "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.", + "type": "object", + "additionalProperties": false, + "properties": { + "locale": { + "enum": ["US", "UK"] + }, + "ignore-words": { + "description": "List of words to ignore.", + "type": "array", + "items": { + "type": "string" + } + }, + "mode": { + "description": "Mode of the analysis.", + "enum": ["restricted", "", "default"], + "default": "" + } + } + }, + "musttag": { + "type": "object", + "additionalProperties": false, + "properties": { + "functions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "tag": { + "type": "string" + }, + "arg-pos": { + "type": "integer" + } + }, + "additionalProperties": false + } + } + } + }, + "nakedret": { + "type": "object", + "additionalProperties": false, + "properties": { + "max-func-lines": { + "description": "Report if a function has more lines of code than this value and it has naked returns.", + "type": "integer", + "minimum": 0, + "default": 30 + } + } + }, + "nestif": { + "type": "object", + "additionalProperties": false, + "properties": { + "min-complexity": { + "description": "Minimum complexity of \"if\" statements to report.", + "type": "integer", + "default": 5 + } + } + }, + "nilnil": { + "type": "object", + "additionalProperties": false, + "properties": { + "checked-types": { + "type": "array", + "description": "Order of return types to check.", + "items": { + "enum": ["ptr", "func", "iface", "map", "chan"] + }, + "default": ["ptr", "func", "iface", "map", "chan"] + } + } + }, + "nlreturn": { + "type": "object", + "additionalProperties": false, + "properties": { + "block-size": { + "description": "set block size that is still ok", + "type": "number", + "default": 0, + "minimum": 0 + } + } + }, + "nolintlint": { + "type": "object", + "additionalProperties": false, + "properties": { + "allow-unused": { + "description": "Enable to ensure that nolint directives are all used.", + "type": "boolean", + "default": true + }, + "allow-no-explanation": { + "description": "Exclude these linters from requiring an explanation.", + "type": "array", + "items": { + "$ref": "#/definitions/linters" + }, + "default": [] + }, + "require-explanation": { + "description": "Enable to require an explanation of nonzero length after each nolint directive.", + "type": "boolean", + "default": false + }, + "require-specific": { + "description": "Enable to require nolint directives to mention the specific linter being suppressed.", + "type": "boolean", + "default": false + } + } + }, + "reassign": { + "type": "object", + "additionalProperties": false, + "properties": { + "patterns": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "nonamedreturns": { + "type": "object", + "additionalProperties": false, + "properties": { + "report-error-in-defer": { + "description": "Report named error if it is assigned inside defer.", + "type": "boolean", + "default": false + } + } + }, + "paralleltest": { + "type": "object", + "additionalProperties": false, + "properties": { + "ignore-missing": { + "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.", + "type": "boolean", + "default": false + }, + "ignore-missing-subtests": { + "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.", + "type": "boolean", + "default": false + } + } + }, + "perfsprint": { + "type": "object", + "additionalProperties": false, + "properties": { + "int-conversion": { + "description": "Optimizes even if it requires an int or uint type cast.", + "type": "boolean", + "default": true + }, + "err-error": { + "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.", + "type": "boolean", + "default": false + }, + "errorf": { + "description": "Optimizes `fmt.Errorf`.", + "type": "boolean", + "default": true + }, + "sprintf1": { + "description": "Optimizes `fmt.Sprintf` with only one argument.", + "type": "boolean", + "default": true + } + } + }, + "prealloc": { + "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.", + "type": "object", + "additionalProperties": false, + "properties": { + "simple": { + "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.", + "type": "boolean", + "default": true + }, + "range-loops": { + "description": "Report preallocation suggestions on range loops.", + "type": "boolean", + "default": true + }, + "for-loops": { + "description": "Report preallocation suggestions on for loops.", + "type": "boolean", + "default": false + } + } + }, + "predeclared": { + "type": "object", + "additionalProperties": false, + "properties": { + "ignore": { + "description": "Comma-separated list of predeclared identifiers to not report on.", + "type": "string" + }, + "q": { + "description": "Include method names and field names (i.e., qualified names) in checks.", + "type": "boolean", + "default": false + } + } + }, + "promlinter": { + "type": "object", + "additionalProperties": false, + "properties": { + "strict": {}, + "disabled-linters": { + "type": "array", + "items": { + "enum": [ + "Help", + "MetricUnits", + "Counter", + "HistogramSummaryReserved", + "MetricTypeInName", + "ReservedChars", + "CamelCase", + "UnitAbbreviations" + ] + } + } + } + }, + "protogetter": { + "type": "object", + "additionalProperties": false, + "properties": { + "skip-generated-by": { + "type": "array", + "items": { + "type": "string", + "examples": ["protoc-gen-go-my-own-generator"] + } + }, + "skip-files": { + "type": "array", + "items": { + "type": "string", + "examples": ["*.pb.go"] + } + }, + "skip-any-generated": { + "description": "Skip any generated files from the checking.", + "type": "boolean", + "default": false + }, + "replace-first-arg-in-append": { + "description": "Skip first argument of append function.", + "type": "boolean", + "default": false + } + } + }, + "revive": { + "type": "object", + "additionalProperties": false, + "examples": [ + { + "ignore-generated-header": true, + "severity": "warning", + "rules": [ + { + "name": "indent-error-flow", + "severity": "warning" + }, + { + "name": "add-constant", + "severity": "warning", + "arguments": [ + { + "maxLitCount": "3", + "allowStrs": "\"\"", + "allowInts": "0,1,2", + "allowFloats": "0.0,0.,1.0,1.,2.0,2." + } + ] + } + ] + } + ], + "properties": { + "max-open-files": { + "type": "integer" + }, + "ignore-generated-header": { + "type": "boolean" + }, + "confidence": { + "type": "number" + }, + "severity": { + "type": "string", + "enum": ["warning", "error"] + }, + "enable-all-rules": { + "type": "boolean", + "default": false + }, + "rules": { + "type": "array", + "items": { + "type": "object", + "required": ["name"], + "properties": { + "name": { + "type": "string", + "title": "The rule name" + }, + "disabled": { + "type": "boolean" + }, + "severity": { + "type": "string", + "enum": ["warning", "error"] + }, + "arguments": { + "type": "array" + } + } + } + } + } + }, + "rowserrcheck": { + "type": "object", + "additionalProperties": false, + "properties": { + "packages": { + "type": "array", + "items": { + "description": "", + "type": "string", + "examples": ["github.com/jmoiron/sqlx"] + } + } + } + }, + "sloglint": { + "type": "object", + "additionalProperties": false, + "properties": { + "kv-only": { + "description": "Enforce using key-value pairs only (incompatible with attr-only).", + "type": "boolean", + "default": false + }, + "no-mixed-args": { + "description": "Enforce not mixing key-value pairs and attributes.", + "type": "boolean", + "default": true + }, + "context-only": { + "description": "Enforce using methods that accept a context.", + "type": "boolean", + "default": false + }, + "static-msg": { + "description": "Enforce using static values for log messages.", + "type": "boolean", + "default": false + }, + "key-naming-case": { + "description": "Enforce a single key naming convention.", + "enum": ["snake", "kebab", "camel", "pascal"] + }, + "attr-only": { + "description": "Enforce using attributes only (incompatible with kv-only).", + "type": "boolean", + "default": false + }, + "no-raw-keys": { + "description": "Enforce using constants instead of raw keys.", + "type": "boolean", + "default": false + }, + "args-on-sep-lines": { + "description": "Enforce putting arguments on separate lines.", + "type": "boolean", + "default": false + } + } + }, + "spancheck": { + "type": "object", + "additionalProperties": false, + "properties": { + "checks": { + "description": "Checks to enable.", + "type": "array", + "items": { + "enum": ["end", "record-error", "set-status"] + } + }, + "ignore-check-signatures": { + "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "staticcheck": { + "type": "object", + "additionalProperties": false, + "properties": { + "go": { + "description": "Targeted Go version", + "type": "string", + "default": "1.13" + }, + "checks": { + "type": "array", + "items": { + "anyOf": [ + { + "enum": ["all"] + }, + { + "type": "string" + } + ] + } + } + } + }, + "stylecheck": { + "type": "object", + "additionalProperties": false, + "properties": { + "go": { + "description": "Targeted Go version", + "type": "string", + "default": "1.13" + }, + "checks": { + "type": "array", + "items": { + "anyOf": [ + { + "enum": ["all"] + }, + { + "type": "string" + } + ] + }, + "default": [ + "all", + "-ST1000", + "-ST1003", + "-ST1016", + "-ST1020", + "-ST1021", + "-ST1022" + ] + }, + "dot-import-whitelist": { + "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.", + "type": "array", + "items": { + "type": "string" + } + }, + "http-status-code-whitelist": { + "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.", + "default": ["200", "400", "404", "500"], + "type": "array", + "items": { + "enum": [ + "100", + "101", + "102", + "103", + "200", + "201", + "202", + "203", + "204", + "205", + "206", + "207", + "208", + "226", + "300", + "301", + "302", + "303", + "304", + "305", + "306", + "307", + "308", + "400", + "401", + "402", + "403", + "404", + "405", + "406", + "407", + "408", + "409", + "410", + "411", + "412", + "413", + "414", + "415", + "416", + "417", + "418", + "421", + "422", + "423", + "424", + "425", + "426", + "428", + "429", + "431", + "451", + "500", + "501", + "502", + "503", + "504", + "505", + "506", + "507", + "508", + "510", + "511" + ] + } + }, + "initialisms": { + "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.", + "type": "array", + "items": { + "type": "string", + "default": [ + "ACL", + "API", + "ASCII", + "CPU", + "CSS", + "DNS", + "EOF", + "GUID", + "HTML", + "HTTP", + "HTTPS", + "ID", + "IP", + "JSON", + "QPS", + "RAM", + "RPC", + "SLA", + "SMTP", + "SQL", + "SSH", + "TCP", + "TLS", + "TTL", + "UDP", + "UI", + "GID", + "UID", + "UUID", + "URI", + "URL", + "UTF8", + "VM", + "XML", + "XMPP", + "XSRF", + "XSS", + "SIP", + "RTP", + "AMQP", + "DB", + "TS" + ] + } + } + } + }, + "tagalign": { + "type": "object", + "additionalProperties": false, + "properties": { + "align": { + "description": "Align and sort can be used together or separately.", + "type": "boolean", + "default": true + }, + "sort": { + "description": "Whether enable tags sort.", + "type": "boolean", + "default": true + }, + "order": { + "description": "Specify the order of tags, the other tags will be sorted by name.", + "type": "array", + "items": { + "type": "string" + }, + "default": [], + "examples": [ + [ + "json", + "yaml", + "yml", + "toml", + "mapstructure", + "binding", + "validate" + ] + ] + }, + "strict": { + "description": "Whether enable strict style.", + "type": "boolean", + "default": false + } + } + }, + "tagliatelle": { + "type": "object", + "additionalProperties": false, + "properties": { + "case": { + "type": "object", + "properties": { + "use-field-name": { + "description": "Use the struct field name to check the name of the struct tag.", + "type": "boolean", + "default": false + }, + "rules": { + "type": "object", + "patternProperties": { + "^.+$": { + "enum": [ + "camel", + "pascal", + "kebab", + "snake", + "goCamel", + "goPascal", + "goKebab", + "goSnake", + "upper", + "upperSnake", + "lower", + "header" + ] + } + } + } + } + } + } + }, + "tenv": { + "type": "object", + "additionalProperties": false, + "properties": { + "all": { + "description": "The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures.", + "type": "boolean", + "default": false + } + } + }, + "testifylint": { + "type": "object", + "additionalProperties": false, + "properties": { + "enable-all": { + "description": "Enable all checkers.", + "type": "boolean", + "default": false + }, + "disable-all": { + "description": "Disable all checkers.", + "type": "boolean", + "default": false + }, + "enable": { + "description": "Enable specific checkers.", + "type": "array", + "items": { + "enum": [ + "blank-import", + "bool-compare", + "compares", + "empty", + "error-is-as", + "error-nil", + "expected-actual", + "go-require", + "float-compare", + "len", + "nil-compare", + "require-error", + "suite-dont-use-pkg", + "suite-extra-assert-call", + "suite-thelper", + "useless-assert" + ] + } + }, + "disable": { + "description": "Enable specific checkers.", + "type": "array", + "items": { + "enum": [ + "blank-import", + "bool-compare", + "compares", + "empty", + "error-is-as", + "error-nil", + "expected-actual", + "go-require", + "float-compare", + "len", + "nil-compare", + "require-error", + "suite-dont-use-pkg", + "suite-extra-assert-call", + "suite-thelper", + "useless-assert" + ] + } + }, + "expected-actual": { + "type": "object", + "additionalProperties": false, + "properties": { + "pattern": { + "description": "Regexp for expected variable name.", + "type": "string" + } + } + }, + "require-error": { + "type": "object", + "additionalProperties": false, + "properties": { + "fn-pattern": { + "description": "Regexp for expected variable name.", + "type": "string" + } + } + }, + "suite-extra-assert-call": { + "type": "object", + "additionalProperties": false, + "properties": { + "mode": { + "description": "To require or remove extra Assert() call?", + "type": "string", + "enum": ["remove", "require"] + } + } + } + } + }, + "testpackage": { + "type": "object", + "additionalProperties": false, + "properties": { + "skip-regexp": { + "description": "Files with names matching this regular expression are skipped.", + "type": "string", + "examples": ["(export|internal)_test\\.go"] + }, + "allow-packages": { + "description": "List of packages that don't end with _test that tests are allowed to be in.", + "type": "array", + "uniqueItems": true, + "items": { + "type": "string", + "examples": ["example"] + } + } + } + }, + "thelper": { + "type": "object", + "additionalProperties": false, + "properties": { + "test": { + "type": "object", + "additionalProperties": false, + "properties": { + "begin": { + "description": "Check if `t.Helper()` begins helper function.", + "default": true, + "type": "boolean" + }, + "first": { + "description": "Check if *testing.T is first param of helper function.", + "default": true, + "type": "boolean" + }, + "name": { + "description": "Check if *testing.T param has t name.", + "default": true, + "type": "boolean" + } + } + }, + "benchmark": { + "type": "object", + "properties": { + "begin": { + "description": "Check if `b.Helper()` begins helper function.", + "default": true, + "type": "boolean" + }, + "first": { + "description": "Check if *testing.B is first param of helper function.", + "default": true, + "type": "boolean" + }, + "name": { + "description": "Check if *testing.B param has b name.", + "default": true, + "type": "boolean" + } + } + }, + "tb": { + "type": "object", + "properties": { + "begin": { + "description": "Check if `tb.Helper()` begins helper function.", + "default": true, + "type": "boolean" + }, + "first": { + "description": "Check if *testing.TB is first param of helper function.", + "default": true, + "type": "boolean" + }, + "name": { + "description": "Check if *testing.TB param has tb name.", + "default": true, + "type": "boolean" + } + } + }, + "fuzz": { + "type": "object", + "properties": { + "begin": { + "description": "Check if `f.Helper()` begins helper function.", + "default": true, + "type": "boolean" + }, + "first": { + "description": "Check if *testing.F is first param of helper function.", + "default": true, + "type": "boolean" + }, + "name": { + "description": "Check if *testing.F param has f name.", + "default": true, + "type": "boolean" + } + } + } + } + }, + "usestdlibvars": { + "type": "object", + "additionalProperties": false, + "properties": { + "http-method": { + "description": "Suggest the use of http.MethodXX.", + "type": "boolean", + "default": true + }, + "http-status-code": { + "description": "Suggest the use of http.StatusXX.", + "type": "boolean", + "default": true + }, + "time-weekday": { + "description": "Suggest the use of time.Weekday.String().", + "type": "boolean", + "default": false + }, + "time-month": { + "description": "Suggest the use of time.Month.String().", + "type": "boolean", + "default": false + }, + "time-layout": { + "description": "Suggest the use of time.Layout.", + "type": "boolean", + "default": false + }, + "crypto-hash": { + "description": "Suggest the use of crypto.Hash.String().", + "type": "boolean", + "default": false + }, + "default-rpc-path": { + "description": "Suggest the use of rpc.DefaultXXPath.", + "type": "boolean", + "default": false + }, + "os-dev-null": { + "description": "Suggest the use of os.DevNull.", + "type": "boolean", + "default": false + }, + "sql-isolation-level": { + "description": "Suggest the use of sql.LevelXX.String().", + "type": "boolean", + "default": false + }, + "tls-signature-scheme": { + "description": "Suggest the use of tls.SignatureScheme.String().", + "type": "boolean", + "default": false + }, + "constant-kind": { + "description": "Suggest the use of constant.Kind.String().", + "type": "boolean", + "default": false + }, + "syslog-priority": { + "description": "Suggest the use of syslog.Priority.", + "type": "boolean", + "default": false + } + } + }, + "unparam": { + "type": "object", + "additionalProperties": false, + "properties": { + "check-exported": { + "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.", + "type": "boolean", + "default": false + } + } + }, + "unused": { + "type": "object", + "additionalProperties": false, + "properties": { + "field-writes-are-uses": { + "description": "", + "type": "boolean", + "default": true + }, + "post-statements-are-reads": { + "description": "", + "type": "boolean", + "default": false + }, + "exported-is-used": { + "description": "", + "type": "boolean", + "default": true + }, + "exported-fields-are-used": { + "description": "", + "type": "boolean", + "default": true + }, + "parameters-are-used": { + "description": "", + "type": "boolean", + "default": true + }, + "local-variables-are-used": { + "description": "", + "type": "boolean", + "default": true + }, + "generated-is-used": { + "description": "", + "type": "boolean", + "default": true + } + } + }, + "varcheck": { + "type": "object", + "additionalProperties": false, + "properties": { + "exported-fields": { + "description": "Check usage of exported variables", + "type": "boolean", + "default": false + } + } + }, + "varnamelen": { + "type": "object", + "additionalProperties": false, + "properties": { + "max-distance": { + "description": "Variables used in at most this N-many lines will be ignored.", + "type": "integer", + "default": 5 + }, + "min-name-length": { + "description": "The minimum length of a variable's name that is considered `long`.", + "type": "integer", + "default": 3 + }, + "check-receiver": { + "description": "Check method receiver names.", + "default": false, + "type": "boolean" + }, + "check-return": { + "description": "Check named return values.", + "default": false, + "type": "boolean" + }, + "check-type-param": { + "description": "Check type parameters.", + "default": false, + "type": "boolean" + }, + "ignore-type-assert-ok": { + "description": "Ignore `ok` variables that hold the bool return value of a type assertion", + "default": false, + "type": "boolean" + }, + "ignore-map-index-ok": { + "description": "Ignore `ok` variables that hold the bool return value of a map index.", + "default": false, + "type": "boolean" + }, + "ignore-chan-recv-ok": { + "description": "Ignore `ok` variables that hold the bool return value of a channel receive.", + "default": false, + "type": "boolean" + }, + "ignore-names": { + "description": "Optional list of variable names that should be ignored completely.", + "default": [[]], + "type": "array", + "items": { + "type": "string" + } + }, + "ignore-decls": { + "description": "Optional list of variable declarations that should be ignored completely.", + "type": "array", + "items": { + "type": "string" + }, + "examples": [ + ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"] + ] + } + } + }, + "whitespace": { + "type": "object", + "additionalProperties": false, + "properties": { + "multi-if": { + "description": "Enforces newlines (or comments) after every multi-line if statement", + "type": "boolean", + "default": false + }, + "multi-func": { + "description": "Enforces newlines (or comments) after every multi-line function signature", + "type": "boolean", + "default": false + } + } + }, + "wrapcheck": { + "type": "object", + "additionalProperties": false, + "properties": { + "ignoreSigs": { + "description": "An array of strings which specify substrings of signatures to ignore.", + "default": [ + ".Errorf(", + "errors.New(", + "errors.Unwrap(", + ".Wrap(", + ".Wrapf(", + ".WithMessage(", + ".WithMessagef(", + ".WithStack(" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "ignoreSigRegexps": { + "description": "An array of strings which specify regular expressions of signatures to ignore.", + "default": [""], + "type": "array", + "items": { + "type": "string" + } + }, + "ignorePackageGlobs": { + "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.", + "default": [""], + "type": "array", + "items": { + "type": "string" + } + }, + "ignoreInterfaceRegexps": { + "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.", + "default": [""], + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "wsl": { + "type": "object", + "additionalProperties": false, + "properties": { + "allow-assign-and-anything": { + "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.", + "type": "boolean", + "default": false + }, + "allow-assign-and-call": { + "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.", + "type": "boolean", + "default": true + }, + "allow-cuddle-declarations": { + "description": "Allow declarations (var) to be cuddled.", + "type": "boolean", + "default": false + }, + "allow-cuddle-with-calls": { + "description": "A list of call idents that everything can be cuddled with.", + "type": "array", + "items": { + "type": "string" + } + }, + "allow-cuddle-with-rhs": { + "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.", + "type": "array", + "items": { + "type": "string" + } + }, + "allow-multiline-assign": { + "description": "Allow multiline assignments to be cuddled.", + "type": "boolean", + "default": true + }, + "allow-separated-leading-comment": { + "description": "Allow leading comments to be separated with empty lines.", + "type": "boolean", + "default": false + }, + "allow-trailing-comment": { + "description": "Allow trailing comments in ending of blocks.", + "type": "boolean", + "default": false + }, + "error-variable-names": { + "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.", + "type": "array", + "items": { + "type": "string" + } + }, + "force-case-trailing-whitespace": { + "description": "Force newlines in end of case at this limit (0 = never).", + "type": "integer", + "minimum": 0, + "default": 0 + }, + "force-err-cuddling": { + "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.", + "type": "boolean", + "default": false + }, + "force-short-decl-cuddling": { + "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.", + "type": "boolean", + "default": false + }, + "strict-append": { + "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.", + "type": "boolean", + "default": true + } + } + }, + "custom": { + "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.", + "type": "object", + "patternProperties": { + "^.*$": { + "type": "object", + "properties": { + "path": { + "description": "The path to the plugin *.so. Can be absolute or local.", + "type": "string", + "examples": ["/path/to/example.so"] + }, + "description": { + "description": "The description of the linter, for documentation purposes only.", + "type": "string" + }, + "original-url": { + "description": "Intended to point to the repo location of the linter, for documentation purposes only.", + "type": "string" + } + }, + "required": ["path"] + } + } + } + }, + "additionalProperties": false + }, + "linters": { + "type": "object", + "properties": { + "enable": { + "description": "List of enabled linters.", + "type": "array", + "items": { + "$ref": "#/definitions/linters" + } + }, + "disable": { + "description": "List of disabled linters.", + "type": "array", + "items": { + "$ref": "#/definitions/linters" + } + }, + "enable-all": { + "description": "Whether to enable all linters. You can re-disable them with `disable` explicitly.", + "type": "boolean", + "default": false + }, + "disable-all": { + "description": "Whether to disable all linters. You can re-enable them with `enable` explicitly.", + "type": "boolean", + "default": false + }, + "presets": { + "description": "Allow to use different presets of linters", + "type": "array", + "items": { + "enum": [ + "bugs", + "comment", + "complexity", + "error", + "format", + "import", + "metalinter", + "module", + "performance", + "sql", + "style", + "test", + "unused" + ] + } + }, + "fast": { + "description": "Enable run of fast linters.", + "type": "boolean", + "default": false + } + }, + "additionalProperties": false + }, + "issues": { + "type": "object", + "properties": { + "exclude": { + "description": "List of regular expressions of issue texts to exclude.\nBut independently from this option we use default exclude patterns. Their usage can be controlled through `exclude-use-default`.", + "type": "array", + "items": { + "type": "string" + } + }, + "exclude-rules": { + "description": "Exclude configuration per-path, per-linter, per-text and per-source", + "type": "array", + "items": { + "type": "object", + "properties": { + "path": { + "type": "string" + }, + "path-except": { + "type": "string" + }, + "linters": { + "type": "array", + "items": { + "$ref": "#/definitions/linters" + } + }, + "text": { + "type": "string" + }, + "source": { + "type": "string" + } + } + } + }, + "exclude-use-default": { + "description": "Independently from option `exclude` we use default exclude patterns. This behavior can be disabled by this option.", + "type": "boolean", + "default": true + }, + "exclude-case-sensitive": { + "description": "If set to true, exclude and exclude-rules regular expressions become case sensitive.", + "type": "boolean", + "default": false + }, + "include": { + "description": "The list of ids of default excludes to include or disable.", + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "max-issues-per-linter": { + "description": "Maximum issues count per one linter. Set to 0 to disable.", + "type": "integer", + "default": 50, + "minimum": 0 + }, + "max-same-issues": { + "description": "Maximum count of issues with the same text. Set to 0 to disable.", + "type": "integer", + "default": 3, + "minimum": 0 + }, + "new": { + "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.", + "type": "boolean", + "default": false + }, + "new-from-rev": { + "description": "Show only new issues created after this git revision.", + "type": "string" + }, + "new-from-patch": { + "description": "Show only new issues created in git patch with this file path.", + "type": "string", + "examples": ["path/to/patch/file"] + }, + "fix": { + "description": "Fix found issues (if it's supported by the linter).", + "type": "boolean", + "default": false + }, + "whole-files": { + "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).", + "type": "boolean", + "default": false + } + }, + "additionalProperties": false + }, + "severity": { + "type": "object", + "properties": { + "default-severity": { + "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.", + "type": "string", + "default": "" + }, + "case-sensitive": { + "description": "If set to true, severity-rules regular expressions become case sensitive.", + "type": "boolean", + "default": false + }, + "rules": { + "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.", + "type": "array", + "items": { + "allOf": [ + { + "oneOf": [ + { + "$ref": "#/definitions/issue-match-path" + }, + { + "$ref": "#/definitions/issue-match-source" + }, + { + "$ref": "#/definitions/issue-match-linters" + }, + { + "$ref": "#/definitions/issue-match-text" + } + ] + }, + { + "properties": { + "severity": { + "type": "string" + } + } + } + ] + }, + "default": [] + } + }, + "additionalProperties": false + } + }, + "type": "object" +} diff --git a/jsonschema/golangci.next.jsonschema.json b/jsonschema/golangci.next.jsonschema.json new file mode 100644 index 000000000000..bc84e042e35d --- /dev/null +++ b/jsonschema/golangci.next.jsonschema.json @@ -0,0 +1,3449 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://json.schemastore.org/golangci-lint.json", + "definitions": { + "gocritic-checks": { + "enum": [ + "appendAssign", + "appendCombine", + "argOrder", + "assignOp", + "badCall", + "badCond", + "badLock", + "badRegexp", + "badSorting", + "boolExprSimplify", + "builtinShadow", + "builtinShadowDecl", + "captLocal", + "caseOrder", + "codegenComment", + "commentedOutCode", + "commentedOutImport", + "commentFormatting", + "defaultCaseOrder", + "deferUnlambda", + "deferInLoop", + "deprecatedComment", + "docStub", + "dupArg", + "dupBranchBody", + "dupCase", + "dupImport", + "dupSubExpr", + "dynamicFmtString", + "elseif", + "emptyDecl", + "emptyFallthrough", + "emptyStringTest", + "equalFold", + "evalOrder", + "exitAfterDefer", + "exposedSyncMutex", + "externalErrorReassign", + "filepathJoin", + "flagDeref", + "flagName", + "hexLiteral", + "httpNoBody", + "hugeParam", + "ifElseChain", + "importShadow", + "indexAlloc", + "initClause", + "ioutilDeprecated", + "mapKey", + "methodExprCall", + "nestingReduce", + "newDeref", + "nilValReturn", + "octalLiteral", + "offBy1", + "paramTypeCombine", + "preferDecodeRune", + "preferFilepathJoin", + "preferFprint", + "preferStringWriter", + "preferWriteByte", + "ptrToRefParam", + "rangeExprCopy", + "rangeValCopy", + "redundantSprint", + "regexpMust", + "regexpPattern", + "regexpSimplify", + "returnAfterHttpError", + "ruleguard", + "singleCaseSwitch", + "sliceClear", + "sloppyLen", + "sloppyReassign", + "sloppyTypeAssert", + "sortSlice", + "sprintfQuotedString", + "sqlQuery", + "stringConcatSimplify", + "stringsCompare", + "stringXbytes", + "suspiciousSorting", + "switchTrue", + "syncMapLoadAndDelete", + "timeCmpSimplify", + "timeExprSimplify", + "tooManyResultsChecker", + "truncateCmp", + "typeAssertChain", + "typeDefFirst", + "typeSwitchVar", + "typeUnparen", + "uncheckedInlineErr", + "underef", + "unlabelStmt", + "unlambda", + "unnamedResult", + "unnecessaryBlock", + "unnecessaryDefer", + "unslice", + "valSwap", + "weakCond", + "whyNoLint", + "wrapperFunc", + "yodaStyleExpr" + ] + }, + "gocritic-tags": { + "enum": [ + "diagnostic", + "style", + "performance", + "experimental", + "opinionated", + "security" + ] + }, + "gosec-rules": { + "enum": [ + "G101", + "G102", + "G103", + "G104", + "G106", + "G107", + "G108", + "G109", + "G110", + "G111", + "G112", + "G113", + "G114", + "G201", + "G202", + "G203", + "G204", + "G301", + "G302", + "G303", + "G304", + "G305", + "G306", + "G307", + "G401", + "G402", + "G403", + "G404", + "G501", + "G502", + "G503", + "G504", + "G505", + "G601", + "G602" + ] + }, + "govet-analyzers": { + "enum": [ + "appends", + "asmdecl", + "assign", + "atomic", + "atomicalign", + "bools", + "buildtag", + "cgocall", + "composites", + "copylocks", + "deepequalerrors", + "defers", + "directive", + "errorsas", + "fieldalignment", + "findcall", + "framepointer", + "httpresponse", + "ifaceassert", + "loopclosure", + "lostcancel", + "nilfunc", + "nilness", + "printf", + "reflectvaluecompare", + "shadow", + "shift", + "sigchanyzer", + "slog", + "sortslice", + "stdmethods", + "stringintconv", + "structtag", + "testinggoroutine", + "tests", + "unmarshal", + "unreachable", + "unsafeptr", + "unusedresult", + "unusedwrite" + ] + }, + "linters": { + "$comment": "anyOf with enum is used to allow auto completion of non-custom linters", + "description": "Linters usable.", + "anyOf": [ + { + "enum": [ + "asasalint", + "asciicheck", + "bidichk", + "bodyclose", + "containedctx", + "contextcheck", + "copyloopvar", + "cyclop", + "deadcode", + "decorder", + "depguard", + "dogsled", + "dupl", + "dupword", + "durationcheck", + "errcheck", + "errchkjson", + "errname", + "errorlint", + "execinquery", + "exhaustive", + "exhaustivestruct", + "exhaustruct", + "exportloopref", + "forbidigo", + "forcetypeassert", + "funlen", + "gci", + "ginkgolinter", + "gocheckcompilerdirectives", + "gochecknoglobals", + "gochecknoinits", + "gochecksumtype", + "gocognit", + "goconst", + "gocritic", + "gocyclo", + "godot", + "godox", + "goerr113", + "gofmt", + "gofumpt", + "goheader", + "goimports", + "golint", + "gomnd", + "gomoddirectives", + "gomodguard", + "goprintffuncname", + "gosec", + "gosimple", + "gosmopolitan", + "govet", + "grouper", + "ifshort", + "importas", + "inamedparam", + "ineffassign", + "interfacebloat", + "interfacer", + "intrange", + "ireturn", + "lll", + "loggercheck", + "maintidx", + "makezero", + "maligned", + "mirror", + "misspell", + "musttag", + "nakedret", + "nestif", + "nilerr", + "nilnil", + "nlreturn", + "noctx", + "nolintlint", + "nonamedreturns", + "nosnakecase", + "nosprintfhostport", + "paralleltest", + "perfsprint", + "prealloc", + "predeclared", + "promlinter", + "protogetter", + "reassign", + "revive", + "rowserrcheck", + "scopelint", + "sloglint", + "sqlclosecheck", + "staticcheck", + "structcheck", + "stylecheck", + "tagalign", + "tagliatelle", + "tenv", + "testableexamples", + "testifylint", + "testpackage", + "thelper", + "tparallel", + "typecheck", + "unconvert", + "unparam", + "unused", + "usestdlibvars", + "varcheck", + "varnamelen", + "wastedassign", + "whitespace", + "wrapcheck", + "wsl", + "zerologlint" + ] + }, + { + "type": "string" + } + ] + }, + "issue-match-path": { + "type": "object", + "properties": { + "path": { + "type": "string" + }, + "severity": { + "$comment": "This is here only to allow `additionalProperties: false`." + } + }, + "additionalProperties": false + }, + "issue-match-linters": { + "type": "object", + "properties": { + "linters": { + "type": "array", + "items": { + "$ref": "#/definitions/linters" + } + }, + "severity": { + "$comment": "This is here only to allow `additionalProperties: false`." + } + }, + "additionalProperties": false + }, + "issue-match-source": { + "type": "object", + "properties": { + "source": { + "type": "string" + }, + "severity": { + "$comment": "This is here only to allow `additionalProperties: false`." + } + }, + "additionalProperties": false + }, + "issue-match-text": { + "type": "object", + "properties": { + "text": { + "type": "string" + }, + "severity": { + "$comment": "This is here only to allow `additionalProperties: false`." + } + }, + "additionalProperties": false + } + }, + "properties": { + "run": { + "description": "Options for analysis running,", + "type": "object", + "properties": { + "concurrency": { + "description": "Number of concurrent runners. Defaults to the number of available CPU cores.", + "type": "integer", + "minimum": 1, + "examples": [4] + }, + "timeout": { + "description": "Timeout for the analysis.", + "type": "string", + "pattern": "^\\d*[sm]$", + "default": "1m", + "examples": ["30s", "5m"] + }, + "issues-exit-code": { + "description": "Exit code when at least one issue was found.", + "type": "integer", + "default": 1 + }, + "tests": { + "description": "Enable inclusion of test files.", + "type": "boolean", + "default": true + }, + "build-tags": { + "description": "List of build tags to pass to all linters.", + "type": "array", + "items": { + "type": "string" + }, + "default": [], + "examples": [["mytag"]] + }, + "skip-dirs": { + "description": "Which directories to skip: issues from them won't be reported.", + "type": "array", + "items": { + "description": "You can use regexp here. The regexp is applied on the full path.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.", + "type": "string", + "examples": ["generated.*"] + }, + "default": [], + "examples": [["src/external_libs", "autogenerated_by_my_lib"]] + }, + "skip-dirs-use-default": { + "description": "Enable skipping of directories \"vendor\", \"third_party\", \"testdata\", \"examples\", \"Godeps\", and \"builtin\".", + "type": "boolean", + "default": true + }, + "skip-files": { + "description": "Which files to skip: they will be analyzed, but issues from them will not be reported.", + "type": "array", + "items": { + "description": "You can use regexp here. There is no need to include all autogenerated files, we confidently recognize them. If that is not the case, please let us know.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.", + "type": "string", + "examples": [".*\\.my\\.go$"] + }, + "default": [], + "examples": [[".*\\.my\\.go$", "lib/bad.go"]] + }, + "modules-download-mode": { + "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.", + "enum": ["mod", "readonly", "vendor"] + }, + "allow-parallel-runners": { + "description": "Allow multiple parallel golangci-lint instances running. If disabled, golangci-lint acquires file lock on start.", + "type": "boolean", + "default": false + }, + "allow-serial-runners": { + "description": "Allow multiple golangci-lint instances running, but serialize them around a lock.", + "type": "boolean", + "default": false + }, + "go": { + "description": "Targeted Go version.", + "type": "string", + "default": "1.17" + } + }, + "additionalProperties": false + }, + "output": { + "description": "Output configuration options.", + "type": "object", + "properties": { + "format": { + "description": "Output format to use.", + "pattern": "^(,?(colored-line-number|line-number|json|colored-tab|tab|checkstyle|code-climate|junit-xml|github-actions|teamcity)(:[^,]+)?)+$", + "default": "colored-line-number", + "examples": [ + "colored-line-number", + "checkstyle:report.json,colored-line-number", + "line-number:golangci-lint.out,colored-line-number:stdout" + ] + }, + "print-issued-lines": { + "description": "Print lines of code with issue.", + "type": "boolean", + "default": true + }, + "print-linter-name": { + "description": "Print linter name in the end of issue text.", + "type": "boolean", + "default": true + }, + "uniq-by-line": { + "description": "Make issues output unique by line.", + "type": "boolean", + "default": true + }, + "path-prefix": { + "description": "Add a prefix to the output file references.", + "type": "string", + "default": "" + }, + "show-stats": { + "description": "Show statistics per linter.", + "type": "boolean", + "default": false + }, + "sort-order": { + "type": "array", + "items": { + "enum": ["linter", "severity", "file"] + } + }, + "sort-results": { + "description": "Sort results by: filepath, line and column.", + "type": "boolean", + "default": true + } + }, + "additionalProperties": false + }, + "linters-settings": { + "description": "All available settings of specific linters.", + "type": "object", + "properties": { + "dupword": { + "type": "object", + "additionalProperties": false, + "properties": { + "keywords": { + "description": "Keywords for detecting duplicate words. If this list is not empty, only the words defined in this list will be detected.", + "type": "array", + "uniqueItems": true, + "items": { + "type": "string", + "examples": ["the", "and", "a"] + } + }, + "ignore": { + "description": "Keywords used to ignore detection.", + "type": "array", + "uniqueItems": true, + "items": { + "type": "string", + "examples": ["0C0C"] + } + } + } + }, + "asasalint": { + "type": "object", + "additionalProperties": false, + "properties": { + "exclude": { + "description": "To specify a set of function names to exclude.", + "type": "array", + "uniqueItems": true, + "items": { + "type": "string", + "examples": ["\\.Wrapf"] + } + }, + "use-builtin-exclusions": { + "description": "To enable/disable the asasalint builtin exclusions of function names.", + "type": "boolean", + "default": true + }, + "ignore-test": { + "description": "Ignore *_test.go files.", + "type": "boolean", + "default": false + } + } + }, + "bidichk": { + "type": "object", + "additionalProperties": false, + "properties": { + "left-to-right-embedding": { + "description": "Disallow: LEFT-TO-RIGHT-EMBEDDING", + "type": "boolean", + "default": false + }, + "right-to-left-embedding": { + "description": "Disallow: RIGHT-TO-LEFT-EMBEDDING", + "type": "boolean", + "default": false + }, + "pop-directional-formatting": { + "description": "Disallow: POP-DIRECTIONAL-FORMATTING", + "type": "boolean", + "default": false + }, + "left-to-right-override": { + "description": "Disallow: LEFT-TO-RIGHT-OVERRIDE", + "type": "boolean", + "default": false + }, + "right-to-left-override": { + "description": "Disallow: RIGHT-TO-LEFT-OVERRIDE", + "type": "boolean", + "default": false + }, + "left-to-right-isolate": { + "description": "Disallow: LEFT-TO-RIGHT-ISOLATE", + "type": "boolean", + "default": false + }, + "right-to-left-isolate": { + "description": "Disallow: RIGHT-TO-LEFT-ISOLATE", + "type": "boolean", + "default": false + }, + "first-strong-isolate": { + "description": "Disallow: FIRST-STRONG-ISOLATE", + "type": "boolean", + "default": false + }, + "pop-directional-isolate": { + "description": "Disallow: POP-DIRECTIONAL-ISOLATE", + "type": "boolean", + "default": false + } + } + }, + "cyclop": { + "type": "object", + "additionalProperties": false, + "properties": { + "skip-tests": { + "description": "Should the linter execute on test files as well", + "type": "boolean", + "default": false + }, + "max-complexity": { + "description": "Max complexity the function can have", + "type": "integer", + "default": 10, + "minimum": 0 + }, + "package-average": { + "description": "Max average complexity in package", + "type": "number", + "default": 0, + "minimum": 0 + } + } + }, + "decorder": { + "type": "object", + "additionalProperties": false, + "properties": { + "dec-order": { + "type": "array", + "default": [["type", "const", "var", "func"]], + "items": { + "enum": ["type", "const", "var", "func"] + } + }, + "ignore-underscore-vars": { + "description": "Underscore vars (vars with \"_\" as the name) will be ignored at all checks", + "default": true, + "type": "boolean" + }, + "disable-dec-order-check": { + "description": "Order of declarations is not checked", + "default": true, + "type": "boolean" + }, + "disable-init-func-first-check": { + "description": "Allow init func to be anywhere in file", + "default": true, + "type": "boolean" + }, + "disable-dec-num-check": { + "description": "Multiple global type, const and var declarations are allowed", + "default": true, + "type": "boolean" + }, + "disable-type-dec-num-check": { + "description": "Type declarations will be ignored for dec num check", + "default": true, + "type": "boolean" + }, + "disable-const-dec-num-check": { + "description": "Const declarations will be ignored for dec num check", + "default": true, + "type": "boolean" + }, + "disable-var-dec-num-check": { + "description": "Var declarations will be ignored for dec num check", + "default": true, + "type": "boolean" + } + } + }, + "depguard": { + "type": "object", + "additionalProperties": false, + "properties": { + "rules": { + "description": "Rules to apply.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^[^.]+$": { + "description": "Name of a rule.", + "additionalProperties": false, + "type": "object", + "properties": { + "list-mode": { + "description": "Used to determine the package matching priority.", + "enum": ["original", "strict", "lax"], + "default": "original" + }, + "files": { + "description": "List of file globs that will match this list of settings to compare against.", + "additionalProperties": false, + "type": "array", + "items": { + "type": "string" + } + }, + "allow": { + "description": "List of allowed packages.", + "additionalProperties": false, + "type": "array", + "items": { + "type": "string" + } + }, + "deny": { + "description": "Packages that are not allowed where the value is a suggestion.", + "additionalProperties": false, + "type": "array", + "items": { + "additionalProperties": false, + "type": "object", + "properties": { + "desc": { + "description": "Description", + "type": "string" + }, + "pkg": { + "description": "Package", + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "dogsled": { + "type": "object", + "additionalProperties": false, + "properties": { + "max-blank-identifiers": { + "description": "Check assignments with too many blank identifiers.", + "type": "integer", + "default": 2, + "minimum": 0 + } + } + }, + "dupl": { + "type": "object", + "additionalProperties": false, + "properties": { + "threshold": { + "description": "Tokens count to trigger issue.", + "type": "integer", + "default": 150, + "minimum": 0 + } + } + }, + "errcheck": { + "type": "object", + "additionalProperties": false, + "properties": { + "check-type-assertions": { + "description": "Report about not checking errors in type assertions, i.e.: `a := b.(MyStruct)`", + "type": "boolean", + "default": false + }, + "check-blank": { + "description": "Report about assignment of errors to blank identifier", + "type": "boolean", + "default": false + }, + "ignore": { + "description": "DEPRECATED: use `exclude-functions` instead. Comma-separated list of pairs of the form \"pkg:regex\".", + "type": "string", + "default": "fmt:.*" + }, + "exclude": { + "description": "DEPRECATED: use `exclude-functions` instead. Path to a file containing a list of functions to exclude from checking.", + "type": "string", + "examples": ["/path/to/file.txt"] + }, + "exclude-functions": { + "description": "List of functions to exclude from checking, where each entry is a single function to exclude", + "type": "array", + "examples": ["io/ioutil.ReadFile", "io.Copy(*bytes.Buffer)"], + "items": { + "type": "string" + } + }, + "disable-default-exclusions": { + "description": "To disable the errcheck built-in exclude list", + "type": "boolean", + "default": false + } + } + }, + "errchkjson": { + "type": "object", + "additionalProperties": false, + "properties": { + "check-error-free-encoding": { + "type": "boolean", + "default": false + }, + "report-no-exported": { + "description": "Issue on struct that doesn't have exported fields.", + "type": "boolean", + "default": false + } + } + }, + "errorlint": { + "type": "object", + "additionalProperties": false, + "properties": { + "errorf": { + "description": "Check whether fmt.Errorf uses the %w verb for formatting errors", + "type": "boolean", + "default": true + }, + "errorf-multi": { + "description": "Permit more than 1 %w verb, valid per Go 1.20", + "type": "boolean", + "default": true + }, + "asserts": { + "description": "Check for plain type assertions and type switches.", + "type": "boolean", + "default": true + }, + "comparison": { + "description": "Check for plain error comparisons", + "type": "boolean", + "default": true + } + } + }, + "exhaustive": { + "type": "object", + "additionalProperties": false, + "properties": { + "check": { + "description": "Program elements to check for exhaustiveness.", + "type": "array", + "uniqueItems": true, + "items": { + "type": "string", + "examples": ["switch", "map"] + } + }, + "check-generated": { + "description": "Check switch statements in generated files", + "type": "boolean", + "default": false + }, + "explicit-exhaustive-switch": { + "description": "Only run exhaustive check on switches with \"//exhaustive:enforce\" comment.", + "type": "boolean", + "default": false + }, + "explicit-exhaustive-map": { + "description": "Only run exhaustive check on map literals with \"//exhaustive:enforce\" comment.", + "type": "boolean", + "default": false + }, + "default-case-required": { + "description": "Switch statement requires default case even if exhaustive.", + "type": "boolean", + "default": false + }, + "default-signifies-exhaustive": { + "description": "Presence of `default` case in switch statements satisfies exhaustiveness, even if all enum members are not listed.", + "type": "boolean", + "default": false + }, + "ignore-enum-members": { + "description": "Enum members matching `regex` do not have to be listed in switch statements to satisfy exhaustiveness", + "type": "string" + }, + "ignore-enum-types": { + "description": "Enum types matching the supplied regex do not have to be listed in switch statements to satisfy exhaustiveness.", + "type": "string" + }, + "package-scope-only": { + "description": "Consider enums only in package scopes, not in inner scopes.", + "type": "boolean", + "default": false + } + } + }, + "exhaustruct": { + "type": "object", + "additionalProperties": false, + "properties": { + "include": { + "description": "List of regular expressions to match struct packages and names.", + "type": "array", + "examples": [".*\\.Test"], + "items": { + "type": "string" + } + }, + "exclude": { + "description": "List of regular expressions to exclude struct packages and names from check.", + "type": "array", + "examples": ["cobra\\.Command$"], + "items": { + "type": "string" + } + } + } + }, + "forbidigo": { + "type": "object", + "additionalProperties": false, + "properties": { + "exclude-godoc-examples": { + "description": "Exclude code in godoc examples.", + "type": "boolean", + "default": true + }, + "analyze-types": { + "description": "Instead of matching the literal source code, use type information to replace expressions with strings that contain the package name and (for methods and fields) the type name.", + "type": "boolean", + "default": true + }, + "forbid": { + "description": "List of identifiers to forbid (written using `regexp`)", + "type": "array", + "examples": ["^print.*$"], + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "p": { + "description": "Pattern", + "type": "string" + }, + "pkg": { + "description": "Package", + "type": "string" + }, + "msg": { + "description": "Message", + "type": "string" + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "funlen": { + "type": "object", + "additionalProperties": false, + "properties": { + "lines": { + "description": "Limit lines number per function.", + "type": "integer", + "default": 60 + }, + "statements": { + "description": "Limit statements number per function.", + "type": "integer", + "default": 40 + }, + "ignore-comments": { + "description": "Ignore comments when counting lines.", + "type": "boolean", + "default": false + } + } + }, + "gci": { + "type": "object", + "additionalProperties": false, + "properties": { + "local-prefixes": { + "description": "DEPRECATED: use 'sections' and 'prefix(github.com/org/project)' instead.", + "type": "string", + "examples": ["github.com/org/project"] + }, + "sections": { + "description": "Section configuration to compare against.", + "type": "array", + "items": { + "type": "string" + }, + "default": ["standard", "default"] + }, + "skip-generated": { + "description": "Skip generated files.", + "type": "boolean", + "default": true + }, + "custom-order": { + "description": "Enable custom order of sections.", + "type": "boolean", + "default": false + } + } + }, + "ginkgolinter": { + "type": "object", + "additionalProperties": false, + "properties": { + "suppress-len-assertion": { + "description": "Suppress the wrong length assertion warning.", + "type": "boolean", + "default": false + }, + "suppress-nil-assertion": { + "description": "Suppress the wrong nil assertion warning.", + "type": "boolean", + "default": false + }, + "suppress-err-assertion": { + "description": "Suppress the wrong error assertion warning.", + "type": "boolean", + "default": false + }, + "suppress-compare-assertion": { + "description": "Suppress the wrong comparison assertion warning.", + "type": "boolean", + "default": false + }, + "suppress-async-assertion": { + "description": "Suppress the function all in async assertion warning.", + "type": "boolean", + "default": false + }, + "suppress-type-compare-assertion": { + "description": "Suppress warning for comparing values from different types, like int32 and uint32.", + "type": "boolean", + "default": false + }, + "forbid-focus-container": { + "description": "Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt.", + "type": "boolean", + "default": false + }, + "allow-havelen-zero": { + "description": "Don't trigger warnings for HaveLen(0).", + "type": "boolean", + "default": false + } + } + }, + "gocognit": { + "type": "object", + "additionalProperties": false, + "properties": { + "min-complexity": { + "description": "Minimal code complexity to report (we recommend 10-20).", + "type": "integer", + "default": 30 + } + } + }, + "goconst": { + "type": "object", + "additionalProperties": false, + "properties": { + "match-constant": { + "description": "Look for existing constants matching the values", + "type": "boolean", + "default": true + }, + "min-len": { + "description": "Minimum length of string constant.", + "type": "integer", + "default": 3 + }, + "min-occurrences": { + "description": "Minimum occurrences count to trigger.", + "type": "integer", + "default": 3 + }, + "ignore-tests": { + "description": "Ignore test files.", + "type": "boolean", + "default": false + }, + "ignore-calls": { + "description": "Ignore when constant is not used as function argument", + "type": "boolean", + "default": true + }, + "ignore-strings": { + "description": "Exclude strings matching the given regular expression", + "type": "string" + }, + "numbers": { + "description": "Search also for duplicated numbers.", + "type": "boolean", + "default": false + }, + "min": { + "description": "Minimum value, only works with `numbers`", + "type": "integer", + "default": 3 + }, + "max": { + "description": "Maximum value, only works with `numbers`", + "type": "integer", + "default": 3 + } + } + }, + "gocritic": { + "type": "object", + "additionalProperties": false, + "properties": { + "enabled-checks": { + "description": "Which checks should be enabled. By default, a list of stable checks is used. To see it, run `GL_DEBUG=gocritic golangci-lint run`.", + "type": "array", + "items": { + "$ref": "#/definitions/gocritic-checks" + } + }, + "disabled-checks": { + "description": "Which checks should be disabled.", + "type": "array", + "items": { + "$ref": "#/definitions/gocritic-checks" + }, + "default": [] + }, + "enabled-tags": { + "description": "Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.", + "type": "array", + "items": { + "$ref": "#/definitions/gocritic-tags" + } + }, + "disabled-tags": { + "description": "Disable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.", + "type": "array", + "items": { + "$ref": "#/definitions/gocritic-tags" + } + }, + "settings": { + "description": "Settings passed to gocritic. Properties must be valid and enabled check names.", + "type": "object", + "propertyNames": { + "$ref": "#/definitions/gocritic-checks" + } + }, + "disable-all": { + "type": "boolean", + "default": false + }, + "enable-all": { + "type": "boolean", + "default": false + } + } + }, + "gocyclo": { + "type": "object", + "additionalProperties": false, + "properties": { + "min-complexity": { + "description": "Minimum code complexity to report (we recommend 10-20).", + "type": "integer", + "default": 30 + } + } + }, + "godot": { + "type": "object", + "additionalProperties": false, + "properties": { + "scope": { + "description": "Comments to be checked.", + "enum": ["declarations", "toplevel", "all"], + "default": "declarations" + }, + "exclude": { + "description": "List of regexps for excluding particular comment lines from check.", + "type": "array", + "items": { + "type": "string" + } + }, + "period": { + "description": "Check that each sentence ends with a period.", + "type": "boolean", + "default": true + }, + "capital": { + "description": "Check that each sentence starts with a capital letter.", + "type": "boolean", + "default": false + }, + "check-all": { + "description": "DEPRECATED: Check all top-level comments, not only declarations.", + "type": "boolean", + "default": false + } + } + }, + "godox": { + "type": "object", + "additionalProperties": false, + "properties": { + "keywords": { + "description": "Report any comments starting with one of these keywords. This is useful for TODO or FIXME comments that might be left in the code accidentally and should be resolved before merging.", + "type": "array", + "items": { + "type": "string" + }, + "default": ["TODO", "BUG", "FIXME"] + } + } + }, + "gofmt": { + "type": "object", + "additionalProperties": false, + "properties": { + "simplify": { + "description": "Simplify code.", + "type": "boolean", + "default": true + }, + "rewrite-rules": { + "description": "Apply the rewrite rules to the source before reformatting.", + "type": "array", + "items": { + "type": "object", + "properties": { + "pattern": { + "type": "string" + }, + "replacement": { + "type": "string" + } + }, + "additionalProperties": false + } + } + } + }, + "interfacebloat": { + "type": "object", + "additionalProperties": false, + "properties": { + "max": { + "description": "The maximum number of methods allowed for an interface.", + "type": "integer" + } + } + }, + "gofumpt": { + "type": "object", + "additionalProperties": false, + "properties": { + "extra-rules": { + "description": "Choose whether or not to use the extra rules that are disabled by default.", + "type": "boolean", + "default": false + }, + "lang-version": { + "description": "Select the Go version to target.", + "type": "string", + "default": "1.15" + }, + "module-path": { + "description": " Module path which contains the source code being formatted.", + "type": "string" + } + } + }, + "goheader": { + "type": "object", + "additionalProperties": false, + "allOf": [ + { + "properties": { + "values": { + "type": "object", + "properties": { + "const": { + "description": "Constants to use in the template.", + "type": "object", + "patternProperties": { + "^.+$": { + "description": "Value for the constant.", + "type": "string" + } + }, + "additionalProperties": false, + "examples": [ + { + "YEAR": "2030", + "COMPANY": "MY FUTURISTIC COMPANY" + } + ] + }, + "regexp": { + "description": "Regular expressions to use in your template.", + "type": "object", + "patternProperties": { + "^.+$": { + "type": "string" + } + }, + "additionalProperties": false, + "examples": [ + { + "AUTHOR": ".*@mycompany\\.com" + } + ] + } + } + } + } + }, + { + "oneOf": [ + { + "properties": { + "template": { + "description": "Template to put on top of every file.", + "type": "string", + "examples": [ + "{{ MY COMPANY }}\nSPDX-License-Identifier: Apache-2.0\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at:\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License." + ] + } + }, + "required": ["template"] + }, + { + "properties": { + "template-path": { + "description": "Path to the file containing the template source.", + "type": "string", + "examples": ["my_header_template.txt"] + } + }, + "required": ["template-path"] + } + ] + } + ] + }, + "goimports": { + "type": "object", + "additionalProperties": false, + "properties": { + "local-prefixes": { + "description": "Put imports beginning with prefix after 3rd-party packages. It is a comma-separated list of prefixes.", + "type": "string", + "examples": ["github.com/org/project"] + } + } + }, + "gomnd": { + "type": "object", + "additionalProperties": false, + "properties": { + "ignored-files": { + "description": "List of file patterns to exclude from analysis.", + "examples": [["magic1_.*.go"]], + "type": "array", + "items": { + "type": "string" + } + }, + "ignored-functions": { + "description": "Comma-separated list of function patterns to exclude from the analysis.", + "examples": [["math.*", "http.StatusText", "make"]], + "type": "array", + "items": { + "type": "string" + } + }, + "ignored-numbers": { + "description": "List of numbers to exclude from analysis.", + "examples": [["1000", "1234_567_890", "3.14159264"]], + "type": "array", + "items": { + "type": "string" + } + }, + "checks": { + "description": "The list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.", + "type": "array", + "items": { + "enum": [ + "argument", + "case", + "condition", + "operation", + "return", + "assign" + ] + } + } + } + }, + "gomoddirectives": { + "type": "object", + "additionalProperties": false, + "properties": { + "replace-local": { + "description": "Allow local `replace` directives.", + "type": "boolean", + "default": true + }, + "replace-allow-list": { + "description": "List of allowed `replace` directives.", + "type": "array", + "items": { + "type": "string" + } + }, + "retract-allow-no-explanation": { + "description": "Allow to not explain why the version has been retracted in the `retract` directives.", + "type": "boolean", + "default": true + }, + "exclude-forbidden": { + "description": "Forbid the use of the `exclude` directives.", + "type": "boolean", + "default": true + } + } + }, + "gomodguard": { + "type": "object", + "additionalProperties": false, + "properties": { + "allowed": { + "type": "object", + "properties": { + "modules": { + "description": "List of allowed modules.", + "type": "array", + "items": { + "type": "string", + "examples": ["gopkg.in/yaml.v2"] + } + }, + "domains": { + "description": "List of allowed module domains.", + "type": "array", + "items": { + "type": "string", + "examples": ["golang.org"] + } + } + } + }, + "blocked": { + "type": "object", + "properties": { + "modules": { + "description": "List of blocked modules.", + "type": "array", + "items": { + "type": "object", + "patternProperties": { + "^.+$": { + "type": "object", + "properties": { + "recommendations": { + "description": "Recommended modules that should be used instead.", + "type": "array", + "items": { + "type": "string" + } + }, + "reason": { + "description": "Reason why the recommended module should be used.", + "type": "string" + } + } + } + }, + "additionalProperties": false + } + }, + "versions": { + "description": "List of blocked module version constraints.", + "type": "array", + "items": { + "type": "object", + "patternProperties": { + "^.*$": { + "type": "object", + "properties": { + "version": { + "description": "Version constraint.", + "type": "string" + }, + "reason": { + "description": "Reason why the version constraint exists.", + "type": "string" + } + }, + "required": ["reason"] + } + } + } + }, + "local_replace_directives": { + "description": "Raise lint issues if loading local path with replace directive", + "type": "boolean", + "default": true + } + } + } + } + }, + "gosimple": { + "type": "object", + "additionalProperties": false, + "properties": { + "go": { + "description": "Targeted Go version", + "type": "string", + "default": "1.13" + }, + "checks": { + "type": "array", + "items": { + "anyOf": [ + { + "enum": ["all"] + }, + { + "type": "string" + } + ] + } + } + } + }, + "gosec": { + "type": "object", + "additionalProperties": false, + "properties": { + "includes": { + "type": "array", + "description": "To select a subset of rules to run", + "examples": [["G401"]], + "items": { + "$ref": "#/definitions/gosec-rules" + } + }, + "excludes": { + "type": "array", + "description": "To specify a set of rules to explicitly exclude", + "examples": [["G401"]], + "items": { + "$ref": "#/definitions/gosec-rules" + } + }, + "exclude-generated": { + "description": "Exclude generated files", + "type": "boolean", + "default": false + }, + "severity": { + "description": "Filter out the issues with a lower severity than the given value", + "type": "string", + "enum": ["low", "medium", "high"], + "default": "low" + }, + "confidence": { + "description": "Filter out the issues with a lower confidence than the given value", + "type": "string", + "enum": ["low", "medium", "high"], + "default": "low" + }, + "config": { + "description": "To specify the configuration of rules", + "type": "object" + }, + "concurrency": { + "description": "Concurrency value", + "type": "integer" + } + } + }, + "gosmopolitan": { + "type": "object", + "additionalProperties": false, + "properties": { + "allow-time-local": { + "description": "Allow and ignore `time.Local` usages.", + "type": "boolean", + "default": false + }, + "escape-hatches": { + "description": "List of fully qualified names in the `full/pkg/path.name` form, to act as \"i18n escape hatches\".", + "type": "array", + "items": { + "type": "string" + } + }, + "ignore-tests": { + "description": "Ignore test files.", + "type": "boolean", + "default": false + }, + "watch-for-scripts": { + "description": "List of Unicode scripts to watch for any usage in string literals.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "govet": { + "type": "object", + "additionalProperties": false, + "properties": { + "check-shadowing": { + "description": "Report shadowed variables.", + "type": "boolean", + "default": true + }, + "settings": { + "description": "Settings per analyzer. Map of analyzer name to specific settings.\nRun `go tool vet help` to find out more.", + "type": "object", + "propertyNames": { + "$ref": "#/definitions/govet-analyzers" + }, + "patternProperties": { + "^.*$": { + "description": "Run `go tool vet help ` to see all settings.", + "type": "object" + } + } + }, + "enable": { + "description": "Enable analyzers by name.", + "type": "array", + "items": { + "$ref": "#/definitions/govet-analyzers" + } + }, + "disable": { + "description": "Disable analyzers by name.", + "type": "array", + "items": { + "$ref": "#/definitions/govet-analyzers" + } + }, + "enable-all": { + "description": "Enable all analyzers.", + "type": "boolean", + "default": false + }, + "disable-all": { + "description": "Disable all analyzers.", + "type": "boolean", + "default": false + } + } + }, + "grouper": { + "type": "object", + "additionalProperties": false, + "properties": { + "const-require-single-const": { + "type": "boolean", + "default": false + }, + "const-require-grouping": { + "type": "boolean", + "default": false + }, + "import-require-single-import": { + "type": "boolean", + "default": false + }, + "import-require-grouping": { + "type": "boolean", + "default": false + }, + "type-require-single-type": { + "type": "boolean", + "default": false + }, + "type-require-grouping": { + "type": "boolean", + "default": false + }, + "var-require-single-var": { + "type": "boolean", + "default": false + }, + "var-require-grouping": { + "type": "boolean", + "default": false + } + } + }, + "importas": { + "type": "object", + "additionalProperties": false, + "properties": { + "no-unaliased": { + "description": "Do not allow unaliased imports of aliased packages.", + "type": "boolean", + "default": false + }, + "no-extra-aliases": { + "description": "Do not allow non-required aliases.", + "type": "boolean", + "default": false + }, + "alias": { + "description": "List of aliases", + "type": "array", + "items": { + "type": "object", + "properties": { + "pkg": { + "description": "Package path e.g. knative.dev/serving/pkg/apis/autoscaling/v1alpha1", + "type": "string" + }, + "alias": { + "description": "Package alias e.g. autoscalingv1alpha1", + "type": "string" + } + }, + "required": ["pkg", "alias"] + } + } + } + }, + "inamedparam": { + "type": "object", + "additionalProperties": false, + "properties": { + "skip-single-param": { + "description": "Skips check for interface methods with only a single parameter.", + "type": "boolean", + "default": false + } + } + }, + "ireturn": { + "type": "object", + "additionalProperties": false, + "description": "Use either `reject` or `allow` properties for interfaces matching.", + "properties": { + "allow": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "enum": ["anon", "error", "empty", "stdlib"] + } + ] + } + }, + "reject": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "enum": ["anon", "error", "empty", "stdlib"] + } + ] + } + } + }, + "anyOf": [ + { + "not": { + "properties": { + "allow": { + "const": "reject" + } + } + }, + "required": ["allow"] + }, + { + "required": ["reject"] + } + ] + }, + "lll": { + "type": "object", + "additionalProperties": false, + "properties": { + "tab-width": { + "description": "Width of \"\\t\" in spaces.", + "type": "integer", + "minimum": 0, + "default": 1 + }, + "line-length": { + "description": "Maximum allowed line length, lines longer will be reported.", + "type": "integer", + "minimum": 1, + "default": 120 + } + } + }, + "maintidx": { + "description": "Maintainability index https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022", + "type": "object", + "additionalProperties": false, + "properties": { + "under": { + "description": "Minimum accatpable maintainability index level (see https://docs.microsoft.com/en-us/visualstudio/code-quality/code-metrics-maintainability-index-range-and-meaning?view=vs-2022)", + "type": "number", + "default": 20 + } + } + }, + "makezero": { + "type": "object", + "additionalProperties": false, + "properties": { + "always": { + "description": "Allow only slices initialized with a length of zero.", + "type": "boolean", + "default": false + } + } + }, + "loggercheck": { + "type": "object", + "additionalProperties": false, + "properties": { + "kitlog": { + "description": "Allow check for the github.com/go-kit/log library.", + "type": "boolean", + "default": true + }, + "klog": { + "description": "Allow check for the k8s.io/klog/v2 library.", + "type": "boolean", + "default": true + }, + "logr": { + "description": "Allow check for the github.com/go-logr/logr library.", + "type": "boolean", + "default": true + }, + "zap": { + "description": "Allow check for the \"sugar logger\" from go.uber.org/zap library.", + "type": "boolean", + "default": true + }, + "require-string-key": { + "description": "Require all logging keys to be inlined constant strings.", + "type": "boolean", + "default": false + }, + "no-printf-like": { + "description": "Require printf-like format specifier (%s, %d for example) not present.", + "type": "boolean", + "default": false + }, + "rules": { + "description": "List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "misspell": { + "description": "Correct spellings using locale preferences for US or UK. Default is to use a neutral variety of English.", + "type": "object", + "additionalProperties": false, + "properties": { + "locale": { + "enum": ["US", "UK"] + }, + "ignore-words": { + "description": "List of words to ignore.", + "type": "array", + "items": { + "type": "string" + } + }, + "mode": { + "description": "Mode of the analysis.", + "enum": ["restricted", "", "default"], + "default": "" + }, + "extra-words": { + "description": "Extra word corrections.", + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "correction": { + "type": "string" + }, + "typo": { + "type": "string" + } + } + } + } + } + }, + "musttag": { + "type": "object", + "additionalProperties": false, + "properties": { + "functions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "tag": { + "type": "string" + }, + "arg-pos": { + "type": "integer" + } + }, + "additionalProperties": false + } + } + } + }, + "nakedret": { + "type": "object", + "additionalProperties": false, + "properties": { + "max-func-lines": { + "description": "Report if a function has more lines of code than this value and it has naked returns.", + "type": "integer", + "minimum": 0, + "default": 30 + } + } + }, + "nestif": { + "type": "object", + "additionalProperties": false, + "properties": { + "min-complexity": { + "description": "Minimum complexity of \"if\" statements to report.", + "type": "integer", + "default": 5 + } + } + }, + "nilnil": { + "type": "object", + "additionalProperties": false, + "properties": { + "checked-types": { + "type": "array", + "description": "Order of return types to check.", + "items": { + "enum": ["ptr", "func", "iface", "map", "chan"] + }, + "default": ["ptr", "func", "iface", "map", "chan"] + } + } + }, + "nlreturn": { + "type": "object", + "additionalProperties": false, + "properties": { + "block-size": { + "description": "set block size that is still ok", + "type": "number", + "default": 0, + "minimum": 0 + } + } + }, + "nolintlint": { + "type": "object", + "additionalProperties": false, + "properties": { + "allow-unused": { + "description": "Enable to ensure that nolint directives are all used.", + "type": "boolean", + "default": true + }, + "allow-no-explanation": { + "description": "Exclude these linters from requiring an explanation.", + "type": "array", + "items": { + "$ref": "#/definitions/linters" + }, + "default": [] + }, + "require-explanation": { + "description": "Enable to require an explanation of nonzero length after each nolint directive.", + "type": "boolean", + "default": false + }, + "require-specific": { + "description": "Enable to require nolint directives to mention the specific linter being suppressed.", + "type": "boolean", + "default": false + } + } + }, + "reassign": { + "type": "object", + "additionalProperties": false, + "properties": { + "patterns": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "nonamedreturns": { + "type": "object", + "additionalProperties": false, + "properties": { + "report-error-in-defer": { + "description": "Report named error if it is assigned inside defer.", + "type": "boolean", + "default": false + } + } + }, + "paralleltest": { + "type": "object", + "additionalProperties": false, + "properties": { + "ignore-missing": { + "description": "Ignore missing calls to `t.Parallel()` and only report incorrect uses of it.", + "type": "boolean", + "default": false + }, + "ignore-missing-subtests": { + "description": "Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are still required to have `t.Parallel`, but subtests are allowed to skip it.", + "type": "boolean", + "default": false + } + } + }, + "perfsprint": { + "type": "object", + "additionalProperties": false, + "properties": { + "int-conversion": { + "description": "Optimizes even if it requires an int or uint type cast.", + "type": "boolean", + "default": true + }, + "err-error": { + "description": "Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.", + "type": "boolean", + "default": false + }, + "errorf": { + "description": "Optimizes `fmt.Errorf`.", + "type": "boolean", + "default": true + }, + "sprintf1": { + "description": "Optimizes `fmt.Sprintf` with only one argument.", + "type": "boolean", + "default": true + }, + "strconcat": { + "description": "Optimizes into strings concatenation.", + "type": "boolean", + "default": true + } + } + }, + "prealloc": { + "description": "We do not recommend using this linter before doing performance profiling.\nFor most programs usage of `prealloc` will be premature optimization.", + "type": "object", + "additionalProperties": false, + "properties": { + "simple": { + "description": "Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.", + "type": "boolean", + "default": true + }, + "range-loops": { + "description": "Report preallocation suggestions on range loops.", + "type": "boolean", + "default": true + }, + "for-loops": { + "description": "Report preallocation suggestions on for loops.", + "type": "boolean", + "default": false + } + } + }, + "predeclared": { + "type": "object", + "additionalProperties": false, + "properties": { + "ignore": { + "description": "Comma-separated list of predeclared identifiers to not report on.", + "type": "string" + }, + "q": { + "description": "Include method names and field names (i.e., qualified names) in checks.", + "type": "boolean", + "default": false + } + } + }, + "promlinter": { + "type": "object", + "additionalProperties": false, + "properties": { + "strict": {}, + "disabled-linters": { + "type": "array", + "items": { + "enum": [ + "Help", + "MetricUnits", + "Counter", + "HistogramSummaryReserved", + "MetricTypeInName", + "ReservedChars", + "CamelCase", + "UnitAbbreviations" + ] + } + } + } + }, + "protogetter": { + "type": "object", + "additionalProperties": false, + "properties": { + "skip-generated-by": { + "type": "array", + "items": { + "type": "string", + "examples": ["protoc-gen-go-my-own-generator"] + } + }, + "skip-files": { + "type": "array", + "items": { + "type": "string", + "examples": ["*.pb.go"] + } + }, + "skip-any-generated": { + "description": "Skip any generated files from the checking.", + "type": "boolean", + "default": false + }, + "replace-first-arg-in-append": { + "description": "Skip first argument of append function.", + "type": "boolean", + "default": false + } + } + }, + "revive": { + "type": "object", + "additionalProperties": false, + "examples": [ + { + "ignore-generated-header": true, + "severity": "warning", + "rules": [ + { + "name": "indent-error-flow", + "severity": "warning" + }, + { + "name": "add-constant", + "severity": "warning", + "arguments": [ + { + "maxLitCount": "3", + "allowStrs": "\"\"", + "allowInts": "0,1,2", + "allowFloats": "0.0,0.,1.0,1.,2.0,2." + } + ] + } + ] + } + ], + "properties": { + "max-open-files": { + "type": "integer" + }, + "ignore-generated-header": { + "type": "boolean" + }, + "confidence": { + "type": "number" + }, + "severity": { + "type": "string", + "enum": ["warning", "error"] + }, + "enable-all-rules": { + "type": "boolean", + "default": false + }, + "rules": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["name"], + "properties": { + "name": { + "type": "string", + "title": "The rule name" + }, + "disabled": { + "type": "boolean" + }, + "severity": { + "type": "string", + "enum": ["warning", "error"] + }, + "exclude": { + "type": "array", + "items": { + "type": "string" + } + }, + "arguments": { + "type": "array" + } + } + } + } + } + }, + "rowserrcheck": { + "type": "object", + "additionalProperties": false, + "properties": { + "packages": { + "type": "array", + "items": { + "description": "", + "type": "string", + "examples": ["github.com/jmoiron/sqlx"] + } + } + } + }, + "sloglint": { + "type": "object", + "additionalProperties": false, + "properties": { + "kv-only": { + "description": "Enforce using key-value pairs only (incompatible with attr-only).", + "type": "boolean", + "default": false + }, + "no-mixed-args": { + "description": "Enforce not mixing key-value pairs and attributes.", + "type": "boolean", + "default": true + }, + "context-only": { + "description": "Enforce using methods that accept a context.", + "type": "boolean", + "default": false + }, + "static-msg": { + "description": "Enforce using static values for log messages.", + "type": "boolean", + "default": false + }, + "key-naming-case": { + "description": "Enforce a single key naming convention.", + "enum": ["snake", "kebab", "camel", "pascal"] + }, + "attr-only": { + "description": "Enforce using attributes only (incompatible with kv-only).", + "type": "boolean", + "default": false + }, + "no-raw-keys": { + "description": "Enforce using constants instead of raw keys.", + "type": "boolean", + "default": false + }, + "args-on-sep-lines": { + "description": "Enforce putting arguments on separate lines.", + "type": "boolean", + "default": false + } + } + }, + "spancheck": { + "type": "object", + "additionalProperties": false, + "properties": { + "checks": { + "description": "Checks to enable.", + "type": "array", + "items": { + "enum": ["end", "record-error", "set-status"] + } + }, + "ignore-check-signatures": { + "description": "A list of regexes for function signatures that silence `record-error` and `set-status` reports if found in the call path to a returned error.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "staticcheck": { + "type": "object", + "additionalProperties": false, + "properties": { + "go": { + "description": "Targeted Go version", + "type": "string", + "default": "1.13" + }, + "checks": { + "type": "array", + "items": { + "anyOf": [ + { + "enum": ["all"] + }, + { + "type": "string" + } + ] + } + } + } + }, + "stylecheck": { + "type": "object", + "additionalProperties": false, + "properties": { + "go": { + "description": "Targeted Go version", + "type": "string", + "default": "1.13" + }, + "checks": { + "type": "array", + "items": { + "anyOf": [ + { + "enum": ["all"] + }, + { + "type": "string" + } + ] + }, + "default": [ + "all", + "-ST1000", + "-ST1003", + "-ST1016", + "-ST1020", + "-ST1021", + "-ST1022" + ] + }, + "dot-import-whitelist": { + "description": "By default, ST1001 forbids all uses of dot imports in non-test packages. This setting allows setting a whitelist of import paths that can be dot-imported anywhere.", + "type": "array", + "items": { + "type": "string" + } + }, + "http-status-code-whitelist": { + "description": "ST1013 recommends using constants from the net/http package instead of hard-coding numeric HTTP status codes. This setting specifies a list of numeric status codes that this check does not complain about.", + "default": ["200", "400", "404", "500"], + "type": "array", + "items": { + "enum": [ + "100", + "101", + "102", + "103", + "200", + "201", + "202", + "203", + "204", + "205", + "206", + "207", + "208", + "226", + "300", + "301", + "302", + "303", + "304", + "305", + "306", + "307", + "308", + "400", + "401", + "402", + "403", + "404", + "405", + "406", + "407", + "408", + "409", + "410", + "411", + "412", + "413", + "414", + "415", + "416", + "417", + "418", + "421", + "422", + "423", + "424", + "425", + "426", + "428", + "429", + "431", + "451", + "500", + "501", + "502", + "503", + "504", + "505", + "506", + "507", + "508", + "510", + "511" + ] + } + }, + "initialisms": { + "description": "ST1003 check, among other things, for the correct capitalization of initialisms. The set of known initialisms can be configured with this option.", + "type": "array", + "items": { + "type": "string", + "default": [ + "ACL", + "API", + "ASCII", + "CPU", + "CSS", + "DNS", + "EOF", + "GUID", + "HTML", + "HTTP", + "HTTPS", + "ID", + "IP", + "JSON", + "QPS", + "RAM", + "RPC", + "SLA", + "SMTP", + "SQL", + "SSH", + "TCP", + "TLS", + "TTL", + "UDP", + "UI", + "GID", + "UID", + "UUID", + "URI", + "URL", + "UTF8", + "VM", + "XML", + "XMPP", + "XSRF", + "XSS", + "SIP", + "RTP", + "AMQP", + "DB", + "TS" + ] + } + } + } + }, + "tagalign": { + "type": "object", + "additionalProperties": false, + "properties": { + "align": { + "description": "Align and sort can be used together or separately.", + "type": "boolean", + "default": true + }, + "sort": { + "description": "Whether enable tags sort.", + "type": "boolean", + "default": true + }, + "order": { + "description": "Specify the order of tags, the other tags will be sorted by name.", + "type": "array", + "items": { + "type": "string" + }, + "default": [], + "examples": [ + [ + "json", + "yaml", + "yml", + "toml", + "mapstructure", + "binding", + "validate" + ] + ] + }, + "strict": { + "description": "Whether enable strict style.", + "type": "boolean", + "default": false + } + } + }, + "tagliatelle": { + "type": "object", + "additionalProperties": false, + "properties": { + "case": { + "type": "object", + "properties": { + "use-field-name": { + "description": "Use the struct field name to check the name of the struct tag.", + "type": "boolean", + "default": false + }, + "rules": { + "type": "object", + "patternProperties": { + "^.+$": { + "enum": [ + "camel", + "pascal", + "kebab", + "snake", + "goCamel", + "goPascal", + "goKebab", + "goSnake", + "upper", + "upperSnake", + "lower", + "header" + ] + } + } + } + } + } + } + }, + "tenv": { + "type": "object", + "additionalProperties": false, + "properties": { + "all": { + "description": "The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures.", + "type": "boolean", + "default": false + } + } + }, + "testifylint": { + "type": "object", + "additionalProperties": false, + "properties": { + "bool-compare": { + "type": "object", + "additionalProperties": false, + "properties": { + "ignore-custom-types": { + "type": "boolean", + "default": false + } + } + }, + "enable-all": { + "description": "Enable all checkers.", + "type": "boolean", + "default": false + }, + "disable-all": { + "description": "Disable all checkers.", + "type": "boolean", + "default": false + }, + "enable": { + "description": "Enable specific checkers.", + "type": "array", + "items": { + "enum": [ + "blank-import", + "bool-compare", + "compares", + "empty", + "error-is-as", + "error-nil", + "expected-actual", + "go-require", + "float-compare", + "len", + "nil-compare", + "require-error", + "suite-dont-use-pkg", + "suite-extra-assert-call", + "suite-thelper", + "useless-assert" + ] + } + }, + "disable": { + "description": "Enable specific checkers.", + "type": "array", + "items": { + "enum": [ + "blank-import", + "bool-compare", + "compares", + "empty", + "error-is-as", + "error-nil", + "expected-actual", + "go-require", + "float-compare", + "len", + "nil-compare", + "require-error", + "suite-dont-use-pkg", + "suite-extra-assert-call", + "suite-thelper", + "useless-assert" + ] + } + }, + "expected-actual": { + "type": "object", + "additionalProperties": false, + "properties": { + "pattern": { + "description": "Regexp for expected variable name.", + "type": "string" + } + } + }, + "require-error": { + "type": "object", + "additionalProperties": false, + "properties": { + "fn-pattern": { + "description": "Regexp for expected variable name.", + "type": "string" + } + } + }, + "suite-extra-assert-call": { + "type": "object", + "additionalProperties": false, + "properties": { + "mode": { + "description": "To require or remove extra Assert() call?", + "type": "string", + "enum": ["remove", "require"] + } + } + } + } + }, + "testpackage": { + "type": "object", + "additionalProperties": false, + "properties": { + "skip-regexp": { + "description": "Files with names matching this regular expression are skipped.", + "type": "string", + "examples": ["(export|internal)_test\\.go"] + }, + "allow-packages": { + "description": "List of packages that don't end with _test that tests are allowed to be in.", + "type": "array", + "uniqueItems": true, + "items": { + "type": "string", + "examples": ["example"] + } + } + } + }, + "thelper": { + "type": "object", + "additionalProperties": false, + "properties": { + "test": { + "type": "object", + "additionalProperties": false, + "properties": { + "begin": { + "description": "Check if `t.Helper()` begins helper function.", + "default": true, + "type": "boolean" + }, + "first": { + "description": "Check if *testing.T is first param of helper function.", + "default": true, + "type": "boolean" + }, + "name": { + "description": "Check if *testing.T param has t name.", + "default": true, + "type": "boolean" + } + } + }, + "benchmark": { + "type": "object", + "properties": { + "begin": { + "description": "Check if `b.Helper()` begins helper function.", + "default": true, + "type": "boolean" + }, + "first": { + "description": "Check if *testing.B is first param of helper function.", + "default": true, + "type": "boolean" + }, + "name": { + "description": "Check if *testing.B param has b name.", + "default": true, + "type": "boolean" + } + } + }, + "tb": { + "type": "object", + "properties": { + "begin": { + "description": "Check if `tb.Helper()` begins helper function.", + "default": true, + "type": "boolean" + }, + "first": { + "description": "Check if *testing.TB is first param of helper function.", + "default": true, + "type": "boolean" + }, + "name": { + "description": "Check if *testing.TB param has tb name.", + "default": true, + "type": "boolean" + } + } + }, + "fuzz": { + "type": "object", + "properties": { + "begin": { + "description": "Check if `f.Helper()` begins helper function.", + "default": true, + "type": "boolean" + }, + "first": { + "description": "Check if *testing.F is first param of helper function.", + "default": true, + "type": "boolean" + }, + "name": { + "description": "Check if *testing.F param has f name.", + "default": true, + "type": "boolean" + } + } + } + } + }, + "usestdlibvars": { + "type": "object", + "additionalProperties": false, + "properties": { + "http-method": { + "description": "Suggest the use of http.MethodXX.", + "type": "boolean", + "default": true + }, + "http-status-code": { + "description": "Suggest the use of http.StatusXX.", + "type": "boolean", + "default": true + }, + "time-weekday": { + "description": "Suggest the use of time.Weekday.String().", + "type": "boolean", + "default": false + }, + "time-month": { + "description": "Suggest the use of time.Month.String().", + "type": "boolean", + "default": false + }, + "time-layout": { + "description": "Suggest the use of time.Layout.", + "type": "boolean", + "default": false + }, + "crypto-hash": { + "description": "Suggest the use of crypto.Hash.String().", + "type": "boolean", + "default": false + }, + "default-rpc-path": { + "description": "Suggest the use of rpc.DefaultXXPath.", + "type": "boolean", + "default": false + }, + "os-dev-null": { + "description": "Suggest the use of os.DevNull.", + "type": "boolean", + "default": false + }, + "sql-isolation-level": { + "description": "Suggest the use of sql.LevelXX.String().", + "type": "boolean", + "default": false + }, + "tls-signature-scheme": { + "description": "Suggest the use of tls.SignatureScheme.String().", + "type": "boolean", + "default": false + }, + "constant-kind": { + "description": "Suggest the use of constant.Kind.String().", + "type": "boolean", + "default": false + }, + "syslog-priority": { + "description": "Suggest the use of syslog.Priority.", + "type": "boolean", + "default": false + } + } + }, + "unconvert": { + "type": "object", + "additionalProperties": false, + "properties": { + "fast-math": { + "type": "boolean", + "default": false + }, + "safe": { + "type": "boolean", + "default": false + } + } + }, + "unparam": { + "type": "object", + "additionalProperties": false, + "properties": { + "check-exported": { + "description": "Inspect exported functions. Set to true if no external program/library imports your code.\n\nWARNING: if you enable this setting, unparam will report a lot of false-positives in text editors:\nif it's called for subdir of a project it can't find external interfaces. All text editor integrations\nwith golangci-lint call it on a directory with the changed file.", + "type": "boolean", + "default": false + } + } + }, + "unused": { + "type": "object", + "additionalProperties": false, + "properties": { + "field-writes-are-uses": { + "description": "", + "type": "boolean", + "default": true + }, + "post-statements-are-reads": { + "description": "", + "type": "boolean", + "default": false + }, + "exported-is-used": { + "description": "", + "type": "boolean", + "default": true + }, + "exported-fields-are-used": { + "description": "", + "type": "boolean", + "default": true + }, + "parameters-are-used": { + "description": "", + "type": "boolean", + "default": true + }, + "local-variables-are-used": { + "description": "", + "type": "boolean", + "default": true + }, + "generated-is-used": { + "description": "", + "type": "boolean", + "default": true + } + } + }, + "varnamelen": { + "type": "object", + "additionalProperties": false, + "properties": { + "max-distance": { + "description": "Variables used in at most this N-many lines will be ignored.", + "type": "integer", + "default": 5 + }, + "min-name-length": { + "description": "The minimum length of a variable's name that is considered `long`.", + "type": "integer", + "default": 3 + }, + "check-receiver": { + "description": "Check method receiver names.", + "default": false, + "type": "boolean" + }, + "check-return": { + "description": "Check named return values.", + "default": false, + "type": "boolean" + }, + "check-type-param": { + "description": "Check type parameters.", + "default": false, + "type": "boolean" + }, + "ignore-type-assert-ok": { + "description": "Ignore `ok` variables that hold the bool return value of a type assertion", + "default": false, + "type": "boolean" + }, + "ignore-map-index-ok": { + "description": "Ignore `ok` variables that hold the bool return value of a map index.", + "default": false, + "type": "boolean" + }, + "ignore-chan-recv-ok": { + "description": "Ignore `ok` variables that hold the bool return value of a channel receive.", + "default": false, + "type": "boolean" + }, + "ignore-names": { + "description": "Optional list of variable names that should be ignored completely.", + "default": [[]], + "type": "array", + "items": { + "type": "string" + } + }, + "ignore-decls": { + "description": "Optional list of variable declarations that should be ignored completely.", + "type": "array", + "items": { + "type": "string" + }, + "examples": [ + ["c echo.Context", "t testing.T", "f *foo.Bar", "const C"] + ] + } + } + }, + "whitespace": { + "type": "object", + "additionalProperties": false, + "properties": { + "multi-if": { + "description": "Enforces newlines (or comments) after every multi-line if statement", + "type": "boolean", + "default": false + }, + "multi-func": { + "description": "Enforces newlines (or comments) after every multi-line function signature", + "type": "boolean", + "default": false + } + } + }, + "wrapcheck": { + "type": "object", + "additionalProperties": false, + "properties": { + "ignoreSigs": { + "description": "An array of strings which specify substrings of signatures to ignore.", + "default": [ + ".Errorf(", + "errors.New(", + "errors.Unwrap(", + ".Wrap(", + ".Wrapf(", + ".WithMessage(", + ".WithMessagef(", + ".WithStack(" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "ignoreSigRegexps": { + "description": "An array of strings which specify regular expressions of signatures to ignore.", + "default": [""], + "type": "array", + "items": { + "type": "string" + } + }, + "ignorePackageGlobs": { + "description": "An array of glob patterns which, if any match the package of the function returning the error, will skip wrapcheck analysis for this error.", + "default": [""], + "type": "array", + "items": { + "type": "string" + } + }, + "ignoreInterfaceRegexps": { + "description": "An array of glob patterns which, if matched to an underlying interface name, will ignore unwrapped errors returned from a function whose call is defined on the given interface.", + "default": [""], + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "wsl": { + "type": "object", + "additionalProperties": false, + "properties": { + "allow-assign-and-anything": { + "description": "Controls if you may cuddle assignments and anything without needing an empty line between them.", + "type": "boolean", + "default": false + }, + "allow-assign-and-call": { + "description": "Allow calls and assignments to be cuddled as long as the lines have any matching variables, fields or types.", + "type": "boolean", + "default": true + }, + "allow-cuddle-declarations": { + "description": "Allow declarations (var) to be cuddled.", + "type": "boolean", + "default": false + }, + "allow-cuddle-with-calls": { + "description": "A list of call idents that everything can be cuddled with.", + "type": "array", + "items": { + "type": "string" + } + }, + "allow-cuddle-with-rhs": { + "description": "AllowCuddleWithRHS is a list of right hand side variables that is allowed to be cuddled with anything.", + "type": "array", + "items": { + "type": "string" + } + }, + "allow-multiline-assign": { + "description": "Allow multiline assignments to be cuddled.", + "type": "boolean", + "default": true + }, + "allow-separated-leading-comment": { + "description": "Allow leading comments to be separated with empty lines.", + "type": "boolean", + "default": false + }, + "allow-trailing-comment": { + "description": "Allow trailing comments in ending of blocks.", + "type": "boolean", + "default": false + }, + "error-variable-names": { + "description": "When force-err-cuddling is enabled this is a list of names used for error variables to check for in the conditional.", + "type": "array", + "items": { + "type": "string" + } + }, + "force-case-trailing-whitespace": { + "description": "Force newlines in end of case at this limit (0 = never).", + "type": "integer", + "minimum": 0, + "default": 0 + }, + "force-err-cuddling": { + "description": "Causes an error when an If statement that checks an error variable doesn't cuddle with the assignment of that variable.", + "type": "boolean", + "default": false + }, + "force-short-decl-cuddling": { + "description": "Causes an error if a short declaration (:=) cuddles with anything other than another short declaration.", + "type": "boolean", + "default": false + }, + "strict-append": { + "description": "If true, append is only allowed to be cuddled if appending value is matching variables, fields or types on line above.", + "type": "boolean", + "default": true + } + } + }, + "copyloopvar": { + "type": "object", + "additionalProperties": false, + "properties": { + "ignore-alias": { + "type": "boolean", + "default": false + } + } + }, + "custom": { + "description": "The custom section can be used to define linter plugins to be loaded at runtime. See README of golangci-lint for more information.\nEach custom linter should have a unique name.", + "type": "object", + "patternProperties": { + "^.*$": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "description": "The plugin type.", + "enum": ["module", "goplugin"], + "default": "goplugin" + }, + "path": { + "description": "The path to the plugin *.so. Can be absolute or local.", + "type": "string", + "examples": ["/path/to/example.so"] + }, + "description": { + "description": "The description of the linter, for documentation purposes only.", + "type": "string" + }, + "original-url": { + "description": "Intended to point to the repo location of the linter, for documentation purposes only.", + "type": "string" + }, + "settings": { + "description": "Plugins settings/configuration. Only work with plugin based on `linterdb.PluginConstructor`.", + "type": "object" + } + }, + "required": ["path"] + } + } + } + }, + "additionalProperties": false + }, + "linters": { + "type": "object", + "properties": { + "enable": { + "description": "List of enabled linters.", + "type": "array", + "items": { + "$ref": "#/definitions/linters" + } + }, + "disable": { + "description": "List of disabled linters.", + "type": "array", + "items": { + "$ref": "#/definitions/linters" + } + }, + "enable-all": { + "description": "Whether to enable all linters. You can re-disable them with `disable` explicitly.", + "type": "boolean", + "default": false + }, + "disable-all": { + "description": "Whether to disable all linters. You can re-enable them with `enable` explicitly.", + "type": "boolean", + "default": false + }, + "presets": { + "description": "Allow to use different presets of linters", + "type": "array", + "items": { + "enum": [ + "bugs", + "comment", + "complexity", + "error", + "format", + "import", + "metalinter", + "module", + "performance", + "sql", + "style", + "test", + "unused" + ] + } + }, + "fast": { + "description": "Enable run of fast linters.", + "type": "boolean", + "default": false + } + }, + "additionalProperties": false + }, + "issues": { + "type": "object", + "properties": { + "exclude": { + "description": "List of regular expressions of issue texts to exclude.\nBut independently from this option we use default exclude patterns. Their usage can be controlled through `exclude-use-default`.", + "type": "array", + "items": { + "type": "string" + } + }, + "exclude-rules": { + "description": "Exclude configuration per-path, per-linter, per-text and per-source", + "type": "array", + "items": { + "type": "object", + "properties": { + "path": { + "type": "string" + }, + "path-except": { + "type": "string" + }, + "linters": { + "type": "array", + "items": { + "$ref": "#/definitions/linters" + } + }, + "text": { + "type": "string" + }, + "source": { + "type": "string" + } + } + } + }, + "exclude-use-default": { + "description": "Independently from option `exclude` we use default exclude patterns. This behavior can be disabled by this option.", + "type": "boolean", + "default": true + }, + "exclude-case-sensitive": { + "description": "If set to true, exclude and exclude-rules regular expressions become case sensitive.", + "type": "boolean", + "default": false + }, + "exclude-generated-strict": { + "description": "To follow strict Go generated file convention", + "type": "boolean", + "default": false + }, + "include": { + "description": "The list of ids of default excludes to include or disable.", + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "max-issues-per-linter": { + "description": "Maximum issues count per one linter. Set to 0 to disable.", + "type": "integer", + "default": 50, + "minimum": 0 + }, + "max-same-issues": { + "description": "Maximum count of issues with the same text. Set to 0 to disable.", + "type": "integer", + "default": 3, + "minimum": 0 + }, + "new": { + "description": "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.", + "type": "boolean", + "default": false + }, + "new-from-rev": { + "description": "Show only new issues created after this git revision.", + "type": "string" + }, + "new-from-patch": { + "description": "Show only new issues created in git patch with this file path.", + "type": "string", + "examples": ["path/to/patch/file"] + }, + "fix": { + "description": "Fix found issues (if it's supported by the linter).", + "type": "boolean", + "default": false + }, + "whole-files": { + "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).", + "type": "boolean", + "default": false + } + }, + "additionalProperties": false + }, + "severity": { + "type": "object", + "properties": { + "default-severity": { + "description": "Set the default severity for issues. If severity rules are defined and the issues do not match or no severity is provided to the rule this will be the default severity applied. Severities should match the supported severity names of the selected out format.", + "type": "string", + "default": "" + }, + "case-sensitive": { + "description": "If set to true, severity-rules regular expressions become case sensitive.", + "type": "boolean", + "default": false + }, + "rules": { + "description": "When a list of severity rules are provided, severity information will be added to lint issues. Severity rules have the same filtering capability as exclude rules except you are allowed to specify one matcher per severity rule.\nOnly affects out formats that support setting severity information.", + "type": "array", + "items": { + "allOf": [ + { + "oneOf": [ + { + "$ref": "#/definitions/issue-match-path" + }, + { + "$ref": "#/definitions/issue-match-source" + }, + { + "$ref": "#/definitions/issue-match-linters" + }, + { + "$ref": "#/definitions/issue-match-text" + } + ] + }, + { + "properties": { + "severity": { + "type": "string" + } + } + } + ], + "required": ["severity"] + }, + "default": [] + } + }, + "required": ["default-severity"], + "additionalProperties": false + } + }, + "type": "object" +} diff --git a/netlify.toml b/netlify.toml deleted file mode 100644 index dcd0c45f1cf1..000000000000 --- a/netlify.toml +++ /dev/null @@ -1,23 +0,0 @@ -[context.production.environment] - GO_VERSION = "1.19" - NODE_VERSION = "17" - # TODO https://github.com/golangci/golangci-lint/pull/2904#issuecomment-1146870535 -# NPM_FLAGS = "--legacy-peer-deps" -# NPM_FLAGS = "--force" - NPM_VERSION = "8.5.5" - -[context.deploy-preview.environment] - GO_VERSION = "1.19" - NODE_VERSION = "17" - # TODO https://github.com/golangci/golangci-lint/pull/2904#issuecomment-1146870535 -# NPM_FLAGS = "--legacy-peer-deps" -# NPM_FLAGS = "--force" - NPM_VERSION = "8.5.5" - -[context.branch-deploy.environment] - GO_VERSION = "1.19" - NODE_VERSION = "17" - # TODO https://github.com/golangci/golangci-lint/pull/2904#issuecomment-1146870535 -# NPM_FLAGS = "--legacy-peer-deps" -# NPM_FLAGS = "--force" - NPM_VERSION = "8.5.5" diff --git a/pkg/commands/cache.go b/pkg/commands/cache.go index f95fdfaec614..4aa8130518b0 100644 --- a/pkg/commands/cache.go +++ b/pkg/commands/cache.go @@ -12,7 +12,13 @@ import ( "github.com/golangci/golangci-lint/pkg/logutils" ) -func (e *Executor) initCache() { +type cacheCommand struct { + cmd *cobra.Command +} + +func newCacheCommand() *cacheCommand { + c := &cacheCommand{} + cacheCmd := &cobra.Command{ Use: "cache", Short: "Cache control and information", @@ -21,28 +27,32 @@ func (e *Executor) initCache() { return cmd.Help() }, } - e.rootCmd.AddCommand(cacheCmd) - cacheCmd.AddCommand(&cobra.Command{ - Use: "clean", - Short: "Clean cache", - Args: cobra.NoArgs, - ValidArgsFunction: cobra.NoFileCompletions, - RunE: e.executeCleanCache, - }) - cacheCmd.AddCommand(&cobra.Command{ - Use: "status", - Short: "Show cache status", - Args: cobra.NoArgs, - ValidArgsFunction: cobra.NoFileCompletions, - Run: e.executeCacheStatus, - }) + cacheCmd.AddCommand( + &cobra.Command{ + Use: "clean", + Short: "Clean cache", + Args: cobra.NoArgs, + ValidArgsFunction: cobra.NoFileCompletions, + RunE: c.executeClean, + }, + &cobra.Command{ + Use: "status", + Short: "Show cache status", + Args: cobra.NoArgs, + ValidArgsFunction: cobra.NoFileCompletions, + Run: c.executeStatus, + }, + ) - // TODO: add trim command? + c.cmd = cacheCmd + + return c } -func (e *Executor) executeCleanCache(_ *cobra.Command, _ []string) error { +func (c *cacheCommand) executeClean(_ *cobra.Command, _ []string) error { cacheDir := cache.DefaultDir() + if err := os.RemoveAll(cacheDir); err != nil { return fmt.Errorf("failed to remove dir %s: %w", cacheDir, err) } @@ -50,13 +60,13 @@ func (e *Executor) executeCleanCache(_ *cobra.Command, _ []string) error { return nil } -func (e *Executor) executeCacheStatus(_ *cobra.Command, _ []string) { +func (c *cacheCommand) executeStatus(_ *cobra.Command, _ []string) { cacheDir := cache.DefaultDir() - fmt.Fprintf(logutils.StdOut, "Dir: %s\n", cacheDir) + _, _ = fmt.Fprintf(logutils.StdOut, "Dir: %s\n", cacheDir) cacheSizeBytes, err := dirSizeBytes(cacheDir) if err == nil { - fmt.Fprintf(logutils.StdOut, "Size: %s\n", fsutils.PrettifyBytesCount(cacheSizeBytes)) + _, _ = fmt.Fprintf(logutils.StdOut, "Size: %s\n", fsutils.PrettifyBytesCount(cacheSizeBytes)) } } @@ -64,7 +74,7 @@ func dirSizeBytes(path string) (int64, error) { var size int64 err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error { if err == nil && !info.IsDir() { - size = info.Size() + size += info.Size() } return err }) diff --git a/pkg/commands/config.go b/pkg/commands/config.go index a16ef63106c1..3d74c89d33f1 100644 --- a/pkg/commands/config.go +++ b/pkg/commands/config.go @@ -7,55 +7,85 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" + "github.com/golangci/golangci-lint/pkg/config" "github.com/golangci/golangci-lint/pkg/exitcodes" "github.com/golangci/golangci-lint/pkg/fsutils" + "github.com/golangci/golangci-lint/pkg/logutils" ) -func (e *Executor) initConfig() { - cmd := &cobra.Command{ +type configCommand struct { + viper *viper.Viper + cmd *cobra.Command + + log logutils.Log +} + +func newConfigCommand(log logutils.Log) *configCommand { + c := &configCommand{ + viper: viper.New(), + log: log, + } + + configCmd := &cobra.Command{ Use: "config", - Short: "Config", + Short: "Config file information", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { return cmd.Help() }, } - e.rootCmd.AddCommand(cmd) - - pathCmd := &cobra.Command{ - Use: "path", - Short: "Print used config path", - Args: cobra.NoArgs, - ValidArgsFunction: cobra.NoFileCompletions, - Run: e.executePathCmd, + + configCmd.AddCommand( + &cobra.Command{ + Use: "path", + Short: "Print used config path", + Args: cobra.NoArgs, + ValidArgsFunction: cobra.NoFileCompletions, + Run: c.execute, + PreRunE: c.preRunE, + }, + ) + + c.cmd = configCmd + + return c +} + +func (c *configCommand) preRunE(cmd *cobra.Command, _ []string) error { + // The command doesn't depend on the real configuration. + // It only needs to know the path of the configuration file. + loader := config.NewLoader(c.log.Child(logutils.DebugKeyConfigReader), c.viper, cmd.Flags(), config.LoaderOptions{}, config.NewDefault()) + + if err := loader.Load(); err != nil { + return fmt.Errorf("can't load config: %w", err) } - e.initRunConfiguration(pathCmd) // allow --config - cmd.AddCommand(pathCmd) + + return nil } -// getUsedConfig returns the resolved path to the golangci config file, or the empty string -// if no configuration could be found. -func (e *Executor) getUsedConfig() string { - usedConfigFile := viper.ConfigFileUsed() +func (c *configCommand) execute(_ *cobra.Command, _ []string) { + usedConfigFile := c.getUsedConfig() + if usedConfigFile == "" { + c.log.Warnf("No config file detected") + os.Exit(exitcodes.NoConfigFileDetected) + } + + fmt.Println(usedConfigFile) +} + +// getUsedConfig returns the resolved path to the golangci config file, +// or the empty string if no configuration could be found. +func (c *configCommand) getUsedConfig() string { + usedConfigFile := c.viper.ConfigFileUsed() if usedConfigFile == "" { return "" } prettyUsedConfigFile, err := fsutils.ShortestRelPath(usedConfigFile, "") if err != nil { - e.log.Warnf("Can't pretty print config file path: %s", err) + c.log.Warnf("Can't pretty print config file path: %s", err) return usedConfigFile } return prettyUsedConfigFile } - -func (e *Executor) executePathCmd(_ *cobra.Command, _ []string) { - usedConfigFile := e.getUsedConfig() - if usedConfigFile == "" { - e.log.Warnf("No config file detected") - os.Exit(exitcodes.NoConfigFileDetected) - } - - fmt.Println(usedConfigFile) -} diff --git a/pkg/commands/custom.go b/pkg/commands/custom.go new file mode 100644 index 000000000000..dd7b1bb2bd75 --- /dev/null +++ b/pkg/commands/custom.go @@ -0,0 +1,78 @@ +package commands + +import ( + "fmt" + "log" + "os" + + "github.com/spf13/cobra" + + "github.com/golangci/golangci-lint/pkg/commands/internal" + "github.com/golangci/golangci-lint/pkg/logutils" +) + +const envKeepTempFiles = "CUSTOM_GCL_KEEP_TEMP_FILES" + +type customCommand struct { + cmd *cobra.Command + + cfg *internal.Configuration + + log logutils.Log +} + +func newCustomCommand(logger logutils.Log) *customCommand { + c := &customCommand{log: logger} + + customCmd := &cobra.Command{ + Use: "custom", + Short: "Build a version of golangci-lint with custom linters", + Args: cobra.NoArgs, + PreRunE: c.preRunE, + RunE: c.runE, + } + + c.cmd = customCmd + + return c +} + +func (c *customCommand) preRunE(_ *cobra.Command, _ []string) error { + cfg, err := internal.LoadConfiguration() + if err != nil { + return err + } + + err = cfg.Validate() + if err != nil { + return err + } + + c.cfg = cfg + + return nil +} + +func (c *customCommand) runE(cmd *cobra.Command, _ []string) error { + tmp, err := os.MkdirTemp(os.TempDir(), "custom-gcl") + if err != nil { + return fmt.Errorf("create temporary directory: %w", err) + } + + defer func() { + if os.Getenv(envKeepTempFiles) != "" { + log.Printf("WARN: The env var %s has been detected: the temporary directory is preserved: %s", envKeepTempFiles, tmp) + + return + } + + _ = os.RemoveAll(tmp) + }() + + err = internal.NewBuilder(c.log, c.cfg, tmp).Build(cmd.Context()) + if err != nil { + return fmt.Errorf("build process: %w", err) + } + + return nil +} diff --git a/pkg/commands/executor.go b/pkg/commands/executor.go deleted file mode 100644 index 6dc3b74b6049..000000000000 --- a/pkg/commands/executor.go +++ /dev/null @@ -1,250 +0,0 @@ -package commands - -import ( - "bytes" - "context" - "crypto/sha256" - "io" - "os" - "path/filepath" - "strings" - "time" - - "github.com/fatih/color" - "github.com/gofrs/flock" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "github.com/spf13/pflag" - "gopkg.in/yaml.v3" - - "github.com/golangci/golangci-lint/internal/cache" - "github.com/golangci/golangci-lint/internal/pkgcache" - "github.com/golangci/golangci-lint/pkg/config" - "github.com/golangci/golangci-lint/pkg/fsutils" - "github.com/golangci/golangci-lint/pkg/golinters/goanalysis/load" - "github.com/golangci/golangci-lint/pkg/goutil" - "github.com/golangci/golangci-lint/pkg/lint" - "github.com/golangci/golangci-lint/pkg/lint/lintersdb" - "github.com/golangci/golangci-lint/pkg/logutils" - "github.com/golangci/golangci-lint/pkg/report" - "github.com/golangci/golangci-lint/pkg/timeutils" -) - -type Executor struct { - rootCmd *cobra.Command - runCmd *cobra.Command - lintersCmd *cobra.Command - - exitCode int - version, commit, date string - - cfg *config.Config // cfg is the unmarshaled data from the golangci config file. - log logutils.Log - reportData report.Data - DBManager *lintersdb.Manager - EnabledLintersSet *lintersdb.EnabledSet - contextLoader *lint.ContextLoader - goenv *goutil.Env - fileCache *fsutils.FileCache - lineCache *fsutils.LineCache - pkgCache *pkgcache.Cache - debugf logutils.DebugFunc - sw *timeutils.Stopwatch - - loadGuard *load.Guard - flock *flock.Flock -} - -// NewExecutor creates and initializes a new command executor. -func NewExecutor(version, commit, date string) *Executor { - startedAt := time.Now() - e := &Executor{ - cfg: config.NewDefault(), - version: version, - commit: commit, - date: date, - DBManager: lintersdb.NewManager(nil, nil), - debugf: logutils.Debug(logutils.DebugKeyExec), - } - - e.debugf("Starting execution...") - e.log = report.NewLogWrapper(logutils.NewStderrLog(logutils.DebugKeyEmpty), &e.reportData) - - // to setup log level early we need to parse config from command line extra time to - // find `-v` option - commandLineCfg, err := e.getConfigForCommandLine() - if err != nil && err != pflag.ErrHelp { - e.log.Fatalf("Can't get config for command line: %s", err) - } - if commandLineCfg != nil { - logutils.SetupVerboseLog(e.log, commandLineCfg.Run.IsVerbose) - - switch commandLineCfg.Output.Color { - case "always": - color.NoColor = false - case "never": - color.NoColor = true - case "auto": - // nothing - default: - e.log.Fatalf("invalid value %q for --color; must be 'always', 'auto', or 'never'", commandLineCfg.Output.Color) - } - } - - // init of commands must be done before config file reading because - // init sets config with the default values of flags - e.initRoot() - e.initRun() - e.initHelp() - e.initLinters() - e.initConfig() - e.initVersion() - e.initCache() - - // init e.cfg by values from config: flags parse will see these values - // like the default ones. It will overwrite them only if the same option - // is found in command-line: it's ok, command-line has higher priority. - - r := config.NewFileReader(e.cfg, commandLineCfg, e.log.Child(logutils.DebugKeyConfigReader)) - if err = r.Read(); err != nil { - e.log.Fatalf("Can't read config: %s", err) - } - - if (commandLineCfg == nil || commandLineCfg.Run.Go == "") && e.cfg != nil && e.cfg.Run.Go == "" { - e.cfg.Run.Go = config.DetectGoVersion() - } - - // recreate after getting config - e.DBManager = lintersdb.NewManager(e.cfg, e.log).WithCustomLinters() - - // Slice options must be explicitly set for proper merging of config and command-line options. - fixSlicesFlags(e.runCmd.Flags()) - fixSlicesFlags(e.lintersCmd.Flags()) - - e.EnabledLintersSet = lintersdb.NewEnabledSet(e.DBManager, - lintersdb.NewValidator(e.DBManager), e.log.Child(logutils.DebugKeyLintersDB), e.cfg) - e.goenv = goutil.NewEnv(e.log.Child(logutils.DebugKeyGoEnv)) - e.fileCache = fsutils.NewFileCache() - e.lineCache = fsutils.NewLineCache(e.fileCache) - - e.sw = timeutils.NewStopwatch("pkgcache", e.log.Child(logutils.DebugKeyStopwatch)) - e.pkgCache, err = pkgcache.NewCache(e.sw, e.log.Child(logutils.DebugKeyPkgCache)) - if err != nil { - e.log.Fatalf("Failed to build packages cache: %s", err) - } - e.loadGuard = load.NewGuard() - e.contextLoader = lint.NewContextLoader(e.cfg, e.log.Child(logutils.DebugKeyLoader), e.goenv, - e.lineCache, e.fileCache, e.pkgCache, e.loadGuard) - if err = e.initHashSalt(version); err != nil { - e.log.Fatalf("Failed to init hash salt: %s", err) - } - e.debugf("Initialized executor in %s", time.Since(startedAt)) - return e -} - -func (e *Executor) Execute() error { - return e.rootCmd.Execute() -} - -func (e *Executor) initHashSalt(version string) error { - binSalt, err := computeBinarySalt(version) - if err != nil { - return errors.Wrap(err, "failed to calculate binary salt") - } - - configSalt, err := computeConfigSalt(e.cfg) - if err != nil { - return errors.Wrap(err, "failed to calculate config salt") - } - - var b bytes.Buffer - b.Write(binSalt) - b.Write(configSalt) - cache.SetSalt(b.Bytes()) - return nil -} - -func computeBinarySalt(version string) ([]byte, error) { - if version != "" && version != "(devel)" { - return []byte(version), nil - } - - if logutils.HaveDebugTag(logutils.DebugKeyBinSalt) { - return []byte("debug"), nil - } - - p, err := os.Executable() - if err != nil { - return nil, err - } - f, err := os.Open(p) - if err != nil { - return nil, err - } - defer f.Close() - h := sha256.New() - if _, err := io.Copy(h, f); err != nil { - return nil, err - } - return h.Sum(nil), nil -} - -func computeConfigSalt(cfg *config.Config) ([]byte, error) { - // We don't hash all config fields to reduce meaningless cache - // invalidations. At least, it has a huge impact on tests speed. - - lintersSettingsBytes, err := yaml.Marshal(cfg.LintersSettings) - if err != nil { - return nil, errors.Wrap(err, "failed to json marshal config linter settings") - } - - var configData bytes.Buffer - configData.WriteString("linters-settings=") - configData.Write(lintersSettingsBytes) - configData.WriteString("\nbuild-tags=%s" + strings.Join(cfg.Run.BuildTags, ",")) - - h := sha256.New() - if _, err := h.Write(configData.Bytes()); err != nil { - return nil, err - } - return h.Sum(nil), nil -} - -func (e *Executor) acquireFileLock() bool { - if e.cfg.Run.AllowParallelRunners { - e.debugf("Parallel runners are allowed, no locking") - return true - } - - lockFile := filepath.Join(os.TempDir(), "golangci-lint.lock") - e.debugf("Locking on file %s...", lockFile) - f := flock.New(lockFile) - const retryDelay = time.Second - - ctx := context.Background() - if !e.cfg.Run.AllowSerialRunners { - const totalTimeout = 5 * time.Second - var cancel context.CancelFunc - ctx, cancel = context.WithTimeout(ctx, totalTimeout) - defer cancel() - } - if ok, _ := f.TryLockContext(ctx, retryDelay); !ok { - return false - } - - e.flock = f - return true -} - -func (e *Executor) releaseFileLock() { - if e.cfg.Run.AllowParallelRunners { - return - } - - if err := e.flock.Unlock(); err != nil { - e.debugf("Failed to unlock on file: %s", err) - } - if err := os.Remove(e.flock.Path()); err != nil { - e.debugf("Failed to remove lock file: %s", err) - } -} diff --git a/pkg/commands/flagsets.go b/pkg/commands/flagsets.go new file mode 100644 index 000000000000..8ec309c60f2d --- /dev/null +++ b/pkg/commands/flagsets.go @@ -0,0 +1,109 @@ +package commands + +import ( + "fmt" + "strings" + + "github.com/fatih/color" + "github.com/spf13/pflag" + "github.com/spf13/viper" + + "github.com/golangci/golangci-lint/pkg/commands/internal" + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/exitcodes" + "github.com/golangci/golangci-lint/pkg/lint/lintersdb" +) + +func setupLintersFlagSet(v *viper.Viper, fs *pflag.FlagSet) { + fs.StringSliceP("disable", "D", nil, color.GreenString("Disable specific linter")) // Hack see Loader.applyStringSliceHack + internal.AddFlagAndBind(v, fs, fs.Bool, "disable-all", "linters.disable-all", false, color.GreenString("Disable all linters")) + + fs.StringSliceP("enable", "E", nil, color.GreenString("Enable specific linter")) // Hack see Loader.applyStringSliceHack + internal.AddFlagAndBind(v, fs, fs.Bool, "enable-all", "linters.enable-all", false, color.GreenString("Enable all linters")) + + internal.AddFlagAndBind(v, fs, fs.Bool, "fast", "linters.fast", false, + color.GreenString("Enable only fast linters from enabled linters set (first run won't be fast)")) + + // Hack see Loader.applyStringSliceHack + fs.StringSliceP("presets", "p", nil, + color.GreenString(fmt.Sprintf("Enable presets (%s) of linters. Run 'golangci-lint help linters' to see "+ + "them. This option implies option --disable-all", strings.Join(lintersdb.AllPresets(), "|")))) + + fs.StringSlice("enable-only", nil, + color.GreenString("Override linters configuration section to only run the specific linter(s)")) // Flags only. +} + +func setupRunFlagSet(v *viper.Viper, fs *pflag.FlagSet) { + internal.AddFlagAndBindP(v, fs, fs.IntP, "concurrency", "j", "run.concurrency", getDefaultConcurrency(), + color.GreenString("Number of CPUs to use (Default: number of logical CPUs)")) + + internal.AddFlagAndBind(v, fs, fs.String, "modules-download-mode", "run.modules-download-mode", "", + color.GreenString("Modules download mode. If not empty, passed as -mod= to go tools")) + internal.AddFlagAndBind(v, fs, fs.Int, "issues-exit-code", "run.issues-exit-code", exitcodes.IssuesFound, + color.GreenString("Exit code when issues were found")) + internal.AddFlagAndBind(v, fs, fs.String, "go", "run.go", "", color.GreenString("Targeted Go version")) + fs.StringSlice("build-tags", nil, color.GreenString("Build tags")) // Hack see Loader.applyStringSliceHack + + internal.AddFlagAndBind(v, fs, fs.Duration, "timeout", "run.timeout", defaultTimeout, color.GreenString("Timeout for total work")) + + internal.AddFlagAndBind(v, fs, fs.Bool, "tests", "run.tests", true, color.GreenString("Analyze tests (*_test.go)")) + fs.StringSlice("skip-dirs", nil, color.GreenString("Regexps of directories to skip")) // Hack see Loader.applyStringSliceHack + internal.AddFlagAndBind(v, fs, fs.Bool, "skip-dirs-use-default", "run.skip-dirs-use-default", true, getDefaultDirectoryExcludeHelp()) + fs.StringSlice("skip-files", nil, color.GreenString("Regexps of files to skip")) // Hack see Loader.applyStringSliceHack + + const allowParallelDesc = "Allow multiple parallel golangci-lint instances running. " + + "If false (default) - golangci-lint acquires file lock on start." + internal.AddFlagAndBind(v, fs, fs.Bool, "allow-parallel-runners", "run.allow-parallel-runners", false, + color.GreenString(allowParallelDesc)) + const allowSerialDesc = "Allow multiple golangci-lint instances running, but serialize them around a lock. " + + "If false (default) - golangci-lint exits with an error if it fails to acquire file lock on start." + internal.AddFlagAndBind(v, fs, fs.Bool, "allow-serial-runners", "run.allow-serial-runners", false, color.GreenString(allowSerialDesc)) +} + +func setupOutputFlagSet(v *viper.Viper, fs *pflag.FlagSet) { + internal.AddFlagAndBind(v, fs, fs.String, "out-format", "output.format", config.OutFormatColoredLineNumber, + color.GreenString(fmt.Sprintf("Format of output: %s", strings.Join(config.OutFormats, "|")))) + internal.AddFlagAndBind(v, fs, fs.Bool, "print-issued-lines", "output.print-issued-lines", true, + color.GreenString("Print lines of code with issue")) + internal.AddFlagAndBind(v, fs, fs.Bool, "print-linter-name", "output.print-linter-name", true, + color.GreenString("Print linter name in issue line")) + internal.AddFlagAndBind(v, fs, fs.Bool, "uniq-by-line", "output.uniq-by-line", true, + color.GreenString("Make issues output unique by line")) + internal.AddFlagAndBind(v, fs, fs.Bool, "sort-results", "output.sort-results", false, + color.GreenString("Sort linter results")) + internal.AddFlagAndBind(v, fs, fs.StringSlice, "sort-order", "output.sort-order", nil, + color.GreenString("Sort order of linter results")) + internal.AddFlagAndBind(v, fs, fs.String, "path-prefix", "output.path-prefix", "", + color.GreenString("Path prefix to add to output")) + internal.AddFlagAndBind(v, fs, fs.Bool, "show-stats", "output.show-stats", false, color.GreenString("Show statistics per linter")) +} + +//nolint:gomnd +func setupIssuesFlagSet(v *viper.Viper, fs *pflag.FlagSet) { + fs.StringSliceP("exclude", "e", nil, color.GreenString("Exclude issue by regexp")) // Hack see Loader.applyStringSliceHack + internal.AddFlagAndBind(v, fs, fs.Bool, "exclude-use-default", "issues.exclude-use-default", true, + getDefaultIssueExcludeHelp()) + internal.AddFlagAndBind(v, fs, fs.Bool, "exclude-case-sensitive", "issues.exclude-case-sensitive", false, + color.GreenString("If set to true exclude and exclude rules regular expressions are case-sensitive")) + + internal.AddFlagAndBind(v, fs, fs.Int, "max-issues-per-linter", "issues.max-issues-per-linter", 50, + color.GreenString("Maximum issues count per one linter. Set to 0 to disable")) + internal.AddFlagAndBind(v, fs, fs.Int, "max-same-issues", "issues.max-same-issues", 3, + color.GreenString("Maximum count of issues with the same text. Set to 0 to disable")) + + const newDesc = "Show only new issues: if there are unstaged changes or untracked files, only those changes " + + "are analyzed, else only changes in HEAD~ are analyzed.\nIt's a super-useful option for integration " + + "of golangci-lint into existing large codebase.\nIt's not practical to fix all existing issues at " + + "the moment of integration: much better to not allow issues in new code.\nFor CI setups, prefer " + + "--new-from-rev=HEAD~, as --new can skip linting the current patch if any scripts generate " + + "unstaged files before golangci-lint runs." + internal.AddFlagAndBindP(v, fs, fs.BoolP, "new", "n", "issues.new", false, color.GreenString(newDesc)) + internal.AddFlagAndBind(v, fs, fs.String, "new-from-rev", "issues.new-from-rev", "", + color.GreenString("Show only new issues created after git revision `REV`")) + internal.AddFlagAndBind(v, fs, fs.String, "new-from-patch", "issues.new-from-patch", "", + color.GreenString("Show only new issues created in git patch with file path `PATH`")) + internal.AddFlagAndBind(v, fs, fs.Bool, "whole-files", "issues.whole-files", false, + color.GreenString("Show issues in any part of update files (requires new-from-rev or new-from-patch)")) + internal.AddFlagAndBind(v, fs, fs.Bool, "fix", "issues.fix", false, + color.GreenString("Fix found issues (if it's supported by the linter)")) +} diff --git a/pkg/commands/help.go b/pkg/commands/help.go index 61d362e7d2be..42da4a3dc9f6 100644 --- a/pkg/commands/help.go +++ b/pkg/commands/help.go @@ -8,11 +8,23 @@ import ( "github.com/fatih/color" "github.com/spf13/cobra" + "github.com/golangci/golangci-lint/pkg/config" "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/lint/lintersdb" "github.com/golangci/golangci-lint/pkg/logutils" ) -func (e *Executor) initHelp() { +type helpCommand struct { + cmd *cobra.Command + + dbManager *lintersdb.Manager + + log logutils.Log +} + +func newHelpCommand(logger logutils.Log) *helpCommand { + c := &helpCommand{log: logger} + helpCmd := &cobra.Command{ Use: "help", Short: "Help", @@ -21,22 +33,83 @@ func (e *Executor) initHelp() { return cmd.Help() }, } - e.rootCmd.SetHelpCommand(helpCmd) - - lintersHelpCmd := &cobra.Command{ - Use: "linters", - Short: "Help about linters", - Args: cobra.NoArgs, - ValidArgsFunction: cobra.NoFileCompletions, - Run: e.executeLintersHelp, + + helpCmd.AddCommand( + &cobra.Command{ + Use: "linters", + Short: "Help about linters", + Args: cobra.NoArgs, + ValidArgsFunction: cobra.NoFileCompletions, + Run: c.execute, + PreRunE: c.preRunE, + }, + ) + + c.cmd = helpCmd + + return c +} + +func (c *helpCommand) preRunE(_ *cobra.Command, _ []string) error { + // The command doesn't depend on the real configuration. + // It just needs the list of all plugins and all presets. + dbManager, err := lintersdb.NewManager(c.log.Child(logutils.DebugKeyLintersDB), config.NewDefault(), lintersdb.NewLinterBuilder()) + if err != nil { + return err + } + + c.dbManager = dbManager + + return nil +} + +func (c *helpCommand) execute(_ *cobra.Command, _ []string) { + var enabledLCs, disabledLCs []*linter.Config + for _, lc := range c.dbManager.GetAllSupportedLinterConfigs() { + if lc.Internal { + continue + } + + if lc.EnabledByDefault { + enabledLCs = append(enabledLCs, lc) + } else { + disabledLCs = append(disabledLCs, lc) + } + } + + color.Green("Enabled by default linters:\n") + printLinters(enabledLCs) + + color.Red("\nDisabled by default linters:\n") + printLinters(disabledLCs) + + color.Green("\nLinters presets:") + c.printPresets() +} + +func (c *helpCommand) printPresets() { + for _, p := range lintersdb.AllPresets() { + linters := c.dbManager.GetAllLinterConfigsForPreset(p) + + var linterNames []string + for _, lc := range linters { + if lc.Internal { + continue + } + + linterNames = append(linterNames, lc.Name()) + } + sort.Strings(linterNames) + + _, _ = fmt.Fprintf(logutils.StdOut, "%s: %s\n", color.YellowString(p), strings.Join(linterNames, ", ")) } - helpCmd.AddCommand(lintersHelpCmd) } -func printLinterConfigs(lcs []*linter.Config) { +func printLinters(lcs []*linter.Config) { sort.Slice(lcs, func(i, j int) bool { return lcs[i].Name() < lcs[j].Name() }) + for _, lc := range lcs { altNamesStr := "" if len(lc.AlternativeNames) != 0 { @@ -55,34 +128,7 @@ func printLinterConfigs(lcs []*linter.Config) { deprecatedMark = " [" + color.RedString("deprecated") + "]" } - fmt.Fprintf(logutils.StdOut, "%s%s%s: %s [fast: %t, auto-fix: %t]\n", color.YellowString(lc.Name()), - altNamesStr, deprecatedMark, linterDescription, !lc.IsSlowLinter(), lc.CanAutoFix) - } -} - -func (e *Executor) executeLintersHelp(_ *cobra.Command, _ []string) { - var enabledLCs, disabledLCs []*linter.Config - for _, lc := range e.DBManager.GetAllSupportedLinterConfigs() { - if lc.EnabledByDefault { - enabledLCs = append(enabledLCs, lc) - } else { - disabledLCs = append(disabledLCs, lc) - } - } - - color.Green("Enabled by default linters:\n") - printLinterConfigs(enabledLCs) - color.Red("\nDisabled by default linters:\n") - printLinterConfigs(disabledLCs) - - color.Green("\nLinters presets:") - for _, p := range e.DBManager.AllPresets() { - linters := e.DBManager.GetAllLinterConfigsForPreset(p) - linterNames := make([]string, 0, len(linters)) - for _, lc := range linters { - linterNames = append(linterNames, lc.Name()) - } - sort.Strings(linterNames) - fmt.Fprintf(logutils.StdOut, "%s: %s\n", color.YellowString(p), strings.Join(linterNames, ", ")) + _, _ = fmt.Fprintf(logutils.StdOut, "%s%s%s: %s [fast: %t, auto-fix: %t]\n", + color.YellowString(lc.Name()), altNamesStr, deprecatedMark, linterDescription, !lc.IsSlowLinter(), lc.CanAutoFix) } } diff --git a/pkg/commands/internal/builder.go b/pkg/commands/internal/builder.go new file mode 100644 index 000000000000..39ec2a251c37 --- /dev/null +++ b/pkg/commands/internal/builder.go @@ -0,0 +1,219 @@ +package internal + +import ( + "context" + "fmt" + "io" + "os" + "os/exec" + "path/filepath" + "runtime" + "strings" + "time" + "unicode" + + "github.com/golangci/golangci-lint/pkg/logutils" +) + +// Builder runs all the required commands to build a binary. +type Builder struct { + cfg *Configuration + + log logutils.Log + + root string + repo string +} + +// NewBuilder creates a new Builder. +func NewBuilder(logger logutils.Log, cfg *Configuration, root string) *Builder { + return &Builder{ + cfg: cfg, + log: logger, + root: root, + repo: filepath.Join(root, "golangci-lint"), + } +} + +// Build builds the custom binary. +func (b Builder) Build(ctx context.Context) error { + b.log.Infof("Cloning golangci-lint repository") + + err := b.clone(ctx) + if err != nil { + return fmt.Errorf("clone golangci-lint: %w", err) + } + + b.log.Infof("Adding plugin imports") + + err = b.updatePluginsFile() + if err != nil { + return fmt.Errorf("update plugin file: %w", err) + } + + b.log.Infof("Adding replace directives") + + err = b.addReplaceDirectives(ctx) + if err != nil { + return fmt.Errorf("add replace directives: %w", err) + } + + b.log.Infof("Running go mod tidy") + + err = b.goModTidy(ctx) + if err != nil { + return fmt.Errorf("go mod tidy: %w", err) + } + + b.log.Infof("Building golangci-lint binary") + + binaryName := b.getBinaryName() + + err = b.goBuild(ctx, binaryName) + if err != nil { + return fmt.Errorf("build golangci-lint binary: %w", err) + } + + b.log.Infof("Moving golangci-lint binary") + + err = b.copyBinary(binaryName) + if err != nil { + return fmt.Errorf("move golangci-lint binary: %w", err) + } + + return nil +} + +func (b Builder) clone(ctx context.Context) error { + //nolint:gosec // the variable is sanitized. + cmd := exec.CommandContext(ctx, + "git", "clone", "--branch", sanitizeVersion(b.cfg.Version), + "--single-branch", "--depth", "1", "-c advice.detachedHead=false", "-q", + "https://github.com/golangci/golangci-lint.git", + ) + cmd.Dir = b.root + + output, err := cmd.CombinedOutput() + if err != nil { + b.log.Infof(string(output)) + + return fmt.Errorf("%s: %w", strings.Join(cmd.Args, " "), err) + } + + return nil +} + +func (b Builder) addReplaceDirectives(ctx context.Context) error { + for _, plugin := range b.cfg.Plugins { + if plugin.Path == "" { + continue + } + + replace := fmt.Sprintf("%s=%s", plugin.Module, plugin.Path) + + cmd := exec.CommandContext(ctx, "go", "mod", "edit", "-replace", replace) + cmd.Dir = b.repo + + b.log.Infof("run: %s", strings.Join(cmd.Args, " ")) + + output, err := cmd.CombinedOutput() + if err != nil { + b.log.Warnf(string(output)) + + return fmt.Errorf("%s: %w", strings.Join(cmd.Args, " "), err) + } + } + + return nil +} + +func (b Builder) goModTidy(ctx context.Context) error { + cmd := exec.CommandContext(ctx, "go", "mod", "tidy") + cmd.Dir = b.repo + + output, err := cmd.CombinedOutput() + if err != nil { + b.log.Warnf(string(output)) + + return fmt.Errorf("%s: %w", strings.Join(cmd.Args, " "), err) + } + + return nil +} + +func (b Builder) goBuild(ctx context.Context, binaryName string) error { + //nolint:gosec // the variable is sanitized. + cmd := exec.CommandContext(ctx, "go", "build", + "-ldflags", + fmt.Sprintf( + "-s -w -X 'main.version=%s-custom-gcl' -X 'main.date=%s'", + sanitizeVersion(b.cfg.Version), time.Now().UTC().String(), + ), + "-o", binaryName, + "./cmd/golangci-lint", + ) + cmd.Dir = b.repo + + output, err := cmd.CombinedOutput() + if err != nil { + b.log.Warnf(string(output)) + + return fmt.Errorf("%s: %w", strings.Join(cmd.Args, " "), err) + } + + return nil +} + +func (b Builder) copyBinary(binaryName string) error { + src := filepath.Join(b.repo, binaryName) + + source, err := os.Open(filepath.Clean(src)) + if err != nil { + return fmt.Errorf("open source file: %w", err) + } + + defer func() { _ = source.Close() }() + + info, err := source.Stat() + if err != nil { + return fmt.Errorf("stat source file: %w", err) + } + + if b.cfg.Destination != "" { + err = os.MkdirAll(b.cfg.Destination, os.ModePerm) + if err != nil { + return fmt.Errorf("create destination directory: %w", err) + } + } + + dst, err := os.OpenFile(filepath.Join(b.cfg.Destination, binaryName), os.O_RDWR|os.O_CREATE|os.O_TRUNC, info.Mode()) + if err != nil { + return fmt.Errorf("create destination file: %w", err) + } + + defer func() { _ = dst.Close() }() + + _, err = io.Copy(dst, source) + if err != nil { + return fmt.Errorf("copy source to destination: %w", err) + } + + return nil +} + +func (b Builder) getBinaryName() string { + name := b.cfg.Name + if runtime.GOOS == "windows" { + name += ".exe" + } + + return name +} + +func sanitizeVersion(v string) string { + fn := func(c rune) bool { + return !(unicode.IsLetter(c) || unicode.IsNumber(c) || c == '.' || c == '/') + } + + return strings.Join(strings.FieldsFunc(v, fn), "") +} diff --git a/pkg/commands/internal/builder_test.go b/pkg/commands/internal/builder_test.go new file mode 100644 index 000000000000..508755cf2271 --- /dev/null +++ b/pkg/commands/internal/builder_test.go @@ -0,0 +1,57 @@ +package internal + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_sanitizeVersion(t *testing.T) { + testCases := []struct { + desc string + input string + expected string + }{ + { + desc: "ampersand", + input: " te&st", + expected: "test", + }, + { + desc: "pipe", + input: " te|st", + expected: "test", + }, + { + desc: "version", + input: "v1.2.3", + expected: "v1.2.3", + }, + { + desc: "branch", + input: "feat/test", + expected: "feat/test", + }, + { + desc: "branch", + input: "value --key", + expected: "valuekey", + }, + { + desc: "hash", + input: "cd8b1177", + expected: "cd8b1177", + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + v := sanitizeVersion(test.input) + + assert.Equal(t, test.expected, v) + }) + } +} diff --git a/pkg/commands/internal/configuration.go b/pkg/commands/internal/configuration.go new file mode 100644 index 000000000000..5327025946cc --- /dev/null +++ b/pkg/commands/internal/configuration.go @@ -0,0 +1,138 @@ +package internal + +import ( + "errors" + "fmt" + "os" + "path/filepath" + "strings" + + "gopkg.in/yaml.v3" +) + +const base = ".custom-gcl" + +const defaultBinaryName = "custom-gcl" + +// Configuration represents the configuration file. +type Configuration struct { + // golangci-lint version. + Version string `yaml:"version"` + + // Name of the binary. + Name string `yaml:"name,omitempty"` + + // Destination is the path to a directory to store the binary. + Destination string `yaml:"destination,omitempty"` + + // Plugins information. + Plugins []*Plugin `yaml:"plugins,omitempty"` +} + +// Validate checks and clean the configuration. +func (c *Configuration) Validate() error { + if strings.TrimSpace(c.Version) == "" { + return errors.New("root field 'version' is required") + } + + if strings.TrimSpace(c.Name) == "" { + c.Name = defaultBinaryName + } + + if len(c.Plugins) == 0 { + return errors.New("no plugins defined") + } + + for _, plugin := range c.Plugins { + if strings.TrimSpace(plugin.Module) == "" { + return errors.New("field 'module' is required") + } + + if strings.TrimSpace(plugin.Import) == "" { + plugin.Import = plugin.Module + } + + if strings.TrimSpace(plugin.Path) == "" && strings.TrimSpace(plugin.Version) == "" { + return errors.New("missing information: 'version' or 'path' should be provided") + } + + if strings.TrimSpace(plugin.Path) != "" && strings.TrimSpace(plugin.Version) != "" { + return errors.New("invalid configuration: 'version' and 'path' should not be provided at the same time") + } + + if strings.TrimSpace(plugin.Path) == "" { + continue + } + + abs, err := filepath.Abs(plugin.Path) + if err != nil { + return err + } + + plugin.Path = abs + } + + return nil +} + +// Plugin represents information about a plugin. +type Plugin struct { + // Module name. + Module string `yaml:"module"` + + // Import to use. + Import string `yaml:"import,omitempty"` + + // Version of the module. + // Only for module available through a Go proxy. + Version string `yaml:"version,omitempty"` + + // Path to the local module. + // Only for local module. + Path string `yaml:"path,omitempty"` +} + +func LoadConfiguration() (*Configuration, error) { + configFilePath, err := findConfigurationFile() + if err != nil { + return nil, fmt.Errorf("file %s not found: %w", configFilePath, err) + } + + file, err := os.Open(configFilePath) + if err != nil { + return nil, fmt.Errorf("file %s open: %w", configFilePath, err) + } + + var cfg Configuration + + err = yaml.NewDecoder(file).Decode(&cfg) + if err != nil { + return nil, fmt.Errorf("YAML decoding: %w", err) + } + + return &cfg, nil +} + +func findConfigurationFile() (string, error) { + entries, err := os.ReadDir(".") + if err != nil { + return "", fmt.Errorf("read directory: %w", err) + } + + for _, entry := range entries { + ext := filepath.Ext(entry.Name()) + + switch strings.ToLower(strings.TrimPrefix(ext, ".")) { + case "yml", "yaml", "json": + if isConf(ext, entry.Name()) { + return entry.Name(), nil + } + } + } + + return "", errors.New("configuration file not found") +} + +func isConf(ext, name string) bool { + return base+ext == name +} diff --git a/pkg/commands/internal/configuration_test.go b/pkg/commands/internal/configuration_test.go new file mode 100644 index 000000000000..3c85a9075f52 --- /dev/null +++ b/pkg/commands/internal/configuration_test.go @@ -0,0 +1,127 @@ +package internal + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestConfiguration_Validate(t *testing.T) { + testCases := []struct { + desc string + cfg *Configuration + }{ + { + desc: "version", + cfg: &Configuration{ + Version: "v1.57.0", + Plugins: []*Plugin{ + { + Module: "example.org/foo/bar", + Import: "example.org/foo/bar/test", + Version: "v1.2.3", + }, + }, + }, + }, + { + desc: "path", + cfg: &Configuration{ + Version: "v1.57.0", + Plugins: []*Plugin{ + { + Module: "example.org/foo/bar", + Import: "example.org/foo/bar/test", + Path: "/my/path", + }, + }, + }, + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + err := test.cfg.Validate() + require.NoError(t, err) + }) + } +} + +func TestConfiguration_Validate_error(t *testing.T) { + testCases := []struct { + desc string + cfg *Configuration + expected string + }{ + { + desc: "missing version", + cfg: &Configuration{}, + expected: "root field 'version' is required", + }, + { + desc: "no plugins", + cfg: &Configuration{ + Version: "v1.57.0", + }, + expected: "no plugins defined", + }, + { + desc: "missing module", + cfg: &Configuration{ + Version: "v1.57.0", + Plugins: []*Plugin{ + { + Module: "", + Import: "example.org/foo/bar/test", + Version: "v1.2.3", + Path: "/my/path", + }, + }, + }, + expected: "field 'module' is required", + }, + { + desc: "module version and path", + cfg: &Configuration{ + Version: "v1.57.0", + Plugins: []*Plugin{ + { + Module: "example.org/foo/bar", + Import: "example.org/foo/bar/test", + Version: "v1.2.3", + Path: "/my/path", + }, + }, + }, + expected: "invalid configuration: 'version' and 'path' should not be provided at the same time", + }, + { + desc: "no module version and path", + cfg: &Configuration{ + Version: "v1.57.0", + Plugins: []*Plugin{ + { + Module: "example.org/foo/bar", + Import: "example.org/foo/bar/test", + }, + }, + }, + expected: "missing information: 'version' or 'path' should be provided", + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + err := test.cfg.Validate() + + assert.EqualError(t, err, test.expected) + }) + } +} diff --git a/pkg/commands/internal/imports.go b/pkg/commands/internal/imports.go new file mode 100644 index 000000000000..3bebf596b1ab --- /dev/null +++ b/pkg/commands/internal/imports.go @@ -0,0 +1,69 @@ +package internal + +import ( + "bytes" + "fmt" + "go/format" + "os" + "path/filepath" + "text/template" +) + +const importsTemplate = ` +package main + +import ( +{{range .Imports -}} + _ "{{.}}" +{{end -}} +) +` + +func (b Builder) updatePluginsFile() error { + importsDest := filepath.Join(b.repo, "cmd", "golangci-lint", "plugins.go") + + info, err := os.Stat(importsDest) + if err != nil { + return fmt.Errorf("file %s not found: %w", importsDest, err) + } + + source, err := generateImports(b.cfg) + if err != nil { + return fmt.Errorf("generate imports: %w", err) + } + + b.log.Infof("generated imports info %s:\n%s\n", importsDest, source) + + err = os.WriteFile(filepath.Clean(importsDest), source, info.Mode()) + if err != nil { + return fmt.Errorf("write file %s: %w", importsDest, err) + } + + return nil +} + +func generateImports(cfg *Configuration) ([]byte, error) { + impTmpl, err := template.New("plugins.go").Parse(importsTemplate) + if err != nil { + return nil, fmt.Errorf("parse template: %w", err) + } + + var imps []string + for _, plugin := range cfg.Plugins { + imps = append(imps, plugin.Import) + } + + buf := &bytes.Buffer{} + + err = impTmpl.Execute(buf, map[string]any{"Imports": imps}) + if err != nil { + return nil, fmt.Errorf("execute template: %w", err) + } + + source, err := format.Source(buf.Bytes()) + if err != nil { + return nil, fmt.Errorf("format source: %w", err) + } + + return source, nil +} diff --git a/pkg/commands/internal/imports_test.go b/pkg/commands/internal/imports_test.go new file mode 100644 index 000000000000..049e55e7f1f1 --- /dev/null +++ b/pkg/commands/internal/imports_test.go @@ -0,0 +1,36 @@ +package internal + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func Test_generateImports(t *testing.T) { + cfg := &Configuration{ + Version: "v1.57.0", + Plugins: []*Plugin{ + { + Module: "example.org/foo/bar", + Import: "example.org/foo/bar/test", + Version: "v1.2.3", + }, + { + Module: "example.com/foo/bar", + Import: "example.com/foo/bar/test", + Path: "/my/path", + }, + }, + } + + data, err := generateImports(cfg) + require.NoError(t, err) + + expected, err := os.ReadFile(filepath.Join("testdata", "imports.go")) + require.NoError(t, err) + + assert.Equal(t, expected, data) +} diff --git a/pkg/commands/internal/testdata/imports.go b/pkg/commands/internal/testdata/imports.go new file mode 100644 index 000000000000..c3c4f1312492 --- /dev/null +++ b/pkg/commands/internal/testdata/imports.go @@ -0,0 +1,6 @@ +package main + +import ( + _ "example.com/foo/bar/test" + _ "example.org/foo/bar/test" +) diff --git a/pkg/commands/internal/vibra.go b/pkg/commands/internal/vibra.go new file mode 100644 index 000000000000..5a5306fdb55e --- /dev/null +++ b/pkg/commands/internal/vibra.go @@ -0,0 +1,32 @@ +package internal + +import ( + "fmt" + + "github.com/spf13/pflag" + "github.com/spf13/viper" +) + +type FlagFunc[T any] func(name string, value T, usage string) *T + +type FlagPFunc[T any] func(name, shorthand string, value T, usage string) *T + +// AddFlagAndBind adds a Cobra/pflag flag and binds it with Viper. +func AddFlagAndBind[T any](v *viper.Viper, fs *pflag.FlagSet, pfn FlagFunc[T], name, bind string, value T, usage string) { + pfn(name, value, usage) + + err := v.BindPFlag(bind, fs.Lookup(name)) + if err != nil { + panic(fmt.Sprintf("failed to bind flag %s: %v", name, err)) + } +} + +// AddFlagAndBindP adds a Cobra/pflag flag and binds it with Viper. +func AddFlagAndBindP[T any](v *viper.Viper, fs *pflag.FlagSet, pfn FlagPFunc[T], name, shorthand, bind string, value T, usage string) { + pfn(name, shorthand, value, usage) + + err := v.BindPFlag(bind, fs.Lookup(name)) + if err != nil { + panic(fmt.Sprintf("failed to bind flag %s: %v", name, err)) + } +} diff --git a/pkg/commands/linters.go b/pkg/commands/linters.go index 13bb944d8a2c..083947707dd4 100644 --- a/pkg/commands/linters.go +++ b/pkg/commands/linters.go @@ -5,45 +5,101 @@ import ( "github.com/fatih/color" "github.com/spf13/cobra" + "github.com/spf13/viper" + "github.com/golangci/golangci-lint/pkg/config" "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/lint/lintersdb" + "github.com/golangci/golangci-lint/pkg/logutils" ) -func (e *Executor) initLinters() { - e.lintersCmd = &cobra.Command{ +type lintersOptions struct { + config.LoaderOptions +} + +type lintersCommand struct { + viper *viper.Viper + cmd *cobra.Command + + opts lintersOptions + + cfg *config.Config + + log logutils.Log + + dbManager *lintersdb.Manager +} + +func newLintersCommand(logger logutils.Log) *lintersCommand { + c := &lintersCommand{ + viper: viper.New(), + cfg: config.NewDefault(), + log: logger, + } + + lintersCmd := &cobra.Command{ Use: "linters", Short: "List current linters configuration", Args: cobra.NoArgs, ValidArgsFunction: cobra.NoFileCompletions, - RunE: e.executeLinters, + RunE: c.execute, + PreRunE: c.preRunE, } - e.rootCmd.AddCommand(e.lintersCmd) - e.initRunConfiguration(e.lintersCmd) + + fs := lintersCmd.Flags() + fs.SortFlags = false // sort them as they are defined here + + setupConfigFileFlagSet(fs, &c.opts.LoaderOptions) + setupLintersFlagSet(c.viper, fs) + + c.cmd = lintersCmd + + return c } -// executeLinters runs the 'linters' CLI command, which displays the supported linters. -func (e *Executor) executeLinters(_ *cobra.Command, _ []string) error { - enabledLintersMap, err := e.EnabledLintersSet.GetEnabledLintersMap() +func (c *lintersCommand) preRunE(cmd *cobra.Command, _ []string) error { + loader := config.NewLoader(c.log.Child(logutils.DebugKeyConfigReader), c.viper, cmd.Flags(), c.opts.LoaderOptions, c.cfg) + + if err := loader.Load(); err != nil { + return fmt.Errorf("can't load config: %w", err) + } + + dbManager, err := lintersdb.NewManager(c.log.Child(logutils.DebugKeyLintersDB), c.cfg, + lintersdb.NewLinterBuilder(), lintersdb.NewPluginModuleBuilder(c.log), lintersdb.NewPluginGoBuilder(c.log)) if err != nil { - return fmt.Errorf("can't get enabled linters: %w", err) + return err } - color.Green("Enabled by your configuration linters:\n") - enabledLinters := make([]*linter.Config, 0, len(enabledLintersMap)) - for _, linter := range enabledLintersMap { - enabledLinters = append(enabledLinters, linter) + c.dbManager = dbManager + + return nil +} + +func (c *lintersCommand) execute(_ *cobra.Command, _ []string) error { + enabledLintersMap, err := c.dbManager.GetEnabledLintersMap() + if err != nil { + return fmt.Errorf("can't get enabled linters: %w", err) } - printLinterConfigs(enabledLinters) + var enabledLinters []*linter.Config var disabledLCs []*linter.Config - for _, lc := range e.DBManager.GetAllSupportedLinterConfigs() { + + for _, lc := range c.dbManager.GetAllSupportedLinterConfigs() { + if lc.Internal { + continue + } + if enabledLintersMap[lc.Name()] == nil { disabledLCs = append(disabledLCs, lc) + } else { + enabledLinters = append(enabledLinters, lc) } } + color.Green("Enabled by your configuration linters:\n") + printLinters(enabledLinters) color.Red("\nDisabled by your configuration linters:\n") - printLinterConfigs(disabledLCs) + printLinters(disabledLCs) return nil } diff --git a/pkg/commands/root.go b/pkg/commands/root.go index 0fdcccff7d8c..be6e22ce1770 100644 --- a/pkg/commands/root.go +++ b/pkg/commands/root.go @@ -1,174 +1,167 @@ package commands import ( + "errors" "fmt" "os" - "runtime" - "runtime/pprof" - "runtime/trace" - "strconv" + "slices" + "github.com/fatih/color" "github.com/spf13/cobra" "github.com/spf13/pflag" - "github.com/golangci/golangci-lint/pkg/config" - "github.com/golangci/golangci-lint/pkg/exitcodes" "github.com/golangci/golangci-lint/pkg/logutils" ) -const ( - // envHelpRun value: "1". - envHelpRun = "HELP_RUN" - envMemProfileRate = "GL_MEM_PROFILE_RATE" -) +func Execute(info BuildInfo) error { + return newRootCommand(info).Execute() +} -func (e *Executor) persistentPreRun(_ *cobra.Command, _ []string) error { - if e.cfg.Run.PrintVersion { - _, _ = fmt.Fprintf(logutils.StdOut, "golangci-lint has version %s built from %s on %s\n", e.version, e.commit, e.date) - os.Exit(exitcodes.Success) // a return nil is not enough to stop the process because we are inside the `preRun`. - } +type rootOptions struct { + PrintVersion bool // Flag only. - runtime.GOMAXPROCS(e.cfg.Run.Concurrency) + Verbose bool // Flag only. + Color string // Flag only. +} - if e.cfg.Run.CPUProfilePath != "" { - f, err := os.Create(e.cfg.Run.CPUProfilePath) - if err != nil { - return fmt.Errorf("can't create file %s: %w", e.cfg.Run.CPUProfilePath, err) - } - if err := pprof.StartCPUProfile(f); err != nil { - return fmt.Errorf("can't start CPU profiling: %w", err) - } - } +type rootCommand struct { + cmd *cobra.Command + opts rootOptions - if e.cfg.Run.MemProfilePath != "" { - if rate := os.Getenv(envMemProfileRate); rate != "" { - runtime.MemProfileRate, _ = strconv.Atoi(rate) - } - } + log logutils.Log +} - if e.cfg.Run.TracePath != "" { - f, err := os.Create(e.cfg.Run.TracePath) - if err != nil { - return fmt.Errorf("can't create file %s: %w", e.cfg.Run.TracePath, err) - } - if err = trace.Start(f); err != nil { - return fmt.Errorf("can't start tracing: %w", err) - } - } +func newRootCommand(info BuildInfo) *rootCommand { + c := &rootCommand{} - return nil -} + rootCmd := &cobra.Command{ + Use: "golangci-lint", + Short: "golangci-lint is a smart linters runner.", + Long: `Smart, fast linters runner.`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, _ []string) error { + if c.opts.PrintVersion { + _ = printVersion(logutils.StdOut, info) + return nil + } -func (e *Executor) persistentPostRun(_ *cobra.Command, _ []string) error { - if e.cfg.Run.CPUProfilePath != "" { - pprof.StopCPUProfile() + return cmd.Help() + }, } - if e.cfg.Run.MemProfilePath != "" { - f, err := os.Create(e.cfg.Run.MemProfilePath) - if err != nil { - return fmt.Errorf("can't create file %s: %w", e.cfg.Run.MemProfilePath, err) - } + fs := rootCmd.Flags() + fs.BoolVar(&c.opts.PrintVersion, "version", false, color.GreenString("Print version")) - var ms runtime.MemStats - runtime.ReadMemStats(&ms) - printMemStats(&ms, e.log) + setupRootPersistentFlags(rootCmd.PersistentFlags(), &c.opts) - if err := pprof.WriteHeapProfile(f); err != nil { - return fmt.Errorf("cCan't write heap profile: %w", err) - } - _ = f.Close() - } + log := logutils.NewStderrLog(logutils.DebugKeyEmpty) - if e.cfg.Run.TracePath != "" { - trace.Stop() - } + // Each command uses a dedicated configuration structure to avoid side effects of bindings. + rootCmd.AddCommand( + newLintersCommand(log).cmd, + newRunCommand(log, info).cmd, + newCacheCommand().cmd, + newConfigCommand(log).cmd, + newVersionCommand(info).cmd, + newCustomCommand(log).cmd, + ) - os.Exit(e.exitCode) + rootCmd.SetHelpCommand(newHelpCommand(log).cmd) - return nil + c.log = log + c.cmd = rootCmd + + return c } -func printMemStats(ms *runtime.MemStats, logger logutils.Log) { - logger.Infof("Mem stats: alloc=%s total_alloc=%s sys=%s "+ - "heap_alloc=%s heap_sys=%s heap_idle=%s heap_released=%s heap_in_use=%s "+ - "stack_in_use=%s stack_sys=%s "+ - "mspan_sys=%s mcache_sys=%s buck_hash_sys=%s gc_sys=%s other_sys=%s "+ - "mallocs_n=%d frees_n=%d heap_objects_n=%d gc_cpu_fraction=%.2f", - formatMemory(ms.Alloc), formatMemory(ms.TotalAlloc), formatMemory(ms.Sys), - formatMemory(ms.HeapAlloc), formatMemory(ms.HeapSys), - formatMemory(ms.HeapIdle), formatMemory(ms.HeapReleased), formatMemory(ms.HeapInuse), - formatMemory(ms.StackInuse), formatMemory(ms.StackSys), - formatMemory(ms.MSpanSys), formatMemory(ms.MCacheSys), formatMemory(ms.BuckHashSys), - formatMemory(ms.GCSys), formatMemory(ms.OtherSys), - ms.Mallocs, ms.Frees, ms.HeapObjects, ms.GCCPUFraction) +func (c *rootCommand) Execute() error { + err := setupLogger(c.log) + if err != nil { + return err + } + + return c.cmd.Execute() } -func formatMemory(memBytes uint64) string { - const Kb = 1024 - const Mb = Kb * 1024 +func setupRootPersistentFlags(fs *pflag.FlagSet, opts *rootOptions) { + fs.BoolP("help", "h", false, color.GreenString("Help for a command")) + fs.BoolVarP(&opts.Verbose, "verbose", "v", false, color.GreenString("Verbose output")) + fs.StringVar(&opts.Color, "color", "auto", color.GreenString("Use color when printing; can be 'always', 'auto', or 'never'")) +} - if memBytes < Kb { - return fmt.Sprintf("%db", memBytes) +func setupLogger(logger logutils.Log) error { + opts, err := forceRootParsePersistentFlags() + if err != nil && !errors.Is(err, pflag.ErrHelp) { + return err } - if memBytes < Mb { - return fmt.Sprintf("%dkb", memBytes/Kb) + + if opts == nil { + return nil } - return fmt.Sprintf("%dmb", memBytes/Mb) -} -func getDefaultConcurrency() int { - if os.Getenv(envHelpRun) == "1" { - // Make stable concurrency for README help generating builds. - const prettyConcurrency = 8 - return prettyConcurrency + logutils.SetupVerboseLog(logger, opts.Verbose) + + switch opts.Color { + case "always": + color.NoColor = false + case "never": + color.NoColor = true + case "auto": + // nothing + default: + logger.Fatalf("invalid value %q for --color; must be 'always', 'auto', or 'never'", opts.Color) } - return runtime.NumCPU() + return nil } -func (e *Executor) initRoot() { - rootCmd := &cobra.Command{ - Use: "golangci-lint", - Short: "golangci-lint is a smart linters runner.", - Long: `Smart, fast linters runner.`, - Args: cobra.NoArgs, - RunE: func(cmd *cobra.Command, _ []string) error { - return cmd.Help() - }, - PersistentPreRunE: e.persistentPreRun, - PersistentPostRunE: e.persistentPostRun, - } +func forceRootParsePersistentFlags() (*rootOptions, error) { + // We use another pflag.FlagSet here to not set `changed` flag on cmd.Flags() options. + // Otherwise, string slice options will be duplicated. + fs := pflag.NewFlagSet("config flag set", pflag.ContinueOnError) - initRootFlagSet(rootCmd.PersistentFlags(), e.cfg, e.needVersionOption()) - e.rootCmd = rootCmd -} + // Ignore unknown flags because we will parse the command flags later. + fs.ParseErrorsWhitelist = pflag.ParseErrorsWhitelist{UnknownFlags: true} -func (e *Executor) needVersionOption() bool { - return e.date != "" -} + opts := &rootOptions{} -func initRootFlagSet(fs *pflag.FlagSet, cfg *config.Config, needVersionOption bool) { - fs.BoolVarP(&cfg.Run.IsVerbose, "verbose", "v", false, wh("verbose output")) + // Don't do `fs.AddFlagSet(cmd.Flags())` because it shares flags representations: + // `changed` variable inside string slice vars will be shared. + // Use another config variable here, + // to not affect main parsing by this parsing of only config option. + setupRootPersistentFlags(fs, opts) - var silent bool - fs.BoolVarP(&silent, "silent", "s", false, wh("disables congrats outputs")) - if err := fs.MarkHidden("silent"); err != nil { - panic(err) - } - err := fs.MarkDeprecated("silent", - "now golangci-lint by default is silent: it doesn't print Congrats message") - if err != nil { - panic(err) + fs.Usage = func() {} // otherwise, help text will be printed twice + + if err := fs.Parse(safeArgs(fs, os.Args)); err != nil { + if errors.Is(err, pflag.ErrHelp) { + return nil, err + } + + return nil, fmt.Errorf("can't parse args: %w", err) } - fs.StringVar(&cfg.Run.CPUProfilePath, "cpu-profile-path", "", wh("Path to CPU profile output file")) - fs.StringVar(&cfg.Run.MemProfilePath, "mem-profile-path", "", wh("Path to memory profile output file")) - fs.StringVar(&cfg.Run.TracePath, "trace-path", "", wh("Path to trace output file")) - fs.IntVarP(&cfg.Run.Concurrency, "concurrency", "j", getDefaultConcurrency(), wh("Concurrency (default NumCPU)")) - if needVersionOption { - fs.BoolVar(&cfg.Run.PrintVersion, "version", false, wh("Print version")) + return opts, nil +} + +// Shorthands are a problem because pflag, with UnknownFlags, will try to parse all the letters as options. +// A shorthand can aggregate several letters (ex `ps -aux`) +// The function replaces non-supported shorthands by a dumb flag. +func safeArgs(fs *pflag.FlagSet, args []string) []string { + var shorthands []string + fs.VisitAll(func(flag *pflag.Flag) { + shorthands = append(shorthands, flag.Shorthand) + }) + + var cleanArgs []string + for _, arg := range args { + if len(arg) > 1 && arg[0] == '-' && arg[1] != '-' && !slices.Contains(shorthands, string(arg[1])) { + cleanArgs = append(cleanArgs, "--potato") + continue + } + + cleanArgs = append(cleanArgs, arg) } - fs.StringVar(&cfg.Output.Color, "color", "auto", wh("Use color when printing; can be 'always', 'auto', or 'never'")) + return cleanArgs } diff --git a/pkg/commands/run.go b/pkg/commands/run.go index 8106dbdbd95f..410170aa2a1e 100644 --- a/pkg/commands/run.go +++ b/pkg/commands/run.go @@ -1,32 +1,51 @@ package commands import ( + "bytes" "context" + "crypto/sha256" + "errors" "fmt" "io" "log" "os" + "path/filepath" "runtime" + "runtime/pprof" + "runtime/trace" + "sort" + "strconv" "strings" "time" "github.com/fatih/color" - "github.com/pkg/errors" + "github.com/gofrs/flock" "github.com/spf13/cobra" "github.com/spf13/pflag" + "github.com/spf13/viper" + "go.uber.org/automaxprocs/maxprocs" + "golang.org/x/exp/maps" + "gopkg.in/yaml.v3" + "github.com/golangci/golangci-lint/internal/cache" + "github.com/golangci/golangci-lint/internal/pkgcache" "github.com/golangci/golangci-lint/pkg/config" "github.com/golangci/golangci-lint/pkg/exitcodes" + "github.com/golangci/golangci-lint/pkg/fsutils" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis/load" + "github.com/golangci/golangci-lint/pkg/goutil" "github.com/golangci/golangci-lint/pkg/lint" + "github.com/golangci/golangci-lint/pkg/lint/linter" "github.com/golangci/golangci-lint/pkg/lint/lintersdb" "github.com/golangci/golangci-lint/pkg/logutils" "github.com/golangci/golangci-lint/pkg/packages" "github.com/golangci/golangci-lint/pkg/printers" + "github.com/golangci/golangci-lint/pkg/report" "github.com/golangci/golangci-lint/pkg/result" - "github.com/golangci/golangci-lint/pkg/result/processors" + "github.com/golangci/golangci-lint/pkg/timeutils" ) -const defaultFileMode = 0644 +const defaultTimeout = time.Minute const ( // envFailOnWarnings value: "1" @@ -35,536 +54,469 @@ const ( envMemLogEvery = "GL_MEM_LOG_EVERY" ) -func getDefaultIssueExcludeHelp() string { - parts := []string{"Use or not use default excludes:"} - for _, ep := range config.DefaultExcludePatterns { - parts = append(parts, - fmt.Sprintf(" # %s %s: %s", ep.ID, ep.Linter, ep.Why), - fmt.Sprintf(" - %s", color.YellowString(ep.Pattern)), - "", - ) - } - return strings.Join(parts, "\n") -} +const ( + // envHelpRun value: "1". + envHelpRun = "HELP_RUN" + envMemProfileRate = "GL_MEM_PROFILE_RATE" +) -func getDefaultDirectoryExcludeHelp() string { - parts := []string{"Use or not use default excluded directories:"} - for _, dir := range packages.StdExcludeDirRegexps { - parts = append(parts, fmt.Sprintf(" - %s", color.YellowString(dir))) - } - parts = append(parts, "") - return strings.Join(parts, "\n") +type runOptions struct { + config.LoaderOptions + + CPUProfilePath string // Flag only. + MemProfilePath string // Flag only. + TracePath string // Flag only. + + PrintResourcesUsage bool // Flag only. } -func wh(text string) string { - return color.GreenString(text) +type runCommand struct { + viper *viper.Viper + cmd *cobra.Command + + opts runOptions + + cfg *config.Config + + buildInfo BuildInfo + + dbManager *lintersdb.Manager + + printer *printers.Printer + + log logutils.Log + debugf logutils.DebugFunc + reportData *report.Data + + contextLoader *lint.ContextLoader + goenv *goutil.Env + + fileCache *fsutils.FileCache + lineCache *fsutils.LineCache + + flock *flock.Flock + + exitCode int } -const defaultTimeout = time.Minute +func newRunCommand(logger logutils.Log, info BuildInfo) *runCommand { + reportData := &report.Data{} -//nolint:funlen,gomnd -func initFlagSet(fs *pflag.FlagSet, cfg *config.Config, m *lintersdb.Manager, isFinalInit bool) { - hideFlag := func(name string) { - if err := fs.MarkHidden(name); err != nil { - panic(err) - } + c := &runCommand{ + viper: viper.New(), + log: report.NewLogWrapper(logger, reportData), + debugf: logutils.Debug(logutils.DebugKeyExec), + cfg: config.NewDefault(), + reportData: reportData, + buildInfo: info, + } - // we run initFlagSet multiple times, but we wouldn't like to see deprecation message multiple times - if isFinalInit { - const deprecateMessage = "flag will be removed soon, please, use .golangci.yml config" - if err := fs.MarkDeprecated(name, deprecateMessage); err != nil { - panic(err) - } - } + runCmd := &cobra.Command{ + Use: "run", + Short: "Run the linters", + Run: c.execute, + PreRunE: c.preRunE, + PostRun: c.postRun, + PersistentPreRunE: c.persistentPreRunE, + PersistentPostRunE: c.persistentPostRunE, } - // Output config - oc := &cfg.Output - fs.StringVar(&oc.Format, "out-format", - config.OutFormatColoredLineNumber, - wh(fmt.Sprintf("Format of output: %s", strings.Join(config.OutFormats, "|")))) - fs.BoolVar(&oc.PrintIssuedLine, "print-issued-lines", true, wh("Print lines of code with issue")) - fs.BoolVar(&oc.PrintLinterName, "print-linter-name", true, wh("Print linter name in issue line")) - fs.BoolVar(&oc.UniqByLine, "uniq-by-line", true, wh("Make issues output unique by line")) - fs.BoolVar(&oc.SortResults, "sort-results", false, wh("Sort linter results")) - fs.BoolVar(&oc.PrintWelcomeMessage, "print-welcome", false, wh("Print welcome message")) - fs.StringVar(&oc.PathPrefix, "path-prefix", "", wh("Path prefix to add to output")) - hideFlag("print-welcome") // no longer used - - fs.BoolVar(&cfg.InternalCmdTest, "internal-cmd-test", false, wh("Option is used only for testing golangci-lint command, don't use it")) - if err := fs.MarkHidden("internal-cmd-test"); err != nil { - panic(err) - } - - // Run config - rc := &cfg.Run - fs.StringVar(&rc.ModulesDownloadMode, "modules-download-mode", "", - "Modules download mode. If not empty, passed as -mod= to go tools") - fs.IntVar(&rc.ExitCodeIfIssuesFound, "issues-exit-code", - exitcodes.IssuesFound, wh("Exit code when issues were found")) - fs.StringVar(&rc.Go, "go", "", wh("Targeted Go version")) - fs.StringSliceVar(&rc.BuildTags, "build-tags", nil, wh("Build tags")) - - fs.DurationVar(&rc.Timeout, "deadline", defaultTimeout, wh("Deadline for total work")) - if err := fs.MarkHidden("deadline"); err != nil { - panic(err) - } - fs.DurationVar(&rc.Timeout, "timeout", defaultTimeout, wh("Timeout for total work")) - - fs.BoolVar(&rc.AnalyzeTests, "tests", true, wh("Analyze tests (*_test.go)")) - fs.BoolVar(&rc.PrintResourcesUsage, "print-resources-usage", false, - wh("Print avg and max memory usage of golangci-lint and total time")) - fs.StringVarP(&rc.Config, "config", "c", "", wh("Read config from file path `PATH`")) - fs.BoolVar(&rc.NoConfig, "no-config", false, wh("Don't read config")) - fs.StringSliceVar(&rc.SkipDirs, "skip-dirs", nil, wh("Regexps of directories to skip")) - fs.BoolVar(&rc.UseDefaultSkipDirs, "skip-dirs-use-default", true, getDefaultDirectoryExcludeHelp()) - fs.StringSliceVar(&rc.SkipFiles, "skip-files", nil, wh("Regexps of files to skip")) - - const allowParallelDesc = "Allow multiple parallel golangci-lint instances running. " + - "If false (default) - golangci-lint acquires file lock on start." - fs.BoolVar(&rc.AllowParallelRunners, "allow-parallel-runners", false, wh(allowParallelDesc)) - const allowSerialDesc = "Allow multiple golangci-lint instances running, but serialize them around a lock. " + - "If false (default) - golangci-lint exits with an error if it fails to acquire file lock on start." - fs.BoolVar(&rc.AllowSerialRunners, "allow-serial-runners", false, wh(allowSerialDesc)) - - // Linters settings config - lsc := &cfg.LintersSettings - - // Hide all linters settings flags: they were initially visible, - // but when number of linters started to grow it became obvious that - // we can't fill 90% of flags by linters settings: common flags became hard to find. - // New linters settings should be done only through config file. - fs.BoolVar(&lsc.Errcheck.CheckTypeAssertions, "errcheck.check-type-assertions", - false, "Errcheck: check for ignored type assertion results") - hideFlag("errcheck.check-type-assertions") - fs.BoolVar(&lsc.Errcheck.CheckAssignToBlank, "errcheck.check-blank", false, - "Errcheck: check for errors assigned to blank identifier: _ = errFunc()") - hideFlag("errcheck.check-blank") - fs.StringVar(&lsc.Errcheck.Exclude, "errcheck.exclude", "", - "Path to a file containing a list of functions to exclude from checking") - hideFlag("errcheck.exclude") - fs.StringVar(&lsc.Errcheck.Ignore, "errcheck.ignore", "fmt:.*", - `Comma-separated list of pairs of the form pkg:regex. The regex is used to ignore names within pkg`) - hideFlag("errcheck.ignore") - - fs.BoolVar(&lsc.Govet.CheckShadowing, "govet.check-shadowing", false, - "Govet: check for shadowed variables") - hideFlag("govet.check-shadowing") - - fs.Float64Var(&lsc.Golint.MinConfidence, "golint.min-confidence", 0.8, - "Golint: minimum confidence of a problem to print it") - hideFlag("golint.min-confidence") - - fs.BoolVar(&lsc.Gofmt.Simplify, "gofmt.simplify", true, "Gofmt: simplify code") - hideFlag("gofmt.simplify") - - fs.IntVar(&lsc.Gocyclo.MinComplexity, "gocyclo.min-complexity", - 30, "Minimal complexity of function to report it") - hideFlag("gocyclo.min-complexity") - - fs.BoolVar(&lsc.Maligned.SuggestNewOrder, "maligned.suggest-new", false, - "Maligned: print suggested more optimal struct fields ordering") - hideFlag("maligned.suggest-new") - - fs.IntVar(&lsc.Dupl.Threshold, "dupl.threshold", - 150, "Dupl: Minimal threshold to detect copy-paste") - hideFlag("dupl.threshold") - - fs.BoolVar(&lsc.Goconst.MatchWithConstants, "goconst.match-constant", - true, "Goconst: look for existing constants matching the values") - hideFlag("goconst.match-constant") - fs.IntVar(&lsc.Goconst.MinStringLen, "goconst.min-len", - 3, "Goconst: minimum constant string length") - hideFlag("goconst.min-len") - fs.IntVar(&lsc.Goconst.MinOccurrencesCount, "goconst.min-occurrences", - 3, "Goconst: minimum occurrences of constant string count to trigger issue") - hideFlag("goconst.min-occurrences") - fs.BoolVar(&lsc.Goconst.ParseNumbers, "goconst.numbers", - false, "Goconst: search also for duplicated numbers") - hideFlag("goconst.numbers") - fs.IntVar(&lsc.Goconst.NumberMin, "goconst.min", - 3, "minimum value, only works with goconst.numbers") - hideFlag("goconst.min") - fs.IntVar(&lsc.Goconst.NumberMax, "goconst.max", - 3, "maximum value, only works with goconst.numbers") - hideFlag("goconst.max") - fs.BoolVar(&lsc.Goconst.IgnoreCalls, "goconst.ignore-calls", - true, "Goconst: ignore when constant is not used as function argument") - hideFlag("goconst.ignore-calls") - - // (@dixonwille) These flag is only used for testing purposes. - fs.StringSliceVar(&lsc.Depguard.Packages, "depguard.packages", nil, - "Depguard: packages to add to the list") - hideFlag("depguard.packages") - - fs.BoolVar(&lsc.Depguard.IncludeGoRoot, "depguard.include-go-root", false, - "Depguard: check list against standard lib") - hideFlag("depguard.include-go-root") - - fs.IntVar(&lsc.Lll.TabWidth, "lll.tab-width", 1, - "Lll: tab width in spaces") - hideFlag("lll.tab-width") - - // Linters config - lc := &cfg.Linters - fs.StringSliceVarP(&lc.Enable, "enable", "E", nil, wh("Enable specific linter")) - fs.StringSliceVarP(&lc.Disable, "disable", "D", nil, wh("Disable specific linter")) - fs.BoolVar(&lc.EnableAll, "enable-all", false, wh("Enable all linters")) - - fs.BoolVar(&lc.DisableAll, "disable-all", false, wh("Disable all linters")) - fs.StringSliceVarP(&lc.Presets, "presets", "p", nil, - wh(fmt.Sprintf("Enable presets (%s) of linters. Run 'golangci-lint linters' to see "+ - "them. This option implies option --disable-all", strings.Join(m.AllPresets(), "|")))) - fs.BoolVar(&lc.Fast, "fast", false, wh("Run only fast linters from enabled linters set (first run won't be fast)")) - - // Issues config - ic := &cfg.Issues - fs.StringSliceVarP(&ic.ExcludePatterns, "exclude", "e", nil, wh("Exclude issue by regexp")) - fs.BoolVar(&ic.UseDefaultExcludes, "exclude-use-default", true, getDefaultIssueExcludeHelp()) - fs.BoolVar(&ic.ExcludeCaseSensitive, "exclude-case-sensitive", false, wh("If set to true exclude "+ - "and exclude rules regular expressions are case sensitive")) - - fs.IntVar(&ic.MaxIssuesPerLinter, "max-issues-per-linter", 50, - wh("Maximum issues count per one linter. Set to 0 to disable")) - fs.IntVar(&ic.MaxSameIssues, "max-same-issues", 3, - wh("Maximum count of issues with the same text. Set to 0 to disable")) - - fs.BoolVarP(&ic.Diff, "new", "n", false, - wh("Show only new issues: if there are unstaged changes or untracked files, only those changes "+ - "are analyzed, else only changes in HEAD~ are analyzed.\nIt's a super-useful option for integration "+ - "of golangci-lint into existing large codebase.\nIt's not practical to fix all existing issues at "+ - "the moment of integration: much better to not allow issues in new code.\nFor CI setups, prefer "+ - "--new-from-rev=HEAD~, as --new can skip linting the current patch if any scripts generate "+ - "unstaged files before golangci-lint runs.")) - fs.StringVar(&ic.DiffFromRevision, "new-from-rev", "", - wh("Show only new issues created after git revision `REV`")) - fs.StringVar(&ic.DiffPatchFilePath, "new-from-patch", "", - wh("Show only new issues created in git patch with file path `PATH`")) - fs.BoolVar(&ic.WholeFiles, "whole-files", false, - wh("Show issues in any part of update files (requires new-from-rev or new-from-patch)")) - fs.BoolVar(&ic.NeedFix, "fix", false, "Fix found issues (if it's supported by the linter)") -} + runCmd.SetOut(logutils.StdOut) // use custom output to properly color it in Windows terminals + runCmd.SetErr(logutils.StdErr) -func (e *Executor) initRunConfiguration(cmd *cobra.Command) { - fs := cmd.Flags() + fs := runCmd.Flags() fs.SortFlags = false // sort them as they are defined here - initFlagSet(fs, e.cfg, e.DBManager, true) -} -func (e *Executor) getConfigForCommandLine() (*config.Config, error) { - // We use another pflag.FlagSet here to not set `changed` flag - // on cmd.Flags() options. Otherwise, string slice options will be duplicated. - fs := pflag.NewFlagSet("config flag set", pflag.ContinueOnError) - - var cfg config.Config - // Don't do `fs.AddFlagSet(cmd.Flags())` because it shares flags representations: - // `changed` variable inside string slice vars will be shared. - // Use another config variable here, not e.cfg, to not - // affect main parsing by this parsing of only config option. - initFlagSet(fs, &cfg, e.DBManager, false) - initVersionFlagSet(fs, &cfg) - - // Parse max options, even force version option: don't want - // to get access to Executor here: it's error-prone to use - // cfg vs e.cfg. - initRootFlagSet(fs, &cfg, true) - - fs.Usage = func() {} // otherwise, help text will be printed twice - if err := fs.Parse(os.Args); err != nil { - if err == pflag.ErrHelp { - return nil, err - } + // Only for testing purpose. + // Don't add other flags here. + fs.BoolVar(&c.cfg.InternalCmdTest, "internal-cmd-test", false, + color.GreenString("Option is used only for testing golangci-lint command, don't use it")) + _ = fs.MarkHidden("internal-cmd-test") - return nil, fmt.Errorf("can't parse args: %s", err) - } + setupConfigFileFlagSet(fs, &c.opts.LoaderOptions) + + setupLintersFlagSet(c.viper, fs) + setupRunFlagSet(c.viper, fs) + setupOutputFlagSet(c.viper, fs) + setupIssuesFlagSet(c.viper, fs) + + setupRunPersistentFlags(runCmd.PersistentFlags(), &c.opts) + + c.cmd = runCmd - return &cfg, nil + return c } -func (e *Executor) initRun() { - e.runCmd = &cobra.Command{ - Use: "run", - Short: "Run the linters", - Run: e.executeRun, - PreRunE: func(_ *cobra.Command, _ []string) error { - if ok := e.acquireFileLock(); !ok { - return errors.New("parallel golangci-lint is running") - } - return nil - }, - PostRun: func(_ *cobra.Command, _ []string) { - e.releaseFileLock() - }, +func (c *runCommand) persistentPreRunE(cmd *cobra.Command, _ []string) error { + if err := c.startTracing(); err != nil { + return err } - e.rootCmd.AddCommand(e.runCmd) - e.runCmd.SetOut(logutils.StdOut) // use custom output to properly color it in Windows terminals - e.runCmd.SetErr(logutils.StdErr) + loader := config.NewLoader(c.log.Child(logutils.DebugKeyConfigReader), c.viper, cmd.Flags(), c.opts.LoaderOptions, c.cfg) - e.initRunConfiguration(e.runCmd) -} + if err := loader.Load(); err != nil { + return fmt.Errorf("can't load config: %w", err) + } -func fixSlicesFlags(fs *pflag.FlagSet) { - // It's a dirty hack to set flag.Changed to true for every string slice flag. - // It's necessary to merge config and command-line slices: otherwise command-line - // flags will always overwrite ones from the config. - fs.VisitAll(func(f *pflag.Flag) { - if f.Value.Type() != "stringSlice" { - return - } + if c.cfg.Run.Concurrency == 0 { + backup := runtime.GOMAXPROCS(0) - s, err := fs.GetStringSlice(f.Name) + // Automatically set GOMAXPROCS to match Linux container CPU quota. + _, err := maxprocs.Set(maxprocs.Logger(c.log.Infof)) if err != nil { - return + runtime.GOMAXPROCS(backup) } + } else { + runtime.GOMAXPROCS(c.cfg.Run.Concurrency) + } - if s == nil { // assume that every string slice flag has nil as the default - return - } + return c.startTracing() +} - var safe []string - for _, v := range s { - // add quotes to escape comma because spf13/pflag use a CSV parser: - // https://github.com/spf13/pflag/blob/85dd5c8bc61cfa382fecd072378089d4e856579d/string_slice.go#L43 - safe = append(safe, `"`+v+`"`) - } +func (c *runCommand) persistentPostRunE(_ *cobra.Command, _ []string) error { + if err := c.stopTracing(); err != nil { + return err + } + + os.Exit(c.exitCode) - // calling Set sets Changed to true: next Set calls will append, not overwrite - _ = f.Value.Set(strings.Join(safe, ",")) - }) + return nil } -// runAnalysis executes the linters that have been enabled in the configuration. -func (e *Executor) runAnalysis(ctx context.Context, args []string) ([]result.Issue, error) { - e.cfg.Run.Args = args +func (c *runCommand) preRunE(_ *cobra.Command, _ []string) error { + dbManager, err := lintersdb.NewManager(c.log.Child(logutils.DebugKeyLintersDB), c.cfg, + lintersdb.NewLinterBuilder(), lintersdb.NewPluginModuleBuilder(c.log), lintersdb.NewPluginGoBuilder(c.log)) + if err != nil { + return err + } + + c.dbManager = dbManager - lintersToRun, err := e.EnabledLintersSet.GetOptimizedLinters() + printer, err := printers.NewPrinter(c.log, &c.cfg.Output, c.reportData) if err != nil { - return nil, err + return err } - enabledLintersMap, err := e.EnabledLintersSet.GetEnabledLintersMap() + c.printer = printer + + c.goenv = goutil.NewEnv(c.log.Child(logutils.DebugKeyGoEnv)) + + c.fileCache = fsutils.NewFileCache() + c.lineCache = fsutils.NewLineCache(c.fileCache) + + sw := timeutils.NewStopwatch("pkgcache", c.log.Child(logutils.DebugKeyStopwatch)) + + pkgCache, err := pkgcache.NewCache(sw, c.log.Child(logutils.DebugKeyPkgCache)) if err != nil { - return nil, err + return fmt.Errorf("failed to build packages cache: %w", err) } - for _, lc := range e.DBManager.GetAllSupportedLinterConfigs() { - isEnabled := enabledLintersMap[lc.Name()] != nil - e.reportData.AddLinter(lc.Name(), isEnabled, lc.EnabledByDefault) + c.contextLoader = lint.NewContextLoader(c.cfg, c.log.Child(logutils.DebugKeyLoader), c.goenv, + c.lineCache, c.fileCache, pkgCache, load.NewGuard()) + + if err = initHashSalt(c.buildInfo.Version, c.cfg); err != nil { + return fmt.Errorf("failed to init hash salt: %w", err) } - lintCtx, err := e.contextLoader.Load(ctx, lintersToRun) - if err != nil { - return nil, errors.Wrap(err, "context loading failed") + if ok := c.acquireFileLock(); !ok { + return errors.New("parallel golangci-lint is running") } - lintCtx.Log = e.log.Child(logutils.DebugKeyLintersContext) - runner, err := lint.NewRunner(e.cfg, e.log.Child(logutils.DebugKeyRunner), - e.goenv, e.EnabledLintersSet, e.lineCache, e.DBManager, lintCtx.Packages) - if err != nil { - return nil, err + return nil +} + +func (c *runCommand) postRun(_ *cobra.Command, _ []string) { + c.releaseFileLock() +} + +func (c *runCommand) execute(_ *cobra.Command, args []string) { + needTrackResources := logutils.IsVerbose() || c.opts.PrintResourcesUsage + + trackResourcesEndCh := make(chan struct{}) + defer func() { // XXX: this defer must be before ctx.cancel defer + if needTrackResources { // wait until resource tracking finished to print properly + <-trackResourcesEndCh + } + }() + + ctx, cancel := context.WithTimeout(context.Background(), c.cfg.Run.Timeout) + defer cancel() + + if needTrackResources { + go watchResources(ctx, trackResourcesEndCh, c.log, c.debugf) } - issues, err := runner.Run(ctx, lintersToRun, lintCtx) - if err != nil { - return nil, err + if err := c.runAndPrint(ctx, args); err != nil { + c.log.Errorf("Running error: %s", err) + if c.exitCode == exitcodes.Success { + var exitErr *exitcodes.ExitError + if errors.As(err, &exitErr) { + c.exitCode = exitErr.Code + } else { + c.exitCode = exitcodes.Failure + } + } } - fixer := processors.NewFixer(e.cfg, e.log, e.fileCache) - return fixer.Process(issues), nil + c.setupExitCode(ctx) } -func (e *Executor) setOutputToDevNull() (savedStdout, savedStderr *os.File) { - savedStdout, savedStderr = os.Stdout, os.Stderr - devNull, err := os.Open(os.DevNull) - if err != nil { - e.log.Warnf("Can't open null device %q: %s", os.DevNull, err) - return +func (c *runCommand) startTracing() error { + if c.opts.CPUProfilePath != "" { + f, err := os.Create(c.opts.CPUProfilePath) + if err != nil { + return fmt.Errorf("can't create file %s: %w", c.opts.CPUProfilePath, err) + } + if err := pprof.StartCPUProfile(f); err != nil { + return fmt.Errorf("can't start CPU profiling: %w", err) + } } - os.Stdout, os.Stderr = devNull, devNull - return + if c.opts.MemProfilePath != "" { + if rate := os.Getenv(envMemProfileRate); rate != "" { + runtime.MemProfileRate, _ = strconv.Atoi(rate) + } + } + + if c.opts.TracePath != "" { + f, err := os.Create(c.opts.TracePath) + if err != nil { + return fmt.Errorf("can't create file %s: %w", c.opts.TracePath, err) + } + if err = trace.Start(f); err != nil { + return fmt.Errorf("can't start tracing: %w", err) + } + } + + return nil } -func (e *Executor) setExitCodeIfIssuesFound(issues []result.Issue) { - if len(issues) != 0 { - e.exitCode = e.cfg.Run.ExitCodeIfIssuesFound +func (c *runCommand) stopTracing() error { + if c.opts.CPUProfilePath != "" { + pprof.StopCPUProfile() } + + if c.opts.MemProfilePath != "" { + f, err := os.Create(c.opts.MemProfilePath) + if err != nil { + return fmt.Errorf("can't create file %s: %w", c.opts.MemProfilePath, err) + } + + var ms runtime.MemStats + runtime.ReadMemStats(&ms) + printMemStats(&ms, c.log) + + if err := pprof.WriteHeapProfile(f); err != nil { + return fmt.Errorf("can't write heap profile: %w", err) + } + _ = f.Close() + } + + if c.opts.TracePath != "" { + trace.Stop() + } + + return nil } -func (e *Executor) runAndPrint(ctx context.Context, args []string) error { - if err := e.goenv.Discover(ctx); err != nil { - e.log.Warnf("Failed to discover go env: %s", err) +func (c *runCommand) runAndPrint(ctx context.Context, args []string) error { + if err := c.goenv.Discover(ctx); err != nil { + c.log.Warnf("Failed to discover go env: %s", err) } if !logutils.HaveDebugTag(logutils.DebugKeyLintersOutput) { // Don't allow linters and loader to print anything log.SetOutput(io.Discard) - savedStdout, savedStderr := e.setOutputToDevNull() + savedStdout, savedStderr := c.setOutputToDevNull() defer func() { os.Stdout, os.Stderr = savedStdout, savedStderr }() } - issues, err := e.runAnalysis(ctx, args) + enabledLintersMap, err := c.dbManager.GetEnabledLintersMap() if err != nil { - return err // XXX: don't loose type + return err } - formats := strings.Split(e.cfg.Output.Format, ",") - for _, format := range formats { - out := strings.SplitN(format, ":", 2) - if len(out) < 2 { - out = append(out, "") - } + c.printDeprecatedLinterMessages(enabledLintersMap) - err := e.printReports(ctx, issues, out[1], out[0]) - if err != nil { - return err - } + issues, err := c.runAnalysis(ctx, args) + if err != nil { + return err // XXX: don't lose type } - e.setExitCodeIfIssuesFound(issues) + // Fills linters information for the JSON printer. + for _, lc := range c.dbManager.GetAllSupportedLinterConfigs() { + isEnabled := enabledLintersMap[lc.Name()] != nil + c.reportData.AddLinter(lc.Name(), isEnabled, lc.EnabledByDefault) + } - e.fileCache.PrintStats(e.log) + err = c.printer.Print(issues) + if err != nil { + return err + } + + c.printStats(issues) + + c.setExitCodeIfIssuesFound(issues) + + c.fileCache.PrintStats(c.log) return nil } -func (e *Executor) printReports(ctx context.Context, issues []result.Issue, path, format string) error { - w, shouldClose, err := e.createWriter(path) - if err != nil { - return fmt.Errorf("can't create output for %s: %w", path, err) - } +// runAnalysis executes the linters that have been enabled in the configuration. +func (c *runCommand) runAnalysis(ctx context.Context, args []string) ([]result.Issue, error) { + c.cfg.Run.Args = args - p, err := e.createPrinter(format, w) + lintersToRun, err := c.dbManager.GetOptimizedLinters() if err != nil { - if file, ok := w.(io.Closer); shouldClose && ok { - _ = file.Close() - } - return err + return nil, err } - if err = p.Print(ctx, issues); err != nil { - if file, ok := w.(io.Closer); shouldClose && ok { - _ = file.Close() - } - return fmt.Errorf("can't print %d issues: %s", len(issues), err) + lintCtx, err := c.contextLoader.Load(ctx, c.log.Child(logutils.DebugKeyLintersContext), lintersToRun) + if err != nil { + return nil, fmt.Errorf("context loading failed: %w", err) } - if file, ok := w.(io.Closer); shouldClose && ok { - _ = file.Close() + runner, err := lint.NewRunner(c.log.Child(logutils.DebugKeyRunner), + c.cfg, c.goenv, c.lineCache, c.fileCache, c.dbManager, lintCtx) + if err != nil { + return nil, err } - return nil + return runner.Run(ctx, lintersToRun) } -func (e *Executor) createWriter(path string) (io.Writer, bool, error) { - if path == "" || path == "stdout" { - return logutils.StdOut, false, nil - } - if path == "stderr" { - return logutils.StdErr, false, nil - } - f, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, defaultFileMode) +func (c *runCommand) setOutputToDevNull() (savedStdout, savedStderr *os.File) { + savedStdout, savedStderr = os.Stdout, os.Stderr + devNull, err := os.Open(os.DevNull) if err != nil { - return nil, false, err + c.log.Warnf("Can't open null device %q: %s", os.DevNull, err) + return } - return f, true, nil + + os.Stdout, os.Stderr = devNull, devNull + return } -func (e *Executor) createPrinter(format string, w io.Writer) (printers.Printer, error) { - var p printers.Printer - switch format { - case config.OutFormatJSON: - p = printers.NewJSON(&e.reportData, w) - case config.OutFormatColoredLineNumber, config.OutFormatLineNumber: - p = printers.NewText(e.cfg.Output.PrintIssuedLine, - format == config.OutFormatColoredLineNumber, e.cfg.Output.PrintLinterName, - e.log.Child(logutils.DebugKeyTextPrinter), w) - case config.OutFormatTab: - p = printers.NewTab(e.cfg.Output.PrintLinterName, e.log.Child(logutils.DebugKeyTabPrinter), w) - case config.OutFormatCheckstyle: - p = printers.NewCheckstyle(w) - case config.OutFormatCodeClimate: - p = printers.NewCodeClimate(w) - case config.OutFormatHTML: - p = printers.NewHTML(w) - case config.OutFormatJunitXML: - p = printers.NewJunitXML(w) - case config.OutFormatGithubActions: - p = printers.NewGithub(w) - default: - return nil, fmt.Errorf("unknown output format %s", format) - } - - return p, nil +func (c *runCommand) setExitCodeIfIssuesFound(issues []result.Issue) { + if len(issues) != 0 { + c.exitCode = c.cfg.Run.ExitCodeIfIssuesFound + } } -// executeRun executes the 'run' CLI command, which runs the linters. -func (e *Executor) executeRun(_ *cobra.Command, args []string) { - needTrackResources := e.cfg.Run.IsVerbose || e.cfg.Run.PrintResourcesUsage - trackResourcesEndCh := make(chan struct{}) - defer func() { // XXX: this defer must be before ctx.cancel defer - if needTrackResources { // wait until resource tracking finished to print properly - <-trackResourcesEndCh +func (c *runCommand) printDeprecatedLinterMessages(enabledLinters map[string]*linter.Config) { + if c.cfg.InternalCmdTest { + return + } + + for name, lc := range enabledLinters { + if !lc.IsDeprecated() { + continue } - }() - e.setTimeoutToDeadlineIfOnlyDeadlineIsSet() - ctx, cancel := context.WithTimeout(context.Background(), e.cfg.Run.Timeout) - defer cancel() + var extra string + if lc.Deprecation.Replacement != "" { + extra = fmt.Sprintf("Replaced by %s.", lc.Deprecation.Replacement) + } - if needTrackResources { - go watchResources(ctx, trackResourcesEndCh, e.log, e.debugf) + c.log.Warnf("The linter '%s' is deprecated (since %s) due to: %s %s", name, lc.Deprecation.Since, lc.Deprecation.Message, extra) } +} - if err := e.runAndPrint(ctx, args); err != nil { - e.log.Errorf("Running error: %s", err) - if e.exitCode == exitcodes.Success { - if exitErr, ok := errors.Cause(err).(*exitcodes.ExitError); ok { - e.exitCode = exitErr.Code - } else { - e.exitCode = exitcodes.Failure - } - } +func (c *runCommand) printStats(issues []result.Issue) { + if c.cfg.Run.ShowStats { + c.log.Warnf("The configuration option `run.show-stats` is deprecated, please use `output.show-stats`") } - e.setupExitCode(ctx) -} + if !c.cfg.Run.ShowStats && !c.cfg.Output.ShowStats { + return + } + + if len(issues) == 0 { + c.cmd.Println("0 issues.") + return + } + + stats := map[string]int{} + for idx := range issues { + stats[issues[idx].FromLinter]++ + } + + c.cmd.Printf("%d issues:\n", len(issues)) + + keys := maps.Keys(stats) + sort.Strings(keys) -// to be removed when deadline is finally decommissioned -func (e *Executor) setTimeoutToDeadlineIfOnlyDeadlineIsSet() { - deadlineValue := e.cfg.Run.Deadline - if deadlineValue != 0 && e.cfg.Run.Timeout == defaultTimeout { - e.cfg.Run.Timeout = deadlineValue + for _, key := range keys { + c.cmd.Printf("* %s: %d\n", key, stats[key]) } } -func (e *Executor) setupExitCode(ctx context.Context) { +func (c *runCommand) setupExitCode(ctx context.Context) { if ctx.Err() != nil { - e.exitCode = exitcodes.Timeout - e.log.Errorf("Timeout exceeded: try increasing it by passing --timeout option") + c.exitCode = exitcodes.Timeout + c.log.Errorf("Timeout exceeded: try increasing it by passing --timeout option") return } - if e.exitCode != exitcodes.Success { + if c.exitCode != exitcodes.Success { return } needFailOnWarnings := os.Getenv(lintersdb.EnvTestRun) == "1" || os.Getenv(envFailOnWarnings) == "1" - if needFailOnWarnings && len(e.reportData.Warnings) != 0 { - e.exitCode = exitcodes.WarningInTest + if needFailOnWarnings && len(c.reportData.Warnings) != 0 { + c.exitCode = exitcodes.WarningInTest return } - if e.reportData.Error != "" { + if c.reportData.Error != "" { // it's a case e.g. when typecheck linter couldn't parse and error and just logged it - e.exitCode = exitcodes.ErrorWasLogged + c.exitCode = exitcodes.ErrorWasLogged return } } +func (c *runCommand) acquireFileLock() bool { + if c.cfg.Run.AllowParallelRunners { + c.debugf("Parallel runners are allowed, no locking") + return true + } + + lockFile := filepath.Join(os.TempDir(), "golangci-lint.lock") + c.debugf("Locking on file %s...", lockFile) + f := flock.New(lockFile) + const retryDelay = time.Second + + ctx := context.Background() + if !c.cfg.Run.AllowSerialRunners { + const totalTimeout = 5 * time.Second + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, totalTimeout) + defer cancel() + } + if ok, _ := f.TryLockContext(ctx, retryDelay); !ok { + return false + } + + c.flock = f + return true +} + +func (c *runCommand) releaseFileLock() { + if c.cfg.Run.AllowParallelRunners { + return + } + + if err := c.flock.Unlock(); err != nil { + c.debugf("Failed to unlock on file: %s", err) + } + if err := os.Remove(c.flock.Path()); err != nil { + c.debugf("Failed to remove lock file: %s", err) + } +} + func watchResources(ctx context.Context, done chan struct{}, logger logutils.Log, debugf logutils.DebugFunc) { startedAt := time.Now() debugf("Started tracking time") @@ -620,3 +572,141 @@ func watchResources(ctx context.Context, done chan struct{}, logger logutils.Log logger.Infof("Execution took %s", time.Since(startedAt)) close(done) } + +func setupConfigFileFlagSet(fs *pflag.FlagSet, cfg *config.LoaderOptions) { + fs.StringVarP(&cfg.Config, "config", "c", "", color.GreenString("Read config from file path `PATH`")) + fs.BoolVar(&cfg.NoConfig, "no-config", false, color.GreenString("Don't read config file")) +} + +func getDefaultIssueExcludeHelp() string { + parts := []string{color.GreenString("Use or not use default excludes:")} + for _, ep := range config.DefaultExcludePatterns { + parts = append(parts, + fmt.Sprintf(" # %s %s: %s", ep.ID, ep.Linter, ep.Why), + fmt.Sprintf(" - %s", color.YellowString(ep.Pattern)), + "", + ) + } + return strings.Join(parts, "\n") +} + +func getDefaultDirectoryExcludeHelp() string { + parts := []string{color.GreenString("Use or not use default excluded directories:")} + for _, dir := range packages.StdExcludeDirRegexps { + parts = append(parts, fmt.Sprintf(" - %s", color.YellowString(dir))) + } + parts = append(parts, "") + return strings.Join(parts, "\n") +} + +func setupRunPersistentFlags(fs *pflag.FlagSet, opts *runOptions) { + fs.BoolVar(&opts.PrintResourcesUsage, "print-resources-usage", false, + color.GreenString("Print avg and max memory usage of golangci-lint and total time")) + + fs.StringVar(&opts.CPUProfilePath, "cpu-profile-path", "", color.GreenString("Path to CPU profile output file")) + fs.StringVar(&opts.MemProfilePath, "mem-profile-path", "", color.GreenString("Path to memory profile output file")) + fs.StringVar(&opts.TracePath, "trace-path", "", color.GreenString("Path to trace output file")) +} + +func getDefaultConcurrency() int { + if os.Getenv(envHelpRun) == "1" { + // Make stable concurrency for generating help documentation. + const prettyConcurrency = 8 + return prettyConcurrency + } + + return runtime.NumCPU() +} + +func printMemStats(ms *runtime.MemStats, logger logutils.Log) { + logger.Infof("Mem stats: alloc=%s total_alloc=%s sys=%s "+ + "heap_alloc=%s heap_sys=%s heap_idle=%s heap_released=%s heap_in_use=%s "+ + "stack_in_use=%s stack_sys=%s "+ + "mspan_sys=%s mcache_sys=%s buck_hash_sys=%s gc_sys=%s other_sys=%s "+ + "mallocs_n=%d frees_n=%d heap_objects_n=%d gc_cpu_fraction=%.2f", + formatMemory(ms.Alloc), formatMemory(ms.TotalAlloc), formatMemory(ms.Sys), + formatMemory(ms.HeapAlloc), formatMemory(ms.HeapSys), + formatMemory(ms.HeapIdle), formatMemory(ms.HeapReleased), formatMemory(ms.HeapInuse), + formatMemory(ms.StackInuse), formatMemory(ms.StackSys), + formatMemory(ms.MSpanSys), formatMemory(ms.MCacheSys), formatMemory(ms.BuckHashSys), + formatMemory(ms.GCSys), formatMemory(ms.OtherSys), + ms.Mallocs, ms.Frees, ms.HeapObjects, ms.GCCPUFraction) +} + +func formatMemory(memBytes uint64) string { + const Kb = 1024 + const Mb = Kb * 1024 + + if memBytes < Kb { + return fmt.Sprintf("%db", memBytes) + } + if memBytes < Mb { + return fmt.Sprintf("%dkb", memBytes/Kb) + } + return fmt.Sprintf("%dmb", memBytes/Mb) +} + +// Related to cache. + +func initHashSalt(version string, cfg *config.Config) error { + binSalt, err := computeBinarySalt(version) + if err != nil { + return fmt.Errorf("failed to calculate binary salt: %w", err) + } + + configSalt, err := computeConfigSalt(cfg) + if err != nil { + return fmt.Errorf("failed to calculate config salt: %w", err) + } + + b := bytes.NewBuffer(binSalt) + b.Write(configSalt) + cache.SetSalt(b.Bytes()) + return nil +} + +func computeBinarySalt(version string) ([]byte, error) { + if version != "" && version != "(devel)" { + return []byte(version), nil + } + + if logutils.HaveDebugTag(logutils.DebugKeyBinSalt) { + return []byte("debug"), nil + } + + p, err := os.Executable() + if err != nil { + return nil, err + } + f, err := os.Open(p) + if err != nil { + return nil, err + } + defer f.Close() + h := sha256.New() + if _, err := io.Copy(h, f); err != nil { + return nil, err + } + return h.Sum(nil), nil +} + +// computeConfigSalt computes configuration hash. +// We don't hash all config fields to reduce meaningless cache invalidations. +// At least, it has a huge impact on tests speed. +// Fields: `LintersSettings` and `Run.BuildTags`. +func computeConfigSalt(cfg *config.Config) ([]byte, error) { + lintersSettingsBytes, err := yaml.Marshal(cfg.LintersSettings) + if err != nil { + return nil, fmt.Errorf("failed to json marshal config linter settings: %w", err) + } + + configData := bytes.NewBufferString("linters-settings=") + configData.Write(lintersSettingsBytes) + configData.WriteString("\nbuild-tags=%s" + strings.Join(cfg.Run.BuildTags, ",")) + + h := sha256.New() + if _, err := h.Write(configData.Bytes()); err != nil { + return nil, err + } + return h.Sum(nil), nil +} diff --git a/pkg/commands/version.go b/pkg/commands/version.go index 93e4a8ed90ec..a03e46e221c8 100644 --- a/pkg/commands/version.go +++ b/pkg/commands/version.go @@ -3,60 +3,96 @@ package commands import ( "encoding/json" "fmt" + "io" "os" + "runtime/debug" "strings" + "github.com/fatih/color" "github.com/spf13/cobra" - "github.com/spf13/pflag" - - "github.com/golangci/golangci-lint/pkg/config" ) -type jsonVersion struct { - Version string `json:"version"` - Commit string `json:"commit"` - Date string `json:"date"` +type BuildInfo struct { + GoVersion string `json:"goVersion"` + Version string `json:"version"` + Commit string `json:"commit"` + Date string `json:"date"` } -func (e *Executor) initVersionConfiguration(cmd *cobra.Command) { - fs := cmd.Flags() - fs.SortFlags = false // sort them as they are defined here - initVersionFlagSet(fs, e.cfg) +type versionInfo struct { + Info BuildInfo + BuildInfo *debug.BuildInfo +} + +type versionOptions struct { + Format string + Debug bool } -func initVersionFlagSet(fs *pflag.FlagSet, cfg *config.Config) { - // Version config - vc := &cfg.Version - fs.StringVar(&vc.Format, "format", "", wh("The version's format can be: 'short', 'json'")) +type versionCommand struct { + cmd *cobra.Command + opts versionOptions + + info BuildInfo } -func (e *Executor) initVersion() { +func newVersionCommand(info BuildInfo) *versionCommand { + c := &versionCommand{info: info} + versionCmd := &cobra.Command{ Use: "version", Short: "Version", Args: cobra.NoArgs, ValidArgsFunction: cobra.NoFileCompletions, - RunE: func(cmd *cobra.Command, _ []string) error { - switch strings.ToLower(e.cfg.Version.Format) { - case "short": - fmt.Println(e.version) - return nil - - case "json": - ver := jsonVersion{ - Version: e.version, - Commit: e.commit, - Date: e.date, - } - return json.NewEncoder(os.Stdout).Encode(&ver) - - default: - fmt.Printf("golangci-lint has version %s built from %s on %s\n", e.version, e.commit, e.date) - return nil - } - }, + RunE: c.execute, } - e.rootCmd.AddCommand(versionCmd) - e.initVersionConfiguration(versionCmd) + fs := versionCmd.Flags() + fs.SortFlags = false // sort them as they are defined here + + fs.StringVar(&c.opts.Format, "format", "", color.GreenString("The version's format can be: 'short', 'json'")) + fs.BoolVar(&c.opts.Debug, "debug", false, color.GreenString("Add build information")) + + c.cmd = versionCmd + + return c +} + +func (c *versionCommand) execute(_ *cobra.Command, _ []string) error { + if c.opts.Debug { + info, ok := debug.ReadBuildInfo() + if !ok { + return nil + } + + switch strings.ToLower(c.opts.Format) { + case "json": + return json.NewEncoder(os.Stdout).Encode(versionInfo{ + Info: c.info, + BuildInfo: info, + }) + + default: + fmt.Println(info.String()) + return printVersion(os.Stdout, c.info) + } + } + + switch strings.ToLower(c.opts.Format) { + case "short": + fmt.Println(c.info.Version) + return nil + + case "json": + return json.NewEncoder(os.Stdout).Encode(c.info) + + default: + return printVersion(os.Stdout, c.info) + } +} + +func printVersion(w io.Writer, info BuildInfo) error { + _, err := fmt.Fprintf(w, "golangci-lint has version %s built with %s from %s on %s\n", + info.Version, info.GoVersion, info.Commit, info.Date) + return err } diff --git a/pkg/config/config.go b/pkg/config/config.go index 9536c80cd0d5..386049da82f7 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -2,26 +2,27 @@ package config import ( "os" + "regexp" "strings" hcversion "github.com/hashicorp/go-version" "github.com/ldez/gomoddirectives" ) -// Config encapsulates the config data specified in the golangci yaml config file. +// Config encapsulates the config data specified in the golangci-lint yaml config file. type Config struct { - cfgDir string // The directory containing the golangci config file. - Run Run + cfgDir string // The directory containing the golangci-lint config file. - Output Output + Run Run `mapstructure:"run"` + + Output Output `mapstructure:"output"` LintersSettings LintersSettings `mapstructure:"linters-settings"` - Linters Linters - Issues Issues - Severity Severity - Version Version + Linters Linters `mapstructure:"linters"` + Issues Issues `mapstructure:"issues"` + Severity Severity `mapstructure:"severity"` - InternalCmdTest bool `mapstructure:"internal-cmd-test"` // Option is used only for testing golangci-lint command, don't use it + InternalCmdTest bool // Option is used only for testing golangci-lint command, don't use it InternalTest bool // Option is used only for testing golangci-lint code, don't use it } @@ -30,6 +31,24 @@ func (c *Config) GetConfigDir() string { return c.cfgDir } +func (c *Config) Validate() error { + validators := []func() error{ + c.Issues.Validate, + c.Severity.Validate, + c.LintersSettings.Validate, + c.Linters.Validate, + c.Output.Validate, + } + + for _, v := range validators { + if err := v(); err != nil { + return err + } + } + + return nil +} + func NewDefault() *Config { return &Config{ LintersSettings: defaultLintersSettings, @@ -38,23 +57,24 @@ func NewDefault() *Config { type Version struct { Format string `mapstructure:"format"` + Debug bool `mapstructure:"debug"` } -func IsGreaterThanOrEqualGo118(v string) bool { - v1, err := hcversion.NewVersion(strings.TrimPrefix(v, "go")) +func IsGoGreaterThanOrEqual(current, limit string) bool { + v1, err := hcversion.NewVersion(strings.TrimPrefix(current, "go")) if err != nil { return false } - limit, err := hcversion.NewVersion("1.18") + l, err := hcversion.NewVersion(limit) if err != nil { return false } - return v1.GreaterThanOrEqual(limit) + return v1.GreaterThanOrEqual(l) } -func DetectGoVersion() string { +func detectGoVersion() string { file, _ := gomoddirectives.GetModuleFile() if file != nil && file.Go != nil && file.Go.Version != "" { @@ -68,3 +88,22 @@ func DetectGoVersion() string { return "1.17" } + +// Trims the Go version to keep only M.m. +// Since Go 1.21 the version inside the go.mod can be a patched version (ex: 1.21.0). +// The version can also include information which we want to remove (ex: 1.21alpha1) +// https://go.dev/doc/toolchain#versions +// This a problem with staticcheck and gocritic. +func trimGoVersion(v string) string { + if v == "" { + return "" + } + + exp := regexp.MustCompile(`(\d\.\d+)(?:\.\d+|[a-z]+\d)`) + + if exp.MatchString(v) { + return exp.FindStringSubmatch(v)[1] + } + + return v +} diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go new file mode 100644 index 000000000000..0fe1855cc19e --- /dev/null +++ b/pkg/config/config_test.go @@ -0,0 +1,135 @@ +package config + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestIsGoGreaterThanOrEqual(t *testing.T) { + testCases := []struct { + desc string + current string + limit string + assert assert.BoolAssertionFunc + }{ + { + desc: "current (with minor.major) lower than limit", + current: "go1.21", + limit: "1.22", + assert: assert.False, + }, + { + desc: "current (with 0 patch) lower than limit", + current: "go1.21.0", + limit: "1.22", + assert: assert.False, + }, + { + desc: "current (current with multiple patches) lower than limit", + current: "go1.21.6", + limit: "1.22", + assert: assert.False, + }, + { + desc: "current lower than limit (with minor.major)", + current: "go1.22", + limit: "1.22", + assert: assert.True, + }, + { + desc: "current lower than limit (with 0 patch)", + current: "go1.22.0", + limit: "1.22", + assert: assert.True, + }, + { + desc: "current lower than limit (current with multiple patches)", + current: "go1.22.6", + limit: "1.22", + assert: assert.True, + }, + { + desc: "current greater than limit", + current: "go1.23.0", + limit: "1.22", + assert: assert.True, + }, + { + desc: "current with no prefix", + current: "1.22", + limit: "1.22", + assert: assert.True, + }, + { + desc: "invalid current value", + current: "go", + limit: "1.22", + assert: assert.False, + }, + { + desc: "invalid limit value", + current: "go1.22", + limit: "go", + assert: assert.False, + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + test.assert(t, IsGoGreaterThanOrEqual(test.current, test.limit)) + }) + } +} + +func Test_trimGoVersion(t *testing.T) { + testCases := []struct { + desc string + version string + expected string + }{ + { + desc: "patched version", + version: "1.22.0", + expected: "1.22", + }, + { + desc: "minor version", + version: "1.22", + expected: "1.22", + }, + { + desc: "RC version", + version: "1.22rc1", + expected: "1.22", + }, + { + desc: "alpha version", + version: "1.22alpha1", + expected: "1.22", + }, + { + desc: "beta version", + version: "1.22beta1", + expected: "1.22", + }, + { + desc: "semver RC version", + version: "1.22.0-rc1", + expected: "1.22", + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + version := trimGoVersion(test.version) + assert.Equal(t, test.expected, version) + }) + } +} diff --git a/pkg/config/issues.go b/pkg/config/issues.go index b2437ec97471..2ac29eacba99 100644 --- a/pkg/config/issues.go +++ b/pkg/config/issues.go @@ -1,6 +1,7 @@ package config import ( + "errors" "fmt" "regexp" ) @@ -54,7 +55,7 @@ var DefaultExcludePatterns = []ExcludePattern{ }, { ID: "EXC0008", - Pattern: "(G104|G307)", + Pattern: "(G104)", Linter: "gosec", Why: "Duplicated errcheck checks", }, @@ -108,6 +109,7 @@ type Issues struct { ExcludeCaseSensitive bool `mapstructure:"exclude-case-sensitive"` ExcludePatterns []string `mapstructure:"exclude"` ExcludeRules []ExcludeRule `mapstructure:"exclude-rules"` + ExcludeGeneratedStrict bool `mapstructure:"exclude-generated-strict"` UseDefaultExcludes bool `mapstructure:"exclude-use-default"` MaxIssuesPerLinter int `mapstructure:"max-issues-per-linter"` @@ -121,47 +123,77 @@ type Issues struct { NeedFix bool `mapstructure:"fix"` } +func (i *Issues) Validate() error { + for i, rule := range i.ExcludeRules { + if err := rule.Validate(); err != nil { + return fmt.Errorf("error in exclude rule #%d: %w", i, err) + } + } + + return nil +} + type ExcludeRule struct { BaseRule `mapstructure:",squash"` } -func (e ExcludeRule) Validate() error { +func (e *ExcludeRule) Validate() error { return e.BaseRule.Validate(excludeRuleMinConditionsCount) } type BaseRule struct { - Linters []string - Path string - Text string - Source string + Linters []string + Path string + PathExcept string `mapstructure:"path-except"` + Text string + Source string } -func (b BaseRule) Validate(minConditionsCount int) error { +func (b *BaseRule) Validate(minConditionsCount int) error { if err := validateOptionalRegex(b.Path); err != nil { - return fmt.Errorf("invalid path regex: %v", err) + return fmt.Errorf("invalid path regex: %w", err) + } + + if err := validateOptionalRegex(b.PathExcept); err != nil { + return fmt.Errorf("invalid path-except regex: %w", err) } + if err := validateOptionalRegex(b.Text); err != nil { - return fmt.Errorf("invalid text regex: %v", err) + return fmt.Errorf("invalid text regex: %w", err) } + if err := validateOptionalRegex(b.Source); err != nil { - return fmt.Errorf("invalid source regex: %v", err) + return fmt.Errorf("invalid source regex: %w", err) } + + if b.Path != "" && b.PathExcept != "" { + return errors.New("path and path-except should not be set at the same time") + } + nonBlank := 0 if len(b.Linters) > 0 { nonBlank++ } - if b.Path != "" { + + // Filtering by path counts as one condition, regardless how it is done (one or both). + // Otherwise, a rule with Path and PathExcept set would pass validation + // whereas before the introduction of path-except that wouldn't have been precise enough. + if b.Path != "" || b.PathExcept != "" { nonBlank++ } + if b.Text != "" { nonBlank++ } + if b.Source != "" { nonBlank++ } + if nonBlank < minConditionsCount { - return fmt.Errorf("at least %d of (text, source, path, linters) should be set", minConditionsCount) + return fmt.Errorf("at least %d of (text, source, path[-except], linters) should be set", minConditionsCount) } + return nil } @@ -169,6 +201,7 @@ func validateOptionalRegex(value string) error { if value == "" { return nil } + _, err := regexp.Compile(value) return err } diff --git a/pkg/config/issues_test.go b/pkg/config/issues_test.go index 208188bc810a..9d590ea85e57 100644 --- a/pkg/config/issues_test.go +++ b/pkg/config/issues_test.go @@ -1,36 +1,205 @@ package config import ( - "fmt" "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestGetExcludePatterns(t *testing.T) { - assert.Equal(t, GetExcludePatterns(nil), DefaultExcludePatterns) + patterns := GetExcludePatterns(nil) - include := make([]string, 2) - include[0], include[1] = DefaultExcludePatterns[0].ID, DefaultExcludePatterns[1].ID + assert.Equal(t, DefaultExcludePatterns, patterns) +} + +func TestGetExcludePatterns_includes(t *testing.T) { + include := []string{DefaultExcludePatterns[0].ID, DefaultExcludePatterns[1].ID} exclude := GetExcludePatterns(include) - assert.Equal(t, len(exclude), len(DefaultExcludePatterns)-len(include)) + assert.Len(t, exclude, len(DefaultExcludePatterns)-len(include)) for _, p := range exclude { - // Not in include. - for _, i := range include { - if i == p.ID { - t.Fatalf("%s can't appear inside include.", p.ID) - } - } - // Must in DefaultExcludePatterns. - var inDefaultExc bool - for _, i := range DefaultExcludePatterns { - if i == p { - inDefaultExc = true - break - } - } - assert.True(t, inDefaultExc, fmt.Sprintf("%s must appear inside DefaultExcludePatterns.", p.ID)) + assert.NotContains(t, include, p.ID) + assert.Contains(t, DefaultExcludePatterns, p) + } +} + +func TestExcludeRule_Validate(t *testing.T) { + testCases := []struct { + desc string + rule *ExcludeRule + expected string + }{ + { + desc: "empty rule", + rule: &ExcludeRule{}, + expected: "at least 2 of (text, source, path[-except], linters) should be set", + }, + { + desc: "only path rule", + rule: &ExcludeRule{ + BaseRule{ + Path: "test", + }, + }, + expected: "at least 2 of (text, source, path[-except], linters) should be set", + }, + { + desc: "only path-except rule", + rule: &ExcludeRule{ + BaseRule{ + PathExcept: "test", + }, + }, + expected: "at least 2 of (text, source, path[-except], linters) should be set", + }, + { + desc: "only text rule", + rule: &ExcludeRule{ + BaseRule{ + Text: "test", + }, + }, + expected: "at least 2 of (text, source, path[-except], linters) should be set", + }, + { + desc: "only source rule", + rule: &ExcludeRule{ + BaseRule{ + Source: "test", + }, + }, + expected: "at least 2 of (text, source, path[-except], linters) should be set", + }, + { + desc: "invalid path rule", + rule: &ExcludeRule{ + BaseRule{ + Path: "**test", + }, + }, + expected: "invalid path regex: error parsing regexp: missing argument to repetition operator: `*`", + }, + { + desc: "invalid path-except rule", + rule: &ExcludeRule{ + BaseRule{ + PathExcept: "**test", + }, + }, + expected: "invalid path-except regex: error parsing regexp: missing argument to repetition operator: `*`", + }, + { + desc: "invalid text rule", + rule: &ExcludeRule{ + BaseRule{ + Text: "**test", + }, + }, + expected: "invalid text regex: error parsing regexp: missing argument to repetition operator: `*`", + }, + { + desc: "invalid source rule", + rule: &ExcludeRule{ + BaseRule{ + Source: "**test", + }, + }, + expected: "invalid source regex: error parsing regexp: missing argument to repetition operator: `*`", + }, + { + desc: "path and path-expect", + rule: &ExcludeRule{ + BaseRule{ + Path: "test", + PathExcept: "test", + }, + }, + expected: "path and path-except should not be set at the same time", + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + err := test.rule.Validate() + require.EqualError(t, err, test.expected) + }) + } +} + +func TestExcludeRule_Validate_error(t *testing.T) { + testCases := []struct { + desc string + rule *ExcludeRule + }{ + { + desc: "path and linter", + rule: &ExcludeRule{ + BaseRule{ + Path: "test", + Linters: []string{"a"}, + }, + }, + }, + { + desc: "path-except and linter", + rule: &ExcludeRule{ + BaseRule{ + PathExcept: "test", + Linters: []string{"a"}, + }, + }, + }, + { + desc: "text and linter", + rule: &ExcludeRule{ + BaseRule{ + Text: "test", + Linters: []string{"a"}, + }, + }, + }, + { + desc: "source and linter", + rule: &ExcludeRule{ + BaseRule{ + Source: "test", + Linters: []string{"a"}, + }, + }, + }, + { + desc: "path and text", + rule: &ExcludeRule{ + BaseRule{ + Path: "test", + Text: "test", + }, + }, + }, + { + desc: "path and text and linter", + rule: &ExcludeRule{ + BaseRule{ + Path: "test", + Text: "test", + Linters: []string{"a"}, + }, + }, + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + err := test.rule.Validate() + require.NoError(t, err) + }) } } diff --git a/pkg/config/linters.go b/pkg/config/linters.go index ccbdc123a1b5..5c2628272c1f 100644 --- a/pkg/config/linters.go +++ b/pkg/config/linters.go @@ -1,5 +1,10 @@ package config +import ( + "errors" + "fmt" +) + type Linters struct { Enable []string Disable []string @@ -9,3 +14,52 @@ type Linters struct { Presets []string } + +func (l *Linters) Validate() error { + if err := l.validateAllDisableEnableOptions(); err != nil { + return err + } + + if err := l.validateDisabledAndEnabledAtOneMoment(); err != nil { + return err + } + + return nil +} + +func (l *Linters) validateAllDisableEnableOptions() error { + if l.EnableAll && l.DisableAll { + return errors.New("--enable-all and --disable-all options must not be combined") + } + + if l.DisableAll { + if len(l.Enable) == 0 && len(l.Presets) == 0 { + return errors.New("all linters were disabled, but no one linter was enabled: must enable at least one") + } + + if len(l.Disable) != 0 { + return errors.New("can't combine options --disable-all and --disable") + } + } + + if l.EnableAll && len(l.Enable) != 0 && !l.Fast { + return errors.New("can't combine options --enable-all and --enable") + } + + return nil +} + +func (l *Linters) validateDisabledAndEnabledAtOneMoment() error { + enabledLintersSet := map[string]bool{} + for _, name := range l.Enable { + enabledLintersSet[name] = true + } + + for _, name := range l.Disable { + if enabledLintersSet[name] { + return fmt.Errorf("linter %q can't be disabled and enabled at one moment", name) + } + } + + return nil +} diff --git a/pkg/config/linters_settings.go b/pkg/config/linters_settings.go index 76a16b87d610..484ce0cc0018 100644 --- a/pkg/config/linters_settings.go +++ b/pkg/config/linters_settings.go @@ -1,9 +1,12 @@ package config import ( + "encoding" + "errors" + "fmt" "runtime" - "github.com/pkg/errors" + "gopkg.in/yaml.v3" ) var defaultLintersSettings = LintersSettings{ @@ -19,10 +22,17 @@ var defaultLintersSettings = LintersSettings{ Dogsled: DogsledSettings{ MaxBlankIdentifiers: 2, }, + Dupl: DuplSettings{ + Threshold: 150, + }, + Errcheck: ErrcheckSettings{ + Ignore: "fmt:.*", + }, ErrorLint: ErrorLintSettings{ - Errorf: true, - Asserts: true, - Comparison: true, + Errorf: true, + ErrorfMulti: true, + Asserts: true, + Comparison: true, }, Exhaustive: ExhaustiveSettings{ Check: []string{"switch"}, @@ -43,9 +53,20 @@ var defaultLintersSettings = LintersSettings{ Gocognit: GocognitSettings{ MinComplexity: 30, }, + Goconst: GoConstSettings{ + MatchWithConstants: true, + MinStringLen: 3, + MinOccurrencesCount: 3, + NumberMin: 3, + NumberMax: 3, + IgnoreCalls: true, + }, Gocritic: GoCriticSettings{ SettingsPerCheck: map[string]GoCriticCheckSettings{}, }, + Gocyclo: GoCycloSettings{ + MinComplexity: 30, + }, Godox: GodoxSettings{ Keywords: []string{}, }, @@ -53,6 +74,9 @@ var defaultLintersSettings = LintersSettings{ Scope: "declarations", Period: true, }, + Gofmt: GoFmtSettings{ + Simplify: true, + }, Gofumpt: GofumptSettings{ LangVersion: "", ModulePath: "", @@ -61,9 +85,14 @@ var defaultLintersSettings = LintersSettings{ Gosec: GoSecSettings{ Concurrency: runtime.NumCPU(), }, - Ifshort: IfshortSettings{ - MaxDeclLines: 1, - MaxDeclChars: 30, + Gosmopolitan: GosmopolitanSettings{ + AllowTimeLocal: false, + EscapeHatches: []string{}, + IgnoreTests: true, + WatchForScripts: []string{"Han"}, + }, + Inamedparam: INamedParamSettings{ + SkipSingleParam: false, }, InterfaceBloat: InterfaceBloatSettings{ Max: 10, @@ -95,6 +124,13 @@ var defaultLintersSettings = LintersSettings{ RequireSpecific: false, AllowUnused: false, }, + PerfSprint: PerfSprintSettings{ + IntConversion: true, + ErrError: false, + ErrorF: true, + SprintF1: true, + StrConcat: true, + }, Prealloc: PreallocSettings{ Simple: true, RangeLoops: true, @@ -104,6 +140,22 @@ var defaultLintersSettings = LintersSettings{ Ignore: "", Qualified: false, }, + SlogLint: SlogLintSettings{ + NoMixedArgs: true, + KVOnly: false, + AttrOnly: false, + ContextOnly: false, + StaticMsg: false, + NoRawKeys: false, + KeyNamingCase: "", + ArgsOnSepLines: false, + }, + TagAlign: TagAlignSettings{ + Align: true, + Sort: true, + Order: nil, + Strict: false, + }, Testpackage: TestpackageSettings{ SkipRegexp: `(export|internal)_test\.go`, AllowPackages: []string{"main"}, @@ -111,6 +163,19 @@ var defaultLintersSettings = LintersSettings{ Unparam: UnparamSettings{ Algo: "cha", }, + Unused: UnusedSettings{ + FieldWritesAreUses: true, + PostStatementsAreReads: false, + ExportedIsUsed: true, + ExportedFieldsAreUsed: true, + ParametersAreUsed: true, + LocalVariablesAreUsed: true, + GeneratedIsUsed: true, + }, + UseStdlibVars: UseStdlibVarsSettings{ + HTTPMethod: true, + HTTPStatusCode: true, + }, Varnamelen: VarnamelenSettings{ MaxDistance: 5, MinNameLength: 3, @@ -133,85 +198,103 @@ var defaultLintersSettings = LintersSettings{ } type LintersSettings struct { - Asasalint AsasalintSettings - BiDiChk BiDiChkSettings - Cyclop Cyclop - Decorder DecorderSettings - Depguard DepGuardSettings - Dogsled DogsledSettings - Dupl DuplSettings - DupWord DupWordSettings - Errcheck ErrcheckSettings - ErrChkJSON ErrChkJSONSettings - ErrorLint ErrorLintSettings - Exhaustive ExhaustiveSettings - ExhaustiveStruct ExhaustiveStructSettings - Exhaustruct ExhaustructSettings - Forbidigo ForbidigoSettings - Funlen FunlenSettings - Gci GciSettings - GinkgoLinter GinkgoLinterSettings - Gocognit GocognitSettings - Goconst GoConstSettings - Gocritic GoCriticSettings - Gocyclo GoCycloSettings - Godot GodotSettings - Godox GodoxSettings - Gofmt GoFmtSettings - Gofumpt GofumptSettings - Goheader GoHeaderSettings - Goimports GoImportsSettings - Golint GoLintSettings - Gomnd GoMndSettings - GoModDirectives GoModDirectivesSettings - Gomodguard GoModGuardSettings - Gosec GoSecSettings - Gosimple StaticCheckSettings - Govet GovetSettings - Grouper GrouperSettings - Ifshort IfshortSettings - ImportAs ImportAsSettings - InterfaceBloat InterfaceBloatSettings - Ireturn IreturnSettings - Lll LllSettings - LoggerCheck LoggerCheckSettings - MaintIdx MaintIdxSettings - Makezero MakezeroSettings - Maligned MalignedSettings - Misspell MisspellSettings - MustTag MustTagSettings - Nakedret NakedretSettings - Nestif NestifSettings - NilNil NilNilSettings - Nlreturn NlreturnSettings - NoLintLint NoLintLintSettings - NoNamedReturns NoNamedReturnsSettings - ParallelTest ParallelTestSettings - Prealloc PreallocSettings - Predeclared PredeclaredSettings - Promlinter PromlinterSettings - Reassign ReassignSettings - Revive ReviveSettings - RowsErrCheck RowsErrCheckSettings - Staticcheck StaticCheckSettings - Structcheck StructCheckSettings - Stylecheck StaticCheckSettings - Tagliatelle TagliatelleSettings - Tenv TenvSettings - Testpackage TestpackageSettings - Thelper ThelperSettings - Unparam UnparamSettings - Unused StaticCheckSettings - UseStdlibVars UseStdlibVarsSettings - Varcheck VarCheckSettings - Varnamelen VarnamelenSettings - Whitespace WhitespaceSettings - Wrapcheck WrapcheckSettings - WSL WSLSettings + Asasalint AsasalintSettings + BiDiChk BiDiChkSettings + CopyLoopVar CopyLoopVarSettings + Cyclop Cyclop + Decorder DecorderSettings + Depguard DepGuardSettings + Dogsled DogsledSettings + Dupl DuplSettings + DupWord DupWordSettings + Errcheck ErrcheckSettings + ErrChkJSON ErrChkJSONSettings + ErrorLint ErrorLintSettings + Exhaustive ExhaustiveSettings + Exhaustruct ExhaustructSettings + Forbidigo ForbidigoSettings + Funlen FunlenSettings + Gci GciSettings + GinkgoLinter GinkgoLinterSettings + Gocognit GocognitSettings + Goconst GoConstSettings + Gocritic GoCriticSettings + Gocyclo GoCycloSettings + Godot GodotSettings + Godox GodoxSettings + Gofmt GoFmtSettings + Gofumpt GofumptSettings + Goheader GoHeaderSettings + Goimports GoImportsSettings + Gomnd GoMndSettings + GoModDirectives GoModDirectivesSettings + Gomodguard GoModGuardSettings + Gosec GoSecSettings + Gosimple StaticCheckSettings + Gosmopolitan GosmopolitanSettings + Govet GovetSettings + Grouper GrouperSettings + ImportAs ImportAsSettings + Inamedparam INamedParamSettings + InterfaceBloat InterfaceBloatSettings + Ireturn IreturnSettings + Lll LllSettings + LoggerCheck LoggerCheckSettings + MaintIdx MaintIdxSettings + Makezero MakezeroSettings + Misspell MisspellSettings + MustTag MustTagSettings + Nakedret NakedretSettings + Nestif NestifSettings + NilNil NilNilSettings + Nlreturn NlreturnSettings + NoLintLint NoLintLintSettings + NoNamedReturns NoNamedReturnsSettings + ParallelTest ParallelTestSettings + PerfSprint PerfSprintSettings + Prealloc PreallocSettings + Predeclared PredeclaredSettings + Promlinter PromlinterSettings + ProtoGetter ProtoGetterSettings + Reassign ReassignSettings + Revive ReviveSettings + RowsErrCheck RowsErrCheckSettings + SlogLint SlogLintSettings + Spancheck SpancheckSettings + Staticcheck StaticCheckSettings + Stylecheck StaticCheckSettings + TagAlign TagAlignSettings + Tagliatelle TagliatelleSettings + Tenv TenvSettings + Testifylint TestifylintSettings + Testpackage TestpackageSettings + Thelper ThelperSettings + Unconvert UnconvertSettings + Unparam UnparamSettings + Unused UnusedSettings + UseStdlibVars UseStdlibVarsSettings + Varnamelen VarnamelenSettings + Whitespace WhitespaceSettings + Wrapcheck WrapcheckSettings + WSL WSLSettings Custom map[string]CustomLinterSettings } +func (s *LintersSettings) Validate() error { + if err := s.Govet.Validate(); err != nil { + return err + } + + for name, settings := range s.Custom { + if err := settings.Validate(); err != nil { + return fmt.Errorf("custom linter %q: %w", name, err) + } + } + + return nil +} + type AsasalintSettings struct { Exclude []string `mapstructure:"exclude"` UseBuiltinExclusions bool `mapstructure:"use-builtin-exclusions"` @@ -230,6 +313,10 @@ type BiDiChkSettings struct { PopDirectionalIsolate bool `mapstructure:"pop-directional-isolate"` } +type CopyLoopVarSettings struct { + IgnoreAlias bool `mapstructure:"ignore-alias"` +} + type Cyclop struct { MaxComplexity int `mapstructure:"max-complexity"` PackageAverage float64 `mapstructure:"package-average"` @@ -237,17 +324,28 @@ type Cyclop struct { } type DepGuardSettings struct { - ListType string `mapstructure:"list-type"` - Packages []string - IncludeGoRoot bool `mapstructure:"include-go-root"` - PackagesWithErrorMessage map[string]string `mapstructure:"packages-with-error-message"` - IgnoreFileRules []string `mapstructure:"ignore-file-rules"` - AdditionalGuards []DepGuardSettings `mapstructure:"additional-guards"` + Rules map[string]*DepGuardList `mapstructure:"rules"` +} + +type DepGuardList struct { + ListMode string `mapstructure:"list-mode"` + Files []string `mapstructure:"files"` + Allow []string `mapstructure:"allow"` + Deny []DepGuardDeny `mapstructure:"deny"` +} + +type DepGuardDeny struct { + Pkg string `mapstructure:"pkg"` + Desc string `mapstructure:"desc"` } type DecorderSettings struct { DecOrder []string `mapstructure:"dec-order"` + IgnoreUnderscoreVars bool `mapstructure:"ignore-underscore-vars"` DisableDecNumCheck bool `mapstructure:"disable-dec-num-check"` + DisableTypeDecNumCheck bool `mapstructure:"disable-type-dec-num-check"` + DisableConstDecNumCheck bool `mapstructure:"disable-const-dec-num-check"` + DisableVarDecNumCheck bool `mapstructure:"disable-var-dec-num-check"` DisableDecOrderCheck bool `mapstructure:"disable-dec-order-check"` DisableInitFuncFirstCheck bool `mapstructure:"disable-init-func-first-check"` } @@ -262,6 +360,7 @@ type DuplSettings struct { type DupWordSettings struct { Keywords []string `mapstructure:"keywords"` + Ignore []string `mapstructure:"ignore"` } type ErrcheckSettings struct { @@ -281,9 +380,10 @@ type ErrChkJSONSettings struct { } type ErrorLintSettings struct { - Errorf bool `mapstructure:"errorf"` - Asserts bool `mapstructure:"asserts"` - Comparison bool `mapstructure:"comparison"` + Errorf bool `mapstructure:"errorf"` + ErrorfMulti bool `mapstructure:"errorf-multi"` + Asserts bool `mapstructure:"asserts"` + Comparison bool `mapstructure:"comparison"` } type ExhaustiveSettings struct { @@ -295,10 +395,7 @@ type ExhaustiveSettings struct { PackageScopeOnly bool `mapstructure:"package-scope-only"` ExplicitExhaustiveMap bool `mapstructure:"explicit-exhaustive-map"` ExplicitExhaustiveSwitch bool `mapstructure:"explicit-exhaustive-switch"` -} - -type ExhaustiveStructSettings struct { - StructPatterns []string `mapstructure:"struct-patterns"` + DefaultCaseRequired bool `mapstructure:"default-case-required"` } type ExhaustructSettings struct { @@ -307,13 +404,51 @@ type ExhaustructSettings struct { } type ForbidigoSettings struct { - Forbid []string `mapstructure:"forbid"` - ExcludeGodocExamples bool `mapstructure:"exclude-godoc-examples"` + Forbid []ForbidigoPattern `mapstructure:"forbid"` + ExcludeGodocExamples bool `mapstructure:"exclude-godoc-examples"` + AnalyzeTypes bool `mapstructure:"analyze-types"` +} + +var _ encoding.TextUnmarshaler = &ForbidigoPattern{} + +// ForbidigoPattern corresponds to forbidigo.pattern and adds mapstructure support. +// The YAML field names must match what forbidigo expects. +type ForbidigoPattern struct { + // patternString gets populated when the config contains a string as entry in ForbidigoSettings.Forbid[] + // because ForbidigoPattern implements encoding.TextUnmarshaler + // and the reader uses the mapstructure.TextUnmarshallerHookFunc as decoder hook. + // + // If the entry is a map, then the other fields are set as usual by mapstructure. + patternString string + + Pattern string `yaml:"p" mapstructure:"p"` + Package string `yaml:"pkg,omitempty" mapstructure:"pkg,omitempty"` + Msg string `yaml:"msg,omitempty" mapstructure:"msg,omitempty"` +} + +func (p *ForbidigoPattern) UnmarshalText(text []byte) error { + // Validation happens when instantiating forbidigo. + p.patternString = string(text) + return nil +} + +// MarshalString converts the pattern into a string as needed by forbidigo.NewLinter. +// +// MarshalString is intentionally not called MarshalText, +// although it has the same signature +// because implementing encoding.TextMarshaler led to infinite recursion when yaml.Marshal called MarshalText. +func (p *ForbidigoPattern) MarshalString() ([]byte, error) { + if p.patternString != "" { + return []byte(p.patternString), nil + } + + return yaml.Marshal(p) } type FunlenSettings struct { - Lines int - Statements int + Lines int + Statements int + IgnoreComments bool `mapstructure:"ignore-comments"` } type GciSettings struct { @@ -324,9 +459,14 @@ type GciSettings struct { } type GinkgoLinterSettings struct { - SuppressLenAssertion bool `mapstructure:"suppress-len-assertion"` - SuppressNilAssertion bool `mapstructure:"suppress-nil-assertion"` - SuppressErrAssertion bool `mapstructure:"suppress-err-assertion"` + SuppressLenAssertion bool `mapstructure:"suppress-len-assertion"` + SuppressNilAssertion bool `mapstructure:"suppress-nil-assertion"` + SuppressErrAssertion bool `mapstructure:"suppress-err-assertion"` + SuppressCompareAssertion bool `mapstructure:"suppress-compare-assertion"` + SuppressAsyncAssertion bool `mapstructure:"suppress-async-assertion"` + SuppressTypeCompareWarning bool `mapstructure:"suppress-type-compare-assertion"` + ForbidFocusContainer bool `mapstructure:"forbid-focus-container"` + AllowHaveLenZero bool `mapstructure:"allow-havelen-zero"` } type GocognitSettings struct { @@ -334,25 +474,29 @@ type GocognitSettings struct { } type GoConstSettings struct { - IgnoreTests bool `mapstructure:"ignore-tests"` - MatchWithConstants bool `mapstructure:"match-constant"` - MinStringLen int `mapstructure:"min-len"` - MinOccurrencesCount int `mapstructure:"min-occurrences"` - ParseNumbers bool `mapstructure:"numbers"` - NumberMin int `mapstructure:"min"` - NumberMax int `mapstructure:"max"` - IgnoreCalls bool `mapstructure:"ignore-calls"` + IgnoreStrings string `mapstructure:"ignore-strings"` + IgnoreTests bool `mapstructure:"ignore-tests"` + MatchWithConstants bool `mapstructure:"match-constant"` + MinStringLen int `mapstructure:"min-len"` + MinOccurrencesCount int `mapstructure:"min-occurrences"` + ParseNumbers bool `mapstructure:"numbers"` + NumberMin int `mapstructure:"min"` + NumberMax int `mapstructure:"max"` + IgnoreCalls bool `mapstructure:"ignore-calls"` } type GoCriticSettings struct { + Go string `mapstructure:"-"` + DisableAll bool `mapstructure:"disable-all"` EnabledChecks []string `mapstructure:"enabled-checks"` + EnableAll bool `mapstructure:"enable-all"` DisabledChecks []string `mapstructure:"disabled-checks"` EnabledTags []string `mapstructure:"enabled-tags"` DisabledTags []string `mapstructure:"disabled-tags"` SettingsPerCheck map[string]GoCriticCheckSettings `mapstructure:"settings"` } -type GoCriticCheckSettings map[string]interface{} +type GoCriticCheckSettings map[string]any type GoCycloSettings struct { MinComplexity int `mapstructure:"min-complexity"` @@ -400,16 +544,12 @@ type GoImportsSettings struct { LocalPrefixes string `mapstructure:"local-prefixes"` } -type GoLintSettings struct { - MinConfidence float64 `mapstructure:"min-confidence"` -} - type GoMndSettings struct { - Settings map[string]map[string]interface{} // Deprecated - Checks []string `mapstructure:"checks"` - IgnoredNumbers []string `mapstructure:"ignored-numbers"` - IgnoredFiles []string `mapstructure:"ignored-files"` - IgnoredFunctions []string `mapstructure:"ignored-functions"` + Settings map[string]map[string]any // Deprecated + Checks []string `mapstructure:"checks"` + IgnoredNumbers []string `mapstructure:"ignored-numbers"` + IgnoredFiles []string `mapstructure:"ignored-files"` + IgnoredFunctions []string `mapstructure:"ignored-functions"` } type GoModDirectivesSettings struct { @@ -438,19 +578,26 @@ type GoModGuardSettings struct { } type GoSecSettings struct { - Includes []string `mapstructure:"includes"` - Excludes []string `mapstructure:"excludes"` - Severity string `mapstructure:"severity"` - Confidence string `mapstructure:"confidence"` - ExcludeGenerated bool `mapstructure:"exclude-generated"` - Config map[string]interface{} `mapstructure:"config"` - Concurrency int `mapstructure:"concurrency"` + Includes []string `mapstructure:"includes"` + Excludes []string `mapstructure:"excludes"` + Severity string `mapstructure:"severity"` + Confidence string `mapstructure:"confidence"` + ExcludeGenerated bool `mapstructure:"exclude-generated"` + Config map[string]any `mapstructure:"config"` + Concurrency int `mapstructure:"concurrency"` +} + +type GosmopolitanSettings struct { + AllowTimeLocal bool `mapstructure:"allow-time-local"` + EscapeHatches []string `mapstructure:"escape-hatches"` + IgnoreTests bool `mapstructure:"ignore-tests"` + WatchForScripts []string `mapstructure:"watch-for-scripts"` } type GovetSettings struct { Go string `mapstructure:"-"` CheckShadowing bool `mapstructure:"check-shadowing"` - Settings map[string]map[string]interface{} + Settings map[string]map[string]any Enable []string Disable []string @@ -460,13 +607,13 @@ type GovetSettings struct { func (cfg *GovetSettings) Validate() error { if cfg.EnableAll && cfg.DisableAll { - return errors.New("enable-all and disable-all can't be combined") + return errors.New("govet: enable-all and disable-all can't be combined") } if cfg.EnableAll && len(cfg.Enable) != 0 { - return errors.New("enable-all and enable can't be combined") + return errors.New("govet: enable-all and enable can't be combined") } if cfg.DisableAll && len(cfg.Disable) != 0 { - return errors.New("disable-all and disable can't be combined") + return errors.New("govet: disable-all and disable can't be combined") } return nil } @@ -482,11 +629,6 @@ type GrouperSettings struct { VarRequireGrouping bool `mapstructure:"var-require-grouping"` } -type IfshortSettings struct { - MaxDeclLines int `mapstructure:"max-decl-lines"` - MaxDeclChars int `mapstructure:"max-decl-chars"` -} - type ImportAsSettings struct { Alias []ImportAsAlias NoUnaliased bool `mapstructure:"no-unaliased"` @@ -498,6 +640,10 @@ type ImportAsAlias struct { Alias string } +type INamedParamSettings struct { + SkipSingleParam bool `mapstructure:"skip-single-param"` +} + type InterfaceBloatSettings struct { Max int `mapstructure:"max"` } @@ -530,15 +676,19 @@ type MakezeroSettings struct { Always bool } -type MalignedSettings struct { - SuggestNewOrder bool `mapstructure:"suggest-new"` -} - type MisspellSettings struct { - Locale string + Mode string `mapstructure:"mode"` + Locale string `mapstructure:"locale"` + ExtraWords []MisspellExtraWords `mapstructure:"extra-words"` + // TODO(ldez): v2 the option must be renamed to `IgnoredRules`. IgnoreWords []string `mapstructure:"ignore-words"` } +type MisspellExtraWords struct { + Typo string `mapstructure:"typo"` + Correction string `mapstructure:"correction"` +} + type MustTagSettings struct { Functions []struct { Name string `mapstructure:"name"` @@ -573,8 +723,19 @@ type NoLintLintSettings struct { type NoNamedReturnsSettings struct { ReportErrorInDefer bool `mapstructure:"report-error-in-defer"` } + type ParallelTestSettings struct { - IgnoreMissing bool `mapstructure:"ignore-missing"` + Go string `mapstructure:"-"` + IgnoreMissing bool `mapstructure:"ignore-missing"` + IgnoreMissingSubtests bool `mapstructure:"ignore-missing-subtests"` +} + +type PerfSprintSettings struct { + IntConversion bool `mapstructure:"int-conversion"` + ErrError bool `mapstructure:"err-error"` + ErrorF bool `mapstructure:"errorf"` + SprintF1 bool `mapstructure:"sprintf1"` + StrConcat bool `mapstructure:"strconcat"` } type PreallocSettings struct { @@ -593,6 +754,13 @@ type PromlinterSettings struct { DisabledLinters []string `mapstructure:"disabled-linters"` } +type ProtoGetterSettings struct { + SkipGeneratedBy []string `mapstructure:"skip-generated-by"` + SkipFiles []string `mapstructure:"skip-files"` + SkipAnyGenerated bool `mapstructure:"skip-any-generated"` + ReplaceFirstArgInAppend bool `mapstructure:"replace-first-arg-in-append"` +} + type ReassignSettings struct { Patterns []string `mapstructure:"patterns"` } @@ -605,9 +773,10 @@ type ReviveSettings struct { EnableAllRules bool `mapstructure:"enable-all-rules"` Rules []struct { Name string - Arguments []interface{} + Arguments []any Severity string Disabled bool + Exclude []string } ErrorCode int `mapstructure:"error-code"` WarningCode int `mapstructure:"warning-code"` @@ -621,6 +790,22 @@ type RowsErrCheckSettings struct { Packages []string } +type SlogLintSettings struct { + NoMixedArgs bool `mapstructure:"no-mixed-args"` + KVOnly bool `mapstructure:"kv-only"` + AttrOnly bool `mapstructure:"attr-only"` + ContextOnly bool `mapstructure:"context-only"` + StaticMsg bool `mapstructure:"static-msg"` + NoRawKeys bool `mapstructure:"no-raw-keys"` + KeyNamingCase string `mapstructure:"key-naming-case"` + ArgsOnSepLines bool `mapstructure:"args-on-sep-lines"` +} + +type SpancheckSettings struct { + Checks []string `mapstructure:"checks"` + IgnoreCheckSignatures []string `mapstructure:"ignore-check-signatures"` +} + type StaticCheckSettings struct { // Deprecated: use the global `run.go` instead. GoVersion string `mapstructure:"go"` @@ -635,8 +820,11 @@ func (s *StaticCheckSettings) HasConfiguration() bool { return len(s.Initialisms) > 0 || len(s.HTTPStatusCodeWhitelist) > 0 || len(s.DotImportWhitelist) > 0 || len(s.Checks) > 0 } -type StructCheckSettings struct { - CheckExportedFields bool `mapstructure:"exported-fields"` +type TagAlignSettings struct { + Align bool `mapstructure:"align"` + Sort bool `mapstructure:"sort"` + Order []string `mapstructure:"order"` + Strict bool `mapstructure:"strict"` } type TagliatelleSettings struct { @@ -646,6 +834,29 @@ type TagliatelleSettings struct { } } +type TestifylintSettings struct { + EnableAll bool `mapstructure:"enable-all"` + DisableAll bool `mapstructure:"disable-all"` + EnabledCheckers []string `mapstructure:"enable"` + DisabledCheckers []string `mapstructure:"disable"` + + BoolCompare struct { + IgnoreCustomTypes bool `mapstructure:"ignore-custom-types"` + } `mapstructure:"bool-compare"` + + ExpectedActual struct { + ExpVarPattern string `mapstructure:"pattern"` + } `mapstructure:"expected-actual"` + + RequireError struct { + FnPattern string `mapstructure:"fn-pattern"` + } `mapstructure:"require-error"` + + SuiteExtraAssertCall struct { + Mode string `mapstructure:"mode"` + } `mapstructure:"suite-extra-assert-call"` +} + type TestpackageSettings struct { SkipRegexp string `mapstructure:"skip-regexp"` AllowPackages []string `mapstructure:"allow-packages"` @@ -683,13 +894,24 @@ type UseStdlibVarsSettings struct { SyslogPriority bool `mapstructure:"syslog-priority"` } +type UnconvertSettings struct { + FastMath bool `mapstructure:"fast-math"` + Safe bool `mapstructure:"safe"` +} + type UnparamSettings struct { CheckExported bool `mapstructure:"check-exported"` Algo string } -type VarCheckSettings struct { - CheckExportedFields bool `mapstructure:"exported-fields"` +type UnusedSettings struct { + FieldWritesAreUses bool `mapstructure:"field-writes-are-uses"` + PostStatementsAreReads bool `mapstructure:"post-statements-are-reads"` + ExportedIsUsed bool `mapstructure:"exported-is-used"` + ExportedFieldsAreUsed bool `mapstructure:"exported-fields-are-used"` + ParametersAreUsed bool `mapstructure:"parameters-are-used"` + LocalVariablesAreUsed bool `mapstructure:"local-variables-are-used"` + GeneratedIsUsed bool `mapstructure:"generated-is-used"` } type VarnamelenSettings struct { @@ -735,19 +957,36 @@ type WSLSettings struct { } // CustomLinterSettings encapsulates the meta-data of a private linter. -// For example, a private linter may be added to the golangci config file as shown below. -// -// linters-settings: -// custom: -// example: -// path: /example.so -// description: The description of the linter -// original-url: github.com/golangci/example-linter type CustomLinterSettings struct { + // Type plugin type. + // It can be `goplugin` or `module`. + Type string `mapstructure:"type"` + // Path to a plugin *.so file that implements the private linter. + // Only for Go plugin system. Path string + // Description describes the purpose of the private linter. Description string - // The URL containing the source code for the private linter. + // OriginalURL The URL containing the source code for the private linter. OriginalURL string `mapstructure:"original-url"` + + // Settings plugin settings only work with linterdb.PluginConstructor symbol. + Settings any +} + +func (s *CustomLinterSettings) Validate() error { + if s.Type == "module" { + if s.Path != "" { + return errors.New("path not supported with module type") + } + + return nil + } + + if s.Path == "" { + return errors.New("path is required") + } + + return nil } diff --git a/pkg/config/linters_settings_test.go b/pkg/config/linters_settings_test.go new file mode 100644 index 000000000000..1fd77d2e2215 --- /dev/null +++ b/pkg/config/linters_settings_test.go @@ -0,0 +1,236 @@ +package config + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestLintersSettings_Validate(t *testing.T) { + testCases := []struct { + desc string + settings *LintersSettings + }{ + { + desc: "custom linter", + settings: &LintersSettings{ + Custom: map[string]CustomLinterSettings{ + "example": { + Type: "module", + }, + }, + }, + }, + { + desc: "govet", + settings: &LintersSettings{ + Govet: GovetSettings{ + Enable: []string{"a"}, + DisableAll: true, + }, + }, + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + err := test.settings.Validate() + assert.NoError(t, err) + }) + } +} + +func TestLintersSettings_Validate_error(t *testing.T) { + testCases := []struct { + desc string + settings *LintersSettings + expected string + }{ + { + desc: "custom linter error", + settings: &LintersSettings{ + Custom: map[string]CustomLinterSettings{ + "example": { + Type: "module", + Path: "example", + }, + }, + }, + expected: `custom linter "example": path not supported with module type`, + }, + { + desc: "govet error", + settings: &LintersSettings{ + Govet: GovetSettings{ + EnableAll: true, + DisableAll: true, + }, + }, + expected: "govet: enable-all and disable-all can't be combined", + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + err := test.settings.Validate() + + assert.EqualError(t, err, test.expected) + }) + } +} + +func TestCustomLinterSettings_Validate(t *testing.T) { + testCases := []struct { + desc string + settings *CustomLinterSettings + }{ + { + desc: "only path", + settings: &CustomLinterSettings{ + Path: "example", + }, + }, + { + desc: "path and type goplugin", + settings: &CustomLinterSettings{ + Type: "goplugin", + Path: "example", + }, + }, + { + desc: "type module", + settings: &CustomLinterSettings{ + Type: "module", + }, + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + err := test.settings.Validate() + assert.NoError(t, err) + }) + } +} + +func TestCustomLinterSettings_Validate_error(t *testing.T) { + testCases := []struct { + desc string + settings *CustomLinterSettings + expected string + }{ + { + desc: "missing path", + settings: &CustomLinterSettings{}, + expected: "path is required", + }, + { + desc: "module and path", + settings: &CustomLinterSettings{ + Type: "module", + Path: "example", + }, + expected: "path not supported with module type", + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + err := test.settings.Validate() + + assert.EqualError(t, err, test.expected) + }) + } +} + +func TestGovetSettings_Validate(t *testing.T) { + testCases := []struct { + desc string + settings *GovetSettings + }{ + { + desc: "empty", + settings: &GovetSettings{}, + }, + { + desc: "disable-all and enable", + settings: &GovetSettings{ + Enable: []string{"a"}, + DisableAll: true, + }, + }, + { + desc: "enable-all and disable", + settings: &GovetSettings{ + Disable: []string{"a"}, + EnableAll: true, + }, + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + err := test.settings.Validate() + assert.NoError(t, err) + }) + } +} + +func TestGovetSettings_Validate_error(t *testing.T) { + testCases := []struct { + desc string + settings *GovetSettings + expected string + }{ + { + desc: "enable-all and disable-all", + settings: &GovetSettings{ + EnableAll: true, + DisableAll: true, + }, + expected: "govet: enable-all and disable-all can't be combined", + }, + { + desc: "enable-all and enable", + settings: &GovetSettings{ + EnableAll: true, + Enable: []string{"a"}, + }, + expected: "govet: enable-all and enable can't be combined", + }, + { + desc: "disable-all and disable", + settings: &GovetSettings{ + DisableAll: true, + Disable: []string{"a"}, + }, + expected: "govet: disable-all and disable can't be combined", + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + err := test.settings.Validate() + + assert.EqualError(t, err, test.expected) + }) + } +} diff --git a/pkg/config/linters_test.go b/pkg/config/linters_test.go new file mode 100644 index 000000000000..5be75600541f --- /dev/null +++ b/pkg/config/linters_test.go @@ -0,0 +1,214 @@ +package config + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestLinters_validateDisabledAndEnabledAtOneMoment(t *testing.T) { + testCases := []struct { + desc string + cfg *Linters + }{ + { + desc: "2 different sets", + cfg: &Linters{ + Enable: []string{"dupl", "gofmt", "misspell"}, + Disable: []string{"goimports", "gosec", "nolintlint"}, + }, + }, + { + desc: "only enable", + cfg: &Linters{ + Enable: []string{"goimports", "gosec", "nolintlint"}, + Disable: nil, + }, + }, + { + desc: "only disable", + cfg: &Linters{ + Enable: nil, + Disable: []string{"dupl", "gofmt", "misspell"}, + }, + }, + { + desc: "no sets", + cfg: &Linters{ + Enable: nil, + Disable: nil, + }, + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + err := test.cfg.validateDisabledAndEnabledAtOneMoment() + require.NoError(t, err) + }) + } +} + +func TestLinters_validateDisabledAndEnabledAtOneMoment_error(t *testing.T) { + testCases := []struct { + desc string + cfg *Linters + expected string + }{ + { + desc: "disable one linter of the enabled linters", + cfg: &Linters{ + Enable: []string{"dupl", "gofmt", "misspell"}, + Disable: []string{"dupl", "gosec", "nolintlint"}, + }, + expected: `linter "dupl" can't be disabled and enabled at one moment`, + }, + { + desc: "disable multiple enabled linters", + cfg: &Linters{ + Enable: []string{"dupl", "gofmt", "misspell"}, + Disable: []string{"dupl", "gofmt", "misspell"}, + }, + expected: `linter "dupl" can't be disabled and enabled at one moment`, + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + err := test.cfg.validateDisabledAndEnabledAtOneMoment() + require.Error(t, err) + + require.EqualError(t, err, test.expected) + }) + } +} + +func TestLinters_validateAllDisableEnableOptions(t *testing.T) { + testCases := []struct { + desc string + cfg *Linters + }{ + { + desc: "nothing", + cfg: &Linters{}, + }, + { + desc: "enable and disable", + cfg: &Linters{ + Enable: []string{"goimports", "gosec", "nolintlint"}, + EnableAll: false, + Disable: []string{"dupl", "gofmt", "misspell"}, + DisableAll: false, + }, + }, + { + desc: "disable-all and enable", + cfg: &Linters{ + Enable: []string{"goimports", "gosec", "nolintlint"}, + EnableAll: false, + Disable: nil, + DisableAll: true, + }, + }, + { + desc: "enable-all and disable", + cfg: &Linters{ + Enable: nil, + EnableAll: true, + Disable: []string{"goimports", "gosec", "nolintlint"}, + DisableAll: false, + }, + }, + { + desc: "enable-all and enable and fast", + cfg: &Linters{ + Enable: []string{"dupl", "gofmt", "misspell"}, + EnableAll: true, + Disable: nil, + DisableAll: false, + Fast: true, + }, + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + err := test.cfg.validateAllDisableEnableOptions() + require.NoError(t, err) + }) + } +} + +func TestLinters_validateAllDisableEnableOptions_error(t *testing.T) { + testCases := []struct { + desc string + cfg *Linters + expected string + }{ + { + desc: "enable-all and disable-all", + cfg: &Linters{ + Enable: nil, + EnableAll: true, + Disable: nil, + DisableAll: true, + Fast: false, + }, + expected: "--enable-all and --disable-all options must not be combined", + }, + { + desc: "disable-all and disable no enable no preset", + cfg: &Linters{ + Enable: nil, + EnableAll: false, + Disable: []string{"dupl", "gofmt", "misspell"}, + DisableAll: true, + Fast: false, + }, + expected: "all linters were disabled, but no one linter was enabled: must enable at least one", + }, + { + desc: "disable-all and disable with enable", + cfg: &Linters{ + Enable: []string{"nolintlint"}, + EnableAll: false, + Disable: []string{"dupl", "gofmt", "misspell"}, + DisableAll: true, + Fast: false, + }, + expected: "can't combine options --disable-all and --disable", + }, + { + desc: "enable-all and enable", + cfg: &Linters{ + Enable: []string{"dupl", "gofmt", "misspell"}, + EnableAll: true, + Disable: nil, + DisableAll: false, + Fast: false, + }, + expected: "can't combine options --enable-all and --enable", + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + err := test.cfg.validateAllDisableEnableOptions() + require.Error(t, err) + + require.EqualError(t, err, test.expected) + }) + } +} diff --git a/pkg/config/loader.go b/pkg/config/loader.go new file mode 100644 index 000000000000..0cad5f0c2a80 --- /dev/null +++ b/pkg/config/loader.go @@ -0,0 +1,327 @@ +package config + +import ( + "errors" + "fmt" + "os" + "path/filepath" + "slices" + "strings" + + "github.com/go-viper/mapstructure/v2" + "github.com/mitchellh/go-homedir" + "github.com/spf13/pflag" + "github.com/spf13/viper" + + "github.com/golangci/golangci-lint/pkg/exitcodes" + "github.com/golangci/golangci-lint/pkg/fsutils" + "github.com/golangci/golangci-lint/pkg/logutils" +) + +var errConfigDisabled = errors.New("config is disabled by --no-config") + +type LoaderOptions struct { + Config string // Flag only. The path to the golangci config file, as specified with the --config argument. + NoConfig bool // Flag only. +} + +type Loader struct { + opts LoaderOptions + + viper *viper.Viper + fs *pflag.FlagSet + + log logutils.Log + + cfg *Config +} + +func NewLoader(log logutils.Log, v *viper.Viper, fs *pflag.FlagSet, opts LoaderOptions, cfg *Config) *Loader { + return &Loader{ + opts: opts, + viper: v, + fs: fs, + log: log, + cfg: cfg, + } +} + +func (l *Loader) Load() error { + err := l.setConfigFile() + if err != nil { + return err + } + + err = l.parseConfig() + if err != nil { + return err + } + + l.applyStringSliceHack() + + l.handleGoVersion() + + err = l.handleEnableOnlyOption() + if err != nil { + return err + } + + return nil +} + +func (l *Loader) handleEnableOnlyOption() error { + only, err := l.fs.GetStringSlice("enable-only") + if err != nil { + return err + } + + if len(only) > 0 { + l.cfg.Linters = Linters{ + Enable: only, + DisableAll: true, + } + } + + return nil +} + +func (l *Loader) handleGoVersion() { + if l.cfg.Run.Go == "" { + l.cfg.Run.Go = detectGoVersion() + } + + l.cfg.LintersSettings.Govet.Go = l.cfg.Run.Go + + l.cfg.LintersSettings.ParallelTest.Go = l.cfg.Run.Go + + if l.cfg.LintersSettings.Gofumpt.LangVersion == "" { + l.cfg.LintersSettings.Gofumpt.LangVersion = l.cfg.Run.Go + } + + trimmedGoVersion := trimGoVersion(l.cfg.Run.Go) + + l.cfg.LintersSettings.Gocritic.Go = trimmedGoVersion + + // staticcheck related linters. + if l.cfg.LintersSettings.Staticcheck.GoVersion == "" { + l.cfg.LintersSettings.Staticcheck.GoVersion = trimmedGoVersion + } + if l.cfg.LintersSettings.Gosimple.GoVersion == "" { + l.cfg.LintersSettings.Gosimple.GoVersion = trimmedGoVersion + } + if l.cfg.LintersSettings.Stylecheck.GoVersion != "" { + l.cfg.LintersSettings.Stylecheck.GoVersion = trimmedGoVersion + } +} + +func (l *Loader) setConfigFile() error { + configFile, err := l.evaluateOptions() + if err != nil { + if errors.Is(err, errConfigDisabled) { + return nil + } + + return fmt.Errorf("can't parse --config option: %w", err) + } + + if configFile != "" { + l.viper.SetConfigFile(configFile) + + // Assume YAML if the file has no extension. + if filepath.Ext(configFile) == "" { + l.viper.SetConfigType("yaml") + } + } else { + l.setupConfigFileSearch() + } + + return nil +} + +func (l *Loader) evaluateOptions() (string, error) { + if l.opts.NoConfig && l.opts.Config != "" { + return "", errors.New("can't combine option --config and --no-config") + } + + if l.opts.NoConfig { + return "", errConfigDisabled + } + + configFile, err := homedir.Expand(l.opts.Config) + if err != nil { + return "", errors.New("failed to expand configuration path") + } + + return configFile, nil +} + +func (l *Loader) setupConfigFileSearch() { + firstArg := extractFirstPathArg() + + absStartPath, err := filepath.Abs(firstArg) + if err != nil { + l.log.Warnf("Can't make abs path for %q: %s", firstArg, err) + absStartPath = filepath.Clean(firstArg) + } + + // start from it + var curDir string + if fsutils.IsDir(absStartPath) { + curDir = absStartPath + } else { + curDir = filepath.Dir(absStartPath) + } + + // find all dirs from it up to the root + configSearchPaths := []string{"./"} + + for { + configSearchPaths = append(configSearchPaths, curDir) + + newCurDir := filepath.Dir(curDir) + if curDir == newCurDir || newCurDir == "" { + break + } + + curDir = newCurDir + } + + // find home directory for global config + if home, err := homedir.Dir(); err != nil { + l.log.Warnf("Can't get user's home directory: %s", err.Error()) + } else if !slices.Contains(configSearchPaths, home) { + configSearchPaths = append(configSearchPaths, home) + } + + l.log.Infof("Config search paths: %s", configSearchPaths) + + l.viper.SetConfigName(".golangci") + + for _, p := range configSearchPaths { + l.viper.AddConfigPath(p) + } +} + +func (l *Loader) parseConfig() error { + if err := l.viper.ReadInConfig(); err != nil { + var configFileNotFoundError viper.ConfigFileNotFoundError + if errors.As(err, &configFileNotFoundError) { + // Load configuration from flags only. + err = l.viper.Unmarshal(l.cfg) + if err != nil { + return fmt.Errorf("can't unmarshal config by viper (flags): %w", err) + } + + return nil + } + + return fmt.Errorf("can't read viper config: %w", err) + } + + err := l.setConfigDir() + if err != nil { + return err + } + + // Load configuration from all sources (flags, file). + if err := l.viper.Unmarshal(l.cfg, fileDecoderHook()); err != nil { + return fmt.Errorf("can't unmarshal config by viper (flags, file): %w", err) + } + + if l.cfg.InternalTest { // just for testing purposes: to detect config file usage + _, _ = fmt.Fprintln(logutils.StdOut, "test") + os.Exit(exitcodes.Success) + } + + return nil +} + +func (l *Loader) setConfigDir() error { + usedConfigFile := l.viper.ConfigFileUsed() + if usedConfigFile == "" { + return nil + } + + if usedConfigFile == os.Stdin.Name() { + usedConfigFile = "" + l.log.Infof("Reading config file stdin") + } else { + var err error + usedConfigFile, err = fsutils.ShortestRelPath(usedConfigFile, "") + if err != nil { + l.log.Warnf("Can't pretty print config file path: %v", err) + } + + l.log.Infof("Used config file %s", usedConfigFile) + } + + usedConfigDir, err := filepath.Abs(filepath.Dir(usedConfigFile)) + if err != nil { + return errors.New("can't get config directory") + } + + l.cfg.cfgDir = usedConfigDir + + return nil +} + +// Hack to append values from StringSlice flags. +// Viper always overrides StringSlice values. +// https://github.com/spf13/viper/issues/1448 +// So StringSlice flags are not bind to Viper like that their values are obtain via Cobra Flags. +func (l *Loader) applyStringSliceHack() { + if l.fs == nil { + return + } + + l.appendStringSlice("enable", &l.cfg.Linters.Enable) + l.appendStringSlice("disable", &l.cfg.Linters.Disable) + l.appendStringSlice("presets", &l.cfg.Linters.Presets) + l.appendStringSlice("build-tags", &l.cfg.Run.BuildTags) + l.appendStringSlice("skip-dirs", &l.cfg.Run.SkipDirs) + l.appendStringSlice("skip-files", &l.cfg.Run.SkipFiles) + l.appendStringSlice("exclude", &l.cfg.Issues.ExcludePatterns) +} + +func (l *Loader) appendStringSlice(name string, current *[]string) { + if l.fs.Changed(name) { + val, _ := l.fs.GetStringSlice(name) + *current = append(*current, val...) + } +} + +func fileDecoderHook() viper.DecoderConfigOption { + return viper.DecodeHook(mapstructure.ComposeDecodeHookFunc( + // Default hooks (https://github.com/spf13/viper/blob/518241257478c557633ab36e474dfcaeb9a3c623/viper.go#L135-L138). + mapstructure.StringToTimeDurationHookFunc(), + mapstructure.StringToSliceHookFunc(","), + + // Needed for forbidigo. + mapstructure.TextUnmarshallerHookFunc(), + )) +} + +func extractFirstPathArg() string { + args := os.Args + + // skip all args ([golangci-lint, run/linters]) before files/dirs list + for len(args) != 0 { + if args[0] == "run" { + args = args[1:] + break + } + + args = args[1:] + } + + // find first file/dir arg + firstArg := "./..." + for _, arg := range args { + if !strings.HasPrefix(arg, "-") { + firstArg = arg + break + } + } + + return firstArg +} diff --git a/pkg/config/output.go b/pkg/config/output.go index d67f110f678d..a0734ab7d31c 100644 --- a/pkg/config/output.go +++ b/pkg/config/output.go @@ -1,15 +1,24 @@ package config +import ( + "errors" + "fmt" + "slices" + "strings" +) + const ( OutFormatJSON = "json" OutFormatLineNumber = "line-number" OutFormatColoredLineNumber = "colored-line-number" OutFormatTab = "tab" + OutFormatColoredTab = "colored-tab" OutFormatCheckstyle = "checkstyle" OutFormatCodeClimate = "code-climate" OutFormatHTML = "html" OutFormatJunitXML = "junit-xml" OutFormatGithubActions = "github-actions" + OutFormatTeamCity = "teamcity" ) var OutFormats = []string{ @@ -22,15 +31,38 @@ var OutFormats = []string{ OutFormatHTML, OutFormatJunitXML, OutFormatGithubActions, + OutFormatTeamCity, } type Output struct { - Format string - Color string - PrintIssuedLine bool `mapstructure:"print-issued-lines"` - PrintLinterName bool `mapstructure:"print-linter-name"` - UniqByLine bool `mapstructure:"uniq-by-line"` - SortResults bool `mapstructure:"sort-results"` - PrintWelcomeMessage bool `mapstructure:"print-welcome"` - PathPrefix string `mapstructure:"path-prefix"` + Format string `mapstructure:"format"` + PrintIssuedLine bool `mapstructure:"print-issued-lines"` + PrintLinterName bool `mapstructure:"print-linter-name"` + UniqByLine bool `mapstructure:"uniq-by-line"` + SortResults bool `mapstructure:"sort-results"` + SortOrder []string `mapstructure:"sort-order"` + PathPrefix string `mapstructure:"path-prefix"` + ShowStats bool `mapstructure:"show-stats"` +} + +func (o *Output) Validate() error { + if !o.SortResults && len(o.SortOrder) > 0 { + return errors.New("sort-results should be 'true' to use sort-order") + } + + validOrders := []string{"linter", "file", "severity"} + + all := strings.Join(o.SortOrder, " ") + + for _, order := range o.SortOrder { + if strings.Count(all, order) > 1 { + return fmt.Errorf("the sort-order name %q is repeated several times", order) + } + + if !slices.Contains(validOrders, order) { + return fmt.Errorf("unsupported sort-order name %q", order) + } + } + + return nil } diff --git a/pkg/config/output_test.go b/pkg/config/output_test.go new file mode 100644 index 000000000000..93b56ff3699b --- /dev/null +++ b/pkg/config/output_test.go @@ -0,0 +1,95 @@ +package config + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestOutput_Validate(t *testing.T) { + testCases := []struct { + desc string + settings *Output + }{ + { + desc: "file", + settings: &Output{ + SortResults: true, + SortOrder: []string{"file"}, + }, + }, + { + desc: "linter", + settings: &Output{ + SortResults: true, + SortOrder: []string{"linter"}, + }, + }, + { + desc: "severity", + settings: &Output{ + SortResults: true, + SortOrder: []string{"severity"}, + }, + }, + { + desc: "multiple", + settings: &Output{ + SortResults: true, + SortOrder: []string{"file", "linter", "severity"}, + }, + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + err := test.settings.Validate() + require.NoError(t, err) + }) + } +} + +func TestOutput_Validate_error(t *testing.T) { + testCases := []struct { + desc string + settings *Output + expected string + }{ + { + desc: "sort-results false and sort-order", + settings: &Output{ + SortOrder: []string{"file"}, + }, + expected: "sort-results should be 'true' to use sort-order", + }, + { + desc: "invalid sort-order", + settings: &Output{ + SortResults: true, + SortOrder: []string{"a"}, + }, + expected: `unsupported sort-order name "a"`, + }, + { + desc: "duplicate", + settings: &Output{ + SortResults: true, + SortOrder: []string{"file", "linter", "severity", "linter"}, + }, + expected: `the sort-order name "linter" is repeated several times`, + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + err := test.settings.Validate() + require.EqualError(t, err, test.expected) + }) + } +} diff --git a/pkg/config/reader.go b/pkg/config/reader.go deleted file mode 100644 index 2dfd3c06c9b0..000000000000 --- a/pkg/config/reader.go +++ /dev/null @@ -1,232 +0,0 @@ -package config - -import ( - "errors" - "fmt" - "os" - "path/filepath" - "strings" - - "github.com/mitchellh/go-homedir" - "github.com/spf13/viper" - - "github.com/golangci/golangci-lint/pkg/exitcodes" - "github.com/golangci/golangci-lint/pkg/fsutils" - "github.com/golangci/golangci-lint/pkg/logutils" - "github.com/golangci/golangci-lint/pkg/sliceutil" -) - -type FileReader struct { - log logutils.Log - cfg *Config - commandLineCfg *Config -} - -func NewFileReader(toCfg, commandLineCfg *Config, log logutils.Log) *FileReader { - return &FileReader{ - log: log, - cfg: toCfg, - commandLineCfg: commandLineCfg, - } -} - -func (r *FileReader) Read() error { - // XXX: hack with double parsing for 2 purposes: - // 1. to access "config" option here. - // 2. to give config less priority than command line. - - configFile, err := r.parseConfigOption() - if err != nil { - if err == errConfigDisabled { - return nil - } - - return fmt.Errorf("can't parse --config option: %s", err) - } - - if configFile != "" { - viper.SetConfigFile(configFile) - - // Assume YAML if the file has no extension. - if filepath.Ext(configFile) == "" { - viper.SetConfigType("yaml") - } - } else { - r.setupConfigFileSearch() - } - - return r.parseConfig() -} - -func (r *FileReader) parseConfig() error { - if err := viper.ReadInConfig(); err != nil { - if _, ok := err.(viper.ConfigFileNotFoundError); ok { - return nil - } - - return fmt.Errorf("can't read viper config: %s", err) - } - - usedConfigFile := viper.ConfigFileUsed() - if usedConfigFile == "" { - return nil - } - - usedConfigFile, err := fsutils.ShortestRelPath(usedConfigFile, "") - if err != nil { - r.log.Warnf("Can't pretty print config file path: %s", err) - } - r.log.Infof("Used config file %s", usedConfigFile) - usedConfigDir := filepath.Dir(usedConfigFile) - if usedConfigDir, err = filepath.Abs(usedConfigDir); err != nil { - return errors.New("can't get config directory") - } - r.cfg.cfgDir = usedConfigDir - - if err := viper.Unmarshal(r.cfg); err != nil { - return fmt.Errorf("can't unmarshal config by viper: %s", err) - } - - if err := r.validateConfig(); err != nil { - return fmt.Errorf("can't validate config: %s", err) - } - - if r.cfg.InternalTest { // just for testing purposes: to detect config file usage - fmt.Fprintln(logutils.StdOut, "test") - os.Exit(exitcodes.Success) - } - - return nil -} - -func (r *FileReader) validateConfig() error { - c := r.cfg - if len(c.Run.Args) != 0 { - return errors.New("option run.args in config isn't supported now") - } - - if c.Run.CPUProfilePath != "" { - return errors.New("option run.cpuprofilepath in config isn't allowed") - } - - if c.Run.MemProfilePath != "" { - return errors.New("option run.memprofilepath in config isn't allowed") - } - - if c.Run.TracePath != "" { - return errors.New("option run.tracepath in config isn't allowed") - } - - if c.Run.IsVerbose { - return errors.New("can't set run.verbose option with config: only on command-line") - } - for i, rule := range c.Issues.ExcludeRules { - if err := rule.Validate(); err != nil { - return fmt.Errorf("error in exclude rule #%d: %v", i, err) - } - } - if len(c.Severity.Rules) > 0 && c.Severity.Default == "" { - return errors.New("can't set severity rule option: no default severity defined") - } - for i, rule := range c.Severity.Rules { - if err := rule.Validate(); err != nil { - return fmt.Errorf("error in severity rule #%d: %v", i, err) - } - } - if err := c.LintersSettings.Govet.Validate(); err != nil { - return fmt.Errorf("error in govet config: %v", err) - } - return nil -} - -func getFirstPathArg() string { - args := os.Args - - // skip all args ([golangci-lint, run/linters]) before files/dirs list - for len(args) != 0 { - if args[0] == "run" { - args = args[1:] - break - } - - args = args[1:] - } - - // find first file/dir arg - firstArg := "./..." - for _, arg := range args { - if !strings.HasPrefix(arg, "-") { - firstArg = arg - break - } - } - - return firstArg -} - -func (r *FileReader) setupConfigFileSearch() { - firstArg := getFirstPathArg() - absStartPath, err := filepath.Abs(firstArg) - if err != nil { - r.log.Warnf("Can't make abs path for %q: %s", firstArg, err) - absStartPath = filepath.Clean(firstArg) - } - - // start from it - var curDir string - if fsutils.IsDir(absStartPath) { - curDir = absStartPath - } else { - curDir = filepath.Dir(absStartPath) - } - - // find all dirs from it up to the root - configSearchPaths := []string{"./"} - - for { - configSearchPaths = append(configSearchPaths, curDir) - newCurDir := filepath.Dir(curDir) - if curDir == newCurDir || newCurDir == "" { - break - } - curDir = newCurDir - } - - // find home directory for global config - if home, err := homedir.Dir(); err != nil { - r.log.Warnf("Can't get user's home directory: %s", err.Error()) - } else if !sliceutil.Contains(configSearchPaths, home) { - configSearchPaths = append(configSearchPaths, home) - } - - r.log.Infof("Config search paths: %s", configSearchPaths) - viper.SetConfigName(".golangci") - for _, p := range configSearchPaths { - viper.AddConfigPath(p) - } -} - -var errConfigDisabled = errors.New("config is disabled by --no-config") - -func (r *FileReader) parseConfigOption() (string, error) { - cfg := r.commandLineCfg - if cfg == nil { - return "", nil - } - - configFile := cfg.Run.Config - if cfg.Run.NoConfig && configFile != "" { - return "", errors.New("can't combine option --config and --no-config") - } - - if cfg.Run.NoConfig { - return "", errConfigDisabled - } - - configFile, err := homedir.Expand(configFile) - if err != nil { - return "", errors.New("failed to expand configuration path") - } - - return configFile, nil -} diff --git a/pkg/config/run.go b/pkg/config/run.go index ff812d0a2583..8a1e58c37319 100644 --- a/pkg/config/run.go +++ b/pkg/config/run.go @@ -4,18 +4,9 @@ import "time" // Run encapsulates the config options for running the linter analysis. type Run struct { - IsVerbose bool `mapstructure:"verbose"` - Silent bool - CPUProfilePath string - MemProfilePath string - TracePath string - Concurrency int - PrintResourcesUsage bool `mapstructure:"print-resources-usage"` + Timeout time.Duration `mapstructure:"timeout"` - Config string // The path to the golangci config file, as specified with the --config argument. - NoConfig bool - - Args []string + Concurrency int `mapstructure:"concurrency"` Go string `mapstructure:"go"` @@ -25,16 +16,16 @@ type Run struct { ExitCodeIfIssuesFound int `mapstructure:"issues-exit-code"` AnalyzeTests bool `mapstructure:"tests"` - // Deprecated: Deadline exists for historical compatibility - // and should not be used. To set run timeout use Timeout instead. - Deadline time.Duration - Timeout time.Duration - - PrintVersion bool SkipFiles []string `mapstructure:"skip-files"` SkipDirs []string `mapstructure:"skip-dirs"` UseDefaultSkipDirs bool `mapstructure:"skip-dirs-use-default"` AllowParallelRunners bool `mapstructure:"allow-parallel-runners"` AllowSerialRunners bool `mapstructure:"allow-serial-runners"` + + // Deprecated: use Output.ShowStats instead. + ShowStats bool `mapstructure:"show-stats"` + + // It's obtain by flags and use for the tests and the context loader. + Args []string // Internal needs. } diff --git a/pkg/config/severity.go b/pkg/config/severity.go index 3068a0ed69ce..a6d2c9ec3fb3 100644 --- a/pkg/config/severity.go +++ b/pkg/config/severity.go @@ -1,5 +1,10 @@ package config +import ( + "errors" + "fmt" +) + const severityRuleMinConditionsCount = 1 type Severity struct { @@ -8,11 +13,29 @@ type Severity struct { Rules []SeverityRule `mapstructure:"rules"` } +func (s *Severity) Validate() error { + if len(s.Rules) > 0 && s.Default == "" { + return errors.New("can't set severity rule option: no default severity defined") + } + + for i, rule := range s.Rules { + if err := rule.Validate(); err != nil { + return fmt.Errorf("error in severity rule #%d: %w", i, err) + } + } + + return nil +} + type SeverityRule struct { BaseRule `mapstructure:",squash"` Severity string } func (s *SeverityRule) Validate() error { + if s.Severity == "" { + return errors.New("severity should be set") + } + return s.BaseRule.Validate(severityRuleMinConditionsCount) } diff --git a/pkg/config/severity_test.go b/pkg/config/severity_test.go new file mode 100644 index 000000000000..049fd1663a8b --- /dev/null +++ b/pkg/config/severity_test.go @@ -0,0 +1,205 @@ +package config + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestSeverity_Validate(t *testing.T) { + testCases := []struct { + desc string + severity *Severity + }{ + { + desc: "default with rules", + severity: &Severity{ + Default: "high", + Rules: []SeverityRule{ + { + Severity: "low", + BaseRule: BaseRule{ + Path: "test", + }, + }, + }, + }, + }, + { + desc: "default without rules", + severity: &Severity{ + Default: "high", + }, + }, + { + desc: "same severity between default and rule", + severity: &Severity{ + Default: "high", + Rules: []SeverityRule{ + { + Severity: "high", + BaseRule: BaseRule{ + Path: "test", + }, + }, + }, + }, + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + err := test.severity.Validate() + require.NoError(t, err) + }) + } +} + +func TestSeverity_Validate_error(t *testing.T) { + testCases := []struct { + desc string + severity *Severity + expected string + }{ + { + desc: "missing default severity", + severity: &Severity{ + Default: "", + Rules: []SeverityRule{ + { + Severity: "low", + BaseRule: BaseRule{ + Path: "test", + }, + }, + }, + }, + expected: "can't set severity rule option: no default severity defined", + }, + { + desc: "missing rule severity", + severity: &Severity{ + Default: "high", + Rules: []SeverityRule{ + { + BaseRule: BaseRule{ + Path: "test", + }, + }, + }, + }, + expected: "error in severity rule #0: severity should be set", + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + err := test.severity.Validate() + require.EqualError(t, err, test.expected) + }) + } +} + +func TestSeverityRule_Validate(t *testing.T) { + rule := &SeverityRule{ + Severity: "low", + BaseRule: BaseRule{ + Path: "test", + }, + } + + err := rule.Validate() + require.NoError(t, err) +} + +func TestSeverityRule_Validate_error(t *testing.T) { + testCases := []struct { + desc string + rule *SeverityRule + expected string + }{ + { + desc: "missing severity", + rule: &SeverityRule{ + BaseRule: BaseRule{ + Path: "test", + }, + }, + expected: "severity should be set", + }, + { + desc: "empty rule", + rule: &SeverityRule{ + Severity: "low", + }, + expected: "at least 1 of (text, source, path[-except], linters) should be set", + }, + { + desc: "invalid path rule", + rule: &SeverityRule{ + Severity: "low", + BaseRule: BaseRule{ + Path: "**test", + }, + }, + expected: "invalid path regex: error parsing regexp: missing argument to repetition operator: `*`", + }, + { + desc: "invalid path-except rule", + rule: &SeverityRule{ + Severity: "low", + BaseRule: BaseRule{ + PathExcept: "**test", + }, + }, + expected: "invalid path-except regex: error parsing regexp: missing argument to repetition operator: `*`", + }, + { + desc: "invalid text rule", + rule: &SeverityRule{ + Severity: "low", + BaseRule: BaseRule{ + Text: "**test", + }, + }, + expected: "invalid text regex: error parsing regexp: missing argument to repetition operator: `*`", + }, + { + desc: "invalid source rule", + rule: &SeverityRule{ + Severity: "low", + BaseRule: BaseRule{ + Source: "**test", + }, + }, + expected: "invalid source regex: error parsing regexp: missing argument to repetition operator: `*`", + }, + { + desc: "path and path-expect", + rule: &SeverityRule{ + Severity: "low", + BaseRule: BaseRule{ + Path: "test", + PathExcept: "test", + }, + }, + expected: "path and path-except should not be set at the same time", + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + err := test.rule.Validate() + require.EqualError(t, err, test.expected) + }) + } +} diff --git a/pkg/fsutils/filecache.go b/pkg/fsutils/filecache.go index 04c66823df2c..e8e5ba19b780 100644 --- a/pkg/fsutils/filecache.go +++ b/pkg/fsutils/filecache.go @@ -5,8 +5,6 @@ import ( "os" "sync" - "github.com/pkg/errors" - "github.com/golangci/golangci-lint/pkg/logutils" ) @@ -26,7 +24,7 @@ func (fc *FileCache) GetFileBytes(filePath string) ([]byte, error) { fileBytes, err := os.ReadFile(filePath) if err != nil { - return nil, errors.Wrapf(err, "can't read file %s", filePath) + return nil, fmt.Errorf("can't read file %s: %w", filePath, err) } fc.files.Store(filePath, fileBytes) @@ -56,7 +54,7 @@ func PrettifyBytesCount(n int64) string { func (fc *FileCache) PrintStats(log logutils.Log) { var size int64 var mapLen int - fc.files.Range(func(_, fileBytes interface{}) bool { + fc.files.Range(func(_, fileBytes any) bool { mapLen++ size += int64(len(fileBytes.([]byte))) diff --git a/pkg/fsutils/files.go b/pkg/fsutils/files.go new file mode 100644 index 000000000000..4398ab9fc1e6 --- /dev/null +++ b/pkg/fsutils/files.go @@ -0,0 +1,33 @@ +package fsutils + +import "path/filepath" + +// Files combines different operations related to handling file paths and content. +type Files struct { + *LineCache + pathPrefix string +} + +func NewFiles(lc *LineCache, pathPrefix string) *Files { + return &Files{ + LineCache: lc, + pathPrefix: pathPrefix, + } +} + +// WithPathPrefix takes a path that is relative to the current directory (as used in issues) +// and adds the configured path prefix, if there is one. +// The resulting path then can be shown to the user or compared against paths specified in the configuration. +func (f *Files) WithPathPrefix(relativePath string) string { + return WithPathPrefix(f.pathPrefix, relativePath) +} + +// WithPathPrefix takes a path that is relative to the current directory (as used in issues) +// and adds the configured path prefix, if there is one. +// The resulting path then can be shown to the user or compared against paths specified in the configuration. +func WithPathPrefix(pathPrefix, relativePath string) string { + if pathPrefix == "" { + return relativePath + } + return filepath.Join(pathPrefix, relativePath) +} diff --git a/pkg/fsutils/fsutils.go b/pkg/fsutils/fsutils.go index a39c105e432a..80bb9c5b44f4 100644 --- a/pkg/fsutils/fsutils.go +++ b/pkg/fsutils/fsutils.go @@ -12,10 +12,12 @@ func IsDir(filename string) bool { return err == nil && fi.IsDir() } -var cachedWd string -var cachedWdError error -var getWdOnce sync.Once -var useCache = true +var ( + cachedWd string + cachedWdError error + getWdOnce sync.Once + useCache = true +) func UseWdCache(use bool) { useCache = use @@ -34,7 +36,7 @@ func Getwd() (string, error) { evaledWd, err := EvalSymlinks(cachedWd) if err != nil { - cachedWd, cachedWdError = "", fmt.Errorf("can't eval symlinks on wd %s: %s", cachedWd, err) + cachedWd, cachedWdError = "", fmt.Errorf("can't eval symlinks on wd %s: %w", cachedWd, err) return } @@ -70,13 +72,13 @@ func ShortestRelPath(path, wd string) (string, error) { var err error wd, err = Getwd() if err != nil { - return "", fmt.Errorf("can't get working directory: %s", err) + return "", fmt.Errorf("can't get working directory: %w", err) } } evaledPath, err := EvalSymlinks(path) if err != nil { - return "", fmt.Errorf("can't eval symlinks for path %s: %s", path, err) + return "", fmt.Errorf("can't eval symlinks for path %s: %w", path, err) } path = evaledPath @@ -92,7 +94,7 @@ func ShortestRelPath(path, wd string) (string, error) { relPath, err := filepath.Rel(wd, absPath) if err != nil { - return "", fmt.Errorf("can't get relative path for path %s and root %s: %s", + return "", fmt.Errorf("can't get relative path for path %s and root %s: %w", absPath, wd, err) } diff --git a/pkg/fsutils/linecache.go b/pkg/fsutils/linecache.go index b02751537e15..2e92264846ef 100644 --- a/pkg/fsutils/linecache.go +++ b/pkg/fsutils/linecache.go @@ -4,8 +4,6 @@ import ( "bytes" "fmt" "sync" - - "github.com/pkg/errors" ) type fileLinesCache [][]byte @@ -39,7 +37,7 @@ func (lc *LineCache) GetLine(filePath string, index1 int) (string, error) { func (lc *LineCache) getRawLine(filePath string, index0 int) ([]byte, error) { fc, err := lc.getFileCache(filePath) if err != nil { - return nil, errors.Wrapf(err, "failed to get file %s lines cache", filePath) + return nil, fmt.Errorf("failed to get file %s lines cache: %w", filePath, err) } if index0 < 0 { @@ -61,7 +59,7 @@ func (lc *LineCache) getFileCache(filePath string) (fileLinesCache, error) { fileBytes, err := lc.fileCache.GetFileBytes(filePath) if err != nil { - return nil, errors.Wrapf(err, "can't get file %s bytes from cache", filePath) + return nil, fmt.Errorf("can't get file %s bytes from cache: %w", filePath, err) } fc := bytes.Split(fileBytes, []byte("\n")) diff --git a/pkg/golinters/asciicheck.go b/pkg/golinters/asciicheck.go index df301b417bc5..7e7ee05e5c8f 100644 --- a/pkg/golinters/asciicheck.go +++ b/pkg/golinters/asciicheck.go @@ -8,10 +8,12 @@ import ( ) func NewAsciicheck() *goanalysis.Linter { + a := asciicheck.NewAnalyzer() + return goanalysis.NewLinter( - "asciicheck", - "Simple linter to check that your code does not contain non-ASCII identifiers", - []*analysis.Analyzer{asciicheck.NewAnalyzer()}, + a.Name, + a.Doc, + []*analysis.Analyzer{a}, nil, ).WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/bidichk.go b/pkg/golinters/bidichk.go index 44215b7e90cf..ef266f55ca37 100644 --- a/pkg/golinters/bidichk.go +++ b/pkg/golinters/bidichk.go @@ -13,7 +13,7 @@ import ( func NewBiDiChkFuncName(cfg *config.BiDiChkSettings) *goanalysis.Linter { a := bidichk.NewAnalyzer() - cfgMap := map[string]map[string]interface{}{} + cfgMap := map[string]map[string]any{} if cfg != nil { var opts []string @@ -45,13 +45,13 @@ func NewBiDiChkFuncName(cfg *config.BiDiChkSettings) *goanalysis.Linter { opts = append(opts, "POP-DIRECTIONAL-ISOLATE") } - cfgMap[a.Name] = map[string]interface{}{ + cfgMap[a.Name] = map[string]any{ "disallowed-runes": strings.Join(opts, ","), } } return goanalysis.NewLinter( - "bidichk", + a.Name, "Checks for dangerous unicode character sequences", []*analysis.Analyzer{a}, cfgMap, diff --git a/pkg/golinters/containedctx.go b/pkg/golinters/containedctx.go index 8592eef1f9ae..8f7859af7d6c 100644 --- a/pkg/golinters/containedctx.go +++ b/pkg/golinters/containedctx.go @@ -15,5 +15,5 @@ func NewContainedCtx() *goanalysis.Linter { a.Doc, []*analysis.Analyzer{a}, nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + ).WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/copyloopvar.go b/pkg/golinters/copyloopvar.go new file mode 100644 index 000000000000..02ce5f37a6cd --- /dev/null +++ b/pkg/golinters/copyloopvar.go @@ -0,0 +1,29 @@ +package golinters + +import ( + "github.com/karamaru-alpha/copyloopvar" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" +) + +func NewCopyLoopVar(settings *config.CopyLoopVarSettings) *goanalysis.Linter { + a := copyloopvar.NewAnalyzer() + + var cfg map[string]map[string]any + if settings != nil { + cfg = map[string]map[string]any{ + a.Name: { + "ignore-alias": settings.IgnoreAlias, + }, + } + } + + return goanalysis.NewLinter( + a.Name, + a.Doc, + []*analysis.Analyzer{a}, + cfg, + ).WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/pkg/golinters/cyclop.go b/pkg/golinters/cyclop.go index 6f55b2797509..f76c55552c25 100644 --- a/pkg/golinters/cyclop.go +++ b/pkg/golinters/cyclop.go @@ -8,14 +8,12 @@ import ( "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" ) -const cyclopName = "cyclop" - func NewCyclop(settings *config.Cyclop) *goanalysis.Linter { a := analyzer.NewAnalyzer() - var cfg map[string]map[string]interface{} + var cfg map[string]map[string]any if settings != nil { - d := map[string]interface{}{ + d := map[string]any{ "skipTests": settings.SkipTests, } @@ -27,11 +25,11 @@ func NewCyclop(settings *config.Cyclop) *goanalysis.Linter { d["packageAverage"] = settings.PackageAverage } - cfg = map[string]map[string]interface{}{a.Name: d} + cfg = map[string]map[string]any{a.Name: d} } return goanalysis.NewLinter( - cyclopName, + a.Name, "checks function and package cyclomatic complexity", []*analysis.Analyzer{a}, cfg, diff --git a/pkg/golinters/deadcode.go b/pkg/golinters/deadcode.go deleted file mode 100644 index 408b180b935c..000000000000 --- a/pkg/golinters/deadcode.go +++ /dev/null @@ -1,61 +0,0 @@ -package golinters - -import ( - "fmt" - "sync" - - deadcodeAPI "github.com/golangci/go-misc/deadcode" - "golang.org/x/tools/go/analysis" - - "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" - "github.com/golangci/golangci-lint/pkg/lint/linter" - "github.com/golangci/golangci-lint/pkg/result" -) - -const deadcodeName = "deadcode" - -func NewDeadcode() *goanalysis.Linter { - var mu sync.Mutex - var resIssues []goanalysis.Issue - - analyzer := &analysis.Analyzer{ - Name: deadcodeName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (interface{}, error) { - prog := goanalysis.MakeFakeLoaderProgram(pass) - - issues, err := deadcodeAPI.Run(prog) - if err != nil { - return nil, err - } - - res := make([]goanalysis.Issue, 0, len(issues)) - for _, i := range issues { - res = append(res, goanalysis.NewIssue(&result.Issue{ - Pos: i.Pos, - Text: fmt.Sprintf("%s is unused", formatCode(i.UnusedIdentName, nil)), - FromLinter: deadcodeName, - }, pass)) - } - - if len(issues) == 0 { - return nil, nil - } - - mu.Lock() - resIssues = append(resIssues, res...) - mu.Unlock() - - return nil, nil - }, - } - - return goanalysis.NewLinter( - deadcodeName, - "Finds unused code", - []*analysis.Analyzer{analyzer}, - nil, - ).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return resIssues - }).WithLoadMode(goanalysis.LoadModeTypesInfo) -} diff --git a/pkg/golinters/decorder.go b/pkg/golinters/decorder.go index 1c93acaa2c61..5202a03a4f95 100644 --- a/pkg/golinters/decorder.go +++ b/pkg/golinters/decorder.go @@ -14,15 +14,23 @@ func NewDecorder(settings *config.DecorderSettings) *goanalysis.Linter { a := decorder.Analyzer // disable all rules/checks by default - cfg := map[string]interface{}{ + cfg := map[string]any{ + "ignore-underscore-vars": false, "disable-dec-num-check": true, + "disable-type-dec-num-check": false, + "disable-const-dec-num-check": false, + "disable-var-dec-num-check": false, "disable-dec-order-check": true, "disable-init-func-first-check": true, } if settings != nil { cfg["dec-order"] = strings.Join(settings.DecOrder, ",") + cfg["ignore-underscore-vars"] = settings.IgnoreUnderscoreVars cfg["disable-dec-num-check"] = settings.DisableDecNumCheck + cfg["disable-type-dec-num-check"] = settings.DisableTypeDecNumCheck + cfg["disable-const-dec-num-check"] = settings.DisableConstDecNumCheck + cfg["disable-var-dec-num-check"] = settings.DisableVarDecNumCheck cfg["disable-dec-order-check"] = settings.DisableDecOrderCheck cfg["disable-init-func-first-check"] = settings.DisableInitFuncFirstCheck } @@ -31,6 +39,6 @@ func NewDecorder(settings *config.DecorderSettings) *goanalysis.Linter { a.Name, a.Doc, []*analysis.Analyzer{a}, - map[string]map[string]interface{}{a.Name: cfg}, + map[string]map[string]any{a.Name: cfg}, ).WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/depguard.go b/pkg/golinters/depguard.go index eb7b0f3304b2..49e471df824d 100644 --- a/pkg/golinters/depguard.go +++ b/pkg/golinters/depguard.go @@ -1,200 +1,50 @@ package golinters import ( - "fmt" - "strings" - "sync" - - "github.com/OpenPeeDeeP/depguard" + "github.com/OpenPeeDeeP/depguard/v2" "golang.org/x/tools/go/analysis" - "golang.org/x/tools/go/loader" //nolint:staticcheck // require changes in github.com/OpenPeeDeeP/depguard "github.com/golangci/golangci-lint/pkg/config" - "github.com/golangci/golangci-lint/pkg/fsutils" "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" "github.com/golangci/golangci-lint/pkg/lint/linter" - "github.com/golangci/golangci-lint/pkg/result" ) -const depguardName = "depguard" - func NewDepguard(settings *config.DepGuardSettings) *goanalysis.Linter { - var mu sync.Mutex - var resIssues []goanalysis.Issue - - analyzer := &analysis.Analyzer{ - Name: depguardName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: goanalysis.DummyRun, - } - - return goanalysis.NewLinter( - depguardName, - "Go linter that checks if package imports are in a list of acceptable packages", - []*analysis.Analyzer{analyzer}, - nil, - ).WithContextSetter(func(lintCtx *linter.Context) { - dg, err := newDepGuard(settings) - - analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { - if err != nil { - return nil, err + conf := depguard.LinterSettings{} + + if settings != nil { + for s, rule := range settings.Rules { + list := &depguard.List{ + ListMode: rule.ListMode, + Files: rule.Files, + Allow: rule.Allow, } - issues, errRun := dg.run(pass) - if errRun != nil { - return nil, errRun - } + // because of bug with Viper parsing (split on dot) we use a list of struct instead of a map. + // https://github.com/spf13/viper/issues/324 + // https://github.com/golangci/golangci-lint/issues/3749#issuecomment-1492536630 - mu.Lock() - resIssues = append(resIssues, issues...) - mu.Unlock() + deny := map[string]string{} + for _, r := range rule.Deny { + deny[r.Pkg] = r.Desc + } + list.Deny = deny - return nil, nil + conf[s] = list } - }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return resIssues - }).WithLoadMode(goanalysis.LoadModeSyntax) -} - -type depGuard struct { - loadConfig *loader.Config - guardians []*guardian -} - -func newDepGuard(settings *config.DepGuardSettings) (*depGuard, error) { - ps, err := newGuardian(settings) - if err != nil { - return nil, err } - d := &depGuard{ - loadConfig: &loader.Config{ - Cwd: "", // fallbacked to os.Getcwd - Build: nil, // fallbacked to build.Default - }, - guardians: []*guardian{ps}, - } + a := depguard.NewUncompiledAnalyzer(&conf) - for _, additional := range settings.AdditionalGuards { - add := additional - ps, err = newGuardian(&add) + return goanalysis.NewLinter( + a.Analyzer.Name, + a.Analyzer.Doc, + []*analysis.Analyzer{a.Analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + err := a.Compile() if err != nil { - return nil, err + lintCtx.Log.Errorf("create analyzer: %v", err) } - - d.guardians = append(d.guardians, ps) - } - - return d, nil -} - -func (d depGuard) run(pass *analysis.Pass) ([]goanalysis.Issue, error) { - prog := goanalysis.MakeFakeLoaderProgram(pass) - - var resIssues []goanalysis.Issue - for _, g := range d.guardians { - issues, errRun := g.run(d.loadConfig, prog, pass) - if errRun != nil { - return nil, errRun - } - - resIssues = append(resIssues, issues...) - } - - return resIssues, nil -} - -type guardian struct { - *depguard.Depguard - pkgsWithErrorMessage map[string]string -} - -func newGuardian(settings *config.DepGuardSettings) (*guardian, error) { - var ignoreFileRules []string - for _, rule := range settings.IgnoreFileRules { - ignoreFileRules = append(ignoreFileRules, fsutils.NormalizePathInRegex(rule)) - } - - dg := &depguard.Depguard{ - Packages: settings.Packages, - IncludeGoRoot: settings.IncludeGoRoot, - IgnoreFileRules: ignoreFileRules, - } - - var err error - dg.ListType, err = getDepGuardListType(settings.ListType) - if err != nil { - return nil, err - } - - // if the list type was a denylist the packages with error messages should be included in the denylist package list - if dg.ListType == depguard.LTBlacklist { - noMessagePackages := make(map[string]bool) - for _, pkg := range dg.Packages { - noMessagePackages[pkg] = true - } - - for pkg := range settings.PackagesWithErrorMessage { - if _, ok := noMessagePackages[pkg]; !ok { - dg.Packages = append(dg.Packages, pkg) - } - } - } - - return &guardian{ - Depguard: dg, - pkgsWithErrorMessage: settings.PackagesWithErrorMessage, - }, nil -} - -func (g guardian) run(loadConfig *loader.Config, prog *loader.Program, pass *analysis.Pass) ([]goanalysis.Issue, error) { - issues, err := g.Run(loadConfig, prog) - if err != nil { - return nil, err - } - - res := make([]goanalysis.Issue, 0, len(issues)) - - for _, issue := range issues { - res = append(res, - goanalysis.NewIssue(&result.Issue{ - Pos: issue.Position, - Text: g.createMsg(issue.PackageName), - FromLinter: depguardName, - }, pass), - ) - } - - return res, nil -} - -func (g guardian) createMsg(pkgName string) string { - msgSuffix := "is in the denylist" - if g.ListType == depguard.LTWhitelist { - msgSuffix = "is not in the allowlist" - } - - var userSuppliedMsgSuffix string - if g.pkgsWithErrorMessage != nil { - userSuppliedMsgSuffix = g.pkgsWithErrorMessage[pkgName] - if userSuppliedMsgSuffix != "" { - userSuppliedMsgSuffix = ": " + userSuppliedMsgSuffix - } - } - - return fmt.Sprintf("%s %s%s", formatCode(pkgName, nil), msgSuffix, userSuppliedMsgSuffix) -} - -func getDepGuardListType(listType string) (depguard.ListType, error) { - if listType == "" { - return depguard.LTBlacklist, nil - } - - listT, found := depguard.StringToListType[strings.ToLower(listType)] - if !found { - return depguard.LTBlacklist, fmt.Errorf("unsure what list type %s is", listType) - } - - return listT, nil + }).WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/dogsled.go b/pkg/golinters/dogsled.go index 00c32c2dc929..79502fe8be6c 100644 --- a/pkg/golinters/dogsled.go +++ b/pkg/golinters/dogsled.go @@ -24,7 +24,7 @@ func NewDogsled(settings *config.DogsledSettings) *goanalysis.Linter { analyzer := &analysis.Analyzer{ Name: dogsledName, Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (interface{}, error) { + Run: func(pass *analysis.Pass) (any, error) { issues := runDogsled(pass, settings) if len(issues) == 0 { diff --git a/pkg/golinters/dupl.go b/pkg/golinters/dupl.go index fe7b12773542..5d772a5f2faa 100644 --- a/pkg/golinters/dupl.go +++ b/pkg/golinters/dupl.go @@ -6,7 +6,6 @@ import ( "sync" duplAPI "github.com/golangci/dupl" - "github.com/pkg/errors" "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/pkg/config" @@ -26,7 +25,7 @@ func NewDupl(settings *config.DuplSettings) *goanalysis.Linter { analyzer := &analysis.Analyzer{ Name: duplName, Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (interface{}, error) { + Run: func(pass *analysis.Pass) (any, error) { issues, err := runDupl(pass, settings) if err != nil { return nil, err @@ -71,7 +70,7 @@ func runDupl(pass *analysis.Pass, settings *config.DuplSettings) ([]goanalysis.I for _, i := range issues { toFilename, err := fsutils.ShortestRelPath(i.To.Filename(), "") if err != nil { - return nil, errors.Wrapf(err, "failed to get shortest rel path for %q", i.To.Filename()) + return nil, fmt.Errorf("failed to get shortest rel path for %q: %w", i.To.Filename(), err) } dupl := fmt.Sprintf("%s:%d-%d", toFilename, i.To.LineStart(), i.To.LineEnd()) diff --git a/pkg/golinters/dupword.go b/pkg/golinters/dupword.go index ae85a6d002a6..6f079ffc895e 100644 --- a/pkg/golinters/dupword.go +++ b/pkg/golinters/dupword.go @@ -13,10 +13,11 @@ import ( func NewDupWord(setting *config.DupWordSettings) *goanalysis.Linter { a := dupword.NewAnalyzer() - cfgMap := map[string]map[string]interface{}{} + cfgMap := map[string]map[string]any{} if setting != nil { - cfgMap[a.Name] = map[string]interface{}{ + cfgMap[a.Name] = map[string]any{ "keyword": strings.Join(setting.Keywords, ","), + "ignore": strings.Join(setting.Ignore, ","), } } diff --git a/pkg/golinters/errcheck.go b/pkg/golinters/errcheck.go index 53fe22e68c02..89b18519c91b 100644 --- a/pkg/golinters/errcheck.go +++ b/pkg/golinters/errcheck.go @@ -11,7 +11,6 @@ import ( "sync" "github.com/kisielk/errcheck/errcheck" - "github.com/pkg/errors" "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/packages" @@ -36,8 +35,8 @@ func NewErrcheck(settings *config.ErrcheckSettings) *goanalysis.Linter { return goanalysis.NewLinter( errcheckName, - "Errcheck is a program for checking for unchecked errors "+ - "in go programs. These unchecked errors can be critical bugs in some cases", + "errcheck is a program for checking for unchecked errors in Go code. "+ + "These unchecked errors can be critical bugs in some cases", []*analysis.Analyzer{analyzer}, nil, ).WithContextSetter(func(lintCtx *linter.Context) { @@ -50,7 +49,7 @@ func NewErrcheck(settings *config.ErrcheckSettings) *goanalysis.Linter { checker.Tags = lintCtx.Cfg.Run.BuildTags - analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + analyzer.Run = func(pass *analysis.Pass) (any, error) { issues := runErrCheck(lintCtx, pass, checker) if err != nil { return nil, err @@ -143,7 +142,7 @@ func parseIgnoreConfig(s string) (map[string]*regexp.Regexp, error) { func getChecker(errCfg *config.ErrcheckSettings) (*errcheck.Checker, error) { ignoreConfig, err := parseIgnoreConfig(errCfg.Ignore) if err != nil { - return nil, errors.Wrap(err, "failed to parse 'ignore' directive") + return nil, fmt.Errorf("failed to parse 'ignore' directive: %w", err) } checker := errcheck.Checker{ @@ -252,7 +251,7 @@ func readExcludeFile(name string) ([]string, error) { } if fh == nil { - return nil, errors.Wrapf(err, "failed reading exclude file: %s", name) + return nil, fmt.Errorf("failed reading exclude file: %s: %w", name, err) } scanner := bufio.NewScanner(fh) @@ -263,7 +262,7 @@ func readExcludeFile(name string) ([]string, error) { } if err := scanner.Err(); err != nil { - return nil, errors.Wrapf(err, "failed scanning file: %s", name) + return nil, fmt.Errorf("failed scanning file: %s: %w", name, err) } return excludes, nil diff --git a/pkg/golinters/errchkjson.go b/pkg/golinters/errchkjson.go index 6cc2208a36fc..1af4450b4e72 100644 --- a/pkg/golinters/errchkjson.go +++ b/pkg/golinters/errchkjson.go @@ -11,22 +11,20 @@ import ( func NewErrChkJSONFuncName(cfg *config.ErrChkJSONSettings) *goanalysis.Linter { a := errchkjson.NewAnalyzer() - cfgMap := map[string]map[string]interface{}{} - cfgMap[a.Name] = map[string]interface{}{ + cfgMap := map[string]map[string]any{} + cfgMap[a.Name] = map[string]any{ "omit-safe": true, } if cfg != nil { - cfgMap[a.Name] = map[string]interface{}{ + cfgMap[a.Name] = map[string]any{ "omit-safe": !cfg.CheckErrorFreeEncoding, "report-no-exported": cfg.ReportNoExported, } } return goanalysis.NewLinter( - "errchkjson", - "Checks types passed to the json encoding functions. "+ - "Reports unsupported types and optionally reports occasions, "+ - "where the check for the returned error can be omitted.", + a.Name, + a.Doc, []*analysis.Analyzer{a}, cfgMap, ).WithLoadMode(goanalysis.LoadModeTypesInfo) diff --git a/pkg/golinters/errname.go b/pkg/golinters/errname.go index 96564cfa8cbe..193a7aba755e 100644 --- a/pkg/golinters/errname.go +++ b/pkg/golinters/errname.go @@ -8,10 +8,12 @@ import ( ) func NewErrName() *goanalysis.Linter { + a := analyzer.New() + return goanalysis.NewLinter( - "errname", - "Checks that sentinel errors are prefixed with the `Err` and error types are suffixed with the `Error`.", - []*analysis.Analyzer{analyzer.New()}, + a.Name, + a.Doc, + []*analysis.Analyzer{a}, nil, ).WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/errorlint.go b/pkg/golinters/errorlint.go index dd9d901617a9..cac94159d6f5 100644 --- a/pkg/golinters/errorlint.go +++ b/pkg/golinters/errorlint.go @@ -11,13 +11,14 @@ import ( func NewErrorLint(cfg *config.ErrorLintSettings) *goanalysis.Linter { a := errorlint.NewAnalyzer() - cfgMap := map[string]map[string]interface{}{} + cfgMap := map[string]map[string]any{} if cfg != nil { - cfgMap[a.Name] = map[string]interface{}{ - "errorf": cfg.Errorf, - "asserts": cfg.Asserts, - "comparison": cfg.Comparison, + cfgMap[a.Name] = map[string]any{ + "errorf": cfg.Errorf, + "errorf-multi": cfg.ErrorfMulti, + "asserts": cfg.Asserts, + "comparison": cfg.Comparison, } } diff --git a/pkg/golinters/exhaustive.go b/pkg/golinters/exhaustive.go index a66f95190aff..fe58e10f0570 100644 --- a/pkg/golinters/exhaustive.go +++ b/pkg/golinters/exhaustive.go @@ -11,9 +11,9 @@ import ( func NewExhaustive(settings *config.ExhaustiveSettings) *goanalysis.Linter { a := exhaustive.Analyzer - var cfg map[string]map[string]interface{} + var cfg map[string]map[string]any if settings != nil { - cfg = map[string]map[string]interface{}{ + cfg = map[string]map[string]any{ a.Name: { exhaustive.CheckFlag: settings.Check, exhaustive.CheckGeneratedFlag: settings.CheckGenerated, @@ -23,6 +23,7 @@ func NewExhaustive(settings *config.ExhaustiveSettings) *goanalysis.Linter { exhaustive.PackageScopeOnlyFlag: settings.PackageScopeOnly, exhaustive.ExplicitExhaustiveMapFlag: settings.ExplicitExhaustiveMap, exhaustive.ExplicitExhaustiveSwitchFlag: settings.ExplicitExhaustiveSwitch, + exhaustive.DefaultCaseRequiredFlag: settings.DefaultCaseRequired, }, } } diff --git a/pkg/golinters/exhaustivestruct.go b/pkg/golinters/exhaustivestruct.go deleted file mode 100644 index 6a1dbd71c5a3..000000000000 --- a/pkg/golinters/exhaustivestruct.go +++ /dev/null @@ -1,31 +0,0 @@ -package golinters - -import ( - "strings" - - "github.com/mbilski/exhaustivestruct/pkg/analyzer" - "golang.org/x/tools/go/analysis" - - "github.com/golangci/golangci-lint/pkg/config" - "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" -) - -func NewExhaustiveStruct(settings *config.ExhaustiveStructSettings) *goanalysis.Linter { - a := analyzer.Analyzer - - var cfg map[string]map[string]interface{} - if settings != nil { - cfg = map[string]map[string]interface{}{ - a.Name: { - "struct_patterns": strings.Join(settings.StructPatterns, ","), - }, - } - } - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) -} diff --git a/pkg/golinters/exhaustruct.go b/pkg/golinters/exhaustruct.go index 37ea055d3ef7..5272879e1db1 100644 --- a/pkg/golinters/exhaustruct.go +++ b/pkg/golinters/exhaustruct.go @@ -1,7 +1,7 @@ package golinters import ( - "github.com/GaijinEntertainment/go-exhaustruct/v2/pkg/analyzer" + "github.com/GaijinEntertainment/go-exhaustruct/v3/analyzer" "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/pkg/config" diff --git a/pkg/golinters/forbidigo.go b/pkg/golinters/forbidigo.go index 95fb47e47b89..6aced29226e1 100644 --- a/pkg/golinters/forbidigo.go +++ b/pkg/golinters/forbidigo.go @@ -1,15 +1,16 @@ package golinters import ( + "fmt" "sync" "github.com/ashanbrown/forbidigo/forbidigo" - "github.com/pkg/errors" "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/pkg/config" "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/logutils" "github.com/golangci/golangci-lint/pkg/result" ) @@ -23,7 +24,7 @@ func NewForbidigo(settings *config.ForbidigoSettings) *goanalysis.Linter { analyzer := &analysis.Analyzer{ Name: forbidigoName, Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (interface{}, error) { + Run: func(pass *analysis.Pass) (any, error) { issues, err := runForbidigo(pass, settings) if err != nil { return nil, err @@ -40,6 +41,9 @@ func NewForbidigo(settings *config.ForbidigoSettings) *goanalysis.Linter { }, } + // Without AnalyzeTypes, LoadModeSyntax is enough. + // But we cannot make this depend on the settings and have to mirror the mode chosen in GetAllSupportedLinterConfigs, + // therefore we have to use LoadModeTypesInfo in all cases. return goanalysis.NewLinter( forbidigoName, "Forbids identifiers", @@ -47,7 +51,7 @@ func NewForbidigo(settings *config.ForbidigoSettings) *goanalysis.Linter { nil, ).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { return resIssues - }).WithLoadMode(goanalysis.LoadModeSyntax) + }).WithLoadMode(goanalysis.LoadModeTypesInfo) } func runForbidigo(pass *analysis.Pass, settings *config.ForbidigoSettings) ([]goanalysis.Issue, error) { @@ -55,18 +59,36 @@ func runForbidigo(pass *analysis.Pass, settings *config.ForbidigoSettings) ([]go forbidigo.OptionExcludeGodocExamples(settings.ExcludeGodocExamples), // disable "//permit" directives so only "//nolint" directives matters within golangci-lint forbidigo.OptionIgnorePermitDirectives(true), + forbidigo.OptionAnalyzeTypes(settings.AnalyzeTypes), } - forbid, err := forbidigo.NewLinter(settings.Forbid, options...) + // Convert patterns back to strings because that is what NewLinter accepts. + var patterns []string + for _, pattern := range settings.Forbid { + buffer, err := pattern.MarshalString() + if err != nil { + return nil, err + } + patterns = append(patterns, string(buffer)) + } + + forbid, err := forbidigo.NewLinter(patterns, options...) if err != nil { - return nil, errors.Wrapf(err, "failed to create linter %q", forbidigoName) + return nil, fmt.Errorf("failed to create linter %q: %w", forbidigoName, err) } var issues []goanalysis.Issue for _, file := range pass.Files { - hints, err := forbid.RunWithConfig(forbidigo.RunConfig{Fset: pass.Fset}, file) + runConfig := forbidigo.RunConfig{ + Fset: pass.Fset, + DebugLog: logutils.Debug(logutils.DebugKeyForbidigo), + } + if settings != nil && settings.AnalyzeTypes { + runConfig.TypesInfo = pass.TypesInfo + } + hints, err := forbid.RunWithConfig(runConfig, file) if err != nil { - return nil, errors.Wrapf(err, "forbidigo linter failed on file %q", file.Name.String()) + return nil, fmt.Errorf("forbidigo linter failed on file %q: %w", file.Name.String(), err) } for _, hint := range hints { diff --git a/pkg/golinters/funlen.go b/pkg/golinters/funlen.go index c562c2aa0455..8def9c1f678a 100644 --- a/pkg/golinters/funlen.go +++ b/pkg/golinters/funlen.go @@ -24,7 +24,7 @@ func NewFunlen(settings *config.FunlenSettings) *goanalysis.Linter { analyzer := &analysis.Analyzer{ Name: funlenName, Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (interface{}, error) { + Run: func(pass *analysis.Pass) (any, error) { issues := runFunlen(pass, settings) if len(issues) == 0 { @@ -52,7 +52,7 @@ func NewFunlen(settings *config.FunlenSettings) *goanalysis.Linter { func runFunlen(pass *analysis.Pass, settings *config.FunlenSettings) []goanalysis.Issue { var lintIssues []funlen.Message for _, file := range pass.Files { - fileIssues := funlen.Run(file, pass.Fset, settings.Lines, settings.Statements) + fileIssues := funlen.Run(file, pass.Fset, settings.Lines, settings.Statements, settings.IgnoreComments) lintIssues = append(lintIssues, fileIssues...) } diff --git a/pkg/golinters/gci.go b/pkg/golinters/gci.go index d07c2126d101..3862267692f4 100644 --- a/pkg/golinters/gci.go +++ b/pkg/golinters/gci.go @@ -2,7 +2,6 @@ package golinters import ( "fmt" - "strings" "sync" gcicfg "github.com/daixiang0/gci/pkg/config" @@ -12,7 +11,6 @@ import ( "github.com/hexops/gotextdiff" "github.com/hexops/gotextdiff/myers" "github.com/hexops/gotextdiff/span" - "github.com/pkg/errors" "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/pkg/config" @@ -58,11 +56,11 @@ func NewGci(settings *config.GciSettings) *goanalysis.Linter { return goanalysis.NewLinter( gciName, - "Gci controls golang package import order and makes it always deterministic.", + "Gci controls Go package import order and makes it always deterministic.", []*analysis.Analyzer{analyzer}, nil, ).WithContextSetter(func(lintCtx *linter.Context) { - analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + analyzer.Run = func(pass *analysis.Pass) (any, error) { issues, err := runGci(pass, lintCtx, cfg, &lock) if err != nil { return nil, err @@ -101,7 +99,7 @@ func runGci(pass *analysis.Pass, lintCtx *linter.Context, cfg *gcicfg.Config, lo is, err := extractIssuesFromPatch(diff, lintCtx, gciName) if err != nil { - return nil, errors.Wrapf(err, "can't extract issues from gci diff output %s", diff) + return nil, fmt.Errorf("can't extract issues from gci diff output %s: %w", diff, err) } for i := range is { @@ -120,7 +118,7 @@ func diffFormattedFilesToArray(paths []string, cfg gcicfg.Config, diffs *[]strin log.InitLogger() defer func() { _ = log.L().Sync() }() - return gci.ProcessFiles(io.GoFilesInPathsGenerator(paths), cfg, func(filePath string, unmodifiedFile, formattedFile []byte) error { + return gci.ProcessFiles(io.GoFilesInPathsGenerator(paths, true), cfg, func(filePath string, unmodifiedFile, formattedFile []byte) error { fileURI := span.URIFromPath(filePath) edits := myers.ComputeEdits(fileURI, string(unmodifiedFile), string(formattedFile)) unifiedEdits := gotextdiff.ToUnified(filePath, filePath, string(unmodifiedFile), edits) @@ -146,7 +144,13 @@ func getErrorTextForGci(settings config.GciSettings) string { } if len(settings.Sections) > 0 { - text += " -s " + strings.Join(settings.Sections, ",") + for _, section := range settings.Sections { + text += " -s " + section + } + } + + if settings.CustomOrder { + text += " --custom-order" } return text diff --git a/pkg/golinters/ginkgolinter.go b/pkg/golinters/ginkgolinter.go index d97050c2ee42..8919de15bf90 100644 --- a/pkg/golinters/ginkgolinter.go +++ b/pkg/golinters/ginkgolinter.go @@ -11,18 +11,23 @@ import ( func NewGinkgoLinter(cfg *config.GinkgoLinterSettings) *goanalysis.Linter { a := ginkgolinter.NewAnalyzer() - cfgMap := make(map[string]map[string]interface{}) + cfgMap := make(map[string]map[string]any) if cfg != nil { - cfgMap[a.Name] = map[string]interface{}{ - "suppress-len-assertion": cfg.SuppressLenAssertion, - "suppress-nil-assertion": cfg.SuppressNilAssertion, - "suppress-err-assertion": cfg.SuppressErrAssertion, + cfgMap[a.Name] = map[string]any{ + "suppress-len-assertion": cfg.SuppressLenAssertion, + "suppress-nil-assertion": cfg.SuppressNilAssertion, + "suppress-err-assertion": cfg.SuppressErrAssertion, + "suppress-compare-assertion": cfg.SuppressCompareAssertion, + "suppress-async-assertion": cfg.SuppressAsyncAssertion, + "suppress-type-compare-assertion": cfg.SuppressTypeCompareWarning, + "forbid-focus-container": cfg.ForbidFocusContainer, + "allow-havelen-0": cfg.AllowHaveLenZero, } } return goanalysis.NewLinter( a.Name, - a.Doc, + "enforces standards of using ginkgo and gomega", []*analysis.Analyzer{a}, cfgMap, ).WithLoadMode(goanalysis.LoadModeTypesInfo) diff --git a/pkg/golinters/goanalysis/adapters.go b/pkg/golinters/goanalysis/adapters.go deleted file mode 100644 index 284215dfc65d..000000000000 --- a/pkg/golinters/goanalysis/adapters.go +++ /dev/null @@ -1,41 +0,0 @@ -package goanalysis - -import ( - "go/types" - - "golang.org/x/tools/go/analysis" - "golang.org/x/tools/go/loader" //nolint:staticcheck // it's an adapter for golang.org/x/tools/go/packages -) - -func MakeFakeLoaderProgram(pass *analysis.Pass) *loader.Program { - var info types.Info - if pass.TypesInfo != nil { - info = *pass.TypesInfo - } - - prog := &loader.Program{ - Fset: pass.Fset, - Created: []*loader.PackageInfo{ - { - Pkg: pass.Pkg, - Importable: true, // not used - TransitivelyErrorFree: true, // TODO ??? - - Files: pass.Files, - Errors: nil, - Info: info, - }, - }, - AllPackages: map[*types.Package]*loader.PackageInfo{ - pass.Pkg: { - Pkg: pass.Pkg, - Importable: true, - TransitivelyErrorFree: true, - Files: pass.Files, - Errors: nil, - Info: info, - }, - }, - } - return prog -} diff --git a/pkg/golinters/goanalysis/errors.go b/pkg/golinters/goanalysis/errors.go index 13b9ccf0af44..f59e02cc6408 100644 --- a/pkg/golinters/goanalysis/errors.go +++ b/pkg/golinters/goanalysis/errors.go @@ -1,9 +1,9 @@ package goanalysis import ( + "errors" "fmt" - "github.com/pkg/errors" "golang.org/x/tools/go/packages" "github.com/golangci/golangci-lint/pkg/lint/linter" diff --git a/pkg/golinters/goanalysis/issue.go b/pkg/golinters/goanalysis/issue.go index f331a3ab9f1a..15d8dd2b333f 100644 --- a/pkg/golinters/goanalysis/issue.go +++ b/pkg/golinters/goanalysis/issue.go @@ -13,9 +13,9 @@ type Issue struct { Pass *analysis.Pass } -func NewIssue(i *result.Issue, pass *analysis.Pass) Issue { +func NewIssue(issue *result.Issue, pass *analysis.Pass) Issue { return Issue{ - Issue: *i, + Issue: *issue, Pass: pass, } } @@ -23,6 +23,7 @@ func NewIssue(i *result.Issue, pass *analysis.Pass) Issue { type EncodingIssue struct { FromLinter string Text string + Severity string Pos token.Position LineRange *result.Range Replacement *result.Replacement diff --git a/pkg/golinters/goanalysis/linter.go b/pkg/golinters/goanalysis/linter.go index 50a4ca088ee9..f8ca2e7553c2 100644 --- a/pkg/golinters/goanalysis/linter.go +++ b/pkg/golinters/goanalysis/linter.go @@ -2,11 +2,11 @@ package goanalysis import ( "context" + "errors" "flag" "fmt" "strings" - "github.com/pkg/errors" "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/pkg/lint/linter" @@ -44,14 +44,14 @@ const ( type Linter struct { name, desc string analyzers []*analysis.Analyzer - cfg map[string]map[string]interface{} + cfg map[string]map[string]any issuesReporter func(*linter.Context) []Issue contextSetter func(*linter.Context) loadMode LoadMode needUseOriginalPackages bool } -func NewLinter(name, desc string, analyzers []*analysis.Analyzer, cfg map[string]map[string]interface{}) *Linter { +func NewLinter(name, desc string, analyzers []*analysis.Analyzer, cfg map[string]map[string]any) *Linter { return &Linter{name: name, desc: desc, analyzers: analyzers, cfg: cfg} } @@ -102,7 +102,7 @@ func (lnt *Linter) allAnalyzerNames() []string { return ret } -func (lnt *Linter) configureAnalyzer(a *analysis.Analyzer, cfg map[string]interface{}) error { +func (lnt *Linter) configureAnalyzer(a *analysis.Analyzer, cfg map[string]any) error { for k, v := range cfg { f := a.Flags.Lookup(k) if f == nil { @@ -116,7 +116,7 @@ func (lnt *Linter) configureAnalyzer(a *analysis.Analyzer, cfg map[string]interf } if err := f.Value.Set(valueToString(v)); err != nil { - return errors.Wrapf(err, "failed to set analyzer setting %q with value %v", k, v) + return fmt.Errorf("failed to set analyzer setting %q with value %v: %w", k, v, err) } } @@ -137,7 +137,7 @@ func (lnt *Linter) configure() error { } if err := lnt.configureAnalyzer(a, analyzerSettings); err != nil { - return errors.Wrapf(err, "failed to configure analyzer %s", analyzerName) + return fmt.Errorf("failed to configure analyzer %s: %w", analyzerName, err) } } @@ -146,11 +146,11 @@ func (lnt *Linter) configure() error { func (lnt *Linter) preRun(lintCtx *linter.Context) error { if err := analysis.Validate(lnt.analyzers); err != nil { - return errors.Wrap(err, "failed to validate analyzers") + return fmt.Errorf("failed to validate analyzers: %w", err) } if err := lnt.configure(); err != nil { - return errors.Wrap(err, "failed to configure analyzers") + return fmt.Errorf("failed to configure analyzers: %w", err) } if lnt.contextSetter != nil { @@ -195,12 +195,12 @@ func allFlagNames(fs *flag.FlagSet) []string { return ret } -func valueToString(v interface{}) string { +func valueToString(v any) string { if ss, ok := v.([]string); ok { return strings.Join(ss, ",") } - if is, ok := v.([]interface{}); ok { + if is, ok := v.([]any); ok { var ss []string for _, i := range is { ss = append(ss, fmt.Sprint(i)) @@ -212,6 +212,6 @@ func valueToString(v interface{}) string { return fmt.Sprint(v) } -func DummyRun(_ *analysis.Pass) (interface{}, error) { +func DummyRun(_ *analysis.Pass) (any, error) { return nil, nil } diff --git a/pkg/golinters/goanalysis/metalinter.go b/pkg/golinters/goanalysis/metalinter.go index 5c24d10964c9..333ab20f1f27 100644 --- a/pkg/golinters/goanalysis/metalinter.go +++ b/pkg/golinters/goanalysis/metalinter.go @@ -2,8 +2,8 @@ package goanalysis import ( "context" + "fmt" - "github.com/pkg/errors" "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/pkg/lint/linter" @@ -24,7 +24,7 @@ func NewMetaLinter(linters []*Linter) *MetaLinter { func (ml MetaLinter) Run(_ context.Context, lintCtx *linter.Context) ([]result.Issue, error) { for _, l := range ml.linters { if err := l.preRun(lintCtx); err != nil { - return nil, errors.Wrapf(err, "failed to pre-run %s", l.Name()) + return nil, fmt.Errorf("failed to pre-run %s: %w", l.Name(), err) } } diff --git a/pkg/golinters/goanalysis/runner.go b/pkg/golinters/goanalysis/runner.go index 4a52c11002c4..8243c345278b 100644 --- a/pkg/golinters/goanalysis/runner.go +++ b/pkg/golinters/goanalysis/runner.go @@ -11,12 +11,13 @@ package goanalysis import ( "encoding/gob" + "fmt" "go/token" "runtime" "sort" "sync" - "github.com/pkg/errors" + "golang.org/x/exp/maps" "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/packages" @@ -60,7 +61,8 @@ type runner struct { } func newRunner(prefix string, logger logutils.Log, pkgCache *pkgcache.Cache, loadGuard *load.Guard, - loadMode LoadMode, sw *timeutils.Stopwatch) *runner { + loadMode LoadMode, sw *timeutils.Stopwatch, +) *runner { return &runner{ prefix: prefix, log: logger, @@ -79,7 +81,8 @@ func newRunner(prefix string, logger logutils.Log, pkgCache *pkgcache.Cache, loa // singlechecker and the multi-analysis commands. // It returns the appropriate exit code. func (r *runner) run(analyzers []*analysis.Analyzer, initialPackages []*packages.Package) ([]Diagnostic, - []error, map[*analysis.Pass]*packages.Package) { + []error, map[*analysis.Pass]*packages.Package, +) { debugf("Analyzing %d packages on load mode %s", len(initialPackages), r.loadMode) defer r.pkgCache.Trim() @@ -115,7 +118,8 @@ func (r *runner) markAllActions(a *analysis.Analyzer, pkg *packages.Package, mar } func (r *runner) makeAction(a *analysis.Analyzer, pkg *packages.Package, - initialPkgs map[*packages.Package]bool, actions map[actKey]*action, actAlloc *actionAllocator) *action { + initialPkgs map[*packages.Package]bool, actions map[actKey]*action, actAlloc *actionAllocator, +) *action { k := actKey{a, pkg} act, ok := actions[k] if ok { @@ -149,7 +153,8 @@ func (r *runner) makeAction(a *analysis.Analyzer, pkg *packages.Package, } func (r *runner) buildActionFactDeps(act *action, a *analysis.Analyzer, pkg *packages.Package, - initialPkgs map[*packages.Package]bool, actions map[actKey]*action, actAlloc *actionAllocator) { + initialPkgs map[*packages.Package]bool, actions map[actKey]*action, actAlloc *actionAllocator, +) { // An analysis that consumes/produces facts // must run on the package's dependencies too. if len(a.FactTypes) == 0 { @@ -159,10 +164,7 @@ func (r *runner) buildActionFactDeps(act *action, a *analysis.Analyzer, pkg *pac act.objectFacts = make(map[objectFactKey]analysis.Fact) act.packageFacts = make(map[packageFactKey]analysis.Fact) - paths := make([]string, 0, len(pkg.Imports)) - for path := range pkg.Imports { - paths = append(paths, path) - } + paths := maps.Keys(pkg.Imports) sort.Strings(paths) // for determinism for _, path := range paths { dep := r.makeAction(a, pkg.Imports[path], initialPkgs, actions, actAlloc) @@ -177,7 +179,8 @@ func (r *runner) buildActionFactDeps(act *action, a *analysis.Analyzer, pkg *pac //nolint:gocritic func (r *runner) prepareAnalysis(pkgs []*packages.Package, - analyzers []*analysis.Analyzer) (map[*packages.Package]bool, []*action, []*action) { + analyzers []*analysis.Analyzer, +) (map[*packages.Package]bool, []*action, []*action) { // Construct the action graph. // Each graph node (action) is one unit of analysis. @@ -212,10 +215,7 @@ func (r *runner) prepareAnalysis(pkgs []*packages.Package, } } - allActions := make([]*action, 0, len(actions)) - for _, act := range actions { - allActions = append(allActions, act) - } + allActions := maps.Values(actions) debugf("Built %d actions", len(actions)) @@ -311,7 +311,7 @@ func extractDiagnostics(roots []*action) (retDiags []Diagnostic, retErrors []err if pe, ok := act.err.(*errorutil.PanicError); ok { panic(pe) } - retErrors = append(retErrors, errors.Wrap(act.err, act.a.Name)) + retErrors = append(retErrors, fmt.Errorf("%s: %w", act.a.Name, act.err)) return } diff --git a/pkg/golinters/goanalysis/runner_action.go b/pkg/golinters/goanalysis/runner_action.go index d6f40a0c465f..6b57cb0c9abb 100644 --- a/pkg/golinters/goanalysis/runner_action.go +++ b/pkg/golinters/goanalysis/runner_action.go @@ -1,6 +1,7 @@ package goanalysis import ( + "errors" "fmt" "go/types" "io" @@ -8,8 +9,6 @@ import ( "runtime/debug" "time" - "github.com/hashicorp/go-multierror" - "github.com/pkg/errors" "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/packages" "golang.org/x/tools/go/types/objectpath" @@ -50,7 +49,7 @@ type action struct { deps []*action objectFacts map[objectFactKey]analysis.Fact packageFacts map[packageFactKey]analysis.Fact - result interface{} + result any diagnostics []analysis.Diagnostic err error r *runner @@ -98,6 +97,13 @@ func (act *action) waitUntilDependingAnalyzersWorked() { func (act *action) analyzeSafe() { defer func() { if p := recover(); p != nil { + if !act.isroot { + // This line allows to display "hidden" panic with analyzers like buildssa. + // Some linters are dependent of sub-analyzers but when a sub-analyzer fails the linter is not aware of that, + // this results to another panic (ex: "interface conversion: interface {} is nil, not *buildssa.SSA"). + act.r.log.Errorf("%s: panic during analysis: %v, %s", act.a.Name, p, string(debug.Stack())) + } + act.err = errorutil.NewPanicError(fmt.Sprintf("%s: package %q (isInitialPkg: %t, needAnalyzeSource: %t): %s", act.a.Name, act.pkg.Name, act.isInitialPkg, act.needAnalyzeSource, p), debug.Stack()) } @@ -119,26 +125,22 @@ func (act *action) analyze() { }(time.Now()) // Report an error if any dependency failures. - var depErrors *multierror.Error + var depErrors error for _, dep := range act.deps { if dep.err == nil { continue } - depErrors = multierror.Append(depErrors, errors.Cause(dep.err)) + depErrors = errors.Join(depErrors, errors.Unwrap(dep.err)) } if depErrors != nil { - depErrors.ErrorFormat = func(e []error) string { - return fmt.Sprintf("failed prerequisites: %v", e) - } - - act.err = depErrors + act.err = fmt.Errorf("failed prerequisites: %w", depErrors) return } // Plumb the output values of the dependencies // into the inputs of this action. Also facts. - inputs := make(map[*analysis.Analyzer]interface{}) + inputs := make(map[*analysis.Analyzer]any) startedAt := time.Now() for _, dep := range act.deps { if dep.pkg == act.pkg { @@ -182,7 +184,7 @@ func (act *action) analyze() { // It looks like there should be !pass.Analyzer.RunDespiteErrors // but govet's cgocall crashes on it. Govet itself contains !pass.Analyzer.RunDespiteErrors condition here, // but it exits before it if packages.Load have failed. - act.err = errors.Wrap(&IllTypedError{Pkg: act.pkg}, "analysis skipped") + act.err = fmt.Errorf("analysis skipped: %w", &IllTypedError{Pkg: act.pkg}) } else { startedAt = time.Now() act.result, act.err = pass.Analyzer.Run(pass) diff --git a/pkg/golinters/goanalysis/runner_loadingpackage.go b/pkg/golinters/goanalysis/runner_loadingpackage.go index e76b6ab6ee99..e39e2212c392 100644 --- a/pkg/golinters/goanalysis/runner_loadingpackage.go +++ b/pkg/golinters/goanalysis/runner_loadingpackage.go @@ -1,6 +1,7 @@ package goanalysis import ( + "errors" "fmt" "go/ast" "go/parser" @@ -11,7 +12,6 @@ import ( "sync" "sync/atomic" - "github.com/pkg/errors" "golang.org/x/tools/go/gcexportdata" "golang.org/x/tools/go/packages" @@ -59,7 +59,7 @@ func (lp *loadingPackage) analyze(loadMode LoadMode, loadSem chan struct{}) { defer lp.decUse(loadMode < LoadModeWholeProgram) if err := lp.loadWithFacts(loadMode); err != nil { - werr := errors.Wrapf(err, "failed to load package %s", lp.pkg.Name) + werr := fmt.Errorf("failed to load package %s: %w", lp.pkg.Name, err) // Don't need to write error to errCh, it will be extracted and reported on another layer. // Unblock depending on actions and propagate error. for _, act := range lp.actions { @@ -290,7 +290,7 @@ func (lp *loadingPackage) loadImportedPackageWithFacts(loadMode LoadMode) error Msg: fmt.Sprintf("could not load export data: %s", err), Kind: packages.ParseError, }) - return errors.Wrap(err, "could not load export data") + return fmt.Errorf("could not load export data: %w", err) } } @@ -446,7 +446,7 @@ type importerFunc func(path string) (*types.Package, error) func (f importerFunc) Import(path string) (*types.Package, error) { return f(path) } -func sizeOfValueTreeBytes(v interface{}) int { +func sizeOfValueTreeBytes(v any) int { return sizeOfReflectValueTreeBytes(reflect.ValueOf(v), map[uintptr]struct{}{}) } diff --git a/pkg/golinters/goanalysis/runners.go b/pkg/golinters/goanalysis/runners.go index 559fb1392b96..c5a0b61261bf 100644 --- a/pkg/golinters/goanalysis/runners.go +++ b/pkg/golinters/goanalysis/runners.go @@ -124,7 +124,8 @@ func getIssuesCacheKey(analyzers []*analysis.Analyzer) string { } func saveIssuesToCache(allPkgs []*packages.Package, pkgsFromCache map[*packages.Package]bool, - issues []result.Issue, lintCtx *linter.Context, analyzers []*analysis.Analyzer) { + issues []result.Issue, lintCtx *linter.Context, analyzers []*analysis.Analyzer, +) { startedAt := time.Now() perPkgIssues := map[*packages.Package][]result.Issue{} for ind := range issues { @@ -151,6 +152,7 @@ func saveIssuesToCache(allPkgs []*packages.Package, pkgsFromCache map[*packages. encodedIssues = append(encodedIssues, EncodingIssue{ FromLinter: i.FromLinter, Text: i.Text, + Severity: i.Severity, Pos: i.Pos, LineRange: i.LineRange, Replacement: i.Replacement, @@ -184,7 +186,8 @@ func saveIssuesToCache(allPkgs []*packages.Package, pkgsFromCache map[*packages. //nolint:gocritic func loadIssuesFromCache(pkgs []*packages.Package, lintCtx *linter.Context, - analyzers []*analysis.Analyzer) ([]result.Issue, map[*packages.Package]bool) { + analyzers []*analysis.Analyzer, +) ([]result.Issue, map[*packages.Package]bool) { startedAt := time.Now() lintResKey := getIssuesCacheKey(analyzers) @@ -222,6 +225,7 @@ func loadIssuesFromCache(pkgs []*packages.Package, lintCtx *linter.Context, issues = append(issues, result.Issue{ FromLinter: i.FromLinter, Text: i.Text, + Severity: i.Severity, Pos: i.Pos, LineRange: i.LineRange, Replacement: i.Replacement, diff --git a/pkg/golinters/gochecknoglobals.go b/pkg/golinters/gochecknoglobals.go index 0fe67e2b0fd8..f889bca8286e 100644 --- a/pkg/golinters/gochecknoglobals.go +++ b/pkg/golinters/gochecknoglobals.go @@ -8,22 +8,19 @@ import ( ) func NewGochecknoglobals() *goanalysis.Linter { - gochecknoglobals := checknoglobals.Analyzer() + a := checknoglobals.Analyzer() - // gochecknoglobals only lints test files if the `-t` flag is passed, so we - // pass the `t` flag as true to the analyzer before running it. This can be - // turned off by using the regular golangci-lint flags such as `--tests` or - // `--skip-files`. - linterConfig := map[string]map[string]interface{}{ - gochecknoglobals.Name: { - "t": true, - }, + // gochecknoglobals only lints test files if the `-t` flag is passed, + // so we pass the `t` flag as true to the analyzer before running it. + // This can be turned off by using the regular golangci-lint flags such as `--tests` or `--skip-files`. + linterConfig := map[string]map[string]any{ + a.Name: {"t": true}, } return goanalysis.NewLinter( - gochecknoglobals.Name, - gochecknoglobals.Doc, - []*analysis.Analyzer{gochecknoglobals}, + a.Name, + "Check that no global variables exist.", + []*analysis.Analyzer{a}, linterConfig, ).WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/gochecknoinits.go b/pkg/golinters/gochecknoinits.go index bb0b783c6cab..a51b531b94ad 100644 --- a/pkg/golinters/gochecknoinits.go +++ b/pkg/golinters/gochecknoinits.go @@ -22,7 +22,7 @@ func NewGochecknoinits() *goanalysis.Linter { analyzer := &analysis.Analyzer{ Name: gochecknoinitsName, Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (interface{}, error) { + Run: func(pass *analysis.Pass) (any, error) { var res []goanalysis.Issue for _, file := range pass.Files { fileIssues := checkFileForInits(file, pass.Fset) diff --git a/pkg/golinters/gochecksumtype.go b/pkg/golinters/gochecksumtype.go new file mode 100644 index 000000000000..5516179dfccb --- /dev/null +++ b/pkg/golinters/gochecksumtype.go @@ -0,0 +1,80 @@ +package golinters + +import ( + "strings" + "sync" + + gochecksumtype "github.com/alecthomas/go-check-sumtype" + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/packages" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +const goCheckSumTypeName = "gochecksumtype" + +func NewGoCheckSumType() *goanalysis.Linter { + var mu sync.Mutex + var resIssues []goanalysis.Issue + + analyzer := &analysis.Analyzer{ + Name: goCheckSumTypeName, + Doc: goanalysis.TheOnlyanalyzerDoc, + Run: func(pass *analysis.Pass) (any, error) { + issues, err := runGoCheckSumType(pass) + if err != nil { + return nil, err + } + + if len(issues) == 0 { + return nil, nil + } + + mu.Lock() + resIssues = append(resIssues, issues...) + mu.Unlock() + + return nil, nil + }, + } + + return goanalysis.NewLinter( + goCheckSumTypeName, + `Run exhaustiveness checks on Go "sum types"`, + []*analysis.Analyzer{analyzer}, + nil, + ).WithIssuesReporter(func(_ *linter.Context) []goanalysis.Issue { + return resIssues + }).WithLoadMode(goanalysis.LoadModeTypesInfo) +} + +func runGoCheckSumType(pass *analysis.Pass) ([]goanalysis.Issue, error) { + var resIssues []goanalysis.Issue + + pkg := &packages.Package{ + Fset: pass.Fset, + Syntax: pass.Files, + Types: pass.Pkg, + TypesInfo: pass.TypesInfo, + } + + var unknownError error + errors := gochecksumtype.Run([]*packages.Package{pkg}) + for _, err := range errors { + err, ok := err.(gochecksumtype.Error) + if !ok { + unknownError = err + continue + } + + resIssues = append(resIssues, goanalysis.NewIssue(&result.Issue{ + FromLinter: goCheckSumTypeName, + Text: strings.TrimPrefix(err.Error(), err.Pos().String()+": "), + Pos: err.Pos(), + }, pass)) + } + + return resIssues, unknownError +} diff --git a/pkg/golinters/gocognit.go b/pkg/golinters/gocognit.go index 49146c52c8f5..406d34ed6cb8 100644 --- a/pkg/golinters/gocognit.go +++ b/pkg/golinters/gocognit.go @@ -24,7 +24,7 @@ func NewGocognit(settings *config.GocognitSettings) *goanalysis.Linter { analyzer := &analysis.Analyzer{ Name: goanalysis.TheOnlyAnalyzerName, Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (interface{}, error) { + Run: func(pass *analysis.Pass) (any, error) { issues := runGocognit(pass, settings) if len(issues) == 0 { diff --git a/pkg/golinters/goconst.go b/pkg/golinters/goconst.go index 24d3198b9a0d..b5188527546b 100644 --- a/pkg/golinters/goconst.go +++ b/pkg/golinters/goconst.go @@ -23,7 +23,7 @@ func NewGoconst(settings *config.GoConstSettings) *goanalysis.Linter { analyzer := &analysis.Analyzer{ Name: goconstName, Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (interface{}, error) { + Run: func(pass *analysis.Pass) (any, error) { issues, err := runGoconst(pass, settings) if err != nil { return nil, err @@ -53,6 +53,7 @@ func NewGoconst(settings *config.GoConstSettings) *goanalysis.Linter { func runGoconst(pass *analysis.Pass, settings *config.GoConstSettings) ([]goanalysis.Issue, error) { cfg := goconstAPI.Config{ + IgnoreStrings: settings.IgnoreStrings, IgnoreTests: settings.IgnoreTests, MatchWithConstants: settings.MatchWithConstants, MinStringLength: settings.MinStringLen, diff --git a/pkg/golinters/gocritic.go b/pkg/golinters/gocritic.go index 0b4af06a4ce7..7fc791db3f02 100644 --- a/pkg/golinters/gocritic.go +++ b/pkg/golinters/gocritic.go @@ -1,6 +1,7 @@ package golinters import ( + "errors" "fmt" "go/ast" "go/types" @@ -12,8 +13,9 @@ import ( "sync" "github.com/go-critic/go-critic/checkers" - gocriticlinter "github.com/go-critic/go-critic/framework/linter" - "github.com/pkg/errors" + gocriticlinter "github.com/go-critic/go-critic/linter" + "golang.org/x/exp/maps" + "golang.org/x/exp/slices" "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/pkg/config" @@ -35,14 +37,14 @@ func NewGoCritic(settings *config.GoCriticSettings, cfg *config.Config) *goanaly var resIssues []goanalysis.Issue wrapper := &goCriticWrapper{ - cfg: cfg, - sizes: types.SizesFor("gc", runtime.GOARCH), + getConfigDir: cfg.GetConfigDir, // Config directory is filled after calling this constructor. + sizes: types.SizesFor("gc", runtime.GOARCH), } analyzer := &analysis.Analyzer{ Name: goCriticName, Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (interface{}, error) { + Run: func(pass *analysis.Pass) (any, error) { issues, err := wrapper.run(pass) if err != nil { return nil, err @@ -73,12 +75,13 @@ Dynamic rules are written declaratively with AST patterns, filters, report messa }). WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { return resIssues - }).WithLoadMode(goanalysis.LoadModeTypesInfo) + }). + WithLoadMode(goanalysis.LoadModeTypesInfo) } type goCriticWrapper struct { settingsWrapper *goCriticSettingsWrapper - cfg *config.Config + getConfigDir func() string sizes types.Sizes once sync.Once } @@ -91,15 +94,15 @@ func (w *goCriticWrapper) init(settings *config.GoCriticSettings, logger logutil w.once.Do(func() { err := checkers.InitEmbeddedRules() if err != nil { - logger.Fatalf("%s: %v: setting an explicit GOROOT can fix this problem.", goCriticName, err) + logger.Fatalf("%s: %v: setting an explicit GOROOT can fix this problem", goCriticName, err) } }) settingsWrapper := newGoCriticSettingsWrapper(settings, logger) - - settingsWrapper.inferEnabledChecks() - - if err := settingsWrapper.validate(); err != nil { + settingsWrapper.InferEnabledChecks() + // Validate must be after InferEnabledChecks, not before. + // Because it uses gathered information about tags set and finally enabled checks. + if err := settingsWrapper.Validate(); err != nil { logger.Fatalf("%s: invalid settings: %s", goCriticName, err) } @@ -108,11 +111,13 @@ func (w *goCriticWrapper) init(settings *config.GoCriticSettings, logger logutil func (w *goCriticWrapper) run(pass *analysis.Pass) ([]goanalysis.Issue, error) { if w.settingsWrapper == nil { - return nil, fmt.Errorf("the settings wrapper is nil") + return nil, errors.New("the settings wrapper is nil") } linterCtx := gocriticlinter.NewContext(pass.Fset, w.sizes) + linterCtx.SetGoVersion(w.settingsWrapper.Go) + enabledCheckers, err := w.buildEnabledCheckers(linterCtx) if err != nil { return nil, err @@ -120,7 +125,7 @@ func (w *goCriticWrapper) run(pass *analysis.Pass) ([]goanalysis.Issue, error) { linterCtx.SetPackageInfo(pass.TypesInfo, pass.Pkg) - pkgIssues := runGocriticOnPackage(linterCtx, enabledCheckers, pass.Files) + pkgIssues := runGoCriticOnPackage(linterCtx, enabledCheckers, pass.Files) issues := make([]goanalysis.Issue, 0, len(pkgIssues)) for i := range pkgIssues { @@ -131,15 +136,15 @@ func (w *goCriticWrapper) run(pass *analysis.Pass) ([]goanalysis.Issue, error) { } func (w *goCriticWrapper) buildEnabledCheckers(linterCtx *gocriticlinter.Context) ([]*gocriticlinter.Checker, error) { - allParams := w.settingsWrapper.getLowerCasedParams() + allLowerCasedParams := w.settingsWrapper.GetLowerCasedParams() var enabledCheckers []*gocriticlinter.Checker for _, info := range gocriticlinter.GetCheckersInfo() { - if !w.settingsWrapper.isCheckEnabled(info.Name) { + if !w.settingsWrapper.IsCheckEnabled(info.Name) { continue } - if err := w.configureCheckerInfo(info, allParams); err != nil { + if err := w.configureCheckerInfo(info, allLowerCasedParams); err != nil { return nil, err } @@ -153,57 +158,17 @@ func (w *goCriticWrapper) buildEnabledCheckers(linterCtx *gocriticlinter.Context return enabledCheckers, nil } -func runGocriticOnPackage(linterCtx *gocriticlinter.Context, checks []*gocriticlinter.Checker, - files []*ast.File) []result.Issue { - var res []result.Issue - for _, f := range files { - filename := filepath.Base(linterCtx.FileSet.Position(f.Pos()).Filename) - linterCtx.SetFileInfo(filename, f) - - issues := runGocriticOnFile(linterCtx, f, checks) - res = append(res, issues...) - } - return res -} - -func runGocriticOnFile(linterCtx *gocriticlinter.Context, f *ast.File, checks []*gocriticlinter.Checker) []result.Issue { - var res []result.Issue - - for _, c := range checks { - // All checkers are expected to use *lint.Context - // as read-only structure, so no copying is required. - for _, warn := range c.Check(f) { - pos := linterCtx.FileSet.Position(warn.Node.Pos()) - issue := result.Issue{ - Pos: pos, - Text: fmt.Sprintf("%s: %s", c.Info.Name, warn.Text), - FromLinter: goCriticName, - } - - if warn.HasQuickFix() { - issue.Replacement = &result.Replacement{ - Inline: &result.InlineFix{ - StartCol: pos.Column - 1, - Length: int(warn.Node.End() - warn.Node.Pos()), - NewString: string(warn.Suggestion.Replacement), - }, - } - } - - res = append(res, issue) - } - } - - return res -} - -func (w *goCriticWrapper) configureCheckerInfo(info *gocriticlinter.CheckerInfo, allParams map[string]config.GoCriticCheckSettings) error { - params := allParams[strings.ToLower(info.Name)] +func (w *goCriticWrapper) configureCheckerInfo( + info *gocriticlinter.CheckerInfo, + allLowerCasedParams map[string]config.GoCriticCheckSettings, +) error { + params := allLowerCasedParams[strings.ToLower(info.Name)] if params == nil { // no config for this checker return nil } - infoParams := normalizeCheckerInfoParams(info) + // To lowercase info param keys here because golangci-lint's config parser lowercases all strings. + infoParams := normalizeMap(info.Params) for k, p := range params { v, ok := infoParams[k] if ok { @@ -217,10 +182,7 @@ func (w *goCriticWrapper) configureCheckerInfo(info *gocriticlinter.CheckerInfo, info.Name, k) } - var supportedKeys []string - for sk := range info.Params { - supportedKeys = append(supportedKeys, sk) - } + supportedKeys := maps.Keys(info.Params) sort.Strings(supportedKeys) return fmt.Errorf("checker %s config param %s doesn't exist, all existing: %s", @@ -230,22 +192,12 @@ func (w *goCriticWrapper) configureCheckerInfo(info *gocriticlinter.CheckerInfo, return nil } -func normalizeCheckerInfoParams(info *gocriticlinter.CheckerInfo) gocriticlinter.CheckerParams { - // lowercase info param keys here because golangci-lint's config parser lowercases all strings - ret := gocriticlinter.CheckerParams{} - for k, v := range info.Params { - ret[strings.ToLower(k)] = v - } - - return ret -} - // normalizeCheckerParamsValue normalizes value types. // go-critic asserts that CheckerParam.Value has some specific types, // but the file parsers (TOML, YAML, JSON) don't create the same representation for raw type. // then we have to convert value types into the expected value types. // Maybe in the future, this kind of conversion will be done in go-critic itself. -func (w *goCriticWrapper) normalizeCheckerParamsValue(p interface{}) interface{} { +func (w *goCriticWrapper) normalizeCheckerParamsValue(p any) any { rv := reflect.ValueOf(p) switch rv.Type().Kind() { case reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, reflect.Int: @@ -254,386 +206,383 @@ func (w *goCriticWrapper) normalizeCheckerParamsValue(p interface{}) interface{} return rv.Bool() case reflect.String: // Perform variable substitution. - return strings.ReplaceAll(rv.String(), "${configDir}", w.cfg.GetConfigDir()) + return strings.ReplaceAll(rv.String(), "${configDir}", w.getConfigDir()) default: return p } } -// TODO(ldez): rewrite and simplify goCriticSettingsWrapper. - -type goCriticSettingsWrapper struct { - *config.GoCriticSettings +func runGoCriticOnPackage(linterCtx *gocriticlinter.Context, checks []*gocriticlinter.Checker, files []*ast.File) []result.Issue { + var res []result.Issue + for _, f := range files { + filename := filepath.Base(linterCtx.FileSet.Position(f.Pos()).Filename) + linterCtx.SetFileInfo(filename, f) - logger logutils.Log + issues := runGoCriticOnFile(linterCtx, f, checks) + res = append(res, issues...) + } + return res +} - allCheckers []*gocriticlinter.CheckerInfo - allCheckerMap map[string]*gocriticlinter.CheckerInfo +func runGoCriticOnFile(linterCtx *gocriticlinter.Context, f *ast.File, checks []*gocriticlinter.Checker) []result.Issue { + var res []result.Issue - inferredEnabledChecks map[string]bool -} + for _, c := range checks { + // All checkers are expected to use *lint.Context + // as read-only structure, so no copying is required. + for _, warn := range c.Check(f) { + pos := linterCtx.FileSet.Position(warn.Pos) + issue := result.Issue{ + Pos: pos, + Text: fmt.Sprintf("%s: %s", c.Info.Name, warn.Text), + FromLinter: goCriticName, + } -func newGoCriticSettingsWrapper(settings *config.GoCriticSettings, logger logutils.Log) *goCriticSettingsWrapper { - allCheckers := gocriticlinter.GetCheckersInfo() + if warn.HasQuickFix() { + issue.Replacement = &result.Replacement{ + Inline: &result.InlineFix{ + StartCol: pos.Column - 1, + Length: int(warn.Suggestion.To - warn.Suggestion.From), + NewString: string(warn.Suggestion.Replacement), + }, + } + } - allCheckerMap := make(map[string]*gocriticlinter.CheckerInfo) - for _, checkInfo := range allCheckers { - allCheckerMap[checkInfo.Name] = checkInfo + res = append(res, issue) + } } - return &goCriticSettingsWrapper{ - GoCriticSettings: settings, - logger: logger, - allCheckers: allCheckers, - allCheckerMap: allCheckerMap, - inferredEnabledChecks: map[string]bool{}, - } + return res } -func (s *goCriticSettingsWrapper) buildTagToCheckersMap() map[string][]string { - tagToCheckers := map[string][]string{} - - for _, checker := range s.allCheckers { - for _, tag := range checker.Tags { - tagToCheckers[tag] = append(tagToCheckers[tag], checker.Name) - } - } +type goCriticChecks[T any] map[string]T - return tagToCheckers +func (m goCriticChecks[T]) has(name string) bool { + _, ok := m[name] + return ok } -func (s *goCriticSettingsWrapper) checkerTagsDebugf() { - if !isGoCriticDebug { - return - } +type goCriticSettingsWrapper struct { + *config.GoCriticSettings - tagToCheckers := s.buildTagToCheckersMap() + logger logutils.Log - allTags := make([]string, 0, len(tagToCheckers)) - for tag := range tagToCheckers { - allTags = append(allTags, tag) - } + allCheckers []*gocriticlinter.CheckerInfo - sort.Strings(allTags) + allChecks goCriticChecks[struct{}] + allChecksByTag goCriticChecks[[]string] + allTagsSorted []string + inferredEnabledChecks goCriticChecks[struct{}] - goCriticDebugf("All gocritic existing tags and checks:") - for _, tag := range allTags { - debugChecksListf(tagToCheckers[tag], " tag %q", tag) - } + // *LowerCased fields are used for GoCriticSettings.SettingsPerCheck validation only. + + allChecksLowerCased goCriticChecks[struct{}] + inferredEnabledChecksLowerCased goCriticChecks[struct{}] } -func (s *goCriticSettingsWrapper) disabledCheckersDebugf() { - if !isGoCriticDebug { - return - } +func newGoCriticSettingsWrapper(settings *config.GoCriticSettings, logger logutils.Log) *goCriticSettingsWrapper { + allCheckers := gocriticlinter.GetCheckersInfo() - var disabledCheckers []string - for _, checker := range s.allCheckers { - if s.inferredEnabledChecks[strings.ToLower(checker.Name)] { - continue - } + allChecks := make(goCriticChecks[struct{}], len(allCheckers)) + allChecksLowerCased := make(goCriticChecks[struct{}], len(allCheckers)) + allChecksByTag := make(goCriticChecks[[]string]) + for _, checker := range allCheckers { + allChecks[checker.Name] = struct{}{} + allChecksLowerCased[strings.ToLower(checker.Name)] = struct{}{} - disabledCheckers = append(disabledCheckers, checker.Name) + for _, tag := range checker.Tags { + allChecksByTag[tag] = append(allChecksByTag[tag], checker.Name) + } } - if len(disabledCheckers) == 0 { - goCriticDebugf("All checks are enabled") - } else { - debugChecksListf(disabledCheckers, "Final not used") + allTagsSorted := maps.Keys(allChecksByTag) + sort.Strings(allTagsSorted) + + return &goCriticSettingsWrapper{ + GoCriticSettings: settings, + logger: logger, + allCheckers: allCheckers, + allChecks: allChecks, + allChecksLowerCased: allChecksLowerCased, + allChecksByTag: allChecksByTag, + allTagsSorted: allTagsSorted, + inferredEnabledChecks: make(goCriticChecks[struct{}]), + inferredEnabledChecksLowerCased: make(goCriticChecks[struct{}]), } } -func (s *goCriticSettingsWrapper) inferEnabledChecks() { - s.checkerTagsDebugf() +func (s *goCriticSettingsWrapper) IsCheckEnabled(name string) bool { + return s.inferredEnabledChecks.has(name) +} - enabledByDefaultChecks := s.getDefaultEnabledCheckersNames() - debugChecksListf(enabledByDefaultChecks, "Enabled by default") +func (s *goCriticSettingsWrapper) GetLowerCasedParams() map[string]config.GoCriticCheckSettings { + return normalizeMap(s.SettingsPerCheck) +} - disabledByDefaultChecks := s.getDefaultDisabledCheckersNames() +// InferEnabledChecks tries to be consistent with (lintersdb.EnabledSet).build. +func (s *goCriticSettingsWrapper) InferEnabledChecks() { + s.debugChecksInitialState() + + enabledByDefaultChecks, disabledByDefaultChecks := s.buildEnabledAndDisabledByDefaultChecks() + debugChecksListf(enabledByDefaultChecks, "Enabled by default") debugChecksListf(disabledByDefaultChecks, "Disabled by default") - enabledChecks := make([]string, 0, len(s.EnabledTags)+len(enabledByDefaultChecks)) + enabledChecks := make(goCriticChecks[struct{}]) - // EnabledTags - if len(s.EnabledTags) != 0 { - tagToCheckers := s.buildTagToCheckersMap() - for _, tag := range s.EnabledTags { - enabledChecks = append(enabledChecks, tagToCheckers[tag]...) + if s.EnableAll { + enabledChecks = make(goCriticChecks[struct{}], len(s.allCheckers)) + for _, info := range s.allCheckers { + enabledChecks[info.Name] = struct{}{} + } + } else if !s.DisableAll { + // enable-all/disable-all revokes the default settings. + enabledChecks = make(goCriticChecks[struct{}], len(enabledByDefaultChecks)) + for _, check := range enabledByDefaultChecks { + enabledChecks[check] = struct{}{} } - - debugChecksListf(enabledChecks, "Enabled by config tags %s", sprintStrings(s.EnabledTags)) } - if !(len(s.EnabledTags) == 0 && len(s.EnabledChecks) != 0) { - // don't use default checks only if we have no enabled tags and enable some checks manually - enabledChecks = append(enabledChecks, enabledByDefaultChecks...) - } + if len(s.EnabledTags) != 0 { + enabledFromTags := s.expandTagsToChecks(s.EnabledTags) + debugChecksListf(enabledFromTags, "Enabled by config tags %s", sprintSortedStrings(s.EnabledTags)) - // DisabledTags - if len(s.DisabledTags) != 0 { - enabledChecks = s.filterByDisableTags(enabledChecks, s.DisabledTags) + for _, check := range enabledFromTags { + enabledChecks[check] = struct{}{} + } } - // EnabledChecks if len(s.EnabledChecks) != 0 { debugChecksListf(s.EnabledChecks, "Enabled by config") - alreadyEnabledChecksSet := stringsSliceToSet(enabledChecks) - for _, enabledCheck := range s.EnabledChecks { - if alreadyEnabledChecksSet[enabledCheck] { - s.logger.Warnf("%s: no need to enable check %q: it's already enabled", goCriticName, enabledCheck) + for _, check := range s.EnabledChecks { + if enabledChecks.has(check) { + s.logger.Warnf("%s: no need to enable check %q: it's already enabled", goCriticName, check) continue } - enabledChecks = append(enabledChecks, enabledCheck) + enabledChecks[check] = struct{}{} + } + } + + if len(s.DisabledTags) != 0 { + disabledFromTags := s.expandTagsToChecks(s.DisabledTags) + debugChecksListf(disabledFromTags, "Disabled by config tags %s", sprintSortedStrings(s.DisabledTags)) + + for _, check := range disabledFromTags { + delete(enabledChecks, check) } } - // DisabledChecks if len(s.DisabledChecks) != 0 { debugChecksListf(s.DisabledChecks, "Disabled by config") - enabledChecksSet := stringsSliceToSet(enabledChecks) - for _, disabledCheck := range s.DisabledChecks { - if !enabledChecksSet[disabledCheck] { - s.logger.Warnf("%s: check %q was explicitly disabled via config. However, as this check "+ - "is disabled by default, there is no need to explicitly disable it via config.", goCriticName, disabledCheck) + for _, check := range s.DisabledChecks { + if !enabledChecks.has(check) { + s.logger.Warnf("%s: no need to disable check %q: it's already disabled", goCriticName, check) continue } - delete(enabledChecksSet, disabledCheck) + delete(enabledChecks, check) } + } + + s.inferredEnabledChecks = enabledChecks + s.inferredEnabledChecksLowerCased = normalizeMap(s.inferredEnabledChecks) + s.debugChecksFinalState() +} - enabledChecks = nil - for enabledCheck := range enabledChecksSet { - enabledChecks = append(enabledChecks, enabledCheck) +func (s *goCriticSettingsWrapper) buildEnabledAndDisabledByDefaultChecks() (enabled, disabled []string) { + for _, info := range s.allCheckers { + if enabledByDef := isEnabledByDefaultGoCriticChecker(info); enabledByDef { + enabled = append(enabled, info.Name) + } else { + disabled = append(disabled, info.Name) } } + return enabled, disabled +} - s.inferredEnabledChecks = map[string]bool{} - for _, check := range enabledChecks { - s.inferredEnabledChecks[strings.ToLower(check)] = true +func (s *goCriticSettingsWrapper) expandTagsToChecks(tags []string) []string { + var checks []string + for _, tag := range tags { + checks = append(checks, s.allChecksByTag[tag]...) } - - debugChecksListf(enabledChecks, "Final used") - - s.disabledCheckersDebugf() + return checks } -func (s *goCriticSettingsWrapper) validate() error { - if len(s.EnabledTags) == 0 { - if len(s.EnabledChecks) != 0 && len(s.DisabledChecks) != 0 { - return errors.New("both enabled and disabled check aren't allowed for gocritic") - } - } else { - if err := validateStringsUniq(s.EnabledTags); err != nil { - return errors.Wrap(err, "validate enabled tags") - } +func (s *goCriticSettingsWrapper) debugChecksInitialState() { + if !isGoCriticDebug { + return + } - tagToCheckers := s.buildTagToCheckersMap() + goCriticDebugf("All gocritic existing tags and checks:") + for _, tag := range s.allTagsSorted { + debugChecksListf(s.allChecksByTag[tag], " tag %q", tag) + } +} - for _, tag := range s.EnabledTags { - if _, ok := tagToCheckers[tag]; !ok { - return fmt.Errorf("gocritic [enabled]tag %q doesn't exist", tag) - } - } +func (s *goCriticSettingsWrapper) debugChecksFinalState() { + if !isGoCriticDebug { + return } - if len(s.DisabledTags) > 0 { - tagToCheckers := s.buildTagToCheckersMap() - for _, tag := range s.EnabledTags { - if _, ok := tagToCheckers[tag]; !ok { - return fmt.Errorf("gocritic [disabled]tag %q doesn't exist", tag) - } + var enabledChecks []string + var disabledChecks []string + + for _, checker := range s.allCheckers { + name := checker.Name + if s.inferredEnabledChecks.has(name) { + enabledChecks = append(enabledChecks, name) + } else { + disabledChecks = append(disabledChecks, name) } } - if err := validateStringsUniq(s.EnabledChecks); err != nil { - return errors.Wrap(err, "validate enabled checks") - } + debugChecksListf(enabledChecks, "Final used") - if err := validateStringsUniq(s.DisabledChecks); err != nil { - return errors.Wrap(err, "validate disabled checks") + if len(disabledChecks) == 0 { + goCriticDebugf("All checks are enabled") + } else { + debugChecksListf(disabledChecks, "Final not used") } +} - if err := s.validateCheckerNames(); err != nil { - return errors.Wrap(err, "validation failed") +// Validate tries to be consistent with (lintersdb.Validator).validateEnabledDisabledLintersConfig. +func (s *goCriticSettingsWrapper) Validate() error { + for _, v := range []func() error{ + s.validateOptionsCombinations, + s.validateCheckerTags, + s.validateCheckerNames, + s.validateDisabledAndEnabledAtOneMoment, + s.validateAtLeastOneCheckerEnabled, + } { + if err := v(); err != nil { + return err + } } - return nil } -func (s *goCriticSettingsWrapper) isCheckEnabled(name string) bool { - return s.inferredEnabledChecks[strings.ToLower(name)] -} +func (s *goCriticSettingsWrapper) validateOptionsCombinations() error { + if s.EnableAll { + if s.DisableAll { + return errors.New("enable-all and disable-all options must not be combined") + } -// getAllCheckerNames returns a map containing all checker names supported by gocritic. -func (s *goCriticSettingsWrapper) getAllCheckerNames() map[string]bool { - allCheckerNames := make(map[string]bool, len(s.allCheckers)) + if len(s.EnabledTags) != 0 { + return errors.New("enable-all and enabled-tags options must not be combined") + } - for _, checker := range s.allCheckers { - allCheckerNames[strings.ToLower(checker.Name)] = true + if len(s.EnabledChecks) != 0 { + return errors.New("enable-all and enabled-checks options must not be combined") + } } - return allCheckerNames -} + if s.DisableAll { + if len(s.DisabledTags) != 0 { + return errors.New("disable-all and disabled-tags options must not be combined") + } -func (s *goCriticSettingsWrapper) getDefaultEnabledCheckersNames() []string { - var enabled []string + if len(s.DisabledChecks) != 0 { + return errors.New("disable-all and disabled-checks options must not be combined") + } - for _, info := range s.allCheckers { - enable := s.isEnabledByDefaultCheck(info) - if enable { - enabled = append(enabled, info.Name) + if len(s.EnabledTags) == 0 && len(s.EnabledChecks) == 0 { + return errors.New("all checks were disabled, but no one check was enabled: at least one must be enabled") } } - return enabled + return nil } -func (s *goCriticSettingsWrapper) getDefaultDisabledCheckersNames() []string { - var disabled []string +func (s *goCriticSettingsWrapper) validateCheckerTags() error { + for _, tag := range s.EnabledTags { + if !s.allChecksByTag.has(tag) { + return fmt.Errorf("enabled tag %q doesn't exist, see %s's documentation", tag, goCriticName) + } + } - for _, info := range s.allCheckers { - enable := s.isEnabledByDefaultCheck(info) - if !enable { - disabled = append(disabled, info.Name) + for _, tag := range s.DisabledTags { + if !s.allChecksByTag.has(tag) { + return fmt.Errorf("disabled tag %q doesn't exist, see %s's documentation", tag, goCriticName) } } - return disabled + return nil } func (s *goCriticSettingsWrapper) validateCheckerNames() error { - allowedNames := s.getAllCheckerNames() - for _, name := range s.EnabledChecks { - if !allowedNames[strings.ToLower(name)] { - return fmt.Errorf("enabled checker %s doesn't exist, all existing checkers: %s", - name, sprintAllowedCheckerNames(allowedNames)) + if !s.allChecks.has(name) { + return fmt.Errorf("enabled check %q doesn't exist, see %s's documentation", name, goCriticName) } } for _, name := range s.DisabledChecks { - if !allowedNames[strings.ToLower(name)] { - return fmt.Errorf("disabled checker %s doesn't exist, all existing checkers: %s", - name, sprintAllowedCheckerNames(allowedNames)) + if !s.allChecks.has(name) { + return fmt.Errorf("disabled check %q doesn't exist, see %s documentation", name, goCriticName) } } - for checkName := range s.SettingsPerCheck { - if _, ok := allowedNames[checkName]; !ok { - return fmt.Errorf("invalid setting, checker %s doesn't exist, all existing checkers: %s", - checkName, sprintAllowedCheckerNames(allowedNames)) + for name := range s.SettingsPerCheck { + lcName := strings.ToLower(name) + if !s.allChecksLowerCased.has(lcName) { + return fmt.Errorf("invalid check settings: check %q doesn't exist, see %s documentation", name, goCriticName) } - - if !s.isCheckEnabled(checkName) { - s.logger.Warnf("%s: settings were provided for not enabled check %q", goCriticName, checkName) + if !s.inferredEnabledChecksLowerCased.has(lcName) { + s.logger.Warnf("%s: settings were provided for disabled check %q", goCriticName, name) } } return nil } -func (s *goCriticSettingsWrapper) getLowerCasedParams() map[string]config.GoCriticCheckSettings { - ret := make(map[string]config.GoCriticCheckSettings, len(s.SettingsPerCheck)) - - for checker, params := range s.SettingsPerCheck { - ret[strings.ToLower(checker)] = params - } - - return ret -} - -func (s *goCriticSettingsWrapper) filterByDisableTags(enabledChecks, disableTags []string) []string { - enabledChecksSet := stringsSliceToSet(enabledChecks) - - for _, enabledCheck := range enabledChecks { - checkInfo, checkInfoExists := s.allCheckerMap[enabledCheck] - if !checkInfoExists { - s.logger.Warnf("%s: check %q was not exists via filtering disabled tags", goCriticName, enabledCheck) - continue +func (s *goCriticSettingsWrapper) validateDisabledAndEnabledAtOneMoment() error { + for _, tag := range s.DisabledTags { + if slices.Contains(s.EnabledTags, tag) { + return fmt.Errorf("tag %q disabled and enabled at one moment", tag) } - - hitTags := intersectStringSlice(checkInfo.Tags, disableTags) - if len(hitTags) != 0 { - delete(enabledChecksSet, enabledCheck) - } - } - - debugChecksListf(enabledChecks, "Disabled by config tags %s", sprintStrings(disableTags)) - - enabledChecks = nil - for enabledCheck := range enabledChecksSet { - enabledChecks = append(enabledChecks, enabledCheck) } - return enabledChecks -} - -func (s *goCriticSettingsWrapper) isEnabledByDefaultCheck(info *gocriticlinter.CheckerInfo) bool { - return !info.HasTag("experimental") && - !info.HasTag("opinionated") && - !info.HasTag("performance") -} - -func validateStringsUniq(ss []string) error { - set := map[string]bool{} - - for _, s := range ss { - _, ok := set[s] - if ok { - return fmt.Errorf("%q occurs multiple times in list", s) + for _, check := range s.DisabledChecks { + if slices.Contains(s.EnabledChecks, check) { + return fmt.Errorf("check %q disabled and enabled at one moment", check) } - set[s] = true } return nil } -func intersectStringSlice(s1, s2 []string) []string { - s1Map := make(map[string]struct{}, len(s1)) - - for _, s := range s1 { - s1Map[s] = struct{}{} - } - - results := make([]string, 0) - for _, s := range s2 { - if _, exists := s1Map[s]; exists { - results = append(results, s) - } +func (s *goCriticSettingsWrapper) validateAtLeastOneCheckerEnabled() error { + if len(s.inferredEnabledChecks) == 0 { + return errors.New("eventually all checks were disabled: at least one must be enabled") } - - return results + return nil } -func sprintAllowedCheckerNames(allowedNames map[string]bool) string { - namesSlice := make([]string, 0, len(allowedNames)) - - for name := range allowedNames { - namesSlice = append(namesSlice, name) +func normalizeMap[ValueT any](in map[string]ValueT) map[string]ValueT { + ret := make(map[string]ValueT, len(in)) + for k, v := range in { + ret[strings.ToLower(k)] = v } - - return sprintStrings(namesSlice) + return ret } -func sprintStrings(ss []string) string { - sort.Strings(ss) - return fmt.Sprint(ss) +func isEnabledByDefaultGoCriticChecker(info *gocriticlinter.CheckerInfo) bool { + // https://github.com/go-critic/go-critic/blob/5b67cfd487ae9fe058b4b19321901b3131810f65/cmd/gocritic/check.go#L342-L345 + return !info.HasTag(gocriticlinter.ExperimentalTag) && + !info.HasTag(gocriticlinter.OpinionatedTag) && + !info.HasTag(gocriticlinter.PerformanceTag) && + !info.HasTag(gocriticlinter.SecurityTag) } -func debugChecksListf(checks []string, format string, args ...interface{}) { +func debugChecksListf(checks []string, format string, args ...any) { if !isGoCriticDebug { return } - goCriticDebugf("%s checks (%d): %s", fmt.Sprintf(format, args...), len(checks), sprintStrings(checks)) + goCriticDebugf("%s checks (%d): %s", fmt.Sprintf(format, args...), len(checks), sprintSortedStrings(checks)) } -func stringsSliceToSet(ss []string) map[string]bool { - ret := make(map[string]bool, len(ss)) - for _, s := range ss { - ret[s] = true - } - - return ret +func sprintSortedStrings(v []string) string { + sort.Strings(slices.Clone(v)) + return fmt.Sprint(v) } diff --git a/pkg/golinters/gocritic_test.go b/pkg/golinters/gocritic_test.go index ec8c977f8c15..957b34b695da 100644 --- a/pkg/golinters/gocritic_test.go +++ b/pkg/golinters/gocritic_test.go @@ -1,61 +1,456 @@ package golinters import ( - "log" - "sort" + "strings" "testing" + "github.com/go-critic/go-critic/checkers" + gocriticlinter "github.com/go-critic/go-critic/linter" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "golang.org/x/exp/maps" + "golang.org/x/exp/slices" + "github.com/golangci/golangci-lint/pkg/config" "github.com/golangci/golangci-lint/pkg/logutils" ) -func Test_intersectStringSlice(t *testing.T) { - s1 := []string{"diagnostic", "experimental", "opinionated"} - s2 := []string{"opinionated", "experimental"} +// https://go-critic.com/overview.html +func Test_goCriticSettingsWrapper_InferEnabledChecks(t *testing.T) { + err := checkers.InitEmbeddedRules() + require.NoError(t, err) - s3 := intersectStringSlice(s1, s2) + allCheckersInfo := gocriticlinter.GetCheckersInfo() - sort.Strings(s3) + allChecksByTag := make(map[string][]string) + allChecks := make([]string, 0, len(allCheckersInfo)) + for _, checker := range allCheckersInfo { + allChecks = append(allChecks, checker.Name) + for _, tag := range checker.Tags { + allChecksByTag[tag] = append(allChecksByTag[tag], checker.Name) + } + } - assert.Equal(t, s3, []string{"experimental", "opinionated"}) -} - -func Test_filterByDisableTags(t *testing.T) { - disabledTags := []string{"experimental", "opinionated"} - enabledChecks := []string{"appendAssign", "sortSlice", "caseOrder", "dupImport"} + enabledByDefaultChecks := make([]string, 0, len(allCheckersInfo)) + for _, info := range allCheckersInfo { + if isEnabledByDefaultGoCriticChecker(info) { + enabledByDefaultChecks = append(enabledByDefaultChecks, info.Name) + } + } + t.Logf("enabled by default checks:\n%s", strings.Join(enabledByDefaultChecks, "\n")) - settingsWrapper := newGoCriticSettingsWrapper(nil, &tLog{}) + insert := func(in []string, toInsert ...string) []string { + return append(slices.Clone(in), toInsert...) + } - filterEnabledChecks := settingsWrapper.filterByDisableTags(enabledChecks, disabledTags) + remove := func(in []string, toRemove ...string) []string { + result := slices.Clone(in) + for _, v := range toRemove { + if i := slices.Index(result, v); i != -1 { + result = slices.Delete(result, i, i+1) + } + } + return result + } - sort.Strings(filterEnabledChecks) + uniq := func(in []string) []string { + result := slices.Clone(in) + slices.Sort(result) + return slices.Compact(result) + } - assert.Equal(t, []string{"appendAssign", "caseOrder"}, filterEnabledChecks) -} + cases := []struct { + name string + sett *config.GoCriticSettings + expectedEnabledChecks []string + }{ + { + name: "no configuration", + sett: &config.GoCriticSettings{}, + expectedEnabledChecks: enabledByDefaultChecks, + }, + { + name: "enable checks", + sett: &config.GoCriticSettings{ + EnabledChecks: []string{"assignOp", "badCall", "emptyDecl"}, + }, + expectedEnabledChecks: insert(enabledByDefaultChecks, "emptyDecl"), + }, + { + name: "disable checks", + sett: &config.GoCriticSettings{ + DisabledChecks: []string{"assignOp", "emptyDecl"}, + }, + expectedEnabledChecks: remove(enabledByDefaultChecks, "assignOp"), + }, + { + name: "enable tags", + sett: &config.GoCriticSettings{ + EnabledTags: []string{"style", "experimental"}, + }, + expectedEnabledChecks: uniq(insert(insert( + enabledByDefaultChecks, + allChecksByTag["style"]...), + allChecksByTag["experimental"]...)), + }, + { + name: "disable tags", + sett: &config.GoCriticSettings{ + DisabledTags: []string{"diagnostic"}, + }, + expectedEnabledChecks: remove(enabledByDefaultChecks, allChecksByTag["diagnostic"]...), + }, + { + name: "enable checks disable checks", + sett: &config.GoCriticSettings{ + EnabledChecks: []string{"badCall", "badLock"}, + DisabledChecks: []string{"assignOp", "badSorting"}, + }, + expectedEnabledChecks: insert(remove(enabledByDefaultChecks, "assignOp"), "badLock"), + }, + { + name: "enable checks enable tags", + sett: &config.GoCriticSettings{ + EnabledChecks: []string{"badCall", "badLock", "hugeParam"}, + EnabledTags: []string{"diagnostic"}, + }, + expectedEnabledChecks: uniq(insert(insert(enabledByDefaultChecks, + allChecksByTag["diagnostic"]...), + "hugeParam")), + }, + { + name: "enable checks disable tags", + sett: &config.GoCriticSettings{ + EnabledChecks: []string{"badCall", "badLock", "boolExprSimplify", "hugeParam"}, + DisabledTags: []string{"style", "diagnostic"}, + }, + expectedEnabledChecks: insert(remove(remove(enabledByDefaultChecks, + allChecksByTag["style"]...), + allChecksByTag["diagnostic"]...), + "hugeParam"), + }, + { + name: "enable all checks via tags", + sett: &config.GoCriticSettings{ + EnabledTags: []string{"diagnostic", "experimental", "opinionated", "performance", "style"}, + }, + expectedEnabledChecks: allChecks, + }, + { + name: "disable checks enable tags", + sett: &config.GoCriticSettings{ + DisabledChecks: []string{"assignOp", "badCall", "badLock", "hugeParam"}, + EnabledTags: []string{"style", "diagnostic"}, + }, + expectedEnabledChecks: remove(uniq(insert(insert(enabledByDefaultChecks, + allChecksByTag["style"]...), + allChecksByTag["diagnostic"]...)), + "assignOp", "badCall", "badLock"), + }, + { + name: "disable checks disable tags", + sett: &config.GoCriticSettings{ + DisabledChecks: []string{"badCall", "badLock", "codegenComment", "hugeParam"}, + DisabledTags: []string{"style"}, + }, + expectedEnabledChecks: remove(remove(enabledByDefaultChecks, + allChecksByTag["style"]...), + "badCall", "codegenComment"), + }, + { + name: "enable tags disable tags", + sett: &config.GoCriticSettings{ + EnabledTags: []string{"experimental"}, + DisabledTags: []string{"style"}, + }, + expectedEnabledChecks: remove(uniq(insert(enabledByDefaultChecks, + allChecksByTag["experimental"]...)), + allChecksByTag["style"]...), + }, + { + name: "enable checks disable checks enable tags", + sett: &config.GoCriticSettings{ + EnabledChecks: []string{"badCall", "badLock", "boolExprSimplify", "indexAlloc", "hugeParam"}, + DisabledChecks: []string{"deprecatedComment", "typeSwitchVar"}, + EnabledTags: []string{"experimental"}, + }, + expectedEnabledChecks: remove(uniq(insert(insert(enabledByDefaultChecks, + allChecksByTag["experimental"]...), + "indexAlloc", "hugeParam")), + "deprecatedComment", "typeSwitchVar"), + }, + { + name: "enable checks disable checks enable tags disable tags", + sett: &config.GoCriticSettings{ + EnabledChecks: []string{"badCall", "badCond", "badLock", "indexAlloc", "hugeParam"}, + DisabledChecks: []string{"deprecatedComment", "typeSwitchVar"}, + EnabledTags: []string{"experimental"}, + DisabledTags: []string{"performance"}, + }, + expectedEnabledChecks: remove(remove(uniq(insert(insert(enabledByDefaultChecks, + allChecksByTag["experimental"]...), + "badCond")), + allChecksByTag["performance"]...), + "deprecatedComment", "typeSwitchVar"), + }, + { + name: "enable single tag only", + sett: &config.GoCriticSettings{ + DisableAll: true, + EnabledTags: []string{"experimental"}, + }, + expectedEnabledChecks: allChecksByTag["experimental"], + }, + { + name: "enable two tags only", + sett: &config.GoCriticSettings{ + DisableAll: true, + EnabledTags: []string{"experimental", "performance"}, + }, + expectedEnabledChecks: uniq(insert(allChecksByTag["experimental"], allChecksByTag["performance"]...)), + }, + { + name: "disable single tag only", + sett: &config.GoCriticSettings{ + EnableAll: true, + DisabledTags: []string{"style"}, + }, + expectedEnabledChecks: remove(allChecks, allChecksByTag["style"]...), + }, + { + name: "disable two tags only", + sett: &config.GoCriticSettings{ + EnableAll: true, + DisabledTags: []string{"style", "diagnostic"}, + }, + expectedEnabledChecks: remove(remove(allChecks, allChecksByTag["style"]...), allChecksByTag["diagnostic"]...), + }, + { + name: "enable some checks only", + sett: &config.GoCriticSettings{ + DisableAll: true, + EnabledChecks: []string{"deferInLoop", "dupImport", "ifElseChain", "mapKey"}, + }, + expectedEnabledChecks: []string{"deferInLoop", "dupImport", "ifElseChain", "mapKey"}, + }, + { + name: "disable some checks only", + sett: &config.GoCriticSettings{ + EnableAll: true, + DisabledChecks: []string{"deferInLoop", "dupImport", "ifElseChain", "mapKey"}, + }, + expectedEnabledChecks: remove(allChecks, "deferInLoop", "dupImport", "ifElseChain", "mapKey"), + }, + { + name: "enable single tag and some checks from another tag only", + sett: &config.GoCriticSettings{ + DisableAll: true, + EnabledTags: []string{"experimental"}, + EnabledChecks: []string{"importShadow"}, + }, + expectedEnabledChecks: insert(allChecksByTag["experimental"], "importShadow"), + }, + { + name: "disable single tag and some checks from another tag only", + sett: &config.GoCriticSettings{ + EnableAll: true, + DisabledTags: []string{"experimental"}, + DisabledChecks: []string{"importShadow"}, + }, + expectedEnabledChecks: remove(remove(allChecks, allChecksByTag["experimental"]...), "importShadow"), + }, + } -type tLog struct{} + for _, tt := range cases { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() -func (l *tLog) Fatalf(format string, args ...interface{}) { - log.Printf(format, args...) -} + lg := logutils.NewStderrLog("Test_goCriticSettingsWrapper_InferEnabledChecks") + wr := newGoCriticSettingsWrapper(tt.sett, lg) -func (l *tLog) Panicf(format string, args ...interface{}) { - log.Printf(format, args...) + wr.InferEnabledChecks() + assert.ElementsMatch(t, tt.expectedEnabledChecks, maps.Keys(wr.inferredEnabledChecks)) + assert.NoError(t, wr.Validate()) + }) + } } -func (l *tLog) Errorf(format string, args ...interface{}) { - log.Printf(format, args...) -} +func Test_goCriticSettingsWrapper_Validate(t *testing.T) { + cases := []struct { + name string + sett *config.GoCriticSettings + expectedErr bool + }{ + { + name: "combine enable-all and disable-all", + sett: &config.GoCriticSettings{ + EnableAll: true, + DisableAll: true, + }, + expectedErr: true, + }, + { + name: "combine enable-all and enabled-tags", + sett: &config.GoCriticSettings{ + EnableAll: true, + EnabledTags: []string{"experimental"}, + }, + expectedErr: true, + }, + { + name: "combine enable-all and enabled-checks", + sett: &config.GoCriticSettings{ + EnableAll: true, + EnabledChecks: []string{"dupImport"}, + }, + expectedErr: true, + }, + { + name: "combine disable-all and disabled-tags", + sett: &config.GoCriticSettings{ + DisableAll: true, + DisabledTags: []string{"style"}, + }, + expectedErr: true, + }, + { + name: "combine disable-all and disable-checks", + sett: &config.GoCriticSettings{ + DisableAll: true, + DisabledChecks: []string{"appendAssign"}, + }, + expectedErr: true, + }, + { + name: "disable-all and no one check enabled", + sett: &config.GoCriticSettings{ + DisableAll: true, + }, + expectedErr: true, + }, + { + name: "unknown enabled tag", + sett: &config.GoCriticSettings{ + EnabledTags: []string{"diagnostic", "go-proverbs"}, + }, + expectedErr: true, + }, + { + name: "unknown disabled tag", + sett: &config.GoCriticSettings{ + DisabledTags: []string{"style", "go-proverbs"}, + }, + expectedErr: true, + }, + { + name: "unknown enabled check", + sett: &config.GoCriticSettings{ + EnabledChecks: []string{"appendAssign", "noExitAfterDefer", "underef"}, + }, + expectedErr: true, + }, + { + name: "unknown disabled check", + sett: &config.GoCriticSettings{ + DisabledChecks: []string{"dupSubExpr", "noExitAfterDefer", "returnAfterHttpError"}, + }, + expectedErr: true, + }, + { + name: "settings for unknown check", + sett: &config.GoCriticSettings{ + SettingsPerCheck: map[string]config.GoCriticCheckSettings{ + "captLocall": {"paramsOnly": false}, + "unnamedResult": {"checkExported": true}, + }, + }, + expectedErr: true, + }, + { + name: "settings for disabled check", + sett: &config.GoCriticSettings{ + DisabledChecks: []string{"elseif"}, + SettingsPerCheck: map[string]config.GoCriticCheckSettings{ + "elseif": {"skipBalanced": true}, + }, + }, + expectedErr: false, // Just logging. + }, + { + name: "settings by lower-cased checker name", + sett: &config.GoCriticSettings{ + EnabledChecks: []string{"tooManyResultsChecker"}, + SettingsPerCheck: map[string]config.GoCriticCheckSettings{ + "toomanyresultschecker": {"maxResults": 3}, + "unnamedResult": {"checkExported": true}, + }, + }, + expectedErr: false, + }, + { + name: "enabled and disabled at one moment check", + sett: &config.GoCriticSettings{ + EnabledChecks: []string{"appendAssign", "codegenComment", "underef"}, + DisabledChecks: []string{"elseif", "underef"}, + }, + expectedErr: true, + }, + { + name: "enabled and disabled at one moment tag", + sett: &config.GoCriticSettings{ + EnabledTags: []string{"performance", "style"}, + DisabledTags: []string{"style", "diagnostic"}, + }, + expectedErr: true, + }, + { + name: "disable all checks via tags", + sett: &config.GoCriticSettings{ + DisabledTags: []string{"diagnostic", "experimental", "opinionated", "performance", "style"}, + }, + expectedErr: true, + }, + { + name: "enable-all and disable all checks via tags", + sett: &config.GoCriticSettings{ + EnableAll: true, + DisabledTags: []string{"diagnostic", "experimental", "opinionated", "performance", "style"}, + }, + expectedErr: true, + }, + { + name: "valid configuration", + sett: &config.GoCriticSettings{ + EnabledTags: []string{"performance"}, + DisabledChecks: []string{"dupImport", "ifElseChain", "octalLiteral", "whyNoLint"}, + SettingsPerCheck: map[string]config.GoCriticCheckSettings{ + "hugeParam": {"sizeThreshold": 100}, + "rangeValCopy": {"skipTestFuncs": true}, + }, + }, + expectedErr: false, + }, + } -func (l *tLog) Warnf(format string, args ...interface{}) { - log.Printf(format, args...) -} + for _, tt := range cases { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() -func (l *tLog) Infof(format string, args ...interface{}) { - log.Printf(format, args...) -} + lg := logutils.NewStderrLog("Test_goCriticSettingsWrapper_Validate") + wr := newGoCriticSettingsWrapper(tt.sett, lg) -func (l *tLog) Child(name string) logutils.Log { return nil } + wr.InferEnabledChecks() -func (l *tLog) SetLevel(level logutils.LogLevel) {} + err := wr.Validate() + if tt.expectedErr { + if assert.Error(t, err) { + t.Log(err) + } + } else { + assert.NoError(t, err) + } + }) + } +} diff --git a/pkg/golinters/gocyclo.go b/pkg/golinters/gocyclo.go index ea82195711b5..b502623ba620 100644 --- a/pkg/golinters/gocyclo.go +++ b/pkg/golinters/gocyclo.go @@ -23,7 +23,7 @@ func NewGocyclo(settings *config.GoCycloSettings) *goanalysis.Linter { analyzer := &analysis.Analyzer{ Name: gocycloName, Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (interface{}, error) { + Run: func(pass *analysis.Pass) (any, error) { issues := runGoCyclo(pass, settings) if len(issues) == 0 { diff --git a/pkg/golinters/godot.go b/pkg/golinters/godot.go index 93ca7577ae89..b0ee64434936 100644 --- a/pkg/golinters/godot.go +++ b/pkg/golinters/godot.go @@ -42,7 +42,7 @@ func NewGodot(settings *config.GodotSettings) *goanalysis.Linter { analyzer := &analysis.Analyzer{ Name: godotName, Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (interface{}, error) { + Run: func(pass *analysis.Pass) (any, error) { issues, err := runGodot(pass, dotSettings) if err != nil { return nil, err diff --git a/pkg/golinters/godox.go b/pkg/golinters/godox.go index 4dba9df00307..955810417dcb 100644 --- a/pkg/golinters/godox.go +++ b/pkg/golinters/godox.go @@ -24,7 +24,7 @@ func NewGodox(settings *config.GodoxSettings) *goanalysis.Linter { analyzer := &analysis.Analyzer{ Name: godoxName, Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (interface{}, error) { + Run: func(pass *analysis.Pass) (any, error) { issues := runGodox(pass, settings) if len(issues) == 0 { diff --git a/pkg/golinters/goerr113.go b/pkg/golinters/goerr113.go index c97b6d587894..10addc57c240 100644 --- a/pkg/golinters/goerr113.go +++ b/pkg/golinters/goerr113.go @@ -10,7 +10,7 @@ import ( func NewGoerr113() *goanalysis.Linter { return goanalysis.NewLinter( "goerr113", - "Golang linter to check the errors handling expressions", + "Go linter to check the errors handling expressions", []*analysis.Analyzer{err113.NewAnalyzer()}, nil, ).WithLoadMode(goanalysis.LoadModeTypesInfo) diff --git a/pkg/golinters/gofmt.go b/pkg/golinters/gofmt.go index 112f422ffecd..d2d0d3ccc5a4 100644 --- a/pkg/golinters/gofmt.go +++ b/pkg/golinters/gofmt.go @@ -1,10 +1,10 @@ package golinters import ( + "fmt" "sync" gofmtAPI "github.com/golangci/gofmt/gofmt" - "github.com/pkg/errors" "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/pkg/config" @@ -31,7 +31,7 @@ func NewGofmt(settings *config.GoFmtSettings) *goanalysis.Linter { []*analysis.Analyzer{analyzer}, nil, ).WithContextSetter(func(lintCtx *linter.Context) { - analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + analyzer.Run = func(pass *analysis.Pass) (any, error) { issues, err := runGofmt(lintCtx, pass, settings) if err != nil { return nil, err @@ -73,7 +73,7 @@ func runGofmt(lintCtx *linter.Context, pass *analysis.Pass, settings *config.GoF is, err := extractIssuesFromPatch(string(diff), lintCtx, gofmtName) if err != nil { - return nil, errors.Wrapf(err, "can't extract issues from gofmt diff output %q", string(diff)) + return nil, fmt.Errorf("can't extract issues from gofmt diff output %q: %w", string(diff), err) } for i := range is { diff --git a/pkg/golinters/gofmt_common.go b/pkg/golinters/gofmt_common.go index 59f4f4590e2c..6b7184d65bc1 100644 --- a/pkg/golinters/gofmt_common.go +++ b/pkg/golinters/gofmt_common.go @@ -6,7 +6,6 @@ import ( "go/token" "strings" - "github.com/pkg/errors" diffpkg "github.com/sourcegraph/go-diff/diff" "github.com/golangci/golangci-lint/pkg/config" @@ -81,6 +80,16 @@ func (p *hunkChangesParser) parseDiffLines(h *diffpkg.Hunk) { ret = append(ret, dl) } + // if > 0, then the original file had a 'No newline at end of file' mark + if h.OrigNoNewlineAt > 0 { + dl := diffLine{ + originalNumber: currentOriginalLineNumber + 1, + typ: diffLineAdded, + data: "", + } + ret = append(ret, dl) + } + p.lines = ret } @@ -238,7 +247,7 @@ func getErrorTextForLinter(settings *config.LintersSettings, linterName string) func extractIssuesFromPatch(patch string, lintCtx *linter.Context, linterName string) ([]result.Issue, error) { diffs, err := diffpkg.ParseMultiFileDiff([]byte(patch)) if err != nil { - return nil, errors.Wrap(err, "can't parse patch") + return nil, fmt.Errorf("can't parse patch: %w", err) } if len(diffs) == 0 { diff --git a/pkg/golinters/gofmt_test.go b/pkg/golinters/gofmt_test.go index c9be0b1ed4b5..e017c7978ed0 100644 --- a/pkg/golinters/gofmt_test.go +++ b/pkg/golinters/gofmt_test.go @@ -6,6 +6,7 @@ import ( diffpkg "github.com/sourcegraph/go-diff/diff" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" "github.com/golangci/golangci-lint/pkg/logutils" "github.com/golangci/golangci-lint/pkg/result" @@ -14,10 +15,10 @@ import ( func testDiffProducesChanges(t *testing.T, log logutils.Log, diff string, expectedChanges ...Change) { diffs, err := diffpkg.ParseMultiFileDiff([]byte(diff)) if err != nil { - assert.NoError(t, err) + require.NoError(t, err) } - assert.Len(t, diffs, 1) + require.Len(t, diffs, 1) hunks := diffs[0].Hunks assert.NotEmpty(t, hunks) diff --git a/pkg/golinters/gofumpt.go b/pkg/golinters/gofumpt.go index 312dfd6d93ba..c2aaf121de7e 100644 --- a/pkg/golinters/gofumpt.go +++ b/pkg/golinters/gofumpt.go @@ -7,7 +7,6 @@ import ( "os" "sync" - "github.com/pkg/errors" "github.com/shazow/go-diff/difflib" "golang.org/x/tools/go/analysis" "mvdan.cc/gofumpt/format" @@ -51,7 +50,7 @@ func NewGofumpt(settings *config.GofumptSettings) *goanalysis.Linter { []*analysis.Analyzer{analyzer}, nil, ).WithContextSetter(func(lintCtx *linter.Context) { - analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + analyzer.Run = func(pass *analysis.Pass) (any, error) { issues, err := runGofumpt(lintCtx, pass, diff, options) if err != nil { return nil, err @@ -89,13 +88,9 @@ func runGofumpt(lintCtx *linter.Context, pass *analysis.Pass, diff differ, optio } if !bytes.Equal(input, output) { - out := bytes.Buffer{} - _, err = out.WriteString(fmt.Sprintf("--- %[1]s\n+++ %[1]s\n", f)) - if err != nil { - return nil, fmt.Errorf("error while running gofumpt: %w", err) - } + out := bytes.NewBufferString(fmt.Sprintf("--- %[1]s\n+++ %[1]s\n", f)) - err = diff.Diff(&out, bytes.NewReader(input), bytes.NewReader(output)) + err := diff.Diff(out, bytes.NewReader(input), bytes.NewReader(output)) if err != nil { return nil, fmt.Errorf("error while running gofumpt: %w", err) } @@ -103,7 +98,7 @@ func runGofumpt(lintCtx *linter.Context, pass *analysis.Pass, diff differ, optio diff := out.String() is, err := extractIssuesFromPatch(diff, lintCtx, gofumptName) if err != nil { - return nil, errors.Wrapf(err, "can't extract issues from gofumpt diff output %q", diff) + return nil, fmt.Errorf("can't extract issues from gofumpt diff output %q: %w", diff, err) } for i := range is { diff --git a/pkg/golinters/goheader.go b/pkg/golinters/goheader.go index d7d27326ecba..5ed5d9d8ded6 100644 --- a/pkg/golinters/goheader.go +++ b/pkg/golinters/goheader.go @@ -31,7 +31,7 @@ func NewGoHeader(settings *config.GoHeaderSettings) *goanalysis.Linter { analyzer := &analysis.Analyzer{ Name: goHeaderName, Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (interface{}, error) { + Run: func(pass *analysis.Pass) (any, error) { issues, err := runGoHeader(pass, conf) if err != nil { return nil, err @@ -97,6 +97,17 @@ func runGoHeader(pass *analysis.Pass, conf *goheader.Configuration) ([]goanalysi FromLinter: goHeaderName, } + if fix := i.Fix(); fix != nil { + issue.LineRange = &result.Range{ + From: issue.Line(), + To: issue.Line() + len(fix.Actual) - 1, + } + issue.Replacement = &result.Replacement{ + NeedOnlyDelete: len(fix.Expected) == 0, + NewLines: fix.Expected, + } + } + issues = append(issues, goanalysis.NewIssue(&issue, pass)) } diff --git a/pkg/golinters/goimports.go b/pkg/golinters/goimports.go index 97ad6d460620..aac27f38e55f 100644 --- a/pkg/golinters/goimports.go +++ b/pkg/golinters/goimports.go @@ -1,10 +1,10 @@ package golinters import ( + "fmt" "sync" goimportsAPI "github.com/golangci/gofmt/goimports" - "github.com/pkg/errors" "golang.org/x/tools/go/analysis" "golang.org/x/tools/imports" @@ -34,7 +34,7 @@ func NewGoimports(settings *config.GoImportsSettings) *goanalysis.Linter { ).WithContextSetter(func(lintCtx *linter.Context) { imports.LocalPrefix = settings.LocalPrefixes - analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + analyzer.Run = func(pass *analysis.Pass) (any, error) { issues, err := runGoImports(lintCtx, pass) if err != nil { return nil, err @@ -71,7 +71,7 @@ func runGoImports(lintCtx *linter.Context, pass *analysis.Pass) ([]goanalysis.Is is, err := extractIssuesFromPatch(string(diff), lintCtx, goimportsName) if err != nil { - return nil, errors.Wrapf(err, "can't extract issues from gofmt diff output %q", string(diff)) + return nil, fmt.Errorf("can't extract issues from gofmt diff output %q: %w", string(diff), err) } for i := range is { diff --git a/pkg/golinters/golint.go b/pkg/golinters/golint.go deleted file mode 100644 index 95c579e34ba8..000000000000 --- a/pkg/golinters/golint.go +++ /dev/null @@ -1,84 +0,0 @@ -package golinters - -import ( - "fmt" - "sync" - - lintAPI "github.com/golangci/lint-1" - "golang.org/x/tools/go/analysis" - - "github.com/golangci/golangci-lint/pkg/config" - "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" - "github.com/golangci/golangci-lint/pkg/lint/linter" - "github.com/golangci/golangci-lint/pkg/result" -) - -const golintName = "golint" - -//nolint:dupl -func NewGolint(settings *config.GoLintSettings) *goanalysis.Linter { - var mu sync.Mutex - var resIssues []goanalysis.Issue - - analyzer := &analysis.Analyzer{ - Name: golintName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (interface{}, error) { - issues, err := runGoLint(pass, settings) - if err != nil { - return nil, err - } - - if len(issues) == 0 { - return nil, nil - } - - mu.Lock() - resIssues = append(resIssues, issues...) - mu.Unlock() - - return nil, nil - }, - } - - return goanalysis.NewLinter( - golintName, - "Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes", - []*analysis.Analyzer{analyzer}, - nil, - ).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return resIssues - }).WithLoadMode(goanalysis.LoadModeTypesInfo) -} - -func runGoLint(pass *analysis.Pass, settings *config.GoLintSettings) ([]goanalysis.Issue, error) { - l := new(lintAPI.Linter) - - ps, err := l.LintPkg(pass.Files, pass.Fset, pass.Pkg, pass.TypesInfo) - if err != nil { - return nil, fmt.Errorf("can't lint %d files: %s", len(pass.Files), err) - } - - if len(ps) == 0 { - return nil, nil - } - - lintIssues := make([]*result.Issue, 0, len(ps)) // This is worst case - for idx := range ps { - if ps[idx].Confidence >= settings.MinConfidence { - lintIssues = append(lintIssues, &result.Issue{ - Pos: ps[idx].Position, - Text: ps[idx].Text, - FromLinter: golintName, - }) - // TODO: use p.Link and p.Category - } - } - - issues := make([]goanalysis.Issue, 0, len(lintIssues)) - for _, issue := range lintIssues { - issues = append(issues, goanalysis.NewIssue(issue, pass)) - } - - return issues, nil -} diff --git a/pkg/golinters/gomnd.go b/pkg/golinters/gomnd.go index 15d84b48bfdd..2e6d77a8015e 100644 --- a/pkg/golinters/gomnd.go +++ b/pkg/golinters/gomnd.go @@ -9,14 +9,14 @@ import ( ) func NewGoMND(settings *config.GoMndSettings) *goanalysis.Linter { - var linterCfg map[string]map[string]interface{} + var linterCfg map[string]map[string]any if settings != nil { // TODO(ldez) For compatibility only, must be drop in v2. if len(settings.Settings) > 0 { linterCfg = settings.Settings } else { - cfg := make(map[string]interface{}) + cfg := make(map[string]any) if len(settings.Checks) > 0 { cfg["checks"] = settings.Checks } @@ -30,7 +30,7 @@ func NewGoMND(settings *config.GoMndSettings) *goanalysis.Linter { cfg["ignored-functions"] = settings.IgnoredFunctions } - linterCfg = map[string]map[string]interface{}{ + linterCfg = map[string]map[string]any{ "mnd": cfg, } } diff --git a/pkg/golinters/gomoddirectives.go b/pkg/golinters/gomoddirectives.go index 81831129a235..56afcd465f08 100644 --- a/pkg/golinters/gomoddirectives.go +++ b/pkg/golinters/gomoddirectives.go @@ -39,7 +39,7 @@ func NewGoModDirectives(settings *config.GoModDirectivesSettings) *goanalysis.Li []*analysis.Analyzer{analyzer}, nil, ).WithContextSetter(func(lintCtx *linter.Context) { - analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + analyzer.Run = func(pass *analysis.Pass) (any, error) { once.Do(func() { results, err := gomoddirectives.Analyze(opts) if err != nil { diff --git a/pkg/golinters/gomodguard.go b/pkg/golinters/gomodguard.go index e21658d5d2a3..157bf56c35de 100644 --- a/pkg/golinters/gomodguard.go +++ b/pkg/golinters/gomodguard.go @@ -72,7 +72,7 @@ func NewGomodguard(settings *config.GoModGuardSettings) *goanalysis.Linter { return } - analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + analyzer.Run = func(pass *analysis.Pass) (any, error) { gomodguardIssues := processor.ProcessFiles(getFileNames(pass)) mu.Lock() diff --git a/pkg/golinters/goprintffuncname.go b/pkg/golinters/goprintffuncname.go index c5516dc7f9b4..e513718ba8dc 100644 --- a/pkg/golinters/goprintffuncname.go +++ b/pkg/golinters/goprintffuncname.go @@ -8,10 +8,12 @@ import ( ) func NewGoPrintfFuncName() *goanalysis.Linter { + a := analyzer.Analyzer + return goanalysis.NewLinter( - "goprintffuncname", - "Checks that printf-like functions are named with `f` at the end", - []*analysis.Analyzer{analyzer.Analyzer}, + a.Name, + a.Doc, + []*analysis.Analyzer{a}, nil, ).WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/gosec.go b/pkg/golinters/gosec.go index 3b102a92f539..0c09c5967262 100644 --- a/pkg/golinters/gosec.go +++ b/pkg/golinters/gosec.go @@ -9,8 +9,8 @@ import ( "strings" "sync" - "github.com/pkg/errors" "github.com/securego/gosec/v2" + "github.com/securego/gosec/v2/issue" "github.com/securego/gosec/v2/rules" "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/packages" @@ -27,20 +27,11 @@ func NewGosec(settings *config.GoSecSettings) *goanalysis.Linter { var mu sync.Mutex var resIssues []goanalysis.Issue - conf := gosec.NewConfig() - var filters []rules.RuleFilter + conf := gosec.NewConfig() if settings != nil { filters = gosecRuleFilters(settings.Includes, settings.Excludes) - - for k, v := range settings.Config { - if k != gosec.Globals { - // Uses ToUpper because the parsing of the map's key change the key to lowercase. - // The value is not impacted by that: the case is respected. - k = strings.ToUpper(k) - } - conf.Set(k, v) - } + conf = toGosecConfig(settings) } logger := log.New(io.Discard, "", 0) @@ -59,7 +50,7 @@ func NewGosec(settings *config.GoSecSettings) *goanalysis.Linter { []*analysis.Analyzer{analyzer}, nil, ).WithContextSetter(func(lintCtx *linter.Context) { - analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + analyzer.Run = func(pass *analysis.Pass) (any, error) { // The `gosecAnalyzer` is here because of concurrency issue. gosecAnalyzer := gosec.NewAnalyzer(conf, true, settings.ExcludeGenerated, false, settings.Concurrency, logger) gosecAnalyzer.LoadRules(ruleDefinitions.RulesInfo()) @@ -85,7 +76,7 @@ func runGoSec(lintCtx *linter.Context, pass *analysis.Pass, settings *config.GoS TypesInfo: pass.TypesInfo, } - analyzer.Check(pkg) + analyzer.CheckRules(pkg) secIssues, _, _ := analyzer.Report() if len(secIssues) == 0 { @@ -106,7 +97,7 @@ func runGoSec(lintCtx *linter.Context, pass *analysis.Pass, settings *config.GoS issues := make([]goanalysis.Issue, 0, len(secIssues)) for _, i := range secIssues { - text := fmt.Sprintf("%s: %s", i.RuleID, i.What) // TODO: use severity and confidence + text := fmt.Sprintf("%s: %s", i.RuleID, i.What) var r *result.Range @@ -127,6 +118,7 @@ func runGoSec(lintCtx *linter.Context, pass *analysis.Pass, settings *config.GoS } issues = append(issues, goanalysis.NewIssue(&result.Issue{ + Severity: convertScoreToString(i.Severity), Pos: token.Position{ Filename: i.File, Line: line, @@ -141,6 +133,48 @@ func runGoSec(lintCtx *linter.Context, pass *analysis.Pass, settings *config.GoS return issues } +func toGosecConfig(settings *config.GoSecSettings) gosec.Config { + conf := gosec.NewConfig() + + for k, v := range settings.Config { + if k == gosec.Globals { + convertGosecGlobals(v, conf) + continue + } + + // Uses ToUpper because the parsing of the map's key change the key to lowercase. + // The value is not impacted by that: the case is respected. + conf.Set(strings.ToUpper(k), v) + } + + return conf +} + +func convertScoreToString(score issue.Score) string { + switch score { + case issue.Low: + return "low" + case issue.Medium: + return "medium" + case issue.High: + return "high" + default: + return "" + } +} + +// based on https://github.com/securego/gosec/blob/47bfd4eb6fc7395940933388550b547538b4c946/config.go#L52-L62 +func convertGosecGlobals(globalOptionFromConfig any, conf gosec.Config) { + globalOptionMap, ok := globalOptionFromConfig.(map[string]any) + if !ok { + return + } + + for k, v := range globalOptionMap { + conf.SetGlobal(gosec.GlobalOption(k), fmt.Sprintf("%v", v)) + } +} + // based on https://github.com/securego/gosec/blob/569328eade2ccbad4ce2d0f21ee158ab5356a5cf/cmd/gosec/main.go#L170-L188 func gosecRuleFilters(includes, excludes []string) []rules.RuleFilter { var filters []rules.RuleFilter @@ -157,27 +191,29 @@ func gosecRuleFilters(includes, excludes []string) []rules.RuleFilter { } // code borrowed from https://github.com/securego/gosec/blob/69213955dacfd560562e780f723486ef1ca6d486/cmd/gosec/main.go#L250-L262 -func convertToScore(str string) (gosec.Score, error) { +func convertToScore(str string) (issue.Score, error) { str = strings.ToLower(str) switch str { case "", "low": - return gosec.Low, nil + return issue.Low, nil case "medium": - return gosec.Medium, nil + return issue.Medium, nil case "high": - return gosec.High, nil + return issue.High, nil default: - return gosec.Low, errors.Errorf("'%s' is invalid, use low instead. Valid options: low, medium, high", str) + return issue.Low, fmt.Errorf("'%s' is invalid, use low instead. Valid options: low, medium, high", str) } } // code borrowed from https://github.com/securego/gosec/blob/69213955dacfd560562e780f723486ef1ca6d486/cmd/gosec/main.go#L264-L276 -func filterIssues(issues []*gosec.Issue, severity, confidence gosec.Score) []*gosec.Issue { - res := make([]*gosec.Issue, 0) - for _, issue := range issues { - if issue.Severity >= severity && issue.Confidence >= confidence { - res = append(res, issue) +func filterIssues(issues []*issue.Issue, severity, confidence issue.Score) []*issue.Issue { + res := make([]*issue.Issue, 0) + + for _, i := range issues { + if i.Severity >= severity && i.Confidence >= confidence { + res = append(res, i) } } + return res } diff --git a/pkg/golinters/gosec_test.go b/pkg/golinters/gosec_test.go new file mode 100644 index 000000000000..9b1b5faeff96 --- /dev/null +++ b/pkg/golinters/gosec_test.go @@ -0,0 +1,70 @@ +package golinters + +import ( + "testing" + + "github.com/securego/gosec/v2" + "github.com/stretchr/testify/assert" + + "github.com/golangci/golangci-lint/pkg/config" +) + +func Test_toGosecConfig(t *testing.T) { + testCases := []struct { + desc string + settings *config.GoSecSettings + expected gosec.Config + }{ + { + desc: "empty config map", + settings: &config.GoSecSettings{}, + expected: gosec.Config{ + "global": map[gosec.GlobalOption]string{}, + }, + }, + { + desc: "with global settings", + settings: &config.GoSecSettings{ + Config: map[string]any{ + gosec.Globals: map[string]any{ + string(gosec.Nosec): true, + string(gosec.Audit): "true", + }, + }, + }, + expected: gosec.Config{ + "global": map[gosec.GlobalOption]string{ + "audit": "true", + "nosec": "true", + }, + }, + }, + { + desc: "rule specified setting", + settings: &config.GoSecSettings{ + Config: map[string]any{ + "g101": map[string]any{ + "pattern": "(?i)example", + }, + "G301": "0750", + }, + }, + expected: gosec.Config{ + "G101": map[string]any{"pattern": "(?i)example"}, + "G301": "0750", + "global": map[gosec.GlobalOption]string{}, + }, + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + conf := toGosecConfig(test.settings) + + assert.Equal(t, test.expected, conf) + }) + } +} diff --git a/pkg/golinters/gosmopolitan.go b/pkg/golinters/gosmopolitan.go new file mode 100644 index 000000000000..2e01fcc70d59 --- /dev/null +++ b/pkg/golinters/gosmopolitan.go @@ -0,0 +1,32 @@ +package golinters + +import ( + "strings" + + "github.com/xen0n/gosmopolitan" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" +) + +func NewGosmopolitan(s *config.GosmopolitanSettings) *goanalysis.Linter { + a := gosmopolitan.NewAnalyzer() + + cfgMap := map[string]map[string]any{} + if s != nil { + cfgMap[a.Name] = map[string]any{ + "allowtimelocal": s.AllowTimeLocal, + "escapehatches": strings.Join(s.EscapeHatches, ","), + "lookattests": !s.IgnoreTests, + "watchforscripts": strings.Join(s.WatchForScripts, ","), + } + } + + return goanalysis.NewLinter( + a.Name, + a.Doc, + []*analysis.Analyzer{a}, + cfgMap, + ).WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/pkg/golinters/govet.go b/pkg/golinters/govet.go index 75f9059229bd..4cf37d26b13e 100644 --- a/pkg/golinters/govet.go +++ b/pkg/golinters/govet.go @@ -1,7 +1,11 @@ package golinters import ( + "slices" + "sort" + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/passes/appends" "golang.org/x/tools/go/analysis/passes/asmdecl" "golang.org/x/tools/go/analysis/passes/assign" "golang.org/x/tools/go/analysis/passes/atomic" @@ -14,6 +18,8 @@ import ( "golang.org/x/tools/go/analysis/passes/copylock" _ "golang.org/x/tools/go/analysis/passes/ctrlflow" // unused, internal analyzer "golang.org/x/tools/go/analysis/passes/deepequalerrors" + "golang.org/x/tools/go/analysis/passes/defers" + "golang.org/x/tools/go/analysis/passes/directive" "golang.org/x/tools/go/analysis/passes/errorsas" "golang.org/x/tools/go/analysis/passes/fieldalignment" "golang.org/x/tools/go/analysis/passes/findcall" @@ -31,6 +37,7 @@ import ( "golang.org/x/tools/go/analysis/passes/shadow" "golang.org/x/tools/go/analysis/passes/shift" "golang.org/x/tools/go/analysis/passes/sigchanyzer" + "golang.org/x/tools/go/analysis/passes/slog" "golang.org/x/tools/go/analysis/passes/sortslice" "golang.org/x/tools/go/analysis/passes/stdmethods" "golang.org/x/tools/go/analysis/passes/stringintconv" @@ -46,10 +53,12 @@ import ( "github.com/golangci/golangci-lint/pkg/config" "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/logutils" ) var ( allAnalyzers = []*analysis.Analyzer{ + appends.Analyzer, asmdecl.Analyzer, assign.Analyzer, atomic.Analyzer, @@ -60,6 +69,8 @@ var ( composite.Analyzer, copylock.Analyzer, deepequalerrors.Analyzer, + defers.Analyzer, + directive.Analyzer, errorsas.Analyzer, fieldalignment.Analyzer, findcall.Analyzer, @@ -75,6 +86,7 @@ var ( shadow.Analyzer, shift.Analyzer, sigchanyzer.Analyzer, + slog.Analyzer, sortslice.Analyzer, stdmethods.Analyzer, stringintconv.Analyzer, @@ -89,8 +101,9 @@ var ( unusedwrite.Analyzer, } - // https://github.com/golang/go/blob/879db69ce2de814bc3203c39b45617ba51cc5366/src/cmd/vet/main.go#L40-L68 + // https://github.com/golang/go/blob/b56645a87b28840a180d64077877cb46570b4176/src/cmd/vet/main.go#L49-L81 defaultAnalyzers = []*analysis.Analyzer{ + appends.Analyzer, asmdecl.Analyzer, assign.Analyzer, atomic.Analyzer, @@ -99,6 +112,8 @@ var ( cgocall.Analyzer, composite.Analyzer, copylock.Analyzer, + defers.Analyzer, + directive.Analyzer, errorsas.Analyzer, framepointer.Analyzer, httpresponse.Analyzer, @@ -109,11 +124,13 @@ var ( printf.Analyzer, shift.Analyzer, sigchanyzer.Analyzer, + slog.Analyzer, stdmethods.Analyzer, stringintconv.Analyzer, structtag.Analyzer, testinggoroutine.Analyzer, tests.Analyzer, + timeformat.Analyzer, unmarshal.Analyzer, unreachable.Analyzer, unsafeptr.Analyzer, @@ -121,22 +138,30 @@ var ( } ) +var ( + govetDebugf = logutils.Debug(logutils.DebugKeyGovet) + isGovetDebug = logutils.HaveDebugTag(logutils.DebugKeyGovet) +) + func NewGovet(settings *config.GovetSettings) *goanalysis.Linter { - var conf map[string]map[string]interface{} + var conf map[string]map[string]any if settings != nil { conf = settings.Settings } return goanalysis.NewLinter( "govet", - "Vet examines Go source code and reports suspicious constructs, "+ - "such as Printf calls whose arguments do not align with the format string", + "Vet examines Go source code and reports suspicious constructs. "+ + "It is roughly the same as 'go vet' and uses its passes.", analyzersFromConfig(settings), conf, ).WithLoadMode(goanalysis.LoadModeTypesInfo) } func analyzersFromConfig(settings *config.GovetSettings) []*analysis.Analyzer { + debugAnalyzersListf(allAnalyzers, "All available analyzers") + debugAnalyzersListf(defaultAnalyzers, "Default analyzers") + if settings == nil { return defaultAnalyzers } @@ -153,40 +178,46 @@ func analyzersFromConfig(settings *config.GovetSettings) []*analysis.Analyzer { } } + debugAnalyzersListf(enabledAnalyzers, "Enabled by config analyzers") + return enabledAnalyzers } func isAnalyzerEnabled(name string, cfg *config.GovetSettings, defaultAnalyzers []*analysis.Analyzer) bool { - if cfg.EnableAll { - for _, n := range cfg.Disable { - if n == name { - return false - } - } - return true + // TODO(ldez) remove loopclosure when go1.23 + if name == loopclosure.Analyzer.Name && config.IsGoGreaterThanOrEqual(cfg.Go, "1.22") { + return false } - // Raw for loops should be OK on small slice lengths. - for _, n := range cfg.Enable { - if n == name { - return true - } - } + switch { + case cfg.EnableAll: + return !slices.Contains(cfg.Disable, name) - for _, n := range cfg.Disable { - if n == name { - return false - } - } + case slices.Contains(cfg.Enable, name): + return true - if cfg.DisableAll { + case slices.Contains(cfg.Disable, name): return false + + case cfg.DisableAll: + return false + + default: + return slices.ContainsFunc(defaultAnalyzers, func(a *analysis.Analyzer) bool { return a.Name == name }) } +} - for _, a := range defaultAnalyzers { - if a.Name == name { - return true - } +func debugAnalyzersListf(analyzers []*analysis.Analyzer, message string) { + if !isGovetDebug { + return + } + + analyzerNames := make([]string, 0, len(analyzers)) + for _, a := range analyzers { + analyzerNames = append(analyzerNames, a.Name) } - return false + + sort.Strings(analyzerNames) + + govetDebugf("%s (%d): %s", message, len(analyzerNames), analyzerNames) } diff --git a/pkg/golinters/govet_test.go b/pkg/golinters/govet_test.go index 020870506067..91b5179243ae 100644 --- a/pkg/golinters/govet_test.go +++ b/pkg/golinters/govet_test.go @@ -1,7 +1,7 @@ package golinters import ( - "sort" + "slices" "testing" "golang.org/x/tools/go/analysis" @@ -18,39 +18,41 @@ import ( func TestGovet(t *testing.T) { // Checking that every default analyzer is in "all analyzers" list. - var checkList []*analysis.Analyzer - checkList = append(checkList, defaultAnalyzers...) + checkList := append([]*analysis.Analyzer{}, defaultAnalyzers...) checkList = append(checkList, shadow.Analyzer) // special case, used in analyzersFromConfig for _, defaultAnalyzer := range checkList { - found := false - for _, a := range allAnalyzers { - if a.Name == defaultAnalyzer.Name { - found = true - break - } - } + found := slices.ContainsFunc(allAnalyzers, func(a *analysis.Analyzer) bool { + return a.Name == defaultAnalyzer.Name + }) if !found { t.Errorf("%s is not in allAnalyzers", defaultAnalyzer.Name) } } } -type sortedAnalyzers []*analysis.Analyzer +func sortAnalyzers(a, b *analysis.Analyzer) int { + if a.Name < b.Name { + return -1 + } + + if a.Name > b.Name { + return 1 + } -func (p sortedAnalyzers) Len() int { return len(p) } -func (p sortedAnalyzers) Less(i, j int) bool { return p[i].Name < p[j].Name } -func (p sortedAnalyzers) Swap(i, j int) { p[i].Name, p[j].Name = p[j].Name, p[i].Name } + return 0 +} func TestGovetSorted(t *testing.T) { // Keeping analyzers sorted so their order match the import order. t.Run("All", func(t *testing.T) { - if !sort.IsSorted(sortedAnalyzers(allAnalyzers)) { + if !slices.IsSortedFunc(allAnalyzers, sortAnalyzers) { t.Error("please keep all analyzers list sorted by name") } }) + t.Run("Default", func(t *testing.T) { - if !sort.IsSorted(sortedAnalyzers(defaultAnalyzers)) { + if !slices.IsSortedFunc(defaultAnalyzers, sortAnalyzers) { t.Error("please keep default analyzers list sorted by name") } }) @@ -70,6 +72,7 @@ func TestGovetAnalyzerIsEnabled(t *testing.T) { Disable []string EnableAll bool DisableAll bool + Go string Name string Enabled bool @@ -81,12 +84,14 @@ func TestGovetAnalyzerIsEnabled(t *testing.T) { {Name: "unsafeptr", Enabled: true, Enable: []string{"unsafeptr"}}, {Name: "shift", Enabled: true, EnableAll: true}, {Name: "shadow", EnableAll: true, Disable: []string{"shadow"}, Enabled: false}, + {Name: "loopclosure", EnableAll: true, Enabled: false, Go: "1.22"}, // TODO(ldez) remove loopclosure when go1.23 } { cfg := &config.GovetSettings{ Enable: tc.Enable, Disable: tc.Disable, EnableAll: tc.EnableAll, DisableAll: tc.DisableAll, + Go: tc.Go, } if enabled := isAnalyzerEnabled(tc.Name, cfg, defaultAnalyzers); enabled != tc.Enabled { t.Errorf("%+v", tc) diff --git a/pkg/golinters/grouper.go b/pkg/golinters/grouper.go index e8c1340e4b7e..41761f2ae019 100644 --- a/pkg/golinters/grouper.go +++ b/pkg/golinters/grouper.go @@ -9,9 +9,9 @@ import ( ) func NewGrouper(settings *config.GrouperSettings) *goanalysis.Linter { - linterCfg := map[string]map[string]interface{}{} + linterCfg := map[string]map[string]any{} if settings != nil { - linterCfg["grouper"] = map[string]interface{}{ + linterCfg["grouper"] = map[string]any{ "const-require-single-const": settings.ConstRequireSingleConst, "const-require-grouping": settings.ConstRequireGrouping, "import-require-single-import": settings.ImportRequireSingleImport, @@ -25,7 +25,7 @@ func NewGrouper(settings *config.GrouperSettings) *goanalysis.Linter { return goanalysis.NewLinter( "grouper", - "An analyzer to analyze expression groups.", + "Analyze expression groups.", []*analysis.Analyzer{grouper.New()}, linterCfg, ).WithLoadMode(goanalysis.LoadModeSyntax) diff --git a/pkg/golinters/ifshort.go b/pkg/golinters/ifshort.go deleted file mode 100644 index c26f08e40365..000000000000 --- a/pkg/golinters/ifshort.go +++ /dev/null @@ -1,28 +0,0 @@ -package golinters - -import ( - "github.com/esimonov/ifshort/pkg/analyzer" - "golang.org/x/tools/go/analysis" - - "github.com/golangci/golangci-lint/pkg/config" - "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" -) - -func NewIfshort(settings *config.IfshortSettings) *goanalysis.Linter { - var cfg map[string]map[string]interface{} - if settings != nil { - cfg = map[string]map[string]interface{}{ - analyzer.Analyzer.Name: { - "max-decl-lines": settings.MaxDeclLines, - "max-decl-chars": settings.MaxDeclChars, - }, - } - } - - return goanalysis.NewLinter( - "ifshort", - "Checks that your code uses short syntax for if-statements whenever possible", - []*analysis.Analyzer{analyzer.Analyzer}, - cfg, - ).WithLoadMode(goanalysis.LoadModeSyntax) -} diff --git a/pkg/golinters/importas.go b/pkg/golinters/importas.go index 1917bbb0c68b..b06aec7a3b4b 100644 --- a/pkg/golinters/importas.go +++ b/pkg/golinters/importas.go @@ -3,6 +3,7 @@ package golinters import ( "fmt" "strconv" + "strings" "github.com/julz/importas" //nolint:misspell "golang.org/x/tools/go/analysis" @@ -36,12 +37,27 @@ func NewImportAs(settings *config.ImportAsSettings) *goanalysis.Linter { lintCtx.Log.Errorf("failed to parse configuration: %v", err) } + uniqPackages := make(map[string]config.ImportAsAlias) + uniqAliases := make(map[string]config.ImportAsAlias) for _, a := range settings.Alias { if a.Pkg == "" { lintCtx.Log.Errorf("invalid configuration, empty package: pkg=%s alias=%s", a.Pkg, a.Alias) continue } + if v, ok := uniqPackages[a.Pkg]; ok { + lintCtx.Log.Errorf("invalid configuration, multiple aliases for the same package: pkg=%s aliases=[%s,%s]", a.Pkg, a.Alias, v.Alias) + } else { + uniqPackages[a.Pkg] = a + } + + // skip the duplication check when the alias is a regular expression replacement pattern (ie. contains `$`). + if v, ok := uniqAliases[a.Alias]; ok && !strings.Contains(a.Alias, "$") { + lintCtx.Log.Errorf("invalid configuration, multiple packages with the same alias: alias=%s packages=[%s,%s]", a.Alias, a.Pkg, v.Pkg) + } else { + uniqAliases[a.Alias] = a + } + err := analyzer.Flags.Set("alias", fmt.Sprintf("%s:%s", a.Pkg, a.Alias)) if err != nil { lintCtx.Log.Errorf("failed to parse configuration: %v", err) diff --git a/pkg/golinters/inamedparam.go b/pkg/golinters/inamedparam.go new file mode 100644 index 000000000000..887f3db2adb9 --- /dev/null +++ b/pkg/golinters/inamedparam.go @@ -0,0 +1,30 @@ +package golinters + +import ( + "github.com/macabu/inamedparam" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" +) + +func NewINamedParam(settings *config.INamedParamSettings) *goanalysis.Linter { + a := inamedparam.Analyzer + + var cfg map[string]map[string]any + + if settings != nil { + cfg = map[string]map[string]any{ + a.Name: { + "skip-single-param": settings.SkipSingleParam, + }, + } + } + + return goanalysis.NewLinter( + a.Name, + a.Doc, + []*analysis.Analyzer{a}, + cfg, + ).WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/pkg/golinters/ineffassign.go b/pkg/golinters/ineffassign.go index c87bb2fa51c0..ac5eb20adb65 100644 --- a/pkg/golinters/ineffassign.go +++ b/pkg/golinters/ineffassign.go @@ -8,10 +8,12 @@ import ( ) func NewIneffassign() *goanalysis.Linter { + a := ineffassign.Analyzer + return goanalysis.NewLinter( - "ineffassign", + a.Name, "Detects when assignments to existing variables are not used", - []*analysis.Analyzer{ineffassign.Analyzer}, + []*analysis.Analyzer{a}, nil, ).WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/interfacebloat.go b/pkg/golinters/interfacebloat.go index 044c96f3b1bf..a6dbfe178fe1 100644 --- a/pkg/golinters/interfacebloat.go +++ b/pkg/golinters/interfacebloat.go @@ -11,9 +11,9 @@ import ( func NewInterfaceBloat(settings *config.InterfaceBloatSettings) *goanalysis.Linter { a := analyzer.New() - var cfg map[string]map[string]interface{} + var cfg map[string]map[string]any if settings != nil { - cfg = map[string]map[string]interface{}{ + cfg = map[string]map[string]any{ a.Name: { analyzer.InterfaceMaxMethodsFlag: settings.Max, }, diff --git a/pkg/golinters/interfacer.go b/pkg/golinters/interfacer.go deleted file mode 100644 index 59125c5c7b4d..000000000000 --- a/pkg/golinters/interfacer.go +++ /dev/null @@ -1,82 +0,0 @@ -package golinters - -import ( - "sync" - - "golang.org/x/tools/go/analysis" - "golang.org/x/tools/go/analysis/passes/buildssa" - "mvdan.cc/interfacer/check" - - "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" - "github.com/golangci/golangci-lint/pkg/lint/linter" - "github.com/golangci/golangci-lint/pkg/result" -) - -const interfacerName = "interfacer" - -func NewInterfacer() *goanalysis.Linter { - var mu sync.Mutex - var resIssues []goanalysis.Issue - - analyzer := &analysis.Analyzer{ - Name: interfacerName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Requires: []*analysis.Analyzer{buildssa.Analyzer}, - Run: func(pass *analysis.Pass) (interface{}, error) { - issues, err := runInterfacer(pass) - if err != nil { - return nil, err - } - - if len(issues) == 0 { - return nil, nil - } - - mu.Lock() - resIssues = append(resIssues, issues...) - mu.Unlock() - - return nil, nil - }, - } - - return goanalysis.NewLinter( - interfacerName, - "Linter that suggests narrower interface types", - []*analysis.Analyzer{analyzer}, - nil, - ).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return resIssues - }).WithLoadMode(goanalysis.LoadModeTypesInfo) -} - -func runInterfacer(pass *analysis.Pass) ([]goanalysis.Issue, error) { - c := &check.Checker{} - - prog := goanalysis.MakeFakeLoaderProgram(pass) - c.Program(prog) - - ssa := pass.ResultOf[buildssa.Analyzer].(*buildssa.SSA) - ssaPkg := ssa.Pkg - c.ProgramSSA(ssaPkg.Prog) - - lintIssues, err := c.Check() - if err != nil { - return nil, err - } - if len(lintIssues) == 0 { - return nil, nil - } - - issues := make([]goanalysis.Issue, 0, len(lintIssues)) - for _, i := range lintIssues { - pos := pass.Fset.Position(i.Pos()) - issues = append(issues, goanalysis.NewIssue(&result.Issue{ - Pos: pos, - Text: i.Message(), - FromLinter: interfacerName, - }, pass)) - } - - return issues, nil -} diff --git a/pkg/golinters/nosnakecase.go b/pkg/golinters/intrange.go similarity index 70% rename from pkg/golinters/nosnakecase.go rename to pkg/golinters/intrange.go index 26d5d6d4c84f..8de956dc129b 100644 --- a/pkg/golinters/nosnakecase.go +++ b/pkg/golinters/intrange.go @@ -1,14 +1,14 @@ package golinters import ( - "github.com/sivchari/nosnakecase" + "github.com/ckaznocha/intrange" "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" ) -func NewNoSnakeCase() *goanalysis.Linter { - a := nosnakecase.Analyzer +func NewIntrange() *goanalysis.Linter { + a := intrange.Analyzer return goanalysis.NewLinter( a.Name, diff --git a/pkg/golinters/ireturn.go b/pkg/golinters/ireturn.go index f2d4aec92fef..dc09dad0eef3 100644 --- a/pkg/golinters/ireturn.go +++ b/pkg/golinters/ireturn.go @@ -13,11 +13,12 @@ import ( func NewIreturn(settings *config.IreturnSettings) *goanalysis.Linter { a := analyzer.NewAnalyzer() - cfg := map[string]map[string]interface{}{} + cfg := map[string]map[string]any{} if settings != nil { - cfg[a.Name] = map[string]interface{}{ - "allow": strings.Join(settings.Allow, ","), - "reject": strings.Join(settings.Reject, ","), + cfg[a.Name] = map[string]any{ + "allow": strings.Join(settings.Allow, ","), + "reject": strings.Join(settings.Reject, ","), + "nonolint": true, } } diff --git a/pkg/golinters/lll.go b/pkg/golinters/lll.go index 551ff98a2c87..61498087a93d 100644 --- a/pkg/golinters/lll.go +++ b/pkg/golinters/lll.go @@ -2,6 +2,7 @@ package golinters import ( "bufio" + "errors" "fmt" "go/token" "os" @@ -19,6 +20,8 @@ import ( const lllName = "lll" +const goCommentDirectivePrefix = "//go:" + //nolint:dupl func NewLLL(settings *config.LllSettings) *goanalysis.Linter { var mu sync.Mutex @@ -27,7 +30,7 @@ func NewLLL(settings *config.LllSettings) *goanalysis.Linter { analyzer := &analysis.Analyzer{ Name: lllName, Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (interface{}, error) { + Run: func(pass *analysis.Pass) (any, error) { issues, err := runLll(pass, settings) if err != nil { return nil, err @@ -80,7 +83,7 @@ func getLLLIssuesForFile(filename string, maxLineLen int, tabSpaces string) ([]r f, err := os.Open(filename) if err != nil { - return nil, fmt.Errorf("can't open file %s: %s", filename, err) + return nil, fmt.Errorf("can't open file %s: %w", filename, err) } defer f.Close() @@ -94,6 +97,10 @@ func getLLLIssuesForFile(filename string, maxLineLen int, tabSpaces string) ([]r line := scanner.Text() line = strings.ReplaceAll(line, "\t", tabSpaces) + if strings.HasPrefix(line, goCommentDirectivePrefix) { + continue + } + if strings.HasPrefix(line, "import") { multiImportEnabled = strings.HasSuffix(line, "(") continue @@ -121,7 +128,7 @@ func getLLLIssuesForFile(filename string, maxLineLen int, tabSpaces string) ([]r } if err := scanner.Err(); err != nil { - if err == bufio.ErrTooLong && maxLineLen < bufio.MaxScanTokenSize { + if errors.Is(err, bufio.ErrTooLong) && maxLineLen < bufio.MaxScanTokenSize { // scanner.Scan() might fail if the line is longer than bufio.MaxScanTokenSize // In the case where the specified maxLineLen is smaller than bufio.MaxScanTokenSize // we can return this line as a long line instead of returning an error. @@ -142,7 +149,7 @@ func getLLLIssuesForFile(filename string, maxLineLen int, tabSpaces string) ([]r FromLinter: lllName, }) } else { - return nil, fmt.Errorf("can't scan file %s: %s", filename, err) + return nil, fmt.Errorf("can't scan file %s: %w", filename, err) } } diff --git a/pkg/golinters/maintidx.go b/pkg/golinters/maintidx.go index 183006b05c5e..55509d970c19 100644 --- a/pkg/golinters/maintidx.go +++ b/pkg/golinters/maintidx.go @@ -11,12 +11,12 @@ import ( func NewMaintIdx(cfg *config.MaintIdxSettings) *goanalysis.Linter { analyzer := maintidx.Analyzer - cfgMap := map[string]map[string]interface{}{ + cfgMap := map[string]map[string]any{ analyzer.Name: {"under": 20}, } if cfg != nil { - cfgMap[analyzer.Name] = map[string]interface{}{ + cfgMap[analyzer.Name] = map[string]any{ "under": cfg.Under, } } diff --git a/pkg/golinters/makezero.go b/pkg/golinters/makezero.go index 5d55f01e7703..a9828629a2e1 100644 --- a/pkg/golinters/makezero.go +++ b/pkg/golinters/makezero.go @@ -1,10 +1,10 @@ package golinters import ( + "fmt" "sync" "github.com/ashanbrown/makezero/makezero" - "github.com/pkg/errors" "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/pkg/config" @@ -23,7 +23,7 @@ func NewMakezero(settings *config.MakezeroSettings) *goanalysis.Linter { analyzer := &analysis.Analyzer{ Name: makezeroName, Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (interface{}, error) { + Run: func(pass *analysis.Pass) (any, error) { issues, err := runMakeZero(pass, settings) if err != nil { return nil, err @@ -59,7 +59,7 @@ func runMakeZero(pass *analysis.Pass, settings *config.MakezeroSettings) ([]goan for _, file := range pass.Files { hints, err := zero.Run(pass.Fset, pass.TypesInfo, file) if err != nil { - return nil, errors.Wrapf(err, "makezero linter failed on file %q", file.Name.String()) + return nil, fmt.Errorf("makezero linter failed on file %q: %w", file.Name.String(), err) } for _, hint := range hints { diff --git a/pkg/golinters/maligned.go b/pkg/golinters/maligned.go deleted file mode 100644 index 9c3ca8b5fe6e..000000000000 --- a/pkg/golinters/maligned.go +++ /dev/null @@ -1,74 +0,0 @@ -package golinters - -import ( - "fmt" - "sync" - - malignedAPI "github.com/golangci/maligned" - "golang.org/x/tools/go/analysis" - - "github.com/golangci/golangci-lint/pkg/config" - "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" - "github.com/golangci/golangci-lint/pkg/lint/linter" - "github.com/golangci/golangci-lint/pkg/result" -) - -const malignedName = "maligned" - -//nolint:dupl -func NewMaligned(settings *config.MalignedSettings) *goanalysis.Linter { - var mu sync.Mutex - var res []goanalysis.Issue - - analyzer := &analysis.Analyzer{ - Name: malignedName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (interface{}, error) { - issues := runMaligned(pass, settings) - - if len(issues) == 0 { - return nil, nil - } - - mu.Lock() - res = append(res, issues...) - mu.Unlock() - - return nil, nil - }, - } - - return goanalysis.NewLinter( - malignedName, - "Tool to detect Go structs that would take less memory if their fields were sorted", - []*analysis.Analyzer{analyzer}, - nil, - ).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return res - }).WithLoadMode(goanalysis.LoadModeTypesInfo) -} - -func runMaligned(pass *analysis.Pass, settings *config.MalignedSettings) []goanalysis.Issue { - prog := goanalysis.MakeFakeLoaderProgram(pass) - - malignedIssues := malignedAPI.Run(prog) - if len(malignedIssues) == 0 { - return nil - } - - issues := make([]goanalysis.Issue, 0, len(malignedIssues)) - for _, i := range malignedIssues { - text := fmt.Sprintf("struct of size %d bytes could be of size %d bytes", i.OldSize, i.NewSize) - if settings.SuggestNewOrder { - text += fmt.Sprintf(":\n%s", formatCodeBlock(i.NewStructDef, nil)) - } - - issues = append(issues, goanalysis.NewIssue(&result.Issue{ - Pos: i.Pos, - Text: text, - FromLinter: malignedName, - }, pass)) - } - - return issues -} diff --git a/pkg/golinters/mirror.go b/pkg/golinters/mirror.go new file mode 100644 index 000000000000..d6e2bb06ac84 --- /dev/null +++ b/pkg/golinters/mirror.go @@ -0,0 +1,70 @@ +package golinters + +import ( + "sync" + + "github.com/butuzov/mirror" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +func NewMirror() *goanalysis.Linter { + var ( + mu sync.Mutex + issues []goanalysis.Issue + ) + + a := mirror.NewAnalyzer() + a.Run = func(pass *analysis.Pass) (any, error) { + // mirror only lints test files if the `--with-tests` flag is passed, + // so we pass the `with-tests` flag as true to the analyzer before running it. + // This can be turned off by using the regular golangci-lint flags such as `--tests` or `--skip-files` + // or can be disabled per linter via exclude rules. + // (see https://github.com/golangci/golangci-lint/issues/2527#issuecomment-1023707262) + violations := mirror.Run(pass, true) + + if len(violations) == 0 { + return nil, nil + } + + for index := range violations { + i := violations[index].Issue(pass.Fset) + + issue := result.Issue{ + FromLinter: a.Name, + Text: i.Message, + Pos: i.Start, + } + + if i.InlineFix != "" { + issue.Replacement = &result.Replacement{ + Inline: &result.InlineFix{ + StartCol: i.Start.Column - 1, + Length: len(i.Original), + NewString: i.InlineFix, + }, + } + } + + mu.Lock() + issues = append(issues, goanalysis.NewIssue(&issue, pass)) + mu.Unlock() + } + + return nil, nil + } + + analyzer := goanalysis.NewLinter( + a.Name, + a.Doc, + []*analysis.Analyzer{a}, + nil, + ).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return issues + }).WithLoadMode(goanalysis.LoadModeTypesInfo) + + return analyzer +} diff --git a/pkg/golinters/misspell.go b/pkg/golinters/misspell.go index b5cc5c8a89d4..8a97534c58ff 100644 --- a/pkg/golinters/misspell.go +++ b/pkg/golinters/misspell.go @@ -5,6 +5,7 @@ import ( "go/token" "strings" "sync" + "unicode" "github.com/golangci/misspell" "golang.org/x/tools/go/analysis" @@ -29,18 +30,18 @@ func NewMisspell(settings *config.MisspellSettings) *goanalysis.Linter { return goanalysis.NewLinter( misspellName, - "Finds commonly misspelled English words in comments", + "Finds commonly misspelled English words", []*analysis.Analyzer{analyzer}, nil, ).WithContextSetter(func(lintCtx *linter.Context) { replacer, ruleErr := createMisspellReplacer(settings) - analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + analyzer.Run = func(pass *analysis.Pass) (any, error) { if ruleErr != nil { return nil, ruleErr } - issues, err := runMisspell(lintCtx, pass, replacer) + issues, err := runMisspell(lintCtx, pass, replacer, settings.Mode) if err != nil { return nil, err } @@ -60,15 +61,16 @@ func NewMisspell(settings *config.MisspellSettings) *goanalysis.Linter { }).WithLoadMode(goanalysis.LoadModeSyntax) } -func runMisspell(lintCtx *linter.Context, pass *analysis.Pass, replacer *misspell.Replacer) ([]goanalysis.Issue, error) { +func runMisspell(lintCtx *linter.Context, pass *analysis.Pass, replacer *misspell.Replacer, mode string) ([]goanalysis.Issue, error) { fileNames := getFileNames(pass) var issues []goanalysis.Issue for _, filename := range fileNames { - lintIssues, err := runMisspellOnFile(lintCtx, filename, replacer) + lintIssues, err := runMisspellOnFile(lintCtx, filename, replacer, mode) if err != nil { return nil, err } + for i := range lintIssues { issues = append(issues, goanalysis.NewIssue(&lintIssues[i], pass)) } @@ -94,6 +96,11 @@ func createMisspellReplacer(settings *config.MisspellSettings) (*misspell.Replac return nil, fmt.Errorf("unknown locale: %q", settings.Locale) } + err := appendExtraWords(replacer, settings.ExtraWords) + if err != nil { + return nil, fmt.Errorf("process extra words: %w", err) + } + if len(settings.IgnoreWords) != 0 { replacer.RemoveRule(settings.IgnoreWords) } @@ -104,25 +111,36 @@ func createMisspellReplacer(settings *config.MisspellSettings) (*misspell.Replac return replacer, nil } -func runMisspellOnFile(lintCtx *linter.Context, filename string, replacer *misspell.Replacer) ([]result.Issue, error) { - var res []result.Issue +func runMisspellOnFile(lintCtx *linter.Context, filename string, replacer *misspell.Replacer, mode string) ([]result.Issue, error) { fileContent, err := lintCtx.FileCache.GetFileBytes(filename) if err != nil { - return nil, fmt.Errorf("can't get file %s contents: %s", filename, err) + return nil, fmt.Errorf("can't get file %s contents: %w", filename, err) + } + + // `r.ReplaceGo` doesn't find issues inside strings: it searches only inside comments. + // `r.Replace` searches all words: it treats input as a plain text. + // The standalone misspell tool uses `r.Replace` by default. + var replace func(input string) (string, []misspell.Diff) + switch strings.ToLower(mode) { + case "restricted": + replace = replacer.ReplaceGo + default: + replace = replacer.Replace } - // use r.Replace, not r.ReplaceGo because r.ReplaceGo doesn't find - // issues inside strings: it searches only inside comments. r.Replace - // searches all words: it treats input as a plain text. A standalone misspell - // tool uses r.Replace by default. - _, diffs := replacer.Replace(string(fileContent)) + _, diffs := replace(string(fileContent)) + + var res []result.Issue + for _, diff := range diffs { text := fmt.Sprintf("`%s` is a misspelling of `%s`", diff.Original, diff.Corrected) + pos := token.Position{ Filename: filename, Line: diff.Line, Column: diff.Column + 1, } + replacement := &result.Replacement{ Inline: &result.InlineFix{ StartCol: diff.Column, @@ -141,3 +159,30 @@ func runMisspellOnFile(lintCtx *linter.Context, filename string, replacer *missp return res, nil } + +func appendExtraWords(replacer *misspell.Replacer, extraWords []config.MisspellExtraWords) error { + if len(extraWords) == 0 { + return nil + } + + extra := make([]string, 0, len(extraWords)*2) + + for _, word := range extraWords { + if word.Typo == "" || word.Correction == "" { + return fmt.Errorf("typo (%q) and correction (%q) fields should not be empty", word.Typo, word.Correction) + } + + if strings.ContainsFunc(word.Typo, func(r rune) bool { return !unicode.IsLetter(r) }) { + return fmt.Errorf("the word %q in the 'typo' field should only contain letters", word.Typo) + } + if strings.ContainsFunc(word.Correction, func(r rune) bool { return !unicode.IsLetter(r) }) { + return fmt.Errorf("the word %q in the 'correction' field should only contain letters", word.Correction) + } + + extra = append(extra, strings.ToLower(word.Typo), strings.ToLower(word.Correction)) + } + + replacer.AddRuleList(extra) + + return nil +} diff --git a/pkg/golinters/misspell_test.go b/pkg/golinters/misspell_test.go new file mode 100644 index 000000000000..29e0862f9b83 --- /dev/null +++ b/pkg/golinters/misspell_test.go @@ -0,0 +1,94 @@ +package golinters + +import ( + "testing" + + "github.com/golangci/misspell" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/golangci/golangci-lint/pkg/config" +) + +func Test_appendExtraWords(t *testing.T) { + extraWords := []config.MisspellExtraWords{ + { + Typo: "iff", + Correction: "if", + }, + { + Typo: "canCELation", + Correction: "canceLLaTION", + }, + } + + replacer := &misspell.Replacer{} + + err := appendExtraWords(replacer, extraWords) + require.NoError(t, err) + + expected := []string{"iff", "if", "cancelation", "cancellation"} + + assert.Equal(t, replacer.Replacements, expected) +} + +func Test_appendExtraWords_error(t *testing.T) { + testCases := []struct { + desc string + extraWords []config.MisspellExtraWords + expected string + }{ + { + desc: "empty fields", + extraWords: []config.MisspellExtraWords{{ + Typo: "", + Correction: "", + }}, + expected: `typo ("") and correction ("") fields should not be empty`, + }, + { + desc: "empty typo", + extraWords: []config.MisspellExtraWords{{ + Typo: "", + Correction: "if", + }}, + expected: `typo ("") and correction ("if") fields should not be empty`, + }, + { + desc: "empty correction", + extraWords: []config.MisspellExtraWords{{ + Typo: "iff", + Correction: "", + }}, + expected: `typo ("iff") and correction ("") fields should not be empty`, + }, + { + desc: "invalid characters in typo", + extraWords: []config.MisspellExtraWords{{ + Typo: "i'ff", + Correction: "if", + }}, + expected: `the word "i'ff" in the 'typo' field should only contain letters`, + }, + { + desc: "invalid characters in correction", + extraWords: []config.MisspellExtraWords{{ + Typo: "iff", + Correction: "i'f", + }}, + expected: `the word "i'f" in the 'correction' field should only contain letters`, + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + replacer := &misspell.Replacer{} + + err := appendExtraWords(replacer, test.extraWords) + require.EqualError(t, err, test.expected) + }) + } +} diff --git a/pkg/golinters/musttag.go b/pkg/golinters/musttag.go index 75500b5aba44..72d91958287d 100644 --- a/pkg/golinters/musttag.go +++ b/pkg/golinters/musttag.go @@ -1,7 +1,7 @@ package golinters import ( - "github.com/junk1tm/musttag" + "go-simpler.org/musttag" "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/pkg/config" diff --git a/pkg/golinters/nakedret.go b/pkg/golinters/nakedret.go index dc2de0345a7a..6153860fb4b2 100644 --- a/pkg/golinters/nakedret.go +++ b/pkg/golinters/nakedret.go @@ -1,134 +1,25 @@ package golinters import ( - "fmt" - "go/ast" - "go/token" - "sync" - + "github.com/alexkohler/nakedret/v2" "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/pkg/config" "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" - "github.com/golangci/golangci-lint/pkg/lint/linter" - "github.com/golangci/golangci-lint/pkg/result" ) -const nakedretName = "nakedret" - -//nolint:dupl func NewNakedret(settings *config.NakedretSettings) *goanalysis.Linter { - var mu sync.Mutex - var resIssues []goanalysis.Issue - - analyzer := &analysis.Analyzer{ - Name: nakedretName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (interface{}, error) { - issues := runNakedRet(pass, settings) - - if len(issues) == 0 { - return nil, nil - } - - mu.Lock() - resIssues = append(resIssues, issues...) - mu.Unlock() - - return nil, nil - }, + var maxLines int + if settings != nil { + maxLines = settings.MaxFuncLines } + a := nakedret.NakedReturnAnalyzer(uint(maxLines)) + return goanalysis.NewLinter( - nakedretName, - "Finds naked returns in functions greater than a specified function length", - []*analysis.Analyzer{analyzer}, + a.Name, + a.Doc, + []*analysis.Analyzer{a}, nil, - ).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return resIssues - }).WithLoadMode(goanalysis.LoadModeSyntax) -} - -func runNakedRet(pass *analysis.Pass, settings *config.NakedretSettings) []goanalysis.Issue { - var issues []goanalysis.Issue - - for _, file := range pass.Files { - v := nakedretVisitor{ - maxLength: settings.MaxFuncLines, - f: pass.Fset, - } - - ast.Walk(&v, file) - - for i := range v.issues { - issues = append(issues, goanalysis.NewIssue(&v.issues[i], pass)) - } - } - - return issues -} - -type nakedretVisitor struct { - maxLength int - f *token.FileSet - issues []result.Issue -} - -func (v *nakedretVisitor) processFuncDecl(funcDecl *ast.FuncDecl) { - file := v.f.File(funcDecl.Pos()) - functionLineLength := file.Position(funcDecl.End()).Line - file.Position(funcDecl.Pos()).Line - - // Scan the body for usage of the named returns - for _, stmt := range funcDecl.Body.List { - s, ok := stmt.(*ast.ReturnStmt) - if !ok { - continue - } - - if len(s.Results) != 0 { - continue - } - - file := v.f.File(s.Pos()) - if file == nil || functionLineLength <= v.maxLength { - continue - } - if funcDecl.Name == nil { - continue - } - - v.issues = append(v.issues, result.Issue{ - FromLinter: nakedretName, - Text: fmt.Sprintf("naked return in func `%s` with %d lines of code", - funcDecl.Name.Name, functionLineLength), - Pos: v.f.Position(s.Pos()), - }) - } -} - -func (v *nakedretVisitor) Visit(node ast.Node) ast.Visitor { - funcDecl, ok := node.(*ast.FuncDecl) - if !ok { - return v - } - - var namedReturns []*ast.Ident - - // We've found a function - if funcDecl.Type != nil && funcDecl.Type.Results != nil { - for _, field := range funcDecl.Type.Results.List { - for _, ident := range field.Names { - if ident != nil { - namedReturns = append(namedReturns, ident) - } - } - } - } - - if len(namedReturns) == 0 || funcDecl.Body == nil { - return v - } - - v.processFuncDecl(funcDecl) - return v + ).WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/nestif.go b/pkg/golinters/nestif.go index 78a516f9d1ec..12ad69eceb39 100644 --- a/pkg/golinters/nestif.go +++ b/pkg/golinters/nestif.go @@ -23,7 +23,7 @@ func NewNestif(settings *config.NestifSettings) *goanalysis.Linter { analyzer := &analysis.Analyzer{ Name: goanalysis.TheOnlyAnalyzerName, Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (interface{}, error) { + Run: func(pass *analysis.Pass) (any, error) { issues := runNestIf(pass, settings) if len(issues) == 0 { diff --git a/pkg/golinters/nilnil.go b/pkg/golinters/nilnil.go index 739b4d4fcb73..804557b76dc2 100644 --- a/pkg/golinters/nilnil.go +++ b/pkg/golinters/nilnil.go @@ -13,9 +13,9 @@ import ( func NewNilNil(cfg *config.NilNilSettings) *goanalysis.Linter { a := analyzer.New() - cfgMap := make(map[string]map[string]interface{}) + cfgMap := make(map[string]map[string]any) if cfg != nil && len(cfg.CheckedTypes) != 0 { - cfgMap[a.Name] = map[string]interface{}{ + cfgMap[a.Name] = map[string]any{ "checked-types": strings.Join(cfg.CheckedTypes, ","), } } diff --git a/pkg/golinters/nlreturn.go b/pkg/golinters/nlreturn.go index fb4919f8a953..a359548f420f 100644 --- a/pkg/golinters/nlreturn.go +++ b/pkg/golinters/nlreturn.go @@ -11,9 +11,9 @@ import ( func NewNLReturn(settings *config.NlreturnSettings) *goanalysis.Linter { a := nlreturn.NewAnalyzer() - cfg := map[string]map[string]interface{}{} + cfg := map[string]map[string]any{} if settings != nil { - cfg[a.Name] = map[string]interface{}{ + cfg[a.Name] = map[string]any{ "block-size": settings.BlockSize, } } diff --git a/pkg/golinters/noctx.go b/pkg/golinters/noctx.go index b7fcd2a737af..cff9c97dcf28 100644 --- a/pkg/golinters/noctx.go +++ b/pkg/golinters/noctx.go @@ -8,10 +8,12 @@ import ( ) func NewNoctx() *goanalysis.Linter { + a := noctx.Analyzer + return goanalysis.NewLinter( - "noctx", - "noctx finds sending http request without context.Context", - []*analysis.Analyzer{noctx.Analyzer}, + a.Name, + "Finds sending http request without context.Context", + []*analysis.Analyzer{a}, nil, ).WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/nolintlint.go b/pkg/golinters/nolintlint.go index a809f44995ee..ae372ab795b2 100644 --- a/pkg/golinters/nolintlint.go +++ b/pkg/golinters/nolintlint.go @@ -24,7 +24,7 @@ func NewNoLintLint(settings *config.NoLintLintSettings) *goanalysis.Linter { analyzer := &analysis.Analyzer{ Name: NoLintLintName, Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (interface{}, error) { + Run: func(pass *analysis.Pass) (any, error) { issues, err := runNoLintLint(pass, settings) if err != nil { return nil, err @@ -76,7 +76,7 @@ func runNoLintLint(pass *analysis.Pass, settings *config.NoLintLintSettings) ([] lintIssues, err := lnt.Run(pass.Fset, nodes...) if err != nil { - return nil, fmt.Errorf("linter failed to run: %s", err) + return nil, fmt.Errorf("linter failed to run: %w", err) } var issues []goanalysis.Issue diff --git a/pkg/golinters/nolintlint/nolintlint.go b/pkg/golinters/nolintlint/nolintlint.go index 9c6b10f38c50..aadc7eb681fc 100644 --- a/pkg/golinters/nolintlint/nolintlint.go +++ b/pkg/golinters/nolintlint/nolintlint.go @@ -19,12 +19,12 @@ type BaseIssue struct { replacement *result.Replacement } -//nolint:gocritic // TODO must be change in the future. +//nolint:gocritic // TODO(ldez) must be change in the future. func (b BaseIssue) Position() token.Position { return b.position } -//nolint:gocritic // TODO must be change in the future. +//nolint:gocritic // TODO(ldez) must be change in the future. func (b BaseIssue) Replacement() *result.Replacement { return b.replacement } @@ -33,53 +33,49 @@ type ExtraLeadingSpace struct { BaseIssue } -//nolint:gocritic // TODO must be change in the future. +//nolint:gocritic // TODO(ldez) must be change in the future. func (i ExtraLeadingSpace) Details() string { return fmt.Sprintf("directive `%s` should not have more than one leading space", i.fullDirective) } -//nolint:gocritic // TODO must be change in the future. func (i ExtraLeadingSpace) String() string { return toString(i) } type NotMachine struct { BaseIssue } -//nolint:gocritic // TODO must be change in the future. +//nolint:gocritic // TODO(ldez) must be change in the future. func (i NotMachine) Details() string { expected := i.fullDirective[:2] + strings.TrimLeftFunc(i.fullDirective[2:], unicode.IsSpace) return fmt.Sprintf("directive `%s` should be written without leading space as `%s`", i.fullDirective, expected) } -//nolint:gocritic // TODO must be change in the future. func (i NotMachine) String() string { return toString(i) } type NotSpecific struct { BaseIssue } -//nolint:gocritic // TODO must be change in the future. +//nolint:gocritic // TODO(ldez) must be change in the future. func (i NotSpecific) Details() string { return fmt.Sprintf("directive `%s` should mention specific linter such as `%s:my-linter`", i.fullDirective, i.directiveWithOptionalLeadingSpace) } -//nolint:gocritic // TODO must be change in the future. func (i NotSpecific) String() string { return toString(i) } type ParseError struct { BaseIssue } -//nolint:gocritic // TODO must be change in the future. +//nolint:gocritic // TODO(ldez) must be change in the future. func (i ParseError) Details() string { return fmt.Sprintf("directive `%s` should match `%s[:] [// ]`", i.fullDirective, i.directiveWithOptionalLeadingSpace) } -//nolint:gocritic // TODO must be change in the future. func (i ParseError) String() string { return toString(i) } type NoExplanation struct { @@ -87,13 +83,12 @@ type NoExplanation struct { fullDirectiveWithoutExplanation string } -//nolint:gocritic // TODO must be change in the future. +//nolint:gocritic // TODO(ldez) must be change in the future. func (i NoExplanation) Details() string { return fmt.Sprintf("directive `%s` should provide explanation such as `%s // this is why`", i.fullDirective, i.fullDirectiveWithoutExplanation) } -//nolint:gocritic // TODO must be change in the future. func (i NoExplanation) String() string { return toString(i) } type UnusedCandidate struct { @@ -101,7 +96,7 @@ type UnusedCandidate struct { ExpectedLinter string } -//nolint:gocritic // TODO must be change in the future. +//nolint:gocritic // TODO(ldez) must be change in the future. func (i UnusedCandidate) Details() string { details := fmt.Sprintf("directive `%s` is unused", i.fullDirective) if i.ExpectedLinter != "" { @@ -110,11 +105,10 @@ func (i UnusedCandidate) Details() string { return details } -//nolint:gocritic // TODO must be change in the future. func (i UnusedCandidate) String() string { return toString(i) } -func toString(i Issue) string { - return fmt.Sprintf("%s at %s", i.Details(), i.Position()) +func toString(issue Issue) string { + return fmt.Sprintf("%s at %s", issue.Details(), issue.Position()) } type Issue interface { @@ -157,8 +151,10 @@ func NewLinter(needs Needs, excludes []string) (*Linter, error) { }, nil } -var leadingSpacePattern = regexp.MustCompile(`^//(\s*)`) -var trailingBlankExplanation = regexp.MustCompile(`\s*(//\s*)?$`) +var ( + leadingSpacePattern = regexp.MustCompile(`^//(\s*)`) + trailingBlankExplanation = regexp.MustCompile(`\s*(//\s*)?$`) +) //nolint:funlen,gocyclo func (l Linter) Run(fset *token.FileSet, nodes ...ast.Node) ([]Issue, error) { @@ -185,7 +181,7 @@ func (l Linter) Run(fset *token.FileSet, nodes ...ast.Node) ([]Issue, error) { } directiveWithOptionalLeadingSpace := "//" - if len(leadingSpace) > 0 { + if leadingSpace != "" { directiveWithOptionalLeadingSpace += " " } @@ -202,7 +198,7 @@ func (l Linter) Run(fset *token.FileSet, nodes ...ast.Node) ([]Issue, error) { } // check for, report and eliminate leading spaces, so we can check for other issues - if len(leadingSpace) > 0 { + if leadingSpace != "" { removeWhitespace := &result.Replacement{ Inline: &result.InlineFix{ StartCol: pos.Column + 1, @@ -231,7 +227,7 @@ func (l Linter) Run(fset *token.FileSet, nodes ...ast.Node) ([]Issue, error) { lintersText, explanation := fullMatches[1], fullMatches[2] var linters []string - if len(lintersText) > 0 && !strings.HasPrefix(lintersText, "all") { + if lintersText != "" && !strings.HasPrefix(lintersText, "all") { lls := strings.Split(lintersText, ",") linters = make([]string, 0, len(lls)) rangeStart := (pos.Column - 1) + len("//") + len(leadingSpace) + len("nolint:") diff --git a/pkg/golinters/nolintlint/nolintlint_test.go b/pkg/golinters/nolintlint/nolintlint_test.go index 3dba4d6578b3..0400e8dfe623 100644 --- a/pkg/golinters/nolintlint/nolintlint_test.go +++ b/pkg/golinters/nolintlint/nolintlint_test.go @@ -11,7 +11,6 @@ import ( "github.com/golangci/golangci-lint/pkg/result" ) -//nolint:funlen func TestLinter_Run(t *testing.T) { type issueWithReplacement struct { issue string diff --git a/pkg/golinters/nonamedreturns.go b/pkg/golinters/nonamedreturns.go index 3dff2f75909f..7856f6d613ef 100644 --- a/pkg/golinters/nonamedreturns.go +++ b/pkg/golinters/nonamedreturns.go @@ -11,9 +11,9 @@ import ( func NewNoNamedReturns(settings *config.NoNamedReturnsSettings) *goanalysis.Linter { a := analyzer.Analyzer - var cfg map[string]map[string]interface{} + var cfg map[string]map[string]any if settings != nil { - cfg = map[string]map[string]interface{}{ + cfg = map[string]map[string]any{ a.Name: { analyzer.FlagReportErrorInDefer: settings.ReportErrorInDefer, }, diff --git a/pkg/golinters/paralleltest.go b/pkg/golinters/paralleltest.go index 55af7350a009..8215619c730c 100644 --- a/pkg/golinters/paralleltest.go +++ b/pkg/golinters/paralleltest.go @@ -9,20 +9,25 @@ import ( ) func NewParallelTest(settings *config.ParallelTestSettings) *goanalysis.Linter { - a := paralleltest.Analyzer + a := paralleltest.NewAnalyzer() - var cfg map[string]map[string]interface{} + var cfg map[string]map[string]any if settings != nil { - cfg = map[string]map[string]interface{}{ - a.Name: { - "i": settings.IgnoreMissing, - }, + d := map[string]any{ + "i": settings.IgnoreMissing, + "ignoremissingsubtests": settings.IgnoreMissingSubtests, } + + if config.IsGoGreaterThanOrEqual(settings.Go, "1.22") { + d["ignoreloopVar"] = true + } + + cfg = map[string]map[string]any{a.Name: d} } return goanalysis.NewLinter( - "paralleltest", - "paralleltest detects missing usage of t.Parallel() method in your Go test", + a.Name, + "Detects missing usage of t.Parallel() method in your Go test", []*analysis.Analyzer{a}, cfg, ).WithLoadMode(goanalysis.LoadModeTypesInfo) diff --git a/pkg/golinters/perfsprint.go b/pkg/golinters/perfsprint.go new file mode 100644 index 000000000000..6fe315fdea4d --- /dev/null +++ b/pkg/golinters/perfsprint.go @@ -0,0 +1,32 @@ +package golinters + +import ( + "github.com/catenacyber/perfsprint/analyzer" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" +) + +func NewPerfSprint(settings *config.PerfSprintSettings) *goanalysis.Linter { + a := analyzer.New() + + cfg := map[string]map[string]any{ + a.Name: {"fiximports": false}, + } + + if settings != nil { + cfg[a.Name]["int-conversion"] = settings.IntConversion + cfg[a.Name]["err-error"] = settings.ErrError + cfg[a.Name]["errorf"] = settings.ErrorF + cfg[a.Name]["sprintf1"] = settings.SprintF1 + cfg[a.Name]["strconcat"] = settings.StrConcat + } + + return goanalysis.NewLinter( + a.Name, + a.Doc, + []*analysis.Analyzer{a}, + cfg, + ).WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/pkg/golinters/prealloc.go b/pkg/golinters/prealloc.go index 75a9b4ec2f44..f48d57562ef2 100644 --- a/pkg/golinters/prealloc.go +++ b/pkg/golinters/prealloc.go @@ -23,7 +23,7 @@ func NewPreAlloc(settings *config.PreallocSettings) *goanalysis.Linter { analyzer := &analysis.Analyzer{ Name: preallocName, Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (interface{}, error) { + Run: func(pass *analysis.Pass) (any, error) { issues := runPreAlloc(pass, settings) if len(issues) == 0 { diff --git a/pkg/golinters/predeclared.go b/pkg/golinters/predeclared.go index caccd482397f..d3c25e274bb6 100644 --- a/pkg/golinters/predeclared.go +++ b/pkg/golinters/predeclared.go @@ -11,9 +11,9 @@ import ( func NewPredeclared(settings *config.PredeclaredSettings) *goanalysis.Linter { a := predeclared.Analyzer - var cfg map[string]map[string]interface{} + var cfg map[string]map[string]any if settings != nil { - cfg = map[string]map[string]interface{}{ + cfg = map[string]map[string]any{ a.Name: { predeclared.IgnoreFlag: settings.Ignore, predeclared.QualifiedFlag: settings.Qualified, diff --git a/pkg/golinters/promlinter.go b/pkg/golinters/promlinter.go index f77847a49aa4..381c57489d0e 100644 --- a/pkg/golinters/promlinter.go +++ b/pkg/golinters/promlinter.go @@ -30,7 +30,7 @@ func NewPromlinter(settings *config.PromlinterSettings) *goanalysis.Linter { analyzer := &analysis.Analyzer{ Name: promlinterName, Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (interface{}, error) { + Run: func(pass *analysis.Pass) (any, error) { issues := runPromLinter(pass, promSettings) if len(issues) == 0 { diff --git a/pkg/golinters/protogetter.go b/pkg/golinters/protogetter.go new file mode 100644 index 000000000000..9a5e7b4db8eb --- /dev/null +++ b/pkg/golinters/protogetter.go @@ -0,0 +1,74 @@ +package golinters + +import ( + "sync" + + "github.com/ghostiam/protogetter" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +func NewProtoGetter(settings *config.ProtoGetterSettings) *goanalysis.Linter { + var mu sync.Mutex + var resIssues []goanalysis.Issue + + var cfg protogetter.Config + if settings != nil { + cfg = protogetter.Config{ + SkipGeneratedBy: settings.SkipGeneratedBy, + SkipFiles: settings.SkipFiles, + SkipAnyGenerated: settings.SkipAnyGenerated, + ReplaceFirstArgInAppend: settings.ReplaceFirstArgInAppend, + } + } + cfg.Mode = protogetter.GolangciLintMode + + a := protogetter.NewAnalyzer(&cfg) + a.Run = func(pass *analysis.Pass) (any, error) { + pgIssues, err := protogetter.Run(pass, &cfg) + if err != nil { + return nil, err + } + + issues := make([]goanalysis.Issue, len(pgIssues)) + for i, issue := range pgIssues { + report := &result.Issue{ + FromLinter: a.Name, + Pos: issue.Pos, + Text: issue.Message, + Replacement: &result.Replacement{ + Inline: &result.InlineFix{ + StartCol: issue.InlineFix.StartCol, + Length: issue.InlineFix.Length, + NewString: issue.InlineFix.NewString, + }, + }, + } + + issues[i] = goanalysis.NewIssue(report, pass) + } + + if len(issues) == 0 { + return nil, nil + } + + mu.Lock() + resIssues = append(resIssues, issues...) + mu.Unlock() + + return nil, nil + } + + return goanalysis.NewLinter( + a.Name, + a.Doc, + []*analysis.Analyzer{a}, + nil, + ).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }).WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/pkg/golinters/reassign.go b/pkg/golinters/reassign.go index bc1b93a54a3f..a6dd6705308f 100644 --- a/pkg/golinters/reassign.go +++ b/pkg/golinters/reassign.go @@ -14,9 +14,9 @@ import ( func NewReassign(settings *config.ReassignSettings) *goanalysis.Linter { a := reassign.NewAnalyzer() - var cfg map[string]map[string]interface{} + var cfg map[string]map[string]any if settings != nil && len(settings.Patterns) > 0 { - cfg = map[string]map[string]interface{}{ + cfg = map[string]map[string]any{ a.Name: { reassign.FlagPattern: fmt.Sprintf("^(%s)$", strings.Join(settings.Patterns, "|")), }, diff --git a/pkg/golinters/revive.go b/pkg/golinters/revive.go index faa9e0243ed2..fafdedd5d2c0 100644 --- a/pkg/golinters/revive.go +++ b/pkg/golinters/revive.go @@ -13,7 +13,6 @@ import ( reviveConfig "github.com/mgechev/revive/config" "github.com/mgechev/revive/lint" "github.com/mgechev/revive/rule" - "github.com/pkg/errors" "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/pkg/config" @@ -35,7 +34,7 @@ type jsonObject struct { // NewRevive returns a new Revive linter. // -//nolint:dupl + func NewRevive(settings *config.ReviveSettings) *goanalysis.Linter { var mu sync.Mutex var resIssues []goanalysis.Issue @@ -52,7 +51,7 @@ func NewRevive(settings *config.ReviveSettings) *goanalysis.Linter { []*analysis.Analyzer{analyzer}, nil, ).WithContextSetter(func(lintCtx *linter.Context) { - analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + analyzer.Run = func(pass *analysis.Pass) (any, error) { issues, err := runRevive(lintCtx, pass, settings) if err != nil { return nil, err @@ -161,7 +160,8 @@ func reviveToIssue(pass *analysis.Pass, object *jsonObject) goanalysis.Issue { // This function mimics the GetConfig function of revive. // This allows to get default values and right types. // https://github.com/golangci/golangci-lint/issues/1745 -// https://github.com/mgechev/revive/blob/v1.1.4/config/config.go#L182 +// https://github.com/mgechev/revive/blob/v1.3.7/config/config.go#L217 +// https://github.com/mgechev/revive/blob/v1.3.7/config/config.go#L169-L174 func getReviveConfig(cfg *config.ReviveSettings) (*lint.Config, error) { conf := defaultConfig() @@ -171,25 +171,33 @@ func getReviveConfig(cfg *config.ReviveSettings) (*lint.Config, error) { err := toml.NewEncoder(buf).Encode(rawRoot) if err != nil { - return nil, errors.Wrap(err, "failed to encode configuration") + return nil, fmt.Errorf("failed to encode configuration: %w", err) } conf = &lint.Config{} _, err = toml.NewDecoder(buf).Decode(conf) if err != nil { - return nil, errors.Wrap(err, "failed to decode configuration") + return nil, fmt.Errorf("failed to decode configuration: %w", err) } } normalizeConfig(conf) + for k, r := range conf.Rules { + err := r.Initialize() + if err != nil { + return nil, fmt.Errorf("error in config of rule %q: %w", k, err) + } + conf.Rules[k] = r + } + reviveDebugf("revive configuration: %#v", conf) return conf, nil } -func createConfigMap(cfg *config.ReviveSettings) map[string]interface{} { - rawRoot := map[string]interface{}{ +func createConfigMap(cfg *config.ReviveSettings) map[string]any { + rawRoot := map[string]any{ "ignoreGeneratedHeader": cfg.IgnoreGeneratedHeader, "confidence": cfg.Confidence, "severity": cfg.Severity, @@ -198,9 +206,9 @@ func createConfigMap(cfg *config.ReviveSettings) map[string]interface{} { "enableAllRules": cfg.EnableAllRules, } - rawDirectives := map[string]map[string]interface{}{} + rawDirectives := map[string]map[string]any{} for _, directive := range cfg.Directives { - rawDirectives[directive.Name] = map[string]interface{}{ + rawDirectives[directive.Name] = map[string]any{ "severity": directive.Severity, } } @@ -209,12 +217,13 @@ func createConfigMap(cfg *config.ReviveSettings) map[string]interface{} { rawRoot["directive"] = rawDirectives } - rawRules := map[string]map[string]interface{}{} + rawRules := map[string]map[string]any{} for _, s := range cfg.Rules { - rawRules[s.Name] = map[string]interface{}{ + rawRules[s.Name] = map[string]any{ "severity": s.Severity, "arguments": safeTomlSlice(s.Arguments), "disabled": s.Disabled, + "exclude": s.Exclude, } } @@ -225,19 +234,19 @@ func createConfigMap(cfg *config.ReviveSettings) map[string]interface{} { return rawRoot } -func safeTomlSlice(r []interface{}) []interface{} { +func safeTomlSlice(r []any) []any { if len(r) == 0 { return nil } - if _, ok := r[0].(map[interface{}]interface{}); !ok { + if _, ok := r[0].(map[any]any); !ok { return r } - var typed []interface{} + var typed []any for _, elt := range r { - item := map[string]interface{}{} - for k, v := range elt.(map[interface{}]interface{}) { + item := map[string]any{} + for k, v := range elt.(map[any]any) { item[k.(string)] = v } @@ -248,7 +257,7 @@ func safeTomlSlice(r []interface{}) []interface{} { } // This element is not exported by revive, so we need copy the code. -// Extracted from https://github.com/mgechev/revive/blob/v1.1.4/config/config.go#L15 +// Extracted from https://github.com/mgechev/revive/blob/v1.3.7/config/config.go#L15 var defaultRules = []lint.Rule{ &rule.VarDeclarationsRule{}, &rule.PackageCommentsRule{}, @@ -268,21 +277,22 @@ var defaultRules = []lint.Rule{ &rule.TimeNamingRule{}, &rule.ContextKeysType{}, &rule.ContextAsArgumentRule{}, + &rule.EmptyBlockRule{}, + &rule.SuperfluousElseRule{}, + &rule.UnusedParamRule{}, + &rule.UnreachableCodeRule{}, + &rule.RedefinesBuiltinIDRule{}, } var allRules = append([]lint.Rule{ &rule.ArgumentsLimitRule{}, &rule.CyclomaticRule{}, &rule.FileHeaderRule{}, - &rule.EmptyBlockRule{}, - &rule.SuperfluousElseRule{}, &rule.ConfusingNamingRule{}, &rule.GetReturnRule{}, &rule.ModifiesParamRule{}, &rule.ConfusingResultsRule{}, &rule.DeepExitRule{}, - &rule.UnusedParamRule{}, - &rule.UnreachableCodeRule{}, &rule.AddConstantRule{}, &rule.FlagParamRule{}, &rule.UnnecessaryStmtRule{}, @@ -290,8 +300,7 @@ var allRules = append([]lint.Rule{ &rule.ModifiesValRecRule{}, &rule.ConstantLogicalExprRule{}, &rule.BoolLiteralRule{}, - &rule.RedefinesBuiltinIDRule{}, - &rule.ImportsBlacklistRule{}, + &rule.ImportsBlocklistRule{}, &rule.FunctionResultsLimitRule{}, &rule.MaxPublicStructsRule{}, &rule.RangeValInClosureRule{}, @@ -316,12 +325,21 @@ var allRules = append([]lint.Rule{ &rule.UnexportedNamingRule{}, &rule.FunctionLength{}, &rule.NestedStructs{}, - &rule.IfReturnRule{}, &rule.UselessBreak{}, + &rule.UncheckedTypeAssertionRule{}, &rule.TimeEqualRule{}, &rule.BannedCharsRule{}, &rule.OptimizeOperandsOrderRule{}, + &rule.UseAnyRule{}, &rule.DataRaceRule{}, + &rule.CommentSpacingsRule{}, + &rule.IfReturnRule{}, + &rule.RedundantImportAlias{}, + &rule.ImportAliasNamingRule{}, + &rule.EnforceMapStyleRule{}, + &rule.EnforceRepeatedArgTypeStyleRule{}, + &rule.EnforceSliceStyleRule{}, + &rule.MaxControlNestingRule{}, }, defaultRules...) const defaultConfidence = 0.8 @@ -344,8 +362,8 @@ func normalizeConfig(cfg *lint.Config) { } if cfg.EnableAllRules { // Add to the configuration all rules not yet present in it - for _, rule := range allRules { - ruleName := rule.Name() + for _, r := range allRules { + ruleName := r.Name() _, alreadyInConf := cfg.Rules[ruleName] if alreadyInConf { continue diff --git a/pkg/golinters/rowserrcheck.go b/pkg/golinters/rowserrcheck.go index 5a66d62e7dd8..d67efd0692a1 100644 --- a/pkg/golinters/rowserrcheck.go +++ b/pkg/golinters/rowserrcheck.go @@ -14,12 +14,12 @@ func NewRowsErrCheck(settings *config.RowsErrCheckSettings) *goanalysis.Linter { pkgs = settings.Packages } - analyzer := rowserr.NewAnalyzer(pkgs...) + a := rowserr.NewAnalyzer(pkgs...) return goanalysis.NewLinter( - "rowserrcheck", - "checks whether Err of rows is checked successfully", - []*analysis.Analyzer{analyzer}, + a.Name, + "checks whether Rows.Err of rows is checked successfully", + []*analysis.Analyzer{a}, nil, ).WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/scopelint.go b/pkg/golinters/scopelint.go deleted file mode 100644 index 7054ef33a596..000000000000 --- a/pkg/golinters/scopelint.go +++ /dev/null @@ -1,190 +0,0 @@ -package golinters - -import ( - "fmt" - "go/ast" - "go/token" - "sync" - - "golang.org/x/tools/go/analysis" - - "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" - "github.com/golangci/golangci-lint/pkg/lint/linter" - "github.com/golangci/golangci-lint/pkg/result" -) - -const scopelintName = "scopelint" - -//nolint:dupl -func NewScopelint() *goanalysis.Linter { - var mu sync.Mutex - var resIssues []goanalysis.Issue - - analyzer := &analysis.Analyzer{ - Name: scopelintName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (interface{}, error) { - issues := runScopeLint(pass) - - if len(issues) == 0 { - return nil, nil - } - - mu.Lock() - resIssues = append(resIssues, issues...) - mu.Unlock() - - return nil, nil - }, - } - - return goanalysis.NewLinter( - scopelintName, - "Scopelint checks for unpinned variables in go programs", - []*analysis.Analyzer{analyzer}, - nil, - ).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return resIssues - }).WithLoadMode(goanalysis.LoadModeSyntax) -} - -func runScopeLint(pass *analysis.Pass) []goanalysis.Issue { - var lintIssues []result.Issue - - for _, file := range pass.Files { - n := Node{ - fset: pass.Fset, - DangerObjects: map[*ast.Object]int{}, - UnsafeObjects: map[*ast.Object]int{}, - SkipFuncs: map[*ast.FuncLit]int{}, - issues: &lintIssues, - } - ast.Walk(&n, file) - } - - var issues []goanalysis.Issue - for i := range lintIssues { - issues = append(issues, goanalysis.NewIssue(&lintIssues[i], pass)) - } - - return issues -} - -// The code below is copy-pasted from https://github.com/kyoh86/scopelint 92cbe2cc9276abda0e309f52cc9e309d407f174e - -// Node represents a Node being linted. -type Node struct { - fset *token.FileSet - DangerObjects map[*ast.Object]int - UnsafeObjects map[*ast.Object]int - SkipFuncs map[*ast.FuncLit]int - issues *[]result.Issue -} - -// Visit method is invoked for each node encountered by Walk. -// If the result visitor w is not nil, Walk visits each of the children -// of node with the visitor w, followed by a call of w.Visit(nil). -// -//nolint:gocyclo,gocritic -func (f *Node) Visit(node ast.Node) ast.Visitor { - switch typedNode := node.(type) { - case *ast.ForStmt: - switch init := typedNode.Init.(type) { - case *ast.AssignStmt: - for _, lh := range init.Lhs { - switch tlh := lh.(type) { - case *ast.Ident: - f.UnsafeObjects[tlh.Obj] = 0 - } - } - } - - case *ast.RangeStmt: - // Memory variables declared in range statement - switch k := typedNode.Key.(type) { - case *ast.Ident: - f.UnsafeObjects[k.Obj] = 0 - } - switch v := typedNode.Value.(type) { - case *ast.Ident: - f.UnsafeObjects[v.Obj] = 0 - } - - case *ast.UnaryExpr: - if typedNode.Op == token.AND { - switch ident := typedNode.X.(type) { - case *ast.Ident: - if _, unsafe := f.UnsafeObjects[ident.Obj]; unsafe { - f.errorf(ident, "Using a reference for the variable on range scope %s", formatCode(ident.Name, nil)) - } - } - } - - case *ast.Ident: - if _, obj := f.DangerObjects[typedNode.Obj]; obj { - // It is the naked variable in scope of range statement. - f.errorf(node, "Using the variable on range scope %s in function literal", formatCode(typedNode.Name, nil)) - break - } - - case *ast.CallExpr: - // Ignore func literals that'll be called immediately. - switch funcLit := typedNode.Fun.(type) { - case *ast.FuncLit: - f.SkipFuncs[funcLit] = 0 - } - - case *ast.FuncLit: - if _, skip := f.SkipFuncs[typedNode]; !skip { - dangers := map[*ast.Object]int{} - for d := range f.DangerObjects { - dangers[d] = 0 - } - for u := range f.UnsafeObjects { - dangers[u] = 0 - f.UnsafeObjects[u]++ - } - return &Node{ - fset: f.fset, - DangerObjects: dangers, - UnsafeObjects: f.UnsafeObjects, - SkipFuncs: f.SkipFuncs, - issues: f.issues, - } - } - - case *ast.ReturnStmt: - unsafe := map[*ast.Object]int{} - for u := range f.UnsafeObjects { - if f.UnsafeObjects[u] == 0 { - continue - } - unsafe[u] = f.UnsafeObjects[u] - } - return &Node{ - fset: f.fset, - DangerObjects: f.DangerObjects, - UnsafeObjects: unsafe, - SkipFuncs: f.SkipFuncs, - issues: f.issues, - } - } - return f -} - -// The variadic arguments may start with link and category types, -// and must end with a format string and any arguments. -// -//nolint:interfacer -func (f *Node) errorf(n ast.Node, format string, args ...interface{}) { - pos := f.fset.Position(n.Pos()) - f.errorAtf(pos, format, args...) -} - -func (f *Node) errorAtf(pos token.Position, format string, args ...interface{}) { - *f.issues = append(*f.issues, result.Issue{ - Pos: pos, - Text: fmt.Sprintf(format, args...), - FromLinter: scopelintName, - }) -} diff --git a/pkg/golinters/sloglint.go b/pkg/golinters/sloglint.go new file mode 100644 index 000000000000..acea90d53646 --- /dev/null +++ b/pkg/golinters/sloglint.go @@ -0,0 +1,31 @@ +package golinters + +import ( + "go-simpler.org/sloglint" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" +) + +func NewSlogLint(settings *config.SlogLintSettings) *goanalysis.Linter { + var opts *sloglint.Options + if settings != nil { + opts = &sloglint.Options{ + NoMixedArgs: settings.NoMixedArgs, + KVOnly: settings.KVOnly, + AttrOnly: settings.AttrOnly, + ContextOnly: settings.ContextOnly, + StaticMsg: settings.StaticMsg, + NoRawKeys: settings.NoRawKeys, + KeyNamingCase: settings.KeyNamingCase, + ArgsOnSepLines: settings.ArgsOnSepLines, + } + } + + a := sloglint.New(opts) + + return goanalysis. + NewLinter(a.Name, a.Doc, []*analysis.Analyzer{a}, nil). + WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/pkg/golinters/spancheck.go b/pkg/golinters/spancheck.go new file mode 100644 index 000000000000..934124477767 --- /dev/null +++ b/pkg/golinters/spancheck.go @@ -0,0 +1,29 @@ +package golinters + +import ( + "github.com/jjti/go-spancheck" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" +) + +func NewSpancheck(settings *config.SpancheckSettings) *goanalysis.Linter { + cfg := spancheck.NewDefaultConfig() + + if settings != nil { + if settings.Checks != nil { + cfg.EnabledChecks = settings.Checks + } + + if settings.IgnoreCheckSignatures != nil { + cfg.IgnoreChecksSignaturesSlice = settings.IgnoreCheckSignatures + } + } + + a := spancheck.NewAnalyzerWithConfig(cfg) + + return goanalysis. + NewLinter(a.Name, a.Doc, []*analysis.Analyzer{a}, nil). + WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/pkg/golinters/sqlclosecheck.go b/pkg/golinters/sqlclosecheck.go index ff2c0c08ff86..e63b292a2046 100644 --- a/pkg/golinters/sqlclosecheck.go +++ b/pkg/golinters/sqlclosecheck.go @@ -8,12 +8,12 @@ import ( ) func NewSQLCloseCheck() *goanalysis.Linter { + a := analyzer.NewAnalyzer() + return goanalysis.NewLinter( - "sqlclosecheck", - "Checks that sql.Rows and sql.Stmt are closed.", - []*analysis.Analyzer{ - analyzer.NewAnalyzer(), - }, + a.Name, + a.Doc, + []*analysis.Analyzer{a}, nil, ).WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/structcheck.go b/pkg/golinters/structcheck.go deleted file mode 100644 index fe49b1be20f9..000000000000 --- a/pkg/golinters/structcheck.go +++ /dev/null @@ -1,71 +0,0 @@ -package golinters - -import ( - "fmt" - "sync" - - structcheckAPI "github.com/golangci/check/cmd/structcheck" - "golang.org/x/tools/go/analysis" - - "github.com/golangci/golangci-lint/pkg/config" - "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" - "github.com/golangci/golangci-lint/pkg/lint/linter" - "github.com/golangci/golangci-lint/pkg/result" -) - -const structcheckName = "structcheck" - -//nolint:dupl -func NewStructcheck(settings *config.StructCheckSettings) *goanalysis.Linter { - var mu sync.Mutex - var resIssues []goanalysis.Issue - - analyzer := &analysis.Analyzer{ - Name: structcheckName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (interface{}, error) { - issues := runStructCheck(pass, settings) - - if len(issues) == 0 { - return nil, nil - } - - mu.Lock() - resIssues = append(resIssues, issues...) - mu.Unlock() - - return nil, nil - }, - } - - return goanalysis.NewLinter( - structcheckName, - "Finds unused struct fields", - []*analysis.Analyzer{analyzer}, - nil, - ).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return resIssues - }).WithLoadMode(goanalysis.LoadModeTypesInfo) -} - -//nolint:dupl -func runStructCheck(pass *analysis.Pass, settings *config.StructCheckSettings) []goanalysis.Issue { - prog := goanalysis.MakeFakeLoaderProgram(pass) - - lintIssues := structcheckAPI.Run(prog, settings.CheckExportedFields) - if len(lintIssues) == 0 { - return nil - } - - issues := make([]goanalysis.Issue, 0, len(lintIssues)) - - for _, i := range lintIssues { - issues = append(issues, goanalysis.NewIssue(&result.Issue{ - Pos: i.Pos, - Text: fmt.Sprintf("%s is unused", formatCode(i.FieldName, nil)), - FromLinter: structcheckName, - }, pass)) - } - - return issues -} diff --git a/pkg/golinters/stylecheck.go b/pkg/golinters/stylecheck.go index 899f6ff58236..d9b0f87c87d1 100644 --- a/pkg/golinters/stylecheck.go +++ b/pkg/golinters/stylecheck.go @@ -15,7 +15,7 @@ func NewStylecheck(settings *config.StaticCheckSettings) *goanalysis.Linter { // `scconfig.Analyzer` is a singleton, then it's not possible to have more than one instance for all staticcheck "sub-linters". // When we will merge the 4 "sub-linters", the problem will disappear: https://github.com/golangci/golangci-lint/issues/357 // Currently only stylecheck analyzer has a configuration in staticcheck. - scconfig.Analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { + scconfig.Analyzer.Run = func(_ *analysis.Pass) (any, error) { return cfg, nil } diff --git a/pkg/golinters/tagalign.go b/pkg/golinters/tagalign.go new file mode 100644 index 000000000000..c23838f702b5 --- /dev/null +++ b/pkg/golinters/tagalign.go @@ -0,0 +1,75 @@ +package golinters + +import ( + "sync" + + "github.com/4meepo/tagalign" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +func NewTagAlign(settings *config.TagAlignSettings) *goanalysis.Linter { + var mu sync.Mutex + var resIssues []goanalysis.Issue + + options := []tagalign.Option{tagalign.WithMode(tagalign.GolangciLintMode)} + + if settings != nil { + options = append(options, tagalign.WithAlign(settings.Align)) + + if settings.Sort || len(settings.Order) > 0 { + options = append(options, tagalign.WithSort(settings.Order...)) + } + + // Strict style will be applied only if Align and Sort are enabled together. + if settings.Strict && settings.Align && settings.Sort { + options = append(options, tagalign.WithStrictStyle()) + } + } + + analyzer := tagalign.NewAnalyzer(options...) + analyzer.Run = func(pass *analysis.Pass) (any, error) { + taIssues := tagalign.Run(pass, options...) + + issues := make([]goanalysis.Issue, len(taIssues)) + for i, issue := range taIssues { + report := &result.Issue{ + FromLinter: analyzer.Name, + Pos: issue.Pos, + Text: issue.Message, + Replacement: &result.Replacement{ + Inline: &result.InlineFix{ + StartCol: issue.InlineFix.StartCol, + Length: issue.InlineFix.Length, + NewString: issue.InlineFix.NewString, + }, + }, + } + + issues[i] = goanalysis.NewIssue(report, pass) + } + + if len(issues) == 0 { + return nil, nil + } + + mu.Lock() + resIssues = append(resIssues, issues...) + mu.Unlock() + + return nil, nil + } + + return goanalysis.NewLinter( + analyzer.Name, + analyzer.Doc, + []*analysis.Analyzer{analyzer}, + nil, + ).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }).WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/pkg/golinters/tenv.go b/pkg/golinters/tenv.go index 174b0dd61565..6c6bd3186f78 100644 --- a/pkg/golinters/tenv.go +++ b/pkg/golinters/tenv.go @@ -11,9 +11,9 @@ import ( func NewTenv(settings *config.TenvSettings) *goanalysis.Linter { a := tenv.Analyzer - var cfg map[string]map[string]interface{} + var cfg map[string]map[string]any if settings != nil { - cfg = map[string]map[string]interface{}{ + cfg = map[string]map[string]any{ a.Name: { tenv.A: settings.All, }, diff --git a/pkg/golinters/testifylint.go b/pkg/golinters/testifylint.go new file mode 100644 index 000000000000..32b194f00f8b --- /dev/null +++ b/pkg/golinters/testifylint.go @@ -0,0 +1,46 @@ +package golinters + +import ( + "github.com/Antonboom/testifylint/analyzer" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" +) + +func NewTestifylint(settings *config.TestifylintSettings) *goanalysis.Linter { + a := analyzer.New() + + cfg := make(map[string]map[string]any) + if settings != nil { + cfg[a.Name] = map[string]any{ + "enable-all": settings.EnableAll, + "disable-all": settings.DisableAll, + + "bool-compare.ignore-custom-types": settings.BoolCompare.IgnoreCustomTypes, + } + if len(settings.EnabledCheckers) > 0 { + cfg[a.Name]["enable"] = settings.EnabledCheckers + } + if len(settings.DisabledCheckers) > 0 { + cfg[a.Name]["disable"] = settings.DisabledCheckers + } + + if p := settings.ExpectedActual.ExpVarPattern; p != "" { + cfg[a.Name]["expected-actual.pattern"] = p + } + if p := settings.RequireError.FnPattern; p != "" { + cfg[a.Name]["require-error.fn-pattern"] = p + } + if m := settings.SuiteExtraAssertCall.Mode; m != "" { + cfg[a.Name]["suite-extra-assert-call.mode"] = m + } + } + + return goanalysis.NewLinter( + a.Name, + a.Doc, + []*analysis.Analyzer{a}, + cfg, + ).WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/pkg/golinters/testpackage.go b/pkg/golinters/testpackage.go index 2cc627595ff1..b8a867eb60ce 100644 --- a/pkg/golinters/testpackage.go +++ b/pkg/golinters/testpackage.go @@ -11,11 +11,11 @@ import ( ) func NewTestpackage(cfg *config.TestpackageSettings) *goanalysis.Linter { - var a = testpackage.NewAnalyzer() + a := testpackage.NewAnalyzer() - var settings map[string]map[string]interface{} + var settings map[string]map[string]any if cfg != nil { - settings = map[string]map[string]interface{}{ + settings = map[string]map[string]any{ a.Name: { testpackage.SkipRegexpFlagName: cfg.SkipRegexp, testpackage.AllowPackagesFlagName: strings.Join(cfg.AllowPackages, ","), diff --git a/pkg/golinters/thelper.go b/pkg/golinters/thelper.go index 41edbe7616fd..1ae85ef42e1f 100644 --- a/pkg/golinters/thelper.go +++ b/pkg/golinters/thelper.go @@ -4,6 +4,7 @@ import ( "strings" "github.com/kulti/thelper/pkg/analyzer" + "golang.org/x/exp/maps" "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/pkg/config" @@ -42,20 +43,17 @@ func NewThelper(cfg *config.ThelperSettings) *goanalysis.Linter { linterLogger.Fatalf("thelper: at least one option must be enabled") } - var args []string - for k := range opts { - args = append(args, k) - } + args := maps.Keys(opts) - cfgMap := map[string]map[string]interface{}{ + cfgMap := map[string]map[string]any{ a.Name: { "checks": strings.Join(args, ","), }, } return goanalysis.NewLinter( - "thelper", - "thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers", + a.Name, + a.Doc, []*analysis.Analyzer{a}, cfgMap, ).WithLoadMode(goanalysis.LoadModeTypesInfo) diff --git a/pkg/golinters/tparallel.go b/pkg/golinters/tparallel.go index cbe97516c49f..643f2c271085 100644 --- a/pkg/golinters/tparallel.go +++ b/pkg/golinters/tparallel.go @@ -8,10 +8,11 @@ import ( ) func NewTparallel() *goanalysis.Linter { + a := tparallel.Analyzer return goanalysis.NewLinter( - "tparallel", - "tparallel detects inappropriate usage of t.Parallel() method in your Go test codes", - []*analysis.Analyzer{tparallel.Analyzer}, + a.Name, + a.Doc, + []*analysis.Analyzer{a}, nil, ).WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/unconvert.go b/pkg/golinters/unconvert.go index def9f156578c..5f8c73182c57 100644 --- a/pkg/golinters/unconvert.go +++ b/pkg/golinters/unconvert.go @@ -3,9 +3,10 @@ package golinters import ( "sync" - unconvertAPI "github.com/golangci/unconvert" + "github.com/golangci/unconvert" "golang.org/x/tools/go/analysis" + "github.com/golangci/golangci-lint/pkg/config" "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" "github.com/golangci/golangci-lint/pkg/lint/linter" "github.com/golangci/golangci-lint/pkg/result" @@ -13,16 +14,16 @@ import ( const unconvertName = "unconvert" -//nolint:dupl -func NewUnconvert() *goanalysis.Linter { +//nolint:dupl // This is not a duplicate of dogsled. +func NewUnconvert(settings *config.UnconvertSettings) *goanalysis.Linter { var mu sync.Mutex var resIssues []goanalysis.Issue analyzer := &analysis.Analyzer{ Name: unconvertName, Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (interface{}, error) { - issues := runUnconvert(pass) + Run: func(pass *analysis.Pass) (any, error) { + issues := runUnconvert(pass, settings) if len(issues) == 0 { return nil, nil @@ -46,18 +47,13 @@ func NewUnconvert() *goanalysis.Linter { }).WithLoadMode(goanalysis.LoadModeTypesInfo) } -func runUnconvert(pass *analysis.Pass) []goanalysis.Issue { - prog := goanalysis.MakeFakeLoaderProgram(pass) +func runUnconvert(pass *analysis.Pass, settings *config.UnconvertSettings) []goanalysis.Issue { + positions := unconvert.Run(pass, settings.FastMath, settings.Safe) - positions := unconvertAPI.Run(prog) - if len(positions) == 0 { - return nil - } - - issues := make([]goanalysis.Issue, 0, len(positions)) - for _, pos := range positions { + var issues []goanalysis.Issue + for _, position := range positions { issues = append(issues, goanalysis.NewIssue(&result.Issue{ - Pos: pos, + Pos: position, Text: "unnecessary conversion", FromLinter: unconvertName, }, pass)) diff --git a/pkg/golinters/unparam.go b/pkg/golinters/unparam.go index 7accf29566cc..4078d94988fb 100644 --- a/pkg/golinters/unparam.go +++ b/pkg/golinters/unparam.go @@ -24,7 +24,7 @@ func NewUnparam(settings *config.UnparamSettings) *goanalysis.Linter { Name: unparamName, Doc: goanalysis.TheOnlyanalyzerDoc, Requires: []*analysis.Analyzer{buildssa.Analyzer}, - Run: func(pass *analysis.Pass) (interface{}, error) { + Run: func(pass *analysis.Pass) (any, error) { issues, err := runUnparam(pass, settings) if err != nil { return nil, err diff --git a/pkg/golinters/unused.go b/pkg/golinters/unused.go index d464690549b2..a93061c96c33 100644 --- a/pkg/golinters/unused.go +++ b/pkg/golinters/unused.go @@ -5,6 +5,9 @@ import ( "sync" "golang.org/x/tools/go/analysis" + "honnef.co/go/tools/analysis/facts/directives" + "honnef.co/go/tools/analysis/facts/generated" + "honnef.co/go/tools/analysis/lint" "honnef.co/go/tools/unused" "github.com/golangci/golangci-lint/pkg/config" @@ -15,11 +18,7 @@ import ( const unusedName = "unused" -type UnusedSettings struct { - GoVersion string -} - -func NewUnused(settings *config.StaticCheckSettings) *goanalysis.Linter { +func NewUnused(settings *config.UnusedSettings, scSettings *config.StaticCheckSettings) *goanalysis.Linter { var mu sync.Mutex var resIssues []goanalysis.Issue @@ -27,12 +26,8 @@ func NewUnused(settings *config.StaticCheckSettings) *goanalysis.Linter { Name: unusedName, Doc: unused.Analyzer.Analyzer.Doc, Requires: unused.Analyzer.Analyzer.Requires, - Run: func(pass *analysis.Pass) (interface{}, error) { - issues, err := runUnused(pass) - if err != nil { - return nil, err - } - + Run: func(pass *analysis.Pass) (any, error) { + issues := runUnused(pass, settings) if len(issues) == 0 { return nil, nil } @@ -45,33 +40,30 @@ func NewUnused(settings *config.StaticCheckSettings) *goanalysis.Linter { }, } - setAnalyzerGoVersion(analyzer, getGoVersion(settings)) + setAnalyzerGoVersion(analyzer, getGoVersion(scSettings)) return goanalysis.NewLinter( unusedName, "Checks Go code for unused constants, variables, functions and types", []*analysis.Analyzer{analyzer}, nil, - ).WithIssuesReporter(func(lintCtx *linter.Context) []goanalysis.Issue { + ).WithIssuesReporter(func(_ *linter.Context) []goanalysis.Issue { return resIssues }).WithLoadMode(goanalysis.LoadModeTypesInfo) } -func runUnused(pass *analysis.Pass) ([]goanalysis.Issue, error) { - res, err := unused.Analyzer.Analyzer.Run(pass) - if err != nil { - return nil, err - } +func runUnused(pass *analysis.Pass, cfg *config.UnusedSettings) []goanalysis.Issue { + res := getUnusedResults(pass, cfg) used := make(map[string]bool) - for _, obj := range res.(unused.Result).Used { + for _, obj := range res.Used { used[fmt.Sprintf("%s %d %s", obj.Position.Filename, obj.Position.Line, obj.Name)] = true } var issues []goanalysis.Issue // Inspired by https://github.com/dominikh/go-tools/blob/d694aadcb1f50c2d8ac0a1dd06217ebb9f654764/lintcmd/lint.go#L177-L197 - for _, object := range res.(unused.Result).Unused { + for _, object := range res.Unused { if object.Kind == "type param" { continue } @@ -90,5 +82,31 @@ func runUnused(pass *analysis.Pass) ([]goanalysis.Issue, error) { issues = append(issues, issue) } - return issues, nil + return issues +} + +func getUnusedResults(pass *analysis.Pass, settings *config.UnusedSettings) unused.Result { + opts := unused.Options{ + FieldWritesAreUses: settings.FieldWritesAreUses, + PostStatementsAreReads: settings.PostStatementsAreReads, + ExportedIsUsed: settings.ExportedIsUsed, + ExportedFieldsAreUsed: settings.ExportedFieldsAreUsed, + ParametersAreUsed: settings.ParametersAreUsed, + LocalVariablesAreUsed: settings.LocalVariablesAreUsed, + GeneratedIsUsed: settings.GeneratedIsUsed, + } + + // ref: https://github.com/dominikh/go-tools/blob/4ec1f474ca6c0feb8e10a8fcca4ab95f5b5b9881/internal/cmd/unused/unused.go#L68 + nodes := unused.Graph(pass.Fset, + pass.Files, + pass.Pkg, + pass.TypesInfo, + pass.ResultOf[directives.Analyzer].([]lint.Directive), + pass.ResultOf[generated.Analyzer].(map[string]generated.Generator), + opts, + ) + + sg := unused.SerializedGraph{} + sg.Merge(nodes) + return sg.Results() } diff --git a/pkg/golinters/usestdlibvars.go b/pkg/golinters/usestdlibvars.go index 0ea4b563b0a0..663a841ac70a 100644 --- a/pkg/golinters/usestdlibvars.go +++ b/pkg/golinters/usestdlibvars.go @@ -11,9 +11,9 @@ import ( func NewUseStdlibVars(cfg *config.UseStdlibVarsSettings) *goanalysis.Linter { a := analyzer.New() - cfgMap := make(map[string]map[string]interface{}) + cfgMap := make(map[string]map[string]any) if cfg != nil { - cfgMap[a.Name] = map[string]interface{}{ + cfgMap[a.Name] = map[string]any{ analyzer.ConstantKindFlag: cfg.ConstantKind, analyzer.CryptoHashFlag: cfg.CryptoHash, analyzer.HTTPMethodFlag: cfg.HTTPMethod, diff --git a/pkg/golinters/util.go b/pkg/golinters/util.go index 1044567a951b..932cbfcf78f6 100644 --- a/pkg/golinters/util.go +++ b/pkg/golinters/util.go @@ -18,14 +18,6 @@ func formatCode(code string, _ *config.Config) string { return fmt.Sprintf("`%s`", code) } -func formatCodeBlock(code string, _ *config.Config) string { - if strings.Contains(code, "`") { - return code // TODO: properly escape or remove - } - - return fmt.Sprintf("```\n%s\n```", code) -} - func getFileNames(pass *analysis.Pass) []string { var fileNames []string for _, f := range pass.Files { diff --git a/pkg/golinters/varcheck.go b/pkg/golinters/varcheck.go deleted file mode 100644 index c2c5b7aa9c35..000000000000 --- a/pkg/golinters/varcheck.go +++ /dev/null @@ -1,72 +0,0 @@ -package golinters - -import ( - "fmt" - "sync" - - varcheckAPI "github.com/golangci/check/cmd/varcheck" - "golang.org/x/tools/go/analysis" - - "github.com/golangci/golangci-lint/pkg/config" - "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" - "github.com/golangci/golangci-lint/pkg/lint/linter" - "github.com/golangci/golangci-lint/pkg/result" -) - -const varcheckName = "varcheck" - -func NewVarcheck(settings *config.VarCheckSettings) *goanalysis.Linter { - var mu sync.Mutex - var resIssues []goanalysis.Issue - - analyzer := &analysis.Analyzer{ - Name: varcheckName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: goanalysis.DummyRun, - } - - return goanalysis.NewLinter( - varcheckName, - "Finds unused global variables and constants", - []*analysis.Analyzer{analyzer}, - nil, - ).WithContextSetter(func(lintCtx *linter.Context) { - analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { - issues := runVarCheck(pass, settings) - - if len(issues) == 0 { - return nil, nil - } - - mu.Lock() - resIssues = append(resIssues, issues...) - mu.Unlock() - - return nil, nil - } - }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return resIssues - }).WithLoadMode(goanalysis.LoadModeTypesInfo) -} - -//nolint:dupl -func runVarCheck(pass *analysis.Pass, settings *config.VarCheckSettings) []goanalysis.Issue { - prog := goanalysis.MakeFakeLoaderProgram(pass) - - lintIssues := varcheckAPI.Run(prog, settings.CheckExportedFields) - if len(lintIssues) == 0 { - return nil - } - - issues := make([]goanalysis.Issue, 0, len(lintIssues)) - - for _, i := range lintIssues { - issues = append(issues, goanalysis.NewIssue(&result.Issue{ - Pos: i.Pos, - Text: fmt.Sprintf("%s is unused", formatCode(i.VarName, nil)), - FromLinter: varcheckName, - }, pass)) - } - - return issues -} diff --git a/pkg/golinters/varnamelen.go b/pkg/golinters/varnamelen.go index d86c04b20a15..688dfa804680 100644 --- a/pkg/golinters/varnamelen.go +++ b/pkg/golinters/varnamelen.go @@ -13,10 +13,10 @@ import ( func NewVarnamelen(settings *config.VarnamelenSettings) *goanalysis.Linter { analyzer := varnamelen.NewAnalyzer() - cfg := map[string]map[string]interface{}{} + cfg := map[string]map[string]any{} if settings != nil { - vnlCfg := map[string]interface{}{ + vnlCfg := map[string]any{ "checkReceiver": strconv.FormatBool(settings.CheckReceiver), "checkReturn": strconv.FormatBool(settings.CheckReturn), "checkTypeParam": strconv.FormatBool(settings.CheckTypeParam), diff --git a/pkg/golinters/wastedassign.go b/pkg/golinters/wastedassign.go index 92798d4f7353..9038c827dc78 100644 --- a/pkg/golinters/wastedassign.go +++ b/pkg/golinters/wastedassign.go @@ -8,10 +8,12 @@ import ( ) func NewWastedAssign() *goanalysis.Linter { + a := wastedassign.Analyzer + return goanalysis.NewLinter( - "wastedassign", - "wastedassign finds wasted assignment statements.", - []*analysis.Analyzer{wastedassign.Analyzer}, + a.Name, + "Finds wasted assignment statements", + []*analysis.Analyzer{a}, nil, ).WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/whitespace.go b/pkg/golinters/whitespace.go index 1b32a7ad63ac..5487b1016ab9 100644 --- a/pkg/golinters/whitespace.go +++ b/pkg/golinters/whitespace.go @@ -1,10 +1,9 @@ package golinters import ( - "go/token" + "fmt" "sync" - "github.com/pkg/errors" "github.com/ultraware/whitespace" "golang.org/x/tools/go/analysis" @@ -16,7 +15,6 @@ import ( const whitespaceName = "whitespace" -//nolint:dupl func NewWhitespace(settings *config.WhitespaceSettings) *goanalysis.Linter { var mu sync.Mutex var resIssues []goanalysis.Issue @@ -24,25 +22,22 @@ func NewWhitespace(settings *config.WhitespaceSettings) *goanalysis.Linter { var wsSettings whitespace.Settings if settings != nil { wsSettings = whitespace.Settings{ + Mode: whitespace.RunningModeGolangCI, MultiIf: settings.MultiIf, MultiFunc: settings.MultiFunc, } } - analyzer := &analysis.Analyzer{ - Name: whitespaceName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: goanalysis.DummyRun, - } + a := whitespace.NewAnalyzer(&wsSettings) return goanalysis.NewLinter( - whitespaceName, - "Tool for detection of leading and trailing whitespace", - []*analysis.Analyzer{analyzer}, + a.Name, + a.Doc, + []*analysis.Analyzer{a}, nil, - ).WithContextSetter(func(lintCtx *linter.Context) { - analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { - issues, err := runWhitespace(lintCtx, pass, wsSettings) + ).WithContextSetter(func(_ *linter.Context) { + a.Run = func(pass *analysis.Pass) (any, error) { + issues, err := runWhitespace(pass, wsSettings) if err != nil { return nil, err } @@ -62,46 +57,45 @@ func NewWhitespace(settings *config.WhitespaceSettings) *goanalysis.Linter { }).WithLoadMode(goanalysis.LoadModeSyntax) } -func runWhitespace(lintCtx *linter.Context, pass *analysis.Pass, wsSettings whitespace.Settings) ([]goanalysis.Issue, error) { - var messages []whitespace.Message - for _, file := range pass.Files { - messages = append(messages, whitespace.Run(file, pass.Fset, wsSettings)...) - } - - if len(messages) == 0 { - return nil, nil - } +func runWhitespace(pass *analysis.Pass, wsSettings whitespace.Settings) ([]goanalysis.Issue, error) { + lintIssues := whitespace.Run(pass, &wsSettings) - issues := make([]goanalysis.Issue, len(messages)) - for k, i := range messages { - issue := result.Issue{ - Pos: token.Position{ - Filename: i.Pos.Filename, - Line: i.Pos.Line, - }, - LineRange: &result.Range{From: i.Pos.Line, To: i.Pos.Line}, - Text: i.Message, - FromLinter: whitespaceName, - Replacement: &result.Replacement{}, + issues := make([]goanalysis.Issue, len(lintIssues)) + for i, issue := range lintIssues { + report := &result.Issue{ + FromLinter: whitespaceName, + Pos: pass.Fset.PositionFor(issue.Diagnostic, false), + Text: issue.Message, } - bracketLine, err := lintCtx.LineCache.GetLine(issue.Pos.Filename, issue.Pos.Line) - if err != nil { - return nil, errors.Wrapf(err, "failed to get line %s:%d", issue.Pos.Filename, issue.Pos.Line) - } + switch issue.MessageType { + case whitespace.MessageTypeRemove: + if len(issue.LineNumbers) == 0 { + continue + } + + report.LineRange = &result.Range{ + From: issue.LineNumbers[0], + To: issue.LineNumbers[len(issue.LineNumbers)-1], + } + + report.Replacement = &result.Replacement{NeedOnlyDelete: true} + + case whitespace.MessageTypeAdd: + report.Pos = pass.Fset.PositionFor(issue.FixStart, false) + report.Replacement = &result.Replacement{ + Inline: &result.InlineFix{ + StartCol: 0, + Length: 1, + NewString: "\n\t", + }, + } - switch i.Type { - case whitespace.MessageTypeLeading: - issue.LineRange.To++ // cover two lines by the issue: opening bracket "{" (issue.Pos.Line) and following empty line - case whitespace.MessageTypeTrailing: - issue.LineRange.From-- // cover two lines by the issue: closing bracket "}" (issue.Pos.Line) and preceding empty line - issue.Pos.Line-- // set in sync with LineRange.From to not break fixer and other code features - case whitespace.MessageTypeAddAfter: - bracketLine += "\n" + default: + return nil, fmt.Errorf("unknown message type: %v", issue.MessageType) } - issue.Replacement.NewLines = []string{bracketLine} - issues[k] = goanalysis.NewIssue(&issue, pass) + issues[i] = goanalysis.NewIssue(report, pass) } return issues, nil diff --git a/pkg/golinters/wrapcheck.go b/pkg/golinters/wrapcheck.go index 098eb87bafc6..6d25db42777e 100644 --- a/pkg/golinters/wrapcheck.go +++ b/pkg/golinters/wrapcheck.go @@ -8,8 +8,6 @@ import ( "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" ) -const wrapcheckName = "wrapcheck" - func NewWrapcheck(settings *config.WrapcheckSettings) *goanalysis.Linter { cfg := wrapcheck.NewDefaultConfig() if settings != nil { @@ -30,7 +28,7 @@ func NewWrapcheck(settings *config.WrapcheckSettings) *goanalysis.Linter { a := wrapcheck.NewAnalyzer(cfg) return goanalysis.NewLinter( - wrapcheckName, + a.Name, a.Doc, []*analysis.Analyzer{a}, nil, diff --git a/pkg/golinters/wsl.go b/pkg/golinters/wsl.go index 4bc702447048..3b090a686ede 100644 --- a/pkg/golinters/wsl.go +++ b/pkg/golinters/wsl.go @@ -1,89 +1,39 @@ package golinters import ( - "sync" - - "github.com/bombsimon/wsl/v3" + "github.com/bombsimon/wsl/v4" "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/pkg/config" "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" - "github.com/golangci/golangci-lint/pkg/lint/linter" - "github.com/golangci/golangci-lint/pkg/result" ) -const wslName = "wsl" - -// NewWSL returns a new WSL linter. func NewWSL(settings *config.WSLSettings) *goanalysis.Linter { - var mu sync.Mutex - var resIssues []goanalysis.Issue - - conf := wsl.DefaultConfig() - + var conf *wsl.Configuration if settings != nil { - conf.StrictAppend = settings.StrictAppend - conf.AllowAssignAndCallCuddle = settings.AllowAssignAndCallCuddle - conf.AllowAssignAndAnythingCuddle = settings.AllowAssignAndAnythingCuddle - conf.AllowMultiLineAssignCuddle = settings.AllowMultiLineAssignCuddle - conf.ForceCaseTrailingWhitespaceLimit = settings.ForceCaseTrailingWhitespaceLimit - conf.AllowTrailingComment = settings.AllowTrailingComment - conf.AllowSeparatedLeadingComment = settings.AllowSeparatedLeadingComment - conf.AllowCuddleDeclaration = settings.AllowCuddleDeclaration - conf.AllowCuddleWithCalls = settings.AllowCuddleWithCalls - conf.AllowCuddleWithRHS = settings.AllowCuddleWithRHS - conf.ForceCuddleErrCheckAndAssign = settings.ForceCuddleErrCheckAndAssign - conf.ErrorVariableNames = settings.ErrorVariableNames - conf.ForceExclusiveShortDeclarations = settings.ForceExclusiveShortDeclarations + conf = &wsl.Configuration{ + StrictAppend: settings.StrictAppend, + AllowAssignAndCallCuddle: settings.AllowAssignAndCallCuddle, + AllowAssignAndAnythingCuddle: settings.AllowAssignAndAnythingCuddle, + AllowMultiLineAssignCuddle: settings.AllowMultiLineAssignCuddle, + ForceCaseTrailingWhitespaceLimit: settings.ForceCaseTrailingWhitespaceLimit, + AllowTrailingComment: settings.AllowTrailingComment, + AllowSeparatedLeadingComment: settings.AllowSeparatedLeadingComment, + AllowCuddleDeclaration: settings.AllowCuddleDeclaration, + AllowCuddleWithCalls: settings.AllowCuddleWithCalls, + AllowCuddleWithRHS: settings.AllowCuddleWithRHS, + ForceCuddleErrCheckAndAssign: settings.ForceCuddleErrCheckAndAssign, + ErrorVariableNames: settings.ErrorVariableNames, + ForceExclusiveShortDeclarations: settings.ForceExclusiveShortDeclarations, + } } - analyzer := &analysis.Analyzer{ - Name: goanalysis.TheOnlyAnalyzerName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (interface{}, error) { - issues := runWSL(pass, &conf) - - if len(issues) == 0 { - return nil, nil - } - - mu.Lock() - resIssues = append(resIssues, issues...) - mu.Unlock() - - return nil, nil - }, - } + a := wsl.NewAnalyzer(conf) return goanalysis.NewLinter( - wslName, - "Whitespace Linter - Forces you to use empty lines!", - []*analysis.Analyzer{analyzer}, + a.Name, + a.Doc, + []*analysis.Analyzer{a}, nil, - ).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return resIssues - }).WithLoadMode(goanalysis.LoadModeSyntax) -} - -func runWSL(pass *analysis.Pass, conf *wsl.Configuration) []goanalysis.Issue { - if conf == nil { - return nil - } - - files := getFileNames(pass) - wslErrors, _ := wsl.NewProcessorWithConfig(*conf).ProcessFiles(files) - if len(wslErrors) == 0 { - return nil - } - - var issues []goanalysis.Issue - for _, err := range wslErrors { - issues = append(issues, goanalysis.NewIssue(&result.Issue{ - FromLinter: wslName, - Pos: err.Position, - Text: err.Reason, - }, pass)) - } - - return issues + ).WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/zerologlint.go b/pkg/golinters/zerologlint.go new file mode 100644 index 000000000000..edde726655f3 --- /dev/null +++ b/pkg/golinters/zerologlint.go @@ -0,0 +1,19 @@ +package golinters + +import ( + "github.com/ykadowak/zerologlint" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" +) + +func NewZerologLint() *goanalysis.Linter { + a := zerologlint.Analyzer + + return goanalysis.NewLinter( + a.Name, + a.Doc, + []*analysis.Analyzer{a}, + nil, + ).WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/pkg/goutil/env.go b/pkg/goutil/env.go index 4873f3f96cbb..7b748d8e9031 100644 --- a/pkg/goutil/env.go +++ b/pkg/goutil/env.go @@ -3,13 +3,12 @@ package goutil import ( "context" "encoding/json" + "fmt" "os" "os/exec" "strings" "time" - "github.com/pkg/errors" - "github.com/golangci/golangci-lint/pkg/logutils" ) @@ -34,20 +33,23 @@ func NewEnv(log logutils.Log) *Env { } } -func (e *Env) Discover(ctx context.Context) error { +func (e Env) Discover(ctx context.Context) error { startedAt := time.Now() - args := []string{"env", "-json"} - args = append(args, string(EnvGoCache), string(EnvGoRoot)) - out, err := exec.CommandContext(ctx, "go", args...).Output() + + //nolint:gosec // Everything is static here. + cmd := exec.CommandContext(ctx, "go", "env", "-json", string(EnvGoCache), string(EnvGoRoot)) + + out, err := cmd.Output() if err != nil { - return errors.Wrap(err, "failed to run 'go env'") + return fmt.Errorf("failed to run '%s': %w", strings.Join(cmd.Args, " "), err) } if err = json.Unmarshal(out, &e.vars); err != nil { - return errors.Wrapf(err, "failed to parse 'go %s' json", strings.Join(args, " ")) + return fmt.Errorf("failed to parse '%s' json: %w", strings.Join(cmd.Args, " "), err) } e.debugf("Read go env for %s: %#v", time.Since(startedAt), e.vars) + return nil } diff --git a/pkg/lint/linter/config.go b/pkg/lint/linter/config.go index 167ac462594c..8e57d6bdf6d2 100644 --- a/pkg/lint/linter/config.go +++ b/pkg/lint/linter/config.go @@ -1,7 +1,8 @@ package linter import ( - "golang.org/x/tools/go/analysis" + "fmt" + "golang.org/x/tools/go/packages" "github.com/golangci/golangci-lint/pkg/config" @@ -42,6 +43,7 @@ type Config struct { AlternativeNames []string OriginalURL string // URL of original (not forked) repo, needed for autogenerated README + Internal bool // Internal linters cannot be disabled (ex: typecheck). CanAutoFix bool IsSlow bool DoesChangeTypes bool @@ -50,6 +52,16 @@ type Config struct { Deprecation *Deprecation } +func (lc *Config) WithEnabledByDefault() *Config { + lc.EnabledByDefault = true + return lc +} + +func (lc *Config) WithInternal() *Config { + lc.Internal = true + return lc +} + func (lc *Config) ConsiderSlow() *Config { lc.IsSlow = true return lc @@ -122,23 +134,27 @@ func (lc *Config) Name() string { return lc.Linter.Name() } -func (lc *Config) WithNoopFallback(cfg *config.Config) *Config { - if cfg != nil && config.IsGreaterThanOrEqualGo118(cfg.Run.Go) { - lc.Linter = &Noop{ - name: lc.Linter.Name(), - desc: lc.Linter.Desc(), - run: func(pass *analysis.Pass) (interface{}, error) { - return nil, nil - }, - } - +func (lc *Config) WithNoopFallback(cfg *config.Config, cond func(cfg *config.Config) error) *Config { + if err := cond(cfg); err != nil { + lc.Linter = NewNoop(lc.Linter, err.Error()) lc.LoadMode = 0 + return lc.WithLoadFiles() } return lc } +func IsGoLowerThanGo122() func(cfg *config.Config) error { + return func(cfg *config.Config) error { + if cfg == nil || config.IsGoGreaterThanOrEqual(cfg.Run.Go, "1.22") { + return nil + } + + return fmt.Errorf("this linter is disabled because the Go version (%s) of your project is lower than Go 1.22", cfg.Run.Go) + } +} + func NewConfig(linter Linter) *Config { lc := &Config{ Linter: linter, diff --git a/pkg/lint/linter/linter.go b/pkg/lint/linter/linter.go index 7d3b2260a519..1d4e7b04ccce 100644 --- a/pkg/lint/linter/linter.go +++ b/pkg/lint/linter/linter.go @@ -3,8 +3,7 @@ package linter import ( "context" - "golang.org/x/tools/go/analysis" - + "github.com/golangci/golangci-lint/pkg/config" "github.com/golangci/golangci-lint/pkg/result" ) @@ -15,14 +14,37 @@ type Linter interface { } type Noop struct { - name string - desc string - run func(pass *analysis.Pass) (interface{}, error) + name string + desc string + reason string +} + +func NewNoop(l Linter, reason string) Noop { + return Noop{ + name: l.Name(), + desc: l.Desc(), + reason: reason, + } +} + +func NewNoopDeprecated(name string, cfg *config.Config) Noop { + noop := Noop{ + name: name, + desc: "Deprecated", + reason: "This linter is fully inactivated: it will not produce any reports.", + } + + if cfg.InternalCmdTest { + noop.reason = "" + } + + return noop } func (n Noop) Run(_ context.Context, lintCtx *Context) ([]result.Issue, error) { - lintCtx.Log.Warnf("%s is disabled because of generics."+ - " You can track the evolution of the generics support by following the https://github.com/golangci/golangci-lint/issues/2649.", n.name) + if n.reason != "" { + lintCtx.Log.Warnf("%s: %s", n.name, n.reason) + } return nil, nil } diff --git a/pkg/lint/lintersdb/builder_linter.go b/pkg/lint/lintersdb/builder_linter.go new file mode 100644 index 000000000000..954315d33dda --- /dev/null +++ b/pkg/lint/lintersdb/builder_linter.go @@ -0,0 +1,711 @@ +package lintersdb + +import ( + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/golinters" + "github.com/golangci/golangci-lint/pkg/lint/linter" +) + +// LinterBuilder builds the "internal" linters based on the configuration. +type LinterBuilder struct{} + +// NewLinterBuilder creates a new LinterBuilder. +func NewLinterBuilder() *LinterBuilder { + return &LinterBuilder{} +} + +// Build loads all the "internal" linters. +// The configuration is use for the linter settings. +func (b LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { + if cfg == nil { + return nil, nil + } + + const megacheckName = "megacheck" + + // The linters are sorted in the alphabetical order (case-insensitive). + // When a new linter is added the version in `WithSince(...)` must be the next minor version of golangci-lint. + return []*linter.Config{ + linter.NewConfig(golinters.NewAsasalint(&cfg.LintersSettings.Asasalint)). + WithSince("1.47.0"). + WithPresets(linter.PresetBugs). + WithLoadForGoAnalysis(). + WithURL("https://github.com/alingse/asasalint"), + + linter.NewConfig(golinters.NewAsciicheck()). + WithSince("v1.26.0"). + WithPresets(linter.PresetBugs, linter.PresetStyle). + WithURL("https://github.com/tdakkota/asciicheck"), + + linter.NewConfig(golinters.NewBiDiChkFuncName(&cfg.LintersSettings.BiDiChk)). + WithSince("1.43.0"). + WithPresets(linter.PresetBugs). + WithURL("https://github.com/breml/bidichk"), + + linter.NewConfig(golinters.NewBodyclose()). + WithSince("v1.18.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetPerformance, linter.PresetBugs). + WithURL("https://github.com/timakin/bodyclose"), + + linter.NewConfig(golinters.NewContainedCtx()). + WithSince("1.44.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/sivchari/containedctx"), + + linter.NewConfig(golinters.NewContextCheck()). + WithSince("v1.43.0"). + WithPresets(linter.PresetBugs). + WithLoadForGoAnalysis(). + WithURL("https://github.com/kkHAIKE/contextcheck"), + + linter.NewConfig(golinters.NewCopyLoopVar(&cfg.LintersSettings.CopyLoopVar)). + WithSince("v1.57.0"). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/karamaru-alpha/copyloopvar"). + WithNoopFallback(cfg, linter.IsGoLowerThanGo122()), + + linter.NewConfig(golinters.NewCyclop(&cfg.LintersSettings.Cyclop)). + WithSince("v1.37.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetComplexity). + WithURL("https://github.com/bkielbasa/cyclop"), + + linter.NewConfig(golinters.NewDecorder(&cfg.LintersSettings.Decorder)). + WithSince("v1.44.0"). + WithPresets(linter.PresetFormatting, linter.PresetStyle). + WithURL("https://gitlab.com/bosi/decorder"), + + linter.NewConfig(linter.NewNoopDeprecated("deadcode", cfg)). + WithSince("v1.0.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetUnused). + WithURL("https://github.com/remyoudompheng/go-misc/tree/master/deadcode"). + Deprecated("The owner seems to have abandoned the linter.", "v1.49.0", "unused"), + + linter.NewConfig(golinters.NewDepguard(&cfg.LintersSettings.Depguard)). + WithSince("v1.4.0"). + WithPresets(linter.PresetStyle, linter.PresetImport, linter.PresetModule). + WithURL("https://github.com/OpenPeeDeeP/depguard"), + + linter.NewConfig(golinters.NewDogsled(&cfg.LintersSettings.Dogsled)). + WithSince("v1.19.0"). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/alexkohler/dogsled"), + + linter.NewConfig(golinters.NewDupl(&cfg.LintersSettings.Dupl)). + WithSince("v1.0.0"). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/mibk/dupl"), + + linter.NewConfig(golinters.NewDupWord(&cfg.LintersSettings.DupWord)). + WithSince("1.50.0"). + WithPresets(linter.PresetComment). + WithURL("https://github.com/Abirdcfly/dupword"), + + linter.NewConfig(golinters.NewDurationCheck()). + WithSince("v1.37.0"). + WithPresets(linter.PresetBugs). + WithLoadForGoAnalysis(). + WithURL("https://github.com/charithe/durationcheck"), + + linter.NewConfig(golinters.NewErrcheck(&cfg.LintersSettings.Errcheck)). + WithEnabledByDefault(). + WithSince("v1.0.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetBugs, linter.PresetError). + WithURL("https://github.com/kisielk/errcheck"), + + linter.NewConfig(golinters.NewErrChkJSONFuncName(&cfg.LintersSettings.ErrChkJSON)). + WithSince("1.44.0"). + WithPresets(linter.PresetBugs). + WithLoadForGoAnalysis(). + WithURL("https://github.com/breml/errchkjson"), + + linter.NewConfig(golinters.NewErrName()). + WithSince("v1.42.0"). + WithPresets(linter.PresetStyle). + WithLoadForGoAnalysis(). + WithURL("https://github.com/Antonboom/errname"), + + linter.NewConfig(golinters.NewErrorLint(&cfg.LintersSettings.ErrorLint)). + WithSince("v1.32.0"). + WithPresets(linter.PresetBugs, linter.PresetError). + WithLoadForGoAnalysis(). + WithURL("https://github.com/polyfloyd/go-errorlint"), + + linter.NewConfig(golinters.NewExecInQuery()). + WithSince("v1.46.0"). + WithPresets(linter.PresetSQL). + WithLoadForGoAnalysis(). + WithURL("https://github.com/lufeee/execinquery"), + + linter.NewConfig(golinters.NewExhaustive(&cfg.LintersSettings.Exhaustive)). + WithSince(" v1.28.0"). + WithPresets(linter.PresetBugs). + WithLoadForGoAnalysis(). + WithURL("https://github.com/nishanths/exhaustive"), + + linter.NewConfig(linter.NewNoopDeprecated("exhaustivestruct", cfg)). + WithSince("v1.32.0"). + WithPresets(linter.PresetStyle, linter.PresetTest). + WithLoadForGoAnalysis(). + WithURL("https://github.com/mbilski/exhaustivestruct"). + Deprecated("The repository of the linter has been deprecated by the owner.", "v1.46.0", "exhaustruct"), + + linter.NewConfig(golinters.NewExhaustruct(&cfg.LintersSettings.Exhaustruct)). + WithSince("v1.46.0"). + WithPresets(linter.PresetStyle, linter.PresetTest). + WithLoadForGoAnalysis(). + WithURL("https://github.com/GaijinEntertainment/go-exhaustruct"), + + linter.NewConfig(golinters.NewExportLoopRef()). + WithSince("v1.28.0"). + WithPresets(linter.PresetBugs). + WithLoadForGoAnalysis(). + WithURL("https://github.com/kyoh86/exportloopref"), + + linter.NewConfig(golinters.NewForbidigo(&cfg.LintersSettings.Forbidigo)). + WithSince("v1.34.0"). + WithPresets(linter.PresetStyle). + // Strictly speaking, + // the additional information is only needed when forbidigoCfg.AnalyzeTypes is chosen by the user. + // But we don't know that here in all cases (sometimes config is not loaded), + // so we have to assume that it is needed to be on the safe side. + WithLoadForGoAnalysis(). + WithURL("https://github.com/ashanbrown/forbidigo"), + + linter.NewConfig(golinters.NewForceTypeAssert()). + WithSince("v1.38.0"). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/gostaticanalysis/forcetypeassert"), + + linter.NewConfig(golinters.NewFunlen(&cfg.LintersSettings.Funlen)). + WithSince("v1.18.0"). + WithPresets(linter.PresetComplexity). + WithURL("https://github.com/ultraware/funlen"), + + linter.NewConfig(golinters.NewGci(&cfg.LintersSettings.Gci)). + WithSince("v1.30.0"). + WithPresets(linter.PresetFormatting, linter.PresetImport). + WithURL("https://github.com/daixiang0/gci"), + + linter.NewConfig(golinters.NewGinkgoLinter(&cfg.LintersSettings.GinkgoLinter)). + WithSince("v1.51.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/nunnatsa/ginkgolinter"), + + linter.NewConfig(golinters.NewGoCheckCompilerDirectives()). + WithSince("v1.51.0"). + WithPresets(linter.PresetBugs). + WithURL("https://github.com/leighmcculloch/gocheckcompilerdirectives"), + + linter.NewConfig(golinters.NewGochecknoglobals()). + WithSince("v1.12.0"). + WithPresets(linter.PresetStyle). + WithLoadForGoAnalysis(). + WithURL("https://github.com/leighmcculloch/gochecknoglobals"), + + linter.NewConfig(golinters.NewGochecknoinits()). + WithSince("v1.12.0"). + WithPresets(linter.PresetStyle), + + linter.NewConfig(golinters.NewGoCheckSumType()). + WithSince("v1.55.0"). + WithPresets(linter.PresetBugs). + WithLoadForGoAnalysis(). + WithURL("https://github.com/alecthomas/go-check-sumtype"), + + linter.NewConfig(golinters.NewGocognit(&cfg.LintersSettings.Gocognit)). + WithSince("v1.20.0"). + WithPresets(linter.PresetComplexity). + WithURL("https://github.com/uudashr/gocognit"), + + linter.NewConfig(golinters.NewGoconst(&cfg.LintersSettings.Goconst)). + WithSince("v1.0.0"). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/jgautheron/goconst"), + + linter.NewConfig(golinters.NewGoCritic(&cfg.LintersSettings.Gocritic, cfg)). + WithSince("v1.12.0"). + WithPresets(linter.PresetStyle, linter.PresetMetaLinter). + WithLoadForGoAnalysis(). + WithURL("https://github.com/go-critic/go-critic"), + + linter.NewConfig(golinters.NewGocyclo(&cfg.LintersSettings.Gocyclo)). + WithSince("v1.0.0"). + WithPresets(linter.PresetComplexity). + WithURL("https://github.com/fzipp/gocyclo"), + + linter.NewConfig(golinters.NewGodot(&cfg.LintersSettings.Godot)). + WithSince("v1.25.0"). + WithPresets(linter.PresetStyle, linter.PresetComment). + WithAutoFix(). + WithURL("https://github.com/tetafro/godot"), + + linter.NewConfig(golinters.NewGodox(&cfg.LintersSettings.Godox)). + WithSince("v1.19.0"). + WithPresets(linter.PresetStyle, linter.PresetComment). + WithURL("https://github.com/matoous/godox"), + + linter.NewConfig(golinters.NewGoerr113()). + WithSince("v1.26.0"). + WithPresets(linter.PresetStyle, linter.PresetError). + WithLoadForGoAnalysis(). + WithURL("https://github.com/Djarvur/go-err113"), + + linter.NewConfig(golinters.NewGofmt(&cfg.LintersSettings.Gofmt)). + WithSince("v1.0.0"). + WithPresets(linter.PresetFormatting). + WithAutoFix(). + WithURL("https://pkg.go.dev/cmd/gofmt"), + + linter.NewConfig(golinters.NewGofumpt(&cfg.LintersSettings.Gofumpt)). + WithSince("v1.28.0"). + WithPresets(linter.PresetFormatting). + WithAutoFix(). + WithURL("https://github.com/mvdan/gofumpt"), + + linter.NewConfig(golinters.NewGoHeader(&cfg.LintersSettings.Goheader)). + WithSince("v1.28.0"). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/denis-tingaikin/go-header"), + + linter.NewConfig(golinters.NewGoimports(&cfg.LintersSettings.Goimports)). + WithSince("v1.20.0"). + WithPresets(linter.PresetFormatting, linter.PresetImport). + WithAutoFix(). + WithURL("https://pkg.go.dev/golang.org/x/tools/cmd/goimports"), + + linter.NewConfig(linter.NewNoopDeprecated("golint", cfg)). + WithSince("v1.0.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/golang/lint"). + Deprecated("The repository of the linter has been archived by the owner.", "v1.41.0", "revive"), + + linter.NewConfig(golinters.NewGoMND(&cfg.LintersSettings.Gomnd)). + WithSince("v1.22.0"). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/tommy-muehle/go-mnd"), + + linter.NewConfig(golinters.NewGoModDirectives(&cfg.LintersSettings.GoModDirectives)). + WithSince("v1.39.0"). + WithPresets(linter.PresetStyle, linter.PresetModule). + WithURL("https://github.com/ldez/gomoddirectives"), + + linter.NewConfig(golinters.NewGomodguard(&cfg.LintersSettings.Gomodguard)). + WithSince("v1.25.0"). + WithPresets(linter.PresetStyle, linter.PresetImport, linter.PresetModule). + WithURL("https://github.com/ryancurrah/gomodguard"), + + linter.NewConfig(golinters.NewGoPrintfFuncName()). + WithSince("v1.23.0"). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/jirfag/go-printf-func-name"), + + linter.NewConfig(golinters.NewGosec(&cfg.LintersSettings.Gosec)). + WithSince("v1.0.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetBugs). + WithURL("https://github.com/securego/gosec"). + WithAlternativeNames("gas"), + + linter.NewConfig(golinters.NewGosimple(&cfg.LintersSettings.Gosimple)). + WithEnabledByDefault(). + WithSince("v1.20.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetStyle). + WithAlternativeNames(megacheckName). + WithURL("https://github.com/dominikh/go-tools/tree/master/simple"), + + linter.NewConfig(golinters.NewGosmopolitan(&cfg.LintersSettings.Gosmopolitan)). + WithSince("v1.53.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetBugs). + WithURL("https://github.com/xen0n/gosmopolitan"), + + linter.NewConfig(golinters.NewGovet(&cfg.LintersSettings.Govet)). + WithEnabledByDefault(). + WithSince("v1.0.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetBugs, linter.PresetMetaLinter). + WithAlternativeNames("vet", "vetshadow"). + WithURL("https://pkg.go.dev/cmd/vet"), + + linter.NewConfig(golinters.NewGrouper(&cfg.LintersSettings.Grouper)). + WithSince("v1.44.0"). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/leonklingele/grouper"), + + linter.NewConfig(linter.NewNoopDeprecated("ifshort", cfg)). + WithSince("v1.36.0"). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/esimonov/ifshort"). + Deprecated("The repository of the linter has been deprecated by the owner.", "v1.48.0", ""), + + linter.NewConfig(golinters.NewImportAs(&cfg.LintersSettings.ImportAs)). + WithSince("v1.38.0"). + WithPresets(linter.PresetStyle). + WithLoadForGoAnalysis(). + WithURL("https://github.com/julz/importas"), + + linter.NewConfig(golinters.NewINamedParam(&cfg.LintersSettings.Inamedparam)). + WithSince("v1.55.0"). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/macabu/inamedparam"), + + linter.NewConfig(golinters.NewIneffassign()). + WithEnabledByDefault(). + WithSince("v1.0.0"). + WithPresets(linter.PresetUnused). + WithURL("https://github.com/gordonklaus/ineffassign"), + + linter.NewConfig(golinters.NewInterfaceBloat(&cfg.LintersSettings.InterfaceBloat)). + WithSince("v1.49.0"). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/sashamelentyev/interfacebloat"), + + linter.NewConfig(linter.NewNoopDeprecated("interfacer", cfg)). + WithSince("v1.0.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/mvdan/interfacer"). + Deprecated("The repository of the linter has been archived by the owner.", "v1.38.0", ""), + + linter.NewConfig(golinters.NewIntrange()). + WithSince("v1.57.0"). + WithURL("https://github.com/ckaznocha/intrange"). + WithNoopFallback(cfg, linter.IsGoLowerThanGo122()), + + linter.NewConfig(golinters.NewIreturn(&cfg.LintersSettings.Ireturn)). + WithSince("v1.43.0"). + WithPresets(linter.PresetStyle). + WithLoadForGoAnalysis(). + WithURL("https://github.com/butuzov/ireturn"), + + linter.NewConfig(golinters.NewLLL(&cfg.LintersSettings.Lll)). + WithSince("v1.8.0"). + WithPresets(linter.PresetStyle), + + linter.NewConfig(golinters.NewLoggerCheck(&cfg.LintersSettings.LoggerCheck)). + WithSince("v1.49.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetStyle, linter.PresetBugs). + WithAlternativeNames("logrlint"). + WithURL("https://github.com/timonwong/loggercheck"), + + linter.NewConfig(golinters.NewMaintIdx(&cfg.LintersSettings.MaintIdx)). + WithSince("v1.44.0"). + WithPresets(linter.PresetComplexity). + WithURL("https://github.com/yagipy/maintidx"), + + linter.NewConfig(golinters.NewMakezero(&cfg.LintersSettings.Makezero)). + WithSince("v1.34.0"). + WithPresets(linter.PresetStyle, linter.PresetBugs). + WithLoadForGoAnalysis(). + WithURL("https://github.com/ashanbrown/makezero"), + + linter.NewConfig(linter.NewNoopDeprecated("maligned", cfg)). + WithSince("v1.0.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetPerformance). + WithURL("https://github.com/mdempsky/maligned"). + Deprecated("The repository of the linter has been archived by the owner.", "v1.38.0", "govet 'fieldalignment'"), + + linter.NewConfig(golinters.NewMirror()). + WithSince("v1.53.0"). + WithPresets(linter.PresetStyle). + WithLoadForGoAnalysis(). + WithURL("https://github.com/butuzov/mirror"), + + linter.NewConfig(golinters.NewMisspell(&cfg.LintersSettings.Misspell)). + WithSince("v1.8.0"). + WithPresets(linter.PresetStyle, linter.PresetComment). + WithAutoFix(). + WithURL("https://github.com/client9/misspell"), + + linter.NewConfig(golinters.NewMustTag(&cfg.LintersSettings.MustTag)). + WithSince("v1.51.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetStyle, linter.PresetBugs). + WithURL("https://github.com/go-simpler/musttag"), + + linter.NewConfig(golinters.NewNakedret(&cfg.LintersSettings.Nakedret)). + WithSince("v1.19.0"). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/alexkohler/nakedret"), + + linter.NewConfig(golinters.NewNestif(&cfg.LintersSettings.Nestif)). + WithSince("v1.25.0"). + WithPresets(linter.PresetComplexity). + WithURL("https://github.com/nakabonne/nestif"), + + linter.NewConfig(golinters.NewNilErr()). + WithSince("v1.38.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetBugs). + WithURL("https://github.com/gostaticanalysis/nilerr"), + + linter.NewConfig(golinters.NewNilNil(&cfg.LintersSettings.NilNil)). + WithSince("v1.43.0"). + WithPresets(linter.PresetStyle). + WithLoadForGoAnalysis(). + WithURL("https://github.com/Antonboom/nilnil"), + + linter.NewConfig(golinters.NewNLReturn(&cfg.LintersSettings.Nlreturn)). + WithSince("v1.30.0"). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/ssgreg/nlreturn"), + + linter.NewConfig(golinters.NewNoctx()). + WithSince("v1.28.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetPerformance, linter.PresetBugs). + WithURL("https://github.com/sonatard/noctx"), + + linter.NewConfig(golinters.NewNoNamedReturns(&cfg.LintersSettings.NoNamedReturns)). + WithSince("v1.46.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/firefart/nonamedreturns"), + + linter.NewConfig(linter.NewNoopDeprecated("nosnakecase", cfg)). + WithSince("v1.47.0"). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/sivchari/nosnakecase"). + Deprecated("The repository of the linter has been deprecated by the owner.", "v1.48.1", "revive 'var-naming'"), + + linter.NewConfig(golinters.NewNoSprintfHostPort()). + WithSince("v1.46.0"). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/stbenjam/no-sprintf-host-port"), + + linter.NewConfig(golinters.NewParallelTest(&cfg.LintersSettings.ParallelTest)). + WithSince("v1.33.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetStyle, linter.PresetTest). + WithURL("https://github.com/kunwardeep/paralleltest"), + + linter.NewConfig(golinters.NewPerfSprint(&cfg.LintersSettings.PerfSprint)). + WithSince("v1.55.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetPerformance). + WithURL("https://github.com/catenacyber/perfsprint"), + + linter.NewConfig(golinters.NewPreAlloc(&cfg.LintersSettings.Prealloc)). + WithSince("v1.19.0"). + WithPresets(linter.PresetPerformance). + WithURL("https://github.com/alexkohler/prealloc"), + + linter.NewConfig(golinters.NewPredeclared(&cfg.LintersSettings.Predeclared)). + WithSince("v1.35.0"). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/nishanths/predeclared"), + + linter.NewConfig(golinters.NewPromlinter(&cfg.LintersSettings.Promlinter)). + WithSince("v1.40.0"). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/yeya24/promlinter"), + + linter.NewConfig(golinters.NewProtoGetter(&cfg.LintersSettings.ProtoGetter)). + WithSince("v1.55.0"). + WithPresets(linter.PresetBugs). + WithLoadForGoAnalysis(). + WithAutoFix(). + WithURL("https://github.com/ghostiam/protogetter"), + + linter.NewConfig(golinters.NewReassign(&cfg.LintersSettings.Reassign)). + WithSince("1.49.0"). + WithPresets(linter.PresetBugs). + WithLoadForGoAnalysis(). + WithURL("https://github.com/curioswitch/go-reassign"), + + linter.NewConfig(golinters.NewRevive(&cfg.LintersSettings.Revive)). + WithSince("v1.37.0"). + WithPresets(linter.PresetStyle, linter.PresetMetaLinter). + ConsiderSlow(). + WithURL("https://github.com/mgechev/revive"), + + linter.NewConfig(golinters.NewRowsErrCheck(&cfg.LintersSettings.RowsErrCheck)). + WithSince("v1.23.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetBugs, linter.PresetSQL). + WithURL("https://github.com/jingyugao/rowserrcheck"), + + linter.NewConfig(golinters.NewSlogLint(&cfg.LintersSettings.SlogLint)). + WithSince("v1.55.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetStyle, linter.PresetFormatting). + WithURL("https://github.com/go-simpler/sloglint"), + + linter.NewConfig(linter.NewNoopDeprecated("scopelint", cfg)). + WithSince("v1.12.0"). + WithPresets(linter.PresetBugs). + WithURL("https://github.com/kyoh86/scopelint"). + Deprecated("The repository of the linter has been deprecated by the owner.", "v1.39.0", "exportloopref"), + + linter.NewConfig(golinters.NewSQLCloseCheck()). + WithSince("v1.28.0"). + WithPresets(linter.PresetBugs, linter.PresetSQL). + WithLoadForGoAnalysis(). + WithURL("https://github.com/ryanrolds/sqlclosecheck"), + + linter.NewConfig(golinters.NewSpancheck(&cfg.LintersSettings.Spancheck)). + WithSince("v1.56.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetBugs). + WithURL("https://github.com/jjti/go-spancheck"), + + linter.NewConfig(golinters.NewStaticcheck(&cfg.LintersSettings.Staticcheck)). + WithEnabledByDefault(). + WithSince("v1.0.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetBugs, linter.PresetMetaLinter). + WithAlternativeNames(megacheckName). + WithURL("https://staticcheck.io/"), + + linter.NewConfig(linter.NewNoopDeprecated("structcheck", cfg)). + WithSince("v1.0.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetUnused). + WithURL("https://github.com/opennota/check"). + Deprecated("The owner seems to have abandoned the linter.", "v1.49.0", "unused"), + + linter.NewConfig(golinters.NewStylecheck(&cfg.LintersSettings.Stylecheck)). + WithSince("v1.20.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/dominikh/go-tools/tree/master/stylecheck"), + + linter.NewConfig(golinters.NewTagAlign(&cfg.LintersSettings.TagAlign)). + WithSince("v1.53.0"). + WithPresets(linter.PresetStyle, linter.PresetFormatting). + WithAutoFix(). + WithURL("https://github.com/4meepo/tagalign"), + + linter.NewConfig(golinters.NewTagliatelle(&cfg.LintersSettings.Tagliatelle)). + WithSince("v1.40.0"). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/ldez/tagliatelle"), + + linter.NewConfig(golinters.NewTenv(&cfg.LintersSettings.Tenv)). + WithSince("v1.43.0"). + WithPresets(linter.PresetStyle). + WithLoadForGoAnalysis(). + WithURL("https://github.com/sivchari/tenv"), + + linter.NewConfig(golinters.NewTestableexamples()). + WithSince("v1.50.0"). + WithPresets(linter.PresetTest). + WithURL("https://github.com/maratori/testableexamples"), + + linter.NewConfig(golinters.NewTestifylint(&cfg.LintersSettings.Testifylint)). + WithSince("v1.55.0"). + WithPresets(linter.PresetTest, linter.PresetBugs). + WithLoadForGoAnalysis(). + WithURL("https://github.com/Antonboom/testifylint"), + + linter.NewConfig(golinters.NewTestpackage(&cfg.LintersSettings.Testpackage)). + WithSince("v1.25.0"). + WithPresets(linter.PresetStyle, linter.PresetTest). + WithURL("https://github.com/maratori/testpackage"), + + linter.NewConfig(golinters.NewThelper(&cfg.LintersSettings.Thelper)). + WithSince("v1.34.0"). + WithPresets(linter.PresetStyle). + WithLoadForGoAnalysis(). + WithURL("https://github.com/kulti/thelper"), + + linter.NewConfig(golinters.NewTparallel()). + WithSince("v1.32.0"). + WithPresets(linter.PresetStyle, linter.PresetTest). + WithLoadForGoAnalysis(). + WithURL("https://github.com/moricho/tparallel"), + + linter.NewConfig(golinters.NewTypecheck()). + WithInternal(). + WithEnabledByDefault(). + WithSince("v1.3.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetBugs). + WithURL(""), + + linter.NewConfig(golinters.NewUnconvert(&cfg.LintersSettings.Unconvert)). + WithSince("v1.0.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/mdempsky/unconvert"), + + linter.NewConfig(golinters.NewUnparam(&cfg.LintersSettings.Unparam)). + WithSince("v1.9.0"). + WithPresets(linter.PresetUnused). + WithLoadForGoAnalysis(). + WithURL("https://github.com/mvdan/unparam"), + + linter.NewConfig(golinters.NewUnused(&cfg.LintersSettings.Unused, &cfg.LintersSettings.Staticcheck)). + WithEnabledByDefault(). + WithSince("v1.20.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetUnused). + WithAlternativeNames(megacheckName). + ConsiderSlow(). + WithChangeTypes(). + WithURL("https://github.com/dominikh/go-tools/tree/master/unused"), + + linter.NewConfig(golinters.NewUseStdlibVars(&cfg.LintersSettings.UseStdlibVars)). + WithSince("v1.48.0"). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/sashamelentyev/usestdlibvars"), + + linter.NewConfig(linter.NewNoopDeprecated("varcheck", cfg)). + WithSince("v1.0.0"). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetUnused). + WithURL("https://github.com/opennota/check"). + Deprecated("The owner seems to have abandoned the linter.", "v1.49.0", "unused"), + + linter.NewConfig(golinters.NewVarnamelen(&cfg.LintersSettings.Varnamelen)). + WithSince("v1.43.0"). + WithPresets(linter.PresetStyle). + WithLoadForGoAnalysis(). + WithURL("https://github.com/blizzy78/varnamelen"), + + linter.NewConfig(golinters.NewWastedAssign()). + WithSince("v1.38.0"). + WithPresets(linter.PresetStyle). + WithLoadForGoAnalysis(). + WithURL("https://github.com/sanposhiho/wastedassign"), + + linter.NewConfig(golinters.NewWhitespace(&cfg.LintersSettings.Whitespace)). + WithSince("v1.19.0"). + WithPresets(linter.PresetStyle). + WithAutoFix(). + WithURL("https://github.com/ultraware/whitespace"), + + linter.NewConfig(golinters.NewWrapcheck(&cfg.LintersSettings.Wrapcheck)). + WithSince("v1.32.0"). + WithPresets(linter.PresetStyle, linter.PresetError). + WithLoadForGoAnalysis(). + WithURL("https://github.com/tomarrell/wrapcheck"), + + linter.NewConfig(golinters.NewWSL(&cfg.LintersSettings.WSL)). + WithSince("v1.20.0"). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/bombsimon/wsl"), + + linter.NewConfig(golinters.NewZerologLint()). + WithSince("v1.53.0"). + WithPresets(linter.PresetBugs). + WithLoadForGoAnalysis(). + WithURL("https://github.com/ykadowak/zerologlint"), + + // nolintlint must be last because it looks at the results of all the previous linters for unused nolint directives + linter.NewConfig(golinters.NewNoLintLint(&cfg.LintersSettings.NoLintLint)). + WithSince("v1.26.0"). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/golangci/golangci-lint/blob/master/pkg/golinters/nolintlint/README.md"), + }, nil +} diff --git a/pkg/lint/lintersdb/builder_plugin_go.go b/pkg/lint/lintersdb/builder_plugin_go.go new file mode 100644 index 000000000000..4c6b4b5988f5 --- /dev/null +++ b/pkg/lint/lintersdb/builder_plugin_go.go @@ -0,0 +1,139 @@ +package lintersdb + +import ( + "errors" + "fmt" + "path/filepath" + "plugin" + + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/logutils" +) + +const goPluginType = "goplugin" + +type AnalyzerPlugin interface { + GetAnalyzers() []*analysis.Analyzer +} + +// PluginGoBuilder builds the custom linters (Go plugin) based on the configuration. +type PluginGoBuilder struct { + log logutils.Log +} + +// NewPluginGoBuilder creates new PluginGoBuilder. +func NewPluginGoBuilder(log logutils.Log) *PluginGoBuilder { + return &PluginGoBuilder{log: log} +} + +// Build loads custom linters that are specified in the golangci-lint config file. +func (b *PluginGoBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { + if cfg == nil || b.log == nil { + return nil, nil + } + + var linters []*linter.Config + + for name, settings := range cfg.LintersSettings.Custom { + if settings.Type != goPluginType && settings.Type != "" { + continue + } + + settings := settings + + lc, err := b.loadConfig(cfg, name, &settings) + if err != nil { + return nil, fmt.Errorf("unable to load custom analyzer %q: %s, %w", name, settings.Path, err) + } else { + linters = append(linters, lc) + } + } + + return linters, nil +} + +// loadConfig loads the configuration of private linters. +// Private linters are dynamically loaded from .so plugin files. +func (b *PluginGoBuilder) loadConfig(cfg *config.Config, name string, settings *config.CustomLinterSettings) (*linter.Config, error) { + analyzers, err := b.getAnalyzerPlugin(cfg, settings.Path, settings.Settings) + if err != nil { + return nil, err + } + + b.log.Infof("Loaded %s: %s", settings.Path, name) + + customLinter := goanalysis.NewLinter(name, settings.Description, analyzers, nil). + WithLoadMode(goanalysis.LoadModeTypesInfo) + + linterConfig := linter.NewConfig(customLinter). + WithEnabledByDefault(). + WithLoadForGoAnalysis(). + WithURL(settings.OriginalURL) + + return linterConfig, nil +} + +// getAnalyzerPlugin loads a private linter as specified in the config file, +// loads the plugin from a .so file, +// and returns the 'AnalyzerPlugin' interface implemented by the private plugin. +// An error is returned if the private linter cannot be loaded +// or the linter does not implement the AnalyzerPlugin interface. +func (b *PluginGoBuilder) getAnalyzerPlugin(cfg *config.Config, path string, settings any) ([]*analysis.Analyzer, error) { + if !filepath.IsAbs(path) { + // resolve non-absolute paths relative to config file's directory + path = filepath.Join(cfg.GetConfigDir(), path) + } + + plug, err := plugin.Open(path) + if err != nil { + return nil, err + } + + analyzers, err := b.lookupPlugin(plug, settings) + if err != nil { + return nil, fmt.Errorf("lookup plugin %s: %w", path, err) + } + + return analyzers, nil +} + +func (b *PluginGoBuilder) lookupPlugin(plug *plugin.Plugin, settings any) ([]*analysis.Analyzer, error) { + symbol, err := plug.Lookup("New") + if err != nil { + analyzers, errP := b.lookupAnalyzerPlugin(plug) + if errP != nil { + return nil, errors.Join(err, errP) + } + + return analyzers, nil + } + + // The type func cannot be used here, must be the explicit signature. + constructor, ok := symbol.(func(any) ([]*analysis.Analyzer, error)) + if !ok { + return nil, fmt.Errorf("plugin does not abide by 'New' function: %T", symbol) + } + + return constructor(settings) +} + +func (b *PluginGoBuilder) lookupAnalyzerPlugin(plug *plugin.Plugin) ([]*analysis.Analyzer, error) { + symbol, err := plug.Lookup("AnalyzerPlugin") + if err != nil { + return nil, err + } + + b.log.Warnf("plugin: 'AnalyzerPlugin' plugins are deprecated, please use the new plugin signature: " + + "https://golangci-lint.run/contributing/new-linters/#create-a-plugin") + + analyzerPlugin, ok := symbol.(AnalyzerPlugin) + if !ok { + return nil, fmt.Errorf("plugin does not abide by 'AnalyzerPlugin' interface: %T", symbol) + } + + return analyzerPlugin.GetAnalyzers(), nil +} diff --git a/pkg/lint/lintersdb/builder_plugin_module.go b/pkg/lint/lintersdb/builder_plugin_module.go new file mode 100644 index 000000000000..904b18bd5e4d --- /dev/null +++ b/pkg/lint/lintersdb/builder_plugin_module.go @@ -0,0 +1,85 @@ +package lintersdb + +import ( + "fmt" + "strings" + + "github.com/golangci/plugin-module-register/register" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/logutils" +) + +const modulePluginType = "module" + +// PluginModuleBuilder builds the custom linters (module plugin) based on the configuration. +type PluginModuleBuilder struct { + log logutils.Log +} + +// NewPluginModuleBuilder creates new PluginModuleBuilder. +func NewPluginModuleBuilder(log logutils.Log) *PluginModuleBuilder { + return &PluginModuleBuilder{log: log} +} + +// Build loads custom linters that are specified in the golangci-lint config file. +func (b *PluginModuleBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { + if cfg == nil || b.log == nil { + return nil, nil + } + + var linters []*linter.Config + + for name, settings := range cfg.LintersSettings.Custom { + if settings.Type != modulePluginType { + continue + } + + b.log.Infof("Loaded %s: %s", settings.Path, name) + + newPlugin, err := register.GetPlugin(name) + if err != nil { + return nil, fmt.Errorf("plugin(%s): %w", name, err) + } + + p, err := newPlugin(settings.Settings) + if err != nil { + return nil, fmt.Errorf("plugin(%s): newPlugin %w", name, err) + } + + analyzers, err := p.BuildAnalyzers() + if err != nil { + return nil, fmt.Errorf("plugin(%s): BuildAnalyzers %w", name, err) + } + + customLinter := goanalysis.NewLinter(name, settings.Description, analyzers, nil) + + switch strings.ToLower(p.GetLoadMode()) { + case register.LoadModeSyntax: + customLinter = customLinter.WithLoadMode(goanalysis.LoadModeSyntax) + case register.LoadModeTypesInfo: + customLinter = customLinter.WithLoadMode(goanalysis.LoadModeTypesInfo) + default: + customLinter = customLinter.WithLoadMode(goanalysis.LoadModeTypesInfo) + } + + lc := linter.NewConfig(customLinter). + WithEnabledByDefault(). + WithURL(settings.OriginalURL) + + switch strings.ToLower(p.GetLoadMode()) { + case register.LoadModeSyntax: + // noop + case register.LoadModeTypesInfo: + lc = lc.WithLoadForGoAnalysis() + default: + lc = lc.WithLoadForGoAnalysis() + } + + linters = append(linters, lc) + } + + return linters, nil +} diff --git a/pkg/lint/lintersdb/enabled_set.go b/pkg/lint/lintersdb/enabled_set.go deleted file mode 100644 index 92615b57aa13..000000000000 --- a/pkg/lint/lintersdb/enabled_set.go +++ /dev/null @@ -1,209 +0,0 @@ -package lintersdb - -import ( - "os" - "sort" - - "github.com/golangci/golangci-lint/pkg/config" - "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" - "github.com/golangci/golangci-lint/pkg/lint/linter" - "github.com/golangci/golangci-lint/pkg/logutils" -) - -// EnvTestRun value: "1" -const EnvTestRun = "GL_TEST_RUN" - -type EnabledSet struct { - m *Manager - v *Validator - log logutils.Log - cfg *config.Config - debugf logutils.DebugFunc -} - -func NewEnabledSet(m *Manager, v *Validator, log logutils.Log, cfg *config.Config) *EnabledSet { - return &EnabledSet{ - m: m, - v: v, - log: log, - cfg: cfg, - debugf: logutils.Debug(logutils.DebugKeyEnabledLinters), - } -} - -func (es EnabledSet) build(lcfg *config.Linters, enabledByDefaultLinters []*linter.Config) map[string]*linter.Config { - es.debugf("Linters config: %#v", lcfg) - resultLintersSet := map[string]*linter.Config{} - switch { - case len(lcfg.Presets) != 0: - break // imply --disable-all - case lcfg.EnableAll: - resultLintersSet = linterConfigsToMap(es.m.GetAllSupportedLinterConfigs()) - case lcfg.DisableAll: - break - default: - resultLintersSet = linterConfigsToMap(enabledByDefaultLinters) - } - - // --presets can only add linters to default set - for _, p := range lcfg.Presets { - for _, lc := range es.m.GetAllLinterConfigsForPreset(p) { - lc := lc - resultLintersSet[lc.Name()] = lc - } - } - - // --fast removes slow linters from current set. - // It should be after --presets to be able to run only fast linters in preset. - // It should be before --enable and --disable to be able to enable or disable specific linter. - if lcfg.Fast { - for name, lc := range resultLintersSet { - if lc.IsSlowLinter() { - delete(resultLintersSet, name) - } - } - } - - for _, name := range lcfg.Enable { - for _, lc := range es.m.GetLinterConfigs(name) { - // it's important to use lc.Name() nor name because name can be alias - resultLintersSet[lc.Name()] = lc - } - } - - for _, name := range lcfg.Disable { - for _, lc := range es.m.GetLinterConfigs(name) { - // it's important to use lc.Name() nor name because name can be alias - delete(resultLintersSet, lc.Name()) - } - } - - return resultLintersSet -} - -func (es EnabledSet) GetEnabledLintersMap() (map[string]*linter.Config, error) { - if err := es.v.validateEnabledDisabledLintersConfig(&es.cfg.Linters); err != nil { - return nil, err - } - - enabledLinters := es.build(&es.cfg.Linters, es.m.GetAllEnabledByDefaultLinters()) - if os.Getenv(EnvTestRun) == "1" { - es.verbosePrintLintersStatus(enabledLinters) - } - return enabledLinters, nil -} - -// GetOptimizedLinters returns enabled linters after optimization (merging) of multiple linters -// into a fewer number of linters. E.g. some go/analysis linters can be optimized into -// one metalinter for data reuse and speed up. -func (es EnabledSet) GetOptimizedLinters() ([]*linter.Config, error) { - if err := es.v.validateEnabledDisabledLintersConfig(&es.cfg.Linters); err != nil { - return nil, err - } - - resultLintersSet := es.build(&es.cfg.Linters, es.m.GetAllEnabledByDefaultLinters()) - es.verbosePrintLintersStatus(resultLintersSet) - es.combineGoAnalysisLinters(resultLintersSet) - - var resultLinters []*linter.Config - for _, lc := range resultLintersSet { - resultLinters = append(resultLinters, lc) - } - - // Make order of execution of linters (go/analysis metalinter and unused) stable. - sort.Slice(resultLinters, func(i, j int) bool { - a, b := resultLinters[i], resultLinters[j] - - if b.Name() == linter.LastLinter { - return true - } - - if a.Name() == linter.LastLinter { - return false - } - - if a.DoesChangeTypes != b.DoesChangeTypes { - return b.DoesChangeTypes // move type-changing linters to the end to optimize speed - } - return a.Name() < b.Name() - }) - - return resultLinters, nil -} - -func (es EnabledSet) combineGoAnalysisLinters(linters map[string]*linter.Config) { - var goanalysisLinters []*goanalysis.Linter - goanalysisPresets := map[string]bool{} - for _, linter := range linters { - lnt, ok := linter.Linter.(*goanalysis.Linter) - if !ok { - continue - } - if lnt.LoadMode() == goanalysis.LoadModeWholeProgram { - // It's ineffective by CPU and memory to run whole-program and incremental analyzers at once. - continue - } - goanalysisLinters = append(goanalysisLinters, lnt) - for _, p := range linter.InPresets { - goanalysisPresets[p] = true - } - } - - if len(goanalysisLinters) <= 1 { - es.debugf("Didn't combine go/analysis linters: got only %d linters", len(goanalysisLinters)) - return - } - - for _, lnt := range goanalysisLinters { - delete(linters, lnt.Name()) - } - - // Make order of execution of go/analysis analyzers stable. - sort.Slice(goanalysisLinters, func(i, j int) bool { - a, b := goanalysisLinters[i], goanalysisLinters[j] - - if b.Name() == linter.LastLinter { - return true - } - - if a.Name() == linter.LastLinter { - return false - } - - return a.Name() <= b.Name() - }) - - ml := goanalysis.NewMetaLinter(goanalysisLinters) - - var presets []string - for p := range goanalysisPresets { - presets = append(presets, p) - } - - mlConfig := &linter.Config{ - Linter: ml, - EnabledByDefault: false, - InPresets: presets, - AlternativeNames: nil, - OriginalURL: "", - } - - mlConfig = mlConfig.WithLoadForGoAnalysis() - - linters[ml.Name()] = mlConfig - es.debugf("Combined %d go/analysis linters into one metalinter", len(goanalysisLinters)) -} - -func (es EnabledSet) verbosePrintLintersStatus(lcs map[string]*linter.Config) { - var linterNames []string - for _, lc := range lcs { - linterNames = append(linterNames, lc.Name()) - } - sort.StringSlice(linterNames).Sort() - es.log.Infof("Active %d linters: %s", len(linterNames), linterNames) - - if len(es.cfg.Linters.Presets) != 0 { - sort.StringSlice(es.cfg.Linters.Presets).Sort() - es.log.Infof("Active presets: %s", es.cfg.Linters.Presets) - } -} diff --git a/pkg/lint/lintersdb/enabled_set_test.go b/pkg/lint/lintersdb/enabled_set_test.go deleted file mode 100644 index f9b6393f71e3..000000000000 --- a/pkg/lint/lintersdb/enabled_set_test.go +++ /dev/null @@ -1,119 +0,0 @@ -package lintersdb - -import ( - "sort" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/golangci/golangci-lint/pkg/config" - "github.com/golangci/golangci-lint/pkg/lint/linter" -) - -//nolint:funlen -func TestGetEnabledLintersSet(t *testing.T) { - type cs struct { - cfg config.Linters - name string // test case name - def []string // enabled by default linters - exp []string // alphabetically ordered enabled linter names - } - allMegacheckLinterNames := []string{"gosimple", "staticcheck", "unused"} - cases := []cs{ - { - cfg: config.Linters{ - Disable: []string{"megacheck"}, - }, - name: "disable all linters from megacheck", - def: allMegacheckLinterNames, - exp: nil, // all disabled - }, - { - cfg: config.Linters{ - Disable: []string{"staticcheck"}, - }, - name: "disable only staticcheck", - def: allMegacheckLinterNames, - exp: []string{"gosimple", "unused"}, - }, - { - name: "don't merge into megacheck", - def: allMegacheckLinterNames, - exp: allMegacheckLinterNames, - }, - { - name: "expand megacheck", - cfg: config.Linters{ - Enable: []string{"megacheck"}, - }, - def: nil, - exp: allMegacheckLinterNames, - }, - { - name: "don't disable anything", - def: []string{"gofmt", "govet"}, - exp: []string{"gofmt", "govet"}, - }, - { - name: "enable gosec by gas alias", - cfg: config.Linters{ - Enable: []string{"gas"}, - }, - exp: []string{"gosec"}, - }, - { - name: "enable gosec by primary name", - cfg: config.Linters{ - Enable: []string{"gosec"}, - }, - exp: []string{"gosec"}, - }, - { - name: "enable gosec by both names", - cfg: config.Linters{ - Enable: []string{"gosec", "gas"}, - }, - exp: []string{"gosec"}, - }, - { - name: "disable gosec by gas alias", - cfg: config.Linters{ - Disable: []string{"gas"}, - }, - def: []string{"gosec"}, - }, - { - name: "disable gosec by primary name", - cfg: config.Linters{ - Disable: []string{"gosec"}, - }, - def: []string{"gosec"}, - }, - } - - m := NewManager(nil, nil) - es := NewEnabledSet(m, NewValidator(m), nil, nil) - for _, c := range cases { - c := c - t.Run(c.name, func(t *testing.T) { - var defaultLinters []*linter.Config - for _, ln := range c.def { - lcs := m.GetLinterConfigs(ln) - assert.NotNil(t, lcs, ln) - defaultLinters = append(defaultLinters, lcs...) - } - - els := es.build(&c.cfg, defaultLinters) - var enabledLinters []string - for ln, lc := range els { - assert.Equal(t, ln, lc.Name()) - enabledLinters = append(enabledLinters, ln) - } - - sort.Strings(enabledLinters) - sort.Strings(c.exp) - - assert.Equal(t, c.exp, enabledLinters) - }) - } -} diff --git a/pkg/lint/lintersdb/manager.go b/pkg/lint/lintersdb/manager.go index 6f406f7d26e3..57d45dd48c33 100644 --- a/pkg/lint/lintersdb/manager.go +++ b/pkg/lint/lintersdb/manager.go @@ -2,898 +2,142 @@ package lintersdb import ( "fmt" - "path/filepath" - "plugin" + "os" + "slices" + "sort" - "github.com/spf13/viper" - "golang.org/x/tools/go/analysis" + "golang.org/x/exp/maps" "github.com/golangci/golangci-lint/pkg/config" - "github.com/golangci/golangci-lint/pkg/golinters" "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" "github.com/golangci/golangci-lint/pkg/lint/linter" "github.com/golangci/golangci-lint/pkg/logutils" - "github.com/golangci/golangci-lint/pkg/report" ) +// EnvTestRun value: "1" +const EnvTestRun = "GL_TEST_RUN" + +type Builder interface { + Build(cfg *config.Config) ([]*linter.Config, error) +} + +// Manager is a type of database for all linters (internals or plugins). +// It provides methods to access to the linter sets. type Manager struct { + log logutils.Log + debugf logutils.DebugFunc + + cfg *config.Config + + linters []*linter.Config + nameToLCs map[string][]*linter.Config - cfg *config.Config - log logutils.Log } -func NewManager(cfg *config.Config, log logutils.Log) *Manager { - m := &Manager{cfg: cfg, log: log} - nameToLCs := make(map[string][]*linter.Config) - for _, lc := range m.GetAllSupportedLinterConfigs() { - for _, name := range lc.AllNames() { - nameToLCs[name] = append(nameToLCs[name], lc) - } +// NewManager creates a new Manager. +// This constructor will call the builders to build and store the linters. +func NewManager(log logutils.Log, cfg *config.Config, builders ...Builder) (*Manager, error) { + m := &Manager{ + log: log, + debugf: logutils.Debug(logutils.DebugKeyEnabledLinters), + nameToLCs: make(map[string][]*linter.Config), } - m.nameToLCs = nameToLCs - return m -} - -// WithCustomLinters loads private linters that are specified in the golangci config file. -func (m *Manager) WithCustomLinters() *Manager { - if m.log == nil { - m.log = report.NewLogWrapper(logutils.NewStderrLog(logutils.DebugKeyEmpty), &report.Data{}) + m.cfg = cfg + if cfg == nil { + m.cfg = config.NewDefault() } - if m.cfg != nil { - for name, settings := range m.cfg.LintersSettings.Custom { - lc, err := m.loadCustomLinterConfig(name, settings) - - if err != nil { - m.log.Errorf("Unable to load custom analyzer %s:%s, %v", - name, - settings.Path, - err) - } else { - m.nameToLCs[name] = append(m.nameToLCs[name], lc) - } + + for _, builder := range builders { + linters, err := builder.Build(m.cfg) + if err != nil { + return nil, fmt.Errorf("build linters: %w", err) } + + m.linters = append(m.linters, linters...) } - return m -} -func (Manager) AllPresets() []string { - return []string{ - linter.PresetBugs, - linter.PresetComment, - linter.PresetComplexity, - linter.PresetError, - linter.PresetFormatting, - linter.PresetImport, - linter.PresetMetaLinter, - linter.PresetModule, - linter.PresetPerformance, - linter.PresetSQL, - linter.PresetStyle, - linter.PresetTest, - linter.PresetUnused, + for _, lc := range m.linters { + for _, name := range lc.AllNames() { + m.nameToLCs[name] = append(m.nameToLCs[name], lc) + } } -} -func (m Manager) allPresetsSet() map[string]bool { - ret := map[string]bool{} - for _, p := range m.AllPresets() { - ret[p] = true + err := NewValidator(m).Validate(m.cfg) + if err != nil { + return nil, err } - return ret + + return m, nil } -func (m Manager) GetLinterConfigs(name string) []*linter.Config { +func (m *Manager) GetLinterConfigs(name string) []*linter.Config { return m.nameToLCs[name] } -func enableLinterConfigs(lcs []*linter.Config, isEnabled func(lc *linter.Config) bool) []*linter.Config { +func (m *Manager) GetAllSupportedLinterConfigs() []*linter.Config { + return m.linters +} + +func (m *Manager) GetAllLinterConfigsForPreset(p string) []*linter.Config { var ret []*linter.Config - for _, lc := range lcs { - lc := lc - lc.EnabledByDefault = isEnabled(lc) - ret = append(ret, lc) + for _, lc := range m.linters { + if lc.IsDeprecated() { + continue + } + + if slices.Contains(lc.InPresets, p) { + ret = append(ret, lc) + } } return ret } -//nolint:funlen -func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { - var ( - asasalintCfg *config.AsasalintSettings - bidichkCfg *config.BiDiChkSettings - cyclopCfg *config.Cyclop - decorderCfg *config.DecorderSettings - depGuardCfg *config.DepGuardSettings - dogsledCfg *config.DogsledSettings - duplCfg *config.DuplSettings - dupwordCfg *config.DupWordSettings - errcheckCfg *config.ErrcheckSettings - errchkjsonCfg *config.ErrChkJSONSettings - errorlintCfg *config.ErrorLintSettings - exhaustiveCfg *config.ExhaustiveSettings - exhaustiveStructCfg *config.ExhaustiveStructSettings - exhaustructCfg *config.ExhaustructSettings - forbidigoCfg *config.ForbidigoSettings - funlenCfg *config.FunlenSettings - gciCfg *config.GciSettings - ginkgolinterCfg *config.GinkgoLinterSettings - gocognitCfg *config.GocognitSettings - goconstCfg *config.GoConstSettings - gocriticCfg *config.GoCriticSettings - gocycloCfg *config.GoCycloSettings - godotCfg *config.GodotSettings - godoxCfg *config.GodoxSettings - gofmtCfg *config.GoFmtSettings - gofumptCfg *config.GofumptSettings - goheaderCfg *config.GoHeaderSettings - goimportsCfg *config.GoImportsSettings - golintCfg *config.GoLintSettings - goMndCfg *config.GoMndSettings - goModDirectivesCfg *config.GoModDirectivesSettings - gomodguardCfg *config.GoModGuardSettings - gosecCfg *config.GoSecSettings - gosimpleCfg *config.StaticCheckSettings - govetCfg *config.GovetSettings - grouperCfg *config.GrouperSettings - ifshortCfg *config.IfshortSettings - importAsCfg *config.ImportAsSettings - interfaceBloatCfg *config.InterfaceBloatSettings - ireturnCfg *config.IreturnSettings - lllCfg *config.LllSettings - loggerCheckCfg *config.LoggerCheckSettings - maintIdxCfg *config.MaintIdxSettings - makezeroCfg *config.MakezeroSettings - malignedCfg *config.MalignedSettings - misspellCfg *config.MisspellSettings - musttagCfg *config.MustTagSettings - nakedretCfg *config.NakedretSettings - nestifCfg *config.NestifSettings - nilNilCfg *config.NilNilSettings - nlreturnCfg *config.NlreturnSettings - noLintLintCfg *config.NoLintLintSettings - noNamedReturnsCfg *config.NoNamedReturnsSettings - parallelTestCfg *config.ParallelTestSettings - preallocCfg *config.PreallocSettings - predeclaredCfg *config.PredeclaredSettings - promlinterCfg *config.PromlinterSettings - reassignCfg *config.ReassignSettings - reviveCfg *config.ReviveSettings - rowserrcheckCfg *config.RowsErrCheckSettings - staticcheckCfg *config.StaticCheckSettings - structcheckCfg *config.StructCheckSettings - stylecheckCfg *config.StaticCheckSettings - tagliatelleCfg *config.TagliatelleSettings - tenvCfg *config.TenvSettings - testpackageCfg *config.TestpackageSettings - thelperCfg *config.ThelperSettings - unparamCfg *config.UnparamSettings - unusedCfg *config.StaticCheckSettings - usestdlibvars *config.UseStdlibVarsSettings - varcheckCfg *config.VarCheckSettings - varnamelenCfg *config.VarnamelenSettings - whitespaceCfg *config.WhitespaceSettings - wrapcheckCfg *config.WrapcheckSettings - wslCfg *config.WSLSettings - ) - - if m.cfg != nil { - asasalintCfg = &m.cfg.LintersSettings.Asasalint - bidichkCfg = &m.cfg.LintersSettings.BiDiChk - cyclopCfg = &m.cfg.LintersSettings.Cyclop - decorderCfg = &m.cfg.LintersSettings.Decorder - depGuardCfg = &m.cfg.LintersSettings.Depguard - dogsledCfg = &m.cfg.LintersSettings.Dogsled - duplCfg = &m.cfg.LintersSettings.Dupl - dupwordCfg = &m.cfg.LintersSettings.DupWord - errcheckCfg = &m.cfg.LintersSettings.Errcheck - errchkjsonCfg = &m.cfg.LintersSettings.ErrChkJSON - errorlintCfg = &m.cfg.LintersSettings.ErrorLint - exhaustiveCfg = &m.cfg.LintersSettings.Exhaustive - exhaustiveStructCfg = &m.cfg.LintersSettings.ExhaustiveStruct - exhaustructCfg = &m.cfg.LintersSettings.Exhaustruct - forbidigoCfg = &m.cfg.LintersSettings.Forbidigo - funlenCfg = &m.cfg.LintersSettings.Funlen - gciCfg = &m.cfg.LintersSettings.Gci - ginkgolinterCfg = &m.cfg.LintersSettings.GinkgoLinter - gocognitCfg = &m.cfg.LintersSettings.Gocognit - goconstCfg = &m.cfg.LintersSettings.Goconst - gocriticCfg = &m.cfg.LintersSettings.Gocritic - gocycloCfg = &m.cfg.LintersSettings.Gocyclo - godotCfg = &m.cfg.LintersSettings.Godot - godoxCfg = &m.cfg.LintersSettings.Godox - gofmtCfg = &m.cfg.LintersSettings.Gofmt - gofumptCfg = &m.cfg.LintersSettings.Gofumpt - goheaderCfg = &m.cfg.LintersSettings.Goheader - goimportsCfg = &m.cfg.LintersSettings.Goimports - golintCfg = &m.cfg.LintersSettings.Golint - goMndCfg = &m.cfg.LintersSettings.Gomnd - goModDirectivesCfg = &m.cfg.LintersSettings.GoModDirectives - gomodguardCfg = &m.cfg.LintersSettings.Gomodguard - gosecCfg = &m.cfg.LintersSettings.Gosec - gosimpleCfg = &m.cfg.LintersSettings.Gosimple - govetCfg = &m.cfg.LintersSettings.Govet - grouperCfg = &m.cfg.LintersSettings.Grouper - ifshortCfg = &m.cfg.LintersSettings.Ifshort - importAsCfg = &m.cfg.LintersSettings.ImportAs - interfaceBloatCfg = &m.cfg.LintersSettings.InterfaceBloat - ireturnCfg = &m.cfg.LintersSettings.Ireturn - lllCfg = &m.cfg.LintersSettings.Lll - loggerCheckCfg = &m.cfg.LintersSettings.LoggerCheck - maintIdxCfg = &m.cfg.LintersSettings.MaintIdx - makezeroCfg = &m.cfg.LintersSettings.Makezero - malignedCfg = &m.cfg.LintersSettings.Maligned - misspellCfg = &m.cfg.LintersSettings.Misspell - musttagCfg = &m.cfg.LintersSettings.MustTag - nakedretCfg = &m.cfg.LintersSettings.Nakedret - nestifCfg = &m.cfg.LintersSettings.Nestif - nilNilCfg = &m.cfg.LintersSettings.NilNil - nlreturnCfg = &m.cfg.LintersSettings.Nlreturn - noLintLintCfg = &m.cfg.LintersSettings.NoLintLint - noNamedReturnsCfg = &m.cfg.LintersSettings.NoNamedReturns - preallocCfg = &m.cfg.LintersSettings.Prealloc - parallelTestCfg = &m.cfg.LintersSettings.ParallelTest - predeclaredCfg = &m.cfg.LintersSettings.Predeclared - promlinterCfg = &m.cfg.LintersSettings.Promlinter - reassignCfg = &m.cfg.LintersSettings.Reassign - reviveCfg = &m.cfg.LintersSettings.Revive - rowserrcheckCfg = &m.cfg.LintersSettings.RowsErrCheck - staticcheckCfg = &m.cfg.LintersSettings.Staticcheck - structcheckCfg = &m.cfg.LintersSettings.Structcheck - stylecheckCfg = &m.cfg.LintersSettings.Stylecheck - tagliatelleCfg = &m.cfg.LintersSettings.Tagliatelle - tenvCfg = &m.cfg.LintersSettings.Tenv - testpackageCfg = &m.cfg.LintersSettings.Testpackage - thelperCfg = &m.cfg.LintersSettings.Thelper - unparamCfg = &m.cfg.LintersSettings.Unparam - unusedCfg = &m.cfg.LintersSettings.Unused - varcheckCfg = &m.cfg.LintersSettings.Varcheck - varnamelenCfg = &m.cfg.LintersSettings.Varnamelen - whitespaceCfg = &m.cfg.LintersSettings.Whitespace - wrapcheckCfg = &m.cfg.LintersSettings.Wrapcheck - wslCfg = &m.cfg.LintersSettings.WSL - - if govetCfg != nil { - govetCfg.Go = m.cfg.Run.Go - } +func (m *Manager) GetEnabledLintersMap() (map[string]*linter.Config, error) { + enabledLinters := m.build(m.GetAllEnabledByDefaultLinters()) - if gofumptCfg != nil && gofumptCfg.LangVersion == "" { - gofumptCfg.LangVersion = m.cfg.Run.Go - } + if os.Getenv(EnvTestRun) == "1" { + m.verbosePrintLintersStatus(enabledLinters) + } - if staticcheckCfg != nil && staticcheckCfg.GoVersion == "" { - staticcheckCfg.GoVersion = m.cfg.Run.Go - } - if gosimpleCfg != nil && gosimpleCfg.GoVersion == "" { - gosimpleCfg.GoVersion = m.cfg.Run.Go - } - if stylecheckCfg != nil && stylecheckCfg.GoVersion != "" { - stylecheckCfg.GoVersion = m.cfg.Run.Go - } - if unusedCfg != nil && unusedCfg.GoVersion == "" { - unusedCfg.GoVersion = m.cfg.Run.Go + return enabledLinters, nil +} + +// GetOptimizedLinters returns enabled linters after optimization (merging) of multiple linters into a fewer number of linters. +// E.g. some go/analysis linters can be optimized into one metalinter for data reuse and speed up. +func (m *Manager) GetOptimizedLinters() ([]*linter.Config, error) { + resultLintersSet := m.build(m.GetAllEnabledByDefaultLinters()) + m.verbosePrintLintersStatus(resultLintersSet) + + m.combineGoAnalysisLinters(resultLintersSet) + + resultLinters := maps.Values(resultLintersSet) + + // Make order of execution of linters (go/analysis metalinter and unused) stable. + sort.Slice(resultLinters, func(i, j int) bool { + a, b := resultLinters[i], resultLinters[j] + + if b.Name() == linter.LastLinter { + return true } - } - const megacheckName = "megacheck" - - // The linters are sorted in the alphabetical order (case-insensitive). - // When a new linter is added the version in `WithSince(...)` must be the next minor version of golangci-lint. - lcs := []*linter.Config{ - linter.NewConfig(golinters.NewAsasalint(asasalintCfg)). - WithSince("1.47.0"). - WithPresets(linter.PresetBugs). - WithLoadForGoAnalysis(). - WithURL("https://github.com/alingse/asasalint"), - - linter.NewConfig(golinters.NewAsciicheck()). - WithSince("v1.26.0"). - WithPresets(linter.PresetBugs, linter.PresetStyle). - WithURL("https://github.com/tdakkota/asciicheck"), - - linter.NewConfig(golinters.NewBiDiChkFuncName(bidichkCfg)). - WithSince("1.43.0"). - WithPresets(linter.PresetBugs). - WithURL("https://github.com/breml/bidichk"), - - linter.NewConfig(golinters.NewBodyclose()). - WithSince("v1.18.0"). - WithLoadForGoAnalysis(). - WithPresets(linter.PresetPerformance, linter.PresetBugs). - WithURL("https://github.com/timakin/bodyclose"), - - linter.NewConfig(golinters.NewContainedCtx()). - WithSince("1.44.0"). - WithPresets(linter.PresetStyle). - WithURL("https://github.com/sivchari/containedctx"), - - linter.NewConfig(golinters.NewContextCheck()). - WithSince("v1.43.0"). - WithPresets(linter.PresetBugs). - WithLoadForGoAnalysis(). - WithURL("https://github.com/kkHAIKE/contextcheck"), - - linter.NewConfig(golinters.NewCyclop(cyclopCfg)). - WithSince("v1.37.0"). - WithLoadForGoAnalysis(). - WithPresets(linter.PresetComplexity). - WithURL("https://github.com/bkielbasa/cyclop"), - - linter.NewConfig(golinters.NewDecorder(decorderCfg)). - WithSince("v1.44.0"). - WithPresets(linter.PresetFormatting, linter.PresetStyle). - WithURL("https://gitlab.com/bosi/decorder"), - - linter.NewConfig(golinters.NewDeadcode()). - WithSince("v1.0.0"). - WithLoadForGoAnalysis(). - WithPresets(linter.PresetUnused). - WithURL("https://github.com/remyoudompheng/go-misc/tree/master/deadcode"). - Deprecated("The owner seems to have abandoned the linter.", "v1.49.0", "unused"), - - linter.NewConfig(golinters.NewDepguard(depGuardCfg)). - WithSince("v1.4.0"). - WithPresets(linter.PresetStyle, linter.PresetImport, linter.PresetModule). - WithURL("https://github.com/OpenPeeDeeP/depguard"), - - linter.NewConfig(golinters.NewDogsled(dogsledCfg)). - WithSince("v1.19.0"). - WithPresets(linter.PresetStyle). - WithURL("https://github.com/alexkohler/dogsled"), - - linter.NewConfig(golinters.NewDupl(duplCfg)). - WithSince("v1.0.0"). - WithPresets(linter.PresetStyle). - WithURL("https://github.com/mibk/dupl"), - - linter.NewConfig(golinters.NewDupWord(dupwordCfg)). - WithSince("1.50.0"). - WithPresets(linter.PresetComment). - WithAutoFix(). - WithURL("https://github.com/Abirdcfly/dupword"), - - linter.NewConfig(golinters.NewDurationCheck()). - WithSince("v1.37.0"). - WithPresets(linter.PresetBugs). - WithLoadForGoAnalysis(). - WithURL("https://github.com/charithe/durationcheck"), - - linter.NewConfig(golinters.NewErrcheck(errcheckCfg)). - WithSince("v1.0.0"). - WithLoadForGoAnalysis(). - WithPresets(linter.PresetBugs, linter.PresetError). - WithURL("https://github.com/kisielk/errcheck"), - - linter.NewConfig(golinters.NewErrChkJSONFuncName(errchkjsonCfg)). - WithSince("1.44.0"). - WithPresets(linter.PresetBugs). - WithLoadForGoAnalysis(). - WithURL("https://github.com/breml/errchkjson"), - - linter.NewConfig(golinters.NewErrName()). - WithSince("v1.42.0"). - WithPresets(linter.PresetStyle). - WithLoadForGoAnalysis(). - WithURL("https://github.com/Antonboom/errname"), - - linter.NewConfig(golinters.NewErrorLint(errorlintCfg)). - WithSince("v1.32.0"). - WithPresets(linter.PresetBugs, linter.PresetError). - WithLoadForGoAnalysis(). - WithURL("https://github.com/polyfloyd/go-errorlint"), - - linter.NewConfig(golinters.NewExecInQuery()). - WithSince("v1.46.0"). - WithPresets(linter.PresetSQL). - WithLoadForGoAnalysis(). - WithURL("https://github.com/lufeee/execinquery"), - - linter.NewConfig(golinters.NewExhaustive(exhaustiveCfg)). - WithSince(" v1.28.0"). - WithPresets(linter.PresetBugs). - WithLoadForGoAnalysis(). - WithURL("https://github.com/nishanths/exhaustive"), - - linter.NewConfig(golinters.NewExhaustiveStruct(exhaustiveStructCfg)). - WithSince("v1.32.0"). - WithPresets(linter.PresetStyle, linter.PresetTest). - WithLoadForGoAnalysis(). - WithURL("https://github.com/mbilski/exhaustivestruct"). - Deprecated("The owner seems to have abandoned the linter.", "v1.46.0", "exhaustruct"), - - linter.NewConfig(golinters.NewExhaustruct(exhaustructCfg)). - WithSince("v1.46.0"). - WithPresets(linter.PresetStyle, linter.PresetTest). - WithLoadForGoAnalysis(). - WithURL("https://github.com/GaijinEntertainment/go-exhaustruct"), - - linter.NewConfig(golinters.NewExportLoopRef()). - WithSince("v1.28.0"). - WithPresets(linter.PresetBugs). - WithLoadForGoAnalysis(). - WithURL("https://github.com/kyoh86/exportloopref"), - - linter.NewConfig(golinters.NewForbidigo(forbidigoCfg)). - WithSince("v1.34.0"). - WithPresets(linter.PresetStyle). - WithURL("https://github.com/ashanbrown/forbidigo"), - - linter.NewConfig(golinters.NewForceTypeAssert()). - WithSince("v1.38.0"). - WithPresets(linter.PresetStyle). - WithURL("https://github.com/gostaticanalysis/forcetypeassert"), - - linter.NewConfig(golinters.NewFunlen(funlenCfg)). - WithSince("v1.18.0"). - WithPresets(linter.PresetComplexity). - WithURL("https://github.com/ultraware/funlen"), - - linter.NewConfig(golinters.NewGci(gciCfg)). - WithSince("v1.30.0"). - WithPresets(linter.PresetFormatting, linter.PresetImport). - WithURL("https://github.com/daixiang0/gci"), - - linter.NewConfig(golinters.NewGinkgoLinter(ginkgolinterCfg)). - WithSince("v1.51.0"). - WithLoadForGoAnalysis(). - WithPresets(linter.PresetStyle). - WithURL("https://github.com/nunnatsa/ginkgolinter"), - - linter.NewConfig(golinters.NewGoCheckCompilerDirectives()). - WithSince("v1.51.0"). - WithPresets(linter.PresetBugs). - WithURL("https://github.com/leighmcculloch/gocheckcompilerdirectives"), - - linter.NewConfig(golinters.NewGochecknoglobals()). - WithSince("v1.12.0"). - WithPresets(linter.PresetStyle). - WithLoadForGoAnalysis(). - WithURL("https://github.com/leighmcculloch/gochecknoglobals"), - - linter.NewConfig(golinters.NewGochecknoinits()). - WithSince("v1.12.0"). - WithPresets(linter.PresetStyle), - - linter.NewConfig(golinters.NewGocognit(gocognitCfg)). - WithSince("v1.20.0"). - WithPresets(linter.PresetComplexity). - WithURL("https://github.com/uudashr/gocognit"), - - linter.NewConfig(golinters.NewGoconst(goconstCfg)). - WithSince("v1.0.0"). - WithPresets(linter.PresetStyle). - WithURL("https://github.com/jgautheron/goconst"), - - linter.NewConfig(golinters.NewGoCritic(gocriticCfg, m.cfg)). - WithSince("v1.12.0"). - WithPresets(linter.PresetStyle, linter.PresetMetaLinter). - WithLoadForGoAnalysis(). - WithURL("https://github.com/go-critic/go-critic"), - - linter.NewConfig(golinters.NewGocyclo(gocycloCfg)). - WithSince("v1.0.0"). - WithPresets(linter.PresetComplexity). - WithURL("https://github.com/fzipp/gocyclo"), - - linter.NewConfig(golinters.NewGodot(godotCfg)). - WithSince("v1.25.0"). - WithPresets(linter.PresetStyle, linter.PresetComment). - WithAutoFix(). - WithURL("https://github.com/tetafro/godot"), - - linter.NewConfig(golinters.NewGodox(godoxCfg)). - WithSince("v1.19.0"). - WithPresets(linter.PresetStyle, linter.PresetComment). - WithURL("https://github.com/matoous/godox"), - - linter.NewConfig(golinters.NewGoerr113()). - WithSince("v1.26.0"). - WithPresets(linter.PresetStyle, linter.PresetError). - WithLoadForGoAnalysis(). - WithURL("https://github.com/Djarvur/go-err113"), - - linter.NewConfig(golinters.NewGofmt(gofmtCfg)). - WithSince("v1.0.0"). - WithPresets(linter.PresetFormatting). - WithAutoFix(). - WithURL("https://pkg.go.dev/cmd/gofmt"), - - linter.NewConfig(golinters.NewGofumpt(gofumptCfg)). - WithSince("v1.28.0"). - WithPresets(linter.PresetFormatting). - WithAutoFix(). - WithURL("https://github.com/mvdan/gofumpt"), - - linter.NewConfig(golinters.NewGoHeader(goheaderCfg)). - WithSince("v1.28.0"). - WithPresets(linter.PresetStyle). - WithURL("https://github.com/denis-tingaikin/go-header"), - - linter.NewConfig(golinters.NewGoimports(goimportsCfg)). - WithSince("v1.20.0"). - WithPresets(linter.PresetFormatting, linter.PresetImport). - WithAutoFix(). - WithURL("https://pkg.go.dev/golang.org/x/tools/cmd/goimports"), - - linter.NewConfig(golinters.NewGolint(golintCfg)). - WithSince("v1.0.0"). - WithLoadForGoAnalysis(). - WithPresets(linter.PresetStyle). - WithURL("https://github.com/golang/lint"). - Deprecated("The repository of the linter has been archived by the owner.", "v1.41.0", "revive"), - - linter.NewConfig(golinters.NewGoMND(goMndCfg)). - WithSince("v1.22.0"). - WithPresets(linter.PresetStyle). - WithURL("https://github.com/tommy-muehle/go-mnd"), - - linter.NewConfig(golinters.NewGoModDirectives(goModDirectivesCfg)). - WithSince("v1.39.0"). - WithPresets(linter.PresetStyle, linter.PresetModule). - WithURL("https://github.com/ldez/gomoddirectives"), - - linter.NewConfig(golinters.NewGomodguard(gomodguardCfg)). - WithSince("v1.25.0"). - WithPresets(linter.PresetStyle, linter.PresetImport, linter.PresetModule). - WithURL("https://github.com/ryancurrah/gomodguard"), - - linter.NewConfig(golinters.NewGoPrintfFuncName()). - WithSince("v1.23.0"). - WithPresets(linter.PresetStyle). - WithURL("https://github.com/jirfag/go-printf-func-name"), - - linter.NewConfig(golinters.NewGosec(gosecCfg)). - WithSince("v1.0.0"). - WithLoadForGoAnalysis(). - WithPresets(linter.PresetBugs). - WithURL("https://github.com/securego/gosec"). - WithAlternativeNames("gas"), - - linter.NewConfig(golinters.NewGosimple(gosimpleCfg)). - WithSince("v1.20.0"). - WithLoadForGoAnalysis(). - WithPresets(linter.PresetStyle). - WithAlternativeNames(megacheckName). - WithURL("https://github.com/dominikh/go-tools/tree/master/simple"), - - linter.NewConfig(golinters.NewGovet(govetCfg)). - WithSince("v1.0.0"). - WithLoadForGoAnalysis(). - WithPresets(linter.PresetBugs, linter.PresetMetaLinter). - WithAlternativeNames("vet", "vetshadow"). - WithURL("https://pkg.go.dev/cmd/vet"), - - linter.NewConfig(golinters.NewGrouper(grouperCfg)). - WithSince("v1.44.0"). - WithPresets(linter.PresetStyle). - WithURL("https://github.com/leonklingele/grouper"), - - linter.NewConfig(golinters.NewIfshort(ifshortCfg)). - WithSince("v1.36.0"). - WithPresets(linter.PresetStyle). - WithURL("https://github.com/esimonov/ifshort"). - Deprecated("The repository of the linter has been deprecated by the owner.", "v1.48.0", ""), - - linter.NewConfig(golinters.NewImportAs(importAsCfg)). - WithSince("v1.38.0"). - WithPresets(linter.PresetStyle). - WithLoadForGoAnalysis(). - WithURL("https://github.com/julz/importas"), - - linter.NewConfig(golinters.NewIneffassign()). - WithSince("v1.0.0"). - WithPresets(linter.PresetUnused). - WithURL("https://github.com/gordonklaus/ineffassign"), - - linter.NewConfig(golinters.NewInterfaceBloat(interfaceBloatCfg)). - WithSince("v1.49.0"). - WithPresets(linter.PresetStyle). - WithURL("https://github.com/sashamelentyev/interfacebloat"), - - linter.NewConfig(golinters.NewInterfacer()). - WithSince("v1.0.0"). - WithLoadForGoAnalysis(). - WithPresets(linter.PresetStyle). - WithURL("https://github.com/mvdan/interfacer"). - Deprecated("The repository of the linter has been archived by the owner.", "v1.38.0", ""), - - linter.NewConfig(golinters.NewIreturn(ireturnCfg)). - WithSince("v1.43.0"). - WithPresets(linter.PresetStyle). - WithLoadForGoAnalysis(). - WithURL("https://github.com/butuzov/ireturn"), - - linter.NewConfig(golinters.NewLLL(lllCfg)). - WithSince("v1.8.0"). - WithPresets(linter.PresetStyle), - - linter.NewConfig(golinters.NewLoggerCheck(loggerCheckCfg)). - WithSince("v1.49.0"). - WithLoadForGoAnalysis(). - WithPresets(linter.PresetStyle, linter.PresetBugs). - WithAlternativeNames("logrlint"). - WithURL("https://github.com/timonwong/loggercheck"), - - linter.NewConfig(golinters.NewMaintIdx(maintIdxCfg)). - WithSince("v1.44.0"). - WithPresets(linter.PresetComplexity). - WithURL("https://github.com/yagipy/maintidx"), - - linter.NewConfig(golinters.NewMakezero(makezeroCfg)). - WithSince("v1.34.0"). - WithPresets(linter.PresetStyle, linter.PresetBugs). - WithLoadForGoAnalysis(). - WithURL("https://github.com/ashanbrown/makezero"), - - linter.NewConfig(golinters.NewMaligned(malignedCfg)). - WithSince("v1.0.0"). - WithLoadForGoAnalysis(). - WithPresets(linter.PresetPerformance). - WithURL("https://github.com/mdempsky/maligned"). - Deprecated("The repository of the linter has been archived by the owner.", "v1.38.0", "govet 'fieldalignment'"), - - linter.NewConfig(golinters.NewMisspell(misspellCfg)). - WithSince("v1.8.0"). - WithPresets(linter.PresetStyle, linter.PresetComment). - WithAutoFix(). - WithURL("https://github.com/client9/misspell"), - - linter.NewConfig(golinters.NewMustTag(musttagCfg)). - WithSince("v1.51.0"). - WithLoadForGoAnalysis(). - WithPresets(linter.PresetStyle, linter.PresetBugs). - WithURL("https://github.com/junk1tm/musttag"), - - linter.NewConfig(golinters.NewNakedret(nakedretCfg)). - WithSince("v1.19.0"). - WithPresets(linter.PresetStyle). - WithURL("https://github.com/alexkohler/nakedret"), - - linter.NewConfig(golinters.NewNestif(nestifCfg)). - WithSince("v1.25.0"). - WithPresets(linter.PresetComplexity). - WithURL("https://github.com/nakabonne/nestif"), - - linter.NewConfig(golinters.NewNilErr()). - WithSince("v1.38.0"). - WithLoadForGoAnalysis(). - WithPresets(linter.PresetBugs). - WithURL("https://github.com/gostaticanalysis/nilerr"), - - linter.NewConfig(golinters.NewNilNil(nilNilCfg)). - WithSince("v1.43.0"). - WithPresets(linter.PresetStyle). - WithLoadForGoAnalysis(). - WithURL("https://github.com/Antonboom/nilnil"), - - linter.NewConfig(golinters.NewNLReturn(nlreturnCfg)). - WithSince("v1.30.0"). - WithPresets(linter.PresetStyle). - WithURL("https://github.com/ssgreg/nlreturn"), - - linter.NewConfig(golinters.NewNoctx()). - WithSince("v1.28.0"). - WithLoadForGoAnalysis(). - WithPresets(linter.PresetPerformance, linter.PresetBugs). - WithURL("https://github.com/sonatard/noctx"), - - linter.NewConfig(golinters.NewNoNamedReturns(noNamedReturnsCfg)). - WithSince("v1.46.0"). - WithLoadForGoAnalysis(). - WithPresets(linter.PresetStyle). - WithURL("https://github.com/firefart/nonamedreturns"), - - linter.NewConfig(golinters.NewNoSnakeCase()). - WithSince("v1.47.0"). - WithPresets(linter.PresetStyle). - WithURL("https://github.com/sivchari/nosnakecase"). - Deprecated("The repository of the linter has been deprecated by the owner.", "v1.48.1", "revive(var-naming)"), - - linter.NewConfig(golinters.NewNoSprintfHostPort()). - WithSince("v1.46.0"). - WithPresets(linter.PresetStyle). - WithURL("https://github.com/stbenjam/no-sprintf-host-port"), - - linter.NewConfig(golinters.NewParallelTest(parallelTestCfg)). - WithSince("v1.33.0"). - WithLoadForGoAnalysis(). - WithPresets(linter.PresetStyle, linter.PresetTest). - WithURL("https://github.com/kunwardeep/paralleltest"), - - linter.NewConfig(golinters.NewPreAlloc(preallocCfg)). - WithSince("v1.19.0"). - WithPresets(linter.PresetPerformance). - WithURL("https://github.com/alexkohler/prealloc"), - - linter.NewConfig(golinters.NewPredeclared(predeclaredCfg)). - WithSince("v1.35.0"). - WithPresets(linter.PresetStyle). - WithURL("https://github.com/nishanths/predeclared"), - - linter.NewConfig(golinters.NewPromlinter(promlinterCfg)). - WithSince("v1.40.0"). - WithPresets(linter.PresetStyle). - WithURL("https://github.com/yeya24/promlinter"), - - linter.NewConfig(golinters.NewReassign(reassignCfg)). - WithSince("1.49.0"). - WithPresets(linter.PresetBugs). - WithLoadForGoAnalysis(). - WithURL("https://github.com/curioswitch/go-reassign"), - - linter.NewConfig(golinters.NewRevive(reviveCfg)). - WithSince("v1.37.0"). - WithPresets(linter.PresetStyle, linter.PresetMetaLinter). - ConsiderSlow(). - WithURL("https://github.com/mgechev/revive"), - - linter.NewConfig(golinters.NewRowsErrCheck(rowserrcheckCfg)). - WithSince("v1.23.0"). - WithLoadForGoAnalysis(). - WithPresets(linter.PresetBugs, linter.PresetSQL). - WithURL("https://github.com/jingyugao/rowserrcheck"). - WithNoopFallback(m.cfg), - - linter.NewConfig(golinters.NewScopelint()). - WithSince("v1.12.0"). - WithPresets(linter.PresetBugs). - WithURL("https://github.com/kyoh86/scopelint"). - Deprecated("The repository of the linter has been deprecated by the owner.", "v1.39.0", "exportloopref"), - - linter.NewConfig(golinters.NewSQLCloseCheck()). - WithSince("v1.28.0"). - WithPresets(linter.PresetBugs, linter.PresetSQL). - WithLoadForGoAnalysis(). - WithURL("https://github.com/ryanrolds/sqlclosecheck"), - - linter.NewConfig(golinters.NewStaticcheck(staticcheckCfg)). - WithSince("v1.0.0"). - WithLoadForGoAnalysis(). - WithPresets(linter.PresetBugs, linter.PresetMetaLinter). - WithAlternativeNames(megacheckName). - WithURL("https://staticcheck.io/"), - - linter.NewConfig(golinters.NewStructcheck(structcheckCfg)). - WithSince("v1.0.0"). - WithLoadForGoAnalysis(). - WithPresets(linter.PresetUnused). - WithURL("https://github.com/opennota/check"). - Deprecated("The owner seems to have abandoned the linter.", "v1.49.0", "unused"). - WithNoopFallback(m.cfg), - - linter.NewConfig(golinters.NewStylecheck(stylecheckCfg)). - WithSince("v1.20.0"). - WithLoadForGoAnalysis(). - WithPresets(linter.PresetStyle). - WithURL("https://github.com/dominikh/go-tools/tree/master/stylecheck"), - - linter.NewConfig(golinters.NewTagliatelle(tagliatelleCfg)). - WithSince("v1.40.0"). - WithPresets(linter.PresetStyle). - WithURL("https://github.com/ldez/tagliatelle"), - - linter.NewConfig(golinters.NewTenv(tenvCfg)). - WithSince("v1.43.0"). - WithPresets(linter.PresetStyle). - WithLoadForGoAnalysis(). - WithURL("https://github.com/sivchari/tenv"), - - linter.NewConfig(golinters.NewTestableexamples()). - WithSince("v1.50.0"). - WithPresets(linter.PresetTest). - WithURL("https://github.com/maratori/testableexamples"), - - linter.NewConfig(golinters.NewTestpackage(testpackageCfg)). - WithSince("v1.25.0"). - WithPresets(linter.PresetStyle, linter.PresetTest). - WithURL("https://github.com/maratori/testpackage"), - - linter.NewConfig(golinters.NewThelper(thelperCfg)). - WithSince("v1.34.0"). - WithPresets(linter.PresetStyle). - WithLoadForGoAnalysis(). - WithURL("https://github.com/kulti/thelper"), - - linter.NewConfig(golinters.NewTparallel()). - WithSince("v1.32.0"). - WithPresets(linter.PresetStyle, linter.PresetTest). - WithLoadForGoAnalysis(). - WithURL("https://github.com/moricho/tparallel"), - - linter.NewConfig(golinters.NewTypecheck()). - WithSince("v1.3.0"). - WithLoadForGoAnalysis(). - WithPresets(linter.PresetBugs). - WithURL(""), - - linter.NewConfig(golinters.NewUnconvert()). - WithSince("v1.0.0"). - WithLoadForGoAnalysis(). - WithPresets(linter.PresetStyle). - WithURL("https://github.com/mdempsky/unconvert"), - - linter.NewConfig(golinters.NewUnparam(unparamCfg)). - WithSince("v1.9.0"). - WithPresets(linter.PresetUnused). - WithLoadForGoAnalysis(). - WithURL("https://github.com/mvdan/unparam"), - - linter.NewConfig(golinters.NewUnused(unusedCfg)). - WithSince("v1.20.0"). - WithLoadForGoAnalysis(). - WithPresets(linter.PresetUnused). - WithAlternativeNames(megacheckName). - ConsiderSlow(). - WithChangeTypes(). - WithURL("https://github.com/dominikh/go-tools/tree/master/unused"), - - linter.NewConfig(golinters.NewUseStdlibVars(usestdlibvars)). - WithSince("v1.48.0"). - WithPresets(linter.PresetStyle). - WithURL("https://github.com/sashamelentyev/usestdlibvars"), - - linter.NewConfig(golinters.NewVarcheck(varcheckCfg)). - WithSince("v1.0.0"). - WithLoadForGoAnalysis(). - WithPresets(linter.PresetUnused). - WithURL("https://github.com/opennota/check"). - Deprecated("The owner seems to have abandoned the linter.", "v1.49.0", "unused"), - - linter.NewConfig(golinters.NewVarnamelen(varnamelenCfg)). - WithSince("v1.43.0"). - WithPresets(linter.PresetStyle). - WithLoadForGoAnalysis(). - WithURL("https://github.com/blizzy78/varnamelen"), - - linter.NewConfig(golinters.NewWastedAssign()). - WithSince("v1.38.0"). - WithPresets(linter.PresetStyle). - WithLoadForGoAnalysis(). - WithURL("https://github.com/sanposhiho/wastedassign"). - WithNoopFallback(m.cfg), - - linter.NewConfig(golinters.NewWhitespace(whitespaceCfg)). - WithSince("v1.19.0"). - WithPresets(linter.PresetStyle). - WithAutoFix(). - WithURL("https://github.com/ultraware/whitespace"), - - linter.NewConfig(golinters.NewWrapcheck(wrapcheckCfg)). - WithSince("v1.32.0"). - WithPresets(linter.PresetStyle, linter.PresetError). - WithLoadForGoAnalysis(). - WithURL("https://github.com/tomarrell/wrapcheck"), - - linter.NewConfig(golinters.NewWSL(wslCfg)). - WithSince("v1.20.0"). - WithPresets(linter.PresetStyle). - WithURL("https://github.com/bombsimon/wsl"), - - // nolintlint must be last because it looks at the results of all the previous linters for unused nolint directives - linter.NewConfig(golinters.NewNoLintLint(noLintLintCfg)). - WithSince("v1.26.0"). - WithPresets(linter.PresetStyle). - WithURL("https://github.com/golangci/golangci-lint/blob/master/pkg/golinters/nolintlint/README.md"), - } + if a.Name() == linter.LastLinter { + return false + } - enabledByDefault := map[string]bool{ - golinters.NewGovet(nil).Name(): true, - golinters.NewErrcheck(errcheckCfg).Name(): true, - golinters.NewStaticcheck(staticcheckCfg).Name(): true, - golinters.NewUnused(unusedCfg).Name(): true, - golinters.NewGosimple(gosimpleCfg).Name(): true, - golinters.NewIneffassign().Name(): true, - golinters.NewTypecheck().Name(): true, - } - return enableLinterConfigs(lcs, func(lc *linter.Config) bool { - return enabledByDefault[lc.Name()] + if a.DoesChangeTypes != b.DoesChangeTypes { + return b.DoesChangeTypes // move type-changing linters to the end to optimize speed + } + return a.Name() < b.Name() }) + + return resultLinters, nil } -func (m Manager) GetAllEnabledByDefaultLinters() []*linter.Config { +func (m *Manager) GetAllEnabledByDefaultLinters() []*linter.Config { var ret []*linter.Config - for _, lc := range m.GetAllSupportedLinterConfigs() { + for _, lc := range m.linters { if lc.EnabledByDefault { ret = append(ret, lc) } @@ -902,88 +146,168 @@ func (m Manager) GetAllEnabledByDefaultLinters() []*linter.Config { return ret } -func linterConfigsToMap(lcs []*linter.Config) map[string]*linter.Config { - ret := map[string]*linter.Config{} - for _, lc := range lcs { - lc := lc // local copy - ret[lc.Name()] = lc +//nolint:gocyclo // the complexity cannot be reduced. +func (m *Manager) build(enabledByDefaultLinters []*linter.Config) map[string]*linter.Config { + m.debugf("Linters config: %#v", m.cfg.Linters) + + resultLintersSet := map[string]*linter.Config{} + switch { + case m.cfg.Linters.DisableAll: + // no default linters + case len(m.cfg.Linters.Presets) != 0: + // imply --disable-all + case m.cfg.Linters.EnableAll: + resultLintersSet = linterConfigsToMap(m.linters) + default: + resultLintersSet = linterConfigsToMap(enabledByDefaultLinters) } - return ret -} - -func (m Manager) GetAllLinterConfigsForPreset(p string) []*linter.Config { - var ret []*linter.Config - for _, lc := range m.GetAllSupportedLinterConfigs() { - if lc.IsDeprecated() { - continue + // --presets can only add linters to default set + for _, p := range m.cfg.Linters.Presets { + for _, lc := range m.GetAllLinterConfigsForPreset(p) { + lc := lc + resultLintersSet[lc.Name()] = lc } + } - for _, ip := range lc.InPresets { - if p == ip { - ret = append(ret, lc) - break + // --fast removes slow linters from current set. + // It should be after --presets to be able to run only fast linters in preset. + // It should be before --enable and --disable to be able to enable or disable specific linter. + if m.cfg.Linters.Fast { + for name, lc := range resultLintersSet { + if lc.IsSlowLinter() { + delete(resultLintersSet, name) } } } - return ret -} + for _, name := range m.cfg.Linters.Enable { + for _, lc := range m.GetLinterConfigs(name) { + // it's important to use lc.Name() nor name because name can be alias + resultLintersSet[lc.Name()] = lc + } + } -// loadCustomLinterConfig loads the configuration of private linters. -// Private linters are dynamically loaded from .so plugin files. -func (m Manager) loadCustomLinterConfig(name string, settings config.CustomLinterSettings) (*linter.Config, error) { - analyzer, err := m.getAnalyzerPlugin(settings.Path) - if err != nil { - return nil, err + for _, name := range m.cfg.Linters.Disable { + for _, lc := range m.GetLinterConfigs(name) { + // it's important to use lc.Name() nor name because name can be alias + delete(resultLintersSet, lc.Name()) + } + } + + // typecheck is not a real linter and cannot be disabled. + if _, ok := resultLintersSet["typecheck"]; !ok && (m.cfg == nil || !m.cfg.InternalCmdTest) { + for _, lc := range m.GetLinterConfigs("typecheck") { + // it's important to use lc.Name() nor name because name can be alias + resultLintersSet[lc.Name()] = lc + } } - m.log.Infof("Loaded %s: %s", settings.Path, name) - customLinter := goanalysis.NewLinter( - name, - settings.Description, - analyzer.GetAnalyzers(), - nil).WithLoadMode(goanalysis.LoadModeTypesInfo) - linterConfig := linter.NewConfig(customLinter) - linterConfig.EnabledByDefault = true - linterConfig.IsSlow = false - linterConfig.WithURL(settings.OriginalURL) - return linterConfig, nil + + return resultLintersSet } -type AnalyzerPlugin interface { - GetAnalyzers() []*analysis.Analyzer +func (m *Manager) combineGoAnalysisLinters(linters map[string]*linter.Config) { + var goanalysisLinters []*goanalysis.Linter + goanalysisPresets := map[string]bool{} + for _, lc := range linters { + lnt, ok := lc.Linter.(*goanalysis.Linter) + if !ok { + continue + } + if lnt.LoadMode() == goanalysis.LoadModeWholeProgram { + // It's ineffective by CPU and memory to run whole-program and incremental analyzers at once. + continue + } + goanalysisLinters = append(goanalysisLinters, lnt) + for _, p := range lc.InPresets { + goanalysisPresets[p] = true + } + } + + if len(goanalysisLinters) <= 1 { + m.debugf("Didn't combine go/analysis linters: got only %d linters", len(goanalysisLinters)) + return + } + + for _, lnt := range goanalysisLinters { + delete(linters, lnt.Name()) + } + + // Make order of execution of go/analysis analyzers stable. + sort.Slice(goanalysisLinters, func(i, j int) bool { + a, b := goanalysisLinters[i], goanalysisLinters[j] + + if b.Name() == linter.LastLinter { + return true + } + + if a.Name() == linter.LastLinter { + return false + } + + return a.Name() <= b.Name() + }) + + ml := goanalysis.NewMetaLinter(goanalysisLinters) + + presets := maps.Keys(goanalysisPresets) + sort.Strings(presets) + + mlConfig := &linter.Config{ + Linter: ml, + EnabledByDefault: false, + InPresets: presets, + AlternativeNames: nil, + OriginalURL: "", + } + + mlConfig = mlConfig.WithLoadForGoAnalysis() + + linters[ml.Name()] = mlConfig + m.debugf("Combined %d go/analysis linters into one metalinter", len(goanalysisLinters)) } -// getAnalyzerPlugin loads a private linter as specified in the config file, -// loads the plugin from a .so file, and returns the 'AnalyzerPlugin' interface -// implemented by the private plugin. -// An error is returned if the private linter cannot be loaded or the linter -// does not implement the AnalyzerPlugin interface. -func (m Manager) getAnalyzerPlugin(path string) (AnalyzerPlugin, error) { - if !filepath.IsAbs(path) { - // resolve non-absolute paths relative to config file's directory - configFilePath := viper.ConfigFileUsed() - absConfigFilePath, err := filepath.Abs(configFilePath) - if err != nil { - return nil, fmt.Errorf("could not get absolute representation of config file path %q: %v", configFilePath, err) +func (m *Manager) verbosePrintLintersStatus(lcs map[string]*linter.Config) { + var linterNames []string + for _, lc := range lcs { + if lc.Internal { + continue } - path = filepath.Join(filepath.Dir(absConfigFilePath), path) + + linterNames = append(linterNames, lc.Name()) } + sort.Strings(linterNames) + m.log.Infof("Active %d linters: %s", len(linterNames), linterNames) - plug, err := plugin.Open(path) - if err != nil { - return nil, err + if len(m.cfg.Linters.Presets) != 0 { + sort.Strings(m.cfg.Linters.Presets) + m.log.Infof("Active presets: %s", m.cfg.Linters.Presets) } +} - symbol, err := plug.Lookup("AnalyzerPlugin") - if err != nil { - return nil, err +func AllPresets() []string { + return []string{ + linter.PresetBugs, + linter.PresetComment, + linter.PresetComplexity, + linter.PresetError, + linter.PresetFormatting, + linter.PresetImport, + linter.PresetMetaLinter, + linter.PresetModule, + linter.PresetPerformance, + linter.PresetSQL, + linter.PresetStyle, + linter.PresetTest, + linter.PresetUnused, } +} - analyzerPlugin, ok := symbol.(AnalyzerPlugin) - if !ok { - return nil, fmt.Errorf("plugin %s does not abide by 'AnalyzerPlugin' interface", path) +func linterConfigsToMap(lcs []*linter.Config) map[string]*linter.Config { + ret := map[string]*linter.Config{} + for _, lc := range lcs { + ret[lc.Name()] = lc } - return analyzerPlugin, nil + return ret } diff --git a/pkg/lint/lintersdb/manager_test.go b/pkg/lint/lintersdb/manager_test.go new file mode 100644 index 000000000000..87fffa82f9cf --- /dev/null +++ b/pkg/lint/lintersdb/manager_test.go @@ -0,0 +1,237 @@ +package lintersdb + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/logutils" +) + +func TestManager_GetEnabledLintersMap(t *testing.T) { + cfg := config.NewDefault() + cfg.Linters.DisableAll = true + cfg.Linters.Enable = []string{"gofmt"} + + m, err := NewManager(logutils.NewStderrLog("skip"), cfg, NewLinterBuilder()) + require.NoError(t, err) + + lintersMap, err := m.GetEnabledLintersMap() + require.NoError(t, err) + + gofmtConfigs := m.GetLinterConfigs("gofmt") + typecheckConfigs := m.GetLinterConfigs("typecheck") + + expected := map[string]*linter.Config{ + "gofmt": gofmtConfigs[0], + "typecheck": typecheckConfigs[0], + } + + assert.Equal(t, expected, lintersMap) +} + +func TestManager_GetOptimizedLinters(t *testing.T) { + cfg := config.NewDefault() + cfg.Linters.DisableAll = true + cfg.Linters.Enable = []string{"gofmt"} + + m, err := NewManager(logutils.NewStderrLog("skip"), cfg, NewLinterBuilder()) + require.NoError(t, err) + + optimizedLinters, err := m.GetOptimizedLinters() + require.NoError(t, err) + + var gaLinters []*goanalysis.Linter + for _, l := range m.GetLinterConfigs("gofmt") { + gaLinters = append(gaLinters, l.Linter.(*goanalysis.Linter)) + } + for _, l := range m.GetLinterConfigs("typecheck") { + gaLinters = append(gaLinters, l.Linter.(*goanalysis.Linter)) + } + + mlConfig := &linter.Config{ + Linter: goanalysis.NewMetaLinter(gaLinters), + InPresets: []string{"bugs", "format"}, + } + + expected := []*linter.Config{mlConfig.WithLoadForGoAnalysis()} + + assert.Equal(t, expected, optimizedLinters) +} + +func TestManager_build(t *testing.T) { + type cs struct { + cfg config.Linters + name string // test case name + def []string // enabled by default linters + exp []string // alphabetically ordered enabled linter names + } + + allMegacheckLinterNames := []string{"gosimple", "staticcheck", "unused"} + + cases := []cs{ + { + cfg: config.Linters{ + Disable: []string{"megacheck"}, + }, + name: "disable all linters from megacheck", + def: allMegacheckLinterNames, + exp: []string{"typecheck"}, // all disabled + }, + { + cfg: config.Linters{ + Disable: []string{"staticcheck"}, + }, + name: "disable only staticcheck", + def: allMegacheckLinterNames, + exp: []string{"gosimple", "typecheck", "unused"}, + }, + { + name: "don't merge into megacheck", + def: allMegacheckLinterNames, + exp: []string{"gosimple", "staticcheck", "typecheck", "unused"}, + }, + { + name: "expand megacheck", + cfg: config.Linters{ + Enable: []string{"megacheck"}, + }, + def: nil, + exp: []string{"gosimple", "staticcheck", "typecheck", "unused"}, + }, + { + name: "don't disable anything", + def: []string{"gofmt", "govet", "typecheck"}, + exp: []string{"gofmt", "govet", "typecheck"}, + }, + { + name: "enable gosec by gas alias", + cfg: config.Linters{ + Enable: []string{"gas"}, + }, + exp: []string{"gosec", "typecheck"}, + }, + { + name: "enable gosec by primary name", + cfg: config.Linters{ + Enable: []string{"gosec"}, + }, + exp: []string{"gosec", "typecheck"}, + }, + { + name: "enable gosec by both names", + cfg: config.Linters{ + Enable: []string{"gosec", "gas"}, + }, + exp: []string{"gosec", "typecheck"}, + }, + { + name: "disable gosec by gas alias", + cfg: config.Linters{ + Disable: []string{"gas"}, + }, + def: []string{"gosec"}, + exp: []string{"typecheck"}, + }, + { + name: "disable gosec by primary name", + cfg: config.Linters{ + Disable: []string{"gosec"}, + }, + def: []string{"gosec"}, + exp: []string{"typecheck"}, + }, + } + + for _, c := range cases { + c := c + t.Run(c.name, func(t *testing.T) { + m, err := NewManager(logutils.NewStderrLog("skip"), &config.Config{Linters: c.cfg}, NewLinterBuilder()) + require.NoError(t, err) + + var defaultLinters []*linter.Config + for _, ln := range c.def { + lcs := m.GetLinterConfigs(ln) + assert.NotNil(t, lcs, ln) + defaultLinters = append(defaultLinters, lcs...) + } + + els := m.build(defaultLinters) + var enabledLinters []string + for ln, lc := range els { + assert.Equal(t, ln, lc.Name()) + enabledLinters = append(enabledLinters, ln) + } + + assert.ElementsMatch(t, c.exp, enabledLinters) + }) + } +} + +func TestManager_combineGoAnalysisLinters(t *testing.T) { + m, err := NewManager(nil, nil) + require.NoError(t, err) + + foo := goanalysis.NewLinter("foo", "example foo", nil, nil).WithLoadMode(goanalysis.LoadModeTypesInfo) + bar := goanalysis.NewLinter("bar", "example bar", nil, nil).WithLoadMode(goanalysis.LoadModeTypesInfo) + + testCases := []struct { + desc string + linters map[string]*linter.Config + expected map[string]*linter.Config + }{ + { + desc: "no combined, one linter", + linters: map[string]*linter.Config{ + "foo": { + Linter: foo, + InPresets: []string{"A"}, + }, + }, + expected: map[string]*linter.Config{ + "foo": { + Linter: foo, + InPresets: []string{"A"}, + }, + }, + }, + { + desc: "combined, several linters", + linters: map[string]*linter.Config{ + "foo": { + Linter: foo, + InPresets: []string{"A"}, + }, + "bar": { + Linter: bar, + InPresets: []string{"B"}, + }, + }, + expected: func() map[string]*linter.Config { + mlConfig := &linter.Config{ + Linter: goanalysis.NewMetaLinter([]*goanalysis.Linter{bar, foo}), + InPresets: []string{"A", "B"}, + } + + return map[string]*linter.Config{ + "goanalysis_metalinter": mlConfig.WithLoadForGoAnalysis(), + } + }(), + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + m.combineGoAnalysisLinters(test.linters) + + assert.Equal(t, test.expected, test.linters) + }) + } +} diff --git a/pkg/lint/lintersdb/validator.go b/pkg/lint/lintersdb/validator.go index 52a70d85900d..364d5082a5e6 100644 --- a/pkg/lint/lintersdb/validator.go +++ b/pkg/lint/lintersdb/validator.go @@ -3,6 +3,7 @@ package lintersdb import ( "errors" "fmt" + "slices" "strings" "github.com/golangci/golangci-lint/pkg/config" @@ -13,9 +14,29 @@ type Validator struct { } func NewValidator(m *Manager) *Validator { - return &Validator{ - m: m, + return &Validator{m: m} +} + +// Validate validates the configuration by calling all other validators for different +// sections in the configuration and then some additional linter validation functions. +func (v Validator) Validate(cfg *config.Config) error { + err := cfg.Validate() + if err != nil { + return err + } + + validators := []func(cfg *config.Linters) error{ + v.validateLintersNames, + v.validatePresets, + } + + for _, v := range validators { + if err := v(&cfg.Linters); err != nil { + return err + } } + + return nil } func (v Validator) validateLintersNames(cfg *config.Linters) error { @@ -39,11 +60,12 @@ func (v Validator) validateLintersNames(cfg *config.Linters) error { } func (v Validator) validatePresets(cfg *config.Linters) error { - allPresets := v.m.allPresetsSet() + presets := AllPresets() + for _, p := range cfg.Presets { - if !allPresets[p] { + if !slices.Contains(presets, p) { return fmt.Errorf("no such preset %q: only next presets exist: (%s)", - p, strings.Join(v.m.AllPresets(), "|")) + p, strings.Join(presets, "|")) } } @@ -53,56 +75,3 @@ func (v Validator) validatePresets(cfg *config.Linters) error { return nil } - -func (v Validator) validateAllDisableEnableOptions(cfg *config.Linters) error { - if cfg.EnableAll && cfg.DisableAll { - return errors.New("--enable-all and --disable-all options must not be combined") - } - - if cfg.DisableAll { - if len(cfg.Enable) == 0 && len(cfg.Presets) == 0 { - return errors.New("all linters were disabled, but no one linter was enabled: must enable at least one") - } - - if len(cfg.Disable) != 0 { - return fmt.Errorf("can't combine options --disable-all and --disable %s", cfg.Disable[0]) - } - } - - if cfg.EnableAll && len(cfg.Enable) != 0 && !cfg.Fast { - return fmt.Errorf("can't combine options --enable-all and --enable %s", cfg.Enable[0]) - } - - return nil -} - -func (v Validator) validateDisabledAndEnabledAtOneMoment(cfg *config.Linters) error { - enabledLintersSet := map[string]bool{} - for _, name := range cfg.Enable { - enabledLintersSet[name] = true - } - - for _, name := range cfg.Disable { - if enabledLintersSet[name] { - return fmt.Errorf("linter %q can't be disabled and enabled at one moment", name) - } - } - - return nil -} - -func (v Validator) validateEnabledDisabledLintersConfig(cfg *config.Linters) error { - validators := []func(cfg *config.Linters) error{ - v.validateLintersNames, - v.validatePresets, - v.validateAllDisableEnableOptions, - v.validateDisabledAndEnabledAtOneMoment, - } - for _, v := range validators { - if err := v(cfg); err != nil { - return err - } - } - - return nil -} diff --git a/pkg/lint/lintersdb/validator_test.go b/pkg/lint/lintersdb/validator_test.go new file mode 100644 index 000000000000..1bfeb7078cb0 --- /dev/null +++ b/pkg/lint/lintersdb/validator_test.go @@ -0,0 +1,217 @@ +package lintersdb + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/golangci/golangci-lint/pkg/config" +) + +type validateErrorTestCase struct { + desc string + cfg *config.Linters + expected string +} + +var validateLintersNamesErrorTestCases = []validateErrorTestCase{ + { + desc: "unknown enabled linter", + cfg: &config.Linters{ + Enable: []string{"golangci"}, + Disable: nil, + }, + expected: `unknown linters: 'golangci', run 'golangci-lint help linters' to see the list of supported linters`, + }, + { + desc: "unknown disabled linter", + cfg: &config.Linters{ + Enable: nil, + Disable: []string{"golangci"}, + }, + expected: `unknown linters: 'golangci', run 'golangci-lint help linters' to see the list of supported linters`, + }, +} + +var validatePresetsErrorTestCases = []validateErrorTestCase{ + { + desc: "unknown preset", + cfg: &config.Linters{ + EnableAll: false, + Presets: []string{"golangci"}, + }, + expected: "no such preset \"golangci\": only next presets exist: " + + "(bugs|comment|complexity|error|format|import|metalinter|module|performance|sql|style|test|unused)", + }, + { + desc: "presets and enable-all", + cfg: &config.Linters{ + EnableAll: true, + Presets: []string{"bugs"}, + }, + expected: `--presets is incompatible with --enable-all`, + }, +} + +type validatorTestCase struct { + desc string + cfg *config.Linters +} + +var validateLintersNamesTestCases = []validatorTestCase{ + { + desc: "no enable no disable", + cfg: &config.Linters{ + Enable: nil, + Disable: nil, + }, + }, + { + desc: "existing enabled linter", + cfg: &config.Linters{ + Enable: []string{"gofmt"}, + Disable: nil, + }, + }, + { + desc: "existing disabled linter", + cfg: &config.Linters{ + Enable: nil, + Disable: []string{"gofmt"}, + }, + }, +} + +var validatePresetsTestCases = []validatorTestCase{ + { + desc: "known preset", + cfg: &config.Linters{ + EnableAll: false, + Presets: []string{"bugs"}, + }, + }, + { + desc: "enable-all and no presets", + cfg: &config.Linters{ + EnableAll: true, + Presets: nil, + }, + }, + { + desc: "no presets", + cfg: &config.Linters{ + EnableAll: false, + Presets: nil, + }, + }, +} + +func TestValidator_Validate(t *testing.T) { + m, err := NewManager(nil, nil, NewLinterBuilder()) + require.NoError(t, err) + + v := NewValidator(m) + + var testCases []validatorTestCase + testCases = append(testCases, validateLintersNamesTestCases...) + testCases = append(testCases, validatePresetsTestCases...) + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + err := v.Validate(&config.Config{Linters: *test.cfg}) + require.NoError(t, err) + }) + } +} + +func TestValidator_Validate_error(t *testing.T) { + m, err := NewManager(nil, nil, NewLinterBuilder()) + require.NoError(t, err) + + v := NewValidator(m) + + var testCases []validateErrorTestCase + testCases = append(testCases, validateLintersNamesErrorTestCases...) + testCases = append(testCases, validatePresetsErrorTestCases...) + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + err := v.Validate(&config.Config{Linters: *test.cfg}) + require.Error(t, err) + + require.EqualError(t, err, test.expected) + }) + } +} + +func TestValidator_validateLintersNames(t *testing.T) { + m, err := NewManager(nil, nil, NewLinterBuilder()) + require.NoError(t, err) + + v := NewValidator(m) + + for _, test := range validateLintersNamesTestCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + err := v.validateLintersNames(test.cfg) + require.NoError(t, err) + }) + } +} + +func TestValidator_validateLintersNames_error(t *testing.T) { + m, err := NewManager(nil, nil, NewLinterBuilder()) + require.NoError(t, err) + + v := NewValidator(m) + + for _, test := range validateLintersNamesErrorTestCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + err := v.validateLintersNames(test.cfg) + require.Error(t, err) + + require.EqualError(t, err, test.expected) + }) + } +} + +func TestValidator_validatePresets(t *testing.T) { + v := NewValidator(nil) + + for _, test := range validatePresetsTestCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + err := v.validatePresets(test.cfg) + require.NoError(t, err) + }) + } +} + +func TestValidator_validatePresets_error(t *testing.T) { + v := NewValidator(nil) + + for _, test := range validatePresetsErrorTestCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + err := v.validatePresets(test.cfg) + require.Error(t, err) + + require.EqualError(t, err, test.expected) + }) + } +} diff --git a/pkg/lint/load.go b/pkg/lint/load.go index c4e1e17659c1..ffc0ac5d45a8 100644 --- a/pkg/lint/load.go +++ b/pkg/lint/load.go @@ -11,7 +11,6 @@ import ( "strings" "time" - "github.com/pkg/errors" "golang.org/x/tools/go/packages" "github.com/golangci/golangci-lint/internal/pkgcache" @@ -37,7 +36,8 @@ type ContextLoader struct { } func NewContextLoader(cfg *config.Config, log logutils.Log, goenv *goutil.Env, - lineCache *fsutils.LineCache, fileCache *fsutils.FileCache, pkgCache *pkgcache.Cache, loadGuard *load.Guard) *ContextLoader { + lineCache *fsutils.LineCache, fileCache *fsutils.FileCache, pkgCache *pkgcache.Cache, loadGuard *load.Guard, +) *ContextLoader { return &ContextLoader{ cfg: cfg, log: log, @@ -51,6 +51,37 @@ func NewContextLoader(cfg *config.Config, log logutils.Log, goenv *goutil.Env, } } +func (cl *ContextLoader) Load(ctx context.Context, log logutils.Log, linters []*linter.Config) (*linter.Context, error) { + loadMode := cl.findLoadMode(linters) + pkgs, err := cl.loadPackages(ctx, loadMode) + if err != nil { + return nil, fmt.Errorf("failed to load packages: %w", err) + } + + deduplicatedPkgs := cl.filterDuplicatePackages(pkgs) + + if len(deduplicatedPkgs) == 0 { + return nil, exitcodes.ErrNoGoFiles + } + + ret := &linter.Context{ + Packages: deduplicatedPkgs, + + // At least `unused` linters works properly only on original (not deduplicated) packages, + // see https://github.com/golangci/golangci-lint/pull/585. + OriginalPackages: pkgs, + + Cfg: cl.cfg, + Log: log, + FileCache: cl.fileCache, + LineCache: cl.lineCache, + PkgCache: cl.pkgCache, + LoadGuard: cl.loadGuard, + } + + return ret, nil +} + func (cl *ContextLoader) prepareBuildContext() { // Set GOROOT to have working cross-compilation: cross-compiled binaries // have invalid GOROOT. XXX: can't use runtime.GOROOT(). @@ -172,11 +203,11 @@ func (cl *ContextLoader) parseLoadedPackagesErrors(pkgs []*packages.Package) err errs = append(errs, err) if strings.Contains(err.Msg, "no Go files") { - return errors.Wrapf(exitcodes.ErrNoGoFiles, "package %s", pkg.PkgPath) + return fmt.Errorf("package %s: %w", pkg.PkgPath, exitcodes.ErrNoGoFiles) } if strings.Contains(err.Msg, "cannot find package") { // when analyzing not existing directory - return errors.Wrap(exitcodes.ErrFailure, err.Msg) + return fmt.Errorf("%v: %w", err.Msg, exitcodes.ErrFailure) } } @@ -195,7 +226,7 @@ func (cl *ContextLoader) loadPackages(ctx context.Context, loadMode packages.Loa buildFlags, err := cl.makeBuildFlags() if err != nil { - return nil, errors.Wrap(err, "failed to make build flags for go list") + return nil, fmt.Errorf("failed to make build flags for go list: %w", err) } conf := &packages.Config{ @@ -211,14 +242,7 @@ func (cl *ContextLoader) loadPackages(ctx context.Context, loadMode packages.Loa cl.debugf("Built loader args are %s", args) pkgs, err := packages.Load(conf, args...) if err != nil { - return nil, errors.Wrap(err, "failed to load with go/packages") - } - - // Currently, go/packages doesn't guarantee that error will be returned - // if context was canceled. See - // https://github.com/golang/tools/commit/c5cec6710e927457c3c29d6c156415e8539a5111#r39261855 - if ctx.Err() != nil { - return nil, errors.Wrap(ctx.Err(), "timed out to load packages") + return nil, fmt.Errorf("failed to load with go/packages: %w", err) } if loadMode&packages.NeedSyntax == 0 { @@ -294,34 +318,3 @@ func (cl *ContextLoader) filterDuplicatePackages(pkgs []*packages.Package) []*pa return retPkgs } - -func (cl *ContextLoader) Load(ctx context.Context, linters []*linter.Config) (*linter.Context, error) { - loadMode := cl.findLoadMode(linters) - pkgs, err := cl.loadPackages(ctx, loadMode) - if err != nil { - return nil, errors.Wrap(err, "failed to load packages") - } - - deduplicatedPkgs := cl.filterDuplicatePackages(pkgs) - - if len(deduplicatedPkgs) == 0 { - return nil, exitcodes.ErrNoGoFiles - } - - ret := &linter.Context{ - Packages: deduplicatedPkgs, - - // At least `unused` linters works properly only on original (not deduplicated) packages, - // see https://github.com/golangci/golangci-lint/pull/585. - OriginalPackages: pkgs, - - Cfg: cl.cfg, - Log: cl.log, - FileCache: cl.fileCache, - LineCache: cl.lineCache, - PkgCache: cl.pkgCache, - LoadGuard: cl.loadGuard, - } - - return ret, nil -} diff --git a/pkg/lint/runner.go b/pkg/lint/runner.go index aed317d4c0d6..0de5298c9add 100644 --- a/pkg/lint/runner.go +++ b/pkg/lint/runner.go @@ -2,14 +2,11 @@ package lint import ( "context" + "errors" "fmt" "runtime/debug" "strings" - "github.com/hashicorp/go-multierror" - "github.com/pkg/errors" - gopackages "golang.org/x/tools/go/packages" - "github.com/golangci/golangci-lint/internal/errorutil" "github.com/golangci/golangci-lint/pkg/config" "github.com/golangci/golangci-lint/pkg/fsutils" @@ -23,14 +20,28 @@ import ( "github.com/golangci/golangci-lint/pkg/timeutils" ) +type processorStat struct { + inCount int + outCount int +} + type Runner struct { + Log logutils.Log + + lintCtx *linter.Context Processors []processors.Processor - Log logutils.Log } -func NewRunner(cfg *config.Config, log logutils.Log, goenv *goutil.Env, es *lintersdb.EnabledSet, - lineCache *fsutils.LineCache, dbManager *lintersdb.Manager, pkgs []*gopackages.Package) (*Runner, error) { - skipFilesProcessor, err := processors.NewSkipFiles(cfg.Run.SkipFiles) +func NewRunner(log logutils.Log, cfg *config.Config, goenv *goutil.Env, + lineCache *fsutils.LineCache, fileCache *fsutils.FileCache, + dbManager *lintersdb.Manager, lintCtx *linter.Context, +) (*Runner, error) { + // Beware that some processors need to add the path prefix when working with paths + // because they get invoked before the path prefixer (exclude and severity rules) + // or process other paths (skip files). + files := fsutils.NewFiles(lineCache, cfg.Output.PathPrefix) + + skipFilesProcessor, err := processors.NewSkipFiles(cfg.Run.SkipFiles, cfg.Output.PathPrefix) if err != nil { return nil, err } @@ -39,30 +50,14 @@ func NewRunner(cfg *config.Config, log logutils.Log, goenv *goutil.Env, es *lint if cfg.Run.UseDefaultSkipDirs { skipDirs = append(skipDirs, packages.StdExcludeDirRegexps...) } - skipDirsProcessor, err := processors.NewSkipDirs(skipDirs, log.Child(logutils.DebugKeySkipDirs), cfg.Run.Args) + skipDirsProcessor, err := processors.NewSkipDirs(skipDirs, log.Child(logutils.DebugKeySkipDirs), cfg.Run.Args, cfg.Output.PathPrefix) if err != nil { return nil, err } - enabledLinters, err := es.GetEnabledLintersMap() + enabledLinters, err := dbManager.GetEnabledLintersMap() if err != nil { - return nil, errors.Wrap(err, "failed to get enabled linters") - } - - // print deprecated messages - if !cfg.InternalCmdTest { - for name, lc := range enabledLinters { - if !lc.IsDeprecated() { - continue - } - - var extra string - if lc.Deprecation.Replacement != "" { - extra = fmt.Sprintf(" Replaced by %s.", lc.Deprecation.Replacement) - } - - log.Warnf("The linter '%s' is deprecated (since %s) due to: %s %s", name, lc.Deprecation.Since, lc.Deprecation.Message, extra) - } + return nil, fmt.Errorf("failed to get enabled linters: %w", err) } return &Runner{ @@ -70,20 +65,20 @@ func NewRunner(cfg *config.Config, log logutils.Log, goenv *goutil.Env, es *lint processors.NewCgo(goenv), // Must go after Cgo. - processors.NewFilenameUnadjuster(pkgs, log.Child(logutils.DebugKeyFilenameUnadjuster)), + processors.NewFilenameUnadjuster(lintCtx.Packages, log.Child(logutils.DebugKeyFilenameUnadjuster)), // Must be before diff, nolint and exclude autogenerated processor at least. processors.NewPathPrettifier(), skipFilesProcessor, skipDirsProcessor, // must be after path prettifier - processors.NewAutogeneratedExclude(), + processors.NewAutogeneratedExclude(cfg.Issues.ExcludeGeneratedStrict), // Must be before exclude because users see already marked output and configure excluding by it. processors.NewIdentifierMarker(), getExcludeProcessor(&cfg.Issues), - getExcludeRulesProcessor(&cfg.Issues, log, lineCache), + getExcludeRulesProcessor(&cfg.Issues, log, files), processors.NewNolint(log.Child(logutils.DebugKeyNolint), dbManager, enabledLinters), processors.NewUniqByLine(cfg), @@ -93,16 +88,50 @@ func NewRunner(cfg *config.Config, log logutils.Log, goenv *goutil.Env, es *lint processors.NewMaxFromLinter(cfg.Issues.MaxIssuesPerLinter, log.Child(logutils.DebugKeyMaxFromLinter), cfg), processors.NewSourceCode(lineCache, log.Child(logutils.DebugKeySourceCode)), processors.NewPathShortener(), - getSeverityRulesProcessor(&cfg.Severity, log, lineCache), + getSeverityRulesProcessor(&cfg.Severity, log, files), + + // The fixer still needs to see paths for the issues that are relative to the current directory. + processors.NewFixer(cfg, log, fileCache), + + // Now we can modify the issues for output. processors.NewPathPrefixer(cfg.Output.PathPrefix), processors.NewSortResults(cfg), }, - Log: log, + lintCtx: lintCtx, + Log: log, }, nil } +func (r *Runner) Run(ctx context.Context, linters []*linter.Config) ([]result.Issue, error) { + sw := timeutils.NewStopwatch("linters", r.Log) + defer sw.Print() + + var ( + lintErrors error + issues []result.Issue + ) + + for _, lc := range linters { + lc := lc + sw.TrackStage(lc.Name(), func() { + linterIssues, err := r.runLinterSafe(ctx, r.lintCtx, lc) + if err != nil { + lintErrors = errors.Join(lintErrors, fmt.Errorf("can't run linter %s", lc.Linter.Name()), err) + r.Log.Warnf("Can't run linter %s: %v", lc.Linter.Name(), err) + + return + } + + issues = append(issues, linterIssues...) + }) + } + + return r.processLintResults(issues), lintErrors +} + func (r *Runner) runLinterSafe(ctx context.Context, lintCtx *linter.Context, - lc *linter.Config) (ret []result.Issue, err error) { + lc *linter.Config, +) (ret []result.Issue, err error) { defer func() { if panicData := recover(); panicData != nil { if pe, ok := panicData.(*errorutil.PanicError); ok { @@ -141,12 +170,7 @@ func (r *Runner) runLinterSafe(ctx context.Context, lintCtx *linter.Context, return issues, nil } -type processorStat struct { - inCount int - outCount int -} - -func (r Runner) processLintResults(inIssues []result.Issue) []result.Issue { +func (r *Runner) processLintResults(inIssues []result.Issue) []result.Issue { sw := timeutils.NewStopwatch("processing", r.Log) var issuesBefore, issuesAfter int @@ -177,7 +201,7 @@ func (r Runner) processLintResults(inIssues []result.Issue) []result.Issue { return outIssues } -func (r Runner) printPerProcessorStat(stat map[string]processorStat) { +func (r *Runner) printPerProcessorStat(stat map[string]processorStat) { parts := make([]string, 0, len(stat)) for name, ps := range stat { if ps.inCount != 0 { @@ -189,33 +213,6 @@ func (r Runner) printPerProcessorStat(stat map[string]processorStat) { } } -func (r Runner) Run(ctx context.Context, linters []*linter.Config, lintCtx *linter.Context) ([]result.Issue, error) { - sw := timeutils.NewStopwatch("linters", r.Log) - defer sw.Print() - - var ( - lintErrors *multierror.Error - issues []result.Issue - ) - - for _, lc := range linters { - lc := lc - sw.TrackStage(lc.Name(), func() { - linterIssues, err := r.runLinterSafe(ctx, lintCtx, lc) - if err != nil { - lintErrors = multierror.Append(lintErrors, fmt.Errorf("can't run linter %s: %w", lc.Linter.Name(), err)) - r.Log.Warnf("Can't run linter %s: %v", lc.Linter.Name(), err) - - return - } - - issues = append(issues, linterIssues...) - }) - } - - return r.processLintResults(issues), lintErrors.ErrorOrNil() -} - func (r *Runner) processIssues(issues []result.Issue, sw *timeutils.Stopwatch, statPerProcessor map[string]processorStat) []result.Issue { for _, p := range r.Processors { var newIssues []result.Issue @@ -244,31 +241,27 @@ func (r *Runner) processIssues(issues []result.Issue, sw *timeutils.Stopwatch, s } func getExcludeProcessor(cfg *config.Issues) processors.Processor { - var excludeTotalPattern string - - if len(cfg.ExcludePatterns) != 0 { - excludeTotalPattern = fmt.Sprintf("(%s)", strings.Join(cfg.ExcludePatterns, "|")) + opts := processors.ExcludeOptions{ + CaseSensitive: cfg.ExcludeCaseSensitive, } - var excludeProcessor processors.Processor - if cfg.ExcludeCaseSensitive { - excludeProcessor = processors.NewExcludeCaseSensitive(excludeTotalPattern) - } else { - excludeProcessor = processors.NewExclude(excludeTotalPattern) + if len(cfg.ExcludePatterns) != 0 { + opts.Pattern = fmt.Sprintf("(%s)", strings.Join(cfg.ExcludePatterns, "|")) } - return excludeProcessor + return processors.NewExclude(opts) } -func getExcludeRulesProcessor(cfg *config.Issues, log logutils.Log, lineCache *fsutils.LineCache) processors.Processor { +func getExcludeRulesProcessor(cfg *config.Issues, log logutils.Log, files *fsutils.Files) processors.Processor { var excludeRules []processors.ExcludeRule for _, r := range cfg.ExcludeRules { excludeRules = append(excludeRules, processors.ExcludeRule{ BaseRule: processors.BaseRule{ - Text: r.Text, - Source: r.Source, - Path: r.Path, - Linters: r.Linters, + Text: r.Text, + Source: r.Source, + Path: r.Path, + PathExcept: r.PathExcept, + Linters: r.Linters, }, }) } @@ -284,54 +277,34 @@ func getExcludeRulesProcessor(cfg *config.Issues, log logutils.Log, lineCache *f } } - var excludeRulesProcessor processors.Processor - if cfg.ExcludeCaseSensitive { - excludeRulesProcessor = processors.NewExcludeRulesCaseSensitive( - excludeRules, - lineCache, - log.Child(logutils.DebugKeyExcludeRules), - ) - } else { - excludeRulesProcessor = processors.NewExcludeRules( - excludeRules, - lineCache, - log.Child(logutils.DebugKeyExcludeRules), - ) + opts := processors.ExcludeRulesOptions{ + Rules: excludeRules, + CaseSensitive: cfg.ExcludeCaseSensitive, } - return excludeRulesProcessor + return processors.NewExcludeRules(log.Child(logutils.DebugKeyExcludeRules), files, opts) } -func getSeverityRulesProcessor(cfg *config.Severity, log logutils.Log, lineCache *fsutils.LineCache) processors.Processor { +func getSeverityRulesProcessor(cfg *config.Severity, log logutils.Log, files *fsutils.Files) processors.Processor { var severityRules []processors.SeverityRule for _, r := range cfg.Rules { severityRules = append(severityRules, processors.SeverityRule{ Severity: r.Severity, BaseRule: processors.BaseRule{ - Text: r.Text, - Source: r.Source, - Path: r.Path, - Linters: r.Linters, + Text: r.Text, + Source: r.Source, + Path: r.Path, + PathExcept: r.PathExcept, + Linters: r.Linters, }, }) } - var severityRulesProcessor processors.Processor - if cfg.CaseSensitive { - severityRulesProcessor = processors.NewSeverityRulesCaseSensitive( - cfg.Default, - severityRules, - lineCache, - log.Child(logutils.DebugKeySeverityRules), - ) - } else { - severityRulesProcessor = processors.NewSeverityRules( - cfg.Default, - severityRules, - lineCache, - log.Child(logutils.DebugKeySeverityRules), - ) + severityOpts := processors.SeverityOptions{ + Default: cfg.Default, + Rules: severityRules, + CaseSensitive: cfg.CaseSensitive, } - return severityRulesProcessor + return processors.NewSeverity(log.Child(logutils.DebugKeySeverityRules), files, severityOpts) } diff --git a/pkg/logutils/log.go b/pkg/logutils/log.go index 2c9609d89479..16067e490ed1 100644 --- a/pkg/logutils/log.go +++ b/pkg/logutils/log.go @@ -1,11 +1,11 @@ package logutils type Log interface { - Fatalf(format string, args ...interface{}) - Panicf(format string, args ...interface{}) - Errorf(format string, args ...interface{}) - Warnf(format string, args ...interface{}) - Infof(format string, args ...interface{}) + Fatalf(format string, args ...any) + Panicf(format string, args ...any) + Errorf(format string, args ...any) + Warnf(format string, args ...any) + Infof(format string, args ...any) Child(name string) Log SetLevel(level LogLevel) diff --git a/pkg/logutils/logutils.go b/pkg/logutils/logutils.go index 62c521eac3e0..c813b41b8f94 100644 --- a/pkg/logutils/logutils.go +++ b/pkg/logutils/logutils.go @@ -22,6 +22,7 @@ const ( DebugKeyExcludeRules = "exclude_rules" DebugKeyExec = "exec" DebugKeyFilenameUnadjuster = "filename_unadjuster" + DebugKeyForbidigo = "forbidigo" DebugKeyGoEnv = "goenv" DebugKeyLinter = "linter" DebugKeyLintersContext = "linters_context" @@ -56,9 +57,10 @@ const ( const ( DebugKeyGoCritic = "gocritic" // Debugs `go-critic` linter. + DebugKeyGovet = "govet" // Debugs `govet` linter. DebugKeyMegacheck = "megacheck" // Debugs `staticcheck` related linters. DebugKeyNolint = "nolint" // Debugs a filter excluding issues by `//nolint` comments. - DebugKeyRevive = "revive" // Debugs `revice` linter. + DebugKeyRevive = "revive" // Debugs `revive` linter. ) func getEnabledDebugs() map[string]bool { @@ -77,9 +79,9 @@ func getEnabledDebugs() map[string]bool { var enabledDebugs = getEnabledDebugs() -type DebugFunc func(format string, args ...interface{}) +type DebugFunc func(format string, args ...any) -func nopDebugf(format string, args ...interface{}) {} +func nopDebugf(_ string, _ ...any) {} func Debug(tag string) DebugFunc { if !enabledDebugs[tag] { @@ -89,7 +91,7 @@ func Debug(tag string) DebugFunc { logger := NewStderrLog(tag) logger.SetLevel(LogLevelDebug) - return func(format string, args ...interface{}) { + return func(format string, args ...any) { logger.Debugf(format, args...) } } @@ -98,8 +100,15 @@ func HaveDebugTag(tag string) bool { return enabledDebugs[tag] } +var verbose bool + func SetupVerboseLog(log Log, isVerbose bool) { if isVerbose { + verbose = isVerbose log.SetLevel(LogLevelInfo) } } + +func IsVerbose() bool { + return verbose +} diff --git a/pkg/logutils/mock.go b/pkg/logutils/mock.go index e897ce1ede9d..efda8cc20f6e 100644 --- a/pkg/logutils/mock.go +++ b/pkg/logutils/mock.go @@ -12,28 +12,28 @@ func NewMockLog() *MockLog { return &MockLog{} } -func (m *MockLog) Fatalf(format string, args ...interface{}) { - mArgs := []interface{}{format} +func (m *MockLog) Fatalf(format string, args ...any) { + mArgs := []any{format} m.Called(append(mArgs, args...)...) } -func (m *MockLog) Panicf(format string, args ...interface{}) { - mArgs := []interface{}{format} +func (m *MockLog) Panicf(format string, args ...any) { + mArgs := []any{format} m.Called(append(mArgs, args...)...) } -func (m *MockLog) Errorf(format string, args ...interface{}) { - mArgs := []interface{}{format} +func (m *MockLog) Errorf(format string, args ...any) { + mArgs := []any{format} m.Called(append(mArgs, args...)...) } -func (m *MockLog) Warnf(format string, args ...interface{}) { - mArgs := []interface{}{format} +func (m *MockLog) Warnf(format string, args ...any) { + mArgs := []any{format} m.Called(append(mArgs, args...)...) } -func (m *MockLog) Infof(format string, args ...interface{}) { - mArgs := []interface{}{format} +func (m *MockLog) Infof(format string, args ...any) { + mArgs := []any{format} m.Called(append(mArgs, args...)...) } diff --git a/pkg/logutils/out.go b/pkg/logutils/out.go index 67c70dc8f283..ef137548671f 100644 --- a/pkg/logutils/out.go +++ b/pkg/logutils/out.go @@ -5,5 +5,7 @@ import ( colorable "github.com/mattn/go-colorable" ) -var StdOut = color.Output // https://github.com/golangci/golangci-lint/issues/14 -var StdErr = colorable.NewColorableStderr() +var ( + StdOut = color.Output // https://github.com/golangci/golangci-lint/issues/14 + StdErr = colorable.NewColorableStderr() +) diff --git a/pkg/logutils/stderr_log.go b/pkg/logutils/stderr_log.go index a68215e7053e..367c94f38529 100644 --- a/pkg/logutils/stderr_log.go +++ b/pkg/logutils/stderr_log.go @@ -67,17 +67,17 @@ func (sl StderrLog) prefix() string { return prefix } -func (sl StderrLog) Fatalf(format string, args ...interface{}) { +func (sl StderrLog) Fatalf(format string, args ...any) { sl.logger.Errorf("%s%s", sl.prefix(), fmt.Sprintf(format, args...)) os.Exit(exitcodes.Failure) } -func (sl StderrLog) Panicf(format string, args ...interface{}) { +func (sl StderrLog) Panicf(format string, args ...any) { v := fmt.Sprintf("%s%s", sl.prefix(), fmt.Sprintf(format, args...)) panic(v) } -func (sl StderrLog) Errorf(format string, args ...interface{}) { +func (sl StderrLog) Errorf(format string, args ...any) { if sl.level > LogLevelError { return } @@ -88,7 +88,7 @@ func (sl StderrLog) Errorf(format string, args ...interface{}) { // called on hidden errors, see log levels comments. } -func (sl StderrLog) Warnf(format string, args ...interface{}) { +func (sl StderrLog) Warnf(format string, args ...any) { if sl.level > LogLevelWarn { return } @@ -96,7 +96,7 @@ func (sl StderrLog) Warnf(format string, args ...interface{}) { sl.logger.Warnf("%s%s", sl.prefix(), fmt.Sprintf(format, args...)) } -func (sl StderrLog) Infof(format string, args ...interface{}) { +func (sl StderrLog) Infof(format string, args ...any) { if sl.level > LogLevelInfo { return } @@ -104,7 +104,7 @@ func (sl StderrLog) Infof(format string, args ...interface{}) { sl.logger.Infof("%s%s", sl.prefix(), fmt.Sprintf(format, args...)) } -func (sl StderrLog) Debugf(format string, args ...interface{}) { +func (sl StderrLog) Debugf(format string, args ...any) { if sl.level > LogLevelDebug { return } diff --git a/pkg/packages/errors.go b/pkg/packages/errors.go index 72fb8601ab70..ff37651affcc 100644 --- a/pkg/packages/errors.go +++ b/pkg/packages/errors.go @@ -1,12 +1,11 @@ package packages import ( + "errors" "fmt" "go/token" "strconv" "strings" - - "github.com/pkg/errors" ) func ParseErrorPosition(pos string) (*token.Position, error) { @@ -19,14 +18,14 @@ func ParseErrorPosition(pos string) (*token.Position, error) { file := parts[0] line, err := strconv.Atoi(parts[1]) if err != nil { - return nil, fmt.Errorf("can't parse line number %q: %s", parts[1], err) + return nil, fmt.Errorf("can't parse line number %q: %w", parts[1], err) } var column int if len(parts) == 3 { // no column column, err = strconv.Atoi(parts[2]) if err != nil { - return nil, errors.Wrapf(err, "failed to parse column from %q", parts[2]) + return nil, fmt.Errorf("failed to parse column from %q: %w", parts[2], err) } } diff --git a/pkg/printers/checkstyle.go b/pkg/printers/checkstyle.go index 307a8e7a0a85..e32eef7f51f5 100644 --- a/pkg/printers/checkstyle.go +++ b/pkg/printers/checkstyle.go @@ -1,13 +1,13 @@ package printers import ( - "context" "encoding/xml" "fmt" "io" "sort" "github.com/go-xmlfmt/xmlfmt" + "golang.org/x/exp/maps" "github.com/golangci/golangci-lint/pkg/result" ) @@ -41,7 +41,7 @@ func NewCheckstyle(w io.Writer) *Checkstyle { return &Checkstyle{w: w} } -func (p Checkstyle) Print(ctx context.Context, issues []result.Issue) error { +func (p Checkstyle) Print(issues []result.Issue) error { out := checkstyleOutput{ Version: "5.0", } @@ -75,10 +75,7 @@ func (p Checkstyle) Print(ctx context.Context, issues []result.Issue) error { file.Errors = append(file.Errors, newError) } - out.Files = make([]*checkstyleFile, 0, len(files)) - for _, file := range files { - out.Files = append(out.Files, file) - } + out.Files = maps.Values(files) sort.Slice(out.Files, func(i, j int) bool { return out.Files[i].Name < out.Files[j].Name diff --git a/pkg/printers/checkstyle_test.go b/pkg/printers/checkstyle_test.go index 6315ab542a24..cf8a7d81b19b 100644 --- a/pkg/printers/checkstyle_test.go +++ b/pkg/printers/checkstyle_test.go @@ -2,7 +2,6 @@ package printers import ( "bytes" - "context" "go/token" "strings" "testing" @@ -47,7 +46,7 @@ func TestCheckstyle_Print(t *testing.T) { buf := new(bytes.Buffer) printer := NewCheckstyle(buf) - err := printer.Print(context.Background(), issues) + err := printer.Print(issues) require.NoError(t, err) //nolint:lll diff --git a/pkg/printers/codeclimate.go b/pkg/printers/codeclimate.go index 8a90f145dd4f..50d6dcff3b5c 100644 --- a/pkg/printers/codeclimate.go +++ b/pkg/printers/codeclimate.go @@ -1,9 +1,7 @@ package printers import ( - "context" "encoding/json" - "fmt" "io" "github.com/golangci/golangci-lint/pkg/result" @@ -35,7 +33,7 @@ func NewCodeClimate(w io.Writer) *CodeClimate { return &CodeClimate{w: w} } -func (p CodeClimate) Print(ctx context.Context, issues []result.Issue) error { +func (p CodeClimate) Print(issues []result.Issue) error { codeClimateIssues := make([]CodeClimateIssue, 0, len(issues)) for i := range issues { issue := &issues[i] @@ -53,12 +51,7 @@ func (p CodeClimate) Print(ctx context.Context, issues []result.Issue) error { codeClimateIssues = append(codeClimateIssues, codeClimateIssue) } - outputJSON, err := json.Marshal(codeClimateIssues) - if err != nil { - return err - } - - _, err = fmt.Fprint(p.w, string(outputJSON)) + err := json.NewEncoder(p.w).Encode(codeClimateIssues) if err != nil { return err } diff --git a/pkg/printers/codeclimate_test.go b/pkg/printers/codeclimate_test.go index 3776e685fb82..6ee9f1cf8b6c 100644 --- a/pkg/printers/codeclimate_test.go +++ b/pkg/printers/codeclimate_test.go @@ -2,7 +2,6 @@ package printers import ( "bytes" - "context" "go/token" "testing" @@ -61,11 +60,12 @@ func TestCodeClimate_Print(t *testing.T) { buf := new(bytes.Buffer) printer := NewCodeClimate(buf) - err := printer.Print(context.Background(), issues) + err := printer.Print(issues) require.NoError(t, err) //nolint:lll - expected := `[{"description":"linter-a: some issue","severity":"warning","fingerprint":"BA73C5DF4A6FD8462FFF1D3140235777","location":{"path":"path/to/filea.go","lines":{"begin":10}}},{"description":"linter-b: another issue","severity":"error","fingerprint":"0777B4FE60242BD8B2E9B7E92C4B9521","location":{"path":"path/to/fileb.go","lines":{"begin":300}}},{"description":"linter-c: issue c","severity":"critical","fingerprint":"BEE6E9FBB6BFA4B7DB9FB036697FB036","location":{"path":"path/to/filec.go","lines":{"begin":200}}}]` + expected := `[{"description":"linter-a: some issue","severity":"warning","fingerprint":"BA73C5DF4A6FD8462FFF1D3140235777","location":{"path":"path/to/filea.go","lines":{"begin":10}}},{"description":"linter-b: another issue","severity":"error","fingerprint":"0777B4FE60242BD8B2E9B7E92C4B9521","location":{"path":"path/to/fileb.go","lines":{"begin":300}}},{"description":"linter-c: issue c","severity":"critical","fingerprint":"BEE6E9FBB6BFA4B7DB9FB036697FB036","location":{"path":"path/to/filec.go","lines":{"begin":200}}}] +` assert.Equal(t, expected, buf.String()) } diff --git a/pkg/printers/github.go b/pkg/printers/github.go index 6a4d05d46f3b..e396119da1cc 100644 --- a/pkg/printers/github.go +++ b/pkg/printers/github.go @@ -1,23 +1,23 @@ package printers import ( - "context" "fmt" "io" + "path/filepath" "github.com/golangci/golangci-lint/pkg/result" ) -type github struct { +type GitHub struct { w io.Writer } const defaultGithubSeverity = "error" -// NewGithub output format outputs issues according to GitHub actions format: -// https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message -func NewGithub(w io.Writer) Printer { - return &github{w: w} +// NewGitHub output format outputs issues according to GitHub actions format: +// https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-error-message +func NewGitHub(w io.Writer) *GitHub { + return &GitHub{w: w} } // print each line as: ::error file=app.js,line=10,col=15::Something went wrong @@ -27,7 +27,12 @@ func formatIssueAsGithub(issue *result.Issue) string { severity = issue.Severity } - ret := fmt.Sprintf("::%s file=%s,line=%d", severity, issue.FilePath(), issue.Line()) + // Convert backslashes to forward slashes. + // This is needed when running on windows. + // Otherwise, GitHub won't be able to show the annotations pointing to the file path with backslashes. + file := filepath.ToSlash(issue.FilePath()) + + ret := fmt.Sprintf("::%s file=%s,line=%d", severity, file, issue.Line()) if issue.Pos.Column != 0 { ret += fmt.Sprintf(",col=%d", issue.Pos.Column) } @@ -36,7 +41,7 @@ func formatIssueAsGithub(issue *result.Issue) string { return ret } -func (p *github) Print(_ context.Context, issues []result.Issue) error { +func (p *GitHub) Print(issues []result.Issue) error { for ind := range issues { _, err := fmt.Fprintln(p.w, formatIssueAsGithub(&issues[ind])) if err != nil { diff --git a/pkg/printers/github_test.go b/pkg/printers/github_test.go index f62185182e99..d927ddd271e6 100644 --- a/pkg/printers/github_test.go +++ b/pkg/printers/github_test.go @@ -3,8 +3,8 @@ package printers import ( "bytes" - "context" "go/token" + "runtime" "testing" "github.com/stretchr/testify/assert" @@ -13,7 +13,7 @@ import ( "github.com/golangci/golangci-lint/pkg/result" ) -func TestGithub_Print(t *testing.T) { +func TestGitHub_Print(t *testing.T) { issues := []result.Issue{ { FromLinter: "linter-a", @@ -45,9 +45,9 @@ func TestGithub_Print(t *testing.T) { } buf := new(bytes.Buffer) - printer := NewGithub(buf) + printer := NewGitHub(buf) - err := printer.Print(context.Background(), issues) + err := printer.Print(issues) require.NoError(t, err) expected := `::warning file=path/to/filea.go,line=10,col=4::some issue (linter-a) @@ -57,7 +57,7 @@ func TestGithub_Print(t *testing.T) { assert.Equal(t, expected, buf.String()) } -func TestFormatGithubIssue(t *testing.T) { +func Test_formatIssueAsGithub(t *testing.T) { sampleIssue := result.Issue{ FromLinter: "sample-linter", Text: "some issue", @@ -73,3 +73,24 @@ func TestFormatGithubIssue(t *testing.T) { sampleIssue.Pos.Column = 0 require.Equal(t, "::error file=path/to/file.go,line=10::some issue (sample-linter)", formatIssueAsGithub(&sampleIssue)) } + +func Test_formatIssueAsGithub_Windows(t *testing.T) { + if runtime.GOOS != "windows" { + t.Skip("Skipping test on non Windows") + } + + sampleIssue := result.Issue{ + FromLinter: "sample-linter", + Text: "some issue", + Pos: token.Position{ + Filename: "path\\to\\file.go", + Offset: 2, + Line: 10, + Column: 4, + }, + } + require.Equal(t, "::error file=path/to/file.go,line=10,col=4::some issue (sample-linter)", formatIssueAsGithub(&sampleIssue)) + + sampleIssue.Pos.Column = 0 + require.Equal(t, "::error file=path/to/file.go,line=10::some issue (sample-linter)", formatIssueAsGithub(&sampleIssue)) +} diff --git a/pkg/printers/html.go b/pkg/printers/html.go index 3d82d7d8bd7f..7dd1e5c623d0 100644 --- a/pkg/printers/html.go +++ b/pkg/printers/html.go @@ -1,7 +1,6 @@ package printers import ( - "context" "fmt" "html/template" "io" @@ -131,7 +130,7 @@ func NewHTML(w io.Writer) *HTML { return &HTML{w: w} } -func (p HTML) Print(_ context.Context, issues []result.Issue) error { +func (p HTML) Print(issues []result.Issue) error { var htmlIssues []htmlIssue for i := range issues { diff --git a/pkg/printers/html_test.go b/pkg/printers/html_test.go index 1c3306d7dec6..23d479ca3b0a 100644 --- a/pkg/printers/html_test.go +++ b/pkg/printers/html_test.go @@ -2,7 +2,6 @@ package printers import ( "bytes" - "context" "go/token" "testing" @@ -153,7 +152,7 @@ func TestHTML_Print(t *testing.T) { buf := new(bytes.Buffer) printer := NewHTML(buf) - err := printer.Print(context.Background(), issues) + err := printer.Print(issues) require.NoError(t, err) assert.Equal(t, expectedHTML, buf.String()) diff --git a/pkg/printers/json.go b/pkg/printers/json.go index cfef51f587fb..28509cac459b 100644 --- a/pkg/printers/json.go +++ b/pkg/printers/json.go @@ -1,7 +1,6 @@ package printers import ( - "context" "encoding/json" "io" @@ -10,7 +9,7 @@ import ( ) type JSON struct { - rd *report.Data + rd *report.Data // TODO(ldez) should be drop in v2. Only use by JSON reporter. w io.Writer } @@ -26,7 +25,7 @@ type JSONResult struct { Report *report.Data } -func (p JSON) Print(ctx context.Context, issues []result.Issue) error { +func (p JSON) Print(issues []result.Issue) error { res := JSONResult{ Issues: issues, Report: p.rd, diff --git a/pkg/printers/json_test.go b/pkg/printers/json_test.go index 402c8d6a271b..78111d9bcfb5 100644 --- a/pkg/printers/json_test.go +++ b/pkg/printers/json_test.go @@ -2,7 +2,6 @@ package printers import ( "bytes" - "context" "go/token" "testing" @@ -47,7 +46,7 @@ func TestJSON_Print(t *testing.T) { printer := NewJSON(nil, buf) - err := printer.Print(context.Background(), issues) + err := printer.Print(issues) require.NoError(t, err) //nolint:lll diff --git a/pkg/printers/junitxml.go b/pkg/printers/junitxml.go index 0424f78b48d7..3e3f82f5805c 100644 --- a/pkg/printers/junitxml.go +++ b/pkg/printers/junitxml.go @@ -1,13 +1,14 @@ package printers import ( - "context" "encoding/xml" "fmt" "io" "sort" "strings" + "golang.org/x/exp/maps" + "github.com/golangci/golangci-lint/pkg/result" ) @@ -45,7 +46,7 @@ func NewJunitXML(w io.Writer) *JunitXML { return &JunitXML{w: w} } -func (p JunitXML) Print(ctx context.Context, issues []result.Issue) error { +func (p JunitXML) Print(issues []result.Issue) error { suites := make(map[string]testSuiteXML) // use a map to group by file for ind := range issues { @@ -72,9 +73,7 @@ func (p JunitXML) Print(ctx context.Context, issues []result.Issue) error { } var res testSuitesXML - for _, val := range suites { - res.TestSuites = append(res.TestSuites, val) - } + res.TestSuites = maps.Values(suites) sort.Slice(res.TestSuites, func(i, j int) bool { return res.TestSuites[i].Suite < res.TestSuites[j].Suite diff --git a/pkg/printers/junitxml_test.go b/pkg/printers/junitxml_test.go index bc994be2fb7c..c10d6403c1d1 100644 --- a/pkg/printers/junitxml_test.go +++ b/pkg/printers/junitxml_test.go @@ -3,7 +3,6 @@ package printers import ( "bytes" - "context" "go/token" "testing" @@ -47,7 +46,7 @@ func TestJunitXML_Print(t *testing.T) { buf := new(bytes.Buffer) printer := NewJunitXML(buf) - err := printer.Print(context.Background(), issues) + err := printer.Print(issues) require.NoError(t, err) expected := ` diff --git a/pkg/printers/printer.go b/pkg/printers/printer.go index bfafb88e2a79..ba2bd2d39f74 100644 --- a/pkg/printers/printer.go +++ b/pkg/printers/printer.go @@ -1,11 +1,141 @@ package printers import ( - "context" + "errors" + "fmt" + "io" + "os" + "strings" + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/logutils" + "github.com/golangci/golangci-lint/pkg/report" "github.com/golangci/golangci-lint/pkg/result" ) -type Printer interface { - Print(ctx context.Context, issues []result.Issue) error +const defaultFileMode = 0o644 + +type issuePrinter interface { + Print(issues []result.Issue) error +} + +// Printer prints issues +type Printer struct { + cfg *config.Output + reportData *report.Data + + log logutils.Log + + stdOut io.Writer + stdErr io.Writer +} + +// NewPrinter creates a new Printer. +func NewPrinter(log logutils.Log, cfg *config.Output, reportData *report.Data) (*Printer, error) { + if log == nil { + return nil, errors.New("missing log argument in constructor") + } + if cfg == nil { + return nil, errors.New("missing config argument in constructor") + } + if reportData == nil { + return nil, errors.New("missing reportData argument in constructor") + } + + return &Printer{ + cfg: cfg, + reportData: reportData, + log: log, + stdOut: logutils.StdOut, + stdErr: logutils.StdErr, + }, nil +} + +// Print prints issues based on the formats defined +func (c *Printer) Print(issues []result.Issue) error { + formats := strings.Split(c.cfg.Format, ",") + + for _, item := range formats { + format, path, _ := strings.Cut(item, ":") + err := c.printReports(issues, path, format) + if err != nil { + return err + } + } + + return nil +} + +func (c *Printer) printReports(issues []result.Issue, path, format string) error { + w, shouldClose, err := c.createWriter(path) + if err != nil { + return fmt.Errorf("can't create output for %s: %w", path, err) + } + + defer func() { + if file, ok := w.(io.Closer); shouldClose && ok { + _ = file.Close() + } + }() + + p, err := c.createPrinter(format, w) + if err != nil { + return err + } + + if err = p.Print(issues); err != nil { + return fmt.Errorf("can't print %d issues: %w", len(issues), err) + } + + return nil +} + +func (c *Printer) createWriter(path string) (io.Writer, bool, error) { + if path == "" || path == "stdout" { + return c.stdOut, false, nil + } + + if path == "stderr" { + return c.stdErr, false, nil + } + + f, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, defaultFileMode) + if err != nil { + return nil, false, err + } + + return f, true, nil +} + +func (c *Printer) createPrinter(format string, w io.Writer) (issuePrinter, error) { + var p issuePrinter + + switch format { + case config.OutFormatJSON: + p = NewJSON(c.reportData, w) + case config.OutFormatColoredLineNumber, config.OutFormatLineNumber: + p = NewText(c.cfg.PrintIssuedLine, + format == config.OutFormatColoredLineNumber, c.cfg.PrintLinterName, + c.log.Child(logutils.DebugKeyTextPrinter), w) + case config.OutFormatTab, config.OutFormatColoredTab: + p = NewTab(c.cfg.PrintLinterName, + format == config.OutFormatColoredTab, + c.log.Child(logutils.DebugKeyTabPrinter), w) + case config.OutFormatCheckstyle: + p = NewCheckstyle(w) + case config.OutFormatCodeClimate: + p = NewCodeClimate(w) + case config.OutFormatHTML: + p = NewHTML(w) + case config.OutFormatJunitXML: + p = NewJunitXML(w) + case config.OutFormatGithubActions: + p = NewGitHub(w) + case config.OutFormatTeamCity: + p = NewTeamCity(w) + default: + return nil, fmt.Errorf("unknown output format %s", format) + } + + return p, nil } diff --git a/pkg/printers/printer_test.go b/pkg/printers/printer_test.go new file mode 100644 index 000000000000..9170e30a0587 --- /dev/null +++ b/pkg/printers/printer_test.go @@ -0,0 +1,202 @@ +package printers + +import ( + "bytes" + "encoding/json" + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/logutils" + "github.com/golangci/golangci-lint/pkg/report" + "github.com/golangci/golangci-lint/pkg/result" +) + +func unmarshalFile(t *testing.T, filename string, v any) { + t.Helper() + + file, err := os.ReadFile(filepath.Join("testdata", filename)) + require.NoError(t, err) + + err = json.Unmarshal(file, v) + require.NoError(t, err) +} + +func TestPrinter_Print_stdout(t *testing.T) { + logger := logutils.NewStderrLog("skip") + + var issues []result.Issue + unmarshalFile(t, "in-issues.json", &issues) + + data := &report.Data{} + unmarshalFile(t, "in-report-data.json", data) + + testCases := []struct { + desc string + cfg *config.Output + expected string + }{ + { + desc: "stdout (implicit)", + cfg: &config.Output{ + Format: "line-number", + }, + expected: "golden-line-number.txt", + }, + { + desc: "stdout (explicit)", + cfg: &config.Output{ + Format: "line-number:stdout", + }, + expected: "golden-line-number.txt", + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + p, err := NewPrinter(logger, test.cfg, data) + require.NoError(t, err) + + var stdOutBuffer bytes.Buffer + p.stdOut = &stdOutBuffer + + var stdErrBuffer bytes.Buffer + p.stdErr = &stdErrBuffer + + err = p.Print(issues) + require.NoError(t, err) + + golden, err := os.ReadFile(filepath.Join("testdata", test.expected)) + require.NoError(t, err) + + assert.Equal(t, 0, stdErrBuffer.Len()) + assert.Equal(t, string(golden), stdOutBuffer.String()) + }) + } +} + +func TestPrinter_Print_stderr(t *testing.T) { + logger := logutils.NewStderrLog("skip") + + var issues []result.Issue + unmarshalFile(t, "in-issues.json", &issues) + + data := &report.Data{} + unmarshalFile(t, "in-report-data.json", data) + + cfg := &config.Output{ + Format: "line-number:stderr", + } + + p, err := NewPrinter(logger, cfg, data) + require.NoError(t, err) + + var stdOutBuffer bytes.Buffer + p.stdOut = &stdOutBuffer + + var stdErrBuffer bytes.Buffer + p.stdErr = &stdErrBuffer + + err = p.Print(issues) + require.NoError(t, err) + + golden, err := os.ReadFile(filepath.Join("testdata", "golden-line-number.txt")) + require.NoError(t, err) + + assert.Equal(t, 0, stdOutBuffer.Len()) + assert.Equal(t, string(golden), stdErrBuffer.String()) +} + +func TestPrinter_Print_file(t *testing.T) { + logger := logutils.NewStderrLog("skip") + + var issues []result.Issue + unmarshalFile(t, "in-issues.json", &issues) + + data := &report.Data{} + unmarshalFile(t, "in-report-data.json", data) + + outputPath := filepath.Join(t.TempDir(), "report.txt") + + cfg := &config.Output{ + Format: "line-number:" + outputPath, + } + + p, err := NewPrinter(logger, cfg, data) + require.NoError(t, err) + + var stdOutBuffer bytes.Buffer + p.stdOut = &stdOutBuffer + + var stdErrBuffer bytes.Buffer + p.stdErr = &stdErrBuffer + + err = p.Print(issues) + require.NoError(t, err) + + golden, err := os.ReadFile(filepath.Join("testdata", "golden-line-number.txt")) + require.NoError(t, err) + + assert.Equal(t, 0, stdOutBuffer.Len()) + assert.Equal(t, 0, stdErrBuffer.Len()) + + actual, err := os.ReadFile(outputPath) + require.NoError(t, err) + + assert.Equal(t, string(golden), string(actual)) +} + +func TestPrinter_Print_multiple(t *testing.T) { + logger := logutils.NewStderrLog("skip") + + var issues []result.Issue + unmarshalFile(t, "in-issues.json", &issues) + + data := &report.Data{} + unmarshalFile(t, "in-report-data.json", data) + + outputPath := filepath.Join(t.TempDir(), "github-actions.txt") + + cfg := &config.Output{ + Format: "github-actions:" + outputPath + + ",json" + + ",line-number:stderr", + } + + p, err := NewPrinter(logger, cfg, data) + require.NoError(t, err) + + var stdOutBuffer bytes.Buffer + p.stdOut = &stdOutBuffer + + var stdErrBuffer bytes.Buffer + p.stdErr = &stdErrBuffer + + err = p.Print(issues) + require.NoError(t, err) + + goldenGitHub, err := os.ReadFile(filepath.Join("testdata", "golden-github-actions.txt")) + require.NoError(t, err) + + actual, err := os.ReadFile(outputPath) + require.NoError(t, err) + + assert.Equal(t, string(goldenGitHub), string(actual)) + + goldenLineNumber, err := os.ReadFile(filepath.Join("testdata", "golden-line-number.txt")) + require.NoError(t, err) + + assert.Equal(t, string(goldenLineNumber), stdErrBuffer.String()) + + goldenJSON, err := os.ReadFile(filepath.Join("testdata", "golden-json.json")) + require.NoError(t, err) + + assert.Equal(t, string(goldenJSON), stdOutBuffer.String()) +} diff --git a/pkg/printers/tab.go b/pkg/printers/tab.go index ffef49108587..c6d390d188cf 100644 --- a/pkg/printers/tab.go +++ b/pkg/printers/tab.go @@ -1,7 +1,6 @@ package printers import ( - "context" "fmt" "io" "text/tabwriter" @@ -14,24 +13,32 @@ import ( type Tab struct { printLinterName bool - log logutils.Log - w io.Writer + useColors bool + + log logutils.Log + w io.Writer } -func NewTab(printLinterName bool, log logutils.Log, w io.Writer) *Tab { +func NewTab(printLinterName, useColors bool, log logutils.Log, w io.Writer) *Tab { return &Tab{ printLinterName: printLinterName, + useColors: useColors, log: log, w: w, } } -func (p *Tab) SprintfColored(ca color.Attribute, format string, args ...interface{}) string { +func (p *Tab) SprintfColored(ca color.Attribute, format string, args ...any) string { c := color.New(ca) + + if !p.useColors { + c.DisableColor() + } + return c.Sprintf(format, args...) } -func (p *Tab) Print(ctx context.Context, issues []result.Issue) error { +func (p *Tab) Print(issues []result.Issue) error { w := tabwriter.NewWriter(p.w, 0, 0, 2, ' ', 0) for i := range issues { @@ -45,15 +52,15 @@ func (p *Tab) Print(ctx context.Context, issues []result.Issue) error { return nil } -func (p *Tab) printIssue(i *result.Issue, w io.Writer) { - text := p.SprintfColored(color.FgRed, "%s", i.Text) +func (p *Tab) printIssue(issue *result.Issue, w io.Writer) { + text := p.SprintfColored(color.FgRed, "%s", issue.Text) if p.printLinterName { - text = fmt.Sprintf("%s\t%s", i.FromLinter, text) + text = fmt.Sprintf("%s\t%s", issue.FromLinter, text) } - pos := p.SprintfColored(color.Bold, "%s:%d", i.FilePath(), i.Line()) - if i.Pos.Column != 0 { - pos += fmt.Sprintf(":%d", i.Pos.Column) + pos := p.SprintfColored(color.Bold, "%s:%d", issue.FilePath(), issue.Line()) + if issue.Pos.Column != 0 { + pos += fmt.Sprintf(":%d", issue.Pos.Column) } fmt.Fprintf(w, "%s\t%s\n", pos, text) diff --git a/pkg/printers/tab_test.go b/pkg/printers/tab_test.go index 882699ef853c..bbd529b099b7 100644 --- a/pkg/printers/tab_test.go +++ b/pkg/printers/tab_test.go @@ -2,10 +2,10 @@ package printers import ( "bytes" - "context" "go/token" "testing" + "github.com/fatih/color" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -14,6 +14,13 @@ import ( ) func TestTab_Print(t *testing.T) { + // force color globally + backup := color.NoColor + t.Cleanup(func() { + color.NoColor = backup + }) + color.NoColor = false + issues := []result.Issue{ { FromLinter: "linter-a", @@ -44,16 +51,50 @@ func TestTab_Print(t *testing.T) { }, } - buf := new(bytes.Buffer) + testCases := []struct { + desc string + printLinterName bool + useColors bool + expected string + }{ + { + desc: "with linter name", + printLinterName: true, + useColors: false, + expected: `path/to/filea.go:10:4 linter-a some issue +path/to/fileb.go:300:9 linter-b another issue +`, + }, + { + desc: "disable all options", + printLinterName: false, + useColors: false, + expected: `path/to/filea.go:10:4 some issue +path/to/fileb.go:300:9 another issue +`, + }, + { + desc: "enable all options", + printLinterName: true, + useColors: true, + //nolint:lll // color characters must be in a simple string. + expected: "\x1b[1mpath/to/filea.go:10\x1b[22m:4 linter-a \x1b[31msome issue\x1b[0m\n\x1b[1mpath/to/fileb.go:300\x1b[22m:9 linter-b \x1b[31manother issue\x1b[0m\n", + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() - printer := NewTab(true, logutils.NewStderrLog(logutils.DebugKeyEmpty), buf) + buf := new(bytes.Buffer) - err := printer.Print(context.Background(), issues) - require.NoError(t, err) + printer := NewTab(test.printLinterName, test.useColors, logutils.NewStderrLog(logutils.DebugKeyEmpty), buf) - expected := `path/to/filea.go:10:4 linter-a some issue -path/to/fileb.go:300:9 linter-b another issue -` + err := printer.Print(issues) + require.NoError(t, err) - assert.Equal(t, expected, buf.String()) + assert.Equal(t, test.expected, buf.String()) + }) + } } diff --git a/pkg/printers/teamcity.go b/pkg/printers/teamcity.go new file mode 100644 index 000000000000..d3693e99716b --- /dev/null +++ b/pkg/printers/teamcity.go @@ -0,0 +1,122 @@ +package printers + +import ( + "fmt" + "io" + "strings" + "unicode/utf8" + + "github.com/golangci/golangci-lint/pkg/result" +) + +// Field limits. +const ( + smallLimit = 255 + largeLimit = 4000 +) + +// TeamCity printer for TeamCity format. +type TeamCity struct { + w io.Writer + escaper *strings.Replacer +} + +// NewTeamCity output format outputs issues according to TeamCity service message format. +func NewTeamCity(w io.Writer) *TeamCity { + return &TeamCity{ + w: w, + // https://www.jetbrains.com/help/teamcity/service-messages.html#Escaped+Values + escaper: strings.NewReplacer( + "'", "|'", + "\n", "|n", + "\r", "|r", + "|", "||", + "[", "|[", + "]", "|]", + ), + } +} + +func (p *TeamCity) Print(issues []result.Issue) error { + uniqLinters := map[string]struct{}{} + + for i := range issues { + issue := issues[i] + + _, ok := uniqLinters[issue.FromLinter] + if !ok { + inspectionType := InspectionType{ + id: issue.FromLinter, + name: issue.FromLinter, + description: issue.FromLinter, + category: "Golangci-lint reports", + } + + _, err := inspectionType.Print(p.w, p.escaper) + if err != nil { + return err + } + + uniqLinters[issue.FromLinter] = struct{}{} + } + + instance := InspectionInstance{ + typeID: issue.FromLinter, + message: issue.Text, + file: issue.FilePath(), + line: issue.Line(), + severity: issue.Severity, + } + + _, err := instance.Print(p.w, p.escaper) + if err != nil { + return err + } + } + + return nil +} + +// InspectionType is the unique description of the conducted inspection. Each specific warning or +// an error in code (inspection instance) has an inspection type. +// https://www.jetbrains.com/help/teamcity/service-messages.html#Inspection+Type +type InspectionType struct { + id string // (mandatory) limited by 255 characters. + name string // (mandatory) limited by 255 characters. + description string // (mandatory) limited by 255 characters. + category string // (mandatory) limited by 4000 characters. +} + +func (i InspectionType) Print(w io.Writer, escaper *strings.Replacer) (int, error) { + return fmt.Fprintf(w, "##teamcity[InspectionType id='%s' name='%s' description='%s' category='%s']\n", + limit(i.id, smallLimit), limit(i.name, smallLimit), limit(escaper.Replace(i.description), largeLimit), limit(i.category, smallLimit)) +} + +// InspectionInstance reports a specific defect, warning, error message. +// Includes location, description, and various optional and custom attributes. +// https://www.jetbrains.com/help/teamcity/service-messages.html#Inspection+Instance +type InspectionInstance struct { + typeID string // (mandatory) limited by 255 characters. + message string // (optional) limited by 4000 characters. + file string // (mandatory) file path limited by 4000 characters. + line int // (optional) line of the file. + severity string // (optional) any linter severity. +} + +func (i InspectionInstance) Print(w io.Writer, replacer *strings.Replacer) (int, error) { + return fmt.Fprintf(w, "##teamcity[inspection typeId='%s' message='%s' file='%s' line='%d' SEVERITY='%s']\n", + limit(i.typeID, smallLimit), + limit(replacer.Replace(i.message), largeLimit), + limit(i.file, largeLimit), + i.line, strings.ToUpper(i.severity)) +} + +func limit(s string, max int) string { + var size, count int + for i := 0; i < max && count < len(s); i++ { + _, size = utf8.DecodeRuneInString(s[count:]) + count += size + } + + return s[:count] +} diff --git a/pkg/printers/teamcity_test.go b/pkg/printers/teamcity_test.go new file mode 100644 index 000000000000..dd955097181d --- /dev/null +++ b/pkg/printers/teamcity_test.go @@ -0,0 +1,105 @@ +package printers + +import ( + "bytes" + "go/token" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/golangci/golangci-lint/pkg/result" +) + +func TestTeamCity_Print(t *testing.T) { + issues := []result.Issue{ + { + FromLinter: "linter-a", + Text: "warning issue", + Pos: token.Position{ + Filename: "path/to/filea.go", + Offset: 2, + Line: 10, + Column: 4, + }, + }, + { + FromLinter: "linter-a", + Severity: "error", + Text: "error issue", + Pos: token.Position{ + Filename: "path/to/filea.go", + Offset: 2, + Line: 10, + }, + }, + { + FromLinter: "linter-b", + Text: "info issue", + SourceLines: []string{ + "func foo() {", + "\tfmt.Println(\"bar\")", + "}", + }, + Pos: token.Position{ + Filename: "path/to/fileb.go", + Offset: 5, + Line: 300, + Column: 9, + }, + }, + } + + buf := new(bytes.Buffer) + printer := NewTeamCity(buf) + + err := printer.Print(issues) + require.NoError(t, err) + + expected := `##teamcity[InspectionType id='linter-a' name='linter-a' description='linter-a' category='Golangci-lint reports'] +##teamcity[inspection typeId='linter-a' message='warning issue' file='path/to/filea.go' line='10' SEVERITY=''] +##teamcity[inspection typeId='linter-a' message='error issue' file='path/to/filea.go' line='10' SEVERITY='ERROR'] +##teamcity[InspectionType id='linter-b' name='linter-b' description='linter-b' category='Golangci-lint reports'] +##teamcity[inspection typeId='linter-b' message='info issue' file='path/to/fileb.go' line='300' SEVERITY=''] +` + + assert.Equal(t, expected, buf.String()) +} + +func TestTeamCity_limit(t *testing.T) { + tests := []struct { + input string + max int + expected string + }{ + { + input: "golangci-lint", + max: 0, + expected: "", + }, + { + input: "golangci-lint", + max: 8, + expected: "golangci", + }, + { + input: "golangci-lint", + max: 13, + expected: "golangci-lint", + }, + { + input: "golangci-lint", + max: 15, + expected: "golangci-lint", + }, + { + input: "こんにちは", + max: 3, + expected: "こんに", + }, + } + + for _, tc := range tests { + require.Equal(t, tc.expected, limit(tc.input, tc.max)) + } +} diff --git a/pkg/printers/testdata/golden-github-actions.txt b/pkg/printers/testdata/golden-github-actions.txt new file mode 100644 index 000000000000..93704a489d1b --- /dev/null +++ b/pkg/printers/testdata/golden-github-actions.txt @@ -0,0 +1,22 @@ +::error file=pkg/experimental/myplugin/myplugin.go,line=13,col=1::don't use `init` function (gochecknoinits) +::error file=pkg/lint/lintersdb/builder_plugin.go,line=59,col=69::hugeParam: settings is heavy (80 bytes); consider passing it by pointer (gocritic) +::error file=pkg/printers/printer_test.go,line=6::File is not `goimports`-ed with -local github.com/golangci/golangci-lint (goimports) +::error file=pkg/config/issues.go,line=107,col=13::struct of size 144 bytes could be of size 128 bytes (maligned) +::error file=pkg/config/linters_settings.go,line=200,col=22::struct of size 3144 bytes could be of size 3096 bytes (maligned) +::error file=pkg/config/linters_settings.go,line=383,col=25::struct of size 72 bytes could be of size 64 bytes (maligned) +::error file=pkg/config/linters_settings.go,line=470,col=22::struct of size 72 bytes could be of size 56 bytes (maligned) +::error file=pkg/config/linters_settings.go,line=482,col=23::struct of size 136 bytes could be of size 128 bytes (maligned) +::error file=pkg/config/linters_settings.go,line=584,col=27::struct of size 64 bytes could be of size 56 bytes (maligned) +::error file=pkg/config/linters_settings.go,line=591,col=20::struct of size 88 bytes could be of size 80 bytes (maligned) +::error file=pkg/config/linters_settings.go,line=710,col=25::struct of size 40 bytes could be of size 32 bytes (maligned) +::error file=pkg/config/linters_settings.go,line=762,col=21::struct of size 112 bytes could be of size 104 bytes (maligned) +::error file=pkg/config/linters_settings.go,line=787,col=23::struct of size 32 bytes could be of size 24 bytes (maligned) +::error file=pkg/config/linters_settings.go,line=817,col=23::struct of size 40 bytes could be of size 32 bytes (maligned) +::error file=pkg/config/linters_settings.go,line=902,col=25::struct of size 80 bytes could be of size 72 bytes (maligned) +::error file=pkg/config/linters_settings.go,line=928,col=18::struct of size 112 bytes could be of size 96 bytes (maligned) +::error file=pkg/config/run.go,line=6,col=10::struct of size 168 bytes could be of size 160 bytes (maligned) +::error file=pkg/lint/linter/config.go,line=36,col=13::struct of size 128 bytes could be of size 120 bytes (maligned) +::error file=pkg/golinters/govet_test.go,line=70,col=23::struct of size 96 bytes could be of size 88 bytes (maligned) +::error file=pkg/result/processors/diff.go,line=17,col=11::struct of size 64 bytes could be of size 56 bytes (maligned) +::warning file=pkg/experimental/myplugin/myplugin.go,line=49,col=14::unused-parameter: parameter 'pass' seems to be unused, consider removing or renaming it as _ (revive) +::error file=pkg/commands/run.go,line=47,col=7::const `defaultFileMode` is unused (unused) diff --git a/pkg/printers/testdata/golden-json.json b/pkg/printers/testdata/golden-json.json new file mode 100644 index 000000000000..c0e6e6795aec --- /dev/null +++ b/pkg/printers/testdata/golden-json.json @@ -0,0 +1 @@ +{"Issues":[{"FromLinter":"gochecknoinits","Text":"don't use `init` function","Severity":"","SourceLines":["func init() {"],"Replacement":null,"Pos":{"Filename":"pkg/experimental/myplugin/myplugin.go","Offset":162,"Line":13,"Column":1},"ExpectNoLint":false,"ExpectedNoLintLinter":""},{"FromLinter":"gocritic","Text":"hugeParam: settings is heavy (80 bytes); consider passing it by pointer","Severity":"","SourceLines":["func (b *PluginBuilder) loadConfig(cfg *config.Config, name string, settings config.CustomLinterSettings) (*linter.Config, error) {"],"Replacement":null,"Pos":{"Filename":"pkg/lint/lintersdb/builder_plugin.go","Offset":1480,"Line":59,"Column":69},"ExpectNoLint":false,"ExpectedNoLintLinter":""},{"FromLinter":"goimports","Text":"File is not `goimports`-ed with -local github.com/golangci/golangci-lint","Severity":"","SourceLines":[""],"Replacement":{"NeedOnlyDelete":false,"NewLines":["","\t\"github.com/stretchr/testify/require\"",""],"Inline":null},"Pos":{"Filename":"pkg/printers/printer_test.go","Offset":0,"Line":6,"Column":0},"ExpectNoLint":false,"ExpectedNoLintLinter":""},{"FromLinter":"maligned","Text":"struct of size 144 bytes could be of size 128 bytes","Severity":"","SourceLines":["type Issues struct {"],"Replacement":null,"Pos":{"Filename":"pkg/config/issues.go","Offset":3338,"Line":107,"Column":13},"ExpectNoLint":false,"ExpectedNoLintLinter":""},{"FromLinter":"maligned","Text":"struct of size 3144 bytes could be of size 3096 bytes","Severity":"","SourceLines":["type LintersSettings struct {"],"Replacement":null,"Pos":{"Filename":"pkg/config/linters_settings.go","Offset":4576,"Line":200,"Column":22},"ExpectNoLint":false,"ExpectedNoLintLinter":""},{"FromLinter":"maligned","Text":"struct of size 72 bytes could be of size 64 bytes","Severity":"","SourceLines":["type ExhaustiveSettings struct {"],"Replacement":null,"Pos":{"Filename":"pkg/config/linters_settings.go","Offset":10829,"Line":383,"Column":25},"ExpectNoLint":false,"ExpectedNoLintLinter":""},{"FromLinter":"maligned","Text":"struct of size 72 bytes could be of size 56 bytes","Severity":"","SourceLines":["type GoConstSettings struct {"],"Replacement":null,"Pos":{"Filename":"pkg/config/linters_settings.go","Offset":14399,"Line":470,"Column":22},"ExpectNoLint":false,"ExpectedNoLintLinter":""},{"FromLinter":"maligned","Text":"struct of size 136 bytes could be of size 128 bytes","Severity":"","SourceLines":["type GoCriticSettings struct {"],"Replacement":null,"Pos":{"Filename":"pkg/config/linters_settings.go","Offset":14934,"Line":482,"Column":23},"ExpectNoLint":false,"ExpectedNoLintLinter":""},{"FromLinter":"maligned","Text":"struct of size 64 bytes could be of size 56 bytes","Severity":"","SourceLines":["type GosmopolitanSettings struct {"],"Replacement":null,"Pos":{"Filename":"pkg/config/linters_settings.go","Offset":18601,"Line":584,"Column":27},"ExpectNoLint":false,"ExpectedNoLintLinter":""},{"FromLinter":"maligned","Text":"struct of size 88 bytes could be of size 80 bytes","Severity":"","SourceLines":["type GovetSettings struct {"],"Replacement":null,"Pos":{"Filename":"pkg/config/linters_settings.go","Offset":18867,"Line":591,"Column":20},"ExpectNoLint":false,"ExpectedNoLintLinter":""},{"FromLinter":"maligned","Text":"struct of size 40 bytes could be of size 32 bytes","Severity":"","SourceLines":["type NoLintLintSettings struct {"],"Replacement":null,"Pos":{"Filename":"pkg/config/linters_settings.go","Offset":22337,"Line":710,"Column":25},"ExpectNoLint":false,"ExpectedNoLintLinter":""},{"FromLinter":"maligned","Text":"struct of size 112 bytes could be of size 104 bytes","Severity":"","SourceLines":["type ReviveSettings struct {"],"Replacement":null,"Pos":{"Filename":"pkg/config/linters_settings.go","Offset":24019,"Line":762,"Column":21},"ExpectNoLint":false,"ExpectedNoLintLinter":""},{"FromLinter":"maligned","Text":"struct of size 32 bytes could be of size 24 bytes","Severity":"","SourceLines":["type SlogLintSettings struct {"],"Replacement":null,"Pos":{"Filename":"pkg/config/linters_settings.go","Offset":24648,"Line":787,"Column":23},"ExpectNoLint":false,"ExpectedNoLintLinter":""},{"FromLinter":"maligned","Text":"struct of size 40 bytes could be of size 32 bytes","Severity":"","SourceLines":["type TagAlignSettings struct {"],"Replacement":null,"Pos":{"Filename":"pkg/config/linters_settings.go","Offset":25936,"Line":817,"Column":23},"ExpectNoLint":false,"ExpectedNoLintLinter":""},{"FromLinter":"maligned","Text":"struct of size 80 bytes could be of size 72 bytes","Severity":"","SourceLines":["type VarnamelenSettings struct {"],"Replacement":null,"Pos":{"Filename":"pkg/config/linters_settings.go","Offset":28758,"Line":902,"Column":25},"ExpectNoLint":false,"ExpectedNoLintLinter":""},{"FromLinter":"maligned","Text":"struct of size 112 bytes could be of size 96 bytes","Severity":"","SourceLines":["type WSLSettings struct {"],"Replacement":null,"Pos":{"Filename":"pkg/config/linters_settings.go","Offset":29898,"Line":928,"Column":18},"ExpectNoLint":false,"ExpectedNoLintLinter":""},{"FromLinter":"maligned","Text":"struct of size 168 bytes could be of size 160 bytes","Severity":"","SourceLines":["type Run struct {"],"Replacement":null,"Pos":{"Filename":"pkg/config/run.go","Offset":112,"Line":6,"Column":10},"ExpectNoLint":false,"ExpectedNoLintLinter":""},{"FromLinter":"maligned","Text":"struct of size 128 bytes could be of size 120 bytes","Severity":"","SourceLines":["type Config struct {"],"Replacement":null,"Pos":{"Filename":"pkg/lint/linter/config.go","Offset":1329,"Line":36,"Column":13},"ExpectNoLint":false,"ExpectedNoLintLinter":""},{"FromLinter":"maligned","Text":"struct of size 96 bytes could be of size 88 bytes","Severity":"","SourceLines":["\tfor _, tc := range []struct {"],"Replacement":null,"Pos":{"Filename":"pkg/golinters/govet_test.go","Offset":1804,"Line":70,"Column":23},"ExpectNoLint":false,"ExpectedNoLintLinter":""},{"FromLinter":"maligned","Text":"struct of size 64 bytes could be of size 56 bytes","Severity":"","SourceLines":["type Diff struct {"],"Replacement":null,"Pos":{"Filename":"pkg/result/processors/diff.go","Offset":233,"Line":17,"Column":11},"ExpectNoLint":false,"ExpectedNoLintLinter":""},{"FromLinter":"revive","Text":"unused-parameter: parameter 'pass' seems to be unused, consider removing or renaming it as _","Severity":"warning","SourceLines":["\t\t\tRun: func(pass *analysis.Pass) (any, error) {"],"Replacement":null,"LineRange":{"From":49,"To":49},"Pos":{"Filename":"pkg/experimental/myplugin/myplugin.go","Offset":921,"Line":49,"Column":14},"ExpectNoLint":false,"ExpectedNoLintLinter":""},{"FromLinter":"unused","Text":"const `defaultFileMode` is unused","Severity":"","SourceLines":["const defaultFileMode = 0644"],"Replacement":null,"Pos":{"Filename":"pkg/commands/run.go","Offset":1209,"Line":47,"Column":7},"ExpectNoLint":false,"ExpectedNoLintLinter":""}],"Report":{"Warnings":[{"Tag":"runner","Text":"The linter 'maligned' is deprecated (since v1.38.0) due to: The repository of the linter has been archived by the owner. Replaced by govet 'fieldalignment'."}],"Linters":[{"Name":"asasalint"},{"Name":"asciicheck"},{"Name":"bidichk"},{"Name":"bodyclose","Enabled":true},{"Name":"containedctx"},{"Name":"contextcheck"},{"Name":"cyclop"},{"Name":"decorder"},{"Name":"deadcode"},{"Name":"depguard","Enabled":true},{"Name":"dogsled","Enabled":true},{"Name":"dupl","Enabled":true},{"Name":"dupword"},{"Name":"durationcheck"},{"Name":"errcheck","Enabled":true,"EnabledByDefault":true},{"Name":"errchkjson"},{"Name":"errname"},{"Name":"errorlint","Enabled":true},{"Name":"execinquery"},{"Name":"exhaustive"},{"Name":"exhaustivestruct"},{"Name":"exhaustruct"},{"Name":"exportloopref","Enabled":true},{"Name":"forbidigo"},{"Name":"forcetypeassert"},{"Name":"funlen","Enabled":true},{"Name":"gci"},{"Name":"ginkgolinter"},{"Name":"gocheckcompilerdirectives","Enabled":true},{"Name":"gochecknoglobals"},{"Name":"gochecknoinits","Enabled":true},{"Name":"gochecksumtype"},{"Name":"gocognit"},{"Name":"goconst","Enabled":true},{"Name":"gocritic","Enabled":true},{"Name":"gocyclo","Enabled":true},{"Name":"godot"},{"Name":"godox"},{"Name":"goerr113"},{"Name":"gofmt","Enabled":true},{"Name":"gofumpt"},{"Name":"goheader"},{"Name":"goimports","Enabled":true},{"Name":"golint"},{"Name":"gomnd","Enabled":true},{"Name":"gomoddirectives"},{"Name":"gomodguard"},{"Name":"goprintffuncname","Enabled":true},{"Name":"gosec","Enabled":true},{"Name":"gosimple","Enabled":true,"EnabledByDefault":true},{"Name":"gosmopolitan"},{"Name":"govet","Enabled":true,"EnabledByDefault":true},{"Name":"grouper"},{"Name":"ifshort"},{"Name":"importas"},{"Name":"inamedparam"},{"Name":"ineffassign","Enabled":true,"EnabledByDefault":true},{"Name":"interfacebloat"},{"Name":"interfacer"},{"Name":"ireturn"},{"Name":"lll","Enabled":true},{"Name":"loggercheck"},{"Name":"maintidx"},{"Name":"makezero"},{"Name":"maligned","Enabled":true},{"Name":"mirror"},{"Name":"misspell","Enabled":true},{"Name":"musttag"},{"Name":"nakedret","Enabled":true},{"Name":"nestif"},{"Name":"nilerr"},{"Name":"nilnil"},{"Name":"nlreturn"},{"Name":"noctx","Enabled":true},{"Name":"nonamedreturns"},{"Name":"nosnakecase"},{"Name":"nosprintfhostport"},{"Name":"paralleltest"},{"Name":"perfsprint"},{"Name":"prealloc"},{"Name":"predeclared"},{"Name":"promlinter"},{"Name":"protogetter"},{"Name":"reassign"},{"Name":"revive","Enabled":true},{"Name":"rowserrcheck"},{"Name":"sloglint"},{"Name":"scopelint"},{"Name":"sqlclosecheck"},{"Name":"spancheck"},{"Name":"staticcheck","Enabled":true,"EnabledByDefault":true},{"Name":"structcheck"},{"Name":"stylecheck","Enabled":true},{"Name":"tagalign"},{"Name":"tagliatelle"},{"Name":"tenv"},{"Name":"testableexamples"},{"Name":"testifylint"},{"Name":"testpackage"},{"Name":"thelper"},{"Name":"tparallel"},{"Name":"typecheck","Enabled":true,"EnabledByDefault":true},{"Name":"unconvert","Enabled":true},{"Name":"unparam","Enabled":true},{"Name":"unused","Enabled":true,"EnabledByDefault":true},{"Name":"usestdlibvars"},{"Name":"varcheck"},{"Name":"varnamelen"},{"Name":"wastedassign"},{"Name":"whitespace","Enabled":true},{"Name":"wrapcheck"},{"Name":"wsl"},{"Name":"zerologlint"},{"Name":"nolintlint","Enabled":true}]}} diff --git a/pkg/printers/testdata/golden-line-number.txt b/pkg/printers/testdata/golden-line-number.txt new file mode 100644 index 000000000000..d735cf681a42 --- /dev/null +++ b/pkg/printers/testdata/golden-line-number.txt @@ -0,0 +1,22 @@ +pkg/experimental/myplugin/myplugin.go:13:1: don't use `init` function +pkg/lint/lintersdb/builder_plugin.go:59:69: hugeParam: settings is heavy (80 bytes); consider passing it by pointer +pkg/printers/printer_test.go:6: File is not `goimports`-ed with -local github.com/golangci/golangci-lint +pkg/config/issues.go:107:13: struct of size 144 bytes could be of size 128 bytes +pkg/config/linters_settings.go:200:22: struct of size 3144 bytes could be of size 3096 bytes +pkg/config/linters_settings.go:383:25: struct of size 72 bytes could be of size 64 bytes +pkg/config/linters_settings.go:470:22: struct of size 72 bytes could be of size 56 bytes +pkg/config/linters_settings.go:482:23: struct of size 136 bytes could be of size 128 bytes +pkg/config/linters_settings.go:584:27: struct of size 64 bytes could be of size 56 bytes +pkg/config/linters_settings.go:591:20: struct of size 88 bytes could be of size 80 bytes +pkg/config/linters_settings.go:710:25: struct of size 40 bytes could be of size 32 bytes +pkg/config/linters_settings.go:762:21: struct of size 112 bytes could be of size 104 bytes +pkg/config/linters_settings.go:787:23: struct of size 32 bytes could be of size 24 bytes +pkg/config/linters_settings.go:817:23: struct of size 40 bytes could be of size 32 bytes +pkg/config/linters_settings.go:902:25: struct of size 80 bytes could be of size 72 bytes +pkg/config/linters_settings.go:928:18: struct of size 112 bytes could be of size 96 bytes +pkg/config/run.go:6:10: struct of size 168 bytes could be of size 160 bytes +pkg/lint/linter/config.go:36:13: struct of size 128 bytes could be of size 120 bytes +pkg/golinters/govet_test.go:70:23: struct of size 96 bytes could be of size 88 bytes +pkg/result/processors/diff.go:17:11: struct of size 64 bytes could be of size 56 bytes +pkg/experimental/myplugin/myplugin.go:49:14: unused-parameter: parameter 'pass' seems to be unused, consider removing or renaming it as _ +pkg/commands/run.go:47:7: const `defaultFileMode` is unused diff --git a/pkg/printers/testdata/in-issues.json b/pkg/printers/testdata/in-issues.json new file mode 100644 index 000000000000..86378851b678 --- /dev/null +++ b/pkg/printers/testdata/in-issues.json @@ -0,0 +1,389 @@ + [ + { + "FromLinter": "gochecknoinits", + "Text": "don't use `init` function", + "Severity": "", + "SourceLines": [ + "func init() {" + ], + "Replacement": null, + "Pos": { + "Filename": "pkg/experimental/myplugin/myplugin.go", + "Offset": 162, + "Line": 13, + "Column": 1 + }, + "ExpectNoLint": false, + "ExpectedNoLintLinter": "" + }, + { + "FromLinter": "gocritic", + "Text": "hugeParam: settings is heavy (80 bytes); consider passing it by pointer", + "Severity": "", + "SourceLines": [ + "func (b *PluginBuilder) loadConfig(cfg *config.Config, name string, settings config.CustomLinterSettings) (*linter.Config, error) {" + ], + "Replacement": null, + "Pos": { + "Filename": "pkg/lint/lintersdb/builder_plugin.go", + "Offset": 1480, + "Line": 59, + "Column": 69 + }, + "ExpectNoLint": false, + "ExpectedNoLintLinter": "" + }, + { + "FromLinter": "goimports", + "Text": "File is not `goimports`-ed with -local github.com/golangci/golangci-lint", + "Severity": "", + "SourceLines": [ + "" + ], + "Replacement": { + "NeedOnlyDelete": false, + "NewLines": [ + "", + "\t\"github.com/stretchr/testify/require\"", + "" + ], + "Inline": null + }, + "Pos": { + "Filename": "pkg/printers/printer_test.go", + "Offset": 0, + "Line": 6, + "Column": 0 + }, + "ExpectNoLint": false, + "ExpectedNoLintLinter": "" + }, + { + "FromLinter": "maligned", + "Text": "struct of size 144 bytes could be of size 128 bytes", + "Severity": "", + "SourceLines": [ + "type Issues struct {" + ], + "Replacement": null, + "Pos": { + "Filename": "pkg/config/issues.go", + "Offset": 3338, + "Line": 107, + "Column": 13 + }, + "ExpectNoLint": false, + "ExpectedNoLintLinter": "" + }, + { + "FromLinter": "maligned", + "Text": "struct of size 3144 bytes could be of size 3096 bytes", + "Severity": "", + "SourceLines": [ + "type LintersSettings struct {" + ], + "Replacement": null, + "Pos": { + "Filename": "pkg/config/linters_settings.go", + "Offset": 4576, + "Line": 200, + "Column": 22 + }, + "ExpectNoLint": false, + "ExpectedNoLintLinter": "" + }, + { + "FromLinter": "maligned", + "Text": "struct of size 72 bytes could be of size 64 bytes", + "Severity": "", + "SourceLines": [ + "type ExhaustiveSettings struct {" + ], + "Replacement": null, + "Pos": { + "Filename": "pkg/config/linters_settings.go", + "Offset": 10829, + "Line": 383, + "Column": 25 + }, + "ExpectNoLint": false, + "ExpectedNoLintLinter": "" + }, + { + "FromLinter": "maligned", + "Text": "struct of size 72 bytes could be of size 56 bytes", + "Severity": "", + "SourceLines": [ + "type GoConstSettings struct {" + ], + "Replacement": null, + "Pos": { + "Filename": "pkg/config/linters_settings.go", + "Offset": 14399, + "Line": 470, + "Column": 22 + }, + "ExpectNoLint": false, + "ExpectedNoLintLinter": "" + }, + { + "FromLinter": "maligned", + "Text": "struct of size 136 bytes could be of size 128 bytes", + "Severity": "", + "SourceLines": [ + "type GoCriticSettings struct {" + ], + "Replacement": null, + "Pos": { + "Filename": "pkg/config/linters_settings.go", + "Offset": 14934, + "Line": 482, + "Column": 23 + }, + "ExpectNoLint": false, + "ExpectedNoLintLinter": "" + }, + { + "FromLinter": "maligned", + "Text": "struct of size 64 bytes could be of size 56 bytes", + "Severity": "", + "SourceLines": [ + "type GosmopolitanSettings struct {" + ], + "Replacement": null, + "Pos": { + "Filename": "pkg/config/linters_settings.go", + "Offset": 18601, + "Line": 584, + "Column": 27 + }, + "ExpectNoLint": false, + "ExpectedNoLintLinter": "" + }, + { + "FromLinter": "maligned", + "Text": "struct of size 88 bytes could be of size 80 bytes", + "Severity": "", + "SourceLines": [ + "type GovetSettings struct {" + ], + "Replacement": null, + "Pos": { + "Filename": "pkg/config/linters_settings.go", + "Offset": 18867, + "Line": 591, + "Column": 20 + }, + "ExpectNoLint": false, + "ExpectedNoLintLinter": "" + }, + { + "FromLinter": "maligned", + "Text": "struct of size 40 bytes could be of size 32 bytes", + "Severity": "", + "SourceLines": [ + "type NoLintLintSettings struct {" + ], + "Replacement": null, + "Pos": { + "Filename": "pkg/config/linters_settings.go", + "Offset": 22337, + "Line": 710, + "Column": 25 + }, + "ExpectNoLint": false, + "ExpectedNoLintLinter": "" + }, + { + "FromLinter": "maligned", + "Text": "struct of size 112 bytes could be of size 104 bytes", + "Severity": "", + "SourceLines": [ + "type ReviveSettings struct {" + ], + "Replacement": null, + "Pos": { + "Filename": "pkg/config/linters_settings.go", + "Offset": 24019, + "Line": 762, + "Column": 21 + }, + "ExpectNoLint": false, + "ExpectedNoLintLinter": "" + }, + { + "FromLinter": "maligned", + "Text": "struct of size 32 bytes could be of size 24 bytes", + "Severity": "", + "SourceLines": [ + "type SlogLintSettings struct {" + ], + "Replacement": null, + "Pos": { + "Filename": "pkg/config/linters_settings.go", + "Offset": 24648, + "Line": 787, + "Column": 23 + }, + "ExpectNoLint": false, + "ExpectedNoLintLinter": "" + }, + { + "FromLinter": "maligned", + "Text": "struct of size 40 bytes could be of size 32 bytes", + "Severity": "", + "SourceLines": [ + "type TagAlignSettings struct {" + ], + "Replacement": null, + "Pos": { + "Filename": "pkg/config/linters_settings.go", + "Offset": 25936, + "Line": 817, + "Column": 23 + }, + "ExpectNoLint": false, + "ExpectedNoLintLinter": "" + }, + { + "FromLinter": "maligned", + "Text": "struct of size 80 bytes could be of size 72 bytes", + "Severity": "", + "SourceLines": [ + "type VarnamelenSettings struct {" + ], + "Replacement": null, + "Pos": { + "Filename": "pkg/config/linters_settings.go", + "Offset": 28758, + "Line": 902, + "Column": 25 + }, + "ExpectNoLint": false, + "ExpectedNoLintLinter": "" + }, + { + "FromLinter": "maligned", + "Text": "struct of size 112 bytes could be of size 96 bytes", + "Severity": "", + "SourceLines": [ + "type WSLSettings struct {" + ], + "Replacement": null, + "Pos": { + "Filename": "pkg/config/linters_settings.go", + "Offset": 29898, + "Line": 928, + "Column": 18 + }, + "ExpectNoLint": false, + "ExpectedNoLintLinter": "" + }, + { + "FromLinter": "maligned", + "Text": "struct of size 168 bytes could be of size 160 bytes", + "Severity": "", + "SourceLines": [ + "type Run struct {" + ], + "Replacement": null, + "Pos": { + "Filename": "pkg/config/run.go", + "Offset": 112, + "Line": 6, + "Column": 10 + }, + "ExpectNoLint": false, + "ExpectedNoLintLinter": "" + }, + { + "FromLinter": "maligned", + "Text": "struct of size 128 bytes could be of size 120 bytes", + "Severity": "", + "SourceLines": [ + "type Config struct {" + ], + "Replacement": null, + "Pos": { + "Filename": "pkg/lint/linter/config.go", + "Offset": 1329, + "Line": 36, + "Column": 13 + }, + "ExpectNoLint": false, + "ExpectedNoLintLinter": "" + }, + { + "FromLinter": "maligned", + "Text": "struct of size 96 bytes could be of size 88 bytes", + "Severity": "", + "SourceLines": [ + "\tfor _, tc := range []struct {" + ], + "Replacement": null, + "Pos": { + "Filename": "pkg/golinters/govet_test.go", + "Offset": 1804, + "Line": 70, + "Column": 23 + }, + "ExpectNoLint": false, + "ExpectedNoLintLinter": "" + }, + { + "FromLinter": "maligned", + "Text": "struct of size 64 bytes could be of size 56 bytes", + "Severity": "", + "SourceLines": [ + "type Diff struct {" + ], + "Replacement": null, + "Pos": { + "Filename": "pkg/result/processors/diff.go", + "Offset": 233, + "Line": 17, + "Column": 11 + }, + "ExpectNoLint": false, + "ExpectedNoLintLinter": "" + }, + { + "FromLinter": "revive", + "Text": "unused-parameter: parameter 'pass' seems to be unused, consider removing or renaming it as _", + "Severity": "warning", + "SourceLines": [ + "\t\t\tRun: func(pass *analysis.Pass) (any, error) {" + ], + "Replacement": null, + "LineRange": { + "From": 49, + "To": 49 + }, + "Pos": { + "Filename": "pkg/experimental/myplugin/myplugin.go", + "Offset": 921, + "Line": 49, + "Column": 14 + }, + "ExpectNoLint": false, + "ExpectedNoLintLinter": "" + }, + { + "FromLinter": "unused", + "Text": "const `defaultFileMode` is unused", + "Severity": "", + "SourceLines": [ + "const defaultFileMode = 0644" + ], + "Replacement": null, + "Pos": { + "Filename": "pkg/commands/run.go", + "Offset": 1209, + "Line": 47, + "Column": 7 + }, + "ExpectNoLint": false, + "ExpectedNoLintLinter": "" + } + ] + diff --git a/pkg/printers/testdata/in-report-data.json b/pkg/printers/testdata/in-report-data.json new file mode 100644 index 000000000000..a6ed3e2de810 --- /dev/null +++ b/pkg/printers/testdata/in-report-data.json @@ -0,0 +1,395 @@ +{ + "Warnings": [ + { + "Tag": "runner", + "Text": "The linter 'maligned' is deprecated (since v1.38.0) due to: The repository of the linter has been archived by the owner. Replaced by govet 'fieldalignment'." + } + ], + "Linters": [ + { + "Name": "asasalint" + }, + { + "Name": "asciicheck" + }, + { + "Name": "bidichk" + }, + { + "Name": "bodyclose", + "Enabled": true + }, + { + "Name": "containedctx" + }, + { + "Name": "contextcheck" + }, + { + "Name": "cyclop" + }, + { + "Name": "decorder" + }, + { + "Name": "deadcode" + }, + { + "Name": "depguard", + "Enabled": true + }, + { + "Name": "dogsled", + "Enabled": true + }, + { + "Name": "dupl", + "Enabled": true + }, + { + "Name": "dupword" + }, + { + "Name": "durationcheck" + }, + { + "Name": "errcheck", + "Enabled": true, + "EnabledByDefault": true + }, + { + "Name": "errchkjson" + }, + { + "Name": "errname" + }, + { + "Name": "errorlint", + "Enabled": true + }, + { + "Name": "execinquery" + }, + { + "Name": "exhaustive" + }, + { + "Name": "exhaustivestruct" + }, + { + "Name": "exhaustruct" + }, + { + "Name": "exportloopref", + "Enabled": true + }, + { + "Name": "forbidigo" + }, + { + "Name": "forcetypeassert" + }, + { + "Name": "funlen", + "Enabled": true + }, + { + "Name": "gci" + }, + { + "Name": "ginkgolinter" + }, + { + "Name": "gocheckcompilerdirectives", + "Enabled": true + }, + { + "Name": "gochecknoglobals" + }, + { + "Name": "gochecknoinits", + "Enabled": true + }, + { + "Name": "gochecksumtype" + }, + { + "Name": "gocognit" + }, + { + "Name": "goconst", + "Enabled": true + }, + { + "Name": "gocritic", + "Enabled": true + }, + { + "Name": "gocyclo", + "Enabled": true + }, + { + "Name": "godot" + }, + { + "Name": "godox" + }, + { + "Name": "goerr113" + }, + { + "Name": "gofmt", + "Enabled": true + }, + { + "Name": "gofumpt" + }, + { + "Name": "goheader" + }, + { + "Name": "goimports", + "Enabled": true + }, + { + "Name": "golint" + }, + { + "Name": "gomnd", + "Enabled": true + }, + { + "Name": "gomoddirectives" + }, + { + "Name": "gomodguard" + }, + { + "Name": "goprintffuncname", + "Enabled": true + }, + { + "Name": "gosec", + "Enabled": true + }, + { + "Name": "gosimple", + "Enabled": true, + "EnabledByDefault": true + }, + { + "Name": "gosmopolitan" + }, + { + "Name": "govet", + "Enabled": true, + "EnabledByDefault": true + }, + { + "Name": "grouper" + }, + { + "Name": "ifshort" + }, + { + "Name": "importas" + }, + { + "Name": "inamedparam" + }, + { + "Name": "ineffassign", + "Enabled": true, + "EnabledByDefault": true + }, + { + "Name": "interfacebloat" + }, + { + "Name": "interfacer" + }, + { + "Name": "ireturn" + }, + { + "Name": "lll", + "Enabled": true + }, + { + "Name": "loggercheck" + }, + { + "Name": "maintidx" + }, + { + "Name": "makezero" + }, + { + "Name": "maligned", + "Enabled": true + }, + { + "Name": "mirror" + }, + { + "Name": "misspell", + "Enabled": true + }, + { + "Name": "musttag" + }, + { + "Name": "nakedret", + "Enabled": true + }, + { + "Name": "nestif" + }, + { + "Name": "nilerr" + }, + { + "Name": "nilnil" + }, + { + "Name": "nlreturn" + }, + { + "Name": "noctx", + "Enabled": true + }, + { + "Name": "nonamedreturns" + }, + { + "Name": "nosnakecase" + }, + { + "Name": "nosprintfhostport" + }, + { + "Name": "paralleltest" + }, + { + "Name": "perfsprint" + }, + { + "Name": "prealloc" + }, + { + "Name": "predeclared" + }, + { + "Name": "promlinter" + }, + { + "Name": "protogetter" + }, + { + "Name": "reassign" + }, + { + "Name": "revive", + "Enabled": true + }, + { + "Name": "rowserrcheck" + }, + { + "Name": "sloglint" + }, + { + "Name": "scopelint" + }, + { + "Name": "sqlclosecheck" + }, + { + "Name": "spancheck" + }, + { + "Name": "staticcheck", + "Enabled": true, + "EnabledByDefault": true + }, + { + "Name": "structcheck" + }, + { + "Name": "stylecheck", + "Enabled": true + }, + { + "Name": "tagalign" + }, + { + "Name": "tagliatelle" + }, + { + "Name": "tenv" + }, + { + "Name": "testableexamples" + }, + { + "Name": "testifylint" + }, + { + "Name": "testpackage" + }, + { + "Name": "thelper" + }, + { + "Name": "tparallel" + }, + { + "Name": "typecheck", + "Enabled": true, + "EnabledByDefault": true + }, + { + "Name": "unconvert", + "Enabled": true + }, + { + "Name": "unparam", + "Enabled": true + }, + { + "Name": "unused", + "Enabled": true, + "EnabledByDefault": true + }, + { + "Name": "usestdlibvars" + }, + { + "Name": "varcheck" + }, + { + "Name": "varnamelen" + }, + { + "Name": "wastedassign" + }, + { + "Name": "whitespace", + "Enabled": true + }, + { + "Name": "wrapcheck" + }, + { + "Name": "wsl" + }, + { + "Name": "zerologlint" + }, + { + "Name": "nolintlint", + "Enabled": true + } + ] + } + diff --git a/pkg/printers/text.go b/pkg/printers/text.go index d59391b29d28..56cced769695 100644 --- a/pkg/printers/text.go +++ b/pkg/printers/text.go @@ -1,7 +1,6 @@ package printers import ( - "context" "fmt" "io" "strings" @@ -14,8 +13,8 @@ import ( type Text struct { printIssuedLine bool - useColors bool printLinterName bool + useColors bool log logutils.Log w io.Writer @@ -24,23 +23,24 @@ type Text struct { func NewText(printIssuedLine, useColors, printLinterName bool, log logutils.Log, w io.Writer) *Text { return &Text{ printIssuedLine: printIssuedLine, - useColors: useColors, printLinterName: printLinterName, + useColors: useColors, log: log, w: w, } } -func (p *Text) SprintfColored(ca color.Attribute, format string, args ...interface{}) string { +func (p *Text) SprintfColored(ca color.Attribute, format string, args ...any) string { + c := color.New(ca) + if !p.useColors { - return fmt.Sprintf(format, args...) + c.DisableColor() } - c := color.New(ca) return c.Sprintf(format, args...) } -func (p *Text) Print(ctx context.Context, issues []result.Issue) error { +func (p *Text) Print(issues []result.Issue) error { for i := range issues { p.printIssue(&issues[i]) @@ -55,32 +55,32 @@ func (p *Text) Print(ctx context.Context, issues []result.Issue) error { return nil } -func (p *Text) printIssue(i *result.Issue) { - text := p.SprintfColored(color.FgRed, "%s", strings.TrimSpace(i.Text)) +func (p *Text) printIssue(issue *result.Issue) { + text := p.SprintfColored(color.FgRed, "%s", strings.TrimSpace(issue.Text)) if p.printLinterName { - text += fmt.Sprintf(" (%s)", i.FromLinter) + text += fmt.Sprintf(" (%s)", issue.FromLinter) } - pos := p.SprintfColored(color.Bold, "%s:%d", i.FilePath(), i.Line()) - if i.Pos.Column != 0 { - pos += fmt.Sprintf(":%d", i.Pos.Column) + pos := p.SprintfColored(color.Bold, "%s:%d", issue.FilePath(), issue.Line()) + if issue.Pos.Column != 0 { + pos += fmt.Sprintf(":%d", issue.Pos.Column) } fmt.Fprintf(p.w, "%s: %s\n", pos, text) } -func (p *Text) printSourceCode(i *result.Issue) { - for _, line := range i.SourceLines { +func (p *Text) printSourceCode(issue *result.Issue) { + for _, line := range issue.SourceLines { fmt.Fprintln(p.w, line) } } -func (p Text) printUnderLinePointer(i *result.Issue) { +func (p *Text) printUnderLinePointer(issue *result.Issue) { // if column == 0 it means column is unknown (e.g. for gosec) - if len(i.SourceLines) != 1 || i.Pos.Column == 0 { + if len(issue.SourceLines) != 1 || issue.Pos.Column == 0 { return } - col0 := i.Pos.Column - 1 - line := i.SourceLines[0] + col0 := issue.Pos.Column - 1 + line := issue.SourceLines[0] prefixRunes := make([]rune, 0, len(line)) for j := 0; j < len(line) && j < col0; j++ { if line[j] == '\t' { diff --git a/pkg/printers/text_test.go b/pkg/printers/text_test.go index 18f7c272f872..f75313490727 100644 --- a/pkg/printers/text_test.go +++ b/pkg/printers/text_test.go @@ -2,10 +2,10 @@ package printers import ( "bytes" - "context" "go/token" "testing" + "github.com/fatih/color" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -14,6 +14,13 @@ import ( ) func TestText_Print(t *testing.T) { + // force color globally + backup := color.NoColor + t.Cleanup(func() { + color.NoColor = backup + }) + color.NoColor = false + issues := []result.Issue{ { FromLinter: "linter-a", @@ -44,19 +51,78 @@ func TestText_Print(t *testing.T) { }, } - buf := new(bytes.Buffer) - - printer := NewText(true, false, true, logutils.NewStderrLog(logutils.DebugKeyEmpty), buf) - - err := printer.Print(context.Background(), issues) - require.NoError(t, err) - - expected := `path/to/filea.go:10:4: some issue (linter-a) + testCases := []struct { + desc string + printIssuedLine bool + printLinterName bool + useColors bool + expected string + }{ + { + desc: "printIssuedLine and printLinterName", + printIssuedLine: true, + printLinterName: true, + useColors: false, + expected: `path/to/filea.go:10:4: some issue (linter-a) +path/to/fileb.go:300:9: another issue (linter-b) +func foo() { + fmt.Println("bar") +} +`, + }, + { + desc: "printLinterName only", + printIssuedLine: false, + printLinterName: true, + useColors: false, + expected: `path/to/filea.go:10:4: some issue (linter-a) path/to/fileb.go:300:9: another issue (linter-b) +`, + }, + { + desc: "printIssuedLine only", + printIssuedLine: true, + printLinterName: false, + useColors: false, + expected: `path/to/filea.go:10:4: some issue +path/to/fileb.go:300:9: another issue func foo() { fmt.Println("bar") } -` +`, + }, + { + desc: "enable all options", + printIssuedLine: true, + printLinterName: true, + useColors: true, + //nolint:lll // color characters must be in a simple string. + expected: "\x1b[1mpath/to/filea.go:10\x1b[22m:4: \x1b[31msome issue\x1b[0m (linter-a)\n\x1b[1mpath/to/fileb.go:300\x1b[22m:9: \x1b[31manother issue\x1b[0m (linter-b)\nfunc foo() {\n\tfmt.Println(\"bar\")\n}\n", + }, + { + desc: "disable all options", + printIssuedLine: false, + printLinterName: false, + useColors: false, + expected: `path/to/filea.go:10:4: some issue +path/to/fileb.go:300:9: another issue +`, + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + buf := new(bytes.Buffer) - assert.Equal(t, expected, buf.String()) + printer := NewText(test.printIssuedLine, test.useColors, test.printLinterName, logutils.NewStderrLog(logutils.DebugKeyEmpty), buf) + + err := printer.Print(issues) + require.NoError(t, err) + + assert.Equal(t, test.expected, buf.String()) + }) + } } diff --git a/pkg/report/log.go b/pkg/report/log.go index 45ab6cae859d..61665f28b759 100644 --- a/pkg/report/log.go +++ b/pkg/report/log.go @@ -20,20 +20,20 @@ func NewLogWrapper(log logutils.Log, reportData *Data) *LogWrapper { } } -func (lw LogWrapper) Fatalf(format string, args ...interface{}) { +func (lw LogWrapper) Fatalf(format string, args ...any) { lw.origLog.Fatalf(format, args...) } -func (lw LogWrapper) Panicf(format string, args ...interface{}) { +func (lw LogWrapper) Panicf(format string, args ...any) { lw.origLog.Panicf(format, args...) } -func (lw LogWrapper) Errorf(format string, args ...interface{}) { +func (lw LogWrapper) Errorf(format string, args ...any) { lw.origLog.Errorf(format, args...) lw.rd.Error = fmt.Sprintf(format, args...) } -func (lw LogWrapper) Warnf(format string, args ...interface{}) { +func (lw LogWrapper) Warnf(format string, args ...any) { lw.origLog.Warnf(format, args...) w := Warning{ Tag: strings.Join(lw.tags, "/"), @@ -43,7 +43,7 @@ func (lw LogWrapper) Warnf(format string, args ...interface{}) { lw.rd.Warnings = append(lw.rd.Warnings, w) } -func (lw LogWrapper) Infof(format string, args ...interface{}) { +func (lw LogWrapper) Infof(format string, args ...any) { lw.origLog.Infof(format, args...) } diff --git a/pkg/result/processors/autogenerated_exclude.go b/pkg/result/processors/autogenerated_exclude.go index 5e41fd6a94d3..9f4092425f29 100644 --- a/pkg/result/processors/autogenerated_exclude.go +++ b/pkg/result/processors/autogenerated_exclude.go @@ -1,37 +1,48 @@ package processors import ( + "errors" + "fmt" "go/parser" "go/token" "path/filepath" + "regexp" "strings" - "github.com/pkg/errors" - "github.com/golangci/golangci-lint/pkg/logutils" "github.com/golangci/golangci-lint/pkg/result" ) -var autogenDebugf = logutils.Debug(logutils.DebugKeyAutogenExclude) +const ( + genCodeGenerated = "code generated" + genDoNotEdit = "do not edit" + genAutoFile = "autogenerated file" // easyjson +) -type ageFileSummary struct { - isGenerated bool -} +var _ Processor = &AutogeneratedExclude{} -type ageFileSummaryCache map[string]*ageFileSummary +type fileSummary struct { + generated bool +} type AutogeneratedExclude struct { - fileSummaryCache ageFileSummaryCache + debugf logutils.DebugFunc + + strict bool + strictPattern *regexp.Regexp + + fileSummaryCache map[string]*fileSummary } -func NewAutogeneratedExclude() *AutogeneratedExclude { +func NewAutogeneratedExclude(strict bool) *AutogeneratedExclude { return &AutogeneratedExclude{ - fileSummaryCache: ageFileSummaryCache{}, + debugf: logutils.Debug(logutils.DebugKeyAutogenExclude), + strict: strict, + strictPattern: regexp.MustCompile(`^// Code generated .* DO NOT EDIT\.$`), + fileSummaryCache: map[string]*fileSummary{}, } } -var _ Processor = &AutogeneratedExclude{} - func (p *AutogeneratedExclude) Name() string { return "autogenerated_exclude" } @@ -40,86 +51,116 @@ func (p *AutogeneratedExclude) Process(issues []result.Issue) ([]result.Issue, e return filterIssuesErr(issues, p.shouldPassIssue) } -func isSpecialAutogeneratedFile(filePath string) bool { - fileName := filepath.Base(filePath) - // fake files or generation definitions to which //line points to for generated files - return filepath.Ext(fileName) != ".go" -} +func (p *AutogeneratedExclude) Finish() {} -func (p *AutogeneratedExclude) shouldPassIssue(i *result.Issue) (bool, error) { - if i.FromLinter == "typecheck" { +func (p *AutogeneratedExclude) shouldPassIssue(issue *result.Issue) (bool, error) { + if issue.FromLinter == "typecheck" { // don't hide typechecking errors in generated files: users expect to see why the project isn't compiling return true, nil } - if filepath.Base(i.FilePath()) == "go.mod" { + if filepath.Base(issue.FilePath()) == "go.mod" { return true, nil } - if isSpecialAutogeneratedFile(i.FilePath()) { + if issue.FilePath() == "" { + return false, errors.New("no file path for issue") + } + + if !isGoFile(issue.FilePath()) { return false, nil } - fs, err := p.getOrCreateFileSummary(i) - if err != nil { - return false, err + // The file is already known. + fs := p.fileSummaryCache[issue.FilePath()] + if fs != nil { + return !fs.generated, nil + } + + fs = &fileSummary{} + p.fileSummaryCache[issue.FilePath()] = fs + + if p.strict { + var err error + fs.generated, err = p.isGeneratedFileStrict(issue.FilePath()) + if err != nil { + return false, fmt.Errorf("failed to get doc (strict) of file %s: %w", issue.FilePath(), err) + } + } else { + doc, err := getComments(issue.FilePath()) + if err != nil { + return false, fmt.Errorf("failed to get doc (lax) of file %s: %w", issue.FilePath(), err) + } + + fs.generated = p.isGeneratedFileLax(doc) } + p.debugf("file %q is generated: %t", issue.FilePath(), fs.generated) + // don't report issues for autogenerated files - return !fs.isGenerated, nil + return !fs.generated, nil } -// isGenerated reports whether the source file is generated code. -// Using a bit laxer rules than https://go.dev/s/generatedcode to -// match more generated code. See #48 and #72. -func isGeneratedFileByComment(doc string) bool { - const ( - genCodeGenerated = "code generated" - genDoNotEdit = "do not edit" - genAutoFile = "autogenerated file" // easyjson - ) - +// isGeneratedFileLax reports whether the source file is generated code. +// The function uses a bit laxer rules than isGeneratedFileStrict to match more generated code. +// See https://github.com/golangci/golangci-lint/issues/48 and https://github.com/golangci/golangci-lint/issues/72. +func (p *AutogeneratedExclude) isGeneratedFileLax(doc string) bool { markers := []string{genCodeGenerated, genDoNotEdit, genAutoFile} + doc = strings.ToLower(doc) + for _, marker := range markers { if strings.Contains(doc, marker) { - autogenDebugf("doc contains marker %q: file is generated", marker) + p.debugf("doc contains marker %q: file is generated", marker) + return true } } - autogenDebugf("doc of len %d doesn't contain any of markers: %s", len(doc), markers) + p.debugf("doc of len %d doesn't contain any of markers: %s", len(doc), markers) + return false } -func (p *AutogeneratedExclude) getOrCreateFileSummary(i *result.Issue) (*ageFileSummary, error) { - fs := p.fileSummaryCache[i.FilePath()] - if fs != nil { - return fs, nil +// isGeneratedFileStrict returns true if the source file has a line that matches the regular expression: +// +// ^// Code generated .* DO NOT EDIT\.$ +// +// This line must appear before the first non-comment, non-blank text in the file. +// Based on https://go.dev/s/generatedcode. +func (p *AutogeneratedExclude) isGeneratedFileStrict(filePath string) (bool, error) { + file, err := parser.ParseFile(token.NewFileSet(), filePath, nil, parser.PackageClauseOnly|parser.ParseComments) + if err != nil { + return false, fmt.Errorf("failed to parse file: %w", err) } - fs = &ageFileSummary{} - p.fileSummaryCache[i.FilePath()] = fs - - if i.FilePath() == "" { - return nil, errors.New("no file path for issue") + if file == nil || len(file.Comments) == 0 { + return false, nil } - doc, err := getDoc(i.FilePath()) - if err != nil { - return nil, errors.Wrapf(err, "failed to get doc of file %s", i.FilePath()) + for _, comment := range file.Comments { + if comment.Pos() > file.Package { + return false, nil + } + + for _, line := range comment.List { + generated := p.strictPattern.MatchString(line.Text) + if generated { + p.debugf("doc contains ignore expression: file is generated") + + return true, nil + } + } } - fs.isGenerated = isGeneratedFileByComment(doc) - autogenDebugf("file %q is generated: %t", i.FilePath(), fs.isGenerated) - return fs, nil + return false, nil } -func getDoc(filePath string) (string, error) { +func getComments(filePath string) (string, error) { fset := token.NewFileSet() syntax, err := parser.ParseFile(fset, filePath, nil, parser.PackageClauseOnly|parser.ParseComments) if err != nil { - return "", errors.Wrap(err, "failed to parse file") + return "", fmt.Errorf("failed to parse file: %w", err) } var docLines []string @@ -130,4 +171,6 @@ func getDoc(filePath string) (string, error) { return strings.Join(docLines, "\n"), nil } -func (p *AutogeneratedExclude) Finish() {} +func isGoFile(name string) bool { + return filepath.Ext(name) == ".go" +} diff --git a/pkg/result/processors/autogenerated_exclude_test.go b/pkg/result/processors/autogenerated_exclude_test.go index 04e38a4dbc5d..c3291e4e3c2d 100644 --- a/pkg/result/processors/autogenerated_exclude_test.go +++ b/pkg/result/processors/autogenerated_exclude_test.go @@ -1,80 +1,119 @@ package processors import ( + "fmt" + "go/token" "path/filepath" - "strings" + "runtime" "testing" "github.com/stretchr/testify/assert" -) - -func TestIsAutogeneratedDetection(t *testing.T) { - all := ` - // generated by stringer -type Pill pill.go; DO NOT EDIT - -// Code generated by "stringer -type Pill pill.go"; DO NOT EDIT - -// Code generated by vfsgen; DO NOT EDIT - -// Created by cgo -godefs - DO NOT EDIT - -/* Created by cgo - DO NOT EDIT. */ - -// Generated by stringer -i a.out.go -o anames.go -p ppc64 -// Do not edit. - -// DO NOT EDIT -// generated by: x86map -fmt=decoder ../x86.csv - -// DO NOT EDIT. -// Generate with: go run gen.go -full -output md5block.go + "github.com/stretchr/testify/require" -// generated by "go run gen.go". DO NOT EDIT. - -// DO NOT EDIT. This file is generated by mksyntaxgo from the RE2 distribution. - -// GENERATED BY make_perl_groups.pl; DO NOT EDIT. - -// generated by mknacl.sh - do not edit + "github.com/golangci/golangci-lint/pkg/result" +) -// DO NOT EDIT ** This file was generated with the bake tool ** DO NOT EDIT // +func TestAutogeneratedExclude_isGeneratedFileLax_generated(t *testing.T) { + p := NewAutogeneratedExclude(false) -// Generated by running + comments := []string{ + ` // generated by stringer -type Pill pill.go; DO NOT EDIT`, + `// Code generated by "stringer -type Pill pill.go"; DO NOT EDIT`, + `// Code generated by vfsgen; DO NOT EDIT`, + `// Created by cgo -godefs - DO NOT EDIT`, + `/* Created by cgo - DO NOT EDIT. */`, + `// Generated by stringer -i a.out.go -o anames.go -p ppc64 +// Do not edit.`, + `// DO NOT EDIT +// generated by: x86map -fmt=decoder ../x86.csv`, + `// DO NOT EDIT. +// Generate with: go run gen.go -full -output md5block.go`, + `// generated by "go run gen.go". DO NOT EDIT.`, + `// DO NOT EDIT. This file is generated by mksyntaxgo from the RE2 distribution.`, + `// GENERATED BY make_perl_groups.pl; DO NOT EDIT.`, + `// generated by mknacl.sh - do not edit`, + `// DO NOT EDIT ** This file was generated with the bake tool ** DO NOT EDIT //`, + `// Generated by running // maketables --tables=all --data=http://www.unicode.org/Public/8.0.0/ucd/UnicodeData.txt // --casefolding=http://www.unicode.org/Public/8.0.0/ucd/CaseFolding.txt -// DO NOT EDIT - -/* +// DO NOT EDIT`, + `/* * CODE GENERATED AUTOMATICALLY WITH github.com/ernesto-jimenez/gogen/unmarshalmap * THIS FILE SHOULD NOT BE EDITED BY HAND -*/ + */`, + `// AUTOGENERATED FILE: easyjson file.go`, + } -// AUTOGENERATED FILE: easyjson file.go -` + for _, comment := range comments { + comment := comment + t.Run(comment, func(t *testing.T) { + t.Parallel() - generatedCases := strings.Split(all, "\n\n") - for _, gc := range generatedCases { - isGenerated := isGeneratedFileByComment(gc) - assert.True(t, isGenerated) + generated := p.isGeneratedFileLax(comment) + assert.True(t, generated) + }) } +} - notGeneratedCases := []string{ +func TestAutogeneratedExclude_isGeneratedFileLax_nonGenerated(t *testing.T) { + p := NewAutogeneratedExclude(false) + + comments := []string{ "code not generated by", "test", } - for _, ngc := range notGeneratedCases { - isGenerated := isGeneratedFileByComment(ngc) - assert.False(t, isGenerated) + + for _, comment := range comments { + comment := comment + t.Run(comment, func(t *testing.T) { + t.Parallel() + + generated := p.isGeneratedFileLax(comment) + assert.False(t, generated) + }) + } +} + +func TestAutogeneratedExclude_isGeneratedFileStrict(t *testing.T) { + p := NewAutogeneratedExclude(true) + + testCases := []struct { + desc string + filepath string + assert assert.BoolAssertionFunc + }{ + { + desc: "", + filepath: filepath.FromSlash("testdata/autogen_go_strict.go"), + assert: assert.True, + }, + { + desc: "", + filepath: filepath.FromSlash("testdata/autogen_go_strict_invalid.go"), + assert: assert.False, + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + generated, err := p.isGeneratedFileStrict(test.filepath) + require.NoError(t, err) + + test.assert(t, generated) + }) } } -func TestGetDoc(t *testing.T) { +func Test_getComments(t *testing.T) { testCases := []struct { fpath string doc string }{ { - fpath: filepath.Join("testdata", "autogen_exclude.go"), + fpath: filepath.FromSlash("testdata/autogen_exclude.go"), doc: `first line second line third line @@ -82,11 +121,11 @@ this text also and this text also`, }, { - fpath: filepath.Join("testdata", "autogen_exclude_doc.go"), + fpath: filepath.FromSlash("testdata/autogen_exclude_doc.go"), doc: `DO NOT EDIT`, }, { - fpath: filepath.Join("testdata", "autogen_exclude_block_comment.go"), + fpath: filepath.FromSlash("testdata/autogen_exclude_block_comment.go"), doc: `* first line * * second line @@ -98,16 +137,156 @@ this one line comment also`, } for _, tc := range testCases { - doc, err := getDoc(tc.fpath) - assert.NoError(t, err) + doc, err := getComments(tc.fpath) + require.NoError(t, err) assert.Equal(t, tc.doc, doc) } } // Issue 954: Some lines can be very long, e.g. auto-generated // embedded resources. Reported on file of 86.2KB. -func TestGetDocFileWithLongLine(t *testing.T) { - fpath := filepath.Join("testdata", "autogen_exclude_long_line.go") - _, err := getDoc(fpath) +func Test_getComments_fileWithLongLine(t *testing.T) { + fpath := filepath.FromSlash("testdata/autogen_exclude_long_line.go") + _, err := getComments(fpath) assert.NoError(t, err) } + +func Test_shouldPassIssue(t *testing.T) { + testCases := []struct { + desc string + strict bool + issue *result.Issue + assert assert.BoolAssertionFunc + }{ + { + desc: "typecheck issue", + strict: false, + issue: &result.Issue{ + FromLinter: "typecheck", + }, + assert: assert.True, + }, + { + desc: "go.mod", + strict: false, + issue: &result.Issue{ + FromLinter: "example", + Pos: token.Position{ + Filename: filepath.FromSlash("/a/b/c/go.mod"), + }, + }, + assert: assert.True, + }, + { + desc: "non Go file", + strict: false, + issue: &result.Issue{ + FromLinter: "example", + Pos: token.Position{ + Filename: filepath.FromSlash("/a/b/c/test.txt"), + }, + }, + assert: assert.False, + }, + { + desc: "lax ", + strict: false, + issue: &result.Issue{ + FromLinter: "example", + Pos: token.Position{ + Filename: filepath.FromSlash("testdata/autogen_go_strict_invalid.go"), + }, + }, + assert: assert.False, + }, + { + desc: "strict ", + strict: true, + issue: &result.Issue{ + FromLinter: "example", + Pos: token.Position{ + Filename: filepath.FromSlash("testdata/autogen_go_strict_invalid.go"), + }, + }, + assert: assert.True, + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + p := NewAutogeneratedExclude(test.strict) + + pass, err := p.shouldPassIssue(test.issue) + require.NoError(t, err) + + test.assert(t, pass) + }) + } +} + +func Test_shouldPassIssue_error(t *testing.T) { + notFoundMsg := "no such file or directory" + if runtime.GOOS == "windows" { + notFoundMsg = "The system cannot find the file specified." + } + + testCases := []struct { + desc string + strict bool + issue *result.Issue + expected string + }{ + { + desc: "missing Filename", + strict: false, + issue: &result.Issue{ + FromLinter: "example", + Pos: token.Position{ + Filename: "", + }, + }, + expected: "no file path for issue", + }, + { + desc: "non-existing file (lax)", + strict: false, + issue: &result.Issue{ + FromLinter: "example", + Pos: token.Position{ + Filename: filepath.FromSlash("no-existing.go"), + }, + }, + expected: fmt.Sprintf("failed to get doc (lax) of file %[1]s: failed to parse file: open %[1]s: %[2]s", + filepath.FromSlash("no-existing.go"), notFoundMsg), + }, + { + desc: "non-existing file (strict)", + strict: true, + issue: &result.Issue{ + FromLinter: "example", + Pos: token.Position{ + Filename: filepath.FromSlash("no-existing.go"), + }, + }, + expected: fmt.Sprintf("failed to get doc (strict) of file %[1]s: failed to parse file: open %[1]s: %[2]s", + filepath.FromSlash("no-existing.go"), notFoundMsg), + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + p := NewAutogeneratedExclude(test.strict) + + pass, err := p.shouldPassIssue(test.issue) + + assert.EqualError(t, err, test.expected) + assert.False(t, pass) + }) + } +} diff --git a/pkg/result/processors/base_rule.go b/pkg/result/processors/base_rule.go index 6958b9f2f37d..88140bfa6b7d 100644 --- a/pkg/result/processors/base_rule.go +++ b/pkg/result/processors/base_rule.go @@ -8,32 +8,39 @@ import ( "github.com/golangci/golangci-lint/pkg/result" ) +const caseInsensitivePrefix = "(?i)" + type BaseRule struct { - Text string - Source string - Path string - Linters []string + Text string + Source string + Path string + PathExcept string + Linters []string } type baseRule struct { - text *regexp.Regexp - source *regexp.Regexp - path *regexp.Regexp - linters []string + text *regexp.Regexp + source *regexp.Regexp + path *regexp.Regexp + pathExcept *regexp.Regexp + linters []string } func (r *baseRule) isEmpty() bool { - return r.text == nil && r.source == nil && r.path == nil && len(r.linters) == 0 + return r.text == nil && r.source == nil && r.path == nil && r.pathExcept == nil && len(r.linters) == 0 } -func (r *baseRule) match(issue *result.Issue, lineCache *fsutils.LineCache, log logutils.Log) bool { +func (r *baseRule) match(issue *result.Issue, files *fsutils.Files, log logutils.Log) bool { if r.isEmpty() { return false } if r.text != nil && !r.text.MatchString(issue.Text) { return false } - if r.path != nil && !r.path.MatchString(issue.FilePath()) { + if r.path != nil && !r.path.MatchString(files.WithPathPrefix(issue.FilePath())) { + return false + } + if r.pathExcept != nil && r.pathExcept.MatchString(issue.FilePath()) { return false } if len(r.linters) != 0 && !r.matchLinter(issue) { @@ -41,7 +48,7 @@ func (r *baseRule) match(issue *result.Issue, lineCache *fsutils.LineCache, log } // the most heavyweight checking last - if r.source != nil && !r.matchSource(issue, lineCache, log) { + if r.source != nil && !r.matchSource(issue, files.LineCache, log) { return false } diff --git a/pkg/result/processors/cgo.go b/pkg/result/processors/cgo.go index c8793871ac97..1ad73c31afe4 100644 --- a/pkg/result/processors/cgo.go +++ b/pkg/result/processors/cgo.go @@ -1,11 +1,10 @@ package processors import ( + "fmt" "path/filepath" "strings" - "github.com/pkg/errors" - "github.com/golangci/golangci-lint/pkg/goutil" "github.com/golangci/golangci-lint/pkg/result" ) @@ -27,17 +26,17 @@ func (p Cgo) Name() string { } func (p Cgo) Process(issues []result.Issue) ([]result.Issue, error) { - return filterIssuesErr(issues, func(i *result.Issue) (bool, error) { - // some linters (.e.g gosec, deadcode) return incorrect filepaths for cgo issues, + return filterIssuesErr(issues, func(issue *result.Issue) (bool, error) { + // some linters (e.g. gosec, deadcode) return incorrect filepaths for cgo issues, // also cgo files have strange issues looking like false positives. // cache dir contains all preprocessed files including cgo files - issueFilePath := i.FilePath() - if !filepath.IsAbs(i.FilePath()) { - absPath, err := filepath.Abs(i.FilePath()) + issueFilePath := issue.FilePath() + if !filepath.IsAbs(issue.FilePath()) { + absPath, err := filepath.Abs(issue.FilePath()) if err != nil { - return false, errors.Wrapf(err, "failed to build abs path for %q", i.FilePath()) + return false, fmt.Errorf("failed to build abs path for %q: %w", issue.FilePath(), err) } issueFilePath = absPath } @@ -46,7 +45,7 @@ func (p Cgo) Process(issues []result.Issue) ([]result.Issue, error) { return false, nil } - if filepath.Base(i.FilePath()) == "_cgo_gotypes.go" { + if filepath.Base(issue.FilePath()) == "_cgo_gotypes.go" { // skip cgo warning for go1.10 return false, nil } diff --git a/pkg/result/processors/diff.go b/pkg/result/processors/diff.go index 67104bab0a76..d607b02182a9 100644 --- a/pkg/result/processors/diff.go +++ b/pkg/result/processors/diff.go @@ -47,7 +47,7 @@ func (p Diff) Process(issues []result.Issue) ([]result.Issue, error) { if p.patchFilePath != "" { patch, err := os.ReadFile(p.patchFilePath) if err != nil { - return nil, fmt.Errorf("can't read from patch file %s: %s", p.patchFilePath, err) + return nil, fmt.Errorf("can't read from patch file %s: %w", p.patchFilePath, err) } patchReader = bytes.NewReader(patch) } else if p.patch != "" { @@ -60,18 +60,18 @@ func (p Diff) Process(issues []result.Issue) ([]result.Issue, error) { WholeFiles: p.wholeFiles, } if err := c.Prepare(); err != nil { - return nil, fmt.Errorf("can't prepare diff by revgrep: %s", err) + return nil, fmt.Errorf("can't prepare diff by revgrep: %w", err) } - return transformIssues(issues, func(i *result.Issue) *result.Issue { - hunkPos, isNew := c.IsNewIssue(i) + return transformIssues(issues, func(issue *result.Issue) *result.Issue { + hunkPos, isNew := c.IsNewIssue(issue) if !isNew { return nil } - newI := *i - newI.HunkPos = hunkPos - return &newI + newIssue := *issue + newIssue.HunkPos = hunkPos + return &newIssue }), nil } diff --git a/pkg/result/processors/exclude.go b/pkg/result/processors/exclude.go index 92959a328ca2..05a56ef9656e 100644 --- a/pkg/result/processors/exclude.go +++ b/pkg/result/processors/exclude.go @@ -6,24 +6,37 @@ import ( "github.com/golangci/golangci-lint/pkg/result" ) +var _ Processor = Exclude{} + type Exclude struct { + name string + pattern *regexp.Regexp } -var _ Processor = Exclude{} +type ExcludeOptions struct { + Pattern string + CaseSensitive bool +} -func NewExclude(pattern string) *Exclude { - var patternRe *regexp.Regexp - if pattern != "" { - patternRe = regexp.MustCompile("(?i)" + pattern) +func NewExclude(opts ExcludeOptions) *Exclude { + p := &Exclude{name: "exclude"} + + prefix := caseInsensitivePrefix + if opts.CaseSensitive { + p.name = "exclude-case-sensitive" + prefix = "" } - return &Exclude{ - pattern: patternRe, + + if opts.Pattern != "" { + p.pattern = regexp.MustCompile(prefix + opts.Pattern) } + + return p } func (p Exclude) Name() string { - return "exclude" + return p.name } func (p Exclude) Process(issues []result.Issue) ([]result.Issue, error) { @@ -31,29 +44,9 @@ func (p Exclude) Process(issues []result.Issue) ([]result.Issue, error) { return issues, nil } - return filterIssues(issues, func(i *result.Issue) bool { - return !p.pattern.MatchString(i.Text) + return filterIssues(issues, func(issue *result.Issue) bool { + return !p.pattern.MatchString(issue.Text) }), nil } func (p Exclude) Finish() {} - -type ExcludeCaseSensitive struct { - *Exclude -} - -var _ Processor = ExcludeCaseSensitive{} - -func NewExcludeCaseSensitive(pattern string) *ExcludeCaseSensitive { - var patternRe *regexp.Regexp - if pattern != "" { - patternRe = regexp.MustCompile(pattern) - } - return &ExcludeCaseSensitive{ - &Exclude{pattern: patternRe}, - } -} - -func (p ExcludeCaseSensitive) Name() string { - return "exclude-case-sensitive" -} diff --git a/pkg/result/processors/exclude_rules.go b/pkg/result/processors/exclude_rules.go index 62533b811533..a20d56d05d41 100644 --- a/pkg/result/processors/exclude_rules.go +++ b/pkg/result/processors/exclude_rules.go @@ -8,6 +8,8 @@ import ( "github.com/golangci/golangci-lint/pkg/result" ) +var _ Processor = ExcludeRules{} + type excludeRule struct { baseRule } @@ -17,49 +19,45 @@ type ExcludeRule struct { } type ExcludeRules struct { - rules []excludeRule - lineCache *fsutils.LineCache - log logutils.Log -} + name string -func NewExcludeRules(rules []ExcludeRule, lineCache *fsutils.LineCache, log logutils.Log) *ExcludeRules { - r := &ExcludeRules{ - lineCache: lineCache, - log: log, - } - r.rules = createRules(rules, "(?i)") + log logutils.Log + files *fsutils.Files - return r + rules []excludeRule } -func createRules(rules []ExcludeRule, prefix string) []excludeRule { - parsedRules := make([]excludeRule, 0, len(rules)) - for _, rule := range rules { - parsedRule := excludeRule{} - parsedRule.linters = rule.Linters - if rule.Text != "" { - parsedRule.text = regexp.MustCompile(prefix + rule.Text) - } - if rule.Source != "" { - parsedRule.source = regexp.MustCompile(prefix + rule.Source) - } - if rule.Path != "" { - path := fsutils.NormalizePathInRegex(rule.Path) - parsedRule.path = regexp.MustCompile(path) - } - parsedRules = append(parsedRules, parsedRule) +type ExcludeRulesOptions struct { + Rules []ExcludeRule + CaseSensitive bool +} + +func NewExcludeRules(log logutils.Log, files *fsutils.Files, opts ExcludeRulesOptions) *ExcludeRules { + p := &ExcludeRules{ + name: "exclude-rules", + files: files, + log: log, } - return parsedRules + + prefix := caseInsensitivePrefix + if opts.CaseSensitive { + prefix = "" + p.name = "exclude-rules-case-sensitive" + } + + p.rules = createRules(opts.Rules, prefix) + + return p } func (p ExcludeRules) Process(issues []result.Issue) ([]result.Issue, error) { if len(p.rules) == 0 { return issues, nil } - return filterIssues(issues, func(i *result.Issue) bool { + return filterIssues(issues, func(issue *result.Issue) bool { for _, rule := range p.rules { rule := rule - if rule.match(i, p.lineCache, p.log) { + if rule.match(issue, p.files, p.log) { return false } } @@ -67,25 +65,35 @@ func (p ExcludeRules) Process(issues []result.Issue) ([]result.Issue, error) { }), nil } -func (ExcludeRules) Name() string { return "exclude-rules" } -func (ExcludeRules) Finish() {} +func (p ExcludeRules) Name() string { return p.name } -var _ Processor = ExcludeRules{} +func (ExcludeRules) Finish() {} -type ExcludeRulesCaseSensitive struct { - *ExcludeRules -} +func createRules(rules []ExcludeRule, prefix string) []excludeRule { + parsedRules := make([]excludeRule, 0, len(rules)) -func NewExcludeRulesCaseSensitive(rules []ExcludeRule, lineCache *fsutils.LineCache, log logutils.Log) *ExcludeRulesCaseSensitive { - r := &ExcludeRules{ - lineCache: lineCache, - log: log, - } - r.rules = createRules(rules, "") + for _, rule := range rules { + parsedRule := excludeRule{} + parsedRule.linters = rule.Linters - return &ExcludeRulesCaseSensitive{r} -} + if rule.Text != "" { + parsedRule.text = regexp.MustCompile(prefix + rule.Text) + } -func (ExcludeRulesCaseSensitive) Name() string { return "exclude-rules-case-sensitive" } + if rule.Source != "" { + parsedRule.source = regexp.MustCompile(prefix + rule.Source) + } + + if rule.Path != "" { + parsedRule.path = regexp.MustCompile(fsutils.NormalizePathInRegex(rule.Path)) + } + + if rule.PathExcept != "" { + parsedRule.pathExcept = regexp.MustCompile(fsutils.NormalizePathInRegex(rule.PathExcept)) + } + + parsedRules = append(parsedRules, parsedRule) + } -var _ Processor = ExcludeCaseSensitive{} + return parsedRules +} diff --git a/pkg/result/processors/exclude_rules_test.go b/pkg/result/processors/exclude_rules_test.go index c247e6ab0f84..96f6788e0933 100644 --- a/pkg/result/processors/exclude_rules_test.go +++ b/pkg/result/processors/exclude_rules_test.go @@ -1,6 +1,7 @@ package processors import ( + "path" "path/filepath" "testing" @@ -10,9 +11,11 @@ import ( "github.com/golangci/golangci-lint/pkg/result" ) -func TestExcludeRulesMultiple(t *testing.T) { +func TestExcludeRules_multiple(t *testing.T) { lineCache := fsutils.NewLineCache(fsutils.NewFileCache()) - p := NewExcludeRules([]ExcludeRule{ + files := fsutils.NewFiles(lineCache, "") + + opts := ExcludeRulesOptions{Rules: []ExcludeRule{ { BaseRule: BaseRule{ Text: "^exclude$", @@ -31,14 +34,23 @@ func TestExcludeRulesMultiple(t *testing.T) { Path: `_test\.go`, }, }, + { + BaseRule: BaseRule{ + Text: "^nontestonly$", + PathExcept: `_test\.go`, + }, + }, { BaseRule: BaseRule{ Source: "^//go:generate ", Linters: []string{"lll"}, }, }, - }, lineCache, nil) + }} + + p := NewExcludeRules(nil, files, opts) + //nolint:dupl cases := []issueTestCase{ {Path: "e.go", Text: "exclude", Linter: "linter"}, {Path: "e.go", Text: "some", Linter: "linter"}, @@ -46,13 +58,18 @@ func TestExcludeRulesMultiple(t *testing.T) { {Path: "e_Test.go", Text: "normal", Linter: "testlinter"}, {Path: "e_test.go", Text: "another", Linter: "linter"}, {Path: "e_test.go", Text: "testonly", Linter: "linter"}, + {Path: "e.go", Text: "nontestonly", Linter: "linter"}, + {Path: "e_test.go", Text: "nontestonly", Linter: "linter"}, {Path: filepath.Join("testdata", "exclude_rules.go"), Line: 3, Linter: "lll"}, } + var issues []result.Issue for _, c := range cases { issues = append(issues, newIssueFromIssueTestCase(c)) } + processedIssues := process(t, p, issues...) + var resultingCases []issueTestCase for _, i := range processedIssues { resultingCases = append(resultingCases, issueTestCase{ @@ -62,23 +79,77 @@ func TestExcludeRulesMultiple(t *testing.T) { Line: i.Line(), }) } + expectedCases := []issueTestCase{ {Path: "e.go", Text: "some", Linter: "linter"}, {Path: "e_Test.go", Text: "normal", Linter: "testlinter"}, {Path: "e_test.go", Text: "another", Linter: "linter"}, + {Path: "e_test.go", Text: "nontestonly", Linter: "linter"}, } + assert.Equal(t, expectedCases, resultingCases) } -func TestExcludeRulesText(t *testing.T) { - p := NewExcludeRules([]ExcludeRule{ - { - BaseRule: BaseRule{ - Text: "^exclude$", - Linters: []string{"linter"}, +func TestExcludeRules_pathPrefix(t *testing.T) { + lineCache := fsutils.NewLineCache(fsutils.NewFileCache()) + pathPrefix := path.Join("some", "dir") + files := fsutils.NewFiles(lineCache, pathPrefix) + + opts := ExcludeRulesOptions{ + Rules: []ExcludeRule{ + { + BaseRule: BaseRule{ + Path: `some/dir/e\.go`, + }, + }, + }, + } + + p := NewExcludeRules(nil, files, opts) + + cases := []issueTestCase{ + {Path: "e.go"}, + {Path: "other.go"}, + } + + var issues []result.Issue + for _, c := range cases { + issues = append(issues, newIssueFromIssueTestCase(c)) + } + + processedIssues := process(t, p, issues...) + + var resultingCases []issueTestCase + for _, i := range processedIssues { + resultingCases = append(resultingCases, issueTestCase{ + Path: i.FilePath(), + Linter: i.FromLinter, + Text: i.Text, + Line: i.Line(), + }) + } + + expectedCases := []issueTestCase{ + {Path: "other.go"}, + } + + assert.Equal(t, expectedCases, resultingCases) +} + +func TestExcludeRules_text(t *testing.T) { + opts := ExcludeRulesOptions{ + Rules: []ExcludeRule{ + { + BaseRule: BaseRule{ + Text: "^exclude$", + Linters: []string{"linter"}, + }, }, }, - }, nil, nil) + } + + p := NewExcludeRules(nil, nil, opts) + texts := []string{"excLude", "1", "", "exclud", "notexclude"} var issues []result.Issue for _, t := range texts { @@ -95,42 +166,51 @@ func TestExcludeRulesText(t *testing.T) { for _, i := range processedIssues { processedTexts = append(processedTexts, i.Text) } + assert.Equal(t, texts[1:], processedTexts) } -func TestExcludeRulesEmpty(t *testing.T) { - processAssertSame(t, NewExcludeRules(nil, nil, nil), newIssueFromTextTestCase("test")) +func TestExcludeRules_empty(t *testing.T) { + processAssertSame(t, NewExcludeRules(nil, nil, ExcludeRulesOptions{}), newIssueFromTextTestCase("test")) } -func TestExcludeRulesCaseSensitiveMultiple(t *testing.T) { +func TestExcludeRules_caseSensitive_multiple(t *testing.T) { lineCache := fsutils.NewLineCache(fsutils.NewFileCache()) - p := NewExcludeRulesCaseSensitive([]ExcludeRule{ - { - BaseRule: BaseRule{ - Text: "^exclude$", - Linters: []string{"linter"}, + files := fsutils.NewFiles(lineCache, "") + + opts := ExcludeRulesOptions{ + CaseSensitive: true, + Rules: []ExcludeRule{ + { + BaseRule: BaseRule{ + Text: "^exclude$", + Linters: []string{"linter"}, + }, }, - }, - { - BaseRule: BaseRule{ - Linters: []string{"testlinter"}, - Path: `_test\.go`, + { + BaseRule: BaseRule{ + Linters: []string{"testlinter"}, + Path: `_test\.go`, + }, }, - }, - { - BaseRule: BaseRule{ - Text: "^testonly$", - Path: `_test\.go`, + { + BaseRule: BaseRule{ + Text: "^testonly$", + Path: `_test\.go`, + }, }, - }, - { - BaseRule: BaseRule{ - Source: "^//go:generate ", - Linters: []string{"lll"}, + { + BaseRule: BaseRule{ + Source: "^//go:generate ", + Linters: []string{"lll"}, + }, }, }, - }, lineCache, nil) + } + + p := NewExcludeRules(nil, files, opts) + //nolint:dupl cases := []issueTestCase{ {Path: "e.go", Text: "exclude", Linter: "linter"}, {Path: "e.go", Text: "excLude", Linter: "linter"}, @@ -142,11 +222,14 @@ func TestExcludeRulesCaseSensitiveMultiple(t *testing.T) { {Path: "e_test.go", Text: "testOnly", Linter: "linter"}, {Path: filepath.Join("testdata", "exclude_rules_case_sensitive.go"), Line: 3, Linter: "lll"}, } + var issues []result.Issue for _, c := range cases { issues = append(issues, newIssueFromIssueTestCase(c)) } + processedIssues := process(t, p, issues...) + var resultingCases []issueTestCase for _, i := range processedIssues { resultingCases = append(resultingCases, issueTestCase{ @@ -156,6 +239,7 @@ func TestExcludeRulesCaseSensitiveMultiple(t *testing.T) { Line: i.Line(), }) } + expectedCases := []issueTestCase{ {Path: "e.go", Text: "excLude", Linter: "linter"}, {Path: "e.go", Text: "some", Linter: "linter"}, @@ -164,19 +248,27 @@ func TestExcludeRulesCaseSensitiveMultiple(t *testing.T) { {Path: "e_test.go", Text: "testOnly", Linter: "linter"}, {Path: filepath.Join("testdata", "exclude_rules_case_sensitive.go"), Line: 3, Linter: "lll"}, } + assert.Equal(t, expectedCases, resultingCases) } -func TestExcludeRulesCaseSensitiveText(t *testing.T) { - p := NewExcludeRulesCaseSensitive([]ExcludeRule{ - { - BaseRule: BaseRule{ - Text: "^exclude$", - Linters: []string{"linter"}, +func TestExcludeRules_caseSensitive_text(t *testing.T) { + opts := ExcludeRulesOptions{ + CaseSensitive: true, + Rules: []ExcludeRule{ + { + BaseRule: BaseRule{ + Text: "^exclude$", + Linters: []string{"linter"}, + }, }, }, - }, nil, nil) + } + + p := NewExcludeRules(nil, nil, opts) + texts := []string{"exclude", "excLude", "1", "", "exclud", "notexclude"} + var issues []result.Issue for _, t := range texts { issues = append(issues, result.Issue{ @@ -192,9 +284,10 @@ func TestExcludeRulesCaseSensitiveText(t *testing.T) { for _, i := range processedIssues { processedTexts = append(processedTexts, i.Text) } + assert.Equal(t, texts[1:], processedTexts) } -func TestExcludeRulesCaseSensitiveEmpty(t *testing.T) { - processAssertSame(t, NewExcludeRulesCaseSensitive(nil, nil, nil), newIssueFromTextTestCase("test")) +func TestExcludeRules_caseSensitive_empty(t *testing.T) { + processAssertSame(t, NewExcludeRules(nil, nil, ExcludeRulesOptions{CaseSensitive: true}), newIssueFromTextTestCase("test")) } diff --git a/pkg/result/processors/exclude_test.go b/pkg/result/processors/exclude_test.go index 3b92ccd75f83..a62f4ef5c362 100644 --- a/pkg/result/processors/exclude_test.go +++ b/pkg/result/processors/exclude_test.go @@ -9,8 +9,10 @@ import ( ) func TestExclude(t *testing.T) { - p := NewExclude("^exclude$") + p := NewExclude(ExcludeOptions{Pattern: "^exclude$"}) + texts := []string{"excLude", "1", "", "exclud", "notexclude"} + var issues []result.Issue for _, t := range texts { issues = append(issues, newIssueFromTextTestCase(t)) @@ -23,16 +25,19 @@ func TestExclude(t *testing.T) { for _, i := range processedIssues { processedTexts = append(processedTexts, i.Text) } + assert.Equal(t, texts[1:], processedTexts) } -func TestNoExclude(t *testing.T) { - processAssertSame(t, NewExclude(""), newIssueFromTextTestCase("test")) +func TestExclude_empty(t *testing.T) { + processAssertSame(t, NewExclude(ExcludeOptions{}), newIssueFromTextTestCase("test")) } -func TestExcludeCaseSensitive(t *testing.T) { - p := NewExcludeCaseSensitive("^exclude$") +func TestExclude_caseSensitive(t *testing.T) { + p := NewExclude(ExcludeOptions{Pattern: "^exclude$", CaseSensitive: true}) + texts := []string{"excLude", "1", "", "exclud", "exclude"} + var issues []result.Issue for _, t := range texts { issues = append(issues, newIssueFromTextTestCase(t)) @@ -45,5 +50,6 @@ func TestExcludeCaseSensitive(t *testing.T) { for _, i := range processedIssues { processedTexts = append(processedTexts, i.Text) } + assert.Equal(t, texts[:len(texts)-1], processedTexts) } diff --git a/pkg/result/processors/filename_unadjuster.go b/pkg/result/processors/filename_unadjuster.go index 2aaafbf58b37..adf82c823c4d 100644 --- a/pkg/result/processors/filename_unadjuster.go +++ b/pkg/result/processors/filename_unadjuster.go @@ -102,29 +102,29 @@ func (p *FilenameUnadjuster) Name() string { } func (p *FilenameUnadjuster) Process(issues []result.Issue) ([]result.Issue, error) { - return transformIssues(issues, func(i *result.Issue) *result.Issue { - issueFilePath := i.FilePath() - if !filepath.IsAbs(i.FilePath()) { - absPath, err := filepath.Abs(i.FilePath()) + return transformIssues(issues, func(issue *result.Issue) *result.Issue { + issueFilePath := issue.FilePath() + if !filepath.IsAbs(issue.FilePath()) { + absPath, err := filepath.Abs(issue.FilePath()) if err != nil { - p.log.Warnf("failed to build abs path for %q: %s", i.FilePath(), err) - return i + p.log.Warnf("failed to build abs path for %q: %s", issue.FilePath(), err) + return issue } issueFilePath = absPath } mapper := p.m[issueFilePath] if mapper == nil { - return i + return issue } - newI := *i - newI.Pos = mapper(i.Pos) - if !p.loggedUnadjustments[i.Pos.Filename] { - p.log.Infof("Unadjusted from %v to %v", i.Pos, newI.Pos) - p.loggedUnadjustments[i.Pos.Filename] = true + newIssue := *issue + newIssue.Pos = mapper(issue.Pos) + if !p.loggedUnadjustments[issue.Pos.Filename] { + p.log.Infof("Unadjusted from %v to %v", issue.Pos, newIssue.Pos) + p.loggedUnadjustments[issue.Pos.Filename] = true } - return &newI + return &newIssue }), nil } diff --git a/pkg/result/processors/fixer.go b/pkg/result/processors/fixer.go index d125e15793a4..5c6d12ac0f74 100644 --- a/pkg/result/processors/fixer.go +++ b/pkg/result/processors/fixer.go @@ -8,8 +8,6 @@ import ( "sort" "strings" - "github.com/pkg/errors" - "github.com/golangci/golangci-lint/internal/robustio" "github.com/golangci/golangci-lint/pkg/config" "github.com/golangci/golangci-lint/pkg/fsutils" @@ -18,6 +16,8 @@ import ( "github.com/golangci/golangci-lint/pkg/timeutils" ) +var _ Processor = Fixer{} + type Fixer struct { cfg *config.Config log logutils.Log @@ -38,9 +38,9 @@ func (f Fixer) printStat() { f.sw.PrintStages() } -func (f Fixer) Process(issues []result.Issue) []result.Issue { +func (f Fixer) Process(issues []result.Issue) ([]result.Issue, error) { if !f.cfg.Issues.NeedFix { - return issues + return issues, nil } outIssues := make([]result.Issue, 0, len(issues)) @@ -69,22 +69,28 @@ func (f Fixer) Process(issues []result.Issue) []result.Issue { } f.printStat() - return outIssues + return outIssues, nil +} + +func (f Fixer) Name() string { + return "fixer" } +func (f Fixer) Finish() {} + func (f Fixer) fixIssuesInFile(filePath string, issues []result.Issue) error { // TODO: don't read the whole file into memory: read line by line; // can't just use bufio.scanner: it has a line length limit origFileData, err := f.fileCache.GetFileBytes(filePath) if err != nil { - return errors.Wrapf(err, "failed to get file bytes for %s", filePath) + return fmt.Errorf("failed to get file bytes for %s: %w", filePath, err) } origFileLines := bytes.Split(origFileData, []byte("\n")) tmpFileName := filepath.Join(filepath.Dir(filePath), fmt.Sprintf(".%s.golangci_fix", filepath.Base(filePath))) tmpOutFile, err := os.Create(tmpFileName) if err != nil { - return errors.Wrapf(err, "failed to make file %s", tmpFileName) + return fmt.Errorf("failed to make file %s: %w", tmpFileName, err) } // merge multiple issues per line into one issue @@ -112,7 +118,7 @@ func (f Fixer) fixIssuesInFile(filePath string, issues []result.Issue) error { tmpOutFile.Close() if err = robustio.Rename(tmpOutFile.Name(), filePath); err != nil { _ = robustio.RemoveAll(tmpOutFile.Name()) - return errors.Wrapf(err, "failed to rename %s -> %s", tmpOutFile.Name(), filePath) + return fmt.Errorf("failed to rename %s -> %s: %w", tmpOutFile.Name(), filePath, err) } return nil @@ -127,20 +133,22 @@ func (f Fixer) mergeLineIssues(lineNum int, lineIssues []result.Issue, origFileL // check issues first for ind := range lineIssues { - i := &lineIssues[ind] - if i.LineRange != nil { + li := &lineIssues[ind] + + if li.LineRange != nil { f.log.Infof("Line %d has multiple issues but at least one of them is ranged: %#v", lineNum, lineIssues) return &lineIssues[0] } - r := i.Replacement - if r.Inline == nil || len(r.NewLines) != 0 || r.NeedOnlyDelete { + inline := li.Replacement.Inline + + if inline == nil || len(li.Replacement.NewLines) != 0 || li.Replacement.NeedOnlyDelete { f.log.Infof("Line %d has multiple issues but at least one of them isn't inline: %#v", lineNum, lineIssues) - return &lineIssues[0] + return li } - if r.Inline.StartCol < 0 || r.Inline.Length <= 0 || r.Inline.StartCol+r.Inline.Length > len(origLine) { - f.log.Warnf("Line %d (%q) has invalid inline fix: %#v, %#v", lineNum, origLine, i, r.Inline) + if inline.StartCol < 0 || inline.Length <= 0 || inline.StartCol+inline.Length > len(origLine) { + f.log.Warnf("Line %d (%q) has invalid inline fix: %#v, %#v", lineNum, origLine, li, inline) return nil } } @@ -241,7 +249,7 @@ func (f Fixer) writeFixedFile(origFileLines [][]byte, issues []result.Issue, tmp outLine += "\n" } if _, err := tmpOutFile.WriteString(outLine); err != nil { - return errors.Wrap(err, "failed to write output line") + return fmt.Errorf("failed to write output line: %w", err) } } diff --git a/pkg/result/processors/identifier_marker.go b/pkg/result/processors/identifier_marker.go index 5cc4e56ba229..1975f6d08682 100644 --- a/pkg/result/processors/identifier_marker.go +++ b/pkg/result/processors/identifier_marker.go @@ -31,27 +31,39 @@ var replacePatterns = []replacePattern{ {`^composites: (\S+) composite literal uses unkeyed fields$`, "composites: `${1}` composite literal uses unkeyed fields"}, // gosec - {`^(\S+): Blacklisted import (\S+): weak cryptographic primitive$`, - "${1}: Blacklisted import `${2}`: weak cryptographic primitive"}, + { + `^(\S+): Blacklisted import (\S+): weak cryptographic primitive$`, + "${1}: Blacklisted import `${2}`: weak cryptographic primitive", + }, {`^TLS InsecureSkipVerify set true.$`, "TLS `InsecureSkipVerify` set true."}, // gosimple {`should replace loop with (.*)$`, "should replace loop with `${1}`"}, - {`should use a simple channel send/receive instead of select with a single case`, - "should use a simple channel send/receive instead of `select` with a single case"}, - {`should omit comparison to bool constant, can be simplified to (.+)$`, - "should omit comparison to bool constant, can be simplified to `${1}`"}, + { + `should use a simple channel send/receive instead of select with a single case`, + "should use a simple channel send/receive instead of `select` with a single case", + }, + { + `should omit comparison to bool constant, can be simplified to (.+)$`, + "should omit comparison to bool constant, can be simplified to `${1}`", + }, {`should write (.+) instead of (.+)$`, "should write `${1}` instead of `${2}`"}, {`redundant return statement$`, "redundant `return` statement"}, - {`should replace this if statement with an unconditional strings.TrimPrefix`, - "should replace this `if` statement with an unconditional `strings.TrimPrefix`"}, + { + `should replace this if statement with an unconditional strings.TrimPrefix`, + "should replace this `if` statement with an unconditional `strings.TrimPrefix`", + }, // staticcheck {`this value of (\S+) is never used$`, "this value of `${1}` is never used"}, - {`should use time.Since instead of time.Now\(\).Sub$`, - "should use `time.Since` instead of `time.Now().Sub`"}, - {`should check returned error before deferring response.Close\(\)$`, - "should check returned error before deferring `response.Close()`"}, + { + `should use time.Since instead of time.Now\(\).Sub$`, + "should use `time.Since` instead of `time.Now().Sub`", + }, + { + `should check returned error before deferring response.Close\(\)$`, + "should check returned error before deferring `response.Close()`", + }, {`no value of type uint is less than 0$`, "no value of type `uint` is less than `0`"}, // unused @@ -59,26 +71,40 @@ var replacePatterns = []replacePattern{ // typecheck {`^unknown field (\S+) in struct literal$`, "unknown field `${1}` in struct literal"}, - {`^invalid operation: (\S+) \(variable of type (\S+)\) has no field or method (\S+)$`, - "invalid operation: `${1}` (variable of type `${2}`) has no field or method `${3}`"}, + { + `^invalid operation: (\S+) \(variable of type (\S+)\) has no field or method (\S+)$`, + "invalid operation: `${1}` (variable of type `${2}`) has no field or method `${3}`", + }, {`^undeclared name: (\S+)$`, "undeclared name: `${1}`"}, - {`^cannot use addr \(variable of type (\S+)\) as (\S+) value in argument to (\S+)$`, - "cannot use addr (variable of type `${1}`) as `${2}` value in argument to `${3}`"}, + { + `^cannot use addr \(variable of type (\S+)\) as (\S+) value in argument to (\S+)$`, + "cannot use addr (variable of type `${1}`) as `${2}` value in argument to `${3}`", + }, {`^other declaration of (\S+)$`, "other declaration of `${1}`"}, {`^(\S+) redeclared in this block$`, "`${1}` redeclared in this block"}, // golint - {`^exported (type|method|function|var|const) (\S+) should have comment or be unexported$`, - "exported ${1} `${2}` should have comment or be unexported"}, - {`^comment on exported (type|method|function|var|const) (\S+) should be of the form "(\S+) ..."$`, - "comment on exported ${1} `${2}` should be of the form `${3} ...`"}, + { + `^exported (type|method|function|var|const) (\S+) should have comment or be unexported$`, + "exported ${1} `${2}` should have comment or be unexported", + }, + { + `^comment on exported (type|method|function|var|const) (\S+) should be of the form "(\S+) ..."$`, + "comment on exported ${1} `${2}` should be of the form `${3} ...`", + }, {`^should replace (.+) with (.+)$`, "should replace `${1}` with `${2}`"}, - {`^if block ends with a return statement, so drop this else and outdent its block$`, - "`if` block ends with a `return` statement, so drop this `else` and outdent its block"}, - {`^(struct field|var|range var|const|type|(?:func|method|interface method) (?:parameter|result)) (\S+) should be (\S+)$`, - "${1} `${2}` should be `${3}`"}, - {`^don't use underscores in Go names; var (\S+) should be (\S+)$`, - "don't use underscores in Go names; var `${1}` should be `${2}`"}, + { + `^if block ends with a return statement, so drop this else and outdent its block$`, + "`if` block ends with a `return` statement, so drop this `else` and outdent its block", + }, + { + `^(struct field|var|range var|const|type|(?:func|method|interface method) (?:parameter|result)) (\S+) should be (\S+)$`, + "${1} `${2}` should be `${3}`", + }, + { + `^don't use underscores in Go names; var (\S+) should be (\S+)$`, + "don't use underscores in Go names; var `${1}` should be `${2}`", + }, } type IdentifierMarker struct { @@ -101,10 +127,10 @@ func NewIdentifierMarker() *IdentifierMarker { } func (im IdentifierMarker) Process(issues []result.Issue) ([]result.Issue, error) { - return transformIssues(issues, func(i *result.Issue) *result.Issue { - iCopy := *i - iCopy.Text = im.markIdentifiers(iCopy.Text) - return &iCopy + return transformIssues(issues, func(issue *result.Issue) *result.Issue { + newIssue := *issue + newIssue.Text = im.markIdentifiers(newIssue.Text) + return &newIssue }), nil } diff --git a/pkg/result/processors/identifier_marker_test.go b/pkg/result/processors/identifier_marker_test.go index 3cda587d24cd..bef3f06afd55 100644 --- a/pkg/result/processors/identifier_marker_test.go +++ b/pkg/result/processors/identifier_marker_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/golangci/golangci-lint/pkg/result" ) @@ -12,45 +13,67 @@ func TestIdentifierMarker(t *testing.T) { //nolint:lll cases := []struct{ in, out string }{ {"unknown field Address in struct literal", "unknown field `Address` in struct literal"}, - {"invalid operation: res (variable of type github.com/iotexproject/iotex-core/explorer/idl/explorer.GetBlkOrActResponse) has no field or method Address", - "invalid operation: `res` (variable of type `github.com/iotexproject/iotex-core/explorer/idl/explorer.GetBlkOrActResponse`) has no field or method `Address`"}, - {"should use a simple channel send/receive instead of select with a single case", - "should use a simple channel send/receive instead of `select` with a single case"}, + { + "invalid operation: res (variable of type github.com/iotexproject/iotex-core/explorer/idl/explorer.GetBlkOrActResponse) has no field or method Address", + "invalid operation: `res` (variable of type `github.com/iotexproject/iotex-core/explorer/idl/explorer.GetBlkOrActResponse`) has no field or method `Address`", + }, + { + "should use a simple channel send/receive instead of select with a single case", + "should use a simple channel send/receive instead of `select` with a single case", + }, {"var testInputs is unused", "var `testInputs` is unused"}, {"undeclared name: stateIDLabel", "undeclared name: `stateIDLabel`"}, - {"exported type Metrics should have comment or be unexported", - "exported type `Metrics` should have comment or be unexported"}, - {`comment on exported function NewMetrics should be of the form "NewMetrics ..."`, - "comment on exported function `NewMetrics` should be of the form `NewMetrics ...`"}, - {"cannot use addr (variable of type string) as github.com/iotexproject/iotex-core/pkg/keypair.PublicKey value in argument to action.FakeSeal", - "cannot use addr (variable of type `string`) as `github.com/iotexproject/iotex-core/pkg/keypair.PublicKey` value in argument to `action.FakeSeal`"}, + { + "exported type Metrics should have comment or be unexported", + "exported type `Metrics` should have comment or be unexported", + }, + { + `comment on exported function NewMetrics should be of the form "NewMetrics ..."`, + "comment on exported function `NewMetrics` should be of the form `NewMetrics ...`", + }, + { + "cannot use addr (variable of type string) as github.com/iotexproject/iotex-core/pkg/keypair.PublicKey value in argument to action.FakeSeal", + "cannot use addr (variable of type `string`) as `github.com/iotexproject/iotex-core/pkg/keypair.PublicKey` value in argument to `action.FakeSeal`", + }, {"other declaration of out", "other declaration of `out`"}, {"should check returned error before deferring response.Close()", "should check returned error before deferring `response.Close()`"}, {"should use time.Since instead of time.Now().Sub", "should use `time.Since` instead of `time.Now().Sub`"}, {"TestFibZeroCount redeclared in this block", "`TestFibZeroCount` redeclared in this block"}, {"should replace i += 1 with i++", "should replace `i += 1` with `i++`"}, {"createEntry - result err is always nil", "`createEntry` - result `err` is always `nil`"}, - {"should omit comparison to bool constant, can be simplified to !projectIntegration.Model.Storage", - "should omit comparison to bool constant, can be simplified to `!projectIntegration.Model.Storage`"}, - {"if block ends with a return statement, so drop this else and outdent its block", - "`if` block ends with a `return` statement, so drop this `else` and outdent its block"}, - {"should write pupData := ms.m[pupID] instead of pupData, _ := ms.m[pupID]", - "should write `pupData := ms.m[pupID]` instead of `pupData, _ := ms.m[pupID]`"}, + { + "should omit comparison to bool constant, can be simplified to !projectIntegration.Model.Storage", + "should omit comparison to bool constant, can be simplified to `!projectIntegration.Model.Storage`", + }, + { + "if block ends with a return statement, so drop this else and outdent its block", + "`if` block ends with a `return` statement, so drop this `else` and outdent its block", + }, + { + "should write pupData := ms.m[pupID] instead of pupData, _ := ms.m[pupID]", + "should write `pupData := ms.m[pupID]` instead of `pupData, _ := ms.m[pupID]`", + }, {"no value of type uint is less than 0", "no value of type `uint` is less than `0`"}, {"redundant return statement", "redundant `return` statement"}, {"struct field Id should be ID", "struct field `Id` should be `ID`"}, - {"don't use underscores in Go names; var Go_lint should be GoLint", - "don't use underscores in Go names; var `Go_lint` should be `GoLint`"}, - {"G501: Blacklisted import crypto/md5: weak cryptographic primitive", - "G501: Blacklisted import `crypto/md5`: weak cryptographic primitive"}, - {"S1017: should replace this if statement with an unconditional strings.TrimPrefix", - "S1017: should replace this `if` statement with an unconditional `strings.TrimPrefix`"}, + { + "don't use underscores in Go names; var Go_lint should be GoLint", + "don't use underscores in Go names; var `Go_lint` should be `GoLint`", + }, + { + "G501: Blacklisted import crypto/md5: weak cryptographic primitive", + "G501: Blacklisted import `crypto/md5`: weak cryptographic primitive", + }, + { + "S1017: should replace this if statement with an unconditional strings.TrimPrefix", + "S1017: should replace this `if` statement with an unconditional `strings.TrimPrefix`", + }, } p := NewIdentifierMarker() for _, c := range cases { out, err := p.Process([]result.Issue{{Text: c.in}}) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, []result.Issue{{Text: c.out}}, out) } } diff --git a/pkg/result/processors/issues.go b/pkg/result/processors/issues.go index 8bc3d847d65a..a65b0c2b0cdf 100644 --- a/pkg/result/processors/issues.go +++ b/pkg/result/processors/issues.go @@ -1,12 +1,12 @@ package processors import ( - "github.com/pkg/errors" + "fmt" "github.com/golangci/golangci-lint/pkg/result" ) -func filterIssues(issues []result.Issue, filter func(i *result.Issue) bool) []result.Issue { +func filterIssues(issues []result.Issue, filter func(issue *result.Issue) bool) []result.Issue { retIssues := make([]result.Issue, 0, len(issues)) for i := range issues { if filter(&issues[i]) { @@ -17,12 +17,12 @@ func filterIssues(issues []result.Issue, filter func(i *result.Issue) bool) []re return retIssues } -func filterIssuesErr(issues []result.Issue, filter func(i *result.Issue) (bool, error)) ([]result.Issue, error) { +func filterIssuesErr(issues []result.Issue, filter func(issue *result.Issue) (bool, error)) ([]result.Issue, error) { retIssues := make([]result.Issue, 0, len(issues)) for i := range issues { ok, err := filter(&issues[i]) if err != nil { - return nil, errors.Wrapf(err, "can't filter issue %#v", issues[i]) + return nil, fmt.Errorf("can't filter issue %#v: %w", issues[i], err) } if ok { @@ -33,12 +33,12 @@ func filterIssuesErr(issues []result.Issue, filter func(i *result.Issue) (bool, return retIssues, nil } -func transformIssues(issues []result.Issue, transform func(i *result.Issue) *result.Issue) []result.Issue { +func transformIssues(issues []result.Issue, transform func(issue *result.Issue) *result.Issue) []result.Issue { retIssues := make([]result.Issue, 0, len(issues)) for i := range issues { - newI := transform(&issues[i]) - if newI != nil { - retIssues = append(retIssues, *newI) + newIssue := transform(&issues[i]) + if newIssue != nil { + retIssues = append(retIssues, *newIssue) } } diff --git a/pkg/result/processors/max_from_linter.go b/pkg/result/processors/max_from_linter.go index 649ed86ae9aa..65b04272bad9 100644 --- a/pkg/result/processors/max_from_linter.go +++ b/pkg/result/processors/max_from_linter.go @@ -33,14 +33,14 @@ func (p *MaxFromLinter) Process(issues []result.Issue) ([]result.Issue, error) { return issues, nil } - return filterIssues(issues, func(i *result.Issue) bool { - if i.Replacement != nil && p.cfg.Issues.NeedFix { + return filterIssues(issues, func(issue *result.Issue) bool { + if issue.Replacement != nil && p.cfg.Issues.NeedFix { // we need to fix all issues at once => we need to return all of them return true } - p.lc[i.FromLinter]++ // always inc for stat - return p.lc[i.FromLinter] <= p.limit + p.lc[issue.FromLinter]++ // always inc for stat + return p.lc[issue.FromLinter] <= p.limit }), nil } diff --git a/pkg/result/processors/max_per_file_from_linter.go b/pkg/result/processors/max_per_file_from_linter.go index 64182e3e22be..372f40cc5814 100644 --- a/pkg/result/processors/max_per_file_from_linter.go +++ b/pkg/result/processors/max_per_file_from_linter.go @@ -5,8 +5,10 @@ import ( "github.com/golangci/golangci-lint/pkg/result" ) -type linterToCountMap map[string]int -type fileToLinterToCountMap map[string]linterToCountMap +type ( + linterToCountMap map[string]int + fileToLinterToCountMap map[string]linterToCountMap +) type MaxPerFileFromLinter struct { flc fileToLinterToCountMap @@ -36,22 +38,22 @@ func (p *MaxPerFileFromLinter) Name() string { } func (p *MaxPerFileFromLinter) Process(issues []result.Issue) ([]result.Issue, error) { - return filterIssues(issues, func(i *result.Issue) bool { - limit := p.maxPerFileFromLinterConfig[i.FromLinter] + return filterIssues(issues, func(issue *result.Issue) bool { + limit := p.maxPerFileFromLinterConfig[issue.FromLinter] if limit == 0 { return true } - lm := p.flc[i.FilePath()] + lm := p.flc[issue.FilePath()] if lm == nil { - p.flc[i.FilePath()] = linterToCountMap{} + p.flc[issue.FilePath()] = linterToCountMap{} } - count := p.flc[i.FilePath()][i.FromLinter] + count := p.flc[issue.FilePath()][issue.FromLinter] if count >= limit { return false } - p.flc[i.FilePath()][i.FromLinter]++ + p.flc[issue.FilePath()][issue.FromLinter]++ return true }), nil } diff --git a/pkg/result/processors/max_same_issues.go b/pkg/result/processors/max_same_issues.go index 391ae5fa7f49..a3ceeb595306 100644 --- a/pkg/result/processors/max_same_issues.go +++ b/pkg/result/processors/max_same_issues.go @@ -37,14 +37,14 @@ func (p *MaxSameIssues) Process(issues []result.Issue) ([]result.Issue, error) { return issues, nil } - return filterIssues(issues, func(i *result.Issue) bool { - if i.Replacement != nil && p.cfg.Issues.NeedFix { + return filterIssues(issues, func(issue *result.Issue) bool { + if issue.Replacement != nil && p.cfg.Issues.NeedFix { // we need to fix all issues at once => we need to return all of them return true } - p.tc[i.Text]++ // always inc for stat - return p.tc[i.Text] <= p.limit + p.tc[issue.Text]++ // always inc for stat + return p.tc[issue.Text] <= p.limit }), nil } diff --git a/pkg/result/processors/nolint.go b/pkg/result/processors/nolint.go index 181d3bf1fea1..48be85b6ad3e 100644 --- a/pkg/result/processors/nolint.go +++ b/pkg/result/processors/nolint.go @@ -9,6 +9,8 @@ import ( "sort" "strings" + "golang.org/x/exp/maps" + "github.com/golangci/golangci-lint/pkg/golinters" "github.com/golangci/golangci-lint/pkg/lint/linter" "github.com/golangci/golangci-lint/pkg/lint/lintersdb" @@ -16,8 +18,10 @@ import ( "github.com/golangci/golangci-lint/pkg/result" ) -var nolintDebugf = logutils.Debug(logutils.DebugKeyNolint) -var nolintRe = regexp.MustCompile(`^nolint( |:|$)`) +var ( + nolintDebugf = logutils.Debug(logutils.DebugKeyNolint) + nolintRe = regexp.MustCompile(`^nolint( |:|$)`) +) type ignoredRange struct { linters []string @@ -95,16 +99,16 @@ func (p *Nolint) Process(issues []result.Issue) ([]result.Issue, error) { return filterIssuesErr(issues, p.shouldPassIssue) } -func (p *Nolint) getOrCreateFileData(i *result.Issue) (*fileData, error) { - fd := p.cache[i.FilePath()] +func (p *Nolint) getOrCreateFileData(issue *result.Issue) (*fileData, error) { + fd := p.cache[issue.FilePath()] if fd != nil { return fd, nil } fd = &fileData{} - p.cache[i.FilePath()] = fd + p.cache[issue.FilePath()] = fd - if i.FilePath() == "" { + if issue.FilePath() == "" { return nil, errors.New("no file path for issue") } @@ -113,14 +117,14 @@ func (p *Nolint) getOrCreateFileData(i *result.Issue) (*fileData, error) { // Don't use cached AST because they consume a lot of memory on large projects. fset := token.NewFileSet() - f, err := parser.ParseFile(fset, i.FilePath(), nil, parser.ParseComments) + f, err := parser.ParseFile(fset, issue.FilePath(), nil, parser.ParseComments) if err != nil { // Don't report error because it's already must be reporter by typecheck or go/analysis. return fd, nil } - fd.ignoredRanges = p.buildIgnoredRangesForFile(f, fset, i.FilePath()) - nolintDebugf("file %s: built nolint ranges are %+v", i.FilePath(), fd.ignoredRanges) + fd.ignoredRanges = p.buildIgnoredRangesForFile(f, fset, issue.FilePath()) + nolintDebugf("file %s: built nolint ranges are %+v", issue.FilePath(), fd.ignoredRanges) return fd, nil } @@ -146,28 +150,28 @@ func (p *Nolint) buildIgnoredRangesForFile(f *ast.File, fset *token.FileSet, fil return allRanges } -func (p *Nolint) shouldPassIssue(i *result.Issue) (bool, error) { - nolintDebugf("got issue: %v", *i) - if i.FromLinter == golinters.NoLintLintName && i.ExpectNoLint && i.ExpectedNoLintLinter != "" { +func (p *Nolint) shouldPassIssue(issue *result.Issue) (bool, error) { + nolintDebugf("got issue: %v", *issue) + if issue.FromLinter == golinters.NoLintLintName && issue.ExpectNoLint && issue.ExpectedNoLintLinter != "" { // don't expect disabled linters to cover their nolint statements nolintDebugf("enabled linters: %v", p.enabledLinters) - if p.enabledLinters[i.ExpectedNoLintLinter] == nil { + if p.enabledLinters[issue.ExpectedNoLintLinter] == nil { return false, nil } - nolintDebugf("checking that lint issue was used for %s: %v", i.ExpectedNoLintLinter, i) + nolintDebugf("checking that lint issue was used for %s: %v", issue.ExpectedNoLintLinter, issue) } - fd, err := p.getOrCreateFileData(i) + fd, err := p.getOrCreateFileData(issue) if err != nil { return false, err } for _, ir := range fd.ignoredRanges { - if ir.doesMatch(i) { - nolintDebugf("found ignored range for issue %v: %v", i, ir) - ir.matchedIssueFromLinter[i.FromLinter] = true + if ir.doesMatch(issue) { + nolintDebugf("found ignored range for issue %v: %v", issue, ir) + ir.matchedIssueFromLinter[issue.FromLinter] = true if ir.originalRange != nil { - ir.originalRange.matchedIssueFromLinter[i.FromLinter] = true + ir.originalRange.matchedIssueFromLinter[issue.FromLinter] = true } return false, nil } @@ -289,10 +293,7 @@ func (p *Nolint) Finish() { return } - unknownLinters := make([]string, 0, len(p.unknownLintersSet)) - for name := range p.unknownLintersSet { - unknownLinters = append(unknownLinters, name) - } + unknownLinters := maps.Keys(p.unknownLintersSet) sort.Strings(unknownLinters) p.log.Warnf("Found unknown linters in //nolint directives: %s", strings.Join(unknownLinters, ", ")) diff --git a/pkg/result/processors/nolint_test.go b/pkg/result/processors/nolint_test.go index 0ebe8c9a78a0..bca041da979f 100644 --- a/pkg/result/processors/nolint_test.go +++ b/pkg/result/processors/nolint_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" "github.com/golangci/golangci-lint/pkg/config" "github.com/golangci/golangci-lint/pkg/golinters" @@ -33,7 +34,9 @@ func newNolint2FileIssue(line int) result.Issue { } func newTestNolintProcessor(log logutils.Log) *Nolint { - return NewNolint(log, lintersdb.NewManager(nil, nil), nil) + dbManager, _ := lintersdb.NewManager(log, config.NewDefault(), lintersdb.NewLinterBuilder()) + + return NewNolint(log, dbManager, nil) } func getMockLog() *logutils.MockLog { @@ -173,9 +176,8 @@ func TestNolintInvalidLinterNameWithViolationOnTheSameLine(t *testing.T) { processedIssues, err := p.Process(issues) p.Finish() - assert.Len(t, processedIssues, 1) + require.NoError(t, err) assert.Equal(t, issues, processedIssues) - assert.NoError(t, err) } func TestNolintAliases(t *testing.T) { @@ -190,7 +192,7 @@ func TestNolintAliases(t *testing.T) { } func TestIgnoredRangeMatches(t *testing.T) { - var testcases = []struct { + testcases := []struct { doc string issue result.Issue linters []string @@ -244,7 +246,9 @@ func TestIgnoredRangeMatches(t *testing.T) { }, linters: testcase.linters, } - assert.Equal(t, testcase.expected, ir.doesMatch(&testcase.issue), testcase.doc) + + l := testcase.issue + assert.Equal(t, testcase.expected, ir.doesMatch(&l), testcase.doc) } } @@ -279,11 +283,15 @@ func TestNolintUnused(t *testing.T) { createProcessor := func(t *testing.T, log *logutils.MockLog, enabledLinters []string) *Nolint { enabledSetLog := logutils.NewMockLog() enabledSetLog.On("Infof", "Active %d linters: %s", len(enabledLinters), enabledLinters) + cfg := &config.Config{Linters: config.Linters{DisableAll: true, Enable: enabledLinters}} - dbManager := lintersdb.NewManager(cfg, nil) - enabledLintersSet := lintersdb.NewEnabledSet(dbManager, lintersdb.NewValidator(dbManager), enabledSetLog, cfg) - enabledLintersMap, err := enabledLintersSet.GetEnabledLintersMap() - assert.NoError(t, err) + + dbManager, err := lintersdb.NewManager(enabledSetLog, cfg, lintersdb.NewLinterBuilder()) + require.NoError(t, err) + + enabledLintersMap, err := dbManager.GetEnabledLintersMap() + require.NoError(t, err) + return NewNolint(log, dbManager, enabledLintersMap) } @@ -341,11 +349,13 @@ func TestNolintUnused(t *testing.T) { enabledSetLog.On("Infof", "Active %d linters: %s", 1, []string{"nolintlint"}) cfg := &config.Config{Linters: config.Linters{DisableAll: true, Enable: []string{"nolintlint"}}} - dbManager := lintersdb.NewManager(cfg, nil) - enabledLintersSet := lintersdb.NewEnabledSet(dbManager, lintersdb.NewValidator(dbManager), enabledSetLog, cfg) - enabledLintersMap, err := enabledLintersSet.GetEnabledLintersMap() - assert.NoError(t, err) + dbManager, err := lintersdb.NewManager(enabledSetLog, cfg, lintersdb.NewLinterBuilder()) + require.NoError(t, err) + + enabledLintersMap, err := dbManager.GetEnabledLintersMap() + require.NoError(t, err) + p := NewNolint(log, dbManager, enabledLintersMap) defer p.Finish() diff --git a/pkg/result/processors/path_prefixer.go b/pkg/result/processors/path_prefixer.go index 04ed83126621..f6b885011bc0 100644 --- a/pkg/result/processors/path_prefixer.go +++ b/pkg/result/processors/path_prefixer.go @@ -1,8 +1,7 @@ package processors import ( - "path/filepath" - + "github.com/golangci/golangci-lint/pkg/fsutils" "github.com/golangci/golangci-lint/pkg/result" ) @@ -27,7 +26,7 @@ func (*PathPrefixer) Name() string { func (p *PathPrefixer) Process(issues []result.Issue) ([]result.Issue, error) { if p.prefix != "" { for i := range issues { - issues[i].Pos.Filename = filepath.Join(p.prefix, issues[i].Pos.Filename) + issues[i].Pos.Filename = fsutils.WithPathPrefix(p.prefix, issues[i].Pos.Filename) } } return issues, nil diff --git a/pkg/result/processors/path_prefixer_test.go b/pkg/result/processors/path_prefixer_test.go index 9c349d501ae2..43fdd1dbc886 100644 --- a/pkg/result/processors/path_prefixer_test.go +++ b/pkg/result/processors/path_prefixer_test.go @@ -47,7 +47,7 @@ func TestPathPrefixer_Process(t *testing.T) { got, err := p.Process(tt.issues) require.NoError(t, err) - assert.Equal(t, got, tt.want) + assert.Equal(t, tt.want, got) }) } } diff --git a/pkg/result/processors/path_prettifier.go b/pkg/result/processors/path_prettifier.go index 3a140999c020..79cdd7473cbc 100644 --- a/pkg/result/processors/path_prettifier.go +++ b/pkg/result/processors/path_prettifier.go @@ -29,19 +29,19 @@ func (p PathPrettifier) Name() string { } func (p PathPrettifier) Process(issues []result.Issue) ([]result.Issue, error) { - return transformIssues(issues, func(i *result.Issue) *result.Issue { - if !filepath.IsAbs(i.FilePath()) { - return i + return transformIssues(issues, func(issue *result.Issue) *result.Issue { + if !filepath.IsAbs(issue.FilePath()) { + return issue } - rel, err := fsutils.ShortestRelPath(i.FilePath(), "") + rel, err := fsutils.ShortestRelPath(issue.FilePath(), "") if err != nil { - return i + return issue } - newI := i - newI.Pos.Filename = rel - return newI + newIssue := issue + newIssue.Pos.Filename = rel + return newIssue }), nil } diff --git a/pkg/result/processors/path_shortener.go b/pkg/result/processors/path_shortener.go index 6b66bea8b020..d7fa5ea91d6b 100644 --- a/pkg/result/processors/path_shortener.go +++ b/pkg/result/processors/path_shortener.go @@ -29,11 +29,11 @@ func (p PathShortener) Name() string { } func (p PathShortener) Process(issues []result.Issue) ([]result.Issue, error) { - return transformIssues(issues, func(i *result.Issue) *result.Issue { - newI := i - newI.Text = strings.ReplaceAll(newI.Text, p.wd+"/", "") - newI.Text = strings.ReplaceAll(newI.Text, p.wd, "") - return newI + return transformIssues(issues, func(issue *result.Issue) *result.Issue { + newIssue := issue + newIssue.Text = strings.ReplaceAll(newIssue.Text, p.wd+"/", "") + newIssue.Text = strings.ReplaceAll(newIssue.Text, p.wd, "") + return newIssue }), nil } diff --git a/pkg/result/processors/processor_test.go b/pkg/result/processors/processor_test.go index 3f396b437266..216a8fcd5997 100644 --- a/pkg/result/processors/processor_test.go +++ b/pkg/result/processors/processor_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/golangci/golangci-lint/pkg/result" ) @@ -21,6 +22,7 @@ func newIssueFromIssueTestCase(c issueTestCase) result.Issue { return result.Issue{ Text: c.Text, FromLinter: c.Linter, + Severity: c.Severity, Pos: token.Position{ Filename: c.Path, Line: c.Line, @@ -38,7 +40,7 @@ func process(t *testing.T, p Processor, issues ...result.Issue) []result.Issue { t.Helper() processedIssues, err := p.Process(issues) - assert.NoError(t, err) + require.NoError(t, err) return processedIssues } diff --git a/pkg/result/processors/severity.go b/pkg/result/processors/severity.go new file mode 100644 index 000000000000..2568ba45c464 --- /dev/null +++ b/pkg/result/processors/severity.go @@ -0,0 +1,126 @@ +package processors + +import ( + "regexp" + + "github.com/golangci/golangci-lint/pkg/fsutils" + "github.com/golangci/golangci-lint/pkg/logutils" + "github.com/golangci/golangci-lint/pkg/result" +) + +const severityFromLinter = "@linter" + +var _ Processor = &Severity{} + +type severityRule struct { + baseRule + severity string +} + +type SeverityRule struct { + BaseRule + Severity string +} + +type SeverityOptions struct { + Default string + Rules []SeverityRule + CaseSensitive bool +} + +type Severity struct { + name string + + log logutils.Log + + files *fsutils.Files + + defaultSeverity string + rules []severityRule +} + +func NewSeverity(log logutils.Log, files *fsutils.Files, opts SeverityOptions) *Severity { + p := &Severity{ + name: "severity-rules", + files: files, + log: log, + defaultSeverity: opts.Default, + } + + prefix := caseInsensitivePrefix + if opts.CaseSensitive { + prefix = "" + p.name = "severity-rules-case-sensitive" + } + + p.rules = createSeverityRules(opts.Rules, prefix) + + return p +} + +func (p *Severity) Process(issues []result.Issue) ([]result.Issue, error) { + if len(p.rules) == 0 && p.defaultSeverity == "" { + return issues, nil + } + + return transformIssues(issues, p.transform), nil +} + +func (p *Severity) transform(issue *result.Issue) *result.Issue { + for _, rule := range p.rules { + if rule.match(issue, p.files, p.log) { + if rule.severity == severityFromLinter || (rule.severity == "" && p.defaultSeverity == severityFromLinter) { + return issue + } + + issue.Severity = rule.severity + if issue.Severity == "" { + issue.Severity = p.defaultSeverity + } + + return issue + } + } + + if p.defaultSeverity != severityFromLinter { + issue.Severity = p.defaultSeverity + } + + return issue +} + +func (p *Severity) Name() string { return p.name } + +func (*Severity) Finish() {} + +func createSeverityRules(rules []SeverityRule, prefix string) []severityRule { + parsedRules := make([]severityRule, 0, len(rules)) + + for _, rule := range rules { + parsedRule := severityRule{} + parsedRule.linters = rule.Linters + parsedRule.severity = rule.Severity + + if rule.Text != "" { + parsedRule.text = regexp.MustCompile(prefix + rule.Text) + } + + if rule.Source != "" { + parsedRule.source = regexp.MustCompile(prefix + rule.Source) + } + + if rule.Path != "" { + path := fsutils.NormalizePathInRegex(rule.Path) + parsedRule.path = regexp.MustCompile(path) + } + + if rule.PathExcept != "" { + pathExcept := fsutils.NormalizePathInRegex(rule.PathExcept) + parsedRule.pathExcept = regexp.MustCompile(pathExcept) + } + + parsedRules = append(parsedRules, parsedRule) + } + + return parsedRules +} diff --git a/pkg/result/processors/severity_rules.go b/pkg/result/processors/severity_rules.go deleted file mode 100644 index 85c1866a21d9..000000000000 --- a/pkg/result/processors/severity_rules.go +++ /dev/null @@ -1,104 +0,0 @@ -package processors - -import ( - "regexp" - - "github.com/golangci/golangci-lint/pkg/fsutils" - "github.com/golangci/golangci-lint/pkg/logutils" - "github.com/golangci/golangci-lint/pkg/result" -) - -type severityRule struct { - baseRule - severity string -} - -type SeverityRule struct { - BaseRule - Severity string -} - -type SeverityRules struct { - defaultSeverity string - rules []severityRule - lineCache *fsutils.LineCache - log logutils.Log -} - -func NewSeverityRules(defaultSeverity string, rules []SeverityRule, lineCache *fsutils.LineCache, log logutils.Log) *SeverityRules { - r := &SeverityRules{ - lineCache: lineCache, - log: log, - defaultSeverity: defaultSeverity, - } - r.rules = createSeverityRules(rules, "(?i)") - - return r -} - -func createSeverityRules(rules []SeverityRule, prefix string) []severityRule { - parsedRules := make([]severityRule, 0, len(rules)) - for _, rule := range rules { - parsedRule := severityRule{} - parsedRule.linters = rule.Linters - parsedRule.severity = rule.Severity - if rule.Text != "" { - parsedRule.text = regexp.MustCompile(prefix + rule.Text) - } - if rule.Source != "" { - parsedRule.source = regexp.MustCompile(prefix + rule.Source) - } - if rule.Path != "" { - path := fsutils.NormalizePathInRegex(rule.Path) - parsedRule.path = regexp.MustCompile(path) - } - parsedRules = append(parsedRules, parsedRule) - } - return parsedRules -} - -func (p SeverityRules) Process(issues []result.Issue) ([]result.Issue, error) { - if len(p.rules) == 0 && p.defaultSeverity == "" { - return issues, nil - } - return transformIssues(issues, func(i *result.Issue) *result.Issue { - for _, rule := range p.rules { - rule := rule - - ruleSeverity := p.defaultSeverity - if rule.severity != "" { - ruleSeverity = rule.severity - } - - if rule.match(i, p.lineCache, p.log) { - i.Severity = ruleSeverity - return i - } - } - i.Severity = p.defaultSeverity - return i - }), nil -} - -func (SeverityRules) Name() string { return "severity-rules" } -func (SeverityRules) Finish() {} - -var _ Processor = SeverityRules{} - -type SeverityRulesCaseSensitive struct { - *SeverityRules -} - -func NewSeverityRulesCaseSensitive(defaultSeverity string, rules []SeverityRule, - lineCache *fsutils.LineCache, log logutils.Log) *SeverityRulesCaseSensitive { - r := &SeverityRules{ - lineCache: lineCache, - log: log, - defaultSeverity: defaultSeverity, - } - r.rules = createSeverityRules(rules, "") - - return &SeverityRulesCaseSensitive{r} -} - -func (SeverityRulesCaseSensitive) Name() string { return "severity-rules-case-sensitive" } diff --git a/pkg/result/processors/severity_rules_test.go b/pkg/result/processors/severity_rules_test.go deleted file mode 100644 index b7407b531018..000000000000 --- a/pkg/result/processors/severity_rules_test.go +++ /dev/null @@ -1,204 +0,0 @@ -package processors - -import ( - "path/filepath" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/golangci/golangci-lint/pkg/fsutils" - "github.com/golangci/golangci-lint/pkg/logutils" - "github.com/golangci/golangci-lint/pkg/report" - "github.com/golangci/golangci-lint/pkg/result" -) - -func TestSeverityRulesMultiple(t *testing.T) { - lineCache := fsutils.NewLineCache(fsutils.NewFileCache()) - log := report.NewLogWrapper(logutils.NewStderrLog(logutils.DebugKeyEmpty), &report.Data{}) - p := NewSeverityRules("error", []SeverityRule{ - { - Severity: "info", - BaseRule: BaseRule{ - Text: "^ssl$", - Linters: []string{"gosec"}, - }, - }, - { - Severity: "info", - BaseRule: BaseRule{ - Linters: []string{"linter"}, - Path: "e.go", - }, - }, - { - Severity: "info", - BaseRule: BaseRule{ - Text: "^testonly$", - Path: `_test\.go`, - }, - }, - { - BaseRule: BaseRule{ - Source: "^//go:generate ", - Linters: []string{"lll"}, - }, - }, - { - Severity: "info", - BaseRule: BaseRule{ - Source: "^//go:dosomething", - }, - }, - { - Severity: "info", - BaseRule: BaseRule{ - Linters: []string{"someotherlinter"}, - }, - }, - { - Severity: "info", - BaseRule: BaseRule{ - Linters: []string{"somelinter"}, - }, - }, - { - Severity: "info", - }, - }, lineCache, log) - - cases := []issueTestCase{ - {Path: "ssl.go", Text: "ssl", Linter: "gosec"}, - {Path: "e.go", Text: "some", Linter: "linter"}, - {Path: "e_test.go", Text: "testonly", Linter: "testlinter"}, - {Path: filepath.Join("testdata", "exclude_rules.go"), Line: 3, Linter: "lll"}, - {Path: filepath.Join("testdata", "severity_rules.go"), Line: 3, Linter: "invalidgo"}, - {Path: "someotherlinter.go", Text: "someotherlinter", Linter: "someotherlinter"}, - {Path: "somenotmatchlinter.go", Text: "somenotmatchlinter", Linter: "somenotmatchlinter"}, - {Path: "empty.go", Text: "empty", Linter: "empty"}, - } - var issues []result.Issue - for _, c := range cases { - issues = append(issues, newIssueFromIssueTestCase(c)) - } - processedIssues := process(t, p, issues...) - var resultingCases []issueTestCase - for _, i := range processedIssues { - resultingCases = append(resultingCases, issueTestCase{ - Path: i.FilePath(), - Linter: i.FromLinter, - Text: i.Text, - Line: i.Line(), - Severity: i.Severity, - }) - } - expectedCases := []issueTestCase{ - {Path: "ssl.go", Text: "ssl", Linter: "gosec", Severity: "info"}, - {Path: "e.go", Text: "some", Linter: "linter", Severity: "info"}, - {Path: "e_test.go", Text: "testonly", Linter: "testlinter", Severity: "info"}, - {Path: filepath.Join("testdata", "exclude_rules.go"), Line: 3, Linter: "lll", Severity: "error"}, - {Path: filepath.Join("testdata", "severity_rules.go"), Line: 3, Linter: "invalidgo", Severity: "info"}, - {Path: "someotherlinter.go", Text: "someotherlinter", Linter: "someotherlinter", Severity: "info"}, - {Path: "somenotmatchlinter.go", Text: "somenotmatchlinter", Linter: "somenotmatchlinter", Severity: "error"}, - {Path: "empty.go", Text: "empty", Linter: "empty", Severity: "error"}, - } - assert.Equal(t, expectedCases, resultingCases) -} - -func TestSeverityRulesText(t *testing.T) { - p := NewSeverityRules("", []SeverityRule{ - { - BaseRule: BaseRule{ - Text: "^severity$", - Linters: []string{"linter"}, - }, - }, - }, nil, nil) - texts := []string{"seveRity", "1", "", "serverit", "notseverity"} - var issues []result.Issue - for _, t := range texts { - issues = append(issues, result.Issue{ - Text: t, - FromLinter: "linter", - }) - } - - processedIssues := process(t, p, issues...) - assert.Len(t, processedIssues, len(issues)) - - var processedTexts []string - for _, i := range processedIssues { - processedTexts = append(processedTexts, i.Text) - } - assert.Equal(t, texts, processedTexts) -} - -func TestSeverityRulesOnlyDefault(t *testing.T) { - lineCache := fsutils.NewLineCache(fsutils.NewFileCache()) - log := report.NewLogWrapper(logutils.NewStderrLog(logutils.DebugKeyEmpty), &report.Data{}) - p := NewSeverityRules("info", []SeverityRule{}, lineCache, log) - - cases := []issueTestCase{ - {Path: "ssl.go", Text: "ssl", Linter: "gosec"}, - {Path: "empty.go", Text: "empty", Linter: "empty"}, - } - var issues []result.Issue - for _, c := range cases { - issues = append(issues, newIssueFromIssueTestCase(c)) - } - processedIssues := process(t, p, issues...) - var resultingCases []issueTestCase - for _, i := range processedIssues { - resultingCases = append(resultingCases, issueTestCase{ - Path: i.FilePath(), - Linter: i.FromLinter, - Text: i.Text, - Line: i.Line(), - Severity: i.Severity, - }) - } - expectedCases := []issueTestCase{ - {Path: "ssl.go", Text: "ssl", Linter: "gosec", Severity: "info"}, - {Path: "empty.go", Text: "empty", Linter: "empty", Severity: "info"}, - } - assert.Equal(t, expectedCases, resultingCases) -} - -func TestSeverityRulesEmpty(t *testing.T) { - processAssertSame(t, NewSeverityRules("", nil, nil, nil), newIssueFromTextTestCase("test")) -} - -func TestSeverityRulesCaseSensitive(t *testing.T) { - lineCache := fsutils.NewLineCache(fsutils.NewFileCache()) - p := NewSeverityRulesCaseSensitive("error", []SeverityRule{ - { - Severity: "info", - BaseRule: BaseRule{ - Text: "^ssl$", - Linters: []string{"gosec", "someotherlinter"}, - }, - }, - }, lineCache, nil) - - cases := []issueTestCase{ - {Path: "e.go", Text: "ssL", Linter: "gosec"}, - } - var issues []result.Issue - for _, c := range cases { - issues = append(issues, newIssueFromIssueTestCase(c)) - } - processedIssues := process(t, p, issues...) - var resultingCases []issueTestCase - for _, i := range processedIssues { - resultingCases = append(resultingCases, issueTestCase{ - Path: i.FilePath(), - Linter: i.FromLinter, - Text: i.Text, - Line: i.Line(), - Severity: i.Severity, - }) - } - expectedCases := []issueTestCase{ - {Path: "e.go", Text: "ssL", Linter: "gosec", Severity: "error"}, - } - assert.Equal(t, expectedCases, resultingCases) -} diff --git a/pkg/result/processors/severity_test.go b/pkg/result/processors/severity_test.go new file mode 100644 index 000000000000..cbf18e6c79ae --- /dev/null +++ b/pkg/result/processors/severity_test.go @@ -0,0 +1,496 @@ +package processors + +import ( + "path" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/golangci/golangci-lint/pkg/fsutils" + "github.com/golangci/golangci-lint/pkg/logutils" + "github.com/golangci/golangci-lint/pkg/result" +) + +func TestSeverity_multiple(t *testing.T) { + lineCache := fsutils.NewLineCache(fsutils.NewFileCache()) + files := fsutils.NewFiles(lineCache, "") + log := logutils.NewStderrLog(logutils.DebugKeyEmpty) + + opts := SeverityOptions{ + Default: "error", + Rules: []SeverityRule{ + { + Severity: "info", + BaseRule: BaseRule{ + Text: "^ssl$", + Linters: []string{"gosec"}, + }, + }, + { + Severity: "info", + BaseRule: BaseRule{ + Linters: []string{"linter"}, + Path: "e.go", + }, + }, + { + Severity: "info", + BaseRule: BaseRule{ + Text: "^testonly$", + Path: `_test\.go`, + }, + }, + { + Severity: "info", + BaseRule: BaseRule{ + Text: "^nontestonly$", + PathExcept: `_test\.go`, + }, + }, + { + BaseRule: BaseRule{ + Source: "^//go:generate ", + Linters: []string{"lll"}, + }, + }, + { + Severity: "info", + BaseRule: BaseRule{ + Source: "^//go:dosomething", + }, + }, + { + Severity: "info", + BaseRule: BaseRule{ + Linters: []string{"someotherlinter"}, + }, + }, + { + Severity: "info", + BaseRule: BaseRule{ + Linters: []string{"somelinter"}, + }, + }, + { + Severity: "info", + }, + }, + } + + p := NewSeverity(log, files, opts) + + cases := []issueTestCase{ + {Path: "ssl.go", Text: "ssl", Linter: "gosec"}, + {Path: "e.go", Text: "some", Linter: "linter"}, + {Path: "e_test.go", Text: "testonly", Linter: "testlinter"}, + {Path: "e.go", Text: "nontestonly", Linter: "testlinter"}, + {Path: "e_test.go", Text: "nontestonly", Linter: "testlinter"}, + {Path: filepath.Join("testdata", "exclude_rules.go"), Line: 3, Linter: "lll"}, + {Path: filepath.Join("testdata", "severity_rules.go"), Line: 3, Linter: "invalidgo"}, + {Path: "someotherlinter.go", Text: "someotherlinter", Linter: "someotherlinter"}, + {Path: "somenotmatchlinter.go", Text: "somenotmatchlinter", Linter: "somenotmatchlinter"}, + {Path: "empty.go", Text: "empty", Linter: "empty"}, + } + + var issues []result.Issue + for _, c := range cases { + issues = append(issues, newIssueFromIssueTestCase(c)) + } + + processedIssues := process(t, p, issues...) + + var resultingCases []issueTestCase + for _, i := range processedIssues { + resultingCases = append(resultingCases, issueTestCase{ + Path: i.FilePath(), + Linter: i.FromLinter, + Text: i.Text, + Line: i.Line(), + Severity: i.Severity, + }) + } + + expectedCases := []issueTestCase{ + {Path: "ssl.go", Text: "ssl", Linter: "gosec", Severity: "info"}, + {Path: "e.go", Text: "some", Linter: "linter", Severity: "info"}, + {Path: "e_test.go", Text: "testonly", Linter: "testlinter", Severity: "info"}, + {Path: "e.go", Text: "nontestonly", Linter: "testlinter", Severity: "info"}, // matched + {Path: "e_test.go", Text: "nontestonly", Linter: "testlinter", Severity: "error"}, // not matched + {Path: filepath.Join("testdata", "exclude_rules.go"), Line: 3, Linter: "lll", Severity: "error"}, + {Path: filepath.Join("testdata", "severity_rules.go"), Line: 3, Linter: "invalidgo", Severity: "info"}, + {Path: "someotherlinter.go", Text: "someotherlinter", Linter: "someotherlinter", Severity: "info"}, + {Path: "somenotmatchlinter.go", Text: "somenotmatchlinter", Linter: "somenotmatchlinter", Severity: "error"}, + {Path: "empty.go", Text: "empty", Linter: "empty", Severity: "error"}, + } + + assert.Equal(t, expectedCases, resultingCases) +} + +func TestSeverity_pathPrefix(t *testing.T) { + lineCache := fsutils.NewLineCache(fsutils.NewFileCache()) + pathPrefix := path.Join("some", "dir") + files := fsutils.NewFiles(lineCache, pathPrefix) + log := logutils.NewStderrLog(logutils.DebugKeyEmpty) + + opts := SeverityOptions{ + Default: "error", + Rules: []SeverityRule{ + { + Severity: "info", + BaseRule: BaseRule{ + Text: "some", + Path: `some/dir/e\.go`, + }, + }, + }, + } + + p := NewSeverity(log, files, opts) + + cases := []issueTestCase{ + {Path: "e.go", Text: "some", Linter: "linter"}, + {Path: "other.go", Text: "some", Linter: "linter"}, + } + + var issues []result.Issue + for _, c := range cases { + issues = append(issues, newIssueFromIssueTestCase(c)) + } + + processedIssues := process(t, p, issues...) + + var resultingCases []issueTestCase + for _, i := range processedIssues { + resultingCases = append(resultingCases, issueTestCase{ + Path: i.FilePath(), + Linter: i.FromLinter, + Text: i.Text, + Line: i.Line(), + Severity: i.Severity, + }) + } + + expectedCases := []issueTestCase{ + {Path: "e.go", Text: "some", Linter: "linter", Severity: "info"}, + {Path: "other.go", Text: "some", Linter: "linter", Severity: "error"}, + } + + assert.Equal(t, expectedCases, resultingCases) +} + +func TestSeverity_text(t *testing.T) { + opts := SeverityOptions{ + Rules: []SeverityRule{ + { + BaseRule: BaseRule{ + Text: "^severity$", + Linters: []string{"linter"}, + }, + }, + }, + } + + p := NewSeverity(nil, nil, opts) + + texts := []string{"seveRity", "1", "", "serverit", "notseverity"} + var issues []result.Issue + for _, t := range texts { + issues = append(issues, result.Issue{ + Text: t, + FromLinter: "linter", + }) + } + + processedIssues := process(t, p, issues...) + assert.Len(t, processedIssues, len(issues)) + + var processedTexts []string + for _, i := range processedIssues { + processedTexts = append(processedTexts, i.Text) + } + + assert.Equal(t, texts, processedTexts) +} + +func TestSeverity_onlyDefault(t *testing.T) { + lineCache := fsutils.NewLineCache(fsutils.NewFileCache()) + files := fsutils.NewFiles(lineCache, "") + log := logutils.NewStderrLog(logutils.DebugKeyEmpty) + + opts := SeverityOptions{ + Default: "info", + Rules: []SeverityRule{}, + } + + p := NewSeverity(log, files, opts) + + cases := []issueTestCase{ + {Path: "ssl.go", Text: "ssl", Linter: "gosec"}, + {Path: "empty.go", Text: "empty", Linter: "empty"}, + } + + var issues []result.Issue + for _, c := range cases { + issues = append(issues, newIssueFromIssueTestCase(c)) + } + + processedIssues := process(t, p, issues...) + + var resultingCases []issueTestCase + for _, i := range processedIssues { + resultingCases = append(resultingCases, issueTestCase{ + Path: i.FilePath(), + Linter: i.FromLinter, + Text: i.Text, + Line: i.Line(), + Severity: i.Severity, + }) + } + + expectedCases := []issueTestCase{ + {Path: "ssl.go", Text: "ssl", Linter: "gosec", Severity: "info"}, + {Path: "empty.go", Text: "empty", Linter: "empty", Severity: "info"}, + } + + assert.Equal(t, expectedCases, resultingCases) +} + +func TestSeverity_empty(t *testing.T) { + p := NewSeverity(nil, nil, SeverityOptions{}) + + processAssertSame(t, p, newIssueFromTextTestCase("test")) +} + +func TestSeverity_caseSensitive(t *testing.T) { + lineCache := fsutils.NewLineCache(fsutils.NewFileCache()) + files := fsutils.NewFiles(lineCache, "") + + opts := SeverityOptions{ + Default: "error", + Rules: []SeverityRule{ + { + Severity: "info", + BaseRule: BaseRule{ + Text: "^ssl$", + Linters: []string{"gosec", "someotherlinter"}, + }, + }, + }, + CaseSensitive: true, + } + + p := NewSeverity(nil, files, opts) + + cases := []issueTestCase{ + {Path: "e.go", Text: "ssL", Linter: "gosec"}, + } + + var issues []result.Issue + for _, c := range cases { + issues = append(issues, newIssueFromIssueTestCase(c)) + } + + processedIssues := process(t, p, issues...) + + var resultingCases []issueTestCase + for _, i := range processedIssues { + resultingCases = append(resultingCases, issueTestCase{ + Path: i.FilePath(), + Linter: i.FromLinter, + Text: i.Text, + Line: i.Line(), + Severity: i.Severity, + }) + } + + expectedCases := []issueTestCase{ + {Path: "e.go", Text: "ssL", Linter: "gosec", Severity: "error"}, + } + + assert.Equal(t, expectedCases, resultingCases) +} + +func TestSeverity_transform(t *testing.T) { + lineCache := fsutils.NewLineCache(fsutils.NewFileCache()) + files := fsutils.NewFiles(lineCache, "") + + testCases := []struct { + desc string + opts SeverityOptions + issue *result.Issue + expected *result.Issue + }{ + { + desc: "apply severity from rule", + opts: SeverityOptions{ + Default: "error", + Rules: []SeverityRule{ + { + Severity: "info", + BaseRule: BaseRule{ + Linters: []string{"linter1"}, + }, + }, + }, + }, + issue: &result.Issue{ + Text: "This is a report", + FromLinter: "linter1", + }, + expected: &result.Issue{ + Text: "This is a report", + FromLinter: "linter1", + Severity: "info", + }, + }, + { + desc: "apply severity from default", + opts: SeverityOptions{ + Default: "error", + Rules: []SeverityRule{ + { + Severity: "info", + BaseRule: BaseRule{ + Linters: []string{"linter1"}, + }, + }, + }, + }, + issue: &result.Issue{ + Text: "This is a report", + FromLinter: "linter2", + }, + expected: &result.Issue{ + Text: "This is a report", + FromLinter: "linter2", + Severity: "error", + }, + }, + { + desc: "severity from rule override severity from linter", + opts: SeverityOptions{ + Default: "error", + Rules: []SeverityRule{ + { + Severity: "info", + BaseRule: BaseRule{ + Linters: []string{"linter1"}, + }, + }, + }, + }, + issue: &result.Issue{ + Text: "This is a report", + FromLinter: "linter1", + Severity: "huge", + }, + expected: &result.Issue{ + Text: "This is a report", + FromLinter: "linter1", + Severity: "info", + }, + }, + { + desc: "severity from default override severity from linter", + opts: SeverityOptions{ + Default: "error", + Rules: []SeverityRule{ + { + Severity: "info", + BaseRule: BaseRule{ + Linters: []string{"linter1"}, + }, + }, + }, + }, + issue: &result.Issue{ + Text: "This is a report", + FromLinter: "linter2", + Severity: "huge", + }, + expected: &result.Issue{ + Text: "This is a report", + FromLinter: "linter2", + Severity: "error", + }, + }, + { + desc: "keep severity from linter as rule", + opts: SeverityOptions{ + Default: "error", + Rules: []SeverityRule{ + { + Severity: severityFromLinter, + BaseRule: BaseRule{ + Linters: []string{"linter1"}, + }, + }, + }, + }, + issue: &result.Issue{ + Text: "This is a report", + FromLinter: "linter1", + Severity: "huge", + }, + expected: &result.Issue{ + Text: "This is a report", + FromLinter: "linter1", + Severity: "huge", + }, + }, + { + desc: "keep severity from linter as default", + opts: SeverityOptions{ + Default: severityFromLinter, + Rules: []SeverityRule{ + { + Severity: "info", + BaseRule: BaseRule{ + Linters: []string{"linter1"}, + }, + }, + }, + }, + issue: &result.Issue{ + Text: "This is a report", + FromLinter: "linter2", + Severity: "huge", + }, + expected: &result.Issue{ + Text: "This is a report", + FromLinter: "linter2", + Severity: "huge", + }, + }, + { + desc: "keep severity from linter as default (without rule)", + opts: SeverityOptions{ + Default: severityFromLinter, + }, + issue: &result.Issue{ + Text: "This is a report", + FromLinter: "linter2", + Severity: "huge", + }, + expected: &result.Issue{ + Text: "This is a report", + FromLinter: "linter2", + Severity: "huge", + }, + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + p := NewSeverity(nil, files, test.opts) + + newIssue := p.transform(test.issue) + + assert.Equal(t, test.expected, newIssue) + }) + } +} diff --git a/pkg/result/processors/skip_dirs.go b/pkg/result/processors/skip_dirs.go index 11ab99104f79..7c4e0b9c0cbe 100644 --- a/pkg/result/processors/skip_dirs.go +++ b/pkg/result/processors/skip_dirs.go @@ -1,12 +1,11 @@ package processors import ( + "fmt" "path/filepath" "regexp" "strings" - "github.com/pkg/errors" - "github.com/golangci/golangci-lint/pkg/fsutils" "github.com/golangci/golangci-lint/pkg/logutils" "github.com/golangci/golangci-lint/pkg/result" @@ -23,19 +22,20 @@ type SkipDirs struct { skippedDirs map[string]*skipStat absArgsDirs []string skippedDirsCache map[string]bool + pathPrefix string } var _ Processor = (*SkipDirs)(nil) const goFileSuffix = ".go" -func NewSkipDirs(patterns []string, log logutils.Log, runArgs []string) (*SkipDirs, error) { +func NewSkipDirs(patterns []string, log logutils.Log, runArgs []string, pathPrefix string) (*SkipDirs, error) { var patternsRe []*regexp.Regexp for _, p := range patterns { p = fsutils.NormalizePathInRegex(p) patternRe, err := regexp.Compile(p) if err != nil { - return nil, errors.Wrapf(err, "can't compile regexp %q", p) + return nil, fmt.Errorf("can't compile regexp %q: %w", p, err) } patternsRe = append(patternsRe, patternRe) } @@ -52,7 +52,7 @@ func NewSkipDirs(patterns []string, log logutils.Log, runArgs []string) (*SkipDi absArg, err := filepath.Abs(arg) if err != nil { - return nil, errors.Wrapf(err, "failed to abs-ify arg %q", arg) + return nil, fmt.Errorf("failed to abs-ify arg %q: %w", arg, err) } absArgsDirs = append(absArgsDirs, absArg) } @@ -63,6 +63,7 @@ func NewSkipDirs(patterns []string, log logutils.Log, runArgs []string) (*SkipDi skippedDirs: map[string]*skipStat{}, absArgsDirs: absArgsDirs, skippedDirsCache: map[string]bool{}, + pathPrefix: pathPrefix, }, nil } @@ -78,15 +79,15 @@ func (p *SkipDirs) Process(issues []result.Issue) ([]result.Issue, error) { return filterIssues(issues, p.shouldPassIssue), nil } -func (p *SkipDirs) shouldPassIssue(i *result.Issue) bool { - if filepath.IsAbs(i.FilePath()) { - if !isSpecialAutogeneratedFile(i.FilePath()) { - p.log.Warnf("Got abs path %s in skip dirs processor, it should be relative", i.FilePath()) +func (p *SkipDirs) shouldPassIssue(issue *result.Issue) bool { + if filepath.IsAbs(issue.FilePath()) { + if isGoFile(issue.FilePath()) { + p.log.Warnf("Got abs path %s in skip dirs processor, it should be relative", issue.FilePath()) } return true } - issueRelDir := filepath.Dir(i.FilePath()) + issueRelDir := filepath.Dir(issue.FilePath()) if toPass, ok := p.skippedDirsCache[issueRelDir]; ok { if !toPass { @@ -121,8 +122,9 @@ func (p *SkipDirs) shouldPassIssueDirs(issueRelDir, issueAbsDir string) bool { // The alternative solution is to find relative to args path, but it has // disadvantages (https://github.com/golangci/golangci-lint/pull/313). + path := fsutils.WithPathPrefix(p.pathPrefix, issueRelDir) for _, pattern := range p.patterns { - if pattern.MatchString(issueRelDir) { + if pattern.MatchString(path) { ps := pattern.String() if p.skippedDirs[issueRelDir] == nil { p.skippedDirs[issueRelDir] = &skipStat{ diff --git a/pkg/result/processors/skip_files.go b/pkg/result/processors/skip_files.go index b7b86bed06ce..f1873a376cc4 100644 --- a/pkg/result/processors/skip_files.go +++ b/pkg/result/processors/skip_files.go @@ -9,24 +9,26 @@ import ( ) type SkipFiles struct { - patterns []*regexp.Regexp + patterns []*regexp.Regexp + pathPrefix string } var _ Processor = (*SkipFiles)(nil) -func NewSkipFiles(patterns []string) (*SkipFiles, error) { +func NewSkipFiles(patterns []string, pathPrefix string) (*SkipFiles, error) { var patternsRe []*regexp.Regexp for _, p := range patterns { p = fsutils.NormalizePathInRegex(p) patternRe, err := regexp.Compile(p) if err != nil { - return nil, fmt.Errorf("can't compile regexp %q: %s", p, err) + return nil, fmt.Errorf("can't compile regexp %q: %w", p, err) } patternsRe = append(patternsRe, patternRe) } return &SkipFiles{ - patterns: patternsRe, + patterns: patternsRe, + pathPrefix: pathPrefix, }, nil } @@ -39,9 +41,10 @@ func (p SkipFiles) Process(issues []result.Issue) ([]result.Issue, error) { return issues, nil } - return filterIssues(issues, func(i *result.Issue) bool { - for _, p := range p.patterns { - if p.MatchString(i.FilePath()) { + return filterIssues(issues, func(issue *result.Issue) bool { + path := fsutils.WithPathPrefix(p.pathPrefix, issue.FilePath()) + for _, pattern := range p.patterns { + if pattern.MatchString(path) { return false } } diff --git a/pkg/result/processors/skip_files_test.go b/pkg/result/processors/skip_files_test.go index 7f16b58158ef..fbea9bb34da1 100644 --- a/pkg/result/processors/skip_files_test.go +++ b/pkg/result/processors/skip_files_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/golangci/golangci-lint/pkg/result" ) @@ -20,8 +21,8 @@ func newFileIssue(file string) result.Issue { } func newTestSkipFiles(t *testing.T, patterns ...string) *SkipFiles { - p, err := NewSkipFiles(patterns) - assert.NoError(t, err) + p, err := NewSkipFiles(patterns, "") + require.NoError(t, err) return p } @@ -47,7 +48,7 @@ func TestSkipFiles(t *testing.T) { } func TestSkipFilesInvalidPattern(t *testing.T) { - p, err := NewSkipFiles([]string{"\\o"}) + p, err := NewSkipFiles([]string{"\\o"}, "") assert.Error(t, err) assert.Nil(t, p) } diff --git a/pkg/result/processors/sort_results.go b/pkg/result/processors/sort_results.go index 740c4fa8c37a..8e4af57e6332 100644 --- a/pkg/result/processors/sort_results.go +++ b/pkg/result/processors/sort_results.go @@ -1,6 +1,9 @@ package processors import ( + "errors" + "fmt" + "slices" "sort" "strings" @@ -13,89 +16,123 @@ import ( // by sorting results.Issues using processor step, and chain based // rules that can compare different properties of the Issues struct. +const ( + orderNameFile = "file" + orderNameLinter = "linter" + orderNameSeverity = "severity" +) + var _ Processor = (*SortResults)(nil) type SortResults struct { - cmp comparator - cfg *config.Config + cmps map[string]*comparator + + cfg *config.Output } func NewSortResults(cfg *config.Config) *SortResults { - // For sorting we are comparing (in next order): file names, line numbers, - // position, and finally - giving up. return &SortResults{ - cmp: ByName{ - next: ByLine{ - next: ByColumn{}, - }, + cmps: map[string]*comparator{ + // For sorting we are comparing (in next order): + // file names, line numbers, position, and finally - giving up. + orderNameFile: byFileName().SetNext(byLine().SetNext(byColumn())), + // For sorting we are comparing: linter name + orderNameLinter: byLinter(), + // For sorting we are comparing: severity + orderNameSeverity: bySeverity(), }, - cfg: cfg, + cfg: &cfg.Output, } } // Process is performing sorting of the result issues. func (sr SortResults) Process(issues []result.Issue) ([]result.Issue, error) { - if !sr.cfg.Output.SortResults { + if !sr.cfg.SortResults { return issues, nil } + if len(sr.cfg.SortOrder) == 0 { + sr.cfg.SortOrder = []string{orderNameFile} + } + + var cmps []*comparator + for _, name := range sr.cfg.SortOrder { + if c, ok := sr.cmps[name]; ok { + cmps = append(cmps, c) + } else { + return nil, fmt.Errorf("unsupported sort-order name %q", name) + } + } + + cmp, err := mergeComparators(cmps) + if err != nil { + return nil, err + } + sort.Slice(issues, func(i, j int) bool { - return sr.cmp.Compare(&issues[i], &issues[j]) == Less + return cmp.Compare(&issues[i], &issues[j]) == less }) return issues, nil } func (sr SortResults) Name() string { return "sort_results" } -func (sr SortResults) Finish() {} + +func (sr SortResults) Finish() {} type compareResult int const ( - Less compareResult = iota - 1 - Equal - Greater - None + less compareResult = iota - 1 + equal + greater + none ) func (c compareResult) isNeutral() bool { // return true if compare result is incomparable or equal. - return c == None || c == Equal + return c == none || c == equal } func (c compareResult) String() string { switch c { - case Less: - return "Less" - case Equal: - return "Equal" - case Greater: - return "Greater" + case less: + return "less" + case equal: + return "equal" + case greater: + return "greater" + default: + return "none" } - - return "None" } -// comparator describe how to implement compare for two "issues" lexicographically -type comparator interface { - Compare(a, b *result.Issue) compareResult - Next() comparator +// comparator describes how to implement compare for two "issues". +type comparator struct { + name string + compare func(a, b *result.Issue) compareResult + next *comparator } -var ( - _ comparator = (*ByName)(nil) - _ comparator = (*ByLine)(nil) - _ comparator = (*ByColumn)(nil) -) +func (cmp *comparator) Next() *comparator { return cmp.next } -type ByName struct{ next comparator } +func (cmp *comparator) SetNext(c *comparator) *comparator { + cmp.next = c + return cmp +} -func (cmp ByName) Next() comparator { return cmp.next } +func (cmp *comparator) String() string { + s := cmp.name + if cmp.Next() != nil { + s += " > " + cmp.Next().String() + } -func (cmp ByName) Compare(a, b *result.Issue) compareResult { - var res compareResult + return s +} - if res = compareResult(strings.Compare(a.FilePath(), b.FilePath())); !res.isNeutral() { +func (cmp *comparator) Compare(a, b *result.Issue) compareResult { + res := cmp.compare(a, b) + if !res.isNeutral() { return res } @@ -106,40 +143,95 @@ func (cmp ByName) Compare(a, b *result.Issue) compareResult { return res } -type ByLine struct{ next comparator } +func byFileName() *comparator { + return &comparator{ + name: "byFileName", + compare: func(a, b *result.Issue) compareResult { + return compareResult(strings.Compare(a.FilePath(), b.FilePath())) + }, + } +} + +func byLine() *comparator { + return &comparator{ + name: "byLine", + compare: func(a, b *result.Issue) compareResult { + return numericCompare(a.Line(), b.Line()) + }, + } +} + +func byColumn() *comparator { + return &comparator{ + name: "byColumn", + compare: func(a, b *result.Issue) compareResult { + return numericCompare(a.Column(), b.Column()) + }, + } +} -func (cmp ByLine) Next() comparator { return cmp.next } +func byLinter() *comparator { + return &comparator{ + name: "byLinter", + compare: func(a, b *result.Issue) compareResult { + return compareResult(strings.Compare(a.FromLinter, b.FromLinter)) + }, + } +} -func (cmp ByLine) Compare(a, b *result.Issue) compareResult { - var res compareResult +func bySeverity() *comparator { + return &comparator{ + name: "bySeverity", + compare: func(a, b *result.Issue) compareResult { + return severityCompare(a.Severity, b.Severity) + }, + } +} - if res = numericCompare(a.Line(), b.Line()); !res.isNeutral() { - return res +func mergeComparators(cmps []*comparator) (*comparator, error) { + if len(cmps) == 0 { + return nil, errors.New("no comparator") } - if next := cmp.Next(); next != nil { - return next.Compare(a, b) + for i := 0; i < len(cmps)-1; i++ { + findComparatorTip(cmps[i]).SetNext(cmps[i+1]) } - return res + return cmps[0], nil } -type ByColumn struct{ next comparator } +func findComparatorTip(cmp *comparator) *comparator { + if cmp.Next() != nil { + return findComparatorTip(cmp.Next()) + } -func (cmp ByColumn) Next() comparator { return cmp.next } + return cmp +} -func (cmp ByColumn) Compare(a, b *result.Issue) compareResult { - var res compareResult +func severityCompare(a, b string) compareResult { + // The position inside the slice define the importance (lower to higher). + classic := []string{"low", "medium", "high", "warning", "error"} + + if slices.Contains(classic, a) && slices.Contains(classic, b) { + switch { + case slices.Index(classic, a) > slices.Index(classic, b): + return greater + case slices.Index(classic, a) < slices.Index(classic, b): + return less + default: + return equal + } + } - if res = numericCompare(a.Column(), b.Column()); !res.isNeutral() { - return res + if slices.Contains(classic, a) { + return greater } - if next := cmp.Next(); next != nil { - return next.Compare(a, b) + if slices.Contains(classic, b) { + return less } - return res + return compareResult(strings.Compare(a, b)) } func numericCompare(a, b int) compareResult { @@ -153,14 +245,14 @@ func numericCompare(a, b int) compareResult { switch { case isZeroValuesBoth || isEqual: - return Equal + return equal case isValuesInvalid || isZeroValueInA || isZeroValueInB: - return None + return none case a > b: - return Greater + return greater case a < b: - return Less + return less } - return Equal + return equal } diff --git a/pkg/result/processors/sort_results_test.go b/pkg/result/processors/sort_results_test.go index f1d05da4c28d..c75b0bbeb8db 100644 --- a/pkg/result/processors/sort_results_test.go +++ b/pkg/result/processors/sort_results_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/golangci/golangci-lint/pkg/config" "github.com/golangci/golangci-lint/pkg/result" @@ -13,6 +14,8 @@ import ( var issues = []result.Issue{ { + FromLinter: "b", + Severity: "medium", Pos: token.Position{ Filename: "file_windows.go", Column: 80, @@ -20,6 +23,8 @@ var issues = []result.Issue{ }, }, { + FromLinter: "a", + Severity: "low", Pos: token.Position{ Filename: "file_linux.go", Column: 70, @@ -27,12 +32,37 @@ var issues = []result.Issue{ }, }, { + FromLinter: "c", + Severity: "high", Pos: token.Position{ Filename: "file_darwin.go", Line: 12, }, }, { + FromLinter: "c", + Severity: "high", + Pos: token.Position{ + Filename: "file_darwin.go", + Column: 60, + Line: 10, + }, + }, +} + +var extraSeverityIssues = []result.Issue{ + { + FromLinter: "c", + Severity: "error", + Pos: token.Position{ + Filename: "file_darwin.go", + Column: 60, + Line: 10, + }, + }, + { + FromLinter: "c", + Severity: "aaaa", Pos: token.Position{ Filename: "file_darwin.go", Column: 60, @@ -46,7 +76,7 @@ type compareTestCase struct { expected compareResult } -func testCompareValues(t *testing.T, cmp comparator, name string, tests []compareTestCase) { +func testCompareValues(t *testing.T, cmp *comparator, name string, tests []compareTestCase) { t.Parallel() for i := 0; i < len(tests); i++ { @@ -59,85 +89,113 @@ func testCompareValues(t *testing.T, cmp comparator, name string, tests []compar } func TestCompareByLine(t *testing.T) { - testCompareValues(t, ByLine{}, "Compare By Line", []compareTestCase{ - {issues[0], issues[1], Less}, // 10 vs 11 - {issues[0], issues[0], Equal}, // 10 vs 10 - {issues[3], issues[3], Equal}, // 10 vs 10 - {issues[0], issues[3], Equal}, // 10 vs 10 - {issues[3], issues[2], Less}, // 10 vs 12 - {issues[1], issues[1], Equal}, // 11 vs 11 - {issues[1], issues[0], Greater}, // 11 vs 10 - {issues[1], issues[2], Less}, // 11 vs 12 - {issues[2], issues[3], Greater}, // 12 vs 10 - {issues[2], issues[1], Greater}, // 12 vs 11 - {issues[2], issues[2], Equal}, // 12 vs 12 + testCompareValues(t, byLine(), "Compare By Line", []compareTestCase{ + {issues[0], issues[1], less}, // 10 vs 11 + {issues[0], issues[0], equal}, // 10 vs 10 + {issues[3], issues[3], equal}, // 10 vs 10 + {issues[0], issues[3], equal}, // 10 vs 10 + {issues[3], issues[2], less}, // 10 vs 12 + {issues[1], issues[1], equal}, // 11 vs 11 + {issues[1], issues[0], greater}, // 11 vs 10 + {issues[1], issues[2], less}, // 11 vs 12 + {issues[2], issues[3], greater}, // 12 vs 10 + {issues[2], issues[1], greater}, // 12 vs 11 + {issues[2], issues[2], equal}, // 12 vs 12 }) } -func TestCompareByName(t *testing.T) { //nolint:dupl - testCompareValues(t, ByName{}, "Compare By Name", []compareTestCase{ - {issues[0], issues[1], Greater}, // file_windows.go vs file_linux.go - {issues[1], issues[2], Greater}, // file_linux.go vs file_darwin.go - {issues[2], issues[3], Equal}, // file_darwin.go vs file_darwin.go - {issues[1], issues[1], Equal}, // file_linux.go vs file_linux.go - {issues[1], issues[0], Less}, // file_linux.go vs file_windows.go - {issues[3], issues[2], Equal}, // file_darwin.go vs file_darwin.go - {issues[2], issues[1], Less}, // file_darwin.go vs file_linux.go - {issues[0], issues[0], Equal}, // file_windows.go vs file_windows.go - {issues[2], issues[2], Equal}, // file_darwin.go vs file_darwin.go - {issues[3], issues[3], Equal}, // file_darwin.go vs file_darwin.go +func TestCompareByFileName(t *testing.T) { //nolint:dupl + testCompareValues(t, byFileName(), "Compare By File Name", []compareTestCase{ + {issues[0], issues[1], greater}, // file_windows.go vs file_linux.go + {issues[1], issues[2], greater}, // file_linux.go vs file_darwin.go + {issues[2], issues[3], equal}, // file_darwin.go vs file_darwin.go + {issues[1], issues[1], equal}, // file_linux.go vs file_linux.go + {issues[1], issues[0], less}, // file_linux.go vs file_windows.go + {issues[3], issues[2], equal}, // file_darwin.go vs file_darwin.go + {issues[2], issues[1], less}, // file_darwin.go vs file_linux.go + {issues[0], issues[0], equal}, // file_windows.go vs file_windows.go + {issues[2], issues[2], equal}, // file_darwin.go vs file_darwin.go + {issues[3], issues[3], equal}, // file_darwin.go vs file_darwin.go }) } func TestCompareByColumn(t *testing.T) { //nolint:dupl - testCompareValues(t, ByColumn{}, "Compare By Column", []compareTestCase{ - {issues[0], issues[1], Greater}, // 80 vs 70 - {issues[1], issues[2], None}, // 70 vs zero value - {issues[3], issues[3], Equal}, // 60 vs 60 - {issues[2], issues[3], None}, // zero value vs 60 - {issues[2], issues[1], None}, // zero value vs 70 - {issues[1], issues[0], Less}, // 70 vs 80 - {issues[1], issues[1], Equal}, // 70 vs 70 - {issues[3], issues[2], None}, // vs zero value - {issues[2], issues[2], Equal}, // zero value vs zero value - {issues[1], issues[1], Equal}, // 70 vs 70 + testCompareValues(t, byColumn(), "Compare By Column", []compareTestCase{ + {issues[0], issues[1], greater}, // 80 vs 70 + {issues[1], issues[2], none}, // 70 vs zero value + {issues[3], issues[3], equal}, // 60 vs 60 + {issues[2], issues[3], none}, // zero value vs 60 + {issues[2], issues[1], none}, // zero value vs 70 + {issues[1], issues[0], less}, // 70 vs 80 + {issues[1], issues[1], equal}, // 70 vs 70 + {issues[3], issues[2], none}, // vs zero value + {issues[2], issues[2], equal}, // zero value vs zero value + {issues[1], issues[1], equal}, // 70 vs 70 + }) +} + +func TestCompareByLinter(t *testing.T) { //nolint:dupl + testCompareValues(t, byLinter(), "Compare By Linter", []compareTestCase{ + {issues[0], issues[1], greater}, // b vs a + {issues[1], issues[2], less}, // a vs c + {issues[2], issues[3], equal}, // c vs c + {issues[1], issues[1], equal}, // a vs a + {issues[1], issues[0], less}, // a vs b + {issues[3], issues[2], equal}, // c vs c + {issues[2], issues[1], greater}, // c vs a + {issues[0], issues[0], equal}, // b vs b + {issues[2], issues[2], equal}, // a vs a + {issues[3], issues[3], equal}, // c vs c + }) +} + +func TestCompareBySeverity(t *testing.T) { + testCompareValues(t, bySeverity(), "Compare By Severity", []compareTestCase{ + {issues[0], issues[1], greater}, // medium vs low + {issues[1], issues[2], less}, // low vs high + {issues[2], issues[3], equal}, // high vs high + {issues[1], issues[1], equal}, // low vs low + {issues[1], issues[0], less}, // low vs medium + {issues[3], issues[2], equal}, // high vs high + {issues[2], issues[1], greater}, // high vs low + {issues[0], issues[0], equal}, // medium vs medium + {issues[2], issues[2], equal}, // low vs low + {issues[3], issues[3], equal}, // high vs high + {extraSeverityIssues[0], extraSeverityIssues[1], greater}, // classic vs unknown + {extraSeverityIssues[1], extraSeverityIssues[0], less}, // unknown vs classic }) } func TestCompareNested(t *testing.T) { - var cmp = ByName{ - next: ByLine{ - next: ByColumn{}, - }, - } + cmp := byFileName().SetNext(byLine().SetNext(byColumn())) testCompareValues(t, cmp, "Nested Comparing", []compareTestCase{ - {issues[1], issues[0], Less}, // file_linux.go vs file_windows.go - {issues[2], issues[1], Less}, // file_darwin.go vs file_linux.go - {issues[0], issues[1], Greater}, // file_windows.go vs file_linux.go - {issues[1], issues[2], Greater}, // file_linux.go vs file_darwin.go - {issues[3], issues[2], Less}, // file_darwin.go vs file_darwin.go, 10 vs 12 - {issues[0], issues[0], Equal}, // file_windows.go vs file_windows.go - {issues[2], issues[3], Greater}, // file_darwin.go vs file_darwin.go, 12 vs 10 - {issues[1], issues[1], Equal}, // file_linux.go vs file_linux.go - {issues[2], issues[2], Equal}, // file_darwin.go vs file_darwin.go - {issues[3], issues[3], Equal}, // file_darwin.go vs file_darwin.go + {issues[1], issues[0], less}, // file_linux.go vs file_windows.go + {issues[2], issues[1], less}, // file_darwin.go vs file_linux.go + {issues[0], issues[1], greater}, // file_windows.go vs file_linux.go + {issues[1], issues[2], greater}, // file_linux.go vs file_darwin.go + {issues[3], issues[2], less}, // file_darwin.go vs file_darwin.go, 10 vs 12 + {issues[0], issues[0], equal}, // file_windows.go vs file_windows.go + {issues[2], issues[3], greater}, // file_darwin.go vs file_darwin.go, 12 vs 10 + {issues[1], issues[1], equal}, // file_linux.go vs file_linux.go + {issues[2], issues[2], equal}, // file_darwin.go vs file_darwin.go + {issues[3], issues[3], equal}, // file_darwin.go vs file_darwin.go }) } func TestNumericCompare(t *testing.T) { - var tests = []struct { + tests := []struct { a, b int expected compareResult }{ - {0, 0, Equal}, - {0, 1, None}, - {1, 0, None}, - {1, -1, None}, - {-1, 1, None}, - {1, 1, Equal}, - {1, 2, Less}, - {2, 1, Greater}, + {0, 0, equal}, + {0, 1, none}, + {1, 0, none}, + {1, -1, none}, + {-1, 1, none}, + {1, 1, equal}, + {1, 2, less}, + {2, 1, greater}, } t.Parallel() @@ -152,31 +210,76 @@ func TestNumericCompare(t *testing.T) { } func TestNoSorting(t *testing.T) { - var tests = make([]result.Issue, len(issues)) + tests := make([]result.Issue, len(issues)) copy(tests, issues) - var sr = NewSortResults(&config.Config{}) + sr := NewSortResults(&config.Config{}) results, err := sr.Process(tests) + require.NoError(t, err) assert.Equal(t, tests, results) - assert.Nil(t, err, nil) } func TestSorting(t *testing.T) { - var tests = make([]result.Issue, len(issues)) + tests := make([]result.Issue, len(issues)) copy(tests, issues) - var expected = make([]result.Issue, len(issues)) - expected[0] = issues[3] - expected[1] = issues[2] - expected[2] = issues[1] - expected[3] = issues[0] - - var cfg = config.Config{} + cfg := config.Config{} cfg.Output.SortResults = true - var sr = NewSortResults(&cfg) + sr := NewSortResults(&cfg) results, err := sr.Process(tests) - assert.Equal(t, results, expected) - assert.Nil(t, err, nil) + require.NoError(t, err) + assert.Equal(t, []result.Issue{issues[3], issues[2], issues[1], issues[0]}, results) +} + +func Test_mergeComparators(t *testing.T) { + testCases := []struct { + desc string + cmps []*comparator + expected string + }{ + { + desc: "one", + cmps: []*comparator{byLinter()}, + expected: "byLinter", + }, + { + desc: "two", + cmps: []*comparator{byLinter(), byFileName()}, + expected: "byLinter > byFileName", + }, + { + desc: "all", + cmps: []*comparator{bySeverity(), byLinter(), byFileName(), byLine(), byColumn()}, + expected: "bySeverity > byLinter > byFileName > byLine > byColumn", + }, + { + desc: "nested", + cmps: []*comparator{bySeverity(), byFileName().SetNext(byLine().SetNext(byColumn())), byLinter()}, + expected: "bySeverity > byFileName > byLine > byColumn > byLinter", + }, + { + desc: "all reverse", + cmps: []*comparator{byColumn(), byLine(), byFileName(), byLinter(), bySeverity()}, + expected: "byColumn > byLine > byFileName > byLinter > bySeverity", + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + cmp, err := mergeComparators(test.cmps) + require.NoError(t, err) + + assert.Equal(t, test.expected, cmp.String()) + }) + } +} + +func Test_mergeComparators_error(t *testing.T) { + _, err := mergeComparators(nil) + require.EqualError(t, err, "no comparator") } diff --git a/pkg/result/processors/source_code.go b/pkg/result/processors/source_code.go index cfd73cb98e04..005b3143f8d0 100644 --- a/pkg/result/processors/source_code.go +++ b/pkg/result/processors/source_code.go @@ -25,22 +25,22 @@ func (p SourceCode) Name() string { } func (p SourceCode) Process(issues []result.Issue) ([]result.Issue, error) { - return transformIssues(issues, func(i *result.Issue) *result.Issue { - newI := *i + return transformIssues(issues, func(issue *result.Issue) *result.Issue { + newIssue := *issue - lineRange := i.GetLineRange() + lineRange := issue.GetLineRange() for lineNumber := lineRange.From; lineNumber <= lineRange.To; lineNumber++ { - line, err := p.lineCache.GetLine(i.FilePath(), lineNumber) + line, err := p.lineCache.GetLine(issue.FilePath(), lineNumber) if err != nil { p.log.Warnf("Failed to get line %d for file %s: %s", - lineNumber, i.FilePath(), err) - return i + lineNumber, issue.FilePath(), err) + return issue } - newI.SourceLines = append(newI.SourceLines, line) + newIssue.SourceLines = append(newIssue.SourceLines, line) } - return &newI + return &newIssue }), nil } diff --git a/pkg/result/processors/testdata/autogen_go_strict.go b/pkg/result/processors/testdata/autogen_go_strict.go new file mode 100644 index 000000000000..0f32d4af731f --- /dev/null +++ b/pkg/result/processors/testdata/autogen_go_strict.go @@ -0,0 +1,7 @@ +// foo foo foo. +// foo foo foo. +// foo foo foo. + +// Code generated by example — DO NOT EDIT. + +package testdata diff --git a/pkg/result/processors/testdata/autogen_go_strict_invalid.go b/pkg/result/processors/testdata/autogen_go_strict_invalid.go new file mode 100644 index 000000000000..c804e3e5f934 --- /dev/null +++ b/pkg/result/processors/testdata/autogen_go_strict_invalid.go @@ -0,0 +1,6 @@ +package testdata + +// Code generated by example; DO NOT EDIT. +func _() { + +} diff --git a/pkg/result/processors/uniq_by_line.go b/pkg/result/processors/uniq_by_line.go index dc0e1e8cf667..aad1e019e35f 100644 --- a/pkg/result/processors/uniq_by_line.go +++ b/pkg/result/processors/uniq_by_line.go @@ -5,8 +5,10 @@ import ( "github.com/golangci/golangci-lint/pkg/result" ) -type lineToCount map[int]int -type fileToLineToCount map[string]lineToCount +type ( + lineToCount map[int]int + fileToLineToCount map[string]lineToCount +) type UniqByLine struct { flc fileToLineToCount @@ -31,26 +33,26 @@ func (p *UniqByLine) Process(issues []result.Issue) ([]result.Issue, error) { return issues, nil } - return filterIssues(issues, func(i *result.Issue) bool { - if i.Replacement != nil && p.cfg.Issues.NeedFix { + return filterIssues(issues, func(issue *result.Issue) bool { + if issue.Replacement != nil && p.cfg.Issues.NeedFix { // if issue will be auto-fixed we shouldn't collapse issues: // e.g. one line can contain 2 misspellings, they will be in 2 issues and misspell should fix both of them. return true } - lc := p.flc[i.FilePath()] + lc := p.flc[issue.FilePath()] if lc == nil { lc = lineToCount{} - p.flc[i.FilePath()] = lc + p.flc[issue.FilePath()] = lc } const limit = 1 - count := lc[i.Line()] + count := lc[issue.Line()] if count == limit { return false } - lc[i.Line()]++ + lc[issue.Line()]++ return true }), nil } diff --git a/pkg/sliceutil/sliceutil.go b/pkg/sliceutil/sliceutil.go deleted file mode 100644 index cb89e34e0c3a..000000000000 --- a/pkg/sliceutil/sliceutil.go +++ /dev/null @@ -1,17 +0,0 @@ -package sliceutil - -// IndexOf get the index of the given value in the given string slice, -// or -1 if not found. -func IndexOf(slice []string, value string) int { - for i, v := range slice { - if v == value { - return i - } - } - return -1 -} - -// Contains check if a string slice contains a value. -func Contains(slice []string, value string) bool { - return IndexOf(slice, value) != -1 -} diff --git a/pkg/sliceutil/sliceutil_test.go b/pkg/sliceutil/sliceutil_test.go deleted file mode 100644 index 647125bf1814..000000000000 --- a/pkg/sliceutil/sliceutil_test.go +++ /dev/null @@ -1,17 +0,0 @@ -package sliceutil - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestContains(t *testing.T) { - assert.True(t, Contains([]string{"val1", "val2", "val3"}, "val2")) - assert.False(t, Contains([]string{"val1", "val2", "val3"}, "val4")) -} - -func TestIndexOf(t *testing.T) { - assert.Equal(t, 1, IndexOf([]string{"val1", "val2", "val3"}, "val2")) - assert.Equal(t, -1, IndexOf([]string{"val1", "val2", "val3"}, "val4")) -} diff --git a/scripts/expand_website_templates/main.go b/scripts/expand_website_templates/main.go deleted file mode 100644 index a9d39ddec441..000000000000 --- a/scripts/expand_website_templates/main.go +++ /dev/null @@ -1,569 +0,0 @@ -package main - -import ( - "bytes" - "crypto/sha256" - "encoding/hex" - "encoding/json" - "flag" - "fmt" - "io" - "log" - "net/http" - "os" - "os/exec" - "path/filepath" - "reflect" - "sort" - "strings" - - "gopkg.in/yaml.v3" - - "github.com/golangci/golangci-lint/internal/renameio" - "github.com/golangci/golangci-lint/pkg/config" - "github.com/golangci/golangci-lint/pkg/lint/linter" - "github.com/golangci/golangci-lint/pkg/lint/lintersdb" -) - -const listItemPrefix = "list-item-" - -var stateFilePath = filepath.Join("docs", "template_data.state") - -func main() { - var onlyWriteState bool - flag.BoolVar(&onlyWriteState, "only-state", false, fmt.Sprintf("Only write hash of state to %s and exit", stateFilePath)) - flag.Parse() - - replacements, err := buildTemplateContext() - if err != nil { - log.Fatalf("Failed to build template context: %s", err) - } - - if err = updateStateFile(replacements); err != nil { - log.Fatalf("Failed to update state file: %s", err) - } - - if onlyWriteState { - return - } - - if err := rewriteDocs(replacements); err != nil { - log.Fatalf("Failed to rewrite docs: %s", err) - } - log.Print("Successfully expanded templates") -} - -func updateStateFile(replacements map[string]string) error { - replBytes, err := json.Marshal(replacements) - if err != nil { - return fmt.Errorf("failed to json marshal replacements: %w", err) - } - - h := sha256.New() - if _, err := h.Write(replBytes); err != nil { - return err - } - - var contentBuf bytes.Buffer - contentBuf.WriteString("This file stores hash of website templates to trigger " + - "Netlify rebuild when something changes, e.g. new linter is added.\n") - contentBuf.WriteString(hex.EncodeToString(h.Sum(nil))) - - return renameio.WriteFile(stateFilePath, contentBuf.Bytes(), os.ModePerm) -} - -func rewriteDocs(replacements map[string]string) error { - madeReplacements := map[string]bool{} - err := filepath.Walk(filepath.Join("docs", "src", "docs"), - func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - if info.IsDir() { - return nil - } - return processDoc(path, replacements, madeReplacements) - }) - if err != nil { - return fmt.Errorf("failed to walk dir: %w", err) - } - - if len(madeReplacements) != len(replacements) { - for key := range replacements { - if !madeReplacements[key] { - log.Printf("Replacement %q wasn't performed", key) - } - } - return fmt.Errorf("%d replacements weren't performed", len(replacements)-len(madeReplacements)) - } - return nil -} - -func processDoc(path string, replacements map[string]string, madeReplacements map[string]bool) error { - contentBytes, err := os.ReadFile(path) - if err != nil { - return fmt.Errorf("failed to read %s: %w", path, err) - } - - content := string(contentBytes) - hasReplacements := false - for key, replacement := range replacements { - nextContent := content - nextContent = strings.ReplaceAll(nextContent, fmt.Sprintf("{.%s}", key), replacement) - - // Yaml formatter in mdx code section makes extra spaces, need to match them too. - nextContent = strings.ReplaceAll(nextContent, fmt.Sprintf("{ .%s }", key), replacement) - - if nextContent != content { - hasReplacements = true - madeReplacements[key] = true - content = nextContent - } - } - if !hasReplacements { - return nil - } - - log.Printf("Expanded template in %s, saving it", path) - if err = renameio.WriteFile(path, []byte(content), os.ModePerm); err != nil { - return fmt.Errorf("failed to write changes to file %s: %w", path, err) - } - - return nil -} - -type latestRelease struct { - TagName string `json:"tag_name"` -} - -func getLatestVersion() (string, error) { - req, err := http.NewRequest( //nolint:noctx - http.MethodGet, - "https://api.github.com/repos/golangci/golangci-lint/releases/latest", - http.NoBody, - ) - if err != nil { - return "", fmt.Errorf("failed to prepare a http request: %w", err) - } - req.Header.Add("Accept", "application/vnd.github.v3+json") - resp, err := http.DefaultClient.Do(req) - if err != nil { - return "", fmt.Errorf("failed to get http response for the latest tag: %w", err) - } - defer resp.Body.Close() - body, err := io.ReadAll(resp.Body) - if err != nil { - return "", fmt.Errorf("failed to read a body for the latest tag: %w", err) - } - release := latestRelease{} - err = json.Unmarshal(body, &release) - if err != nil { - return "", fmt.Errorf("failed to unmarshal the body for the latest tag: %w", err) - } - return release.TagName, nil -} - -func buildTemplateContext() (map[string]string, error) { - golangciYamlExample, err := os.ReadFile(".golangci.reference.yml") - if err != nil { - return nil, fmt.Errorf("can't read .golangci.reference.yml: %w", err) - } - - snippets, err := extractExampleSnippets(golangciYamlExample) - if err != nil { - return nil, fmt.Errorf("can't read .golangci.reference.yml: %w", err) - } - - if err = exec.Command("make", "build").Run(); err != nil { - return nil, fmt.Errorf("can't run go install: %w", err) - } - - lintersOut, err := exec.Command("./golangci-lint", "help", "linters").Output() - if err != nil { - return nil, fmt.Errorf("can't run linters cmd: %w", err) - } - - lintersOutParts := bytes.Split(lintersOut, []byte("\n\n")) - - helpCmd := exec.Command("./golangci-lint", "run", "-h") - helpCmd.Env = append(helpCmd.Env, os.Environ()...) - helpCmd.Env = append(helpCmd.Env, "HELP_RUN=1") // make default concurrency stable: don't depend on machine CPU number - help, err := helpCmd.Output() - if err != nil { - return nil, fmt.Errorf("can't run help cmd: %w", err) - } - - helpLines := bytes.Split(help, []byte("\n")) - shortHelp := bytes.Join(helpLines[2:], []byte("\n")) - changeLog, err := os.ReadFile("CHANGELOG.md") - if err != nil { - return nil, err - } - - latestVersion, err := getLatestVersion() - if err != nil { - return nil, fmt.Errorf("failed to get the latest version: %w", err) - } - - return map[string]string{ - "LintersExample": snippets.LintersSettings, - "ConfigurationExample": snippets.ConfigurationFile, - "LintersCommandOutputEnabledOnly": string(lintersOutParts[0]), - "LintersCommandOutputDisabledOnly": string(lintersOutParts[1]), - "EnabledByDefaultLinters": getLintersListMarkdown(true), - "DisabledByDefaultLinters": getLintersListMarkdown(false), - "DefaultExclusions": getDefaultExclusions(), - "ThanksList": getThanksList(), - "RunHelpText": string(shortHelp), - "ChangeLog": string(changeLog), - "LatestVersion": latestVersion, - }, nil -} - -func getDefaultExclusions() string { - bufferString := bytes.NewBufferString("") - - for _, pattern := range config.DefaultExcludePatterns { - _, _ = fmt.Fprintln(bufferString) - _, _ = fmt.Fprintf(bufferString, "### %s\n", pattern.ID) - _, _ = fmt.Fprintln(bufferString) - _, _ = fmt.Fprintf(bufferString, "- linter: `%s`\n", pattern.Linter) - _, _ = fmt.Fprintf(bufferString, "- pattern: `%s`\n", strings.ReplaceAll(pattern.Pattern, "`", "`")) - _, _ = fmt.Fprintf(bufferString, "- why: %s\n", pattern.Why) - } - - return bufferString.String() -} - -func getLintersListMarkdown(enabled bool) string { - var neededLcs []*linter.Config - lcs := lintersdb.NewManager(nil, nil).GetAllSupportedLinterConfigs() - for _, lc := range lcs { - if lc.EnabledByDefault == enabled { - neededLcs = append(neededLcs, lc) - } - } - - sort.Slice(neededLcs, func(i, j int) bool { - return neededLcs[i].Name() < neededLcs[j].Name() - }) - - lines := []string{ - "|Name|Description|Presets|AutoFix|Since|", - "|---|---|---|---|---|---|", - } - - for _, lc := range neededLcs { - line := fmt.Sprintf("|%s|%s|%s|%v|%s|", - getName(lc), - getDesc(lc), - strings.Join(lc.InPresets, ", "), - check(lc.CanAutoFix, "Auto fix supported"), - lc.Since, - ) - lines = append(lines, line) - } - - return strings.Join(lines, "\n") -} - -func getName(lc *linter.Config) string { - name := lc.Name() - - if lc.OriginalURL != "" { - name = fmt.Sprintf("[%s](%s)", name, lc.OriginalURL) - } - - if hasSettings(lc.Name()) { - name = fmt.Sprintf("%s [%s](#%s)", name, spanWithID(listItemPrefix+lc.Name(), "Configuration", "⚙️"), lc.Name()) - } - - if !lc.IsDeprecated() { - return name - } - - title := "deprecated" - if lc.Deprecation.Replacement != "" { - title += fmt.Sprintf(" since %s", lc.Deprecation.Since) - } - - return name + " " + span(title, "⚠") -} - -func getDesc(lc *linter.Config) string { - desc := lc.Linter.Desc() - if lc.IsDeprecated() { - desc = lc.Deprecation.Message - if lc.Deprecation.Replacement != "" { - desc += fmt.Sprintf(" Replaced by %s.", lc.Deprecation.Replacement) - } - } - - return strings.ReplaceAll(desc, "\n", "
") -} - -func check(b bool, title string) string { - if b { - return span(title, "✔") - } - return "" -} - -func hasSettings(name string) bool { - tp := reflect.TypeOf(config.LintersSettings{}) - - for i := 0; i < tp.NumField(); i++ { - if strings.EqualFold(name, tp.Field(i).Name) { - return true - } - } - - return false -} - -func span(title, icon string) string { - return fmt.Sprintf(`%s`, title, icon) -} - -func spanWithID(id, title, icon string) string { - return fmt.Sprintf(`%s`, id, title, icon) -} - -type authorDetails struct { - Linters []string - Profile string - Avatar string -} - -func getThanksList() string { - addedAuthors := map[string]*authorDetails{} - - for _, lc := range lintersdb.NewManager(nil, nil).GetAllSupportedLinterConfigs() { - if lc.OriginalURL == "" { - continue - } - - linterURL := lc.OriginalURL - if lc.Name() == "staticcheck" { - linterURL = "https://github.com/dominikh/go-tools" - } - - if author := extractAuthor(linterURL, "https://github.com/"); author != "" && author != "golangci" { - if _, ok := addedAuthors[author]; ok { - addedAuthors[author].Linters = append(addedAuthors[author].Linters, lc.Name()) - } else { - addedAuthors[author] = &authorDetails{ - Linters: []string{lc.Name()}, - Profile: fmt.Sprintf("[%[1]s](https://github.com/sponsors/%[1]s)", author), - Avatar: fmt.Sprintf(`%[1]s`, author), - } - } - } else if author := extractAuthor(linterURL, "https://gitlab.com/"); author != "" { - if _, ok := addedAuthors[author]; ok { - addedAuthors[author].Linters = append(addedAuthors[author].Linters, lc.Name()) - } else { - addedAuthors[author] = &authorDetails{ - Linters: []string{lc.Name()}, - Profile: fmt.Sprintf("[%[1]s](https://gitlab.com/%[1]s)", author), - } - } - } else { - continue - } - } - - var authors []string - for author := range addedAuthors { - authors = append(authors, author) - } - - sort.Slice(authors, func(i, j int) bool { - return strings.ToLower(authors[i]) < strings.ToLower(authors[j]) - }) - - lines := []string{ - "|Author|Linter(s)|", - "|---|---|", - } - - for _, author := range authors { - lines = append(lines, fmt.Sprintf("|%s %s|%s|", - addedAuthors[author].Avatar, addedAuthors[author].Profile, strings.Join(addedAuthors[author].Linters, ", "))) - } - - return strings.Join(lines, "\n") -} - -func extractAuthor(originalURL, prefix string) string { - if !strings.HasPrefix(originalURL, prefix) { - return "" - } - - return strings.SplitN(strings.TrimPrefix(originalURL, prefix), "/", 2)[0] -} - -type SettingSnippets struct { - ConfigurationFile string - LintersSettings string -} - -func extractExampleSnippets(example []byte) (*SettingSnippets, error) { - var data yaml.Node - err := yaml.Unmarshal(example, &data) - if err != nil { - return nil, err - } - - root := data.Content[0] - - globalNode := &yaml.Node{ - Kind: root.Kind, - Style: root.Style, - Tag: root.Tag, - Value: root.Value, - Anchor: root.Anchor, - Alias: root.Alias, - HeadComment: root.HeadComment, - LineComment: root.LineComment, - FootComment: root.FootComment, - Line: root.Line, - Column: root.Column, - } - - snippets := SettingSnippets{} - - builder := strings.Builder{} - - for j, node := range root.Content { - switch node.Value { - case "run", "output", "linters", "linters-settings", "issues", "severity": - default: - continue - } - - nextNode := root.Content[j+1] - - newNode := &yaml.Node{ - Kind: nextNode.Kind, - Content: []*yaml.Node{ - { - HeadComment: fmt.Sprintf("See the dedicated %q documentation section.", node.Value), - Kind: node.Kind, - Style: node.Style, - Tag: node.Tag, - Value: "option", - }, - { - Kind: node.Kind, - Style: node.Style, - Tag: node.Tag, - Value: "value", - }, - }, - } - - globalNode.Content = append(globalNode.Content, node, newNode) - - if node.Value == "linters-settings" { - snippets.LintersSettings, err = getLintersSettingSnippets(node, nextNode) - if err != nil { - return nil, err - } - - _, _ = builder.WriteString( - fmt.Sprintf( - "### `%s` configuration\n\nSee the dedicated [linters-settings](/usage/linters) documentation section.\n\n", - node.Value, - ), - ) - continue - } - - nodeSection := &yaml.Node{ - Kind: root.Kind, - Style: root.Style, - Tag: root.Tag, - Value: root.Value, - Content: []*yaml.Node{node, nextNode}, - } - - snippet, errSnip := marshallSnippet(nodeSection) - if errSnip != nil { - return nil, errSnip - } - - _, _ = builder.WriteString(fmt.Sprintf("### `%s` configuration\n\n%s", node.Value, snippet)) - } - - overview, err := marshallSnippet(globalNode) - if err != nil { - return nil, err - } - - snippets.ConfigurationFile = overview + builder.String() - - return &snippets, nil -} - -func getLintersSettingSnippets(node, nextNode *yaml.Node) (string, error) { - builder := &strings.Builder{} - - for i := 0; i < len(nextNode.Content); i += 2 { - r := &yaml.Node{ - Kind: nextNode.Kind, - Style: nextNode.Style, - Tag: nextNode.Tag, - Value: node.Value, - Content: []*yaml.Node{ - { - Kind: node.Kind, - Value: node.Value, - }, - { - Kind: nextNode.Kind, - Content: []*yaml.Node{nextNode.Content[i], nextNode.Content[i+1]}, - }, - }, - } - - _, _ = fmt.Fprintf(builder, "### %s\n\n", nextNode.Content[i].Value) - _, _ = fmt.Fprintln(builder, "```yaml") - - encoder := yaml.NewEncoder(builder) - encoder.SetIndent(2) - - err := encoder.Encode(r) - if err != nil { - return "", err - } - - _, _ = fmt.Fprintln(builder, "```") - _, _ = fmt.Fprintln(builder) - _, _ = fmt.Fprintf(builder, "[%s](#%s)\n\n", span("Back to the top", "🔼"), listItemPrefix+nextNode.Content[i].Value) - _, _ = fmt.Fprintln(builder) - } - - return builder.String(), nil -} - -func marshallSnippet(node *yaml.Node) (string, error) { - builder := &strings.Builder{} - - if node.Value != "" { - _, _ = fmt.Fprintf(builder, "### %s\n\n", node.Value) - } - _, _ = fmt.Fprintln(builder, "```yaml") - - encoder := yaml.NewEncoder(builder) - encoder.SetIndent(2) - - err := encoder.Encode(node) - if err != nil { - return "", err - } - - _, _ = fmt.Fprintln(builder, "```") - _, _ = fmt.Fprintln(builder) - - return builder.String(), nil -} diff --git a/scripts/gen_github_action_config/go.mod b/scripts/gen_github_action_config/go.mod index c896001f0f50..b85d092b275a 100644 --- a/scripts/gen_github_action_config/go.mod +++ b/scripts/gen_github_action_config/go.mod @@ -1,16 +1,15 @@ module github.com/golangci/golangci-lint/scripts/gen_github_action_config -go 1.18 +go 1.21 require ( - github.com/shurcooL/githubv4 v0.0.0-20220922232305-70b4d362a8cb - golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 + github.com/shurcooL/githubv4 v0.0.0-20240120211514-18a1ae0e79dc + golang.org/x/oauth2 v0.18.0 ) require ( - github.com/golang/protobuf v1.5.2 // indirect - github.com/shurcooL/graphql v0.0.0-20220606043923-3cf50f8a0a29 // indirect - golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.28.0 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/protobuf v1.33.0 // indirect ) diff --git a/scripts/gen_github_action_config/go.sum b/scripts/gen_github_action_config/go.sum index 05a78d29a013..ecf74253b38e 100644 --- a/scripts/gen_github_action_config/go.sum +++ b/scripts/gen_github_action_config/go.sum @@ -1,27 +1,44 @@ -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= -github.com/shurcooL/githubv4 v0.0.0-20220922232305-70b4d362a8cb h1:Ptg7eUGaD22iZMracv+h7ghDJkGaeQ1FQ9BnkRB6DOo= -github.com/shurcooL/githubv4 v0.0.0-20220922232305-70b4d362a8cb/go.mod h1:hAF0iLZy4td2EX+/8Tw+4nodhlMrwN3HupfaXj3zkGo= -github.com/shurcooL/graphql v0.0.0-20220606043923-3cf50f8a0a29 h1:B1PEwpArrNp4dkQrfxh/abbBAOZBVp0ds+fBEOUOqOc= -github.com/shurcooL/graphql v0.0.0-20220606043923-3cf50f8a0a29/go.mod h1:AuYgA5Kyo4c7HfUmvRGs/6rGlMMV/6B1bVnB9JxJEEg= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/shurcooL/githubv4 v0.0.0-20240120211514-18a1ae0e79dc h1:vH0NQbIDk+mJLvBliNGfcQgUmhlniWBDXC79oRxfZA0= +github.com/shurcooL/githubv4 v0.0.0-20240120211514-18a1ae0e79dc/go.mod h1:zqMwyHmnN/eDOZOdiTohqIUKUrTFX62PNlu7IJdu0q8= +github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 h1:17JxqqJY66GmZVHkmAsGEkcIu0oCe3AM420QDgGwZx0= +github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466/go.mod h1:9dIRpgIY7hVhoqfe0/FcYp0bpInZaT7dc3BYOprrIUE= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e h1:TsQ7F31D3bUCLeqPT0u+yjp1guoArKaNKmCr22PYgTQ= -golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 h1:nt+Q6cXKz4MosCSpnbMtqiQ8Oz0pxTef2B4Vca2lvfk= -golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= +golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= +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/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/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/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.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/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/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +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= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= 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.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= diff --git a/scripts/gen_github_action_config/main.go b/scripts/gen_github_action_config/main.go index e5998f869dea..d6b6ba769a2d 100644 --- a/scripts/gen_github_action_config/main.go +++ b/scripts/gen_github_action_config/main.go @@ -215,7 +215,7 @@ func fetchAllReleases(ctx context.Context) ([]release, error) { } `graphql:"repository(owner: $owner, name: $name)"` } - vars := map[string]interface{}{ + vars := map[string]any{ "owner": githubv4.String("golangci"), "name": githubv4.String("golangci-lint"), "releasesCursor": (*githubv4.String)(nil), diff --git a/scripts/website/dump_info/main.go b/scripts/website/dump_info/main.go new file mode 100644 index 000000000000..599981ea50ae --- /dev/null +++ b/scripts/website/dump_info/main.go @@ -0,0 +1,132 @@ +package main + +import ( + "bytes" + "encoding/json" + "fmt" + "log" + "os" + "os/exec" + "path/filepath" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/lint/lintersdb" + "github.com/golangci/golangci-lint/scripts/website/types" +) + +func main() { + err := saveLinters() + if err != nil { + log.Fatalf("Save linters: %v", err) + } + + err = saveDefaultExclusions() + if err != nil { + log.Fatalf("Save default exclusions: %v", err) + } + + err = saveCLIHelp(filepath.Join("assets", "cli-help.json")) + if err != nil { + log.Fatalf("Save CLI help: %v", err) + } +} + +func saveLinters() error { + linters, _ := lintersdb.NewLinterBuilder().Build(config.NewDefault()) + + var wraps []types.LinterWrapper + for _, l := range linters { + wrapper := types.LinterWrapper{ + Name: l.Linter.Name(), + Desc: l.Linter.Desc(), + EnabledByDefault: l.EnabledByDefault, + LoadMode: l.LoadMode, + InPresets: l.InPresets, + AlternativeNames: l.AlternativeNames, + OriginalURL: l.OriginalURL, + Internal: l.Internal, + CanAutoFix: l.CanAutoFix, + IsSlow: l.IsSlow, + DoesChangeTypes: l.DoesChangeTypes, + Since: l.Since, + } + + if l.Deprecation != nil { + wrapper.Deprecation = &types.Deprecation{ + Since: l.Deprecation.Since, + Message: l.Deprecation.Message, + Replacement: l.Deprecation.Replacement, + } + } + + wraps = append(wraps, wrapper) + } + + return saveToJSONFile(filepath.Join("assets", "linters-info.json"), wraps) +} + +func saveDefaultExclusions() error { + var excludePatterns []types.ExcludePattern + + for _, pattern := range config.DefaultExcludePatterns { + excludePatterns = append(excludePatterns, types.ExcludePattern{ + ID: pattern.ID, + Pattern: pattern.Pattern, + Linter: pattern.Linter, + Why: pattern.Why, + }) + } + + return saveToJSONFile(filepath.Join("assets", "default-exclusions.json"), excludePatterns) +} + +func saveCLIHelp(dst string) error { + err := exec.Command("make", "build").Run() + if err != nil { + return fmt.Errorf("can't run make build: %w", err) + } + + lintersOut, err := exec.Command("./golangci-lint", "help", "linters").Output() + if err != nil { + return fmt.Errorf("can't run linters cmd: %w", err) + } + + lintersOutParts := bytes.Split(lintersOut, []byte("\n\n")) + + helpCmd := exec.Command("./golangci-lint", "run", "-h") + helpCmd.Env = append(helpCmd.Env, os.Environ()...) + helpCmd.Env = append(helpCmd.Env, "HELP_RUN=1") // make default concurrency stable: don't depend on machine CPU number + help, err := helpCmd.Output() + if err != nil { + return fmt.Errorf("can't run help cmd: %w", err) + } + + helpLines := bytes.Split(help, []byte("\n")) + shortHelp := bytes.Join(helpLines[2:], []byte("\n")) + + data := types.CLIHelp{ + Enable: string(lintersOutParts[0]), + Help: string(shortHelp), + } + + return saveToJSONFile(dst, data) +} + +func saveToJSONFile(dst string, data any) error { + file, err := os.Create(dst) + if err != nil { + return fmt.Errorf("open file (%s): %w", dst, err) + } + + defer func() { _ = file.Close() }() + + encoder := json.NewEncoder(file) + encoder.SetIndent("", " ") + + err = encoder.Encode(data) + if err != nil { + return fmt.Errorf("encode JSON (%s): %w", dst, err) + } + + return nil +} diff --git a/scripts/website/expand_templates/exclusions.go b/scripts/website/expand_templates/exclusions.go new file mode 100644 index 000000000000..31678d5b7bb9 --- /dev/null +++ b/scripts/website/expand_templates/exclusions.go @@ -0,0 +1,48 @@ +package main + +import ( + "bytes" + "path/filepath" + "strings" + "text/template" + + "github.com/golangci/golangci-lint/scripts/website/types" +) + +const exclusionTmpl = `{{ $tick := "` + "`" + `" }} +### {{ .ID }} + +- linter: {{ $tick }}{{ .Linter }}{{ $tick }} +- pattern: {{ $tick }}{{ .Pattern }}{{ $tick }} +- why: {{ .Why }} +` + +func getDefaultExclusions() (string, error) { + defaultExcludePatterns, err := readJSONFile[[]types.ExcludePattern](filepath.Join("assets", "default-exclusions.json")) + if err != nil { + return "", err + } + + bufferString := bytes.NewBufferString("") + + tmpl, err := template.New("exclusions").Parse(exclusionTmpl) + if err != nil { + return "", err + } + + for _, pattern := range defaultExcludePatterns { + data := map[string]any{ + "ID": pattern.ID, + "Linter": pattern.Linter, + "Pattern": strings.ReplaceAll(pattern.Pattern, "`", "`"), + "Why": pattern.Why, + } + + err := tmpl.Execute(bufferString, data) + if err != nil { + return "", err + } + } + + return bufferString.String(), nil +} diff --git a/scripts/website/expand_templates/linters.go b/scripts/website/expand_templates/linters.go new file mode 100644 index 000000000000..3c7a42db13eb --- /dev/null +++ b/scripts/website/expand_templates/linters.go @@ -0,0 +1,330 @@ +package main + +import ( + "fmt" + "os" + "path/filepath" + "reflect" + "sort" + "strings" + "unicode" + "unicode/utf8" + + "gopkg.in/yaml.v3" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/scripts/website/types" +) + +const listItemPrefix = "list-item-" + +func getExampleSnippets() (*SettingSnippets, error) { + reference, err := os.ReadFile(".golangci.reference.yml") + if err != nil { + return nil, fmt.Errorf("can't read .golangci.reference.yml: %w", err) + } + + snippets, err := extractExampleSnippets(reference) + if err != nil { + return nil, fmt.Errorf("can't extract example snippets from .golangci.reference.yml: %w", err) + } + + return snippets, nil +} + +func getLintersListMarkdown(enabled bool) string { + linters, err := readJSONFile[[]*types.LinterWrapper](filepath.Join("assets", "linters-info.json")) + if err != nil { + panic(err) + } + + var neededLcs []*types.LinterWrapper + for _, lc := range linters { + if lc.Internal { + continue + } + + if lc.EnabledByDefault == enabled { + neededLcs = append(neededLcs, lc) + } + } + + sort.Slice(neededLcs, func(i, j int) bool { + return neededLcs[i].Name < neededLcs[j].Name + }) + + lines := []string{ + "|Name|Description|Presets|AutoFix|Since|", + "|---|---|---|---|---|---|", + } + + for _, lc := range neededLcs { + line := fmt.Sprintf("|%s|%s|%s|%v|%s|", + getName(lc), + getDesc(lc), + strings.Join(lc.InPresets, ", "), + check(lc.CanAutoFix, "Auto fix supported"), + lc.Since, + ) + lines = append(lines, line) + } + + return strings.Join(lines, "\n") +} + +func getName(lc *types.LinterWrapper) string { + name := lc.Name + + if lc.OriginalURL != "" { + name = fmt.Sprintf("[%s](%s)", name, lc.OriginalURL) + } + + if hasSettings(lc.Name) { + name = fmt.Sprintf("%s [%s](#%s)", name, spanWithID(listItemPrefix+lc.Name, "Configuration", "⚙️"), lc.Name) + } + + if lc.Deprecation == nil { + return name + } + + title := "deprecated" + if lc.Deprecation.Replacement != "" { + title += fmt.Sprintf(" since %s", lc.Deprecation.Since) + } + + return name + " " + span(title, "⚠") +} + +func check(b bool, title string) string { + if b { + return span(title, "✔") + } + return "" +} + +func getDesc(lc *types.LinterWrapper) string { + desc := lc.Desc + if lc.Deprecation != nil { + desc = lc.Deprecation.Message + if lc.Deprecation.Replacement != "" { + desc += fmt.Sprintf(" Replaced by %s.", lc.Deprecation.Replacement) + } + } + + return formatDesc(desc) +} + +func formatDesc(desc string) string { + runes := []rune(desc) + + r, _ := utf8.DecodeRuneInString(desc) + runes[0] = unicode.ToUpper(r) + + if runes[len(runes)-1] != '.' { + runes = append(runes, '.') + } + + return strings.ReplaceAll(string(runes), "\n", "
") +} + +func hasSettings(name string) bool { + tp := reflect.TypeOf(config.LintersSettings{}) + + for i := 0; i < tp.NumField(); i++ { + if strings.EqualFold(name, tp.Field(i).Name) { + return true + } + } + + return false +} + +func span(title, icon string) string { + return fmt.Sprintf(`%s`, title, icon) +} + +func spanWithID(id, title, icon string) string { + return fmt.Sprintf(`%s`, id, title, icon) +} + +type SettingSnippets struct { + ConfigurationFile string + LintersSettings string +} + +func extractExampleSnippets(example []byte) (*SettingSnippets, error) { + var data yaml.Node + err := yaml.Unmarshal(example, &data) + if err != nil { + return nil, err + } + + root := data.Content[0] + + globalNode := &yaml.Node{ + Kind: root.Kind, + Style: root.Style, + Tag: root.Tag, + Value: root.Value, + Anchor: root.Anchor, + Alias: root.Alias, + HeadComment: root.HeadComment, + LineComment: root.LineComment, + FootComment: root.FootComment, + Line: root.Line, + Column: root.Column, + } + + snippets := SettingSnippets{} + + builder := strings.Builder{} + + for j, node := range root.Content { + switch node.Value { + case "run", "output", "linters", "linters-settings", "issues", "severity": + default: + continue + } + + nextNode := root.Content[j+1] + + newNode := &yaml.Node{ + Kind: nextNode.Kind, + Content: []*yaml.Node{ + { + HeadComment: fmt.Sprintf("See the dedicated %q documentation section.", node.Value), + Kind: node.Kind, + Style: node.Style, + Tag: node.Tag, + Value: "option", + }, + { + Kind: node.Kind, + Style: node.Style, + Tag: node.Tag, + Value: "value", + }, + }, + } + + globalNode.Content = append(globalNode.Content, node, newNode) + + if node.Value == "linters-settings" { + snippets.LintersSettings, err = getLintersSettingSections(node, nextNode) + if err != nil { + return nil, err + } + + _, _ = builder.WriteString( + fmt.Sprintf( + "### `%s` configuration\n\nSee the dedicated [linters-settings](/usage/linters) documentation section.\n\n", + node.Value, + ), + ) + continue + } + + nodeSection := &yaml.Node{ + Kind: root.Kind, + Style: root.Style, + Tag: root.Tag, + Value: root.Value, + Content: []*yaml.Node{node, nextNode}, + } + + snippet, errSnip := marshallSnippet(nodeSection) + if errSnip != nil { + return nil, errSnip + } + + _, _ = builder.WriteString(fmt.Sprintf("### `%s` configuration\n\n%s", node.Value, snippet)) + } + + overview, err := marshallSnippet(globalNode) + if err != nil { + return nil, err + } + + snippets.ConfigurationFile = overview + builder.String() + + return &snippets, nil +} + +func getLintersSettingSections(node, nextNode *yaml.Node) (string, error) { + linters, err := readJSONFile[[]*types.LinterWrapper](filepath.Join("assets", "linters-info.json")) + if err != nil { + return "", err + } + + lintersDesc := make(map[string]string) + for _, lc := range linters { + if lc.Internal { + continue + } + + // it's important to use lc.Name() nor name because name can be alias + lintersDesc[lc.Name] = getDesc(lc) + } + + builder := &strings.Builder{} + + for i := 0; i < len(nextNode.Content); i += 2 { + r := &yaml.Node{ + Kind: nextNode.Kind, + Style: nextNode.Style, + Tag: nextNode.Tag, + Value: node.Value, + Content: []*yaml.Node{ + { + Kind: node.Kind, + Value: node.Value, + }, + { + Kind: nextNode.Kind, + Content: []*yaml.Node{nextNode.Content[i], nextNode.Content[i+1]}, + }, + }, + } + + _, _ = fmt.Fprintf(builder, "### %s\n\n", nextNode.Content[i].Value) + _, _ = fmt.Fprintf(builder, "%s\n\n", lintersDesc[nextNode.Content[i].Value]) + _, _ = fmt.Fprintln(builder, "```yaml") + + encoder := yaml.NewEncoder(builder) + encoder.SetIndent(2) + + err := encoder.Encode(r) + if err != nil { + return "", err + } + + _, _ = fmt.Fprintln(builder, "```") + _, _ = fmt.Fprintln(builder) + _, _ = fmt.Fprintf(builder, "[%s](#%s)\n\n", span("Back to the top", "🔼"), listItemPrefix+nextNode.Content[i].Value) + _, _ = fmt.Fprintln(builder) + } + + return builder.String(), nil +} + +func marshallSnippet(node *yaml.Node) (string, error) { + builder := &strings.Builder{} + + if node.Value != "" { + _, _ = fmt.Fprintf(builder, "### %s\n\n", node.Value) + } + _, _ = fmt.Fprintln(builder, "```yaml") + + encoder := yaml.NewEncoder(builder) + encoder.SetIndent(2) + + err := encoder.Encode(node) + if err != nil { + return "", err + } + + _, _ = fmt.Fprintln(builder, "```") + _, _ = fmt.Fprintln(builder) + + return builder.String(), nil +} diff --git a/scripts/website/expand_templates/main.go b/scripts/website/expand_templates/main.go new file mode 100644 index 000000000000..e2951f3fc388 --- /dev/null +++ b/scripts/website/expand_templates/main.go @@ -0,0 +1,195 @@ +package main + +import ( + "encoding/json" + "fmt" + "io" + "log" + "net/http" + "os" + "path/filepath" + "strings" + "time" + + "github.com/golangci/golangci-lint/internal/renameio" + "github.com/golangci/golangci-lint/scripts/website/types" +) + +func main() { + replacements, err := buildTemplateContext() + if err != nil { + log.Fatalf("Failed to build template context: %s", err) + } + + if err := rewriteDocs(replacements); err != nil { + log.Fatalf("Failed to rewrite docs: %s", err) + } + + log.Print("Successfully expanded templates") +} + +func rewriteDocs(replacements map[string]string) error { + madeReplacements := map[string]bool{} + + err := filepath.Walk(filepath.Join("docs", "src", "docs"), + func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if info.IsDir() { + return nil + } + return processDoc(path, replacements, madeReplacements) + }) + if err != nil { + return fmt.Errorf("walk dir: %w", err) + } + + if len(madeReplacements) != len(replacements) { + for key := range replacements { + if !madeReplacements[key] { + log.Printf("Replacement %q wasn't performed", key) + } + } + return fmt.Errorf("%d replacements weren't performed", len(replacements)-len(madeReplacements)) + } + return nil +} + +func processDoc(path string, replacements map[string]string, madeReplacements map[string]bool) error { + contentBytes, err := os.ReadFile(path) + if err != nil { + return fmt.Errorf("read %s: %w", path, err) + } + + content := string(contentBytes) + hasReplacements := false + for key, replacement := range replacements { + nextContent := content + nextContent = strings.ReplaceAll(nextContent, fmt.Sprintf("{.%s}", key), replacement) + + // Yaml formatter in mdx code section makes extra spaces, need to match them too. + nextContent = strings.ReplaceAll(nextContent, fmt.Sprintf("{ .%s }", key), replacement) + + if nextContent != content { + hasReplacements = true + madeReplacements[key] = true + content = nextContent + } + } + if !hasReplacements { + return nil + } + + log.Printf("Expanded template in %s, saving it", path) + if err = renameio.WriteFile(path, []byte(content), os.ModePerm); err != nil { + return fmt.Errorf("write changes to file %s: %w", path, err) + } + + return nil +} + +type latestRelease struct { + TagName string `json:"tag_name"` +} + +func getLatestVersion() (string, error) { + endpoint := "https://api.github.com/repos/golangci/golangci-lint/releases/latest" + + //nolint:noctx + req, err := http.NewRequest(http.MethodGet, endpoint, http.NoBody) + if err != nil { + return "", fmt.Errorf("prepare a HTTP request: %w", err) + } + + req.Header.Set("Accept", "application/vnd.github.v3+json") + + client := &http.Client{Timeout: 2 * time.Second} + + resp, err := client.Do(req) + + if err != nil { + return "", fmt.Errorf("get HTTP response for the latest tag: %w", err) + } + + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return "", fmt.Errorf("read a body for the latest tag: %w", err) + } + + release := latestRelease{} + + err = json.Unmarshal(body, &release) + if err != nil { + return "", fmt.Errorf("unmarshal the body for the latest tag: %w", err) + } + + return release.TagName, nil +} + +func buildTemplateContext() (map[string]string, error) { + snippets, err := getExampleSnippets() + if err != nil { + return nil, err + } + + pluginReference, err := getPluginReference() + if err != nil { + return nil, fmt.Errorf("read plugin reference file: %w", err) + } + + helps, err := readJSONFile[types.CLIHelp](filepath.Join("assets", "cli-help.json")) + if err != nil { + return nil, err + } + + changeLog, err := os.ReadFile("CHANGELOG.md") + if err != nil { + return nil, fmt.Errorf("read CHANGELOG.md: %w", err) + } + + latestVersion, err := getLatestVersion() + if err != nil { + return nil, fmt.Errorf("get the latest version: %w", err) + } + + exclusions, err := getDefaultExclusions() + if err != nil { + return nil, fmt.Errorf("default exclusions: %w", err) + } + + return map[string]string{ + "CustomGCLReference": pluginReference, + "LintersExample": snippets.LintersSettings, + "ConfigurationExample": snippets.ConfigurationFile, + "LintersCommandOutputEnabledOnly": helps.Enable, + "EnabledByDefaultLinters": getLintersListMarkdown(true), + "DisabledByDefaultLinters": getLintersListMarkdown(false), + "DefaultExclusions": exclusions, + "ThanksList": getThanksList(), + "RunHelpText": helps.Help, + "ChangeLog": string(changeLog), + "LatestVersion": latestVersion, + }, nil +} + +func readJSONFile[T any](src string) (T, error) { + file, err := os.Open(src) + if err != nil { + var zero T + return zero, fmt.Errorf("open file %s: %w", src, err) + } + + defer func() { _ = file.Close() }() + + var result T + err = json.NewDecoder(file).Decode(&result) + if err != nil { + var zero T + return zero, fmt.Errorf("decode JSON file %s: %w", src, err) + } + + return result, nil +} diff --git a/scripts/expand_website_templates/main_test.go b/scripts/website/expand_templates/main_test.go similarity index 100% rename from scripts/expand_website_templates/main_test.go rename to scripts/website/expand_templates/main_test.go diff --git a/scripts/website/expand_templates/plugins.go b/scripts/website/expand_templates/plugins.go new file mode 100644 index 000000000000..8991252efe9a --- /dev/null +++ b/scripts/website/expand_templates/plugins.go @@ -0,0 +1,15 @@ +package main + +import ( + "fmt" + "os" +) + +func getPluginReference() (string, error) { + reference, err := os.ReadFile(".custom-gcl.reference.yml") + if err != nil { + return "", fmt.Errorf("can't read .custom-gcl.reference.yml: %w", err) + } + + return string(reference), nil +} diff --git a/scripts/website/expand_templates/thanks.go b/scripts/website/expand_templates/thanks.go new file mode 100644 index 000000000000..d4a548f629e0 --- /dev/null +++ b/scripts/website/expand_templates/thanks.go @@ -0,0 +1,87 @@ +package main + +import ( + "fmt" + "sort" + "strings" + + "golang.org/x/exp/maps" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/lint/lintersdb" +) + +type authorDetails struct { + Linters []string + Profile string + Avatar string +} + +func getThanksList() string { + addedAuthors := map[string]*authorDetails{} + + linters, _ := lintersdb.NewLinterBuilder().Build(config.NewDefault()) + + for _, lc := range linters { + if lc.Internal { + continue + } + + if lc.OriginalURL == "" { + continue + } + + linterURL := lc.OriginalURL + if lc.Name() == "staticcheck" { + linterURL = "https://github.com/dominikh/go-tools" + } + + if author := extractAuthor(linterURL, "https://github.com/"); author != "" && author != "golangci" { + if _, ok := addedAuthors[author]; ok { + addedAuthors[author].Linters = append(addedAuthors[author].Linters, lc.Name()) + } else { + addedAuthors[author] = &authorDetails{ + Linters: []string{lc.Name()}, + Profile: fmt.Sprintf("[%[1]s](https://github.com/sponsors/%[1]s)", author), + Avatar: fmt.Sprintf(`%[1]s`, author), + } + } + } else if author := extractAuthor(linterURL, "https://gitlab.com/"); author != "" { + if _, ok := addedAuthors[author]; ok { + addedAuthors[author].Linters = append(addedAuthors[author].Linters, lc.Name()) + } else { + addedAuthors[author] = &authorDetails{ + Linters: []string{lc.Name()}, + Profile: fmt.Sprintf("[%[1]s](https://gitlab.com/%[1]s)", author), + } + } + } else { + continue + } + } + + authors := maps.Keys(addedAuthors) + sort.Slice(authors, func(i, j int) bool { + return strings.ToLower(authors[i]) < strings.ToLower(authors[j]) + }) + + lines := []string{ + "|Author|Linter(s)|", + "|---|---|", + } + + for _, author := range authors { + lines = append(lines, fmt.Sprintf("|%s %s|%s|", + addedAuthors[author].Avatar, addedAuthors[author].Profile, strings.Join(addedAuthors[author].Linters, ", "))) + } + + return strings.Join(lines, "\n") +} + +func extractAuthor(originalURL, prefix string) string { + if !strings.HasPrefix(originalURL, prefix) { + return "" + } + + return strings.SplitN(strings.TrimPrefix(originalURL, prefix), "/", 2)[0] +} diff --git a/scripts/website/types/types.go b/scripts/website/types/types.go new file mode 100644 index 000000000000..955c6c4331cf --- /dev/null +++ b/scripts/website/types/types.go @@ -0,0 +1,47 @@ +package types + +import ( + "golang.org/x/tools/go/packages" +) + +type CLIHelp struct { + Enable string `json:"enable"` + Help string `json:"help"` +} + +type ExcludePattern struct { + ID string `json:"id,omitempty"` + Pattern string `json:"pattern,omitempty"` + Linter string `json:"linter,omitempty"` + Why string `json:"why,omitempty"` +} + +type Deprecation struct { + Since string `json:"since,omitempty"` + Message string `json:"message,omitempty"` + Replacement string `json:"replacement,omitempty"` +} + +// LinterWrapper same fields but with struct tags. +// The field Name and Desc are added to have the information about the linter. +// The field Linter is removed (not serializable). +type LinterWrapper struct { + Name string `json:"name"` // From linter. + Desc string `json:"desc"` // From linter. + + EnabledByDefault bool `json:"enabledByDefault,omitempty"` + + LoadMode packages.LoadMode `json:"loadMode,omitempty"` + + InPresets []string `json:"inPresets,omitempty"` + AlternativeNames []string `json:"alternativeNames,omitempty"` + + OriginalURL string `json:"originalURL,omitempty"` + Internal bool `json:"internal"` + CanAutoFix bool `json:"canAutoFix,omitempty"` + IsSlow bool `json:"isSlow"` + DoesChangeTypes bool `json:"doesChangeTypes,omitempty"` + + Since string `json:"since,omitempty"` + Deprecation *Deprecation `json:"deprecation,omitempty"` +} diff --git a/test/bench/bench_test.go b/test/bench/bench_test.go index c96d14a37453..bd7530b3e2f3 100644 --- a/test/bench/bench_test.go +++ b/test/bench/bench_test.go @@ -20,18 +20,18 @@ import ( "github.com/golangci/golangci-lint/test/testshared" ) -func chdir(b *testing.B, dir string) { +func chdir(b testing.TB, dir string) { if err := os.Chdir(dir); err != nil { b.Fatalf("can't chdir to %s: %s", dir, err) } } -func prepareGoSource(b *testing.B) { +func prepareGoSource(b testing.TB) { chdir(b, filepath.Join(build.Default.GOROOT, "src")) } -func prepareGithubProject(owner, name string) func(*testing.B) { - return func(b *testing.B) { +func prepareGithubProject(owner, name string) func(testing.TB) { + return func(b testing.TB) { dir := filepath.Join(build.Default.GOPATH, "src", "github.com", owner, name) _, err := os.Stat(dir) if os.IsNotExist(err) { @@ -76,10 +76,10 @@ func printCommand(cmd string, args ...string) { } func getGolangciLintCommonArgs() []string { - return []string{"run", "--no-config", "--issues-exit-code=0", "--deadline=30m", "--disable-all", "--enable=govet"} + return []string{"run", "--no-config", "--issues-exit-code=0", "--timeout=30m", "--disable-all", "--enable=govet"} } -func runGolangciLintForBench(b *testing.B) { +func runGolangciLintForBench(b testing.TB) { args := getGolangciLintCommonArgs() args = append(args, getBenchLintersArgs()...) printCommand("golangci-lint", args...) @@ -180,7 +180,7 @@ type runResult struct { duration time.Duration } -func runOne(b *testing.B, run func(*testing.B), progName string) *runResult { +func runOne(b *testing.B, run func(testing.TB), progName string) *runResult { doneCh := make(chan struct{}) peakMemCh := trackPeakMemoryUsage(b, doneCh, progName) startedAt := time.Now() @@ -200,7 +200,7 @@ func BenchmarkGolangciLint(b *testing.B) { type bcase struct { name string - prepare func(*testing.B) + prepare func(testing.TB) } bcases := []bcase{ { diff --git a/test/enabled_linters_test.go b/test/enabled_linters_test.go index 15a7d76825f6..0224223156c4 100644 --- a/test/enabled_linters_test.go +++ b/test/enabled_linters_test.go @@ -2,15 +2,17 @@ package test import ( "fmt" + "slices" "sort" "strings" "testing" + "github.com/stretchr/testify/require" + "github.com/golangci/golangci-lint/pkg/lint/lintersdb" "github.com/golangci/golangci-lint/test/testshared" ) -//nolint:funlen func TestEnabledLinters(t *testing.T) { // require to display the message "Active x linters: [x,y]" t.Setenv(lintersdb.EnvTestRun, "1") @@ -29,7 +31,7 @@ func TestEnabledLinters(t *testing.T) { disable: - govet `, - enabledLinters: getEnabledByDefaultFastLintersExcept("govet"), + enabledLinters: getEnabledByDefaultFastLintersExcept(t, "govet"), }, { name: "enable revive in config", @@ -38,12 +40,12 @@ func TestEnabledLinters(t *testing.T) { enable: - revive `, - enabledLinters: getEnabledByDefaultFastLintersWith("revive"), + enabledLinters: getEnabledByDefaultFastLintersWith(t, "revive"), }, { name: "disable govet in cmd", args: []string{"-Dgovet"}, - enabledLinters: getEnabledByDefaultFastLintersExcept("govet"), + enabledLinters: getEnabledByDefaultFastLintersExcept(t, "govet"), }, { name: "enable gofmt in cmd and enable revive in config", @@ -53,7 +55,7 @@ func TestEnabledLinters(t *testing.T) { enable: - revive `, - enabledLinters: getEnabledByDefaultFastLintersWith("revive", "gofmt"), + enabledLinters: getEnabledByDefaultFastLintersWith(t, "revive", "gofmt"), }, { name: "fast option in config", @@ -61,7 +63,7 @@ func TestEnabledLinters(t *testing.T) { linters: fast: true `, - enabledLinters: getEnabledByDefaultFastLintersWith(), + enabledLinters: getEnabledByDefaultFastLintersWith(t), noImplicitFast: true, }, { @@ -70,13 +72,13 @@ func TestEnabledLinters(t *testing.T) { linters: fast: false `, - enabledLinters: getEnabledByDefaultLinters(), + enabledLinters: getEnabledByDefaultLinters(t), noImplicitFast: true, }, { name: "set fast option in command-line", args: []string{"--fast"}, - enabledLinters: getEnabledByDefaultFastLintersWith(), + enabledLinters: getEnabledByDefaultFastLintersWith(t), noImplicitFast: true, }, { @@ -86,7 +88,7 @@ func TestEnabledLinters(t *testing.T) { fast: false `, args: []string{"--fast"}, - enabledLinters: getEnabledByDefaultFastLintersWith(), + enabledLinters: getEnabledByDefaultFastLintersWith(t), noImplicitFast: true, }, { @@ -96,13 +98,13 @@ func TestEnabledLinters(t *testing.T) { fast: true `, args: []string{"--fast=false"}, - enabledLinters: getEnabledByDefaultLinters(), + enabledLinters: getEnabledByDefaultLinters(t), noImplicitFast: true, }, { name: "fast option combined with enable and enable-all", args: []string{"--enable-all", "--fast", "--enable=unused"}, - enabledLinters: getAllFastLintersWith("unused"), + enabledLinters: getAllFastLintersWith(t, "unused"), noImplicitFast: true, }, } @@ -127,7 +129,7 @@ func TestEnabledLinters(t *testing.T) { Runner(). Run() - sort.StringSlice(c.enabledLinters).Sort() + sort.Strings(c.enabledLinters) r.ExpectOutputContains(fmt.Sprintf("Active %d linters: [%s]", len(c.enabledLinters), strings.Join(c.enabledLinters, " "))) @@ -135,18 +137,12 @@ func TestEnabledLinters(t *testing.T) { } } -func inSlice(s []string, v string) bool { - for _, sv := range s { - if sv == v { - return true - } - } +func getEnabledByDefaultFastLintersExcept(t *testing.T, except ...string) []string { + t.Helper() - return false -} + m, err := lintersdb.NewManager(nil, nil, lintersdb.NewLinterBuilder()) + require.NoError(t, err) -func getEnabledByDefaultFastLintersExcept(except ...string) []string { - m := lintersdb.NewManager(nil, nil) ebdl := m.GetAllEnabledByDefaultLinters() var ret []string for _, lc := range ebdl { @@ -154,7 +150,7 @@ func getEnabledByDefaultFastLintersExcept(except ...string) []string { continue } - if !inSlice(except, lc.Name()) { + if !slices.Contains(except, lc.Name()) { ret = append(ret, lc.Name()) } } @@ -162,8 +158,13 @@ func getEnabledByDefaultFastLintersExcept(except ...string) []string { return ret } -func getAllFastLintersWith(with ...string) []string { - linters := lintersdb.NewManager(nil, nil).GetAllSupportedLinterConfigs() +func getAllFastLintersWith(t *testing.T, with ...string) []string { + t.Helper() + + dbManager, err := lintersdb.NewManager(nil, nil, lintersdb.NewLinterBuilder()) + require.NoError(t, err) + + linters := dbManager.GetAllSupportedLinterConfigs() ret := append([]string{}, with...) for _, lc := range linters { if lc.IsSlowLinter() { @@ -175,18 +176,32 @@ func getAllFastLintersWith(with ...string) []string { return ret } -func getEnabledByDefaultLinters() []string { - ebdl := lintersdb.NewManager(nil, nil).GetAllEnabledByDefaultLinters() +func getEnabledByDefaultLinters(t *testing.T) []string { + t.Helper() + + dbManager, err := lintersdb.NewManager(nil, nil, lintersdb.NewLinterBuilder()) + require.NoError(t, err) + + ebdl := dbManager.GetAllEnabledByDefaultLinters() var ret []string for _, lc := range ebdl { + if lc.Internal { + continue + } + ret = append(ret, lc.Name()) } return ret } -func getEnabledByDefaultFastLintersWith(with ...string) []string { - ebdl := lintersdb.NewManager(nil, nil).GetAllEnabledByDefaultLinters() +func getEnabledByDefaultFastLintersWith(t *testing.T, with ...string) []string { + t.Helper() + + dbManager, err := lintersdb.NewManager(nil, nil, lintersdb.NewLinterBuilder()) + require.NoError(t, err) + + ebdl := dbManager.GetAllEnabledByDefaultLinters() ret := append([]string{}, with...) for _, lc := range ebdl { if lc.IsSlowLinter() { diff --git a/test/fix_test.go b/test/fix_test.go index bccf620f5989..87dff82dbe3d 100644 --- a/test/fix_test.go +++ b/test/fix_test.go @@ -14,7 +14,9 @@ import ( // value: "1" const envKeepTempFiles = "GL_KEEP_TEMP_FILES" -func TestFix(t *testing.T) { +func setupTestFix(t *testing.T) []string { + t.Helper() + testshared.SkipOnWindows(t) tmpDir := filepath.Join(testdataDir, "fix.tmp") @@ -33,10 +35,53 @@ func TestFix(t *testing.T) { testshared.InstallGolangciLint(t) - sources := findSources(t, tmpDir, "in", "*.go") + return findSources(t, tmpDir, "in", "*.go") +} + +func TestFix(t *testing.T) { + sources := setupTestFix(t) + + for _, input := range sources { + input := input + + t.Run(filepath.Base(input), func(t *testing.T) { + t.Parallel() + + rc := testshared.ParseTestDirectives(t, input) + if rc == nil { + t.Logf("Skipped: %s", input) + return + } + + testshared.NewRunnerBuilder(t). + WithArgs("--disable-all", + "--print-issued-lines=false", + "--print-linter-name=false", + "--out-format=line-number", + "--fix"). + WithRunContext(rc). + WithTargetPath(input). + Runner(). + Run(). + ExpectExitCode(rc.ExitCode) + + output, err := os.ReadFile(input) + require.NoError(t, err) + + expectedOutput, err := os.ReadFile(filepath.Join(testdataDir, "fix", "out", filepath.Base(input))) + require.NoError(t, err) + + require.Equal(t, string(expectedOutput), string(output)) + }) + } +} + +func TestFix_pathPrefix(t *testing.T) { + sources := setupTestFix(t) for _, input := range sources { input := input + t.Run(filepath.Base(input), func(t *testing.T) { t.Parallel() @@ -47,13 +92,12 @@ func TestFix(t *testing.T) { } testshared.NewRunnerBuilder(t). - WithArgs( - "--disable-all", + WithArgs("--disable-all", "--print-issued-lines=false", "--print-linter-name=false", "--out-format=line-number", "--fix", - ). + "--path-prefix=foobar/"). WithRunContext(rc). WithTargetPath(input). Runner(). diff --git a/test/linters_test.go b/test/linters_test.go index 58af3e1c6cb2..4ae7a67b8f8e 100644 --- a/test/linters_test.go +++ b/test/linters_test.go @@ -31,6 +31,9 @@ func TestSourcesFromTestdataSubDir(t *testing.T) { subDirs := []string{ "loggercheck", "ginkgolinter", + "zerologlint", + "protogetter", + "spancheck", } for _, dir := range subDirs { @@ -81,10 +84,11 @@ func testOneSource(t *testing.T, log *logutils.StderrLog, binPath, sourcePath st } args := []string{ - "--allow-parallel-runners", + "--go=1.22", // TODO(ldez) remove this line when we will run go1.23 on the CI. (related to intrange, copyloopvar) "--disable-all", "--out-format=json", "--max-same-issues=100", + "--max-issues-per-linter=100", } for _, addArg := range []string{"", "-Etypecheck"} { @@ -96,7 +100,6 @@ func testOneSource(t *testing.T, log *logutils.StderrLog, binPath, sourcePath st cmd := testshared.NewRunnerBuilder(t). WithBinPath(binPath). - WithNoParallelRunners(). WithArgs(caseArgs...). WithRunContext(rc). WithTargetPath(sourcePath). diff --git a/test/ruleguard/README.md b/test/ruleguard/README.md index 2e2441698750..35797144a3ee 100644 --- a/test/ruleguard/README.md +++ b/test/ruleguard/README.md @@ -1 +1,14 @@ -This directory contains ruleguard files that are used in functional tests. +This directory contains ruleguard files that are used in functional tests: + +```bash +T=gocritic.go make test_linters +``` + +```bash +T=gocritic.go make test_fix +``` + +Helpful: + +- https://go-critic.com/overview.html +- https://github.com/go-critic/go-critic/blob/master/checkers/rules/rules.go diff --git a/test/ruleguard/dup.go b/test/ruleguard/dup.go deleted file mode 100644 index 944651b6f041..000000000000 --- a/test/ruleguard/dup.go +++ /dev/null @@ -1,22 +0,0 @@ -// go:build ruleguard -package ruleguard - -import "github.com/quasilyte/go-ruleguard/dsl" - -// Suppose that we want to report the duplicated left and right operands of binary operations. -// -// But if the operand has some side effects, this rule can cause false positives: -// `f() && f()` can make sense (although it's not the best piece of code). -// -// This is where *filters* come to the rescue. -func DupSubExpr(m dsl.Matcher) { - // All filters are written as a Where() argument. - // In our case, we need to assert that $x is "pure". - // It can be achieved by checking the m["x"] member Pure field. - m.Match(`$x || $x`, - `$x && $x`, - `$x | $x`, - `$x & $x`). - Where(m["x"].Pure). - Report(`suspicious identical LHS and RHS`) -} diff --git a/test/ruleguard/preferWriteString.go b/test/ruleguard/preferWriteString.go new file mode 100644 index 000000000000..c3057ba45118 --- /dev/null +++ b/test/ruleguard/preferWriteString.go @@ -0,0 +1,12 @@ +//go:build ruleguard + +package ruleguard + +import "github.com/quasilyte/go-ruleguard/dsl" + +func preferWriteString(m dsl.Matcher) { + m.Match(`$w.Write([]byte($s))`). + Where(m["w"].Type.Implements("io.StringWriter")). + Suggest("$w.WriteString($s)"). + Report(`$w.WriteString($s) should be preferred to the $$`) +} diff --git a/test/ruleguard/rangeExprCopy.go b/test/ruleguard/rangeExprCopy.go index d68b45e61158..042ba14d4236 100644 --- a/test/ruleguard/rangeExprCopy.go +++ b/test/ruleguard/rangeExprCopy.go @@ -1,11 +1,12 @@ -// go:build ruleguard +//go:build ruleguard + package ruleguard import ( "github.com/quasilyte/go-ruleguard/dsl" ) -func RangeExprVal(m dsl.Matcher) { +func rangeExprCopy(m dsl.Matcher) { m.Match(`for _, $_ := range $x { $*_ }`, `for _, $_ = range $x { $*_ }`). Where(m["x"].Addressable && m["x"].Type.Size >= 512). Report(`$x copy can be avoided with &$x`). diff --git a/test/ruleguard/strings_simplify.go b/test/ruleguard/stringsSimplify.go similarity index 90% rename from test/ruleguard/strings_simplify.go rename to test/ruleguard/stringsSimplify.go index 2e73a50b3621..3371436a7e83 100644 --- a/test/ruleguard/strings_simplify.go +++ b/test/ruleguard/stringsSimplify.go @@ -1,9 +1,10 @@ -// go:build ruleguard +//go:build ruleguard + package ruleguard import "github.com/quasilyte/go-ruleguard/dsl" -func StringsSimplify(m dsl.Matcher) { +func stringsSimplify(m dsl.Matcher) { // Some issues have simple fixes that can be expressed as // a replacement pattern. Rules can use Suggest() function // to add a quickfix action for such issues. diff --git a/test/run_test.go b/test/run_test.go index ec532541e1ae..c5e24fcb04a2 100644 --- a/test/run_test.go +++ b/test/run_test.go @@ -4,7 +4,7 @@ import ( "path/filepath" "testing" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" _ "github.com/valyala/quicktemplate" "github.com/golangci/golangci-lint/pkg/exitcodes" @@ -54,20 +54,6 @@ func TestSymlinkLoop(t *testing.T) { ExpectNoIssues() } -// TODO(ldez): remove this in v2. -func TestDeadline(t *testing.T) { - projectRoot := filepath.Join("..", "...") - - testshared.NewRunnerBuilder(t). - WithArgs("--deadline=1ms"). - WithTargetPath(projectRoot). - Runner(). - Install(). - Run(). - ExpectExitCode(exitcodes.Timeout). - ExpectOutputContains(`Timeout exceeded: try increasing it by passing --timeout option`) -} - func TestTimeout(t *testing.T) { projectRoot := filepath.Join("..", "...") @@ -82,43 +68,21 @@ func TestTimeout(t *testing.T) { } func TestTimeoutInConfig(t *testing.T) { - cases := []struct { - cfg string - }{ - { - cfg: ` - run: - deadline: 1ms - `, - }, - { - cfg: ` - run: - timeout: 1ms - `, - }, - { - // timeout should override deadline - cfg: ` + testshared.InstallGolangciLint(t) + + cfg := ` run: - deadline: 100s timeout: 1ms - `, - }, - } + ` - testshared.InstallGolangciLint(t) - - for _, c := range cases { - // Run with disallowed option set only in config - testshared.NewRunnerBuilder(t). - WithConfig(c.cfg). - WithTargetPath(testdataDir, minimalPkg). - Runner(). - Run(). - ExpectExitCode(exitcodes.Timeout). - ExpectOutputContains(`Timeout exceeded: try increasing it by passing --timeout option`) - } + // Run with disallowed option set only in config + testshared.NewRunnerBuilder(t). + WithConfig(cfg). + WithTargetPath(testdataDir, minimalPkg). + Runner(). + Run(). + ExpectExitCode(exitcodes.Timeout). + ExpectOutputContains(`Timeout exceeded: try increasing it by passing --timeout option`) } func TestTestsAreLintedByDefault(t *testing.T) { @@ -133,12 +97,12 @@ func TestTestsAreLintedByDefault(t *testing.T) { func TestCgoOk(t *testing.T) { testshared.NewRunnerBuilder(t). WithNoConfig(). - WithArgs( - "--timeout=3m", + WithArgs("--timeout=3m", "--enable-all", "-D", - "nosnakecase,gci", + "nosnakecase", ). + WithArgs("--go=1.22"). // TODO(ldez) remove this line when we will run go1.23 on the CI. (related to intrange, copyloopvar) WithTargetPath(testdataDir, "cgo"). Runner(). Install(). @@ -243,7 +207,7 @@ func TestLineDirective(t *testing.T) { }, configPath: "testdata/linedirective/gomodguard.yml", targetPath: "linedirective", - expected: "import of package `github.com/ryancurrah/gomodguard` is blocked because the module is not " + + expected: "import of package `golang.org/x/tools/go/analysis` is blocked because the module is not " + "in the allowed modules list. (gomodguard)", }, { @@ -356,6 +320,7 @@ func TestUnsafeOk(t *testing.T) { testshared.NewRunnerBuilder(t). WithNoConfig(). WithArgs("--enable-all"). + WithArgs("--go=1.22"). // TODO(ldez) remove this line when we will run go1.23 on the CI. (related to intrange, copyloopvar) WithTargetPath(testdataDir, "unsafe"). Runner(). Install(). @@ -514,6 +479,7 @@ func TestEnableAllFastAndEnableCanCoexist(t *testing.T) { testshared.NewRunnerBuilder(t). WithNoConfig(). WithArgs(test.args...). + WithArgs("--go=1.22"). // TODO(ldez) remove this line when we will run go1.23 on the CI. (related to intrange, copyloopvar) WithTargetPath(testdataDir, minimalPkg). Runner(). Run(). @@ -536,7 +502,7 @@ func TestEnabledPresetsAreNotDuplicated(t *testing.T) { func TestAbsPathDirAnalysis(t *testing.T) { dir := filepath.Join("testdata_etc", "abspath") // abs paths don't work with testdata dir absDir, err := filepath.Abs(dir) - assert.NoError(t, err) + require.NoError(t, err) testshared.NewRunnerBuilder(t). WithNoConfig(). @@ -555,7 +521,7 @@ func TestAbsPathDirAnalysis(t *testing.T) { func TestAbsPathFileAnalysis(t *testing.T) { dir := filepath.Join("testdata_etc", "abspath", "with_issue.go") // abs paths don't work with testdata dir absDir, err := filepath.Abs(dir) - assert.NoError(t, err) + require.NoError(t, err) testshared.NewRunnerBuilder(t). WithNoConfig(). @@ -570,86 +536,6 @@ func TestAbsPathFileAnalysis(t *testing.T) { ExpectHasIssue("indent-error-flow: if block ends with a return statement, so drop this else and outdent its block (revive)") } -func TestDisallowedOptionsInConfig(t *testing.T) { - cases := []struct { - cfg string - option string - }{ - { - cfg: ` - ruN: - Args: - - 1 - `, - }, - { - cfg: ` - run: - CPUProfilePath: path - `, - option: "--cpu-profile-path=path", - }, - { - cfg: ` - run: - MemProfilePath: path - `, - option: "--mem-profile-path=path", - }, - { - cfg: ` - run: - TracePath: path - `, - option: "--trace-path=path", - }, - { - cfg: ` - run: - Verbose: true - `, - option: "-v", - }, - } - - testshared.InstallGolangciLint(t) - - for _, c := range cases { - // Run with disallowed option set only in config - testshared.NewRunnerBuilder(t). - WithConfig(c.cfg). - WithTargetPath(testdataDir, minimalPkg). - Runner(). - Run(). - ExpectExitCode(exitcodes.Failure) - - if c.option == "" { - continue - } - - args := []string{c.option, "--fast"} - - // Run with disallowed option set only in command-line - testshared.NewRunnerBuilder(t). - WithNoConfig(). - WithArgs(args...). - WithTargetPath(testdataDir, minimalPkg). - Runner(). - Run(). - ExpectExitCode(exitcodes.Success) - - // Run with disallowed option set both in command-line and in config - - testshared.NewRunnerBuilder(t). - WithConfig(c.cfg). - WithArgs(args...). - WithTargetPath(testdataDir, minimalPkg). - Runner(). - Run(). - ExpectExitCode(exitcodes.Failure) - } -} - func TestPathPrefix(t *testing.T) { testCases := []struct { desc string diff --git a/test/testdata/configs/copyloopvar.yml b/test/testdata/configs/copyloopvar.yml new file mode 100644 index 000000000000..2c3b5872edc9 --- /dev/null +++ b/test/testdata/configs/copyloopvar.yml @@ -0,0 +1,3 @@ +linters-settings: + copyloopvar: + ignore-alias: true diff --git a/test/testdata/configs/depguard.yml b/test/testdata/configs/depguard.yml index aa06e3ee9e61..133b9adf2b82 100644 --- a/test/testdata/configs/depguard.yml +++ b/test/testdata/configs/depguard.yml @@ -1,7 +1,12 @@ linters-settings: depguard: - include-go-root: true - packages: - - compress/* - packages-with-error-message: - log: "don't use log" + rules: + main: + deny: + - pkg: compress + desc: "nope" + - pkg: log + desc: "don't use log" + - pkg: "golang.org/x/tools/go/analysis" + desc: "example import with dot" + diff --git a/test/testdata/configs/depguard_additional_guards.yml b/test/testdata/configs/depguard_additional_guards.yml index 099edc4600b3..0894d2eed80a 100644 --- a/test/testdata/configs/depguard_additional_guards.yml +++ b/test/testdata/configs/depguard_additional_guards.yml @@ -1,16 +1,16 @@ linters-settings: depguard: - list-type: denylist - include-go-root: true - packages: - - compress/* - packages-with-error-message: - log: "don't use log" - additional-guards: - - list-type: denylist - include-go-root: true - packages: - - fmt - packages-with-error-message: - strings: "disallowed in additional guard" + rules: + main: + deny: + - pkg: fmt + desc: "nope" + - pkg: strings + desc: "nope" + - pkg: compress + desc: "nope" + - pkg: log + desc: "don't use log" + - pkg: "golang.org/x/tools/go/analysis" + desc: "example import with dot" diff --git a/test/testdata/configs/depguard_ignore_file_rules.yml b/test/testdata/configs/depguard_ignore_file_rules.yml index 2fe4b023e8e2..c71f7895188c 100644 --- a/test/testdata/configs/depguard_ignore_file_rules.yml +++ b/test/testdata/configs/depguard_ignore_file_rules.yml @@ -1,10 +1,13 @@ linters-settings: depguard: - list-type: denylist - include-go-root: true - packages: - - compress/* - packages-with-error-message: - log: "don't use log" - ignore-file-rules: - - "**/*_ignore_file_rules.go" + rules: + main: + files: + - "!**/*_ignore_file_rules.go" + deny: + - pkg: compress + desc: "nope" + - pkg: log + desc: "don't use log" + - pkg: "golang.org/x/tools/go/analysis" + desc: "example import with dot" diff --git a/test/testdata/configs/dupword_ignore_the.yml b/test/testdata/configs/dupword_ignore_the.yml new file mode 100644 index 000000000000..6fdb846444ae --- /dev/null +++ b/test/testdata/configs/dupword_ignore_the.yml @@ -0,0 +1,4 @@ +linters-settings: + dupword: + ignore: + - "the" diff --git a/test/testdata/configs/exhaustivestruct.yml b/test/testdata/configs/exhaustivestruct.yml deleted file mode 100644 index 21d69c55dd76..000000000000 --- a/test/testdata/configs/exhaustivestruct.yml +++ /dev/null @@ -1,5 +0,0 @@ -linters-settings: - exhaustivestruct: - struct-patterns: - - '*.ExhaustiveStructCustom' - - '*.ExhaustiveStructCustom2' diff --git a/test/testdata/configs/forbidigo_struct.yml b/test/testdata/configs/forbidigo_struct.yml new file mode 100644 index 000000000000..84d05c579b64 --- /dev/null +++ b/test/testdata/configs/forbidigo_struct.yml @@ -0,0 +1,8 @@ +linters-settings: + forbidigo: + analyze-types: true + forbid: + - p: fmt\.Print.* + pkg: ^fmt$ + - p: time.Sleep + msg: no sleeping! diff --git a/test/testdata/configs/gci.yml b/test/testdata/configs/gci.yml index 487e26383697..3291610acc8b 100644 --- a/test/testdata/configs/gci.yml +++ b/test/testdata/configs/gci.yml @@ -2,5 +2,6 @@ linters-settings: gci: sections: - standard - - prefix(github.com/golangci/golangci-lint) + - prefix(github.com/golangci/golangci-lint,github.com/daixiang0/gci) - default + custom-order: true diff --git a/test/testdata/configs/go-header-fix.yml b/test/testdata/configs/go-header-fix.yml new file mode 100644 index 000000000000..fa1371e3b1ee --- /dev/null +++ b/test/testdata/configs/go-header-fix.yml @@ -0,0 +1,9 @@ +linters-settings: + goheader: + values: + const: + AUTHOR: The Awesome Project Authors + template: |- + Copyright 2024 {{ AUTHOR }} + + Use of this source code is governed by LICENSE diff --git a/test/testdata/configs/gocritic-fix.yml b/test/testdata/configs/gocritic-fix.yml index 5ea41749a5de..7587a761a884 100644 --- a/test/testdata/configs/gocritic-fix.yml +++ b/test/testdata/configs/gocritic-fix.yml @@ -4,5 +4,4 @@ linters-settings: - ruleguard settings: ruleguard: - rules: 'ruleguard/rangeExprCopy.go,ruleguard/strings_simplify.go' - + rules: 'ruleguard/rangeExprCopy.go,ruleguard/stringsSimplify.go' diff --git a/test/testdata/configs/gocritic.yml b/test/testdata/configs/gocritic.yml index 019e6afb83fa..d424cb1798b3 100644 --- a/test/testdata/configs/gocritic.yml +++ b/test/testdata/configs/gocritic.yml @@ -1,20 +1,20 @@ linters-settings: gocritic: + disabled-checks: + - appendAssign + - switchTrue enabled-checks: - - rangeValCopy - - flagDeref - - wrapperFunc + - hugeParam - ruleguard settings: - rangeValCopy: - sizeThreshold: 2 + hugeParam: + sizeThreshold: 24 ruleguard: - debug: dupSubExpr failOn: dsl,import - # comma-separated paths to ruleguard files. + # Comma-separated paths to ruleguard files. # The ${configDir} is substituted by the directory containing the golangci-lint config file. # Note about the directory structure for functional tests: # The ruleguard files used in functional tests cannot be under the 'testdata' directory. # This is because they import the 'github.com/quasilyte/go-ruleguard/dsl' package, # which needs to be added to go.mod. The testdata directory is ignored by go mod. - rules: '${configDir}/../../ruleguard/strings_simplify.go,${configDir}/../../ruleguard/dup.go' + rules: '${configDir}/../../ruleguard/preferWriteString.go,${configDir}/../../ruleguard/stringsSimplify.go' diff --git a/test/testdata/configs/gosec_global_option.yml b/test/testdata/configs/gosec_global_option.yml new file mode 100644 index 000000000000..fc0c3e27ac6f --- /dev/null +++ b/test/testdata/configs/gosec_global_option.yml @@ -0,0 +1,5 @@ +linters-settings: + gosec: + config: + global: + nosec: true diff --git a/test/testdata/configs/gosmopolitan_allow_time_local.yml b/test/testdata/configs/gosmopolitan_allow_time_local.yml new file mode 100644 index 000000000000..22c14053bbcf --- /dev/null +++ b/test/testdata/configs/gosmopolitan_allow_time_local.yml @@ -0,0 +1,3 @@ +linters-settings: + gosmopolitan: + allow-time-local: true diff --git a/test/testdata/configs/gosmopolitan_dont_ignore_tests.yml b/test/testdata/configs/gosmopolitan_dont_ignore_tests.yml new file mode 100644 index 000000000000..099296be3be0 --- /dev/null +++ b/test/testdata/configs/gosmopolitan_dont_ignore_tests.yml @@ -0,0 +1,3 @@ +linters-settings: + gosmopolitan: + ignore-tests: false diff --git a/test/testdata/configs/gosmopolitan_escape_hatches.yml b/test/testdata/configs/gosmopolitan_escape_hatches.yml new file mode 100644 index 000000000000..4783f84eb690 --- /dev/null +++ b/test/testdata/configs/gosmopolitan_escape_hatches.yml @@ -0,0 +1,8 @@ +linters-settings: + gosmopolitan: + escape-hatches: + - 'command-line-arguments.A' + - 'command-line-arguments.B' + - 'command-line-arguments.C' + - 'command-line-arguments.D' + - 'fmt.Println' diff --git a/test/testdata/configs/gosmopolitan_scripts.yml b/test/testdata/configs/gosmopolitan_scripts.yml new file mode 100644 index 000000000000..4d61bc18f355 --- /dev/null +++ b/test/testdata/configs/gosmopolitan_scripts.yml @@ -0,0 +1,6 @@ +linters-settings: + gosmopolitan: + watch-for-scripts: + - Hiragana + - Katakana + - Latin diff --git a/test/testdata/configs/importas.yml b/test/testdata/configs/importas.yml index b76192f668e7..b06608500f7a 100644 --- a/test/testdata/configs/importas.yml +++ b/test/testdata/configs/importas.yml @@ -5,5 +5,5 @@ linters-settings: alias: fff - pkg: os alias: std_os - - pkg: github.com/pkg/errors - alias: pkgerr + - pkg: golang.org/x/tools/go/analysis + alias: ananas diff --git a/test/testdata/configs/importas_strict.yml b/test/testdata/configs/importas_strict.yml index 589f2c40d0fc..0f780f265787 100644 --- a/test/testdata/configs/importas_strict.yml +++ b/test/testdata/configs/importas_strict.yml @@ -6,5 +6,5 @@ linters-settings: alias: fff - pkg: os alias: std_os - - pkg: github.com/pkg/errors - alias: pkgerr + - pkg: golang.org/x/tools/go/analysis + alias: ananas diff --git a/test/testdata/configs/inamedparam_skip_single_param.yml b/test/testdata/configs/inamedparam_skip_single_param.yml new file mode 100644 index 000000000000..8d95bf8cfb61 --- /dev/null +++ b/test/testdata/configs/inamedparam_skip_single_param.yml @@ -0,0 +1,3 @@ +linters-settings: + inamedparam: + skip-single-param: true diff --git a/test/testdata/configs/ireturn_reject_generics.yml b/test/testdata/configs/ireturn_reject_generics.yml new file mode 100644 index 000000000000..90289d1306ae --- /dev/null +++ b/test/testdata/configs/ireturn_reject_generics.yml @@ -0,0 +1,4 @@ +linters-settings: + ireturn: + reject: + - generic diff --git a/test/testdata/configs/ireturn_stdlib_reject.yml b/test/testdata/configs/ireturn_reject_stdlib.yml similarity index 100% rename from test/testdata/configs/ireturn_stdlib_reject.yml rename to test/testdata/configs/ireturn_reject_stdlib.yml diff --git a/test/testdata/configs/misspell.yml b/test/testdata/configs/misspell.yml index ccb7772c8df8..d115cba91b06 100644 --- a/test/testdata/configs/misspell.yml +++ b/test/testdata/configs/misspell.yml @@ -1,4 +1,6 @@ linters-settings: misspell: + locale: US ignore-words: - langauge + - Dialogue diff --git a/test/testdata/configs/misspell_custom.yml b/test/testdata/configs/misspell_custom.yml new file mode 100644 index 000000000000..c0f3a27cfddb --- /dev/null +++ b/test/testdata/configs/misspell_custom.yml @@ -0,0 +1,7 @@ +linters-settings: + misspell: + extra-words: + - typo: "iff" + correction: "if" + - typo: "cancelation" + correction: "cancellation" diff --git a/test/testdata/configs/multiple-issues-fix.yml b/test/testdata/configs/multiple-issues-fix.yml new file mode 100644 index 000000000000..451973c5a144 --- /dev/null +++ b/test/testdata/configs/multiple-issues-fix.yml @@ -0,0 +1,4 @@ +linters-settings: + gofumpt: + extra-rules: true + diff --git a/test/testdata/configs/path-except.yml b/test/testdata/configs/path-except.yml new file mode 100644 index 000000000000..712bbd5a6013 --- /dev/null +++ b/test/testdata/configs/path-except.yml @@ -0,0 +1,13 @@ +linters-settings: + forbidigo: + forbid: + - fmt\.Print.* + - time.Sleep(# no sleeping!)? + +issues: + exclude-rules: + # Apply forbidigo only to test files, exclude + # it everywhere else. + - path-except: _test\.go + linters: + - forbidigo diff --git a/test/testdata/configs/perfsprint_custom.yml b/test/testdata/configs/perfsprint_custom.yml new file mode 100644 index 000000000000..f813f99ac2ce --- /dev/null +++ b/test/testdata/configs/perfsprint_custom.yml @@ -0,0 +1,7 @@ +linters-settings: + perfsprint: + int-conversion: false + err-error: true + errorf: false + sprintf1: false + diff --git a/test/testdata/configs/sloglint_args_on_sep_lines.yml b/test/testdata/configs/sloglint_args_on_sep_lines.yml new file mode 100644 index 000000000000..6f544b0239ee --- /dev/null +++ b/test/testdata/configs/sloglint_args_on_sep_lines.yml @@ -0,0 +1,3 @@ +linters-settings: + sloglint: + args-on-sep-lines: true diff --git a/test/testdata/configs/sloglint_attr_only.yml b/test/testdata/configs/sloglint_attr_only.yml new file mode 100644 index 000000000000..a61f2ab4185a --- /dev/null +++ b/test/testdata/configs/sloglint_attr_only.yml @@ -0,0 +1,3 @@ +linters-settings: + sloglint: + attr-only: true diff --git a/test/testdata/configs/sloglint_context_only.yml b/test/testdata/configs/sloglint_context_only.yml new file mode 100644 index 000000000000..a15bbe49680a --- /dev/null +++ b/test/testdata/configs/sloglint_context_only.yml @@ -0,0 +1,3 @@ +linters-settings: + sloglint: + context-only: true diff --git a/test/testdata/configs/sloglint_key_naming_case.yml b/test/testdata/configs/sloglint_key_naming_case.yml new file mode 100644 index 000000000000..653d8c0b480d --- /dev/null +++ b/test/testdata/configs/sloglint_key_naming_case.yml @@ -0,0 +1,3 @@ +linters-settings: + sloglint: + key-naming-case: snake diff --git a/test/testdata/configs/sloglint_kv_only.yml b/test/testdata/configs/sloglint_kv_only.yml new file mode 100644 index 000000000000..b482546c64db --- /dev/null +++ b/test/testdata/configs/sloglint_kv_only.yml @@ -0,0 +1,3 @@ +linters-settings: + sloglint: + kv-only: true diff --git a/test/testdata/configs/sloglint_no_raw_keys.yml b/test/testdata/configs/sloglint_no_raw_keys.yml new file mode 100644 index 000000000000..57db6dbaaff6 --- /dev/null +++ b/test/testdata/configs/sloglint_no_raw_keys.yml @@ -0,0 +1,3 @@ +linters-settings: + sloglint: + no-raw-keys: true diff --git a/test/testdata/configs/sloglint_static_msg.yml b/test/testdata/configs/sloglint_static_msg.yml new file mode 100644 index 000000000000..e4898e97839b --- /dev/null +++ b/test/testdata/configs/sloglint_static_msg.yml @@ -0,0 +1,3 @@ +linters-settings: + sloglint: + static-msg: true diff --git a/test/testdata/configs/tagalign_align_only.yml b/test/testdata/configs/tagalign_align_only.yml new file mode 100644 index 000000000000..0895a58fb19e --- /dev/null +++ b/test/testdata/configs/tagalign_align_only.yml @@ -0,0 +1,3 @@ +linters-settings: + tagalign: + sort: false diff --git a/test/testdata/configs/tagalign_order_only.yml b/test/testdata/configs/tagalign_order_only.yml new file mode 100644 index 000000000000..4ea9664e05b7 --- /dev/null +++ b/test/testdata/configs/tagalign_order_only.yml @@ -0,0 +1,7 @@ +linters-settings: + tagalign: + align: false + order: + - "xml" + - "json" + - "yaml" diff --git a/test/testdata/configs/tagalign_sort_only.yml b/test/testdata/configs/tagalign_sort_only.yml new file mode 100644 index 000000000000..19e6444365c9 --- /dev/null +++ b/test/testdata/configs/tagalign_sort_only.yml @@ -0,0 +1,4 @@ +linters-settings: + tagalign: + align: false + sort: true diff --git a/test/testdata/configs/tagalign_strict.yml b/test/testdata/configs/tagalign_strict.yml new file mode 100644 index 000000000000..84a0dd88c387 --- /dev/null +++ b/test/testdata/configs/tagalign_strict.yml @@ -0,0 +1,5 @@ +linters-settings: + tagalign: + align: true + sort: true + strict: true diff --git a/test/testdata/configs/testifylint_bool_compare_only.yml b/test/testdata/configs/testifylint_bool_compare_only.yml new file mode 100644 index 000000000000..dcf3c7732c71 --- /dev/null +++ b/test/testdata/configs/testifylint_bool_compare_only.yml @@ -0,0 +1,6 @@ +linters-settings: + testifylint: + disable-all: true + enable: bool-compare + bool-compare: + ignore-custom-types: true diff --git a/test/testdata/configs/testifylint_require_error_only.yml b/test/testdata/configs/testifylint_require_error_only.yml new file mode 100644 index 000000000000..dde08e3a5491 --- /dev/null +++ b/test/testdata/configs/testifylint_require_error_only.yml @@ -0,0 +1,6 @@ +linters-settings: + testifylint: + disable-all: true + enable: require-error + require-error: + fn-pattern: ^NoError$ diff --git a/test/testdata/configs/usestdlibvars_non_default.yml b/test/testdata/configs/usestdlibvars_non_default.yml new file mode 100644 index 000000000000..f50ce6fc341e --- /dev/null +++ b/test/testdata/configs/usestdlibvars_non_default.yml @@ -0,0 +1,12 @@ +linters-settings: + usestdlibvars: + http-method: false + http-status-code: false + time-weekday: true + time-month: true + time-layout: true + crypto-hash: true + default-rpc-path: true + sql-isolation-level: true + tls-signature-scheme: true + constant-kind: true diff --git a/test/testdata/copyloopvar.go b/test/testdata/copyloopvar.go new file mode 100644 index 000000000000..b5f1a88423b9 --- /dev/null +++ b/test/testdata/copyloopvar.go @@ -0,0 +1,40 @@ +//go:build go1.22 + +//golangcitest:args -Ecopyloopvar +package testdata + +import "fmt" + +func copyloopvarCase1() { + slice := []int{1, 2, 3} + fns := make([]func(), 0, len(slice)*2) + for i, v := range slice { + i := i // want `The copy of the 'for' variable "i" can be deleted \(Go 1\.22\+\)` + fns = append(fns, func() { + fmt.Println(i) + }) + v := v // want `The copy of the 'for' variable "v" can be deleted \(Go 1\.22\+\)` + fns = append(fns, func() { + fmt.Println(v) + }) + _v := v // want `The copy of the 'for' variable "v" can be deleted \(Go 1\.22\+\)` + _ = _v + } + for _, fn := range fns { + fn() + } +} + +func copyloopvarCase2() { + loopCount := 3 + fns := make([]func(), 0, loopCount) + for i := 1; i <= loopCount; i++ { + i := i // want `The copy of the 'for' variable "i" can be deleted \(Go 1\.22\+\)` + fns = append(fns, func() { + fmt.Println(i) + }) + } + for _, fn := range fns { + fn() + } +} diff --git a/test/testdata/copyloopvar_custom.go b/test/testdata/copyloopvar_custom.go new file mode 100644 index 000000000000..9ee37c6c005e --- /dev/null +++ b/test/testdata/copyloopvar_custom.go @@ -0,0 +1,41 @@ +//go:build go1.22 + +//golangcitest:args -Ecopyloopvar +//golangcitest:config_path testdata/configs/copyloopvar.yml +package testdata + +import "fmt" + +func copyloopvarCase1() { + slice := []int{1, 2, 3} + fns := make([]func(), 0, len(slice)*2) + for i, v := range slice { + i := i // want `The copy of the 'for' variable "i" can be deleted \(Go 1\.22\+\)` + fns = append(fns, func() { + fmt.Println(i) + }) + v := v // want `The copy of the 'for' variable "v" can be deleted \(Go 1\.22\+\)` + fns = append(fns, func() { + fmt.Println(v) + }) + _v := v + _ = _v + } + for _, fn := range fns { + fn() + } +} + +func copyloopvarCase2() { + loopCount := 3 + fns := make([]func(), 0, loopCount) + for i := 1; i <= loopCount; i++ { + i := i // want `The copy of the 'for' variable "i" can be deleted \(Go 1\.22\+\)` + fns = append(fns, func() { + fmt.Println(i) + }) + } + for _, fn := range fns { + fn() + } +} diff --git a/test/testdata/deadcode.go b/test/testdata/deadcode.go deleted file mode 100644 index 670047a548f0..000000000000 --- a/test/testdata/deadcode.go +++ /dev/null @@ -1,21 +0,0 @@ -//golangcitest:args -Edeadcode --internal-cmd-test -package testdata - -var y int - -var unused int // want "`unused` is unused" - -func f(x int) { -} - -func g(x int) { // want "`g` is unused" -} - -func H(x int) { -} - -func init() { - f(y) -} - -var _ int diff --git a/test/testdata/depguard.go b/test/testdata/depguard.go index b1b1946b43e4..5aa20fded6ec 100644 --- a/test/testdata/depguard.go +++ b/test/testdata/depguard.go @@ -3,10 +3,13 @@ package testdata import ( - "compress/gzip" // want "`compress/gzip` is in the denylist" - "log" // want "`log` is in the denylist: don't use log" + "compress/gzip" // want "import 'compress/gzip' is not allowed from list 'main': nope" + "log" // want "import 'log' is not allowed from list 'main': don't use log" + + "golang.org/x/tools/go/analysis" // want "import 'golang.org/x/tools/go/analysis' is not allowed from list 'main': example import with dot" ) func SpewDebugInfo() { log.Println(gzip.BestCompression) + _ = analysis.Analyzer{} } diff --git a/test/testdata/depguard_additional_guards.go b/test/testdata/depguard_additional_guards.go index 46f2f43ebab6..01e85c01f58c 100644 --- a/test/testdata/depguard_additional_guards.go +++ b/test/testdata/depguard_additional_guards.go @@ -3,14 +3,17 @@ package testdata import ( - "compress/gzip" // want "`compress/gzip` is in the denylist" - "fmt" // want "`fmt` is in the denylist" - "log" // want "`log` is in the denylist: don't use log" - "strings" // want "`strings` is in the denylist: disallowed in additional guard" + "compress/gzip" // want "import 'compress/gzip' is not allowed from list 'main': nope" + "fmt" // want "import 'fmt' is not allowed from list 'main': nope" + "log" // want "import 'log' is not allowed from list 'main': don't use log" + "strings" // want "import 'strings' is not allowed from list 'main': nope" + + "golang.org/x/tools/go/analysis" // want "import 'golang.org/x/tools/go/analysis' is not allowed from list 'main': example import with dot" ) func SpewDebugInfo() { log.Println(gzip.BestCompression) log.Println(fmt.Sprintf("SpewDebugInfo")) log.Println(strings.ToLower("SpewDebugInfo")) + _ = analysis.Analyzer{} } diff --git a/test/testdata/depguard_ignore_file_rules.go b/test/testdata/depguard_ignore_file_rules.go index 767292375d88..d7b9401dcf4f 100644 --- a/test/testdata/depguard_ignore_file_rules.go +++ b/test/testdata/depguard_ignore_file_rules.go @@ -7,8 +7,11 @@ package testdata import ( "compress/gzip" "log" + + "golang.org/x/tools/go/analysis" ) func SpewDebugInfo() { log.Println(gzip.BestCompression) + _ = analysis.Analyzer{} } diff --git a/test/testdata/dupword_ignore_the.go b/test/testdata/dupword_ignore_the.go new file mode 100644 index 000000000000..f321b005fa93 --- /dev/null +++ b/test/testdata/dupword_ignore_the.go @@ -0,0 +1,16 @@ +//golangcitest:args -Edupword +//golangcitest:config_path testdata/configs/dupword_ignore_the.yml +package testdata + +import "fmt" + +func duplicateWordInComments() { + // this line include duplicated word the the + fmt.Println("hello") +} + +func duplicateWordInStr() { + a := "this line include duplicate word and and" // want `Duplicate words \(and\) found` + b := "print the\n the line, print the the \n\t the line. and and" // want `Duplicate words \(and\) found` + fmt.Println(a, b) +} diff --git a/test/testdata/errorlint_errorf.go b/test/testdata/errorlint_errorf.go index e6fc58ce6462..3b727f630c11 100644 --- a/test/testdata/errorlint_errorf.go +++ b/test/testdata/errorlint_errorf.go @@ -16,11 +16,11 @@ func (customError) Error() string { func errorLintErrorf() { err := errors.New("oops") fmt.Errorf("error: %w", err) - fmt.Errorf("error: %v", err) // want "non-wrapping format verb for fmt.Errorf. Use `%w` to format errors" - fmt.Errorf("%v %v", err, err) // want "non-wrapping format verb for fmt.Errorf. Use `%w` to format errors" - fmt.Errorf("error: %s", err.Error()) // want "non-wrapping format verb for fmt.Errorf. Use `%w` to format errors" + fmt.Errorf("error: %v", err) // want "non-wrapping format verb for fmt.Errorf. Use `%w` to format errors" + fmt.Errorf("%v %v", err, err) // want "non-wrapping format verb for fmt.Errorf. Use `%w` to format errors" + fmt.Errorf("error: %s", err.Error()) customError := customError{} - fmt.Errorf("error: %s", customError.Error()) // want "non-wrapping format verb for fmt.Errorf. Use `%w` to format errors" + fmt.Errorf("error: %s", customError.Error()) strErr := "oops" fmt.Errorf("%v", strErr) } diff --git a/test/testdata/exhaustivestruct.go b/test/testdata/exhaustivestruct.go deleted file mode 100644 index 50476cebaffa..000000000000 --- a/test/testdata/exhaustivestruct.go +++ /dev/null @@ -1,46 +0,0 @@ -//golangcitest:args -Eexhaustivestruct --internal-cmd-test -package testdata - -import "time" - -type ExhaustiveStruct struct { - A string - B int - c bool // private field inside the same package are not ignored - D float64 - E time.Time -} - -func exhaustiveStruct() { - // pass - _ = ExhaustiveStruct{ - A: "a", - B: 0, - c: false, - D: 1.0, - E: time.Now(), - } - - // failPrivate - _ = ExhaustiveStruct{ // want "c is missing in ExhaustiveStruct" - A: "a", - B: 0, - D: 1.0, - E: time.Now(), - } - - // fail - _ = ExhaustiveStruct{ // want "B is missing in ExhaustiveStruct" - A: "a", - c: false, - D: 1.0, - E: time.Now(), - } - - // failMultiple - _ = ExhaustiveStruct{ // want "B, D are missing in ExhaustiveStruct" - A: "a", - c: false, - E: time.Now(), - } -} diff --git a/test/testdata/exhaustivestruct_custom.go b/test/testdata/exhaustivestruct_custom.go deleted file mode 100644 index 08fde43f8e88..000000000000 --- a/test/testdata/exhaustivestruct_custom.go +++ /dev/null @@ -1,129 +0,0 @@ -//golangcitest:args -Eexhaustivestruct --internal-cmd-test -//golangcitest:config_path testdata/configs/exhaustivestruct.yml -package testdata - -import "time" - -type ExhaustiveStructCustom struct { - A string - B int - c bool // private field inside the same package are not ignored - D float64 - E time.Time -} - -func exhaustiveStructCustom() { - // pass - _ = ExhaustiveStructCustom{ - A: "a", - B: 0, - c: false, - D: 1.0, - E: time.Now(), - } - - // fail - _ = ExhaustiveStructCustom{ // want "B is missing in ExhaustiveStructCustom" - A: "a", - c: false, - D: 1.0, - E: time.Now(), - } - - // failMultiple - _ = ExhaustiveStructCustom{ // want "B, D are missing in ExhaustiveStructCustom" - A: "a", - c: false, - E: time.Now(), - } - - // failPrivate - _ = ExhaustiveStructCustom{ // want "c is missing in ExhaustiveStructCustom" - A: "a", - B: 0, - D: 1.0, - E: time.Now(), - } - -} - -type ExhaustiveStructCustom1 struct { - A string - B int - c bool // private field inside the same package are not ignored - D float64 - E time.Time -} - -func exhaustiveStructCustom1() { - _ = ExhaustiveStructCustom1{ - A: "a", - B: 0, - c: false, - D: 1.0, - E: time.Now(), - } - - _ = ExhaustiveStructCustom1{ - A: "a", - c: false, - D: 1.0, - E: time.Now(), - } - - _ = ExhaustiveStructCustom1{ - A: "a", - c: false, - E: time.Now(), - } - - _ = ExhaustiveStructCustom1{ - A: "a", - B: 0, - D: 1.0, - E: time.Now(), - } -} - -type ExhaustiveStructCustom2 struct { - A string - B int - c bool // private field inside the same package are not ignored - D float64 - E time.Time -} - -func exhaustiveStructCustom2() { - // pass - _ = ExhaustiveStructCustom2{ - A: "a", - B: 0, - c: false, - D: 1.0, - E: time.Now(), - } - - // fail - _ = ExhaustiveStructCustom2{ // want "B is missing in ExhaustiveStructCustom2" - A: "a", - c: false, - D: 1.0, - E: time.Now(), - } - - // failMultiple - _ = ExhaustiveStructCustom2{ // want "B, D are missing in ExhaustiveStructCustom2" - A: "a", - c: false, - E: time.Now(), - } - - // failPrivate - _ = ExhaustiveStructCustom2{ // want "c is missing in ExhaustiveStructCustom2" - A: "a", - B: 0, - D: 1.0, - E: time.Now(), - } - -} diff --git a/test/testdata/exhaustruct.go b/test/testdata/exhaustruct.go index 35675a5e6a82..e8c3a4031d9a 100644 --- a/test/testdata/exhaustruct.go +++ b/test/testdata/exhaustruct.go @@ -22,7 +22,7 @@ func exhaustruct() { } // failPrivate - _ = Exhaustruct{ // want "c is missing in Exhaustruct" + _ = Exhaustruct{ // want "testdata.Exhaustruct is missing field c" A: "a", B: 0, D: 1.0, @@ -30,7 +30,7 @@ func exhaustruct() { } // fail - _ = Exhaustruct{ // want "B is missing in Exhaustruct" + _ = Exhaustruct{ // want "testdata.Exhaustruct is missing field B" A: "a", c: false, D: 1.0, @@ -38,7 +38,7 @@ func exhaustruct() { } // failMultiple - _ = Exhaustruct{ // want "B, D are missing in Exhaustruct" + _ = Exhaustruct{ // want "testdata.Exhaustruct is missing fields B, D" A: "a", c: false, E: time.Now(), diff --git a/test/testdata/exhaustruct_custom.go b/test/testdata/exhaustruct_custom.go index 60d00a5c2180..11105af0c48a 100644 --- a/test/testdata/exhaustruct_custom.go +++ b/test/testdata/exhaustruct_custom.go @@ -23,7 +23,7 @@ func exhaustructCustom() { } // fail - _ = ExhaustructCustom{ // want "B is missing in ExhaustructCustom" + _ = ExhaustructCustom{ // want "testdata.ExhaustructCustom is missing field B" A: "a", c: false, D: 1.0, @@ -31,14 +31,14 @@ func exhaustructCustom() { } // failMultiple - _ = ExhaustructCustom{ // want "B, D are missing in ExhaustructCustom" + _ = ExhaustructCustom{ // want "testdata.ExhaustructCustom is missing fields B, D" A: "a", c: false, E: time.Now(), } // failPrivate - _ = ExhaustructCustom{ // want "c is missing in ExhaustructCustom" + _ = ExhaustructCustom{ // want "testdata.ExhaustructCustom is missing field c" A: "a", B: 0, D: 1.0, diff --git a/test/testdata/fix/in/gci.go b/test/testdata/fix/in/gci.go index 2449e8bfb86d..6fd16389f769 100644 --- a/test/testdata/fix/in/gci.go +++ b/test/testdata/fix/in/gci.go @@ -5,12 +5,16 @@ package gci import ( "github.com/golangci/golangci-lint/pkg/config" - "github.com/pkg/errors" + "golang.org/x/tools/go/analysis" + "fmt" + + gcicfg "github.com/daixiang0/gci/pkg/config" ) func GoimportsLocalTest() { fmt.Print("x") _ = config.Config{} - _ = errors.New("") + _ = analysis.Analyzer{} + _ = gcicfg.BoolConfig{} } diff --git a/test/testdata/fix/in/go-header_1.go b/test/testdata/fix/in/go-header_1.go new file mode 100644 index 000000000000..7fd59b97a29c --- /dev/null +++ b/test/testdata/fix/in/go-header_1.go @@ -0,0 +1,6 @@ +// Copyright 1999 The Awesome Project Authors + +//golangcitest:args -Egoheader +//golangcitest:expected_exitcode 0 +//golangcitest:config_path testdata/configs/go-header-fix.yml +package p diff --git a/test/testdata/fix/in/go-header_2.go b/test/testdata/fix/in/go-header_2.go new file mode 100644 index 000000000000..ed70ffd4ee24 --- /dev/null +++ b/test/testdata/fix/in/go-header_2.go @@ -0,0 +1,8 @@ +/* Copyright 1999 The Awesome Project Authors + +Use of this source code is governed */ + +//golangcitest:args -Egoheader +//golangcitest:expected_exitcode 0 +//golangcitest:config_path testdata/configs/go-header-fix.yml +package p diff --git a/test/testdata/fix/in/go-header_3.go b/test/testdata/fix/in/go-header_3.go new file mode 100644 index 000000000000..2961f0d5a9ab --- /dev/null +++ b/test/testdata/fix/in/go-header_3.go @@ -0,0 +1,10 @@ +/* +Copyright 1999 The Awesome + +Use of this source code is governed by LICENSE +*/ + +//golangcitest:args -Egoheader +//golangcitest:expected_exitcode 0 +//golangcitest:config_path testdata/configs/go-header-fix.yml +package p diff --git a/test/testdata/fix/in/gofmt.go b/test/testdata/fix/in/gofmt.go index 46dc6c811fd0..7b71332b0e25 100644 --- a/test/testdata/fix/in/gofmt.go +++ b/test/testdata/fix/in/gofmt.go @@ -7,4 +7,4 @@ package p return 1 } return 2 -} +} \ No newline at end of file diff --git a/test/testdata/fix/in/multiple-issues-fix.go b/test/testdata/fix/in/multiple-issues-fix.go new file mode 100644 index 000000000000..af56df5227c0 --- /dev/null +++ b/test/testdata/fix/in/multiple-issues-fix.go @@ -0,0 +1,11 @@ +//golangcitest:args -Egocritic,gofumpt +//golangcitest:config_path testdata/configs/multiple-issues-fix.yml +//golangcitest:expected_exitcode 0 +package p + +import "fmt" + +func main() { + //standard greeting + fmt.Println("hello world") +} diff --git a/test/testdata/fix/in/whitespace.go b/test/testdata/fix/in/whitespace.go index 20c20315c31b..028d9d25693c 100644 --- a/test/testdata/fix/in/whitespace.go +++ b/test/testdata/fix/in/whitespace.go @@ -5,6 +5,7 @@ package p import "fmt" +//line yaccpar:1 func oneLeadingNewline() { fmt.Println("Hello world") @@ -58,4 +59,26 @@ func multiIfFunc() { 2 == 2 { fmt.Println("Hello multi-line world") } + + if true { + if true { + if true { + if 1 == 1 && + 2 == 2 { + fmt.Println("Hello nested multi-line world") + } + } + } + } +} + +func notGoFmted() { + + + + + fmt.Println("Hello world") + + + } diff --git a/test/testdata/fix/out/gci.go b/test/testdata/fix/out/gci.go index 489adb5235fb..0f1fc812f7f9 100644 --- a/test/testdata/fix/out/gci.go +++ b/test/testdata/fix/out/gci.go @@ -6,13 +6,15 @@ package gci import ( "fmt" - "github.com/pkg/errors" - + gcicfg "github.com/daixiang0/gci/pkg/config" "github.com/golangci/golangci-lint/pkg/config" + + "golang.org/x/tools/go/analysis" ) func GoimportsLocalTest() { fmt.Print("x") _ = config.Config{} - _ = errors.New("") + _ = analysis.Analyzer{} + _ = gcicfg.BoolConfig{} } diff --git a/test/testdata/fix/out/go-header_1.go b/test/testdata/fix/out/go-header_1.go new file mode 100644 index 000000000000..e8f7529b627c --- /dev/null +++ b/test/testdata/fix/out/go-header_1.go @@ -0,0 +1,8 @@ +// Copyright 2024 The Awesome Project Authors +// +// Use of this source code is governed by LICENSE + +//golangcitest:args -Egoheader +//golangcitest:expected_exitcode 0 +//golangcitest:config_path testdata/configs/go-header-fix.yml +package p diff --git a/test/testdata/fix/out/go-header_2.go b/test/testdata/fix/out/go-header_2.go new file mode 100644 index 000000000000..80a336a47a8e --- /dev/null +++ b/test/testdata/fix/out/go-header_2.go @@ -0,0 +1,8 @@ +/* Copyright 2024 The Awesome Project Authors + +Use of this source code is governed by LICENSE */ + +//golangcitest:args -Egoheader +//golangcitest:expected_exitcode 0 +//golangcitest:config_path testdata/configs/go-header-fix.yml +package p diff --git a/test/testdata/fix/out/go-header_3.go b/test/testdata/fix/out/go-header_3.go new file mode 100644 index 000000000000..040cad6e8758 --- /dev/null +++ b/test/testdata/fix/out/go-header_3.go @@ -0,0 +1,10 @@ +/* +Copyright 2024 The Awesome Project Authors + +Use of this source code is governed by LICENSE +*/ + +//golangcitest:args -Egoheader +//golangcitest:expected_exitcode 0 +//golangcitest:config_path testdata/configs/go-header-fix.yml +package p diff --git a/test/testdata/fix/out/multiple-issues-fix.go b/test/testdata/fix/out/multiple-issues-fix.go new file mode 100644 index 000000000000..524fb94140e8 --- /dev/null +++ b/test/testdata/fix/out/multiple-issues-fix.go @@ -0,0 +1,11 @@ +//golangcitest:args -Egocritic,gofumpt +//golangcitest:config_path testdata/configs/multiple-issues-fix.yml +//golangcitest:expected_exitcode 0 +package p + +import "fmt" + +func main() { + // standard greeting + fmt.Println("hello world") +} diff --git a/test/testdata/fix/out/whitespace.go b/test/testdata/fix/out/whitespace.go index 16be0dcd5fc3..ec8d4065375b 100644 --- a/test/testdata/fix/out/whitespace.go +++ b/test/testdata/fix/out/whitespace.go @@ -5,6 +5,7 @@ package p import "fmt" +//line yaccpar:1 func oneLeadingNewline() { fmt.Println("Hello world") } @@ -40,7 +41,6 @@ func oneLeadingNewlineWithCommentFunc() { } func twoLeadingNewlines() { - fmt.Println("Hello world") } @@ -56,4 +56,20 @@ func multiIfFunc() { fmt.Println("Hello multi-line world") } + + if true { + if true { + if true { + if 1 == 1 && + 2 == 2 { + + fmt.Println("Hello nested multi-line world") + } + } + } + } +} + +func notGoFmted() { + fmt.Println("Hello world") } diff --git a/test/testdata/forbidigo_example.go b/test/testdata/forbidigo_example.go index 0a2897883a56..52114a4474b1 100644 --- a/test/testdata/forbidigo_example.go +++ b/test/testdata/forbidigo_example.go @@ -4,10 +4,12 @@ package testdata import ( "fmt" + fmt2 "fmt" "time" ) func Forbidigo() { fmt.Printf("too noisy!!!") // want "use of `fmt\\.Printf` forbidden by pattern `fmt\\\\.Print\\.\\*`" + fmt2.Printf("too noisy!!!") // Not detected because analyze-types is false by default for backward compatibility. time.Sleep(time.Nanosecond) // want "no sleeping!" } diff --git a/test/testdata/forbidigo_struct_config.go b/test/testdata/forbidigo_struct_config.go new file mode 100644 index 000000000000..c39ba208cee4 --- /dev/null +++ b/test/testdata/forbidigo_struct_config.go @@ -0,0 +1,13 @@ +//golangcitest:args -Eforbidigo +//golangcitest:config_path testdata/configs/forbidigo_struct.yml +package testdata + +import ( + fmt2 "fmt" + "time" +) + +func Forbidigo() { + fmt2.Printf("too noisy!!!") // want "use of `fmt2\\.Printf` forbidden by pattern `fmt\\\\.Print\\.\\*`" + time.Sleep(time.Nanosecond) // want "no sleeping!" +} diff --git a/test/testdata/gci.go b/test/testdata/gci.go index ef2e1954ca44..cf0b7dea3693 100644 --- a/test/testdata/gci.go +++ b/test/testdata/gci.go @@ -3,15 +3,16 @@ package testdata import ( + "golang.org/x/tools/go/analysis" // want "File is not \\`gci\\`-ed with --skip-generated -s standard -s prefix\\(github.com/golangci/golangci-lint,github.com/daixiang0/gci\\) -s default --custom-order" + "github.com/golangci/golangci-lint/pkg/config" "fmt" - - "github.com/golangci/golangci-lint/pkg/config" // want "File is not \\`gci\\`-ed with --skip-generated -s standard,prefix\\(github.com/golangci/golangci-lint\\),default" - - "github.com/pkg/errors" // want "File is not \\`gci\\`-ed with --skip-generated -s standard,prefix\\(github.com/golangci/golangci-lint\\),default" + "errors" + gcicfg "github.com/daixiang0/gci/pkg/config" // want "File is not \\`gci\\`-ed with --skip-generated -s standard -s prefix\\(github.com/golangci/golangci-lint,github.com/daixiang0/gci\\) -s default --custom-order" ) func GoimportsLocalTest() { - fmt.Print("x") + fmt.Print(errors.New("x")) _ = config.Config{} - _ = errors.New("") + _ = analysis.Analyzer{} + _ = gcicfg.BoolConfig{} } diff --git a/test/testdata/ginkgolinter/configs/ginkgolinter_allow_havelen0.yml b/test/testdata/ginkgolinter/configs/ginkgolinter_allow_havelen0.yml new file mode 100644 index 000000000000..8309f8590559 --- /dev/null +++ b/test/testdata/ginkgolinter/configs/ginkgolinter_allow_havelen0.yml @@ -0,0 +1,3 @@ +linters-settings: + ginkgolinter: + allow-havelen-zero: true diff --git a/test/testdata/ginkgolinter/configs/ginkgolinter_suppress_async.yml b/test/testdata/ginkgolinter/configs/ginkgolinter_suppress_async.yml new file mode 100644 index 000000000000..cb074cddfd8f --- /dev/null +++ b/test/testdata/ginkgolinter/configs/ginkgolinter_suppress_async.yml @@ -0,0 +1,3 @@ +linters-settings: + ginkgolinter: + suppress-async-assertion: true diff --git a/test/testdata/ginkgolinter/configs/ginkgolinter_suppress_compare.yml b/test/testdata/ginkgolinter/configs/ginkgolinter_suppress_compare.yml new file mode 100644 index 000000000000..75ff24d8ff06 --- /dev/null +++ b/test/testdata/ginkgolinter/configs/ginkgolinter_suppress_compare.yml @@ -0,0 +1,3 @@ +linters-settings: + ginkgolinter: + suppress-compare-assertion: true diff --git a/test/testdata/ginkgolinter/configs/ginkgolinter_suppress_focused_containers.yml b/test/testdata/ginkgolinter/configs/ginkgolinter_suppress_focused_containers.yml new file mode 100644 index 000000000000..83f49e878b9e --- /dev/null +++ b/test/testdata/ginkgolinter/configs/ginkgolinter_suppress_focused_containers.yml @@ -0,0 +1,3 @@ +linters-settings: + ginkgolinter: + forbid-focus-container: true diff --git a/test/testdata/ginkgolinter/ginkgolinter.go b/test/testdata/ginkgolinter/ginkgolinter.go index 8af228a41aed..6de26066e0bb 100644 --- a/test/testdata/ginkgolinter/ginkgolinter.go +++ b/test/testdata/ginkgolinter/ginkgolinter.go @@ -3,6 +3,9 @@ package ginkgolinter import ( "errors" + "time" + + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) @@ -49,3 +52,36 @@ func ErrorUsecase() { Expect(err != nil).To(BeTrue()) // want "ginkgo-linter: wrong error assertion; consider using .Expect\\(err\\)\\.To\\(HaveOccurred\\(\\)\\). instead" Expect(funcReturnsErr()).To(BeNil()) // want "ginkgo-linter: wrong error assertion; consider using .Expect\\(funcReturnsErr\\(\\)\\)\\.To\\(Succeed\\(\\)\\). instead" } + +func HaveLen0Usecase() { + x := make([]string, 0) + Expect(x).To(HaveLen(0)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(x\\)\\.To\\(BeEmpty\\(\\)\\). instead" +} + +func WrongComparisonUsecase() { + x := 8 + Expect(x == 8).To(BeTrue()) // want "ginkgo-linter: wrong comparison assertion; consider using .Expect\\(x\\)\\.To\\(Equal\\(8\\)\\). instead" + Expect(x < 9).To(BeTrue()) // want "ginkgo-linter: wrong comparison assertion; consider using .Expect\\(x\\)\\.To\\(BeNumerically\\(\"<\", 9\\)\\). instead" + Expect(x < 7).To(Equal(false)) // want "ginkgo-linter: wrong comparison assertion; consider using .Expect\\(x\\)\\.ToNot\\(BeNumerically\\(\"<\", 7\\)\\). instead" + + p1, p2 := &x, &x + Expect(p1 == p2).To(Equal(true)) // want "ginkgo-linter: wrong comparison assertion; consider using .Expect\\(p1\\).To\\(BeIdenticalTo\\(p2\\)\\). instead" +} + +func slowInt() int { + time.Sleep(time.Second) + return 42 +} + +func WrongEventuallyWithFunction() { + Eventually(slowInt).Should(Equal(42)) // valid + Eventually(slowInt()).Should(Equal(42)) // want "ginkgo-linter: use a function call in Eventually. This actually checks nothing, because Eventually receives the function returned value, instead of function itself, and this value is never changed; consider using .Eventually\\(slowInt\\)\\.Should\\(Equal\\(42\\)\\). instead" +} + +var _ = FDescribe("Should warn for focused containers", func() { + FContext("should not allow FContext", func() { + FWhen("should not allow FWhen", func() { + FIt("should not allow FIt", func() {}) + }) + }) +}) diff --git a/test/testdata/ginkgolinter/ginkgolinter_havelen0.go b/test/testdata/ginkgolinter/ginkgolinter_havelen0.go new file mode 100644 index 000000000000..4ca9a61b2e77 --- /dev/null +++ b/test/testdata/ginkgolinter/ginkgolinter_havelen0.go @@ -0,0 +1,88 @@ +//golangcitest:config_path configs/ginkgolinter_allow_havelen0.yml +//golangcitest:args --disable-all -Eginkgolinter +package ginkgolinter + +import ( + "errors" + "time" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func LenUsecase_havelen0() { + var fakeVarUnderTest []int + Expect(fakeVarUnderTest).Should(BeEmpty()) // valid + Expect(fakeVarUnderTest).ShouldNot(HaveLen(5)) // valid + + Expect(len(fakeVarUnderTest)).Should(Equal(0)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.Should\\(BeEmpty\\(\\)\\). instead" + Expect(len(fakeVarUnderTest)).ShouldNot(Equal(2)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.ShouldNot\\(HaveLen\\(2\\)\\). instead" + Expect(len(fakeVarUnderTest)).To(BeNumerically("==", 0)) // // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.To\\(BeEmpty\\(\\)\\). instead" + + fakeVarUnderTest = append(fakeVarUnderTest, 3) + Expect(len(fakeVarUnderTest)).ShouldNot(Equal(0)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.ShouldNot\\(BeEmpty\\(\\)\\). instead" + Expect(len(fakeVarUnderTest)).Should(Equal(1)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.Should\\(HaveLen\\(1\\)\\). instead" + Expect(len(fakeVarUnderTest)).To(BeNumerically(">", 0)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.ToNot\\(BeEmpty\\(\\)\\). instead" + Expect(len(fakeVarUnderTest)).To(BeNumerically(">=", 1)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.ToNot\\(BeEmpty\\(\\)\\). instead" + Expect(len(fakeVarUnderTest)).To(BeNumerically("!=", 0)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.ToNot\\(BeEmpty\\(\\)\\). instead" +} + +func NilUsecase_havelen0() { + y := 5 + x := &y + Expect(x == nil).To(Equal(true)) // want "ginkgo-linter: wrong nil assertion; consider using .Expect\\(x\\)\\.To\\(BeNil\\(\\)\\). instead" + Expect(nil == x).To(Equal(true)) // want "ginkgo-linter: wrong nil assertion; consider using .Expect\\(x\\)\\.To\\(BeNil\\(\\)\\). instead" + Expect(x != nil).To(Equal(true)) // want "ginkgo-linter: wrong nil assertion; consider using .Expect\\(x\\)\\.ToNot\\(BeNil\\(\\)\\). instead" + Expect(x == nil).To(BeTrue()) // want "ginkgo-linter: wrong nil assertion; consider using .Expect\\(x\\)\\.To\\(BeNil\\(\\)\\). instead" + Expect(x == nil).To(BeFalse()) // want "ginkgo-linter: wrong nil assertion; consider using .Expect\\(x\\)\\.ToNot\\(BeNil\\(\\)\\). instead" +} +func BooleanUsecase_havelen0() { + x := true + Expect(x).To(Equal(true)) // want "ginkgo-linter: wrong boolean assertion; consider using .Expect\\(x\\)\\.To\\(BeTrue\\(\\)\\). instead" + x = false + Expect(x).To(Equal(false)) // want "ginkgo-linter: wrong boolean assertion; consider using .Expect\\(x\\)\\.To\\(BeFalse\\(\\)\\). instead" +} + +func ErrorUsecase_havelen0() { + err := errors.New("fake error") + funcReturnsErr := func() error { return err } + + Expect(err).To(BeNil()) // want "ginkgo-linter: wrong error assertion; consider using .Expect\\(err\\)\\.ToNot\\(HaveOccurred\\(\\)\\). instead" + Expect(err == nil).To(Equal(true)) // want "ginkgo-linter: wrong error assertion; consider using .Expect\\(err\\)\\.ToNot\\(HaveOccurred\\(\\)\\). instead" + Expect(err == nil).To(BeFalse()) // want "ginkgo-linter: wrong error assertion; consider using .Expect\\(err\\)\\.To\\(HaveOccurred\\(\\)\\). instead" + Expect(err != nil).To(BeTrue()) // want "ginkgo-linter: wrong error assertion; consider using .Expect\\(err\\)\\.To\\(HaveOccurred\\(\\)\\). instead" + Expect(funcReturnsErr()).To(BeNil()) // want "ginkgo-linter: wrong error assertion; consider using .Expect\\(funcReturnsErr\\(\\)\\)\\.To\\(Succeed\\(\\)\\). instead" +} + +func HaveLen0Usecase_havelen0() { + x := make([]string, 0) + Expect(x).To(HaveLen(0)) +} + +func WrongComparisonUsecase_havelen0() { + x := 8 + Expect(x == 8).To(BeTrue()) // want "ginkgo-linter: wrong comparison assertion; consider using .Expect\\(x\\)\\.To\\(Equal\\(8\\)\\). instead" + Expect(x < 9).To(BeTrue()) // want "ginkgo-linter: wrong comparison assertion; consider using .Expect\\(x\\)\\.To\\(BeNumerically\\(\"<\", 9\\)\\). instead" + Expect(x < 7).To(Equal(false)) // want "ginkgo-linter: wrong comparison assertion; consider using .Expect\\(x\\)\\.ToNot\\(BeNumerically\\(\"<\", 7\\)\\). instead" + + p1, p2 := &x, &x + Expect(p1 == p2).To(Equal(true)) // want "ginkgo-linter: wrong comparison assertion; consider using .Expect\\(p1\\).To\\(BeIdenticalTo\\(p2\\)\\). instead" +} + +func slowInt_havelen0() int { + time.Sleep(time.Second) + return 42 +} + +func WrongEventuallyWithFunction_havelen0() { + Eventually(slowInt_havelen0).Should(Equal(42)) // valid + Eventually(slowInt_havelen0()).Should(Equal(42)) // want "ginkgo-linter: use a function call in Eventually. This actually checks nothing, because Eventually receives the function returned value, instead of function itself, and this value is never changed; consider using .Eventually\\(slowInt_havelen0\\)\\.Should\\(Equal\\(42\\)\\). instead" +} + +var _ = FDescribe("Should warn for focused containers", func() { + FContext("should not allow FContext", func() { + FWhen("should not allow FWhen", func() { + FIt("should not allow FIt", func() {}) + }) + }) +}) diff --git a/test/testdata/ginkgolinter/ginkgolinter_suppress_async.go b/test/testdata/ginkgolinter/ginkgolinter_suppress_async.go new file mode 100644 index 000000000000..015010a546d5 --- /dev/null +++ b/test/testdata/ginkgolinter/ginkgolinter_suppress_async.go @@ -0,0 +1,89 @@ +//golangcitest:config_path configs/ginkgolinter_suppress_async.yml +//golangcitest:args --disable-all -Eginkgolinter +package ginkgolinter + +import ( + "errors" + "time" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func LenUsecase_async() { + var fakeVarUnderTest []int + Expect(fakeVarUnderTest).Should(BeEmpty()) // valid + Expect(fakeVarUnderTest).ShouldNot(HaveLen(5)) // valid + + Expect(len(fakeVarUnderTest)).Should(Equal(0)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.Should\\(BeEmpty\\(\\)\\). instead" + Expect(len(fakeVarUnderTest)).ShouldNot(Equal(2)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.ShouldNot\\(HaveLen\\(2\\)\\). instead" + Expect(len(fakeVarUnderTest)).To(BeNumerically("==", 0)) // // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.To\\(BeEmpty\\(\\)\\). instead" + + fakeVarUnderTest = append(fakeVarUnderTest, 3) + Expect(len(fakeVarUnderTest)).ShouldNot(Equal(0)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.ShouldNot\\(BeEmpty\\(\\)\\). instead" + Expect(len(fakeVarUnderTest)).Should(Equal(1)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.Should\\(HaveLen\\(1\\)\\). instead" + Expect(len(fakeVarUnderTest)).To(BeNumerically(">", 0)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.ToNot\\(BeEmpty\\(\\)\\). instead" + Expect(len(fakeVarUnderTest)).To(BeNumerically(">=", 1)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.ToNot\\(BeEmpty\\(\\)\\). instead" + Expect(len(fakeVarUnderTest)).To(BeNumerically("!=", 0)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.ToNot\\(BeEmpty\\(\\)\\). instead" +} + +func NilUsecase_async() { + y := 5 + x := &y + Expect(x == nil).To(Equal(true)) // want "ginkgo-linter: wrong nil assertion; consider using .Expect\\(x\\)\\.To\\(BeNil\\(\\)\\). instead" + Expect(nil == x).To(Equal(true)) // want "ginkgo-linter: wrong nil assertion; consider using .Expect\\(x\\)\\.To\\(BeNil\\(\\)\\). instead" + Expect(x != nil).To(Equal(true)) // want "ginkgo-linter: wrong nil assertion; consider using .Expect\\(x\\)\\.ToNot\\(BeNil\\(\\)\\). instead" + Expect(x == nil).To(BeTrue()) // want "ginkgo-linter: wrong nil assertion; consider using .Expect\\(x\\)\\.To\\(BeNil\\(\\)\\). instead" + Expect(x == nil).To(BeFalse()) // want "ginkgo-linter: wrong nil assertion; consider using .Expect\\(x\\)\\.ToNot\\(BeNil\\(\\)\\). instead" +} +func BooleanUsecase_async() { + x := true + Expect(x).To(Equal(true)) // want "ginkgo-linter: wrong boolean assertion; consider using .Expect\\(x\\)\\.To\\(BeTrue\\(\\)\\). instead" + x = false + Expect(x).To(Equal(false)) // want "ginkgo-linter: wrong boolean assertion; consider using .Expect\\(x\\)\\.To\\(BeFalse\\(\\)\\). instead" +} + +func ErrorUsecase_async() { + err := errors.New("fake error") + funcReturnsErr := func() error { return err } + + Expect(err).To(BeNil()) // want "ginkgo-linter: wrong error assertion; consider using .Expect\\(err\\)\\.ToNot\\(HaveOccurred\\(\\)\\). instead" + Expect(err == nil).To(Equal(true)) // want "ginkgo-linter: wrong error assertion; consider using .Expect\\(err\\)\\.ToNot\\(HaveOccurred\\(\\)\\). instead" + Expect(err == nil).To(BeFalse()) // want "ginkgo-linter: wrong error assertion; consider using .Expect\\(err\\)\\.To\\(HaveOccurred\\(\\)\\). instead" + Expect(err != nil).To(BeTrue()) // want "ginkgo-linter: wrong error assertion; consider using .Expect\\(err\\)\\.To\\(HaveOccurred\\(\\)\\). instead" + Expect(funcReturnsErr()).To(BeNil()) // want "ginkgo-linter: wrong error assertion; consider using .Expect\\(funcReturnsErr\\(\\)\\)\\.To\\(Succeed\\(\\)\\). instead" +} + +func HaveLen0Usecase_async() { + x := make([]string, 0) + Expect(x).To(HaveLen(0)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(x\\)\\.To\\(BeEmpty\\(\\)\\). instead" +} + +func WrongComparisonUsecase_async() { + x := 8 + Expect(x == 8).To(BeTrue()) // want "ginkgo-linter: wrong comparison assertion; consider using .Expect\\(x\\)\\.To\\(Equal\\(8\\)\\). instead" + Expect(x < 9).To(BeTrue()) // want "ginkgo-linter: wrong comparison assertion; consider using .Expect\\(x\\)\\.To\\(BeNumerically\\(\"<\", 9\\)\\). instead" + Expect(x < 7).To(Equal(false)) // want "ginkgo-linter: wrong comparison assertion; consider using .Expect\\(x\\)\\.ToNot\\(BeNumerically\\(\"<\", 7\\)\\). instead" + + p1, p2 := &x, &x + Expect(p1 == p2).To(Equal(true)) // want "ginkgo-linter: wrong comparison assertion; consider using .Expect\\(p1\\).To\\(BeIdenticalTo\\(p2\\)\\). instead" +} + +func slowInt_async() int { + time.Sleep(time.Second) + return 42 +} + +// WrongEventuallyWithFunction_async Should trigger no warning +func WrongEventuallyWithFunction_async() { + Eventually(slowInt_async).Should(Equal(42)) // valid + Eventually(slowInt_async()).Should(Equal(42)) // suppressed +} + +var _ = FDescribe("Should warn for focused containers", func() { + FContext("should not allow FContext", func() { + FWhen("should not allow FWhen", func() { + FIt("should not allow FIt", func() {}) + }) + }) +}) diff --git a/test/testdata/ginkgolinter/ginkgolinter_suppress_compare.go b/test/testdata/ginkgolinter/ginkgolinter_suppress_compare.go new file mode 100644 index 000000000000..8460371da30b --- /dev/null +++ b/test/testdata/ginkgolinter/ginkgolinter_suppress_compare.go @@ -0,0 +1,89 @@ +//golangcitest:config_path configs/ginkgolinter_suppress_compare.yml +//golangcitest:args --disable-all -Eginkgolinter +package ginkgolinter + +import ( + "errors" + "time" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func LenUsecase_compare() { + var fakeVarUnderTest []int + Expect(fakeVarUnderTest).Should(BeEmpty()) // valid + Expect(fakeVarUnderTest).ShouldNot(HaveLen(5)) // valid + + Expect(len(fakeVarUnderTest)).Should(Equal(0)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.Should\\(BeEmpty\\(\\)\\). instead" + Expect(len(fakeVarUnderTest)).ShouldNot(Equal(2)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.ShouldNot\\(HaveLen\\(2\\)\\). instead" + Expect(len(fakeVarUnderTest)).To(BeNumerically("==", 0)) // // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.To\\(BeEmpty\\(\\)\\). instead" + + fakeVarUnderTest = append(fakeVarUnderTest, 3) + Expect(len(fakeVarUnderTest)).ShouldNot(Equal(0)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.ShouldNot\\(BeEmpty\\(\\)\\). instead" + Expect(len(fakeVarUnderTest)).Should(Equal(1)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.Should\\(HaveLen\\(1\\)\\). instead" + Expect(len(fakeVarUnderTest)).To(BeNumerically(">", 0)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.ToNot\\(BeEmpty\\(\\)\\). instead" + Expect(len(fakeVarUnderTest)).To(BeNumerically(">=", 1)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.ToNot\\(BeEmpty\\(\\)\\). instead" + Expect(len(fakeVarUnderTest)).To(BeNumerically("!=", 0)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.ToNot\\(BeEmpty\\(\\)\\). instead" +} + +func NilUsecase_compare() { + y := 5 + x := &y + Expect(x == nil).To(Equal(true)) // want "ginkgo-linter: wrong nil assertion; consider using .Expect\\(x\\)\\.To\\(BeNil\\(\\)\\). instead" + Expect(nil == x).To(Equal(true)) // want "ginkgo-linter: wrong nil assertion; consider using .Expect\\(x\\)\\.To\\(BeNil\\(\\)\\). instead" + Expect(x != nil).To(Equal(true)) // want "ginkgo-linter: wrong nil assertion; consider using .Expect\\(x\\)\\.ToNot\\(BeNil\\(\\)\\). instead" + Expect(x == nil).To(BeTrue()) // want "ginkgo-linter: wrong nil assertion; consider using .Expect\\(x\\)\\.To\\(BeNil\\(\\)\\). instead" + Expect(x == nil).To(BeFalse()) // want "ginkgo-linter: wrong nil assertion; consider using .Expect\\(x\\)\\.ToNot\\(BeNil\\(\\)\\). instead" +} +func BooleanUsecase_compare() { + x := true + Expect(x).To(Equal(true)) // want "ginkgo-linter: wrong boolean assertion; consider using .Expect\\(x\\)\\.To\\(BeTrue\\(\\)\\). instead" + x = false + Expect(x).To(Equal(false)) // want "ginkgo-linter: wrong boolean assertion; consider using .Expect\\(x\\)\\.To\\(BeFalse\\(\\)\\). instead" +} + +func ErrorUsecase_compare() { + err := errors.New("fake error") + funcReturnsErr := func() error { return err } + + Expect(err).To(BeNil()) // want "ginkgo-linter: wrong error assertion; consider using .Expect\\(err\\)\\.ToNot\\(HaveOccurred\\(\\)\\). instead" + Expect(err == nil).To(Equal(true)) // want "ginkgo-linter: wrong error assertion; consider using .Expect\\(err\\)\\.ToNot\\(HaveOccurred\\(\\)\\). instead" + Expect(err == nil).To(BeFalse()) // want "ginkgo-linter: wrong error assertion; consider using .Expect\\(err\\)\\.To\\(HaveOccurred\\(\\)\\). instead" + Expect(err != nil).To(BeTrue()) // want "ginkgo-linter: wrong error assertion; consider using .Expect\\(err\\)\\.To\\(HaveOccurred\\(\\)\\). instead" + Expect(funcReturnsErr()).To(BeNil()) // want "ginkgo-linter: wrong error assertion; consider using .Expect\\(funcReturnsErr\\(\\)\\)\\.To\\(Succeed\\(\\)\\). instead" +} + +func HaveLen0Usecase_compare() { + x := make([]string, 0) + Expect(x).To(HaveLen(0)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(x\\)\\.To\\(BeEmpty\\(\\)\\). instead" +} + +// WrongComparisonUsecase_compare should not trigger any warning +func WrongComparisonUsecase_compare() { + x := 8 + Expect(x == 8).To(BeTrue()) + Expect(x < 9).To(BeTrue()) + Expect(x < 7).To(Equal(false)) + + p1, p2 := &x, &x + Expect(p1 == p2).To(Equal(true)) +} + +func slowInt_compare() int { + time.Sleep(time.Second) + return 42 +} + +func WrongEventuallyWithFunction_compare() { + Eventually(slowInt_compare).Should(Equal(42)) // valid + Eventually(slowInt_compare()).Should(Equal(42)) // want "ginkgo-linter: use a function call in Eventually. This actually checks nothing, because Eventually receives the function returned value, instead of function itself, and this value is never changed; consider using .Eventually\\(slowInt_compare\\)\\.Should\\(Equal\\(42\\)\\). instead" +} + +var _ = FDescribe("Should warn for focused containers", func() { + FContext("should not allow FContext", func() { + FWhen("should not allow FWhen", func() { + FIt("should not allow FIt", func() {}) + }) + }) +}) diff --git a/test/testdata/ginkgolinter/ginkgolinter_suppress_err.go b/test/testdata/ginkgolinter/ginkgolinter_suppress_err.go index 7663e2cb2290..db5accc34132 100644 --- a/test/testdata/ginkgolinter/ginkgolinter_suppress_err.go +++ b/test/testdata/ginkgolinter/ginkgolinter_suppress_err.go @@ -4,6 +4,9 @@ package ginkgolinter import ( "errors" + "time" + + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) @@ -40,6 +43,7 @@ func BooleanUsecase_err() { Expect(x).To(Equal(false)) // want "ginkgo-linter: wrong boolean assertion; consider using .Expect\\(x\\)\\.To\\(BeFalse\\(\\)\\). instead" } +// ErrorUsecase_err should not trigger any warning func ErrorUsecase_err() { err := errors.New("fake error") funcReturnsErr := func() error { return err } @@ -50,3 +54,36 @@ func ErrorUsecase_err() { Expect(err != nil).To(BeTrue()) Expect(funcReturnsErr()).To(BeNil()) } + +func HaveLen0Usecase_err() { + x := make([]string, 0) + Expect(x).To(HaveLen(0)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(x\\)\\.To\\(BeEmpty\\(\\)\\). instead" +} + +func WrongComparisonUsecase_err() { + x := 8 + Expect(x == 8).To(BeTrue()) // want "ginkgo-linter: wrong comparison assertion; consider using .Expect\\(x\\)\\.To\\(Equal\\(8\\)\\). instead" + Expect(x < 9).To(BeTrue()) // want "ginkgo-linter: wrong comparison assertion; consider using .Expect\\(x\\)\\.To\\(BeNumerically\\(\"<\", 9\\)\\). instead" + Expect(x < 7).To(Equal(false)) // want "ginkgo-linter: wrong comparison assertion; consider using .Expect\\(x\\)\\.ToNot\\(BeNumerically\\(\"<\", 7\\)\\). instead" + + p1, p2 := &x, &x + Expect(p1 == p2).To(Equal(true)) // want "ginkgo-linter: wrong comparison assertion; consider using .Expect\\(p1\\).To\\(BeIdenticalTo\\(p2\\)\\). instead" +} + +func slowInt_err() int { + time.Sleep(time.Second) + return 42 +} + +func WrongEventuallyWithFunction_err() { + Eventually(slowInt_err).Should(Equal(42)) // valid + Eventually(slowInt_err()).Should(Equal(42)) // want "ginkgo-linter: use a function call in Eventually. This actually checks nothing, because Eventually receives the function returned value, instead of function itself, and this value is never changed; consider using .Eventually\\(slowInt_err\\)\\.Should\\(Equal\\(42\\)\\). instead" +} + +var _ = FDescribe("Should warn for focused containers", func() { + FContext("should not allow FContext", func() { + FWhen("should not allow FWhen", func() { + FIt("should not allow FIt", func() {}) + }) + }) +}) diff --git a/test/testdata/ginkgolinter/ginkgolinter_suppress_focused_containers.go b/test/testdata/ginkgolinter/ginkgolinter_suppress_focused_containers.go new file mode 100644 index 000000000000..ec0d352288c9 --- /dev/null +++ b/test/testdata/ginkgolinter/ginkgolinter_suppress_focused_containers.go @@ -0,0 +1,90 @@ +//golangcitest:args --disable-all -Eginkgolinter +//golangcitest:config_path configs/ginkgolinter_suppress_focused_containers.yml +package ginkgolinter + +import ( + "errors" + "time" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func LenUsecase_focus() { + var fakeVarUnderTest []int + Expect(fakeVarUnderTest).Should(BeEmpty()) // valid + Expect(fakeVarUnderTest).ShouldNot(HaveLen(5)) // valid + + Expect(len(fakeVarUnderTest)).Should(Equal(0)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.Should\\(BeEmpty\\(\\)\\). instead" + Expect(len(fakeVarUnderTest)).ShouldNot(Equal(2)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.ShouldNot\\(HaveLen\\(2\\)\\). instead" + Expect(len(fakeVarUnderTest)).To(BeNumerically("==", 0)) // // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.To\\(BeEmpty\\(\\)\\). instead" + + fakeVarUnderTest = append(fakeVarUnderTest, 3) + Expect(len(fakeVarUnderTest)).ShouldNot(Equal(0)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.ShouldNot\\(BeEmpty\\(\\)\\). instead" + Expect(len(fakeVarUnderTest)).Should(Equal(1)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.Should\\(HaveLen\\(1\\)\\). instead" + Expect(len(fakeVarUnderTest)).To(BeNumerically(">", 0)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.ToNot\\(BeEmpty\\(\\)\\). instead" + Expect(len(fakeVarUnderTest)).To(BeNumerically(">=", 1)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.ToNot\\(BeEmpty\\(\\)\\). instead" + Expect(len(fakeVarUnderTest)).To(BeNumerically("!=", 0)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.ToNot\\(BeEmpty\\(\\)\\). instead" +} + +func NilUsecase_focus() { + y := 5 + x := &y + Expect(x == nil).To(Equal(true)) // want "ginkgo-linter: wrong nil assertion; consider using .Expect\\(x\\)\\.To\\(BeNil\\(\\)\\). instead" + Expect(nil == x).To(Equal(true)) // want "ginkgo-linter: wrong nil assertion; consider using .Expect\\(x\\)\\.To\\(BeNil\\(\\)\\). instead" + Expect(x != nil).To(Equal(true)) // want "ginkgo-linter: wrong nil assertion; consider using .Expect\\(x\\)\\.ToNot\\(BeNil\\(\\)\\). instead" + Expect(x == nil).To(BeTrue()) // want "ginkgo-linter: wrong nil assertion; consider using .Expect\\(x\\)\\.To\\(BeNil\\(\\)\\). instead" + Expect(x == nil).To(BeFalse()) // want "ginkgo-linter: wrong nil assertion; consider using .Expect\\(x\\)\\.ToNot\\(BeNil\\(\\)\\). instead" +} +func BooleanUsecase_focus() { + x := true + Expect(x).To(Equal(true)) // want "ginkgo-linter: wrong boolean assertion; consider using .Expect\\(x\\)\\.To\\(BeTrue\\(\\)\\). instead" + x = false + Expect(x).To(Equal(false)) // want "ginkgo-linter: wrong boolean assertion; consider using .Expect\\(x\\)\\.To\\(BeFalse\\(\\)\\). instead" +} + +func ErrorUsecase_focus() { + err := errors.New("fake error") + funcReturnsErr := func() error { return err } + + Expect(err).To(BeNil()) // want "ginkgo-linter: wrong error assertion; consider using .Expect\\(err\\)\\.ToNot\\(HaveOccurred\\(\\)\\). instead" + Expect(err == nil).To(Equal(true)) // want "ginkgo-linter: wrong error assertion; consider using .Expect\\(err\\)\\.ToNot\\(HaveOccurred\\(\\)\\). instead" + Expect(err == nil).To(BeFalse()) // want "ginkgo-linter: wrong error assertion; consider using .Expect\\(err\\)\\.To\\(HaveOccurred\\(\\)\\). instead" + Expect(err != nil).To(BeTrue()) // want "ginkgo-linter: wrong error assertion; consider using .Expect\\(err\\)\\.To\\(HaveOccurred\\(\\)\\). instead" + Expect(funcReturnsErr()).To(BeNil()) // want "ginkgo-linter: wrong error assertion; consider using .Expect\\(funcReturnsErr\\(\\)\\)\\.To\\(Succeed\\(\\)\\). instead" +} + +func HaveLen0Usecase_focus() { + x := make([]string, 0) + Expect(x).To(HaveLen(0)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(x\\)\\.To\\(BeEmpty\\(\\)\\). instead" +} + +func WrongComparisonUsecase_focus() { + x := 8 + Expect(x == 8).To(BeTrue()) // want "ginkgo-linter: wrong comparison assertion; consider using .Expect\\(x\\)\\.To\\(Equal\\(8\\)\\). instead" + Expect(x < 9).To(BeTrue()) // want "ginkgo-linter: wrong comparison assertion; consider using .Expect\\(x\\)\\.To\\(BeNumerically\\(\"<\", 9\\)\\). instead" + Expect(x < 7).To(Equal(false)) // want "ginkgo-linter: wrong comparison assertion; consider using .Expect\\(x\\)\\.ToNot\\(BeNumerically\\(\"<\", 7\\)\\). instead" + + p1, p2 := &x, &x + Expect(p1 == p2).To(Equal(true)) // want "ginkgo-linter: wrong comparison assertion; consider using .Expect\\(p1\\).To\\(BeIdenticalTo\\(p2\\)\\). instead" +} + +func slowInt_focus() int { + time.Sleep(time.Second) + return 42 +} + +func WrongEventuallyWithFunction_focus() { + Eventually(slowInt_focus).Should(Equal(42)) // valid + Eventually(slowInt_focus()).Should(Equal(42)) // want "ginkgo-linter: use a function call in Eventually. This actually checks nothing, because Eventually receives the function returned value, instead of function itself, and this value is never changed; consider using .Eventually\\(slowInt_focus\\)\\.Should\\(Equal\\(42\\)\\). instead" +} + +var _ = Describe("Should warn for focused containers", func() { + FContext("should not allow FContext", func() { // want "ginkgo-linter: Focus container found. This is used only for local debug and should not be part of the actual source code, consider to replace with \"Context\"" + FWhen("should not allow FWhen", func() { // want "ginkgo-linter: Focus container found. This is used only for local debug and should not be part of the actual source code, consider to replace with \"When\"" + FIt("should not allow FIt", func() { // want "ginkgo-linter: Focus container found. This is used only for local debug and should not be part of the actual source code, consider to replace with \"It\"" + + }) + }) + }) +}) diff --git a/test/testdata/ginkgolinter/ginkgolinter_suppress_len.go b/test/testdata/ginkgolinter/ginkgolinter_suppress_len.go index 0d1e33eae13c..81fc2652903f 100644 --- a/test/testdata/ginkgolinter/ginkgolinter_suppress_len.go +++ b/test/testdata/ginkgolinter/ginkgolinter_suppress_len.go @@ -4,9 +4,13 @@ package ginkgolinter import ( "errors" + "time" + + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) +// LenUsecase_len should not trigger any warning func LenUsecase_len() { var fakeVarUnderTest []int Expect(fakeVarUnderTest).Should(BeEmpty()) // valid @@ -50,3 +54,36 @@ func ErrorUsecase_len() { Expect(err != nil).To(BeTrue()) // want "ginkgo-linter: wrong error assertion; consider using .Expect\\(err\\)\\.To\\(HaveOccurred\\(\\)\\). instead" Expect(funcReturnsErr()).To(BeNil()) // want "ginkgo-linter: wrong error assertion; consider using .Expect\\(funcReturnsErr\\(\\)\\)\\.To\\(Succeed\\(\\)\\). instead" } + +func HaveLen0Usecase_len() { + x := make([]string, 0) + Expect(x).To(HaveLen(0)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(x\\)\\.To\\(BeEmpty\\(\\)\\). instead" +} + +func WrongComparisonUsecase_len() { + x := 8 + Expect(x == 8).To(BeTrue()) // want "ginkgo-linter: wrong comparison assertion; consider using .Expect\\(x\\)\\.To\\(Equal\\(8\\)\\). instead" + Expect(x < 9).To(BeTrue()) // want "ginkgo-linter: wrong comparison assertion; consider using .Expect\\(x\\)\\.To\\(BeNumerically\\(\"<\", 9\\)\\). instead" + Expect(x < 7).To(Equal(false)) // want "ginkgo-linter: wrong comparison assertion; consider using .Expect\\(x\\)\\.ToNot\\(BeNumerically\\(\"<\", 7\\)\\). instead" + + p1, p2 := &x, &x + Expect(p1 == p2).To(Equal(true)) // want "ginkgo-linter: wrong comparison assertion; consider using .Expect\\(p1\\).To\\(BeIdenticalTo\\(p2\\)\\). instead" +} + +func slowInt_len() int { + time.Sleep(time.Second) + return 42 +} + +func WrongEventuallyWithFunction_len() { + Eventually(slowInt_len).Should(Equal(42)) // valid + Eventually(slowInt_len()).Should(Equal(42)) // want "ginkgo-linter: use a function call in Eventually. This actually checks nothing, because Eventually receives the function returned value, instead of function itself, and this value is never changed; consider using .Eventually\\(slowInt_len\\)\\.Should\\(Equal\\(42\\)\\). instead" +} + +var _ = FDescribe("Should warn for focused containers", func() { + FContext("should not allow FContext", func() { + FWhen("should not allow FWhen", func() { + FIt("should not allow FIt", func() {}) + }) + }) +}) diff --git a/test/testdata/ginkgolinter/ginkgolinter_suppress_nil.go b/test/testdata/ginkgolinter/ginkgolinter_suppress_nil.go index f1a30473e5ec..5eb93ac5998c 100644 --- a/test/testdata/ginkgolinter/ginkgolinter_suppress_nil.go +++ b/test/testdata/ginkgolinter/ginkgolinter_suppress_nil.go @@ -4,6 +4,9 @@ package ginkgolinter import ( "errors" + "time" + + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) @@ -24,6 +27,7 @@ func LenUsecase_nil() { Expect(len(fakeVarUnderTest)).To(BeNumerically("!=", 0)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(fakeVarUnderTest\\)\\.ToNot\\(BeEmpty\\(\\)\\). instead" } +// NilUsecase_nil should not trigger any warning func NilUsecase_nil() { y := 5 x := &y @@ -50,3 +54,36 @@ func ErrorUsecase_nil() { Expect(err != nil).To(BeTrue()) // want "ginkgo-linter: wrong error assertion; consider using .Expect\\(err\\)\\.To\\(HaveOccurred\\(\\)\\). instead" Expect(funcReturnsErr()).To(BeNil()) // want "ginkgo-linter: wrong error assertion; consider using .Expect\\(funcReturnsErr\\(\\)\\)\\.To\\(Succeed\\(\\)\\). instead" } + +func HaveLen0Usecase_nil() { + x := make([]string, 0) + Expect(x).To(HaveLen(0)) // want "ginkgo-linter: wrong length assertion; consider using .Expect\\(x\\)\\.To\\(BeEmpty\\(\\)\\). instead" +} + +func WrongComparisonUsecase_nil() { + x := 8 + Expect(x == 8).To(BeTrue()) // want "ginkgo-linter: wrong comparison assertion; consider using .Expect\\(x\\)\\.To\\(Equal\\(8\\)\\). instead" + Expect(x < 9).To(BeTrue()) // want "ginkgo-linter: wrong comparison assertion; consider using .Expect\\(x\\)\\.To\\(BeNumerically\\(\"<\", 9\\)\\). instead" + Expect(x < 7).To(Equal(false)) // want "ginkgo-linter: wrong comparison assertion; consider using .Expect\\(x\\)\\.ToNot\\(BeNumerically\\(\"<\", 7\\)\\). instead" + + p1, p2 := &x, &x + Expect(p1 == p2).To(Equal(true)) // want "ginkgo-linter: wrong comparison assertion; consider using .Expect\\(p1\\).To\\(BeIdenticalTo\\(p2\\)\\). instead" +} + +func slowInt_nil() int { + time.Sleep(time.Second) + return 42 +} + +func WrongEventuallyWithFunction_nil() { + Eventually(slowInt_nil).Should(Equal(42)) // valid + Eventually(slowInt_nil()).Should(Equal(42)) // want "ginkgo-linter: use a function call in Eventually. This actually checks nothing, because Eventually receives the function returned value, instead of function itself, and this value is never changed; consider using .Eventually\\(slowInt_nil\\)\\.Should\\(Equal\\(42\\)\\). instead" +} + +var _ = FDescribe("Should warn for focused containers", func() { + FContext("should not allow FContext", func() { + FWhen("should not allow FWhen", func() { + FIt("should not allow FIt", func() {}) + }) + }) +}) diff --git a/test/testdata/ginkgolinter/go.mod b/test/testdata/ginkgolinter/go.mod index 48dca07b5779..41c050b148bb 100644 --- a/test/testdata/ginkgolinter/go.mod +++ b/test/testdata/ginkgolinter/go.mod @@ -2,11 +2,19 @@ module ginkgolinter go 1.19 -require github.com/onsi/gomega v1.24.1 +require ( + github.com/onsi/ginkgo/v2 v2.11.0 + github.com/onsi/gomega v1.27.8 +) require ( + github.com/go-logr/logr v1.2.4 // indirect + github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/google/go-cmp v0.5.9 // indirect - golang.org/x/net v0.2.0 // indirect - golang.org/x/text v0.4.0 // indirect + github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect + golang.org/x/net v0.10.0 // indirect + golang.org/x/sys v0.9.0 // indirect + golang.org/x/text v0.9.0 // indirect + golang.org/x/tools v0.9.3 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/test/testdata/ginkgolinter/go.sum b/test/testdata/ginkgolinter/go.sum index a3d1dba1a6c3..1237add6917f 100644 --- a/test/testdata/ginkgolinter/go.sum +++ b/test/testdata/ginkgolinter/go.sum @@ -1,15 +1,41 @@ -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +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/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/onsi/ginkgo/v2 v2.5.0 h1:TRtrvv2vdQqzkwrQ1ke6vtXf7IK34RBUJafIy1wMwls= -github.com/onsi/gomega v1.24.1 h1:KORJXNNTzJXzu4ScJWssJfJMnJ+2QJqhoQSRwNlze9E= -github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM= -golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A= -golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= +github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= +github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc= +github.com/onsi/gomega v1.27.8/go.mod h1:2J8vzI/s+2shY9XHRApDkdgPo1TKT7P2u6fXeJKFnNQ= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= +golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM= +golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= +google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/test/testdata/gochecknoglobals.go b/test/testdata/gochecknoglobals.go index 3da3a2a32a02..4d4a60cfc979 100644 --- a/test/testdata/gochecknoglobals.go +++ b/test/testdata/gochecknoglobals.go @@ -8,10 +8,10 @@ import ( ) var noGlobalsVar int // want "noGlobalsVar is a global variable" -var ErrSomeType = errors.New("test that global erorrs aren't warned") +var ErrSomeType = errors.New("test that global errors aren't warned") var ( - OnlyDigites = regexp.MustCompile(`^\d+$`) + OnlyDigits = regexp.MustCompile(`^\d+$`) BadNamedErr = errors.New("this is bad") // want "BadNamedErr is a global variable" ) diff --git a/test/testdata/gochecksumtype.go b/test/testdata/gochecksumtype.go new file mode 100644 index 000000000000..47ae3b9a90d1 --- /dev/null +++ b/test/testdata/gochecksumtype.go @@ -0,0 +1,38 @@ +//golangcitest:args -Egochecksumtype +package testdata + +import ( + "log" +) + +//sumtype:decl +type SumType interface{ isSumType() } + +//sumtype:decl +type One struct{} // want "type 'One' is not an interface" + +func (One) isSumType() {} + +type Two struct{} + +func (Two) isSumType() {} + +func sumTypeTest() { + var sum SumType = One{} + switch sum.(type) { // want "exhaustiveness check failed for sum type.*SumType.*missing cases for Two" + case One: + } + + switch sum.(type) { // want "exhaustiveness check failed for sum type.*SumType.*missing cases for Two" + case One: + default: + panic("??") + } + + log.Println("??") + + switch sum.(type) { + case One: + case Two: + } +} diff --git a/test/testdata/gocritic.go b/test/testdata/gocritic.go index afca6f3c479c..a87a193d075f 100644 --- a/test/testdata/gocritic.go +++ b/test/testdata/gocritic.go @@ -4,6 +4,7 @@ package testdata import ( "flag" + "io" "log" "strings" ) @@ -11,38 +12,61 @@ import ( var _ = *flag.Bool("global1", false, "") // want `flagDeref: immediate deref in \*flag.Bool\(.global1., false, ..\) is most likely an error; consider using flag\.BoolVar` type size1 struct { - a bool + a [12]bool } type size2 struct { size1 - b bool + b [12]bool } -func gocriticRangeValCopySize1(ss []size1) { - for _, s := range ss { - log.Print(s) +func gocriticAppendAssign() { + var positives, negatives []int + positives = append(negatives, 1) + negatives = append(negatives, -1) + log.Print(positives, negatives) +} + +func gocriticDupSubExpr(x bool) { + if x && x { // want "dupSubExpr: suspicious identical LHS and RHS.*" + log.Print("x is true") } } -func gocriticRangeValCopySize2(ss []size2) { - for _, s := range ss { // want "rangeValCopy: each iteration copies 2 bytes.*" - log.Print(s) +func gocriticHugeParamSize1(ss size1) { + log.Print(ss) +} + +func gocriticHugeParamSize2(ss size2) { // want "hugeParam: ss is heavy \\(24 bytes\\); consider passing it by pointer" + log.Print(ss) +} + +func gocriticHugeParamSize2Ptr(ss *size2) { + log.Print(*ss) +} + +func gocriticSwitchTrue() { + switch true { + case false: + log.Print("false") + default: + log.Print("default") } } +func goCriticPreferStringWriter(w interface { + io.Writer + io.StringWriter +}) { + w.Write([]byte("test")) // want "ruleguard: w\\.WriteString\\(\"test\"\\) should be preferred.*" +} + func gocriticStringSimplify() { s := "Most of the time, travellers worry about their luggage." s = strings.Replace(s, ",", "", -1) // want "ruleguard: this Replace call can be simplified.*" log.Print(s) } -func gocriticDup(x bool) { - if x && x { // want "ruleguard: suspicious identical LHS and RHS.*" - log.Print("x is true") - } -} - func gocriticRuleWrapperFunc() { strings.Replace("abcabc", "a", "d", -1) // want "ruleguard: this Replace call can be simplified.*" } diff --git a/test/testdata/goimports_local.go b/test/testdata/goimports_local.go index 8d9bd41b1f56..b89b4ded6045 100644 --- a/test/testdata/goimports_local.go +++ b/test/testdata/goimports_local.go @@ -6,11 +6,11 @@ import ( "fmt" "github.com/golangci/golangci-lint/pkg/config" // want "File is not `goimports`-ed with -local github.com/golangci/golangci-lint" - "github.com/pkg/errors" + "golang.org/x/tools/go/analysis" ) func GoimportsLocalPrefixTest() { fmt.Print("x") _ = config.Config{} - _ = errors.New("") + _ = analysis.Analyzer{} } diff --git a/test/testdata/golint.go b/test/testdata/golint.go deleted file mode 100644 index feb52f007fbb..000000000000 --- a/test/testdata/golint.go +++ /dev/null @@ -1,22 +0,0 @@ -//golangcitest:args -Egolint --internal-cmd-test -package testdata - -var Go_lint string // want "don't use underscores in Go names; var `Go_lint` should be `GoLint`" - -func ExportedFuncWithNoComment() { -} - -var ExportedVarWithNoComment string - -type ExportedStructWithNoComment struct{} - -type ExportedInterfaceWithNoComment interface{} - -// Bad comment -func ExportedFuncWithBadComment() {} - -type GolintTest struct{} - -func (receiver1 GolintTest) A() {} - -func (receiver2 GolintTest) B() {} // want "receiver name receiver2 should be consistent with previous receiver name receiver1 for GolintTest" diff --git a/test/testdata/gosec_global_option.go b/test/testdata/gosec_global_option.go new file mode 100644 index 000000000000..0a9407ea75de --- /dev/null +++ b/test/testdata/gosec_global_option.go @@ -0,0 +1,14 @@ +//golangcitest:args -Egosec +//golangcitest:config_path testdata/configs/gosec_global_option.yml +package testdata + +import ( + "crypto/md5" // want "G501: Blocklisted import crypto/md5: weak cryptographic primitive" + "log" +) + +func Gosec() { + // #nosec G401 + h := md5.New() // want "G401: Use of weak cryptographic primitive" + log.Print(h) +} diff --git a/test/testdata/gosmopolitan.go b/test/testdata/gosmopolitan.go new file mode 100644 index 000000000000..bdb1aa0a3fe5 --- /dev/null +++ b/test/testdata/gosmopolitan.go @@ -0,0 +1,25 @@ +//golangcitest:args -Egosmopolitan +package testdata + +import ( + "fmt" + "time" +) + +type col struct { + // struct tag should not get reported + Foo string `gorm:"column:bar;not null;comment:'不应该报告这一行'"` +} + +func main() { + fmt.Println("hello world") + fmt.Println("你好,世界") // want `string literal contains rune in Han script` + fmt.Println("こんにちは、セカイ") + + _ = col{Foo: "hello"} + _ = col{Foo: "你好"} // want `string literal contains rune in Han script` + + x := time.Local // want `usage of time.Local` + _ = time.Now().In(x) + _ = time.Date(2023, 1, 2, 3, 4, 5, 678901234, time.Local) // want `usage of time.Local` +} diff --git a/test/testdata/gosmopolitan_allow_time_local.go b/test/testdata/gosmopolitan_allow_time_local.go new file mode 100644 index 000000000000..e2380740c91d --- /dev/null +++ b/test/testdata/gosmopolitan_allow_time_local.go @@ -0,0 +1,12 @@ +//golangcitest:args -Egosmopolitan +//golangcitest:config_path testdata/configs/gosmopolitan_allow_time_local.yml +//golangcitest:expected_exitcode 0 +package testdata + +import ( + "time" +) + +func main() { + _ = time.Local +} diff --git a/test/testdata/gosmopolitan_dont_ignore_test.go b/test/testdata/gosmopolitan_dont_ignore_test.go new file mode 100644 index 000000000000..36bdc56bf4e1 --- /dev/null +++ b/test/testdata/gosmopolitan_dont_ignore_test.go @@ -0,0 +1,12 @@ +//golangcitest:args -Egosmopolitan +//golangcitest:config_path testdata/configs/gosmopolitan_dont_ignore_tests.yml +package testdata + +import ( + "time" +) + +func main() { + _ = "开启检查测试文件" // want `string literal contains rune in Han script` + _ = time.Local // want `usage of time.Local` +} diff --git a/test/testdata/gosmopolitan_escape_hatches.go b/test/testdata/gosmopolitan_escape_hatches.go new file mode 100644 index 000000000000..85b96be745f0 --- /dev/null +++ b/test/testdata/gosmopolitan_escape_hatches.go @@ -0,0 +1,38 @@ +//golangcitest:args -Egosmopolitan +//golangcitest:config_path testdata/configs/gosmopolitan_escape_hatches.yml +package testdata + +import ( + myAlias "fmt" +) + +type A string +type B = string +type C struct { + foo string + Bar string +} + +func D(fmt string) string { + myAlias.Println(fmt, "测试") + return myAlias.Sprintf("%s 测试", fmt) // want `string literal contains rune in Han script` +} + +type X struct { + baz string +} + +func main() { + _ = A("测试") + _ = string(A(string("测试"))) + _ = B("测试") + _ = C{ + foo: "测试", + Bar: "测试", + } + _ = D("测试") + + _ = &X{ + baz: "测试", // want `string literal contains rune in Han script` + } +} diff --git a/test/testdata/gosmopolitan_ignore_test.go b/test/testdata/gosmopolitan_ignore_test.go new file mode 100644 index 000000000000..6972c1359335 --- /dev/null +++ b/test/testdata/gosmopolitan_ignore_test.go @@ -0,0 +1,12 @@ +//golangcitest:args -Egosmopolitan +//golangcitest:expected_exitcode 0 +package testdata + +import ( + "time" +) + +func main() { + _ = "默认不检查测试文件" + _ = time.Local +} diff --git a/test/testdata/gosmopolitan_scripts.go b/test/testdata/gosmopolitan_scripts.go new file mode 100644 index 000000000000..04702991640f --- /dev/null +++ b/test/testdata/gosmopolitan_scripts.go @@ -0,0 +1,14 @@ +//golangcitest:args -Egosmopolitan +//golangcitest:config_path testdata/configs/gosmopolitan_scripts.yml +package testdata + +import ( + "fmt" +) + +func main() { + fmt.Println("hello world") // want `string literal contains rune in Latin script` + fmt.Println("should not report this line") //nolint:gosmopolitan + fmt.Println("你好,世界") + fmt.Println("こんにちは、セカイ") // want `string literal contains rune in Hiragana script` +} diff --git a/test/testdata/ifshort.go b/test/testdata/ifshort.go deleted file mode 100644 index 71906fa850b8..000000000000 --- a/test/testdata/ifshort.go +++ /dev/null @@ -1,13 +0,0 @@ -//go:build !windows - -//golangcitest:args -Eifshort --internal-cmd-test -package testdata - -func DontUseShortSyntaxWhenPossible() { - getValue := func() interface{} { return nil } - - v := getValue() // want "variable 'v' is only used in the if-statement .*" - if v != nil { - return - } -} diff --git a/test/testdata/importas.go b/test/testdata/importas.go index 20dfe1bcefb9..18a43c5e5bec 100644 --- a/test/testdata/importas.go +++ b/test/testdata/importas.go @@ -7,12 +7,12 @@ import ( "os" wrong_alias_again "os" // want `import "os" imported as "wrong_alias_again" but must be "std_os" according to config` - wrong "github.com/pkg/errors" // want `import "github.com/pkg/errors" imported as "wrong" but must be "pkgerr" according to config` + wrong "golang.org/x/tools/go/analysis" // want `import "golang.org/x/tools/go/analysis" imported as "wrong" but must be "ananas" according to config` ) func ImportAsWrongAlias() { wrong_alias.Println("foo") wrong_alias_again.Stdout.WriteString("bar") os.Stdout.WriteString("test") - _ = wrong.New("baz") + _ = wrong.Analyzer{} } diff --git a/test/testdata/importas_strict.go b/test/testdata/importas_strict.go index b381837c2743..76f7fefe5c9c 100644 --- a/test/testdata/importas_strict.go +++ b/test/testdata/importas_strict.go @@ -7,12 +7,12 @@ import ( "os" // want `import "os" imported without alias but must be with alias "std_os" according to config` wrong_alias_again "os" // want `import "os" imported as "wrong_alias_again" but must be "std_os" according to config` - wrong "github.com/pkg/errors" // want `import "github.com/pkg/errors" imported as "wrong" but must be "pkgerr" according to config` + wrong "golang.org/x/tools/go/analysis" // want `import "golang.org/x/tools/go/analysis" imported as "wrong" but must be "ananas" according to config` ) func ImportAsStrictWrongAlias() { wrong_alias.Println("foo") wrong_alias_again.Stdout.WriteString("bar") os.Stdout.WriteString("test") - _ = wrong.New("baz") + _ = wrong.Analyzer{} } diff --git a/test/testdata/inamedparam.go b/test/testdata/inamedparam.go new file mode 100644 index 000000000000..97d3cc2a98ac --- /dev/null +++ b/test/testdata/inamedparam.go @@ -0,0 +1,29 @@ +//golangcitest:args -Einamedparam +package testdata + +import "context" + +type tStruct struct { + a int +} + +type Doer interface { + Do() string +} + +type NamedParam interface { + Void() + + NoArgs() string + + WithName(ctx context.Context, number int, toggle bool, tStruct *tStruct, doer Doer) (bool, error) + + WithoutName( + context.Context, // want "interface method WithoutName must have named param for type context.Context" + int, // want "interface method WithoutName must have named param for type int" + bool, // want "interface method WithoutName must have named param for type bool" + tStruct, // want "interface method WithoutName must have named param for type tStruct" + Doer, // want "interface method WithoutName must have named param for type Doer" + struct{ b bool }, // want "interface method WithoutName must have all named params" + ) +} diff --git a/test/testdata/inamedparam_skip_single_param.go b/test/testdata/inamedparam_skip_single_param.go new file mode 100644 index 000000000000..3475f95b7232 --- /dev/null +++ b/test/testdata/inamedparam_skip_single_param.go @@ -0,0 +1,18 @@ +//golangcitest:args -Einamedparam +//golangcitest:config_path testdata/configs/inamedparam_skip_single_param.yml +package testdata + +import "context" + +type NamedParam interface { + Void() + + SingleParam(string) error + + WithName(ctx context.Context, number int, toggle bool) (bool, error) + + WithoutName( + context.Context, // want "interface method WithoutName must have named param for type context.Context" + int, // want "interface method WithoutName must have named param for type int" + ) +} diff --git a/test/testdata/interfacer.go b/test/testdata/interfacer.go deleted file mode 100644 index 59e64e35656c..000000000000 --- a/test/testdata/interfacer.go +++ /dev/null @@ -1,8 +0,0 @@ -//golangcitest:args -Einterfacer --internal-cmd-test -package testdata - -import "io" - -func InterfacerCheck(f io.ReadCloser) { // want "`f` can be `io.Closer`" - f.Close() -} diff --git a/test/testdata/intrange.go b/test/testdata/intrange.go new file mode 100644 index 000000000000..2220d9618fdf --- /dev/null +++ b/test/testdata/intrange.go @@ -0,0 +1,21 @@ +//go:build go1.22 + +//golangcitest:args -Eintrange +package testdata + +import "math" + +func CheckIntrange() { + for i := 0; i < 10; i++ { // want `for loop can be changed to use an integer range \(Go 1\.22\+\)` + } + + for i := uint8(0); i < math.MaxInt8; i++ { // want `for loop can be changed to use an integer range \(Go 1\.22\+\)` + } + + for i := 0; i < 10; i += 2 { + } + + for i := 0; i < 10; i++ { + i += 1 + } +} diff --git a/test/testdata/ireturn_reject_generics.go b/test/testdata/ireturn_reject_generics.go new file mode 100644 index 000000000000..ea5be6884c7d --- /dev/null +++ b/test/testdata/ireturn_reject_generics.go @@ -0,0 +1,25 @@ +//golangcitest:args -Eireturn +//golangcitest:config_path testdata/configs/ireturn_reject_generics.yml +package testdata + +import ( + "bytes" + "io" +) + +func NewWriter() io.Writer { + var buf bytes.Buffer + return &buf +} + +func TestError() error { + return nil +} + +func Get[K comparable, V int64 | float64](m map[K]V) V { // want `Get returns generic interface \(V\)` + var s V + for _, v := range m { + s += v + } + return s +} diff --git a/test/testdata/ireturn_reject_stdlib.go b/test/testdata/ireturn_reject_stdlib.go index 8f09e785cf68..3c935b855b7e 100644 --- a/test/testdata/ireturn_reject_stdlib.go +++ b/test/testdata/ireturn_reject_stdlib.go @@ -1,5 +1,5 @@ //golangcitest:args -Eireturn -//golangcitest:config_path testdata/configs/ireturn_stdlib_reject.yml +//golangcitest:config_path testdata/configs/ireturn_reject_stdlib.yml package testdata import ( diff --git a/test/testdata/linedirective/gomodguard.yml b/test/testdata/linedirective/gomodguard.yml index 6e1b0ef81c0c..e6f4125ba952 100644 --- a/test/testdata/linedirective/gomodguard.yml +++ b/test/testdata/linedirective/gomodguard.yml @@ -2,4 +2,4 @@ linters-settings: gomodguard: allowed: domains: - - golang.org + - github.com diff --git a/test/testdata/linedirective/hello.go b/test/testdata/linedirective/hello.go index c511f8b51ecc..b4699f7ab98d 100644 --- a/test/testdata/linedirective/hello.go +++ b/test/testdata/linedirective/hello.go @@ -3,7 +3,7 @@ package main import ( - "github.com/ryancurrah/gomodguard" + "golang.org/x/tools/go/analysis" ) func _() { @@ -26,6 +26,10 @@ func b() { fmt.Println("foo") } +func c(){ + _ = analysis.Analyzer{} +} + func wsl() bool { return true diff --git a/test/testdata/lll.go b/test/testdata/lll.go index 001da2e3dcb3..89a143ab5f9a 100644 --- a/test/testdata/lll.go +++ b/test/testdata/lll.go @@ -2,6 +2,19 @@ //golangcitest:config_path testdata/configs/lll.yml package testdata +import ( + _ "unsafe" +) + func Lll() { // In my experience, long lines are the lines with comments, not the code. So this is a long comment // want "line is 137 characters" } + +//go:generate mockgen -source lll.go -destination a_verylong_generate_mock_my_lll_interface.go --package testdata -self_package github.com/golangci/golangci-lint/test/testdata +type MyLllInterface interface { +} + +//go:linkname VeryLongNameForTestAndLinkNameFunction github.com/golangci/golangci-lint/test/testdata.VeryLongNameForTestAndLinkedNameFunction +func VeryLongNameForTestAndLinkNameFunction() + +func VeryLongNameForTestAndLinkedNameFunction() {} diff --git a/test/testdata/maligned.go b/test/testdata/maligned.go deleted file mode 100644 index 553fd53ac656..000000000000 --- a/test/testdata/maligned.go +++ /dev/null @@ -1,8 +0,0 @@ -//golangcitest:args -Emaligned --internal-cmd-test -package testdata - -type BadAlignedStruct struct { // want "struct of size 24 bytes could be of size 16 bytes" - B bool - I int - B2 bool -} diff --git a/test/testdata/mirror.go b/test/testdata/mirror.go new file mode 100644 index 000000000000..92967aea47b7 --- /dev/null +++ b/test/testdata/mirror.go @@ -0,0 +1,12 @@ +//golangcitest:args -Emirror +package testdata + +import ( + "strings" + "unicode/utf8" +) + +func foobar() { + _ = utf8.RuneCount([]byte("foobar")) // want `avoid allocations with utf8\.RuneCountInString` + _ = strings.Compare(string([]byte{'f', 'o', 'o', 'b', 'a', 'r'}), string([]byte{'f', 'o', 'o', 'b', 'a', 'r'})) // want `avoid allocations with bytes\.Compare` +} diff --git a/test/testdata/misspell.go b/test/testdata/misspell.go index a866f117a37f..7646066e9b7e 100644 --- a/test/testdata/misspell.go +++ b/test/testdata/misspell.go @@ -7,3 +7,4 @@ func Misspell() { } // the word langauge should be ignored here: it's set in config +// the word Dialogue should be ignored here: it's set in config diff --git a/test/testdata/misspell_custom.go b/test/testdata/misspell_custom.go new file mode 100644 index 000000000000..32362fb636a1 --- /dev/null +++ b/test/testdata/misspell_custom.go @@ -0,0 +1,10 @@ +//golangcitest:args -Emisspell +//golangcitest:config_path testdata/configs/misspell_custom.yml +package testdata + +func Misspell() { + // comment with incorrect spelling: occured // want "`occured` is a misspelling of `occurred`" +} + +// the word iff should be reported here // want "\\`iff\\` is a misspelling of \\`if\\`" +// the word cancelation should be reported here // want "\\`cancelation\\` is a misspelling of \\`cancellation\\`" diff --git a/test/testdata/musttag.go b/test/testdata/musttag.go index daf84298fee0..d9ed7d9bfd12 100644 --- a/test/testdata/musttag.go +++ b/test/testdata/musttag.go @@ -8,12 +8,11 @@ import ( // builtin functions: func musttagJSON() { - var user struct { // want `exported fields should be annotated with the "json" tag` + var user struct { Name string Email string `json:"email"` } - json.Marshal(user) - json.Unmarshal(nil, &user) + json.Marshal(user) // want "the given struct should be annotated with the `json` tag" } // custom functions from config: @@ -23,5 +22,4 @@ func musttagASN1() { Email string `asn1:"email"` } asn1.Marshal(user) - asn1.Unmarshal(nil, &user) } diff --git a/test/testdata/musttag_custom.go b/test/testdata/musttag_custom.go index 42bdea3fb511..0e6f820252b9 100644 --- a/test/testdata/musttag_custom.go +++ b/test/testdata/musttag_custom.go @@ -9,20 +9,18 @@ import ( // builtin functions: func musttagJSONCustom() { - var user struct { // want `exported fields should be annotated with the "json" tag` + var user struct { Name string Email string `json:"email"` } - json.Marshal(user) - json.Unmarshal(nil, &user) + json.Marshal(user) // want "the given struct should be annotated with the `json` tag" } // custom functions from config: func musttagASN1Custom() { - var user struct { // want `exported fields should be annotated with the "asn1" tag` + var user struct { Name string Email string `asn1:"email"` } - asn1.Marshal(user) - asn1.Unmarshal(nil, &user) + asn1.Marshal(user) // want "the given struct should be annotated with the `asn1` tag" } diff --git a/test/testdata/nakedret.go b/test/testdata/nakedret.go index fc9e90432e2a..b1230a95bd71 100644 --- a/test/testdata/nakedret.go +++ b/test/testdata/nakedret.go @@ -1,11 +1,15 @@ //golangcitest:args -Enakedret package testdata +import "fmt" + func NakedretIssue() (a int, b string) { if a > 0 { - return + return // want "naked return in func `NakedretIssue` with 33 lines of code" } + fmt.Println("nakedret") + if b == "" { return 0, "0" } @@ -30,8 +34,8 @@ func NakedretIssue() (a int, b string) { // ... // ... - // len of this function is 31 - return // want "naked return in func `NakedretIssue` with 31 lines of code" + // len of this function is 33 + return // want "naked return in func `NakedretIssue` with 33 lines of code" } func NoNakedretIssue() (a int, b string) { diff --git a/test/testdata/nonamedreturns_custom.go b/test/testdata/nonamedreturns_custom.go index 9040e313cf74..b42927086be6 100644 --- a/test/testdata/nonamedreturns_custom.go +++ b/test/testdata/nonamedreturns_custom.go @@ -56,21 +56,21 @@ var ( ) // this should not match as the implementation does not need named parameters (see below) -type funcDefintion func(arg1, arg2 interface{}) (num int, err error) +type funcDefinition func(arg1, arg2 interface{}) (num int, err error) -func funcDefintionImpl(arg1, arg2 interface{}) (int, error) { +func funcDefinitionImpl(arg1, arg2 interface{}) (int, error) { return 0, nil } -func funcDefintionImpl2(arg1, arg2 interface{}) (num int, err error) { // want `named return "num" with type "int" found` +func funcDefinitionImpl2(arg1, arg2 interface{}) (num int, err error) { // want `named return "num" with type "int" found` return 0, nil } -func funcDefintionImpl3(arg1, arg2 interface{}) (num int, _ error) { // want `named return "num" with type "int" found` +func funcDefinitionImpl3(arg1, arg2 interface{}) (num int, _ error) { // want `named return "num" with type "int" found` return 0, nil } -func funcDefintionImpl4(arg1, arg2 interface{}) (_ int, _ error) { +func funcDefinitionImpl4(arg1, arg2 interface{}) (_ int, _ error) { return 0, nil } @@ -88,12 +88,12 @@ func test() { a := funcVar() _ = a - var function funcDefintion - function = funcDefintionImpl + var function funcDefinition + function = funcDefinitionImpl i, err := function("", "") _ = i _ = err - function = funcDefintionImpl2 + function = funcDefinitionImpl2 i, err = function("", "") _ = i _ = err diff --git a/test/testdata/nosnakecase.go b/test/testdata/nosnakecase.go deleted file mode 100644 index 5a0d207337af..000000000000 --- a/test/testdata/nosnakecase.go +++ /dev/null @@ -1,149 +0,0 @@ -//golangcitest:args -Enosnakecase --internal-cmd-test -package testdata - -import ( - _ "fmt" - f_m_t "fmt" // want "f_m_t contains underscore. You should use mixedCap or MixedCap." -) - -// global variable name with underscore. -var v_v = 0 // want "v_v contains underscore. You should use mixedCap or MixedCap." - -// global constant name with underscore. -const c_c = 0 // want "c_c contains underscore. You should use mixedCap or MixedCap." - -// struct name with underscore. -type S_a struct { // want "S_a contains underscore. You should use mixedCap or MixedCap." - fi int -} - -// non-exported struct field name with underscore. -type Sa struct { - fi_a int // // want "fi_a contains underscore. You should use mixedCap or MixedCap." -} - -// function as struct field, with parameter name with underscore. -type Sb struct { - fib func(p_a int) // want "p_a contains underscore. You should use mixedCap or MixedCap." -} - -// exported struct field with underscore. -type Sc struct { - Fi_A int // want "Fi_A contains underscore. You should use mixedCap or MixedCap." -} - -// function as struct field, with return name with underscore. -type Sd struct { - fib func(p int) (r_a int) // want "r_a contains underscore. You should use mixedCap or MixedCap." -} - -// interface name with underscore. -type I_a interface { // want "I_a contains underscore. You should use mixedCap or MixedCap." - fn(p int) -} - -// interface with parameter name with underscore. -type Ia interface { - fn(p_a int) // want "p_a contains underscore. You should use mixedCap or MixedCap." -} - -// interface with parameter name with underscore. -type Ib interface { - Fn(p_a int) // want "p_a contains underscore. You should use mixedCap or MixedCap." -} - -// function as struct field, with return name with underscore. -type Ic interface { - Fn_a() // want "Fn_a contains underscore. You should use mixedCap or MixedCap." -} - -// interface with return name with underscore. -type Id interface { - Fn() (r_a int) // want "r_a contains underscore. You should use mixedCap or MixedCap." -} - -// function name with underscore. -func f_a() {} // want "f_a contains underscore. You should use mixedCap or MixedCap." - -// function's parameter name with underscore. -func fb(p_a int) {} // want "p_a contains underscore. You should use mixedCap or MixedCap." - -// named return with underscore. -func fc() (r_b int) { // want "r_b contains underscore. You should use mixedCap or MixedCap." - return 0 -} - -// local variable (short declaration) with underscore. -func fd(p int) int { - v_b := p * 2 // want "v_b contains underscore. You should use mixedCap or MixedCap." - - return v_b // want "v_b contains underscore. You should use mixedCap or MixedCap." -} - -// local constant with underscore. -func fe(p int) int { - const v_b = 2 // want "v_b contains underscore. You should use mixedCap or MixedCap." - - return v_b * p // want "v_b contains underscore. You should use mixedCap or MixedCap." -} - -// local variable with underscore. -func ff(p int) int { - var v_b = 2 // want "v_b contains underscore. You should use mixedCap or MixedCap." - - return v_b * p // want "v_b contains underscore. You should use mixedCap or MixedCap." -} - -// inner function, parameter name with underscore. -func fg() { - fgl := func(p_a int) {} // want "p_a contains underscore. You should use mixedCap or MixedCap." - fgl(1) -} - -type Foo struct{} - -// method name with underscore. -func (f Foo) f_a() {} // want "f_a contains underscore. You should use mixedCap or MixedCap." - -// method's parameter name with underscore. -func (f Foo) fb(p_a int) {} // want "p_a contains underscore. You should use mixedCap or MixedCap." - -// named return with underscore. -func (f Foo) fc() (r_b int) { return 0 } // want "r_b contains underscore. You should use mixedCap or MixedCap." - -// local variable (short declaration) with underscore. -func (f Foo) fd(p int) int { - v_b := p * 2 // want "v_b contains underscore. You should use mixedCap or MixedCap." - - return v_b // want "v_b contains underscore. You should use mixedCap or MixedCap." -} - -// local constant with underscore. -func (f Foo) fe(p int) int { - const v_b = 2 // want "v_b contains underscore. You should use mixedCap or MixedCap." - - return v_b * p // want "v_b contains underscore. You should use mixedCap or MixedCap." -} - -// local variable with underscore. -func (f Foo) ff(p int) int { - var v_b = 2 // want "v_b contains underscore. You should use mixedCap or MixedCap." - - return v_b * p // want "v_b contains underscore. You should use mixedCap or MixedCap." -} - -func fna(a, p_a int) {} // want "p_a contains underscore. You should use mixedCap or MixedCap." - -func fna1(a string, p_a int) {} // want "p_a contains underscore. You should use mixedCap or MixedCap." - -func fnb(a, b, p_a int) {} // want "p_a contains underscore. You should use mixedCap or MixedCap." - -func fnb1(a, b string, p_a int) {} // want "p_a contains underscore. You should use mixedCap or MixedCap." - -func fnd( - p_a int, // want "p_a contains underscore. You should use mixedCap or MixedCap." - p_b int, // want "p_b contains underscore. You should use mixedCap or MixedCap." - p_c int, // want "p_c contains underscore. You should use mixedCap or MixedCap." -) { - f_m_t.Println("") // want "f_m_t contains underscore. You should use mixedCap or MixedCap." -} diff --git a/test/testdata/path_except.go b/test/testdata/path_except.go new file mode 100644 index 000000000000..ab7b33a09c00 --- /dev/null +++ b/test/testdata/path_except.go @@ -0,0 +1,14 @@ +//golangcitest:args -Eforbidigo +//golangcitest:config_path testdata/configs/path-except.yml +//golangcitest:expected_exitcode 0 +package testdata + +import ( + "fmt" + "time" +) + +func Forbidigo() { + fmt.Printf("too noisy!!!") + time.Sleep(time.Nanosecond) +} diff --git a/test/testdata/path_except_test.go b/test/testdata/path_except_test.go new file mode 100644 index 000000000000..5f69f87a58e7 --- /dev/null +++ b/test/testdata/path_except_test.go @@ -0,0 +1,14 @@ +//golangcitest:args -Eforbidigo +//golangcitest:config_path testdata/configs/path-except.yml +package testdata + +import ( + "fmt" + "testing" + "time" +) + +func TestForbidigo(t *testing.T) { + fmt.Printf("too noisy!!!") // want "use of `fmt\\.Printf` forbidden by pattern `fmt\\\\.Print\\.\\*`" + time.Sleep(time.Nanosecond) // want "no sleeping!" +} diff --git a/test/testdata/perfsprint.go b/test/testdata/perfsprint.go new file mode 100644 index 000000000000..ca2ae1db3124 --- /dev/null +++ b/test/testdata/perfsprint.go @@ -0,0 +1,53 @@ +//golangcitest:args -Eperfsprint +package testdata + +import ( + "fmt" +) + +func TestPerfsprint() { + var ( + s string + err error + b bool + i int + i64 int64 + ui uint + ) + + fmt.Sprintf("%s", s) // want "fmt.Sprintf can be replaced with just using the string" + fmt.Sprint(s) // want "fmt.Sprint can be replaced with just using the string" + fmt.Sprintf("%s", err) + fmt.Sprint(err) + fmt.Sprintf("%t", b) // want "fmt.Sprintf can be replaced with faster strconv.FormatBool" + fmt.Sprint(b) // want "fmt.Sprint can be replaced with faster strconv.FormatBool" + fmt.Sprintf("%d", i) // want "fmt.Sprintf can be replaced with faster strconv.Itoa" + fmt.Sprint(i) // want "fmt.Sprint can be replaced with faster strconv.Itoa" + fmt.Sprintf("%d", i64) // want "fmt.Sprintf can be replaced with faster strconv.FormatInt" + fmt.Sprint(i64) // want "fmt.Sprint can be replaced with faster strconv.FormatInt" + fmt.Sprintf("%d", ui) // want "fmt.Sprintf can be replaced with faster strconv.FormatUint" + fmt.Sprint(ui) // want "fmt.Sprint can be replaced with faster strconv.FormatUint" + fmt.Sprintf("%x", []byte{'a'}) // want "fmt.Sprintf can be replaced with faster hex.EncodeToString" + fmt.Errorf("hello") // want "fmt.Errorf can be replaced with errors.New" + fmt.Sprintf("Hello %s", s) // want "fmt.Sprintf can be replaced with string concatenation" + + fmt.Sprint("test", 42) + fmt.Sprint(42, 42) + fmt.Sprintf("test") // want "fmt.Sprintf can be replaced with just using the string" + fmt.Sprintf("%v") // want "fmt.Sprintf can be replaced with just using the string" + fmt.Sprintf("%d") // want "fmt.Sprintf can be replaced with just using the string" + fmt.Sprintf("%d", 42, 42) + fmt.Sprintf("%#d", 42) + fmt.Sprintf("value %d", 42) + fmt.Sprintf("val%d", 42) + fmt.Sprintf("%s %v", "hello", "world") + fmt.Sprintf("%#v", 42) + fmt.Sprintf("%T", struct{ string }{}) + fmt.Sprintf("%%v", 42) + fmt.Sprintf("%3d", 42) + fmt.Sprintf("% d", 42) + fmt.Sprintf("%-10d", 42) + fmt.Sprintf("%[2]d %[1]d\n", 11, 22) + fmt.Sprintf("%[3]*.[2]*[1]f", 12.0, 2, 6) + fmt.Sprintf("%d %d %#[1]x %#x", 16, 17) +} diff --git a/test/testdata/perfsprint_custom.go b/test/testdata/perfsprint_custom.go new file mode 100644 index 000000000000..04de585b7eff --- /dev/null +++ b/test/testdata/perfsprint_custom.go @@ -0,0 +1,54 @@ +//golangcitest:args -Eperfsprint +//golangcitest:config_path testdata/configs/perfsprint_custom.yml +package testdata + +import ( + "fmt" +) + +func TestPerfsprint2() { + var ( + s string + err error + b bool + i int + i64 int64 + ui uint + ) + + fmt.Sprintf("%s", s) // want "fmt.Sprintf can be replaced with just using the string" + fmt.Sprint(s) // want "fmt.Sprint can be replaced with just using the string" + fmt.Sprintf("%s", err) // want "fmt.Sprintf can be replaced with err.Error()" + fmt.Sprint(err) // want "fmt.Sprint can be replaced with err.Error()" + fmt.Sprintf("%t", b) // want "fmt.Sprintf can be replaced with faster strconv.FormatBool" + fmt.Sprint(b) // want "fmt.Sprint can be replaced with faster strconv.FormatBool" + fmt.Sprintf("%d", i) // want "fmt.Sprintf can be replaced with faster strconv.Itoa" + fmt.Sprint(i) // want "fmt.Sprint can be replaced with faster strconv.Itoa" + fmt.Sprintf("%d", i64) // want "fmt.Sprintf can be replaced with faster strconv.FormatInt" + fmt.Sprint(i64) // want "fmt.Sprint can be replaced with faster strconv.FormatInt" + fmt.Sprintf("%d", ui) + fmt.Sprint(ui) + fmt.Sprintf("%x", []byte{'a'}) // want "fmt.Sprintf can be replaced with faster hex.EncodeToString" + fmt.Errorf("hello") + fmt.Sprintf("Hello %s", s) // want "fmt.Sprintf can be replaced with string concatenation" + + fmt.Sprint("test", 42) + fmt.Sprint(42, 42) + fmt.Sprintf("test") + fmt.Sprintf("%v") + fmt.Sprintf("%d") + fmt.Sprintf("%d", 42, 42) + fmt.Sprintf("%#d", 42) + fmt.Sprintf("value %d", 42) + fmt.Sprintf("val%d", 42) + fmt.Sprintf("%s %v", "hello", "world") + fmt.Sprintf("%#v", 42) + fmt.Sprintf("%T", struct{ string }{}) + fmt.Sprintf("%%v", 42) + fmt.Sprintf("%3d", 42) + fmt.Sprintf("% d", 42) + fmt.Sprintf("%-10d", 42) + fmt.Sprintf("%[2]d %[1]d\n", 11, 22) + fmt.Sprintf("%[3]*.[2]*[1]f", 12.0, 2, 6) + fmt.Sprintf("%d %d %#[1]x %#x", 16, 17) +} diff --git a/test/testdata/protogetter/go.mod b/test/testdata/protogetter/go.mod new file mode 100644 index 000000000000..6120ad190c30 --- /dev/null +++ b/test/testdata/protogetter/go.mod @@ -0,0 +1,16 @@ +module protogetter + +go 1.19 + +require ( + google.golang.org/grpc v1.57.0 + google.golang.org/protobuf v1.31.0 +) + +require ( + github.com/golang/protobuf v1.5.3 // indirect + golang.org/x/net v0.9.0 // indirect + golang.org/x/sys v0.7.0 // indirect + golang.org/x/text v0.9.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 // indirect +) diff --git a/test/testdata/protogetter/go.sum b/test/testdata/protogetter/go.sum new file mode 100644 index 000000000000..820c8ebcdca8 --- /dev/null +++ b/test/testdata/protogetter/go.sum @@ -0,0 +1,20 @@ +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +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.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 h1:0nDDozoAU19Qb2HwhXadU8OcsiO/09cnTqhUtq2MEOM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= +google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= +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= diff --git a/test/testdata/protogetter/proto/test.go b/test/testdata/protogetter/proto/test.go new file mode 100644 index 000000000000..e48a033c009f --- /dev/null +++ b/test/testdata/protogetter/proto/test.go @@ -0,0 +1,23 @@ +package proto + +func (x *Embedded) CustomMethod() interface{} { + return nil +} + +type Other struct { +} + +func (x *Other) MyMethod(certs *Test) *Embedded { + return nil +} + +func (x *Test) Equal(v *Test) bool { + return false +} + +func (x *Embedded) SetS(s string) { + x.S = s +} + +func (x *Embedded) SetMap(_ map[string]string) { +} diff --git a/test/testdata/protogetter/proto/test.pb.go b/test/testdata/protogetter/proto/test.pb.go new file mode 100644 index 000000000000..64e7b6a37f4e --- /dev/null +++ b/test/testdata/protogetter/proto/test.pb.go @@ -0,0 +1,315 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.31.0 +// protoc v4.23.4 +// source: test.proto + +package proto + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Test struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + D float64 `protobuf:"fixed64,1,opt,name=d,proto3" json:"d,omitempty"` + F float32 `protobuf:"fixed32,2,opt,name=f,proto3" json:"f,omitempty"` + I32 int32 `protobuf:"varint,3,opt,name=i32,proto3" json:"i32,omitempty"` + I64 int64 `protobuf:"varint,4,opt,name=i64,proto3" json:"i64,omitempty"` + U32 uint32 `protobuf:"varint,5,opt,name=u32,proto3" json:"u32,omitempty"` + U64 uint64 `protobuf:"varint,6,opt,name=u64,proto3" json:"u64,omitempty"` + T bool `protobuf:"varint,7,opt,name=t,proto3" json:"t,omitempty"` + B []byte `protobuf:"bytes,8,opt,name=b,proto3" json:"b,omitempty"` + S string `protobuf:"bytes,9,opt,name=s,proto3" json:"s,omitempty"` + Embedded *Embedded `protobuf:"bytes,10,opt,name=embedded,proto3" json:"embedded,omitempty"` + RepeatedEmbeddeds []*Embedded `protobuf:"bytes,11,rep,name=repeated_embeddeds,json=repeatedEmbeddeds,proto3" json:"repeated_embeddeds,omitempty"` +} + +func (x *Test) Reset() { + *x = Test{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Test) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Test) ProtoMessage() {} + +func (x *Test) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Test.ProtoReflect.Descriptor instead. +func (*Test) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{0} +} + +func (x *Test) GetD() float64 { + if x != nil { + return x.D + } + return 0 +} + +func (x *Test) GetF() float32 { + if x != nil { + return x.F + } + return 0 +} + +func (x *Test) GetI32() int32 { + if x != nil { + return x.I32 + } + return 0 +} + +func (x *Test) GetI64() int64 { + if x != nil { + return x.I64 + } + return 0 +} + +func (x *Test) GetU32() uint32 { + if x != nil { + return x.U32 + } + return 0 +} + +func (x *Test) GetU64() uint64 { + if x != nil { + return x.U64 + } + return 0 +} + +func (x *Test) GetT() bool { + if x != nil { + return x.T + } + return false +} + +func (x *Test) GetB() []byte { + if x != nil { + return x.B + } + return nil +} + +func (x *Test) GetS() string { + if x != nil { + return x.S + } + return "" +} + +func (x *Test) GetEmbedded() *Embedded { + if x != nil { + return x.Embedded + } + return nil +} + +func (x *Test) GetRepeatedEmbeddeds() []*Embedded { + if x != nil { + return x.RepeatedEmbeddeds + } + return nil +} + +type Embedded struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + S string `protobuf:"bytes,1,opt,name=s,proto3" json:"s,omitempty"` + Embedded *Embedded `protobuf:"bytes,2,opt,name=embedded,proto3" json:"embedded,omitempty"` +} + +func (x *Embedded) Reset() { + *x = Embedded{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Embedded) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Embedded) ProtoMessage() {} + +func (x *Embedded) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Embedded.ProtoReflect.Descriptor instead. +func (*Embedded) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{1} +} + +func (x *Embedded) GetS() string { + if x != nil { + return x.S + } + return "" +} + +func (x *Embedded) GetEmbedded() *Embedded { + if x != nil { + return x.Embedded + } + return nil +} + +var File_test_proto protoreflect.FileDescriptor + +var file_test_proto_rawDesc = []byte{ + 0x0a, 0x0a, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf5, 0x01, 0x0a, + 0x04, 0x54, 0x65, 0x73, 0x74, 0x12, 0x0c, 0x0a, 0x01, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, + 0x52, 0x01, 0x64, 0x12, 0x0c, 0x0a, 0x01, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x02, 0x52, 0x01, + 0x66, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x33, 0x32, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, + 0x69, 0x33, 0x32, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x36, 0x34, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x03, 0x69, 0x36, 0x34, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x33, 0x32, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x03, 0x75, 0x33, 0x32, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x36, 0x34, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x75, 0x36, 0x34, 0x12, 0x0c, 0x0a, 0x01, 0x74, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x01, 0x74, 0x12, 0x0c, 0x0a, 0x01, 0x62, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x01, 0x62, 0x12, 0x0c, 0x0a, 0x01, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x01, 0x73, 0x12, 0x25, 0x0a, 0x08, 0x65, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x18, + 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x45, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, + 0x52, 0x08, 0x65, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x12, 0x38, 0x0a, 0x12, 0x72, 0x65, + 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x65, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x73, + 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x45, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, + 0x64, 0x52, 0x11, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x45, 0x6d, 0x62, 0x65, 0x64, + 0x64, 0x65, 0x64, 0x73, 0x22, 0x3f, 0x0a, 0x08, 0x45, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, + 0x12, 0x0c, 0x0a, 0x01, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x01, 0x73, 0x12, 0x25, + 0x0a, 0x08, 0x65, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x09, 0x2e, 0x45, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x52, 0x08, 0x65, 0x6d, 0x62, + 0x65, 0x64, 0x64, 0x65, 0x64, 0x32, 0x1f, 0x0a, 0x07, 0x54, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, + 0x12, 0x14, 0x0a, 0x04, 0x63, 0x61, 0x6c, 0x6c, 0x12, 0x05, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x1a, + 0x05, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x68, 0x6f, 0x73, 0x74, 0x69, 0x61, 0x6d, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x67, 0x65, 0x74, 0x74, 0x65, 0x72, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x64, 0x61, + 0x74, 0x61, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_test_proto_rawDescOnce sync.Once + file_test_proto_rawDescData = file_test_proto_rawDesc +) + +func file_test_proto_rawDescGZIP() []byte { + file_test_proto_rawDescOnce.Do(func() { + file_test_proto_rawDescData = protoimpl.X.CompressGZIP(file_test_proto_rawDescData) + }) + return file_test_proto_rawDescData +} + +var file_test_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_test_proto_goTypes = []interface{}{ + (*Test)(nil), // 0: Test + (*Embedded)(nil), // 1: Embedded +} +var file_test_proto_depIdxs = []int32{ + 1, // 0: Test.embedded:type_name -> Embedded + 1, // 1: Test.repeated_embeddeds:type_name -> Embedded + 1, // 2: Embedded.embedded:type_name -> Embedded + 0, // 3: Testing.call:input_type -> Test + 0, // 4: Testing.call:output_type -> Test + 4, // [4:5] is the sub-list for method output_type + 3, // [3:4] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name +} + +func init() { file_test_proto_init() } +func file_test_proto_init() { + if File_test_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_test_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Test); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Embedded); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_test_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_test_proto_goTypes, + DependencyIndexes: file_test_proto_depIdxs, + MessageInfos: file_test_proto_msgTypes, + }.Build() + File_test_proto = out.File + file_test_proto_rawDesc = nil + file_test_proto_goTypes = nil + file_test_proto_depIdxs = nil +} diff --git a/test/testdata/protogetter/proto/test.proto b/test/testdata/protogetter/proto/test.proto new file mode 100644 index 000000000000..83a536a8ba45 --- /dev/null +++ b/test/testdata/protogetter/proto/test.proto @@ -0,0 +1,26 @@ +syntax = "proto3"; + +option go_package = "github.com/ghostiam/protogetter/testdata/proto"; + +message Test { + double d = 1; + float f = 2; + int32 i32 = 3; + int64 i64 = 4; + uint32 u32 = 5; + uint64 u64 = 6; + bool t = 7; + bytes b = 8; + string s = 9; + Embedded embedded = 10; + repeated Embedded repeated_embeddeds = 11; +} + +message Embedded { + string s = 1; + Embedded embedded = 2; +} + +service Testing { + rpc call(Test) returns (Test); +} diff --git a/test/testdata/protogetter/proto/test_grpc.pb.go b/test/testdata/protogetter/proto/test_grpc.pb.go new file mode 100644 index 000000000000..e4500fd6b4f5 --- /dev/null +++ b/test/testdata/protogetter/proto/test_grpc.pb.go @@ -0,0 +1,109 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.3.0 +// - protoc v4.23.4 +// source: test.proto + +package proto + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +const ( + Testing_Call_FullMethodName = "/Testing/call" +) + +// TestingClient is the client API for Testing service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type TestingClient interface { + Call(ctx context.Context, in *Test, opts ...grpc.CallOption) (*Test, error) +} + +type testingClient struct { + cc grpc.ClientConnInterface +} + +func NewTestingClient(cc grpc.ClientConnInterface) TestingClient { + return &testingClient{cc} +} + +func (c *testingClient) Call(ctx context.Context, in *Test, opts ...grpc.CallOption) (*Test, error) { + out := new(Test) + err := c.cc.Invoke(ctx, Testing_Call_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// TestingServer is the server API for Testing service. +// All implementations must embed UnimplementedTestingServer +// for forward compatibility +type TestingServer interface { + Call(context.Context, *Test) (*Test, error) + mustEmbedUnimplementedTestingServer() +} + +// UnimplementedTestingServer must be embedded to have forward compatible implementations. +type UnimplementedTestingServer struct { +} + +func (UnimplementedTestingServer) Call(context.Context, *Test) (*Test, error) { + return nil, status.Errorf(codes.Unimplemented, "method Call not implemented") +} +func (UnimplementedTestingServer) mustEmbedUnimplementedTestingServer() {} + +// UnsafeTestingServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to TestingServer will +// result in compilation errors. +type UnsafeTestingServer interface { + mustEmbedUnimplementedTestingServer() +} + +func RegisterTestingServer(s grpc.ServiceRegistrar, srv TestingServer) { + s.RegisterService(&Testing_ServiceDesc, srv) +} + +func _Testing_Call_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Test) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TestingServer).Call(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Testing_Call_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TestingServer).Call(ctx, req.(*Test)) + } + return interceptor(ctx, in, info, handler) +} + +// Testing_ServiceDesc is the grpc.ServiceDesc for Testing service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Testing_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "Testing", + HandlerType: (*TestingServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "call", + Handler: _Testing_Call_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "test.proto", +} diff --git a/test/testdata/protogetter/protogetter.go b/test/testdata/protogetter/protogetter.go new file mode 100644 index 000000000000..47cd401e250a --- /dev/null +++ b/test/testdata/protogetter/protogetter.go @@ -0,0 +1,151 @@ +//golangcitest:args -Eprotogetter +package protogetter + +import ( + "fmt" + + "protogetter/proto" +) + +type Test struct { + Embedded *proto.Embedded +} + +func testInvalid(t *proto.Test) { + func(...interface{}) {}(t.B, t.D) // want `avoid direct access to proto field t\.B, use t\.GetB\(\) instead` + func(...interface{}) {}(t.GetB(), t.D) // want `avoid direct access to proto field t\.D, use t\.GetD\(\) instead` + func(...interface{}) {}(t.B, t.GetD()) // want `avoid direct access to proto field t\.B, use t\.GetB\(\) instead` + + _ = t.D // want `avoid direct access to proto field t\.D, use t\.GetD\(\) instead` + _ = t.F // want `avoid direct access to proto field t\.F, use t\.GetF\(\) instead` + _ = t.I32 // want `avoid direct access to proto field t\.I32, use t\.GetI32\(\) instead` + _ = t.I64 // want `avoid direct access to proto field t\.I64, use t\.GetI64\(\) instead` + _ = t.U32 // want `avoid direct access to proto field t\.U32, use t\.GetU32\(\) instead` + _ = t.U64 // want `avoid direct access to proto field t\.U64, use t\.GetU64\(\) instead` + _ = t.T // want `avoid direct access to proto field t\.T, use t\.GetT\(\) instead` + _ = t.B // want `avoid direct access to proto field t\.B, use t\.GetB\(\) instead` + _ = t.S // want `avoid direct access to proto field t\.S, use t\.GetS\(\) instead` + _ = t.Embedded // want `avoid direct access to proto field t\.Embedded, use t\.GetEmbedded\(\) instead` + _ = t.Embedded.S // want `avoid direct access to proto field t\.Embedded\.S, use t\.GetEmbedded\(\)\.GetS\(\) instead` + _ = t.GetEmbedded().S // want `avoid direct access to proto field t\.GetEmbedded\(\)\.S, use t\.GetEmbedded\(\)\.GetS\(\) instead` + _ = t.Embedded.Embedded // want `avoid direct access to proto field t\.Embedded\.Embedded, use t\.GetEmbedded\(\)\.GetEmbedded\(\) instead` + _ = t.GetEmbedded().Embedded // want `avoid direct access to proto field t\.GetEmbedded\(\)\.Embedded, use t\.GetEmbedded\(\)\.GetEmbedded\(\) instead` + _ = t.Embedded.Embedded.S // want `avoid direct access to proto field t\.Embedded\.Embedded\.S, use t\.GetEmbedded\(\)\.GetEmbedded\(\).GetS\(\) instead` + _ = t.GetEmbedded().GetEmbedded().S // want `avoid direct access to proto field t\.GetEmbedded\(\)\.GetEmbedded\(\)\.S, use t\.GetEmbedded\(\)\.GetEmbedded\(\)\.GetS\(\) instead` + _ = t.RepeatedEmbeddeds // want `avoid direct access to proto field t\.RepeatedEmbeddeds, use t\.GetRepeatedEmbeddeds\(\) instead` + _ = t.RepeatedEmbeddeds[0] // want `avoid direct access to proto field t\.RepeatedEmbeddeds, use t\.GetRepeatedEmbeddeds\(\) instead` + _ = t.RepeatedEmbeddeds[0].S // want `avoid direct access to proto field t\.RepeatedEmbeddeds\[0\]\.S, use t\.GetRepeatedEmbeddeds\(\)\[0\]\.GetS\(\) instead` + _ = t.GetRepeatedEmbeddeds()[0].S // want `avoid direct access to proto field t\.GetRepeatedEmbeddeds\(\)\[0\]\.S, use t\.GetRepeatedEmbeddeds\(\)\[0\]\.GetS\(\) instead` + _ = t.RepeatedEmbeddeds[0].Embedded // want `avoid direct access to proto field t\.RepeatedEmbeddeds\[0\]\.Embedded, use t\.GetRepeatedEmbeddeds\(\)\[0\]\.GetEmbedded\(\) instead` + _ = t.GetRepeatedEmbeddeds()[0].Embedded // want `avoid direct access to proto field t\.GetRepeatedEmbeddeds\(\)\[0\]\.Embedded, use t\.GetRepeatedEmbeddeds\(\)\[0\]\.GetEmbedded\(\) instead` + _ = t.RepeatedEmbeddeds[0].Embedded.S // want `avoid direct access to proto field t\.RepeatedEmbeddeds\[0\]\.Embedded\.S, use t\.GetRepeatedEmbeddeds\(\)\[0\].GetEmbedded\(\).GetS\(\) instead` + _ = t.GetRepeatedEmbeddeds()[0].GetEmbedded().S // want `avoid direct access to proto field t\.GetRepeatedEmbeddeds\(\)\[0\].GetEmbedded\(\).S, use t\.GetRepeatedEmbeddeds\(\)\[0\].GetEmbedded\(\).GetS\(\) instead` + _ = t.RepeatedEmbeddeds[t.I64].Embedded.S // want `avoid direct access to proto field t\.RepeatedEmbeddeds\[t.I64\]\.Embedded\.S, use t\.GetRepeatedEmbeddeds\(\)\[t\.GetI64\(\)\].GetEmbedded\(\).GetS\(\) instead` + _ = t.GetRepeatedEmbeddeds()[t.I64].GetEmbedded().S // want `avoid direct access to proto field t\.GetRepeatedEmbeddeds\(\)\[t\.I64\]\.GetEmbedded\(\)\.S, use t\.GetRepeatedEmbeddeds\(\)\[t\.GetI64\(\)\]\.GetEmbedded\(\).GetS\(\) instead` + + var many []*proto.Test + manyIndex := 42 + + _ = many[0].T // want `avoid direct access to proto field many\[0\]\.T, use many\[0\]\.GetT\(\) instead` + _ = many[1].Embedded.S // want `avoid direct access to proto field many\[1\]\.Embedded\.S, use many\[1\]\.GetEmbedded\(\)\.GetS\(\) instead` + _ = many[2].GetEmbedded().S // want `avoid direct access to proto field many\[2\]\.GetEmbedded\(\)\.S, use many\[2\].GetEmbedded\(\)\.GetS\(\) instead` + _ = many[3].Embedded.Embedded.S // want `avoid direct access to proto field many\[3\]\.Embedded\.Embedded\.S, use many\[3\].GetEmbedded\(\)\.GetEmbedded\(\)\.GetS\(\) instead` + _ = many[manyIndex].S // want `avoid direct access to proto field many\[manyIndex\]\.S, use many\[manyIndex\]\.GetS\(\) instead` + + test := many[0].Embedded.S == "" || t.Embedded.CustomMethod() == nil || t.S == "" || t.Embedded == nil // want `avoid direct access to proto field many\[0\]\.Embedded\.S, use many\[0\]\.GetEmbedded\(\).GetS\(\) instead` + _ = test + + other := proto.Other{} + _ = other.MyMethod(nil).S // want `avoid direct access to proto field other\.MyMethod\(nil\)\.S, use other\.MyMethod\(nil\)\.GetS\(\) instead` + + ems := t.RepeatedEmbeddeds // want `avoid direct access to proto field t\.RepeatedEmbeddeds, use t\.GetRepeatedEmbeddeds\(\) instead` + _ = ems[len(ems)-1].S // want `avoid direct access to proto field ems\[len\(ems\)-1\]\.S, use ems\[len\(ems\)-1\]\.GetS\(\) instead` + + ch := make(chan string) + ch <- t.S // want `avoid direct access to proto field t\.S, use t\.GetS\(\) instead` + + for _, v := range t.RepeatedEmbeddeds { // want `avoid direct access to proto field t\.RepeatedEmbeddeds, use t\.GetRepeatedEmbeddeds\(\) instead` + _ = v + } + + fn := func(...interface{}) bool { return false } + fn((*proto.Test)(nil).S) // want `avoid direct access to proto field \(\*proto\.Test\)\(nil\)\.S, use \(\*proto\.Test\)\(nil\)\.GetS\(\) instead` + + var ptrs *[]proto.Test + _ = (*ptrs)[42].RepeatedEmbeddeds // want `avoid direct access to proto field \(\*ptrs\)\[42\]\.RepeatedEmbeddeds, use \(\*ptrs\)\[42\].GetRepeatedEmbeddeds\(\) instead` + _ = (*ptrs)[t.I64].RepeatedEmbeddeds // want `avoid direct access to proto field \(\*ptrs\)\[t\.I64\]\.RepeatedEmbeddeds, use \(\*ptrs\)\[t\.GetI64\(\)\].GetRepeatedEmbeddeds\(\) instead` + + var anyType interface{} + _ = anyType.(*proto.Test).S // want `avoid direct access to proto field anyType\.\(\*proto\.Test\)\.S, use anyType\.\(\*proto\.Test\)\.GetS\(\) instead` + + t.Embedded.SetS("test") // want `avoid direct access to proto field t\.Embedded\.SetS\("test"\), use t\.GetEmbedded\(\)\.SetS\("test"\) instead` + t.Embedded.SetMap(map[string]string{"test": "test"}) // want `avoid direct access to proto field t\.Embedded\.SetMap\(map\[string\]string{"test": "test"}\), use t\.GetEmbedded\(\)\.SetMap\(map\[string\]string{"test": "test"}\) instead` +} + +func testValid(t *proto.Test) { + func(...interface{}) {}(t.GetB(), t.GetD()) + func(...interface{}) {}(&t.B, &t.D) + + _, t.T = true, true + _, t.T, _ = true, true, false + _, _, t.T = true, true, false + t.T, _ = true, true + t.D = 2 + t.I32++ + t.I32 += 2 + + fmt.Scanf("Test", &t.S, &t.B, &t.T) + + t.D = 1.0 + t.F = 1.0 + t.I32 = 1 + t.I64 = 1 + t.U32 = 1 + t.U64 = 1 + t.T = true + t.B = []byte{1} + t.S = "1" + t.Embedded = &proto.Embedded{} + t.Embedded.S = "1" + t.GetEmbedded().S = "1" + t.Embedded.Embedded = &proto.Embedded{} + t.GetEmbedded().Embedded = &proto.Embedded{} + t.Embedded.Embedded.S = "1" + t.GetEmbedded().GetEmbedded().S = "1" + t.RepeatedEmbeddeds = []*proto.Embedded{{S: "1"}} + + _ = t.GetD() + _ = t.GetF() + _ = t.GetI32() + _ = t.GetI64() + _ = t.GetU32() + _ = t.GetU64() + _ = t.GetT() + _ = t.GetB() + _ = t.GetS() + _ = t.GetEmbedded() + _ = t.GetEmbedded().GetS() + _ = t.GetEmbedded().GetEmbedded() + _ = t.GetEmbedded().GetEmbedded().GetS() + _ = t.GetRepeatedEmbeddeds() + _ = t.GetRepeatedEmbeddeds()[0] + _ = t.GetRepeatedEmbeddeds()[0].GetS() + _ = t.GetRepeatedEmbeddeds()[0].GetEmbedded() + _ = t.GetRepeatedEmbeddeds()[0].GetEmbedded().GetS() + + other := proto.Other{} + other.MyMethod(nil).CustomMethod() + other.MyMethod(nil).GetS() + + var tt Test + _ = tt.Embedded.GetS() + _ = tt.Embedded.GetEmbedded().GetS() + + ems := t.GetRepeatedEmbeddeds() + _ = ems[len(ems)-1].GetS() + + ch := make(chan string) + ch <- t.GetS() + + t.Equal(&proto.Test{S: "test", I64: 42}) +} diff --git a/test/testdata/scopelint.go b/test/testdata/scopelint.go deleted file mode 100644 index 3afd2f06aba5..000000000000 --- a/test/testdata/scopelint.go +++ /dev/null @@ -1,17 +0,0 @@ -//golangcitest:args -Escopelint --internal-cmd-test -package testdata - -import "fmt" - -func ScopelintTest() { - values := []string{"a", "b", "c"} - var funcs []func() - for _, val := range values { - funcs = append(funcs, func() { - fmt.Println(val) // want "Using the variable on range scope `val` in function literal" - }) - } - for _, f := range funcs { - f() - } -} diff --git a/test/testdata/sloglint.go b/test/testdata/sloglint.go new file mode 100644 index 000000000000..71faeb43000b --- /dev/null +++ b/test/testdata/sloglint.go @@ -0,0 +1,13 @@ +//go:build go1.21 + +//golangcitest:args -Esloglint +package testdata + +import "log/slog" + +func test() { + slog.Info("msg", "foo", 1, "bar", 2) + slog.Info("msg", slog.Int("foo", 1), slog.Int("bar", 2)) + + slog.Info("msg", "foo", 1, slog.Int("bar", 2)) // want `key-value pairs and attributes should not be mixed` +} diff --git a/test/testdata/sloglint_args_on_sep_lines.go b/test/testdata/sloglint_args_on_sep_lines.go new file mode 100644 index 000000000000..9bdd89764cbe --- /dev/null +++ b/test/testdata/sloglint_args_on_sep_lines.go @@ -0,0 +1,17 @@ +//go:build go1.21 + +//golangcitest:args -Esloglint +//golangcitest:config_path testdata/configs/sloglint_args_on_sep_lines.yml +package testdata + +import "log/slog" + +func test() { + slog.Info("msg", "foo", 1) + slog.Info("msg", + "foo", 1, + "bar", 2, + ) + + slog.Info("msg", "foo", 1, "bar", 2) // want `arguments should be put on separate lines` +} diff --git a/test/testdata/sloglint_attr_only.go b/test/testdata/sloglint_attr_only.go new file mode 100644 index 000000000000..3153026e4557 --- /dev/null +++ b/test/testdata/sloglint_attr_only.go @@ -0,0 +1,13 @@ +//go:build go1.21 + +//golangcitest:args -Esloglint +//golangcitest:config_path testdata/configs/sloglint_attr_only.yml +package testdata + +import "log/slog" + +func test() { + slog.Info("msg", slog.Int("foo", 1), slog.Int("bar", 2)) + + slog.Info("msg", "foo", 1, "bar", 2) // want `key-value pairs should not be used` +} diff --git a/test/testdata/sloglint_context_only.go b/test/testdata/sloglint_context_only.go new file mode 100644 index 000000000000..78f39e373432 --- /dev/null +++ b/test/testdata/sloglint_context_only.go @@ -0,0 +1,16 @@ +//go:build go1.21 + +//golangcitest:args -Esloglint +//golangcitest:config_path testdata/configs/sloglint_context_only.yml +package testdata + +import ( + "context" + "log/slog" +) + +func test() { + slog.InfoContext(context.Background(), "msg") + + slog.Info("msg") // want `methods without a context should not be used` +} diff --git a/test/testdata/sloglint_key_naming_case.go b/test/testdata/sloglint_key_naming_case.go new file mode 100644 index 000000000000..d278cd974c80 --- /dev/null +++ b/test/testdata/sloglint_key_naming_case.go @@ -0,0 +1,24 @@ +//go:build go1.21 + +//golangcitest:args -Esloglint +//golangcitest:config_path testdata/configs/sloglint_key_naming_case.yml +package testdata + +import "log/slog" + +const ( + snakeKey = "foo_bar" + kebabKey = "foo-bar" +) + +func test() { + slog.Info("msg", "foo_bar", 1) + slog.Info("msg", snakeKey, 1) + slog.Info("msg", slog.Int("foo_bar", 1)) + slog.Info("msg", slog.Int(snakeKey, 1)) + + slog.Info("msg", "foo-bar", 1) // want `keys should be written in snake_case` + slog.Info("msg", kebabKey, 1) // want `keys should be written in snake_case` + slog.Info("msg", slog.Int("foo-bar", 1)) // want `keys should be written in snake_case` + slog.Info("msg", slog.Int(kebabKey, 1)) // want `keys should be written in snake_case` +} diff --git a/test/testdata/sloglint_kv_only.go b/test/testdata/sloglint_kv_only.go new file mode 100644 index 000000000000..efbcefcc8591 --- /dev/null +++ b/test/testdata/sloglint_kv_only.go @@ -0,0 +1,13 @@ +//go:build go1.21 + +//golangcitest:args -Esloglint +//golangcitest:config_path testdata/configs/sloglint_kv_only.yml +package testdata + +import "log/slog" + +func test() { + slog.Info("msg", "foo", 1, "bar", 2) + + slog.Info("msg", slog.Int("foo", 1), slog.Int("bar", 2)) // want `attributes should not be used` +} diff --git a/test/testdata/sloglint_no_raw_keys.go b/test/testdata/sloglint_no_raw_keys.go new file mode 100644 index 000000000000..ff248993142f --- /dev/null +++ b/test/testdata/sloglint_no_raw_keys.go @@ -0,0 +1,21 @@ +//go:build go1.21 + +//golangcitest:args -Esloglint +//golangcitest:config_path testdata/configs/sloglint_no_raw_keys.yml +package testdata + +import "log/slog" + +const foo = "foo" + +func Foo(value int) slog.Attr { + return slog.Int("foo", value) +} + +func test() { + slog.Info("msg", foo, 1) + slog.Info("msg", Foo(1)) + + slog.Info("msg", "foo", 1) // want `raw keys should not be used` + slog.Info("msg", slog.Int("foo", 1)) // want `raw keys should not be used` +} diff --git a/test/testdata/sloglint_static_msg.go b/test/testdata/sloglint_static_msg.go new file mode 100644 index 000000000000..261a40b6601f --- /dev/null +++ b/test/testdata/sloglint_static_msg.go @@ -0,0 +1,19 @@ +//go:build go1.21 + +//golangcitest:args -Esloglint +//golangcitest:config_path testdata/configs/sloglint_static_msg.yml +package testdata + +import ( + "log/slog" +) + +func test() { + slog.Info("msg") + + const msg1 = "msg" + slog.Info(msg1) + + msg2 := "msg" + slog.Info(msg2) // want `message should be a string literal or a constant` +} diff --git a/test/testdata/spancheck/configs/enable_all.yml b/test/testdata/spancheck/configs/enable_all.yml new file mode 100644 index 000000000000..1ea3518098bb --- /dev/null +++ b/test/testdata/spancheck/configs/enable_all.yml @@ -0,0 +1,8 @@ +linters-settings: + spancheck: + checks: + - "end" + - "record-error" + - "set-status" + ignore-check-signatures: + - "recordErr" diff --git a/test/testdata/spancheck/go.mod b/test/testdata/spancheck/go.mod new file mode 100644 index 000000000000..de347098a901 --- /dev/null +++ b/test/testdata/spancheck/go.mod @@ -0,0 +1,14 @@ +module spancheck + +go 1.20 + +require ( + go.opentelemetry.io/otel v1.21.0 + go.opentelemetry.io/otel/trace v1.21.0 +) + +require ( + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + go.opentelemetry.io/otel/metric v1.21.0 // indirect +) diff --git a/test/testdata/spancheck/go.sum b/test/testdata/spancheck/go.sum new file mode 100644 index 000000000000..e09fe7a75588 --- /dev/null +++ b/test/testdata/spancheck/go.sum @@ -0,0 +1,16 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= +go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= +go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= +go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= +go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= +go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/test/testdata/spancheck/spancheck_default.go b/test/testdata/spancheck/spancheck_default.go new file mode 100644 index 000000000000..e1fff76da927 --- /dev/null +++ b/test/testdata/spancheck/spancheck_default.go @@ -0,0 +1,90 @@ +//golangcitest:args -Espancheck +package spancheck + +import ( + "context" + "errors" + "fmt" + + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/codes" +) + +type testDefaultError struct{} + +func (e *testDefaultError) Error() string { + return "foo" +} + +// incorrect + +func _() { + otel.Tracer("foo").Start(context.Background(), "bar") // want "span is unassigned, probable memory leak" + ctx, _ := otel.Tracer("foo").Start(context.Background(), "bar") // want "span is unassigned, probable memory leak" + fmt.Print(ctx) +} + +func _() { + ctx, span := otel.Tracer("foo").Start(context.Background(), "bar") // want "span.End is not called on all paths, possible memory leak" + print(ctx.Done(), span.IsRecording()) +} // want "return can be reached without calling span.End" + +func _() { + var ctx, span = otel.Tracer("foo").Start(context.Background(), "bar") // want "span.End is not called on all paths, possible memory leak" + print(ctx.Done(), span.IsRecording()) +} // want "return can be reached without calling span.End" + +func _() { + _, span := otel.Tracer("foo").Start(context.Background(), "bar") // want "span.End is not called on all paths, possible memory leak" + _, span = otel.Tracer("foo").Start(context.Background(), "bar") + fmt.Print(span) + defer span.End() +} // want "return can be reached without calling span.End" + +// correct + +func _() error { + _, span := otel.Tracer("foo").Start(context.Background(), "bar") + defer span.End() + + return nil +} + +func _() error { + _, span := otel.Tracer("foo").Start(context.Background(), "bar") + defer span.End() + + if true { + return nil + } + + return nil +} + +func _() error { + _, span := otel.Tracer("foo").Start(context.Background(), "bar") + defer span.End() + + if false { + err := errors.New("foo") + span.SetStatus(codes.Error, err.Error()) + span.RecordError(err) + return err + } + + if true { + span.SetStatus(codes.Error, "foo") + span.RecordError(errors.New("foo")) + return errors.New("bar") + } + + return nil +} + +func _() { + _, span := otel.Tracer("foo").Start(context.Background(), "bar") + defer span.End() + + _, span = otel.Tracer("foo").Start(context.Background(), "bar") + defer span.End() +} diff --git a/test/testdata/spancheck/spancheck_enable_all.go b/test/testdata/spancheck/spancheck_enable_all.go new file mode 100644 index 000000000000..382e714043e4 --- /dev/null +++ b/test/testdata/spancheck/spancheck_enable_all.go @@ -0,0 +1,206 @@ +//golangcitest:config_path configs/enable_all.yml +//golangcitest:args -Espancheck +package spancheck + +import ( + "context" + "errors" + "fmt" + + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/codes" + "go.opentelemetry.io/otel/trace" +) + +type testError struct{} + +func (e *testError) Error() string { + return "foo" +} + +// incorrect + +func _() { + otel.Tracer("foo").Start(context.Background(), "bar") // want "span is unassigned, probable memory leak" + ctx, _ := otel.Tracer("foo").Start(context.Background(), "bar") // want "span is unassigned, probable memory leak" + fmt.Print(ctx) +} + +func _() { + ctx, span := otel.Tracer("foo").Start(context.Background(), "bar") // want "span.End is not called on all paths, possible memory leak" + print(ctx.Done(), span.IsRecording()) +} // want "return can be reached without calling span.End" + +func _() { + var ctx, span = otel.Tracer("foo").Start(context.Background(), "bar") // want "span.End is not called on all paths, possible memory leak" + print(ctx.Done(), span.IsRecording()) +} // want "return can be reached without calling span.End" + +func _() { + _, span := otel.Tracer("foo").Start(context.Background(), "bar") // want "span.End is not called on all paths, possible memory leak" + _, span = otel.Tracer("foo").Start(context.Background(), "bar") + fmt.Print(span) + defer span.End() +} // want "return can be reached without calling span.End" + +func _() error { + _, span := otel.Tracer("foo").Start(context.Background(), "bar") // want "span.SetStatus is not called on all paths" + defer span.End() + + if true { + err := errors.New("foo") + span.RecordError(err) + return err // want "return can be reached without calling span.SetStatus" + } + + return nil +} + +func _() error { + _, span := otel.Tracer("foo").Start(context.Background(), "bar") // want "span.SetStatus is not called on all paths" + defer span.End() + + if true { + span.RecordError(errors.New("foo")) + return errors.New("foo") // want "return can be reached without calling span.SetStatus" + } + + return nil +} + +func _() error { + _, span := otel.Tracer("foo").Start(context.Background(), "bar") // want "span.SetStatus is not called on all paths" + defer span.End() + + if true { + span.RecordError(errors.New("foo")) + return &testError{} // want "return can be reached without calling span.SetStatus" + } + + return nil +} + +func _() error { + _, span := otel.Tracer("foo").Start(context.Background(), "bar") // want "span.RecordError is not called on all paths" + defer span.End() + + if true { + span.SetStatus(codes.Error, "foo") + return &testError{} // want "return can be reached without calling span.RecordError" + } + + return nil +} + +func _() (string, error) { + _, span := otel.Tracer("foo").Start(context.Background(), "bar") // want "span.SetStatus is not called on all paths" + defer span.End() + + if true { + span.RecordError(errors.New("foo")) + return "", &testError{} // want "return can be reached without calling span.SetStatus" + } + + return "", nil +} + +func _() (string, error) { + _, span := otel.Tracer("foo").Start(context.Background(), "bar") // want "span.SetStatus is not called on all paths" + defer span.End() + + if true { + span.RecordError(errors.New("foo")) + return "", errors.New("foo") // want "return can be reached without calling span.SetStatus" + } + + return "", nil +} + +func _() { + f := func() error { + _, span := otel.Tracer("foo").Start(context.Background(), "bar") // want "span.SetStatus is not called on all paths" + defer span.End() + + if true { + span.RecordError(errors.New("foo")) + return errors.New("foo") // want "return can be reached without calling span.SetStatus" + } + + return nil + } + fmt.Println(f) +} + +func _() error { + _, span := otel.Tracer("foo").Start(context.Background(), "bar") // want "span.SetStatus is not called on all paths" + defer span.End() + + { + if true { + span.RecordError(errors.New("foo")) + return errors.New("foo") // want "return can be reached without calling span.SetStatus" + } + } + + return nil +} + +// correct + +func _() error { + _, span := otel.Tracer("foo").Start(context.Background(), "bar") + defer span.End() + + return nil +} + +func _() error { + _, span := otel.Tracer("foo").Start(context.Background(), "bar") + defer span.End() + + if true { + return nil + } + + return nil +} + +func _() error { + _, span := otel.Tracer("foo").Start(context.Background(), "bar") + defer span.End() + + if false { + err := errors.New("foo") + span.SetStatus(codes.Error, err.Error()) + span.RecordError(err) + return err + } + + if true { + span.SetStatus(codes.Error, "foo") + span.RecordError(errors.New("foo")) + return errors.New("bar") + } + + return nil +} + +func _() { + _, span := otel.Tracer("foo").Start(context.Background(), "bar") + defer span.End() + + _, span = otel.Tracer("foo").Start(context.Background(), "bar") + defer span.End() +} + +// ignore error because of matching func sig +func _() error { + _, span := otel.Tracer("foo").Start(context.Background(), "bar") + defer span.End() + + err := errors.New("foo") + recordError(span, err) + return err +} + +func recordError(span trace.Span, err error) {} diff --git a/test/testdata/sqlclosecheck.go b/test/testdata/sqlclosecheck.go index 6bbe32914364..5a5a13f78b6f 100644 --- a/test/testdata/sqlclosecheck.go +++ b/test/testdata/sqlclosecheck.go @@ -16,7 +16,6 @@ var ( ) func rowsCorrectDeferBlock() { - rows, err := db.QueryContext(ctx, "SELECT name FROM users WHERE age=?", age) if err != nil { log.Fatal(err) @@ -69,7 +68,7 @@ func rowsCorrectDefer() { } func rowsMissingClose() { - rows, err := db.QueryContext(ctx, "SELECT name FROM users WHERE age=?", age) // want "Rows/Stmt was not closed" + rows, err := db.QueryContext(ctx, "SELECT name FROM users WHERE age=?", age) // want "Rows/Stmt/NamedStmt was not closed" if err != nil { log.Fatal(err) } @@ -91,6 +90,13 @@ func rowsMissingClose() { log.Printf("%s are %d years old", strings.Join(names, ", "), age) } +func rowsMissingCloseG[T ~int64](db *sql.DB, a T) { + rows, _ := db.Query("select id from tb") // want "Rows/Stmt/NamedStmt was not closed" + for rows.Next() { + // ... + } +} + func rowsNonDeferClose() { rows, err := db.QueryContext(ctx, "SELECT name FROM users WHERE age=?", age) if err != nil { @@ -202,7 +208,7 @@ func stmtCorrectDefer() { func stmtMissingClose() { // In normal use, create one Stmt when your process starts. - stmt, err := db.PrepareContext(ctx, "SELECT username FROM users WHERE id = ?") // want "Rows/Stmt was not closed" + stmt, err := db.PrepareContext(ctx, "SELECT username FROM users WHERE id = ?") // want "Rows/Stmt/NamedStmt was not closed" if err != nil { log.Fatal(err) } diff --git a/test/testdata/structcheck.go b/test/testdata/structcheck.go deleted file mode 100644 index 88f06e4d9e48..000000000000 --- a/test/testdata/structcheck.go +++ /dev/null @@ -1,6 +0,0 @@ -//golangcitest:args -Estructcheck -package testdata - -type t struct { - unusedField int // want "`unusedField` is unused" -} diff --git a/test/testdata/tagalign.go b/test/testdata/tagalign.go new file mode 100644 index 000000000000..428b237f5f2a --- /dev/null +++ b/test/testdata/tagalign.go @@ -0,0 +1,15 @@ +//golangcitest:args -Etagalign +package testdata + +import "time" + +type TagAlignExampleAlignSort struct { + Foo time.Duration `json:"foo,omitempty" yaml:"foo" xml:"foo" binding:"required" gorm:"column:foo" zip:"foo" validate:"required"` // want `binding:"required" gorm:"column:foo" json:"foo,omitempty" validate:"required" xml:"foo" yaml:"foo" zip:"foo"` + Bar int `validate:"required" yaml:"bar" xml:"bar" binding:"required" json:"bar,omitempty" gorm:"column:bar" zip:"bar" ` // want `binding:"required" gorm:"column:bar" json:"bar,omitempty" validate:"required" xml:"bar" yaml:"bar" zip:"bar"` + FooBar int `gorm:"column:fooBar" validate:"required" xml:"fooBar" binding:"required" json:"fooBar,omitempty" zip:"fooBar" yaml:"fooBar"` // want `binding:"required" gorm:"column:fooBar" json:"fooBar,omitempty" validate:"required" xml:"fooBar" yaml:"fooBar" zip:"fooBar"` +} + +type TagAlignExampleAlignSort2 struct { + Foo int ` xml:"foo" json:"foo,omitempty" yaml:"foo" zip:"foo" binding:"required" gorm:"column:foo" validate:"required"` // want `binding:"required" gorm:"column:foo" json:"foo,omitempty" validate:"required" xml:"foo" yaml:"foo" zip:"foo"` + Bar int `validate:"required" gorm:"column:bar" yaml:"bar" xml:"bar" binding:"required" json:"bar" zip:"bar" ` // want `binding:"required" gorm:"column:bar" json:"bar" validate:"required" xml:"bar" yaml:"bar" zip:"bar"` +} diff --git a/test/testdata/tagalign_align_only.go b/test/testdata/tagalign_align_only.go new file mode 100644 index 000000000000..a71f958e74d4 --- /dev/null +++ b/test/testdata/tagalign_align_only.go @@ -0,0 +1,31 @@ +//golangcitest:args -Etagalign +//golangcitest:config_path testdata/configs/tagalign_align_only.yml +package testdata + +import "time" + +type TagAlignExampleAlignOnlyKO struct { + Foo time.Time `gorm:"column:foo" json:"foo,omitempty" xml:"foo" yaml:"foo" zip:"foo"` // want `gorm:"column:foo" json:"foo,omitempty" xml:"foo" yaml:"foo" zip:"foo"` + FooBar struct{} `gorm:"column:fooBar" zip:"fooBar" json:"fooBar,omitempty" xml:"fooBar" yaml:"fooBar"` // want `gorm:"column:fooBar" zip:"fooBar" json:"fooBar,omitempty" xml:"fooBar" yaml:"fooBar"` + FooFoo struct { + Foo int `json:"foo" yaml:"foo"` // want `json:"foo" yaml:"foo"` + Bar int `yaml:"bar" json:"bar"` // want `yaml:"bar" json:"bar"` + BarBar string `json:"barBar" yaml:"barBar"` + } `xml:"fooFoo" json:"fooFoo"` + NoTag struct{} + BarBar struct{} `json:"barBar,omitempty" gorm:"column:barBar" yaml:"barBar" xml:"barBar" zip:"barBar"` + Boo struct{} `gorm:"column:boo" json:"boo,omitempty" xml:"boo" yaml:"boo" zip:"boo"` // want `gorm:"column:boo" json:"boo,omitempty" xml:"boo" yaml:"boo" zip:"boo"` +} + +type TagAlignExampleAlignOnlyOK struct { + Foo time.Time `gorm:"column:foo" json:"foo,omitempty" xml:"foo" yaml:"foo" zip:"foo"` + FooBar struct{} `gorm:"column:fooBar" zip:"fooBar" json:"fooBar,omitempty" xml:"fooBar" yaml:"fooBar"` + FooFoo struct { + Foo int `json:"foo" yaml:"foo"` + Bar int `yaml:"bar" json:"bar"` + BarBar string `json:"barBar" yaml:"barBar"` + } `xml:"fooFoo" json:"fooFoo"` + NoTag struct{} + BarBar struct{} `json:"barBar,omitempty" gorm:"column:barBar" yaml:"barBar" xml:"barBar" zip:"barBar"` + Boo struct{} `gorm:"column:boo" json:"boo,omitempty" xml:"boo" yaml:"boo" zip:"boo"` +} diff --git a/test/testdata/tagalign_order_only.go b/test/testdata/tagalign_order_only.go new file mode 100644 index 000000000000..5837fc6d838a --- /dev/null +++ b/test/testdata/tagalign_order_only.go @@ -0,0 +1,15 @@ +//golangcitest:args -Etagalign +//golangcitest:config_path testdata/configs/tagalign_order_only.yml +package testdata + +import "time" + +type TagAlignExampleOrderOnlyKO struct { + Foo time.Time `xml:"foo" json:"foo,omitempty" yaml:"foo" zip:"foo" gorm:"column:foo" validate:"required"` // want `xml:"foo" json:"foo,omitempty" yaml:"foo" gorm:"column:foo" validate:"required" zip:"foo"` + FooBar struct{} `gorm:"column:fooBar" validate:"required" zip:"fooBar" xml:"fooBar" json:"fooBar,omitempty" yaml:"fooBar"` // want `xml:"fooBar" json:"fooBar,omitempty" yaml:"fooBar" gorm:"column:fooBar" validate:"required" zip:"fooBar"` +} + +type TagAlignExampleOrderOnlyOK struct { + Foo time.Time `xml:"foo" json:"foo,omitempty" yaml:"foo" gorm:"column:foo" validate:"required" zip:"foo"` + FooBar struct{} `xml:"fooBar" json:"fooBar,omitempty" yaml:"fooBar" gorm:"column:fooBar" validate:"required" zip:"fooBar"` +} diff --git a/test/testdata/tagalign_sort_only.go b/test/testdata/tagalign_sort_only.go new file mode 100644 index 000000000000..600f4bbb2e8e --- /dev/null +++ b/test/testdata/tagalign_sort_only.go @@ -0,0 +1,15 @@ +//golangcitest:args -Etagalign +//golangcitest:config_path testdata/configs/tagalign_sort_only.yml +package testdata + +import "time" + +type TagAlignExampleSortOnlyKO struct { + Foo time.Time `xml:"foo" json:"foo,omitempty" yaml:"foo" gorm:"column:foo" validate:"required" zip:"foo"` // want `gorm:"column:foo" json:"foo,omitempty" validate:"required" xml:"foo" yaml:"foo" zip:"foo"` + FooBar struct{} `gorm:"column:fooBar" validate:"required" zip:"fooBar" xml:"fooBar" json:"fooBar,omitempty" yaml:"fooBar"` // want `gorm:"column:fooBar" json:"fooBar,omitempty" validate:"required" xml:"fooBar" yaml:"fooBar" zip:"fooBar"` +} + +type TagAlignExampleSortOnlyOK struct { + Foo time.Time `gorm:"column:foo" json:"foo,omitempty" validate:"required" xml:"foo" yaml:"foo" zip:"foo"` + FooBar struct{} `gorm:"column:fooBar" json:"fooBar,omitempty" validate:"required" xml:"fooBar" yaml:"fooBar" zip:"fooBar"` +} diff --git a/test/testdata/tagalign_strict.go b/test/testdata/tagalign_strict.go new file mode 100644 index 000000000000..6689d486fc52 --- /dev/null +++ b/test/testdata/tagalign_strict.go @@ -0,0 +1,10 @@ +//golangcitest:args -Etagalign +//golangcitest:config_path testdata/configs/tagalign_strict.yml +package testdata + +import "time" + +type TagAlignExampleStrictKO struct { + Foo time.Time `json:"foo,omitempty" validate:"required" zip:"foo"` // want ` json:"foo,omitempty" validate:"required" zip:"foo"` + FooBar struct{} `gorm:"column:fooBar" validate:"required" zip:"fooBar" xml:"fooBar" json:"fooBar,omitempty" yaml:"fooBar"` // want `gorm:"column:fooBar" json:"fooBar,omitempty" validate:"required" xml:"fooBar" yaml:"fooBar" zip:"fooBar"` +} diff --git a/test/testdata/testifylint.go b/test/testdata/testifylint.go new file mode 100644 index 000000000000..3de4bad1985b --- /dev/null +++ b/test/testdata/testifylint.go @@ -0,0 +1,74 @@ +//golangcitest:args -Etestifylint +package testdata + +import ( + "io" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" +) + +type Bool bool + +func TestTestifylint(t *testing.T) { + var ( + predicate bool + resultInt int + resultFloat float64 + arr []string + err error + ) + + assert.Equal(t, predicate, true) // want "bool-compare: use assert\\.True" + assert.Equal(t, Bool(predicate), false) // want "bool-compare: use assert\\.False" + assert.True(t, resultInt == 1) // want "compares: use assert\\.Equal" + assert.Equal(t, len(arr), 0) // want "empty: use assert\\.Empty" + assert.Error(t, err, io.EOF) // want "error-is-as: invalid usage of assert\\.Error, use assert\\.ErrorIs instead" + assert.Nil(t, err) // want "error-nil: use assert\\.NoError" + assert.Equal(t, resultInt, 42) // want "expected-actual: need to reverse actual and expected values" + assert.Equal(t, resultFloat, 42.42) // want "float-compare: use assert\\.InEpsilon \\(or InDelta\\)" + assert.Equal(t, len(arr), 10) // want "len: use assert\\.Len" + + assert.True(t, predicate) + assert.Equal(t, resultInt, 1) // want "expected-actual: need to reverse actual and expected values" + assert.Empty(t, arr) + assert.ErrorIs(t, err, io.EOF) // want "require-error: for error assertions use require" + assert.NoError(t, err) // want "require-error: for error assertions use require" + assert.Equal(t, 42, resultInt) + assert.InEpsilon(t, 42.42, resultFloat, 0.0001) + assert.Len(t, arr, 10) + + require.ErrorIs(t, err, io.EOF) + require.NoError(t, err) + + t.Run("formatted", func(t *testing.T) { + assert.Equal(t, predicate, true, "message") // want "bool-compare: use assert\\.True" + assert.Equal(t, predicate, true, "message %d", 42) // want "bool-compare: use assert\\.True" + assert.Equalf(t, predicate, true, "message") // want "bool-compare: use assert\\.Truef" + assert.Equalf(t, predicate, true, "message %d", 42) // want "bool-compare: use assert\\.Truef" + }) + + assert.Equal(t, arr, nil) // want "nil-compare: use assert\\.Nil" + assert.Nil(t, arr) + + go func() { + if assert.Error(t, err) { + require.ErrorIs(t, err, io.EOF) // want "go-require: require must only be used in the goroutine running the test function" + } + }() +} + +type SuiteExample struct { + suite.Suite +} + +func TestSuiteExample(t *testing.T) { + suite.Run(t, new(SuiteExample)) +} + +func (s *SuiteExample) TestAll() { + var b bool + s.Assert().True(b) // want "suite-extra-assert-call: need to simplify the assertion to s\\.True" +} diff --git a/test/testdata/testifylint_bool_compare.go b/test/testdata/testifylint_bool_compare.go new file mode 100644 index 000000000000..977e823ca5e8 --- /dev/null +++ b/test/testdata/testifylint_bool_compare.go @@ -0,0 +1,17 @@ +//golangcitest:args -Etestifylint +//golangcitest:config_path testdata/configs/testifylint_bool_compare_only.yml +package testdata + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +type Bool bool + +func TestTestifylint(t *testing.T) { + var predicate bool + assert.Equal(t, predicate, true) // want "bool-compare: use assert\\.True" + assert.Equal(t, Bool(predicate), false) +} diff --git a/test/testdata/testifylint_require_error.go b/test/testdata/testifylint_require_error.go new file mode 100644 index 000000000000..0ba35e8403e9 --- /dev/null +++ b/test/testdata/testifylint_require_error.go @@ -0,0 +1,73 @@ +//golangcitest:args -Etestifylint +//golangcitest:config_path testdata/configs/testifylint_require_error_only.yml +package testdata + +import ( + "io" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" +) + +func TestTestifylint(t *testing.T) { + var ( + predicate bool + resultInt int + resultFloat float64 + arr []string + err error + ) + + assert.Equal(t, predicate, true) + assert.True(t, resultInt == 1) + assert.Equal(t, len(arr), 0) + assert.Error(t, err, io.EOF) + assert.Nil(t, err) + assert.Equal(t, resultInt, 42) + assert.Equal(t, resultFloat, 42.42) + assert.Equal(t, len(arr), 10) + + assert.True(t, predicate) + assert.Equal(t, resultInt, 1) + assert.Empty(t, arr) + assert.ErrorIs(t, err, io.EOF) + assert.NoError(t, err) // want "require-error: for error assertions use require" + assert.Equal(t, 42, resultInt) + assert.NoErrorf(t, err, "boom!") + assert.InEpsilon(t, 42.42, resultFloat, 0.0001) + assert.Len(t, arr, 10) + + require.ErrorIs(t, err, io.EOF) + require.NoError(t, err) + + t.Run("formatted", func(t *testing.T) { + assert.Equal(t, predicate, true, "message") + assert.Equal(t, predicate, true, "message %d", 42) + assert.Equalf(t, predicate, true, "message") + assert.Equalf(t, predicate, true, "message %d", 42) + }) + + assert.Equal(t, arr, nil) + assert.Nil(t, arr) + + go func() { + if assert.Error(t, err) { + require.ErrorIs(t, err, io.EOF) + } + }() +} + +type SuiteExample struct { + suite.Suite +} + +func TestSuiteExample(t *testing.T) { + suite.Run(t, new(SuiteExample)) +} + +func (s *SuiteExample) TestAll() { + var b bool + s.Assert().True(b) +} diff --git a/test/testdata/unconvert.go b/test/testdata/unconvert.go index bbd7ad090901..b0c422c5eef8 100644 --- a/test/testdata/unconvert.go +++ b/test/testdata/unconvert.go @@ -1,10 +1,183 @@ //golangcitest:args -Eunconvert package testdata -import "log" +import "io" -func Unconvert() { - a := 1 - b := int(a) // want "unnecessary conversion" - log.Print(b) +// Various explicit conversions of untyped constants +// that cannot be removed. +func _() { + const ( + _ = byte(0) + _ = int((real)(0i)) + _ = complex64(complex(1, 2)) + _ = (bool)(true || false) + + PtrSize = 4 << (^uintptr(0) >> 63) + c0 = uintptr(PtrSize) + c1 = uintptr((8-PtrSize)/4*2860486313 + (PtrSize-4)/4*33054211828000289) + ) + + i := int64(0) + _ = i +} + +// Make sure we distinguish function calls from +// conversion to function type. +func _() { + type F func(F) int + var f F + + _ = F(F(nil)) // want "unnecessary conversion" + _ = f(F(nil)) +} + +// Make sure we don't remove explicit conversions that +// prevent fusing floating-point operation. +func _() { + var f1, f2, f3, ftmp float64 + _ = f1 + float64(f2*f3) + ftmp = float64(f2 * f3) + _ = f1 + ftmp + ftmp = f2 * f3 + _ = f1 + float64(ftmp) + + var c1, c2, c3, ctmp complex128 + _ = c1 + complex128(c2*c3) + ctmp = complex128(c2 * c3) + _ = c1 + ctmp + ctmp = c2 * c3 + _ = c1 + complex128(ctmp) +} + +// Basic contains conversion errors for builtin data types +func Basic() { + var vbool bool + var vbyte byte + var vcomplex128 complex128 + var vcomplex64 complex64 + var verror error + var vfloat32 float32 + var vfloat64 float64 + var vint int + var vint16 int16 + var vint32 int32 + var vint64 int64 + var vint8 int8 + var vrune rune + var vstring string + var vuint uint + var vuint16 uint16 + var vuint32 uint32 + var vuint64 uint64 + var vuint8 uint8 + var vuintptr uintptr + + _ = bool(vbool) // want "unnecessary conversion" + _ = byte(vbyte) // want "unnecessary conversion" + _ = error(verror) // want "unnecessary conversion" + _ = int(vint) // want "unnecessary conversion" + _ = int16(vint16) // want "unnecessary conversion" + _ = int32(vint32) // want "unnecessary conversion" + _ = int64(vint64) // want "unnecessary conversion" + _ = int8(vint8) // want "unnecessary conversion" + _ = rune(vrune) // want "unnecessary conversion" + _ = string(vstring) // want "unnecessary conversion" + _ = uint(vuint) // want "unnecessary conversion" + _ = uint16(vuint16) // want "unnecessary conversion" + _ = uint32(vuint32) // want "unnecessary conversion" + _ = uint64(vuint64) // want "unnecessary conversion" + _ = uint8(vuint8) // want "unnecessary conversion" + _ = uintptr(vuintptr) // want "unnecessary conversion" + + _ = float32(vfloat32) + _ = float64(vfloat64) + _ = complex128(vcomplex128) + _ = complex64(vcomplex64) + + // Pointers + _ = (*bool)(&vbool) // want "unnecessary conversion" + _ = (*byte)(&vbyte) // want "unnecessary conversion" + _ = (*complex128)(&vcomplex128) // want "unnecessary conversion" + _ = (*complex64)(&vcomplex64) // want "unnecessary conversion" + _ = (*error)(&verror) // want "unnecessary conversion" + _ = (*float32)(&vfloat32) // want "unnecessary conversion" + _ = (*float64)(&vfloat64) // want "unnecessary conversion" + _ = (*int)(&vint) // want "unnecessary conversion" + _ = (*int16)(&vint16) // want "unnecessary conversion" + _ = (*int32)(&vint32) // want "unnecessary conversion" + _ = (*int64)(&vint64) // want "unnecessary conversion" + _ = (*int8)(&vint8) // want "unnecessary conversion" + _ = (*rune)(&vrune) // want "unnecessary conversion" + _ = (*string)(&vstring) // want "unnecessary conversion" + _ = (*uint)(&vuint) // want "unnecessary conversion" + _ = (*uint16)(&vuint16) // want "unnecessary conversion" + _ = (*uint32)(&vuint32) // want "unnecessary conversion" + _ = (*uint64)(&vuint64) // want "unnecessary conversion" + _ = (*uint8)(&vuint8) // want "unnecessary conversion" + _ = (*uintptr)(&vuintptr) // want "unnecessary conversion" +} + +// Counter is an int64 +type Counter int64 + +// ID is a typed identifier +type ID string + +// Metric is a struct +type Metric struct { + ID ID + Counter Counter +} + +// Custom contains conversion errors for builtin data types +func Custom() { + type Local struct{ id ID } + + var counter Counter + var id ID + var m Metric + var local Local + var x struct{ id ID } + + _ = Counter(counter) // want "unnecessary conversion" + _ = ID(id) // want "unnecessary conversion" + _ = Metric(m) // want "unnecessary conversion" + _ = Local(local) // want "unnecessary conversion" + _ = (struct{ id ID })(x) // want "unnecessary conversion" + + // Pointers + _ = (*Counter)(&counter) // want "unnecessary conversion" + _ = (*ID)(&id) // want "unnecessary conversion" + _ = (*Metric)(&m) // want "unnecessary conversion" + _ = (*Local)(&local) // want "unnecessary conversion" + _ = (*struct{ id ID })(&x) // want "unnecessary conversion" +} + +// Interfaces contains conversion errors for interfaces +func Interfaces() { + var writer io.Writer + + _ = (io.Writer)(writer) // want "unnecessary conversion" + _ = (*io.Writer)(&writer) // want "unnecessary conversion" +} + +// Constructor is a func type +type Constructor func() ID + +// Funcs contains conversion errors for func types +func Funcs() { + type Local func(ID) + type Recursive func(Recursive) + + var ctor Constructor + var local Local + var recursive Recursive + + _ = Constructor(ctor) // want "unnecessary conversion" + _ = Local(local) // want "unnecessary conversion" + _ = Recursive(recursive) // want "unnecessary conversion" + + _ = (*Constructor)(&ctor) // want "unnecessary conversion" + _ = (*Local)(&local) // want "unnecessary conversion" + _ = (*Recursive)(&recursive) // want "unnecessary conversion" } diff --git a/test/testdata/usestdlibvars_non_default.go b/test/testdata/usestdlibvars_non_default.go new file mode 100644 index 000000000000..c9915fad7a01 --- /dev/null +++ b/test/testdata/usestdlibvars_non_default.go @@ -0,0 +1,54 @@ +//golangcitest:args -Eusestdlibvars +//golangcitest:config_path testdata/configs/usestdlibvars_non_default.yml +package testdata + +import "net/http" + +func _200() { + _ = 200 +} + +func _200_1() { + var w http.ResponseWriter + w.WriteHeader(200) +} + +const ( + _ = "Bool" // want `"Bool" can be replaced by constant\.Bool\.String\(\)` + _ = "Complex" // want `"Complex" can be replaced by constant\.Complex\.String\(\)` +) + +const ( + _ = "BLAKE2b-256" // want `"BLAKE2b-256" can be replaced by crypto\.BLAKE2b_256\.String\(\)` + _ = "BLAKE2b-384" // want `"BLAKE2b-384" can be replaced by crypto\.BLAKE2b_384\.String\(\)` +) + +const ( + _ = "/_goRPC_" // want `"/_goRPC_" can be replaced by rpc\.DefaultRPCPath` + _ = "/debug/rpc" // want `"/debug/rpc" can be replaced by rpc\.DefaultDebugPath` +) + +const ( + _ = "Read Committed" // want `"Read Committed" can be replaced by sql\.LevelReadCommitted\.String\(\)` + _ = "Read Uncommitted" // want `"Read Uncommitted" can be replaced by sql\.LevelReadUncommitted\.String\(\)` +) + +const ( + _ = "01/02 03:04:05PM '06 -0700" // want `"01/02 03:04:05PM '06 -0700" can be replaced by time\.Layout` + _ = "02 Jan 06 15:04 -0700" // want `"02 Jan 06 15:04 -0700" can be replaced by time\.RFC822Z` +) + +const ( + _ = "April" // want `"April" can be replaced by time\.April\.String\(\)` + _ = "August" // want `"August" can be replaced by time\.August\.String\(\)` +) + +const ( + _ = "Friday" // want `"Friday" can be replaced by time\.Friday\.String\(\)` + _ = "Monday" // want `"Monday" can be replaced by time\.Monday\.String\(\)` +) + +const ( + _ = "ECDSAWithP256AndSHA256" // want `"ECDSAWithP256AndSHA256" can be replaced by tls\.ECDSAWithP256AndSHA256\.String\(\)` + _ = "ECDSAWithP384AndSHA384" // want `"ECDSAWithP384AndSHA384" can be replaced by tls\.ECDSAWithP384AndSHA384\.String\(\)` +) diff --git a/test/testdata/varcheck.go b/test/testdata/varcheck.go deleted file mode 100644 index 858c236d2010..000000000000 --- a/test/testdata/varcheck.go +++ /dev/null @@ -1,4 +0,0 @@ -//golangcitest:args -Evarcheck --internal-cmd-test -package testdata - -var v string // want "`v` is unused" diff --git a/test/testdata/wastedassign.go b/test/testdata/wastedassign.go index 714f3a6382a7..041b0f40bcbb 100644 --- a/test/testdata/wastedassign.go +++ b/test/testdata/wastedassign.go @@ -117,6 +117,18 @@ func mugen() { return } +func mugenG[T ~int](hoge T) { + var i int + for { + hoge = 5 // want "assigned to hoge, but reassigned without using the value" + // break + } + + println(i) + println(hoge) + return +} + func noMugen() { var i int var hoge int diff --git a/test/testdata/zerologlint/go.mod b/test/testdata/zerologlint/go.mod new file mode 100644 index 000000000000..7fa01dcba9f1 --- /dev/null +++ b/test/testdata/zerologlint/go.mod @@ -0,0 +1,14 @@ +module zerologlint + +go 1.19 + +require ( + github.com/rs/zerolog v1.29.1 + golang.org/x/exp v0.0.0-20230321023759-10a507213a29 +) + +require ( + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.18 // indirect + golang.org/x/sys v0.7.0 // indirect +) diff --git a/test/testdata/zerologlint/go.sum b/test/testdata/zerologlint/go.sum new file mode 100644 index 000000000000..8d3ce039655a --- /dev/null +++ b/test/testdata/zerologlint/go.sum @@ -0,0 +1,21 @@ +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= +github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.29.1 h1:cO+d60CHkknCbvzEWxP0S9K6KqyTjrCNUy1LdQLCGPc= +github.com/rs/zerolog v1.29.1/go.mod h1:Le6ESbR7hc+DP6Lt1THiV8CQSdkkNrd3R0XbEgp3ZBU= +golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= +golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/test/testdata/zerologlint/zerologlint.go b/test/testdata/zerologlint/zerologlint.go new file mode 100644 index 000000000000..d7e335de8358 --- /dev/null +++ b/test/testdata/zerologlint/zerologlint.go @@ -0,0 +1,77 @@ +//golangcitest:args -Ezerologlint +package zerologlint + +import ( + "fmt" + "slices" + + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" +) + +func expectWarnings() { + log.Error() // want "must be dispatched by Msg or Send method" + log.Info() // want "must be dispatched by Msg or Send method" + log.Fatal() // want "must be dispatched by Msg or Send method" + log.Debug() // want "must be dispatched by Msg or Send method" + log.Warn() // want "must be dispatched by Msg or Send method" + + err := fmt.Errorf("foobarerror") + log.Error().Err(err) // want "must be dispatched by Msg or Send method" + log.Error().Err(err).Str("foo", "bar").Int("foo", 1) // want "must be dispatched by Msg or Send method" + + logger := log.Error() // want "must be dispatched by Msg or Send method" + logger.Err(err).Str("foo", "bar").Int("foo", 1) + + // include zerolog.Dict() + log.Info(). // want "must be dispatched by Msg or Send method" + Str("foo", "bar"). + Dict("dict", zerolog.Dict(). + Str("bar", "baz"). + Int("n", 1), + ) + + // conditional + logger2 := log.Info() // want "must be dispatched by Msg or Send method" + if err != nil { + logger2 = log.Error() // want "must be dispatched by Msg or Send method" + } + logger2.Str("foo", "bar") +} + +func expectNoWarnings() { + log.Fatal().Send() + log.Panic().Msg("") + log.Debug().Send() + log.Info().Msg("") + log.Warn().Send() + log.Error().Msg("") + + log.Error().Str("foo", "bar").Send() + err := fmt.Errorf("foobarerror") + log.Error().Err(err).Str("foo", "bar").Int("foo", 1).Msg("") + + logger := log.Error() + logger.Send() + + // include zerolog.Dict() + log.Info(). + Str("foo", "bar"). + Dict("dict", zerolog.Dict(). + Str("bar", "baz"). + Int("n", 1), + ).Send() + + // conditional + logger2 := log.Info() + if err != nil { + logger2 = log.Error() + } + logger2.Send() +} + +// https://github.com/ykadowak/zerologlint/pull/2 +func packageNil() { + s := []int{1, 2, 3} + slices.Sort(s) +} diff --git a/test/testshared/analysis.go b/test/testshared/analysis.go index 9ef29fd81e02..3bc1d8e08898 100644 --- a/test/testshared/analysis.go +++ b/test/testshared/analysis.go @@ -110,7 +110,7 @@ func parseComments(sourcePath string, fileData []byte) (map[key][]expectation, e func parseExpectations(text string) (lineDelta int, expects []expectation, err error) { var scanErr string sc := new(scanner.Scanner).Init(strings.NewReader(text)) - sc.Error = func(s *scanner.Scanner, msg string) { + sc.Error = func(_ *scanner.Scanner, msg string) { scanErr = msg // e.g. bad string escape } sc.Mode = scanner.ScanIdents | scanner.ScanStrings | scanner.ScanRawStrings | scanner.ScanInts diff --git a/test/testshared/analysis_test.go b/test/testshared/analysis_test.go index 2c7f69666d06..7446b041c2f7 100644 --- a/test/testshared/analysis_test.go +++ b/test/testshared/analysis_test.go @@ -8,7 +8,6 @@ import ( "github.com/stretchr/testify/require" ) -//nolint:funlen func Test_parseComments(t *testing.T) { testCases := []struct { filename string diff --git a/test/testshared/directives.go b/test/testshared/directives.go index 01c011bb436f..34f37daf3a15 100644 --- a/test/testshared/directives.go +++ b/test/testshared/directives.go @@ -59,7 +59,13 @@ func ParseTestDirectives(tb testing.TB, sourcePath string) *RunContext { continue } - if !strings.HasPrefix(line, "//golangcitest:") { + switch { + case strings.HasPrefix(line, "//golangcitest:"): + // Ok + case !strings.Contains(line, "golangcitest"): + // Assume this is a regular comment (required for go-header tests) + continue + default: require.Failf(tb, "invalid prefix of comment line %s", line) } diff --git a/test/testshared/directives_test.go b/test/testshared/directives_test.go index ffe15c909bf0..2f8ec6c3291e 100644 --- a/test/testshared/directives_test.go +++ b/test/testshared/directives_test.go @@ -30,42 +30,42 @@ func Test_evaluateBuildTags(t *testing.T) { assert assert.BoolAssertionFunc }{ { - desc: "", + desc: "old build tag syntax, version inside the range", tag: "// +build go1.18", assert: assert.True, }, { - desc: "", + desc: "old build tag syntax, version outside the range", tag: "// +build go1.42", assert: assert.False, }, { - desc: "", + desc: "version inside the range", tag: "//go:build go1.18", assert: assert.True, }, { - desc: "", + desc: "version outside the range", tag: "//go:build go1.42", assert: assert.False, }, { - desc: "", + desc: "supported OS", tag: "//go:build " + runtime.GOOS, assert: assert.True, }, { - desc: "", + desc: "negate unsupported OS", tag: "//go:build !wondiws", assert: assert.True, }, { - desc: "", + desc: "unsupported OS", tag: "//go:build wondiws", assert: assert.False, }, { - desc: "", + desc: "version inside the range and supported OS", tag: "//go:build go1.18 && " + runtime.GOOS, assert: assert.True, }, diff --git a/test/testshared/runner.go b/test/testshared/runner.go index 329411a9cbec..0be6d7404930 100644 --- a/test/testshared/runner.go +++ b/test/testshared/runner.go @@ -163,13 +163,13 @@ func (b *RunnerBuilder) Runner() *Runner { b.tb.Fatal("--no-config and -c cannot be used at the same time") } - arguments := []string{ - "--go=1.17", // TODO(ldez): we force to use an old version of Go for the CI and the tests. - "--internal-cmd-test", - } + var arguments []string - if b.allowParallelRunners { - arguments = append(arguments, "--allow-parallel-runners") + if b.command == "run" { + arguments = append(arguments, "--internal-cmd-test") + if b.allowParallelRunners { + arguments = append(arguments, "--allow-parallel-runners") + } } if b.noConfig { @@ -350,7 +350,7 @@ func InstallGolangciLint(tb testing.TB) string { tb.Log(string(output)) } - assert.NoError(tb, err, "Can't go install golangci-lint %s", string(output)) + require.NoError(tb, err, "Can't go install golangci-lint %s", string(output)) } abs, err := filepath.Abs(defaultBinaryName()) diff --git a/test/testshared/runner_test.go b/test/testshared/runner_test.go index c647e8c13d98..5d2b3634387d 100644 --- a/test/testshared/runner_test.go +++ b/test/testshared/runner_test.go @@ -9,7 +9,6 @@ import ( "github.com/golangci/golangci-lint/pkg/exitcodes" ) -//nolint:funlen func TestRunnerBuilder_Runner(t *testing.T) { testCases := []struct { desc string @@ -23,20 +22,26 @@ func TestRunnerBuilder_Runner(t *testing.T) { env: []string(nil), command: "run", args: []string{ - "--go=1.17", "--internal-cmd-test", "--allow-parallel-runners", }, }, }, { - desc: "with command", + desc: "with non run command", builder: NewRunnerBuilder(t).WithCommand("example"), expected: &Runner{ env: []string(nil), command: "example", + }, + }, + { + desc: "with run command", + builder: NewRunnerBuilder(t).WithCommand("run"), + expected: &Runner{ + env: []string(nil), + command: "run", args: []string{ - "--go=1.17", "--internal-cmd-test", "--allow-parallel-runners", }, @@ -49,7 +54,6 @@ func TestRunnerBuilder_Runner(t *testing.T) { env: []string(nil), command: "run", args: []string{ - "--go=1.17", "--internal-cmd-test", "--allow-parallel-runners", "--no-config", @@ -63,7 +67,6 @@ func TestRunnerBuilder_Runner(t *testing.T) { env: []string(nil), command: "run", args: []string{ - "--go=1.17", "--internal-cmd-test", "--allow-parallel-runners", "-c", @@ -78,7 +81,6 @@ func TestRunnerBuilder_Runner(t *testing.T) { env: []string(nil), command: "run", args: []string{ - "--go=1.17", "--internal-cmd-test", "--allow-parallel-runners", "-c", @@ -96,7 +98,6 @@ func TestRunnerBuilder_Runner(t *testing.T) { env: []string{"FOO=BAR", "FII=BIR"}, command: "run", args: []string{ - "--go=1.17", "--internal-cmd-test", "--allow-parallel-runners", }, @@ -109,7 +110,6 @@ func TestRunnerBuilder_Runner(t *testing.T) { env: []string(nil), command: "run", args: []string{ - "--go=1.17", "--internal-cmd-test", }, }, @@ -121,7 +121,6 @@ func TestRunnerBuilder_Runner(t *testing.T) { env: []string(nil), command: "run", args: []string{ - "--go=1.17", "--internal-cmd-test", "--allow-parallel-runners", "-Efoo", @@ -137,7 +136,6 @@ func TestRunnerBuilder_Runner(t *testing.T) { env: []string(nil), command: "run", args: []string{ - "--go=1.17", "--internal-cmd-test", "--allow-parallel-runners", filepath.FromSlash("testdata/all.go"), @@ -156,7 +154,6 @@ func TestRunnerBuilder_Runner(t *testing.T) { env: []string(nil), command: "run", args: []string{ - "--go=1.17", "--internal-cmd-test", "--allow-parallel-runners", "-c", @@ -179,8 +176,6 @@ func TestRunnerBuilder_Runner(t *testing.T) { assert.NotNil(t, runner.log) assert.NotNil(t, runner.tb) assert.Equal(t, test.expected.env, runner.env) - assert.Equal(t, test.expected.env, runner.env) - assert.Equal(t, test.expected.env, runner.env) assert.Equal(t, test.expected.command, runner.command) assert.Equal(t, test.expected.args, runner.args) }) diff --git a/tools/go.mod b/tools/go.mod deleted file mode 100644 index c41a97068082..000000000000 --- a/tools/go.mod +++ /dev/null @@ -1,163 +0,0 @@ -module github.com/golangci/golangci-lint/tools - -go 1.19 - -require github.com/goreleaser/goreleaser v1.14.1 - -require ( - cloud.google.com/go v0.103.0 // indirect - cloud.google.com/go/compute v1.7.0 // indirect - cloud.google.com/go/iam v0.3.0 // indirect - cloud.google.com/go/kms v1.4.0 // indirect - cloud.google.com/go/storage v1.24.0 // indirect - code.gitea.io/sdk/gitea v0.15.1 // indirect - github.com/AlekSi/pointer v1.2.0 // indirect - github.com/Azure/azure-sdk-for-go v66.0.0+incompatible // indirect - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.1 // indirect - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.0.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.4.1 // indirect - github.com/Azure/go-autorest v14.2.0+incompatible // indirect - github.com/Azure/go-autorest/autorest v0.11.28 // indirect - github.com/Azure/go-autorest/autorest/adal v0.9.21 // indirect - github.com/Azure/go-autorest/autorest/azure/auth v0.5.11 // indirect - github.com/Azure/go-autorest/autorest/azure/cli v0.4.6 // indirect - github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect - github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect - github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect - github.com/Azure/go-autorest/logger v0.2.1 // indirect - github.com/Azure/go-autorest/tracing v0.6.0 // indirect - github.com/AzureAD/microsoft-authentication-library-for-go v0.4.0 // indirect - github.com/Masterminds/goutils v1.1.1 // indirect - github.com/Masterminds/semver v1.5.0 // indirect - github.com/Masterminds/semver/v3 v3.2.0 // indirect - github.com/Masterminds/sprig v2.22.0+incompatible // indirect - github.com/Microsoft/go-winio v0.5.2 // indirect - github.com/ProtonMail/go-crypto v0.0.0-20210512092938-c05353c2d58c // indirect - github.com/acomagu/bufpipe v1.0.3 // indirect - github.com/atc0005/go-teams-notify/v2 v2.7.0 // indirect - github.com/aws/aws-sdk-go v1.44.68 // indirect - github.com/aws/aws-sdk-go-v2 v1.16.8 // indirect - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.3 // indirect - github.com/aws/aws-sdk-go-v2/config v1.15.15 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.12.10 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.9 // indirect - github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.21 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.15 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.9 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.3.16 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.6 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.3 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.10 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.9 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.9 // indirect - github.com/aws/aws-sdk-go-v2/service/kms v1.18.1 // indirect - github.com/aws/aws-sdk-go-v2/service/s3 v1.27.2 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.11.13 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.16.10 // indirect - github.com/aws/smithy-go v1.12.0 // indirect - github.com/aymanbagabas/go-osc52 v1.2.1 // indirect - github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb // indirect - github.com/caarlos0/ctrlc v1.2.0 // indirect - github.com/caarlos0/env/v6 v6.10.1 // indirect - github.com/caarlos0/go-reddit/v3 v3.0.1 // indirect - github.com/caarlos0/go-shellwords v1.0.12 // indirect - github.com/caarlos0/log v0.2.1 // indirect - github.com/cavaliergopher/cpio v1.0.1 // indirect - github.com/cenkalti/backoff/v4 v4.1.3 // indirect - github.com/charmbracelet/lipgloss v0.6.0 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect - github.com/dghubble/go-twitter v0.0.0-20211115160449-93a8679adecb // indirect - github.com/dghubble/oauth1 v0.7.2 // indirect - github.com/dghubble/sling v1.4.0 // indirect - github.com/dimchansky/utfbom v1.1.1 // indirect - github.com/disgoorg/disgo v0.14.1 // indirect - github.com/disgoorg/json v1.0.0 // indirect - github.com/disgoorg/log v1.2.0 // indirect - github.com/disgoorg/snowflake/v2 v2.0.1 // indirect - github.com/emirpasic/gods v1.12.0 // indirect - github.com/go-git/gcfg v1.5.0 // indirect - github.com/go-git/go-billy/v5 v5.3.1 // indirect - github.com/go-git/go-git/v5 v5.4.2 // indirect - github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible // indirect - github.com/gobwas/glob v0.2.3 // indirect - github.com/golang-jwt/jwt v3.2.1+incompatible // indirect - github.com/golang-jwt/jwt/v4 v4.4.2 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.2 // indirect - github.com/google/go-cmp v0.5.9 // indirect - github.com/google/go-github/v48 v48.2.0 // indirect - github.com/google/go-querystring v1.1.0 // indirect - github.com/google/uuid v1.3.0 // indirect - github.com/google/wire v0.5.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.1.0 // indirect - github.com/googleapis/gax-go/v2 v2.4.0 // indirect - github.com/goreleaser/chglog v0.2.2 // indirect - github.com/goreleaser/fileglob v1.3.0 // indirect - github.com/goreleaser/nfpm/v2 v2.23.0 // indirect - github.com/gorilla/websocket v1.5.0 // indirect - github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-retryablehttp v0.7.1 // indirect - github.com/hashicorp/go-version v1.2.1 // indirect - github.com/huandu/xstrings v1.3.2 // indirect - github.com/iancoleman/orderedmap v0.2.0 // indirect - github.com/imdario/mergo v0.3.13 // indirect - github.com/inconshreveable/mousetrap v1.0.1 // indirect - github.com/invopop/jsonschema v0.7.0 // indirect - github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/kevinburke/ssh_config v1.1.0 // indirect - github.com/klauspost/compress v1.15.13 // indirect - github.com/klauspost/pgzip v1.2.5 // indirect - github.com/kylelemons/godebug v1.1.0 // indirect - github.com/lucasb-eyer/go-colorful v1.2.0 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect - github.com/mattn/go-mastodon v0.0.6 // indirect - github.com/mattn/go-runewidth v0.0.14 // indirect - github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/reflectwalk v1.0.2 // indirect - github.com/muesli/mango v0.1.0 // indirect - github.com/muesli/mango-cobra v1.2.0 // indirect - github.com/muesli/mango-pflag v0.1.0 // indirect - github.com/muesli/reflow v0.3.0 // indirect - github.com/muesli/roff v0.1.0 // indirect - github.com/muesli/termenv v0.13.0 // indirect - github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/rivo/uniseg v0.4.2 // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b // indirect - github.com/sergi/go-diff v1.2.0 // indirect - github.com/slack-go/slack v0.12.1 // indirect - github.com/spf13/cobra v1.6.1 // indirect - github.com/spf13/pflag v1.0.5 // indirect - github.com/technoweenie/multipartstreamer v1.0.1 // indirect - github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 // indirect - github.com/ulikunitz/xz v0.5.11 // indirect - github.com/withfig/autocomplete-tools/integrations/cobra v1.2.1 // indirect - github.com/xanzy/go-gitlab v0.77.0 // indirect - github.com/xanzy/ssh-agent v0.3.1 // indirect - gitlab.com/digitalxero/go-conventional-commit v1.0.7 // indirect - go.opencensus.io v0.23.0 // indirect - gocloud.dev v0.27.0 // indirect - golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect - golang.org/x/net v0.0.0-20220805013720-a33c5aa5df48 // indirect - golang.org/x/oauth2 v0.0.0-20220722155238-128564f6959c // indirect - golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect - golang.org/x/sys v0.1.0 // indirect - golang.org/x/text v0.5.0 // indirect - golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 // indirect - golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect - google.golang.org/api v0.91.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20220802133213-ce4fa296bf78 // indirect - google.golang.org/grpc v1.48.0 // indirect - google.golang.org/protobuf v1.28.1 // indirect - gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect - gopkg.in/mail.v2 v2.3.1 // indirect - gopkg.in/warnings.v0 v0.1.2 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect -) diff --git a/tools/go.sum b/tools/go.sum deleted file mode 100644 index c6fa04e33d9c..000000000000 --- a/tools/go.sum +++ /dev/null @@ -1,2493 +0,0 @@ -bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= -bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM= -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.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.82.0/go.mod h1:vlKccHJGuFBFufnAnuB08dfEH9Y3H7dzDzRECFdC2TA= -cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= -cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= -cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= -cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= -cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= -cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= -cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= -cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= -cloud.google.com/go v0.100.1/go.mod h1:fs4QogzfH5n2pBXBP9vRiU+eCny7lD2vmFZy79Iuw1U= -cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= -cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= -cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= -cloud.google.com/go v0.103.0 h1:YXtxp9ymmZjlGzxV7VrYQ8aaQuAgcqxSy6YhDX4I458= -cloud.google.com/go v0.103.0/go.mod h1:vwLx1nqLrzLX/fpwSMOXmFIqBOyHsvHbnAdbGSJ+mKk= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= -cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= -cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= -cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= -cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= -cloud.google.com/go/compute v1.7.0 h1:v/k9Eueb8aAJ0vZuxKMrgm6kPhCLZU9HxFU+AFDs9Uk= -cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= -cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c= -cloud.google.com/go/iam v0.3.0 h1:exkAomrVUuzx9kWFI1wm3KI0uoDeUFPB4kKGzx6x+Gc= -cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= -cloud.google.com/go/kms v1.4.0 h1:iElbfoE61VeLhnZcGOltqL8HIly8Nhbe5t6JlH9GXjo= -cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA= -cloud.google.com/go/monitoring v1.1.0/go.mod h1:L81pzz7HKn14QCMaCs6NTQkdBnE87TElyanS95vIcl4= -cloud.google.com/go/monitoring v1.5.0/go.mod h1:/o9y8NYX5j91JjD/JvGLYbi86kL11OjyJXq2XziLJu4= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/pubsub v1.24.0/go.mod h1:rWv09Te1SsRpRGPiWOMDKraMQTJyJps4MkUCoMGUgqw= -cloud.google.com/go/secretmanager v1.5.0/go.mod h1:5C9kM+RwSpkURNovKySkNvGQLUaOgyoR5W0RUx2SyHQ= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= -cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= -cloud.google.com/go/storage v1.24.0 h1:a4N0gIkx83uoVFGz8B2eAV3OhN90QoWF5OZWLKl39ig= -cloud.google.com/go/storage v1.24.0/go.mod h1:3xrJEFMXBsQLgxwThyjuD3aYlroL0TMRec1ypGUQ0KE= -cloud.google.com/go/trace v1.0.0/go.mod h1:4iErSByzxkyHWzzlAj63/Gmjz0NH1ASqhJguHpGcr6A= -cloud.google.com/go/trace v1.2.0/go.mod h1:Wc8y/uYyOhPy12KEnXG9XGrvfMz5F5SrYecQlbW1rwM= -code.cloudfoundry.org/clock v0.0.0-20180518195852-02e53af36e6c/go.mod h1:QD9Lzhd/ux6eNQVUDVRJX/RKTigpewimNYBi7ivZKY8= -code.gitea.io/gitea-vet v0.2.1/go.mod h1:zcNbT/aJEmivCAhfmkHOlT645KNOf9W2KnkLgFjGGfE= -code.gitea.io/sdk/gitea v0.15.1 h1:WJreC7YYuxbn0UDaPuWIe/mtiNKTvLN8MLkaw71yx/M= -code.gitea.io/sdk/gitea v0.15.1/go.mod h1:klY2LVI3s3NChzIk/MzMn7G1FHrfU7qd63iSMVoHRBA= -contrib.go.opencensus.io/exporter/aws v0.0.0-20200617204711-c478e41e60e9/go.mod h1:uu1P0UCM/6RbsMrgPa98ll8ZcHM858i/AD06a9aLRCA= -contrib.go.opencensus.io/exporter/stackdriver v0.13.13/go.mod h1:5pSSGY0Bhuk7waTHuDf4aQ8D2DrhgETRo9fy6k3Xlzc= -contrib.go.opencensus.io/integrations/ocsql v0.1.7/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20210715213245-6c3934b029d8/go.mod h1:CzsSbkDixRphAF5hS6wbMKq0eI6ccJRb7/A0M6JBnwg= -github.com/AlekSi/pointer v1.2.0 h1:glcy/gc4h8HnG2Z3ZECSzZ1IX1x2JxRVuDzaJwQE0+w= -github.com/AlekSi/pointer v1.2.0/go.mod h1:gZGfd3dpW4vEc/UlyfKKi1roIqcCgwOIvb0tSNSBle0= -github.com/Azure/azure-amqp-common-go/v3 v3.2.3/go.mod h1:7rPmbSfszeovxGfc5fSAXE4ehlXQZHpMja2OtxC2Tas= -github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go v63.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go v65.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go v66.0.0+incompatible h1:bmmC38SlE8/E81nNADlgmVGurPWMHDX2YNXVQMrBpEE= -github.com/Azure/azure-sdk-for-go v66.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.0.0/go.mod h1:uGG2W01BaETf0Ozp+QxxKJdMBNRWPdstHG0Fmdwn1/U= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.1 h1:tz19qLF65vuu2ibfTqGVJxG/zZAI27NEIIbvAOQwYbw= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.1/go.mod h1:uGG2W01BaETf0Ozp+QxxKJdMBNRWPdstHG0Fmdwn1/U= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.0.0 h1:Yoicul8bnVdQrhDMTHxdEckRGX01XvwXDHUT9zYZ3k0= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.0.0/go.mod h1:+6sju8gk8FRmSajX3Oz4G5Gm7P+mbqE9FVaXXFYTkCM= -github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 h1:jp0dGvZ7ZK0mgqnTSClMxa5xuRL7NZgHameVYF6BurY= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= -github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.0.2/go.mod h1:LH9XQnMr2ZYxQdVdCrzLO9mxeDyrDFa6wbSI3x5zCZk= -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.4.1 h1:QSdcrd/UFJv6Bp/CfoVf2SrENpFn9P6Yh8yb+xNhYMM= -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.4.1/go.mod h1:eZ4g6GUvXiGulfIbbhh1Xr4XwUYaYaWMqzGD/284wCA= -github.com/Azure/go-amqp v0.17.0/go.mod h1:9YJ3RhxRT1gquYnzpZO1vcYMMpAdJT+QEg6fwmw9Zlg= -github.com/Azure/go-amqp v0.17.5/go.mod h1:9YJ3RhxRT1gquYnzpZO1vcYMMpAdJT+QEg6fwmw9Zlg= -github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= -github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= -github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= -github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= -github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc= -github.com/Azure/go-autorest/autorest v0.11.25/go.mod h1:7l8ybrIdUmGqZMTD0sRtAr8NvbHjfofbf8RSP2q7w7U= -github.com/Azure/go-autorest/autorest v0.11.27/go.mod h1:7l8ybrIdUmGqZMTD0sRtAr8NvbHjfofbf8RSP2q7w7U= -github.com/Azure/go-autorest/autorest v0.11.28 h1:ndAExarwr5Y+GaHE6VCaY1kyS/HwwGGyuimVhWsHOEM= -github.com/Azure/go-autorest/autorest v0.11.28/go.mod h1:MrkzG3Y3AH668QyF9KRk5neJnGgmhQ6krbhR8Q5eMvA= -github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= -github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= -github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= -github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= -github.com/Azure/go-autorest/autorest/adal v0.9.20/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= -github.com/Azure/go-autorest/autorest/adal v0.9.21 h1:jjQnVFXPfekaqb8vIsv2G1lxshoW+oGv4MDlhRtnYZk= -github.com/Azure/go-autorest/autorest/adal v0.9.21/go.mod h1:zua7mBUaCc5YnSLKYgGJR/w5ePdMDA6H56upLsHzA9U= -github.com/Azure/go-autorest/autorest/azure/auth v0.5.11 h1:P6bYXFoao05z5uhOQzbC3Qd8JqF3jUoocoTeIxkp2cA= -github.com/Azure/go-autorest/autorest/azure/auth v0.5.11/go.mod h1:84w/uV8E37feW2NCJ08uT9VBfjfUHpgLVnG2InYD6cg= -github.com/Azure/go-autorest/autorest/azure/cli v0.4.5/go.mod h1:ADQAXrkgm7acgWVUNamOgh8YNrv4p27l3Wc55oVfpzg= -github.com/Azure/go-autorest/autorest/azure/cli v0.4.6 h1:w77/uPk80ZET2F+AfQExZyEWtn+0Rk/uw17m9fv5Ajc= -github.com/Azure/go-autorest/autorest/azure/cli v0.4.6/go.mod h1:piCfgPho7BiIDdEQ1+g4VmKyD5y+p/XtSNqE6Hc4QD0= -github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/autorest/mocks v0.4.2 h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw= -github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU= -github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk= -github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= -github.com/Azure/go-autorest/autorest/validation v0.3.1 h1:AgyqjAd94fwNAoTjl/WQXg4VvFeRFpO+UhNyRXqF1ac= -github.com/Azure/go-autorest/autorest/validation v0.3.1/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E= -github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= -github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= -github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= -github.com/AzureAD/microsoft-authentication-library-for-go v0.4.0 h1:WVsrXCnHlDDX8ls+tootqRE87/hL9S/g4ewig9RsD/c= -github.com/AzureAD/microsoft-authentication-library-for-go v0.4.0/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= -github.com/GoogleCloudPlatform/cloudsql-proxy v1.31.2/go.mod h1:qR6jVnZTKDCW3j+fC9mOEPHm++1nKDMkqbbkD6KNsfo= -github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= -github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= -github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= -github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= -github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= -github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= -github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= -github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= -github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= -github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= -github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= -github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= -github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= -github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= -github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= -github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8= -github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= -github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= -github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= -github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= -github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= -github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= -github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= -github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= -github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= -github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= -github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= -github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= -github.com/ProtonMail/go-crypto v0.0.0-20210512092938-c05353c2d58c h1:bNpaLLv2Y4kslsdkdCwAYu8Bak1aGVtxwi8Z/wy4Yuo= -github.com/ProtonMail/go-crypto v0.0.0-20210512092938-c05353c2d58c/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= -github.com/ProtonMail/go-mime v0.0.0-20220302105931-303f85f7fe0f h1:CGq7OieOz3wyQJ1fO8S0eO9TCW1JyvLrf8fhzz1i8ko= -github.com/ProtonMail/gopenpgp/v2 v2.2.2 h1:u2m7xt+CZWj88qK1UUNBoXeJCFJwJCZ/Ff4ymGoxEXs= -github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= -github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= -github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk= -github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= -github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= -github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= -github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-metrics v0.3.3/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/atc0005/go-teams-notify/v2 v2.7.0 h1:yRKblRTM/v+FnbibPAQiBcgT+aUBn/8zj9E/UxBdIRg= -github.com/atc0005/go-teams-notify/v2 v2.7.0/go.mod h1:nJeYAr8U1KtT376MUHHiy47nqy/4Mn0UR8veVQxdMcM= -github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= -github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= -github.com/aws/aws-sdk-go v1.15.27/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= -github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= -github.com/aws/aws-sdk-go v1.43.11/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= -github.com/aws/aws-sdk-go v1.43.31/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= -github.com/aws/aws-sdk-go v1.44.45/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= -github.com/aws/aws-sdk-go v1.44.68 h1:7zNr5+HLG0TMq+ZcZ8KhT4eT2KyL7v+u7/jANKEIinM= -github.com/aws/aws-sdk-go v1.44.68/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= -github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/aws/aws-sdk-go-v2 v1.16.8 h1:gOe9UPR98XSf7oEJCcojYg+N2/jCRm4DdeIsP85pIyQ= -github.com/aws/aws-sdk-go-v2 v1.16.8/go.mod h1:6CpKuLXg2w7If3ABZCl/qZ6rEgwtjZTn4eAf4RcEyuw= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.3 h1:S/ZBwevQkr7gv5YxONYpGQxlMFFYSRfz3RMcjsC9Qhk= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.3/go.mod h1:gNsR5CaXKmQSSzrmGxmwmct/r+ZBfbxorAuXYsj/M5Y= -github.com/aws/aws-sdk-go-v2/config v1.15.15 h1:yBV+J7Au5KZwOIrIYhYkTGJbifZPCkAnCFSvGsF3ui8= -github.com/aws/aws-sdk-go-v2/config v1.15.15/go.mod h1:A1Lzyy/o21I5/s2FbyX5AevQfSVXpvvIDCoVFD0BC4E= -github.com/aws/aws-sdk-go-v2/credentials v1.12.10 h1:7gGcMQePejwiKoDWjB9cWnpfVdnz/e5JwJFuT6OrroI= -github.com/aws/aws-sdk-go-v2/credentials v1.12.10/go.mod h1:g5eIM5XRs/OzIIK81QMBl+dAuDyoLN0VYaLP+tBqEOk= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.9 h1:hz8tc+OW17YqxyFFPSkvfSikbqWcyyHRyPVSTzC0+aI= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.9/go.mod h1:KDCCm4ONIdHtUloDcFvK2+vshZvx4Zmj7UMDfusuz5s= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.21 h1:bpiKFJ9aC0xTVpygSRRRL/YHC1JZ+pHQHENATHuoiwo= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.21/go.mod h1:iIYPrQ2rYfZiB/iADYlhj9HHZ9TTi6PqKQPAqygohbE= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.15 h1:bx5F2mr6H6FC7zNIQoDoUr8wEKnvmwRncujT3FYRtic= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.15/go.mod h1:pWrr2OoHlT7M/Pd2y4HV3gJyPb3qj5qMmnPkKSNPYK4= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.9 h1:5sbyznZC2TeFpa4fvtpvpcGbzeXEEs1l1Jo51ynUNsQ= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.9/go.mod h1:08tUpeSGN33QKSO7fwxXczNfiwCpbj+GxK6XKwqWVv0= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.16 h1:f0ySVcmQhwmzn7zQozd8wBM3yuGBfzdpsOaKQ0/Epzw= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.16/go.mod h1:CYmI+7x03jjJih8kBEEFKRQc40UjUokT0k7GbvrhhTc= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.6 h1:3L8pcjvgaSOs0zzZcMKzxDSkYKEpwJ2dNVDdxm68jAY= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.6/go.mod h1:O7Oc4peGZDEKlddivslfYFvAbgzvl/GH3J8j3JIGBXc= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.3 h1:4n4KCtv5SUoT5Er5XV41huuzrCqepxlW3SDI9qHQebc= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.3/go.mod h1:gkb2qADY+OHaGLKNTYxMaQNacfeyQpZ4csDTQMeFmcw= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.10 h1:7LJcuRalaLw+GYQTMGmVUl4opg2HrDZkvn/L3KvIQfw= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.10/go.mod h1:Qks+dxK3O+Z2deAhNo6cJ8ls1bam3tUGUAcgxQP1c70= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.9 h1:sHfDuhbOuuWSIAEDd3pma6p0JgUcR2iePxtCE8gfCxQ= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.9/go.mod h1:yQowTpvdZkFVuHrLBXmczat4W+WJKg/PafBZnGBLga0= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.9 h1:sJdKvydGYDML9LTFcp6qq6Z5fIjN0Rdq2Gvw1hUg8tc= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.9/go.mod h1:Rc5+wn2k8gFSi3V1Ch4mhxOzjMh+bYSXVFfVaqowQOY= -github.com/aws/aws-sdk-go-v2/service/kms v1.18.1 h1:y07kzPdcjuuyDVYWf1CCsQQ6kcAWMbFy+yIJ71xQBS0= -github.com/aws/aws-sdk-go-v2/service/kms v1.18.1/go.mod h1:4PZMUkc9rXHWGVB5J9vKaZy3D7Nai79ORworQ3ASMiM= -github.com/aws/aws-sdk-go-v2/service/s3 v1.27.2 h1:NvzGue25jKnuAsh6yQ+TZ4ResMcnp49AWgWGm2L4b5o= -github.com/aws/aws-sdk-go-v2/service/s3 v1.27.2/go.mod h1:u+566cosFI+d+motIz3USXEh6sN8Nq4GrNXSg2RXVMo= -github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.15.14/go.mod h1:xakbH8KMsQQKqzX87uyyzTHshc/0/Df8bsTneTS5pFU= -github.com/aws/aws-sdk-go-v2/service/sns v1.17.10/go.mod h1:uITsRNVMeCB3MkWpXxXw0eDz8pW4TYLzj+eyQtbhSxM= -github.com/aws/aws-sdk-go-v2/service/sqs v1.19.1/go.mod h1:A94o564Gj+Yn+7QO1eLFeI7UVv3riy/YBFOfICVqFvU= -github.com/aws/aws-sdk-go-v2/service/ssm v1.27.6/go.mod h1:fiFzQgj4xNOg4/wqmAiPvzgDMXPD+cUEplX/CYn+0j0= -github.com/aws/aws-sdk-go-v2/service/sso v1.11.13 h1:DQpf+al+aWozOEmVEdml67qkVZ6vdtGUi71BZZWw40k= -github.com/aws/aws-sdk-go-v2/service/sso v1.11.13/go.mod h1:d7ptRksDDgvXaUvxyHZ9SYh+iMDymm94JbVcgvSYSzU= -github.com/aws/aws-sdk-go-v2/service/sts v1.16.10 h1:7tquJrhjYz2EsCBvA9VTl+sBAAh1bv7h/sGASdZOGGo= -github.com/aws/aws-sdk-go-v2/service/sts v1.16.10/go.mod h1:cftkHYN6tCDNfkSasAmclSfl4l7cySoay8vz7p/ce0E= -github.com/aws/smithy-go v1.12.0 h1:gXpeZel/jPoWQ7OEmLIgCUnhkFftqNfwWUwAHSlp1v0= -github.com/aws/smithy-go v1.12.0/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= -github.com/aymanbagabas/go-osc52 v1.0.3/go.mod h1:zT8H+Rk4VSabYN90pWyugflM3ZhpTZNC7cASDfUCdT4= -github.com/aymanbagabas/go-osc52 v1.2.1 h1:q2sWUyDcozPLcLabEMd+a+7Ea2DitxZVN9hTxab9L4E= -github.com/aymanbagabas/go-osc52 v1.2.1/go.mod h1:zT8H+Rk4VSabYN90pWyugflM3ZhpTZNC7cASDfUCdT4= -github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= -github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= -github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb h1:m935MPodAbYS46DG4pJSv7WO+VECIWUQ7OJYSoTrMh4= -github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI= -github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= -github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= -github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= -github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= -github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= -github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= -github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= -github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= -github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= -github.com/caarlos0/ctrlc v1.2.0 h1:AtbThhmbeYx1WW3WXdWrd94EHKi+0NPRGS4/4pzrjwk= -github.com/caarlos0/ctrlc v1.2.0/go.mod h1:n3gDlSjsXZ7rbD9/RprIR040b7oaLfNStikPd4gFago= -github.com/caarlos0/env/v6 v6.10.1 h1:t1mPSxNpei6M5yAeu1qtRdPAK29Nbcf/n3G7x+b3/II= -github.com/caarlos0/env/v6 v6.10.1/go.mod h1:hvp/ryKXKipEkcuYjs9mI4bBCg+UI0Yhgm5Zu0ddvwc= -github.com/caarlos0/go-reddit/v3 v3.0.1 h1:w8ugvsrHhaE/m4ez0BO/sTBOBWI9WZTjG7VTecHnql4= -github.com/caarlos0/go-reddit/v3 v3.0.1/go.mod h1:QlwgmG5SAqxMeQvg/A2dD1x9cIZCO56BMnMdjXLoisI= -github.com/caarlos0/go-rpmutils v0.2.1-0.20211112020245-2cd62ff89b11 h1:IRrDwVlWQr6kS1U8/EtyA1+EHcc4yl8pndcqXWrEamg= -github.com/caarlos0/go-shellwords v1.0.12 h1:HWrUnu6lGbWfrDcFiHcZiwOLzHWjjrPVehULaTFgPp8= -github.com/caarlos0/go-shellwords v1.0.12/go.mod h1:bYeeX1GrTLPl5cAMYEzdm272qdsQAZiaHgeF0KTk1Gw= -github.com/caarlos0/log v0.2.1 h1:E5vf0Sg24tUbrGanknDu2UH0CZq6cCColThb8gTQnHQ= -github.com/caarlos0/log v0.2.1/go.mod h1:BLxpdZKXvWBjB6fshua4c8d7ApdYjypEDok6ibt+pXk= -github.com/caarlos0/sshmarshal v0.0.0-20220308164159-9ddb9f83c6b3 h1:w2ANoiT4ubmh4Nssa3/QW1M7lj3FZkma8f8V5aBDxXM= -github.com/caarlos0/testfs v0.4.4 h1:3PHvzHi5Lt+g332CiShwS8ogTgS3HjrmzZxCm6JCDr8= -github.com/caarlos0/testfs v0.4.4/go.mod h1:bRN55zgG4XCUVVHZCeU+/Tz1Q6AxEJOEJTliBy+1DMk= -github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= -github.com/cavaliergopher/cpio v1.0.1 h1:KQFSeKmZhv0cr+kawA3a0xTQCU4QxXF1vhU7P7av2KM= -github.com/cavaliergopher/cpio v1.0.1/go.mod h1:pBdaqQjnvXxdS/6CvNDwIANIFSP0xRKI16PX4xejRQc= -github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= -github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= -github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= -github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= -github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/charmbracelet/keygen v0.3.0 h1:mXpsQcH7DDlST5TddmXNXjS0L7ECk4/kLQYyBcsan2Y= -github.com/charmbracelet/lipgloss v0.6.0 h1:1StyZB9vBSOyuZxQUcUwGr17JmojPNm87inij9N3wJY= -github.com/charmbracelet/lipgloss v0.6.0/go.mod h1:tHh2wr34xcHjC2HCXIlGSG1jaDF0S0atAUvBMP6Ppuk= -github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= -github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= -github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= -github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc= -github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= -github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= -github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= -github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= -github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= -github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= -github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= -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-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -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-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -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-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= -github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= -github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= -github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= -github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= -github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= -github.com/containerd/aufs v1.0.0/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= -github.com/containerd/btrfs v0.0.0-20201111183144-404b9149801e/go.mod h1:jg2QkJcsabfHugurUvvPhS3E08Oxiuh5W/g1ybB4e0E= -github.com/containerd/btrfs v0.0.0-20210316141732-918d888fb676/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= -github.com/containerd/btrfs v1.0.0/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= -github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI= -github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= -github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= -github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= -github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= -github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= -github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= -github.com/containerd/cgroups v1.0.3/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8= -github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= -github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= -github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= -github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= -github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= -github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= -github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ= -github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU= -github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI= -github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= -github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g= -github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c= -github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s= -github.com/containerd/containerd v1.6.1/go.mod h1:1nJz5xCZPusx6jJU8Frfct988y0NpumIq9ODB0kLtoE= -github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= -github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= -github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ= -github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= -github.com/containerd/continuity v0.2.2/go.mod h1:pWygW9u7LtS1o4N/Tn0FoCFDIXZ7rxcMX7HX1Dmibvk= -github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= -github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= -github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= -github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= -github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= -github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= -github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= -github.com/containerd/go-cni v1.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZHtSlv++smU= -github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk= -github.com/containerd/go-cni v1.1.0/go.mod h1:Rflh2EJ/++BA2/vY5ao3K6WJRR/bZKsX123aPk+kUtA= -github.com/containerd/go-cni v1.1.3/go.mod h1:Rflh2EJ/++BA2/vY5ao3K6WJRR/bZKsX123aPk+kUtA= -github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= -github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= -github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHrqVs8FTi9vpyHwPwiNEGaACDxT/N/pLcvMSRA9g= -github.com/containerd/go-runc v0.0.0-20201020171139-16b287bc67d0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= -github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= -github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak9TYCG3juvb0= -github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6TNsg0ctmizkrOgXRNQjAPFWpMYRWuiB6dSF4Pfa5SA= -github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow= -github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms= -github.com/containerd/imgcrypt v1.1.3/go.mod h1:/TPA1GIDXMzbj01yd8pIbQiLdQxed5ue1wb8bP7PQu4= -github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c= -github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= -github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= -github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM= -github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= -github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= -github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= -github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= -github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= -github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ= -github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= -github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk= -github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg= -github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= -github.com/containerd/zfs v0.0.0-20200918131355-0a33824f23a2/go.mod h1:8IgZOBdv8fAgXddBT4dBXJPtxyRsejFIpXoklgxgEjw= -github.com/containerd/zfs v0.0.0-20210301145711-11e8f1707f62/go.mod h1:A9zfAbMlQwE+/is6hi0Xw8ktpL+6glmqZYtevJgaB8Y= -github.com/containerd/zfs v0.0.0-20210315114300-dde8f0fda960/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= -github.com/containerd/zfs v0.0.0-20210324211415-d5c4544f0433/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= -github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= -github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/containernetworking/cni v1.0.1/go.mod h1:AKuhXbN5EzmD4yTNtfSsX3tPcmtrBI6QcRV0NiNt15Y= -github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM= -github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= -github.com/containernetworking/plugins v1.0.1/go.mod h1:QHCfGpaTwYTbbH+nZXKVTxNBDZcxSOplJT5ico8/FLE= -github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc= -github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4= -github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= -github.com/containers/ocicrypt v1.1.2/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= -github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= -github.com/coreos/go-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q= -github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= -github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= -github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= -github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= -github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= -github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I= -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/denisenkom/go-mssqldb v0.12.2/go.mod h1:lnIw1mZukFRZDJYQ0Pb833QS2IaC3l5HkEfra2LJ+sk= -github.com/dennwc/varint v1.0.0/go.mod h1:hnItb35rvZvJrbTALZtY/iQfDs48JKRG1RPpgziApxA= -github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= -github.com/devigned/tab v0.1.1/go.mod h1:XG9mPq0dFghrYvoBF3xdRrJzSTX1b7IQrvaL9mzjeJY= -github.com/dghubble/go-twitter v0.0.0-20211115160449-93a8679adecb h1:7ENzkH+O3juL+yj2undESLTaAeRllHwCs/b8z6aWSfc= -github.com/dghubble/go-twitter v0.0.0-20211115160449-93a8679adecb/go.mod h1:qhZBgV9e4WyB1JNjHpcXVkUe3knWUwYuAPB1hITdm50= -github.com/dghubble/oauth1 v0.7.2 h1:pwcinOZy8z6XkNxvPmUDY52M7RDPxt0Xw1zgZ6Cl5JA= -github.com/dghubble/oauth1 v0.7.2/go.mod h1:9erQdIhqhOHG/7K9s/tgh9Ks/AfoyrO5mW/43Lu2+kE= -github.com/dghubble/sling v1.4.0 h1:/n8MRosVTthvMbwlNZgLx579OGVjUOy3GNEv5BIqAWY= -github.com/dghubble/sling v1.4.0/go.mod h1:0r40aNsU9EdDUVBNhfCstAtFgutjgJGYbO1oNzkMoM8= -github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/dgryski/go-sip13 v0.0.0-20200911182023-62edffca9245/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/digitalocean/godo v1.78.0/go.mod h1:GBmu8MkjZmNARE7IXRPmkbbnocNN8+uBm0xbEVw2LCs= -github.com/digitalocean/godo v1.81.0/go.mod h1:BPCqvwbjbGqxuUnIKB4EvS/AX7IDnNmt5fwvIkWo+ew= -github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= -github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= -github.com/disgoorg/disgo v0.14.1 h1:J1GoRZfbCPFcNd3OH+W3XbAVEdvV3kVAoNqJrPjzY1I= -github.com/disgoorg/disgo v0.14.1/go.mod h1:YiVpXSmyXLRalYQHTHUFWEQvolCNzw0zh6nfug07b/M= -github.com/disgoorg/json v1.0.0 h1:kDhSM661fgIuNoZF3BO5/odaR5NSq80AWb937DH+Pdo= -github.com/disgoorg/json v1.0.0/go.mod h1:BHDwdde0rpQFDVsRLKhma6Y7fTbQKub/zdGO5O9NqqA= -github.com/disgoorg/log v1.2.0 h1:sqlXnu/ZKAlIlHV9IO+dbMto7/hCQ474vlIdMWk8QKo= -github.com/disgoorg/log v1.2.0/go.mod h1:3x1KDG6DI1CE2pDwi3qlwT3wlXpeHW/5rVay+1qDqOo= -github.com/disgoorg/snowflake/v2 v2.0.1 h1:CuUxGLwggUxEswZOmZ+mZ5i0xSumQdXW9tXW7uGqe+0= -github.com/disgoorg/snowflake/v2 v2.0.1/go.mod h1:SPU9c2CNn5DSyb86QcKtdZgix9osEtKrHLW4rMhfLCs= -github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= -github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko= -github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= -github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= -github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/cli v20.10.14+incompatible h1:dSBKJOVesDgHo7rbxlYjYsXe7gPzrTT+/cKQgpDAazg= -github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= -github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v20.10.14+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v20.10.17+incompatible h1:JYCuMrWaVNophQTOrMMoSwudOVEfcegoZZrleKc1xwE= -github.com/docker/docker v20.10.17+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= -github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= -github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= -github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= -github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= -github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= -github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= -github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= -github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= -github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= -github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= -github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= -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.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= -github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= -github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= -github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= -github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= -github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= -github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= -github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= -github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= -github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= -github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= -github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= -github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= -github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= -github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U= -github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= -github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= -github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= -github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-billy/v5 v5.3.1 h1:CPiOUAzKtMRvolEKw+bG1PLRpT7D3LIs3/3ey4Aiu34= -github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-git-fixtures/v4 v4.2.1 h1:n9gGL1Ct/yIw+nfsfr8s4+sbhT+Ncu2SubfXjIWgci8= -github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0= -github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4= -github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.1/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/stdr v1.2.0/go.mod h1:YkVgnZu1ZjjL7xTxrfm/LLZBfkhTqSR1ydtm6jTKKwI= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-openapi/analysis v0.21.2/go.mod h1:HZwRk4RRisyG8vx2Oe6aqeSQcoxRp47Xkp3+K6q+LdY= -github.com/go-openapi/errors v0.19.8/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.19.9/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.20.2/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= -github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= -github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= -github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= -github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= -github.com/go-openapi/loads v0.21.1/go.mod h1:/DtAMXXneXFjbQMGEtbamCZb+4x7eGwkvZCvBmwUG+g= -github.com/go-openapi/runtime v0.23.1/go.mod h1:AKurw9fNre+h3ELZfk6ILsfvPN+bvvlaU/M9q/r9hpk= -github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= -github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= -github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= -github.com/go-openapi/strfmt v0.21.0/go.mod h1:ZRQ409bWMj+SOgXofQAGTIo2Ebu72Gs+WaRADcS5iNg= -github.com/go-openapi/strfmt v0.21.1/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k= -github.com/go-openapi/strfmt v0.21.2/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k= -github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= -github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/validate v0.21.0/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg= -github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= -github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= -github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= -github.com/go-resty/resty/v2 v2.1.1-0.20191201195748-d7b97669fe48/go.mod h1:dZGr0i9PLlaaTD4H/hoZIDjQ+r6xq8mgbRzHZf7f2J8= -github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible h1:2cauKuaELYAEARXRkq2LrJ0yDDv1rW7+wrTEdVL3uaU= -github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM= -github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho= -github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= -github.com/go-zookeeper/zk v1.0.2/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= -github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= -github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= -github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= -github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= -github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= -github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs= -github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= -github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= -github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk= -github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28= -github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo= -github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk= -github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw= -github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360= -github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg= -github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE= -github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8= -github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= -github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= -github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= -github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= -github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= -github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= -github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= -github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= -github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= -github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= -github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= -github.com/goccy/go-yaml v1.9.5/go.mod h1:U/jl18uSupI5rdI2jmuCswEA2htH9eXfferR3KfscvA= -github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= -github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= -github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= -github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= -github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= -github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c= -github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= -github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs= -github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= -github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -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/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/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.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -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.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= -github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= -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.4.1/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.1/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.4/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.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0= -github.com/google/go-github/v48 v48.2.0 h1:68puzySE6WqUY9KWmpOsDEQfDZsso98rT6pZcz9HqcE= -github.com/google/go-github/v48 v48.2.0/go.mod h1:dDlehKBDo850ZPvCTK0sEqTCVWcrGl2LcDiajkYi89Y= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= -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/go-replayers/grpcreplay v1.1.0 h1:S5+I3zYyZ+GQz68OfbURDdt/+cSMqCK1wrvNx7WBzTE= -github.com/google/go-replayers/grpcreplay v1.1.0/go.mod h1:qzAvJ8/wi57zq7gWqaE6AwLM6miiXUQwP1S+I9icmhk= -github.com/google/go-replayers/httpreplay v1.1.1 h1:H91sIMlt1NZzN7R+/ASswyouLJfW0WLW7fhyUFvDEkY= -github.com/google/go-replayers/httpreplay v1.1.1/go.mod h1:gN9GeLIs7l6NUoVaSSnv2RiqK1NiwAmD0MrKeC9IIks= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible h1:xmapqc1AyLoB+ddYT6r04bD9lIjlOqGaREovi0SzFaE= -github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= -github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= -github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210506205249-923b5ab0fc1a/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20220318212150-b2ab0324ddda/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= -github.com/google/pprof v0.0.0-20220608213341-c488b8fa1db3/go.mod h1:gSuNB+gJaOiQKLEZ+q+PK9Mq3SOzhRcw2GsGS/FhYDk= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= -github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= -github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0/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/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8= -github.com/google/wire v0.5.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU= -github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= -github.com/googleapis/enterprise-certificate-proxy v0.1.0 h1:zO8WHNx/MYiAKJ3d5spxZXZE6KHmIQGQcAzwUzV7qQw= -github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= -github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= -github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= -github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= -github.com/googleapis/gax-go/v2 v2.4.0 h1:dS9eYAjhrE2RjmzYw2XAPvcXfmcQLtFEQWn0CR82awk= -github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= -github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= -github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= -github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= -github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= -github.com/gophercloud/gophercloud v0.24.0/go.mod h1:Q8fZtyi5zZxPS/j9aj3sSxtvj41AdQMDwyo1myduD5c= -github.com/gophercloud/gophercloud v0.25.0/go.mod h1:Q8fZtyi5zZxPS/j9aj3sSxtvj41AdQMDwyo1myduD5c= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/goreleaser/chglog v0.2.2 h1:V7nf07baXtGAgGevvqgW2MM4kZ6gOr12vKNSAU3VIZ0= -github.com/goreleaser/chglog v0.2.2/go.mod h1:2s5JwtCOWjZa8AIneL+xdUl9SRuigCjRHNHsX30dupE= -github.com/goreleaser/fileglob v1.3.0 h1:/X6J7U8lbDpQtBvGcwwPS6OpzkNVlVEsFUVRx9+k+7I= -github.com/goreleaser/fileglob v1.3.0/go.mod h1:Jx6BoXv3mbYkEzwm9THo7xbr5egkAraxkGorbJb4RxU= -github.com/goreleaser/goreleaser v1.14.1 h1:b+cW4BSDL5Ii32scSX8IoXrnpwHIItXgZyMskBhNK8s= -github.com/goreleaser/goreleaser v1.14.1/go.mod h1:Fy+WdlEubGsR0VqAEqQhmdowIRM10mQ0uB1/Pfhqdng= -github.com/goreleaser/nfpm/v2 v2.23.0 h1:ZcurGlXkaaY2XFHP7XvstjiJ+aGBGsYfKufxwYZnjkk= -github.com/goreleaser/nfpm/v2 v2.23.0/go.mod h1:Tpqen33Ol5R31AY1uYBJv/dinpifuoMtvp3V0eqDpbU= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= -github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grafana/regexp v0.0.0-20220304095617-2e8d9baf4ac2/go.mod h1:M5qHK+eWfAv8VR/265dIuEpL3fNfeC21tXXp9itM24A= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.10.2/go.mod h1:chrfS3YoLAlKTRE5cFWvCbt8uGAjshktT4PveTUpsFQ= -github.com/hanwen/go-fuse v1.0.0/go.mod h1:unqXarDXqzAk0rt98O2tVndEPIpUgLD9+rwFisZH3Ok= -github.com/hanwen/go-fuse/v2 v2.1.0/go.mod h1:oRyA5eK+pvJyv5otpO/DgccS8y/RvYMaO00GgRLGryc= -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= -github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0= -github.com/hashicorp/consul/api v1.13.0/go.mod h1:ZlVrynguJKcYr54zGaDbaL3fOvKC9m72FhPvA8T35KQ= -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= -github.com/hashicorp/cronexpr v1.1.1/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4= -github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= -github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= -github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-hclog v0.12.2 h1:F1fdYblUEsxKiailtkhCCG2g4bipEgaHiDc8vffNpD4= -github.com/hashicorp/go-hclog v0.12.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-immutable-radix v1.2.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= -github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= -github.com/hashicorp/go-retryablehttp v0.7.1 h1:sUiuQAnLlbvmExtFQs72iFW/HXeUn8Z1aJLQ4LJJbTQ= -github.com/hashicorp/go-retryablehttp v0.7.1/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI= -github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= -github.com/hashicorp/memberlist v0.3.1/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= -github.com/hashicorp/nomad/api v0.0.0-20220629141207-c2428e1673ec/go.mod h1:jP79oXjopTyH6E8LF0CEMq67STgrlmBRIyijA0tuR5o= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= -github.com/hetznercloud/hcloud-go v1.33.1/go.mod h1:XX/TQub3ge0yWR2yHWmnDVIrB+MQbda1pHxkUmDlUME= -github.com/hetznercloud/hcloud-go v1.35.0/go.mod h1:mepQwR6va27S3UQthaEPGS86jtzSY9xWL1e9dyxXpgA= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= -github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= -github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA= -github.com/iancoleman/orderedmap v0.2.0 h1:sq1N/TFpYH++aViPcaKjys3bDClUEU7s5B+z6jq8pNA= -github.com/iancoleman/orderedmap v0.2.0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA= -github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= -github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= -github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= -github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= -github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= -github.com/intel/goresctrl v0.2.0/go.mod h1:+CZdzouYFn5EsxgqAQTEzMfwKwuc0fVdMrT9FCCAVRQ= -github.com/invopop/jsonschema v0.7.0 h1:2vgQcBz1n256N+FpX3Jq7Y17AjYt46Ig3zIWyy770So= -github.com/invopop/jsonschema v0.7.0/go.mod h1:O9uiLokuu0+MGFlyiaqtWxwqJm41/+8Nj0lD7A36YH0= -github.com/ionos-cloud/sdk-go/v6 v6.1.0/go.mod h1:Ox3W0iiEz0GHnfY9e5LmAxwklsxguuNFEUSu0gVRTME= -github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= -github.com/j-keck/arping v1.0.2/go.mod h1:aJbELhR92bSk7tp79AWM/ftfc90EfEi2bQJrbBFOsPw= -github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= -github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= -github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= -github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= -github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= -github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= -github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= -github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= -github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= -github.com/jackc/pgconn v1.12.1/go.mod h1:ZkhRC59Llhrq3oSfrikvwQ5NaxYExr6twkdkMLaKono= -github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= -github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= -github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= -github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= -github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= -github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= -github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= -github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.3.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= -github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= -github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= -github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= -github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= -github.com/jackc/pgtype v1.11.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= -github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= -github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= -github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= -github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= -github.com/jackc/pgx/v4 v4.16.1/go.mod h1:SIhx0D5hoADaiXZVyv+3gSm3LCIIINTVO0PficsvWGQ= -github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.2.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jarcoal/httpmock v1.2.0 h1:gSvTxxFR/MEMfsGrvRbdfpRUMBStovlSRLw0Ep1bwwc= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= -github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= -github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= -github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= -github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= -github.com/kevinburke/ssh_config v1.1.0 h1:pH/t1WS9NzT8go394IqZeJTMHVm6Cr6ZJ6AQ+mdNo/o= -github.com/kevinburke/ssh_config v1.1.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.15.13 h1:NFn1Wr8cfnenSJSA46lLq4wHCcBzKTSjnBIexDMMOV0= -github.com/klauspost/compress v1.15.13/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= -github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= -github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= -github.com/kolo/xmlrpc v0.0.0-20201022064351-38db28db192b/go.mod h1:pcaDhQK0/NJZEvtCO0qQPPropqV0sJOJ6YW7X+9kRwM= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= -github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= -github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= -github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= -github.com/linode/linodego v1.4.0/go.mod h1:PVsRxSlOiJyvG4/scTszpmZDTdgS+to3X6eS8pRrWI8= -github.com/linode/linodego v1.8.0/go.mod h1:heqhl91D8QTPVm2k9qZHP78zzbOdTFLXE9NJc3bcc50= -github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo= -github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= -github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= -github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= -github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= -github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= -github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= -github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= -github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= -github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= -github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= -github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-mastodon v0.0.6 h1:lqU1sOeeIapaDsDUL6udDZIzMb2Wqapo347VZlaOzf0= -github.com/mattn/go-mastodon v0.0.6/go.mod h1:cg7RFk2pcUfHZw/IvKe1FUzmlq5KnLFqs7eV2PHplV8= -github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= -github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= -github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= -github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= -github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= -github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= -github.com/microsoft/ApplicationInsights-Go v0.4.4/go.mod h1:fKRUseBqkw6bDiXTs3ESTiU/4YTIHsQS4W3fP2ieF4U= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= -github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= -github.com/miekg/dns v1.1.48/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= -github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= -github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= -github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= -github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= -github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= -github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= -github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= -github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= -github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= -github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= -github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= -github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= -github.com/moby/sys/signal v0.6.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg= -github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= -github.com/moby/sys/symlink v0.2.0/go.mod h1:7uZVF2dqJjG/NsClqul95CqKOBRQyYSNnJ6BMgR/gFs= -github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= -github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A= -github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc= -github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= -github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= -github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= -github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= -github.com/muesli/mango v0.1.0 h1:DZQK45d2gGbql1arsYA4vfg4d7I9Hfx5rX/GCmzsAvI= -github.com/muesli/mango v0.1.0/go.mod h1:5XFpbC8jY5UUv89YQciiXNlbi+iJgt29VDC5xbzrLL4= -github.com/muesli/mango-cobra v1.2.0 h1:DQvjzAM0PMZr85Iv9LIMaYISpTOliMEg+uMFtNbYvWg= -github.com/muesli/mango-cobra v1.2.0/go.mod h1:vMJL54QytZAJhCT13LPVDfkvCUJ5/4jNUKF/8NC2UjA= -github.com/muesli/mango-pflag v0.1.0 h1:UADqbYgpUyRoBja3g6LUL+3LErjpsOwaC9ywvBWe7Sg= -github.com/muesli/mango-pflag v0.1.0/go.mod h1:YEQomTxaCUp8PrbhFh10UfbhbQrM/xJ4i2PB8VTLLW0= -github.com/muesli/reflow v0.2.1-0.20210115123740-9e1d0d53df68/go.mod h1:Xk+z4oIWdQqJzsxyjgl3P22oYZnHdZ8FFTHAQQt5BMQ= -github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= -github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= -github.com/muesli/roff v0.1.0 h1:YD0lalCotmYuF5HhZliKWlIx7IEhiXeSfq7hNjFqGF8= -github.com/muesli/roff v0.1.0/go.mod h1:pjAHQM9hdUUwm/krAfrLGgJkXJ+YuhtsfZ42kieB2Ig= -github.com/muesli/termenv v0.11.1-0.20220204035834-5ac8409525e0/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs= -github.com/muesli/termenv v0.13.0 h1:wK20DRpJdDX8b7Ek2QfhvqhRQFZ237RGRO0RQ/Iqdy0= -github.com/muesli/termenv v0.13.0/go.mod h1:sP1+uffeLaEYpyOTb8pLCUctGcGLnoFjSn4YJK5e2bc= -github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= -github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= -github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= -github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= -github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= -github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= -github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0= -github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= -github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= -github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= -github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v1.0.0-rc1.0.20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.0.2-0.20211117181255-693428a734f5/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= -github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0= -github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= -github.com/opencontainers/runc v1.1.0/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc= -github.com/opencontainers/runc v1.1.2 h1:2VSZwLx5k/BfsBxMMipG/LYUnmqOD/BPkIVgQUcTlLw= -github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= -github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= -github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= -github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= -github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= -github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= -github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= -github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= -github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= -github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= -github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/ory/dockertest/v3 v3.9.1 h1:v4dkG+dlu76goxMiTT2j8zV7s4oPPEppKT8K8p2f1kY= -github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= -github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= -github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= -github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= -github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= -github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 h1:Qj1ukM4GlMWXNdMBuXcXfz/Kw9s1qm0CLY32QxuSImI= -github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= -github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= -github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= -github.com/prometheus/alertmanager v0.24.0/go.mod h1:r6fy/D7FRuZh5YbnX6J3MBY0eI4Pb5yPYS7/bPSXXqI= -github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= -github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= -github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= -github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= -github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.34.0/go.mod h1:gB3sOl7P0TvJabZpLY5uQMpUqRCPPCyRLCZYc7JZTNE= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/common/assets v0.1.0/go.mod h1:D17UVUE12bHbim7HzwUvtqm6gwBEaDQ0F+hIGbFbccI= -github.com/prometheus/common/assets v0.2.0/go.mod h1:D17UVUE12bHbim7HzwUvtqm6gwBEaDQ0F+hIGbFbccI= -github.com/prometheus/common/sigv4 v0.1.0/go.mod h1:2Jkxxk9yYvCkE5G1sQT7GuEXm57JrvHu9k5YwTjsNtI= -github.com/prometheus/exporter-toolkit v0.7.1/go.mod h1:ZUBIj498ePooX9t/2xtDjeQYwvRpiPP2lh5u4iblj2g= -github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/prometheus v0.35.0/go.mod h1:7HaLx5kEPKJ0GDgbODG0fZgXbQ8K/XjZNJXQmbmgQlY= -github.com/prometheus/prometheus v0.37.0/go.mod h1:egARUgz+K93zwqsVIAneFlLZefyGOON44WyAp4Xqbbk= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rakyll/embedmd v0.0.0-20171029212350-c8060a0752a2/go.mod h1:7jOTMgqac46PZcF54q6l2hkLEG8op93fZu61KmxWDV4= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.2 h1:YwD0ulJSJytLpiaWua0sBDusfsCZohxjxzVTYjwxfV8= -github.com/rivo/uniseg v0.4.2/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= -github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= -github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= -github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= -github.com/safchain/ethtool v0.0.0-20210803160452-9aa261dae9b1/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= -github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= -github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b h1:qYTY2tN72LhgDj2rtWG+LI6TXFl2ygFQQ4YezfVaGQE= -github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b/go.mod h1:/pA7k3zsXKdjjAiUhB5CjuKib9KJGCaLvZwtxGC8U0s= -github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/scaleway/scaleway-sdk-go v1.0.0-beta.9/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg= -github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= -github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= -github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= -github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= -github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= -github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= -github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/slack-go/slack v0.12.1 h1:X97b9g2hnITDtNsNe5GkGx6O2/Sz/uC20ejRZN6QxOw= -github.com/slack-go/slack v0.12.1/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs= -github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= -github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= -github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= -github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= -github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= -github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= -github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= -github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -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 v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.3.1-0.20190311161405-34c6fa2dc709/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -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.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= -github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM= -github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog= -github.com/tedsuo/ifrit v0.0.0-20180802180643-bea94bb476cc/go.mod h1:eyZnKCc955uh98WQvzOm0dgAeLnf2O0Rz0LPoC5ze+0= -github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= -github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 h1:nrZ3ySNYwJbSpD6ce9duiP+QkD3JuLCcWkdaehUS/3Y= -github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80/go.mod h1:iFyPdL66DjUD96XmzVL3ZntbzcflLnznH0fr99w5VqE= -github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= -github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= -github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= -github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= -github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= -github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= -github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= -github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= -github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= -github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= -github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= -github.com/vultr/govultr/v2 v2.17.2/go.mod h1:ZFOKGWmgjytfyjeyAdhQlSWwTjh2ig+X49cAp50dzXI= -github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= -github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= -github.com/withfig/autocomplete-tools/integrations/cobra v1.2.1 h1:+dBg5k7nuTE38VVdoroRsT0Z88fmvdYrI2EjzJst35I= -github.com/withfig/autocomplete-tools/integrations/cobra v1.2.1/go.mod h1:nmuySobZb4kFgFy6BptpXp/BBw+xFSyvVPP6auoJB4k= -github.com/xanzy/go-gitlab v0.77.0 h1:UrbGlxkWVCbkpa6Fk6cM8ARh+rLACWemkJnsawT7t98= -github.com/xanzy/go-gitlab v0.77.0/go.mod h1:d/a0vswScO7Agg1CZNz15Ic6SSvBG9vfw8egL99t4kA= -github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= -github.com/xanzy/ssh-agent v0.3.1 h1:AmzO1SSWxw73zxFZPRwaMN1MohDw8UyHnmuxyceTEGo= -github.com/xanzy/ssh-agent v0.3.1/go.mod h1:QIE4lCeL7nkC25x+yA3LBIYfwCc1TFziCtG7cBAac6w= -github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= -github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= -github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= -github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= -github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= -github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= -github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= -github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= -gitlab.com/digitalxero/go-conventional-commit v1.0.7 h1:8/dO6WWG+98PMhlZowt/YjuiKhqhGlOCwlIV8SqqGh8= -gitlab.com/digitalxero/go-conventional-commit v1.0.7/go.mod h1:05Xc2BFsSyC5tKhK0y+P3bs0AwUtNuTp+mTpbCU/DZ0= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= -go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= -go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= -go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= -go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= -go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= -go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= -go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= -go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= -go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg= -go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng= -go.mongodb.org/mongo-driver v1.8.3/go.mod h1:0sQWfOeY63QTntERDJJ/0SuKK0T1uVSgKCuAROlKEPY= -go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= -go.opencensus.io v0.15.0/go.mod h1:UffZAU+4sDEINUGP/B7UfBBkq4fqLu9zXAX7ke6CHW0= -go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= -go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.28.0/go.mod h1:vEhqr0m4eTc+DWxfsXoXue2GBgV2uUwVznkGIHW/e5w= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.31.0/go.mod h1:PFmBsWbldL1kiWZk9+0LBZz2brhByaGsvp6pRICMlPE= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.32.0/go.mod h1:5eCOqeGphOyz6TsY3ZDNjE33SM/TFAK3RGuCL2naTgY= -go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= -go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs= -go.opentelemetry.io/otel v1.6.0/go.mod h1:bfJD2DZVw0LBxghOTlgnlI0CV3hLDu9XF/QKOUXMTQQ= -go.opentelemetry.io/otel v1.6.1/go.mod h1:blzUabWHkX6LJewxvadmzafgh/wnvBSDBdOuwkAtrWQ= -go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk= -go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0/go.mod h1:VpP4/RMn8bv8gNo9uK7/IMY4mtWLELsS+JIP0inH0h4= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.6.1/go.mod h1:NEu79Xo32iVb+0gVNV8PMd7GoWqnyDXRlj04yFjqz40= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.7.0/go.mod h1:M1hVZHNxcbkAlcvrOMlpQ4YOO3Awf+4N2dxkZL3xm04= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.3.0/go.mod h1:hO1KLR7jcKaDDKDkvI9dP/FIhpmna5lkqPUQdEjFAM8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.6.1/go.mod h1:YJ/JbY5ag/tSQFXzH3mtDmHqzF3aFn3DI/aB1n7pt4w= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.7.0/go.mod h1:ceUgdyfNv4h4gLxHR0WNfDiiVmZFodZhZSbOLhpxqXE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.3.0/go.mod h1:keUU7UfnwWTWpJ+FWnyqmogPa82nuU5VUANFq49hlMY= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.6.1/go.mod h1:UJJXJj0rltNIemDMwkOJyggsvyMG9QHfJeFH0HS5JjM= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.7.0/go.mod h1:E+/KKhwOSw8yoPxSSuUHG6vKppkvhN+S1Jc7Nib3k3o= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.3.0/go.mod h1:QNX1aly8ehqqX1LEa6YniTU7VY9I6R3X/oPxhGdTceE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.6.1/go.mod h1:DAKwdo06hFLc0U88O10x4xnb5sc7dDRDqRuiN+io8JE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.7.0/go.mod h1:aFXT9Ng2seM9eizF+LfKiyPBGy8xIZKwhusC1gIu3hA= -go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= -go.opentelemetry.io/otel/metric v0.28.0/go.mod h1:TrzsfQAmQaB1PDcdhBauLMk7nyyg9hm+GoQq/ekE9Iw= -go.opentelemetry.io/otel/metric v0.30.0/go.mod h1:/ShZ7+TS4dHzDFmfi1kSXMhMVubNoP0oIaBp70J6UXU= -go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= -go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= -go.opentelemetry.io/otel/sdk v1.3.0/go.mod h1:rIo4suHNhQwBIPg9axF8V9CA72Wz2mKF1teNrup8yzs= -go.opentelemetry.io/otel/sdk v1.6.1/go.mod h1:IVYrddmFZ+eJqu2k38qD3WezFR2pymCzm8tdxyh3R4E= -go.opentelemetry.io/otel/sdk v1.7.0/go.mod h1:uTEOTwaqIVuTGiJN7ii13Ibp75wJmYUDe374q6cZwUU= -go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= -go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= -go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= -go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk= -go.opentelemetry.io/otel/trace v1.6.0/go.mod h1:qs7BrU5cZ8dXQHBGxHMOxwME/27YH2qEp4/+tZLLwJE= -go.opentelemetry.io/otel/trace v1.6.1/go.mod h1:RkFRM1m0puWIq10oxImnGEduNBzxiN7TXluRBtE+5j0= -go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48yyE4TNvoHqU= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v0.11.0/go.mod h1:QpEjXPrNQzrFDZgoTo49dgHR9RYRSrg3NAKnUGl9YpQ= -go.opentelemetry.io/proto/otlp v0.12.1/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.opentelemetry.io/proto/otlp v0.16.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/automaxprocs v1.5.1/go.mod h1:BF4eumQw0P9GtnuxxovUd06vwm1o18oMzFtK66vU6XU= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= -go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= -gocloud.dev v0.27.0 h1:j0WTUsnKTxCsWO7y8T+YCiBZUmLl9w/WIowqAY3yo0g= -gocloud.dev v0.27.0/go.mod h1:YlYKhYsY5/1JdHGWQDkAuqkezVKowu7qbe9aIeUF6p0= -golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= -golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211202192323-5770296d904e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -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-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -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-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/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-20190125091013-d26f9f9a57f3/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-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= -golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= -golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220802222814-0bcc04d9c69b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.0.0-20220805013720-a33c5aa5df48 h1:N9Vc/rorQUDes6B9CNdIxAn5jODGj2wzfrei2x4wNj4= -golang.org/x/net v0.0.0-20220805013720-a33c5aa5df48/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220628200809-02e64fa58f26/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220722155238-128564f6959c h1:q3gFqPqH7NVofKo3c3yETAP//pPI+G5mvB7qqj1Y5kY= -golang.org/x/oauth2 v0.0.0-20220722155238-128564f6959c/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -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-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190412183630-56d357773e84/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-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/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-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210503080704-8803ae5d1324/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/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-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/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.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220224211638-0e9765cccd65/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 h1:ftMN5LMiBFjbzleLqtoBZk7KdJwhuybIU+FckUHgoyQ= -golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/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-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200325010219-a49f79bcc224/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= -golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= -golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= -golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/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= -golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f h1:uF6paiQQebLeSXkrTqHqz0MXhXXS1KgF41eUdBNvxK0= -golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.46.0/go.mod h1:ceL4oozhkAiTID8XMmJBsIxID/9wMXJVVFXPg4ylg3I= -google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= -google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= -google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= -google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= -google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= -google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= -google.golang.org/api v0.58.0/go.mod h1:cAbP2FsxoGVNwtgNAmmn3y5G1TWAiVYRmg4yku3lv+E= -google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU= -google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= -google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= -google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= -google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= -google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= -google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= -google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= -google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= -google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= -google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= -google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6FO2g= -google.golang.org/api v0.86.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= -google.golang.org/api v0.90.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= -google.golang.org/api v0.91.0 h1:731+JzuwaJoZXRQGmPoBiV+SrsAfUaIkdMCWTcQNPyA= -google.golang.org/api v0.91.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= -google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200117163144-32f20d992d24/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210429181445-86c259c2b4ab/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210517163617-5e0236093d7a/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= -google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210921142501-181ce0d877f6/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211018162055-cf77aa76bad2/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= -google.golang.org/genproto v0.0.0-20220329172620-7be39ac1afc7/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220802133213-ce4fa296bf78 h1:QntLWYqZeuBtJkth3m/6DLznnI0AHJr+AgJXvVh/izw= -google.golang.org/genproto v0.0.0-20220802133213-ce4fa296bf78/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc= -google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -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.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.48.0 h1:rQOsyJ/8+ufEDJd/Gdsz7HG220Mh9HAhFHRGnIjda0w= -google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= -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.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -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.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= -gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= -gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= -gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/mail.v2 v2.3.1 h1:WYFn/oANrAGP2C0dcV6/pbkPzv8yGzqTjPmTeO7qoXk= -gopkg.in/mail.v2 v2.3.1/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw= -gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/telebot.v3 v3.0.0/go.mod h1:7rExV8/0mDDNu9epSrDm/8j22KLaActH1Tbee6YjzWg= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -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.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= -gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= -k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= -k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8= -k8s.io/api v0.22.5/go.mod h1:mEhXyLaSD1qTOf40rRiKXkc+2iCem09rWLlFwhCEiAs= -k8s.io/api v0.23.5/go.mod h1:Na4XuKng8PXJ2JsploYYrivXrINeTaycCGcYgF91Xm8= -k8s.io/api v0.24.2/go.mod h1:AHqbSkTm6YrQ0ObxjO3Pmp/ubFF/KuM7jU+3khoBsOg= -k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= -k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= -k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc= -k8s.io/apimachinery v0.22.1/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= -k8s.io/apimachinery v0.22.5/go.mod h1:xziclGKwuuJ2RM5/rSFQSYAj0zdbci3DH8kj+WvyN0U= -k8s.io/apimachinery v0.23.5/go.mod h1:BEuFMMBaIbcOqVIJqNZJXGFTP4W6AycEpb5+m/97hrM= -k8s.io/apimachinery v0.24.2/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= -k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= -k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= -k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= -k8s.io/apiserver v0.22.5/go.mod h1:s2WbtgZAkTKt679sYtSudEQrTGWUSQAPe6MupLnlmaQ= -k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= -k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k= -k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0= -k8s.io/client-go v0.22.5/go.mod h1:cs6yf/61q2T1SdQL5Rdcjg9J1ElXSwbjSrW2vFImM4Y= -k8s.io/client-go v0.23.5/go.mod h1:flkeinTO1CirYgzMPRWxUCnV0G4Fbu2vLhYCObnt/r4= -k8s.io/client-go v0.24.2/go.mod h1:zg4Xaoo+umDsfCWr4fCnmLEtQXyCNXCvJuSsglNcV30= -k8s.io/code-generator v0.19.7/go.mod h1:lwEq3YnLYb/7uVXLorOJfxg+cUu2oihFhHZ0n9NIla0= -k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= -k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI= -k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM= -k8s.io/component-base v0.22.5/go.mod h1:VK3I+TjuF9eaa+Ln67dKxhGar5ynVbwnGrUiNF4MqCI= -k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM= -k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= -k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= -k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc= -k8s.io/cri-api v0.23.1/go.mod h1:REJE3PSU0h/LOV1APBrupxrEJqnoxZC8KWzkBUHwrK4= -k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= -k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= -k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/klog/v2 v2.40.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/klog/v2 v2.70.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= -k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= -k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= -k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= -k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65/go.mod h1:sX9MT8g7NVZM5lVL/j8QyCCJe8YSMW30QvGZWaCIDIk= -k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= -k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= -k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20211116205334-6203023598ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs= -sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY= -sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= -sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= -sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/tools/package-lock.json b/tools/package-lock.json index 38551f80dc57..14a90643dd78 100644 --- a/tools/package-lock.json +++ b/tools/package-lock.json @@ -1195,9 +1195,9 @@ } }, "semver": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" }, "shebang-command": { "version": "1.2.0", diff --git a/tools/tools.go b/tools/tools.go deleted file mode 100644 index b36a0271d599..000000000000 --- a/tools/tools.go +++ /dev/null @@ -1,14 +0,0 @@ -//go:build tools -// +build tools - -package tools - -// Manage tool dependencies via go.mod. -// -// https://github.com/golang/go/wiki/Modules#how-can-i-track-tool-dependencies-for-a-module -// https://github.com/golang/go/issues/25922 -// -//nolint:all -import ( - _ "github.com/goreleaser/goreleaser" -)