From 0d86f21e52a82df464d6e192daa6b8cc44c7eb63 Mon Sep 17 00:00:00 2001 From: GolangCI-Lint Releaser <65486276+golangci-releaser@users.noreply.github.com> Date: Tue, 25 Mar 2025 23:02:59 +0100 Subject: [PATCH 001/152] docs: update GitHub Action assets (#5634) --- assets/github-action-config-v2.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/github-action-config-v2.json b/assets/github-action-config-v2.json index 2f3d958d2540..8ef161513b62 100644 --- a/assets/github-action-config-v2.json +++ b/assets/github-action-config-v2.json @@ -1,7 +1,7 @@ { "MinorVersionToConfig": { "latest": { - "TargetVersion": "v2.0.1" + "TargetVersion": "v2.0.2" }, "v1.10": { "Error": "golangci-lint version 'v1.10' isn't supported: we support only v2.0.0 and later versions" @@ -190,7 +190,7 @@ "Error": "golangci-lint version 'v1.9' isn't supported: we support only v2.0.0 and later versions" }, "v2.0": { - "TargetVersion": "v2.0.1" + "TargetVersion": "v2.0.2" } } } From 928a7d586f589512a7c67afbe0f72b6fcac3074b Mon Sep 17 00:00:00 2001 From: Oleksandr Redko Date: Tue, 25 Mar 2025 15:05:18 -0700 Subject: [PATCH 002/152] docs: add version field to configuration sample (#5632) --- scripts/website/expand_templates/linters.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/scripts/website/expand_templates/linters.go b/scripts/website/expand_templates/linters.go index 4e4c28c0505b..87a386e4ace0 100644 --- a/scripts/website/expand_templates/linters.go +++ b/scripts/website/expand_templates/linters.go @@ -254,7 +254,7 @@ func (e *ExampleSnippetsExtractor) extractExampleSnippets(example []byte) (*Sett for j, node := range root.Content { switch node.Value { - case "run", "output", keyLinters, keyFormatters, "issues", "severity": + case "run", "output", keyLinters, keyFormatters, "issues", "severity", "version": default: continue } @@ -280,6 +280,11 @@ func (e *ExampleSnippetsExtractor) extractExampleSnippets(example []byte) (*Sett }, } + if node.Value == "version" { + node.HeadComment = `See the dedicated "version" documentation section.` + newNode = nextNode + } + globalNode.Content = append(globalNode.Content, node, newNode) if node.Value == keyLinters || node.Value == keyFormatters { From 56838cd9150a4b3a1a78ef5fed977a6f0fe91478 Mon Sep 17 00:00:00 2001 From: Oleksandr Redko Date: Tue, 25 Mar 2025 15:25:36 -0700 Subject: [PATCH 003/152] docs: remove golint in nolint example (#5635) --- docs/src/docs/usage/false-positives.mdx | 2 +- pkg/result/processors/nolint_filter_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/docs/usage/false-positives.mdx b/docs/src/docs/usage/false-positives.mdx index 3a489d7560ab..bf542a9a406f 100644 --- a/docs/src/docs/usage/false-positives.mdx +++ b/docs/src/docs/usage/false-positives.mdx @@ -122,7 +122,7 @@ var bad_name int //nolint:all To exclude issues from specific linters only: ```go -var bad_name int //nolint:golint,unused +var bad_name int //nolint:wsl,unused ``` To exclude issues for the block of code use this directive on the beginning of a line: diff --git a/pkg/result/processors/nolint_filter_test.go b/pkg/result/processors/nolint_filter_test.go index 852602a86ad2..79dc6c1ce4bb 100644 --- a/pkg/result/processors/nolint_filter_test.go +++ b/pkg/result/processors/nolint_filter_test.go @@ -63,7 +63,7 @@ func TestTestNolintFilter_Process(t *testing.T) { processAssertEmpty(t, p, newNolintFileIssue(6, "any")) processAssertEmpty(t, p, newNolintFileIssue(7, "any")) - processAssertSame(t, p, newNolintFileIssue(1, "golint")) // no directive + processAssertSame(t, p, newNolintFileIssue(1, "wsl")) // no directive // test preceding comments processAssertEmpty(t, p, newNolintFileIssue(10, "any")) // preceding comment for var From 86cc7c6bfbe4d6ca515f9c45b58cfa03cfd0c3da Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Mar 2025 02:53:39 +0100 Subject: [PATCH 004/152] build(deps): bump github.com/kunwardeep/paralleltest from 1.0.10 to 1.0.13 (#5636) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 33e81653d8a7..423c12939046 100644 --- a/go.mod +++ b/go.mod @@ -64,7 +64,7 @@ require ( github.com/kisielk/errcheck v1.9.0 github.com/kkHAIKE/contextcheck v1.1.6 github.com/kulti/thelper v0.6.3 - github.com/kunwardeep/paralleltest v1.0.10 + github.com/kunwardeep/paralleltest v1.0.13 github.com/lasiar/canonicalheader v1.1.2 github.com/ldez/exptostd v0.4.2 github.com/ldez/gomoddirectives v0.6.1 diff --git a/go.sum b/go.sum index 9662b6c7db46..3d633f4b3ffa 100644 --- a/go.sum +++ b/go.sum @@ -365,8 +365,8 @@ 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.10 h1:wrodoaKYzS2mdNVnc4/w31YaXFtsc21PCTdvWJ/lDDs= -github.com/kunwardeep/paralleltest v1.0.10/go.mod h1:2C7s65hONVqY7Q5Efj5aLzRCNLjw2h4eMc9EcypGjcY= +github.com/kunwardeep/paralleltest v1.0.13 h1:fxM9P2K5Xmsh+mey0N+Z3DvqAHnOtOAmQoW1mV0OND8= +github.com/kunwardeep/paralleltest v1.0.13/go.mod h1:di4moFqtfz3ToSKxhNjhOZL+696QtJGCFe132CbBLGk= github.com/lasiar/canonicalheader v1.1.2 h1:vZ5uqwvDbyJCnMhmFYimgMZnJMjwljN5VGY0VKbMXb4= github.com/lasiar/canonicalheader v1.1.2/go.mod h1:qJCeLFS0G/QlLQ506T+Fk/fWMa2VmBUiEI2cuMK4djI= github.com/ldez/exptostd v0.4.2 h1:l5pOzHBz8mFOlbcifTxzfyYbgEmoUqjxLFHZkjlbHXs= From 35a64dad1b524333df22a873c4c20fcaabe72d1b Mon Sep 17 00:00:00 2001 From: Oleksandr Redko Date: Wed, 26 Mar 2025 10:45:08 -0700 Subject: [PATCH 005/152] docs: fix config reference for formatters (#5638) --- .golangci.next.reference.yml | 8 -------- .golangci.reference.yml | 8 -------- 2 files changed, 16 deletions(-) diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index 1fd85366eed1..47ab27b30c3b 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -42,7 +42,6 @@ linters: - forbidigo - forcetypeassert - funlen - - gci - ginkgolinter - gocheckcompilerdirectives - gochecknoglobals @@ -54,10 +53,7 @@ linters: - gocyclo - godot - godox - - gofmt - - gofumpt - goheader - - goimports - gomoddirectives - gomodguard - goprintffuncname @@ -153,7 +149,6 @@ linters: - forbidigo - forcetypeassert - funlen - - gci - ginkgolinter - gocheckcompilerdirectives - gochecknoglobals @@ -165,10 +160,7 @@ linters: - gocyclo - godot - godox - - gofmt - - gofumpt - goheader - - goimports - gomoddirectives - gomodguard - goprintffuncname diff --git a/.golangci.reference.yml b/.golangci.reference.yml index 1fd85366eed1..47ab27b30c3b 100644 --- a/.golangci.reference.yml +++ b/.golangci.reference.yml @@ -42,7 +42,6 @@ linters: - forbidigo - forcetypeassert - funlen - - gci - ginkgolinter - gocheckcompilerdirectives - gochecknoglobals @@ -54,10 +53,7 @@ linters: - gocyclo - godot - godox - - gofmt - - gofumpt - goheader - - goimports - gomoddirectives - gomodguard - goprintffuncname @@ -153,7 +149,6 @@ linters: - forbidigo - forcetypeassert - funlen - - gci - ginkgolinter - gocheckcompilerdirectives - gochecknoglobals @@ -165,10 +160,7 @@ linters: - gocyclo - godot - godox - - gofmt - - gofumpt - goheader - - goimports - gomoddirectives - gomodguard - goprintffuncname From f15e6c4865d5b55c04e192a6ac49c4117ff0b1c7 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Wed, 26 Mar 2025 20:31:28 +0100 Subject: [PATCH 006/152] docs: improve version documentation (#5639) --- .golangci.next.reference.yml | 2 ++ .golangci.reference.yml | 2 ++ docs/src/docs/usage/configuration.mdx | 8 -------- scripts/website/expand_templates/linters.go | 19 +++++++++++++------ 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index 47ab27b30c3b..81d741134a69 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -4,6 +4,8 @@ # This file is not a configuration example, # it contains the exhaustive configuration with explanations of the options. +# Defines the configuration version. +# The only possible value is "2". version: "2" linters: diff --git a/.golangci.reference.yml b/.golangci.reference.yml index 47ab27b30c3b..81d741134a69 100644 --- a/.golangci.reference.yml +++ b/.golangci.reference.yml @@ -4,6 +4,8 @@ # This file is not a configuration example, # it contains the exhaustive configuration with explanations of the options. +# Defines the configuration version. +# The only possible value is "2". version: "2" linters: diff --git a/docs/src/docs/usage/configuration.mdx b/docs/src/docs/usage/configuration.mdx index fbc4b889b704..276480ad7d7c 100644 --- a/docs/src/docs/usage/configuration.mdx +++ b/docs/src/docs/usage/configuration.mdx @@ -42,14 +42,6 @@ The configuration file can be validated with the JSON Schema: https://golangci-l { .ConfigurationExample } -### `version` configuration - -```yaml -# Defines the configuration version. -# The only possible value is "2". -version: "2" -``` - ## Command-Line Options ### run diff --git a/scripts/website/expand_templates/linters.go b/scripts/website/expand_templates/linters.go index 87a386e4ace0..a6c0183863ce 100644 --- a/scripts/website/expand_templates/linters.go +++ b/scripts/website/expand_templates/linters.go @@ -206,8 +206,7 @@ type ExampleSnippetsExtractor struct { func NewExampleSnippetsExtractor() *ExampleSnippetsExtractor { return &ExampleSnippetsExtractor{ - // TODO(ldez) replace .golangci.next.reference.yml by .golangci.reference.yml - referencePath: ".golangci.next.reference.yml", + referencePath: ".golangci.reference.yml", assetsPath: "assets", } } @@ -281,11 +280,19 @@ func (e *ExampleSnippetsExtractor) extractExampleSnippets(example []byte) (*Sett } if node.Value == "version" { - node.HeadComment = `See the dedicated "version" documentation section.` - newNode = nextNode - } + n := &yaml.Node{ + HeadComment: fmt.Sprintf("See the dedicated %q documentation section.", node.Value), + Kind: node.Kind, + Style: node.Style, + Tag: node.Tag, + Value: node.Value, + Content: node.Content, + } - globalNode.Content = append(globalNode.Content, node, newNode) + globalNode.Content = append(globalNode.Content, n, nextNode) + } else { + globalNode.Content = append(globalNode.Content, node, newNode) + } if node.Value == keyLinters || node.Value == keyFormatters { for i := 0; i < len(nextNode.Content); i++ { From 54b4e2db36754079f5f1ac6f3af1d64c54982dd7 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Thu, 27 Mar 2025 14:20:04 +0100 Subject: [PATCH 007/152] docs: fix settings examples (#5643) --- scripts/website/expand_templates/linters.go | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/scripts/website/expand_templates/linters.go b/scripts/website/expand_templates/linters.go index a6c0183863ce..0b6c88e5dfa2 100644 --- a/scripts/website/expand_templates/linters.go +++ b/scripts/website/expand_templates/linters.go @@ -379,18 +379,29 @@ func (e *ExampleSnippetsExtractor) getSettingSections(node, nextNode *yaml.Node) for i := 0; i < len(nextNode.Content); i += 2 { r := &yaml.Node{ - Kind: nextNode.Kind, - Style: nextNode.Style, + Kind: yaml.MappingNode, Tag: nextNode.Tag, Value: node.Value, Content: []*yaml.Node{ { - Kind: node.Kind, + Kind: yaml.ScalarNode, Value: node.Value, + Tag: node.Tag, }, { - Kind: nextNode.Kind, - Content: []*yaml.Node{nextNode.Content[i], nextNode.Content[i+1]}, + Kind: yaml.MappingNode, + Content: []*yaml.Node{ + { + Kind: yaml.ScalarNode, + Value: "settings", + Tag: node.Tag, + }, + { + Kind: yaml.MappingNode, + Tag: nextNode.Tag, + Content: []*yaml.Node{nextNode.Content[i], nextNode.Content[i+1]}, + }, + }, }, }, } From 95d2005001598994b83ba83b5ec11622488afed1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Mar 2025 23:44:29 +0100 Subject: [PATCH 008/152] build(deps): bump tar-fs and puppeteer in /docs (#5653) --- docs/package-lock.json | 1494 +++++++++++++++++++++++++++++++++++----- docs/package.json | 2 +- 2 files changed, 1333 insertions(+), 163 deletions(-) diff --git a/docs/package-lock.json b/docs/package-lock.json index 5d1ab9e51dab..5693665902e0 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -40,7 +40,7 @@ "postcss": "^8.4.31", "prism-react-renderer": "^1.3.5", "prop-types": "^15.8.1", - "puppeteer": "^13.7.0", + "puppeteer": "^24.4.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-headroom": "^3.2.1", @@ -4206,6 +4206,187 @@ "@parcel/core": "^2.6.2" } }, + "node_modules/@puppeteer/browsers": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.8.0.tgz", + "integrity": "sha512-yTwt2KWRmCQAfhvbCRjebaSX8pV1//I0Y3g+A7f/eS7gf0l4eRJoUCvcYdVtboeU4CTOZQuqYbZNS8aBYb8ROQ==", + "license": "Apache-2.0", + "dependencies": { + "debug": "^4.4.0", + "extract-zip": "^2.0.1", + "progress": "^2.0.3", + "proxy-agent": "^6.5.0", + "semver": "^7.7.1", + "tar-fs": "^3.0.8", + "yargs": "^17.7.2" + }, + "bin": { + "browsers": "lib/cjs/main-cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@puppeteer/browsers/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@puppeteer/browsers/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@puppeteer/browsers/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@puppeteer/browsers/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/@puppeteer/browsers/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@puppeteer/browsers/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/@puppeteer/browsers/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@puppeteer/browsers/node_modules/tar-fs": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.8.tgz", + "integrity": "sha512-ZoROL70jptorGAlgAYiLoBLItEKw/fUxg9BSYK/dF/GAGYFJOJJJMvjPAKDJraCXFwadD456FCuvLWgfhMsPwg==", + "license": "MIT", + "dependencies": { + "pump": "^3.0.0", + "tar-stream": "^3.1.5" + }, + "optionalDependencies": { + "bare-fs": "^4.0.1", + "bare-path": "^3.0.0" + } + }, + "node_modules/@puppeteer/browsers/node_modules/tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "license": "MIT", + "dependencies": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, + "node_modules/@puppeteer/browsers/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@puppeteer/browsers/node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/@puppeteer/browsers/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@puppeteer/browsers/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/@sideway/address": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.3.tgz", @@ -4320,6 +4501,12 @@ "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==" }, + "node_modules/@tootallnate/quickjs-emscripten": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", + "license": "MIT" + }, "node_modules/@trysound/sax": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", @@ -4600,9 +4787,10 @@ } }, "node_modules/@types/yauzl": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.1.tgz", - "integrity": "sha512-A1b8SU4D10uoPjwb0lnHmmu8wZhR9d+9o2PKBQT2jU5YPTKsxac6M2qGAdY7VcL+dHHhARVUDmeg0rOrcd9EjA==", + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "license": "MIT", "optional": true, "dependencies": { "@types/node": "*" @@ -5020,14 +5208,12 @@ } }, "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dependencies": { - "debug": "4" - }, + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", + "license": "MIT", "engines": { - "node": ">= 6.0.0" + "node": ">= 14" } }, "node_modules/ajv": { @@ -5268,11 +5454,29 @@ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" }, + "node_modules/ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/ast-types-flow": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=" }, + "node_modules/ast-types/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, "node_modules/astral-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", @@ -5359,6 +5563,34 @@ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", "integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==" }, + "node_modules/b4a": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", + "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==", + "license": "Apache-2.0" + }, + "node_modules/babel-eslint": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", + "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==", + "deprecated": "babel-eslint is now @babel/eslint-parser. This package will no longer receive updates.", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.7.0", + "@babel/traverse": "^7.7.0", + "@babel/types": "^7.7.0", + "eslint-visitor-keys": "^1.0.0", + "resolve": "^1.12.0" + }, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "eslint": ">= 4.12.1" + } + }, "node_modules/babel-loader": { "version": "8.2.3", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.3.tgz", @@ -5580,6 +5812,78 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, + "node_modules/bare-events": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.4.tgz", + "integrity": "sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==", + "license": "Apache-2.0", + "optional": true + }, + "node_modules/bare-fs": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.0.2.tgz", + "integrity": "sha512-S5mmkMesiduMqnz51Bfh0Et9EX0aTCJxhsI4bvzFFLs8Z1AV8RDHadfY5CyLwdoLHgXbNBEN1gQcbEtGwuvixw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "bare-events": "^2.5.4", + "bare-path": "^3.0.0", + "bare-stream": "^2.6.4" + }, + "engines": { + "bare": ">=1.16.0" + }, + "peerDependencies": { + "bare-buffer": "*" + }, + "peerDependenciesMeta": { + "bare-buffer": { + "optional": true + } + } + }, + "node_modules/bare-os": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.6.1.tgz", + "integrity": "sha512-uaIjxokhFidJP+bmmvKSgiMzj2sV5GPHaZVAIktcxcpCyBFFWO+YlikVAdhmUo2vYFvFhOXIAlldqV29L8126g==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "bare": ">=1.14.0" + } + }, + "node_modules/bare-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz", + "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "bare-os": "^3.0.1" + } + }, + "node_modules/bare-stream": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.6.5.tgz", + "integrity": "sha512-jSmxKJNJmHySi6hC42zlZnq00rga4jjxcgNZjY9N5WlOe/iOoGRtdwGsHzQv2RlH2KOYMwGUXhf2zXd32BA9RA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "streamx": "^2.21.0" + }, + "peerDependencies": { + "bare-buffer": "*", + "bare-events": "*" + }, + "peerDependenciesMeta": { + "bare-buffer": { + "optional": true + }, + "bare-events": { + "optional": true + } + } + }, "node_modules/base-x": { "version": "3.0.9", "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", @@ -5601,6 +5905,15 @@ "node": "^4.5.0 || >= 5.9" } }, + "node_modules/basic-ftp": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", + "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/better-opn": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/better-opn/-/better-opn-2.1.1.tgz", @@ -5899,7 +6212,8 @@ "node_modules/buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "license": "MIT", "engines": { "node": "*" } @@ -6583,6 +6897,25 @@ "node": ">=6.0" } }, + "node_modules/chromium-bidi": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-2.1.2.tgz", + "integrity": "sha512-vtRWBK2uImo5/W2oG6/cDkkHSm+2t6VHgnj+Rcwhb0pP74OoUb4GipyRX/T/y39gYQPhioP0DPShn+A7P6CHNw==", + "license": "Apache-2.0", + "dependencies": { + "mitt": "^3.0.1", + "zod": "^3.24.1" + }, + "peerDependencies": { + "devtools-protocol": "*" + } + }, + "node_modules/chromium-bidi/node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "license": "MIT" + }, "node_modules/ci-info": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", @@ -8192,6 +8525,15 @@ "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==" }, + "node_modules/data-uri-to-buffer": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", + "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, "node_modules/dataloader": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-1.4.0.tgz", @@ -8337,6 +8679,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/degenerator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", + "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", + "license": "MIT", + "dependencies": { + "ast-types": "^0.13.4", + "escodegen": "^2.1.0", + "esprima": "^4.0.1" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/delaunator": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.0.tgz", @@ -8530,9 +8886,10 @@ } }, "node_modules/devtools-protocol": { - "version": "0.0.981744", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.981744.tgz", - "integrity": "sha512-0cuGS8+jhR67Fy7qG3i3Pc7Aw494sb9yG9QgpG97SFVWwolgYjlhJg7n+UaHxOQT30d1TYu/EYe9k01ivLErIg==" + "version": "0.0.1413902", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1413902.tgz", + "integrity": "sha512-yRtvFD8Oyk7C9Os3GmnFZLu53yAfsnyw1s+mLmHHUK0GQEc9zthHWvS1r67Zqzm5t7v56PILHIVZ7kmFMaL2yQ==", + "license": "BSD-3-Clause" }, "node_modules/dir-glob": { "version": "3.0.1", @@ -8762,6 +9119,15 @@ "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==" }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/envinfo": { "version": "7.8.1", "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", @@ -8954,6 +9320,37 @@ "node": ">=0.8.0" } }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/eslint": { "version": "7.32.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", @@ -10098,6 +10495,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "license": "BSD-2-Clause", "dependencies": { "debug": "^4.1.1", "get-stream": "^5.1.0", @@ -10117,11 +10515,15 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "license": "MIT", "dependencies": { "pump": "^3.0.0" }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/fast-deep-equal": { @@ -10129,6 +10531,12 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "license": "MIT" + }, "node_modules/fast-glob": { "version": "3.2.11", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", @@ -10210,7 +10618,8 @@ "node_modules/fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "license": "MIT", "dependencies": { "pend": "~1.2.0" } @@ -13441,6 +13850,20 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, + "node_modules/gatsby/node_modules/type-fest": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", + "license": "(MIT OR CC0-1.0)", + "optional": true, + "peer": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/gatsby/node_modules/universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", @@ -13591,6 +14014,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-uri": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.4.tgz", + "integrity": "sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ==", + "license": "MIT", + "dependencies": { + "basic-ftp": "^5.0.2", + "data-uri-to-buffer": "^6.0.2", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/git-up": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/git-up/-/git-up-7.0.0.tgz", @@ -14358,6 +14795,19 @@ "node": ">= 0.8" } }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/http2-wrapper": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", @@ -14382,15 +14832,16 @@ } }, "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", "dependencies": { - "agent-base": "6", + "agent-base": "^7.1.2", "debug": "4" }, "engines": { - "node": ">= 6" + "node": ">= 14" } }, "node_modules/human-signals": { @@ -14457,15 +14908,19 @@ } }, "node_modules/import-fresh": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", - "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" }, "engines": { "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/import-from": { @@ -14668,6 +15123,25 @@ "loose-envify": "^1.0.0" } }, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "license": "MIT", + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ip-address/node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "license": "BSD-3-Clause" + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -15290,6 +15764,12 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "license": "MIT" + }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -15311,11 +15791,6 @@ "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz", "integrity": "sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w==" }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "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", @@ -17095,6 +17570,15 @@ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, + "node_modules/netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/next-tick": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", @@ -17697,6 +18181,38 @@ "node": ">=6" } }, + "node_modules/pac-proxy-agent": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz", + "integrity": "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==", + "license": "MIT", + "dependencies": { + "@tootallnate/quickjs-emscripten": "^0.23.0", + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "get-uri": "^6.0.1", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.6", + "pac-resolver": "^7.0.1", + "socks-proxy-agent": "^8.0.5" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-resolver": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", + "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", + "license": "MIT", + "dependencies": { + "degenerator": "^5.0.0", + "netmask": "^2.0.2" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/package-json": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", @@ -17808,17 +18324,21 @@ } }, "node_modules/parse-json": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz", - "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1", + "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/parse-latin": { @@ -18002,7 +18522,8 @@ "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "license": "MIT" }, "node_modules/performance-now": { "version": "2.1.0", @@ -18374,10 +18895,39 @@ "node": ">= 0.10" } }, + "node_modules/proxy-agent": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz", + "integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.1", + "https-proxy-agent": "^7.0.6", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.1.0", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.5" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" }, "node_modules/pseudomap": { "version": "1.0.2", @@ -18413,46 +18963,77 @@ } }, "node_modules/puppeteer": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-13.7.0.tgz", - "integrity": "sha512-U1uufzBjz3+PkpCxFrWzh4OrMIdIb2ztzCu0YEPfRHjHswcSwHZswnK+WdsOQJsRV8WeTg3jLhJR4D867+fjsA==", + "version": "24.4.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.4.0.tgz", + "integrity": "sha512-E4JhJzjS8AAI+6N/b+Utwarhz6zWl3+MR725fal+s3UlOlX2eWdsvYYU+Q5bXMjs9eZEGkNQroLkn7j11s2k1Q==", "hasInstallScript": true, + "license": "Apache-2.0", "dependencies": { - "cross-fetch": "3.1.5", - "debug": "4.3.4", - "devtools-protocol": "0.0.981744", - "extract-zip": "2.0.1", - "https-proxy-agent": "5.0.1", - "pkg-dir": "4.2.0", - "progress": "2.0.3", - "proxy-from-env": "1.1.0", - "rimraf": "3.0.2", - "tar-fs": "2.1.1", - "unbzip2-stream": "1.4.3", - "ws": "8.5.0" + "@puppeteer/browsers": "2.8.0", + "chromium-bidi": "2.1.2", + "cosmiconfig": "^9.0.0", + "devtools-protocol": "0.0.1413902", + "puppeteer-core": "24.4.0", + "typed-query-selector": "^2.12.0" + }, + "bin": { + "puppeteer": "lib/cjs/puppeteer/node/cli.js" }, "engines": { - "node": ">=10.18.1" + "node": ">=18" } }, - "node_modules/puppeteer/node_modules/cross-fetch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", - "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "node_modules/puppeteer-core": { + "version": "24.4.0", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.4.0.tgz", + "integrity": "sha512-eFw66gCnWo0X8Hyf9KxxJtms7a61NJVMiSaWfItsFPzFBsjsWdmcNlBdsA1WVwln6neoHhsG+uTVesKmTREn/g==", + "license": "Apache-2.0", "dependencies": { - "node-fetch": "2.6.7" + "@puppeteer/browsers": "2.8.0", + "chromium-bidi": "2.1.2", + "debug": "^4.4.0", + "devtools-protocol": "0.0.1413902", + "typed-query-selector": "^2.12.0", + "ws": "^8.18.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/puppeteer-core/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/puppeteer/node_modules/ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "node_modules/puppeteer-core/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/puppeteer-core/node_modules/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==", + "license": "MIT", "engines": { "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { @@ -18463,6 +19044,50 @@ } } }, + "node_modules/puppeteer/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/puppeteer/node_modules/cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/puppeteer/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/qs": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", @@ -20590,6 +21215,16 @@ "node": ">=8.0.0" } }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, "node_modules/snake-case": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-2.1.0.tgz", @@ -20645,6 +21280,34 @@ "node": ">=10.0.0" } }, + "node_modules/socks": { + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.4.tgz", + "integrity": "sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ==", + "license": "MIT", + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/source-list-map": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", @@ -20861,6 +21524,19 @@ "node": ">=10.0.0" } }, + "node_modules/streamx": { + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.22.0.tgz", + "integrity": "sha512-sLh1evHOzBy/iWRiR6d1zRcLao4gGZr3C1kzNz4fopCOKJb6xD9ub8Mpi9Mr1R6id5o43S+d93fI48UC5uM9aw==", + "license": "MIT", + "dependencies": { + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.0" + }, + "optionalDependencies": { + "bare-events": "^2.2.0" + } + }, "node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -21421,9 +22097,10 @@ } }, "node_modules/tar-fs": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.2.tgz", + "integrity": "sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==", + "license": "MIT", "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", @@ -21591,6 +22268,15 @@ "node": ">=0.4.0" } }, + "node_modules/text-decoder": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", + "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.6.4" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -21844,6 +22530,12 @@ "resolved": "https://registry.npmjs.org/type-of/-/type-of-2.0.1.tgz", "integrity": "sha1-5yoXQYllaOn2KDeNgW1pEvfyOXI=" }, + "node_modules/typed-query-selector": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.0.tgz", + "integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==", + "license": "MIT" + }, "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -21857,6 +22549,20 @@ "is-typedarray": "^1.0.0" } }, + "node_modules/typescript": { + "version": "5.8.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", + "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/ua-parser-js": { "version": "0.7.33", "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.33.tgz", @@ -21889,15 +22595,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/unbzip2-stream": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", - "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", - "dependencies": { - "buffer": "^5.2.1", - "through": "^2.3.8" - } - }, "node_modules/unc-path-regex": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", @@ -23258,7 +23955,8 @@ "node_modules/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "license": "MIT", "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" @@ -23317,6 +24015,15 @@ "node": ">=6" } }, + "node_modules/zod": { + "version": "3.24.2", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz", + "integrity": "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, "node_modules/zwitch": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz", @@ -25102,7 +25809,8 @@ "@emotion/use-insertion-effect-with-fallbacks": { "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==" + "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", + "requires": {} }, "@emotion/utils": { "version": "1.2.1", @@ -26336,6 +27044,126 @@ "nullthrows": "^1.1.1" } }, + "@puppeteer/browsers": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.8.0.tgz", + "integrity": "sha512-yTwt2KWRmCQAfhvbCRjebaSX8pV1//I0Y3g+A7f/eS7gf0l4eRJoUCvcYdVtboeU4CTOZQuqYbZNS8aBYb8ROQ==", + "requires": { + "debug": "^4.4.0", + "extract-zip": "^2.0.1", + "progress": "^2.0.3", + "proxy-agent": "^6.5.0", + "semver": "^7.7.1", + "tar-fs": "^3.0.8", + "yargs": "^17.7.2" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==" + }, + "tar-fs": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.8.tgz", + "integrity": "sha512-ZoROL70jptorGAlgAYiLoBLItEKw/fUxg9BSYK/dF/GAGYFJOJJJMvjPAKDJraCXFwadD456FCuvLWgfhMsPwg==", + "requires": { + "bare-fs": "^4.0.1", + "bare-path": "^3.0.0", + "pump": "^3.0.0", + "tar-stream": "^3.1.5" + } + }, + "tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "requires": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" + } + } + }, "@sideway/address": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.3.tgz", @@ -26431,6 +27259,11 @@ "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==" }, + "@tootallnate/quickjs-emscripten": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==" + }, "@trysound/sax": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", @@ -26705,9 +27538,9 @@ } }, "@types/yauzl": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.1.tgz", - "integrity": "sha512-A1b8SU4D10uoPjwb0lnHmmu8wZhR9d+9o2PKBQT2jU5YPTKsxac6M2qGAdY7VcL+dHHhARVUDmeg0rOrcd9EjA==", + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", "optional": true, "requires": { "@types/node": "*" @@ -26989,7 +27822,8 @@ "acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==" + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "requires": {} }, "acorn-loose": { "version": "8.3.0", @@ -27017,12 +27851,9 @@ "integrity": "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==" }, "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "requires": { - "debug": "4" - } + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==" }, "ajv": { "version": "6.12.6", @@ -27190,6 +28021,21 @@ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" }, + "ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "requires": { + "tslib": "^2.0.1" + }, + "dependencies": { + "tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + } + } + }, "ast-types-flow": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", @@ -27262,6 +28108,25 @@ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", "integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==" }, + "b4a": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", + "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==" + }, + "babel-eslint": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", + "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==", + "peer": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.7.0", + "@babel/traverse": "^7.7.0", + "@babel/types": "^7.7.0", + "eslint-visitor-keys": "^1.0.0", + "resolve": "^1.12.0" + } + }, "babel-loader": { "version": "8.2.3", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.3.tgz", @@ -27453,6 +28318,47 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, + "bare-events": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.4.tgz", + "integrity": "sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==", + "optional": true + }, + "bare-fs": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.0.2.tgz", + "integrity": "sha512-S5mmkMesiduMqnz51Bfh0Et9EX0aTCJxhsI4bvzFFLs8Z1AV8RDHadfY5CyLwdoLHgXbNBEN1gQcbEtGwuvixw==", + "optional": true, + "requires": { + "bare-events": "^2.5.4", + "bare-path": "^3.0.0", + "bare-stream": "^2.6.4" + } + }, + "bare-os": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.6.1.tgz", + "integrity": "sha512-uaIjxokhFidJP+bmmvKSgiMzj2sV5GPHaZVAIktcxcpCyBFFWO+YlikVAdhmUo2vYFvFhOXIAlldqV29L8126g==", + "optional": true + }, + "bare-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz", + "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==", + "optional": true, + "requires": { + "bare-os": "^3.0.1" + } + }, + "bare-stream": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.6.5.tgz", + "integrity": "sha512-jSmxKJNJmHySi6hC42zlZnq00rga4jjxcgNZjY9N5WlOe/iOoGRtdwGsHzQv2RlH2KOYMwGUXhf2zXd32BA9RA==", + "optional": true, + "requires": { + "streamx": "^2.21.0" + } + }, "base-x": { "version": "3.0.9", "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", @@ -27471,6 +28377,11 @@ "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" }, + "basic-ftp": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", + "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==" + }, "better-opn": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/better-opn/-/better-opn-2.1.1.tgz", @@ -27688,7 +28599,7 @@ "buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==" }, "buffer-from": { "version": "1.1.1", @@ -28274,6 +29185,22 @@ "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==" }, + "chromium-bidi": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-2.1.2.tgz", + "integrity": "sha512-vtRWBK2uImo5/W2oG6/cDkkHSm+2t6VHgnj+Rcwhb0pP74OoUb4GipyRX/T/y39gYQPhioP0DPShn+A7P6CHNw==", + "requires": { + "mitt": "^3.0.1", + "zod": "^3.24.1" + }, + "dependencies": { + "mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==" + } + } + }, "ci-info": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", @@ -28711,7 +29638,8 @@ "icss-utils": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==" + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "requires": {} }, "loader-utils": { "version": "2.0.2", @@ -28726,7 +29654,8 @@ "postcss-modules-extract-imports": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==" + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "requires": {} }, "postcss-modules-local-by-default": { "version": "4.0.0", @@ -28845,7 +29774,8 @@ "cssnano-utils": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.0.1.tgz", - "integrity": "sha512-VNCHL364lh++/ono+S3j9NlUK+d97KNkxI77NlqZU2W3xd2/qmyN61dsa47pTpb55zuU4G4lI7qFjAXZJH1OAQ==" + "integrity": "sha512-VNCHL364lh++/ono+S3j9NlUK+d97KNkxI77NlqZU2W3xd2/qmyN61dsa47pTpb55zuU4G4lI7qFjAXZJH1OAQ==", + "requires": {} }, "p-limit": { "version": "3.1.0", @@ -28886,22 +29816,26 @@ "postcss-discard-comments": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.0.2.tgz", - "integrity": "sha512-6VQ3pYTsJHEsN2Bic88Aa7J/Brn4Bv8j/rqaFQZkH+pcVkKYwxCIvoMQkykEW7fBjmofdTnQgcivt5CCBJhtrg==" + "integrity": "sha512-6VQ3pYTsJHEsN2Bic88Aa7J/Brn4Bv8j/rqaFQZkH+pcVkKYwxCIvoMQkykEW7fBjmofdTnQgcivt5CCBJhtrg==", + "requires": {} }, "postcss-discard-duplicates": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.0.2.tgz", - "integrity": "sha512-LKY81YjUjc78p6rbXIsnppsaFo8XzCoMZkXVILJU//sK0DgPkPSpuq/cZvHss3EtdKvWNYgWzQL+wiJFtEET4g==" + "integrity": "sha512-LKY81YjUjc78p6rbXIsnppsaFo8XzCoMZkXVILJU//sK0DgPkPSpuq/cZvHss3EtdKvWNYgWzQL+wiJFtEET4g==", + "requires": {} }, "postcss-discard-empty": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.0.2.tgz", - "integrity": "sha512-SxBsbTjlsKUvZLL+dMrdWauuNZU8TBq5IOL/DHa6jBUSXFEwmDqeXRfTIK/FQpPTa8MJMxEHjSV3UbiuyLARPQ==" + "integrity": "sha512-SxBsbTjlsKUvZLL+dMrdWauuNZU8TBq5IOL/DHa6jBUSXFEwmDqeXRfTIK/FQpPTa8MJMxEHjSV3UbiuyLARPQ==", + "requires": {} }, "postcss-discard-overridden": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.0.3.tgz", - "integrity": "sha512-yRTXknIZA4k8Yo4FiF1xbsLj/VBxfXEWxJNIrtIy6HC9KQ4xJxcPtoaaskh6QptCGrrcGnhKsTsENTRPZOBu4g==" + "integrity": "sha512-yRTXknIZA4k8Yo4FiF1xbsLj/VBxfXEWxJNIrtIy6HC9KQ4xJxcPtoaaskh6QptCGrrcGnhKsTsENTRPZOBu4g==", + "requires": {} }, "postcss-merge-longhand": { "version": "5.0.5", @@ -28962,7 +29896,8 @@ "postcss-normalize-charset": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.0.2.tgz", - "integrity": "sha512-fEMhYXzO8My+gC009qDc/3bgnFP8Fv1Ic8uw4ec4YTlhIOw63tGPk1YFd7fk9bZUf1DAbkhiL/QPWs9JLqdF2g==" + "integrity": "sha512-fEMhYXzO8My+gC009qDc/3bgnFP8Fv1Ic8uw4ec4YTlhIOw63tGPk1YFd7fk9bZUf1DAbkhiL/QPWs9JLqdF2g==", + "requires": {} }, "postcss-normalize-display-values": { "version": "5.0.2", @@ -29470,6 +30405,11 @@ "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==" }, + "data-uri-to-buffer": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", + "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==" + }, "dataloader": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-1.4.0.tgz", @@ -29566,6 +30506,16 @@ "object-keys": "^1.1.1" } }, + "degenerator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", + "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", + "requires": { + "ast-types": "^0.13.4", + "escodegen": "^2.1.0", + "esprima": "^4.0.1" + } + }, "delaunator": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.0.tgz", @@ -29726,9 +30676,9 @@ } }, "devtools-protocol": { - "version": "0.0.981744", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.981744.tgz", - "integrity": "sha512-0cuGS8+jhR67Fy7qG3i3Pc7Aw494sb9yG9QgpG97SFVWwolgYjlhJg7n+UaHxOQT30d1TYu/EYe9k01ivLErIg==" + "version": "0.0.1413902", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1413902.tgz", + "integrity": "sha512-yRtvFD8Oyk7C9Os3GmnFZLu53yAfsnyw1s+mLmHHUK0GQEc9zthHWvS1r67Zqzm5t7v56PILHIVZ7kmFMaL2yQ==" }, "dir-glob": { "version": "3.0.1", @@ -29929,6 +30879,11 @@ "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==" }, + "env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==" + }, "envinfo": { "version": "7.8.1", "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", @@ -30087,6 +31042,25 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, + "escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "requires": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true + } + } + }, "eslint": { "version": "7.32.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", @@ -30503,7 +31477,8 @@ "eslint-plugin-react-hooks": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", - "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==" + "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", + "requires": {} }, "eslint-scope": { "version": "5.1.1", @@ -30941,6 +31916,11 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, + "fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" + }, "fast-glob": { "version": "3.2.11", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", @@ -31021,7 +32001,7 @@ "fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", "requires": { "pend": "~1.2.0" } @@ -31763,7 +32743,8 @@ "postcss-flexbugs-fixes": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-5.0.2.tgz", - "integrity": "sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==" + "integrity": "sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==", + "requires": {} }, "resolve-from": { "version": "5.0.0", @@ -31806,6 +32787,13 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, + "type-fest": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", + "optional": true, + "peer": true + }, "universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", @@ -33001,7 +33989,8 @@ "gatsby-script": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/gatsby-script/-/gatsby-script-1.10.0.tgz", - "integrity": "sha512-8jAtQR0mw3G8sCy6i2D1jfGvUF5d9AIboEQuo9ZEChT4Ep5f+PSRxiWZqSjhKvintAOIeS4QXCJP5Rtp3xZKLg==" + "integrity": "sha512-8jAtQR0mw3G8sCy6i2D1jfGvUF5d9AIboEQuo9ZEChT4Ep5f+PSRxiWZqSjhKvintAOIeS4QXCJP5Rtp3xZKLg==", + "requires": {} }, "gatsby-sharp": { "version": "0.19.0", @@ -33477,6 +34466,16 @@ "get-intrinsic": "^1.1.1" } }, + "get-uri": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.4.tgz", + "integrity": "sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ==", + "requires": { + "basic-ftp": "^5.0.2", + "data-uri-to-buffer": "^6.0.2", + "debug": "^4.3.4" + } + }, "git-up": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/git-up/-/git-up-7.0.0.tgz", @@ -33755,7 +34754,8 @@ "graphql-type-json": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/graphql-type-json/-/graphql-type-json-0.3.2.tgz", - "integrity": "sha512-J+vjof74oMlCWXSvt0DOf2APEdZOCdubEvGDUAlqH//VBYcOYsGgRW7Xzorr44LvkjiuvecWc8fChxuZZbChtg==" + "integrity": "sha512-J+vjof74oMlCWXSvt0DOf2APEdZOCdubEvGDUAlqH//VBYcOYsGgRW7Xzorr44LvkjiuvecWc8fChxuZZbChtg==", + "requires": {} }, "gray-matter": { "version": "4.0.3", @@ -34074,6 +35074,15 @@ } } }, + "http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "requires": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + } + }, "http2-wrapper": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", @@ -34091,11 +35100,11 @@ } }, "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "requires": { - "agent-base": "6", + "agent-base": "^7.1.2", "debug": "4" } }, @@ -34133,9 +35142,9 @@ "integrity": "sha512-AizQPcaofEtO11RZhPPHBOJRdo/20MKQF9mBLnVkBoyHi1/zXK8fzVdnEpSV9gxqtnh6Qomfp3F0xT5qP/vThw==" }, "import-fresh": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", - "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "requires": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -34286,6 +35295,22 @@ "loose-envify": "^1.0.0" } }, + "ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "requires": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "dependencies": { + "sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==" + } + } + }, "ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -34742,6 +35767,11 @@ "esprima": "^4.0.0" } }, + "jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" + }, "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -34757,11 +35787,6 @@ "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz", "integrity": "sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w==" }, - "json-parse-better-errors": { - "version": "1.0.2", - "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", @@ -36156,6 +37181,11 @@ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, + "netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==" + }, "next-tick": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", @@ -36580,6 +37610,30 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, + "pac-proxy-agent": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz", + "integrity": "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==", + "requires": { + "@tootallnate/quickjs-emscripten": "^0.23.0", + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "get-uri": "^6.0.1", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.6", + "pac-resolver": "^7.0.1", + "socks-proxy-agent": "^8.0.5" + } + }, + "pac-resolver": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", + "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", + "requires": { + "degenerator": "^5.0.0", + "netmask": "^2.0.2" + } + }, "package-json": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", @@ -36675,13 +37729,13 @@ } }, "parse-json": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz", - "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "requires": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1", + "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, @@ -36840,7 +37894,7 @@ "pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" }, "performance-now": { "version": "2.1.0", @@ -37037,7 +38091,8 @@ "prism-react-renderer": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-1.3.5.tgz", - "integrity": "sha512-IJ+MSwBWKG+SM3b2SUfdrhC+gu01QkV2KmRQgREThBfSQRoufqRfxfHUxpG1WcaFjP+kojcFyO9Qqtpgt3qLCg==" + "integrity": "sha512-IJ+MSwBWKG+SM3b2SUfdrhC+gu01QkV2KmRQgREThBfSQRoufqRfxfHUxpG1WcaFjP+kojcFyO9Qqtpgt3qLCg==", + "requires": {} }, "probe-image-size": { "version": "7.2.3", @@ -37118,6 +38173,28 @@ "ipaddr.js": "1.9.1" } }, + "proxy-agent": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz", + "integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==", + "requires": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.1", + "https-proxy-agent": "^7.0.6", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.1.0", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.5" + }, + "dependencies": { + "lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==" + } + } + }, "proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -37151,36 +38228,75 @@ } }, "puppeteer": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-13.7.0.tgz", - "integrity": "sha512-U1uufzBjz3+PkpCxFrWzh4OrMIdIb2ztzCu0YEPfRHjHswcSwHZswnK+WdsOQJsRV8WeTg3jLhJR4D867+fjsA==", - "requires": { - "cross-fetch": "3.1.5", - "debug": "4.3.4", - "devtools-protocol": "0.0.981744", - "extract-zip": "2.0.1", - "https-proxy-agent": "5.0.1", - "pkg-dir": "4.2.0", - "progress": "2.0.3", - "proxy-from-env": "1.1.0", - "rimraf": "3.0.2", - "tar-fs": "2.1.1", - "unbzip2-stream": "1.4.3", - "ws": "8.5.0" + "version": "24.4.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.4.0.tgz", + "integrity": "sha512-E4JhJzjS8AAI+6N/b+Utwarhz6zWl3+MR725fal+s3UlOlX2eWdsvYYU+Q5bXMjs9eZEGkNQroLkn7j11s2k1Q==", + "requires": { + "@puppeteer/browsers": "2.8.0", + "chromium-bidi": "2.1.2", + "cosmiconfig": "^9.0.0", + "devtools-protocol": "0.0.1413902", + "puppeteer-core": "24.4.0", + "typed-query-selector": "^2.12.0" }, "dependencies": { - "cross-fetch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", - "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", "requires": { - "node-fetch": "2.6.7" + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + } + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "requires": { + "argparse": "^2.0.1" + } + } + } + }, + "puppeteer-core": { + "version": "24.4.0", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.4.0.tgz", + "integrity": "sha512-eFw66gCnWo0X8Hyf9KxxJtms7a61NJVMiSaWfItsFPzFBsjsWdmcNlBdsA1WVwln6neoHhsG+uTVesKmTREn/g==", + "requires": { + "@puppeteer/browsers": "2.8.0", + "chromium-bidi": "2.1.2", + "debug": "^4.4.0", + "devtools-protocol": "0.0.1413902", + "typed-query-selector": "^2.12.0", + "ws": "^8.18.1" + }, + "dependencies": { + "debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "requires": { + "ms": "^2.1.3" } }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, "ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==" + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==", + "requires": {} } } }, @@ -37527,7 +38643,8 @@ "react-icons": { "version": "4.7.1", "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.7.1.tgz", - "integrity": "sha512-yHd3oKGMgm7zxo3EA7H2n7vxSoiGmHk5t6Ou4bXsfcgWyhfDKMpyKfhHR6Bjnn63c+YXBLBPUql9H4wPJM6sXw==" + "integrity": "sha512-yHd3oKGMgm7zxo3EA7H2n7vxSoiGmHk5t6Ou4bXsfcgWyhfDKMpyKfhHR6Bjnn63c+YXBLBPUql9H4wPJM6sXw==", + "requires": {} }, "react-is": { "version": "16.13.1", @@ -37654,7 +38771,8 @@ "redux-thunk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz", - "integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==" + "integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==", + "requires": {} }, "regenerate": { "version": "1.4.0", @@ -38818,6 +39936,11 @@ "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.5.tgz", "integrity": "sha512-8mo9bslnBO3tr5PEVFzMPIWwWnipGS0xVbYf65zxDqfNwmzYn1LpiKNrR6DlClusuvo+hDHd1zKpmfAe83NQSQ==" }, + "smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==" + }, "snake-case": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-2.1.0.tgz", @@ -38864,6 +39987,25 @@ "debug": "~4.3.1" } }, + "socks": { + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.4.tgz", + "integrity": "sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ==", + "requires": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + } + }, + "socks-proxy-agent": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", + "requires": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "socks": "^2.8.3" + } + }, "source-list-map": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", @@ -39064,6 +40206,16 @@ "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==" }, + "streamx": { + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.22.0.tgz", + "integrity": "sha512-sLh1evHOzBy/iWRiR6d1zRcLao4gGZr3C1kzNz4fopCOKJb6xD9ub8Mpi9Mr1R6id5o43S+d93fI48UC5uM9aw==", + "requires": { + "bare-events": "^2.2.0", + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.0" + } + }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -39479,9 +40631,9 @@ "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" }, "tar-fs": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.2.tgz", + "integrity": "sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==", "requires": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", @@ -39591,6 +40743,14 @@ } } }, + "text-decoder": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", + "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", + "requires": { + "b4a": "^1.6.4" + } + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -39797,6 +40957,11 @@ "resolved": "https://registry.npmjs.org/type-of/-/type-of-2.0.1.tgz", "integrity": "sha1-5yoXQYllaOn2KDeNgW1pEvfyOXI=" }, + "typed-query-selector": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.0.tgz", + "integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==" + }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -39810,6 +40975,12 @@ "is-typedarray": "^1.0.0" } }, + "typescript": { + "version": "5.8.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", + "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", + "peer": true + }, "ua-parser-js": { "version": "0.7.33", "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.33.tgz", @@ -39826,15 +40997,6 @@ "which-boxed-primitive": "^1.0.2" } }, - "unbzip2-stream": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", - "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", - "requires": { - "buffer": "^5.2.1", - "through": "^2.3.8" - } - }, "unc-path-regex": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", @@ -40359,7 +41521,8 @@ "use-editable": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/use-editable/-/use-editable-2.3.3.tgz", - "integrity": "sha512-7wVD2JbfAFJ3DK0vITvXBdpd9JAz5BcKAAolsnLBuBn6UDDwBGuCIAGvR3yA2BNKm578vAMVHFCWaOcA+BhhiA==" + "integrity": "sha512-7wVD2JbfAFJ3DK0vITvXBdpd9JAz5BcKAAolsnLBuBn6UDDwBGuCIAGvR3yA2BNKm578vAMVHFCWaOcA+BhhiA==", + "requires": {} }, "util-deprecate": { "version": "1.0.2", @@ -40503,7 +41666,8 @@ "acorn-import-attributes": { "version": "1.9.5", "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", - "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==" + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "requires": {} }, "schema-utils": { "version": "3.3.0", @@ -40787,7 +41951,8 @@ "ws": { "version": "8.2.3", "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", - "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==" + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "requires": {} }, "x-is-string": { "version": "0.1.0", @@ -40900,7 +42065,7 @@ "yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", "requires": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" @@ -40946,6 +42111,11 @@ } } }, + "zod": { + "version": "3.24.2", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz", + "integrity": "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==" + }, "zwitch": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz", diff --git a/docs/package.json b/docs/package.json index 21766c5f5406..cfd2de97c49e 100644 --- a/docs/package.json +++ b/docs/package.json @@ -37,7 +37,7 @@ "postcss": "^8.4.31", "prism-react-renderer": "^1.3.5", "prop-types": "^15.8.1", - "puppeteer": "^13.7.0", + "puppeteer": "^24.4.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-headroom": "^3.2.1", From a1a9836c44c1aecf0913a181f6934a21285f1feb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 29 Mar 2025 01:12:24 +0100 Subject: [PATCH 009/152] build(deps): bump github.com/ghostiam/protogetter from 0.3.12 to 0.3.13 (#5658) Co-authored-by: Fernandez Ludovic --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 423c12939046..7eae5155e2de 100644 --- a/go.mod +++ b/go.mod @@ -39,7 +39,7 @@ require ( github.com/fatih/color v1.18.0 github.com/firefart/nonamedreturns v1.0.5 github.com/fzipp/gocyclo v0.6.0 - github.com/ghostiam/protogetter v0.3.12 + github.com/ghostiam/protogetter v0.3.13 github.com/go-critic/go-critic v0.13.0 github.com/go-viper/mapstructure/v2 v2.2.1 github.com/go-xmlfmt/xmlfmt v1.1.3 diff --git a/go.sum b/go.sum index 3d633f4b3ffa..a73360d747ac 100644 --- a/go.sum +++ b/go.sum @@ -170,8 +170,8 @@ github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwV 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/ghostiam/protogetter v0.3.12 h1:xTPjH97iKph27vXRRKV0OCke5sAMoHPbVeVstdzmCLE= -github.com/ghostiam/protogetter v0.3.12/go.mod h1:WZ0nw9pfzsgxuRsPOFQomgDVSWtDLJRfQJEhsGbmQMA= +github.com/ghostiam/protogetter v0.3.13 h1:T4qt1JU0xvx8+jO30+JaA49fngUd6YNajqwk0Rn3t1s= +github.com/ghostiam/protogetter v0.3.13/go.mod h1:WZ0nw9pfzsgxuRsPOFQomgDVSWtDLJRfQJEhsGbmQMA= github.com/go-critic/go-critic v0.13.0 h1:kJzM7wzltQasSUXtYyTl6UaPVySO6GkaR1thFnJ6afY= github.com/go-critic/go-critic v0.13.0/go.mod h1:M/YeuJ3vOCQDnP2SU+ZhjgRzwzcBW87JqLpMJLrZDLI= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= From 3f0afe4a96174dd8ea4a0d2f3559898eca8b2b4d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 29 Mar 2025 01:13:13 +0100 Subject: [PATCH 010/152] build(deps): bump github.com/Antonboom/testifylint from 1.6.0 to 1.6.1 (#5654) Co-authored-by: Fernandez Ludovic --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7eae5155e2de..65ad99e18cfa 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/Abirdcfly/dupword v0.1.3 github.com/Antonboom/errname v1.1.0 github.com/Antonboom/nilnil v1.1.0 - github.com/Antonboom/testifylint v1.6.0 + github.com/Antonboom/testifylint v1.6.1 github.com/BurntSushi/toml v1.5.0 github.com/Crocmagnon/fatcontext v0.7.1 github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 diff --git a/go.sum b/go.sum index a73360d747ac..e06df5d5f89c 100644 --- a/go.sum +++ b/go.sum @@ -43,8 +43,8 @@ github.com/Antonboom/errname v1.1.0 h1:A+ucvdpMwlo/myWrkHEUEBWc/xuXdud23S8tmTb/o github.com/Antonboom/errname v1.1.0/go.mod h1:O1NMrzgUcVBGIfi3xlVuvX8Q/VP/73sseCaAppfjqZw= github.com/Antonboom/nilnil v1.1.0 h1:jGxJxjgYS3VUUtOTNk8Z1icwT5ESpLH/426fjmQG+ng= github.com/Antonboom/nilnil v1.1.0/go.mod h1:b7sAlogQjFa1wV8jUW3o4PMzDVFLbTux+xnQdvzdcIE= -github.com/Antonboom/testifylint v1.6.0 h1:6rdILVPt4+rqcvhid8w9wJNynKLUgqHNpFyM67UeXyc= -github.com/Antonboom/testifylint v1.6.0/go.mod h1:k+nEkathI2NFjKO6HvwmSrbzUcQ6FAnbZV+ZRrnXPLI= +github.com/Antonboom/testifylint v1.6.1 h1:6ZSytkFWatT8mwZlmRCHkWz1gPi+q6UBSbieji2Gj/o= +github.com/Antonboom/testifylint v1.6.1/go.mod h1:k+nEkathI2NFjKO6HvwmSrbzUcQ6FAnbZV+ZRrnXPLI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= From 45bd17c6dfde1da5e0144e654d9b48071afe88c1 Mon Sep 17 00:00:00 2001 From: Oleksandr Redko Date: Sat, 29 Mar 2025 11:48:12 -0700 Subject: [PATCH 011/152] docs: cleanup config reference (#5659) --- .golangci.next.reference.yml | 72 ++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index 81d741134a69..52a474c759b3 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -121,7 +121,7 @@ linters: - wsl - zerologlint - # Disable specific linter + # Disable specific linter. # https://golangci-lint.run/usage/linters/#disabled-by-default disable: - asasalint @@ -266,7 +266,7 @@ linters: # Default: 10 max-complexity: 10 # The maximal average package complexity. - # If it's higher than 0.0 (float) the check is enabled + # If it's higher than 0.0 (float) the check is enabled. # Default: 0.0 package-average: 0.5 @@ -279,7 +279,7 @@ linters: - var - func - # If true, underscore vars (vars with "_" as the name) will be ignored at all checks + # 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 @@ -295,15 +295,15 @@ linters: # Default: true (disabled) disable-dec-num-check: false - # If true, type declarations will be ignored for dec num check + # 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 + # 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 + # If true, var declarations will be ignored for dec num check. # Default: false (var statements are not ignored) disable-var-dec-num-check: false @@ -428,7 +428,7 @@ linters: # 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) + # 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. @@ -508,7 +508,7 @@ linters: # Optional message that gets included in error reports. - pattern: ^fmt\.Print.*$ msg: Do not commit print statements. - # Alternatively, put messages at the end of the regex, surrounded by `(# )?` + # Alternatively, put messages at the end of the regex, surrounded by `(# )?`. # Escape any special characters. Those messages get included in error reports. - pattern: 'fmt\.Print.*(# Do not commit print statements\.)?' # Forbid spew Dump, whether it is called as function or method. @@ -563,11 +563,11 @@ linters: # Default: false suppress-async-assertion: true - # Suppress warning for comparing values from different types, like `int32` and `uint32` + # 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` + # Trigger warning for ginkgo focus containers like `FDescribe`, `FContext`, `FWhen` or `FIt`. # Default: false forbid-focus-container: true @@ -581,7 +581,7 @@ linters: force-expect-to: true # Best effort validation of async intervals (timeout and polling). - # Ignored the suppress-async-assertion is true. + # Ignored the `suppress-async-assertion` is true. # Default: false validate-async-intervals: true @@ -597,7 +597,7 @@ linters: # Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed. # Default: true default-signifies-exhaustive: false - # Include shared interfaces in the exhaustiviness check. + # Include shared interfaces in the exhaustiveness check. # Default: false include-shared-interfaces: true @@ -619,10 +619,10 @@ linters: # Search also for duplicated numbers. # Default: false numbers: true - # Minimum value, only works with goconst.numbers + # Minimum value, only works with `goconst.numbers`. # Default: 3 min: 2 - # Maximum value, only works with goconst.numbers + # Maximum value, only works with `goconst.numbers`. # Default: 3 max: 2 # Ignore when constant is not used as function argument. @@ -1095,7 +1095,7 @@ linters: # 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.com/overview. + # The list of supported checkers can be found at https://go-critic.com/overview. settings: # Must be valid enabled check name. captLocal: @@ -1234,19 +1234,19 @@ linters: # for example: AUTHOR: .*@mycompany\.com # The template used for checking. - # Put here copyright header template for source code files + # Put here copyright header template for source code files. # Note: {{ YEAR }} is a builtin value that returns the year relative to the current machine time. # Default: "" template: |- {{ 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. @@ -1494,13 +1494,13 @@ linters: # 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 + # Maximum allowed permissions mode for os.Mkdir and os.MkdirAll. # Default: "0750" G301: "0750" - # Maximum allowed permissions mode for os.OpenFile and os.Chmod + # Maximum allowed permissions mode for os.OpenFile and os.Chmod. # Default: "0600" G302: "0600" - # Maximum allowed permissions mode for os.WriteFile and ioutil.WriteFile + # Maximum allowed permissions mode for os.WriteFile and ioutil.WriteFile. # Default: "0600" G306: "0600" @@ -1536,7 +1536,7 @@ linters: # Default: false disable-all: true # Enable analyzers by name. - # (in addition to default: + # (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, @@ -1636,7 +1636,7 @@ linters: # Default: false enable-all: true # Disable analyzers by name. - # (in addition to default + # (In addition to default # atomicalign, deepequalerrors, fieldalignment, findcall, nilness, reflectvaluecompare, shadow, sortslice, # timeformat, unusedwrite # ). @@ -1703,16 +1703,16 @@ linters: # Default: false strict: true unusedresult: - # Comma-separated list of functions whose results must be used - # (in addition to default: + # 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) + # 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 @@ -1778,7 +1778,7 @@ linters: 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 + # See https://github.com/julz/importas#use-regular-expression for details. - pkg: knative.dev/serving/pkg/apis/(\w+)/(v[\w\d]+) alias: $1$2 # An explicit empty alias can be used to ensure no aliases are used for a package. @@ -1917,14 +1917,14 @@ linters: - 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" + # 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` + # Values always ignored: `.+_test.go`. # Default: [] ignored-files: - 'magic1_.+\.go$' @@ -1979,7 +1979,7 @@ linters: - unsafeptr nlreturn: - # Size of the block (including return statement that is still "OK") + # Size of the block (including return statement that is still "OK"), # so no return split required. # Default: 1 block-size: 2 @@ -2681,7 +2681,7 @@ linters: exclude: [""] rowserrcheck: - # database/sql is always checked + # database/sql is always checked. # Default: [] packages: - github.com/jmoiron/sqlx @@ -3267,7 +3267,7 @@ linters: # Align and sort can be used together or separately. # # Whether enable align. If true, the struct tags will be aligned. - # e.g.: + # E.g.: # type FooBar struct { # Bar string `json:"bar" validate:"required"` # FooFoo int8 `json:"foo_foo" validate:"required"` @@ -3281,7 +3281,7 @@ linters: 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"` + # 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. @@ -3947,7 +3947,7 @@ formatters: gci: # 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 > localmodule`, + # The default order of sections is `standard > default > custom > blank > dot > alias > localmodule`. # If `custom-order` is `true`, it follows the order of `sections` option. # Default: ["standard", "default"] sections: From 8411157015f79215d00e3b6156bfc3843498bda5 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Sun, 30 Mar 2025 14:27:46 +0200 Subject: [PATCH 012/152] dev: rewrite and simplify thanks page generation (#5662) --- pkg/lint/lintersdb/builder_linter.go | 2 +- scripts/website/expand_templates/thanks.go | 96 ++++++++---- .../website/expand_templates/thanks_test.go | 142 ++++++++++++++++++ 3 files changed, 211 insertions(+), 29 deletions(-) create mode 100644 scripts/website/expand_templates/thanks_test.go diff --git a/pkg/lint/lintersdb/builder_linter.go b/pkg/lint/lintersdb/builder_linter.go index 6c533d2e4878..7e8e4ad1ba51 100644 --- a/pkg/lint/lintersdb/builder_linter.go +++ b/pkg/lint/lintersdb/builder_linter.go @@ -450,7 +450,7 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { linter.NewConfig(misspell.New(&cfg.Linters.Settings.Misspell)). WithSince("v1.8.0"). WithAutoFix(). - WithURL("https://github.com/client9/misspell"), + WithURL("https://github.com/golangci/misspell"), linter.NewConfig(musttag.New(&cfg.Linters.Settings.MustTag)). WithSince("v1.51.0"). diff --git a/scripts/website/expand_templates/thanks.go b/scripts/website/expand_templates/thanks.go index c3b8c8daee72..66ee8511c6e8 100644 --- a/scripts/website/expand_templates/thanks.go +++ b/scripts/website/expand_templates/thanks.go @@ -3,6 +3,7 @@ package main import ( "fmt" "maps" + "regexp" "slices" "strings" @@ -11,6 +12,11 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/lint/lintersdb" ) +const ( + hostGitHub = "github" + hostGitLab = "gitlab" +) + type authorDetails struct { Linters []string Profile string @@ -35,29 +41,29 @@ func getThanksList() string { continue } - linterURL := extractLinterURL(lc) + info := extractInfo(lc) - if author := extractAuthor(linterURL, "https://github.com/"); author != "" && author != "golangci" { - if _, ok := addedAuthors[author]; ok { - addedAuthors[author].Linters = append(addedAuthors[author].Linters, lc.Name()) + switch { + case info.FromGitHub(): + if _, ok := addedAuthors[info.Author]; ok { + addedAuthors[info.Author].Linters = append(addedAuthors[info.Author].Linters, lc.Name()) } else { - addedAuthors[author] = &authorDetails{ + addedAuthors[info.Author] = &authorDetails{ Linters: []string{lc.Name()}, - Profile: fmt.Sprintf("[%[1]s](https://github.com/sponsors/%[1]s)", author), - Avatar: fmt.Sprintf(`%[1]s`, author), + Profile: fmt.Sprintf("[%[1]s](https://github.com/sponsors/%[1]s)", info.Author), + Avatar: fmt.Sprintf(`%[1]s`, info.Author), } } - } else if author := extractAuthor(linterURL, "https://gitlab.com/"); author != "" { - if _, ok := addedAuthors[author]; ok { - addedAuthors[author].Linters = append(addedAuthors[author].Linters, lc.Name()) + + case info.FromGitLab(): + if _, ok := addedAuthors[info.Author]; ok { + addedAuthors[info.Author].Linters = append(addedAuthors[info.Author].Linters, lc.Name()) } else { - addedAuthors[author] = &authorDetails{ + addedAuthors[info.Author] = &authorDetails{ Linters: []string{lc.Name()}, - Profile: fmt.Sprintf("[%[1]s](https://gitlab.com/%[1]s)", author), + Profile: fmt.Sprintf("[%[1]s](https://gitlab.com/%[1]s)", info.Author), } } - } else { - continue } } @@ -78,31 +84,65 @@ func getThanksList() string { return strings.Join(lines, "\n") } -func extractLinterURL(lc *linter.Config) string { +type authorInfo struct { + Author string + Host string +} + +func extractInfo(lc *linter.Config) authorInfo { + exp := regexp.MustCompile(`https://(github|gitlab)\.com/([^/]+)/.*`) + switch lc.Name() { case "staticcheck": - return "https://github.com/dominikh/go-tools" + return authorInfo{Author: "dominikh", Host: hostGitHub} - case "depguard": - return "https://github.com/dixonwille/depguard" + case "misspell": + return authorInfo{Author: "client9", Host: hostGitHub} default: - if strings.HasPrefix(lc.OriginalURL, "https://github.com/gostaticanalysis/") { - return "https://github.com/tenntenn/gostaticanalysis" + if strings.HasPrefix(lc.OriginalURL, "https://pkg.go.dev/") { + return authorInfo{Author: "golang", Host: hostGitHub} } - if strings.HasPrefix(lc.OriginalURL, "https://github.com/go-simpler/") { - return "https://github.com/tmzane/go-simpler" + if !exp.MatchString(lc.OriginalURL) { + return authorInfo{} + } + + submatch := exp.FindAllStringSubmatch(lc.OriginalURL, -1) + + info := authorInfo{ + Author: submatch[0][2], + Host: submatch[0][1], } - return lc.OriginalURL + switch info.Author { + case "gostaticanalysis": + info.Author = "tenntenn" + + case "go-simpler": + info.Author = "tmzane" + + case "curioswitch": + info.Author = "chokoswitch" + + case "GaijinEntertainment": + info.Author = "xobotyi" + + case "OpenPeeDeeP": + info.Author = "dixonwille" + + case "golangci": + return authorInfo{} + } + + return info } } -func extractAuthor(originalURL, prefix string) string { - if !strings.HasPrefix(originalURL, prefix) { - return "" - } +func (i authorInfo) FromGitHub() bool { + return i.Host == hostGitHub +} - return strings.SplitN(strings.TrimPrefix(originalURL, prefix), "/", 2)[0] +func (i authorInfo) FromGitLab() bool { + return i.Host == hostGitLab } diff --git a/scripts/website/expand_templates/thanks_test.go b/scripts/website/expand_templates/thanks_test.go new file mode 100644 index 000000000000..6af152336e99 --- /dev/null +++ b/scripts/website/expand_templates/thanks_test.go @@ -0,0 +1,142 @@ +package main + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/golangci/golangci-lint/v2/pkg/lint/linter" + "github.com/golangci/golangci-lint/v2/pkg/result" +) + +type FakeLinter struct { + name string +} + +func (*FakeLinter) Run(_ context.Context, _ *linter.Context) ([]result.Issue, error) { + return nil, nil +} + +func (f *FakeLinter) Name() string { + return f.name +} + +func (*FakeLinter) Desc() string { + return "fake linter" +} + +func Test_extractInfo(t *testing.T) { + testCases := []struct { + desc string + lc *linter.Config + expected authorInfo + }{ + { + desc: "from GitHub", + lc: &linter.Config{ + Linter: &FakeLinter{name: "fake"}, + OriginalURL: "https://github.com/owner/linter", + }, + expected: authorInfo{Author: "owner", Host: "github"}, + }, + { + desc: "from GitLab", + lc: &linter.Config{ + Linter: &FakeLinter{name: "fake"}, + OriginalURL: "https://gitlab.com/owner/linter", + }, + expected: authorInfo{Author: "owner", Host: "gitlab"}, + }, + { + desc: "staticcheck", + lc: &linter.Config{ + Linter: &FakeLinter{name: "staticcheck"}, + OriginalURL: "https://github.com/owner/linter", + }, + expected: authorInfo{Author: "dominikh", Host: "github"}, + }, + { + desc: "gostaticanalysis", + lc: &linter.Config{ + Linter: &FakeLinter{name: "fake"}, + OriginalURL: "https://github.com/gostaticanalysis/linter", + }, + expected: authorInfo{Author: "tenntenn", Host: "github"}, + }, + { + desc: "go-simpler", + lc: &linter.Config{ + Linter: &FakeLinter{name: "fake"}, + OriginalURL: "https://github.com/go-simpler/linter", + }, + expected: authorInfo{Author: "tmzane", Host: "github"}, + }, + { + desc: "curioswitch", + lc: &linter.Config{ + Linter: &FakeLinter{name: "fake"}, + OriginalURL: "https://github.com/curioswitch/linter", + }, + expected: authorInfo{Author: "chokoswitch", Host: "github"}, + }, + { + desc: "GaijinEntertainment", + lc: &linter.Config{ + Linter: &FakeLinter{name: "fake"}, + OriginalURL: "https://github.com/GaijinEntertainment/linter", + }, + expected: authorInfo{Author: "xobotyi", Host: "github"}, + }, + { + desc: "OpenPeeDeeP", + lc: &linter.Config{ + Linter: &FakeLinter{name: "fake"}, + OriginalURL: "https://github.com/OpenPeeDeeP/linter", + }, + expected: authorInfo{Author: "dixonwille", Host: "github"}, + }, + { + desc: "misspell", + lc: &linter.Config{ + Linter: &FakeLinter{name: "misspell"}, + OriginalURL: "https://github.com/myorg/linter", + }, + expected: authorInfo{Author: "client9", Host: "github"}, + }, + { + desc: "pkg.go.dev", + lc: &linter.Config{ + Linter: &FakeLinter{name: "fake"}, + OriginalURL: "https://pkg.go.dev/linter", + }, + expected: authorInfo{Author: "golang", Host: "github"}, + }, + { + desc: "golangci", + lc: &linter.Config{ + Linter: &FakeLinter{name: "fake"}, + OriginalURL: "https://github.com/golangci/linter", + }, + expected: authorInfo{}, + }, + { + desc: "invalid", + lc: &linter.Config{ + Linter: &FakeLinter{name: "fake"}, + OriginalURL: "https://example.com/linter", + }, + expected: authorInfo{}, + }, + } + + for _, test := range testCases { + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + info := extractInfo(test.lc) + + assert.Equal(t, test.expected, info) + }) + } +} From a395a3e952f0467fc87658e4e560a3506cfdfb1f Mon Sep 17 00:00:00 2001 From: Oleksandr Redko Date: Mon, 31 Mar 2025 06:06:39 -0700 Subject: [PATCH 013/152] docs: remove tenv linter settings (#5665) --- .golangci.next.reference.yml | 6 ------ .golangci.reference.yml | 6 ------ jsonschema/golangci.jsonschema.json | 15 --------------- jsonschema/golangci.next.jsonschema.json | 15 --------------- 4 files changed, 42 deletions(-) diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index 52a474c759b3..2667c443973d 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -3395,12 +3395,6 @@ linters: # Default: false ignore: true - 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 diff --git a/.golangci.reference.yml b/.golangci.reference.yml index 81d741134a69..339fe9bcca52 100644 --- a/.golangci.reference.yml +++ b/.golangci.reference.yml @@ -3395,12 +3395,6 @@ linters: # Default: false ignore: true - 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 diff --git a/jsonschema/golangci.jsonschema.json b/jsonschema/golangci.jsonschema.json index 776a489afd98..e775096e315b 100644 --- a/jsonschema/golangci.jsonschema.json +++ b/jsonschema/golangci.jsonschema.json @@ -803,7 +803,6 @@ "stylecheck", "tagalign", "tagliatelle", - "tenv", "testableexamples", "testifylint", "testpackage", @@ -3339,17 +3338,6 @@ } } }, - "tenvSettings": { - "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 - } - } - }, "testifylintSettings": { "type": "object", "additionalProperties": false, @@ -4475,9 +4463,6 @@ "tagliatelle": { "$ref": "#/definitions/settings/definitions/tagliatelleSettings" }, - "tenv": { - "$ref": "#/definitions/settings/definitions/tenvSettings" - }, "testifylint": { "$ref": "#/definitions/settings/definitions/testifylintSettings" }, diff --git a/jsonschema/golangci.next.jsonschema.json b/jsonschema/golangci.next.jsonschema.json index 776a489afd98..e775096e315b 100644 --- a/jsonschema/golangci.next.jsonschema.json +++ b/jsonschema/golangci.next.jsonschema.json @@ -803,7 +803,6 @@ "stylecheck", "tagalign", "tagliatelle", - "tenv", "testableexamples", "testifylint", "testpackage", @@ -3339,17 +3338,6 @@ } } }, - "tenvSettings": { - "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 - } - } - }, "testifylintSettings": { "type": "object", "additionalProperties": false, @@ -4475,9 +4463,6 @@ "tagliatelle": { "$ref": "#/definitions/settings/definitions/tagliatelleSettings" }, - "tenv": { - "$ref": "#/definitions/settings/definitions/tenvSettings" - }, "testifylint": { "$ref": "#/definitions/settings/definitions/testifylintSettings" }, From 3f275e32ba2214884b9233a698f5b202f8e88a13 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Mon, 31 Mar 2025 17:09:18 +0200 Subject: [PATCH 014/152] docs: improve default exclusions render (#5661) --- .../gatsby-theme-docs/src/styles/global.js | 1 + .../website/expand_templates/exclusions.go | 36 ++++++++++--------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/docs/src/@rocketseat/gatsby-theme-docs/src/styles/global.js b/docs/src/@rocketseat/gatsby-theme-docs/src/styles/global.js index f1a5617fe722..6b6a61d464f9 100644 --- a/docs/src/@rocketseat/gatsby-theme-docs/src/styles/global.js +++ b/docs/src/@rocketseat/gatsby-theme-docs/src/styles/global.js @@ -66,6 +66,7 @@ export default function GlobalStyle() { font-weight: 400; } + span.inline-code, code.inline-code { display: inline-block; vertical-align: middle; diff --git a/scripts/website/expand_templates/exclusions.go b/scripts/website/expand_templates/exclusions.go index 99638b72d39a..b84cae8a1b03 100644 --- a/scripts/website/expand_templates/exclusions.go +++ b/scripts/website/expand_templates/exclusions.go @@ -10,22 +10,26 @@ import ( const exclusionTmpl = `{{- $tick := "` + "`" + `" -}} {{- range $name, $rules := . }} -### {{ $tick }}{{ $name }}{{ $tick }} -{{ range $rule := $rules }} -{{ $tick }}{{ range $linter := $rule.Linters }}{{ $linter }}{{ end }}{{ $tick }}: -{{ if $rule.Path -}} -- Path: {{ $tick }}{{ $rule.Path }}{{ $tick }} -{{ end -}} -{{ if $rule.PathExcept -}} -- Path Except: {{ $tick }}{{ $rule.PathExcept }}{{ $tick }} -{{ end -}} -{{ if $rule.Text -}} -- Text: {{ $tick }}{{ $rule.Text }}{{ $tick }} -{{ end -}} -{{ if $rule.Source -}} -- Source: {{ $tick }}{{ $rule.Source }}{{ $tick }} -{{ end -}} -{{ end }}{{ end }}` +### Preset {{ $tick }}{{ $name }}{{ $tick }} + + + + + + + + + +{{- range $rule := $rules }} + + + + +{{- end }} + +
LinterIssue Text
{{ range $linter := $rule.Linters }}{{ $linter }}{{ end }}{{ if $rule.Text }}{{ $rule.Text }}{{ end }}
+ +{{ end }}` func getExclusionPresets() (string, error) { linterExclusionPresets, err := readJSONFile[map[string][]types.ExcludeRule](filepath.Join("assets", "exclusion-presets.json")) From 6f6f105de5647e69903563b55698a8801fd6cb8d Mon Sep 17 00:00:00 2001 From: kasaikou Date: Tue, 1 Apr 2025 00:45:23 +0900 Subject: [PATCH 015/152] docs: fix `go get -tool` command (#5669) --- docs/src/docs/welcome/install.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/docs/welcome/install.mdx b/docs/src/docs/welcome/install.mdx index 335443a92403..c67c1dbf971a 100644 --- a/docs/src/docs/welcome/install.mdx +++ b/docs/src/docs/welcome/install.mdx @@ -203,7 +203,7 @@ go tool -modfile=golangci-lint.mod golangci-lint run ```sh # Update golangci-lint -go get -tool -modfile=golangci-lint.mod github.com/golangci/v2/golangci-lint/cmd/golangci-lint@latest +go get -tool -modfile=golangci-lint.mod github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest ``` **Method 2: dedicated module** From db2214f2fe56830722f03e76078ca7245b9a97ab Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Tue, 1 Apr 2025 13:42:59 +0200 Subject: [PATCH 016/152] fix: gocritic importshadow checker (#5673) --- pkg/goformat/runner.go | 8 +- pkg/golinters/gocritic/gocritic.go | 337 +----------------- pkg/golinters/gocritic/gocritic_settings.go | 330 +++++++++++++++++ .../testdata/gocritic_importShadow.go | 17 + .../testdata/gocritic_inportShadow.yml | 8 + pkg/golinters/revive/revive.go | 6 +- pkg/lint/package.go | 4 +- 7 files changed, 378 insertions(+), 332 deletions(-) create mode 100644 pkg/golinters/gocritic/gocritic_settings.go create mode 100644 pkg/golinters/gocritic/testdata/gocritic_importShadow.go create mode 100644 pkg/golinters/gocritic/testdata/gocritic_inportShadow.yml diff --git a/pkg/goformat/runner.go b/pkg/goformat/runner.go index 4105b9fbf718..3207f117d552 100644 --- a/pkg/goformat/runner.go +++ b/pkg/goformat/runner.go @@ -12,7 +12,7 @@ import ( "regexp" "strings" - "github.com/rogpeppe/go-internal/diff" + rpdiff "github.com/rogpeppe/go-internal/diff" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/fsutils" @@ -32,11 +32,11 @@ type Runner struct { exitCode int } -func NewRunner(log logutils.Log, +func NewRunner(logger logutils.Log, metaFormatter *goformatters.MetaFormatter, matcher *processors.GeneratedFileMatcher, opts RunnerOptions) *Runner { return &Runner{ - log: log, + log: logger, matcher: matcher, metaFormatter: metaFormatter, opts: opts, @@ -128,7 +128,7 @@ func (c *Runner) process(path string, stdout io.Writer, in io.Reader) error { if c.opts.diff { newName := filepath.ToSlash(path) oldName := newName + ".orig" - _, err = stdout.Write(diff.Diff(oldName, input, newName, output)) + _, err = stdout.Write(rpdiff.Diff(oldName, input, newName, output)) if err != nil { return err } diff --git a/pkg/golinters/gocritic/gocritic.go b/pkg/golinters/gocritic/gocritic.go index 4fcd9b124385..0a9ec0561cd0 100644 --- a/pkg/golinters/gocritic/gocritic.go +++ b/pkg/golinters/gocritic/gocritic.go @@ -88,6 +88,7 @@ func (w *goCriticWrapper) init(logger logutils.Log, settings *config.GoCriticSet settingsWrapper := newSettingsWrapper(settings, logger) 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 { @@ -113,7 +114,19 @@ func (w *goCriticWrapper) run(pass *analysis.Pass) error { linterCtx.SetPackageInfo(pass.TypesInfo, pass.Pkg) - runOnPackage(pass, enabledCheckers, pass.Files) + needFileInfo := slices.ContainsFunc(enabledCheckers, func(c *gocriticlinter.Checker) bool { + // Related to https://github.com/go-critic/go-critic/blob/440ff466685b41e67d231a1c4a8f5e093374ee93/checkers/importShadow_checker.go#L23 + return strings.EqualFold(c.Info.Name, "importShadow") + }) + + for _, f := range pass.Files { + if needFileInfo { + // Related to https://github.com/go-critic/go-critic/blob/440ff466685b41e67d231a1c4a8f5e093374ee93/checkers/importShadow_checker.go#L23 + linterCtx.SetFileInfo(f.Name.Name, f) + } + + runOnFile(pass, f, enabledCheckers) + } return nil } @@ -195,12 +208,6 @@ func (w *goCriticWrapper) normalizeCheckerParamsValue(p any) any { } } -func runOnPackage(pass *analysis.Pass, checks []*gocriticlinter.Checker, files []*ast.File) { - for _, f := range files { - runOnFile(pass, f, checks) - } -} - func runOnFile(pass *analysis.Pass, f *ast.File, checks []*gocriticlinter.Checker) { for _, c := range checks { // All checkers are expected to use *lint.Context @@ -227,312 +234,6 @@ func runOnFile(pass *analysis.Pass, f *ast.File, checks []*gocriticlinter.Checke } } -type goCriticChecks[T any] map[string]T - -func (m goCriticChecks[T]) has(name string) bool { - _, ok := m[name] - return ok -} - -type settingsWrapper struct { - *config.GoCriticSettings - - logger logutils.Log - - allCheckers []*gocriticlinter.CheckerInfo - - allChecks goCriticChecks[struct{}] - allChecksByTag goCriticChecks[[]string] - allTagsSorted []string - inferredEnabledChecks goCriticChecks[struct{}] - - // *LowerCased fields are used for GoCriticSettings.SettingsPerCheck validation only. - - allChecksLowerCased goCriticChecks[struct{}] - inferredEnabledChecksLowerCased goCriticChecks[struct{}] -} - -func newSettingsWrapper(settings *config.GoCriticSettings, logger logutils.Log) *settingsWrapper { - allCheckers := gocriticlinter.GetCheckersInfo() - - 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{}{} - - for _, tag := range checker.Tags { - allChecksByTag[tag] = append(allChecksByTag[tag], checker.Name) - } - } - - allTagsSorted := slices.Sorted(maps.Keys(allChecksByTag)) - - return &settingsWrapper{ - GoCriticSettings: settings, - logger: logger, - allCheckers: allCheckers, - allChecks: allChecks, - allChecksLowerCased: allChecksLowerCased, - allChecksByTag: allChecksByTag, - allTagsSorted: allTagsSorted, - inferredEnabledChecks: make(goCriticChecks[struct{}]), - inferredEnabledChecksLowerCased: make(goCriticChecks[struct{}]), - } -} - -func (s *settingsWrapper) IsCheckEnabled(name string) bool { - return s.inferredEnabledChecks.has(name) -} - -func (s *settingsWrapper) GetLowerCasedParams() map[string]config.GoCriticCheckSettings { - return normalizeMap(s.SettingsPerCheck) -} - -// InferEnabledChecks tries to be consistent with (lintersdb.Manager).build. -func (s *settingsWrapper) InferEnabledChecks() { - s.debugChecksInitialState() - - enabledByDefaultChecks, disabledByDefaultChecks := s.buildEnabledAndDisabledByDefaultChecks() - - debugChecksListf(enabledByDefaultChecks, "Enabled by default") - debugChecksListf(disabledByDefaultChecks, "Disabled by default") - - enabledChecks := make(goCriticChecks[struct{}]) - - 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{}{} - } - } - - if len(s.EnabledTags) != 0 { - enabledFromTags := s.expandTagsToChecks(s.EnabledTags) - - debugChecksListf(enabledFromTags, "Enabled by config tags %s", s.EnabledTags) - - for _, check := range enabledFromTags { - enabledChecks[check] = struct{}{} - } - } - - if len(s.EnabledChecks) != 0 { - debugChecksListf(s.EnabledChecks, "Enabled by config") - - for _, check := range s.EnabledChecks { - if enabledChecks.has(check) { - s.logger.Warnf("%s: no need to enable check %q: it's already enabled", linterName, check) - continue - } - enabledChecks[check] = struct{}{} - } - } - - if len(s.DisabledTags) != 0 { - disabledFromTags := s.expandTagsToChecks(s.DisabledTags) - - debugChecksListf(disabledFromTags, "Disabled by config tags %s", s.DisabledTags) - - for _, check := range disabledFromTags { - delete(enabledChecks, check) - } - } - - if len(s.DisabledChecks) != 0 { - debugChecksListf(s.DisabledChecks, "Disabled by config") - - for _, check := range s.DisabledChecks { - if !enabledChecks.has(check) { - s.logger.Warnf("%s: no need to disable check %q: it's already disabled", linterName, check) - continue - } - delete(enabledChecks, check) - } - } - - s.inferredEnabledChecks = enabledChecks - s.inferredEnabledChecksLowerCased = normalizeMap(s.inferredEnabledChecks) - - s.debugChecksFinalState() -} - -func (s *settingsWrapper) 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 -} - -func (s *settingsWrapper) expandTagsToChecks(tags []string) []string { - var checks []string - for _, tag := range tags { - checks = append(checks, s.allChecksByTag[tag]...) - } - return checks -} - -func (s *settingsWrapper) debugChecksInitialState() { - if !isDebug { - return - } - - debugf("All gocritic existing tags and checks:") - for _, tag := range s.allTagsSorted { - debugChecksListf(s.allChecksByTag[tag], " tag %q", tag) - } -} - -func (s *settingsWrapper) debugChecksFinalState() { - if !isDebug { - return - } - - var enabledChecks []string - var disabledChecks []string - - for _, checker := range s.allCheckers { - check := checker.Name - if s.inferredEnabledChecks.has(check) { - enabledChecks = append(enabledChecks, check) - } else { - disabledChecks = append(disabledChecks, check) - } - } - - debugChecksListf(enabledChecks, "Final used") - - if len(disabledChecks) == 0 { - debugf("All checks are enabled") - } else { - debugChecksListf(disabledChecks, "Final not used") - } -} - -// Validate tries to be consistent with (lintersdb.Validator).validateEnabledDisabledLintersConfig. -func (s *settingsWrapper) 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 *settingsWrapper) validateOptionsCombinations() error { - if s.EnableAll { - if s.DisableAll { - return errors.New("enable-all and disable-all options must not be combined") - } - - if len(s.EnabledTags) != 0 { - return errors.New("enable-all and enabled-tags options must not be combined") - } - - if len(s.EnabledChecks) != 0 { - return errors.New("enable-all and enabled-checks options must not be combined") - } - } - - if s.DisableAll { - if len(s.DisabledTags) != 0 { - return errors.New("disable-all and disabled-tags options must not be combined") - } - - if len(s.DisabledChecks) != 0 { - return errors.New("disable-all and disabled-checks options must not be combined") - } - - 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 nil -} - -func (s *settingsWrapper) 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, linterName) - } - } - - for _, tag := range s.DisabledTags { - if !s.allChecksByTag.has(tag) { - return fmt.Errorf("disabled tag %q doesn't exist, see %s's documentation", tag, linterName) - } - } - - return nil -} - -func (s *settingsWrapper) validateCheckerNames() error { - for _, check := range s.EnabledChecks { - if !s.allChecks.has(check) { - return fmt.Errorf("enabled check %q doesn't exist, see %s's documentation", check, linterName) - } - } - - for _, check := range s.DisabledChecks { - if !s.allChecks.has(check) { - return fmt.Errorf("disabled check %q doesn't exist, see %s documentation", check, linterName) - } - } - - for check := range s.SettingsPerCheck { - lcName := strings.ToLower(check) - if !s.allChecksLowerCased.has(lcName) { - return fmt.Errorf("invalid check settings: check %q doesn't exist, see %s documentation", check, linterName) - } - if !s.inferredEnabledChecksLowerCased.has(lcName) { - s.logger.Warnf("%s: settings were provided for disabled check %q", check, linterName) - } - } - - return nil -} - -func (s *settingsWrapper) 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) - } - } - - for _, check := range s.DisabledChecks { - if slices.Contains(s.EnabledChecks, check) { - return fmt.Errorf("check %q disabled and enabled at one moment", check) - } - } - - return nil -} - -func (s *settingsWrapper) validateAtLeastOneCheckerEnabled() error { - if len(s.inferredEnabledChecks) == 0 { - return errors.New("eventually all checks were disabled: at least one must be enabled") - } - return nil -} - func normalizeMap[ValueT any](in map[string]ValueT) map[string]ValueT { ret := make(map[string]ValueT, len(in)) for k, v := range in { @@ -548,13 +249,3 @@ func isEnabledByDefaultGoCriticChecker(info *gocriticlinter.CheckerInfo) bool { !info.HasTag(gocriticlinter.PerformanceTag) && !info.HasTag(gocriticlinter.SecurityTag) } - -func debugChecksListf(checks []string, format string, args ...any) { - if !isDebug { - return - } - - v := slices.Sorted(slices.Values(checks)) - - debugf("%s checks (%d): %s", fmt.Sprintf(format, args...), len(checks), strings.Join(v, ", ")) -} diff --git a/pkg/golinters/gocritic/gocritic_settings.go b/pkg/golinters/gocritic/gocritic_settings.go new file mode 100644 index 000000000000..13e1f8f2a5b9 --- /dev/null +++ b/pkg/golinters/gocritic/gocritic_settings.go @@ -0,0 +1,330 @@ +package gocritic + +import ( + "errors" + "fmt" + "maps" + "slices" + "strings" + + gocriticlinter "github.com/go-critic/go-critic/linter" + + "github.com/golangci/golangci-lint/v2/pkg/config" + "github.com/golangci/golangci-lint/v2/pkg/logutils" +) + +type settingsWrapper struct { + *config.GoCriticSettings + + logger logutils.Log + + allCheckers []*gocriticlinter.CheckerInfo + + allChecks goCriticChecks[struct{}] + allChecksByTag goCriticChecks[[]string] + allTagsSorted []string + inferredEnabledChecks goCriticChecks[struct{}] + + // *LowerCased fields are used for GoCriticSettings.SettingsPerCheck validation only. + + allChecksLowerCased goCriticChecks[struct{}] + inferredEnabledChecksLowerCased goCriticChecks[struct{}] +} + +func newSettingsWrapper(settings *config.GoCriticSettings, logger logutils.Log) *settingsWrapper { + allCheckers := gocriticlinter.GetCheckersInfo() + + 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{}{} + + for _, tag := range checker.Tags { + allChecksByTag[tag] = append(allChecksByTag[tag], checker.Name) + } + } + + allTagsSorted := slices.Sorted(maps.Keys(allChecksByTag)) + + return &settingsWrapper{ + GoCriticSettings: settings, + logger: logger, + allCheckers: allCheckers, + allChecks: allChecks, + allChecksLowerCased: allChecksLowerCased, + allChecksByTag: allChecksByTag, + allTagsSorted: allTagsSorted, + inferredEnabledChecks: make(goCriticChecks[struct{}]), + inferredEnabledChecksLowerCased: make(goCriticChecks[struct{}]), + } +} + +func (s *settingsWrapper) IsCheckEnabled(name string) bool { + return s.inferredEnabledChecks.has(name) +} + +func (s *settingsWrapper) GetLowerCasedParams() map[string]config.GoCriticCheckSettings { + return normalizeMap(s.SettingsPerCheck) +} + +// InferEnabledChecks tries to be consistent with (lintersdb.Manager).build. +func (s *settingsWrapper) InferEnabledChecks() { + s.debugChecksInitialState() + + enabledByDefaultChecks, disabledByDefaultChecks := s.buildEnabledAndDisabledByDefaultChecks() + + debugChecksListf(enabledByDefaultChecks, "Enabled by default") + debugChecksListf(disabledByDefaultChecks, "Disabled by default") + + enabledChecks := make(goCriticChecks[struct{}]) + + 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{}{} + } + } + + if len(s.EnabledTags) != 0 { + enabledFromTags := s.expandTagsToChecks(s.EnabledTags) + + debugChecksListf(enabledFromTags, "Enabled by config tags %s", s.EnabledTags) + + for _, check := range enabledFromTags { + enabledChecks[check] = struct{}{} + } + } + + if len(s.EnabledChecks) != 0 { + debugChecksListf(s.EnabledChecks, "Enabled by config") + + for _, check := range s.EnabledChecks { + if enabledChecks.has(check) { + s.logger.Warnf("%s: no need to enable check %q: it's already enabled", linterName, check) + continue + } + enabledChecks[check] = struct{}{} + } + } + + if len(s.DisabledTags) != 0 { + disabledFromTags := s.expandTagsToChecks(s.DisabledTags) + + debugChecksListf(disabledFromTags, "Disabled by config tags %s", s.DisabledTags) + + for _, check := range disabledFromTags { + delete(enabledChecks, check) + } + } + + if len(s.DisabledChecks) != 0 { + debugChecksListf(s.DisabledChecks, "Disabled by config") + + for _, check := range s.DisabledChecks { + if !enabledChecks.has(check) { + s.logger.Warnf("%s: no need to disable check %q: it's already disabled", linterName, check) + continue + } + delete(enabledChecks, check) + } + } + + s.inferredEnabledChecks = enabledChecks + s.inferredEnabledChecksLowerCased = normalizeMap(s.inferredEnabledChecks) + + s.debugChecksFinalState() +} + +func (s *settingsWrapper) 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 +} + +func (s *settingsWrapper) expandTagsToChecks(tags []string) []string { + var checks []string + for _, tag := range tags { + checks = append(checks, s.allChecksByTag[tag]...) + } + return checks +} + +func (s *settingsWrapper) debugChecksInitialState() { + if !isDebug { + return + } + + debugf("All gocritic existing tags and checks:") + for _, tag := range s.allTagsSorted { + debugChecksListf(s.allChecksByTag[tag], " tag %q", tag) + } +} + +func (s *settingsWrapper) debugChecksFinalState() { + if !isDebug { + return + } + + var enabledChecks []string + var disabledChecks []string + + for _, checker := range s.allCheckers { + check := checker.Name + if s.inferredEnabledChecks.has(check) { + enabledChecks = append(enabledChecks, check) + } else { + disabledChecks = append(disabledChecks, check) + } + } + + debugChecksListf(enabledChecks, "Final used") + + if len(disabledChecks) == 0 { + debugf("All checks are enabled") + } else { + debugChecksListf(disabledChecks, "Final not used") + } +} + +// Validate tries to be consistent with (lintersdb.Validator).validateEnabledDisabledLintersConfig. +func (s *settingsWrapper) 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 *settingsWrapper) validateOptionsCombinations() error { + if s.EnableAll { + if s.DisableAll { + return errors.New("enable-all and disable-all options must not be combined") + } + + if len(s.EnabledTags) != 0 { + return errors.New("enable-all and enabled-tags options must not be combined") + } + + if len(s.EnabledChecks) != 0 { + return errors.New("enable-all and enabled-checks options must not be combined") + } + } + + if s.DisableAll { + if len(s.DisabledTags) != 0 { + return errors.New("disable-all and disabled-tags options must not be combined") + } + + if len(s.DisabledChecks) != 0 { + return errors.New("disable-all and disabled-checks options must not be combined") + } + + 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 nil +} + +func (s *settingsWrapper) 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, linterName) + } + } + + for _, tag := range s.DisabledTags { + if !s.allChecksByTag.has(tag) { + return fmt.Errorf("disabled tag %q doesn't exist, see %s's documentation", tag, linterName) + } + } + + return nil +} + +func (s *settingsWrapper) validateCheckerNames() error { + for _, check := range s.EnabledChecks { + if !s.allChecks.has(check) { + return fmt.Errorf("enabled check %q doesn't exist, see %s's documentation", check, linterName) + } + } + + for _, check := range s.DisabledChecks { + if !s.allChecks.has(check) { + return fmt.Errorf("disabled check %q doesn't exist, see %s documentation", check, linterName) + } + } + + for check := range s.SettingsPerCheck { + lcName := strings.ToLower(check) + if !s.allChecksLowerCased.has(lcName) { + return fmt.Errorf("invalid check settings: check %q doesn't exist, see %s documentation", check, linterName) + } + if !s.inferredEnabledChecksLowerCased.has(lcName) { + s.logger.Warnf("%s: settings were provided for disabled check %q", check, linterName) + } + } + + return nil +} + +func (s *settingsWrapper) 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) + } + } + + for _, check := range s.DisabledChecks { + if slices.Contains(s.EnabledChecks, check) { + return fmt.Errorf("check %q disabled and enabled at one moment", check) + } + } + + return nil +} + +func (s *settingsWrapper) validateAtLeastOneCheckerEnabled() error { + if len(s.inferredEnabledChecks) == 0 { + return errors.New("eventually all checks were disabled: at least one must be enabled") + } + return nil +} + +type goCriticChecks[T any] map[string]T + +func (m goCriticChecks[T]) has(name string) bool { + _, ok := m[name] + return ok +} + +func debugChecksListf(checks []string, format string, args ...any) { + if !isDebug { + return + } + + v := slices.Sorted(slices.Values(checks)) + + debugf("%s checks (%d): %s", fmt.Sprintf(format, args...), len(checks), strings.Join(v, ", ")) +} diff --git a/pkg/golinters/gocritic/testdata/gocritic_importShadow.go b/pkg/golinters/gocritic/testdata/gocritic_importShadow.go new file mode 100644 index 000000000000..5f0242ba5a99 --- /dev/null +++ b/pkg/golinters/gocritic/testdata/gocritic_importShadow.go @@ -0,0 +1,17 @@ +//golangcitest:args -Egocritic +//golangcitest:config_path testdata/gocritic_inportShadow.yml +package testdata + +import ( + "fmt" + "path/filepath" +) + +func Bar() { + filepath.Join("a", "b") +} + +func foo() { + filepath := "foo.txt" // want "importShadow: shadow of imported package 'filepath'" + fmt.Printf("File path: %s\n", filepath) +} diff --git a/pkg/golinters/gocritic/testdata/gocritic_inportShadow.yml b/pkg/golinters/gocritic/testdata/gocritic_inportShadow.yml new file mode 100644 index 000000000000..14a2192e72b9 --- /dev/null +++ b/pkg/golinters/gocritic/testdata/gocritic_inportShadow.yml @@ -0,0 +1,8 @@ +version: "2" + +linters: + settings: + gocritic: + disable-all: true + enabled-checks: + - importShadow diff --git a/pkg/golinters/revive/revive.go b/pkg/golinters/revive/revive.go index 544f398a06b1..5f9b3a90ace1 100644 --- a/pkg/golinters/revive/revive.go +++ b/pkg/golinters/revive/revive.go @@ -453,11 +453,11 @@ func extractRulesName(rules []lint.Rule) []string { // Extracted from https://github.com/mgechev/revive/blob/v1.7.0/formatter/severity.go // Modified to use pointers (related to hugeParam rule). -func severity(config *lint.Config, failure *lint.Failure) lint.Severity { - if cfg, ok := config.Rules[failure.RuleName]; ok && cfg.Severity == lint.SeverityError { +func severity(cfg *lint.Config, failure *lint.Failure) lint.Severity { + if cfg, ok := cfg.Rules[failure.RuleName]; ok && cfg.Severity == lint.SeverityError { return lint.SeverityError } - if cfg, ok := config.Directives[failure.RuleName]; ok && cfg.Severity == lint.SeverityError { + if cfg, ok := cfg.Directives[failure.RuleName]; ok && cfg.Severity == lint.SeverityError { return lint.SeverityError } return lint.SeverityWarning diff --git a/pkg/lint/package.go b/pkg/lint/package.go index f9bf2230d074..3127a24b8e56 100644 --- a/pkg/lint/package.go +++ b/pkg/lint/package.go @@ -39,13 +39,13 @@ type PackageLoader struct { } // NewPackageLoader creates a new PackageLoader. -func NewPackageLoader(log logutils.Log, cfg *config.Config, args []string, goenv *goutil.Env, loadGuard *load.Guard) *PackageLoader { +func NewPackageLoader(log logutils.Log, cfg *config.Config, args []string, env *goutil.Env, loadGuard *load.Guard) *PackageLoader { return &PackageLoader{ cfg: cfg, args: args, log: log, debugf: logutils.Debug(logutils.DebugKeyLoader), - goenv: goenv, + goenv: env, pkgTestIDRe: regexp.MustCompile(`^(.*) \[(.*)\.test\]`), loadGuard: loadGuard, } From a2a26aebe61893d183bf0b2b530240188085f1d3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Apr 2025 14:24:09 +0200 Subject: [PATCH 017/152] build(deps): bump the linter-testdata group across 2 directories with 4 updates (#5676) Co-authored-by: Fernandez Ludovic --- pkg/golinters/ginkgolinter/testdata/go.mod | 12 +++++----- pkg/golinters/ginkgolinter/testdata/go.sum | 28 +++++++++++----------- pkg/golinters/protogetter/testdata/go.mod | 4 ++-- pkg/golinters/protogetter/testdata/go.sum | 8 +++---- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/pkg/golinters/ginkgolinter/testdata/go.mod b/pkg/golinters/ginkgolinter/testdata/go.mod index 90dc39e4cea8..8c158398b857 100644 --- a/pkg/golinters/ginkgolinter/testdata/go.mod +++ b/pkg/golinters/ginkgolinter/testdata/go.mod @@ -3,18 +3,18 @@ module ginkgolinter go 1.23.0 require ( - github.com/onsi/ginkgo/v2 v2.23.0 - github.com/onsi/gomega v1.36.2 + github.com/onsi/ginkgo/v2 v2.23.3 + github.com/onsi/gomega v1.36.3 ) require ( github.com/go-logr/logr v1.4.2 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect - github.com/google/go-cmp v0.6.0 // indirect + github.com/google/go-cmp v0.7.0 // indirect github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect - golang.org/x/net v0.35.0 // indirect - golang.org/x/sys v0.30.0 // indirect - golang.org/x/text v0.22.0 // indirect + golang.org/x/net v0.37.0 // indirect + golang.org/x/sys v0.31.0 // indirect + golang.org/x/text v0.23.0 // indirect golang.org/x/tools v0.30.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/pkg/golinters/ginkgolinter/testdata/go.sum b/pkg/golinters/ginkgolinter/testdata/go.sum index 724f093a7a0c..572cf22bd836 100644 --- a/pkg/golinters/ginkgolinter/testdata/go.sum +++ b/pkg/golinters/ginkgolinter/testdata/go.sum @@ -4,28 +4,28 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg= github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= -github.com/onsi/ginkgo/v2 v2.23.0 h1:FA1xjp8ieYDzlgS5ABTpdUDB7wtngggONc8a7ku2NqQ= -github.com/onsi/ginkgo/v2 v2.23.0/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM= -github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= -github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= +github.com/onsi/ginkgo/v2 v2.23.3 h1:edHxnszytJ4lD9D5Jjc4tiDkPBZ3siDeJJkUZJJVkp0= +github.com/onsi/ginkgo/v2 v2.23.3/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM= +github.com/onsi/gomega v1.36.3 h1:hID7cr8t3Wp26+cYnfcjR6HpJ00fdogN6dqZ1t6IylU= +github.com/onsi/gomega v1.36.3/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0= 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/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= -golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= -golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= -golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= -golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= +golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= -google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk= -google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= +google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= 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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/pkg/golinters/protogetter/testdata/go.mod b/pkg/golinters/protogetter/testdata/go.mod index 04826463206b..f3c8b01bdbc5 100644 --- a/pkg/golinters/protogetter/testdata/go.mod +++ b/pkg/golinters/protogetter/testdata/go.mod @@ -3,8 +3,8 @@ module protogetter go 1.22.0 require ( - google.golang.org/grpc v1.71.0 - google.golang.org/protobuf v1.36.5 + google.golang.org/grpc v1.71.1 + google.golang.org/protobuf v1.36.6 ) require ( diff --git a/pkg/golinters/protogetter/testdata/go.sum b/pkg/golinters/protogetter/testdata/go.sum index 387f3d99eb4c..979d39513453 100644 --- a/pkg/golinters/protogetter/testdata/go.sum +++ b/pkg/golinters/protogetter/testdata/go.sum @@ -28,7 +28,7 @@ golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= -google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg= -google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= -google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= -google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI= +google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= From 544018f712a7506c49ecdb75b8cb5a4e7bbb7534 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Tue, 1 Apr 2025 20:20:54 +0200 Subject: [PATCH 018/152] docs: update demo (#5677) --- docs/static/demo.gif | Bin 181448 -> 317958 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/static/demo.gif b/docs/static/demo.gif index 8a255c90e8343e2b75ac379c2fbdd9e37fb1e9f6..d9fccbf5921cb3c677fe2d2239fdeb4fdf12c0ed 100644 GIT binary patch literal 317958 zcmeFY~@b0Szl52|Xb>J7Gx&5vMXSIWsXtfCL+b1RtA(n3{x=m6V);l!AkliiwPZm5h>^ zoQQ~m0zyH-NI}6&K}AZ*Dn><4NkvXiMZrKNY(PywK}|_ZLkgiGW2M6a(~(2y@zLo? zY3b?N>3L-7rOhGa$uR^4#YI>tL}{4ClnlhtamDe7#WQOp z#pR_;1Ed-7Wf(YR_*rDkzsu=ZDI#MkDyS$?kSdFFshByd+DEC`|54{4*5DP>P!!N` z4Aw%%(CQY@)_SXtPoghCqirre`q`S2WcSHv@vqjjYVSM_Rly zw6JxwV&k=yXR{NRu~X2tb9A%wN&bj~|It{<;gg+{o4a#t$rnnxFM2XxIe6Xeblqc$ zzJ;ZKhr&EDv3`7Y_7WC{Dr-TlRJ{`le90*MzL@%j#0EtLgk(2{{&WbBO^u*~MChAE zib_OAdPh4s#eUU~jqr`FDvu9vi?8TU$jMD8uSksWO_5W|@OR9}`kNUE%c7^xYMIVf z)5@`P$oZR*Q&E{8;7}OuQKF+?QeIlh%~P5lS~jp+RZ>`!>{n}SR_oza*VI}sB-A*) z-&`Eq+Be*m?$>T*+n(av-dNQkA=!~1)xCV)qoLLR*{Q!SbFjB{cyeZV=WfKnXhKS2 z^7wJu(q`J(b-Jr`dc1#nX>G1Cc~Mzuu{nPE_Gx8dV(r7Hb=|k?yZf6XmD?@G+b=IW z8}obLzU~_vA70)Z%{CqFtsYxhUp_ospYL45Uv4-1?rx7B^xr-`T|JwdJ~slMFPC2~ zW?n9bUY?HNjR5%51|0qZfCFgY=o<36Z)K&m08tcjrSgmpACxyNCjI4qy8>|NR8o{GGJ8UZc|R@pS7h~tQ_BXE zD_3R@L^HiDG#RMO8H(q!9!ycL${k4-`g*uLP?a~9F6Dzpp;Dbck);&PVmeq|FqNm3 zrIM;rQ#ey(SoLXTu%>9P%%UrpLbbMdq3Xj_q3KX<$x@y3)?lh?UFk}b$JOD=P+i$t z8x(|2sa9XU(G~cH)oi%FVyiELPBl%fp>k&^f%o(3a6{GJScYr}rFvua!Bqa+BD0ak znxnaL>!CFDrrMLG`maZ;BTaQ@YwbShR2t3o7hC<&tmdQ54Oe^PS*qz8EsZxv^HrbM zMq8Th&epp^;8dEe%@0@mQ$^-utu2pt=UYSRnr*GmkM~zcYh!I~a5w;oX&s74_+cG} z!jQl2jUlkV?t`PiwBd`d|6#+A_go65q{i`RAMODj#3ji*pAjxVBU$*)&IB?Yxurk zC(gwEU?-lR;cpKag?q;|jrH|85QX#uU^m&hmw7M6b@t<4s>g1@UfR#wgS~Vp63c#u zFX5;BcxEV|6J0#?3yKa!F1HU7eszH~Dl>WEL2ios;Xz)8Kg(f$cHF1Kg8baV!$SYK zb6Ac81DsnSK<-%@ob2G}EQ4Bndw5jVj>LLg-c9)VxT2q-=(sW~SIfJI>_f&r-ftAQ ze!TLy@=i21*Q1lVb$`~=`t7*Srw#kLMW>C&wMVB-=e?|F&DXP^&sy$xi_Th~Zja8| z0LX0T?TAG7=N%}F#pj(Eg2(4wIEri+-S`If7d^ytO`WJsosHdD5)@J0=%n`R-nAro z#g~I@b;p-OTzza;!+dl0S0h4u#aE+ZcgI&_QbWz1Rk1uOpEce`S$;%qLOQvg(o$r< znbtLMxS27uE4i69`F3(MXX;ekfj}BD0ZSBgyYSCxbV0vea_(clTXvmuxLfhqE4f?! zc?VY)oMNngP*|j}SYjCb#aMd387g>szZId#@vt3Z!0|9%_9>%hfj_LGdMPe|k_*VF&n_J>RVdaK7Ac$2+||tReq`B2zb2%VFcEl(YZ4o^ygf z-|v;dU!JypcA~2~D-*pq3q2&Vf|=KeQI*=c5p&UD41pPl6oDLgE9>6G^xANN{thh9 zb02DqzbJczLYTTC5K}IblYT!bFwZ$6z8DcAgt&t^X~>(nIRimeK zj_R(|Ezo!o<{X+uzBk{D*Zv2hY%zt_1Mb1M`HSgSE=N`=1!Rl*9KzfVq~bzAm9Xdl zGmKl2D9d@%)YISwIr|WsM8I$-E}}Cqa+nmA2X$N=tf`f}RT`a}RljqZ&{uX~F?FDO z&R@ngOZnp3w<|bB_Jg@BKpdyi!&XV&Sc=ZloJ}{XnDsQ+fWTb7t92xzdMUZw;aq{b zfe}Z~t7HJ{233S%6o*HtLv%F^uP`$7-D)N2jFt>moNy*#Jpgl;OOgBTBm565Qx&*e z4u+l?f&4**Hwi4h1(pDe`ioru#Rlo?^K*=BJjqX^OO!QFjVXT z8IWY-O2aY-NyE+uKH6`TN{MSQ?Cxi>50;8fbb>pUsUPZUdhs4>kjn;#hQRUWXg z$i^wM=6ZliTdX%hLS~L3e*km$y~+>5>s;h8SxUJK*1t(N#UIp*jOT&{E5JaA@rS9W zL0exop_ziWT%Ed2Zis9aH)VGoHW=+Y-ZW5xV!LMicSJ+;y&|_25w;7pD&-B)zDghp z%y`^I=efwk4J01G9PT~9u=uhA%zr^r@FKVU%ah7iGty2W%dsH zhoJlJ7b{V9fEhiHP$HNdRB0^z8Y-ngvga4ajz5-3> zgqr=7fZ7)6(tWQGmT3T$5YWs}wthAOjHw1Fbx2(=gzg|qR(~@0_bgK9xG(&S?m3dW zdp~G6S{YZ@Ttkt?3T6TnI44S@lJ!q#ab$p0D++DCmP^CIjDYwetn=Xmov9@C?aH*f z;XR4R23s=;1GcL6P^yq=(&6<^%>4l%@xBzs!*HQ6V$+;sPDZ&b&XM{Xm5rm9hp7y# zntVmCGO4w4Fi|!{ym>>zNXr}Ps`xsPqXa0B;7!HO4)H1pw8Y!_%j3eZd{g*lskZB+yZ1UY=v4}prpii8L1}MQQ!Su9oO(O>P_t~|5o0y zd(-2}c`kPqb^flCa=+t~~~$mvK$Ye~I$y(8-i88FQij z{Kdiz#t}d)XKE11Jph^K<}#D)d0#2rdN_LYI#=}hAly`BI#1)K@Et{pPFv$_-RMmz zI`@$ocGG;HhWjkR{>?VM+?0p69NTF=E-t;?imHg8ej9sSeSEoV$8J3j(0tk?ThncnY`u&hd)gI+ zKa7XBUgv3gX+qlm&5yO-){Q-%{(wKOW4FO8OF3UIli^SMnr;8)#$Il#(w|Pl+n)9` z;s2K4FZW}T8SAe+{P=ngAcg{kposUs7`34&2~f0pD8@V#>mFL%`5Q+FhHnTX^nej3 zz(|$o@akcd_b_T=Z(1R5`UEcuLvN-8Z8$*A=OTYIC{-5go?dScK1N|L|16+gxTnz(AQ3Bi(0zB&je$EG+1O(`K z1Ie7hedQQkTp0cyfkAPRP+EWRpZX7V#G#!+q1{XY z@%dbIQh}xUfhGOHDqO%ych5ykd*wuzIG6+e%PkapKW55xetDP zI-piJPI?(>t?aPn{?O5UmmS0KTaR!$*FOxFbcgqxCm!$5JiwFVp%;OHYk}b?i4kZE zlK%|x1iS&5&LFwmKLxg&Z z)ks*28IJ=sTDKwIk}Dcg9(#fZqT>Rk;b5P%qZ(QuWt3yBL$O=Rml)P5HdGOq(B5mzAykqDtTueiRK)Hs|B!e#(X|c z5YdWhObm2_lf-u#rR{!ClafuL+K3|J0}Gxb3UUE3sS)IHl5oF+OcvPrwLq9$pe8Ns z5eu+rIf$JLD4~UM<(zC!l9myehV?H4CyDp)09U{YB#e(JI1Wf7Ny4*06tsB1oB0Q% zg*c>z-Lj5YNe@C2L4O3GM=*zj7cy`~viOX%NO=EJSkkfLfT(cN2O3g5xWG9iVe7P+ z^3<4*01Pz?kboA5wGkVwF?i#9VEKnEea{@jLN1{}+$R(eMM3^$lUe{UI^R*~yDVt)6+QNx133$mz@omQX-&oGkfy%Aq%qKngsn zg*`-#gct!ZcE+eVNNp%cMj8OM{VQ2VE9M6Vay}%=I~OZR6=sX%A7{#=og-hBV^3P3 z7jt1AabezDU_>m0ft7ReNJ{}^uN|4|n~*6=sJ4!@%AA1%mS7-{(&%SJhFryNx~ z1H=vpCt*#DXKBb!Zj4oIcw^b{c!|JCjqJ}=pHhzE0szrbgP6Gjr<^e+*PGhOn%jP0 zOpPZO{%GzW@+fA-EiK|?KDWoP0AQ^H-edr|ph+m%h#?jz!4@d1OD*g0p_a`d&~Q@o z?vGZlx@O#o=7&yphE6reBs-l2fH>ln^$~EK+c2PQH$U1?wOaSd+JP9~4$*OsLpYZ% zTW_jmdB%ZeB%u5Spa7tQ4caiqTnkF+AQf{5Kj9!ZcTkgedXQB<8q(4J>||04qd3N) zO6lZy>Wr!D#GL5lGU*bq_uv`E;rrPow%p|r--TY$B_Y-=SL`lTj3Z;xtu>rfaQb~y`h(%ehW?@bAy54g_WEJ= zoslL3aZiTPYIO0<11Tx`iDGoAZZ`0Z6vVIQcV`$`%(-kZamYS#(VbGO{4OO!# zRy@(xqzpBZ%heszHa!isW5~2D({`8)_ZCZb4b%2D4-eZ*3^db@kdI8NiH{Z2PW>F2 zZx)+LpKCGGin4Y70uLE|sTY#r@%1vxDX zwRIhbW0luC4A*R9hh&W~Z6hjRgLHKxq;G?ga?=-ilh$nWU}@dt-#SC<=8n=P+sh_m z=;qJDO)j&o+`UbKv@LSBtu&P_k(aH+fGsJBZGFaVxnJ9wcH2s=+e&%cYA@Ryd)rzP zJNS${y1#bL-|rZ#kw$uKmld!0xWI#2yL5 zp6jo@C)+)b*1eUSy`L|8^E-P`iT!HGzVEO71o-e)=iyf1>b_~|K6q&VkHmo`)`2wZ zK}_0#t>b}7$U)M}!N<`9&!dA3vqJ}t!&ueB+}6V{e-2BE4vQ&|+)fXN(T^&B9evk0 zI{JK6zk1|VdW1B5)GBcd!#bv9JMK<9_H#UD3q2luIS!Iog%l5ro1HXpoSdqi%(kAi z{W-xaIa#JW?KwT6#5~>nbvmSRD(rB&zj`_$v9Ucecq(yr#zBX#adzLT@1J(|WG3;r zdIrFjfK#3$a*Bh@&r#OIkkijG;G*bj=Qw4e*i;wzYa(yVFNmE+hb6j3(=I62q>11c zv}2=(j%&vfmrP?rWMy3x>6aYg5;X8j9{8Ccx8#*Tx*-4WD-lgW;kGLY_!uiyH#_`F zj!I12{8}lTUorh!O_E=A?ON-MPm}6Kca8V0`Hf*XuR;2ai6rm4wHu2w9&@T&n{*y) z^V<*R+;-`=_SoE?*KVELxSXi&T*D`&!@Fh8?>w;uzqZ}|TI2MB-+6~~!X)qgB{}_m z-v^&@1hw7&87ue(@BR+Ik8!$*bn1yVe@H63iC^nUYPD zU$N6|0cT&)+P})O+p_e&3dzU%v)dZ%{<`$XR?fSo-~BD{$8M)P$k-aA`O_daZ&=&Y zkF}>!^Sg1X=P#1a(`&c0zn?#*KQF?~Z%6>*4~s0CSW(~PSD;` z_(LK73z0-;TPX^no+g)A*`pH2ZrXT^^LAG)iQi#0Tx z)YBDGjc-29mY7PuU{qZlr&Pd=T611L@Z zxgO4xm?O6~%e(9hRs2S#GJEp4+!;w%lr$6lwzxRe7C>eG^7G%#$y#6fgV5u`=@lHA zO9}y*zFZ1~?P@RnB6NikZSB<-mzDkY0;h2YkdBmnlU2x5pSL0z^?W?-*SvRky_}%st zpGZ@6m8LW@q*_ZBd*l$V$pn(G)>fo?wIIsOI<86zj6HmB)dhF1M^qe|tKVuXLTYs1 zT0i0UXldHk=oy&%5wz*@oAB$ubL!zYF!f1x>oEQX7BI97fW%dpJv`PJ+Q!?~8rczHJj&evXP#unEpMf}vODFeF}x4^78Pp28vycYK*bhXr@rEhyJcW@WR7SjFjT* z)~piWcjBo?Zs&>8Q@?tqhOjomgT*xn-Bw6;siPdi*KLWVYS*>2 zKOP|IOOBlglA|TOaFVfy;l|c?*U>}vXia?J zC(j)>5lTR}MKV+03(JWNbMm!rUM5x)nZ0=Twc48UW}Z##bRzusvK|$Ju#!xzN`#-B z4eilPPnef>WVmm3G8T!lihh)4bhQlwKeMvJEVE}aqAgRIud;UBWQ-c^4zpgvAZ1Qe zY?*IPhzW_R@$98+RkbaL8!C;->12Exh88DGSj}p*AR7A5hC8-F?FuD2am<&&Ermq= zlm1tsDR}jJfto}zd&jBdH8FL;4q*)!eT9@AIXe-euNrQ(Q>h-7d!jqSW49DvwFk28 zByNnxo)fS=_m}LXz{b2kjM36T@*iZf@HG7drvFM>?#n_%v?JwWGKqSa6xfoq|F}=n zkllPxl2^fr_%oeN!G55ur!o;!I-P^*aG+|-GM+FxoqJt;pzgLfnsPdww|#t|>DM@t zfi;sq&333A+c=!fF;mcPfA}^hX((S~rm(#DP_M>wu-I{?DC79hpvQQi{Lf5rFx!#Q zj7WcV=}d{I{n5J}(!To9nbJ?iN2WKVz0IdHW%|cQ=HSQfcC6WQdA4Iqf}*Z&j@b$x z`(wB@CHPL_L}uo|ZMt^f>O6 zCYzqpIyS9<&v3JjiVpnenrkUID+hm=-5v_GOd31=*g0Cdb75`0>M3(RdRMx>GuKwR zQq~0cXAXRO)&y2?p1?}6K)SN;!1O;KrX;sSE3)q-=ymSrNU_AqV{gABbq9XD`r5p!&q2KiJA~F`P zR!q;iFaRU3?0)}b!}3{Z5W?ybThm;{;IuH5dw3b&vs}OxzA&7?a+Nsql+RbTFyjB| zDtTu)PiSmm)T8h!_2#&MwaI?)2hw%TCHV)LfRE#T3fD}JKdaan7biAEuCpMi*-Dy= zlahtkIs7GAYEFw&T!+_r@-3NK;fvEWEH?#uUVnAV7H9B2-4xk|Wf+bv&VmYWO59S@ zP0kkQt`Ba?{GQV+u$Sg{m~Sg$G1F`~mlkF|-d5#crhd>|TI?>kt*LoVws%@uYCO2D z>sd*14qsZ%XTEEg5l?b0TUv?xc-OQ;k?1kDw7PwiCpk8^_T#Q8HUw!g{aO4Rjy#jR zj$9Ygf!pfry}OkD$Ht@E7JQz4@otmoE~1mW^-IZzlr5^V;67;ymo}}Rp9vYi4}NjD ztl&4^;l#!pn%i|rm=hDHt@}Po!*bOyVX`M_CopEa_ceovVo`>Q{4%uF)rRgloypE~ zy2R&efx(K9MmqUKN$bt3R_c*CoN4y1#I-#BIms%Zeqlz#sT%#~iIb+*QVrI(M(f@q zH^Il13oQ4Rv(zK6yQUcgDvtu}v~xAVr;V^Qj~-C!McCZK7LC)_0Zq!?*t+IH?)2|b zPH9)vcTao5l%5mTDc3pi_XpZz&NF3{8ztYwJ1nVw{2oiYy{mmb*-QPg(gshyYcan& zgZ*~g!2Z45BluDmnf~O!nf@^6{&JN^;dLOH{BOqm_NL;u{fX1>`IWnuvJR>j)A01C zIsy2DUFxr!wxs71^P9(w-=7}Feox=j!SgQC;p%7U@c7%;zgGkB+ZE~BfojztxptYi z?O=>*B-eIvpLUeyD%9+D;i`7@pH&#s?fhHqSYlP!h#lN-I&hyV@%TE}WjpYTD+z2m z7{7K9nN$+TbkJpWkYZGlb$3usbx;gfP+oVCf;y>xR?yIQ67Y7?iB-_+cH&xhG8~sP z`gUSOcQO~3vs8DYbak@Xm$PqoB3^ZJvXyh;cfo19c!tY(<+>hpy5RiwWdg2USKeJh z7-hoQU8j{@qQj+P(_M#~T@pV_B@w%K@VcehN@e)E*JZlpj!Wcix|dzL6^l!hV!G!u zyH)H3ui0O;Z?DI4!_|e@LJ=y0) zUhwO>F9O&Pm1A!35%IwzTKyyR|Wx5)q4f@ez-qEe?)@|L< zGwab^{I)&c(aY%31G%=t>d~97(PP)PlkL&_tI@OUwsZWkN4l}g>9#Amv6r`FH;C=G zu44$kWA}XR57}dg)nkt~?N8HV$lGHtG3{`~aWwpKgr0UF|2U@HIO0t^*mfMpbsQPe zff76ZCVL!BuLHejoN#&^)2{>TW}F0Z0;i?}7cxQ4H}Pht17B}~%4UL)pp(dNf;MJ? zM81=>W&+YZLGIQ`u`|JRJwcVzNlh@xN+BAGVymY=S=cd zPqNx}vCT{hZclQ=c5#BIMDVA$d%Ae|r^Mx^;Cwe-{I*k4u2X`LZlTyI+3YD1y>8K- zDTV1NaldYfn<-_)X{nlSX~?u1-?Z#bx18Rzrp>ehL64%}v`);lvV4z9&9q+kw3=Iw z`p&fB^|WSAj~2nqJNg-&nVz@uGiJIodf;Atw;4;{8AJYFqnsI=>X~=8y(Tj=cH1*% zvAyQt*-!YhmOZ^z{Id>nvo<%qwzjj*`06JSvmbM2Kh?~B?wPfpnRVEib-bB%0?#=U z%zc5(x$w_@m7jCfn{%_Bb9bBj<~QdNJNG?j&a-CjN6*~PnK`eWxnEueUPB_k3Fcvt zd2jxCANhG-y?H;|d4IS00KfUb*!iHGd3bQmd`QoH=!rh`1WG>+z*9m9BUp%pEJX1y zM9VM4=q<$BF2uPl#QQBI#4aT28A8_QA>#ndjD^&lg|wT6bns#Z!Qx-YVkZA$mi%Hi zg%R)iyx=|pCKEzV>|#OAVqwiIs_)QKF{HSkpH|`CBIayw^U=h zRO_}>=eJZJyX3tCQzl;G9*1J1EHvyawcaeXftT9}mOCKJo&3vQIo=$^OS1h-E#k|4 ze#`x_%L6&fgEh-TJtmRjFhMPoKPQGb{m}f8&2k{K~Z6%FM|-93|jbY!Ej9 zp~`k;v1VndXJvV2Wo2h&HFge;4S;b&R}%JtDbE1H^ObGA)g9Z_UANUeKeP5{D1_K- z^Vz32Z1s3%^<-!D^k(%8Z0`yZfnj_jB*A{p_y8?ylqQt`pLpGvVGBhCLU7y{`&;uKIg! z@Aur@_rCe>dBp8~&)xH^-TTqI_j7j7Yj^M0?cQ&seJJ5RjA7qfVBbe!-&cR%@BO~N z`+k7`eqh}GeNgUxaP59b?|$g)e%S8*pWFR#q=N{;gGh#hD1n1$g@YLVgV^^6aqb84 z{s#$h2Z^}{Nwo*by$30?2dTRUX}1UINQW7OhkqFkGX)N_6b`fX4|Coh=DHu|`5)%T z9Twys7SOE?nJ!;uKYP~&bLpp9JJnmpP?i4ugQaJ9`Kkj*d-0Oba=YQNEcRY}LJXm`? z)O$QUdpxpxJbHUPhIBGccrw9oGAVE}rEoH>e=_s_WY+y;&i`aS?qnhNWHBua`d?+x zF=U_DcIazA6y>!W`q~fuKU<=@0Am0XfckX-4uC&@mi|vm4y<@gDqv62<&RCl6T=YD zi3vmDrPL+H%~TBP+t#fY(#jgZZ4={(>35mui=WOTh)9!^irFP@#s^tB5c4k{b3p9ht3dD@%AY4o{yQk( zH@q=UqAuAob2FbzgXuZW15wdc+c)5<1e;1B_(U(m@A~>s!AZYA*XDX6B6v&fZ9^ud zedW=>s>Qrx4Enmx=q|{9Jhmt*3aRTpZy;~P)hMfeHlew!!wd)=3rB?s zn?eq!qSKG^L;qhlZ0%hf4W8pE3LqYFR5}H7X`rPjnFx0$?AL&YuFi_Qg*54dbY>T> zU^-pXLHQVeI+biKG5;JJy=CDYkXWJ()6Y~kek z^>$?ch^laIsV9K7>X3)qw(Se^dKceC^_vlvu822d0v{03$aOzC(BXL*MxMh6iz416 zNuE4)2A~<{#M!Fy5eCSh(Pw0zOJTbaR|e7s1;RS83(O2`6fr485`K&2lp}ypr7T__ zq0Z&TbBsK*4|L-#_3ZVA)@Ylg~VYFJL|mkDR13oqme?39mz zdL3MSHv6T`8mGL!QK{u~J&=VzDj>f={g2F0Eor;fp ziK#`sEmSJraifb4;B*ZxKSvwA=cs$ql=?43zkdZT=@2b0`~Kj{#Y~;=`OG85V?sj{E03 zvQ-_dhT(Y8EG2;(1qvj>G0lJqloT;R0%IuV5LfnO($D9YcLSNeen9`y16khAQ-dsP z3QqR#I_m}`toRnQY60GMglLgbGs(QtSTT8T%T|}ab0cc-*`2W`-kOKS@>rRS4nMjb zXJ-b?v_3l_Uru8ueEoF-@G#rJ7gmQeykeQqB9`lxNIpzKA*n5wwJIN5(2!{IAs*bRajFPeLj6OiN>bln_s6x zQ{cZf3*?Tf)6r#cj_~EZX?N)cqN`DT?8wp@Cj#RLHH z3?dzv+4UDd;x;Z}lD@TF0a#<;1~nV6f8Pw6RRyU>uJf;nxfJ{lOj*20Z|V zfHRNN<)m~IKkb_8i8iZ(nCi>``fZ0MOzT+csiKuxqhbIlZQxMANuxy#$o1O>AAR~Z zMgBFEZ&c>dzPe9sD#m8eQ^cD*gvlzfZjBVLv_4puR?({c{i7Z_0Wnk>NNfRsHJ|mO zBY==l{GvXFCuj_eLehKUWmJ;EN6s5 zkTfDHHomixnBuQKEdwfX>YieVuFk^P1KR$-w7j`&|%?)TqXj%xouT8FmUJXHXlu<;g9XKU}z#uGFd+ zY-1b+aNtH0vVLn@{!t+pjMg<)(S?}h?QFLPrGdk~ye)XJjDWz&zIb^wJL-QZzaRIR z5nkdNPjgas0hz;&Efq~Tl**|W(GydqFtOgs)2}G0Y*XWK>1Qyk3)fR?cfvxMh-EO) z*deC+@YoF?Dp9L92>mzn#9sl7!@G4ZE+bcM=)y*&RS1Rqn@+TeSOJPpK)rd&FD#Y! z2;O^gSzWq)#{qgaj0?^(!J-;BR-xG^HfF!!&(>YYudf|4XsQaEmKZ$23HqKydVw;D zMveK@Sd56wIkFaL+rDlD2^(r+6S^~?>L_$f)r^|DFTDM@DlC!yG>-e!vZi8e z7mBo+m*Y7xc{LI3D2~cKuM*wQHI0I#>$3hSnNDFaR?C7wK0?b=!tj&1+>T0&(Vx-4 zw2}fW$g$S@iN<&7bqe5EyeaZmG|pQ6aHyTt_zI4kP!XLr`j0#}>?MV8G{&B1q}6LB z1|uL|S!tcM;7D0OJ-xof9=6GqP&+3i8&7-7^AtO4|F<$HyuuLjzeur$_&m4D8B<)ePT$^2in2h?>ffp8FKWfp!7^O%XWgpb=?`jXu3H`s> zTwVt+co~sm_&*AW?IMFl)0EtL@f%$hts zerxILEx0~f0iqLeIPH4B7Xz%3S8RmY1PpZE)-u}&KtaLx6X-3AV z{m%Xz(Xk-}adhA+wj>=iff!INXz54f{ViGMPmb-B0egxw5csJZG)Ar8JuU+R=UZ)RhKUQRxiV_)$%^i+ zd;5lguGfeEJRH=-VX!Bh16c>9E1@9j;!6z&MjpedkIdClonTd=Ds0g@E~HVuqxn9% zj~IA<(&(()x+IGZmidDW>EPUL`KRN{3flsE0=T~ciJ>j5;u#NOqdsGOnB5VO#8O+(h= zac>MQV?R9&W{U^_5)PEjrJt79q8%k)BV|gG@J%*1x}sj_#V~K#c{qkZx5ZUA0>b|m z_WxJEl>h$#Zd4YES8yl%hhwp#kp=LT3lKT}1O>nM}CgZ{Lb5%`1GcIrV&MjS&28S-Pfptm2?x%q5$ z3$PWOo8Au`#Ka+5jM;(8%Q9)A;Ng)L!iYlNt8dl5 z`Xw5Hv{kXeTPjO*++zIGLO&$*FQNZHqO<3#B!Tf8PsO=>n7 z(FN-r0&Xknb6?HXEn)(u<_}rfzOYFFO-2ZbY%dB`&n?26Oc^BfHw+5xa3L~^b6qVx zy`lV!T~Y}pu1^@(!fRz83o@t;!$LO3Yks=tQ=6k-<1!g(>og!DxE*o3go(LZtgmR^ zNXN&i;O7`nfL?aG6u(L7^^`f)iZ1(GT*N2t;w;(jA%cw+Hhl?ur z{ZH>5#~qrWG(F!MEotoEPgQ^HUfQqFsRV3 zOv-Ua^8M8`)@z3%AW6M4E2O_3qTz&vHm%R>u^0C?2LVYhUcJYHWx+t3{cYAS>mIZi zFQR|?g{3kOt^vM2rMJi2eYBsCxtClMSCacz2^TS>`!x<{~2Y|w&(i#dd;-N zqEhg^cTNa{0dYTxnj`GzWg6d*w!*N~ZZQq&?wy)=}j37hV2nbUKwL^IW+~ z!F1d&ZxeNT14#NYQC|7qGL{Kg*~FA0EINI0Xk74f zkF+mVdh95UOtsgs1YMTL{Zws1{witdC;Ikc&V6Wv$QY@)wT_frxf*{}dRRrz%wP&8 zRrTkag9JQPw>v<}+N;gNE*W&+luNlFT;hmX_&YTH`--Cq5-NCKs(kPp?mvZxDyBl4 zn{Uc4^&0f_noZ2XL^FK%+Bs`dpTgFCew)QI&RX?QFhv*>IL~B2yQBkC-QV0o%*EP- zKdi{jk<^)MqZM9aeP>FD0NMx1*RN`M>Ft{bGSt`OSV{ejr!WR}j04f}i7ncJc=}opocdv2&&^L(g>92y;QTP7o0eSN4Wm^}>V<1{*QgfbdHfgwtibGcTyE=!%zA~B#2qzQWLW@B{hVuMd7#yBCKUbdKO56 zeM-^C+(Rr)Y*oA`D)#zhOxi&-{!CHqwez2vN@xWw_}NQ7LtZhxYX#_NI4T_iG-lKG z&y`aABj{=|7@(e$5?B`1`fnxgf5qMZvN!MkGeWs8Mbd@Gp(@d#pu4~aW3vjtAS7keuZu4Evk_Jj8HZ|xMcMPP=3rVZ>VA# zjbgOqFiCQeL(fzQX;n*dP2l4tu#pNYtYVxA7!vz)Ul)5ck)T2#0Qu~mXHbnrC&Io& z$ZV4Fez*3-)1bhxR@kJKlkPotO_?4iS@kA+Fw!iK zK6G3s?+>}u&*gT2i}9DW8aTsRfr&Ou`T>nVp;%~WIq&RT6ig~_T4TLR$oHun$I1Q9 zAh+mQwhNWGJ zofsVjR2Tv(u?5ITeHD=)UMLbWpI}{jK9(T-L0XD zJihdxp%Z!vy{jvw5OX(_$gq%(_3I3vVMHTP*74Uy7ZkhS>{VYCb2U^^EBWVAq!un` z`xFh!?7@U^im3q^IZuoWC4G=~K1rQQ#;~av29^hwtrhA^Te>C3=2{k-5n#+O8L)5H zI;|NK27dS3?M;O%AgLr??*GmqV3K-HDA^v5ZHjsy`Mt_|tkx23^`FQsV6h!x&5^xI z$Z4wTcaftgd1+5tukf7yXyZTGA;d5`czP>&oz`Ar);ETW?|;7^`F*>aHS=z9IO}%n zdjD$FKek%TTY%6IGjWK&@*XJa{l?_OK@oZwr?G$`H3m@0&z;=rAxfBBX)ubgmA4~G zwF5|hje6MvQPQSCW1KDXov4Hi9C@)8qk4LsU}cZjltU_$4haYO*R=5;JyYlZ3EY$* zK`3A3fOQ*n7*Toy|C6;vNPz|VooT;fSsLk~fh`#rn2HncQoSR3P)QW^Xbl-sTn3f% zoNdg4?9yChEQYuz$z}8Z`cWG1^Tl#OaWkO$uh$`eCYgeq*!RW7fV(#3@NE1tyabK!uD!!Ul6ac(=uoia<=c4!XdTwJeqb>VF3u`~Oc+!9)B%q2h`X z0{b6J>07R4)gAuE!3aM;G6RDIi3CyP)|s~7f9THwkF)lcKN`0dp>D%SmTE*fo{5cg zOwRza&d-vi?QBG}OmY&9lz)@@KoVdGY3zlRYQ?wQgcv1+nysNK{fd_j6-jA00A(zHXA6h54 z)gq@FDipzIW|%jetQhlAszg5%+}sLRZ8Z@bTHXI$wNuy=?^e-pQj1iOb{1S}J`kVk zPst8CyLH=Hb-Qqz*7=?4hMcN>7nGOoh_NECXJ)|8)a9j0ezl6sknw-8_nuKrc3sw zDtcqNW#@j&exLn);~8U*{cHdDekUU%V_oxFYtHkW^H?-S9Ng*3-F-sE1Nz4o$}_z< zdfm-pf6U*0BBZJjo(Kp`a2t9cc+104z;CAr}`)Wa}67T;&=RL>QzPM474RGZY^k8bqLtcmT+8 z7z()Q%MEU&HMU3a1ZhgSTpnmTPKomQ8frFlsPedfRNd2})X--B{c=X^Ir;Ecj5;+a zU4J$}mU?#%djCvo@BC9w$!k?}WT+S5>bd$iLBDnjgg?Uj- z81bmYCaxxS%$t1=74yd>Tm>4@MSb9boT1fQ4d2*yxMc(JwuW=Uo!`5PP1mU@<8j}T zNBXBtpmrno2Oc&r1)V$bOZ-`X(Eig><*tk{8?}qohO+Fru@3f8wHOol#p_K})yT)} zvG&3!lKy!6zAc|beXfN@WHdizG6^`&X}eP8ZS_-fOWh1@8|%Ev%! z0vYc3xsfphhgsC+drnyi&P89beFCa5fMs!XoT~w<3W>i5IP%u#D)kj4UHBncNRjC~ z!y@_T(Z)tbhGd5knsSs2GBLbb3pz7f7iyfQT6yQ#dF6WNl1I8>o>Ng}n+!u_D(q-s zj74j6v1?Ictx_aIslaSQJh%OlX4vkI?l+>y3ohld{0B*)0U?9(mR4OzqG-_b?$edY zkjZXYTv@eCrcrBS6mR6F5#e(0T^QtlDmE1Ge^iJ6h$y}gbB%4S)y#|YX3I5|v`Q!W zz6^w()Ap9oD(!q&w17w-oM#tlx@46FG$fKrjI4_TR(T2c;vT*tteSS47RYHw06xzs z*9CDkWmbV1GZl$tI|I8z8B2H1t~WgXYTS#BF4fH$zta?t4^%TPiGN*riuAB^rzh*t zX*qVZik07Qud4?u{qxPkqRaq525je#ENdD8$S5{U-PN{Xf@}cOFb}%!>{G1Odtmj| z0l(1>brltR^|0pOSD{&(%x?d;nho> z2Dy)7-#`(e2i7Eqo*)1C+HMfF)_R~O=7j3f%LB&J^>Lxmk2t3`2}3HQ4@n&ZW|%=u zi~5Y8fQPk2lS)Eu$b&QLb@ZS22n8NvMC?vE>(cZ3c~*a4VsKQCbWb`(SrO zKSDeIvPV|#M%KxJC|Jzhb>wk?piX6DQ z@xQe$PT<)@$xBZr4sH;E>slDf9W^oT8!$-llbJ)uw~MJW!zJn=nzM+K*Q0Fxxc@Q$ z%v_$fj}weoT5HEGUTf@6y;HYtpHXaE&)e{NOv9$8cgjh_oUMkMz7yZhN47ilR(z}Mbdrh{qdYYr!O-%o!w4vT7J~=JgFkYUaiB$>HSQPUg@8^-}cX4YdajCaqev0 zouR?gU#x9HjpAp@e4kYW|8;1~;`j-hEr{>mR(k7v?L!LhXihuq8ZEBdTC2O^=dNlz zv3NVFSl{=ruZyE6Zk1M}tfTfvL$UveF;D|8osO`h$hZwrMtsWk4$2%#F~-PS&UP3- z#Lf!j|b2vW8t) zY+RbQ)l4@6&?IU=>{n+vChEGp%4j3sB>d4wf=C~C&Eg8QSR z1aG1*Bs6doXH2(8tL~_rQ!u5Dfg)b#J*qm=6?;j+2>Tl!aV*3nNfKvhl*uuO7XpUL z{bay2Z)eZ}nJ`Brc!h6lTU9LhYVM*^kyRgE8NT*BI=KQp-ouC^eKU`!_IelC815ZM zhOhs}9d0}ol-AlfM36k)T?qOoyO4Qv`t_x*Z7oeOFK<-A!FR1d98nkhzP;OoMr!YF ze$p1mf+Z<#5ypQziMB-dzYY6W@y6oD6+5NWJk}&{S&{mAUG5WQyF{ZEO^0QnigVMAS>&Zg*-I>nM9t6wYiOnEhT0mSi_!y+T+>)T;N^6FtB*K>}j z!~pJ?&64-HHNhh_T6!q*1ojaVeaaRabQSmstOd3n=katNxQ@~ z{iCf6LPy>UT--*4`hsc_&EgS8sWi%MgX1m4m{Z{VGc9CenL`M|6-t3nSOiTkao_jh zxn|Pg@}ui0s-O`@r`Ocu2a!ihRN4i;a}M`x9}tfg z_B`-Ade=eg>G(3)SW4kG$gJUyeZ^Y_!PNFWS}HAAiVy(%aQTi6thV#r)_zh3s%)p- zZ$t0)-?uflL>>QEwJtywe*arbjji~9T57hOm$lSb!whBv1cM!1tanh^8_s}lp|*RTVa3O^y{vU*jwxj+sn%{#V&`s(dO1zRv~CN`UX`9V5{PA zM1(%*w!)=AV@A%8irwS^V`Acba`2FB54$|06b}C4f1~vIAJ)&!umbhAd7byr$=X{- zzV_q+A0!%wH{a=rQA7CnA;pWGy}_?Xmv-tYE0n9Y_k@~T`wL?|6-6~m`KDcu4(jA5sUrJ&9u@&TRx^-jv z$<8(O*U22gjZ1eqmMrIb*1JeQ3xzT&`leT(C4#*nCuPZ~bC2z~?chdg0HLAeRQN%8tXU5?rJAS3h zp=KsbeLj(1cSN98k=a%^qM7!>+iABriuSz$-TK%;q3DCKUs3?_Pv4pCrd8cOvaKk z4{!X3B^UFcHS&DKB^gWZfaKA|&DUfsxe8P9C94S;OYX5z%!LdYOHS^y^_KqZuWvS# z41Nr|K?7e5nR>D}W`L`l5<(vogpKeF)nli`f>(DcGisdYR;h0$`5|8pXvr;2KA4DtPrnEs3+HmeAjzl5 zVd6zTcA#>xhGo((IvsUfBMF-Cmyaze@_3t&XByPjN<93f?@h(ow4W(W>1+#&lUc{B z8e2>1qu&;sEKL|stIxdYy0P`rgEY&Et~Wuu&*SsWFI>#gOnZNFNNKle!wIjv*6w3r zuJ5W7ytXZOu0!qqaPHyl)r96}{n3_{ckt0EeM$ALAN!xy?@q>8PUB@Pxrwvh7`y8C zosHukw26OY>ko0PVu(3r z)Oiv|O)ma!fWTn1SkI9SaVgCm<(azdi8y1o5Omr)w!*>1zS;Mza;DdGU{~{Gsk;U& z)_G-qvc%WXWV;LmIoR~C`RBj=C;$Ka;GgxO!v{hC(E|LxZf;;xpi+H3bol=ZDAUXj zA#Xy#eFo=F{X0(Q9 zZXJ|~l}HdX9Pu`2PgkELvA=vnQ1bRL>KjH4eCJ&riMb17SHfG>)Bg-HQI8cuBISqVq*QEN6Fmk&Ly9RncZPo7`|}}S^g~L`hPxH7vrlEl!d`m0tBipI?~}@3ZY|b- z{L)MA$Rm7Wcr5$HzSF*|qU5*t-e`Dr6m5CBYu0x7DM#nBPc0iab?|8hJl0I5V69z! zdp>$5Rd4g%I%)nm988 z1gGZ%e9|ubNPUb-wV7x}ovb?Z{H#XRF8$6?jHmxk|1;+d6(*ml5K8ctdAlZ?7JlfwRM0R(ERz?d;jk?+kEBWU#miU2lIn31`1 z5MOJY;02|ekVYU?aXcZcx4-$%pnOo4n06N^^%}|&&GwY=KSlnUZ=wGPCZ&=A_*DcHqF3SxW^;)PfDq~ zy_$~^NsD!0_>VV+r=>nxM|()#V>h4jhICo1x%RuJ=~6n(yBvRQ_QE-Vx7yL=&%=E( z6w@He&y2+V_Vk7Bso4609rWjj5|bl~D(x0Lm(2lUHjaTYGOCypS&8{cvlKKNSm ziMCbs-G@1JEt8Byq z17(0NH;?5)67;N2LaT^iG^EK-xvOWULU2|J~oz&74j<5z0 zH>PNcsWe0g%Zpz}glMCkbgy8M4xjfYw5;}asF1@pEpMMEE$rtVy7>vR59{liN@tmf zb2*4EImK>lVR}@(f`%5?KU~Tp;N#^5ajl-=PakCWpK67CzPBA)$FUMSI3{OJsXXP$ zr{0ary}YX}ELStEm{i`bXB^-@cLp>~jZ=6Va9iUtpn5}bWQVC&+^a;{G(WjsQ61xJ zHk*jO7D1O&!?c_95umt|WVsYU3sG^3bK(`AiLedPuqi2`5S&`mGd3r&W2PGzTh`mC zT6(#a0#Rfyb&AmduZfP)uqo)3}x@bs~QL%rHt(eNkNBU`R_ zK05wc<;dViW=90Gs zl3{1wG2}v=AMH~%z&%V?)tnJ|YrOmUqN{sFXp%9om+3b9tbgl`%ioF=zw4pQurNXAYYW`?qm*yu?B4Yjkf4$4|7@jGW@wH(Fz$qZlIE&_lpcOeVK$s8O5pn;c*Nl z8yA%uobJ!YC+UtBss|aq$^-Km_TQ&YZl}e8S@*}n@6|V))^+&*19WH?GBA+?z#Y1|z_l zMf{hP9ZQ`35r$~!u{%ND#^B(nc$H2*$6NmhZ`T#N+BnwVbyiFM%m^6#2(93%!f^(NvkQ;g-+KA=Jj0`-QCh|3uT-lqf?jEou`Eo=# z6&c$@N0_b&-yQz@87$q%TiCoSZXoad=aQ@IZ`?~hc*0%?B_%Fsq)0%>#@##MN7*;v ziuaXKbp>hMg}0N=z;bAq{qIOatrazYN3#G|I?qqxw9wD>O^00YtnwweEk@l2Sd_9c z4#h9}u4`GtDELKMc&KT9-}8kux6(vq20P-Hfgh~Ws(E?ex<4gAx-A{C_079S0H~%S zIyDt^m-g)F{c}1umL6>X#4H&wj*hAHpP>Rs6DM}@|44bV=~ki(f5KAl~R+;xA4 zrSL53R&NRux0!bB)c0%t6Ok+$aUf)1O zjnMqp3~2ayJ?qlxqsQNEmpo*^X7S3q%HVh&!eX)U^-_vQ3#kS%5-%~-j*>t+znDzI zEy_bpN=sZ0oQ9MNk<~Q6UxLJKWN_VMoE=f4RDilALTw9ASu-($bCV45Kp7VCvrxVm z4}vSFHGp(VNz{-PhB-kWiU{210|FCZAE@$U5{Mx$i2Z=kV7$lswRXQEOMNN8tCF%I zp8oC;YfXX!Df%40y^C=$AUBtJ2%zwlCzqHQ6p*bCi)49ut&3}61x7J{s^{(+W9?qT z?V18W`MXvH3N>sOT;>U0vY8srpn1?5_yF`SA`mNu-N!0?q6S~sB7YGE!K_JuXQaOQ zOA6do`5*jLe~Q_!&$y}pbN29v;MWwL3+V^{dLx4;7PLFicpS30cR~Z9^uPZkU0LHExA}HD)>4Wpv8KkakKF;KIo#n>C zvZ#ZwCTg+RU*QE2+;S!SF-1XyMR%T;8z&>S^L0!mMXqPiJrY!}ME;!=LB*;YBw~d? zc-&v;jRdHgMuc^0!Sf`Y$t%Fo*Ye$D;N`CxmM#U*z%5~Cc&Voik7~ds3Gye&(3LN` zH8Z7lfrYCG>y23_J;p5@$4d`37m&_Cd8Sn_Gq;QR+kY8oQVwhWe(2-BtAH~THbT;Y zw-&`8KI@&LsUh^aIt5x~p2ln`KVN6K{w;KcFQ2hSgP=K;&ja=Do{CI7T(e}L>1SSW z_`Kq|Graz;8kG4NbzAjk@sJ%<#n*M+6_XtC9-^J4!=Jsq#}qxGFaIw?1=Y zBZo1dR~rgi4+d%xo!0O3(37aR;5pV6jyYt-#8ZIv_8>0<7gcPdmH>zrHfm9mE+qm_ zP~~NuMSotN5l_un>KO797&-w6NT3hex{zXk-mVd8^8hU>;j?bCaGzQD>mg_^B+iCi)*K$ z)atTk`%dM~TzzojzV=0?!D)+&RTJz46cC5+h#+ECMZ0RhV2Mq z1bK~s+=GQ`tnnb#MEP&nf9RIzU~Ib>^zoA7kuG5KoXhJ3orC&r;jT?9_WRRRUGIDa z)-AZKf!8_OyZN2%J#SYS^Q)mN8+6zf-a{zz!ydJF295U>DpSEpjZW_$_GqV=%*R7A z_`l{;UpUVZKD1^4>8)Hhyp{~KB|Bb0L>LSBCbZoQxw9t75+K>|cpPgQ#( zG>hKh<&fAbQ$Mc8X!R$A_4vQC15k@DO4o;0&-GVK_Zy=N#NfJ@(n~Jl>k?L1XDEv-?W9QxXXJ+!noMe zy)=ZeC@~;KGd~YANrXgFZq?ggwI*MkEWOHzITR68x`3Ah2|Nx538mZIt~w9vQBGZS zj{7J@@8jqE9VO&%(}T@i?>!XY`VobDL_*?=sEW6lEM#KSZAYW<%I zQm}C4R9v+2mFVprO+D3nSl6R1T}3mo(ruupV~&p6u5s>ARtomW=bmrxtM07z14$y; z?6~|9Eab_r2CmEKrUK0{tB9!O+un;c(HE|_43s72+?*Y-9yp8#+*o3wVAbaD$xAKWF8IX#Rr44)U>6b zLaMyt5@M4m5oQbCi$&zq9_HZ>K;nQV_)R<>Vjb@Ro%hfa0Ev1Gu;)KuQ{_JM6FUTx zl|r}|021*RP_aWq<0EotuvZ+l-=7o4IEY`5B0_^cAjo)aHQ7JD2aoJ{@MZ<P0@q`t7iHKEq@CGS}z*&@MQ5Z;;HQ4>sqy+{M1UOD(qtgLtGWxBG z6jq2q+lW-mgpY#GJ@jk=%r_#6*JSDR)J*+31d2bo^}{6h8tA+={15<{gM~T>A6a0K z`|)4`H9=hpxV=G~N514L09@~xz)CPc*br4xXaH0f#Ae(b|@OF28cr^#GMQrB!RSf zAjeKfs0f@Okl+3k?M!=I-=$_m1sKqPYlXLxB_L%o@crHR&qR414Qwt{+c#h@gV-7f zO?A2)_DK;80GxF;svwfIMuCLW5Jj{%WligH_Jg+b;U@|36kSvm5xMt#j}ZY{k`!7c zf^(&aA`xV8Ek#}V^&3X-B30n^&=#62k$=pGx3vOc_NW;Oriu*Iz^ZSj!pdlGstE8T z>~MMx$b<@&h#?nWX&u8>zQDpFrNH_a5D6gK%h2RCA@fvs+Cz-v`^iNvc^qaz6?*wRO**4_P%?8ssH)NBI>Yx@gbRb2;t7hlrD+r6StS`e2Zc zY_(J$Esb>+-TDHtI=R@;xtRU&p6866!{&F4ZQ#B2PKux2FYc%m6<s{3Rc^qbQw%h_+(<7=0pY#gzdyGPX{+4MKnw|7VJO- z8I$cyD;fZzVODmhLEPeC#O(t9^k#@7u0R`dN< zCJIlp;%QK$Hh6yHiXc#9O@Zz55z3pO+E6N1^mEU#Xv)$)5xjG4X}T){5SIY2_p9>S zRlh%34vAU&GtRSZ3Ta_hK?Ypr$PGg-CvB7(1CUelT6TZx#`rSi#EzAv@p@d_RJD%V zpQbTh-9#BfMN#QYslmc6Wz9a;;prB1bxj?1s)xjYC>nCnTdJA1BYvH+j;NxzgiV`6 zswC;=PkS5qO^J?~XFyXIw${1Tw6}}LxFssv@-!cP4N%a&ko0oT6rm@z+=}fO-NDY- zq=CuXyv(0EU$QyqRPJ}jdY|UOYU`l==`6D@?>rCd`(0h}3Hc8hYq|qd+F6YuMMfUN zsRV4@8-ItQYUu_2q3YoI%8)sO10VNynvu0vFWFS$2uvLb} zzjtJdm}owc_KGsqHTdZkEaKgdujfyDHs_7%Wf$5mz%{Z``GC#BxBj|B6M^L9Za~@j zQoZ;VeTI?URZ%U~83-ljs3_Lu{{5#_9|nD#y?8F7I91U=d1JuP=|k^YQ_lGI0STJ6 zPD>XU>gdl&I)J&7H>b>S!~uP-M>buN`kgeYXc8awxo-XM9}2=FPv`X6MON8F{}WGt zEL4F0iuNnkOXt?n+{S=}8W}dybmNJMt6m(nKR@tHhb>o|*MyD@p*~z(JZ%glXB65~ z8knEA=$WlF9tT(P;29|IQPBz44Dge5T)?!s`|ED>q19c4jR6F;JGc>)iZyB75JbbO zZ$S1`et2&^@ts8V*3cA4)CjLXgBjr4LVKb1akDu+`QnIu;~DWk^x*+Xcsj`1C$elj zNRSFN&~OIKos9pp4PHjfpGnc9h{Y1OBK#2|a`XMT(GqN$pp)(fm^D?01xbbK=o!MC zp4<*TjCk;)*=?VM>#K3Os+y@19AQRwFVb?^%K35~3ib?B7nV39%m|yA3*|N%3@K-+ zWTa^L3RdxOt)0%YdDO>qM%XmzE?gm|zOi`C@?rAWtCSNWV6L+A`Z_$cL{9`#Nkg^6 zb+)aFDJ@0L0rkbM%M1FPqC^@6lk#0L3kb%yP?$=Iw1_q(C!GFgMIzT{^VS0ZFJDgk z9pWBheanCmCx%=C!fnF-@B?%D}iAXnd56s5MJ;IXL~bl;ofOFb6&-n7DBCwpK1Sm3L#fdf;%c$cJ$AG$s}i zkIK_0!65qRRQJKu+8+S@>=vXh4}Wy#8C?l7#U{AdLG~1!+ZrGQleqQS^P*hiEFP1D zOhV-%V86Kj1^!aJQ@#sHzLSujSdG={&t?&`?BIW<7)lR<{heyM;KRhwgQi>()J7jY zpJb?&%fCwwlhUmqgF5rsjlsilW9i#L$XXX5DqD((#bI-(Jz86XD0xrs4Jh?JjCGVr zz)EEl)PQosXI=_(`4|B5`&Uiy^yjg3;*hEX!7Dyp$fRJiN<|27;++|Cxs3m(W39Ok;0jm&!ZjMBHD5XKO4gtd0@PR&}L7lr}AjJxek%_Xp zqm$e@G;_+Wb=6OySI+kg?-T=rs8^Z6jd(iopuX-8bl&ldjIHy=Po#$(89usTxJOv7 zA{8o~bC0v*)XNhFAo_q%%&TtLw0* zRN)TUnYrdU!gVulL-^f5PH@lXl3o!QlZ7u6C#^#qmCPA#pS$rq7F3V98i+bbh2DF2 z|5!>k;9wG&VO192(|C?~yx(i$!NK(!4Py+9wwJMn(&o|;Wwvo*a9MRC9Xmj~ZFq`Q z-~{ot^)qJ?(&B;^@*C8OmQ>;=4-=O%MV;$4s+GjqUI(_k=~+t!9u3JGef}X1#nU`b zPL)8F?~~QXuOVGF^PqFz_aDK0i1jHb&GjOyYjq-gwZ4&I>QN^Abax6UZ>>8(B6}b# zvDc;`5#uwdLGccxBNc-za#<~DTYdyCeOQ9tI(*3Rat`F9$r;}m#KP%I2e?@icrLp} z-}O(wz|Z3wAo4m`HC=Yknl$H>qV_J$_?X+Ku8#|#V-!o{KAIX9%I_EfVN}HmpnPKS zzPsLK`YHJ0e7uN*8+x%4iGyu_VZ~-0{~+qjp^?W61m6IYt_g_L50qv z9)oiTQ!zi-E*tFpxT_fVmZ{^;yXU!u_6{^#|8ObQzti`_$+c7w2}&>%;&MVhZMX;4 zm9`vos0XmLq5)4w+x!c&&YcV)0ujeTX;68fyoYsyUVPiA2mUk5JUhVuM-1F0>Tv-9 zk>>kY1EAse2u&yyLaMz1sxLC-kG+bAm`aJYi~0(#uL=`KR}Z-zzYV$ajXi6U_+&-ftTAz%{v2rdBKk37IdseLzRfOq&!29xHAc z+K34oek=phIjFUCi zGqD78{plgJ0gk5WSAKFU|2ZUWl2ti-vpAHq#>8}Y9Mzex#n?;zY=Gi% zy}!qDr&~;}src~WXU0_e{vIguxEcgC>mxS0egCjMAy2^{Fz1~JSe^e1oMa(h^8R9C zwX1T}Bi?xsv4x_;r55i~;{x=A>Nz}^Ss$IOq#?KJzV`y$UjTY5LA}i4YMIl#vz_BC zuOJ=hKxYWx2h1so?|!yO31N3Y0zLZx8UqjnOF$2)`f(y?D36q_#0jkgzYde%AT{5c z%}(SEWKubad{&h+9bL(=%4Tn_hgu$i9l*hJTMBOo@TmxxM!J0_p6$Yw#~>JlY<4;# z*Q2G-rX6-bz_K$#X^jE(+j7@%Wu)0IHi2K5vyZEl3O?=3?4Qp+V*oqQ0t;%PX*<_{ zRm@*L1KQBS#!o}Hwm|XwWxs-aT?sDHv6V|Kb#t`_=BqN2Xz>t8!^-8(M zELhAKL#L%MP`j1V=MySrKd)nHOHHqp(iKygUbx)1S@7T`uwoX%rvQU~j7?fxAhsBQ$VKLwW`#lOJvs`0q$nAC}N$^sL`10b@r(9?rsK{F;K}DHXd;9 z1p&C156?=61ewYCh)2l%GMEAEP|L)*RFDC|;*gY0SZc_$XbYx#1rPgxOLM=p7Fr7o zlF7k$1I$BO02qMofkgiU)X_tQ{;znzu2lKLBi`v_qaFf5{qMFIDpUjA;6z}oDO@A0 z@}ReUSOSVo(U`6e6?!OktReAq`TQCOz!T%5gcRkm^FZ zVx`X^97iK!fPw`%|KjKbj0WRj(!7qotd&zKdX~%@~uu;0VM!I1m3Ung> zb}(<_4uWp1D3{Wb>)(?1syWJg%dIVA!DbMsk`Kn&D}IcfD9b+k&G{644EOGd z2##hE`LDMscM*2Akf6WvLgYF$>&9d_r)iZ9rRIpZr$dx@_8jB2guXFIH zp(Ys=ycDWr46D#;8>Yw~m5}sQa?=Ex+pr>2YN&OR*8wuzx*e^U^gu(qCI#1R&_mb4 zK~tr$>Uz347UE|NF%tW01cdw?_M3ADDs6-v;D>7U!h>n~%QGM^fL9}Hlc@@P2Le+t z@SFfB$@Yo`oo6+}n0%XWEQLe~pgS+Em+chC49`U4uO6e6#^E_0g=Zt+yLjvj8mD|W z1B|=6PsmAHVg&+nlZf!JF^~zKe)buyw*a0+fEumRYOm4xTK)CmKqVd^a>=2&fu6LB zmhZdu0QBicEy#&S{q(N&0xg;?R_&4-qsI^&cZRcfj@9@amO%vL@eHlEz@0d8QdI6X zN=yqKV#bwS_C}BAmaILDWmBU(hP>UA!`wD=;roSH5 z)t%`u9!+#%Hpv_6qXZsKqp1++;tvj+ z!7tOE!4G1YE2rqH0QanH_(gA~V&B;xZrgUrX$DB>iW1MFFP?H_nj5w^Cm>qo;rfEB zKqQ}id8rcYd3U=(mL3GT3ZF%m(JH2}V%#m}x$7QG$3M{0O=|NWiN|8xJKN=M<&5O#7S z#F5SP$43N97z)G?LrHErANoi#h*o{bvdwT z8qP zaF>8iar{`eOfSQ?fSmb|OdLmFIWVujC5^^jSF_}n#YqWhuIF)cb>Z>O1s>9=OffTf zV!Z7teFGM5-^4m%1AgPfva2gP+7{^3vgjg!9YV1E%;?(Gprd?F`i^|}?@jozF^6ut z1%lxrf@DfzZkG9i>J}&GSLs_`g>um(@gVoIStDw(DI0<+zi5+JPkIHq5dm~vk=Mm> zgd5vFwL)J_wVXhBCJQ)0_dz5v*rg|VFBWq1?{|?-DA)nc+S&euAPVd(imCO0W{rhl z9)WGJ`qy~6J63Da+$Cz~(rF?{#t=1GDkxn|jjmj>s070?>{4BnO-nA>y&%tz6}n_P z*K+|4ppP`>4y`<>AB#xG!#3YsklEC3%KG^X+3{I>ev?=0M<1o^_T3Hx?JwSSn&f|N zJeSGKb-4ejg|YcAV5$D`@YuN`1^&6?ADK-8)`R4Ag#SwnhoC_~B>Wd1c{koDyCn%an+CK*AsnI^O(n-Hk$_ zAINCU+-B**i71iXF<4OF0y#S{CVS)SY-4E&bn}a(^i_)u#KPXYjC~KFA>;+SRF=_o zh;w#?W@W;<;|xU+GfX;9J$P0J0ir#IJZogFoU-j^O^~y9@8)x2WcTF?b|1Can@ru^ zEM@yYh}=pImV_%7@)tqUEJmLCC00IF?iKj>cmSWSNaF%4 z>5*J`4v!Nhqyu>@B+M!9{WeYuU6TwzQk4%2nATYcfHreCt?HsOz`P}@xQGTHyPi|R z36a4wMOwP%92wo?mh+YUmX*YXbQA#qB+&A2%;anX!ma{GM>xj?P)jpf0Dt{4LarW- zo<#=$aR5I=Z_7>^k_teK(c8hZh*k&)0RYl29~N?wML;fo8)t;WDF^Ge&@3wt@kl(VA|Nooxe~B9zx*{?b(w( z%58i1^rpsl}Cqt^>Jf8OOqz2|syKS?TPJgBfJW zrm4+dw8qLJkT28o>kG#r*RxJpugrs348O^373RiUhH<2!+qcx#TR`-~nkFhN%D8z8 zs*QPUg?&C(zc!!GhoSau&r7(?x|1u%WwaWy6N6xi!hx60Dd}|s&~4l2iye;%KgVWY zZy72yQB4(jK`V#}A!gX^1YiB{QKz67)AYx(dU_*pPHo#*{U*Y(G3u=6`W}+PhG+-U zGblbPLBX0^$n%y7|9qsAc&r<&=+`+a(U2w)Mi~o;u-h=rh$*(~f;)%q$Bg9GjIWWgoO`BpVEU zo~y2FJXxtREPrH6C}P7qME3~XvRbNuaVW%lSAM-3e(z{>MVG{0vWs9*JHCquQrrwl zFsVGcr+g5l7s2jAOs_IvH_DpF1FC0m!|!P)v93l|qWbMO4a6Bt z`8j^9)=0)?xG!wtsa9isa23TMPD}3t6DE4!bp6uRhv#Hhx39USL)F%S!^6O6(+E)j z;iL2cOY!p@I!RT-U24Jn^!AJl0|>Z2D%>Z$8VS=74%9eO-J^UpA_)ufwq>k9mf~ch zp`0;JEd7Ky|HnA1!>Cq&Vjrnp^a#36GKMbf=ML7oHLQes%WwE&7NmEt$$O*5Nh>Qv zPEYrS_ZQx^d`&`XQVWY*D^?WW$oIdMxzwOcYdOR1snARxqR82A7;zw#Ba9 zLfc)cj~;k$#5P=}aS1D93?Hms8Ep%4_oa}twOVGM7mQ(Ue@@nf-|Z~6q!wbWQ07ks z-qT6k`r`E|xb(wX3zb)|!hDF!#g<%(AanH4VCYrMnoD76kz`NIeYsk(Bx1Xe}H8#jjwRUFPA z^x>0G7TEm6R36O6`zbt?=W(P5h}5oB?fBA=mssenrvH1B#v7SEo%0qP=StE*%@rfR z*FmJEr!kuZjP2#-DqKQj<%2iE*FW-LmzcHR|CE7u5EHbkD)qL;5K!svi%1_c5<1AS z@%7=R^+C)b<9A;nHbS{LQ~ra&6^dXDb3I6V(hRJQg>Ygvruu61(N>L~5Uk%$X>rXW z`n^au$rQ;Jb3R?E28h`~Hb^Gb1CXdFMurKM?qFtoW&dp>Oa!GUc6I=&D=f$~S}64+ zl)`5Y)NJ`Pv{_FAe36=Y>ure=q19Yy)LD0u6d`n2iyA;}lpQBN^}2Hsu>2k=Ku(&d zb5#gLZ6wo-X+!nSVxpXx5Exm_)S=J@Jjpbg0U4sV%=HSAg-Y?*5So-K#Mn(K9p1lR zZ%GJ||Dw)RMbl6tOM&Z$`ApDV3eLC$ZbYRpX7>95BlrRK`vG8szlT6jF2q^fjWqQk z0ywg&>H8Gg$!ARhC~EcJKm)Q->3kr@y1*PlID6D?UfbgUL^+<=a5`xp^yU)6Et|}| z*N)d$0{VMO2jE636wK@r(uNHHtMK@)N@K$b6LVbbZ(5=wcL0z>2+zs!L5E2hYRQT- z8Bz2^6hAfmdtH&CjPzhEmf7SKrj`ov{30Pw{@G5x#`Na!+SQK{wLloNLpUFEA>HsJ3qi(AP5M1>WW$tSx0!Dz1%Jeg{&?Q_; z*U1K1r+278146h2mdmC!uBO8EL=vdE5nc7G6scuJ1#IRY(BnCS;2?aSyde{_rc#L+ zcLp#5s=;mg)M&ZmOxn8XhLJuRF)BjwBtt-lA^$Iu&c&bU{{R1b?|e24!!YML&zV9S zGv|yX<#5d*Bx)h4sBKOo=Y%B9AyINkDwS$O4kb-V>QdJnDwX=IQkTnB`R#lA{R!{) zZhO9-@5k%@yg#czUUEL(5)=z65(zzMU-GmRN8r_EU)PDszn!CIj5cz`+TF3lc%lnh z%a^`?Z%-b8Y}23T=H;KKz+T)UqGPth5{y6QW03Ru{S^D-_et|yvHzM-j4DPwfT1F8dbl`F~jli9S{?ix<(U15>!GDQ$L^}$(L1g3JX zpe$-Qv%k9DA)0)ZV#1nHWe+xh{+llqcOv@OBQ7^|9T=sV^1+ksUQnw!33lfm5Wcp@ zSfgD85RBM9yMrst&i`#IB`$q|Sn_ zl)m9%CQ^19_b{|Keykn5@{zC7#}517^=FL=RNi9V9Q7oJnX6bmiil(=;-=QVW)*)foQm z{}Hd?yHNb!Wtj{O-_1vQJk+$k2ohn#7)mGhM(uBDKPu6-gs{(q+QAEu1@?`k4=!=_ zvpnS$LIFX7VAJ8r7_6EuXO=g2|Ir*5_UF8CQ-qhHm_eS$IXDdNL6y7r50Zzs$(0qv zzTaYHXgw1@wCb-)k=S=AILBZ-6fm~Udmcq6w5hyu4??@W{y@S&6X-vzMseAE_tK%a z1<~(}Hy*Sk2cRbyH{@UqHwh5_7dS_ zWsEoxJy;xt4ENGz(BFLGDQB}CjiMc8aZU&B_qNfULp)oPx2erXJx%~k)}xd~PhqJz zD>nEws>~#!#Tp%QLEhZl((G$#Bn4TCF#sdSnL6{SAz{A&yz_@|cw<&yJ|L3|+ju zedpO{9HL5=0Gzj8S?;k>DM@nPxU!>e!1Dt>qH5k&_Pdf;3;v3cFlDh+6Qr7 zN!}uc=um5H917exeEjT)Hal;d>~wfGEK8!bW97v$on7`c#uHz${+d^02MCePvmrP5 zU8bY!c`)onk1;P||HPk6x(Z349|oq#>CkjSLZXj+avc#6h@`=fZuYy8Ks-)YC~0#)*pHTtFWgqsD2Ss0^$JrB-wKlE8!; zQZGC1)KI#zO{lmlNBq~yRsvL_^Z*Q*{o8DiPoY5uM)o>MKPuk`J$Qw5Z{#cY%{`nN zB(H#Wd=Y}>gP{h3*Z;EXa^f!b3!don@4bC&U+RS|^qY1AYkY6PEhSK))t?S{AC%Gw zQHY!S3d&|7?i{aS&#o;;yzoE0(Oik9+|!W`8Go|(6G?)fKpQN3979e1~bzoPgz0WgAbNGEwzii>?oe~KWmN2jgDgi69=#Xf$UyoG43XE9t+wL z$eFRL#E~fm(*k!wp6OxA{IbMY2wtpIe9ygEoc_z0ls0Ay8&y-;?L?KO3lHJoS{=tnJU3X(_DG!6!>5H;B$S? zp}>ky*XRaL?BnJ@`3j(s9Pk6~>S-N!OO96j+hooBUjJw5d$BWE=e%> zvJlNXrfolvwkuOE5uf$mo!cZFq!bmyIY!KVz~U#2)(a4>)bqQ0-mlMkk`ONTJZMQ* z-|@rvAN3QTrM&AuOY~~(o^*Wto${(nRBavvxSwa6zXwb4djF~fD(+aoof}^EEoky} z;D4GEur9<*@BfBgj{jiIL2^OZzlM~*f~y;Z^NBw9#uLnP=^6ENoyl}m-`8pafEeI8 z)Bju@K^O= zRWOOoYyIg33;=%h`3K!if|np+^Ssokc9f;WkqpC=0aQIGXp7jAV6IN%gWJMwOOx!S z3)c(hpcE$A8e(NdG56EWZhJ*`GfcQe=bVfj3eBq{d z1iAu$s?EKhms~Y-u$vBHOCox`6PP0jY`9Lxr!-q{k5z~XU9!U?=$I?+~ISH{Os1lZg0Pl67E*z`Db{R6|F~OA=|+Y^Q=nojGNi;MpBpY9N$+ zaeBCBaf28~r3(c^=^L7xmRZ=bWvpyZ`q1{Ye}-LGA$oISoZD%3MIkI9iSrMH)&o@U zgIzJFCv*>)Fl$h5X51V`@Ys+A9i%uW=<@mrCs5_V{PW{l0TW);2i_lcKOMVNrxo_X z55(UY`eM`E4X^Ek)t7l-OTf_qnmcnnVRgeR;RVpC4oNr#QLjk^*g*QCL%2iA4&*;O z$aLPdx84VMFki7=rFTo27%@S&B@8>$_#L~%zEd?CeW`8fAccSi*&${hF2J&R-TNM+ z$vh>O?OSs4v{%b}Jerh8nD^N!HYLGDNLejMSfeY$MN;C@19tFzN2#a zoX=~tu7z3Ej0B^cz+d>z*D+p2{-oFh>Y{hJVV!emZa;@2A+`zoGHSlUMKmodA5wPT z6J^My+nb&T0w3DxE0;gpTyhxvc}dsd(aP_ zZ{1d>@7!;5r`Jr0BqOT37NWlUH8WTkYe7@2s;PBkZ$O4aWAc}Z_!8BPT@HfqAXS_u z*|ovfv!aP&O?J#lCR#?0>uAPAWH^7`Njv9p?(kJshyO@vhIMg#VM0kE)>PCa7gnci zFE@1vdy#i}qd}LiwM*JlliFwr*D8(bO|lBuR%obI^~RCU990Oe+_d~UhtU`RFWs!g zDwiFHC_hutC>g_7nEFbS?aO28%_4TR$;RekSI#~YeE+%U)9Le85JdVFqt7qYtu>oG zA7u}+Fm11mO7hzGD%F*S^IL0<#8+THX1;zCvl<-oJI+?!m6szYi+)-cKCe2`=6k*&As6>pcP-YA~uFzY1F zK_-N%2#|TkdmZ>Z=+_mnpHVfd!@NKVYBBxO5l{?n z9(UU?;3Hz@reIYnq2kKh7ZW1p1rWOHg+_+?7|(FP(uG$Nw|=-lX!6@tfoEvl%@ylr8uXz!{mtnfISE)pJ`nL?b_Po>TC0>x7o^n8RQ89Z400 n`A$>a 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

q@X6>c&|zQRXte+I7%FR`!rfaLT1^ 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

9^gH@ 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≪Yp8z_dVRu9|y5kh&!d_4&vga^Jq&n6ti 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 z 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

5GUHN=Z;x!c?#^BXVVCWxsK|I(uWi&>eqzJ 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 ZKhgYuC!+sTOZ>07@SiaM-y?5!{2xvUWw8JN literal 181448 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

s5$?X+-|)H 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 Date: Wed, 2 Apr 2025 16:23:16 +0200 Subject: [PATCH 019/152] build(deps): bump github.com/alexkohler/nakedret/v2 from 2.0.5 to 2.0.6 (#5681) Co-authored-by: Fernandez Ludovic --- go.mod | 2 +- go.sum | 4 ++-- pkg/golinters/nakedret/nakedret.go | 8 +++++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 65ad99e18cfa..4ed57dbde0ea 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1 github.com/OpenPeeDeeP/depguard/v2 v2.2.1 github.com/alecthomas/go-check-sumtype v0.3.1 - github.com/alexkohler/nakedret/v2 v2.0.5 + github.com/alexkohler/nakedret/v2 v2.0.6 github.com/alexkohler/prealloc v1.0.0 github.com/alingse/asasalint v0.0.11 github.com/alingse/nilnesserr v0.1.2 diff --git a/go.sum b/go.sum index e06df5d5f89c..89c53f136c30 100644 --- a/go.sum +++ b/go.sum @@ -70,8 +70,8 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy 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.5 h1:fP5qLgtwbx9EJE8dGEERT02YwS8En4r9nnZ71RK+EVU= -github.com/alexkohler/nakedret/v2 v2.0.5/go.mod h1:bF5i0zF2Wo2o4X4USt9ntUWve6JbFv02Ff4vlkmS/VU= +github.com/alexkohler/nakedret/v2 v2.0.6 h1:ME3Qef1/KIKr3kWX3nti3hhgNxw6aqN5pZmQiFSsuzQ= +github.com/alexkohler/nakedret/v2 v2.0.6/go.mod h1:l3RKju/IzOMQHmsEvXwkqMDzHHvurNQfAgE1eVmT40Q= 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= diff --git a/pkg/golinters/nakedret/nakedret.go b/pkg/golinters/nakedret/nakedret.go index 1b278872e612..1b769acd8c8d 100644 --- a/pkg/golinters/nakedret/nakedret.go +++ b/pkg/golinters/nakedret/nakedret.go @@ -9,12 +9,14 @@ import ( ) func New(settings *config.NakedretSettings) *goanalysis.Linter { - var maxLines uint + cfg := &nakedret.NakedReturnRunner{} + if settings != nil { - maxLines = settings.MaxFuncLines + // SkipTestFiles is intentionally ignored => should be managed with `linters.exclusions.rules`. + cfg.MaxLength = settings.MaxFuncLines } - a := nakedret.NakedReturnAnalyzer(maxLines, false) + a := nakedret.NakedReturnAnalyzer(cfg) return goanalysis.NewLinter( a.Name, From be9882baa20f41536aa8a6c59e54b67a3af51348 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Apr 2025 17:16:52 +0200 Subject: [PATCH 020/152] build(deps): bump github.com/shirou/gopsutil/v4 from 4.25.2 to 4.25.3 (#5680) Co-authored-by: Fernandez Ludovic --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4ed57dbde0ea..0371577a30cd 100644 --- a/go.mod +++ b/go.mod @@ -96,7 +96,7 @@ require ( github.com/sashamelentyev/interfacebloat v1.1.0 github.com/sashamelentyev/usestdlibvars v1.28.0 github.com/securego/gosec/v2 v2.22.2 - github.com/shirou/gopsutil/v4 v4.25.2 + github.com/shirou/gopsutil/v4 v4.25.3 github.com/sirupsen/logrus v1.9.3 github.com/sivchari/containedctx v1.0.3 github.com/sonatard/noctx v0.1.0 diff --git a/go.sum b/go.sum index 89c53f136c30..9b31b1685d68 100644 --- a/go.sum +++ b/go.sum @@ -517,8 +517,8 @@ github.com/securego/gosec/v2 v2.22.2 h1:IXbuI7cJninj0nRpZSLCUlotsj8jGusohfONMrHo github.com/securego/gosec/v2 v2.22.2/go.mod h1:UEBGA+dSKb+VqM6TdehR7lnQtIIMorYJ4/9CW1KVQBE= 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/shirou/gopsutil/v4 v4.25.2 h1:NMscG3l2CqtWFS86kj3vP7soOczqrQYIEhO/pMvvQkk= -github.com/shirou/gopsutil/v4 v4.25.2/go.mod h1:34gBYJzyqCDT11b6bMHP0XCvWeU3J61XRT7a2EmCRTA= +github.com/shirou/gopsutil/v4 v4.25.3 h1:SeA68lsu8gLggyMbmCn8cmp97V1TI9ld9sVzAUcKcKE= +github.com/shirou/gopsutil/v4 v4.25.3/go.mod h1:xbuxyoZj+UsgnZrENu3lQivsngRR5BdjbJwf2fv4szA= 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= From a45ddd1fe031c1620fc4bdd3383832ea4ed11d1c Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Wed, 2 Apr 2025 22:48:16 +0200 Subject: [PATCH 021/152] docs: add link to issues related to some integrations (#5682) --- docs/src/docs/welcome/integrations.mdx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/src/docs/welcome/integrations.mdx b/docs/src/docs/welcome/integrations.mdx index ba7c372fb2e9..2da993e0242d 100644 --- a/docs/src/docs/welcome/integrations.mdx +++ b/docs/src/docs/welcome/integrations.mdx @@ -6,10 +6,14 @@ title: Integrations ### GoLand +The integration for golangci-lint v2 is currently in work in progress: [GO-18363](https://youtrack.jetbrains.com/issue/GO-18363/Go-Linter-plugin-fails-with-golangci-lint-v2). + Install [plugin](https://plugins.jetbrains.com/plugin/12496-go-linter). ### Visual Studio Code +The integration for golangci-lint v2 is currently in work in progress: [vscode-go#3732](https://github.com/golang/vscode-go/issues/3732). + Install the [extension](https://marketplace.visualstudio.com/items?itemName=golang.Go).

From d0b46ebbe9d099deb0ff31d51117f2877d1d38ad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Apr 2025 02:21:29 +0200 Subject: [PATCH 022/152] build(deps): bump github.com/Crocmagnon/fatcontext from 0.7.1 to 0.7.2 (#5685) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 0371577a30cd..bf92c5112000 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/Antonboom/nilnil v1.1.0 github.com/Antonboom/testifylint v1.6.1 github.com/BurntSushi/toml v1.5.0 - github.com/Crocmagnon/fatcontext v0.7.1 + github.com/Crocmagnon/fatcontext v0.7.2 github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1 github.com/OpenPeeDeeP/depguard/v2 v2.2.1 diff --git a/go.sum b/go.sum index 9b31b1685d68..58f9e777a774 100644 --- a/go.sum +++ b/go.sum @@ -49,8 +49,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/Crocmagnon/fatcontext v0.7.1 h1:SC/VIbRRZQeQWj/TcQBS6JmrXcfA+BU4OGSVUt54PjM= -github.com/Crocmagnon/fatcontext v0.7.1/go.mod h1:1wMvv3NXEBJucFGfwOJBxSVWcoIO6emV215SMkW9MFU= +github.com/Crocmagnon/fatcontext v0.7.2 h1:BY5/dUhs2kuD3sDn7vZrgOneRib5EHk9GOiyK8Vg+14= +github.com/Crocmagnon/fatcontext v0.7.2/go.mod h1:OAZCUteH59eiddbJZ9/bF4ppC140jYD/hepU2FDkFk4= 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/v3 v3.3.1 h1:Sz1JIXEcSfhz7fUi7xHnhpIE0thVASYjvosApmHuD2k= From e5891399a4c3f831a2f3dae4869227833910991c Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Fri, 4 Apr 2025 02:40:18 +0200 Subject: [PATCH 023/152] feat: add config path placeholder (#5650) --- .golangci.next.reference.yml | 3 + pkg/config/placeholders.go | 18 ++ pkg/golinters/depguard/depguard.go | 5 +- pkg/golinters/gocritic/gocritic.go | 93 +----- pkg/golinters/gocritic/gocritic_settings.go | 175 +++++++++--- ...itic_test.go => gocritic_settings_test.go} | 265 ++++++++++-------- pkg/golinters/gocritic/testdata/gocritic.yml | 2 +- pkg/golinters/goheader/goheader.go | 5 +- pkg/golinters/internal/commons.go | 3 - pkg/lint/lintersdb/builder_linter.go | 8 +- 10 files changed, 319 insertions(+), 258 deletions(-) create mode 100644 pkg/config/placeholders.go rename pkg/golinters/gocritic/{gocritic_test.go => gocritic_settings_test.go} (61%) diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index 2667c443973d..8b02677be8e0 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -335,6 +335,7 @@ linters: # List of file globs that will match this list of settings to compare against. # By default, if a path is relative, it is relative to the directory where the golangci-lint command is executed. # The placeholder '${base-path}' is substituted with a path relative to the mode defined with `run.relative-path-mode`. + # The placeholder '${config-path}' is substituted with a path relative to the configuration file. # Default: $all files: - "!**/*_a _file.go" @@ -1161,6 +1162,7 @@ linters: # Comma-separated list of file paths containing ruleguard rules. # By default, if a path is relative, it is relative to the directory where the golangci-lint command is executed. # The placeholder '${base-path}' is substituted with a path relative to the mode defined with `run.relative-path-mode`. + # The placeholder '${config-path}' is substituted with a path relative to the configuration file. # Glob patterns such as 'rules-*.go' may be specified. # Default: "" rules: '${base-path}/ruleguard/rules-*.go,${base-path}/myrule1.go' @@ -1256,6 +1258,7 @@ linters: # Useful if you need to load the template from a specific file. # By default, if a path is relative, it is relative to the directory where the golangci-lint command is executed. # The placeholder '${base-path}' is substituted with a path relative to the mode defined with `run.relative-path-mode`. + # The placeholder '${config-path}' is substituted with a path relative to the configuration file. # Default: "" template-path: /path/to/my/template.tmpl diff --git a/pkg/config/placeholders.go b/pkg/config/placeholders.go new file mode 100644 index 000000000000..b3f35f7b3ac4 --- /dev/null +++ b/pkg/config/placeholders.go @@ -0,0 +1,18 @@ +package config + +import "strings" + +const ( + // placeholderBasePath used inside linters to evaluate relative paths. + placeholderBasePath = "${base-path}" + + // placeholderConfigPath used inside linters to paths relative to configuration. + placeholderConfigPath = "${config-path}" +) + +func NewPlaceholderReplacer(cfg *Config) *strings.Replacer { + return strings.NewReplacer( + placeholderBasePath, cfg.GetBasePath(), + placeholderConfigPath, cfg.GetConfigDir(), + ) +} diff --git a/pkg/golinters/depguard/depguard.go b/pkg/golinters/depguard/depguard.go index ab0863d6a064..c1f66b0c81cc 100644 --- a/pkg/golinters/depguard/depguard.go +++ b/pkg/golinters/depguard/depguard.go @@ -8,18 +8,17 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" - "github.com/golangci/golangci-lint/v2/pkg/golinters/internal" "github.com/golangci/golangci-lint/v2/pkg/lint/linter" ) -func New(settings *config.DepGuardSettings, basePath string) *goanalysis.Linter { +func New(settings *config.DepGuardSettings, replacer *strings.Replacer) *goanalysis.Linter { conf := depguard.LinterSettings{} if settings != nil { for s, rule := range settings.Rules { var extendedPatterns []string for _, file := range rule.Files { - extendedPatterns = append(extendedPatterns, strings.ReplaceAll(file, internal.PlaceholderBasePath, basePath)) + extendedPatterns = append(extendedPatterns, replacer.Replace(file)) } list := &depguard.List{ diff --git a/pkg/golinters/gocritic/gocritic.go b/pkg/golinters/gocritic/gocritic.go index 0a9ec0561cd0..486303dab0c6 100644 --- a/pkg/golinters/gocritic/gocritic.go +++ b/pkg/golinters/gocritic/gocritic.go @@ -5,8 +5,6 @@ import ( "fmt" "go/ast" "go/types" - "maps" - "reflect" "runtime" "slices" "strings" @@ -19,7 +17,6 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" - "github.com/golangci/golangci-lint/v2/pkg/golinters/internal" "github.com/golangci/golangci-lint/v2/pkg/lint/linter" "github.com/golangci/golangci-lint/v2/pkg/logutils" ) @@ -31,7 +28,7 @@ var ( isDebug = logutils.HaveDebugTag(logutils.DebugKeyGoCritic) ) -func New(settings *config.GoCriticSettings) *goanalysis.Linter { +func New(settings *config.GoCriticSettings, replacer *strings.Replacer) *goanalysis.Linter { wrapper := &goCriticWrapper{ sizes: types.SizesFor("gc", runtime.GOARCH), } @@ -58,23 +55,18 @@ Dynamic rules are written declaratively with AST patterns, filters, report messa nil, ). WithContextSetter(func(context *linter.Context) { - wrapper.replacer = strings.NewReplacer( - internal.PlaceholderBasePath, context.Cfg.GetBasePath(), - ) - - wrapper.init(context.Log, settings) + wrapper.init(context.Log, settings, replacer) }). WithLoadMode(goanalysis.LoadModeTypesInfo) } type goCriticWrapper struct { settingsWrapper *settingsWrapper - replacer *strings.Replacer sizes types.Sizes once sync.Once } -func (w *goCriticWrapper) init(logger logutils.Log, settings *config.GoCriticSettings) { +func (w *goCriticWrapper) init(logger logutils.Log, settings *config.GoCriticSettings, replacer *strings.Replacer) { if settings == nil { return } @@ -86,12 +78,9 @@ func (w *goCriticWrapper) init(logger logutils.Log, settings *config.GoCriticSet } }) - settingsWrapper := newSettingsWrapper(settings, logger) - settingsWrapper.InferEnabledChecks() + settingsWrapper := newSettingsWrapper(logger, settings, replacer) - // 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 { + if err := settingsWrapper.Load(); err != nil { logger.Fatalf("%s: invalid settings: %s", linterName, err) } @@ -140,7 +129,8 @@ func (w *goCriticWrapper) buildEnabledCheckers(linterCtx *gocriticlinter.Context continue } - if err := w.configureCheckerInfo(info, allLowerCasedParams); err != nil { + err := w.settingsWrapper.setCheckerParams(info, allLowerCasedParams) + if err != nil { return nil, err } @@ -155,59 +145,6 @@ func (w *goCriticWrapper) buildEnabledCheckers(linterCtx *gocriticlinter.Context return enabledCheckers, nil } -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 - } - - // 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 { - v.Value = w.normalizeCheckerParamsValue(p) - continue - } - - // param `k` isn't supported - if len(info.Params) == 0 { - return fmt.Errorf("checker %s config param %s doesn't exist: checker doesn't have params", - info.Name, k) - } - - supportedKeys := slices.Sorted(maps.Keys(info.Params)) - - return fmt.Errorf("checker %s config param %s doesn't exist, all existing: %s", - info.Name, k, supportedKeys) - } - - return nil -} - -// 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 any) any { - rv := reflect.ValueOf(p) - switch rv.Type().Kind() { - case reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, reflect.Int: - return int(rv.Int()) - case reflect.Bool: - return rv.Bool() - case reflect.String: - // Perform variable substitution. - return w.replacer.Replace(rv.String()) - default: - return p - } -} - func runOnFile(pass *analysis.Pass, f *ast.File, checks []*gocriticlinter.Checker) { for _, c := range checks { // All checkers are expected to use *lint.Context @@ -233,19 +170,3 @@ func runOnFile(pass *analysis.Pass, f *ast.File, checks []*gocriticlinter.Checke } } } - -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 ret -} - -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) -} diff --git a/pkg/golinters/gocritic/gocritic_settings.go b/pkg/golinters/gocritic/gocritic_settings.go index 13e1f8f2a5b9..e3267eeec46b 100644 --- a/pkg/golinters/gocritic/gocritic_settings.go +++ b/pkg/golinters/gocritic/gocritic_settings.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "maps" + "reflect" "slices" "strings" @@ -16,6 +17,8 @@ import ( type settingsWrapper struct { *config.GoCriticSettings + replacer *strings.Replacer + logger logutils.Log allCheckers []*gocriticlinter.CheckerInfo @@ -31,12 +34,13 @@ type settingsWrapper struct { inferredEnabledChecksLowerCased goCriticChecks[struct{}] } -func newSettingsWrapper(settings *config.GoCriticSettings, logger logutils.Log) *settingsWrapper { +func newSettingsWrapper(logger logutils.Log, settings *config.GoCriticSettings, replacer *strings.Replacer) *settingsWrapper { allCheckers := gocriticlinter.GetCheckersInfo() 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{}{} @@ -46,17 +50,18 @@ func newSettingsWrapper(settings *config.GoCriticSettings, logger logutils.Log) } } - allTagsSorted := slices.Sorted(maps.Keys(allChecksByTag)) - return &settingsWrapper{ - GoCriticSettings: settings, - logger: logger, - allCheckers: allCheckers, - allChecks: allChecks, + GoCriticSettings: settings, + replacer: replacer, + logger: logger, + + allCheckers: allCheckers, + allChecks: allChecks, + allChecksByTag: allChecksByTag, + allTagsSorted: slices.Sorted(maps.Keys(allChecksByTag)), + inferredEnabledChecks: make(goCriticChecks[struct{}]), + allChecksLowerCased: allChecksLowerCased, - allChecksByTag: allChecksByTag, - allTagsSorted: allTagsSorted, - inferredEnabledChecks: make(goCriticChecks[struct{}]), inferredEnabledChecksLowerCased: make(goCriticChecks[struct{}]), } } @@ -69,8 +74,15 @@ func (s *settingsWrapper) GetLowerCasedParams() map[string]config.GoCriticCheckS return normalizeMap(s.SettingsPerCheck) } -// InferEnabledChecks tries to be consistent with (lintersdb.Manager).build. -func (s *settingsWrapper) InferEnabledChecks() { +func (s *settingsWrapper) Load() error { + s.inferEnabledChecks() + + // validate must be after inferEnabledChecks, not before. + // Because it uses gathered information about tags set and finally enabled checks. + return s.validate() +} + +func (s *settingsWrapper) inferEnabledChecks() { s.debugChecksInitialState() enabledByDefaultChecks, disabledByDefaultChecks := s.buildEnabledAndDisabledByDefaultChecks() @@ -78,22 +90,30 @@ func (s *settingsWrapper) InferEnabledChecks() { debugChecksListf(enabledByDefaultChecks, "Enabled by default") debugChecksListf(disabledByDefaultChecks, "Disabled by default") - enabledChecks := make(goCriticChecks[struct{}]) + var enabledChecks goCriticChecks[struct{}] + + switch { + case s.DisableAll: + // disable-all revokes the default settings. + enabledChecks = make(goCriticChecks[struct{}]) - if s.EnableAll { + case s.EnableAll: + // enable-all revokes the default settings. 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. + + default: enabledChecks = make(goCriticChecks[struct{}], len(enabledByDefaultChecks)) + for _, check := range enabledByDefaultChecks { enabledChecks[check] = struct{}{} } } - if len(s.EnabledTags) != 0 { + if len(s.EnabledTags) > 0 { enabledFromTags := s.expandTagsToChecks(s.EnabledTags) debugChecksListf(enabledFromTags, "Enabled by config tags %s", s.EnabledTags) @@ -103,7 +123,7 @@ func (s *settingsWrapper) InferEnabledChecks() { } } - if len(s.EnabledChecks) != 0 { + if len(s.EnabledChecks) > 0 { debugChecksListf(s.EnabledChecks, "Enabled by config") for _, check := range s.EnabledChecks { @@ -111,11 +131,12 @@ func (s *settingsWrapper) InferEnabledChecks() { s.logger.Warnf("%s: no need to enable check %q: it's already enabled", linterName, check) continue } + enabledChecks[check] = struct{}{} } } - if len(s.DisabledTags) != 0 { + if len(s.DisabledTags) > 0 { disabledFromTags := s.expandTagsToChecks(s.DisabledTags) debugChecksListf(disabledFromTags, "Disabled by config tags %s", s.DisabledTags) @@ -125,7 +146,7 @@ func (s *settingsWrapper) InferEnabledChecks() { } } - if len(s.DisabledChecks) != 0 { + if len(s.DisabledChecks) > 0 { debugChecksListf(s.DisabledChecks, "Disabled by config") for _, check := range s.DisabledChecks { @@ -133,6 +154,7 @@ func (s *settingsWrapper) InferEnabledChecks() { s.logger.Warnf("%s: no need to disable check %q: it's already disabled", linterName, check) continue } + delete(enabledChecks, check) } } @@ -145,29 +167,64 @@ func (s *settingsWrapper) InferEnabledChecks() { func (s *settingsWrapper) buildEnabledAndDisabledByDefaultChecks() (enabled, disabled []string) { for _, info := range s.allCheckers { - if enabledByDef := isEnabledByDefaultGoCriticChecker(info); enabledByDef { + if isEnabledByDefaultGoCriticChecker(info) { enabled = append(enabled, info.Name) } else { disabled = append(disabled, info.Name) } } + return enabled, disabled } func (s *settingsWrapper) expandTagsToChecks(tags []string) []string { var checks []string + for _, tag := range tags { checks = append(checks, s.allChecksByTag[tag]...) } + return checks } +func (s *settingsWrapper) setCheckerParams( + 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 + } + + // 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 { + v.Value = s.normalizeCheckerParamsValue(p) + continue + } + + // param `k` isn't supported + if len(info.Params) == 0 { + return fmt.Errorf("checker %s config param %s doesn't exist: checker doesn't have params", + info.Name, k) + } + + return fmt.Errorf("checker %s config param %s doesn't exist, all existing: %s", + info.Name, k, slices.Sorted(maps.Keys(info.Params))) + } + + return nil +} + func (s *settingsWrapper) debugChecksInitialState() { if !isDebug { return } debugf("All gocritic existing tags and checks:") + for _, tag := range s.allTagsSorted { debugChecksListf(s.allChecksByTag[tag], " tag %q", tag) } @@ -182,11 +239,10 @@ func (s *settingsWrapper) debugChecksFinalState() { var disabledChecks []string for _, checker := range s.allCheckers { - check := checker.Name - if s.inferredEnabledChecks.has(check) { - enabledChecks = append(enabledChecks, check) + if s.IsCheckEnabled(checker.Name) { + enabledChecks = append(enabledChecks, checker.Name) } else { - disabledChecks = append(disabledChecks, check) + disabledChecks = append(disabledChecks, checker.Name) } } @@ -199,8 +255,32 @@ func (s *settingsWrapper) debugChecksFinalState() { } } -// Validate tries to be consistent with (lintersdb.Validator).validateEnabledDisabledLintersConfig. -func (s *settingsWrapper) Validate() error { +// 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 (s *settingsWrapper) normalizeCheckerParamsValue(p any) any { + rv := reflect.ValueOf(p) + + switch rv.Type().Kind() { + case reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, reflect.Int: + return int(rv.Int()) + + case reflect.Bool: + return rv.Bool() + + case reflect.String: + // Perform variable substitution. + return s.replacer.Replace(rv.String()) + + default: + return p + } +} + +// validate tries to be consistent with (lintersdb.Validator).validateEnabledDisabledLintersConfig. +func (s *settingsWrapper) validate() error { for _, v := range []func() error{ s.validateOptionsCombinations, s.validateCheckerTags, @@ -216,26 +296,26 @@ func (s *settingsWrapper) Validate() error { } func (s *settingsWrapper) validateOptionsCombinations() error { - if s.EnableAll { - if s.DisableAll { - return errors.New("enable-all and disable-all options must not be combined") - } + if s.EnableAll && s.DisableAll { + return errors.New("enable-all and disable-all options must not be combined") + } - if len(s.EnabledTags) != 0 { + switch { + case s.EnableAll: + if len(s.EnabledTags) > 0 { return errors.New("enable-all and enabled-tags options must not be combined") } - if len(s.EnabledChecks) != 0 { + if len(s.EnabledChecks) > 0 { return errors.New("enable-all and enabled-checks options must not be combined") } - } - if s.DisableAll { - if len(s.DisabledTags) != 0 { + case s.DisableAll: + if len(s.DisabledTags) > 0 { return errors.New("disable-all and disabled-tags options must not be combined") } - if len(s.DisabledChecks) != 0 { + if len(s.DisabledChecks) > 0 { return errors.New("disable-all and disabled-checks options must not be combined") } @@ -278,9 +358,11 @@ func (s *settingsWrapper) validateCheckerNames() error { for check := range s.SettingsPerCheck { lcName := strings.ToLower(check) + if !s.allChecksLowerCased.has(lcName) { return fmt.Errorf("invalid check settings: check %q doesn't exist, see %s documentation", check, linterName) } + if !s.inferredEnabledChecksLowerCased.has(lcName) { s.logger.Warnf("%s: settings were provided for disabled check %q", check, linterName) } @@ -309,6 +391,7 @@ func (s *settingsWrapper) validateAtLeastOneCheckerEnabled() error { if len(s.inferredEnabledChecks) == 0 { return errors.New("eventually all checks were disabled: at least one must be enabled") } + return nil } @@ -328,3 +411,21 @@ func debugChecksListf(checks []string, format string, args ...any) { debugf("%s checks (%d): %s", fmt.Sprintf(format, args...), len(checks), strings.Join(v, ", ")) } + +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 ret +} + +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) +} diff --git a/pkg/golinters/gocritic/gocritic_test.go b/pkg/golinters/gocritic/gocritic_settings_test.go similarity index 61% rename from pkg/golinters/gocritic/gocritic_test.go rename to pkg/golinters/gocritic/gocritic_settings_test.go index b742afc9de53..cbb26922c27f 100644 --- a/pkg/golinters/gocritic/gocritic_test.go +++ b/pkg/golinters/gocritic/gocritic_settings_test.go @@ -16,14 +16,15 @@ import ( ) // https://go-critic.com/overview.html -func Test_settingsWrapper_InferEnabledChecks(t *testing.T) { +func Test_settingsWrapper_inferEnabledChecks(t *testing.T) { err := checkers.InitEmbeddedRules() require.NoError(t, err) allCheckersInfo := gocriticlinter.GetCheckersInfo() - allChecksByTag := make(map[string][]string) - allChecks := make([]string, 0, len(allCheckersInfo)) + allChecksByTag := make(map[string]Slicer) + allChecks := make(Slicer, 0, len(allCheckersInfo)) + for _, checker := range allCheckersInfo { allChecks = append(allChecks, checker.Name) for _, tag := range checker.Tags { @@ -31,169 +32,160 @@ func Test_settingsWrapper_InferEnabledChecks(t *testing.T) { } } - enabledByDefaultChecks := make([]string, 0, len(allCheckersInfo)) + enabledByDefaultChecks := make(Slicer, 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")) - insert := func(in []string, toInsert ...string) []string { - return slices.Concat(in, toInsert) - } - - 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 - } - - uniq := func(in []string) []string { - return slices.Compact(slices.Sorted(slices.Values(in))) - } + t.Logf("enabled by default checks:\n%s", strings.Join(enabledByDefaultChecks, "\n")) - cases := []struct { + testCases := []struct { name string - sett *config.GoCriticSettings + settings *config.GoCriticSettings expectedEnabledChecks []string }{ { name: "no configuration", - sett: &config.GoCriticSettings{}, + settings: &config.GoCriticSettings{}, expectedEnabledChecks: enabledByDefaultChecks, }, { name: "enable checks", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ EnabledChecks: []string{"assignOp", "badCall", "emptyDecl"}, }, - expectedEnabledChecks: insert(enabledByDefaultChecks, "emptyDecl"), + expectedEnabledChecks: enabledByDefaultChecks.add("emptyDecl"), }, { name: "disable checks", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ DisabledChecks: []string{"assignOp", "emptyDecl"}, }, - expectedEnabledChecks: remove(enabledByDefaultChecks, "assignOp"), + expectedEnabledChecks: enabledByDefaultChecks.remove("assignOp"), }, { name: "enable tags", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ EnabledTags: []string{"style", "experimental"}, }, - expectedEnabledChecks: uniq(insert(insert( - enabledByDefaultChecks, - allChecksByTag["style"]...), - allChecksByTag["experimental"]...)), + expectedEnabledChecks: enabledByDefaultChecks. + add(allChecksByTag["style"]...). + add(allChecksByTag["experimental"]...). + uniq(), }, { name: "disable tags", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ DisabledTags: []string{"diagnostic"}, }, - expectedEnabledChecks: remove(enabledByDefaultChecks, allChecksByTag["diagnostic"]...), + expectedEnabledChecks: enabledByDefaultChecks.remove(allChecksByTag["diagnostic"]...), }, { name: "enable checks disable checks", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ EnabledChecks: []string{"badCall", "badLock"}, DisabledChecks: []string{"assignOp", "badSorting"}, }, - expectedEnabledChecks: insert(remove(enabledByDefaultChecks, "assignOp"), "badLock"), + expectedEnabledChecks: enabledByDefaultChecks. + remove("assignOp"). + add("badLock"), }, { name: "enable checks enable tags", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ EnabledChecks: []string{"badCall", "badLock", "hugeParam"}, EnabledTags: []string{"diagnostic"}, }, - expectedEnabledChecks: uniq(insert(insert(enabledByDefaultChecks, - allChecksByTag["diagnostic"]...), - "hugeParam")), + expectedEnabledChecks: enabledByDefaultChecks. + add(allChecksByTag["diagnostic"]...). + add("hugeParam"). + uniq(), }, { name: "enable checks disable tags", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ EnabledChecks: []string{"badCall", "badLock", "boolExprSimplify", "hugeParam"}, DisabledTags: []string{"style", "diagnostic"}, }, - expectedEnabledChecks: insert(remove(remove(enabledByDefaultChecks, - allChecksByTag["style"]...), - allChecksByTag["diagnostic"]...), - "hugeParam"), + expectedEnabledChecks: enabledByDefaultChecks. + remove(allChecksByTag["style"]...). + remove(allChecksByTag["diagnostic"]...). + add("hugeParam"), }, { name: "enable all checks via tags", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ EnabledTags: []string{"diagnostic", "experimental", "opinionated", "performance", "style"}, }, expectedEnabledChecks: allChecks, }, { name: "disable checks enable tags", - sett: &config.GoCriticSettings{ + settings: &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"), + expectedEnabledChecks: enabledByDefaultChecks. + add(allChecksByTag["style"]...). + add(allChecksByTag["diagnostic"]...). + uniq(). + remove("assignOp", "badCall", "badLock"), }, { name: "disable checks disable tags", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ DisabledChecks: []string{"badCall", "badLock", "codegenComment", "hugeParam"}, DisabledTags: []string{"style"}, }, - expectedEnabledChecks: remove(remove(enabledByDefaultChecks, - allChecksByTag["style"]...), - "badCall", "codegenComment"), + expectedEnabledChecks: enabledByDefaultChecks. + remove(allChecksByTag["style"]...). + remove("badCall", "codegenComment"), }, { name: "enable tags disable tags", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ EnabledTags: []string{"experimental"}, DisabledTags: []string{"style"}, }, - expectedEnabledChecks: remove(uniq(insert(enabledByDefaultChecks, - allChecksByTag["experimental"]...)), - allChecksByTag["style"]...), + expectedEnabledChecks: enabledByDefaultChecks. + add(allChecksByTag["experimental"]...). + uniq(). + remove(allChecksByTag["style"]...), }, { name: "enable checks disable checks enable tags", - sett: &config.GoCriticSettings{ + settings: &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"), + expectedEnabledChecks: enabledByDefaultChecks. + add(allChecksByTag["experimental"]...). + add("indexAlloc", "hugeParam"). + uniq(). + remove("deprecatedComment", "typeSwitchVar"), }, { name: "enable checks disable checks enable tags disable tags", - sett: &config.GoCriticSettings{ + settings: &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"), + expectedEnabledChecks: enabledByDefaultChecks. + add(allChecksByTag["experimental"]...). + add("badCond"). + uniq(). + remove(allChecksByTag["performance"]...). + remove("deprecatedComment", "typeSwitchVar"), }, { name: "enable single tag only", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ DisableAll: true, EnabledTags: []string{"experimental"}, }, @@ -201,31 +193,35 @@ func Test_settingsWrapper_InferEnabledChecks(t *testing.T) { }, { name: "enable two tags only", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ DisableAll: true, EnabledTags: []string{"experimental", "performance"}, }, - expectedEnabledChecks: uniq(insert(allChecksByTag["experimental"], allChecksByTag["performance"]...)), + expectedEnabledChecks: allChecksByTag["experimental"]. + add(allChecksByTag["performance"]...). + uniq(), }, { name: "disable single tag only", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ EnableAll: true, DisabledTags: []string{"style"}, }, - expectedEnabledChecks: remove(allChecks, allChecksByTag["style"]...), + expectedEnabledChecks: allChecks.remove(allChecksByTag["style"]...), }, { name: "disable two tags only", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ EnableAll: true, DisabledTags: []string{"style", "diagnostic"}, }, - expectedEnabledChecks: remove(remove(allChecks, allChecksByTag["style"]...), allChecksByTag["diagnostic"]...), + expectedEnabledChecks: allChecks. + remove(allChecksByTag["style"]...). + remove(allChecksByTag["diagnostic"]...), }, { name: "enable some checks only", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ DisableAll: true, EnabledChecks: []string{"deferInLoop", "dupImport", "ifElseChain", "mapKey"}, }, @@ -233,55 +229,60 @@ func Test_settingsWrapper_InferEnabledChecks(t *testing.T) { }, { name: "disable some checks only", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ EnableAll: true, DisabledChecks: []string{"deferInLoop", "dupImport", "ifElseChain", "mapKey"}, }, - expectedEnabledChecks: remove(allChecks, "deferInLoop", "dupImport", "ifElseChain", "mapKey"), + expectedEnabledChecks: allChecks. + remove("deferInLoop", "dupImport", "ifElseChain", "mapKey"), }, { name: "enable single tag and some checks from another tag only", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ DisableAll: true, EnabledTags: []string{"experimental"}, EnabledChecks: []string{"importShadow"}, }, - expectedEnabledChecks: insert(allChecksByTag["experimental"], "importShadow"), + expectedEnabledChecks: allChecksByTag["experimental"].add("importShadow"), }, { name: "disable single tag and some checks from another tag only", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ EnableAll: true, DisabledTags: []string{"experimental"}, DisabledChecks: []string{"importShadow"}, }, - expectedEnabledChecks: remove(remove(allChecks, allChecksByTag["experimental"]...), "importShadow"), + expectedEnabledChecks: allChecks. + remove(allChecksByTag["experimental"]...). + remove("importShadow"), }, } - for _, tt := range cases { - t.Run(tt.name, func(t *testing.T) { + for _, test := range testCases { + t.Run(test.name, func(t *testing.T) { t.Parallel() - lg := logutils.NewStderrLog("Test_goCriticSettingsWrapper_InferEnabledChecks") - wr := newSettingsWrapper(tt.sett, lg) + lg := logutils.NewStderrLog(t.Name()) + wr := newSettingsWrapper(lg, test.settings, nil) + + wr.inferEnabledChecks() + + assert.ElementsMatch(t, test.expectedEnabledChecks, slices.Collect(maps.Keys(wr.inferredEnabledChecks))) - wr.InferEnabledChecks() - assert.ElementsMatch(t, tt.expectedEnabledChecks, slices.Collect(maps.Keys(wr.inferredEnabledChecks))) - assert.NoError(t, wr.Validate()) + assert.NoError(t, wr.validate()) }) } } -func Test_settingsWrapper_Validate(t *testing.T) { - cases := []struct { +func Test_settingsWrapper_Load(t *testing.T) { + testCases := []struct { name string - sett *config.GoCriticSettings + settings *config.GoCriticSettings expectedErr bool }{ { name: "combine enable-all and disable-all", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ EnableAll: true, DisableAll: true, }, @@ -289,7 +290,7 @@ func Test_settingsWrapper_Validate(t *testing.T) { }, { name: "combine enable-all and enabled-tags", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ EnableAll: true, EnabledTags: []string{"experimental"}, }, @@ -297,7 +298,7 @@ func Test_settingsWrapper_Validate(t *testing.T) { }, { name: "combine enable-all and enabled-checks", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ EnableAll: true, EnabledChecks: []string{"dupImport"}, }, @@ -305,7 +306,7 @@ func Test_settingsWrapper_Validate(t *testing.T) { }, { name: "combine disable-all and disabled-tags", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ DisableAll: true, DisabledTags: []string{"style"}, }, @@ -313,7 +314,7 @@ func Test_settingsWrapper_Validate(t *testing.T) { }, { name: "combine disable-all and disable-checks", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ DisableAll: true, DisabledChecks: []string{"appendAssign"}, }, @@ -321,42 +322,42 @@ func Test_settingsWrapper_Validate(t *testing.T) { }, { name: "disable-all and no one check enabled", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ DisableAll: true, }, expectedErr: true, }, { name: "unknown enabled tag", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ EnabledTags: []string{"diagnostic", "go-proverbs"}, }, expectedErr: true, }, { name: "unknown disabled tag", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ DisabledTags: []string{"style", "go-proverbs"}, }, expectedErr: true, }, { name: "unknown enabled check", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ EnabledChecks: []string{"appendAssign", "noExitAfterDefer", "underef"}, }, expectedErr: true, }, { name: "unknown disabled check", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ DisabledChecks: []string{"dupSubExpr", "noExitAfterDefer", "returnAfterHttpError"}, }, expectedErr: true, }, { name: "settings for unknown check", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ SettingsPerCheck: map[string]config.GoCriticCheckSettings{ "captLocall": {"paramsOnly": false}, "unnamedResult": {"checkExported": true}, @@ -366,7 +367,7 @@ func Test_settingsWrapper_Validate(t *testing.T) { }, { name: "settings for disabled check", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ DisabledChecks: []string{"elseif"}, SettingsPerCheck: map[string]config.GoCriticCheckSettings{ "elseif": {"skipBalanced": true}, @@ -376,7 +377,7 @@ func Test_settingsWrapper_Validate(t *testing.T) { }, { name: "settings by lower-cased checker name", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ EnabledChecks: []string{"tooManyResultsChecker"}, SettingsPerCheck: map[string]config.GoCriticCheckSettings{ "toomanyresultschecker": {"maxResults": 3}, @@ -387,7 +388,7 @@ func Test_settingsWrapper_Validate(t *testing.T) { }, { name: "enabled and disabled at one moment check", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ EnabledChecks: []string{"appendAssign", "codegenComment", "underef"}, DisabledChecks: []string{"elseif", "underef"}, }, @@ -395,7 +396,7 @@ func Test_settingsWrapper_Validate(t *testing.T) { }, { name: "enabled and disabled at one moment tag", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ EnabledTags: []string{"performance", "style"}, DisabledTags: []string{"style", "diagnostic"}, }, @@ -403,14 +404,14 @@ func Test_settingsWrapper_Validate(t *testing.T) { }, { name: "disable all checks via tags", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ DisabledTags: []string{"diagnostic", "experimental", "opinionated", "performance", "style"}, }, expectedErr: true, }, { name: "enable-all and disable all checks via tags", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ EnableAll: true, DisabledTags: []string{"diagnostic", "experimental", "opinionated", "performance", "style"}, }, @@ -418,7 +419,7 @@ func Test_settingsWrapper_Validate(t *testing.T) { }, { name: "valid configuration", - sett: &config.GoCriticSettings{ + settings: &config.GoCriticSettings{ EnabledTags: []string{"performance"}, DisabledChecks: []string{"dupImport", "ifElseChain", "octalLiteral", "whyNoLint"}, SettingsPerCheck: map[string]config.GoCriticCheckSettings{ @@ -430,17 +431,15 @@ func Test_settingsWrapper_Validate(t *testing.T) { }, } - for _, tt := range cases { - t.Run(tt.name, func(t *testing.T) { + for _, test := range testCases { + t.Run(test.name, func(t *testing.T) { t.Parallel() - lg := logutils.NewStderrLog("Test_goCriticSettingsWrapper_Validate") - wr := newSettingsWrapper(tt.sett, lg) + lg := logutils.NewStderrLog(t.Name()) + wr := newSettingsWrapper(lg, test.settings, nil) - wr.InferEnabledChecks() - - err := wr.Validate() - if tt.expectedErr { + err := wr.Load() + if test.expectedErr { if assert.Error(t, err) { t.Log(err) } @@ -450,3 +449,25 @@ func Test_settingsWrapper_Validate(t *testing.T) { }) } } + +type Slicer []string + +func (s Slicer) add(toAdd ...string) Slicer { + return slices.Concat(s, toAdd) +} + +func (s Slicer) remove(toRemove ...string) Slicer { + result := slices.Clone(s) + + for _, v := range toRemove { + if i := slices.Index(result, v); i != -1 { + result = slices.Delete(result, i, i+1) + } + } + + return result +} + +func (s Slicer) uniq() Slicer { + return slices.Compact(slices.Sorted(slices.Values(s))) +} diff --git a/pkg/golinters/gocritic/testdata/gocritic.yml b/pkg/golinters/gocritic/testdata/gocritic.yml index 5c90af7d6f78..e64cb2e54406 100644 --- a/pkg/golinters/gocritic/testdata/gocritic.yml +++ b/pkg/golinters/gocritic/testdata/gocritic.yml @@ -14,7 +14,7 @@ linters: sizeThreshold: 24 ruleguard: failOn: dsl,import - rules: '${base-path}/ruleguard/preferWriteString.go,${base-path}/ruleguard/stringsSimplify.go' + rules: '${base-path}/ruleguard/preferWriteString.go,${config-path}/ruleguard/stringsSimplify.go' run: relative-path-mode: cfg diff --git a/pkg/golinters/goheader/goheader.go b/pkg/golinters/goheader/goheader.go index 491e54a7819c..e03d3277d2c7 100644 --- a/pkg/golinters/goheader/goheader.go +++ b/pkg/golinters/goheader/goheader.go @@ -9,18 +9,17 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" - "github.com/golangci/golangci-lint/v2/pkg/golinters/internal" ) const linterName = "goheader" -func New(settings *config.GoHeaderSettings, basePath string) *goanalysis.Linter { +func New(settings *config.GoHeaderSettings, replacer *strings.Replacer) *goanalysis.Linter { conf := &goheader.Configuration{} if settings != nil { conf = &goheader.Configuration{ Values: settings.Values, Template: settings.Template, - TemplatePath: strings.ReplaceAll(settings.TemplatePath, internal.PlaceholderBasePath, basePath), + TemplatePath: replacer.Replace(settings.TemplatePath), } } diff --git a/pkg/golinters/internal/commons.go b/pkg/golinters/internal/commons.go index ebc211902dc8..d19c1fd45082 100644 --- a/pkg/golinters/internal/commons.go +++ b/pkg/golinters/internal/commons.go @@ -4,6 +4,3 @@ import "github.com/golangci/golangci-lint/v2/pkg/logutils" // LinterLogger must be use only when the context logger is not available. var LinterLogger = logutils.NewStderrLog(logutils.DebugKeyLinter) - -// PlaceholderBasePath used inside linters to evaluate relative paths. -const PlaceholderBasePath = "${base-path}" diff --git a/pkg/lint/lintersdb/builder_linter.go b/pkg/lint/lintersdb/builder_linter.go index 7e8e4ad1ba51..00c333aadb9f 100644 --- a/pkg/lint/lintersdb/builder_linter.go +++ b/pkg/lint/lintersdb/builder_linter.go @@ -129,6 +129,8 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { return nil, nil } + placeholderReplacer := config.NewPlaceholderReplacer(cfg) + // 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{ @@ -180,7 +182,7 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { WithSince("v1.44.0"). WithURL("https://gitlab.com/bosi/decorder"), - linter.NewConfig(depguard.New(&cfg.Linters.Settings.Depguard, cfg.GetBasePath())). + linter.NewConfig(depguard.New(&cfg.Linters.Settings.Depguard, placeholderReplacer)). WithSince("v1.4.0"). WithURL("https://github.com/OpenPeeDeeP/depguard"), @@ -300,7 +302,7 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { WithSince("v1.0.0"). WithURL("https://github.com/jgautheron/goconst"), - linter.NewConfig(gocritic.New(&cfg.Linters.Settings.Gocritic)). + linter.NewConfig(gocritic.New(&cfg.Linters.Settings.Gocritic, placeholderReplacer)). WithSince("v1.12.0"). WithLoadForGoAnalysis(). WithAutoFix(). @@ -340,7 +342,7 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { WithAutoFix(). WithURL("https://github.com/segmentio/golines"), - linter.NewConfig(goheader.New(&cfg.Linters.Settings.Goheader, cfg.GetBasePath())). + linter.NewConfig(goheader.New(&cfg.Linters.Settings.Goheader, placeholderReplacer)). WithSince("v1.28.0"). WithAutoFix(). WithURL("https://github.com/denis-tingaikin/go-header"), From f6398072c92883959a262bfb240097261f9e1bb4 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Fri, 4 Apr 2025 02:56:08 +0200 Subject: [PATCH 024/152] feat: add an option to display absolute paths (#5651) --- .golangci.next.reference.yml | 7 ++++ jsonschema/golangci.next.jsonschema.json | 5 +++ pkg/commands/flagsets.go | 2 ++ pkg/config/output.go | 32 +++++++++++++++++- pkg/config/output_test.go | 33 +++++++++++++++---- pkg/fsutils/basepath.go | 3 ++ pkg/lint/runner.go | 2 +- pkg/result/processors/path_prettifier.go | 21 ++++++++---- pkg/result/processors/path_prettifier_test.go | 3 +- 9 files changed, 92 insertions(+), 16 deletions(-) diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index 8b02677be8e0..747ffa58cb3d 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -4152,9 +4152,16 @@ output: path: ./path/to/output.json # Add a prefix to the output file references. + # This option is ignored when using `output.path-mode: abs` mode. # Default: "" path-prefix: "" + # By default, the report are related to the path obtained by `run.relative-path-mode`. + # The mode `abs` allows to show absolute file paths instead of relative file paths. + # The option `output.path-prefix` is ignored when using `abs` mode. + # Default: "" + path-mode: "abs" + # Order to use when sorting results. # Possible values: `file`, `linter`, and `severity`. # diff --git a/jsonschema/golangci.next.jsonschema.json b/jsonschema/golangci.next.jsonschema.json index e775096e315b..48d68df53cad 100644 --- a/jsonschema/golangci.next.jsonschema.json +++ b/jsonschema/golangci.next.jsonschema.json @@ -4222,6 +4222,11 @@ } } }, + "path-mode": { + "type": "string", + "default": "", + "examples": ["abs"] + }, "path-prefix": { "description": "Add a prefix to the output file references.", "type": "string", diff --git a/pkg/commands/flagsets.go b/pkg/commands/flagsets.go index 2ef165852d02..cc4b00436e3a 100644 --- a/pkg/commands/flagsets.go +++ b/pkg/commands/flagsets.go @@ -62,6 +62,8 @@ func setupRunFlagSet(v *viper.Viper, fs *pflag.FlagSet) { func setupOutputFlagSet(v *viper.Viper, fs *pflag.FlagSet) { internal.AddFlagAndBind(v, fs, fs.String, "path-prefix", "output.path-prefix", "", color.GreenString("Path prefix to add to output")) + internal.AddFlagAndBind(v, fs, fs.String, "path-mode", "output.path-mode", "", + color.GreenString("Path mode to use (empty, or 'abs')")) internal.AddFlagAndBind(v, fs, fs.Bool, "show-stats", "output.show-stats", true, color.GreenString("Show statistics per linter")) setupOutputFormatsFlagSet(v, fs) diff --git a/pkg/config/output.go b/pkg/config/output.go index 43dce3900ccc..803dc3ac2941 100644 --- a/pkg/config/output.go +++ b/pkg/config/output.go @@ -4,16 +4,34 @@ import ( "fmt" "slices" "strings" + + "github.com/golangci/golangci-lint/v2/pkg/fsutils" ) type Output struct { Formats Formats `mapstructure:"formats"` SortOrder []string `mapstructure:"sort-order"` - PathPrefix string `mapstructure:"path-prefix"` ShowStats bool `mapstructure:"show-stats"` + PathPrefix string `mapstructure:"path-prefix"` + PathMode string `mapstructure:"path-mode"` } func (o *Output) Validate() error { + validators := []func() error{ + o.validateSortOrder, + o.validatePathMode, + } + + for _, v := range validators { + if err := v(); err != nil { + return err + } + } + + return nil +} + +func (o *Output) validateSortOrder() error { validOrders := []string{"linter", "file", "severity"} all := strings.Join(o.SortOrder, " ") @@ -30,3 +48,15 @@ func (o *Output) Validate() error { return nil } + +func (o *Output) validatePathMode() error { + switch o.PathMode { + case "", fsutils.OutputPathModeAbsolute: + // Valid + + default: + return fmt.Errorf("unsupported output path mode %q", o.PathMode) + } + + return nil +} diff --git a/pkg/config/output_test.go b/pkg/config/output_test.go index 1e19323d15a0..2b498648113a 100644 --- a/pkg/config/output_test.go +++ b/pkg/config/output_test.go @@ -4,6 +4,8 @@ import ( "testing" "github.com/stretchr/testify/require" + + "github.com/golangci/golangci-lint/v2/pkg/fsutils" ) func TestOutput_Validate(t *testing.T) { @@ -12,29 +14,41 @@ func TestOutput_Validate(t *testing.T) { settings *Output }{ { - desc: "file", + desc: "SortOrder: file", settings: &Output{ SortOrder: []string{"file"}, }, }, { - desc: "linter", + desc: "SortOrder: linter", settings: &Output{ SortOrder: []string{"linter"}, }, }, { - desc: "severity", + desc: "SortOrder: severity", settings: &Output{ SortOrder: []string{"severity"}, }, }, { - desc: "multiple", + desc: "SortOrder: multiple", settings: &Output{ SortOrder: []string{"file", "linter", "severity"}, }, }, + { + desc: "PathMode: empty", + settings: &Output{ + PathMode: "", + }, + }, + { + desc: "PathMode: absolute", + settings: &Output{ + PathMode: fsutils.OutputPathModeAbsolute, + }, + }, } for _, test := range testCases { @@ -54,19 +68,26 @@ func TestOutput_Validate_error(t *testing.T) { expected string }{ { - desc: "invalid sort-order", + desc: "SortOrder: invalid", settings: &Output{ SortOrder: []string{"a"}, }, expected: `unsupported sort-order name "a"`, }, { - desc: "duplicate", + desc: "SortOrder: duplicate", settings: &Output{ SortOrder: []string{"file", "linter", "severity", "linter"}, }, expected: `the sort-order name "linter" is repeated several times`, }, + { + desc: "PathMode: invalid", + settings: &Output{ + PathMode: "example", + }, + expected: `unsupported output path mode "example"`, + }, } for _, test := range testCases { diff --git a/pkg/fsutils/basepath.go b/pkg/fsutils/basepath.go index f0f4bc762d2a..3761fa0eaa71 100644 --- a/pkg/fsutils/basepath.go +++ b/pkg/fsutils/basepath.go @@ -19,6 +19,9 @@ const ( RelativePathModeWd = "wd" ) +// OutputPathModeAbsolute path mode used to show absolute paths in output reports (user-facing). +const OutputPathModeAbsolute = "abs" + func AllRelativePathModes() []string { return []string{RelativePathModeGoMod, RelativePathModeGitRoot, RelativePathModeCfg, RelativePathModeWd} } diff --git a/pkg/lint/runner.go b/pkg/lint/runner.go index ebb35a0d7460..5ede9b24dae5 100644 --- a/pkg/lint/runner.go +++ b/pkg/lint/runner.go @@ -110,7 +110,7 @@ func NewRunner(log logutils.Log, cfg *config.Config, goenv *goutil.Env, processors.NewSourceCode(lineCache, log.Child(logutils.DebugKeySourceCode)), processors.NewPathShortener(), processors.NewSeverity(log.Child(logutils.DebugKeySeverityRules), lineCache, &cfg.Severity), - processors.NewPathPrettifier(log, cfg.Output.PathPrefix), + processors.NewPathPrettifier(log, &cfg.Output), processors.NewSortResults(&cfg.Output), }, lintCtx: lintCtx, diff --git a/pkg/result/processors/path_prettifier.go b/pkg/result/processors/path_prettifier.go index 31270044f1fe..cb6ef8ebc27d 100644 --- a/pkg/result/processors/path_prettifier.go +++ b/pkg/result/processors/path_prettifier.go @@ -3,6 +3,8 @@ package processors import ( "path/filepath" + "github.com/golangci/golangci-lint/v2/pkg/config" + "github.com/golangci/golangci-lint/v2/pkg/fsutils" "github.com/golangci/golangci-lint/v2/pkg/logutils" "github.com/golangci/golangci-lint/v2/pkg/result" ) @@ -12,14 +14,15 @@ var _ Processor = (*PathPrettifier)(nil) // PathPrettifier modifies report file path to be relative to the base path. // Also handles the `output.path-prefix` option. type PathPrettifier struct { - prefix string - log logutils.Log + cfg *config.Output + + log logutils.Log } -func NewPathPrettifier(log logutils.Log, prefix string) *PathPrettifier { +func NewPathPrettifier(log logutils.Log, cfg *config.Output) *PathPrettifier { return &PathPrettifier{ - prefix: prefix, - log: log.Child(logutils.DebugKeyPathPrettifier), + cfg: cfg, + log: log.Child(logutils.DebugKeyPathPrettifier), } } @@ -28,13 +31,17 @@ func (*PathPrettifier) Name() string { } func (p *PathPrettifier) Process(issues []result.Issue) ([]result.Issue, error) { + if p.cfg.PathMode == fsutils.OutputPathModeAbsolute { + return issues, nil + } + return transformIssues(issues, func(issue *result.Issue) *result.Issue { newIssue := issue - if p.prefix == "" { + if p.cfg.PathPrefix == "" { newIssue.Pos.Filename = issue.RelativePath } else { - newIssue.Pos.Filename = filepath.Join(p.prefix, issue.RelativePath) + newIssue.Pos.Filename = filepath.Join(p.cfg.PathPrefix, issue.RelativePath) } return newIssue diff --git a/pkg/result/processors/path_prettifier_test.go b/pkg/result/processors/path_prettifier_test.go index ddd38e49759f..824509712ef7 100644 --- a/pkg/result/processors/path_prettifier_test.go +++ b/pkg/result/processors/path_prettifier_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/logutils" "github.com/golangci/golangci-lint/v2/pkg/result" ) @@ -59,7 +60,7 @@ func TestPathPrettifier_Process(t *testing.T) { }, } { t.Run(tt.name, func(t *testing.T) { - p := NewPathPrettifier(logutils.NewStderrLog(logutils.DebugKeyEmpty), tt.prefix) + p := NewPathPrettifier(logutils.NewStderrLog(logutils.DebugKeyEmpty), &config.Output{PathPrefix: tt.prefix}) got, err := p.Process(tt.issues) require.NoError(t, err) From 2edb46dd187f24d3e1ead6535fef5cac48f7c8b6 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Fri, 4 Apr 2025 02:56:20 +0200 Subject: [PATCH 025/152] feat: colored diff for fmt command (#5652) --- go.mod | 2 ++ go.sum | 6 ++++-- pkg/commands/fmt.go | 8 +++++--- pkg/goformat/runner.go | 23 ++++++++++++++++++----- 4 files changed, 29 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index bf92c5112000..403f4796e4eb 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,7 @@ require ( github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1 github.com/OpenPeeDeeP/depguard/v2 v2.2.1 + github.com/alecthomas/chroma/v2 v2.15.0 github.com/alecthomas/go-check-sumtype v0.3.1 github.com/alexkohler/nakedret/v2 v2.0.6 github.com/alexkohler/prealloc v1.0.0 @@ -148,6 +149,7 @@ require ( github.com/chavacava/garif v0.1.0 // indirect github.com/dave/dst v0.27.3 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dlclark/regexp2 v1.11.4 // indirect github.com/ebitengine/purego v0.8.2 // indirect github.com/ettle/strcase v0.2.0 // indirect github.com/fatih/structtag v1.2.0 // indirect diff --git a/go.sum b/go.sum index 58f9e777a774..524549f6890b 100644 --- a/go.sum +++ b/go.sum @@ -61,6 +61,8 @@ github.com/OpenPeeDeeP/depguard/v2 v2.2.1 h1:vckeWVESWp6Qog7UZSARNqfu/cZqvki8zsu github.com/OpenPeeDeeP/depguard/v2 v2.2.1/go.mod h1:q4DKzC4UcVaAvcfd41CZh0PWpGgzrVxUYBlgKNGquUo= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= +github.com/alecthomas/chroma/v2 v2.15.0 h1:LxXTQHFoYrstG2nnV9y2X5O94sOBzf0CIUpSTbpxvMc= +github.com/alecthomas/chroma/v2 v2.15.0/go.mod h1:gUhVLrPDXPtp/f+L1jo9xepo9gL4eLwRuGAunSZMkio= github.com/alecthomas/go-check-sumtype v0.3.1 h1:u9aUvbGINJxLVXiFvHUlPEaD7VDULsrxJb4Aq31NLkU= github.com/alecthomas/go-check-sumtype v0.3.1/go.mod h1:A8TSiN3UPRw3laIgWEUOHHLPa6/r9MtoigdlP5h3K/E= github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= @@ -148,8 +150,8 @@ 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.5.0 h1:SRdnP5ZKvcO9KKRP1KJrhFR3RrlGuD+42t4429eC9k8= github.com/denis-tingaikin/go-header v0.5.0/go.mod h1:mMenU5bWrok6Wl2UsZjy+1okegmwQ3UgWl4V1D8gjlY= -github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= -github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo= +github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/ebitengine/purego v0.8.2 h1:jPPGWs2sZ1UgOSgD2bClL0MJIqu58nOmIcBuXr62z1I= github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= diff --git a/pkg/commands/fmt.go b/pkg/commands/fmt.go index c6b10a62b652..502dcebdfe9c 100644 --- a/pkg/commands/fmt.go +++ b/pkg/commands/fmt.go @@ -20,8 +20,9 @@ import ( type fmtOptions struct { config.LoaderOptions - diff bool // Flag only. - stdin bool // Flag only. + diff bool // Flag only. + diffColored bool // Flag only. + stdin bool // Flag only. } type fmtCommand struct { @@ -70,6 +71,7 @@ func newFmtCommand(logger logutils.Log, info BuildInfo) *fmtCommand { setupFormattersFlagSet(c.viper, fs) fs.BoolVarP(&c.opts.diff, "diff", "d", false, color.GreenString("Display diffs instead of rewriting files")) + fs.BoolVar(&c.opts.diffColored, "diff-colored", false, color.GreenString("Display diffs instead of rewriting files (with colors)")) fs.BoolVar(&c.opts.stdin, "stdin", false, color.GreenString("Use standard input for piping source files")) c.cmd = fmtCmd @@ -102,7 +104,7 @@ func (c *fmtCommand) preRunE(_ *cobra.Command, _ []string) error { matcher := processors.NewGeneratedFileMatcher(c.cfg.Formatters.Exclusions.Generated) - opts, err := goformat.NewRunnerOptions(c.cfg, c.opts.diff, c.opts.stdin) + opts, err := goformat.NewRunnerOptions(c.cfg, c.opts.diff, c.opts.diffColored, c.opts.stdin) if err != nil { return fmt.Errorf("build walk options: %w", err) } diff --git a/pkg/goformat/runner.go b/pkg/goformat/runner.go index 3207f117d552..5e1a2a6b1075 100644 --- a/pkg/goformat/runner.go +++ b/pkg/goformat/runner.go @@ -12,6 +12,7 @@ import ( "regexp" "strings" + "github.com/alecthomas/chroma/v2/quick" rpdiff "github.com/rogpeppe/go-internal/diff" "github.com/golangci/golangci-lint/v2/pkg/config" @@ -128,9 +129,19 @@ func (c *Runner) process(path string, stdout io.Writer, in io.Reader) error { if c.opts.diff { newName := filepath.ToSlash(path) oldName := newName + ".orig" - _, err = stdout.Write(rpdiff.Diff(oldName, input, newName, output)) - if err != nil { - return err + + patch := rpdiff.Diff(oldName, input, newName, output) + + if c.opts.colors { + err = quick.Highlight(stdout, string(patch), "diff", "terminal", "native") + if err != nil { + return err + } + } else { + _, err = stdout.Write(patch) + if err != nil { + return err + } } c.exitCode = 1 @@ -168,10 +179,11 @@ type RunnerOptions struct { patterns []*regexp.Regexp generated string diff bool + colors bool stdin bool } -func NewRunnerOptions(cfg *config.Config, diff, stdin bool) (RunnerOptions, error) { +func NewRunnerOptions(cfg *config.Config, diff, diffColored, stdin bool) (RunnerOptions, error) { basePath, err := fsutils.GetBasePath(context.Background(), cfg.Run.RelativePathMode, cfg.GetConfigDir()) if err != nil { return RunnerOptions{}, fmt.Errorf("get base path: %w", err) @@ -180,7 +192,8 @@ func NewRunnerOptions(cfg *config.Config, diff, stdin bool) (RunnerOptions, erro opts := RunnerOptions{ basePath: basePath, generated: cfg.Formatters.Exclusions.Generated, - diff: diff, + diff: diff || diffColored, + colors: diffColored, stdin: stdin, } From fe1e49e27eb6c80e838661deb317613de7116af7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Apr 2025 02:58:04 +0200 Subject: [PATCH 026/152] build(deps): bump github.com/tomarrell/wrapcheck/v2 from 2.10.0 to 2.11.0 (#5656) Co-authored-by: Fernandez Ludovic --- .golangci.next.reference.yml | 3 +++ go.mod | 2 +- go.sum | 4 ++-- jsonschema/golangci.next.jsonschema.json | 5 +++++ pkg/config/linters_settings.go | 1 + pkg/golinters/wrapcheck/wrapcheck.go | 2 ++ 6 files changed, 14 insertions(+), 3 deletions(-) diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index 747ffa58cb3d..f42a6de9b348 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -3755,6 +3755,9 @@ linters: # Default: [] ignore-interface-regexps: - ^(?i)c(?-i)ach(ing|e) + # Determines whether wrapcheck should report errors returned from inside the package. + # Default: false + report-internal-errors: true wsl: # Do strict checking when assigning from append (x = append(x, y)). diff --git a/go.mod b/go.mod index 403f4796e4eb..686b9927f018 100644 --- a/go.mod +++ b/go.mod @@ -112,7 +112,7 @@ require ( github.com/tetafro/godot v1.5.0 github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67 github.com/timonwong/loggercheck v0.10.1 - github.com/tomarrell/wrapcheck/v2 v2.10.0 + github.com/tomarrell/wrapcheck/v2 v2.11.0 github.com/tommy-muehle/go-mnd/v2 v2.5.1 github.com/ultraware/funlen v0.2.0 github.com/ultraware/whitespace v0.2.0 diff --git a/go.sum b/go.sum index 524549f6890b..dc2da5042e52 100644 --- a/go.sum +++ b/go.sum @@ -585,8 +585,8 @@ github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFA 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.10.0 h1:SzRCryzy4IrAH7bVGG4cK40tNUhmVmMDuJujy4XwYDg= -github.com/tomarrell/wrapcheck/v2 v2.10.0/go.mod h1:g9vNIyhb5/9TQgumxQyOEqDHsmGYcGsVMOx/xGkqdMo= +github.com/tomarrell/wrapcheck/v2 v2.11.0 h1:BJSt36snX9+4WTIXeJ7nvHBQBcm1h2SjQMSlmQ6aFSU= +github.com/tomarrell/wrapcheck/v2 v2.11.0/go.mod h1:wFL9pDWDAbXhhPZZt+nG8Fu+h29TtnZ2MW6Lx4BRXIU= 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.2.0 h1:gCHmCn+d2/1SemTdYMiKLAHFYxTYz7z9VIDRaTGyLkI= diff --git a/jsonschema/golangci.next.jsonschema.json b/jsonschema/golangci.next.jsonschema.json index 48d68df53cad..dedbf8676bb2 100644 --- a/jsonschema/golangci.next.jsonschema.json +++ b/jsonschema/golangci.next.jsonschema.json @@ -3922,6 +3922,11 @@ "items": { "type": "string" } + }, + "report-internal-errors": { + "description": "Determines whether wrapcheck should report errors returned from inside the package.", + "type": "boolean", + "default": false } } }, diff --git a/pkg/config/linters_settings.go b/pkg/config/linters_settings.go index 86ee4fea48d2..45109fe4b088 100644 --- a/pkg/config/linters_settings.go +++ b/pkg/config/linters_settings.go @@ -965,6 +965,7 @@ type WrapcheckSettings struct { IgnoreSigRegexps []string `mapstructure:"ignore-sig-regexps"` IgnorePackageGlobs []string `mapstructure:"ignore-package-globs"` IgnoreInterfaceRegexps []string `mapstructure:"ignore-interface-regexps"` + ReportInternalErrors bool `mapstructure:"report-internal-errors"` } type WSLSettings struct { diff --git a/pkg/golinters/wrapcheck/wrapcheck.go b/pkg/golinters/wrapcheck/wrapcheck.go index 8918a82eaf1a..8a4427f7d368 100644 --- a/pkg/golinters/wrapcheck/wrapcheck.go +++ b/pkg/golinters/wrapcheck/wrapcheck.go @@ -10,8 +10,10 @@ import ( func New(settings *config.WrapcheckSettings) *goanalysis.Linter { cfg := wrapcheck.NewDefaultConfig() + if settings != nil { cfg.ExtraIgnoreSigs = settings.ExtraIgnoreSigs + cfg.ReportInternalErrors = settings.ReportInternalErrors if len(settings.IgnoreSigs) != 0 { cfg.IgnoreSigs = settings.IgnoreSigs From ed7e596a16a405504c1dcb9737e885bdd07ecacd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Apr 2025 02:58:38 +0200 Subject: [PATCH 027/152] build(deps): bump github.com/kunwardeep/paralleltest from 1.0.13 to 1.0.14 (#5657) Co-authored-by: Fernandez Ludovic --- go.mod | 2 +- go.sum | 4 +-- .../paralleltest/testdata/paralleltest_cgo.go | 25 ------------------- ..._custom.go => paralleltest_custom_test.go} | 2 +- ...ustom.yml => paralleltest_custom_test.yml} | 0 .../{paralleltest.go => paralleltest_test.go} | 0 6 files changed, 4 insertions(+), 29 deletions(-) delete mode 100644 pkg/golinters/paralleltest/testdata/paralleltest_cgo.go rename pkg/golinters/paralleltest/testdata/{paralleltest_custom.go => paralleltest_custom_test.go} (86%) rename pkg/golinters/paralleltest/testdata/{paralleltest_custom.yml => paralleltest_custom_test.yml} (100%) rename pkg/golinters/paralleltest/testdata/{paralleltest.go => paralleltest_test.go} (100%) diff --git a/go.mod b/go.mod index 686b9927f018..cd5a3d641e29 100644 --- a/go.mod +++ b/go.mod @@ -65,7 +65,7 @@ require ( github.com/kisielk/errcheck v1.9.0 github.com/kkHAIKE/contextcheck v1.1.6 github.com/kulti/thelper v0.6.3 - github.com/kunwardeep/paralleltest v1.0.13 + github.com/kunwardeep/paralleltest v1.0.14 github.com/lasiar/canonicalheader v1.1.2 github.com/ldez/exptostd v0.4.2 github.com/ldez/gomoddirectives v0.6.1 diff --git a/go.sum b/go.sum index dc2da5042e52..6ce2de71bbd2 100644 --- a/go.sum +++ b/go.sum @@ -367,8 +367,8 @@ 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.13 h1:fxM9P2K5Xmsh+mey0N+Z3DvqAHnOtOAmQoW1mV0OND8= -github.com/kunwardeep/paralleltest v1.0.13/go.mod h1:di4moFqtfz3ToSKxhNjhOZL+696QtJGCFe132CbBLGk= +github.com/kunwardeep/paralleltest v1.0.14 h1:wAkMoMeGX/kGfhQBPODT/BL8XhK23ol/nuQ3SwFaUw8= +github.com/kunwardeep/paralleltest v1.0.14/go.mod h1:di4moFqtfz3ToSKxhNjhOZL+696QtJGCFe132CbBLGk= github.com/lasiar/canonicalheader v1.1.2 h1:vZ5uqwvDbyJCnMhmFYimgMZnJMjwljN5VGY0VKbMXb4= github.com/lasiar/canonicalheader v1.1.2/go.mod h1:qJCeLFS0G/QlLQ506T+Fk/fWMa2VmBUiEI2cuMK4djI= github.com/ldez/exptostd v0.4.2 h1:l5pOzHBz8mFOlbcifTxzfyYbgEmoUqjxLFHZkjlbHXs= diff --git a/pkg/golinters/paralleltest/testdata/paralleltest_cgo.go b/pkg/golinters/paralleltest/testdata/paralleltest_cgo.go deleted file mode 100644 index e961d17bf042..000000000000 --- a/pkg/golinters/paralleltest/testdata/paralleltest_cgo.go +++ /dev/null @@ -1,25 +0,0 @@ -//golangcitest:args -Eparalleltest -package testdata - -/* - #include - #include - - void myprint(char* s) { - printf("%d\n", s); - } -*/ -import "C" - -import ( - "testing" - "unsafe" -) - -func _() { - cs := C.CString("Hello from stdio\n") - C.myprint(cs) - C.free(unsafe.Pointer(cs)) -} - -func TestFunctionMissingCallToParallel(t *testing.T) {} // want "Function TestFunctionMissingCallToParallel missing the call to method parallel" diff --git a/pkg/golinters/paralleltest/testdata/paralleltest_custom.go b/pkg/golinters/paralleltest/testdata/paralleltest_custom_test.go similarity index 86% rename from pkg/golinters/paralleltest/testdata/paralleltest_custom.go rename to pkg/golinters/paralleltest/testdata/paralleltest_custom_test.go index c03b0996e70f..efd68f14241e 100644 --- a/pkg/golinters/paralleltest/testdata/paralleltest_custom.go +++ b/pkg/golinters/paralleltest/testdata/paralleltest_custom_test.go @@ -1,5 +1,5 @@ //golangcitest:args -Eparalleltest -//golangcitest:config_path testdata/paralleltest_custom.yml +//golangcitest:config_path testdata/paralleltest_custom_test.yml //golangcitest:expected_exitcode 0 package testdata diff --git a/pkg/golinters/paralleltest/testdata/paralleltest_custom.yml b/pkg/golinters/paralleltest/testdata/paralleltest_custom_test.yml similarity index 100% rename from pkg/golinters/paralleltest/testdata/paralleltest_custom.yml rename to pkg/golinters/paralleltest/testdata/paralleltest_custom_test.yml diff --git a/pkg/golinters/paralleltest/testdata/paralleltest.go b/pkg/golinters/paralleltest/testdata/paralleltest_test.go similarity index 100% rename from pkg/golinters/paralleltest/testdata/paralleltest.go rename to pkg/golinters/paralleltest/testdata/paralleltest_test.go From 30318270c6fbb603c6a9b8655fbea44f1e16f7e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Apr 2025 03:00:45 +0200 Subject: [PATCH 028/152] build(deps): bump github.com/mgechev/revive from 1.7.0 to 1.8.0 (#5663) Co-authored-by: Fernandez Ludovic --- .golangci.next.reference.yml | 60 ++++++++++++++++++------------------ go.mod | 4 +-- go.sum | 8 ++--- 3 files changed, 36 insertions(+), 36 deletions(-) diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index f42a6de9b348..144550b4b25d 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -2172,10 +2172,10 @@ linters: disabled: false exclude: [""] arguments: - - maxLitCount: "3" - allowStrs: '""' - allowInts: "0,1,2" - allowFloats: "0.0,0.,1.0,1.,2.0,2." + - max-lit-count: "3" + allow-strs: '""' + allow-ints: "0,1,2" + allow-floats: "0.0,0.,1.0,1.,2.0,2." # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#argument-limit - name: argument-limit severity: warning @@ -2254,7 +2254,7 @@ linters: disabled: false exclude: [""] arguments: - - allowTypesBefore: "*testing.T,*github.com/user/repo/testing.Harness" + - allow-types-before: "*testing.T,*github.com/user/repo/testing.Harness" # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#context-keys-type - name: context-keys-type severity: warning @@ -2294,7 +2294,7 @@ linters: disabled: false exclude: [""] arguments: - - allowedPackages: ["github.com/onsi/ginkgo/v2", "github.com/onsi/gomega"] + - allowed-packages: ["github.com/onsi/ginkgo/v2", "github.com/onsi/gomega"] # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#duplicated-imports - name: duplicated-imports severity: warning @@ -2306,8 +2306,8 @@ linters: disabled: false exclude: [""] arguments: - - "preserveScope" - - "allowJump" + - "preserve-scope" + - "allow-jump" # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#empty-block - name: empty-block severity: warning @@ -2333,8 +2333,8 @@ linters: arguments: - "short" # Or this parameter: - - funcArgStyle: "full" - funcRetValStyle: "short" + - func-arg-style: "full" + func-ret-val-style: "short" # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#enforce-slice-style - name: enforce-slice-style severity: warning @@ -2370,15 +2370,15 @@ linters: disabled: false exclude: [""] arguments: - - "checkPrivateReceivers" - - "disableStutteringCheck" - - "sayRepetitiveInsteadOfStutters" - - "checkPublicInterface" - - "disableChecksOnConstants" - - "disableChecksOnFunctions" - - "disableChecksOnMethods" - - "disableChecksOnTypes" - - "disableChecksOnVariables" + - "check-private-receivers" + - "disable-stuttering-check" + - "say-repetitive-instead-of-stutters" + - "check-public-interface" + - "disable-checks-on-constants" + - "disable-checks-on-functions" + - "disable-checks-on-methods" + - "disable-checks-on-types" + - "disable-checks-on-variables" # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#file-header - name: file-header severity: warning @@ -2393,8 +2393,8 @@ linters: exclude: [""] arguments: - max: 100 - skipComments: true - skipBlankLines: true + skip-comments: true + skip-blank-lines: true # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#filename-format - name: filename-format severity: warning @@ -2442,8 +2442,8 @@ linters: arguments: - "^[a-z][a-z0-9]{0,}$" # Or this parameter: - - allowRegex: "^[a-z][a-z0-9]{0,}$" - denyRegex: '^v\d+$' + - allow-regex: "^[a-z][a-z0-9]{0,}$" + deny-regex: '^v\d+$' # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#import-shadowing - name: import-shadowing severity: warning @@ -2468,7 +2468,7 @@ linters: disabled: false exclude: [""] arguments: - - "preserveScope" + - "preserve-scope" # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#line-length-limit - name: line-length-limit severity: warning @@ -2533,7 +2533,7 @@ linters: disabled: false exclude: [""] arguments: - - maxLength: 2 + - max-length: 2 # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#redefines-builtin-id - name: redefines-builtin-id severity: warning @@ -2583,7 +2583,7 @@ linters: disabled: false exclude: [""] arguments: - - "preserveScope" + - "preserve-scope" # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#time-equal - name: time-equal severity: warning @@ -2600,7 +2600,7 @@ linters: disabled: false exclude: [""] arguments: - - acceptIgnoredAssertionResult: true + - accept-ignored-assertion-result: true # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#unconditional-recursion - name: unconditional-recursion severity: warning @@ -2640,14 +2640,14 @@ linters: disabled: false exclude: [""] arguments: - - allowRegex: "^_" + - allow-regex: "^_" # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#unused-receiver - name: unused-receiver severity: warning disabled: false exclude: [""] arguments: - - allowRegex: "^_" + - allow-regex: "^_" # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#use-any - name: use-any severity: warning @@ -2676,7 +2676,7 @@ linters: arguments: - [ "ID" ] # AllowList - [ "VM" ] # DenyList - - - upperCaseConst: true # Extra parameter (upperCaseConst|skipPackageNameChecks) + - - upper-case-const: true # Extra parameter (upper-case-const|skip-package-name-checks) # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#waitgroup-by-value - name: waitgroup-by-value severity: warning diff --git a/go.mod b/go.mod index cd5a3d641e29..131f84276e0b 100644 --- a/go.mod +++ b/go.mod @@ -78,7 +78,7 @@ require ( github.com/maratori/testpackage v1.1.1 github.com/matoous/godox v1.1.0 github.com/mattn/go-colorable v0.1.14 - github.com/mgechev/revive v1.7.0 + github.com/mgechev/revive v1.8.0 github.com/mitchellh/go-homedir v1.1.0 github.com/moricho/tparallel v0.3.2 github.com/nakabonne/nestif v0.3.1 @@ -193,7 +193,7 @@ require ( github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect github.com/rivo/uniseg v0.4.7 // indirect - github.com/spf13/afero v1.12.0 // indirect + github.com/spf13/afero v1.14.0 // indirect github.com/spf13/cast v1.5.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/stretchr/objx v0.5.2 // indirect diff --git a/go.sum b/go.sum index 6ce2de71bbd2..95c07121a923 100644 --- a/go.sum +++ b/go.sum @@ -408,8 +408,8 @@ github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6T github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= 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/mgechev/revive v1.7.0 h1:JyeQ4yO5K8aZhIKf5rec56u0376h8AlKNQEmjfkjKlY= -github.com/mgechev/revive v1.7.0/go.mod h1:qZnwcNhoguE58dfi96IJeSTPeZQejNeoMQLUZGi4SW4= +github.com/mgechev/revive v1.8.0 h1:GRtZfbR+USnEs9kiTgokw0LKEQfPPM3EJpu/88IcXl4= +github.com/mgechev/revive v1.8.0/go.mod h1:AEte1jB8fAHGObV1BshB7WSfp3x/WZwAu/xNiClBK2Y= 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/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -534,8 +534,8 @@ github.com/sonatard/noctx v0.1.0 h1:JjqOc2WN16ISWAjAk8M5ej0RfExEXtkEyExl2hLW+OM= github.com/sonatard/noctx v0.1.0/go.mod h1:0RvBxqY8D4j9cTTTWE8ylt2vqj2EPI8fHmrxHdsaZ2c= 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.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= -github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= +github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= +github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo= 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.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= From 835bf75c67768b08e0e47d563454288e217e87cb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Apr 2025 03:04:11 +0200 Subject: [PATCH 029/152] build(deps): bump github.com/polyfloyd/go-errorlint from 1.7.1 to 1.8.0 (#5686) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 131f84276e0b..362c61861eed 100644 --- a/go.mod +++ b/go.mod @@ -86,7 +86,7 @@ require ( github.com/nishanths/predeclared v0.2.2 github.com/nunnatsa/ginkgolinter v0.19.1 github.com/pelletier/go-toml/v2 v2.2.3 - github.com/polyfloyd/go-errorlint v1.7.1 + github.com/polyfloyd/go-errorlint v1.8.0 github.com/quasilyte/go-ruleguard/dsl v0.3.22 github.com/raeperd/recvcheck v0.2.0 github.com/rogpeppe/go-internal v1.14.1 diff --git a/go.sum b/go.sum index 95c07121a923..68b4c3401cc7 100644 --- a/go.sum +++ b/go.sum @@ -456,8 +456,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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.7.1 h1:RyLVXIbosq1gBdk/pChWA8zWYLsq9UEw7a1L5TVMCnA= -github.com/polyfloyd/go-errorlint v1.7.1/go.mod h1:aXjNb1x2TNhoLsk26iv1yl7a+zTnXPhwEMtEXukiLR8= +github.com/polyfloyd/go-errorlint v1.8.0 h1:DL4RestQqRLr8U4LygLw8g2DX6RN1eBJOpa2mzsrl1Q= +github.com/polyfloyd/go-errorlint v1.8.0/go.mod h1:G2W0Q5roxbLCt0ZQbdoxQxXktTjwNyDbEaj3n7jvl4s= 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= From 045099586be0dc948b24938426531f93113d99ff Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Fri, 4 Apr 2025 03:30:04 +0200 Subject: [PATCH 030/152] feat: add warn-unused option for fmt command (#5668) --- .golangci.next.reference.yml | 3 +++ jsonschema/golangci.next.jsonschema.json | 4 ++++ pkg/config/formatters.go | 5 +++-- pkg/goformat/runner.go | 25 +++++++++++++++++++----- pkg/result/processors/exclusion_paths.go | 4 ++-- 5 files changed, 32 insertions(+), 9 deletions(-) diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index 144550b4b25d..5870d1aef573 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -4022,6 +4022,9 @@ formatters: chain-split-dots: false exclusions: + # Log a warning if an exclusion path is unused. + # Default: false + warn-unused: true # Mode of the generated files analysis. # # - `strict`: sources are excluded by strictly following the Go generated file convention. diff --git a/jsonschema/golangci.next.jsonschema.json b/jsonschema/golangci.next.jsonschema.json index dedbf8676bb2..d561849627fd 100644 --- a/jsonschema/golangci.next.jsonschema.json +++ b/jsonschema/golangci.next.jsonschema.json @@ -4634,6 +4634,10 @@ "items": { "type": "string" } + }, + "warn-unused": { + "type": "boolean", + "default": false } } } diff --git a/pkg/config/formatters.go b/pkg/config/formatters.go index 145ea861ab42..e1723ac101fd 100644 --- a/pkg/config/formatters.go +++ b/pkg/config/formatters.go @@ -22,6 +22,7 @@ func (f *Formatters) Validate() error { } type FormatterExclusions struct { - Generated string `mapstructure:"generated"` - Paths []string `mapstructure:"paths"` + Generated string `mapstructure:"generated"` + Paths []string `mapstructure:"paths"` + WarnUnused bool `mapstructure:"warn-unused"` } diff --git a/pkg/goformat/runner.go b/pkg/goformat/runner.go index 5e1a2a6b1075..fa1d1acc3019 100644 --- a/pkg/goformat/runner.go +++ b/pkg/goformat/runner.go @@ -67,6 +67,14 @@ func (c *Runner) Run(paths []string) error { } } + for pattern, count := range c.opts.excludedPathCounter { + if c.opts.warnUnused && count == 0 { + c.log.Warnf("The pattern %q match no issues", pattern) + } else { + c.log.Infof("Skipped %d issues by pattern %q", count, pattern) + } + } + return nil } @@ -181,6 +189,9 @@ type RunnerOptions struct { diff bool colors bool stdin bool + + warnUnused bool + excludedPathCounter map[*regexp.Regexp]int } func NewRunnerOptions(cfg *config.Config, diff, diffColored, stdin bool) (RunnerOptions, error) { @@ -190,11 +201,13 @@ func NewRunnerOptions(cfg *config.Config, diff, diffColored, stdin bool) (Runner } opts := RunnerOptions{ - basePath: basePath, - generated: cfg.Formatters.Exclusions.Generated, - diff: diff || diffColored, - colors: diffColored, - stdin: stdin, + basePath: basePath, + generated: cfg.Formatters.Exclusions.Generated, + diff: diff || diffColored, + colors: diffColored, + stdin: stdin, + excludedPathCounter: make(map[*regexp.Regexp]int), + warnUnused: cfg.Formatters.Exclusions.WarnUnused, } for _, pattern := range cfg.Formatters.Exclusions.Paths { @@ -204,6 +217,7 @@ func NewRunnerOptions(cfg *config.Config, diff, diffColored, stdin bool) (Runner } opts.patterns = append(opts.patterns, exp) + opts.excludedPathCounter[exp] = 0 } return opts, nil @@ -221,6 +235,7 @@ func (o RunnerOptions) MatchAnyPattern(path string) (bool, error) { for _, pattern := range o.patterns { if pattern.MatchString(rel) { + o.excludedPathCounter[pattern]++ return true, nil } } diff --git a/pkg/result/processors/exclusion_paths.go b/pkg/result/processors/exclusion_paths.go index dafad44d1d3b..104c33eefa5b 100644 --- a/pkg/result/processors/exclusion_paths.go +++ b/pkg/result/processors/exclusion_paths.go @@ -79,7 +79,7 @@ func (p *ExclusionPaths) Process(issues []result.Issue) ([]result.Issue, error) func (p *ExclusionPaths) Finish() { for pattern, count := range p.excludedPathCounter { if p.warnUnused && count == 0 { - p.log.Warnf("The pattern %q match %d issues", pattern, count) + p.log.Warnf("The pattern %q match no issues", pattern) } else { p.log.Infof("Skipped %d issues by pattern %q", count, pattern) } @@ -87,7 +87,7 @@ func (p *ExclusionPaths) Finish() { for pattern, count := range p.excludedPathExceptCounter { if p.warnUnused && count == 0 { - p.log.Warnf("The pattern %q match %d issues", pattern, count) + p.log.Warnf("The pattern %q match no issues", pattern) } } } From 38d2facb815a96a528410f98f472ef623479f7e2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Apr 2025 03:39:24 +0200 Subject: [PATCH 031/152] build(deps): bump github.com/firefart/nonamedreturns from 1.0.5 to 1.0.6 (#5687) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 362c61861eed..cf99f0988673 100644 --- a/go.mod +++ b/go.mod @@ -38,7 +38,7 @@ require ( github.com/daixiang0/gci v0.13.6 github.com/denis-tingaikin/go-header v0.5.0 github.com/fatih/color v1.18.0 - github.com/firefart/nonamedreturns v1.0.5 + github.com/firefart/nonamedreturns v1.0.6 github.com/fzipp/gocyclo v0.6.0 github.com/ghostiam/protogetter v0.3.13 github.com/go-critic/go-critic v0.13.0 diff --git a/go.sum b/go.sum index 68b4c3401cc7..32262f617180 100644 --- a/go.sum +++ b/go.sum @@ -164,8 +164,8 @@ github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= 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.5 h1:tM+Me2ZaXs8tfdDw3X6DOX++wMCOqzYUho6tUTYIdRA= -github.com/firefart/nonamedreturns v1.0.5/go.mod h1:gHJjDqhGM4WyPt639SOZs+G89Ko7QKH5R5BhnO6xJhw= +github.com/firefart/nonamedreturns v1.0.6 h1:vmiBcKV/3EqKY3ZiPxCINmpS431OcE1S47AQUwhrg8E= +github.com/firefart/nonamedreturns v1.0.6/go.mod h1:R8NisJnSIpvPWheCq0mNRXJok6D8h7fagJTF8EMEwCo= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= From ab604ca7d6f28f011ce00d48c3905c8aebd76dd0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Apr 2025 03:51:19 +0200 Subject: [PATCH 032/152] build(deps): bump github.com/bombsimon/wsl/v4 from 4.6.0 to 4.7.0 (#5689) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index cf99f0988673..0656657dd5cf 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( github.com/ashanbrown/makezero v1.2.0 github.com/bkielbasa/cyclop v1.2.3 github.com/blizzy78/varnamelen v0.8.0 - github.com/bombsimon/wsl/v4 v4.6.0 + github.com/bombsimon/wsl/v4 v4.7.0 github.com/breml/bidichk v0.3.3 github.com/breml/errchkjson v0.4.1 github.com/butuzov/ireturn v0.3.1 diff --git a/go.sum b/go.sum index 32262f617180..2d0ebf4e5dad 100644 --- a/go.sum +++ b/go.sum @@ -96,8 +96,8 @@ github.com/bkielbasa/cyclop v1.2.3 h1:faIVMIGDIANuGPWH031CZJTi2ymOQBULs9H21HSMa5 github.com/bkielbasa/cyclop v1.2.3/go.mod h1:kHTwA9Q0uZqOADdupvcFJQtp/ksSnytRMe8ztxG8Fuo= github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ089M= github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= -github.com/bombsimon/wsl/v4 v4.6.0 h1:ew2R/N42su553DKTYqt3HSxaQN+uHQPv4xZ2MBmwaW4= -github.com/bombsimon/wsl/v4 v4.6.0/go.mod h1:uV/+6BkffuzSAVYD+yGyld1AChO7/EuLrCF/8xTiapg= +github.com/bombsimon/wsl/v4 v4.7.0 h1:1Ilm9JBPRczjyUs6hvOPKvd7VL1Q++PL8M0SXBDf+jQ= +github.com/bombsimon/wsl/v4 v4.7.0/go.mod h1:uV/+6BkffuzSAVYD+yGyld1AChO7/EuLrCF/8xTiapg= github.com/breml/bidichk v0.3.3 h1:WSM67ztRusf1sMoqH6/c4OBCUlRVTKq+CbSeo0R17sE= github.com/breml/bidichk v0.3.3/go.mod h1:ISbsut8OnjB367j5NseXEGGgO/th206dVa427kR8YTE= github.com/breml/errchkjson v0.4.1 h1:keFSS8D7A2T0haP9kzZTi7o26r7kE3vymjZNeNDRDwg= From d1f1519139d6fbac7f6e6c38b412cee6cab3c83f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Apr 2025 03:51:34 +0200 Subject: [PATCH 033/152] build(deps): bump github.com/alecthomas/chroma/v2 from 2.15.0 to 2.16.0 (#5690) --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 0656657dd5cf..65dd9a8f5b18 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1 github.com/OpenPeeDeeP/depguard/v2 v2.2.1 - github.com/alecthomas/chroma/v2 v2.15.0 + github.com/alecthomas/chroma/v2 v2.16.0 github.com/alecthomas/go-check-sumtype v0.3.1 github.com/alexkohler/nakedret/v2 v2.0.6 github.com/alexkohler/prealloc v1.0.0 @@ -149,7 +149,7 @@ require ( github.com/chavacava/garif v0.1.0 // indirect github.com/dave/dst v0.27.3 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/dlclark/regexp2 v1.11.4 // indirect + github.com/dlclark/regexp2 v1.11.5 // indirect github.com/ebitengine/purego v0.8.2 // indirect github.com/ettle/strcase v0.2.0 // indirect github.com/fatih/structtag v1.2.0 // indirect diff --git a/go.sum b/go.sum index 2d0ebf4e5dad..80c50fb083d6 100644 --- a/go.sum +++ b/go.sum @@ -61,8 +61,8 @@ github.com/OpenPeeDeeP/depguard/v2 v2.2.1 h1:vckeWVESWp6Qog7UZSARNqfu/cZqvki8zsu github.com/OpenPeeDeeP/depguard/v2 v2.2.1/go.mod h1:q4DKzC4UcVaAvcfd41CZh0PWpGgzrVxUYBlgKNGquUo= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= -github.com/alecthomas/chroma/v2 v2.15.0 h1:LxXTQHFoYrstG2nnV9y2X5O94sOBzf0CIUpSTbpxvMc= -github.com/alecthomas/chroma/v2 v2.15.0/go.mod h1:gUhVLrPDXPtp/f+L1jo9xepo9gL4eLwRuGAunSZMkio= +github.com/alecthomas/chroma/v2 v2.16.0 h1:QC5ZMizk67+HzxFDjQ4ASjni5kWBTGiigRG1u23IGvA= +github.com/alecthomas/chroma/v2 v2.16.0/go.mod h1:RVX6AvYm4VfYe/zsk7mjHueLDZor3aWCNE14TFlepBk= github.com/alecthomas/go-check-sumtype v0.3.1 h1:u9aUvbGINJxLVXiFvHUlPEaD7VDULsrxJb4Aq31NLkU= github.com/alecthomas/go-check-sumtype v0.3.1/go.mod h1:A8TSiN3UPRw3laIgWEUOHHLPa6/r9MtoigdlP5h3K/E= github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= @@ -150,8 +150,8 @@ 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.5.0 h1:SRdnP5ZKvcO9KKRP1KJrhFR3RrlGuD+42t4429eC9k8= github.com/denis-tingaikin/go-header v0.5.0/go.mod h1:mMenU5bWrok6Wl2UsZjy+1okegmwQ3UgWl4V1D8gjlY= -github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo= -github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ= +github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/ebitengine/purego v0.8.2 h1:jPPGWs2sZ1UgOSgD2bClL0MJIqu58nOmIcBuXr62z1I= github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= From 427b310bee70e306eba0bcea75b54332987bc1be Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Apr 2025 03:52:11 +0200 Subject: [PATCH 034/152] build(deps): bump go-simpler.org/sloglint from 0.9.0 to 0.10.0 (#5688) Co-authored-by: Fernandez Ludovic --- .golangci.next.reference.yml | 7 ++++++- go.mod | 2 +- go.sum | 4 ++-- jsonschema/golangci.next.jsonschema.json | 5 +++++ pkg/config/linters_settings.go | 1 + pkg/golinters/sloglint/sloglint.go | 1 + 6 files changed, 16 insertions(+), 4 deletions(-) diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index 5870d1aef573..7b9b2a4c39ef 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -2722,11 +2722,16 @@ linters: # https://github.com/go-simpler/sloglint?tab=readme-ov-file#static-messages # Default: false static-msg: true + # Enforce message style. + # Values: lowercased, capitalized + # https://github.com/go-simpler/sloglint?tab=readme-ov-file#message-style + # Default: "" + msg-style: capitalized # Enforce using constants instead of raw keys. # https://github.com/go-simpler/sloglint?tab=readme-ov-file#no-raw-keys # Default: false no-raw-keys: true - # Enforce a single key naming convention. + # Enforce key naming convention. # Values: snake, kebab, camel, pascal # https://github.com/go-simpler/sloglint?tab=readme-ov-file#key-naming-convention # Default: "" diff --git a/go.mod b/go.mod index 65dd9a8f5b18..c08aa85e2e88 100644 --- a/go.mod +++ b/go.mod @@ -125,7 +125,7 @@ require ( github.com/ykadowak/zerologlint v0.1.5 gitlab.com/bosi/decorder v0.4.2 go-simpler.org/musttag v0.13.0 - go-simpler.org/sloglint v0.9.0 + go-simpler.org/sloglint v0.10.0 go.uber.org/automaxprocs v1.6.0 golang.org/x/mod v0.24.0 golang.org/x/sys v0.31.0 diff --git a/go.sum b/go.sum index 80c50fb083d6..80a6c032636e 100644 --- a/go.sum +++ b/go.sum @@ -626,8 +626,8 @@ go-simpler.org/assert v0.9.0 h1:PfpmcSvL7yAnWyChSjOz6Sp6m9j5lyK8Ok9pEL31YkQ= go-simpler.org/assert v0.9.0/go.mod h1:74Eqh5eI6vCK6Y5l3PI8ZYFXG4Sa+tkr70OIPJAUr28= go-simpler.org/musttag v0.13.0 h1:Q/YAW0AHvaoaIbsPj3bvEI5/QFP7w696IMUpnKXQfCE= go-simpler.org/musttag v0.13.0/go.mod h1:FTzIGeK6OkKlUDVpj0iQUXZLUO1Js9+mvykDQy9C5yM= -go-simpler.org/sloglint v0.9.0 h1:/40NQtjRx9txvsB/RN022KsUJU+zaaSb/9q9BSefSrE= -go-simpler.org/sloglint v0.9.0/go.mod h1:G/OrAF6uxj48sHahCzrbarVMptL2kjWTaUeC8+fOGww= +go-simpler.org/sloglint v0.10.0 h1:wrW6kIuFLDZ7rW0tKRmUX5uklauXNo5+HKwjwmeNVvg= +go-simpler.org/sloglint v0.10.0/go.mod h1:CFDO8R1i77dlciGfPEPvYke2ZMx4eyGiEIWkyeW2Pvw= 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= diff --git a/jsonschema/golangci.next.jsonschema.json b/jsonschema/golangci.next.jsonschema.json index d561849627fd..90b438dd0068 100644 --- a/jsonschema/golangci.next.jsonschema.json +++ b/jsonschema/golangci.next.jsonschema.json @@ -2962,6 +2962,11 @@ "type": "boolean", "default": false }, + "msg-style": { + "description": "Enforce message style.", + "enum": ["", "lowercased", "capitalized"], + "default": false + }, "key-naming-case": { "description": "Enforce a single key naming convention.", "enum": ["snake", "kebab", "camel", "pascal"] diff --git a/pkg/config/linters_settings.go b/pkg/config/linters_settings.go index 45109fe4b088..046645e40f98 100644 --- a/pkg/config/linters_settings.go +++ b/pkg/config/linters_settings.go @@ -784,6 +784,7 @@ type SlogLintSettings struct { NoGlobal string `mapstructure:"no-global"` Context string `mapstructure:"context"` StaticMsg bool `mapstructure:"static-msg"` + MsgStyle string `mapstructure:"msg-style"` NoRawKeys bool `mapstructure:"no-raw-keys"` KeyNamingCase string `mapstructure:"key-naming-case"` ForbiddenKeys []string `mapstructure:"forbidden-keys"` diff --git a/pkg/golinters/sloglint/sloglint.go b/pkg/golinters/sloglint/sloglint.go index 01e75e44ab48..021157dd66b7 100644 --- a/pkg/golinters/sloglint/sloglint.go +++ b/pkg/golinters/sloglint/sloglint.go @@ -18,6 +18,7 @@ func New(settings *config.SlogLintSettings) *goanalysis.Linter { NoGlobal: settings.NoGlobal, ContextOnly: settings.Context, StaticMsg: settings.StaticMsg, + MsgStyle: settings.MsgStyle, NoRawKeys: settings.NoRawKeys, KeyNamingCase: settings.KeyNamingCase, ForbiddenKeys: settings.ForbiddenKeys, From 61bbcc4ed4330b862bfdb1dc858c0e7190af1ed1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Apr 2025 04:06:29 +0200 Subject: [PATCH 035/152] build(deps): bump dependencies in the linter-testdata group (#5691) Co-authored-by: Fernandez Ludovic --- pkg/golinters/ginkgolinter/testdata/go.mod | 2 +- pkg/golinters/ginkgolinter/testdata/go.sum | 4 ++-- pkg/golinters/protogetter/testdata/go.mod | 8 ++++---- pkg/golinters/protogetter/testdata/go.sum | 12 ++++++------ pkg/golinters/spancheck/testdata/go.mod | 2 +- pkg/golinters/zerologlint/testdata/go.mod | 8 ++++---- pkg/golinters/zerologlint/testdata/go.sum | 13 +++++++------ 7 files changed, 25 insertions(+), 24 deletions(-) diff --git a/pkg/golinters/ginkgolinter/testdata/go.mod b/pkg/golinters/ginkgolinter/testdata/go.mod index 8c158398b857..b9c242a0ded4 100644 --- a/pkg/golinters/ginkgolinter/testdata/go.mod +++ b/pkg/golinters/ginkgolinter/testdata/go.mod @@ -4,7 +4,7 @@ go 1.23.0 require ( github.com/onsi/ginkgo/v2 v2.23.3 - github.com/onsi/gomega v1.36.3 + github.com/onsi/gomega v1.37.0 ) require ( diff --git a/pkg/golinters/ginkgolinter/testdata/go.sum b/pkg/golinters/ginkgolinter/testdata/go.sum index 572cf22bd836..4a6722c54bc5 100644 --- a/pkg/golinters/ginkgolinter/testdata/go.sum +++ b/pkg/golinters/ginkgolinter/testdata/go.sum @@ -10,8 +10,8 @@ github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/Z github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/onsi/ginkgo/v2 v2.23.3 h1:edHxnszytJ4lD9D5Jjc4tiDkPBZ3siDeJJkUZJJVkp0= github.com/onsi/ginkgo/v2 v2.23.3/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM= -github.com/onsi/gomega v1.36.3 h1:hID7cr8t3Wp26+cYnfcjR6HpJ00fdogN6dqZ1t6IylU= -github.com/onsi/gomega v1.36.3/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0= +github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y= +github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0= 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/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= diff --git a/pkg/golinters/protogetter/testdata/go.mod b/pkg/golinters/protogetter/testdata/go.mod index f3c8b01bdbc5..64d3739fe4e5 100644 --- a/pkg/golinters/protogetter/testdata/go.mod +++ b/pkg/golinters/protogetter/testdata/go.mod @@ -1,6 +1,6 @@ module protogetter -go 1.22.0 +go 1.23.0 require ( google.golang.org/grpc v1.71.1 @@ -8,8 +8,8 @@ require ( ) require ( - golang.org/x/net v0.34.0 // indirect - golang.org/x/sys v0.29.0 // indirect - golang.org/x/text v0.21.0 // indirect + golang.org/x/net v0.38.0 // indirect + golang.org/x/sys v0.31.0 // indirect + golang.org/x/text v0.23.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect ) diff --git a/pkg/golinters/protogetter/testdata/go.sum b/pkg/golinters/protogetter/testdata/go.sum index 979d39513453..98076ebf7ddb 100644 --- a/pkg/golinters/protogetter/testdata/go.sum +++ b/pkg/golinters/protogetter/testdata/go.sum @@ -20,12 +20,12 @@ go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= -golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= -golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= -golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= -golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= +golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI= diff --git a/pkg/golinters/spancheck/testdata/go.mod b/pkg/golinters/spancheck/testdata/go.mod index 838836345136..df3444491ace 100644 --- a/pkg/golinters/spancheck/testdata/go.mod +++ b/pkg/golinters/spancheck/testdata/go.mod @@ -1,6 +1,6 @@ module spancheck -go 1.22.0 +go 1.23.0 require ( go.opentelemetry.io/otel v1.35.0 diff --git a/pkg/golinters/zerologlint/testdata/go.mod b/pkg/golinters/zerologlint/testdata/go.mod index 5d75bdc3f5f4..42508c71c705 100644 --- a/pkg/golinters/zerologlint/testdata/go.mod +++ b/pkg/golinters/zerologlint/testdata/go.mod @@ -1,11 +1,11 @@ module zerologlint -go 1.19 +go 1.23.0 -require github.com/rs/zerolog v1.33.0 +require github.com/rs/zerolog v1.34.0 require ( - github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - golang.org/x/sys v0.25.0 // indirect + golang.org/x/sys v0.31.0 // indirect ) diff --git a/pkg/golinters/zerologlint/testdata/go.sum b/pkg/golinters/zerologlint/testdata/go.sum index b52b48f18cd0..4c01b0c5ed90 100644 --- a/pkg/golinters/zerologlint/testdata/go.sum +++ b/pkg/golinters/zerologlint/testdata/go.sum @@ -1,17 +1,18 @@ 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.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 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/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= -github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= +github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= +github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= 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.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= From d22bf5d5add3791423157b9c94aa74de67397744 Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Fri, 4 Apr 2025 15:40:40 +1300 Subject: [PATCH 036/152] docs: add `redundant-test-main-exit` to `revive` rules (#5692) Co-authored-by: Fernandez Ludovic --- .golangci.next.reference.yml | 5 +++++ .golangci.reference.yml | 5 +++++ jsonschema/golangci.jsonschema.json | 1 + jsonschema/golangci.next.jsonschema.json | 1 + 4 files changed, 12 insertions(+) diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index 7b9b2a4c39ef..f5e908617715 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -2549,6 +2549,11 @@ linters: severity: warning disabled: false exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#redundant-test-main-exit + - name: redundant-test-main-exit + severity: warning + disabled: false + exclude: [""] # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#string-format - name: string-format severity: warning diff --git a/.golangci.reference.yml b/.golangci.reference.yml index 339fe9bcca52..446e06780a00 100644 --- a/.golangci.reference.yml +++ b/.golangci.reference.yml @@ -2546,6 +2546,11 @@ linters: severity: warning disabled: false exclude: [""] + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#redundant-test-main-exit + - name: redundant-test-main-exit + severity: warning + disabled: false + exclude: [""] # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#string-format - name: string-format severity: warning diff --git a/jsonschema/golangci.jsonschema.json b/jsonschema/golangci.jsonschema.json index e775096e315b..591551a7eade 100644 --- a/jsonschema/golangci.jsonschema.json +++ b/jsonschema/golangci.jsonschema.json @@ -632,6 +632,7 @@ "redefines-builtin-id", "redundant-build-tag", "redundant-import-alias", + "redundant-test-main-exit", "string-format", "string-of-int", "struct-tag", diff --git a/jsonschema/golangci.next.jsonschema.json b/jsonschema/golangci.next.jsonschema.json index 90b438dd0068..ff3eaf96cef8 100644 --- a/jsonschema/golangci.next.jsonschema.json +++ b/jsonschema/golangci.next.jsonschema.json @@ -632,6 +632,7 @@ "redefines-builtin-id", "redundant-build-tag", "redundant-import-alias", + "redundant-test-main-exit", "string-format", "string-of-int", "struct-tag", From df1b1bb8064cd61af00fda63edda117fcc76b6b2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Apr 2025 13:36:40 +0200 Subject: [PATCH 037/152] build(deps): bump github.com/alingse/nilnesserr from 0.1.2 to 0.2.0 (#5693) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c08aa85e2e88..9a99824781d4 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/alexkohler/nakedret/v2 v2.0.6 github.com/alexkohler/prealloc v1.0.0 github.com/alingse/asasalint v0.0.11 - github.com/alingse/nilnesserr v0.1.2 + github.com/alingse/nilnesserr v0.2.0 github.com/ashanbrown/forbidigo v1.6.0 github.com/ashanbrown/makezero v1.2.0 github.com/bkielbasa/cyclop v1.2.3 diff --git a/go.sum b/go.sum index 80a6c032636e..2b67984db937 100644 --- a/go.sum +++ b/go.sum @@ -78,8 +78,8 @@ github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pO 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/alingse/nilnesserr v0.1.2 h1:Yf8Iwm3z2hUUrP4muWfW83DF4nE3r1xZ26fGWUKCZlo= -github.com/alingse/nilnesserr v0.1.2/go.mod h1:1xJPrXonEtX7wyTq8Dytns5P2hNzoWymVUIaKm4HNFg= +github.com/alingse/nilnesserr v0.2.0 h1:raLem5KG7EFVb4UIDAXgrv3N2JIaffeKNtcEXkEWd/w= +github.com/alingse/nilnesserr v0.2.0/go.mod h1:1xJPrXonEtX7wyTq8Dytns5P2hNzoWymVUIaKm4HNFg= 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.2.0 h1:/2Lp1bypdmK9wDIq7uWBlDF1iMUpIIS4A+pF6C9IEUU= From 7eac7fabc2295dd289e980f5683852bfc385fda8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Apr 2025 14:24:48 +0200 Subject: [PATCH 038/152] build(deps): bump github.com/securego/gosec/v2 from 2.22.2 to 2.22.3 (#5694) Co-authored-by: Fernandez Ludovic --- .golangci.next.reference.yml | 2 -- go.mod | 4 ++-- go.sum | 16 ++++++++-------- jsonschema/golangci.next.jsonschema.json | 3 +-- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index f5e908617715..6245b6245ba0 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -1342,7 +1342,6 @@ linters: - 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 - G115 # Potential integer overflow when converting between integer types - G201 # SQL query construction using format string @@ -1387,7 +1386,6 @@ linters: - 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 - G115 # Potential integer overflow when converting between integer types - G201 # SQL query construction using format string diff --git a/go.mod b/go.mod index 9a99824781d4..c26cbf90b53d 100644 --- a/go.mod +++ b/go.mod @@ -96,7 +96,7 @@ require ( github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 github.com/sashamelentyev/interfacebloat v1.1.0 github.com/sashamelentyev/usestdlibvars v1.28.0 - github.com/securego/gosec/v2 v2.22.2 + github.com/securego/gosec/v2 v2.22.3 github.com/shirou/gopsutil/v4 v4.25.3 github.com/sirupsen/logrus v1.9.3 github.com/sivchari/containedctx v1.0.3 @@ -210,7 +210,7 @@ require ( golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect golang.org/x/sync v0.12.0 // indirect golang.org/x/text v0.23.0 // indirect - google.golang.org/protobuf v1.36.5 // indirect + google.golang.org/protobuf v1.36.6 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/go.sum b/go.sum index 2b67984db937..c7df923c9de6 100644 --- a/go.sum +++ b/go.sum @@ -435,10 +435,10 @@ github.com/nunnatsa/ginkgolinter v0.19.1 h1:mjwbOlDQxZi9Cal+KfbEJTCz327OLNfwNvoZ github.com/nunnatsa/ginkgolinter v0.19.1/go.mod h1:jkQ3naZDmxaZMXPWaS9rblH+i+GWXQCaS/JFIWcOH2s= 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.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU= -github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk= -github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= -github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= +github.com/onsi/ginkgo/v2 v2.23.3 h1:edHxnszytJ4lD9D5Jjc4tiDkPBZ3siDeJJkUZJJVkp0= +github.com/onsi/ginkgo/v2 v2.23.3/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM= +github.com/onsi/gomega v1.36.3 h1:hID7cr8t3Wp26+cYnfcjR6HpJ00fdogN6dqZ1t6IylU= +github.com/onsi/gomega v1.36.3/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0= 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= @@ -515,8 +515,8 @@ github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tM github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= github.com/sashamelentyev/usestdlibvars v1.28.0 h1:jZnudE2zKCtYlGzLVreNp5pmCdOxXUzwsMDBkR21cyQ= github.com/sashamelentyev/usestdlibvars v1.28.0/go.mod h1:9nl0jgOfHKWNFS43Ojw0i7aRoS4j6EBye3YBhmAIRF8= -github.com/securego/gosec/v2 v2.22.2 h1:IXbuI7cJninj0nRpZSLCUlotsj8jGusohfONMrHoF6g= -github.com/securego/gosec/v2 v2.22.2/go.mod h1:UEBGA+dSKb+VqM6TdehR7lnQtIIMorYJ4/9CW1KVQBE= +github.com/securego/gosec/v2 v2.22.3 h1:mRrCNmRF2NgZp4RJ8oJ6yPJ7G4x6OCiAXHd8x4trLRc= +github.com/securego/gosec/v2 v2.22.3/go.mod h1:42M9Xs0v1WseinaB/BmNGO8AVqG8vRfhC2686ACY48k= 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/shirou/gopsutil/v4 v4.25.3 h1:SeA68lsu8gLggyMbmCn8cmp97V1TI9ld9sVzAUcKcKE= @@ -983,8 +983,8 @@ 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.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= -google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= 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= diff --git a/jsonschema/golangci.next.jsonschema.json b/jsonschema/golangci.next.jsonschema.json index ff3eaf96cef8..814c7cfe9c8e 100644 --- a/jsonschema/golangci.next.jsonschema.json +++ b/jsonschema/golangci.next.jsonschema.json @@ -490,7 +490,6 @@ "G110", "G111", "G112", - "G113", "G114", "G115", "G201", @@ -2966,7 +2965,7 @@ "msg-style": { "description": "Enforce message style.", "enum": ["", "lowercased", "capitalized"], - "default": false + "default": "" }, "key-naming-case": { "description": "Enforce a single key naming convention.", From 65b3c073cac39bb9b7b580b2a148511f8fc84490 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Fri, 4 Apr 2025 17:02:18 +0200 Subject: [PATCH 039/152] fix: memory leaks when using go1.(N) with golangci-lint built with with go1.(N-1) (#5695) --- pkg/goanalysis/pkgerrors/errors.go | 2 +- pkg/goanalysis/runner_loadingpackage.go | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/pkg/goanalysis/pkgerrors/errors.go b/pkg/goanalysis/pkgerrors/errors.go index 05d2c5238f8b..587e72720e98 100644 --- a/pkg/goanalysis/pkgerrors/errors.go +++ b/pkg/goanalysis/pkgerrors/errors.go @@ -15,7 +15,7 @@ type IllTypedError struct { } func (e *IllTypedError) Error() string { - return fmt.Sprintf("errors in package: %v", e.Pkg.Errors) + return fmt.Sprintf("IllTypedError: errors in package: %v", e.Pkg.Errors) } func BuildIssuesFromIllTypedError(errs []error, lintCtx *linter.Context) ([]result.Issue, error) { diff --git a/pkg/goanalysis/runner_loadingpackage.go b/pkg/goanalysis/runner_loadingpackage.go index 0bf8f3fbb362..d22dbea30d72 100644 --- a/pkg/goanalysis/runner_loadingpackage.go +++ b/pkg/goanalysis/runner_loadingpackage.go @@ -24,6 +24,9 @@ import ( const unsafePkgName = "unsafe" +// https://github.com/golang/go/blob/go1.23.8/src/internal/types/errors/codes.go#L1484 +const tooNew = 151 + type loadingPackage struct { pkg *packages.Package imports map[string]*loadingPackage @@ -436,6 +439,14 @@ func (lp *loadingPackage) convertError(err error) []packages.Error { case types.Error: // from type checker + + // https://github.com/golang/go/blob/go1.23.8/src/go/types/api.go#L52-L57 + if int(reflect.ValueOf(err).FieldByName("go116code").Int()) == tooNew { + // https://github.com/golang/go/blob/go1.23.8/src/go/types/check.go#L380 + // https://github.com/golang/go/blob/go1.23.8/src/go/types/check.go#L349 + panic(err.Msg) + } + errs = append(errs, packages.Error{ Pos: err.Fset.Position(err.Pos).String(), Msg: err.Msg, From 756a7b550cfbdeababc9d1f6bafafe2d9c5e03af Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Apr 2025 18:56:14 +0200 Subject: [PATCH 040/152] build(deps): bump go-simpler.org/sloglint from 0.10.0 to 0.10.1 (#5696) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c26cbf90b53d..62afdbf29c08 100644 --- a/go.mod +++ b/go.mod @@ -125,7 +125,7 @@ require ( github.com/ykadowak/zerologlint v0.1.5 gitlab.com/bosi/decorder v0.4.2 go-simpler.org/musttag v0.13.0 - go-simpler.org/sloglint v0.10.0 + go-simpler.org/sloglint v0.10.1 go.uber.org/automaxprocs v1.6.0 golang.org/x/mod v0.24.0 golang.org/x/sys v0.31.0 diff --git a/go.sum b/go.sum index c7df923c9de6..41a925528d21 100644 --- a/go.sum +++ b/go.sum @@ -626,8 +626,8 @@ go-simpler.org/assert v0.9.0 h1:PfpmcSvL7yAnWyChSjOz6Sp6m9j5lyK8Ok9pEL31YkQ= go-simpler.org/assert v0.9.0/go.mod h1:74Eqh5eI6vCK6Y5l3PI8ZYFXG4Sa+tkr70OIPJAUr28= go-simpler.org/musttag v0.13.0 h1:Q/YAW0AHvaoaIbsPj3bvEI5/QFP7w696IMUpnKXQfCE= go-simpler.org/musttag v0.13.0/go.mod h1:FTzIGeK6OkKlUDVpj0iQUXZLUO1Js9+mvykDQy9C5yM= -go-simpler.org/sloglint v0.10.0 h1:wrW6kIuFLDZ7rW0tKRmUX5uklauXNo5+HKwjwmeNVvg= -go-simpler.org/sloglint v0.10.0/go.mod h1:CFDO8R1i77dlciGfPEPvYke2ZMx4eyGiEIWkyeW2Pvw= +go-simpler.org/sloglint v0.10.1 h1:gYHgZdbPzRa9/RQ8zYQLnHfmgWivCpNK2MAwnrhnKdA= +go-simpler.org/sloglint v0.10.1/go.mod h1:CFDO8R1i77dlciGfPEPvYke2ZMx4eyGiEIWkyeW2Pvw= 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= From ace25c9962003f2c32ba0050ea1f82c29018e92a Mon Sep 17 00:00:00 2001 From: Tatsuya Kyushima <49891479+kyu08@users.noreply.github.com> Date: Sat, 5 Apr 2025 21:58:09 +0900 Subject: [PATCH 041/152] docs: explicitly describe that the `migrate` command automatically migrate `linters.presets` (#5697) Co-authored-by: Fernandez Ludovic --- docs/src/docs/product/migration-guide.mdx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/src/docs/product/migration-guide.mdx b/docs/src/docs/product/migration-guide.mdx index b458d93fde4f..ac3da4cf6d2c 100644 --- a/docs/src/docs/product/migration-guide.mdx +++ b/docs/src/docs/product/migration-guide.mdx @@ -43,6 +43,8 @@ The `migrate` command enforces the following default values: Other fields explicitly defined in the configuration file are migrated even if the value is the same as the default value. +The `migrate` command automatically migrates `linters.presets` in individual linters to `linters.enable`. + ```txt Migrate configuration file from v1 to v2 @@ -189,7 +191,9 @@ There are 2 new options (they are not strictly equivalent to the previous option #### `linters.presets` -This property have been removed. +This property has been removed. + +The `migrate` command automatically migrates `linters.presets` in individual linters to `linters.enable`.
v1 From 8bf74c4f59949bcc7ce7c9baeb94aa5cb6e1811c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 5 Apr 2025 22:25:07 +0200 Subject: [PATCH 042/152] build(deps): bump golang.org/x/sys from 0.31.0 to 0.32.0 (#5699) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 62afdbf29c08..f3d1a0c0abda 100644 --- a/go.mod +++ b/go.mod @@ -128,7 +128,7 @@ require ( go-simpler.org/sloglint v0.10.1 go.uber.org/automaxprocs v1.6.0 golang.org/x/mod v0.24.0 - golang.org/x/sys v0.31.0 + golang.org/x/sys v0.32.0 golang.org/x/tools v0.31.0 gopkg.in/yaml.v3 v3.0.1 honnef.co/go/tools v0.6.1 diff --git a/go.sum b/go.sum index 41a925528d21..a172332bb990 100644 --- a/go.sum +++ b/go.sum @@ -819,8 +819,8 @@ 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.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= +golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 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.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= From 638ece2c7a4773d38dc7a499e11618424914d3de Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 5 Apr 2025 22:39:48 +0200 Subject: [PATCH 043/152] build(deps): bump go-simpler.org/sloglint from 0.10.1 to 0.11.0 (#5698) Co-authored-by: Fernandez Ludovic --- go.mod | 2 +- go.sum | 4 ++-- pkg/lint/lintersdb/builder_linter.go | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f3d1a0c0abda..6b1a093621de 100644 --- a/go.mod +++ b/go.mod @@ -125,7 +125,7 @@ require ( github.com/ykadowak/zerologlint v0.1.5 gitlab.com/bosi/decorder v0.4.2 go-simpler.org/musttag v0.13.0 - go-simpler.org/sloglint v0.10.1 + go-simpler.org/sloglint v0.11.0 go.uber.org/automaxprocs v1.6.0 golang.org/x/mod v0.24.0 golang.org/x/sys v0.32.0 diff --git a/go.sum b/go.sum index a172332bb990..259c79bb7137 100644 --- a/go.sum +++ b/go.sum @@ -626,8 +626,8 @@ go-simpler.org/assert v0.9.0 h1:PfpmcSvL7yAnWyChSjOz6Sp6m9j5lyK8Ok9pEL31YkQ= go-simpler.org/assert v0.9.0/go.mod h1:74Eqh5eI6vCK6Y5l3PI8ZYFXG4Sa+tkr70OIPJAUr28= go-simpler.org/musttag v0.13.0 h1:Q/YAW0AHvaoaIbsPj3bvEI5/QFP7w696IMUpnKXQfCE= go-simpler.org/musttag v0.13.0/go.mod h1:FTzIGeK6OkKlUDVpj0iQUXZLUO1Js9+mvykDQy9C5yM= -go-simpler.org/sloglint v0.10.1 h1:gYHgZdbPzRa9/RQ8zYQLnHfmgWivCpNK2MAwnrhnKdA= -go-simpler.org/sloglint v0.10.1/go.mod h1:CFDO8R1i77dlciGfPEPvYke2ZMx4eyGiEIWkyeW2Pvw= +go-simpler.org/sloglint v0.11.0 h1:JlR1X4jkbeaffiyjLtymeqmGDKBDO1ikC6rjiuFAOco= +go-simpler.org/sloglint v0.11.0/go.mod h1:CFDO8R1i77dlciGfPEPvYke2ZMx4eyGiEIWkyeW2Pvw= 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= diff --git a/pkg/lint/lintersdb/builder_linter.go b/pkg/lint/lintersdb/builder_linter.go index 00c333aadb9f..c246250dad16 100644 --- a/pkg/lint/lintersdb/builder_linter.go +++ b/pkg/lint/lintersdb/builder_linter.go @@ -555,6 +555,7 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { linter.NewConfig(sloglint.New(&cfg.Linters.Settings.SlogLint)). WithSince("v1.55.0"). WithLoadForGoAnalysis(). + WithAutoFix(). WithURL("https://github.com/go-simpler/sloglint"), linter.NewConfig(sqlclosecheck.New()). From bd59ef8272c485b7211ce9a550489a6087873f93 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Apr 2025 23:45:48 +0200 Subject: [PATCH 044/152] build(deps): bump golang.org/x/oauth2 from 0.28.0 to 0.29.0 in /scripts/gen_github_action_config in the scripts group (#5704) --- scripts/gen_github_action_config/go.mod | 2 +- scripts/gen_github_action_config/go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/gen_github_action_config/go.mod b/scripts/gen_github_action_config/go.mod index d3da48a46556..c76a4de5840a 100644 --- a/scripts/gen_github_action_config/go.mod +++ b/scripts/gen_github_action_config/go.mod @@ -5,7 +5,7 @@ go 1.23.0 require ( github.com/shurcooL/githubv4 v0.0.0-20240429030203-be2daab69064 github.com/stretchr/testify v1.10.0 - golang.org/x/oauth2 v0.28.0 + golang.org/x/oauth2 v0.29.0 ) require ( diff --git a/scripts/gen_github_action_config/go.sum b/scripts/gen_github_action_config/go.sum index 1898ebd5e03c..b9b970ef73ac 100644 --- a/scripts/gen_github_action_config/go.sum +++ b/scripts/gen_github_action_config/go.sum @@ -10,8 +10,8 @@ github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 h1:17JxqqJY66GmZV github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466/go.mod h1:9dIRpgIY7hVhoqfe0/FcYp0bpInZaT7dc3BYOprrIUE= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= -golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= +golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98= +golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= 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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= From 8c929e0665808d583263d73eabd596e409dd9eb9 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Tue, 8 Apr 2025 12:21:32 +0200 Subject: [PATCH 045/152] feat: add golangci-lint-fmt pre-commit hook (#5705) --- .pre-commit-hooks.yaml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml index dea4b598a090..9738d4b25755 100644 --- a/.pre-commit-hooks.yaml +++ b/.pre-commit-hooks.yaml @@ -8,12 +8,20 @@ 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. + description: Fast linters runner for Go. Runs on all files in the module. 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 +- id: golangci-lint-fmt + name: golangci-lint-fmt + description: Fast linters runner for Go. Formats all files in the repo. + entry: golangci-lint fmt + types: [go] + language: golang + require_serial: true + pass_filenames: false - id: golangci-lint-config-verify name: golangci-lint-config-verify description: Verifies the configuration file From ea6a565e9157e47fd52cf25504733e8eba06487d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Apr 2025 03:25:48 +0200 Subject: [PATCH 046/152] build(deps): bump golang.org/x/tools from 0.31.0 to 0.32.0 (#5708) --- go.mod | 4 ++-- go.sum | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index 6b1a093621de..b3e8a53424c6 100644 --- a/go.mod +++ b/go.mod @@ -129,7 +129,7 @@ require ( go.uber.org/automaxprocs v1.6.0 golang.org/x/mod v0.24.0 golang.org/x/sys v0.32.0 - golang.org/x/tools v0.31.0 + golang.org/x/tools v0.32.0 gopkg.in/yaml.v3 v3.0.1 honnef.co/go/tools v0.6.1 mvdan.cc/gofumpt v0.7.0 @@ -208,7 +208,7 @@ require ( go.uber.org/zap v1.24.0 // indirect golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect - golang.org/x/sync v0.12.0 // indirect + golang.org/x/sync v0.13.0 // indirect golang.org/x/text v0.23.0 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/ini.v1 v1.67.0 // indirect diff --git a/go.sum b/go.sum index 259c79bb7137..da7f81f5f7d8 100644 --- a/go.sum +++ b/go.sum @@ -739,8 +739,8 @@ golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= -golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= +golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= 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= @@ -762,8 +762,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= -golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= +golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= 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= @@ -902,8 +902,8 @@ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= -golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU= -golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ= +golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU= +golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s= 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= From a7a49fed797beb0d195ce6daf33355ff30fe5f3c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Apr 2025 04:28:43 +0200 Subject: [PATCH 047/152] build(deps): bump github.com/butuzov/ireturn from 0.3.1 to 0.4.0 (#5710) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b3e8a53424c6..bf7b85f927b3 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/bombsimon/wsl/v4 v4.7.0 github.com/breml/bidichk v0.3.3 github.com/breml/errchkjson v0.4.1 - github.com/butuzov/ireturn v0.3.1 + github.com/butuzov/ireturn v0.4.0 github.com/butuzov/mirror v1.3.0 github.com/catenacyber/perfsprint v0.9.1 github.com/charithe/durationcheck v0.0.10 diff --git a/go.sum b/go.sum index da7f81f5f7d8..9c397a506666 100644 --- a/go.sum +++ b/go.sum @@ -102,8 +102,8 @@ github.com/breml/bidichk v0.3.3 h1:WSM67ztRusf1sMoqH6/c4OBCUlRVTKq+CbSeo0R17sE= github.com/breml/bidichk v0.3.3/go.mod h1:ISbsut8OnjB367j5NseXEGGgO/th206dVa427kR8YTE= github.com/breml/errchkjson v0.4.1 h1:keFSS8D7A2T0haP9kzZTi7o26r7kE3vymjZNeNDRDwg= github.com/breml/errchkjson v0.4.1/go.mod h1:a23OvR6Qvcl7DG/Z4o0el6BRAjKnaReoPQFciAl9U3s= -github.com/butuzov/ireturn v0.3.1 h1:mFgbEI6m+9W8oP/oDdfA34dLisRFCj2G6o/yiI1yZrY= -github.com/butuzov/ireturn v0.3.1/go.mod h1:ZfRp+E7eJLC0NQmk1Nrm1LOrn/gQlOykv+cVPdiXH5M= +github.com/butuzov/ireturn v0.4.0 h1:+s76bF/PfeKEdbG8b54aCocxXmi0wvYdOVsWxVO7n8E= +github.com/butuzov/ireturn v0.4.0/go.mod h1:ghI0FrCmap8pDWZwfPisFD1vEc56VKH4NpQUxDHta70= github.com/butuzov/mirror v1.3.0 h1:HdWCXzmwlQHdVhwvsfBb2Au0r3HyINry3bDWLYXiKoc= github.com/butuzov/mirror v1.3.0/go.mod h1:AEij0Z8YMALaq4yQj9CPPVYOyJQyiexpQEQgihajRfI= github.com/catenacyber/perfsprint v0.9.1 h1:5LlTp4RwTooQjJCvGEFV6XksZvWE7wCOUvjD2z0vls0= From 06cc97c52b79176477558b6d1222ee504d25f02b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Apr 2025 04:30:03 +0200 Subject: [PATCH 048/152] build(deps): bump github.com/pelletier/go-toml/v2 from 2.2.3 to 2.2.4 (#5711) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index bf7b85f927b3..142079fc123d 100644 --- a/go.mod +++ b/go.mod @@ -85,7 +85,7 @@ require ( github.com/nishanths/exhaustive v0.12.0 github.com/nishanths/predeclared v0.2.2 github.com/nunnatsa/ginkgolinter v0.19.1 - github.com/pelletier/go-toml/v2 v2.2.3 + github.com/pelletier/go-toml/v2 v2.2.4 github.com/polyfloyd/go-errorlint v1.8.0 github.com/quasilyte/go-ruleguard/dsl v0.3.22 github.com/raeperd/recvcheck v0.2.0 diff --git a/go.sum b/go.sum index 9c397a506666..5cfb4c9ad89d 100644 --- a/go.sum +++ b/go.sum @@ -448,8 +448,8 @@ github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT9 github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= -github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= +github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= +github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pkg/errors v0.8.0/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= From 927cad8197465a7eec89f19ef33503d5b17ed126 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Wed, 9 Apr 2025 15:11:59 +0200 Subject: [PATCH 049/152] docs: update section about vscode integration (#5706) Co-authored-by: logica0419 --- docs/src/docs/welcome/integrations.mdx | 33 ++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/docs/src/docs/welcome/integrations.mdx b/docs/src/docs/welcome/integrations.mdx index 2da993e0242d..11a4889da617 100644 --- a/docs/src/docs/welcome/integrations.mdx +++ b/docs/src/docs/welcome/integrations.mdx @@ -12,12 +12,10 @@ Install [plugin](https://plugins.jetbrains.com/plugin/12496-go-linter). ### Visual Studio Code -The integration for golangci-lint v2 is currently in work in progress: [vscode-go#3732](https://github.com/golang/vscode-go/issues/3732). - Install the [extension](https://marketplace.visualstudio.com/items?itemName=golang.Go).
-Recommended settings +Recommended settings for those who installed golangci-lint manually ```json "go.lintTool": "golangci-lint", @@ -35,7 +33,34 @@ Install the [extension](https://marketplace.visualstudio.com/items?itemName=gola ``` Using it in an editor without `--fast-only` can freeze your editor. -Golangci-lint automatically discovers `.golangci.yml` config for edited file: you don't need to configure it in VS Code settings. +Golangci-lint automatically discovers the `.golangci.yml` config for the edited file, so you don't need to configure it in VS Code settings. + +
+ +
+Recommended settings for those who installed golangci-lint via extension + +Install `golangci-lint-v2` via the `Go: Install/Update Tools` command after setting these configs. +This will enable golangci-lint v1 to co-exist with v2. +And use the following settings: + +```json +"go.lintTool": "golangci-lint-v2", +"go.lintFlags": [ + "--fast-only" +], +"go.formatTool": "custom", +"go.alternateTools": { + "customFormatter": "golangci-lint-v2" +}, +"go.formatFlags": [ + "fmt", + "--stdin" +] +``` + +Using it in an editor without `--fast-only` can freeze your editor. +Golangci-lint automatically discovers the `.golangci.yml` config for the edited file, so you don't need to configure it in VS Code settings.
From 72fe3b653b5e4f0cea2a55da2241f9f78209f60d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Apr 2025 22:02:43 +0200 Subject: [PATCH 050/152] build(deps): bump github.com/jgautheron/goconst from 1.7.1 to 1.8.1 (#5712) Co-authored-by: Fernandez Ludovic --- .golangci.next.reference.yml | 9 +++- go.mod | 2 +- go.sum | 4 +- jsonschema/golangci.next.jsonschema.json | 17 ++++++- pkg/config/linters_settings.go | 21 +++++--- pkg/config/loader.go | 11 +++- pkg/golinters/goconst/goconst.go | 51 ++++++++++++------- .../goconst_eval_and_find_duplicates.go | 25 +++++++++ .../goconst_eval_and_find_duplicates.yml | 8 +++ .../goconst_eval_const_expressions.go | 29 +++++++++++ .../goconst_eval_const_expressions.yml | 6 +++ .../testdata/goconst_find_duplicates.go | 29 +++++++++++ .../testdata/goconst_find_duplicates.yml | 6 +++ pkg/lint/lintersdb/builder_linter.go | 1 + 14 files changed, 186 insertions(+), 33 deletions(-) create mode 100644 pkg/golinters/goconst/testdata/goconst_eval_and_find_duplicates.go create mode 100644 pkg/golinters/goconst/testdata/goconst_eval_and_find_duplicates.yml create mode 100644 pkg/golinters/goconst/testdata/goconst_eval_const_expressions.go create mode 100644 pkg/golinters/goconst/testdata/goconst_eval_const_expressions.yml create mode 100644 pkg/golinters/goconst/testdata/goconst_find_duplicates.go create mode 100644 pkg/golinters/goconst/testdata/goconst_find_duplicates.yml diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index 6245b6245ba0..13c0b5cf1344 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -631,7 +631,14 @@ linters: ignore-calls: false # Exclude strings matching the given regular expression. # Default: "" - ignore-strings: 'foo.+' + ignore-string-values: + - 'foo.+' + # Detects constants with identical values. + # Default: false + find-duplicates: true + # Evaluates of constant expressions like Prefix + "suffix". + # Default: false + eval-const-expressions: true gocritic: # Disable all checks. diff --git a/go.mod b/go.mod index 142079fc123d..9557cdc3dcb5 100644 --- a/go.mod +++ b/go.mod @@ -57,7 +57,7 @@ require ( github.com/gostaticanalysis/forcetypeassert v0.2.0 github.com/gostaticanalysis/nilerr v0.1.1 github.com/hashicorp/go-version v1.7.0 - github.com/jgautheron/goconst v1.7.1 + github.com/jgautheron/goconst v1.8.1 github.com/jingyugao/rowserrcheck v1.1.1 github.com/jjti/go-spancheck v0.6.4 github.com/julz/importas v0.2.0 diff --git a/go.sum b/go.sum index 5cfb4c9ad89d..7d65bcaa5c89 100644 --- a/go.sum +++ b/go.sum @@ -331,8 +331,8 @@ github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSo github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= 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.1 h1:VpdAG7Ca7yvvJk5n8dMwQhfEZJh95kl/Hl9S1OI5Jkk= -github.com/jgautheron/goconst v1.7.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= +github.com/jgautheron/goconst v1.8.1 h1:PPqCYp3K/xlOj5JmIe6O1Mj6r1DbkdbLtR3AJuZo414= +github.com/jgautheron/goconst v1.8.1/go.mod h1:A0oxgBCHy55NQn6sYpO7UdnA9p+h7cPtoOZUmvNIako= 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/jjti/go-spancheck v0.6.4 h1:Tl7gQpYf4/TMU7AT84MN83/6PutY21Nb9fuQjFTpRRc= diff --git a/jsonschema/golangci.next.jsonschema.json b/jsonschema/golangci.next.jsonschema.json index 814c7cfe9c8e..8149984411dd 100644 --- a/jsonschema/golangci.next.jsonschema.json +++ b/jsonschema/golangci.next.jsonschema.json @@ -1487,9 +1487,12 @@ "type": "boolean", "default": true }, - "ignore-strings": { + "ignore-string-values": { "description": "Exclude strings matching the given regular expression", - "type": "string" + "type": "array", + "items": { + "type": "string" + } }, "numbers": { "description": "Search also for duplicated numbers.", @@ -1505,6 +1508,16 @@ "description": "Maximum value, only works with `numbers`", "type": "integer", "default": 3 + }, + "find-duplicates": { + "description": "Detects constants with identical values", + "type": "boolean", + "default": false + }, + "eval-const-expressions": { + "description": "Evaluates of constant expressions like Prefix + \"suffix\"", + "type": "boolean", + "default": false } } }, diff --git a/pkg/config/linters_settings.go b/pkg/config/linters_settings.go index 046645e40f98..16269033c7e9 100644 --- a/pkg/config/linters_settings.go +++ b/pkg/config/linters_settings.go @@ -451,14 +451,19 @@ type GocognitSettings struct { } type GoConstSettings struct { - IgnoreStrings string `mapstructure:"ignore-strings"` - 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"` + IgnoreStringValues []string `mapstructure:"ignore-string-values"` + 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"` + FindDuplicates bool `mapstructure:"find-duplicates"` + EvalConstExpressions bool `mapstructure:"eval-const-expressions"` + + // Deprecated: use IgnoreStringValues instead. + IgnoreStrings string `mapstructure:"ignore-strings"` } type GoCriticSettings struct { diff --git a/pkg/config/loader.go b/pkg/config/loader.go index ffa02d6bcdb5..19a17e7d71db 100644 --- a/pkg/config/loader.go +++ b/pkg/config/loader.go @@ -190,8 +190,15 @@ func (l *Loader) handleDeprecation() error { return nil } -func (*Loader) handleLinterOptionDeprecations() { - // The function is empty but deprecations will happen in the future. +func (l *Loader) handleLinterOptionDeprecations() { + // Deprecated since v2.1.0. + if l.cfg.Linters.Settings.Goconst.IgnoreStrings != "" { + l.log.Warnf("The configuration option `linters.settings.goconst.ignore-strings` is deprecated, " + + "please use `linters.settings.goconst.ignore-string-values`.") + + l.cfg.Linters.Settings.Goconst.IgnoreStringValues = append(l.cfg.Linters.Settings.Goconst.IgnoreStringValues, + l.cfg.Linters.Settings.Goconst.IgnoreStrings) + } } func (l *Loader) handleEnableOnlyOption() error { diff --git a/pkg/golinters/goconst/goconst.go b/pkg/golinters/goconst/goconst.go index 26196f6929d6..f3af64625243 100644 --- a/pkg/golinters/goconst/goconst.go +++ b/pkg/golinters/goconst/goconst.go @@ -48,19 +48,21 @@ func New(settings *config.GoConstSettings) *goanalysis.Linter { nil, ).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { return resIssues - }).WithLoadMode(goanalysis.LoadModeSyntax) + }).WithLoadMode(goanalysis.LoadModeTypesInfo) } func runGoconst(pass *analysis.Pass, settings *config.GoConstSettings) ([]goanalysis.Issue, error) { cfg := goconstAPI.Config{ - IgnoreStrings: settings.IgnoreStrings, - MatchWithConstants: settings.MatchWithConstants, - MinStringLength: settings.MinStringLen, - MinOccurrences: settings.MinOccurrencesCount, - ParseNumbers: settings.ParseNumbers, - NumberMin: settings.NumberMin, - NumberMax: settings.NumberMax, - ExcludeTypes: map[goconstAPI.Type]bool{}, + IgnoreStrings: settings.IgnoreStringValues, + MatchWithConstants: settings.MatchWithConstants, + MinStringLength: settings.MinStringLen, + MinOccurrences: settings.MinOccurrencesCount, + ParseNumbers: settings.ParseNumbers, + NumberMin: settings.NumberMin, + NumberMax: settings.NumberMax, + ExcludeTypes: map[goconstAPI.Type]bool{}, + FindDuplicates: settings.FindDuplicates, + EvalConstExpressions: settings.EvalConstExpressions, // Should be managed with `linters.exclusions.rules`. IgnoreTests: false, @@ -70,7 +72,7 @@ func runGoconst(pass *analysis.Pass, settings *config.GoConstSettings) ([]goanal cfg.ExcludeTypes[goconstAPI.Call] = true } - lintIssues, err := goconstAPI.Run(pass.Files, pass.Fset, &cfg) + lintIssues, err := goconstAPI.Run(pass.Files, pass.Fset, pass.TypesInfo, &cfg) if err != nil { return nil, err } @@ -80,17 +82,32 @@ func runGoconst(pass *analysis.Pass, settings *config.GoConstSettings) ([]goanal } res := make([]goanalysis.Issue, 0, len(lintIssues)) - for _, i := range lintIssues { - text := fmt.Sprintf("string %s has %d occurrences", internal.FormatCode(i.Str, nil), i.OccurrencesCount) + for i := range lintIssues { + issue := &lintIssues[i] - if i.MatchingConst == "" { - text += ", make it a constant" - } else { - text += fmt.Sprintf(", but such constant %s already exists", internal.FormatCode(i.MatchingConst, nil)) + var text string + + switch { + case issue.OccurrencesCount > 0: + text = fmt.Sprintf("string %s has %d occurrences", internal.FormatCode(issue.Str, nil), issue.OccurrencesCount) + + if issue.MatchingConst == "" { + text += ", make it a constant" + } else { + text += fmt.Sprintf(", but such constant %s already exists", internal.FormatCode(issue.MatchingConst, nil)) + } + + case issue.DuplicateConst != "": + text = fmt.Sprintf("This constant is a duplicate of %s at %s", + internal.FormatCode(issue.DuplicateConst, nil), + issue.DuplicatePos.String()) + + default: + continue } res = append(res, goanalysis.NewIssue(&result.Issue{ - Pos: i.Pos, + Pos: issue.Pos, Text: text, FromLinter: linterName, }, pass)) diff --git a/pkg/golinters/goconst/testdata/goconst_eval_and_find_duplicates.go b/pkg/golinters/goconst/testdata/goconst_eval_and_find_duplicates.go new file mode 100644 index 000000000000..64a4c3e119eb --- /dev/null +++ b/pkg/golinters/goconst/testdata/goconst_eval_and_find_duplicates.go @@ -0,0 +1,25 @@ +//golangcitest:args -Egoconst +//golangcitest:config_path testdata/goconst_eval_and_find_duplicates.yml +package testdata + +import "fmt" + +const ( + envPrefix = "FOO_" + EnvUser = envPrefix + "USER" + EnvPassword = envPrefix + "PASSWORD" +) + +const EnvUserFull = "FOO_USER" // want "This constant is a duplicate of `EnvUser` at .*goconst_eval_and_find_duplicates.go:9:16" + +const KiB = 1 << 10 + +func _() { + fmt.Println(envPrefix, EnvUser, EnvPassword, EnvUserFull) + + const kilobytes = 1024 // want "This constant is a duplicate of `KiB` at .*goconst_eval_and_find_duplicates.go:15:13" + fmt.Println(kilobytes) + + kib := 1024 + fmt.Println(kib) +} diff --git a/pkg/golinters/goconst/testdata/goconst_eval_and_find_duplicates.yml b/pkg/golinters/goconst/testdata/goconst_eval_and_find_duplicates.yml new file mode 100644 index 000000000000..445d6b77263d --- /dev/null +++ b/pkg/golinters/goconst/testdata/goconst_eval_and_find_duplicates.yml @@ -0,0 +1,8 @@ +version: "2" + +linters: + settings: + goconst: + find-duplicates: true + eval-const-expressions: true + numbers: true diff --git a/pkg/golinters/goconst/testdata/goconst_eval_const_expressions.go b/pkg/golinters/goconst/testdata/goconst_eval_const_expressions.go new file mode 100644 index 000000000000..4cc272945b43 --- /dev/null +++ b/pkg/golinters/goconst/testdata/goconst_eval_const_expressions.go @@ -0,0 +1,29 @@ +//golangcitest:args -Egoconst +//golangcitest:config_path testdata/goconst_eval_const_expressions.yml +package testdata + +const ( + prefix = "example.com/" + API = prefix + "api" + Web = prefix + "web" +) + +const Full = "example.com/api" + +func _() { + a0 := "example.com/api" // want "string `example.com/api` has 3 occurrences, but such constant `API` already exists" + a1 := "example.com/api" + a2 := "example.com/api" + + _ = a0 + _ = a1 + _ = a2 + + b0 := "example.com/web" // want "string `example.com/web` has 3 occurrences, but such constant `Web` already exists" + b1 := "example.com/web" + b2 := "example.com/web" + + _ = b0 + _ = b1 + _ = b2 +} diff --git a/pkg/golinters/goconst/testdata/goconst_eval_const_expressions.yml b/pkg/golinters/goconst/testdata/goconst_eval_const_expressions.yml new file mode 100644 index 000000000000..7c2303aef7d8 --- /dev/null +++ b/pkg/golinters/goconst/testdata/goconst_eval_const_expressions.yml @@ -0,0 +1,6 @@ +version: "2" + +linters: + settings: + goconst: + eval-const-expressions: true diff --git a/pkg/golinters/goconst/testdata/goconst_find_duplicates.go b/pkg/golinters/goconst/testdata/goconst_find_duplicates.go new file mode 100644 index 000000000000..a1605cfe6358 --- /dev/null +++ b/pkg/golinters/goconst/testdata/goconst_find_duplicates.go @@ -0,0 +1,29 @@ +//golangcitest:args -Egoconst +//golangcitest:config_path testdata/goconst_find_duplicates.yml +package testdata + +const SingleConst = "single constant" + +const ( + GroupedConst1 = "grouped constant" + GroupedConst2 = "another grouped" +) + +const ( + GroupedDuplicateConst1 = "grouped duplicate value" + GroupedDuplicateConst2 = "grouped duplicate value" // want "This constant is a duplicate of `GroupedDuplicateConst1` at .*goconst_find_duplicates.go:13:2" +) + +const DuplicateConst1 = "duplicate value" + +const DuplicateConst2 = "duplicate value" // want "This constant is a duplicate of `DuplicateConst1` at .*goconst_find_duplicates.go:17:7" + +const ( + SpecialDuplicateConst1 = "special\nvalue\twith\rchars" + SpecialDuplicateConst2 = "special\nvalue\twith\rchars" // want "This constant is a duplicate of `SpecialDuplicateConst1` at .*goconst_find_duplicates.go:22:2" +) + +func _() { + const DuplicateScopedConst1 = "duplicate scoped value" + const DuplicateScopedConst2 = "duplicate scoped value" // want "This constant is a duplicate of `DuplicateScopedConst1` at .*goconst_find_duplicates.go:27:8" +} diff --git a/pkg/golinters/goconst/testdata/goconst_find_duplicates.yml b/pkg/golinters/goconst/testdata/goconst_find_duplicates.yml new file mode 100644 index 000000000000..8a64450696e7 --- /dev/null +++ b/pkg/golinters/goconst/testdata/goconst_find_duplicates.yml @@ -0,0 +1,6 @@ +version: "2" + +linters: + settings: + goconst: + find-duplicates: true diff --git a/pkg/lint/lintersdb/builder_linter.go b/pkg/lint/lintersdb/builder_linter.go index c246250dad16..a05e0bbd7f4c 100644 --- a/pkg/lint/lintersdb/builder_linter.go +++ b/pkg/lint/lintersdb/builder_linter.go @@ -300,6 +300,7 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { linter.NewConfig(goconst.New(&cfg.Linters.Settings.Goconst)). WithSince("v1.0.0"). + WithLoadForGoAnalysis(). WithURL("https://github.com/jgautheron/goconst"), linter.NewConfig(gocritic.New(&cfg.Linters.Settings.Gocritic, placeholderReplacer)). From 99132265db0c1db0819509334cebc15fc03fc496 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Thu, 10 Apr 2025 15:09:40 +0200 Subject: [PATCH 051/152] build(deps): bump github.com/golangci/unconvert to HEAD (#5713) --- go.mod | 2 +- go.sum | 4 ++-- pkg/golinters/unconvert/unconvert.go | 9 ++++++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 9557cdc3dcb5..b6295abf0896 100644 --- a/go.mod +++ b/go.mod @@ -52,7 +52,7 @@ require ( github.com/golangci/misspell v0.6.0 github.com/golangci/plugin-module-register v0.1.1 github.com/golangci/revgrep v0.8.0 - github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed + github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e github.com/gordonklaus/ineffassign v0.1.0 github.com/gostaticanalysis/forcetypeassert v0.2.0 github.com/gostaticanalysis/nilerr v0.1.1 diff --git a/go.sum b/go.sum index 7d65bcaa5c89..55504ee646e6 100644 --- a/go.sum +++ b/go.sum @@ -265,8 +265,8 @@ github.com/golangci/plugin-module-register v0.1.1 h1:TCmesur25LnyJkpsVrupv1Cdzo+ github.com/golangci/plugin-module-register v0.1.1/go.mod h1:TTpqoB6KkwOJMV8u7+NyXMrkwwESJLOkfl9TxR1DGFc= github.com/golangci/revgrep v0.8.0 h1:EZBctwbVd0aMeRnNUsFogoyayvKHyxlV3CdUA46FX2s= github.com/golangci/revgrep v0.8.0/go.mod h1:U4R/s9dlXZsg8uJmaR1GrloUr14D7qDl8gi2iPXJH8k= -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/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e h1:gD6P7NEo7Eqtt0ssnqSJNNndxe69DOQ24A5h7+i3KpM= +github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e/go.mod h1:h+wZwLjUTJnm/P2rwlbJdRPZXOzaT36/FwnPnY2inzc= 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= diff --git a/pkg/golinters/unconvert/unconvert.go b/pkg/golinters/unconvert/unconvert.go index 5ca8e09ad110..d48cf5175ad4 100644 --- a/pkg/golinters/unconvert/unconvert.go +++ b/pkg/golinters/unconvert/unconvert.go @@ -18,11 +18,14 @@ func New(settings *config.UnconvertSettings) *goanalysis.Linter { var mu sync.Mutex var resIssues []goanalysis.Issue + unconvert.SetFastMath(settings.FastMath) + unconvert.SetSafe(settings.Safe) + analyzer := &analysis.Analyzer{ Name: linterName, Doc: goanalysis.TheOnlyanalyzerDoc, Run: func(pass *analysis.Pass) (any, error) { - issues := runUnconvert(pass, settings) + issues := runUnconvert(pass) if len(issues) == 0 { return nil, nil @@ -46,8 +49,8 @@ func New(settings *config.UnconvertSettings) *goanalysis.Linter { }).WithLoadMode(goanalysis.LoadModeTypesInfo) } -func runUnconvert(pass *analysis.Pass, settings *config.UnconvertSettings) []goanalysis.Issue { - positions := unconvert.Run(pass, settings.FastMath, settings.Safe) +func runUnconvert(pass *analysis.Pass) []goanalysis.Issue { + positions := unconvert.Run(pass) var issues []goanalysis.Issue for _, position := range positions { From 516e0f042ffb6ec5fdcdcfeadfea6ea35f5bdd54 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 10 Apr 2025 15:30:34 +0200 Subject: [PATCH 052/152] build(deps): bump github.com/timonwong/loggercheck from 0.10.1 to 0.11.0 (#5715) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b6295abf0896..f8f3e09fba62 100644 --- a/go.mod +++ b/go.mod @@ -111,7 +111,7 @@ require ( github.com/tdakkota/asciicheck v0.4.1 github.com/tetafro/godot v1.5.0 github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67 - github.com/timonwong/loggercheck v0.10.1 + github.com/timonwong/loggercheck v0.11.0 github.com/tomarrell/wrapcheck/v2 v2.11.0 github.com/tommy-muehle/go-mnd/v2 v2.5.1 github.com/ultraware/funlen v0.2.0 diff --git a/go.sum b/go.sum index 55504ee646e6..64c32c957c21 100644 --- a/go.sum +++ b/go.sum @@ -579,8 +579,8 @@ github.com/tetafro/godot v1.5.0 h1:aNwfVI4I3+gdxjMgYPus9eHmoBeJIbnajOyqZYStzuw= github.com/tetafro/godot v1.5.0/go.mod h1:2oVxTBSftRTh4+MVfUaUXR6bn2GDXCaMcOG4Dk3rfio= github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67 h1:9LPGD+jzxMlnk5r6+hJnar67cgpDIz/iyD+rfl5r2Vk= github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67/go.mod h1:mkjARE7Yr8qU23YcGMSALbIxTQ9r9QBVahQOBRfU460= -github.com/timonwong/loggercheck v0.10.1 h1:uVZYClxQFpw55eh+PIoqM7uAOHMrhVcDoWDery9R8Lg= -github.com/timonwong/loggercheck v0.10.1/go.mod h1:HEAWU8djynujaAVX7QI65Myb8qgfcZ1uKbdpg3ZzKl8= +github.com/timonwong/loggercheck v0.11.0 h1:jdaMpYBl+Uq9mWPXv1r8jc5fC3gyXx4/WGwTnnNKn4M= +github.com/timonwong/loggercheck v0.11.0/go.mod h1:HEAWU8djynujaAVX7QI65Myb8qgfcZ1uKbdpg3ZzKl8= 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= From 941b1eff1c75d42f6bb63d250cc09ca5e5b15ce6 Mon Sep 17 00:00:00 2001 From: Oleksandr Redko Date: Thu, 10 Apr 2025 23:59:11 +0300 Subject: [PATCH 053/152] govet: add `httpmux` analyzer (#5717) --- .golangci.next.reference.yml | 3 +++ pkg/golinters/govet/govet.go | 2 ++ 2 files changed, 5 insertions(+) diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index 13c0b5cf1344..a7d9017d28f6 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -1587,6 +1587,8 @@ linters: - findcall # Report assembly that clobbers the frame pointer before saving it. - framepointer + # Report using Go 1.22 enhanced ServeMux patterns in older Go versions. + - httpmux # Check for mistakes using HTTP responses. - httpresponse # Detect impossible interface-to-interface type assertions. @@ -1668,6 +1670,7 @@ linters: - fieldalignment - findcall - framepointer + - httpmux - httpresponse - ifaceassert - loopclosure diff --git a/pkg/golinters/govet/govet.go b/pkg/golinters/govet/govet.go index 3ffdc22ebb2a..4f3380841382 100644 --- a/pkg/golinters/govet/govet.go +++ b/pkg/golinters/govet/govet.go @@ -24,6 +24,7 @@ import ( "golang.org/x/tools/go/analysis/passes/fieldalignment" "golang.org/x/tools/go/analysis/passes/findcall" "golang.org/x/tools/go/analysis/passes/framepointer" + "golang.org/x/tools/go/analysis/passes/httpmux" "golang.org/x/tools/go/analysis/passes/httpresponse" "golang.org/x/tools/go/analysis/passes/ifaceassert" _ "golang.org/x/tools/go/analysis/passes/inspect" // unused internal analyzer @@ -77,6 +78,7 @@ var ( fieldalignment.Analyzer, findcall.Analyzer, framepointer.Analyzer, + httpmux.Analyzer, httpresponse.Analyzer, ifaceassert.Analyzer, loopclosure.Analyzer, From ec2da937d93ca88e63f30ec046dfa84f8082fc13 Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Thu, 10 Apr 2025 23:01:05 +0200 Subject: [PATCH 054/152] dev: update JSON schema --- jsonschema/golangci.next.jsonschema.json | 1 + 1 file changed, 1 insertion(+) diff --git a/jsonschema/golangci.next.jsonschema.json b/jsonschema/golangci.next.jsonschema.json index 8149984411dd..5dc6b9d9570d 100644 --- a/jsonschema/golangci.next.jsonschema.json +++ b/jsonschema/golangci.next.jsonschema.json @@ -539,6 +539,7 @@ "fieldalignment", "findcall", "framepointer", + "httpmux", "httpresponse", "ifaceassert", "loopclosure", From e0e6eae1797b9b8d4beeeecff15104ff4e75e180 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 11 Apr 2025 18:37:47 +0200 Subject: [PATCH 055/152] build(deps): bump github.com/mgechev/revive from 1.8.0 to 1.9.0 (#5721) --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index f8f3e09fba62..6bd75fbffa3a 100644 --- a/go.mod +++ b/go.mod @@ -78,7 +78,7 @@ require ( github.com/maratori/testpackage v1.1.1 github.com/matoous/godox v1.1.0 github.com/mattn/go-colorable v0.1.14 - github.com/mgechev/revive v1.8.0 + github.com/mgechev/revive v1.9.0 github.com/mitchellh/go-homedir v1.1.0 github.com/moricho/tparallel v0.3.2 github.com/nakabonne/nestif v0.3.1 @@ -209,7 +209,7 @@ require ( golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect golang.org/x/sync v0.13.0 // indirect - golang.org/x/text v0.23.0 // indirect + golang.org/x/text v0.24.0 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 64c32c957c21..063680d733df 100644 --- a/go.sum +++ b/go.sum @@ -408,8 +408,8 @@ github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6T github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= 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/mgechev/revive v1.8.0 h1:GRtZfbR+USnEs9kiTgokw0LKEQfPPM3EJpu/88IcXl4= -github.com/mgechev/revive v1.8.0/go.mod h1:AEte1jB8fAHGObV1BshB7WSfp3x/WZwAu/xNiClBK2Y= +github.com/mgechev/revive v1.9.0 h1:8LaA62XIKrb8lM6VsBSQ92slt/o92z5+hTw3CmrvSrM= +github.com/mgechev/revive v1.9.0/go.mod h1:LAPq3+MgOf7GcL5PlWIkHb0PT7XH4NuC2LdWymhb9Mo= 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/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -841,8 +841,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= +golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= 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= From a39e032e73ac05b8caceedbe61a380bd62c866d9 Mon Sep 17 00:00:00 2001 From: Manuel Doncel Martos Date: Sat, 12 Apr 2025 01:18:50 +0200 Subject: [PATCH 056/152] Add funcorder linter (#5630) --- .golangci.next.reference.yml | 10 +++++ go.mod | 1 + go.sum | 2 + jsonschema/golangci.next.jsonschema.json | 20 +++++++++ pkg/config/linters_settings.go | 10 +++++ pkg/golinters/funcorder/funcorder.go | 29 +++++++++++++ .../funcorder/funcorder_integration_test.go | 11 +++++ pkg/golinters/funcorder/testdata/funcorder.go | 40 ++++++++++++++++++ .../testdata/funcorder_disable_constructor.go | 41 +++++++++++++++++++ .../funcorder_disable_constructor.yml | 6 +++ .../testdata/funcorder_struct_method.go | 41 +++++++++++++++++++ .../testdata/funcorder_struct_method.yml | 6 +++ pkg/lint/lintersdb/builder_linter.go | 5 +++ 13 files changed, 222 insertions(+) create mode 100644 pkg/golinters/funcorder/funcorder.go create mode 100644 pkg/golinters/funcorder/funcorder_integration_test.go create mode 100644 pkg/golinters/funcorder/testdata/funcorder.go create mode 100644 pkg/golinters/funcorder/testdata/funcorder_disable_constructor.go create mode 100644 pkg/golinters/funcorder/testdata/funcorder_disable_constructor.yml create mode 100644 pkg/golinters/funcorder/testdata/funcorder_struct_method.go create mode 100644 pkg/golinters/funcorder/testdata/funcorder_struct_method.yml diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index a7d9017d28f6..cababbea228f 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -43,6 +43,7 @@ linters: - fatcontext - forbidigo - forcetypeassert + - funcorder - funlen - ginkgolinter - gocheckcompilerdirectives @@ -150,6 +151,7 @@ linters: - fatcontext - forbidigo - forcetypeassert + - funcorder - funlen - ginkgolinter - gocheckcompilerdirectives @@ -530,6 +532,14 @@ linters: # Default: false analyze-types: true + funcorder: + # Checks that constructors are placed after the structure declaration. + # Default: true + constructor: false + # Checks if the exported methods of a structure are placed before the non-exported ones. + # Default: true + struct-method: false + funlen: # Checks the number of lines in a function. # If lower than 0, disable the check. diff --git a/go.mod b/go.mod index 6bd75fbffa3a..c229136ae43d 100644 --- a/go.mod +++ b/go.mod @@ -74,6 +74,7 @@ require ( github.com/ldez/usetesting v0.4.2 github.com/leonklingele/grouper v1.1.2 github.com/macabu/inamedparam v0.2.0 + github.com/manuelarte/funcorder v0.2.1 github.com/maratori/testableexamples v1.0.0 github.com/maratori/testpackage v1.1.1 github.com/matoous/godox v1.1.0 diff --git a/go.sum b/go.sum index 063680d733df..f657816a2e6c 100644 --- a/go.sum +++ b/go.sum @@ -391,6 +391,8 @@ github.com/macabu/inamedparam v0.2.0 h1:VyPYpOc10nkhI2qeNUdh3Zket4fcZjEWe35poddB github.com/macabu/inamedparam v0.2.0/go.mod h1:+Pee9/YfGe5LJ62pYXqB89lJ+0k5bsR8Wgz/C0Zlq3U= github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/manuelarte/funcorder v0.2.1 h1:7QJsw3qhljoZ5rH0xapIvjw31EcQeFbF31/7kQ/xS34= +github.com/manuelarte/funcorder v0.2.1/go.mod h1:BQQ0yW57+PF9ZpjpeJDKOffEsQbxDFKW8F8zSMe/Zd0= 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.1 h1:S58XVV5AD7HADMmD0fNnziNHqKvSdDuEKdPD1rNTU04= diff --git a/jsonschema/golangci.next.jsonschema.json b/jsonschema/golangci.next.jsonschema.json index 5dc6b9d9570d..996a5ec3721f 100644 --- a/jsonschema/golangci.next.jsonschema.json +++ b/jsonschema/golangci.next.jsonschema.json @@ -741,6 +741,7 @@ "fatcontext", "forbidigo", "forcetypeassert", + "funcorder", "funlen", "ginkgolinter", "gocheckcompilerdirectives", @@ -1302,6 +1303,22 @@ } } }, + "funcorderSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "constructor": { + "description": "Checks that constructors are placed after the structure declaration.", + "type": "boolean", + "default": true + }, + "struct-method": { + "description": "Checks if the exported methods of a structure are placed before the non-exported ones.", + "type": "boolean", + "default": true + } + } + }, "funlenSettings": { "type": "object", "additionalProperties": false, @@ -4345,6 +4362,9 @@ "forbidigo": { "$ref": "#/definitions/settings/definitions/forbidigoSettings" }, + "funcorder": { + "$ref": "#/definitions/settings/definitions/funcorderSettings" + }, "funlen": { "$ref": "#/definitions/settings/definitions/funlenSettings" }, diff --git a/pkg/config/linters_settings.go b/pkg/config/linters_settings.go index 16269033c7e9..16a8bb9501b9 100644 --- a/pkg/config/linters_settings.go +++ b/pkg/config/linters_settings.go @@ -41,6 +41,10 @@ var defaultLintersSettings = LintersSettings{ Forbidigo: ForbidigoSettings{ ExcludeGodocExamples: true, }, + FuncOrder: FuncOrderSettings{ + Constructor: true, + StructMethod: true, + }, Funlen: FunlenSettings{ IgnoreComments: true, }, @@ -217,6 +221,7 @@ type LintersSettings struct { Exhaustruct ExhaustructSettings `mapstructure:"exhaustruct"` Fatcontext FatcontextSettings `mapstructure:"fatcontext"` Forbidigo ForbidigoSettings `mapstructure:"forbidigo"` + FuncOrder FuncOrderSettings `mapstructure:"funcorder"` Funlen FunlenSettings `mapstructure:"funlen"` GinkgoLinter GinkgoLinterSettings `mapstructure:"ginkgolinter"` Gocognit GocognitSettings `mapstructure:"gocognit"` @@ -420,6 +425,11 @@ type ForbidigoPattern struct { Msg string `yaml:"msg,omitempty" mapstructure:"msg,omitempty"` } +type FuncOrderSettings struct { + Constructor bool `mapstructure:"constructor,omitempty"` + StructMethod bool `mapstructure:"struct-method,omitempty"` +} + type FunlenSettings struct { Lines int `mapstructure:"lines"` Statements int `mapstructure:"statements"` diff --git a/pkg/golinters/funcorder/funcorder.go b/pkg/golinters/funcorder/funcorder.go new file mode 100644 index 000000000000..7b8e9689e587 --- /dev/null +++ b/pkg/golinters/funcorder/funcorder.go @@ -0,0 +1,29 @@ +package funcorder + +import ( + "github.com/manuelarte/funcorder/analyzer" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/v2/pkg/config" + "github.com/golangci/golangci-lint/v2/pkg/goanalysis" +) + +func New(settings *config.FuncOrderSettings) *goanalysis.Linter { + a := analyzer.NewAnalyzer() + + cfg := map[string]map[string]any{} + + if settings != nil { + cfg[a.Name] = map[string]any{ + analyzer.ConstructorCheckName: settings.Constructor, + analyzer.StructMethodCheckName: settings.StructMethod, + } + } + + return goanalysis.NewLinter( + a.Name, + a.Doc, + []*analysis.Analyzer{a}, + cfg, + ).WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/pkg/golinters/funcorder/funcorder_integration_test.go b/pkg/golinters/funcorder/funcorder_integration_test.go new file mode 100644 index 000000000000..31ee6ec82d4b --- /dev/null +++ b/pkg/golinters/funcorder/funcorder_integration_test.go @@ -0,0 +1,11 @@ +package funcorder + +import ( + "testing" + + "github.com/golangci/golangci-lint/v2/test/testshared/integration" +) + +func TestFromTestdata(t *testing.T) { + integration.RunTestdata(t) +} diff --git a/pkg/golinters/funcorder/testdata/funcorder.go b/pkg/golinters/funcorder/testdata/funcorder.go new file mode 100644 index 000000000000..b9ae4e81fafa --- /dev/null +++ b/pkg/golinters/funcorder/testdata/funcorder.go @@ -0,0 +1,40 @@ +//golangcitest:args -Efuncorder +package testdata + +import "time" + +type MyStruct struct { + Name string +} + +func (m MyStruct) lenName() int { // want `unexported method "lenName" for struct "MyStruct" should be placed after the exported method "SetName"` + return len(m.Name) +} + +func (m MyStruct) GetName() string { + return m.Name +} + +func (m *MyStruct) SetName(name string) { + m.Name = name +} + +type MyStruct2 struct { + Name string +} + +func (m MyStruct2) GetName() string { + return m.Name +} + +func (m *MyStruct2) SetName(name string) { + m.Name = name +} + +func NewMyStruct2() *MyStruct2 { // want `constructor "NewMyStruct2" for struct "MyStruct2" should be placed before struct method "GetName"` + return &MyStruct2{Name: "John"} +} + +func NewTime() time.Time { + return time.Now() +} diff --git a/pkg/golinters/funcorder/testdata/funcorder_disable_constructor.go b/pkg/golinters/funcorder/testdata/funcorder_disable_constructor.go new file mode 100644 index 000000000000..d131d5dee356 --- /dev/null +++ b/pkg/golinters/funcorder/testdata/funcorder_disable_constructor.go @@ -0,0 +1,41 @@ +//golangcitest:args -Efuncorder +//golangcitest:config_path testdata/funcorder_disable_constructor.yml +package testdata + +import "time" + +type MyStruct struct { + Name string +} + +func (m MyStruct) lenName() int { // want `unexported method "lenName" for struct "MyStruct" should be placed after the exported method "SetName"` + return len(m.Name) +} + +func (m MyStruct) GetName() string { + return m.Name +} + +func (m *MyStruct) SetName(name string) { + m.Name = name +} + +type MyStruct2 struct { + Name string +} + +func (m MyStruct2) GetName() string { + return m.Name +} + +func (m *MyStruct2) SetName(name string) { + m.Name = name +} + +func NewMyStruct2() *MyStruct2 { + return &MyStruct2{Name: "John"} +} + +func NewTime() time.Time { + return time.Now() +} diff --git a/pkg/golinters/funcorder/testdata/funcorder_disable_constructor.yml b/pkg/golinters/funcorder/testdata/funcorder_disable_constructor.yml new file mode 100644 index 000000000000..df43fb02f4d4 --- /dev/null +++ b/pkg/golinters/funcorder/testdata/funcorder_disable_constructor.yml @@ -0,0 +1,6 @@ +version: "2" + +linters: + settings: + funcorder: + constructor: false diff --git a/pkg/golinters/funcorder/testdata/funcorder_struct_method.go b/pkg/golinters/funcorder/testdata/funcorder_struct_method.go new file mode 100644 index 000000000000..a44f980e8b9e --- /dev/null +++ b/pkg/golinters/funcorder/testdata/funcorder_struct_method.go @@ -0,0 +1,41 @@ +//golangcitest:args -Efuncorder +//golangcitest:config_path testdata/funcorder_struct_method.yml +package testdata + +import "time" + +type MyStruct struct { + Name string +} + +func (m MyStruct) lenName() int { + return len(m.Name) +} + +func (m MyStruct) GetName() string { + return m.Name +} + +func (m *MyStruct) SetName(name string) { + m.Name = name +} + +type MyStruct2 struct { + Name string +} + +func (m MyStruct2) GetName() string { + return m.Name +} + +func (m *MyStruct2) SetName(name string) { + m.Name = name +} + +func NewMyStruct2() *MyStruct2 { // want `constructor "NewMyStruct2" for struct "MyStruct2" should be placed before struct method "GetName"` + return &MyStruct2{Name: "John"} +} + +func NewTime() time.Time { + return time.Now() +} diff --git a/pkg/golinters/funcorder/testdata/funcorder_struct_method.yml b/pkg/golinters/funcorder/testdata/funcorder_struct_method.yml new file mode 100644 index 000000000000..70b27b44f9cd --- /dev/null +++ b/pkg/golinters/funcorder/testdata/funcorder_struct_method.yml @@ -0,0 +1,6 @@ +version: "2" + +linters: + settings: + funcorder: + struct-method: false diff --git a/pkg/lint/lintersdb/builder_linter.go b/pkg/lint/lintersdb/builder_linter.go index a05e0bbd7f4c..5ac3e5ba2fb0 100644 --- a/pkg/lint/lintersdb/builder_linter.go +++ b/pkg/lint/lintersdb/builder_linter.go @@ -29,6 +29,7 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/golinters/fatcontext" "github.com/golangci/golangci-lint/v2/pkg/golinters/forbidigo" "github.com/golangci/golangci-lint/v2/pkg/golinters/forcetypeassert" + "github.com/golangci/golangci-lint/v2/pkg/golinters/funcorder" "github.com/golangci/golangci-lint/v2/pkg/golinters/funlen" "github.com/golangci/golangci-lint/v2/pkg/golinters/gci" "github.com/golangci/golangci-lint/v2/pkg/golinters/ginkgolinter" @@ -256,6 +257,10 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { WithLoadForGoAnalysis(). WithURL("https://github.com/gostaticanalysis/forcetypeassert"), + linter.NewConfig(funcorder.New(&cfg.Linters.Settings.FuncOrder)). + WithSince("v2.1.0"). + WithURL("https://github.com/manuelarte/funcorder"), + linter.NewConfig(fatcontext.New(&cfg.Linters.Settings.Fatcontext)). WithSince("v1.58.0"). WithLoadForGoAnalysis(). From cab8d9b5c146a3f797b0511928c849d5fbd38824 Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Sat, 12 Apr 2025 18:53:14 +0200 Subject: [PATCH 057/152] chore: prepare release --- CHANGELOG.md | 38 + docs/src/docs/welcome/integrations.mdx | 2 + jsonschema/golangci.jsonschema.json | 1 + jsonschema/golangci.v2.0.jsonschema.json | 4738 ++++++++++++++++++++++ 4 files changed, 4779 insertions(+) create mode 100644 jsonschema/golangci.v2.0.jsonschema.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 139fa186e548..d8161a8a8c9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,44 @@ If you value it, consider supporting us, we appreciate it! ❤️ [![Open Collective backers and sponsors](https://img.shields.io/badge/OpenCollective-Donate-blue?logo=opencollective&style=for-the-badge)](https://opencollective.com/golangci-lint) [![GitHub Sponsors](https://img.shields.io/badge/GitHub-Donate-blue?logo=github&style=for-the-badge)](https://github.com/sponsors/golangci) +### v2.1.0 + +1. Enhancements + * Add an option to display absolute paths (`--path-mode=abs`) + * Add configuration path placeholder (`${config-path}`) + * Add `warn-unused` option for `fmt` command + * Colored diff for `fmt` command (`golangci-lint fmt --diff-colored`) +2. New linters + * Add `funcorder` linter https://github.com/manuelarte/funcorder +3. Linters new features or changes + * `go-errorlint`: from 1.7.1 to 1.8.0 (automatic error comparison and type assertion fixes) + * ⚠️ `goconst`: `ignore-strings` is deprecated and replaced by `ignore-string-values` + * `goconst`: from 1.7.1 to 1.8.1 (new options: `find-duplicates`, `eval-const-expressions`) + * `govet`: add `httpmux` analyzer + * `nilnesserr`: from 0.1.2 to 0.2.0 (detect more cases) + * `paralleltest`: from 1.0.10 to 1.0.14 (checks only `_test.go` files) + * `revive`: from 1.7.0 to 1.9.0 (support kebab case for setting names) + * `sloglint`: from 0.9.0 to 0.11.0 (autofix, new option `msg-style`, suggest `slog.DiscardHandler`) + * `wrapcheck`: from 2.10.0 to 2.11.0 (new option `report-internal-errors`) + * `wsl`: from 4.6.0 to 4.7.0 (cgo files are always excluded) +4. Linters bug fixes + * `fatcontext`: from 0.7.1 to 0.7.2 + * `gocritic`: fix `importshadow` checker + * `gosec`: from 2.22.2 to 2.22.3 + * `ireturn`: from 0.3.1 to 0.4.0 + * `loggercheck`: from 0.10.1 to 0.11.0 + * `nakedret`: from 2.0.5 to 2.0.6 + * `nonamedreturns`: from 1.0.5 to 1.0.6 + * `protogetter`: from 0.3.12 to 0.3.13 + * `testifylint`: from 1.6.0 to 1.6.1 + * `unconvert`: update to HEAD +5. Misc. + * Fixes memory leaks when using go1.(N) with golangci-lint built with go1.(N-X) + * Adds `golangci-lint-fmt` pre-commit hook +6. Documentation + * Improvements + * Updates section about vscode integration + ### v2.0.2 1. Misc. diff --git a/docs/src/docs/welcome/integrations.mdx b/docs/src/docs/welcome/integrations.mdx index 11a4889da617..8658e2aa3f5c 100644 --- a/docs/src/docs/welcome/integrations.mdx +++ b/docs/src/docs/welcome/integrations.mdx @@ -20,6 +20,7 @@ Install the [extension](https://marketplace.visualstudio.com/items?itemName=gola ```json "go.lintTool": "golangci-lint", "go.lintFlags": [ + "--path-mode=abs", "--fast-only" ], "go.formatTool": "custom", @@ -47,6 +48,7 @@ And use the following settings: ```json "go.lintTool": "golangci-lint-v2", "go.lintFlags": [ + "--path-mode=abs", "--fast-only" ], "go.formatTool": "custom", diff --git a/jsonschema/golangci.jsonschema.json b/jsonschema/golangci.jsonschema.json index 591551a7eade..437943b5f318 100644 --- a/jsonschema/golangci.jsonschema.json +++ b/jsonschema/golangci.jsonschema.json @@ -665,6 +665,7 @@ }, "tagliatelle-cases": { "enum": [ + "", "camel", "pascal", "kebab", diff --git a/jsonschema/golangci.v2.0.jsonschema.json b/jsonschema/golangci.v2.0.jsonschema.json new file mode 100644 index 000000000000..437943b5f318 --- /dev/null +++ b/jsonschema/golangci.v2.0.jsonschema.json @@ -0,0 +1,4738 @@ +{ + "$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", + "badSyncOnceFunc", + "boolExprSimplify", + "builtinShadow", + "builtinShadowDecl", + "captLocal", + "caseOrder", + "codegenComment", + "commentFormatting", + "commentedOutCode", + "commentedOutImport", + "defaultCaseOrder", + "deferInLoop", + "deferUnlambda", + "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", + "rangeAppendAll", + "rangeExprCopy", + "rangeValCopy", + "redundantSprint", + "regexpMust", + "regexpPattern", + "regexpSimplify", + "returnAfterHttpError", + "ruleguard", + "singleCaseSwitch", + "sliceClear", + "sloppyLen", + "sloppyReassign", + "sloppyTypeAssert", + "sortSlice", + "sprintfQuotedString", + "sqlQuery", + "stringConcatSimplify", + "stringXbytes", + "stringsCompare", + "switchTrue", + "syncMapLoadAndDelete", + "timeExprSimplify", + "todoCommentWithoutDetail", + "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" + ] + }, + "staticcheck-checks": { + "enum": [ + "*", + "all", + "SA*", + "-SA*", + "SA1*", + "-SA1*", + "SA1000", + "-SA1000", + "SA1001", + "-SA1001", + "SA1002", + "-SA1002", + "SA1003", + "-SA1003", + "SA1004", + "-SA1004", + "SA1005", + "-SA1005", + "SA1006", + "-SA1006", + "SA1007", + "-SA1007", + "SA1008", + "-SA1008", + "SA1010", + "-SA1010", + "SA1011", + "-SA1011", + "SA1012", + "-SA1012", + "SA1013", + "-SA1013", + "SA1014", + "-SA1014", + "SA1015", + "-SA1015", + "SA1016", + "-SA1016", + "SA1017", + "-SA1017", + "SA1018", + "-SA1018", + "SA1019", + "-SA1019", + "SA1020", + "-SA1020", + "SA1021", + "-SA1021", + "SA1023", + "-SA1023", + "SA1024", + "-SA1024", + "SA1025", + "-SA1025", + "SA1026", + "-SA1026", + "SA1027", + "-SA1027", + "SA1028", + "-SA1028", + "SA1029", + "-SA1029", + "SA1030", + "-SA1030", + "SA1031", + "-SA1031", + "SA1032", + "-SA1032", + "SA2*", + "-SA2*", + "SA2000", + "-SA2000", + "SA2001", + "-SA2001", + "SA2002", + "-SA2002", + "SA2003", + "-SA2003", + "SA3*", + "-SA3*", + "SA3000", + "-SA3000", + "SA3001", + "-SA3001", + "SA4*", + "-SA4*", + "SA4000", + "-SA4000", + "SA4001", + "-SA4001", + "SA4003", + "-SA4003", + "SA4004", + "-SA4004", + "SA4005", + "-SA4005", + "SA4006", + "-SA4006", + "SA4008", + "-SA4008", + "SA4009", + "-SA4009", + "SA4010", + "-SA4010", + "SA4011", + "-SA4011", + "SA4012", + "-SA4012", + "SA4013", + "-SA4013", + "SA4014", + "-SA4014", + "SA4015", + "-SA4015", + "SA4016", + "-SA4016", + "SA4017", + "-SA4017", + "SA4018", + "-SA4018", + "SA4019", + "-SA4019", + "SA4020", + "-SA4020", + "SA4021", + "-SA4021", + "SA4022", + "-SA4022", + "SA4023", + "-SA4023", + "SA4024", + "-SA4024", + "SA4025", + "-SA4025", + "SA4026", + "-SA4026", + "SA4027", + "-SA4027", + "SA4028", + "-SA4028", + "SA4029", + "-SA4029", + "SA4030", + "-SA4030", + "SA4031", + "-SA4031", + "SA4032", + "-SA4032", + "SA5*", + "-SA5*", + "SA5000", + "-SA5000", + "SA5001", + "-SA5001", + "SA5002", + "-SA5002", + "SA5003", + "-SA5003", + "SA5004", + "-SA5004", + "SA5005", + "-SA5005", + "SA5007", + "-SA5007", + "SA5008", + "-SA5008", + "SA5009", + "-SA5009", + "SA5010", + "-SA5010", + "SA5011", + "-SA5011", + "SA5012", + "-SA5012", + "SA6*", + "-SA6*", + "SA6000", + "-SA6000", + "SA6001", + "-SA6001", + "SA6002", + "-SA6002", + "SA6003", + "-SA6003", + "SA6005", + "-SA6005", + "SA6006", + "-SA6006", + "SA9*", + "-SA9*", + "SA9001", + "-SA9001", + "SA9002", + "-SA9002", + "SA9003", + "-SA9003", + "SA9004", + "-SA9004", + "SA9005", + "-SA9005", + "SA9006", + "-SA9006", + "SA9007", + "-SA9007", + "SA9008", + "-SA9008", + "SA9009", + "-SA9009", + "ST*", + "-ST*", + "ST1*", + "-ST1*", + "ST1000", + "-ST1000", + "ST1001", + "-ST1001", + "ST1003", + "-ST1003", + "ST1005", + "-ST1005", + "ST1006", + "-ST1006", + "ST1008", + "-ST1008", + "ST1011", + "-ST1011", + "ST1012", + "-ST1012", + "ST1013", + "-ST1013", + "ST1015", + "-ST1015", + "ST1016", + "-ST1016", + "ST1017", + "-ST1017", + "ST1018", + "-ST1018", + "ST1019", + "-ST1019", + "ST1020", + "-ST1020", + "ST1021", + "-ST1021", + "ST1022", + "-ST1022", + "ST1023", + "-ST1023", + "S*", + "-S*", + "S1*", + "-S1*", + "S1000", + "-S1000", + "S1001", + "-S1001", + "S1002", + "-S1002", + "S1003", + "-S1003", + "S1004", + "-S1004", + "S1005", + "-S1005", + "S1006", + "-S1006", + "S1007", + "-S1007", + "S1008", + "-S1008", + "S1009", + "-S1009", + "S1010", + "-S1010", + "S1011", + "-S1011", + "S1012", + "-S1012", + "S1016", + "-S1016", + "S1017", + "-S1017", + "S1018", + "-S1018", + "S1019", + "-S1019", + "S1020", + "-S1020", + "S1021", + "-S1021", + "S1023", + "-S1023", + "S1024", + "-S1024", + "S1025", + "-S1025", + "S1028", + "-S1028", + "S1029", + "-S1029", + "S1030", + "-S1030", + "S1031", + "-S1031", + "S1032", + "-S1032", + "S1033", + "-S1033", + "S1034", + "-S1034", + "S1035", + "-S1035", + "S1036", + "-S1036", + "S1037", + "-S1037", + "S1038", + "-S1038", + "S1039", + "-S1039", + "S1040", + "-S1040", + "QF*", + "-QF*", + "QF1*", + "-QF1*", + "QF1001", + "-QF1001", + "QF1002", + "-QF1002", + "QF1003", + "-QF1003", + "QF1004", + "-QF1004", + "QF1005", + "-QF1005", + "QF1006", + "-QF1006", + "QF1007", + "-QF1007", + "QF1008", + "-QF1008", + "QF1009", + "-QF1009", + "QF1010", + "-QF1010", + "QF1011", + "-QF1011", + "QF1012", + "-QF1012" + ] + }, + "gosec-rules": { + "enum": [ + "G101", + "G102", + "G103", + "G104", + "G106", + "G107", + "G108", + "G109", + "G110", + "G111", + "G112", + "G113", + "G114", + "G115", + "G201", + "G202", + "G203", + "G204", + "G301", + "G302", + "G303", + "G304", + "G305", + "G306", + "G307", + "G401", + "G402", + "G403", + "G404", + "G405", + "G406", + "G501", + "G502", + "G503", + "G504", + "G505", + "G506", + "G507", + "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", + "stdversion", + "stringintconv", + "structtag", + "testinggoroutine", + "tests", + "timeformat", + "unmarshal", + "unreachable", + "unsafeptr", + "unusedresult", + "unusedwrite", + "waitgroup" + ] + }, + "revive-rules": { + "enum": [ + "add-constant", + "argument-limit", + "atomic", + "banned-characters", + "bare-return", + "blank-imports", + "bool-literal-in-expr", + "call-to-gc", + "cognitive-complexity", + "comment-spacings", + "comments-density", + "confusing-naming", + "confusing-results", + "constant-logical-expr", + "context-as-argument", + "context-keys-type", + "cyclomatic", + "datarace", + "deep-exit", + "defer", + "dot-imports", + "duplicated-imports", + "early-return", + "empty-block", + "empty-lines", + "enforce-map-style", + "enforce-repeated-arg-type-style", + "enforce-slice-style", + "error-naming", + "error-return", + "error-strings", + "errorf", + "exported", + "file-header", + "file-length-limit", + "filename-format", + "flag-parameter", + "function-length", + "function-result-limit", + "get-return", + "identical-branches", + "if-return", + "import-alias-naming", + "import-shadowing", + "imports-blocklist", + "increment-decrement", + "indent-error-flow", + "line-length-limit", + "max-control-nesting", + "max-public-structs", + "modifies-parameter", + "modifies-value-receiver", + "nested-structs", + "optimize-operands-order", + "package-comments", + "range-val-address", + "range-val-in-closure", + "range", + "receiver-naming", + "redefines-builtin-id", + "redundant-build-tag", + "redundant-import-alias", + "redundant-test-main-exit", + "string-format", + "string-of-int", + "struct-tag", + "superfluous-else", + "time-equal", + "time-naming", + "unchecked-type-assertion", + "unconditional-recursion", + "unexported-naming", + "unexported-return", + "unhandled-error", + "unnecessary-stmt", + "unreachable-code", + "unused-parameter", + "unused-receiver", + "use-any", + "use-errors-new", + "useless-break", + "var-declaration", + "var-naming", + "waitgroup-by-value" + ] + }, + "iface-analyzers": { + "enum": [ + "identical", + "unused", + "opaque" + ] + }, + "tagliatelle-cases": { + "enum": [ + "", + "camel", + "pascal", + "kebab", + "snake", + "goCamel", + "goPascal", + "goKebab", + "goSnake", + "upper", + "upperSnake", + "lower", + "header" + ] + }, + "relative-path-modes": { + "enum": [ + "gomod", + "gitroot", + "cfg", + "wd" + ] + }, + "simple-format": { + "type": "object", + "additionalProperties": false, + "properties": { + "path": { + "$ref": "#/definitions/formats-path", + "default": "stdout" + } + } + }, + "formats-path" : { + "anyOf": [ + { + "enum": [ + "stdout", + "stderr" + ] + }, + { + "type": "string" + } + ] + }, + "linter-names": { + "$comment": "anyOf with enum is used to allow auto-completion of non-custom linters", + "description": "Usable linter names.", + "anyOf": [ + { + "enum": [ + "asasalint", + "asciicheck", + "bidichk", + "bodyclose", + "canonicalheader", + "containedctx", + "contextcheck", + "copyloopvar", + "cyclop", + "decorder", + "depguard", + "dogsled", + "dupl", + "dupword", + "durationcheck", + "errcheck", + "errchkjson", + "errname", + "errorlint", + "exhaustive", + "exhaustruct", + "exptostd", + "fatcontext", + "forbidigo", + "forcetypeassert", + "funlen", + "ginkgolinter", + "gocheckcompilerdirectives", + "gochecknoglobals", + "gochecknoinits", + "gochecksumtype", + "gocognit", + "goconst", + "gocritic", + "gocyclo", + "godot", + "godox", + "err113", + "goheader", + "gomoddirectives", + "gomodguard", + "goprintffuncname", + "gosec", + "gosimple", + "gosmopolitan", + "govet", + "grouper", + "iface", + "importas", + "inamedparam", + "ineffassign", + "interfacebloat", + "intrange", + "ireturn", + "lll", + "loggercheck", + "maintidx", + "makezero", + "mirror", + "misspell", + "mnd", + "musttag", + "nakedret", + "nestif", + "nilerr", + "nilnesserr", + "nilnil", + "nlreturn", + "noctx", + "nolintlint", + "nonamedreturns", + "nosprintfhostport", + "paralleltest", + "perfsprint", + "prealloc", + "predeclared", + "promlinter", + "protogetter", + "reassign", + "recvcheck", + "revive", + "rowserrcheck", + "sloglint", + "sqlclosecheck", + "staticcheck", + "stylecheck", + "tagalign", + "tagliatelle", + "testableexamples", + "testifylint", + "testpackage", + "thelper", + "tparallel", + "unconvert", + "unparam", + "unused", + "usestdlibvars", + "usetesting", + "varnamelen", + "wastedassign", + "whitespace", + "wrapcheck", + "wsl", + "zerologlint" + ] + }, + { + "type": "string" + } + ] + }, + "formatter-names": { + "description": "Usable formatter names.", + "enum": [ + "gci", + "gofmt", + "gofumpt", + "goimports", + "golines" + ] + }, + "settings": { + "definitions": { + "dupwordSettings": { + "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"] + } + } + } + }, + "asasalintSettings": { + "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 + } + } + }, + "bidichkSettings": { + "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 + } + } + }, + "cyclopSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "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 + } + } + }, + "decorderSettings": { + "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" + } + } + }, + "depguardSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "rules": { + "description": "Rules to apply.", + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^[^.]+$": { + "description": "Name of a rule.", + "type": "object", + "additionalProperties": false, + "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.", + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "desc": { + "description": "Description", + "type": "string" + }, + "pkg": { + "description": "Package", + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "dogsledSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "max-blank-identifiers": { + "description": "Check assignments with too many blank identifiers.", + "type": "integer", + "default": 2, + "minimum": 0 + } + } + }, + "duplSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "threshold": { + "description": "Tokens count to trigger issue.", + "type": "integer", + "default": 150, + "minimum": 0 + } + } + }, + "errcheckSettings": { + "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 + }, + "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 + } + } + }, + "errchkjsonSettings": { + "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 + } + } + }, + "errorlintSettings": { + "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 + }, + "allowed-errors": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "err": { + "type": "string" + }, + "fun": { + "type": "string" + } + } + } + }, + "allowed-errors-wildcard": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "err": { + "type": "string" + }, + "fun": { + "type": "string" + } + } + } + } + } + }, + "exhaustiveSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "check": { + "description": "Program elements to check for exhaustiveness.", + "type": "array", + "uniqueItems": true, + "items": { + "type": "string", + "examples": ["switch", "map"] + } + }, + "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 + } + } + }, + "exhaustructSettings": { + "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" + } + } + } + }, + "fatcontextSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "check-struct-pointers": { + "description": "Check for potential fat contexts in struct pointers.", + "type": "boolean", + "default": false + } + } + }, + "forbidigoSettings": { + "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", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "pattern": { + "description": "Pattern", + "type": "string" + }, + "pkg": { + "description": "Package", + "type": "string" + }, + "msg": { + "description": "Message", + "type": "string" + } + } + } + } + } + }, + "funlenSettings": { + "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": true + } + } + }, + "gciSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "sections": { + "description": "Section configuration to compare against.", + "type": "array", + "items": { + "anyOf": [ + { + "enum": [ + "standard", + "default", + "blank", + "dot", + "alias", + "localmodule" + ] + }, + { + "type": "string" + } + ] + }, + "default": ["standard", "default"] + }, + "no-inline-comments": { + "description": "Checks that no inline Comments are present.", + "type": "boolean", + "default": false + }, + "no-prefix-comments": { + "description": "Checks that no prefix Comments(comment lines above an import) are present.", + "type": "boolean", + "default": false + }, + "custom-order": { + "description": "Enable custom order of sections.", + "type": "boolean", + "default": false + }, + "no-lex-order": { + "description": "Drops lexical ordering for custom sections.", + "type": "boolean", + "default": false + } + } + }, + "ginkgolinterSettings": { + "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 + }, + "force-expect-to": { + "description": "Force using `Expect` with `To`, `ToNot` or `NotTo`", + "type": "boolean", + "default": false + }, + "validate-async-intervals": { + "description": "Best effort validation of async intervals (timeout and polling).", + "type": "boolean", + "default": false + }, + "forbid-spec-pollution": { + "description": "Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`.", + "type": "boolean", + "default": false + }, + "force-succeed": { + "description": "Force using the Succeed matcher for error functions, and the HaveOccurred matcher for non-function error values.", + "type": "boolean", + "default": false + } + } + }, + "gochecksumtypeSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "default-signifies-exhaustive": { + "description": "Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.", + "type": "boolean", + "default": true + }, + "include-shared-interfaces": { + "description": "Include shared interfaces in the exhaustiviness check.", + "type": "boolean", + "default": false + } + } + }, + "gocognitSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "min-complexity": { + "description": "Minimal code complexity to report (we recommend 10-20).", + "type": "integer", + "default": 30 + } + } + }, + "goconstSettings": { + "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-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 + } + } + }, + "gocriticSettings": { + "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", + "additionalProperties": false, + "properties": { + "captLocal": { + "type": "object", + "additionalProperties": false, + "properties": { + "paramsOnly" : { + "type": "boolean", + "default": true + } + } + }, + "commentedOutCode": { + "type": "object", + "additionalProperties": false, + "properties": { + "minLength" : { + "type": "number", + "default": 15 + } + } + }, + "elseif": { + "type": "object", + "additionalProperties": false, + "properties": { + "skipBalanced" : { + "type": "boolean", + "default": true + } + } + }, + "hugeParam": { + "type": "object", + "additionalProperties": false, + "properties": { + "sizeThreshold" : { + "type": "number", + "default": 80 + } + } + }, + "ifElseChain": { + "type": "object", + "additionalProperties": false, + "properties": { + "minThreshold" : { + "type": "number", + "default": 2 + } + } + }, + "nestingReduce": { + "type": "object", + "additionalProperties": false, + "properties": { + "bodyWidth" : { + "type": "number", + "default": 5 + } + } + }, + "rangeExprCopy": { + "type": "object", + "additionalProperties": false, + "properties": { + "sizeThreshold" : { + "type": "number", + "default": 512 + }, + "skipTestFuncs" : { + "type": "boolean", + "default": true + } + } + }, + "rangeValCopy": { + "type": "object", + "additionalProperties": false, + "properties": { + "sizeThreshold" : { + "type": "number", + "default": 128 + }, + "skipTestFuncs" : { + "type": "boolean", + "default": true + } + } + }, + "ruleguard": { + "type": "object", + "additionalProperties": false, + "properties": { + "debug" : { + "type": "string" + }, + "enable" : { + "type": "string" + }, + "disable" : { + "type": "string" + }, + "failOn" : { + "type": "string" + }, + "rules" : { + "type": "string" + } + } + }, + "tooManyResultsChecker": { + "type": "object", + "additionalProperties": false, + "properties": { + "maxResults" : { + "type": "number", + "default": 5 + } + } + }, + "truncateCmp": { + "type": "object", + "additionalProperties": false, + "properties": { + "skipArchDependent" : { + "type": "boolean", + "default": true + } + } + }, + "underef": { + "type": "object", + "additionalProperties": false, + "properties": { + "skipRecvDeref" : { + "type": "boolean", + "default": true + } + } + }, + "unnamedResult": { + "type": "object", + "additionalProperties": false, + "properties": { + "checkExported" : { + "type": "boolean", + "default": false + } + } + } + } + }, + "disable-all": { + "type": "boolean", + "default": false + }, + "enable-all": { + "type": "boolean", + "default": false + } + } + }, + "gocycloSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "min-complexity": { + "description": "Minimum code complexity to report (we recommend 10-20).", + "type": "integer", + "default": 30 + } + } + }, + "godotSettings": { + "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 + } + } + }, + "godoxSettings": { + "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"] + } + } + }, + "gofmtSettings": { + "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", + "additionalProperties": false, + "properties": { + "pattern": { + "type": "string" + }, + "replacement": { + "type": "string" + } + } + } + } + } + }, + "golinesSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "max-len": { + "type": "integer", + "default": 100 + }, + "tab-len": { + "type": "integer", + "default": 4 + }, + "shorten-comments": { + "type": "boolean", + "default": false + }, + "reformat-tags": { + "type": "boolean", + "default": true + }, + "chain-split-dots": { + "type": "boolean", + "default": true + } + } + }, + "interfacebloatSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "max": { + "description": "The maximum number of methods allowed for an interface.", + "type": "integer" + } + } + }, + "gofumptSettings": { + "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 + }, + "module-path": { + "description": " Module path which contains the source code being formatted.", + "type": "string" + } + } + }, + "goheaderSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "values": { + "type": "object", + "additionalProperties": false, + "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", + "additionalProperties": false, + "patternProperties": { + "^.+$": { + "type": "string" + } + }, + "examples": [ + { + "AUTHOR": ".*@mycompany\\.com" + } + ] + } + } + }, + "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." + ] + }, + "template-path": { + "description": "Path to the file containing the template source.", + "type": "string", + "examples": ["my_header_template.txt"] + } + }, + "oneOf": [ + { "required": ["template"] }, + { "required": ["template-path"] } + ] + }, + "goimportsSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "local-prefixes": { + "description": "Put imports beginning with prefix after 3rd-party packages. It is a list of prefixes.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "gomoddirectivesSettings": { + "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": false + }, + "exclude-forbidden": { + "description": "Forbid the use of the `exclude` directives.", + "type": "boolean", + "default": false + }, + "toolchain-forbidden": { + "description": "Forbid the use of the `toolchain` directive.", + "type": "boolean", + "default": false + }, + "toolchain-pattern": { + "description": "Defines a pattern to validate `toolchain` directive.", + "type": "string" + }, + "tool-forbidden": { + "description": "Forbid the use of the `tool` directives.", + "type": "boolean", + "default": false + }, + "go-debug-forbidden": { + "description": "Forbid the use of the `godebug` directive.", + "type": "boolean", + "default": false + }, + "go-version-pattern": { + "description": "Defines a pattern to validate `go` minimum version directive.", + "type": "string", + "default": "" + } + } + }, + "gomodguardSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "allowed": { + "type": "object", + "additionalProperties": false, + "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", + "additionalProperties": false, + "properties": { + "modules": { + "description": "List of blocked modules.", + "type": "array", + "items": { + "type": "object", + "patternProperties": { + "^.+$": { + "type": "object", + "additionalProperties": false, + "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", + "additionalProperties": false, + "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 + } + } + } + } + }, + "gosecSettings": { + "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" + } + }, + "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" + } + } + }, + "gosmopolitanSettings": { + "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" + } + }, + "watch-for-scripts": { + "description": "List of Unicode scripts to watch for any usage in string literals.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "govetSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "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 + } + } + }, + "grouperSettings": { + "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 + } + } + }, + "ifaceSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "enable": { + "description": "Enable analyzers by name.", + "type": "array", + "items": { + "$ref": "#/definitions/iface-analyzers" + } + }, + "settings": { + "type": "object", + "additionalProperties": false, + "properties": { + "unused": { + "type": "object", + "additionalProperties": false, + "properties": { + "exclude": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + } + } + }, + "importasSettings": { + "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", + "additionalProperties": false, + "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"] + } + } + } + }, + "inamedparamSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "skip-single-param": { + "description": "Skips check for interface methods with only a single parameter.", + "type": "boolean", + "default": false + } + } + }, + "ireturnSettings": { + "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"] + } + ] + }, + "lllSettings": { + "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 + } + } + }, + "maintidxSettings": { + "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 + } + } + }, + "makezeroSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "always": { + "description": "Allow only slices initialized with a length of zero.", + "type": "boolean", + "default": false + } + } + }, + "loggercheckSettings": { + "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 + }, + "slog": { + "description": "Allow check for the log/slog 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" + } + } + } + }, + "misspellSettings": { + "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-rules": { + "description": "List of rules 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" + } + } + } + } + } + }, + "musttagSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "functions": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "tag": { + "type": "string" + }, + "arg-pos": { + "type": "integer" + } + } + } + } + } + }, + "nakedretSettings": { + "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 + } + } + }, + "nestifSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "min-complexity": { + "description": "Minimum complexity of \"if\" statements to report.", + "type": "integer", + "default": 5 + } + } + }, + "nilnilSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "only-two": { + "type": "boolean", + "description": "To check functions with only two return values.", + "default": true + }, + "detect-opposite": { + "type": "boolean", + "description": "In addition, detect opposite situation (simultaneous return of non-nil error and valid value).", + "default": false + }, + "checked-types": { + "type": "array", + "description": "List of return types to check.", + "items": { + "enum": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"] + }, + "default": ["chan", "func", "iface", "map", "ptr", "uintptr", "unsafeptr"] + } + } + }, + "nlreturnSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "block-size": { + "description": "set block size that is still ok", + "type": "number", + "default": 0, + "minimum": 0 + } + } + }, + "mndSettings": { + "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" + ] + } + } + } + }, + "nolintlintSettings": { + "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/linter-names" + }, + "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 + } + } + }, + "reassignSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "patterns": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "recvcheckSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "disable-builtin": { + "description": "Disables the built-in method exclusions.", + "type": "boolean", + "default": true + }, + "exclusions": { + "description": "User-defined method exclusions.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "nonamedreturnsSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "report-error-in-defer": { + "description": "Report named error if it is assigned inside defer.", + "type": "boolean", + "default": false + } + } + }, + "paralleltestSettings": { + "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 + } + } + }, + "perfsprintSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "integer-format": { + "description": "Enable/disable optimization of integer formatting.", + "type": "boolean", + "default": true + }, + "int-conversion": { + "description": "Optimizes even if it requires an int or uint type cast.", + "type": "boolean", + "default": true + }, + "error-format": { + "description": "Enable/disable optimization of error formatting.", + "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 + }, + "string-format": { + "description": "Enable/disable optimization of string formatting.", + "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 + }, + "bool-format": { + "description": "Enable/disable optimization of bool formatting.", + "type": "boolean", + "default": true + }, + "hex-format": { + "description": "Enable/disable optimization of hex formatting.", + "type": "boolean", + "default": true + } + } + }, + "preallocSettings": { + "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 + } + } + }, + "predeclaredSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "ignore": { + "description": "List of predeclared identifiers to not report on.", + "type": "array", + "items": { + "type": "string" + } + }, + "qualified-name": { + "description": "Include method names and field names in checks.", + "type": "boolean", + "default": false + } + } + }, + "promlinterSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "strict": {}, + "disabled-linters": { + "type": "array", + "items": { + "enum": [ + "Help", + "MetricUnits", + "Counter", + "HistogramSummaryReserved", + "MetricTypeInName", + "ReservedChars", + "CamelCase", + "UnitAbbreviations" + ] + } + } + } + }, + "protogetterSettings": { + "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 + } + } + }, + "reviveSettings": { + "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" + }, + "confidence": { + "type": "number" + }, + "severity": { + "type": "string", + "enum": ["warning", "error"] + }, + "enable-all-rules": { + "type": "boolean", + "default": false + }, + "directives": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "enum": ["specify-disable-reason"] + }, + "severity": { + "type": "string", + "enum": ["warning", "error"] + }, + "exclude": { + "type": "array", + "items": { + "type": "string" + } + }, + "arguments": { + "type": "array" + } + } + } + }, + "rules": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["name"], + "properties": { + "name": { + "$ref": "#/definitions/revive-rules", + "title": "The rule name" + }, + "disabled": { + "type": "boolean" + }, + "severity": { + "type": "string", + "enum": ["warning", "error"] + }, + "exclude": { + "type": "array", + "items": { + "type": "string" + } + }, + "arguments": { + "type": "array" + } + } + } + } + } + }, + "rowserrcheckSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "packages": { + "type": "array", + "items": { + "description": "", + "type": "string", + "examples": ["github.com/jmoiron/sqlx"] + } + } + } + }, + "sloglintSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "kv-only": { + "description": "Enforce using key-value pairs only (incompatible with attr-only).", + "type": "boolean", + "default": false + }, + "no-global": { + "description": "Enforce not using global loggers.", + "enum": ["", "all", "default"], + "default": "" + }, + "no-mixed-args": { + "description": "Enforce not mixing key-value pairs and attributes.", + "type": "boolean", + "default": true + }, + "context": { + "description": "Enforce using methods that accept a context.", + "enum": ["", "all", "scope"], + "default": "" + }, + "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 + }, + "forbidden-keys": { + "description": "Enforce not using specific keys.", + "type": "array", + "items": { + "type": "string" + } + }, + "args-on-sep-lines": { + "description": "Enforce putting arguments on separate lines.", + "type": "boolean", + "default": false + } + } + }, + "spancheckSettings": { + "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" + } + }, + "extra-start-span-signatures": { + "description": "A list of regexes for additional function signatures that create spans.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "staticcheckSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "checks": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/staticcheck-checks" + }, + { + "type": "string" + } + ] + } + }, + "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" + ] + } + } + } + }, + "tagalignSettings": { + "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 + } + } + }, + "tagliatelleSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "case": { + "type": "object", + "additionalProperties": false, + "properties": { + "use-field-name": { + "description": "Use the struct field name to check the name of the struct tag.", + "type": "boolean", + "default": false + }, + "ignored-fields": { + "description": "The field names to ignore.", + "type": "array", + "items": { + "type": "string", + "examples": ["example"] + } + }, + "rules": { + "type": "object", + "patternProperties": { + "^.+$": { + "$ref": "#/definitions/tagliatelle-cases" + } + } + }, + "extended-rules": { + "description": "Defines the association between tag name and case.", + "type": "object", + "patternProperties": { + "^.+$": { + "type": "object", + "additionalProperties": false, + "required": ["case"], + "properties": { + "case": { + "$ref": "#/definitions/tagliatelle-cases" + }, + "extra-initialisms": { + "type": "boolean", + "default": false + }, + "initialism-overrides": { + "type": "object", + "patternProperties": { + "^.+$": { + "type": "boolean", + "default": false + } + } + } + } + } + } + }, + "overrides": { + "description": "Overrides the default/root configuration.", + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["pkg"], + "properties": { + "pkg": { + "description": "A package path.", + "type": "string" + }, + "use-field-name": { + "description": "Use the struct field name to check the name of the struct tag.", + "type": "boolean", + "default": false + }, + "ignored-fields": { + "description": "The field names to ignore.", + "type": "array", + "items": { + "type": "string", + "examples": ["example"] + } + }, + "ignore": { + "description": "Ignore the package (takes precedence over all other configurations).", + "type": "boolean", + "default": false + }, + "rules": { + "type": "object", + "patternProperties": { + "^.+$": { + "$ref": "#/definitions/tagliatelle-cases" + } + } + }, + "extended-rules": { + "description": "Defines the association between tag name and case.", + "type": "object", + "patternProperties": { + "^.+$": { + "type": "object", + "additionalProperties": false, + "required": ["case"], + "properties": { + "case": { + "$ref": "#/definitions/tagliatelle-cases" + }, + "extra-initialisms": { + "type": "boolean", + "default": false + }, + "initialism-overrides": { + "type": "object", + "patternProperties": { + "^.+$": { + "type": "boolean", + "default": false + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "testifylintSettings": { + "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", + "contains", + "empty", + "encoded-compare", + "equal-values", + "error-is-as", + "error-nil", + "expected-actual", + "float-compare", + "formatter", + "go-require", + "len", + "negative-positive", + "nil-compare", + "regexp", + "require-error", + "suite-broken-parallel", + "suite-dont-use-pkg", + "suite-extra-assert-call", + "suite-method-signature", + "suite-subtest-run", + "suite-thelper", + "useless-assert" + ] + }, + "default": [ + "blank-import", + "bool-compare", + "compares", + "contains", + "empty", + "encoded-compare", + "equal-values", + "error-is-as", + "error-nil", + "expected-actual", + "float-compare", + "formatter", + "go-require", + "len", + "negative-positive", + "nil-compare", + "regexp", + "require-error", + "suite-broken-parallel", + "suite-dont-use-pkg", + "suite-extra-assert-call", + "suite-method-signature", + "suite-subtest-run", + "useless-assert" + ] + }, + "disable": { + "description": "Disable specific checkers.", + "type": "array", + "items": { + "enum": [ + "blank-import", + "bool-compare", + "compares", + "contains", + "empty", + "encoded-compare", + "equal-values", + "error-is-as", + "error-nil", + "expected-actual", + "float-compare", + "formatter", + "go-require", + "len", + "negative-positive", + "nil-compare", + "regexp", + "require-error", + "suite-broken-parallel", + "suite-dont-use-pkg", + "suite-extra-assert-call", + "suite-method-signature", + "suite-subtest-run", + "suite-thelper", + "useless-assert" + ], + "default": [ + "suite-thelper" + ] + } + }, + "bool-compare": { + "type": "object", + "additionalProperties": false, + "properties": { + "ignore-custom-types": { + "description": "To ignore user defined types (over builtin bool).", + "type": "boolean", + "default": false + } + } + }, + "expected-actual": { + "type": "object", + "additionalProperties": false, + "properties": { + "pattern": { + "description": "Regexp for expected variable name.", + "type": "string", + "default": "(^(exp(ected)?|want(ed)?)([A-Z]\\w*)?$)|(^(\\w*[a-z])?(Exp(ected)?|Want(ed)?)$)" + } + } + }, + "formatter": { + "type": "object", + "additionalProperties": false, + "properties": { + "check-format-string": { + "description": "To enable go vet's printf checks.", + "type": "boolean", + "default": true + }, + "require-f-funcs": { + "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.", + "type": "boolean", + "default": false + }, + "require-string-msg": { + "description": "To require that the first element of msgAndArgs (msg) has a string type.", + "type": "boolean", + "default": true + } + } + }, + "go-require": { + "type": "object", + "additionalProperties": false, + "properties": { + "ignore-http-handlers": { + "description": "To ignore HTTP handlers (like http.HandlerFunc).", + "type": "boolean", + "default": false + } + } + }, + "require-error": { + "type": "object", + "additionalProperties": false, + "properties": { + "fn-pattern": { + "description": "Regexp for assertions to analyze. If defined, then only matched error assertions will be reported.", + "type": "string", + "default": "" + } + } + }, + "suite-extra-assert-call": { + "type": "object", + "additionalProperties": false, + "properties": { + "mode": { + "description": "To require or remove extra Assert() call?", + "type": "string", + "enum": ["remove", "require"], + "default": "remove" + } + } + } + } + }, + "testpackageSettings": { + "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"] + } + } + } + }, + "thelperSettings": { + "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", + "additionalProperties": false, + "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", + "additionalProperties": false, + "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", + "additionalProperties": false, + "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" + } + } + } + } + }, + "usestdlibvarsSettings": { + "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 + }, + "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 + } + } + }, + "usetestingSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "context-background": { + "type": "boolean", + "default": true + }, + "context-todo": { + "type": "boolean", + "default": true + }, + "os-chdir": { + "type": "boolean", + "default": true + }, + "os-mkdir-temp": { + "type": "boolean", + "default": true + }, + "os-setenv": { + "type": "boolean", + "default": true + }, + "os-create-temp": { + "type": "boolean", + "default": true + }, + "os-temp-dir": { + "type": "boolean", + "default": false + } + } + }, + "unconvertSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "fast-math": { + "type": "boolean", + "default": false + }, + "safe": { + "type": "boolean", + "default": false + } + } + }, + "unparamSettings": { + "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 + } + } + }, + "unusedSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "field-writes-are-uses": { + "description": "", + "type": "boolean", + "default": true + }, + "post-statements-are-reads": { + "description": "", + "type": "boolean", + "default": false + }, + "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 + } + } + }, + "varnamelenSettings": { + "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"] + ] + } + } + }, + "whitespaceSettings": { + "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 + } + } + }, + "wrapcheckSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "extra-ignore-sigs": { + "description": "An array of strings specifying additional substrings of signatures to ignore.", + "default": [ + ".CustomError(", + ".SpecificWrap(" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "ignore-sigs": { + "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" + } + }, + "ignore-sig-regexps": { + "description": "An array of strings which specify regular expressions of signatures to ignore.", + "default": [""], + "type": "array", + "items": { + "type": "string" + } + }, + "ignore-package-globs": { + "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" + } + }, + "ignore-interface-regexps": { + "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" + } + } + } + }, + "wslSettings": { + "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-cuddle-used-in-block": { + "description": "Allow cuddling with any block as long as the variable is used somewhere in the block", + "type": "boolean", + "default": false + }, + "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 + } + } + }, + "copyloopvarSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "check-alias": { + "type": "boolean", + "default": false + } + } + }, + "customSettings": { + "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" + } + }, + "oneOf": [ + { + "properties": { + "type": {"enum": ["module"] } + }, + "required": ["type"] + }, + { + "required": ["path"] + } + ] + } + } + } + } + } + }, + "type": "object", + "additionalProperties": false, + "required": ["version"], + "properties": { + "version": { + "type": "string", + "default": "2" + }, + "run": { + "description": "Options for analysis running,", + "type": "object", + "additionalProperties": false, + "properties": { + "concurrency": { + "description": "Number of concurrent runners. Defaults to the number of available CPU cores.", + "type": "integer", + "minimum": 0, + "examples": [4] + }, + "timeout": { + "description": "Timeout for the analysis.", + "type": "string", + "pattern": "^((\\d+h)?(\\d+m)?(\\d+(?:\\.\\d)?s)?|0)$", + "default": "1m", + "examples": ["30s", "5m", "5m30s"] + }, + "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"]] + }, + "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" + }, + "relative-path-mode": { + "description": "The mode used to evaluate relative paths.", + "type": "string", + "$ref": "#/definitions/relative-path-modes", + "default": "wd" + } + } + }, + "output": { + "description": "Output configuration options.", + "type": "object", + "additionalProperties": false, + "properties": { + "formats": { + "description": "Output formats to use.", + "type": "object", + "additionalProperties": false, + "properties": { + "text": { + "type": "object", + "additionalProperties": false, + "properties": { + "path": { + "$ref": "#/definitions/formats-path", + "default": "stdout" + }, + "print-linter-name": { + "type": "boolean", + "default": true + }, + "print-issued-lines": { + "type": "boolean", + "default": true + }, + "colors": { + "type": "boolean", + "default": true + } + } + }, + "json": { + "$ref": "#/definitions/simple-format" + }, + "tab": { + "type": "object", + "additionalProperties": false, + "properties": { + "path": { + "$ref": "#/definitions/formats-path", + "default": "stdout" + }, + "print-linter-name": { + "type": "boolean", + "default": true + }, + "colors": { + "type": "boolean", + "default": true + } + } + }, + "html": { + "$ref": "#/definitions/simple-format" + }, + "checkstyle": { + "$ref": "#/definitions/simple-format" + }, + "code-climate": { + "$ref": "#/definitions/simple-format" + }, + "junit-xml": { + "type": "object", + "additionalProperties": false, + "properties": { + "path": { + "$ref": "#/definitions/formats-path", + "default": "stdout" + }, + "extended": { + "type": "boolean", + "default": true + } + } + }, + "teamcity": { + "$ref": "#/definitions/simple-format" + }, + "sarif": { + "$ref": "#/definitions/simple-format" + } + } + }, + "path-prefix": { + "description": "Add a prefix to the output file references.", + "type": "string", + "default": "" + }, + "show-stats": { + "description": "Show statistics per linter.", + "type": "boolean", + "default": true + }, + "sort-order": { + "type": "array", + "items": { + "enum": ["linter", "severity", "file"] + } + } + } + }, + "linters": { + "type": "object", + "additionalProperties": false, + "properties": { + "default": { + "enum": [ + "standard", + "all", + "none", + "fast" + ] + }, + "enable": { + "description": "List of enabled linters.", + "type": "array", + "items": { + "$ref": "#/definitions/linter-names" + } + }, + "disable": { + "description": "List of disabled linters.", + "type": "array", + "items": { + "$ref": "#/definitions/linter-names" + } + }, + "settings": { + "description": "All available settings of specific linters.", + "type": "object", + "additionalProperties": false, + "properties": { + "dupword": { + "$ref": "#/definitions/settings/definitions/dupwordSettings" + }, + "asasalint": { + "$ref": "#/definitions/settings/definitions/asasalintSettings" + }, + "bidichk": { + "$ref": "#/definitions/settings/definitions/bidichkSettings" + }, + "cyclop": { + "$ref": "#/definitions/settings/definitions/cyclopSettings" + }, + "decorder": { + "$ref": "#/definitions/settings/definitions/decorderSettings" + }, + "depguard":{ + "$ref": "#/definitions/settings/definitions/depguardSettings" + }, + "dogsled": { + "$ref": "#/definitions/settings/definitions/dogsledSettings" + }, + "dupl": { + "$ref": "#/definitions/settings/definitions/duplSettings" + }, + "errcheck": { + "$ref": "#/definitions/settings/definitions/errcheckSettings" + }, + "errchkjson": { + "$ref": "#/definitions/settings/definitions/errchkjsonSettings" + }, + "errorlint": { + "$ref": "#/definitions/settings/definitions/errorlintSettings" + }, + "exhaustive": { + "$ref": "#/definitions/settings/definitions/exhaustiveSettings" + }, + "exhaustruct": { + "$ref": "#/definitions/settings/definitions/exhaustructSettings" + }, + "fatcontext": { + "$ref": "#/definitions/settings/definitions/fatcontextSettings" + }, + "forbidigo": { + "$ref": "#/definitions/settings/definitions/forbidigoSettings" + }, + "funlen": { + "$ref": "#/definitions/settings/definitions/funlenSettings" + }, + "ginkgolinter": { + "$ref": "#/definitions/settings/definitions/ginkgolinterSettings" + }, + "gochecksumtype": { + "$ref": "#/definitions/settings/definitions/gochecksumtypeSettings" + }, + "gocognit": { + "$ref": "#/definitions/settings/definitions/gocognitSettings" + }, + "goconst": { + "$ref": "#/definitions/settings/definitions/goconstSettings" + }, + "gocritic": { + "$ref": "#/definitions/settings/definitions/gocriticSettings" + }, + "gocyclo": { + "$ref": "#/definitions/settings/definitions/gocycloSettings" + }, + "godot": { + "$ref": "#/definitions/settings/definitions/godotSettings" + }, + "godox": { + "$ref": "#/definitions/settings/definitions/godoxSettings" + }, + "interfacebloat":{ + "$ref": "#/definitions/settings/definitions/interfacebloatSettings" + }, + "goheader": { + "$ref": "#/definitions/settings/definitions/goheaderSettings" + }, + "gomoddirectives": { + "$ref": "#/definitions/settings/definitions/gomoddirectivesSettings" + }, + "gomodguard": { + "$ref": "#/definitions/settings/definitions/gomodguardSettings" + }, + "gosec": { + "$ref": "#/definitions/settings/definitions/gosecSettings" + }, + "gosmopolitan": { + "$ref": "#/definitions/settings/definitions/gosmopolitanSettings" + }, + "govet": { + "$ref": "#/definitions/settings/definitions/govetSettings" + }, + "grouper": { + "$ref": "#/definitions/settings/definitions/grouperSettings" + }, + "iface": { + "$ref": "#/definitions/settings/definitions/ifaceSettings" + }, + "importas": { + "$ref": "#/definitions/settings/definitions/importasSettings" + }, + "inamedparam": { + "$ref": "#/definitions/settings/definitions/inamedparamSettings" + }, + "ireturn": { + "$ref": "#/definitions/settings/definitions/ireturnSettings" + }, + "lll": { + "$ref": "#/definitions/settings/definitions/lllSettings" + }, + "maintidx": { + "$ref": "#/definitions/settings/definitions/maintidxSettings" + }, + "makezero":{ + "$ref": "#/definitions/settings/definitions/makezeroSettings" + }, + "loggercheck": { + "$ref": "#/definitions/settings/definitions/loggercheckSettings" + }, + "misspell": { + "$ref": "#/definitions/settings/definitions/misspellSettings" + }, + "musttag": { + "$ref": "#/definitions/settings/definitions/musttagSettings" + }, + "nakedret": { + "$ref": "#/definitions/settings/definitions/nakedretSettings" + }, + "nestif": { + "$ref": "#/definitions/settings/definitions/nestifSettings" + }, + "nilnil": { + "$ref": "#/definitions/settings/definitions/nilnilSettings" + }, + "nlreturn": { + "$ref": "#/definitions/settings/definitions/nlreturnSettings" + }, + "mnd": { + "$ref": "#/definitions/settings/definitions/mndSettings" + }, + "nolintlint":{ + "$ref": "#/definitions/settings/definitions/nolintlintSettings" + }, + "reassign": { + "$ref": "#/definitions/settings/definitions/reassignSettings" + }, + "recvcheck": { + "$ref": "#/definitions/settings/definitions/recvcheckSettings" + }, + "nonamedreturns": { + "$ref": "#/definitions/settings/definitions/nonamedreturnsSettings" + }, + "paralleltest": { + "$ref": "#/definitions/settings/definitions/paralleltestSettings" + }, + "perfsprint": { + "$ref": "#/definitions/settings/definitions/perfsprintSettings" + }, + "prealloc": { + "$ref": "#/definitions/settings/definitions/preallocSettings" + }, + "predeclared": { + "$ref": "#/definitions/settings/definitions/predeclaredSettings" + }, + "promlinter": { + "$ref": "#/definitions/settings/definitions/promlinterSettings" + }, + "protogetter": { + "$ref": "#/definitions/settings/definitions/protogetterSettings" + }, + "revive": { + "$ref": "#/definitions/settings/definitions/reviveSettings" + }, + "rowserrcheck": { + "$ref": "#/definitions/settings/definitions/rowserrcheckSettings" + }, + "sloglint": { + "$ref": "#/definitions/settings/definitions/sloglintSettings" + }, + "spancheck": { + "$ref": "#/definitions/settings/definitions/spancheckSettings" + }, + "staticcheck":{ + "$ref": "#/definitions/settings/definitions/staticcheckSettings" + }, + "tagalign": { + "$ref": "#/definitions/settings/definitions/tagalignSettings" + }, + "tagliatelle": { + "$ref": "#/definitions/settings/definitions/tagliatelleSettings" + }, + "testifylint": { + "$ref": "#/definitions/settings/definitions/testifylintSettings" + }, + "testpackage": { + "$ref": "#/definitions/settings/definitions/testpackageSettings" + }, + "thelper": { + "$ref": "#/definitions/settings/definitions/thelperSettings" + }, + "usestdlibvars": { + "$ref": "#/definitions/settings/definitions/usestdlibvarsSettings" + }, + "usetesting": { + "$ref": "#/definitions/settings/definitions/usetestingSettings" + }, + "unconvert": { + "$ref": "#/definitions/settings/definitions/unconvertSettings" + }, + "unparam": { + "$ref": "#/definitions/settings/definitions/unparamSettings" + }, + "unused": { + "$ref": "#/definitions/settings/definitions/unusedSettings" + }, + "varnamelen": { + "$ref": "#/definitions/settings/definitions/varnamelenSettings" + }, + "whitespace": { + "$ref": "#/definitions/settings/definitions/whitespaceSettings" + }, + "wrapcheck": { + "$ref": "#/definitions/settings/definitions/wrapcheckSettings" + }, + "wsl": { + "$ref": "#/definitions/settings/definitions/wslSettings" + }, + "copyloopvar": { + "$ref": "#/definitions/settings/definitions/copyloopvarSettings" + }, + "custom":{ + "$ref": "#/definitions/settings/definitions/customSettings" + } + } + }, + "exclusions":{ + "type": "object", + "additionalProperties": false, + "properties": { + "generated": { + "enum": ["strict", "lax", "disable"], + "default": "strict" + }, + "warn-unused": { + "type": "boolean", + "default": false + }, + "presets": { + "type": "array", + "items": { + "enum": [ + "comments", + "std-error-handling", + "common-false-positives", + "legacy" + ] + } + }, + "rules": { + "type": "array", + "items": { + "type": "object", + "properties": { + "path": { + "type": "string" + }, + "path-except": { + "type": "string" + }, + "linters": { + "type": "array", + "items": { + "$ref": "#/definitions/linter-names" + } + }, + "text": { + "type": "string" + }, + "source": { + "type": "string" + } + }, + "anyOf": [ + { "required": ["path"] }, + { "required": ["path-except"] }, + { "required": ["linters"] }, + { "required": ["text"] }, + { "required": ["source"] } + ] + } + }, + "paths": { + "type": "array", + "items": { + "type": "string" + } + }, + "paths-except": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "formatters": { + "type": "object", + "additionalProperties": false, + "properties": { + "enable": { + "description": "List of enabled formatters.", + "type": "array", + "items": { + "$ref": "#/definitions/formatter-names" + } + }, + "settings": { + "type": "object", + "additionalProperties": false, + "properties": { + "gci": { + "$ref": "#/definitions/settings/definitions/gciSettings" + }, + "gofmt": { + "$ref": "#/definitions/settings/definitions/gofmtSettings" + }, + "gofumpt": { + "$ref": "#/definitions/settings/definitions/gofumptSettings" + }, + "goimports": { + "$ref": "#/definitions/settings/definitions/goimportsSettings" + }, + "golines": { + "$ref": "#/definitions/settings/definitions/golinesSettings" + } + } + }, + "exclusions": { + "type": "object", + "additionalProperties": false, + "properties": { + "generated": { + "enum": ["strict", "lax", "disable"], + "default": "strict" + }, + "paths": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "issues": { + "type": "object", + "additionalProperties": false, + "properties": { + "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-merge-base": { + "description": "Show only new issues created after the best common ancestor (merge-base against HEAD).", + "type": "string" + }, + "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 + }, + "uniq-by-line": { + "description": "Make issues output unique by line.", + "type": "boolean", + "default": true + }, + "whole-files": { + "description": "Show issues in any part of update files (requires new-from-rev or new-from-patch).", + "type": "boolean", + "default": false + } + } + }, + "severity": { + "type": "object", + "additionalProperties": false, + "properties": { + "default": { + "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": "" + }, + "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": { + "type": "object", + "additionalProperties": false, + "properties": { + "severity": { + "type": "string" + }, + "path": { + "type": "string" + }, + "path-except": { + "type": "string" + }, + "linters": { + "type": "array", + "items": { + "$ref": "#/definitions/linter-names" + } + }, + "text": { + "type": "string" + }, + "source": { + "type": "string" + } + }, + "required": ["severity"], + "anyOf": [ + { "required": ["path"] }, + { "required": ["path-except"] }, + { "required": ["linters"] }, + { "required": ["text"] }, + { "required": ["source"] } + ] + }, + "default": [] + } + }, + "required": ["default"] + } + } +} From 16162127c3536857fb165cbe6c6a2ab64cfea349 Mon Sep 17 00:00:00 2001 From: GolangCI-Lint Releaser <65486276+golangci-releaser@users.noreply.github.com> Date: Sat, 12 Apr 2025 19:35:32 +0200 Subject: [PATCH 058/152] docs: update GitHub Action assets (#5723) --- assets/github-action-config-v1.json | 3 +++ assets/github-action-config-v2.json | 5 ++++- assets/github-action-config.json | 3 +++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/assets/github-action-config-v1.json b/assets/github-action-config-v1.json index 596dfd69ba75..28c21d7b0786 100644 --- a/assets/github-action-config-v1.json +++ b/assets/github-action-config-v1.json @@ -191,6 +191,9 @@ }, "v2.0": { "Error": "golangci-lint version 'v2.0' isn't supported: only v1 versions are supported" + }, + "v2.1": { + "Error": "golangci-lint version 'v2.1' isn't supported: only v1 versions are supported" } } } diff --git a/assets/github-action-config-v2.json b/assets/github-action-config-v2.json index 8ef161513b62..a0a27322f486 100644 --- a/assets/github-action-config-v2.json +++ b/assets/github-action-config-v2.json @@ -1,7 +1,7 @@ { "MinorVersionToConfig": { "latest": { - "TargetVersion": "v2.0.2" + "TargetVersion": "v2.1.0" }, "v1.10": { "Error": "golangci-lint version 'v1.10' isn't supported: we support only v2.0.0 and later versions" @@ -191,6 +191,9 @@ }, "v2.0": { "TargetVersion": "v2.0.2" + }, + "v2.1": { + "TargetVersion": "v2.1.0" } } } diff --git a/assets/github-action-config.json b/assets/github-action-config.json index 596dfd69ba75..28c21d7b0786 100644 --- a/assets/github-action-config.json +++ b/assets/github-action-config.json @@ -191,6 +191,9 @@ }, "v2.0": { "Error": "golangci-lint version 'v2.0' isn't supported: only v1 versions are supported" + }, + "v2.1": { + "Error": "golangci-lint version 'v2.1' isn't supported: only v1 versions are supported" } } } From cb0ee160c341cc1b6f7748b76e5d056cf8eeeb63 Mon Sep 17 00:00:00 2001 From: GolangCI-Lint Releaser <65486276+golangci-releaser@users.noreply.github.com> Date: Sat, 12 Apr 2025 19:54:56 +0200 Subject: [PATCH 059/152] docs: update documentation assets (#5722) Co-authored-by: Fernandez Ludovic --- .golangci.reference.yml | 179 +++++++++++++--------- assets/cli-help.json | 4 +- assets/linters-info.json | 19 ++- jsonschema/golangci.jsonschema.json | 58 ++++++- jsonschema/golangci.next.jsonschema.json | 1 + jsonschema/golangci.v1.64.jsonschema.json | 1 + 6 files changed, 183 insertions(+), 79 deletions(-) diff --git a/.golangci.reference.yml b/.golangci.reference.yml index 446e06780a00..cababbea228f 100644 --- a/.golangci.reference.yml +++ b/.golangci.reference.yml @@ -43,6 +43,7 @@ linters: - fatcontext - forbidigo - forcetypeassert + - funcorder - funlen - ginkgolinter - gocheckcompilerdirectives @@ -121,7 +122,7 @@ linters: - wsl - zerologlint - # Disable specific linter + # Disable specific linter. # https://golangci-lint.run/usage/linters/#disabled-by-default disable: - asasalint @@ -150,6 +151,7 @@ linters: - fatcontext - forbidigo - forcetypeassert + - funcorder - funlen - ginkgolinter - gocheckcompilerdirectives @@ -266,7 +268,7 @@ linters: # Default: 10 max-complexity: 10 # The maximal average package complexity. - # If it's higher than 0.0 (float) the check is enabled + # If it's higher than 0.0 (float) the check is enabled. # Default: 0.0 package-average: 0.5 @@ -279,7 +281,7 @@ linters: - var - func - # If true, underscore vars (vars with "_" as the name) will be ignored at all checks + # 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 @@ -295,15 +297,15 @@ linters: # Default: true (disabled) disable-dec-num-check: false - # If true, type declarations will be ignored for dec num check + # 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 + # 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 + # If true, var declarations will be ignored for dec num check. # Default: false (var statements are not ignored) disable-var-dec-num-check: false @@ -335,6 +337,7 @@ linters: # List of file globs that will match this list of settings to compare against. # By default, if a path is relative, it is relative to the directory where the golangci-lint command is executed. # The placeholder '${base-path}' is substituted with a path relative to the mode defined with `run.relative-path-mode`. + # The placeholder '${config-path}' is substituted with a path relative to the configuration file. # Default: $all files: - "!**/*_a _file.go" @@ -428,7 +431,7 @@ linters: # 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) + # 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. @@ -508,7 +511,7 @@ linters: # Optional message that gets included in error reports. - pattern: ^fmt\.Print.*$ msg: Do not commit print statements. - # Alternatively, put messages at the end of the regex, surrounded by `(# )?` + # Alternatively, put messages at the end of the regex, surrounded by `(# )?`. # Escape any special characters. Those messages get included in error reports. - pattern: 'fmt\.Print.*(# Do not commit print statements\.)?' # Forbid spew Dump, whether it is called as function or method. @@ -529,6 +532,14 @@ linters: # Default: false analyze-types: true + funcorder: + # Checks that constructors are placed after the structure declaration. + # Default: true + constructor: false + # Checks if the exported methods of a structure are placed before the non-exported ones. + # Default: true + struct-method: false + funlen: # Checks the number of lines in a function. # If lower than 0, disable the check. @@ -563,11 +574,11 @@ linters: # Default: false suppress-async-assertion: true - # Suppress warning for comparing values from different types, like `int32` and `uint32` + # 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` + # Trigger warning for ginkgo focus containers like `FDescribe`, `FContext`, `FWhen` or `FIt`. # Default: false forbid-focus-container: true @@ -581,7 +592,7 @@ linters: force-expect-to: true # Best effort validation of async intervals (timeout and polling). - # Ignored the suppress-async-assertion is true. + # Ignored the `suppress-async-assertion` is true. # Default: false validate-async-intervals: true @@ -597,7 +608,7 @@ linters: # Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed. # Default: true default-signifies-exhaustive: false - # Include shared interfaces in the exhaustiviness check. + # Include shared interfaces in the exhaustiveness check. # Default: false include-shared-interfaces: true @@ -619,10 +630,10 @@ linters: # Search also for duplicated numbers. # Default: false numbers: true - # Minimum value, only works with goconst.numbers + # Minimum value, only works with `goconst.numbers`. # Default: 3 min: 2 - # Maximum value, only works with goconst.numbers + # Maximum value, only works with `goconst.numbers`. # Default: 3 max: 2 # Ignore when constant is not used as function argument. @@ -630,7 +641,14 @@ linters: ignore-calls: false # Exclude strings matching the given regular expression. # Default: "" - ignore-strings: 'foo.+' + ignore-string-values: + - 'foo.+' + # Detects constants with identical values. + # Default: false + find-duplicates: true + # Evaluates of constant expressions like Prefix + "suffix". + # Default: false + eval-const-expressions: true gocritic: # Disable all checks. @@ -1095,7 +1113,7 @@ linters: # 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.com/overview. + # The list of supported checkers can be found at https://go-critic.com/overview. settings: # Must be valid enabled check name. captLocal: @@ -1161,6 +1179,7 @@ linters: # Comma-separated list of file paths containing ruleguard rules. # By default, if a path is relative, it is relative to the directory where the golangci-lint command is executed. # The placeholder '${base-path}' is substituted with a path relative to the mode defined with `run.relative-path-mode`. + # The placeholder '${config-path}' is substituted with a path relative to the configuration file. # Glob patterns such as 'rules-*.go' may be specified. # Default: "" rules: '${base-path}/ruleguard/rules-*.go,${base-path}/myrule1.go' @@ -1234,19 +1253,19 @@ linters: # for example: AUTHOR: .*@mycompany\.com # The template used for checking. - # Put here copyright header template for source code files + # Put here copyright header template for source code files. # Note: {{ YEAR }} is a builtin value that returns the year relative to the current machine time. # Default: "" template: |- {{ 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. @@ -1256,6 +1275,7 @@ linters: # Useful if you need to load the template from a specific file. # By default, if a path is relative, it is relative to the directory where the golangci-lint command is executed. # The placeholder '${base-path}' is substituted with a path relative to the mode defined with `run.relative-path-mode`. + # The placeholder '${config-path}' is substituted with a path relative to the configuration file. # Default: "" template-path: /path/to/my/template.tmpl @@ -1339,7 +1359,6 @@ linters: - 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 - G115 # Potential integer overflow when converting between integer types - G201 # SQL query construction using format string @@ -1384,7 +1403,6 @@ linters: - 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 - G115 # Potential integer overflow when converting between integer types - G201 # SQL query construction using format string @@ -1494,13 +1512,13 @@ linters: # 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 + # Maximum allowed permissions mode for os.Mkdir and os.MkdirAll. # Default: "0750" G301: "0750" - # Maximum allowed permissions mode for os.OpenFile and os.Chmod + # Maximum allowed permissions mode for os.OpenFile and os.Chmod. # Default: "0600" G302: "0600" - # Maximum allowed permissions mode for os.WriteFile and ioutil.WriteFile + # Maximum allowed permissions mode for os.WriteFile and ioutil.WriteFile. # Default: "0600" G306: "0600" @@ -1536,7 +1554,7 @@ linters: # Default: false disable-all: true # Enable analyzers by name. - # (in addition to default: + # (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, @@ -1579,6 +1597,8 @@ linters: - findcall # Report assembly that clobbers the frame pointer before saving it. - framepointer + # Report using Go 1.22 enhanced ServeMux patterns in older Go versions. + - httpmux # Check for mistakes using HTTP responses. - httpresponse # Detect impossible interface-to-interface type assertions. @@ -1636,7 +1656,7 @@ linters: # Default: false enable-all: true # Disable analyzers by name. - # (in addition to default + # (In addition to default # atomicalign, deepequalerrors, fieldalignment, findcall, nilness, reflectvaluecompare, shadow, sortslice, # timeformat, unusedwrite # ). @@ -1660,6 +1680,7 @@ linters: - fieldalignment - findcall - framepointer + - httpmux - httpresponse - ifaceassert - loopclosure @@ -1703,16 +1724,16 @@ linters: # Default: false strict: true unusedresult: - # Comma-separated list of functions whose results must be used - # (in addition to default: + # 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) + # 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 @@ -1778,7 +1799,7 @@ linters: 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 + # See https://github.com/julz/importas#use-regular-expression for details. - pkg: knative.dev/serving/pkg/apis/(\w+)/(v[\w\d]+) alias: $1$2 # An explicit empty alias can be used to ensure no aliases are used for a package. @@ -1917,14 +1938,14 @@ linters: - 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" + # 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` + # Values always ignored: `.+_test.go`. # Default: [] ignored-files: - 'magic1_.+\.go$' @@ -1979,7 +2000,7 @@ linters: - unsafeptr nlreturn: - # Size of the block (including return statement that is still "OK") + # Size of the block (including return statement that is still "OK"), # so no return split required. # Default: 1 block-size: 2 @@ -2169,10 +2190,10 @@ linters: disabled: false exclude: [""] arguments: - - maxLitCount: "3" - allowStrs: '""' - allowInts: "0,1,2" - allowFloats: "0.0,0.,1.0,1.,2.0,2." + - max-lit-count: "3" + allow-strs: '""' + allow-ints: "0,1,2" + allow-floats: "0.0,0.,1.0,1.,2.0,2." # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#argument-limit - name: argument-limit severity: warning @@ -2251,7 +2272,7 @@ linters: disabled: false exclude: [""] arguments: - - allowTypesBefore: "*testing.T,*github.com/user/repo/testing.Harness" + - allow-types-before: "*testing.T,*github.com/user/repo/testing.Harness" # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#context-keys-type - name: context-keys-type severity: warning @@ -2291,7 +2312,7 @@ linters: disabled: false exclude: [""] arguments: - - allowedPackages: ["github.com/onsi/ginkgo/v2", "github.com/onsi/gomega"] + - allowed-packages: ["github.com/onsi/ginkgo/v2", "github.com/onsi/gomega"] # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#duplicated-imports - name: duplicated-imports severity: warning @@ -2303,8 +2324,8 @@ linters: disabled: false exclude: [""] arguments: - - "preserveScope" - - "allowJump" + - "preserve-scope" + - "allow-jump" # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#empty-block - name: empty-block severity: warning @@ -2330,8 +2351,8 @@ linters: arguments: - "short" # Or this parameter: - - funcArgStyle: "full" - funcRetValStyle: "short" + - func-arg-style: "full" + func-ret-val-style: "short" # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#enforce-slice-style - name: enforce-slice-style severity: warning @@ -2367,15 +2388,15 @@ linters: disabled: false exclude: [""] arguments: - - "checkPrivateReceivers" - - "disableStutteringCheck" - - "sayRepetitiveInsteadOfStutters" - - "checkPublicInterface" - - "disableChecksOnConstants" - - "disableChecksOnFunctions" - - "disableChecksOnMethods" - - "disableChecksOnTypes" - - "disableChecksOnVariables" + - "check-private-receivers" + - "disable-stuttering-check" + - "say-repetitive-instead-of-stutters" + - "check-public-interface" + - "disable-checks-on-constants" + - "disable-checks-on-functions" + - "disable-checks-on-methods" + - "disable-checks-on-types" + - "disable-checks-on-variables" # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#file-header - name: file-header severity: warning @@ -2390,8 +2411,8 @@ linters: exclude: [""] arguments: - max: 100 - skipComments: true - skipBlankLines: true + skip-comments: true + skip-blank-lines: true # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#filename-format - name: filename-format severity: warning @@ -2439,8 +2460,8 @@ linters: arguments: - "^[a-z][a-z0-9]{0,}$" # Or this parameter: - - allowRegex: "^[a-z][a-z0-9]{0,}$" - denyRegex: '^v\d+$' + - allow-regex: "^[a-z][a-z0-9]{0,}$" + deny-regex: '^v\d+$' # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#import-shadowing - name: import-shadowing severity: warning @@ -2465,7 +2486,7 @@ linters: disabled: false exclude: [""] arguments: - - "preserveScope" + - "preserve-scope" # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#line-length-limit - name: line-length-limit severity: warning @@ -2530,7 +2551,7 @@ linters: disabled: false exclude: [""] arguments: - - maxLength: 2 + - max-length: 2 # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#redefines-builtin-id - name: redefines-builtin-id severity: warning @@ -2585,7 +2606,7 @@ linters: disabled: false exclude: [""] arguments: - - "preserveScope" + - "preserve-scope" # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#time-equal - name: time-equal severity: warning @@ -2602,7 +2623,7 @@ linters: disabled: false exclude: [""] arguments: - - acceptIgnoredAssertionResult: true + - accept-ignored-assertion-result: true # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#unconditional-recursion - name: unconditional-recursion severity: warning @@ -2642,14 +2663,14 @@ linters: disabled: false exclude: [""] arguments: - - allowRegex: "^_" + - allow-regex: "^_" # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#unused-receiver - name: unused-receiver severity: warning disabled: false exclude: [""] arguments: - - allowRegex: "^_" + - allow-regex: "^_" # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#use-any - name: use-any severity: warning @@ -2678,7 +2699,7 @@ linters: arguments: - [ "ID" ] # AllowList - [ "VM" ] # DenyList - - - upperCaseConst: true # Extra parameter (upperCaseConst|skipPackageNameChecks) + - - upper-case-const: true # Extra parameter (upper-case-const|skip-package-name-checks) # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#waitgroup-by-value - name: waitgroup-by-value severity: warning @@ -2686,7 +2707,7 @@ linters: exclude: [""] rowserrcheck: - # database/sql is always checked + # database/sql is always checked. # Default: [] packages: - github.com/jmoiron/sqlx @@ -2724,11 +2745,16 @@ linters: # https://github.com/go-simpler/sloglint?tab=readme-ov-file#static-messages # Default: false static-msg: true + # Enforce message style. + # Values: lowercased, capitalized + # https://github.com/go-simpler/sloglint?tab=readme-ov-file#message-style + # Default: "" + msg-style: capitalized # Enforce using constants instead of raw keys. # https://github.com/go-simpler/sloglint?tab=readme-ov-file#no-raw-keys # Default: false no-raw-keys: true - # Enforce a single key naming convention. + # Enforce key naming convention. # Values: snake, kebab, camel, pascal # https://github.com/go-simpler/sloglint?tab=readme-ov-file#key-naming-convention # Default: "" @@ -3272,7 +3298,7 @@ linters: # Align and sort can be used together or separately. # # Whether enable align. If true, the struct tags will be aligned. - # e.g.: + # E.g.: # type FooBar struct { # Bar string `json:"bar" validate:"required"` # FooFoo int8 `json:"foo_foo" validate:"required"` @@ -3286,7 +3312,7 @@ linters: 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"` + # 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. @@ -3757,6 +3783,9 @@ linters: # Default: [] ignore-interface-regexps: - ^(?i)c(?-i)ach(ing|e) + # Determines whether wrapcheck should report errors returned from inside the package. + # Default: false + report-internal-errors: true wsl: # Do strict checking when assigning from append (x = append(x, y)). @@ -3946,7 +3975,7 @@ formatters: gci: # 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 > localmodule`, + # The default order of sections is `standard > default > custom > blank > dot > alias > localmodule`. # If `custom-order` is `true`, it follows the order of `sections` option. # Default: ["standard", "default"] sections: @@ -4021,6 +4050,9 @@ formatters: chain-split-dots: false exclusions: + # Log a warning if an exclusion path is unused. + # Default: false + warn-unused: true # Mode of the generated files analysis. # # - `strict`: sources are excluded by strictly following the Go generated file convention. @@ -4154,9 +4186,16 @@ output: path: ./path/to/output.json # Add a prefix to the output file references. + # This option is ignored when using `output.path-mode: abs` mode. # Default: "" path-prefix: "" + # By default, the report are related to the path obtained by `run.relative-path-mode`. + # The mode `abs` allows to show absolute file paths instead of relative file paths. + # The option `output.path-prefix` is ignored when using `abs` mode. + # Default: "" + path-mode: "abs" + # Order to use when sorting results. # Possible values: `file`, `linter`, and `severity`. # diff --git a/assets/cli-help.json b/assets/cli-help.json index 64c4581bf757..407240d603e0 100644 --- a/assets/cli-help.json +++ b/assets/cli-help.json @@ -1,5 +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.\ngovet: Vet examines Go source code and reports suspicious constructs. It is roughly the same as 'go vet' and uses its passes. [auto-fix]\nineffassign: Detects when assignments to existing variables are not used. [fast]\nstaticcheck: It's the set of rules from staticcheck. [auto-fix]\nunused: Checks Go code for unused constants, variables, functions and types.", - "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 --default string Default set of linters to enable (default \"standard\")\n -D, --disable strings Disable specific linter\n -E, --enable strings Enable specific linter\n --enable-only strings Override linters configuration section to only run the specific linter(s)\n --fast-only Filter enabled linters to run only fast linters\n -j, --concurrency int Number of CPUs to use (Default: Automatically set to match Linux container CPU quota and fall back to the number of logical CPUs in the machine)\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 --build-tags strings Build tags\n --timeout duration Timeout for total work. Disabled by default\n --tests Analyze tests (*_test.go) (default true)\n --allow-parallel-runners Allow multiple parallel golangci-lint instances running.\n 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.\n If false (default) - golangci-lint exits with an error if it fails to acquire file lock on start.\n --path-prefix string Path prefix to add to output\n --show-stats Show statistics per linter (default true)\n --output.text.path stdout Output path can be either stdout, `stderr` or path to the file to write to.\n --output.text.print-linter-name Print linter name in the end of issue text. (default true)\n --output.text.print-issued-lines Print lines of code with issue. (default true)\n --output.text.colors Use colors. (default true)\n --output.json.path stdout Output path can be either stdout, `stderr` or path to the file to write to.\n --output.tab.path stdout Output path can be either stdout, `stderr` or path to the file to write to.\n --output.tab.print-linter-name Print linter name in the end of issue text. (default true)\n --output.tab.colors Use colors. (default true)\n --output.html.path stdout Output path can be either stdout, `stderr` or path to the file to write to.\n --output.checkstyle.path stdout Output path can be either stdout, `stderr` or path to the file to write to.\n --output.code-climate.path stdout Output path can be either stdout, `stderr` or path to the file to write to.\n --output.junit-xml.path stdout Output path can be either stdout, `stderr` or path to the file to write to.\n --output.junit-xml.extended Support extra JUnit XML fields.\n --output.teamcity.path stdout Output path can be either stdout, `stderr` or path to the file to write to.\n --output.sarif.path stdout Output path can be either stdout, `stderr` or path to the file to write to.\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 --uniq-by-line Make issues output unique by line (default true)\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 --new-from-merge-base string Show only new issues created after the best common ancestor (merge-base against HEAD)\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 --cpu-profile-path string Path to CPU profile output file\n --mem-profile-path string Path to memory profile output file\n --print-resources-usage Print avg and max memory usage of golangci-lint and total time\n --trace-path string Path to trace output file\n\nGlobal Flags:\n --color string Use color when printing; can be 'always', 'auto', or 'never' (default \"auto\")\n -h, --help Help for a command\n -v, --verbose Verbose output\n", - "fmtHelp": "Usage:\n golangci-lint fmt [flags]\n\nFlags:\n -c, --config PATH Read config from file path PATH\n --no-config Don't read config file\n -E, --enable strings Enable specific formatter\n -d, --diff Display diffs instead of rewriting files\n --stdin Use standard input for piping source files\n\nGlobal Flags:\n --color string Use color when printing; can be 'always', 'auto', or 'never' (default \"auto\")\n -h, --help Help for a command\n -v, --verbose Verbose output\n" + "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 --default string Default set of linters to enable (default \"standard\")\n -D, --disable strings Disable specific linter\n -E, --enable strings Enable specific linter\n --enable-only strings Override linters configuration section to only run the specific linter(s)\n --fast-only Filter enabled linters to run only fast linters\n -j, --concurrency int Number of CPUs to use (Default: Automatically set to match Linux container CPU quota and fall back to the number of logical CPUs in the machine)\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 --build-tags strings Build tags\n --timeout duration Timeout for total work. Disabled by default\n --tests Analyze tests (*_test.go) (default true)\n --allow-parallel-runners Allow multiple parallel golangci-lint instances running.\n 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.\n If false (default) - golangci-lint exits with an error if it fails to acquire file lock on start.\n --path-prefix string Path prefix to add to output\n --path-mode string Path mode to use (empty, or 'abs')\n --show-stats Show statistics per linter (default true)\n --output.text.path stdout Output path can be either stdout, `stderr` or path to the file to write to.\n --output.text.print-linter-name Print linter name in the end of issue text. (default true)\n --output.text.print-issued-lines Print lines of code with issue. (default true)\n --output.text.colors Use colors. (default true)\n --output.json.path stdout Output path can be either stdout, `stderr` or path to the file to write to.\n --output.tab.path stdout Output path can be either stdout, `stderr` or path to the file to write to.\n --output.tab.print-linter-name Print linter name in the end of issue text. (default true)\n --output.tab.colors Use colors. (default true)\n --output.html.path stdout Output path can be either stdout, `stderr` or path to the file to write to.\n --output.checkstyle.path stdout Output path can be either stdout, `stderr` or path to the file to write to.\n --output.code-climate.path stdout Output path can be either stdout, `stderr` or path to the file to write to.\n --output.junit-xml.path stdout Output path can be either stdout, `stderr` or path to the file to write to.\n --output.junit-xml.extended Support extra JUnit XML fields.\n --output.teamcity.path stdout Output path can be either stdout, `stderr` or path to the file to write to.\n --output.sarif.path stdout Output path can be either stdout, `stderr` or path to the file to write to.\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 --uniq-by-line Make issues output unique by line (default true)\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 --new-from-merge-base string Show only new issues created after the best common ancestor (merge-base against HEAD)\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 --cpu-profile-path string Path to CPU profile output file\n --mem-profile-path string Path to memory profile output file\n --print-resources-usage Print avg and max memory usage of golangci-lint and total time\n --trace-path string Path to trace output file\n\nGlobal Flags:\n --color string Use color when printing; can be 'always', 'auto', or 'never' (default \"auto\")\n -h, --help Help for a command\n -v, --verbose Verbose output\n", + "fmtHelp": "Usage:\n golangci-lint fmt [flags]\n\nFlags:\n -c, --config PATH Read config from file path PATH\n --no-config Don't read config file\n -E, --enable strings Enable specific formatter\n -d, --diff Display diffs instead of rewriting files\n --diff-colored Display diffs instead of rewriting files (with colors)\n --stdin Use standard input for piping source files\n\nGlobal Flags:\n --color string Use color when printing; can be 'always', 'auto', or 'never' (default \"auto\")\n -h, --help Help for a command\n -v, --verbose Verbose output\n" } diff --git a/assets/linters-info.json b/assets/linters-info.json index 8711ae5270e4..99ffd81b0865 100644 --- a/assets/linters-info.json +++ b/assets/linters-info.json @@ -246,6 +246,16 @@ "isSlow": true, "since": "v1.38.0" }, + { + "name": "funcorder", + "desc": "checks the order of functions, methods, and constructors", + "Groups": null, + "loadMode": 8199, + "originalURL": "https://github.com/manuelarte/funcorder", + "internal": false, + "isSlow": false, + "since": "v2.1.0" + }, { "name": "fatcontext", "desc": "detects nested contexts in loops and function literals", @@ -331,10 +341,10 @@ "name": "goconst", "desc": "Finds repeated strings that could be replaced by a constant", "Groups": null, - "loadMode": 8199, + "loadMode": 8767, "originalURL": "https://github.com/jgautheron/goconst", "internal": false, - "isSlow": false, + "isSlow": true, "since": "v1.0.0" }, { @@ -570,7 +580,7 @@ }, { "name": "loggercheck", - "desc": "Checks key value pairs for common logger libraries (kitlog,klog,logr,zap).", + "desc": "Checks key value pairs for common logger libraries (kitlog,klog,logr,slog,zap).", "Groups": null, "loadMode": 8767, "originalURL": "https://github.com/timonwong/loggercheck", @@ -614,7 +624,7 @@ "desc": "Finds commonly misspelled English words", "Groups": null, "loadMode": 8199, - "originalURL": "https://github.com/client9/misspell", + "originalURL": "https://github.com/golangci/misspell", "internal": false, "canAutoFix": true, "isSlow": false, @@ -832,6 +842,7 @@ "loadMode": 8767, "originalURL": "https://github.com/go-simpler/sloglint", "internal": false, + "canAutoFix": true, "isSlow": true, "since": "v1.55.0" }, diff --git a/jsonschema/golangci.jsonschema.json b/jsonschema/golangci.jsonschema.json index 437943b5f318..0f2ef5fcc50b 100644 --- a/jsonschema/golangci.jsonschema.json +++ b/jsonschema/golangci.jsonschema.json @@ -490,7 +490,6 @@ "G110", "G111", "G112", - "G113", "G114", "G115", "G201", @@ -540,6 +539,7 @@ "fieldalignment", "findcall", "framepointer", + "httpmux", "httpresponse", "ifaceassert", "loopclosure", @@ -742,6 +742,7 @@ "fatcontext", "forbidigo", "forcetypeassert", + "funcorder", "funlen", "ginkgolinter", "gocheckcompilerdirectives", @@ -1303,6 +1304,22 @@ } } }, + "funcorderSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "constructor": { + "description": "Checks that constructors are placed after the structure declaration.", + "type": "boolean", + "default": true + }, + "struct-method": { + "description": "Checks if the exported methods of a structure are placed before the non-exported ones.", + "type": "boolean", + "default": true + } + } + }, "funlenSettings": { "type": "object", "additionalProperties": false, @@ -1489,9 +1506,12 @@ "type": "boolean", "default": true }, - "ignore-strings": { + "ignore-string-values": { "description": "Exclude strings matching the given regular expression", - "type": "string" + "type": "array", + "items": { + "type": "string" + } }, "numbers": { "description": "Search also for duplicated numbers.", @@ -1507,6 +1527,16 @@ "description": "Maximum value, only works with `numbers`", "type": "integer", "default": 3 + }, + "find-duplicates": { + "description": "Detects constants with identical values", + "type": "boolean", + "default": false + }, + "eval-const-expressions": { + "description": "Evaluates of constant expressions like Prefix + \"suffix\"", + "type": "boolean", + "default": false } } }, @@ -2964,6 +2994,11 @@ "type": "boolean", "default": false }, + "msg-style": { + "description": "Enforce message style.", + "enum": ["", "lowercased", "capitalized"], + "default": "" + }, "key-naming-case": { "description": "Enforce a single key naming convention.", "enum": ["snake", "kebab", "camel", "pascal"] @@ -3924,6 +3959,11 @@ "items": { "type": "string" } + }, + "report-internal-errors": { + "description": "Determines whether wrapcheck should report errors returned from inside the package.", + "type": "boolean", + "default": false } } }, @@ -4224,6 +4264,11 @@ } } }, + "path-mode": { + "type": "string", + "default": "", + "examples": ["abs"] + }, "path-prefix": { "description": "Add a prefix to the output file references.", "type": "string", @@ -4318,6 +4363,9 @@ "forbidigo": { "$ref": "#/definitions/settings/definitions/forbidigoSettings" }, + "funcorder": { + "$ref": "#/definitions/settings/definitions/funcorderSettings" + }, "funlen": { "$ref": "#/definitions/settings/definitions/funlenSettings" }, @@ -4626,6 +4674,10 @@ "items": { "type": "string" } + }, + "warn-unused": { + "type": "boolean", + "default": false } } } diff --git a/jsonschema/golangci.next.jsonschema.json b/jsonschema/golangci.next.jsonschema.json index 996a5ec3721f..0f2ef5fcc50b 100644 --- a/jsonschema/golangci.next.jsonschema.json +++ b/jsonschema/golangci.next.jsonschema.json @@ -665,6 +665,7 @@ }, "tagliatelle-cases": { "enum": [ + "", "camel", "pascal", "kebab", diff --git a/jsonschema/golangci.v1.64.jsonschema.json b/jsonschema/golangci.v1.64.jsonschema.json index f80ccf06235a..b265c1a8233c 100644 --- a/jsonschema/golangci.v1.64.jsonschema.json +++ b/jsonschema/golangci.v1.64.jsonschema.json @@ -310,6 +310,7 @@ }, "tagliatelle-cases": { "enum": [ + "", "camel", "pascal", "kebab", From d9d46b459b8f1b025ae26a56c233a7bea881590f Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Sat, 12 Apr 2025 20:08:41 +0200 Subject: [PATCH 060/152] chore: downgrade goreleaser to v2.8.1 Related to a regression inside v2.8.2 --- .github/workflows/release.yml | 2 +- jsonschema/golangci.v1.jsonschema.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e807c3aeaeb3..0a75cb50cfe3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -69,7 +69,7 @@ jobs: - name: Create release uses: goreleaser/goreleaser-action@v6 with: - version: latest + version: v2.8.1 args: release --clean --timeout=90m env: AUR_KEY: ${{ secrets.AUR_KEY }} diff --git a/jsonschema/golangci.v1.jsonschema.json b/jsonschema/golangci.v1.jsonschema.json index f80ccf06235a..b265c1a8233c 100644 --- a/jsonschema/golangci.v1.jsonschema.json +++ b/jsonschema/golangci.v1.jsonschema.json @@ -310,6 +310,7 @@ }, "tagliatelle-cases": { "enum": [ + "", "camel", "pascal", "kebab", From 93dabf9013aa0cea82ad58e5f90146fc2e62587b Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Sat, 12 Apr 2025 20:12:29 +0200 Subject: [PATCH 061/152] chore: prepare release --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d8161a8a8c9b..9be50477f621 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ If you value it, consider supporting us, we appreciate it! ❤️ [![Open Collective backers and sponsors](https://img.shields.io/badge/OpenCollective-Donate-blue?logo=opencollective&style=for-the-badge)](https://opencollective.com/golangci-lint) [![GitHub Sponsors](https://img.shields.io/badge/GitHub-Donate-blue?logo=github&style=for-the-badge)](https://github.com/sponsors/golangci) +### v2.1.1 + +The release process of the v2.1.0 as failed due to a regression inside goreleaser. +The binaries of v2.1.0 has been published but not the other articfacts (AUR, Docker, etc.) + ### v2.1.0 1. Enhancements From d1b1db7a7cd23e633149c65de1a86a1b3d7e597e Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Sat, 12 Apr 2025 20:47:50 +0200 Subject: [PATCH 062/152] docs: update changelog --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9be50477f621..e6d6689591c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,8 +9,9 @@ If you value it, consider supporting us, we appreciate it! ❤️ ### v2.1.1 -The release process of the v2.1.0 as failed due to a regression inside goreleaser. -The binaries of v2.1.0 has been published but not the other articfacts (AUR, Docker, etc.) +The release process of v2.1.0 failed due to a regression inside goreleaser. + +The binaries of v2.1.0 have been published, but not the other artifacts (AUR, Docker, etc.). ### v2.1.0 From 50f7446eda68cbf0219a8b09d6421a023e4d7543 Mon Sep 17 00:00:00 2001 From: GolangCI-Lint Releaser <65486276+golangci-releaser@users.noreply.github.com> Date: Sat, 12 Apr 2025 20:53:32 +0200 Subject: [PATCH 063/152] docs: update GitHub Action assets (#5724) --- assets/github-action-config-v2.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/github-action-config-v2.json b/assets/github-action-config-v2.json index a0a27322f486..470995520d2c 100644 --- a/assets/github-action-config-v2.json +++ b/assets/github-action-config-v2.json @@ -1,7 +1,7 @@ { "MinorVersionToConfig": { "latest": { - "TargetVersion": "v2.1.0" + "TargetVersion": "v2.1.1" }, "v1.10": { "Error": "golangci-lint version 'v1.10' isn't supported: we support only v2.0.0 and later versions" @@ -193,7 +193,7 @@ "TargetVersion": "v2.0.2" }, "v2.1": { - "TargetVersion": "v2.1.0" + "TargetVersion": "v2.1.1" } } } From 997470cefa6efbcf9ff8387e8c4343d2307c7f94 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Apr 2025 00:10:11 +0200 Subject: [PATCH 064/152] build(deps): bump github.com/ghostiam/protogetter from 0.3.13 to 0.3.14 (#5727) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c229136ae43d..478da1d73d14 100644 --- a/go.mod +++ b/go.mod @@ -40,7 +40,7 @@ require ( github.com/fatih/color v1.18.0 github.com/firefart/nonamedreturns v1.0.6 github.com/fzipp/gocyclo v0.6.0 - github.com/ghostiam/protogetter v0.3.13 + github.com/ghostiam/protogetter v0.3.14 github.com/go-critic/go-critic v0.13.0 github.com/go-viper/mapstructure/v2 v2.2.1 github.com/go-xmlfmt/xmlfmt v1.1.3 diff --git a/go.sum b/go.sum index f657816a2e6c..055044042393 100644 --- a/go.sum +++ b/go.sum @@ -172,8 +172,8 @@ github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwV 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/ghostiam/protogetter v0.3.13 h1:T4qt1JU0xvx8+jO30+JaA49fngUd6YNajqwk0Rn3t1s= -github.com/ghostiam/protogetter v0.3.13/go.mod h1:WZ0nw9pfzsgxuRsPOFQomgDVSWtDLJRfQJEhsGbmQMA= +github.com/ghostiam/protogetter v0.3.14 h1:4vabcsVL3M4YDaAcq3r0nDVRPjfVGxJCEk5viVY+TuI= +github.com/ghostiam/protogetter v0.3.14/go.mod h1:WZ0nw9pfzsgxuRsPOFQomgDVSWtDLJRfQJEhsGbmQMA= github.com/go-critic/go-critic v0.13.0 h1:kJzM7wzltQasSUXtYyTl6UaPVySO6GkaR1thFnJ6afY= github.com/go-critic/go-critic v0.13.0/go.mod h1:M/YeuJ3vOCQDnP2SU+ZhjgRzwzcBW87JqLpMJLrZDLI= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= From 624edd14d9ee6b0ea8248639913de7435d33a9a0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Apr 2025 00:24:36 +0200 Subject: [PATCH 065/152] build(deps): bump mvdan.cc/gofumpt from 0.7.0 to 0.8.0 (#5728) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 478da1d73d14..0a7572c96443 100644 --- a/go.mod +++ b/go.mod @@ -133,7 +133,7 @@ require ( golang.org/x/tools v0.32.0 gopkg.in/yaml.v3 v3.0.1 honnef.co/go/tools v0.6.1 - mvdan.cc/gofumpt v0.7.0 + mvdan.cc/gofumpt v0.8.0 mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4 ) diff --git a/go.sum b/go.sum index 055044042393..1b873c45f40b 100644 --- a/go.sum +++ b/go.sum @@ -1015,8 +1015,8 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.6.1 h1:R094WgE8K4JirYjBaOpz/AvTyUu/3wbmAoskKN/pxTI= honnef.co/go/tools v0.6.1/go.mod h1:3puzxxljPCe8RGJX7BIy1plGbxEOZni5mR2aXe3/uk4= -mvdan.cc/gofumpt v0.7.0 h1:bg91ttqXmi9y2xawvkuMXyvAA/1ZGJqYAEGjXuP0JXU= -mvdan.cc/gofumpt v0.7.0/go.mod h1:txVFJy/Sc/mvaycET54pV8SW8gWxTlUuGHVEcncmNUo= +mvdan.cc/gofumpt v0.8.0 h1:nZUCeC2ViFaerTcYKstMmfysj6uhQrA2vJe+2vwGU6k= +mvdan.cc/gofumpt v0.8.0/go.mod h1:vEYnSzyGPmjvFkqJWtXkh79UwPWP9/HMxQdGEXZHjpg= mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4 h1:WjUu4yQoT5BHT1w8Zu56SP8367OuBV5jvo+4Ulppyf8= mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4/go.mod h1:rthT7OuvRbaGcd5ginj6dA2oLE7YNlta9qhBNNdCaLE= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= From 15817283fd6b2c1049f5f8215df94084a9597cd4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Apr 2025 02:42:41 +0200 Subject: [PATCH 066/152] build(deps): bump github.com/ldez/exptostd from 0.4.2 to 0.4.3 (#5730) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 0a7572c96443..9e2018998f69 100644 --- a/go.mod +++ b/go.mod @@ -67,7 +67,7 @@ require ( github.com/kulti/thelper v0.6.3 github.com/kunwardeep/paralleltest v1.0.14 github.com/lasiar/canonicalheader v1.1.2 - github.com/ldez/exptostd v0.4.2 + github.com/ldez/exptostd v0.4.3 github.com/ldez/gomoddirectives v0.6.1 github.com/ldez/grignotin v0.9.0 github.com/ldez/tagliatelle v0.7.1 diff --git a/go.sum b/go.sum index 1b873c45f40b..c1d7f1fc4a55 100644 --- a/go.sum +++ b/go.sum @@ -371,8 +371,8 @@ github.com/kunwardeep/paralleltest v1.0.14 h1:wAkMoMeGX/kGfhQBPODT/BL8XhK23ol/nu github.com/kunwardeep/paralleltest v1.0.14/go.mod h1:di4moFqtfz3ToSKxhNjhOZL+696QtJGCFe132CbBLGk= github.com/lasiar/canonicalheader v1.1.2 h1:vZ5uqwvDbyJCnMhmFYimgMZnJMjwljN5VGY0VKbMXb4= github.com/lasiar/canonicalheader v1.1.2/go.mod h1:qJCeLFS0G/QlLQ506T+Fk/fWMa2VmBUiEI2cuMK4djI= -github.com/ldez/exptostd v0.4.2 h1:l5pOzHBz8mFOlbcifTxzfyYbgEmoUqjxLFHZkjlbHXs= -github.com/ldez/exptostd v0.4.2/go.mod h1:iZBRYaUmcW5jwCR3KROEZ1KivQQp6PHXbDPk9hqJKCQ= +github.com/ldez/exptostd v0.4.3 h1:Ag1aGiq2epGePuRJhez2mzOpZ8sI9Gimcb4Sb3+pk9Y= +github.com/ldez/exptostd v0.4.3/go.mod h1:iZBRYaUmcW5jwCR3KROEZ1KivQQp6PHXbDPk9hqJKCQ= github.com/ldez/gomoddirectives v0.6.1 h1:Z+PxGAY+217f/bSGjNZr/b2KTXcyYLgiWI6geMBN2Qc= github.com/ldez/gomoddirectives v0.6.1/go.mod h1:cVBiu3AHR9V31em9u2kwfMKD43ayN5/XDgr+cdaFaKs= github.com/ldez/grignotin v0.9.0 h1:MgOEmjZIVNn6p5wPaGp/0OKWyvq42KnzAt/DAb8O4Ow= From 3afce899b2a3b477168b847c34d565c62d4fad18 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Apr 2025 02:42:47 +0200 Subject: [PATCH 067/152] build(deps): bump github.com/ldez/usetesting from 0.4.2 to 0.4.3 (#5729) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9e2018998f69..d70d8f9e5569 100644 --- a/go.mod +++ b/go.mod @@ -71,7 +71,7 @@ require ( github.com/ldez/gomoddirectives v0.6.1 github.com/ldez/grignotin v0.9.0 github.com/ldez/tagliatelle v0.7.1 - github.com/ldez/usetesting v0.4.2 + github.com/ldez/usetesting v0.4.3 github.com/leonklingele/grouper v1.1.2 github.com/macabu/inamedparam v0.2.0 github.com/manuelarte/funcorder v0.2.1 diff --git a/go.sum b/go.sum index c1d7f1fc4a55..7a42d3c50572 100644 --- a/go.sum +++ b/go.sum @@ -379,8 +379,8 @@ github.com/ldez/grignotin v0.9.0 h1:MgOEmjZIVNn6p5wPaGp/0OKWyvq42KnzAt/DAb8O4Ow= github.com/ldez/grignotin v0.9.0/go.mod h1:uaVTr0SoZ1KBii33c47O1M8Jp3OP3YDwhZCmzT9GHEk= github.com/ldez/tagliatelle v0.7.1 h1:bTgKjjc2sQcsgPiT902+aadvMjCeMHrY7ly2XKFORIk= github.com/ldez/tagliatelle v0.7.1/go.mod h1:3zjxUpsNB2aEZScWiZTHrAXOl1x25t3cRmzfK1mlo2I= -github.com/ldez/usetesting v0.4.2 h1:J2WwbrFGk3wx4cZwSMiCQQ00kjGR0+tuuyW0Lqm4lwA= -github.com/ldez/usetesting v0.4.2/go.mod h1:eEs46T3PpQ+9RgN9VjpY6qWdiw2/QmfiDeWmdZdrjIQ= +github.com/ldez/usetesting v0.4.3 h1:pJpN0x3fMupdTf/IapYjnkhiY1nSTN+pox1/GyBRw3k= +github.com/ldez/usetesting v0.4.3/go.mod h1:eEs46T3PpQ+9RgN9VjpY6qWdiw2/QmfiDeWmdZdrjIQ= github.com/leonklingele/grouper v1.1.2 h1:o1ARBDLOmmasUaNDesWqWCIFH3u7hoFlM84YrjT3mIY= github.com/leonklingele/grouper v1.1.2/go.mod h1:6D0M/HVkhs2yRKRFZUoGjeDy7EZTfFBE9gl4kjmIGkA= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= From a05ea26b7bce86298e3e7fa6800af90142122675 Mon Sep 17 00:00:00 2001 From: Oleksandr Redko Date: Mon, 14 Apr 2025 14:16:29 +0300 Subject: [PATCH 068/152] dev: simplify mnd implementation (#5731) --- pkg/golinters/mnd/mnd.go | 7 +++---- pkg/golinters/mnd/testdata/mnd_custom.go | 24 +++++++++++++++++++++++ pkg/golinters/mnd/testdata/mnd_custom.yml | 7 +++++++ 3 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 pkg/golinters/mnd/testdata/mnd_custom.go create mode 100644 pkg/golinters/mnd/testdata/mnd_custom.yml diff --git a/pkg/golinters/mnd/mnd.go b/pkg/golinters/mnd/mnd.go index 744186bc3e63..52521e92dd15 100644 --- a/pkg/golinters/mnd/mnd.go +++ b/pkg/golinters/mnd/mnd.go @@ -9,11 +9,10 @@ import ( ) func New(settings *config.MndSettings) *goanalysis.Linter { - return newMND(mnd.Analyzer, settings, nil) -} + a := mnd.Analyzer -func newMND(a *analysis.Analyzer, settings *config.MndSettings, linterCfg map[string]map[string]any) *goanalysis.Linter { - if len(linterCfg) == 0 && settings != nil { + var linterCfg map[string]map[string]any + if settings != nil { cfg := make(map[string]any) if len(settings.Checks) > 0 { cfg["checks"] = settings.Checks diff --git a/pkg/golinters/mnd/testdata/mnd_custom.go b/pkg/golinters/mnd/testdata/mnd_custom.go new file mode 100644 index 000000000000..75530516b3ab --- /dev/null +++ b/pkg/golinters/mnd/testdata/mnd_custom.go @@ -0,0 +1,24 @@ +//golangcitest:args -Emnd +//golangcitest:config_path testdata/mnd_custom.yml +package testdata + +import ( + "log" + "net/http" + "time" +) + +func Mnd() { + c := &http.Client{ + Timeout: 5 * time.Second, + } + + res, err := c.Get("https://www.google.com") + if err != nil { + log.Fatal(err) + } + defer res.Body.Close() + if res.StatusCode != 200 { // want "Magic number: 200, in detected" + log.Println("Something went wrong") + } +} diff --git a/pkg/golinters/mnd/testdata/mnd_custom.yml b/pkg/golinters/mnd/testdata/mnd_custom.yml new file mode 100644 index 000000000000..7987bf91019e --- /dev/null +++ b/pkg/golinters/mnd/testdata/mnd_custom.yml @@ -0,0 +1,7 @@ +version: "2" + +linters: + settings: + mnd: + ignored-numbers: + - '5' From 7dde13b4c5c8972cba342bde837b1e7aeddbb16b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Apr 2025 17:26:31 +0200 Subject: [PATCH 069/152] build(deps): bump github.com/ghostiam/protogetter from 0.3.14 to 0.3.15 (#5732) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d70d8f9e5569..00695fdf37ad 100644 --- a/go.mod +++ b/go.mod @@ -40,7 +40,7 @@ require ( github.com/fatih/color v1.18.0 github.com/firefart/nonamedreturns v1.0.6 github.com/fzipp/gocyclo v0.6.0 - github.com/ghostiam/protogetter v0.3.14 + github.com/ghostiam/protogetter v0.3.15 github.com/go-critic/go-critic v0.13.0 github.com/go-viper/mapstructure/v2 v2.2.1 github.com/go-xmlfmt/xmlfmt v1.1.3 diff --git a/go.sum b/go.sum index 7a42d3c50572..9bc80fb7cd9b 100644 --- a/go.sum +++ b/go.sum @@ -172,8 +172,8 @@ github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwV 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/ghostiam/protogetter v0.3.14 h1:4vabcsVL3M4YDaAcq3r0nDVRPjfVGxJCEk5viVY+TuI= -github.com/ghostiam/protogetter v0.3.14/go.mod h1:WZ0nw9pfzsgxuRsPOFQomgDVSWtDLJRfQJEhsGbmQMA= +github.com/ghostiam/protogetter v0.3.15 h1:1KF5sXel0HE48zh1/vn0Loiw25A9ApyseLzQuif1mLY= +github.com/ghostiam/protogetter v0.3.15/go.mod h1:WZ0nw9pfzsgxuRsPOFQomgDVSWtDLJRfQJEhsGbmQMA= github.com/go-critic/go-critic v0.13.0 h1:kJzM7wzltQasSUXtYyTl6UaPVySO6GkaR1thFnJ6afY= github.com/go-critic/go-critic v0.13.0/go.mod h1:M/YeuJ3vOCQDnP2SU+ZhjgRzwzcBW87JqLpMJLrZDLI= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= From 6de1453c15a923e0b2782e7fdb6d8c58d38e7313 Mon Sep 17 00:00:00 2001 From: Chris Reeves Date: Tue, 15 Apr 2025 11:51:51 +0100 Subject: [PATCH 070/152] docs: fix default value of linters.exclusions.generated (#5735) --- .golangci.next.reference.yml | 4 ++-- .golangci.reference.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index cababbea228f..37866ff00f2c 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -3902,8 +3902,8 @@ linters: # - `lax`: sources are excluded if they contain lines like `autogenerated file`, `code generated`, `do not edit`, etc. # - `disable`: disable the generated files exclusion. # - # Default: lax - generated: strict + # Default: strict + generated: lax # Log a warning if an exclusion rule is unused. # Default: false warn-unused: true diff --git a/.golangci.reference.yml b/.golangci.reference.yml index cababbea228f..37866ff00f2c 100644 --- a/.golangci.reference.yml +++ b/.golangci.reference.yml @@ -3902,8 +3902,8 @@ linters: # - `lax`: sources are excluded if they contain lines like `autogenerated file`, `code generated`, `do not edit`, etc. # - `disable`: disable the generated files exclusion. # - # Default: lax - generated: strict + # Default: strict + generated: lax # Log a warning if an exclusion rule is unused. # Default: false warn-unused: true From 00a561d9a79578a2800dece2f04c60ad479a3798 Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Mon, 14 Apr 2025 00:27:34 +0200 Subject: [PATCH 071/152] chore: prepare release --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e6d6689591c4..08b729267d2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ If you value it, consider supporting us, we appreciate it! ❤️ [![Open Collective backers and sponsors](https://img.shields.io/badge/OpenCollective-Donate-blue?logo=opencollective&style=for-the-badge)](https://opencollective.com/golangci-lint) [![GitHub Sponsors](https://img.shields.io/badge/GitHub-Donate-blue?logo=github&style=for-the-badge)](https://github.com/sponsors/golangci) +### v2.1.2 + +1. Linters bug fixes + * `exptostd`: from 0.4.2 to 0.4.3 + * `gofumpt`: from 0.7.0 to 0.8.0 + * `protogetter`: from 0.3.13 to 0.3.15 + * `usetesting`: from 0.4.2 to 0.4.3 + ### v2.1.1 The release process of v2.1.0 failed due to a regression inside goreleaser. From 50e1e98922da68aa39dc17b1293842031114cf14 Mon Sep 17 00:00:00 2001 From: GolangCI-Lint Releaser <65486276+golangci-releaser@users.noreply.github.com> Date: Tue, 15 Apr 2025 16:07:47 +0200 Subject: [PATCH 072/152] docs: update GitHub Action assets (#5738) --- assets/github-action-config-v2.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/github-action-config-v2.json b/assets/github-action-config-v2.json index 470995520d2c..4ec367aa9ef7 100644 --- a/assets/github-action-config-v2.json +++ b/assets/github-action-config-v2.json @@ -1,7 +1,7 @@ { "MinorVersionToConfig": { "latest": { - "TargetVersion": "v2.1.1" + "TargetVersion": "v2.1.2" }, "v1.10": { "Error": "golangci-lint version 'v1.10' isn't supported: we support only v2.0.0 and later versions" @@ -193,7 +193,7 @@ "TargetVersion": "v2.0.2" }, "v2.1": { - "TargetVersion": "v2.1.1" + "TargetVersion": "v2.1.2" } } } From 60f4cffc211d3719e68f3318ed90ae7d687c2246 Mon Sep 17 00:00:00 2001 From: Nikita Mironov Date: Wed, 16 Apr 2025 13:01:09 +0200 Subject: [PATCH 073/152] docs: update section about GoLand integration (#5740) --- docs/src/docs/welcome/integrations.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/src/docs/welcome/integrations.mdx b/docs/src/docs/welcome/integrations.mdx index 8658e2aa3f5c..02850e1a60c7 100644 --- a/docs/src/docs/welcome/integrations.mdx +++ b/docs/src/docs/welcome/integrations.mdx @@ -6,9 +6,9 @@ title: Integrations ### GoLand -The integration for golangci-lint v2 is currently in work in progress: [GO-18363](https://youtrack.jetbrains.com/issue/GO-18363/Go-Linter-plugin-fails-with-golangci-lint-v2). - -Install [plugin](https://plugins.jetbrains.com/plugin/12496-go-linter). +Starting from the version 2025.1, GoLand has built-in support of golangci-lint. +For IntelliJ IDEA with the Go plugin, please install the [plugin](https://plugins.jetbrains.com/plugin/12496-go-linter). +Both v1 and v2 versions are supported. ### Visual Studio Code From 43e07c47273e04c4d721ce3fef80562ab3333959 Mon Sep 17 00:00:00 2001 From: sivchari Date: Wed, 16 Apr 2025 23:46:05 +0900 Subject: [PATCH 074/152] fix: order of staticcheck settings during migration (#5741) Co-authored-by: Fernandez Ludovic --- .../migrate/migrate_linters_settings.go | 26 ++- ...ters-settings_staticcheck_merge.golden.yml | 204 ++++++++++++++++++ .../linters-settings_staticcheck_merge.yml | 172 +++++++++++++++ 3 files changed, 400 insertions(+), 2 deletions(-) create mode 100644 pkg/commands/internal/migrate/testdata/yaml/linters-settings_staticcheck_merge.golden.yml create mode 100644 pkg/commands/internal/migrate/testdata/yaml/linters-settings_staticcheck_merge.yml diff --git a/pkg/commands/internal/migrate/migrate_linters_settings.go b/pkg/commands/internal/migrate/migrate_linters_settings.go index a0559388d403..5accd9f593e5 100644 --- a/pkg/commands/internal/migrate/migrate_linters_settings.go +++ b/pkg/commands/internal/migrate/migrate_linters_settings.go @@ -789,10 +789,32 @@ func toSpancheckSettings(old versionone.SpancheckSettings) versiontwo.SpancheckS } func toStaticCheckSettings(old versionone.LintersSettings) versiontwo.StaticCheckSettings { - checks := slices.Concat(old.Staticcheck.Checks, old.Stylecheck.Checks, old.Gosimple.Checks) + var checks []string + + for _, check := range slices.Concat(old.Staticcheck.Checks, old.Stylecheck.Checks, old.Gosimple.Checks) { + if check == "*" { + checks = append(checks, "all") + continue + } + checks = append(checks, check) + } + + checks = Unique(checks) + + slices.SortFunc(checks, func(a, b string) int { + if a == "all" { + return -1 + } + + if b == "all" { + return 1 + } + + return strings.Compare(a, b) + }) return versiontwo.StaticCheckSettings{ - Checks: Unique(checks), + Checks: checks, Initialisms: old.Stylecheck.Initialisms, DotImportWhitelist: old.Stylecheck.DotImportWhitelist, HTTPStatusCodeWhitelist: old.Stylecheck.HTTPStatusCodeWhitelist, diff --git a/pkg/commands/internal/migrate/testdata/yaml/linters-settings_staticcheck_merge.golden.yml b/pkg/commands/internal/migrate/testdata/yaml/linters-settings_staticcheck_merge.golden.yml new file mode 100644 index 000000000000..229a095f01f8 --- /dev/null +++ b/pkg/commands/internal/migrate/testdata/yaml/linters-settings_staticcheck_merge.golden.yml @@ -0,0 +1,204 @@ +version: "2" +linters: + settings: + staticcheck: + checks: + - all + - -S1000 + - -S1001 + - -S1002 + - -SA1000 + - -SA1001 + - -SA1002 + - -ST1000 + - -ST1001 + - -ST1003 + - S1003 + - S1004 + - S1005 + - S1006 + - S1007 + - S1008 + - S1009 + - S1010 + - S1011 + - S1012 + - S1016 + - S1017 + - S1018 + - S1019 + - S1020 + - S1021 + - S1023 + - S1024 + - S1025 + - S1028 + - S1029 + - S1030 + - S1031 + - S1032 + - S1033 + - S1034 + - S1035 + - S1036 + - S1037 + - S1038 + - S1039 + - S1040 + - SA1003 + - SA1004 + - SA1005 + - SA1006 + - SA1007 + - SA1008 + - SA1010 + - SA1011 + - SA1012 + - SA1013 + - SA1014 + - SA1015 + - SA1016 + - SA1017 + - SA1018 + - SA1019 + - SA1020 + - SA1021 + - SA1023 + - SA1024 + - SA1025 + - SA1026 + - SA1027 + - SA1028 + - SA1029 + - SA1030 + - SA1031 + - SA1032 + - SA2000 + - SA2001 + - SA2002 + - SA2003 + - SA3000 + - SA3001 + - SA4000 + - SA4001 + - SA4003 + - SA4004 + - SA4005 + - SA4006 + - SA4008 + - SA4009 + - SA4010 + - SA4011 + - SA4012 + - SA4013 + - SA4014 + - SA4015 + - SA4016 + - SA4017 + - SA4018 + - SA4019 + - SA4020 + - SA4021 + - SA4022 + - SA4023 + - SA4024 + - SA4025 + - SA4026 + - SA4027 + - SA4028 + - SA4029 + - SA4030 + - SA4031 + - SA4032 + - SA5000 + - SA5001 + - SA5002 + - SA5003 + - SA5004 + - SA5005 + - SA5007 + - SA5008 + - SA5009 + - SA5010 + - SA5011 + - SA5012 + - SA6000 + - SA6001 + - SA6002 + - SA6003 + - SA6005 + - SA6006 + - SA9001 + - SA9002 + - SA9003 + - SA9004 + - SA9005 + - SA9006 + - SA9007 + - SA9008 + - SA9009 + - ST1005 + - ST1006 + - ST1008 + - ST1011 + - ST1012 + - ST1013 + - ST1015 + - ST1016 + - ST1017 + - ST1018 + - ST1019 + - ST1020 + - ST1021 + - ST1022 + - ST1023 + 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 + dot-import-whitelist: + - fmt + http-status-code-whitelist: + - "200" + - "400" + - "404" + - "500" diff --git a/pkg/commands/internal/migrate/testdata/yaml/linters-settings_staticcheck_merge.yml b/pkg/commands/internal/migrate/testdata/yaml/linters-settings_staticcheck_merge.yml new file mode 100644 index 000000000000..3d9fe3cbbfc0 --- /dev/null +++ b/pkg/commands/internal/migrate/testdata/yaml/linters-settings_staticcheck_merge.yml @@ -0,0 +1,172 @@ +issues: + # Only to not generate unrelated elements inside golden. + exclude-use-default: false + # Only to not generate unrelated elements inside golden. + exclude-generated: strict + # Only to not generate unrelated elements inside golden. + exclude-dirs-use-default: false + +linters-settings: + staticcheck: + checks: + - all + - '-SA1000' + - '-SA1001' + - '-SA1002' + - SA1003 + - SA1004 + - SA1005 + - SA1006 + - SA1007 + - SA1008 + - SA1010 + - SA1011 + - SA1012 + - SA1013 + - SA1014 + - SA1015 + - SA1016 + - SA1017 + - SA1018 + - SA1019 + - SA1020 + - SA1021 + - SA1023 + - SA1024 + - SA1025 + - SA1026 + - SA1027 + - SA1028 + - SA1029 + - SA1030 + - SA1031 + - SA1032 + - SA2000 + - SA2001 + - SA2002 + - SA2003 + - SA3000 + - SA3001 + - SA4000 + - SA4001 + - SA4003 + - SA4004 + - SA4005 + - SA4006 + - SA4008 + - SA4009 + - SA4010 + - SA4011 + - SA4012 + - SA4013 + - SA4014 + - SA4015 + - SA4016 + - SA4017 + - SA4018 + - SA4019 + - SA4020 + - SA4021 + - SA4022 + - SA4023 + - SA4024 + - SA4025 + - SA4026 + - SA4027 + - SA4028 + - SA4029 + - SA4030 + - SA4031 + - SA4032 + - SA5000 + - SA5001 + - SA5002 + - SA5003 + - SA5004 + - SA5005 + - SA5007 + - SA5008 + - SA5009 + - SA5010 + - SA5011 + - SA5012 + - SA6000 + - SA6001 + - SA6002 + - SA6003 + - SA6005 + - SA6006 + - SA9001 + - SA9002 + - SA9003 + - SA9004 + - SA9005 + - SA9006 + - SA9007 + - SA9008 + - SA9009 + + gosimple: + checks: + - '*' + - '-S1000' + - '-S1001' + - '-S1002' + - S1003 + - S1004 + - S1005 + - S1006 + - S1007 + - S1008 + - S1009 + - S1010 + - S1011 + - S1012 + - S1016 + - S1017 + - S1018 + - S1019 + - S1020 + - S1021 + - S1023 + - S1024 + - S1025 + - S1028 + - S1029 + - S1030 + - S1031 + - S1032 + - S1033 + - S1034 + - S1035 + - S1036 + - S1037 + - S1038 + - S1039 + - S1040 + + stylecheck: + dot-import-whitelist: + - fmt + 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" ] + http-status-code-whitelist: [ "200", "400", "404", "500" ] + checks: + - all + - '-ST1000' + - '-ST1001' + - '-ST1003' + - ST1005 + - ST1006 + - ST1008 + - ST1011 + - ST1012 + - ST1013 + - ST1015 + - ST1016 + - ST1017 + - ST1018 + - ST1019 + - ST1020 + - ST1021 + - ST1022 + - ST1023 From f1e4d89b5b2cf524e0aa095173c7ec4145eebb68 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Wed, 16 Apr 2025 16:46:16 +0200 Subject: [PATCH 075/152] fix: add go.mod hash to the cache salt (#5739) --- pkg/commands/run.go | 43 ++++++++++++++++++++++++++++++++++++++-- pkg/config/config.go | 12 ++++++++--- pkg/config/loader.go | 2 +- pkg/logutils/logutils.go | 1 + 4 files changed, 52 insertions(+), 6 deletions(-) diff --git a/pkg/commands/run.go b/pkg/commands/run.go index a3e9df6de3fc..53902eafac24 100644 --- a/pkg/commands/run.go +++ b/pkg/commands/run.go @@ -21,10 +21,12 @@ import ( "github.com/fatih/color" "github.com/gofrs/flock" + "github.com/ldez/grignotin/goenv" "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/spf13/viper" "go.uber.org/automaxprocs/maxprocs" + "golang.org/x/mod/sumdb/dirhash" "gopkg.in/yaml.v3" "github.com/golangci/golangci-lint/v2/internal/cache" @@ -216,7 +218,7 @@ func (c *runCommand) preRunE(_ *cobra.Command, args []string) error { c.contextBuilder = lint.NewContextBuilder(c.cfg, pkgLoader, pkgCache, guard) - if err = initHashSalt(c.buildInfo.Version, c.cfg); err != nil { + if err = initHashSalt(c.log.Child(logutils.DebugKeyGoModSalt), c.buildInfo.Version, c.cfg); err != nil { return fmt.Errorf("failed to init hash salt: %w", err) } @@ -618,7 +620,7 @@ func formatMemory(memBytes uint64) string { // Related to cache. -func initHashSalt(version string, cfg *config.Config) error { +func initHashSalt(logger logutils.Log, version string, cfg *config.Config) error { binSalt, err := computeBinarySalt(version) if err != nil { return fmt.Errorf("failed to calculate binary salt: %w", err) @@ -629,9 +631,18 @@ func initHashSalt(version string, cfg *config.Config) error { return fmt.Errorf("failed to calculate config salt: %w", err) } + goModSalt, err := computeGoModSalt() + if err != nil { + // NOTE: missing go.mod must be ignored. + logger.Warnf("Failed to calculate go.mod salt: %v", err) + } + b := bytes.NewBuffer(binSalt) b.Write(configSalt) + b.WriteString(goModSalt) + cache.SetSalt(b) + return nil } @@ -648,15 +659,19 @@ func computeBinarySalt(version string) ([]byte, error) { 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 } @@ -678,5 +693,29 @@ func computeConfigSalt(cfg *config.Config) ([]byte, error) { if _, err := h.Write(configData.Bytes()); err != nil { return nil, err } + return h.Sum(nil), nil } + +func computeGoModSalt() (string, error) { + values, err := goenv.Get(context.Background(), goenv.GOMOD) + if err != nil { + return "", fmt.Errorf("failed to get goenv: %w", err) + } + + goModPath := filepath.Clean(values[goenv.GOMOD]) + + data, err := os.ReadFile(goModPath) + if err != nil { + return "", fmt.Errorf("failed to read go.mod: %w", err) + } + + sum, err := dirhash.Hash1([]string{goModPath}, func(string) (io.ReadCloser, error) { + return io.NopCloser(bytes.NewReader(data)), nil + }) + if err != nil { + return "", fmt.Errorf("failed to compute go.sum: %w", err) + } + + return sum, nil +} diff --git a/pkg/config/config.go b/pkg/config/config.go index a6236a23f3af..6d7586621d8b 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -13,6 +13,8 @@ import ( "github.com/ldez/grignotin/goenv" "github.com/ldez/grignotin/gomod" "golang.org/x/mod/modfile" + + "github.com/golangci/golangci-lint/v2/pkg/logutils" ) // defaultGoVersion the value should be "oldstable" - 1. @@ -102,8 +104,8 @@ func IsGoGreaterThanOrEqual(current, limit string) bool { return v1.GreaterThanOrEqual(l) } -func detectGoVersion(ctx context.Context) string { - return cmp.Or(detectGoVersionFromGoMod(ctx), defaultGoVersion) +func detectGoVersion(ctx context.Context, log logutils.Log) string { + return cmp.Or(detectGoVersionFromGoMod(ctx, log), defaultGoVersion) } // detectGoVersionFromGoMod tries to get Go version from go.mod. @@ -111,7 +113,7 @@ func detectGoVersion(ctx context.Context) string { // else it returns `go` version if present, // else it returns `GOVERSION` version if present, // else it returns empty. -func detectGoVersionFromGoMod(ctx context.Context) string { +func detectGoVersionFromGoMod(ctx context.Context, log logutils.Log) string { values, err := goenv.Get(ctx, goenv.GOMOD, goenv.GOVERSION) if err != nil { values = map[string]string{ @@ -128,6 +130,10 @@ func detectGoVersionFromGoMod(ctx context.Context) string { return parseGoVersion(values[goenv.GOVERSION]) } + if file.Module != nil { + log.Infof("Module name %q", file.Module.Mod.Path) + } + // The toolchain exists only if 'toolchain' version > 'go' version. // If 'toolchain' version <= 'go' version, `go mod tidy` will remove 'toolchain' version from go.mod. if file.Toolchain != nil && file.Toolchain.Name != "" { diff --git a/pkg/config/loader.go b/pkg/config/loader.go index 19a17e7d71db..3ff9306486ab 100644 --- a/pkg/config/loader.go +++ b/pkg/config/loader.go @@ -161,7 +161,7 @@ func (l *Loader) checkConfigurationVersion() error { func (l *Loader) handleGoVersion() { if l.cfg.Run.Go == "" { - l.cfg.Run.Go = detectGoVersion(context.Background()) + l.cfg.Run.Go = detectGoVersion(context.Background(), l.log) } l.cfg.Linters.Settings.Govet.Go = l.cfg.Run.Go diff --git a/pkg/logutils/logutils.go b/pkg/logutils/logutils.go index 2fbb4a7b2493..0ee48a3664bd 100644 --- a/pkg/logutils/logutils.go +++ b/pkg/logutils/logutils.go @@ -17,6 +17,7 @@ const envDebug = "GL_DEBUG" const ( DebugKeyBinSalt = "bin_salt" + DebugKeyGoModSalt = "gomod_salt" DebugKeyConfigReader = "config_reader" DebugKeyEmpty = "" DebugKeyEnabledLinters = "enabled_linters" From 7326c96cc1e5664263ce376c47c7d03beca1fb10 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Wed, 16 Apr 2025 22:56:36 +0200 Subject: [PATCH 076/152] dev: disable check-generated job (#5742) --- .github/workflows/pr-checks.yml | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index e46b77a06362..f5c69841abef 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -27,21 +27,22 @@ jobs: git diff --exit-code go.mod git diff --exit-code go.sum + # This check is disabled because of GitHub API instability: 504 Gateway Timeout. # Checks: GitHub action assets - check-generated: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - uses: actions/setup-go@v5 - with: - 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 }} +# check-generated: +# runs-on: ubuntu-latest +# steps: +# - uses: actions/checkout@v4 +# with: +# fetch-depth: 0 +# - uses: actions/setup-go@v5 +# with: +# 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 }} check-local-install-script: name: Installation script (local) From 221803a464609c9c6454ff56752854260e4715f6 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Thu, 17 Apr 2025 23:02:11 +0200 Subject: [PATCH 077/152] fix: related information position (#5746) --- pkg/goanalysis/runners.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pkg/goanalysis/runners.go b/pkg/goanalysis/runners.go index 5ffc1529363b..fe8d8fe854d3 100644 --- a/pkg/goanalysis/runners.go +++ b/pkg/goanalysis/runners.go @@ -136,10 +136,16 @@ func buildIssues(diags []Diagnostic, linterNameBuilder func(diag *Diagnostic) st if len(diag.Related) > 0 { for _, info := range diag.Related { + relatedPos := diag.Pkg.Fset.Position(info.Pos) + + if relatedPos.Filename != diag.Position.Filename { + relatedPos = diag.Position + } + issues = append(issues, result.Issue{ FromLinter: linterName, Text: fmt.Sprintf("%s(related information): %s", diag.Analyzer.Name, info.Message), - Pos: diag.Pkg.Fset.Position(info.Pos), + Pos: relatedPos, Pkg: diag.Pkg, }) } From c77bb6ba8cbd512446d576b43db9c196a1f1fb4d Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Sat, 19 Apr 2025 16:25:44 +0200 Subject: [PATCH 078/152] docs: GoLand IDE only support v1 for now (#5750) --- docs/src/docs/welcome/integrations.mdx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/src/docs/welcome/integrations.mdx b/docs/src/docs/welcome/integrations.mdx index 02850e1a60c7..5ffa4c6e73db 100644 --- a/docs/src/docs/welcome/integrations.mdx +++ b/docs/src/docs/welcome/integrations.mdx @@ -6,9 +6,10 @@ title: Integrations ### GoLand -Starting from the version 2025.1, GoLand has built-in support of golangci-lint. +Starting from version 2025.1, GoLand has built-in support of golangci-lint. For IntelliJ IDEA with the Go plugin, please install the [plugin](https://plugins.jetbrains.com/plugin/12496-go-linter). -Both v1 and v2 versions are supported. + +**Only v1 is supported for now.** ### Visual Studio Code From d0588f0b92414cf65930b33e1b197428600a6359 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Mon, 21 Apr 2025 16:34:49 +0200 Subject: [PATCH 079/152] fix: convert uint as pointer of uint for the migration (#5755) --- .../internal/migrate/cloner/cloner.go | 2 +- .../linters-settings_nakedret_zero.golden.yml | 6 ++++ .../yaml/linters-settings_nakedret_zero.yml | 11 +++++++ .../migrate/versionone/linters_settings.go | 2 +- .../internal/migrate/versiontwo/formatters.go | 5 +-- .../migrate/versiontwo/linters_settings.go | 32 +++++++++++++------ .../internal/migrate/versiontwo/output.go | 3 +- 7 files changed, 47 insertions(+), 14 deletions(-) create mode 100644 pkg/commands/internal/migrate/testdata/yaml/linters-settings_nakedret_zero.golden.yml create mode 100644 pkg/commands/internal/migrate/testdata/yaml/linters-settings_nakedret_zero.yml diff --git a/pkg/commands/internal/migrate/cloner/cloner.go b/pkg/commands/internal/migrate/cloner/cloner.go index 9c2400bc69b1..9a94aaf8e070 100644 --- a/pkg/commands/internal/migrate/cloner/cloner.go +++ b/pkg/commands/internal/migrate/cloner/cloner.go @@ -142,7 +142,7 @@ func convertType(expr ast.Expr) ast.Expr { } switch ident.Name { - case "bool", "string", "int", "int8", "int16", "int32", "int64", "float32", "float64": + case "bool", "string", "uint", "uint8", "uint16", "uint32", "uint64", "int", "int8", "int16", "int32", "int64", "float32", "float64": return &ast.StarExpr{X: ident} default: diff --git a/pkg/commands/internal/migrate/testdata/yaml/linters-settings_nakedret_zero.golden.yml b/pkg/commands/internal/migrate/testdata/yaml/linters-settings_nakedret_zero.golden.yml new file mode 100644 index 000000000000..69e5a3b11394 --- /dev/null +++ b/pkg/commands/internal/migrate/testdata/yaml/linters-settings_nakedret_zero.golden.yml @@ -0,0 +1,6 @@ +version: "2" + +linters: + settings: + nakedret: + max-func-lines: 0 diff --git a/pkg/commands/internal/migrate/testdata/yaml/linters-settings_nakedret_zero.yml b/pkg/commands/internal/migrate/testdata/yaml/linters-settings_nakedret_zero.yml new file mode 100644 index 000000000000..c15f3c7bab1a --- /dev/null +++ b/pkg/commands/internal/migrate/testdata/yaml/linters-settings_nakedret_zero.yml @@ -0,0 +1,11 @@ +issues: + # Only to not generate unrelated elements inside golden. + exclude-use-default: false + # Only to not generate unrelated elements inside golden. + exclude-generated: strict + # Only to not generate unrelated elements inside golden. + exclude-dirs-use-default: false + +linters-settings: + nakedret: + max-func-lines: 0 diff --git a/pkg/commands/internal/migrate/versionone/linters_settings.go b/pkg/commands/internal/migrate/versionone/linters_settings.go index 49427c447530..44583b7d34e0 100644 --- a/pkg/commands/internal/migrate/versionone/linters_settings.go +++ b/pkg/commands/internal/migrate/versionone/linters_settings.go @@ -489,7 +489,7 @@ type MustTagSettings struct { } type NakedretSettings struct { - MaxFuncLines uint `mapstructure:"max-func-lines"` + MaxFuncLines *uint `mapstructure:"max-func-lines"` } type NestifSettings struct { diff --git a/pkg/commands/internal/migrate/versiontwo/formatters.go b/pkg/commands/internal/migrate/versiontwo/formatters.go index bd1b6f931155..417714947a69 100644 --- a/pkg/commands/internal/migrate/versiontwo/formatters.go +++ b/pkg/commands/internal/migrate/versiontwo/formatters.go @@ -9,6 +9,7 @@ type Formatters struct { } type FormatterExclusions struct { - Generated *string `yaml:"generated,omitempty" toml:"generated,multiline,omitempty"` - Paths []string `yaml:"paths,omitempty" toml:"paths,multiline,omitempty"` + Generated *string `yaml:"generated,omitempty" toml:"generated,multiline,omitempty"` + Paths []string `yaml:"paths,omitempty" toml:"paths,multiline,omitempty"` + WarnUnused *bool `yaml:"warn-unused,omitempty" toml:"warn-unused,multiline,omitempty"` } diff --git a/pkg/commands/internal/migrate/versiontwo/linters_settings.go b/pkg/commands/internal/migrate/versiontwo/linters_settings.go index 3461620e20f7..3a0d6b7b6a2a 100644 --- a/pkg/commands/internal/migrate/versiontwo/linters_settings.go +++ b/pkg/commands/internal/migrate/versiontwo/linters_settings.go @@ -21,6 +21,7 @@ type LintersSettings struct { Exhaustruct ExhaustructSettings `yaml:"exhaustruct,omitempty" toml:"exhaustruct,multiline,omitempty"` Fatcontext FatcontextSettings `yaml:"fatcontext,omitempty" toml:"fatcontext,multiline,omitempty"` Forbidigo ForbidigoSettings `yaml:"forbidigo,omitempty" toml:"forbidigo,multiline,omitempty"` + FuncOrder FuncOrderSettings `yaml:"funcorder,omitempty" toml:"funcorder,multiline,omitempty"` Funlen FunlenSettings `yaml:"funlen,omitempty" toml:"funlen,multiline,omitempty"` GinkgoLinter GinkgoLinterSettings `yaml:"ginkgolinter,omitempty" toml:"ginkgolinter,multiline,omitempty"` Gocognit GocognitSettings `yaml:"gocognit,omitempty" toml:"gocognit,multiline,omitempty"` @@ -210,6 +211,11 @@ type ForbidigoPattern struct { Msg *string `yaml:"msg,omitempty,omitempty" toml:"msg,omitempty,multiline,omitempty"` } +type FuncOrderSettings struct { + Constructor *bool `yaml:"constructor,omitempty,omitempty" toml:"constructor,omitempty,multiline,omitempty"` + StructMethod *bool `yaml:"struct-method,omitempty,omitempty" toml:"struct-method,omitempty,multiline,omitempty"` +} + type FunlenSettings struct { Lines *int `yaml:"lines,omitempty" toml:"lines,multiline,omitempty"` Statements *int `yaml:"statements,omitempty" toml:"statements,multiline,omitempty"` @@ -241,14 +247,18 @@ type GocognitSettings struct { } type GoConstSettings struct { - IgnoreStrings *string `yaml:"ignore-strings,omitempty" toml:"ignore-strings,multiline,omitempty"` - MatchWithConstants *bool `yaml:"match-constant,omitempty" toml:"match-constant,multiline,omitempty"` - MinStringLen *int `yaml:"min-len,omitempty" toml:"min-len,multiline,omitempty"` - MinOccurrencesCount *int `yaml:"min-occurrences,omitempty" toml:"min-occurrences,multiline,omitempty"` - ParseNumbers *bool `yaml:"numbers,omitempty" toml:"numbers,multiline,omitempty"` - NumberMin *int `yaml:"min,omitempty" toml:"min,multiline,omitempty"` - NumberMax *int `yaml:"max,omitempty" toml:"max,multiline,omitempty"` - IgnoreCalls *bool `yaml:"ignore-calls,omitempty" toml:"ignore-calls,multiline,omitempty"` + IgnoreStringValues []string `yaml:"ignore-string-values,omitempty" toml:"ignore-string-values,multiline,omitempty"` + MatchWithConstants *bool `yaml:"match-constant,omitempty" toml:"match-constant,multiline,omitempty"` + MinStringLen *int `yaml:"min-len,omitempty" toml:"min-len,multiline,omitempty"` + MinOccurrencesCount *int `yaml:"min-occurrences,omitempty" toml:"min-occurrences,multiline,omitempty"` + ParseNumbers *bool `yaml:"numbers,omitempty" toml:"numbers,multiline,omitempty"` + NumberMin *int `yaml:"min,omitempty" toml:"min,multiline,omitempty"` + NumberMax *int `yaml:"max,omitempty" toml:"max,multiline,omitempty"` + IgnoreCalls *bool `yaml:"ignore-calls,omitempty" toml:"ignore-calls,multiline,omitempty"` + FindDuplicates *bool `yaml:"find-duplicates,omitempty" toml:"find-duplicates,multiline,omitempty"` + EvalConstExpressions *bool `yaml:"eval-const-expressions,omitempty" toml:"eval-const-expressions,multiline,omitempty"` + + IgnoreStrings *string `yaml:"ignore-strings,omitempty" toml:"ignore-strings,multiline,omitempty"` } type GoCriticSettings struct { @@ -436,7 +446,7 @@ type MustTagFunction struct { } type NakedretSettings struct { - MaxFuncLines uint `yaml:"max-func-lines,omitempty" toml:"max-func-lines,multiline,omitempty"` + MaxFuncLines *uint `yaml:"max-func-lines,omitempty" toml:"max-func-lines,multiline,omitempty"` } type NestifSettings struct { @@ -444,6 +454,7 @@ type NestifSettings struct { } type NilNilSettings struct { + OnlyTwo *bool `yaml:"only-two,omitempty" toml:"only-two,multiline,omitempty"` DetectOpposite *bool `yaml:"detect-opposite,omitempty" toml:"detect-opposite,multiline,omitempty"` CheckedTypes []string `yaml:"checked-types,omitempty" toml:"checked-types,multiline,omitempty"` } @@ -560,6 +571,7 @@ type SlogLintSettings struct { NoGlobal *string `yaml:"no-global,omitempty" toml:"no-global,multiline,omitempty"` Context *string `yaml:"context,omitempty" toml:"context,multiline,omitempty"` StaticMsg *bool `yaml:"static-msg,omitempty" toml:"static-msg,multiline,omitempty"` + MsgStyle *string `yaml:"msg-style,omitempty" toml:"msg-style,multiline,omitempty"` NoRawKeys *bool `yaml:"no-raw-keys,omitempty" toml:"no-raw-keys,multiline,omitempty"` KeyNamingCase *string `yaml:"key-naming-case,omitempty" toml:"key-naming-case,multiline,omitempty"` ForbiddenKeys []string `yaml:"forbidden-keys,omitempty" toml:"forbidden-keys,multiline,omitempty"` @@ -639,6 +651,7 @@ type TestifylintExpectedActual struct { type TestifylintFormatter struct { CheckFormatString *bool `yaml:"check-format-string,omitempty" toml:"check-format-string,multiline,omitempty"` RequireFFuncs *bool `yaml:"require-f-funcs,omitempty" toml:"require-f-funcs,multiline,omitempty"` + RequireStringMsg *bool `yaml:"require-string-msg,omitempty" toml:"require-string-msg,multiline,omitempty"` } type TestifylintGoRequire struct { @@ -736,6 +749,7 @@ type WrapcheckSettings struct { IgnoreSigRegexps []string `yaml:"ignore-sig-regexps,omitempty" toml:"ignore-sig-regexps,multiline,omitempty"` IgnorePackageGlobs []string `yaml:"ignore-package-globs,omitempty" toml:"ignore-package-globs,multiline,omitempty"` IgnoreInterfaceRegexps []string `yaml:"ignore-interface-regexps,omitempty" toml:"ignore-interface-regexps,multiline,omitempty"` + ReportInternalErrors *bool `yaml:"report-internal-errors,omitempty" toml:"report-internal-errors,multiline,omitempty"` } type WSLSettings struct { diff --git a/pkg/commands/internal/migrate/versiontwo/output.go b/pkg/commands/internal/migrate/versiontwo/output.go index ed6bab7e375d..16afb6701eef 100644 --- a/pkg/commands/internal/migrate/versiontwo/output.go +++ b/pkg/commands/internal/migrate/versiontwo/output.go @@ -5,6 +5,7 @@ package versiontwo type Output struct { Formats Formats `yaml:"formats,omitempty" toml:"formats,multiline,omitempty"` SortOrder []string `yaml:"sort-order,omitempty" toml:"sort-order,multiline,omitempty"` - PathPrefix *string `yaml:"path-prefix,omitempty" toml:"path-prefix,multiline,omitempty"` ShowStats *bool `yaml:"show-stats,omitempty" toml:"show-stats,multiline,omitempty"` + PathPrefix *string `yaml:"path-prefix,omitempty" toml:"path-prefix,multiline,omitempty"` + PathMode *string `yaml:"path-mode,omitempty" toml:"path-mode,multiline,omitempty"` } From 6d2a94be6b20f1c06e95d79479c6fdc34a69c45f Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Mon, 21 Apr 2025 20:11:02 +0200 Subject: [PATCH 080/152] build(deps): bump go.augendre.info/fatcontext from 0.7.2 to 0.8.0 (#5757) --- go.mod | 2 +- go.sum | 4 ++-- pkg/golinters/fatcontext/fatcontext.go | 2 +- scripts/website/expand_templates/thanks.go | 3 +++ 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 00695fdf37ad..a8835e203561 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,6 @@ require ( github.com/Antonboom/nilnil v1.1.0 github.com/Antonboom/testifylint v1.6.1 github.com/BurntSushi/toml v1.5.0 - github.com/Crocmagnon/fatcontext v0.7.2 github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1 github.com/OpenPeeDeeP/depguard/v2 v2.2.1 @@ -127,6 +126,7 @@ require ( gitlab.com/bosi/decorder v0.4.2 go-simpler.org/musttag v0.13.0 go-simpler.org/sloglint v0.11.0 + go.augendre.info/fatcontext v0.8.0 go.uber.org/automaxprocs v1.6.0 golang.org/x/mod v0.24.0 golang.org/x/sys v0.32.0 diff --git a/go.sum b/go.sum index 9bc80fb7cd9b..ff028d1c4652 100644 --- a/go.sum +++ b/go.sum @@ -49,8 +49,6 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/Crocmagnon/fatcontext v0.7.2 h1:BY5/dUhs2kuD3sDn7vZrgOneRib5EHk9GOiyK8Vg+14= -github.com/Crocmagnon/fatcontext v0.7.2/go.mod h1:OAZCUteH59eiddbJZ9/bF4ppC140jYD/hepU2FDkFk4= 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/v3 v3.3.1 h1:Sz1JIXEcSfhz7fUi7xHnhpIE0thVASYjvosApmHuD2k= @@ -630,6 +628,8 @@ go-simpler.org/musttag v0.13.0 h1:Q/YAW0AHvaoaIbsPj3bvEI5/QFP7w696IMUpnKXQfCE= go-simpler.org/musttag v0.13.0/go.mod h1:FTzIGeK6OkKlUDVpj0iQUXZLUO1Js9+mvykDQy9C5yM= go-simpler.org/sloglint v0.11.0 h1:JlR1X4jkbeaffiyjLtymeqmGDKBDO1ikC6rjiuFAOco= go-simpler.org/sloglint v0.11.0/go.mod h1:CFDO8R1i77dlciGfPEPvYke2ZMx4eyGiEIWkyeW2Pvw= +go.augendre.info/fatcontext v0.8.0 h1:2dfk6CQbDGeu1YocF59Za5Pia7ULeAM6friJ3LP7lmk= +go.augendre.info/fatcontext v0.8.0/go.mod h1:oVJfMgwngMsHO+KB2MdgzcO+RvtNdiCEOlWvSFtax/s= 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= diff --git a/pkg/golinters/fatcontext/fatcontext.go b/pkg/golinters/fatcontext/fatcontext.go index 8f34064dc057..e0506259bee9 100644 --- a/pkg/golinters/fatcontext/fatcontext.go +++ b/pkg/golinters/fatcontext/fatcontext.go @@ -1,7 +1,7 @@ package fatcontext import ( - "github.com/Crocmagnon/fatcontext/pkg/analyzer" + "go.augendre.info/fatcontext/pkg/analyzer" "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" diff --git a/scripts/website/expand_templates/thanks.go b/scripts/website/expand_templates/thanks.go index 66ee8511c6e8..a3a0035cf60c 100644 --- a/scripts/website/expand_templates/thanks.go +++ b/scripts/website/expand_templates/thanks.go @@ -99,6 +99,9 @@ func extractInfo(lc *linter.Config) authorInfo { case "misspell": return authorInfo{Author: "client9", Host: hostGitHub} + case "fatcontext": + return authorInfo{Author: "Crocmagnon", Host: hostGitHub} + default: if strings.HasPrefix(lc.OriginalURL, "https://pkg.go.dev/") { return authorInfo{Author: "golang", Host: hostGitHub} From 2f6a2f41948d57d4d837a8c89c071f739d5434e6 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Tue, 22 Apr 2025 12:28:51 +0200 Subject: [PATCH 081/152] docs: GoLand IDE support v2 (#5758) --- docs/src/docs/welcome/integrations.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/docs/welcome/integrations.mdx b/docs/src/docs/welcome/integrations.mdx index 5ffa4c6e73db..747b7ee29e2d 100644 --- a/docs/src/docs/welcome/integrations.mdx +++ b/docs/src/docs/welcome/integrations.mdx @@ -9,7 +9,7 @@ title: Integrations Starting from version 2025.1, GoLand has built-in support of golangci-lint. For IntelliJ IDEA with the Go plugin, please install the [plugin](https://plugins.jetbrains.com/plugin/12496-go-linter). -**Only v1 is supported for now.** +Both v1 and v2 versions are supported. ### Visual Studio Code From ce777622c61db6fbcc8c5d1c6c733eb97829bfa3 Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Tue, 22 Apr 2025 22:50:13 +0200 Subject: [PATCH 082/152] chore: prepare release --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 08b729267d2c..b2b57f004361 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,16 @@ If you value it, consider supporting us, we appreciate it! ❤️ ### v2.1.2 +1. Linters bug fixes + * `fatcontext`: from 0.7.2 to 0.8.0 +2. Misc. + * migration: fix `nakedret.max-func-lines: 0` + * migration: fix order of `staticcheck` settings + * fix: add `go.mod` hash to the cache salt + * fix: use diagnostic position for related information position + +### v2.1.2 + 1. Linters bug fixes * `exptostd`: from 0.4.2 to 0.4.3 * `gofumpt`: from 0.7.0 to 0.8.0 From 8ac3c76d49578ec3ac50d27a88a8a3c88760b2b2 Mon Sep 17 00:00:00 2001 From: GolangCI-Lint Releaser <65486276+golangci-releaser@users.noreply.github.com> Date: Thu, 24 Apr 2025 19:25:27 +0200 Subject: [PATCH 083/152] docs: update GitHub Action assets (#5762) --- assets/github-action-config-v2.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/github-action-config-v2.json b/assets/github-action-config-v2.json index 4ec367aa9ef7..99f2a6f8b3c9 100644 --- a/assets/github-action-config-v2.json +++ b/assets/github-action-config-v2.json @@ -1,7 +1,7 @@ { "MinorVersionToConfig": { "latest": { - "TargetVersion": "v2.1.2" + "TargetVersion": "v2.1.3" }, "v1.10": { "Error": "golangci-lint version 'v1.10' isn't supported: we support only v2.0.0 and later versions" @@ -193,7 +193,7 @@ "TargetVersion": "v2.0.2" }, "v2.1": { - "TargetVersion": "v2.1.2" + "TargetVersion": "v2.1.3" } } } From 6ed40806ab563c7fc5bd7bb1d8b441f2d76a0f8a Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Thu, 24 Apr 2025 19:31:36 +0200 Subject: [PATCH 084/152] chore: prepare release (#5763) --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b2b57f004361..6fe75cef256a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,13 @@ If you value it, consider supporting us, we appreciate it! ❤️ [![Open Collective backers and sponsors](https://img.shields.io/badge/OpenCollective-Donate-blue?logo=opencollective&style=for-the-badge)](https://opencollective.com/golangci-lint) [![GitHub Sponsors](https://img.shields.io/badge/GitHub-Donate-blue?logo=github&style=for-the-badge)](https://github.com/sponsors/golangci) -### v2.1.2 +### v2.1.4 + +Due to an error related to Snapcraft, some artifacts of the v2.1.3 release have not been published. + +This release contains the same things as v2.1.3. + +### v2.1.3 1. Linters bug fixes * `fatcontext`: from 0.7.2 to 0.8.0 From b20759833c1d9974349b26b800c545b925ccb771 Mon Sep 17 00:00:00 2001 From: GolangCI-Lint Releaser <65486276+golangci-releaser@users.noreply.github.com> Date: Thu, 24 Apr 2025 20:10:44 +0200 Subject: [PATCH 085/152] docs: update GitHub Action assets (#5764) --- assets/github-action-config-v2.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/github-action-config-v2.json b/assets/github-action-config-v2.json index 99f2a6f8b3c9..21655966a391 100644 --- a/assets/github-action-config-v2.json +++ b/assets/github-action-config-v2.json @@ -1,7 +1,7 @@ { "MinorVersionToConfig": { "latest": { - "TargetVersion": "v2.1.3" + "TargetVersion": "v2.1.4" }, "v1.10": { "Error": "golangci-lint version 'v1.10' isn't supported: we support only v2.0.0 and later versions" @@ -193,7 +193,7 @@ "TargetVersion": "v2.0.2" }, "v2.1": { - "TargetVersion": "v2.1.3" + "TargetVersion": "v2.1.4" } } } From 8c14421d29bd005dee63044d07aa897b7d1bf8b0 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Thu, 24 Apr 2025 21:22:31 +0200 Subject: [PATCH 086/152] chore: prepare release (#5765) --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6fe75cef256a..c0d05c10ac45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ If you value it, consider supporting us, we appreciate it! ❤️ [![Open Collective backers and sponsors](https://img.shields.io/badge/OpenCollective-Donate-blue?logo=opencollective&style=for-the-badge)](https://opencollective.com/golangci-lint) [![GitHub Sponsors](https://img.shields.io/badge/GitHub-Donate-blue?logo=github&style=for-the-badge)](https://github.com/sponsors/golangci) +### v2.1.5 + +Due to an error related to Snapcraft, some artifacts of the v2.1.4 release have not been published. + +This release contains the same things as v2.1.3. + ### v2.1.4 Due to an error related to Snapcraft, some artifacts of the v2.1.3 release have not been published. From f6c2e6c999dfae444d1fe7f1b0d49becdae44547 Mon Sep 17 00:00:00 2001 From: GolangCI-Lint Releaser <65486276+golangci-releaser@users.noreply.github.com> Date: Thu, 24 Apr 2025 21:58:42 +0200 Subject: [PATCH 087/152] docs: update GitHub Action assets (#5766) --- assets/github-action-config-v2.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/github-action-config-v2.json b/assets/github-action-config-v2.json index 21655966a391..45ba44130ecc 100644 --- a/assets/github-action-config-v2.json +++ b/assets/github-action-config-v2.json @@ -1,7 +1,7 @@ { "MinorVersionToConfig": { "latest": { - "TargetVersion": "v2.1.4" + "TargetVersion": "v2.1.5" }, "v1.10": { "Error": "golangci-lint version 'v1.10' isn't supported: we support only v2.0.0 and later versions" @@ -193,7 +193,7 @@ "TargetVersion": "v2.0.2" }, "v2.1": { - "TargetVersion": "v2.1.4" + "TargetVersion": "v2.1.5" } } } From 46b086a9ad559fd1fc69cd9310455cda0fdc0d2a Mon Sep 17 00:00:00 2001 From: Tom Vendolsky <75443136+lvlcn-t@users.noreply.github.com> Date: Sat, 26 Apr 2025 16:46:38 +0200 Subject: [PATCH 088/152] docs: add note about golangci-lint v2 integration in VS Code (#5768) --- docs/src/docs/welcome/integrations.mdx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/src/docs/welcome/integrations.mdx b/docs/src/docs/welcome/integrations.mdx index 747b7ee29e2d..03e6d7e8d57e 100644 --- a/docs/src/docs/welcome/integrations.mdx +++ b/docs/src/docs/welcome/integrations.mdx @@ -15,6 +15,8 @@ Both v1 and v2 versions are supported. Install the [extension](https://marketplace.visualstudio.com/items?itemName=golang.Go). +**Note:** To use golangci-lint v2, you may need to switch to the pre-release version of the extension: [vscode-go#3732](https://github.com/golang/vscode-go/issues/3732#issuecomment-2805974456). +
Recommended settings for those who installed golangci-lint manually From 69778fe6e7f8c8c6d211be3d105a645352267d79 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 27 Apr 2025 13:37:09 +0200 Subject: [PATCH 089/152] build(deps): bump go-simpler.org/musttag from 0.13.0 to 0.13.1 (#5769) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a8835e203561..299b00f4b7ad 100644 --- a/go.mod +++ b/go.mod @@ -124,7 +124,7 @@ require ( github.com/yeya24/promlinter v0.3.0 github.com/ykadowak/zerologlint v0.1.5 gitlab.com/bosi/decorder v0.4.2 - go-simpler.org/musttag v0.13.0 + go-simpler.org/musttag v0.13.1 go-simpler.org/sloglint v0.11.0 go.augendre.info/fatcontext v0.8.0 go.uber.org/automaxprocs v1.6.0 diff --git a/go.sum b/go.sum index ff028d1c4652..f6145378e65f 100644 --- a/go.sum +++ b/go.sum @@ -624,8 +624,8 @@ gitlab.com/bosi/decorder v0.4.2 h1:qbQaV3zgwnBZ4zPMhGLW4KZe7A7NwxEhJx39R3shffo= gitlab.com/bosi/decorder v0.4.2/go.mod h1:muuhHoaJkA9QLcYHq4Mj8FJUwDZ+EirSHRiaTcTf6T8= go-simpler.org/assert v0.9.0 h1:PfpmcSvL7yAnWyChSjOz6Sp6m9j5lyK8Ok9pEL31YkQ= go-simpler.org/assert v0.9.0/go.mod h1:74Eqh5eI6vCK6Y5l3PI8ZYFXG4Sa+tkr70OIPJAUr28= -go-simpler.org/musttag v0.13.0 h1:Q/YAW0AHvaoaIbsPj3bvEI5/QFP7w696IMUpnKXQfCE= -go-simpler.org/musttag v0.13.0/go.mod h1:FTzIGeK6OkKlUDVpj0iQUXZLUO1Js9+mvykDQy9C5yM= +go-simpler.org/musttag v0.13.1 h1:lw2sJyu7S1X8lc8zWUAdH42y+afdcCnHhWpnkWvd6vU= +go-simpler.org/musttag v0.13.1/go.mod h1:8r450ehpMLQgvpb6sg+hV5Ur47eH6olp/3yEanfG97k= go-simpler.org/sloglint v0.11.0 h1:JlR1X4jkbeaffiyjLtymeqmGDKBDO1ikC6rjiuFAOco= go-simpler.org/sloglint v0.11.0/go.mod h1:CFDO8R1i77dlciGfPEPvYke2ZMx4eyGiEIWkyeW2Pvw= go.augendre.info/fatcontext v0.8.0 h1:2dfk6CQbDGeu1YocF59Za5Pia7ULeAM6friJ3LP7lmk= From 896c0417487bfc7ab34c328dded269e5c4e1acc9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 27 Apr 2025 13:55:13 +0200 Subject: [PATCH 090/152] build(deps): bump github.com/alecthomas/chroma/v2 from 2.16.0 to 2.17.0 (#5772) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 299b00f4b7ad..721d47da1d09 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1 github.com/OpenPeeDeeP/depguard/v2 v2.2.1 - github.com/alecthomas/chroma/v2 v2.16.0 + github.com/alecthomas/chroma/v2 v2.17.0 github.com/alecthomas/go-check-sumtype v0.3.1 github.com/alexkohler/nakedret/v2 v2.0.6 github.com/alexkohler/prealloc v1.0.0 diff --git a/go.sum b/go.sum index f6145378e65f..ae592c359d42 100644 --- a/go.sum +++ b/go.sum @@ -59,8 +59,8 @@ github.com/OpenPeeDeeP/depguard/v2 v2.2.1 h1:vckeWVESWp6Qog7UZSARNqfu/cZqvki8zsu github.com/OpenPeeDeeP/depguard/v2 v2.2.1/go.mod h1:q4DKzC4UcVaAvcfd41CZh0PWpGgzrVxUYBlgKNGquUo= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= -github.com/alecthomas/chroma/v2 v2.16.0 h1:QC5ZMizk67+HzxFDjQ4ASjni5kWBTGiigRG1u23IGvA= -github.com/alecthomas/chroma/v2 v2.16.0/go.mod h1:RVX6AvYm4VfYe/zsk7mjHueLDZor3aWCNE14TFlepBk= +github.com/alecthomas/chroma/v2 v2.17.0 h1:3r2Cgk+nXNICMBxIFGnTRTbQFUwMiLisW+9uos0TtUI= +github.com/alecthomas/chroma/v2 v2.17.0/go.mod h1:RVX6AvYm4VfYe/zsk7mjHueLDZor3aWCNE14TFlepBk= github.com/alecthomas/go-check-sumtype v0.3.1 h1:u9aUvbGINJxLVXiFvHUlPEaD7VDULsrxJb4Aq31NLkU= github.com/alecthomas/go-check-sumtype v0.3.1/go.mod h1:A8TSiN3UPRw3laIgWEUOHHLPa6/r9MtoigdlP5h3K/E= github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= From 1b791de9afa9dfae80a029ed2141918063b26c20 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 27 Apr 2025 14:06:48 +0200 Subject: [PATCH 091/152] build(deps): bump github.com/tetafro/godot from 1.5.0 to 1.5.1 (#5770) Co-authored-by: Fernandez Ludovic --- go.mod | 2 +- go.sum | 4 ++-- pkg/golinters/godot/testdata/fix/in/godot.go | 7 +++++++ pkg/golinters/godot/testdata/fix/out/godot.go | 7 +++++++ pkg/golinters/godot/testdata/godot.go | 9 +++++++++ 5 files changed, 26 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 721d47da1d09..ec68a6153c50 100644 --- a/go.mod +++ b/go.mod @@ -109,7 +109,7 @@ require ( github.com/stbenjam/no-sprintf-host-port v0.2.0 github.com/stretchr/testify v1.10.0 github.com/tdakkota/asciicheck v0.4.1 - github.com/tetafro/godot v1.5.0 + github.com/tetafro/godot v1.5.1 github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67 github.com/timonwong/loggercheck v0.11.0 github.com/tomarrell/wrapcheck/v2 v2.11.0 diff --git a/go.sum b/go.sum index ae592c359d42..f1d4e0d34ecf 100644 --- a/go.sum +++ b/go.sum @@ -575,8 +575,8 @@ 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.5.0 h1:aNwfVI4I3+gdxjMgYPus9eHmoBeJIbnajOyqZYStzuw= -github.com/tetafro/godot v1.5.0/go.mod h1:2oVxTBSftRTh4+MVfUaUXR6bn2GDXCaMcOG4Dk3rfio= +github.com/tetafro/godot v1.5.1 h1:PZnjCol4+FqaEzvZg5+O8IY2P3hfY9JzRBNPv1pEDS4= +github.com/tetafro/godot v1.5.1/go.mod h1:cCdPtEndkmqqrhiCfkmxDodMQJ/f3L1BCNskCUZdTwk= github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67 h1:9LPGD+jzxMlnk5r6+hJnar67cgpDIz/iyD+rfl5r2Vk= github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67/go.mod h1:mkjARE7Yr8qU23YcGMSALbIxTQ9r9QBVahQOBRfU460= github.com/timonwong/loggercheck v0.11.0 h1:jdaMpYBl+Uq9mWPXv1r8jc5fC3gyXx4/WGwTnnNKn4M= diff --git a/pkg/golinters/godot/testdata/fix/in/godot.go b/pkg/golinters/godot/testdata/fix/in/godot.go index 13b8da1c0ea9..d662c7ca53de 100644 --- a/pkg/golinters/godot/testdata/fix/in/godot.go +++ b/pkg/golinters/godot/testdata/fix/in/godot.go @@ -11,3 +11,10 @@ func godot(a, b int) int { // Nothing to do here return a + b } + +// Foo Lorem ipsum dolor sit amet, consectetur adipiscing elit. +// Aenean rhoncus odio enim, et pulvinar libero ultrices quis. +// Nulla at erat tellus. Maecenas id dapibus velit, ut porttitor ipsum +func Foo() { + // nothing to do here +} diff --git a/pkg/golinters/godot/testdata/fix/out/godot.go b/pkg/golinters/godot/testdata/fix/out/godot.go index 6960f06c044c..11d633e280c1 100644 --- a/pkg/golinters/godot/testdata/fix/out/godot.go +++ b/pkg/golinters/godot/testdata/fix/out/godot.go @@ -11,3 +11,10 @@ func godot(a, b int) int { // Nothing to do here return a + b } + +// Foo Lorem ipsum dolor sit amet, consectetur adipiscing elit. +// Aenean rhoncus odio enim, et pulvinar libero ultrices quis. +// Nulla at erat tellus. Maecenas id dapibus velit, ut porttitor ipsum. +func Foo() { + // nothing to do here +} diff --git a/pkg/golinters/godot/testdata/godot.go b/pkg/golinters/godot/testdata/godot.go index 93a904894691..c81134687b2a 100644 --- a/pkg/golinters/godot/testdata/godot.go +++ b/pkg/golinters/godot/testdata/godot.go @@ -7,3 +7,12 @@ package testdata func Godot() { // nothing to do here } + +// want +4 "Comment should end in a period" + +// Foo Lorem ipsum dolor sit amet, consectetur adipiscing elit. +// Aenean rhoncus odio enim, et pulvinar libero ultrices quis. +// Nulla at erat tellus. Maecenas id dapibus velit, ut porttitor ipsum +func Foo() { + // nothing to do here +} From 6973f4cf335f10e81bbcb2488cc27e6bb8729062 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Apr 2025 21:37:05 +0200 Subject: [PATCH 092/152] build(deps): bump base-x from 3.0.9 to 3.0.11 in /docs (#5776) --- docs/package-lock.json | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/package-lock.json b/docs/package-lock.json index 5693665902e0..ccf2b1809d7f 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -5885,9 +5885,10 @@ } }, "node_modules/base-x": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", - "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.11.tgz", + "integrity": "sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==", + "license": "MIT", "dependencies": { "safe-buffer": "^5.0.1" } @@ -28360,9 +28361,9 @@ } }, "base-x": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", - "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.11.tgz", + "integrity": "sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==", "requires": { "safe-buffer": "^5.0.1" } From 2ea61ac0ae9adeddc5551e444eb2c852df09e941 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 May 2025 13:55:08 +0200 Subject: [PATCH 093/152] build(deps): bump the linter-testdata group across 2 directories with 2 updates (#5777) --- pkg/golinters/ginkgolinter/testdata/go.mod | 9 ++++---- pkg/golinters/ginkgolinter/testdata/go.sum | 27 ++++++++++++++-------- pkg/golinters/protogetter/testdata/go.mod | 4 ++-- pkg/golinters/protogetter/testdata/go.sum | 8 +++---- 4 files changed, 29 insertions(+), 19 deletions(-) diff --git a/pkg/golinters/ginkgolinter/testdata/go.mod b/pkg/golinters/ginkgolinter/testdata/go.mod index b9c242a0ded4..fe2cc945898c 100644 --- a/pkg/golinters/ginkgolinter/testdata/go.mod +++ b/pkg/golinters/ginkgolinter/testdata/go.mod @@ -3,7 +3,7 @@ module ginkgolinter go 1.23.0 require ( - github.com/onsi/ginkgo/v2 v2.23.3 + github.com/onsi/ginkgo/v2 v2.23.4 github.com/onsi/gomega v1.37.0 ) @@ -11,10 +11,11 @@ require ( github.com/go-logr/logr v1.4.2 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/google/go-cmp v0.7.0 // indirect - github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect + github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect + go.uber.org/automaxprocs v1.6.0 // indirect golang.org/x/net v0.37.0 // indirect - golang.org/x/sys v0.31.0 // indirect + golang.org/x/sys v0.32.0 // indirect golang.org/x/text v0.23.0 // indirect - golang.org/x/tools v0.30.0 // indirect + golang.org/x/tools v0.31.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/pkg/golinters/ginkgolinter/testdata/go.sum b/pkg/golinters/ginkgolinter/testdata/go.sum index 4a6722c54bc5..0acd79618257 100644 --- a/pkg/golinters/ginkgolinter/testdata/go.sum +++ b/pkg/golinters/ginkgolinter/testdata/go.sum @@ -6,27 +6,36 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg= -github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= -github.com/onsi/ginkgo/v2 v2.23.3 h1:edHxnszytJ4lD9D5Jjc4tiDkPBZ3siDeJJkUZJJVkp0= -github.com/onsi/ginkgo/v2 v2.23.3/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM= +github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8= +github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus= +github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8= github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y= github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0= 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/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= +github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= +go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= +golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= -golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= -golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= +golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU= +golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ= google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= -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/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 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/pkg/golinters/protogetter/testdata/go.mod b/pkg/golinters/protogetter/testdata/go.mod index 64d3739fe4e5..0cca1725136e 100644 --- a/pkg/golinters/protogetter/testdata/go.mod +++ b/pkg/golinters/protogetter/testdata/go.mod @@ -3,7 +3,7 @@ module protogetter go 1.23.0 require ( - google.golang.org/grpc v1.71.1 + google.golang.org/grpc v1.72.0 google.golang.org/protobuf v1.36.6 ) @@ -11,5 +11,5 @@ require ( golang.org/x/net v0.38.0 // indirect golang.org/x/sys v0.31.0 // indirect golang.org/x/text v0.23.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a // indirect ) diff --git a/pkg/golinters/protogetter/testdata/go.sum b/pkg/golinters/protogetter/testdata/go.sum index 98076ebf7ddb..11d34e556344 100644 --- a/pkg/golinters/protogetter/testdata/go.sum +++ b/pkg/golinters/protogetter/testdata/go.sum @@ -26,9 +26,9 @@ golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= -google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI= -google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a h1:51aaUVRocpvUOSQKM6Q7VuoaktNIaMCLuhZB6DKksq4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a/go.mod h1:uRxBH1mhmO8PGhU89cMcHaXKZqO+OfakD8QQO0oYwlQ= +google.golang.org/grpc v1.72.0 h1:S7UkcVa60b5AAQTaO6ZKamFp1zMZSU0fGDK2WZLbBnM= +google.golang.org/grpc v1.72.0/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= From 999631accee0624ba7f17e3f754455d02e2c79aa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 4 May 2025 16:07:04 +0200 Subject: [PATCH 094/152] build(deps): bump github.com/shirou/gopsutil/v4 from 4.25.3 to 4.25.4 (#5778) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ec68a6153c50..ed601d61b551 100644 --- a/go.mod +++ b/go.mod @@ -97,7 +97,7 @@ require ( github.com/sashamelentyev/interfacebloat v1.1.0 github.com/sashamelentyev/usestdlibvars v1.28.0 github.com/securego/gosec/v2 v2.22.3 - github.com/shirou/gopsutil/v4 v4.25.3 + github.com/shirou/gopsutil/v4 v4.25.4 github.com/sirupsen/logrus v1.9.3 github.com/sivchari/containedctx v1.0.3 github.com/sonatard/noctx v0.1.0 diff --git a/go.sum b/go.sum index f1d4e0d34ecf..e3ef36b2d472 100644 --- a/go.sum +++ b/go.sum @@ -519,8 +519,8 @@ github.com/securego/gosec/v2 v2.22.3 h1:mRrCNmRF2NgZp4RJ8oJ6yPJ7G4x6OCiAXHd8x4tr github.com/securego/gosec/v2 v2.22.3/go.mod h1:42M9Xs0v1WseinaB/BmNGO8AVqG8vRfhC2686ACY48k= 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/shirou/gopsutil/v4 v4.25.3 h1:SeA68lsu8gLggyMbmCn8cmp97V1TI9ld9sVzAUcKcKE= -github.com/shirou/gopsutil/v4 v4.25.3/go.mod h1:xbuxyoZj+UsgnZrENu3lQivsngRR5BdjbJwf2fv4szA= +github.com/shirou/gopsutil/v4 v4.25.4 h1:cdtFO363VEOOFrUCjZRh4XVJkb548lyF0q0uTeMqYPw= +github.com/shirou/gopsutil/v4 v4.25.4/go.mod h1:xbuxyoZj+UsgnZrENu3lQivsngRR5BdjbJwf2fv4szA= 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= From 75865b1cbd423e9529ed5ff3e1ec6f6aeec1fb86 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 4 May 2025 16:14:48 +0200 Subject: [PATCH 095/152] build(deps): bump github.com/alecthomas/chroma/v2 from 2.17.0 to 2.17.2 (#5779) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ed601d61b551..97b5fa5cfb14 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1 github.com/OpenPeeDeeP/depguard/v2 v2.2.1 - github.com/alecthomas/chroma/v2 v2.17.0 + github.com/alecthomas/chroma/v2 v2.17.2 github.com/alecthomas/go-check-sumtype v0.3.1 github.com/alexkohler/nakedret/v2 v2.0.6 github.com/alexkohler/prealloc v1.0.0 diff --git a/go.sum b/go.sum index e3ef36b2d472..2ed1a4b31878 100644 --- a/go.sum +++ b/go.sum @@ -59,8 +59,8 @@ github.com/OpenPeeDeeP/depguard/v2 v2.2.1 h1:vckeWVESWp6Qog7UZSARNqfu/cZqvki8zsu github.com/OpenPeeDeeP/depguard/v2 v2.2.1/go.mod h1:q4DKzC4UcVaAvcfd41CZh0PWpGgzrVxUYBlgKNGquUo= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= -github.com/alecthomas/chroma/v2 v2.17.0 h1:3r2Cgk+nXNICMBxIFGnTRTbQFUwMiLisW+9uos0TtUI= -github.com/alecthomas/chroma/v2 v2.17.0/go.mod h1:RVX6AvYm4VfYe/zsk7mjHueLDZor3aWCNE14TFlepBk= +github.com/alecthomas/chroma/v2 v2.17.2 h1:Rm81SCZ2mPoH+Q8ZCc/9YvzPUN/E7HgPiPJD8SLV6GI= +github.com/alecthomas/chroma/v2 v2.17.2/go.mod h1:RVX6AvYm4VfYe/zsk7mjHueLDZor3aWCNE14TFlepBk= github.com/alecthomas/go-check-sumtype v0.3.1 h1:u9aUvbGINJxLVXiFvHUlPEaD7VDULsrxJb4Aq31NLkU= github.com/alecthomas/go-check-sumtype v0.3.1/go.mod h1:A8TSiN3UPRw3laIgWEUOHHLPa6/r9MtoigdlP5h3K/E= github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= From eabc2638a66daf5bb6c6fb052a32fa3ef7b6600d Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Sun, 4 May 2025 17:36:36 +0200 Subject: [PATCH 096/152] chore: prepare release --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c0d05c10ac45..403a833fcb27 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ If you value it, consider supporting us, we appreciate it! ❤️ [![Open Collective backers and sponsors](https://img.shields.io/badge/OpenCollective-Donate-blue?logo=opencollective&style=for-the-badge)](https://opencollective.com/golangci-lint) [![GitHub Sponsors](https://img.shields.io/badge/GitHub-Donate-blue?logo=github&style=for-the-badge)](https://github.com/sponsors/golangci) +### v2.1.6 + +1. Linters bug fixes + * `godot`: from 1.5.0 to 1.5.1 + * `musttag`: from 0.13.0 to 0.13.1 +2. Documentation + * Add note about golangci-lint v2 integration in VS Code + ### v2.1.5 Due to an error related to Snapcraft, some artifacts of the v2.1.4 release have not been published. From 66dba6452068fd4074691ccde56e388c5b9deaa1 Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Sun, 4 May 2025 21:16:10 +0200 Subject: [PATCH 097/152] docs: update GitHub Action assets --- assets/github-action-config-v2.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/github-action-config-v2.json b/assets/github-action-config-v2.json index 45ba44130ecc..2a099a8ff534 100644 --- a/assets/github-action-config-v2.json +++ b/assets/github-action-config-v2.json @@ -1,7 +1,7 @@ { "MinorVersionToConfig": { "latest": { - "TargetVersion": "v2.1.5" + "TargetVersion": "v2.1.6" }, "v1.10": { "Error": "golangci-lint version 'v1.10' isn't supported: we support only v2.0.0 and later versions" @@ -193,7 +193,7 @@ "TargetVersion": "v2.0.2" }, "v2.1": { - "TargetVersion": "v2.1.5" + "TargetVersion": "v2.1.6" } } } From fd9a0f2150183f66d8f2f41bbea8706b48881c7d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 4 May 2025 22:13:28 +0200 Subject: [PATCH 098/152] build(deps): bump github.com/manuelarte/funcorder from 0.2.1 to 0.3.0 (#5743) Co-authored-by: Fernandez Ludovic --- .golangci.next.reference.yml | 3 +++ go.mod | 2 +- go.sum | 4 ++-- jsonschema/golangci.next.jsonschema.json | 5 +++++ pkg/config/linters_settings.go | 1 + pkg/golinters/funcorder/funcorder.go | 1 + 6 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index 37866ff00f2c..dbcc0377a400 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -539,6 +539,9 @@ linters: # Checks if the exported methods of a structure are placed before the non-exported ones. # Default: true struct-method: false + # Checks if the constructors and/or structure methods are sorted alphabetically. + # Default: false + alphabetical: true funlen: # Checks the number of lines in a function. diff --git a/go.mod b/go.mod index 97b5fa5cfb14..b2a3c45e11cc 100644 --- a/go.mod +++ b/go.mod @@ -73,7 +73,7 @@ require ( github.com/ldez/usetesting v0.4.3 github.com/leonklingele/grouper v1.1.2 github.com/macabu/inamedparam v0.2.0 - github.com/manuelarte/funcorder v0.2.1 + github.com/manuelarte/funcorder v0.3.0 github.com/maratori/testableexamples v1.0.0 github.com/maratori/testpackage v1.1.1 github.com/matoous/godox v1.1.0 diff --git a/go.sum b/go.sum index 2ed1a4b31878..182df4b27f2b 100644 --- a/go.sum +++ b/go.sum @@ -389,8 +389,8 @@ github.com/macabu/inamedparam v0.2.0 h1:VyPYpOc10nkhI2qeNUdh3Zket4fcZjEWe35poddB github.com/macabu/inamedparam v0.2.0/go.mod h1:+Pee9/YfGe5LJ62pYXqB89lJ+0k5bsR8Wgz/C0Zlq3U= github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/manuelarte/funcorder v0.2.1 h1:7QJsw3qhljoZ5rH0xapIvjw31EcQeFbF31/7kQ/xS34= -github.com/manuelarte/funcorder v0.2.1/go.mod h1:BQQ0yW57+PF9ZpjpeJDKOffEsQbxDFKW8F8zSMe/Zd0= +github.com/manuelarte/funcorder v0.3.0 h1:mV1joNYIjIUnnyZ6wfaC+sCWB6IvG62ay3xuhbklHps= +github.com/manuelarte/funcorder v0.3.0/go.mod h1:wBFktqsi8PyQvNYEUpF5Lt+V/xqgaevfCi4SSpUhyPo= 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.1 h1:S58XVV5AD7HADMmD0fNnziNHqKvSdDuEKdPD1rNTU04= diff --git a/jsonschema/golangci.next.jsonschema.json b/jsonschema/golangci.next.jsonschema.json index 0f2ef5fcc50b..9af538279cbc 100644 --- a/jsonschema/golangci.next.jsonschema.json +++ b/jsonschema/golangci.next.jsonschema.json @@ -1317,6 +1317,11 @@ "description": "Checks if the exported methods of a structure are placed before the non-exported ones.", "type": "boolean", "default": true + }, + "alphabetical": { + "description": "Checks if the constructors and/or structure methods are sorted alphabetically.", + "type": "boolean", + "default": false } } }, diff --git a/pkg/config/linters_settings.go b/pkg/config/linters_settings.go index 16a8bb9501b9..065abfab47c1 100644 --- a/pkg/config/linters_settings.go +++ b/pkg/config/linters_settings.go @@ -428,6 +428,7 @@ type ForbidigoPattern struct { type FuncOrderSettings struct { Constructor bool `mapstructure:"constructor,omitempty"` StructMethod bool `mapstructure:"struct-method,omitempty"` + Alphabetical bool `mapstructure:"alphabetical,omitempty"` } type FunlenSettings struct { diff --git a/pkg/golinters/funcorder/funcorder.go b/pkg/golinters/funcorder/funcorder.go index 7b8e9689e587..605304f26203 100644 --- a/pkg/golinters/funcorder/funcorder.go +++ b/pkg/golinters/funcorder/funcorder.go @@ -17,6 +17,7 @@ func New(settings *config.FuncOrderSettings) *goanalysis.Linter { cfg[a.Name] = map[string]any{ analyzer.ConstructorCheckName: settings.Constructor, analyzer.StructMethodCheckName: settings.StructMethod, + analyzer.AlphabeticalCheckName: settings.Alphabetical, } } From af60e9f6c7bc26abd82dc0da1d1cc3dc0dddaecf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 4 May 2025 23:06:05 +0200 Subject: [PATCH 099/152] build(deps): bump github.com/sonatard/noctx from 0.1.0 to 0.3.3 (#5771) Co-authored-by: Fernandez Ludovic --- go.mod | 2 +- go.sum | 4 +- pkg/golinters/noctx/noctx.go | 2 +- pkg/golinters/noctx/testdata/noctx.go | 134 +++++++++++++++------- pkg/golinters/noctx/testdata/noctx_cgo.go | 133 ++++++++++++++------- 5 files changed, 188 insertions(+), 87 deletions(-) diff --git a/go.mod b/go.mod index b2a3c45e11cc..1e7e82b195f4 100644 --- a/go.mod +++ b/go.mod @@ -100,7 +100,7 @@ require ( github.com/shirou/gopsutil/v4 v4.25.4 github.com/sirupsen/logrus v1.9.3 github.com/sivchari/containedctx v1.0.3 - github.com/sonatard/noctx v0.1.0 + github.com/sonatard/noctx v0.3.3 github.com/sourcegraph/go-diff v0.7.0 github.com/spf13/cobra v1.9.1 github.com/spf13/pflag v1.0.6 diff --git a/go.sum b/go.sum index 182df4b27f2b..9875fd835bef 100644 --- a/go.sum +++ b/go.sum @@ -530,8 +530,8 @@ 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/sonatard/noctx v0.1.0 h1:JjqOc2WN16ISWAjAk8M5ej0RfExEXtkEyExl2hLW+OM= -github.com/sonatard/noctx v0.1.0/go.mod h1:0RvBxqY8D4j9cTTTWE8ylt2vqj2EPI8fHmrxHdsaZ2c= +github.com/sonatard/noctx v0.3.3 h1:9+wFUxZfjiCdNadFaGH55sa7Y1r6yKZiAsUVmCP+tjw= +github.com/sonatard/noctx v0.3.3/go.mod h1:64XdbzFb18XL4LporKXp8poqZtPKbCrqQ402CV+kJas= 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.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= diff --git a/pkg/golinters/noctx/noctx.go b/pkg/golinters/noctx/noctx.go index b0c5f9b50040..18391d4b5581 100644 --- a/pkg/golinters/noctx/noctx.go +++ b/pkg/golinters/noctx/noctx.go @@ -12,7 +12,7 @@ func New() *goanalysis.Linter { return goanalysis.NewLinter( a.Name, - "Finds sending http request without context.Context", + "Detects function and method with missing usage of context.Context", []*analysis.Analyzer{a}, nil, ).WithLoadMode(goanalysis.LoadModeTypesInfo) diff --git a/pkg/golinters/noctx/testdata/noctx.go b/pkg/golinters/noctx/testdata/noctx.go index 8b077a566206..8a34443e2029 100644 --- a/pkg/golinters/noctx/testdata/noctx.go +++ b/pkg/golinters/noctx/testdata/noctx.go @@ -3,73 +3,58 @@ package testdata import ( "context" + "database/sql" "net/http" ) var newRequestPkg = http.NewRequest -func Noctx() { - const url = "http://example.com" +func _() { + const url = "https://example.com" + cli := &http.Client{} ctx := context.Background() - http.Get(url) // want `net/http\.Get must not be called` - _ = http.Get // OK - f := http.Get // OK - f(url) // want `net/http\.Get must not be called` - - http.Head(url) // want `net/http\.Head must not be called` - http.Post(url, "", nil) // want `net/http\.Post must not be called` - http.PostForm(url, nil) // want `net/http\.PostForm must not be called` - - cli.Get(url) // want `\(\*net/http\.Client\)\.Get must not be called` - _ = cli.Get // OK - m := cli.Get // OK - m(url) // want `\(\*net/http\.Client\)\.Get must not be called` - - cli.Head(url) // want `\(\*net/http\.Client\)\.Head must not be called` - cli.Post(url, "", nil) // want `\(\*net/http\.Client\)\.Post must not be called` - cli.PostForm(url, nil) // want `\(\*net/http\.Client\)\.PostForm must not be called` - req, _ := http.NewRequest(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext` + req, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` cli.Do(req) req2, _ := http.NewRequestWithContext(ctx, http.MethodPost, url, nil) // OK cli.Do(req2) - req3, _ := http.NewRequest(http.MethodPost, url, nil) // OK + req3, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` req3 = req3.WithContext(ctx) cli.Do(req3) f2 := func(req *http.Request, ctx context.Context) *http.Request { return req } - req4, _ := http.NewRequest(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext` + req4, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` req4 = f2(req4, ctx) - req41, _ := http.NewRequest(http.MethodPost, url, nil) // OK + req41, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` req41 = req41.WithContext(ctx) req41 = f2(req41, ctx) newRequest := http.NewRequest - req5, _ := newRequest(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext` + req5, _ := newRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` cli.Do(req5) - req51, _ := newRequest(http.MethodPost, url, nil) // OK + req51, _ := newRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` req51 = req51.WithContext(ctx) cli.Do(req51) - req52, _ := newRequestPkg(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext` + req52, _ := newRequestPkg(http.MethodPost, url, nil) // TODO: false negative `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` cli.Do(req52) type MyRequest = http.Request f3 := func(req *MyRequest, ctx context.Context) *MyRequest { return req } - req6, _ := http.NewRequest(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext` + req6, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` req6 = f3(req6, ctx) - req61, _ := http.NewRequest(http.MethodPost, url, nil) // OK + req61, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` req61 = req61.WithContext(ctx) req61 = f3(req61, ctx) @@ -77,22 +62,22 @@ func Noctx() { f4 := func(req *MyRequest2, ctx context.Context) *MyRequest2 { return req } - req7, _ := http.NewRequest(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext` + req7, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` req71 := MyRequest2(*req7) f4(&req71, ctx) - req72, _ := http.NewRequest(http.MethodPost, url, nil) // OK + req72, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` req72 = req72.WithContext(ctx) req73 := MyRequest2(*req7) f4(&req73, ctx) req8, _ := func() (*http.Request, error) { - return http.NewRequest(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext` + return http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` }() cli.Do(req8) req82, _ := func() (*http.Request, error) { - req82, _ := http.NewRequest(http.MethodPost, url, nil) // OK + req82, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` req82 = req82.WithContext(ctx) return req82, nil }() @@ -101,34 +86,99 @@ func Noctx() { f5 := func(req, req2 *http.Request, ctx context.Context) (*http.Request, *http.Request) { return req, req2 } - req9, _ := http.NewRequest(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext` + req9, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` req9, _ = f5(req9, req9, ctx) - req91, _ := http.NewRequest(http.MethodPost, url, nil) // OK + req91, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` req91 = req91.WithContext(ctx) req9, _ = f5(req91, req91, ctx) - req10, _ := http.NewRequest(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext` - req11, _ := http.NewRequest(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext` + req10, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` + req11, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` req10, req11 = f5(req10, req11, ctx) - req101, _ := http.NewRequest(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext` - req111, _ := http.NewRequest(http.MethodPost, url, nil) // OK + req101, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` + req111, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` req111 = req111.WithContext(ctx) req101, req111 = f5(req101, req111, ctx) func() (*http.Request, *http.Request) { - req12, _ := http.NewRequest(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext` - req13, _ := http.NewRequest(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext` + req12, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` + req13, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` return req12, req13 }() func() (*http.Request, *http.Request) { - req14, _ := http.NewRequest(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext` - req15, _ := http.NewRequest(http.MethodPost, url, nil) // OK + req14, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` + req15, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` req15 = req15.WithContext(ctx) return req14, req15 }() + + req121, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` + req121.AddCookie(&http.Cookie{Name: "k", Value: "v"}) + req121 = req121.WithContext(context.WithValue(req121.Context(), struct{}{}, 0)) + cli.Do(req121) +} + +func _() { + const url = "http://example.com" + cli := &http.Client{} + + http.Get(url) // want `net/http\.Get must not be called. use net/http\.NewRequestWithContext and \(\*net/http.Client\)\.Do\(\*http.Request\)` + _ = http.Get // OK + f := http.Get // OK + f(url) // want `net/http\.Get must not be called. use net/http\.NewRequestWithContext and \(\*net/http.Client\)\.Do\(\*http.Request\)` + + http.Head(url) // want `net/http\.Head must not be called. use net/http\.NewRequestWithContext and \(\*net/http.Client\)\.Do\(\*http.Request\)` + http.Post(url, "", nil) // want `net/http\.Post must not be called. use net/http\.NewRequestWithContext and \(\*net/http.Client\)\.Do\(\*http.Request\)` + http.PostForm(url, nil) // want `net/http\.PostForm must not be called. use net/http\.NewRequestWithContext and \(\*net/http.Client\)\.Do\(\*http.Request\)` + + cli.Get(url) // want `\(\*net/http\.Client\)\.Get must not be called. use \(\*net/http.Client\)\.Do\(\*http.Request\)` + _ = cli.Get // OK + m := cli.Get // OK + m(url) // want `\(\*net/http\.Client\)\.Get must not be called. use \(\*net/http.Client\)\.Do\(\*http.Request\)` + + cli.Head(url) // want `\(\*net/http\.Client\)\.Head must not be called. use \(\*net/http.Client\)\.Do\(\*http.Request\)` + cli.Post(url, "", nil) // want `\(\*net/http\.Client\)\.Post must not be called. use \(\*net/http.Client\)\.Do\(\*http.Request\)` + cli.PostForm(url, nil) // want `\(\*net/http\.Client\)\.PostForm must not be called. use \(\*net/http.Client\)\.Do\(\*http.Request\)` } +func _() { + ctx := context.Background() + + db, _ := sql.Open("noctx", "noctx://") + + db.Exec("select * from testdata") // want `\(\*database/sql\.DB\)\.Exec must not be called. use \(\*database/sql\.DB\)\.ExecContext` + db.ExecContext(ctx, "select * from testdata") + + db.Ping() // want `\(\*database/sql\.DB\)\.Ping must not be called. use \(\*database/sql\.DB\)\.PingContext` + db.PingContext(ctx) + + db.Prepare("select * from testdata") // want `\(\*database/sql\.DB\)\.Prepare must not be called. use \(\*database/sql\.DB\)\.PrepareContext` + db.PrepareContext(ctx, "select * from testdata") + + db.Query("select * from testdata") // want `\(\*database/sql\.DB\)\.Query must not be called. use \(\*database/sql\.DB\)\.QueryContext` + db.QueryContext(ctx, "select * from testdata") + + db.QueryRow("select * from testdata") // want `\(\*database/sql\.DB\)\.QueryRow must not be called. use \(\*database/sql\.DB\)\.QueryRowContext` + db.QueryRowContext(ctx, "select * from testdata") + + // transactions + + tx, _ := db.Begin() + tx.Exec("select * from testdata") // want `\(\*database/sql\.Tx\)\.Exec must not be called. use \(\*database/sql\.Tx\)\.ExecContext` + tx.ExecContext(ctx, "select * from testdata") + + tx.Prepare("select * from testdata") // want `\(\*database/sql\.Tx\)\.Prepare must not be called. use \(\*database/sql\.Tx\)\.PrepareContext` + tx.PrepareContext(ctx, "select * from testdata") + + tx.Query("select * from testdata") // want `\(\*database/sql\.Tx\)\.Query must not be called. use \(\*database/sql\.Tx\)\.QueryContext` + tx.QueryContext(ctx, "select * from testdata") + + tx.QueryRow("select * from testdata") // want `\(\*database/sql\.Tx\)\.QueryRow must not be called. use \(\*database/sql\.Tx\)\.QueryRowContext` + tx.QueryRowContext(ctx, "select * from testdata") + + _ = tx.Commit() +} diff --git a/pkg/golinters/noctx/testdata/noctx_cgo.go b/pkg/golinters/noctx/testdata/noctx_cgo.go index 64f5ea6c0d49..63b15477d8c3 100644 --- a/pkg/golinters/noctx/testdata/noctx_cgo.go +++ b/pkg/golinters/noctx/testdata/noctx_cgo.go @@ -13,6 +13,7 @@ import "C" import ( "context" + "database/sql" "net/http" "unsafe" ) @@ -26,67 +27,51 @@ func _() { var newRequestPkg = http.NewRequest func _() { - const url = "http://example.com" + const url = "https://example.com" + cli := &http.Client{} ctx := context.Background() - http.Get(url) // want `net/http\.Get must not be called` - _ = http.Get // OK - f := http.Get // OK - f(url) // want `net/http\.Get must not be called` - - http.Head(url) // want `net/http\.Head must not be called` - http.Post(url, "", nil) // want `net/http\.Post must not be called` - http.PostForm(url, nil) // want `net/http\.PostForm must not be called` - cli.Get(url) // want `\(\*net/http\.Client\)\.Get must not be called` - _ = cli.Get // OK - m := cli.Get // OK - m(url) // want `\(\*net/http\.Client\)\.Get must not be called` - - cli.Head(url) // want `\(\*net/http\.Client\)\.Head must not be called` - cli.Post(url, "", nil) // want `\(\*net/http\.Client\)\.Post must not be called` - cli.PostForm(url, nil) // want `\(\*net/http\.Client\)\.PostForm must not be called` - - req, _ := http.NewRequest(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext` + req, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` cli.Do(req) req2, _ := http.NewRequestWithContext(ctx, http.MethodPost, url, nil) // OK cli.Do(req2) - req3, _ := http.NewRequest(http.MethodPost, url, nil) // OK + req3, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` req3 = req3.WithContext(ctx) cli.Do(req3) f2 := func(req *http.Request, ctx context.Context) *http.Request { return req } - req4, _ := http.NewRequest(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext` + req4, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` req4 = f2(req4, ctx) - req41, _ := http.NewRequest(http.MethodPost, url, nil) // OK + req41, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` req41 = req41.WithContext(ctx) req41 = f2(req41, ctx) newRequest := http.NewRequest - req5, _ := newRequest(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext` + req5, _ := newRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` cli.Do(req5) - req51, _ := newRequest(http.MethodPost, url, nil) // OK + req51, _ := newRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` req51 = req51.WithContext(ctx) cli.Do(req51) - req52, _ := newRequestPkg(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext` + req52, _ := newRequestPkg(http.MethodPost, url, nil) // TODO: false negative `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` cli.Do(req52) type MyRequest = http.Request f3 := func(req *MyRequest, ctx context.Context) *MyRequest { return req } - req6, _ := http.NewRequest(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext` + req6, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` req6 = f3(req6, ctx) - req61, _ := http.NewRequest(http.MethodPost, url, nil) // OK + req61, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` req61 = req61.WithContext(ctx) req61 = f3(req61, ctx) @@ -94,22 +79,22 @@ func _() { f4 := func(req *MyRequest2, ctx context.Context) *MyRequest2 { return req } - req7, _ := http.NewRequest(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext` + req7, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` req71 := MyRequest2(*req7) f4(&req71, ctx) - req72, _ := http.NewRequest(http.MethodPost, url, nil) // OK + req72, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` req72 = req72.WithContext(ctx) req73 := MyRequest2(*req7) f4(&req73, ctx) req8, _ := func() (*http.Request, error) { - return http.NewRequest(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext` + return http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` }() cli.Do(req8) req82, _ := func() (*http.Request, error) { - req82, _ := http.NewRequest(http.MethodPost, url, nil) // OK + req82, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` req82 = req82.WithContext(ctx) return req82, nil }() @@ -118,33 +103,99 @@ func _() { f5 := func(req, req2 *http.Request, ctx context.Context) (*http.Request, *http.Request) { return req, req2 } - req9, _ := http.NewRequest(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext` + req9, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` req9, _ = f5(req9, req9, ctx) - req91, _ := http.NewRequest(http.MethodPost, url, nil) // OK + req91, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` req91 = req91.WithContext(ctx) req9, _ = f5(req91, req91, ctx) - req10, _ := http.NewRequest(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext` - req11, _ := http.NewRequest(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext` + req10, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` + req11, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` req10, req11 = f5(req10, req11, ctx) - req101, _ := http.NewRequest(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext` - req111, _ := http.NewRequest(http.MethodPost, url, nil) // OK + req101, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` + req111, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` req111 = req111.WithContext(ctx) req101, req111 = f5(req101, req111, ctx) func() (*http.Request, *http.Request) { - req12, _ := http.NewRequest(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext` - req13, _ := http.NewRequest(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext` + req12, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` + req13, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` return req12, req13 }() func() (*http.Request, *http.Request) { - req14, _ := http.NewRequest(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext` - req15, _ := http.NewRequest(http.MethodPost, url, nil) // OK + req14, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` + req15, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` req15 = req15.WithContext(ctx) return req14, req15 }() + + req121, _ := http.NewRequest(http.MethodPost, url, nil) // want `net/http\.NewRequest must not be called. use net/http\.NewRequestWithContext` + req121.AddCookie(&http.Cookie{Name: "k", Value: "v"}) + req121 = req121.WithContext(context.WithValue(req121.Context(), struct{}{}, 0)) + cli.Do(req121) +} + +func _() { + const url = "http://example.com" + cli := &http.Client{} + + http.Get(url) // want `net/http\.Get must not be called. use net/http\.NewRequestWithContext and \(\*net/http.Client\)\.Do\(\*http.Request\)` + _ = http.Get // OK + f := http.Get // OK + f(url) // want `net/http\.Get must not be called. use net/http\.NewRequestWithContext and \(\*net/http.Client\)\.Do\(\*http.Request\)` + + http.Head(url) // want `net/http\.Head must not be called. use net/http\.NewRequestWithContext and \(\*net/http.Client\)\.Do\(\*http.Request\)` + http.Post(url, "", nil) // want `net/http\.Post must not be called. use net/http\.NewRequestWithContext and \(\*net/http.Client\)\.Do\(\*http.Request\)` + http.PostForm(url, nil) // want `net/http\.PostForm must not be called. use net/http\.NewRequestWithContext and \(\*net/http.Client\)\.Do\(\*http.Request\)` + + cli.Get(url) // want `\(\*net/http\.Client\)\.Get must not be called. use \(\*net/http.Client\)\.Do\(\*http.Request\)` + _ = cli.Get // OK + m := cli.Get // OK + m(url) // want `\(\*net/http\.Client\)\.Get must not be called. use \(\*net/http.Client\)\.Do\(\*http.Request\)` + + cli.Head(url) // want `\(\*net/http\.Client\)\.Head must not be called. use \(\*net/http.Client\)\.Do\(\*http.Request\)` + cli.Post(url, "", nil) // want `\(\*net/http\.Client\)\.Post must not be called. use \(\*net/http.Client\)\.Do\(\*http.Request\)` + cli.PostForm(url, nil) // want `\(\*net/http\.Client\)\.PostForm must not be called. use \(\*net/http.Client\)\.Do\(\*http.Request\)` +} + +func _() { + ctx := context.Background() + + db, _ := sql.Open("noctx", "noctx://") + + db.Exec("select * from testdata") // want `\(\*database/sql\.DB\)\.Exec must not be called. use \(\*database/sql\.DB\)\.ExecContext` + db.ExecContext(ctx, "select * from testdata") + + db.Ping() // want `\(\*database/sql\.DB\)\.Ping must not be called. use \(\*database/sql\.DB\)\.PingContext` + db.PingContext(ctx) + + db.Prepare("select * from testdata") // want `\(\*database/sql\.DB\)\.Prepare must not be called. use \(\*database/sql\.DB\)\.PrepareContext` + db.PrepareContext(ctx, "select * from testdata") + + db.Query("select * from testdata") // want `\(\*database/sql\.DB\)\.Query must not be called. use \(\*database/sql\.DB\)\.QueryContext` + db.QueryContext(ctx, "select * from testdata") + + db.QueryRow("select * from testdata") // want `\(\*database/sql\.DB\)\.QueryRow must not be called. use \(\*database/sql\.DB\)\.QueryRowContext` + db.QueryRowContext(ctx, "select * from testdata") + + // transactions + + tx, _ := db.Begin() + tx.Exec("select * from testdata") // want `\(\*database/sql\.Tx\)\.Exec must not be called. use \(\*database/sql\.Tx\)\.ExecContext` + tx.ExecContext(ctx, "select * from testdata") + + tx.Prepare("select * from testdata") // want `\(\*database/sql\.Tx\)\.Prepare must not be called. use \(\*database/sql\.Tx\)\.PrepareContext` + tx.PrepareContext(ctx, "select * from testdata") + + tx.Query("select * from testdata") // want `\(\*database/sql\.Tx\)\.Query must not be called. use \(\*database/sql\.Tx\)\.QueryContext` + tx.QueryContext(ctx, "select * from testdata") + + tx.QueryRow("select * from testdata") // want `\(\*database/sql\.Tx\)\.QueryRow must not be called. use \(\*database/sql\.Tx\)\.QueryRowContext` + tx.QueryRowContext(ctx, "select * from testdata") + + _ = tx.Commit() } From 5546285060b42d2e036126d0f10b4d4ee6647e79 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 May 2025 22:57:00 +0200 Subject: [PATCH 100/152] build(deps): bump golangci/golangci-lint-action from 7.0.0 to 8.0.0 in the github-actions group (#5780) --- .github/workflows/pr-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-tests.yml b/.github/workflows/pr-tests.yml index 380472037050..5f5606e97835 100644 --- a/.github/workflows/pr-tests.yml +++ b/.github/workflows/pr-tests.yml @@ -41,7 +41,7 @@ jobs: # - 1.18rc1 -> 1.18.0-rc.1 go-version: ${{ env.GO_VERSION }} - name: lint - uses: golangci/golangci-lint-action@v7.0.0 + uses: golangci/golangci-lint-action@v8.0.0 with: version: latest From 9e01be592bef3e264df30aeb4444d1429fc60ba0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 May 2025 22:57:28 +0200 Subject: [PATCH 101/152] build(deps): bump golang.org/x/oauth2 from 0.29.0 to 0.30.0 in /scripts/gen_github_action_config in the scripts group (#5781) --- scripts/gen_github_action_config/go.mod | 2 +- scripts/gen_github_action_config/go.sum | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/scripts/gen_github_action_config/go.mod b/scripts/gen_github_action_config/go.mod index c76a4de5840a..32b5cca642a1 100644 --- a/scripts/gen_github_action_config/go.mod +++ b/scripts/gen_github_action_config/go.mod @@ -5,7 +5,7 @@ go 1.23.0 require ( github.com/shurcooL/githubv4 v0.0.0-20240429030203-be2daab69064 github.com/stretchr/testify v1.10.0 - golang.org/x/oauth2 v0.29.0 + golang.org/x/oauth2 v0.30.0 ) require ( diff --git a/scripts/gen_github_action_config/go.sum b/scripts/gen_github_action_config/go.sum index b9b970ef73ac..16f1f14cd28c 100644 --- a/scripts/gen_github_action_config/go.sum +++ b/scripts/gen_github_action_config/go.sum @@ -1,7 +1,5 @@ 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/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 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/shurcooL/githubv4 v0.0.0-20240429030203-be2daab69064 h1:RCQBSFx5JrsbHltqTtJ+kN3U0Y3a/N/GlVdmRSoxzyE= @@ -10,8 +8,8 @@ github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 h1:17JxqqJY66GmZV github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466/go.mod h1:9dIRpgIY7hVhoqfe0/FcYp0bpInZaT7dc3BYOprrIUE= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98= -golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= +golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= +golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= 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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= From ed782d7ccc1f046017ec50028911e1ffbcb42726 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 May 2025 08:43:57 +0200 Subject: [PATCH 102/152] build(deps): bump github.com/jjti/go-spancheck from 0.6.4 to 0.6.5 (#5784) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1e7e82b195f4..70370e73d9ae 100644 --- a/go.mod +++ b/go.mod @@ -58,7 +58,7 @@ require ( github.com/hashicorp/go-version v1.7.0 github.com/jgautheron/goconst v1.8.1 github.com/jingyugao/rowserrcheck v1.1.1 - github.com/jjti/go-spancheck v0.6.4 + github.com/jjti/go-spancheck v0.6.5 github.com/julz/importas v0.2.0 github.com/karamaru-alpha/copyloopvar v1.2.1 github.com/kisielk/errcheck v1.9.0 diff --git a/go.sum b/go.sum index 9875fd835bef..ed6eb8577de7 100644 --- a/go.sum +++ b/go.sum @@ -333,8 +333,8 @@ github.com/jgautheron/goconst v1.8.1 h1:PPqCYp3K/xlOj5JmIe6O1Mj6r1DbkdbLtR3AJuZo github.com/jgautheron/goconst v1.8.1/go.mod h1:A0oxgBCHy55NQn6sYpO7UdnA9p+h7cPtoOZUmvNIako= 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/jjti/go-spancheck v0.6.4 h1:Tl7gQpYf4/TMU7AT84MN83/6PutY21Nb9fuQjFTpRRc= -github.com/jjti/go-spancheck v0.6.4/go.mod h1:yAEYdKJ2lRkDA8g7X+oKUHXOWVAXSBJRv04OhF+QUjk= +github.com/jjti/go-spancheck v0.6.5 h1:lmi7pKxa37oKYIMScialXUK6hP3iY5F1gu+mLBPgYB8= +github.com/jjti/go-spancheck v0.6.5/go.mod h1:aEogkeatBrbYsyW6y5TgDfihCulDYciL1B7rG2vSsrU= 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= From f0c85146f8387ca32d2207fde8f87447038e59e8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 May 2025 08:45:03 +0200 Subject: [PATCH 103/152] build(deps): bump golang.org/x/sys from 0.32.0 to 0.33.0 (#5785) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 70370e73d9ae..7af6dc58f00c 100644 --- a/go.mod +++ b/go.mod @@ -129,7 +129,7 @@ require ( go.augendre.info/fatcontext v0.8.0 go.uber.org/automaxprocs v1.6.0 golang.org/x/mod v0.24.0 - golang.org/x/sys v0.32.0 + golang.org/x/sys v0.33.0 golang.org/x/tools v0.32.0 gopkg.in/yaml.v3 v3.0.1 honnef.co/go/tools v0.6.1 diff --git a/go.sum b/go.sum index ed6eb8577de7..2e633e945d0c 100644 --- a/go.sum +++ b/go.sum @@ -821,8 +821,8 @@ 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.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= -golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 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.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= From 4af8bfc6babe74607093cbe4c329f29da463c49e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 May 2025 09:04:06 +0200 Subject: [PATCH 104/152] build(deps): bump golang.org/x/tools from 0.32.0 to 0.33.0 (#5786) Co-authored-by: Fernandez Ludovic --- .golangci.next.reference.yml | 3 +++ go.mod | 4 ++-- go.sum | 12 ++++++------ jsonschema/golangci.next.jsonschema.json | 1 + pkg/golinters/govet/govet.go | 2 ++ 5 files changed, 14 insertions(+), 8 deletions(-) diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index dbcc0377a400..6a33e30e33d7 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -1600,6 +1600,8 @@ linters: - findcall # Report assembly that clobbers the frame pointer before saving it. - framepointer + # Check format of addresses passed to net.Dial. + - hostport # Report using Go 1.22 enhanced ServeMux patterns in older Go versions. - httpmux # Check for mistakes using HTTP responses. @@ -1683,6 +1685,7 @@ linters: - fieldalignment - findcall - framepointer + - hostport - httpmux - httpresponse - ifaceassert diff --git a/go.mod b/go.mod index 7af6dc58f00c..7fe86342c3ec 100644 --- a/go.mod +++ b/go.mod @@ -130,7 +130,7 @@ require ( go.uber.org/automaxprocs v1.6.0 golang.org/x/mod v0.24.0 golang.org/x/sys v0.33.0 - golang.org/x/tools v0.32.0 + golang.org/x/tools v0.33.0 gopkg.in/yaml.v3 v3.0.1 honnef.co/go/tools v0.6.1 mvdan.cc/gofumpt v0.8.0 @@ -209,7 +209,7 @@ require ( go.uber.org/zap v1.24.0 // indirect golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect - golang.org/x/sync v0.13.0 // indirect + golang.org/x/sync v0.14.0 // indirect golang.org/x/text v0.24.0 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/ini.v1 v1.67.0 // indirect diff --git a/go.sum b/go.sum index 2e633e945d0c..48e83d966edf 100644 --- a/go.sum +++ b/go.sum @@ -741,8 +741,8 @@ golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= -golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= +golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= +golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= 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= @@ -764,8 +764,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= -golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= +golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= 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= @@ -904,8 +904,8 @@ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= -golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU= -golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s= +golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= +golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= 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= diff --git a/jsonschema/golangci.next.jsonschema.json b/jsonschema/golangci.next.jsonschema.json index 9af538279cbc..5868d65451b2 100644 --- a/jsonschema/golangci.next.jsonschema.json +++ b/jsonschema/golangci.next.jsonschema.json @@ -539,6 +539,7 @@ "fieldalignment", "findcall", "framepointer", + "hostport", "httpmux", "httpresponse", "ifaceassert", diff --git a/pkg/golinters/govet/govet.go b/pkg/golinters/govet/govet.go index 4f3380841382..e4de5b0f4459 100644 --- a/pkg/golinters/govet/govet.go +++ b/pkg/golinters/govet/govet.go @@ -24,6 +24,7 @@ import ( "golang.org/x/tools/go/analysis/passes/fieldalignment" "golang.org/x/tools/go/analysis/passes/findcall" "golang.org/x/tools/go/analysis/passes/framepointer" + "golang.org/x/tools/go/analysis/passes/hostport" "golang.org/x/tools/go/analysis/passes/httpmux" "golang.org/x/tools/go/analysis/passes/httpresponse" "golang.org/x/tools/go/analysis/passes/ifaceassert" @@ -78,6 +79,7 @@ var ( fieldalignment.Analyzer, findcall.Analyzer, framepointer.Analyzer, + hostport.Analyzer, httpmux.Analyzer, httpresponse.Analyzer, ifaceassert.Analyzer, From e905d8072c5f0a75434d1ddee57bdcdcf52fb00f Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Wed, 7 May 2025 09:22:29 +0200 Subject: [PATCH 105/152] build(deps): bump github.com/ashanbrown/makezero from 1.2.0 to 2.0.1 (#5782) --- go.mod | 2 +- go.sum | 9 ++------- pkg/golinters/makezero/makezero.go | 2 +- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 7fe86342c3ec..5f674f0fc464 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/alingse/asasalint v0.0.11 github.com/alingse/nilnesserr v0.2.0 github.com/ashanbrown/forbidigo v1.6.0 - github.com/ashanbrown/makezero v1.2.0 + github.com/ashanbrown/makezero/v2 v2.0.1 github.com/bkielbasa/cyclop v1.2.3 github.com/blizzy78/varnamelen v0.8.0 github.com/bombsimon/wsl/v4 v4.7.0 diff --git a/go.sum b/go.sum index 48e83d966edf..d45301e293e7 100644 --- a/go.sum +++ b/go.sum @@ -80,8 +80,8 @@ github.com/alingse/nilnesserr v0.2.0 h1:raLem5KG7EFVb4UIDAXgrv3N2JIaffeKNtcEXkEW github.com/alingse/nilnesserr v0.2.0/go.mod h1:1xJPrXonEtX7wyTq8Dytns5P2hNzoWymVUIaKm4HNFg= 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.2.0 h1:/2Lp1bypdmK9wDIq7uWBlDF1iMUpIIS4A+pF6C9IEUU= -github.com/ashanbrown/makezero v1.2.0/go.mod h1:dxlPhHbDMC6N6xICzFBSK+4njQDdK8euNO0qjQMtGY4= +github.com/ashanbrown/makezero/v2 v2.0.1 h1:r8GtKetWOgoJ4sLyUx97UTwyt2dO7WkGFHizn/Lo8TY= +github.com/ashanbrown/makezero/v2 v2.0.1/go.mod h1:kKU4IMxmYW1M4fiEHMb2vc5SFoPzXvgbMR9gIp5pjSw= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= @@ -696,7 +696,6 @@ 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.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= @@ -737,7 +736,6 @@ 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.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= @@ -827,7 +825,6 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= @@ -840,7 +837,6 @@ 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.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= @@ -901,7 +897,6 @@ golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= diff --git a/pkg/golinters/makezero/makezero.go b/pkg/golinters/makezero/makezero.go index 04b4fe93dadf..8b86f120679e 100644 --- a/pkg/golinters/makezero/makezero.go +++ b/pkg/golinters/makezero/makezero.go @@ -3,7 +3,7 @@ package makezero import ( "fmt" - "github.com/ashanbrown/makezero/makezero" + "github.com/ashanbrown/makezero/v2/makezero" "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" From acbcbdbd1583e557c882d618192a5b5ffb773b34 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Wed, 7 May 2025 11:06:32 +0200 Subject: [PATCH 106/152] build(deps): bump github.com/ashanbrown/forbidigo from 1.6.0 to 2.1.0 (#5783) --- go.mod | 2 +- go.sum | 11 ++--------- pkg/golinters/forbidigo/forbidigo.go | 2 +- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/go.mod b/go.mod index 5f674f0fc464..4dc784cf12b2 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/alexkohler/prealloc v1.0.0 github.com/alingse/asasalint v0.0.11 github.com/alingse/nilnesserr v0.2.0 - github.com/ashanbrown/forbidigo v1.6.0 + github.com/ashanbrown/forbidigo/v2 v2.1.0 github.com/ashanbrown/makezero/v2 v2.0.1 github.com/bkielbasa/cyclop v1.2.3 github.com/blizzy78/varnamelen v0.8.0 diff --git a/go.sum b/go.sum index d45301e293e7..3cb33099781e 100644 --- a/go.sum +++ b/go.sum @@ -78,8 +78,8 @@ github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQ github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= github.com/alingse/nilnesserr v0.2.0 h1:raLem5KG7EFVb4UIDAXgrv3N2JIaffeKNtcEXkEWd/w= github.com/alingse/nilnesserr v0.2.0/go.mod h1:1xJPrXonEtX7wyTq8Dytns5P2hNzoWymVUIaKm4HNFg= -github.com/ashanbrown/forbidigo v1.6.0 h1:D3aewfM37Yb3pxHujIPSpTf6oQk9sc9WZi8gerOIVIY= -github.com/ashanbrown/forbidigo v1.6.0/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU= +github.com/ashanbrown/forbidigo/v2 v2.1.0 h1:NAxZrWqNUQiDz19FKScQ/xvwzmij6BiOw3S0+QUQ+Hs= +github.com/ashanbrown/forbidigo/v2 v2.1.0/go.mod h1:0zZfdNAuZIL7rSComLGthgc/9/n2FqspBOH90xlCHdA= github.com/ashanbrown/makezero/v2 v2.0.1 h1:r8GtKetWOgoJ4sLyUx97UTwyt2dO7WkGFHizn/Lo8TY= github.com/ashanbrown/makezero/v2 v2.0.1/go.mod h1:kKU4IMxmYW1M4fiEHMb2vc5SFoPzXvgbMR9gIp5pjSw= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= @@ -560,7 +560,6 @@ github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/ 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= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -694,7 +693,6 @@ 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.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/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= @@ -734,7 +732,6 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= @@ -812,7 +809,6 @@ golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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= @@ -823,7 +819,6 @@ golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 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.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= @@ -835,7 +830,6 @@ 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.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.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= @@ -895,7 +889,6 @@ 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.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= diff --git a/pkg/golinters/forbidigo/forbidigo.go b/pkg/golinters/forbidigo/forbidigo.go index 45f9088fa97d..f7c5efd3d8f1 100644 --- a/pkg/golinters/forbidigo/forbidigo.go +++ b/pkg/golinters/forbidigo/forbidigo.go @@ -3,7 +3,7 @@ package forbidigo import ( "fmt" - "github.com/ashanbrown/forbidigo/forbidigo" + "github.com/ashanbrown/forbidigo/v2/forbidigo" "golang.org/x/tools/go/analysis" "gopkg.in/yaml.v3" From fd792aec377b3e473c52e73e8d08b5f0bcdec290 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 May 2025 14:42:51 +0200 Subject: [PATCH 107/152] build(deps): bump github.com/securego/gosec/v2 from 2.22.3 to 2.22.4 (#5788) --- go.mod | 6 +++--- go.sum | 24 ++++++++++++------------ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 4dc784cf12b2..bcb9e58ccf16 100644 --- a/go.mod +++ b/go.mod @@ -96,7 +96,7 @@ require ( github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 github.com/sashamelentyev/interfacebloat v1.1.0 github.com/sashamelentyev/usestdlibvars v1.28.0 - github.com/securego/gosec/v2 v2.22.3 + github.com/securego/gosec/v2 v2.22.4 github.com/shirou/gopsutil/v4 v4.25.4 github.com/sirupsen/logrus v1.9.3 github.com/sivchari/containedctx v1.0.3 @@ -141,7 +141,7 @@ require ( github.com/Masterminds/semver/v3 v3.3.1 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/ccojocar/zxcvbn-go v1.0.2 // indirect + github.com/ccojocar/zxcvbn-go v1.0.4 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect github.com/charmbracelet/x/ansi v0.8.0 // indirect @@ -210,7 +210,7 @@ require ( golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect golang.org/x/sync v0.14.0 // indirect - golang.org/x/text v0.24.0 // indirect + golang.org/x/text v0.25.0 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 3cb33099781e..96a2731998e3 100644 --- a/go.sum +++ b/go.sum @@ -106,8 +106,8 @@ github.com/butuzov/mirror v1.3.0 h1:HdWCXzmwlQHdVhwvsfBb2Au0r3HyINry3bDWLYXiKoc= github.com/butuzov/mirror v1.3.0/go.mod h1:AEij0Z8YMALaq4yQj9CPPVYOyJQyiexpQEQgihajRfI= github.com/catenacyber/perfsprint v0.9.1 h1:5LlTp4RwTooQjJCvGEFV6XksZvWE7wCOUvjD2z0vls0= github.com/catenacyber/perfsprint v0.9.1/go.mod h1:q//VWC2fWbcdSLEY1R3l8n0zQCDPdE4IjZwyY1HMunM= -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/ccojocar/zxcvbn-go v1.0.4 h1:FWnCIRMXPj43ukfX000kvBZvV6raSxakYr1nzyNrUcc= +github.com/ccojocar/zxcvbn-go v1.0.4/go.mod h1:3GxGX+rHmueTUMvm5ium7irpyjmm7ikxYFOSJB21Das= 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/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -291,8 +291,8 @@ 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-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg= -github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8= +github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 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= @@ -435,10 +435,10 @@ github.com/nunnatsa/ginkgolinter v0.19.1 h1:mjwbOlDQxZi9Cal+KfbEJTCz327OLNfwNvoZ github.com/nunnatsa/ginkgolinter v0.19.1/go.mod h1:jkQ3naZDmxaZMXPWaS9rblH+i+GWXQCaS/JFIWcOH2s= 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.23.3 h1:edHxnszytJ4lD9D5Jjc4tiDkPBZ3siDeJJkUZJJVkp0= -github.com/onsi/ginkgo/v2 v2.23.3/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM= -github.com/onsi/gomega v1.36.3 h1:hID7cr8t3Wp26+cYnfcjR6HpJ00fdogN6dqZ1t6IylU= -github.com/onsi/gomega v1.36.3/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0= +github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus= +github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8= +github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y= +github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0= 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= @@ -515,8 +515,8 @@ github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tM github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= github.com/sashamelentyev/usestdlibvars v1.28.0 h1:jZnudE2zKCtYlGzLVreNp5pmCdOxXUzwsMDBkR21cyQ= github.com/sashamelentyev/usestdlibvars v1.28.0/go.mod h1:9nl0jgOfHKWNFS43Ojw0i7aRoS4j6EBye3YBhmAIRF8= -github.com/securego/gosec/v2 v2.22.3 h1:mRrCNmRF2NgZp4RJ8oJ6yPJ7G4x6OCiAXHd8x4trLRc= -github.com/securego/gosec/v2 v2.22.3/go.mod h1:42M9Xs0v1WseinaB/BmNGO8AVqG8vRfhC2686ACY48k= +github.com/securego/gosec/v2 v2.22.4 h1:21VdNGcKicFSv6rUDBc0cEtEl7lWyCKZxKIm0iwvrIM= +github.com/securego/gosec/v2 v2.22.4/go.mod h1:ww5Yie7KJ3AH8XZQTletkW5zOmIse6FACs/Ys8VR3qE= 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/shirou/gopsutil/v4 v4.25.4 h1:cdtFO363VEOOFrUCjZRh4XVJkb548lyF0q0uTeMqYPw= @@ -833,8 +833,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= -golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= +golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= 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= From 5a945fd5546aaa14f315105a651a236736217595 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 11 May 2025 14:11:28 +0200 Subject: [PATCH 108/152] build(deps): bump github.com/manuelarte/funcorder from 0.3.0 to 0.5.0 (#5792) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index bcb9e58ccf16..3f294565b54e 100644 --- a/go.mod +++ b/go.mod @@ -73,7 +73,7 @@ require ( github.com/ldez/usetesting v0.4.3 github.com/leonklingele/grouper v1.1.2 github.com/macabu/inamedparam v0.2.0 - github.com/manuelarte/funcorder v0.3.0 + github.com/manuelarte/funcorder v0.5.0 github.com/maratori/testableexamples v1.0.0 github.com/maratori/testpackage v1.1.1 github.com/matoous/godox v1.1.0 diff --git a/go.sum b/go.sum index 96a2731998e3..a522b52fb450 100644 --- a/go.sum +++ b/go.sum @@ -389,8 +389,8 @@ github.com/macabu/inamedparam v0.2.0 h1:VyPYpOc10nkhI2qeNUdh3Zket4fcZjEWe35poddB github.com/macabu/inamedparam v0.2.0/go.mod h1:+Pee9/YfGe5LJ62pYXqB89lJ+0k5bsR8Wgz/C0Zlq3U= github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/manuelarte/funcorder v0.3.0 h1:mV1joNYIjIUnnyZ6wfaC+sCWB6IvG62ay3xuhbklHps= -github.com/manuelarte/funcorder v0.3.0/go.mod h1:wBFktqsi8PyQvNYEUpF5Lt+V/xqgaevfCi4SSpUhyPo= +github.com/manuelarte/funcorder v0.5.0 h1:llMuHXXbg7tD0i/LNw8vGnkDTHFpTnWqKPI85Rknc+8= +github.com/manuelarte/funcorder v0.5.0/go.mod h1:Yt3CiUQthSBMBxjShjdXMexmzpP8YGvGLjrxJNkO2hA= 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.1 h1:S58XVV5AD7HADMmD0fNnziNHqKvSdDuEKdPD1rNTU04= From 3e52be7b0d94868487584e6ce19e72a9bb906507 Mon Sep 17 00:00:00 2001 From: Cooper Benson Date: Sun, 11 May 2025 12:07:41 -0600 Subject: [PATCH 109/152] Add swaggo/swag formatter (#5749) Co-authored-by: Fernandez Ludovic --- .github/dependabot.yml | 1 + .golangci.next.reference.yml | 1 + go.mod | 1 + go.sum | 2 ++ jsonschema/golangci.next.jsonschema.json | 3 ++- pkg/config/linters.go | 2 +- pkg/goformatters/meta_formatter.go | 7 +++++- pkg/goformatters/swaggo/swaggo.go | 23 +++++++++++++++++++ pkg/golinters/swaggo/swaggo.go | 23 +++++++++++++++++++ .../swaggo/swaggo_integration_test.go | 19 +++++++++++++++ .../swaggo/testdata/fix/in/swaggo.go | 18 +++++++++++++++ .../swaggo/testdata/fix/out/swaggo.go | 18 +++++++++++++++ pkg/golinters/swaggo/testdata/swaggo.go | 18 +++++++++++++++ pkg/golinters/swaggo/testdata/swaggo.yml | 5 ++++ pkg/lint/lintersdb/builder_linter.go | 6 +++++ pkg/result/processors/fixer.go | 3 ++- .../processors/max_per_file_from_linter.go | 3 ++- 17 files changed, 148 insertions(+), 5 deletions(-) create mode 100644 pkg/goformatters/swaggo/swaggo.go create mode 100644 pkg/golinters/swaggo/swaggo.go create mode 100644 pkg/golinters/swaggo/swaggo_integration_test.go create mode 100644 pkg/golinters/swaggo/testdata/fix/in/swaggo.go create mode 100644 pkg/golinters/swaggo/testdata/fix/out/swaggo.go create mode 100644 pkg/golinters/swaggo/testdata/swaggo.go create mode 100644 pkg/golinters/swaggo/testdata/swaggo.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 32b46fe168b1..ea714629b2d0 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -10,6 +10,7 @@ updates: # Ignore forked linters because of their versioning issues. - dependency-name: "github.com/golangci/dupl" - dependency-name: "github.com/golangci/gofmt" + - dependency-name: "github.com/golangci/swaggoswag" - dependency-name: "github.com/golangci/unconvert" - package-ecosystem: github-actions directory: "/" diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index 6a33e30e33d7..7f6798f02abd 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -3975,6 +3975,7 @@ formatters: - gofumpt - goimports - golines + - swaggo # Formatters settings. settings: diff --git a/go.mod b/go.mod index 3f294565b54e..3ae5aac563ca 100644 --- a/go.mod +++ b/go.mod @@ -51,6 +51,7 @@ require ( github.com/golangci/misspell v0.6.0 github.com/golangci/plugin-module-register v0.1.1 github.com/golangci/revgrep v0.8.0 + github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e github.com/gordonklaus/ineffassign v0.1.0 github.com/gostaticanalysis/forcetypeassert v0.2.0 diff --git a/go.sum b/go.sum index a522b52fb450..414fb890e851 100644 --- a/go.sum +++ b/go.sum @@ -263,6 +263,8 @@ github.com/golangci/plugin-module-register v0.1.1 h1:TCmesur25LnyJkpsVrupv1Cdzo+ github.com/golangci/plugin-module-register v0.1.1/go.mod h1:TTpqoB6KkwOJMV8u7+NyXMrkwwESJLOkfl9TxR1DGFc= github.com/golangci/revgrep v0.8.0 h1:EZBctwbVd0aMeRnNUsFogoyayvKHyxlV3CdUA46FX2s= github.com/golangci/revgrep v0.8.0/go.mod h1:U4R/s9dlXZsg8uJmaR1GrloUr14D7qDl8gi2iPXJH8k= +github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e h1:ai0EfmVYE2bRA5htgAG9r7s3tHsfjIhN98WshBTJ9jM= +github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e/go.mod h1:Vrn4B5oR9qRwM+f54koyeH3yzphlecwERs0el27Fr/s= github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e h1:gD6P7NEo7Eqtt0ssnqSJNNndxe69DOQ24A5h7+i3KpM= github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e/go.mod h1:h+wZwLjUTJnm/P2rwlbJdRPZXOzaT36/FwnPnY2inzc= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= diff --git a/jsonschema/golangci.next.jsonschema.json b/jsonschema/golangci.next.jsonschema.json index 5868d65451b2..5aeaf040c2ff 100644 --- a/jsonschema/golangci.next.jsonschema.json +++ b/jsonschema/golangci.next.jsonschema.json @@ -837,7 +837,8 @@ "gofmt", "gofumpt", "goimports", - "golines" + "golines", + "swaggo" ] }, "settings": { diff --git a/pkg/config/linters.go b/pkg/config/linters.go index 590d9448a197..2669f2e64778 100644 --- a/pkg/config/linters.go +++ b/pkg/config/linters.go @@ -49,5 +49,5 @@ func (l *Linters) validateNoFormatters() error { } func getAllFormatterNames() []string { - return []string{"gci", "gofmt", "gofumpt", "goimports", "golines"} + return []string{"gci", "gofmt", "gofumpt", "goimports", "golines", "swaggo"} } diff --git a/pkg/goformatters/meta_formatter.go b/pkg/goformatters/meta_formatter.go index 718caaa96003..dbedcd4cba19 100644 --- a/pkg/goformatters/meta_formatter.go +++ b/pkg/goformatters/meta_formatter.go @@ -12,6 +12,7 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/goformatters/gofumpt" "github.com/golangci/golangci-lint/v2/pkg/goformatters/goimports" "github.com/golangci/golangci-lint/v2/pkg/goformatters/golines" + "github.com/golangci/golangci-lint/v2/pkg/goformatters/swaggo" "github.com/golangci/golangci-lint/v2/pkg/logutils" ) @@ -41,6 +42,10 @@ func NewMetaFormatter(log logutils.Log, cfg *config.Formatters, runCfg *config.R m.formatters = append(m.formatters, goimports.New(&cfg.Settings.GoImports)) } + if slices.Contains(cfg.Enable, swaggo.Name) { + m.formatters = append(m.formatters, swaggo.New()) + } + // gci is a last because the only goal of gci is to handle imports. if slices.Contains(cfg.Enable, gci.Name) { formatter, err := gci.New(&cfg.Settings.Gci) @@ -86,5 +91,5 @@ func (m *MetaFormatter) Format(filename string, src []byte) []byte { } func IsFormatter(name string) bool { - return slices.Contains([]string{gofmt.Name, gofumpt.Name, goimports.Name, gci.Name, golines.Name}, name) + return slices.Contains([]string{gofmt.Name, gofumpt.Name, goimports.Name, gci.Name, golines.Name, swaggo.Name}, name) } diff --git a/pkg/goformatters/swaggo/swaggo.go b/pkg/goformatters/swaggo/swaggo.go new file mode 100644 index 000000000000..2479fb35baba --- /dev/null +++ b/pkg/goformatters/swaggo/swaggo.go @@ -0,0 +1,23 @@ +package swaggo + +import "github.com/golangci/swaggoswag" + +const Name = "swaggo" + +type Formatter struct { + formatter *swaggoswag.Formatter +} + +func New() *Formatter { + return &Formatter{ + formatter: swaggoswag.NewFormatter(), + } +} + +func (*Formatter) Name() string { + return Name +} + +func (f *Formatter) Format(path string, src []byte) ([]byte, error) { + return f.formatter.Format(path, src) +} diff --git a/pkg/golinters/swaggo/swaggo.go b/pkg/golinters/swaggo/swaggo.go new file mode 100644 index 000000000000..8c4eec8e448d --- /dev/null +++ b/pkg/golinters/swaggo/swaggo.go @@ -0,0 +1,23 @@ +package swaggo + +import ( + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/v2/pkg/goanalysis" + "github.com/golangci/golangci-lint/v2/pkg/goformatters" + "github.com/golangci/golangci-lint/v2/pkg/goformatters/swaggo" + "github.com/golangci/golangci-lint/v2/pkg/golinters/internal" +) + +const linterName = "swaggo" + +func New() *goanalysis.Linter { + a := goformatters.NewAnalyzer( + internal.LinterLogger.Child(linterName), + "Check if swaggo comments are formatted", + swaggo.New(), + ) + + return goanalysis.NewLinter(a.Name, a.Doc, []*analysis.Analyzer{a}, nil). + WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/pkg/golinters/swaggo/swaggo_integration_test.go b/pkg/golinters/swaggo/swaggo_integration_test.go new file mode 100644 index 000000000000..23fd3f1ff788 --- /dev/null +++ b/pkg/golinters/swaggo/swaggo_integration_test.go @@ -0,0 +1,19 @@ +package swaggo + +import ( + "testing" + + "github.com/golangci/golangci-lint/v2/test/testshared/integration" +) + +func TestFromTestdata(t *testing.T) { + integration.RunTestdata(t) +} + +func TestFix(t *testing.T) { + integration.RunFix(t) +} + +func TestFixPathPrefix(t *testing.T) { + integration.RunFixPathPrefix(t) +} diff --git a/pkg/golinters/swaggo/testdata/fix/in/swaggo.go b/pkg/golinters/swaggo/testdata/fix/in/swaggo.go new file mode 100644 index 000000000000..33c814b2805b --- /dev/null +++ b/pkg/golinters/swaggo/testdata/fix/in/swaggo.go @@ -0,0 +1,18 @@ +//golangcitest:config_path testdata/swaggo.yml +//golangcitest:expected_exitcode 0 +package api + +import "net/http" + +// @Summary Add a new pet to the store +// @Description get string by ID +// @ID get-string-by-int +// @Accept json +// @Produce json +// @Param some_id path int true "Some ID" Format(int64) +// @Param some_id body web.Pet true "Some ID" +// @Success 200 {string} string "ok" +// @Failure 400 {object} web.APIError "We need ID!!" +// @Failure 404 {object} web.APIError "Can not find ID" +// @Router /testapi/get-string-by-int/{some_id} [get] +func GetStringByInt(w http.ResponseWriter, r *http.Request) {} diff --git a/pkg/golinters/swaggo/testdata/fix/out/swaggo.go b/pkg/golinters/swaggo/testdata/fix/out/swaggo.go new file mode 100644 index 000000000000..8c4d2a2cdd40 --- /dev/null +++ b/pkg/golinters/swaggo/testdata/fix/out/swaggo.go @@ -0,0 +1,18 @@ +//golangcitest:config_path testdata/swaggo.yml +//golangcitest:expected_exitcode 0 +package api + +import "net/http" + +// @Summary Add a new pet to the store +// @Description get string by ID +// @ID get-string-by-int +// @Accept json +// @Produce json +// @Param some_id path int true "Some ID" Format(int64) +// @Param some_id body web.Pet true "Some ID" +// @Success 200 {string} string "ok" +// @Failure 400 {object} web.APIError "We need ID!!" +// @Failure 404 {object} web.APIError "Can not find ID" +// @Router /testapi/get-string-by-int/{some_id} [get] +func GetStringByInt(w http.ResponseWriter, r *http.Request) {} diff --git a/pkg/golinters/swaggo/testdata/swaggo.go b/pkg/golinters/swaggo/testdata/swaggo.go new file mode 100644 index 000000000000..db6b7da9dcfc --- /dev/null +++ b/pkg/golinters/swaggo/testdata/swaggo.go @@ -0,0 +1,18 @@ +//golangcitest:config_path testdata/swaggo.yml +package api + +import "net/http" + +// want +1 "File is not properly formatted" +// @Summary Add a new pet to the store +// @Description get string by ID +// @ID get-string-by-int +// @Accept json +// @Produce json +// @Param some_id path int true "Some ID" Format(int64) +// @Param some_id body web.Pet true "Some ID" +// @Success 200 {string} string "ok" +// @Failure 400 {object} web.APIError "We need ID!!" +// @Failure 404 {object} web.APIError "Can not find ID" +// @Router /testapi/get-string-by-int/{some_id} [get] +func GetStringByInt(w http.ResponseWriter, r *http.Request) {} diff --git a/pkg/golinters/swaggo/testdata/swaggo.yml b/pkg/golinters/swaggo/testdata/swaggo.yml new file mode 100644 index 000000000000..458e2fca7eeb --- /dev/null +++ b/pkg/golinters/swaggo/testdata/swaggo.yml @@ -0,0 +1,5 @@ +version: "2" + +formatters: + enable: + - swaggo diff --git a/pkg/lint/lintersdb/builder_linter.go b/pkg/lint/lintersdb/builder_linter.go index 5ac3e5ba2fb0..93ff1d35a5ff 100644 --- a/pkg/lint/lintersdb/builder_linter.go +++ b/pkg/lint/lintersdb/builder_linter.go @@ -94,6 +94,7 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/golinters/spancheck" "github.com/golangci/golangci-lint/v2/pkg/golinters/sqlclosecheck" "github.com/golangci/golangci-lint/v2/pkg/golinters/staticcheck" + "github.com/golangci/golangci-lint/v2/pkg/golinters/swaggo" "github.com/golangci/golangci-lint/v2/pkg/golinters/tagalign" "github.com/golangci/golangci-lint/v2/pkg/golinters/tagliatelle" "github.com/golangci/golangci-lint/v2/pkg/golinters/testableexamples" @@ -581,6 +582,11 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { WithAutoFix(). WithURL("https://staticcheck.dev/"), + linter.NewConfig(swaggo.New()). + WithSince("v2.2.0"). + WithAutoFix(). + WithURL("https://github.com/swaggo/swaggo"), + linter.NewConfig(tagalign.New(&cfg.Linters.Settings.TagAlign)). WithSince("v1.53.0"). WithAutoFix(). diff --git a/pkg/result/processors/fixer.go b/pkg/result/processors/fixer.go index 14dd3454eab6..d2beaa0ebafe 100644 --- a/pkg/result/processors/fixer.go +++ b/pkg/result/processors/fixer.go @@ -22,6 +22,7 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/goformatters/gofumpt" "github.com/golangci/golangci-lint/v2/pkg/goformatters/goimports" "github.com/golangci/golangci-lint/v2/pkg/goformatters/golines" + "github.com/golangci/golangci-lint/v2/pkg/goformatters/swaggo" "github.com/golangci/golangci-lint/v2/pkg/logutils" "github.com/golangci/golangci-lint/v2/pkg/result" "github.com/golangci/golangci-lint/v2/pkg/timeutils" @@ -79,7 +80,7 @@ func (p Fixer) process(issues []result.Issue) ([]result.Issue, error) { // filenames / linters / edits editsByLinter := make(map[string]map[string][]diff.Edit) - formatters := []string{gofumpt.Name, goimports.Name, gofmt.Name, gci.Name, golines.Name} + formatters := []string{gofumpt.Name, goimports.Name, gofmt.Name, gci.Name, golines.Name, swaggo.Name} var notFixableIssues []result.Issue diff --git a/pkg/result/processors/max_per_file_from_linter.go b/pkg/result/processors/max_per_file_from_linter.go index fdb6bb0278da..2608c22e22ab 100644 --- a/pkg/result/processors/max_per_file_from_linter.go +++ b/pkg/result/processors/max_per_file_from_linter.go @@ -7,6 +7,7 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/goformatters/gofumpt" "github.com/golangci/golangci-lint/v2/pkg/goformatters/goimports" "github.com/golangci/golangci-lint/v2/pkg/goformatters/golines" + "github.com/golangci/golangci-lint/v2/pkg/goformatters/swaggo" "github.com/golangci/golangci-lint/v2/pkg/result" ) @@ -24,7 +25,7 @@ func NewMaxPerFileFromLinter(cfg *config.Config) *MaxPerFileFromLinter { if !cfg.Issues.NeedFix { // if we don't fix we do this limiting to not annoy user; // otherwise we need to fix all issues in the file at once - for _, f := range []string{gofmt.Name, gofumpt.Name, goimports.Name, gci.Name, golines.Name} { + for _, f := range []string{gofmt.Name, gofumpt.Name, goimports.Name, gci.Name, golines.Name, swaggo.Name} { maxPerFileFromLinterConfig[f] = 1 } } From b24761d3fc9a4414fafe5abb079e13620b90d5cb Mon Sep 17 00:00:00 2001 From: Gabriel Augendre Date: Sun, 11 May 2025 20:10:19 +0200 Subject: [PATCH 110/152] feat: add arangolint linter (#5718) Co-authored-by: Fernandez Ludovic --- .github/dependabot.yml | 1 + .golangci.next.reference.yml | 2 + go.mod | 1 + go.sum | 2 + jsonschema/golangci.next.jsonschema.json | 1 + pkg/golinters/arangolint/arangolint.go | 19 +++++++ .../arangolint/arangolint_integration_test.go | 11 ++++ .../arangolint/testdata/arangolint.go | 35 +++++++++++++ .../arangolint/testdata/arangolint_cgo.go | 52 +++++++++++++++++++ pkg/golinters/arangolint/testdata/go.mod | 19 +++++++ pkg/golinters/arangolint/testdata/go.sum | 46 ++++++++++++++++ pkg/lint/lintersdb/builder_linter.go | 6 +++ 12 files changed, 195 insertions(+) create mode 100644 pkg/golinters/arangolint/arangolint.go create mode 100644 pkg/golinters/arangolint/arangolint_integration_test.go create mode 100644 pkg/golinters/arangolint/testdata/arangolint.go create mode 100644 pkg/golinters/arangolint/testdata/arangolint_cgo.go create mode 100644 pkg/golinters/arangolint/testdata/go.mod create mode 100644 pkg/golinters/arangolint/testdata/go.sum diff --git a/.github/dependabot.yml b/.github/dependabot.yml index ea714629b2d0..1e4618407dd5 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -38,6 +38,7 @@ updates: - "*" # Group all updates into a single larger pull request. - package-ecosystem: gomod directories: + - pkg/golinters/arangolint/testdata/ - pkg/golinters/ginkgolinter/testdata/ - pkg/golinters/loggercheck/testdata/ - pkg/golinters/protogetter/testdata/ diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index 7f6798f02abd..f53ddc68fde9 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -17,6 +17,7 @@ linters: # Enable specific linter. # https://golangci-lint.run/usage/linters/#enabled-by-default enable: + - arangolint - asasalint - asciicheck - bidichk @@ -125,6 +126,7 @@ linters: # Disable specific linter. # https://golangci-lint.run/usage/linters/#disabled-by-default disable: + - arangolint - asasalint - asciicheck - bidichk diff --git a/go.mod b/go.mod index 3ae5aac563ca..3a5195744126 100644 --- a/go.mod +++ b/go.mod @@ -127,6 +127,7 @@ require ( gitlab.com/bosi/decorder v0.4.2 go-simpler.org/musttag v0.13.1 go-simpler.org/sloglint v0.11.0 + go.augendre.info/arangolint v0.2.0 go.augendre.info/fatcontext v0.8.0 go.uber.org/automaxprocs v1.6.0 golang.org/x/mod v0.24.0 diff --git a/go.sum b/go.sum index 414fb890e851..5aec366fb13e 100644 --- a/go.sum +++ b/go.sum @@ -629,6 +629,8 @@ go-simpler.org/musttag v0.13.1 h1:lw2sJyu7S1X8lc8zWUAdH42y+afdcCnHhWpnkWvd6vU= go-simpler.org/musttag v0.13.1/go.mod h1:8r450ehpMLQgvpb6sg+hV5Ur47eH6olp/3yEanfG97k= go-simpler.org/sloglint v0.11.0 h1:JlR1X4jkbeaffiyjLtymeqmGDKBDO1ikC6rjiuFAOco= go-simpler.org/sloglint v0.11.0/go.mod h1:CFDO8R1i77dlciGfPEPvYke2ZMx4eyGiEIWkyeW2Pvw= +go.augendre.info/arangolint v0.2.0 h1:2NP/XudpPmfBhQKX4rMk+zDYIj//qbt4hfZmSSTcpj8= +go.augendre.info/arangolint v0.2.0/go.mod h1:Vx4KSJwu48tkE+8uxuf0cbBnAPgnt8O1KWiT7bljq7w= go.augendre.info/fatcontext v0.8.0 h1:2dfk6CQbDGeu1YocF59Za5Pia7ULeAM6friJ3LP7lmk= go.augendre.info/fatcontext v0.8.0/go.mod h1:oVJfMgwngMsHO+KB2MdgzcO+RvtNdiCEOlWvSFtax/s= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= diff --git a/jsonschema/golangci.next.jsonschema.json b/jsonschema/golangci.next.jsonschema.json index 5aeaf040c2ff..78960fabeaf1 100644 --- a/jsonschema/golangci.next.jsonschema.json +++ b/jsonschema/golangci.next.jsonschema.json @@ -718,6 +718,7 @@ "anyOf": [ { "enum": [ + "arangolint", "asasalint", "asciicheck", "bidichk", diff --git a/pkg/golinters/arangolint/arangolint.go b/pkg/golinters/arangolint/arangolint.go new file mode 100644 index 000000000000..7a46d93d02a9 --- /dev/null +++ b/pkg/golinters/arangolint/arangolint.go @@ -0,0 +1,19 @@ +package arangolint + +import ( + "go.augendre.info/arangolint/pkg/analyzer" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/v2/pkg/goanalysis" +) + +func New() *goanalysis.Linter { + a := analyzer.NewAnalyzer() + + return goanalysis.NewLinter( + a.Name, + a.Doc, + []*analysis.Analyzer{a}, + nil, + ).WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/pkg/golinters/arangolint/arangolint_integration_test.go b/pkg/golinters/arangolint/arangolint_integration_test.go new file mode 100644 index 000000000000..db0f1aef0923 --- /dev/null +++ b/pkg/golinters/arangolint/arangolint_integration_test.go @@ -0,0 +1,11 @@ +package arangolint + +import ( + "testing" + + "github.com/golangci/golangci-lint/v2/test/testshared/integration" +) + +func TestFromTestdata(t *testing.T) { + integration.RunTestdata(t) +} diff --git a/pkg/golinters/arangolint/testdata/arangolint.go b/pkg/golinters/arangolint/testdata/arangolint.go new file mode 100644 index 000000000000..1cc3f28a87c2 --- /dev/null +++ b/pkg/golinters/arangolint/testdata/arangolint.go @@ -0,0 +1,35 @@ +//golangcitest:args -Earangolint +package arangolint + +import ( + "context" + + "github.com/arangodb/go-driver/v2/arangodb" +) + +func _() { + ctx := context.Background() + arangoClient := arangodb.NewClient(nil) + db, _ := arangoClient.GetDatabase(ctx, "name", nil) + + // direct nil + db.BeginTransaction(ctx, arangodb.TransactionCollections{}, nil) // want "missing AllowImplicit option" + trx, _ := db.BeginTransaction(ctx, arangodb.TransactionCollections{}, nil) // want "missing AllowImplicit option" + _ = trx + + // direct missing + db.BeginTransaction(ctx, arangodb.TransactionCollections{}, &arangodb.BeginTransactionOptions{LockTimeout: 0}) // want "missing AllowImplicit option" + trx, _ = db.BeginTransaction(ctx, arangodb.TransactionCollections{}, &arangodb.BeginTransactionOptions{LockTimeout: 0}) // want "missing AllowImplicit option" + + // direct false + db.BeginTransaction(ctx, arangodb.TransactionCollections{}, &arangodb.BeginTransactionOptions{AllowImplicit: false}) + trx, _ = db.BeginTransaction(ctx, arangodb.TransactionCollections{}, &arangodb.BeginTransactionOptions{AllowImplicit: false}) + + // direct true + db.BeginTransaction(ctx, arangodb.TransactionCollections{}, &arangodb.BeginTransactionOptions{AllowImplicit: true}) + trx, _ = db.BeginTransaction(ctx, arangodb.TransactionCollections{}, &arangodb.BeginTransactionOptions{AllowImplicit: true}) + + // direct with other fields + db.BeginTransaction(ctx, arangodb.TransactionCollections{}, &arangodb.BeginTransactionOptions{AllowImplicit: true, LockTimeout: 0}) + trx, _ = db.BeginTransaction(ctx, arangodb.TransactionCollections{}, &arangodb.BeginTransactionOptions{AllowImplicit: true, LockTimeout: 0}) +} diff --git a/pkg/golinters/arangolint/testdata/arangolint_cgo.go b/pkg/golinters/arangolint/testdata/arangolint_cgo.go new file mode 100644 index 000000000000..3bc9bc7fefb8 --- /dev/null +++ b/pkg/golinters/arangolint/testdata/arangolint_cgo.go @@ -0,0 +1,52 @@ +//golangcitest:args -Earangolint +package arangolint + +/* + #include + #include + + void myprint(char* s) { + printf("%d\n", s); + } +*/ +import "C" + +import ( + "context" + "unsafe" + + "github.com/arangodb/go-driver/v2/arangodb" +) + +func _() { + cs := C.CString("Hello from stdio\n") + C.myprint(cs) + C.free(unsafe.Pointer(cs)) +} + +func _() { + ctx := context.Background() + arangoClient := arangodb.NewClient(nil) + db, _ := arangoClient.GetDatabase(ctx, "name", nil) + + // direct nil + db.BeginTransaction(ctx, arangodb.TransactionCollections{}, nil) // want "missing AllowImplicit option" + trx, _ := db.BeginTransaction(ctx, arangodb.TransactionCollections{}, nil) // want "missing AllowImplicit option" + _ = trx + + // direct missing + db.BeginTransaction(ctx, arangodb.TransactionCollections{}, &arangodb.BeginTransactionOptions{LockTimeout: 0}) // want "missing AllowImplicit option" + trx, _ = db.BeginTransaction(ctx, arangodb.TransactionCollections{}, &arangodb.BeginTransactionOptions{LockTimeout: 0}) // want "missing AllowImplicit option" + + // direct false + db.BeginTransaction(ctx, arangodb.TransactionCollections{}, &arangodb.BeginTransactionOptions{AllowImplicit: false}) + trx, _ = db.BeginTransaction(ctx, arangodb.TransactionCollections{}, &arangodb.BeginTransactionOptions{AllowImplicit: false}) + + // direct true + db.BeginTransaction(ctx, arangodb.TransactionCollections{}, &arangodb.BeginTransactionOptions{AllowImplicit: true}) + trx, _ = db.BeginTransaction(ctx, arangodb.TransactionCollections{}, &arangodb.BeginTransactionOptions{AllowImplicit: true}) + + // direct with other fields + db.BeginTransaction(ctx, arangodb.TransactionCollections{}, &arangodb.BeginTransactionOptions{AllowImplicit: true, LockTimeout: 0}) + trx, _ = db.BeginTransaction(ctx, arangodb.TransactionCollections{}, &arangodb.BeginTransactionOptions{AllowImplicit: true, LockTimeout: 0}) +} diff --git a/pkg/golinters/arangolint/testdata/go.mod b/pkg/golinters/arangolint/testdata/go.mod new file mode 100644 index 000000000000..c9d56c70228d --- /dev/null +++ b/pkg/golinters/arangolint/testdata/go.mod @@ -0,0 +1,19 @@ +module arangolint + +go 1.23.0 + +require github.com/arangodb/go-driver/v2 v2.1.3 + +require ( + github.com/arangodb/go-velocypack v0.0.0-20200318135517-5af53c29c67e // indirect + github.com/dchest/siphash v1.2.3 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/kkdai/maglev v0.2.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/rs/zerolog v1.33.0 // indirect + golang.org/x/net v0.33.0 // indirect + golang.org/x/sys v0.28.0 // indirect + golang.org/x/text v0.21.0 // indirect +) diff --git a/pkg/golinters/arangolint/testdata/go.sum b/pkg/golinters/arangolint/testdata/go.sum new file mode 100644 index 000000000000..9f27a49c38c8 --- /dev/null +++ b/pkg/golinters/arangolint/testdata/go.sum @@ -0,0 +1,46 @@ +github.com/arangodb/go-driver/v2 v2.1.3 h1:PpLSe8E2RalFuqTGi2yfHDe3ltOomfFCIToB66p1lr8= +github.com/arangodb/go-driver/v2 v2.1.3/go.mod h1:aoDzrsO7PQEFat3Q9pp4zfv6W+WotA7GcCeJQJfX+tc= +github.com/arangodb/go-velocypack v0.0.0-20200318135517-5af53c29c67e h1:Xg+hGrY2LcQBbxd0ZFdbGSyRKTYMZCfBbw/pMJFOk1g= +github.com/arangodb/go-velocypack v0.0.0-20200318135517-5af53c29c67e/go.mod h1:mq7Shfa/CaixoDxiyAAc5jZ6CVBAyPaNQCGS7mkj4Ho= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +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/dchest/siphash v1.2.2/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4= +github.com/dchest/siphash v1.2.3 h1:QXwFc8cFOR2dSa/gE6o/HokBMWtLUaNDVd+22aKHeEA= +github.com/dchest/siphash v1.2.3/go.mod h1:0NvQU092bT0ipiFN++/rXm69QG9tVxLAlQHIXMPAkHc= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/kkdai/maglev v0.2.0 h1:w6DCW0kAA6fstZqXkrBrlgIC3jeIRXkjOYea/m6EK/Y= +github.com/kkdai/maglev v0.2.0/go.mod h1:d+mt8Lmt3uqi9aRb/BnPjzD0fy+ETs1vVXiGRnqHVZ4= +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.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +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/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +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/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= +github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +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= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +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.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/pkg/lint/lintersdb/builder_linter.go b/pkg/lint/lintersdb/builder_linter.go index 93ff1d35a5ff..c975549cf6ba 100644 --- a/pkg/lint/lintersdb/builder_linter.go +++ b/pkg/lint/lintersdb/builder_linter.go @@ -3,6 +3,7 @@ package lintersdb import ( "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/golinters" + "github.com/golangci/golangci-lint/v2/pkg/golinters/arangolint" "github.com/golangci/golangci-lint/v2/pkg/golinters/asasalint" "github.com/golangci/golangci-lint/v2/pkg/golinters/asciicheck" "github.com/golangci/golangci-lint/v2/pkg/golinters/bidichk" @@ -136,6 +137,11 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { // 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(arangolint.New()). + WithSince("v2.2.0"). + WithLoadForGoAnalysis(). + WithURL("https://github.com/Crocmagnon/arangolint"), + linter.NewConfig(asasalint.New(&cfg.Linters.Settings.Asasalint)). WithSince("v1.47.0"). WithLoadForGoAnalysis(). From c61f43fdbcf4cff709b84dba0823fa13589b23dd Mon Sep 17 00:00:00 2001 From: Manuel Doncel Martos Date: Tue, 13 May 2025 10:29:41 +0200 Subject: [PATCH 111/152] feat: add embeddedstructfieldcheck linter (#5761) Co-authored-by: Fernandez Ludovic --- .golangci.next.reference.yml | 2 + go.mod | 1 + go.sum | 2 + jsonschema/golangci.next.jsonschema.json | 1 + .../embeddedstructfieldcheck.go | 19 +++++++++ ...beddedstructfieldcheck_integration_test.go | 19 +++++++++ .../embeddedstructfieldcheck_comments.go | 27 +++++++++++++ .../embeddedstructfieldcheck_simple.go | 39 +++++++++++++++++++ .../embeddedstructfieldcheck_special_cases.go | 11 ++++++ .../testdata/fix/in/comments.go | 39 +++++++++++++++++++ .../testdata/fix/in/simple.go | 23 +++++++++++ .../testdata/fix/out/comments.go | 39 +++++++++++++++++++ .../testdata/fix/out/simple.go | 25 ++++++++++++ pkg/lint/lintersdb/builder_linter.go | 5 +++ 14 files changed, 252 insertions(+) create mode 100644 pkg/golinters/embeddedstructfieldcheck/embeddedstructfieldcheck.go create mode 100644 pkg/golinters/embeddedstructfieldcheck/embeddedstructfieldcheck_integration_test.go create mode 100644 pkg/golinters/embeddedstructfieldcheck/testdata/embeddedstructfieldcheck_comments.go create mode 100644 pkg/golinters/embeddedstructfieldcheck/testdata/embeddedstructfieldcheck_simple.go create mode 100644 pkg/golinters/embeddedstructfieldcheck/testdata/embeddedstructfieldcheck_special_cases.go create mode 100644 pkg/golinters/embeddedstructfieldcheck/testdata/fix/in/comments.go create mode 100644 pkg/golinters/embeddedstructfieldcheck/testdata/fix/in/simple.go create mode 100644 pkg/golinters/embeddedstructfieldcheck/testdata/fix/out/comments.go create mode 100644 pkg/golinters/embeddedstructfieldcheck/testdata/fix/out/simple.go diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index f53ddc68fde9..ff015539fabb 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -33,6 +33,7 @@ linters: - dupl - dupword - durationcheck + - embeddedstructfieldcheck - err113 - errcheck - errchkjson @@ -142,6 +143,7 @@ linters: - dupl - dupword - durationcheck + - embeddedstructfieldcheck - err113 - errcheck - errchkjson diff --git a/go.mod b/go.mod index 3a5195744126..ca6b23a4880b 100644 --- a/go.mod +++ b/go.mod @@ -74,6 +74,7 @@ require ( github.com/ldez/usetesting v0.4.3 github.com/leonklingele/grouper v1.1.2 github.com/macabu/inamedparam v0.2.0 + github.com/manuelarte/embeddedstructfieldcheck v0.2.1 github.com/manuelarte/funcorder v0.5.0 github.com/maratori/testableexamples v1.0.0 github.com/maratori/testpackage v1.1.1 diff --git a/go.sum b/go.sum index 5aec366fb13e..6c6f2bf9639b 100644 --- a/go.sum +++ b/go.sum @@ -391,6 +391,8 @@ github.com/macabu/inamedparam v0.2.0 h1:VyPYpOc10nkhI2qeNUdh3Zket4fcZjEWe35poddB github.com/macabu/inamedparam v0.2.0/go.mod h1:+Pee9/YfGe5LJ62pYXqB89lJ+0k5bsR8Wgz/C0Zlq3U= github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/manuelarte/embeddedstructfieldcheck v0.2.1 h1:oKexdVGs8Jy31IzOD/EMKfZmgogFhAaDbHb1o0qmA1Q= +github.com/manuelarte/embeddedstructfieldcheck v0.2.1/go.mod h1:LSo/IQpPfx1dXMcX4ibZCYA7Yy6ayZHIaOGM70+1Wy8= github.com/manuelarte/funcorder v0.5.0 h1:llMuHXXbg7tD0i/LNw8vGnkDTHFpTnWqKPI85Rknc+8= github.com/manuelarte/funcorder v0.5.0/go.mod h1:Yt3CiUQthSBMBxjShjdXMexmzpP8YGvGLjrxJNkO2hA= github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI= diff --git a/jsonschema/golangci.next.jsonschema.json b/jsonschema/golangci.next.jsonschema.json index 78960fabeaf1..9da8ac328072 100644 --- a/jsonschema/golangci.next.jsonschema.json +++ b/jsonschema/golangci.next.jsonschema.json @@ -734,6 +734,7 @@ "dupl", "dupword", "durationcheck", + "embeddedstructfieldcheck", "errcheck", "errchkjson", "errname", diff --git a/pkg/golinters/embeddedstructfieldcheck/embeddedstructfieldcheck.go b/pkg/golinters/embeddedstructfieldcheck/embeddedstructfieldcheck.go new file mode 100644 index 000000000000..781bcf5d201e --- /dev/null +++ b/pkg/golinters/embeddedstructfieldcheck/embeddedstructfieldcheck.go @@ -0,0 +1,19 @@ +package embeddedstructfieldcheck + +import ( + "github.com/manuelarte/embeddedstructfieldcheck/analyzer" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/v2/pkg/goanalysis" +) + +func New() *goanalysis.Linter { + a := analyzer.NewAnalyzer() + + return goanalysis.NewLinter( + a.Name, + a.Doc, + []*analysis.Analyzer{a}, + nil, + ).WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/pkg/golinters/embeddedstructfieldcheck/embeddedstructfieldcheck_integration_test.go b/pkg/golinters/embeddedstructfieldcheck/embeddedstructfieldcheck_integration_test.go new file mode 100644 index 000000000000..ba4258467733 --- /dev/null +++ b/pkg/golinters/embeddedstructfieldcheck/embeddedstructfieldcheck_integration_test.go @@ -0,0 +1,19 @@ +package embeddedstructfieldcheck + +import ( + "testing" + + "github.com/golangci/golangci-lint/v2/test/testshared/integration" +) + +func TestFromTestdata(t *testing.T) { + integration.RunTestdata(t) +} + +func TestFix(t *testing.T) { + integration.RunFix(t) +} + +func TestFixPathPrefix(t *testing.T) { + integration.RunFixPathPrefix(t) +} diff --git a/pkg/golinters/embeddedstructfieldcheck/testdata/embeddedstructfieldcheck_comments.go b/pkg/golinters/embeddedstructfieldcheck/testdata/embeddedstructfieldcheck_comments.go new file mode 100644 index 000000000000..12a6a4fa1ddf --- /dev/null +++ b/pkg/golinters/embeddedstructfieldcheck/testdata/embeddedstructfieldcheck_comments.go @@ -0,0 +1,27 @@ +//golangcitest:args -Eembeddedstructfieldcheck +package simple + +import "time" + +type ValidStructWithSingleLineComments struct { + // time.Time Single line comment + time.Time + + // version Single line comment + version int +} + +type StructWithSingleLineComments struct { + // time.Time Single line comment + time.Time // want `there must be an empty line separating embedded fields from regular fields` + // version Single line comment + version int +} + +type StructWithMultiLineComments struct { + // time.Time Single line comment + time.Time // want `there must be an empty line separating embedded fields from regular fields` + // version Single line comment + // very long comment + version int +} diff --git a/pkg/golinters/embeddedstructfieldcheck/testdata/embeddedstructfieldcheck_simple.go b/pkg/golinters/embeddedstructfieldcheck/testdata/embeddedstructfieldcheck_simple.go new file mode 100644 index 000000000000..47b155e5f52a --- /dev/null +++ b/pkg/golinters/embeddedstructfieldcheck/testdata/embeddedstructfieldcheck_simple.go @@ -0,0 +1,39 @@ +//golangcitest:args -Eembeddedstructfieldcheck +package simple + +import ( + "context" + "time" +) + +type ValidStruct struct { + time.Time + + version int +} + +type NoSpaceStruct struct { + time.Time // want `there must be an empty line separating embedded fields from regular fields` + version int +} + +type NotSortedStruct struct { + version int + + time.Time // want `embedded fields should be listed before regular fields` +} + +type MixedEmbeddedAndNotEmbedded struct { + context.Context + + name string + + time.Time // want `embedded fields should be listed before regular fields` + + age int +} + +type EmbeddedWithPointers struct { + *time.Time // want `there must be an empty line separating embedded fields from regular fields` + version int +} diff --git a/pkg/golinters/embeddedstructfieldcheck/testdata/embeddedstructfieldcheck_special_cases.go b/pkg/golinters/embeddedstructfieldcheck/testdata/embeddedstructfieldcheck_special_cases.go new file mode 100644 index 000000000000..95b5356b5824 --- /dev/null +++ b/pkg/golinters/embeddedstructfieldcheck/testdata/embeddedstructfieldcheck_special_cases.go @@ -0,0 +1,11 @@ +//golangcitest:args -Eembeddedstructfieldcheck +package simple + +import "time" + +func myFunction() { + type myType struct { + version int + time.Time // want `embedded fields should be listed before regular fields` + } +} diff --git a/pkg/golinters/embeddedstructfieldcheck/testdata/fix/in/comments.go b/pkg/golinters/embeddedstructfieldcheck/testdata/fix/in/comments.go new file mode 100644 index 000000000000..5cd45dc171b7 --- /dev/null +++ b/pkg/golinters/embeddedstructfieldcheck/testdata/fix/in/comments.go @@ -0,0 +1,39 @@ +//golangcitest:args -Eembeddedstructfieldcheck +//golangcitest:expected_exitcode 0 +package testdata + +import "time" + +type ValidStructWithSingleLineComments struct { + // time.Time Single line comment + time.Time + + // version Single line comment + version int +} + +type StructWithSingleLineComments struct { + // time.Time Single line comment + time.Time // want `there must be an empty line separating embedded fields from regular fields` + + // version Single line comment + version int +} + +type StructWithMultiLineComments struct { + // time.Time Single line comment + time.Time // want `there must be an empty line separating embedded fields from regular fields` + + // version Single line comment + // very long comment + version int +} + +type A struct { + // comment + ValidStructWithSingleLineComments + // C is foo + StructWithSingleLineComments // want `there must be an empty line separating embedded fields from regular fields` + + D string +} diff --git a/pkg/golinters/embeddedstructfieldcheck/testdata/fix/in/simple.go b/pkg/golinters/embeddedstructfieldcheck/testdata/fix/in/simple.go new file mode 100644 index 000000000000..578ddc0d170e --- /dev/null +++ b/pkg/golinters/embeddedstructfieldcheck/testdata/fix/in/simple.go @@ -0,0 +1,23 @@ +//golangcitest:args -Eembeddedstructfieldcheck +//golangcitest:expected_exitcode 0 +package testdata + +import ( + "time" +) + +type ValidStruct struct { + time.Time + + version int +} + +type NoSpaceStruct struct { + time.Time // want `there must be an empty line separating embedded fields from regular fields` + version int +} + +type EmbeddedWithPointers struct { + *time.Time // want `there must be an empty line separating embedded fields from regular fields` + version int +} diff --git a/pkg/golinters/embeddedstructfieldcheck/testdata/fix/out/comments.go b/pkg/golinters/embeddedstructfieldcheck/testdata/fix/out/comments.go new file mode 100644 index 000000000000..5cd45dc171b7 --- /dev/null +++ b/pkg/golinters/embeddedstructfieldcheck/testdata/fix/out/comments.go @@ -0,0 +1,39 @@ +//golangcitest:args -Eembeddedstructfieldcheck +//golangcitest:expected_exitcode 0 +package testdata + +import "time" + +type ValidStructWithSingleLineComments struct { + // time.Time Single line comment + time.Time + + // version Single line comment + version int +} + +type StructWithSingleLineComments struct { + // time.Time Single line comment + time.Time // want `there must be an empty line separating embedded fields from regular fields` + + // version Single line comment + version int +} + +type StructWithMultiLineComments struct { + // time.Time Single line comment + time.Time // want `there must be an empty line separating embedded fields from regular fields` + + // version Single line comment + // very long comment + version int +} + +type A struct { + // comment + ValidStructWithSingleLineComments + // C is foo + StructWithSingleLineComments // want `there must be an empty line separating embedded fields from regular fields` + + D string +} diff --git a/pkg/golinters/embeddedstructfieldcheck/testdata/fix/out/simple.go b/pkg/golinters/embeddedstructfieldcheck/testdata/fix/out/simple.go new file mode 100644 index 000000000000..a35f19ff4a15 --- /dev/null +++ b/pkg/golinters/embeddedstructfieldcheck/testdata/fix/out/simple.go @@ -0,0 +1,25 @@ +//golangcitest:args -Eembeddedstructfieldcheck +//golangcitest:expected_exitcode 0 +package testdata + +import ( + "time" +) + +type ValidStruct struct { + time.Time + + version int +} + +type NoSpaceStruct struct { + time.Time // want `there must be an empty line separating embedded fields from regular fields` + + version int +} + +type EmbeddedWithPointers struct { + *time.Time // want `there must be an empty line separating embedded fields from regular fields` + + version int +} diff --git a/pkg/lint/lintersdb/builder_linter.go b/pkg/lint/lintersdb/builder_linter.go index c975549cf6ba..37f18bdc9eae 100644 --- a/pkg/lint/lintersdb/builder_linter.go +++ b/pkg/lint/lintersdb/builder_linter.go @@ -19,6 +19,7 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/golinters/dupl" "github.com/golangci/golangci-lint/v2/pkg/golinters/dupword" "github.com/golangci/golangci-lint/v2/pkg/golinters/durationcheck" + "github.com/golangci/golangci-lint/v2/pkg/golinters/embeddedstructfieldcheck" "github.com/golangci/golangci-lint/v2/pkg/golinters/err113" "github.com/golangci/golangci-lint/v2/pkg/golinters/errcheck" "github.com/golangci/golangci-lint/v2/pkg/golinters/errchkjson" @@ -212,6 +213,10 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { WithLoadForGoAnalysis(). WithURL("https://github.com/charithe/durationcheck"), + linter.NewConfig(embeddedstructfieldcheck.New()). + WithSince("v2.2.0"). + WithURL("https://github.com/manuelarte/embeddedstructfieldcheck"), + linter.NewConfig(errcheck.New(&cfg.Linters.Settings.Errcheck)). WithGroups(config.GroupStandard). WithSince("v1.0.0"). From 8c225c34db818afc0b424a41d69b7896fe0baf32 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Tue, 13 May 2025 17:34:00 +0200 Subject: [PATCH 112/152] fix: exclusions path-expect (#5798) --- pkg/result/processors/exclusion_paths.go | 2 +- pkg/result/processors/exclusion_paths_test.go | 41 ++++++++++++++----- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/pkg/result/processors/exclusion_paths.go b/pkg/result/processors/exclusion_paths.go index 104c33eefa5b..90c5f522f8bd 100644 --- a/pkg/result/processors/exclusion_paths.go +++ b/pkg/result/processors/exclusion_paths.go @@ -114,5 +114,5 @@ func (p *ExclusionPaths) shouldPassIssue(issue *result.Issue) bool { matched = true } - return !matched + return matched } diff --git a/pkg/result/processors/exclusion_paths_test.go b/pkg/result/processors/exclusion_paths_test.go index 44e17d207d38..deac410ab366 100644 --- a/pkg/result/processors/exclusion_paths_test.go +++ b/pkg/result/processors/exclusion_paths_test.go @@ -128,9 +128,9 @@ func TestExclusionPaths_Process(t *testing.T) { {RelativePath: filepath.FromSlash("base/d/file.go")}, }, expected: []result.Issue{ - {RelativePath: filepath.FromSlash("base/a/file.go")}, - {RelativePath: filepath.FromSlash("base/b/file.go")}, - {RelativePath: filepath.FromSlash("base/d/file.go")}, + {RelativePath: filepath.FromSlash("base/c/file.go")}, + {RelativePath: filepath.FromSlash("base/c/a/file.go")}, + {RelativePath: filepath.FromSlash("base/c/b/file.go")}, }, }, { @@ -151,9 +151,9 @@ func TestExclusionPaths_Process(t *testing.T) { {RelativePath: filepath.FromSlash("base/d/file.go")}, }, expected: []result.Issue{ - {RelativePath: filepath.FromSlash("base/a/file.go")}, - {RelativePath: filepath.FromSlash("base/b/file.go")}, - {RelativePath: filepath.FromSlash("base/d/file.go")}, + {RelativePath: filepath.FromSlash("base/c/file.go")}, + {RelativePath: filepath.FromSlash("base/c/a/file.go")}, + {RelativePath: filepath.FromSlash("base/c/b/file.go")}, }, }, { @@ -174,13 +174,14 @@ func TestExclusionPaths_Process(t *testing.T) { {RelativePath: filepath.FromSlash("base/e/file.go")}, }, expected: []result.Issue{ - {RelativePath: filepath.FromSlash("base/a/file.go")}, - {RelativePath: filepath.FromSlash("base/b/file.go")}, - {RelativePath: filepath.FromSlash("base/d/file.go")}, + {RelativePath: filepath.FromSlash("base/c/file.go")}, + {RelativePath: filepath.FromSlash("base/c/a/file.go")}, + {RelativePath: filepath.FromSlash("base/c/b/file.go")}, + {RelativePath: filepath.FromSlash("base/e/file.go")}, }, }, { - desc: "pathsExcept and paths", + desc: "pathsExcept and paths (disjoint)", cfg: &config.LinterExclusions{ Paths: []string{"^base/b/"}, PathsExcept: []string{`^base/c/.*$`}, @@ -194,9 +195,29 @@ func TestExclusionPaths_Process(t *testing.T) { {RelativePath: filepath.FromSlash("base/d/file.go")}, }, expected: []result.Issue{ + {RelativePath: filepath.FromSlash("base/c/file.go")}, + {RelativePath: filepath.FromSlash("base/c/a/file.go")}, + {RelativePath: filepath.FromSlash("base/c/b/file.go")}, + }, + }, + { + desc: "pathsExcept and paths (intersection)", + cfg: &config.LinterExclusions{ + Paths: []string{"^base/c/a/"}, + PathsExcept: []string{`^base/c/.*$`}, + }, + issues: []result.Issue{ {RelativePath: filepath.FromSlash("base/a/file.go")}, + {RelativePath: filepath.FromSlash("base/b/file.go")}, + {RelativePath: filepath.FromSlash("base/c/file.go")}, + {RelativePath: filepath.FromSlash("base/c/a/file.go")}, + {RelativePath: filepath.FromSlash("base/c/b/file.go")}, {RelativePath: filepath.FromSlash("base/d/file.go")}, }, + expected: []result.Issue{ + {RelativePath: filepath.FromSlash("base/c/file.go")}, + {RelativePath: filepath.FromSlash("base/c/b/file.go")}, + }, }, } From aec176a6a2827c993b59f601fc42c44bcaeda61e Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Tue, 13 May 2025 22:40:48 +0200 Subject: [PATCH 113/152] dev: simplify linter constructors (#5796) --- pkg/goanalysis/linter.go | 27 ++++-- pkg/golinters/arangolint/arangolint.go | 12 +-- pkg/golinters/asasalint/asasalint.go | 12 +-- pkg/golinters/asciicheck/asciicheck.go | 12 +-- pkg/golinters/bidichk/bidichk.go | 16 ++-- pkg/golinters/bodyclose/bodyclose.go | 12 +-- .../canonicalheader/canonicalheader.go | 12 +-- pkg/golinters/containedctx/containedctx.go | 12 +-- pkg/golinters/contextcheck/contextcheck.go | 15 ++-- pkg/golinters/copyloopvar/copyloopvar.go | 20 ++--- pkg/golinters/cyclop/cyclop.go | 26 ++---- pkg/golinters/decorder/decorder.go | 13 +-- pkg/golinters/depguard/depguard.go | 25 +++--- pkg/golinters/dogsled/dogsled.go | 27 +++--- pkg/golinters/dupl/dupl.go | 52 +++++------ pkg/golinters/dupword/dupword.go | 17 ++-- pkg/golinters/durationcheck/durationcheck.go | 12 +-- .../embeddedstructfieldcheck.go | 12 +-- pkg/golinters/err113/err113.go | 13 +-- pkg/golinters/errcheck/errcheck.go | 47 +++++----- pkg/golinters/errchkjson/errchkjson.go | 19 ++-- pkg/golinters/errname/errname.go | 12 +-- pkg/golinters/errorlint/errorlint.go | 19 ++-- pkg/golinters/exhaustive/exhaustive.go | 38 ++++---- pkg/golinters/exhaustruct/exhaustruct.go | 15 ++-- pkg/golinters/exptostd/exptostd.go | 12 +-- pkg/golinters/fatcontext/fatcontext.go | 17 ++-- pkg/golinters/forbidigo/forbidigo.go | 35 ++++---- .../forcetypeassert/forcetypeassert.go | 13 +-- pkg/golinters/funcorder/funcorder.go | 17 ++-- pkg/golinters/funlen/funlen.go | 12 +-- pkg/golinters/gci/gci.go | 23 ++--- pkg/golinters/ginkgolinter/ginkgolinter.go | 13 +-- .../gocheckcompilerdirectives.go | 12 +-- .../gochecknoglobals/gochecknoglobals.go | 13 +-- .../gochecknoinits/gochecknoinits.go | 23 ++--- .../gochecksumtype/gochecksumtype.go | 50 +++++------ pkg/golinters/gocognit/gocognit.go | 42 ++++----- pkg/golinters/goconst/goconst.go | 50 +++++------ pkg/golinters/gocritic/gocritic.go | 32 +++---- pkg/golinters/gocyclo/gocyclo.go | 42 ++++----- pkg/golinters/godot/godot.go | 35 +++----- pkg/golinters/godox/godox.go | 25 ++---- pkg/golinters/gofmt/gofmt.go | 25 ++---- pkg/golinters/gofumpt/gofumpt.go | 25 ++---- pkg/golinters/goheader/goheader.go | 33 +++---- pkg/golinters/goimports/goimports.go | 25 ++---- pkg/golinters/golines/golines.go | 25 ++---- .../gomoddirectives/gomoddirectives.go | 57 ++++++------ pkg/golinters/gomodguard/gomodguard.go | 69 +++++++-------- .../goprintffuncname/goprintffuncname.go | 12 +-- pkg/golinters/gosec/gosec.go | 41 +++++---- pkg/golinters/gosmopolitan/gosmopolitan.go | 16 ++-- pkg/golinters/grouper/grouper.go | 18 ++-- pkg/golinters/importas/importas.go | 87 +++++++++---------- pkg/golinters/inamedparam/inamedparam.go | 21 ++--- pkg/golinters/ineffassign/ineffassign.go | 13 +-- .../interfacebloat/interfacebloat.go | 20 ++--- pkg/golinters/intrange/intrange.go | 12 +-- pkg/golinters/ireturn/ireturn.go | 16 ++-- pkg/golinters/lll/lll.go | 35 +++----- pkg/golinters/loggercheck/loggercheck.go | 11 +-- pkg/golinters/maintidx/maintidx.go | 21 ++--- pkg/golinters/makezero/makezero.go | 35 +++----- pkg/golinters/mirror/mirror.go | 19 ++-- pkg/golinters/misspell/misspell.go | 33 +++---- pkg/golinters/mnd/mnd.go | 20 ++--- pkg/golinters/musttag/musttag.go | 5 +- pkg/golinters/nakedret/nakedret.go | 12 +-- pkg/golinters/nestif/nestif.go | 29 +++---- pkg/golinters/nilerr/nilerr.go | 13 +-- pkg/golinters/nilnesserr/nilnesserr.go | 12 +-- pkg/golinters/nilnil/nilnil.go | 19 ++-- pkg/golinters/nlreturn/nlreturn.go | 18 ++-- pkg/golinters/noctx/noctx.go | 13 +-- pkg/golinters/nolintlint/nolintlint.go | 50 +++++------ .../nonamedreturns/nonamedreturns.go | 20 ++--- .../nosprintfhostport/nosprintfhostport.go | 12 +-- pkg/golinters/paralleltest/paralleltest.go | 21 ++--- pkg/golinters/perfsprint/perfsprint.go | 37 ++++---- pkg/golinters/prealloc/prealloc.go | 29 +++---- pkg/golinters/predeclared/predeclared.go | 16 ++-- pkg/golinters/promlinter/promlinter.go | 42 ++++----- pkg/golinters/protogetter/protogetter.go | 13 +-- pkg/golinters/reassign/reassign.go | 20 ++--- pkg/golinters/recvcheck/recvcheck.go | 12 +-- pkg/golinters/revive/revive.go | 55 ++++++------ pkg/golinters/rowserrcheck/rowserrcheck.go | 14 ++- pkg/golinters/sloglint/sloglint.go | 6 +- pkg/golinters/spancheck/spancheck.go | 5 +- pkg/golinters/sqlclosecheck/sqlclosecheck.go | 12 +-- pkg/golinters/swaggo/swaggo.go | 19 ++-- pkg/golinters/tagalign/tagalign.go | 12 +-- pkg/golinters/tagliatelle/tagliatelle.go | 12 +-- .../testableexamples/testableexamples.go | 12 +-- pkg/golinters/testifylint/testifylint.go | 28 +++--- pkg/golinters/testpackage/testpackage.go | 16 ++-- pkg/golinters/thelper/thelper.go | 19 ++-- pkg/golinters/tparallel/tparallel.go | 11 +-- pkg/golinters/typecheck.go | 21 ++--- pkg/golinters/unconvert/unconvert.go | 42 ++++----- pkg/golinters/unparam/unparam.go | 37 ++++---- pkg/golinters/usestdlibvars/usestdlibvars.go | 16 ++-- pkg/golinters/usetesting/usetesting.go | 16 ++-- pkg/golinters/varnamelen/varnamelen.go | 18 ++-- pkg/golinters/wastedassign/wastedassign.go | 13 +-- pkg/golinters/whitespace/whitespace.go | 12 +-- pkg/golinters/wrapcheck/wrapcheck.go | 12 +-- pkg/golinters/wsl/wsl.go | 13 +-- pkg/golinters/zerologlint/zerologlint.go | 12 +-- 110 files changed, 970 insertions(+), 1508 deletions(-) diff --git a/pkg/goanalysis/linter.go b/pkg/goanalysis/linter.go index 80ccfe456408..53f5b7bae455 100644 --- a/pkg/goanalysis/linter.go +++ b/pkg/goanalysis/linter.go @@ -13,11 +13,6 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/result" ) -const ( - TheOnlyAnalyzerName = "the_only_name" - TheOnlyanalyzerDoc = "the_only_doc" -) - type LoadMode int func (loadMode LoadMode) String() string { @@ -55,6 +50,10 @@ func NewLinter(name, desc string, analyzers []*analysis.Analyzer, cfg map[string return &Linter{name: name, desc: desc, analyzers: analyzers, cfg: cfg} } +func NewLinterFromAnalyzer(analyzer *analysis.Analyzer) *Linter { + return NewLinter(analyzer.Name, analyzer.Doc, []*analysis.Analyzer{analyzer}, nil) +} + func (lnt *Linter) Run(_ context.Context, lintCtx *linter.Context) ([]result.Issue, error) { if err := lnt.preRun(lintCtx); err != nil { return nil, err @@ -71,6 +70,24 @@ func (lnt *Linter) LoadMode() LoadMode { return lnt.loadMode } +func (lnt *Linter) WithDesc(desc string) *Linter { + lnt.desc = desc + + return lnt +} + +func (lnt *Linter) WithConfig(cfg map[string]any) *Linter { + if len(cfg) == 0 { + return lnt + } + + lnt.cfg = map[string]map[string]any{ + lnt.name: cfg, + } + + return lnt +} + func (lnt *Linter) WithLoadMode(loadMode LoadMode) *Linter { lnt.loadMode = loadMode return lnt diff --git a/pkg/golinters/arangolint/arangolint.go b/pkg/golinters/arangolint/arangolint.go index 7a46d93d02a9..1598d532a879 100644 --- a/pkg/golinters/arangolint/arangolint.go +++ b/pkg/golinters/arangolint/arangolint.go @@ -2,18 +2,12 @@ package arangolint import ( "go.augendre.info/arangolint/pkg/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := analyzer.NewAnalyzer() - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(analyzer.NewAnalyzer()). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/asasalint/asasalint.go b/pkg/golinters/asasalint/asasalint.go index 5f33428c2224..0261e109d8aa 100644 --- a/pkg/golinters/asasalint/asasalint.go +++ b/pkg/golinters/asasalint/asasalint.go @@ -2,7 +2,6 @@ package asasalint import ( "github.com/alingse/asasalint" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -19,15 +18,12 @@ func New(settings *config.AsasalintSettings) *goanalysis.Linter { cfg.IgnoreTest = false } - a, err := asasalint.NewAnalyzer(cfg) + analyzer, err := asasalint.NewAnalyzer(cfg) if err != nil { internal.LinterLogger.Fatalf("asasalint: create analyzer: %v", err) } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(analyzer). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/asciicheck/asciicheck.go b/pkg/golinters/asciicheck/asciicheck.go index b5cdaa80bbeb..4872770365c6 100644 --- a/pkg/golinters/asciicheck/asciicheck.go +++ b/pkg/golinters/asciicheck/asciicheck.go @@ -2,18 +2,12 @@ package asciicheck import ( "github.com/tdakkota/asciicheck" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := asciicheck.NewAnalyzer() - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(asciicheck.NewAnalyzer()). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/bidichk/bidichk.go b/pkg/golinters/bidichk/bidichk.go index 2d2a8d664fa4..c35daafbfb77 100644 --- a/pkg/golinters/bidichk/bidichk.go +++ b/pkg/golinters/bidichk/bidichk.go @@ -4,16 +4,14 @@ import ( "strings" "github.com/breml/bidichk/pkg/bidichk" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.BiDiChkSettings) *goanalysis.Linter { - a := bidichk.NewAnalyzer() + var cfg map[string]any - cfg := map[string]map[string]any{} if settings != nil { var opts []string @@ -45,15 +43,13 @@ func New(settings *config.BiDiChkSettings) *goanalysis.Linter { opts = append(opts, "POP-DIRECTIONAL-ISOLATE") } - cfg[a.Name] = map[string]any{ + cfg = map[string]any{ "disallowed-runes": strings.Join(opts, ","), } } - return goanalysis.NewLinter( - a.Name, - "Checks for dangerous unicode character sequences", - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(bidichk.NewAnalyzer()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/bodyclose/bodyclose.go b/pkg/golinters/bodyclose/bodyclose.go index 0c86fbe76513..f68c4d0a9e6a 100644 --- a/pkg/golinters/bodyclose/bodyclose.go +++ b/pkg/golinters/bodyclose/bodyclose.go @@ -2,18 +2,12 @@ package bodyclose import ( "github.com/timakin/bodyclose/passes/bodyclose" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := bodyclose.Analyzer - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(bodyclose.Analyzer). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/canonicalheader/canonicalheader.go b/pkg/golinters/canonicalheader/canonicalheader.go index bda1dfbd20d3..24e95f143e9d 100644 --- a/pkg/golinters/canonicalheader/canonicalheader.go +++ b/pkg/golinters/canonicalheader/canonicalheader.go @@ -2,18 +2,12 @@ package canonicalheader import ( "github.com/lasiar/canonicalheader" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := canonicalheader.Analyzer - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(canonicalheader.Analyzer). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/containedctx/containedctx.go b/pkg/golinters/containedctx/containedctx.go index 6bdb08350dd7..6d17b8e46fcf 100644 --- a/pkg/golinters/containedctx/containedctx.go +++ b/pkg/golinters/containedctx/containedctx.go @@ -2,18 +2,12 @@ package containedctx import ( "github.com/sivchari/containedctx" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := containedctx.Analyzer - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(containedctx.Analyzer). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/contextcheck/contextcheck.go b/pkg/golinters/contextcheck/contextcheck.go index 9d01fb7a2038..88c71d2d3eb2 100644 --- a/pkg/golinters/contextcheck/contextcheck.go +++ b/pkg/golinters/contextcheck/contextcheck.go @@ -2,7 +2,6 @@ package contextcheck import ( "github.com/kkHAIKE/contextcheck" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" "github.com/golangci/golangci-lint/v2/pkg/lint/linter" @@ -11,12 +10,10 @@ import ( func New() *goanalysis.Linter { analyzer := contextcheck.NewAnalyzer(contextcheck.Configuration{}) - return goanalysis.NewLinter( - analyzer.Name, - analyzer.Doc, - []*analysis.Analyzer{analyzer}, - nil, - ).WithContextSetter(func(lintCtx *linter.Context) { - analyzer.Run = contextcheck.NewRun(lintCtx.Packages, false) - }).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(analyzer). + WithContextSetter(func(lintCtx *linter.Context) { + analyzer.Run = contextcheck.NewRun(lintCtx.Packages, false) + }). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/copyloopvar/copyloopvar.go b/pkg/golinters/copyloopvar/copyloopvar.go index f6ca96f99567..9dc81de58af2 100644 --- a/pkg/golinters/copyloopvar/copyloopvar.go +++ b/pkg/golinters/copyloopvar/copyloopvar.go @@ -2,28 +2,22 @@ package copyloopvar import ( "github.com/karamaru-alpha/copyloopvar" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.CopyLoopVarSettings) *goanalysis.Linter { - a := copyloopvar.NewAnalyzer() + var cfg map[string]any - var cfg map[string]map[string]any if settings != nil { - cfg = map[string]map[string]any{ - a.Name: { - "check-alias": settings.CheckAlias, - }, + cfg = map[string]any{ + "check-alias": settings.CheckAlias, } } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(copyloopvar.NewAnalyzer()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/cyclop/cyclop.go b/pkg/golinters/cyclop/cyclop.go index 41db272cd4e3..0a0e2dbc635b 100644 --- a/pkg/golinters/cyclop/cyclop.go +++ b/pkg/golinters/cyclop/cyclop.go @@ -2,37 +2,29 @@ package cyclop import ( "github.com/bkielbasa/cyclop/pkg/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.CyclopSettings) *goanalysis.Linter { - a := analyzer.NewAnalyzer() + cfg := map[string]any{} - var cfg map[string]map[string]any if settings != nil { - d := map[string]any{ - // Should be managed with `linters.exclusions.rules`. - "skipTests": false, - } + // Should be managed with `linters.exclusions.rules`. + cfg["skipTests"] = false if settings.MaxComplexity != 0 { - d["maxComplexity"] = settings.MaxComplexity + cfg["maxComplexity"] = settings.MaxComplexity } if settings.PackageAverage != 0 { - d["packageAverage"] = settings.PackageAverage + cfg["packageAverage"] = settings.PackageAverage } - - cfg = map[string]map[string]any{a.Name: d} } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(analyzer.NewAnalyzer()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/decorder/decorder.go b/pkg/golinters/decorder/decorder.go index 03a7853c27e2..a67bdfade155 100644 --- a/pkg/golinters/decorder/decorder.go +++ b/pkg/golinters/decorder/decorder.go @@ -4,15 +4,12 @@ import ( "strings" "gitlab.com/bosi/decorder" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.DecorderSettings) *goanalysis.Linter { - a := decorder.Analyzer - // disable all rules/checks by default cfg := map[string]any{ "ignore-underscore-vars": false, @@ -35,10 +32,8 @@ func New(settings *config.DecorderSettings) *goanalysis.Linter { cfg["disable-init-func-first-check"] = settings.DisableInitFuncFirstCheck } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - map[string]map[string]any{a.Name: cfg}, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(decorder.Analyzer). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/depguard/depguard.go b/pkg/golinters/depguard/depguard.go index c1f66b0c81cc..cc01f4f47ab5 100644 --- a/pkg/golinters/depguard/depguard.go +++ b/pkg/golinters/depguard/depguard.go @@ -4,7 +4,6 @@ import ( "strings" "github.com/OpenPeeDeeP/depguard/v2" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -41,17 +40,15 @@ func New(settings *config.DepGuardSettings, replacer *strings.Replacer) *goanaly } } - a := depguard.NewUncompiledAnalyzer(&conf) - - 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 { - lintCtx.Log.Errorf("create analyzer: %v", err) - } - }).WithLoadMode(goanalysis.LoadModeSyntax) + analyzer := depguard.NewUncompiledAnalyzer(&conf) + + return goanalysis. + NewLinterFromAnalyzer(analyzer.Analyzer). + WithContextSetter(func(lintCtx *linter.Context) { + err := analyzer.Compile() + if err != nil { + lintCtx.Log.Errorf("create analyzer: %v", err) + } + }). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/dogsled/dogsled.go b/pkg/golinters/dogsled/dogsled.go index 23d48ba57274..c5e872182cc7 100644 --- a/pkg/golinters/dogsled/dogsled.go +++ b/pkg/golinters/dogsled/dogsled.go @@ -11,24 +11,17 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) -const linterName = "dogsled" - func New(settings *config.DogsledSettings) *goanalysis.Linter { - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - return run(pass, settings.MaxBlankIdentifiers) - }, - Requires: []*analysis.Analyzer{inspect.Analyzer}, - } - - return goanalysis.NewLinter( - linterName, - "Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f())", - []*analysis.Analyzer{analyzer}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: "dogsled", + Doc: "Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f())", + Run: func(pass *analysis.Pass) (any, error) { + return run(pass, settings.MaxBlankIdentifiers) + }, + Requires: []*analysis.Analyzer{inspect.Analyzer}, + }). + WithLoadMode(goanalysis.LoadModeSyntax) } func run(pass *analysis.Pass, maxBlanks int) (any, error) { diff --git a/pkg/golinters/dupl/dupl.go b/pkg/golinters/dupl/dupl.go index 993bfd6f2326..654c795ff696 100644 --- a/pkg/golinters/dupl/dupl.go +++ b/pkg/golinters/dupl/dupl.go @@ -22,35 +22,31 @@ func New(settings *config.DuplSettings) *goanalysis.Linter { var mu sync.Mutex var resIssues []goanalysis.Issue - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - issues, err := runDupl(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. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: linterName, + Doc: "Detects duplicate fragments of code.", + Run: func(pass *analysis.Pass) (any, error) { + issues, err := runDupl(pass, settings) + if err != nil { + return nil, err + } + + if len(issues) == 0 { + return nil, nil + } + + mu.Lock() + resIssues = append(resIssues, issues...) + mu.Unlock() - return goanalysis.NewLinter( - linterName, - "Detects duplicate fragments of code.", - []*analysis.Analyzer{analyzer}, - nil, - ).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return resIssues - }).WithLoadMode(goanalysis.LoadModeSyntax) + return nil, nil + }, + }). + WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }). + WithLoadMode(goanalysis.LoadModeSyntax) } func runDupl(pass *analysis.Pass, settings *config.DuplSettings) ([]goanalysis.Issue, error) { diff --git a/pkg/golinters/dupword/dupword.go b/pkg/golinters/dupword/dupword.go index 62851475f608..7b989bc22a8f 100644 --- a/pkg/golinters/dupword/dupword.go +++ b/pkg/golinters/dupword/dupword.go @@ -4,27 +4,24 @@ import ( "strings" "github.com/Abirdcfly/dupword" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.DupWordSettings) *goanalysis.Linter { - a := dupword.NewAnalyzer() + var cfg map[string]any - cfg := map[string]map[string]any{} if settings != nil { - cfg[a.Name] = map[string]any{ + cfg = map[string]any{ "keyword": strings.Join(settings.Keywords, ","), "ignore": strings.Join(settings.Ignore, ","), } } - return goanalysis.NewLinter( - a.Name, - "checks for duplicate words in the source code", - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(dupword.NewAnalyzer()). + WithDesc("Checks for duplicate words in the source code"). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/durationcheck/durationcheck.go b/pkg/golinters/durationcheck/durationcheck.go index d3e74231f5b3..b6723fa12574 100644 --- a/pkg/golinters/durationcheck/durationcheck.go +++ b/pkg/golinters/durationcheck/durationcheck.go @@ -2,18 +2,12 @@ package durationcheck import ( "github.com/charithe/durationcheck" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := durationcheck.Analyzer - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(durationcheck.Analyzer). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/embeddedstructfieldcheck/embeddedstructfieldcheck.go b/pkg/golinters/embeddedstructfieldcheck/embeddedstructfieldcheck.go index 781bcf5d201e..0932ac4fed66 100644 --- a/pkg/golinters/embeddedstructfieldcheck/embeddedstructfieldcheck.go +++ b/pkg/golinters/embeddedstructfieldcheck/embeddedstructfieldcheck.go @@ -2,18 +2,12 @@ package embeddedstructfieldcheck import ( "github.com/manuelarte/embeddedstructfieldcheck/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := analyzer.NewAnalyzer() - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(analyzer.NewAnalyzer()). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/err113/err113.go b/pkg/golinters/err113/err113.go index 78ef99d6a1a9..d3b3a4c1cca7 100644 --- a/pkg/golinters/err113/err113.go +++ b/pkg/golinters/err113/err113.go @@ -2,18 +2,13 @@ package err113 import ( "github.com/Djarvur/go-err113" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := err113.NewAnalyzer() - - return goanalysis.NewLinter( - a.Name, - "Go linter to check the errors handling expressions", - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(err113.NewAnalyzer()). + WithDesc("Check errors handling expressions"). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/errcheck/errcheck.go b/pkg/golinters/errcheck/errcheck.go index 56d00c350b4f..c3c813d4f828 100644 --- a/pkg/golinters/errcheck/errcheck.go +++ b/pkg/golinters/errcheck/errcheck.go @@ -25,36 +25,35 @@ func New(settings *config.ErrcheckSettings) *goanalysis.Linter { analyzer := &analysis.Analyzer{ Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: goanalysis.DummyRun, + Doc: "errcheck is a program for checking for unchecked errors in Go code. " + + "These unchecked errors can be critical bugs in some cases", + Run: goanalysis.DummyRun, } - return goanalysis.NewLinter( - linterName, - "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) { - checker := getChecker(settings) - checker.Tags = lintCtx.Cfg.Run.BuildTags + return goanalysis. + NewLinterFromAnalyzer(analyzer). + WithContextSetter(func(lintCtx *linter.Context) { + checker := getChecker(settings) + checker.Tags = lintCtx.Cfg.Run.BuildTags - analyzer.Run = func(pass *analysis.Pass) (any, error) { - issues := runErrCheck(lintCtx, pass, checker) + analyzer.Run = func(pass *analysis.Pass) (any, error) { + issues := runErrCheck(lintCtx, pass, checker) - if len(issues) == 0 { - return nil, nil - } + if len(issues) == 0 { + return nil, nil + } - mu.Lock() - resIssues = append(resIssues, issues...) - mu.Unlock() + mu.Lock() + resIssues = append(resIssues, issues...) + mu.Unlock() - return nil, nil - } - }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return resIssues - }).WithLoadMode(goanalysis.LoadModeTypesInfo) + return nil, nil + } + }). + WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }). + WithLoadMode(goanalysis.LoadModeTypesInfo) } func runErrCheck(lintCtx *linter.Context, pass *analysis.Pass, checker *errcheck.Checker) []goanalysis.Issue { diff --git a/pkg/golinters/errchkjson/errchkjson.go b/pkg/golinters/errchkjson/errchkjson.go index a705406e49f5..02510ab49901 100644 --- a/pkg/golinters/errchkjson/errchkjson.go +++ b/pkg/golinters/errchkjson/errchkjson.go @@ -2,30 +2,25 @@ package errchkjson import ( "github.com/breml/errchkjson" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.ErrChkJSONSettings) *goanalysis.Linter { - a := errchkjson.NewAnalyzer() - - cfg := map[string]map[string]any{} - cfg[a.Name] = map[string]any{ + cfg := map[string]any{ "omit-safe": true, } + if settings != nil { - cfg[a.Name] = map[string]any{ + cfg = map[string]any{ "omit-safe": !settings.CheckErrorFreeEncoding, "report-no-exported": settings.ReportNoExported, } } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(errchkjson.NewAnalyzer()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/errname/errname.go b/pkg/golinters/errname/errname.go index 36d6f12356fd..a66f3211f4e9 100644 --- a/pkg/golinters/errname/errname.go +++ b/pkg/golinters/errname/errname.go @@ -2,18 +2,12 @@ package errname import ( "github.com/Antonboom/errname/pkg/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := analyzer.New() - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(analyzer.New()). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/errorlint/errorlint.go b/pkg/golinters/errorlint/errorlint.go index 7560bc0af90b..f32217796920 100644 --- a/pkg/golinters/errorlint/errorlint.go +++ b/pkg/golinters/errorlint/errorlint.go @@ -2,7 +2,6 @@ package errorlint import ( "github.com/polyfloyd/go-errorlint/errorlint" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -23,12 +22,10 @@ func New(settings *config.ErrorLintSettings) *goanalysis.Linter { } } - a := errorlint.NewAnalyzer(opts...) - - cfg := map[string]map[string]any{} + var cfg map[string]any if settings != nil { - cfg[a.Name] = map[string]any{ + cfg = map[string]any{ "errorf": settings.Errorf, "errorf-multi": settings.ErrorfMulti, "asserts": settings.Asserts, @@ -36,13 +33,11 @@ func New(settings *config.ErrorLintSettings) *goanalysis.Linter { } } - return goanalysis.NewLinter( - a.Name, - "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.", - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(errorlint.NewAnalyzer(opts...)). + WithDesc("Find code that can cause problems with the error wrapping scheme introduced in Go 1.13."). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeTypesInfo) } func toAllowPairs(data []config.ErrorLintAllowPair) []errorlint.AllowPair { diff --git a/pkg/golinters/exhaustive/exhaustive.go b/pkg/golinters/exhaustive/exhaustive.go index be77e54a4bc6..ec240739d69e 100644 --- a/pkg/golinters/exhaustive/exhaustive.go +++ b/pkg/golinters/exhaustive/exhaustive.go @@ -2,37 +2,31 @@ package exhaustive import ( "github.com/nishanths/exhaustive" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.ExhaustiveSettings) *goanalysis.Linter { - a := exhaustive.Analyzer + var cfg map[string]any - var cfg map[string]map[string]any if settings != nil { - cfg = map[string]map[string]any{ - a.Name: { - exhaustive.CheckFlag: settings.Check, - exhaustive.DefaultSignifiesExhaustiveFlag: settings.DefaultSignifiesExhaustive, - exhaustive.IgnoreEnumMembersFlag: settings.IgnoreEnumMembers, - exhaustive.IgnoreEnumTypesFlag: settings.IgnoreEnumTypes, - exhaustive.PackageScopeOnlyFlag: settings.PackageScopeOnly, - exhaustive.ExplicitExhaustiveMapFlag: settings.ExplicitExhaustiveMap, - exhaustive.ExplicitExhaustiveSwitchFlag: settings.ExplicitExhaustiveSwitch, - exhaustive.DefaultCaseRequiredFlag: settings.DefaultCaseRequired, - // Should be managed with `linters.exclusions.generated`. - exhaustive.CheckGeneratedFlag: true, - }, + cfg = map[string]any{ + exhaustive.CheckFlag: settings.Check, + exhaustive.DefaultSignifiesExhaustiveFlag: settings.DefaultSignifiesExhaustive, + exhaustive.IgnoreEnumMembersFlag: settings.IgnoreEnumMembers, + exhaustive.IgnoreEnumTypesFlag: settings.IgnoreEnumTypes, + exhaustive.PackageScopeOnlyFlag: settings.PackageScopeOnly, + exhaustive.ExplicitExhaustiveMapFlag: settings.ExplicitExhaustiveMap, + exhaustive.ExplicitExhaustiveSwitchFlag: settings.ExplicitExhaustiveSwitch, + exhaustive.DefaultCaseRequiredFlag: settings.DefaultCaseRequired, + // Should be managed with `linters.exclusions.generated`. + exhaustive.CheckGeneratedFlag: true, } } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(exhaustive.Analyzer). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/exhaustruct/exhaustruct.go b/pkg/golinters/exhaustruct/exhaustruct.go index 9b742129969d..290878e1c404 100644 --- a/pkg/golinters/exhaustruct/exhaustruct.go +++ b/pkg/golinters/exhaustruct/exhaustruct.go @@ -1,8 +1,7 @@ package exhaustruct import ( - "github.com/GaijinEntertainment/go-exhaustruct/v3/analyzer" - "golang.org/x/tools/go/analysis" + exhaustruct "github.com/GaijinEntertainment/go-exhaustruct/v3/analyzer" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -11,20 +10,18 @@ import ( func New(settings *config.ExhaustructSettings) *goanalysis.Linter { var include, exclude []string + if settings != nil { include = settings.Include exclude = settings.Exclude } - a, err := analyzer.NewAnalyzer(include, exclude) + analyzer, err := exhaustruct.NewAnalyzer(include, exclude) if err != nil { internal.LinterLogger.Fatalf("exhaustruct configuration: %v", err) } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(analyzer). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/exptostd/exptostd.go b/pkg/golinters/exptostd/exptostd.go index 731a4a0ccad7..dbd78dce91cb 100644 --- a/pkg/golinters/exptostd/exptostd.go +++ b/pkg/golinters/exptostd/exptostd.go @@ -2,18 +2,12 @@ package exptostd import ( "github.com/ldez/exptostd" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := exptostd.NewAnalyzer() - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(exptostd.NewAnalyzer()). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/fatcontext/fatcontext.go b/pkg/golinters/fatcontext/fatcontext.go index e0506259bee9..58933c660588 100644 --- a/pkg/golinters/fatcontext/fatcontext.go +++ b/pkg/golinters/fatcontext/fatcontext.go @@ -2,27 +2,22 @@ package fatcontext import ( "go.augendre.info/fatcontext/pkg/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.FatcontextSettings) *goanalysis.Linter { - a := analyzer.NewAnalyzer() - - cfg := map[string]map[string]any{} + var cfg map[string]any if settings != nil { - cfg[a.Name] = map[string]any{ + cfg = map[string]any{ analyzer.FlagCheckStructPointers: settings.CheckStructPointers, } } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(analyzer.NewAnalyzer()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/forbidigo/forbidigo.go b/pkg/golinters/forbidigo/forbidigo.go index f7c5efd3d8f1..796faf3a6ef0 100644 --- a/pkg/golinters/forbidigo/forbidigo.go +++ b/pkg/golinters/forbidigo/forbidigo.go @@ -15,28 +15,23 @@ import ( const linterName = "forbidigo" func New(settings *config.ForbidigoSettings) *goanalysis.Linter { - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - err := runForbidigo(pass, settings) - if err != nil { - return nil, err - } - - return nil, nil - }, - } - // 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( - linterName, - "Forbids identifiers", - []*analysis.Analyzer{analyzer}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + // therefore, we have to use LoadModeTypesInfo in all cases. + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: linterName, + Doc: "Forbids identifiers", + Run: func(pass *analysis.Pass) (any, error) { + err := runForbidigo(pass, settings) + if err != nil { + return nil, err + } + + return nil, nil + }, + }). + WithLoadMode(goanalysis.LoadModeTypesInfo) } func runForbidigo(pass *analysis.Pass, settings *config.ForbidigoSettings) error { diff --git a/pkg/golinters/forcetypeassert/forcetypeassert.go b/pkg/golinters/forcetypeassert/forcetypeassert.go index e82355380c25..19a0e3450b37 100644 --- a/pkg/golinters/forcetypeassert/forcetypeassert.go +++ b/pkg/golinters/forcetypeassert/forcetypeassert.go @@ -2,18 +2,13 @@ package forcetypeassert import ( "github.com/gostaticanalysis/forcetypeassert" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := forcetypeassert.Analyzer - - return goanalysis.NewLinter( - a.Name, - "finds forced type assertions", - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(forcetypeassert.Analyzer). + WithDesc("Find forced type assertions"). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/funcorder/funcorder.go b/pkg/golinters/funcorder/funcorder.go index 605304f26203..06400753ebdb 100644 --- a/pkg/golinters/funcorder/funcorder.go +++ b/pkg/golinters/funcorder/funcorder.go @@ -2,29 +2,24 @@ package funcorder import ( "github.com/manuelarte/funcorder/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.FuncOrderSettings) *goanalysis.Linter { - a := analyzer.NewAnalyzer() - - cfg := map[string]map[string]any{} + var cfg map[string]any if settings != nil { - cfg[a.Name] = map[string]any{ + cfg = map[string]any{ analyzer.ConstructorCheckName: settings.Constructor, analyzer.StructMethodCheckName: settings.StructMethod, analyzer.AlphabeticalCheckName: settings.Alphabetical, } } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(analyzer.NewAnalyzer()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/funlen/funlen.go b/pkg/golinters/funlen/funlen.go index 541d4fd36041..6e0f93b51303 100644 --- a/pkg/golinters/funlen/funlen.go +++ b/pkg/golinters/funlen/funlen.go @@ -2,7 +2,6 @@ package funlen import ( "github.com/ultraware/funlen" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -22,12 +21,7 @@ func New(settings *config.FunlenSettings) *goanalysis.Linter { cfg.ignoreComments = settings.IgnoreComments } - a := funlen.NewAnalyzer(cfg.lineLimit, cfg.stmtLimit, cfg.ignoreComments) - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(funlen.NewAnalyzer(cfg.lineLimit, cfg.stmtLimit, cfg.ignoreComments)). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/gci/gci.go b/pkg/golinters/gci/gci.go index 627a4e6849f2..4357a3b15fc1 100644 --- a/pkg/golinters/gci/gci.go +++ b/pkg/golinters/gci/gci.go @@ -1,8 +1,6 @@ package gci import ( - "golang.org/x/tools/go/analysis" - "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" "github.com/golangci/golangci-lint/v2/pkg/goformatters" @@ -18,16 +16,13 @@ func New(settings *config.GciSettings) *goanalysis.Linter { internal.LinterLogger.Fatalf("%s: create analyzer: %v", linterName, err) } - a := goformatters.NewAnalyzer( - internal.LinterLogger.Child(linterName), - "Checks if code and import statements are formatted, with additional rules.", - formatter, - ) - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer( + goformatters.NewAnalyzer( + internal.LinterLogger.Child(linterName), + "Check if code and import statements are formatted, with additional rules.", + formatter, + ), + ). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/ginkgolinter/ginkgolinter.go b/pkg/golinters/ginkgolinter/ginkgolinter.go index f4521cdaf81f..519e968e5d8b 100644 --- a/pkg/golinters/ginkgolinter/ginkgolinter.go +++ b/pkg/golinters/ginkgolinter/ginkgolinter.go @@ -3,7 +3,6 @@ package ginkgolinter import ( "github.com/nunnatsa/ginkgolinter" "github.com/nunnatsa/ginkgolinter/types" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -29,12 +28,8 @@ func New(settings *config.GinkgoLinterSettings) *goanalysis.Linter { } } - a := ginkgolinter.NewAnalyzerWithConfig(cfg) - - return goanalysis.NewLinter( - a.Name, - "enforces standards of using ginkgo and gomega", - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(ginkgolinter.NewAnalyzerWithConfig(cfg)). + WithDesc("enforces standards of using ginkgo and gomega"). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/gocheckcompilerdirectives/gocheckcompilerdirectives.go b/pkg/golinters/gocheckcompilerdirectives/gocheckcompilerdirectives.go index 97534848d802..71f4be8c41db 100644 --- a/pkg/golinters/gocheckcompilerdirectives/gocheckcompilerdirectives.go +++ b/pkg/golinters/gocheckcompilerdirectives/gocheckcompilerdirectives.go @@ -2,18 +2,12 @@ package gocheckcompilerdirectives import ( "4d63.com/gocheckcompilerdirectives/checkcompilerdirectives" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := checkcompilerdirectives.Analyzer() - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(checkcompilerdirectives.Analyzer()). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/gochecknoglobals/gochecknoglobals.go b/pkg/golinters/gochecknoglobals/gochecknoglobals.go index 8d850a2de59f..2fd3f3c3bee1 100644 --- a/pkg/golinters/gochecknoglobals/gochecknoglobals.go +++ b/pkg/golinters/gochecknoglobals/gochecknoglobals.go @@ -2,18 +2,13 @@ package gochecknoglobals import ( "4d63.com/gochecknoglobals/checknoglobals" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := checknoglobals.Analyzer() - - return goanalysis.NewLinter( - a.Name, - "Check that no global variables exist.", - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(checknoglobals.Analyzer()). + WithDesc("Check that no global variables exist."). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/gochecknoinits/gochecknoinits.go b/pkg/golinters/gochecknoinits/gochecknoinits.go index b5fa6f0d4117..c027aa8ab928 100644 --- a/pkg/golinters/gochecknoinits/gochecknoinits.go +++ b/pkg/golinters/gochecknoinits/gochecknoinits.go @@ -11,22 +11,15 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/golinters/internal" ) -const linterName = "gochecknoinits" - func New() *goanalysis.Linter { - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: run, - Requires: []*analysis.Analyzer{inspect.Analyzer}, - } - - return goanalysis.NewLinter( - linterName, - "Checks that no init functions are present in Go code", - []*analysis.Analyzer{analyzer}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: "gochecknoinits", + Doc: "Checks that no init functions are present in Go code", + Run: run, + Requires: []*analysis.Analyzer{inspect.Analyzer}, + }). + WithLoadMode(goanalysis.LoadModeSyntax) } func run(pass *analysis.Pass) (any, error) { diff --git a/pkg/golinters/gochecksumtype/gochecksumtype.go b/pkg/golinters/gochecksumtype/gochecksumtype.go index 78cbd574d20b..85be045dfa8a 100644 --- a/pkg/golinters/gochecksumtype/gochecksumtype.go +++ b/pkg/golinters/gochecksumtype/gochecksumtype.go @@ -20,35 +20,31 @@ func New(settings *config.GoChecksumTypeSettings) *goanalysis.Linter { var mu sync.Mutex var resIssues []goanalysis.Issue - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - issues, err := runGoCheckSumType(pass, settings) - if err != nil { - return nil, err - } + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: linterName, + Doc: `Run exhaustiveness checks on Go "sum types"`, + Run: func(pass *analysis.Pass) (any, error) { + issues, err := runGoCheckSumType(pass, settings) + if err != nil { + return nil, err + } + + if len(issues) == 0 { + return nil, nil + } + + mu.Lock() + resIssues = append(resIssues, issues...) + mu.Unlock() - if len(issues) == 0 { return nil, nil - } - - mu.Lock() - resIssues = append(resIssues, issues...) - mu.Unlock() - - return nil, nil - }, - } - - return goanalysis.NewLinter( - linterName, - `Run exhaustiveness checks on Go "sum types"`, - []*analysis.Analyzer{analyzer}, - nil, - ).WithIssuesReporter(func(_ *linter.Context) []goanalysis.Issue { - return resIssues - }).WithLoadMode(goanalysis.LoadModeTypesInfo) + }, + }). + WithIssuesReporter(func(_ *linter.Context) []goanalysis.Issue { + return resIssues + }). + WithLoadMode(goanalysis.LoadModeTypesInfo) } func runGoCheckSumType(pass *analysis.Pass, settings *config.GoChecksumTypeSettings) ([]goanalysis.Issue, error) { diff --git a/pkg/golinters/gocognit/gocognit.go b/pkg/golinters/gocognit/gocognit.go index 689a70a12383..e60bcfb17080 100644 --- a/pkg/golinters/gocognit/gocognit.go +++ b/pkg/golinters/gocognit/gocognit.go @@ -21,32 +21,28 @@ func New(settings *config.GocognitSettings) *goanalysis.Linter { var mu sync.Mutex var resIssues []goanalysis.Issue - analyzer := &analysis.Analyzer{ - Name: goanalysis.TheOnlyAnalyzerName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - issues := runGocognit(pass, settings) + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: linterName, + Doc: "Computes and checks the cognitive complexity of functions", + Run: func(pass *analysis.Pass) (any, error) { + issues := runGocognit(pass, settings) - if len(issues) == 0 { - return nil, nil - } - - mu.Lock() - resIssues = append(resIssues, issues...) - mu.Unlock() + if len(issues) == 0 { + return nil, nil + } - return nil, nil - }, - } + mu.Lock() + resIssues = append(resIssues, issues...) + mu.Unlock() - return goanalysis.NewLinter( - linterName, - "Computes and checks the cognitive complexity of functions", - []*analysis.Analyzer{analyzer}, - nil, - ).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return resIssues - }).WithLoadMode(goanalysis.LoadModeSyntax) + return nil, nil + }, + }). + WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }). + WithLoadMode(goanalysis.LoadModeSyntax) } func runGocognit(pass *analysis.Pass, settings *config.GocognitSettings) []goanalysis.Issue { diff --git a/pkg/golinters/goconst/goconst.go b/pkg/golinters/goconst/goconst.go index f3af64625243..f32a4c6575e2 100644 --- a/pkg/golinters/goconst/goconst.go +++ b/pkg/golinters/goconst/goconst.go @@ -20,35 +20,31 @@ func New(settings *config.GoConstSettings) *goanalysis.Linter { var mu sync.Mutex var resIssues []goanalysis.Issue - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - issues, err := runGoconst(pass, settings) - if err != nil { - return nil, err - } + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: linterName, + Doc: "Finds repeated strings that could be replaced by a constant", + Run: func(pass *analysis.Pass) (any, error) { + issues, err := runGoconst(pass, settings) + if err != nil { + return nil, err + } + + if len(issues) == 0 { + return nil, nil + } + + mu.Lock() + resIssues = append(resIssues, issues...) + mu.Unlock() - if len(issues) == 0 { return nil, nil - } - - mu.Lock() - resIssues = append(resIssues, issues...) - mu.Unlock() - - return nil, nil - }, - } - - return goanalysis.NewLinter( - linterName, - "Finds repeated strings that could be replaced by a constant", - []*analysis.Analyzer{analyzer}, - nil, - ).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return resIssues - }).WithLoadMode(goanalysis.LoadModeTypesInfo) + }, + }). + WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }). + WithLoadMode(goanalysis.LoadModeTypesInfo) } func runGoconst(pass *analysis.Pass, settings *config.GoConstSettings) ([]goanalysis.Issue, error) { diff --git a/pkg/golinters/gocritic/gocritic.go b/pkg/golinters/gocritic/gocritic.go index 486303dab0c6..cd7337590cfd 100644 --- a/pkg/golinters/gocritic/gocritic.go +++ b/pkg/golinters/gocritic/gocritic.go @@ -33,27 +33,21 @@ func New(settings *config.GoCriticSettings, replacer *strings.Replacer) *goanaly sizes: types.SizesFor("gc", runtime.GOARCH), } - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - err := wrapper.run(pass) - if err != nil { - return nil, err - } - - return nil, nil - }, - } - - return goanalysis.NewLinter( - linterName, - `Provides diagnostics that check for bugs, performance and style issues. + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: linterName, + Doc: `Provides diagnostics that check for bugs, performance and style issues. Extensible without recompilation through dynamic rules. Dynamic rules are written declaratively with AST patterns, filters, report message and optional suggestion.`, - []*analysis.Analyzer{analyzer}, - nil, - ). + Run: func(pass *analysis.Pass) (any, error) { + err := wrapper.run(pass) + if err != nil { + return nil, err + } + + return nil, nil + }, + }). WithContextSetter(func(context *linter.Context) { wrapper.init(context.Log, settings, replacer) }). diff --git a/pkg/golinters/gocyclo/gocyclo.go b/pkg/golinters/gocyclo/gocyclo.go index 05691695d2aa..514194709385 100644 --- a/pkg/golinters/gocyclo/gocyclo.go +++ b/pkg/golinters/gocyclo/gocyclo.go @@ -20,32 +20,28 @@ func New(settings *config.GoCycloSettings) *goanalysis.Linter { var mu sync.Mutex var resIssues []goanalysis.Issue - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - issues := runGoCyclo(pass, settings) + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: linterName, + Doc: "Computes and checks the cyclomatic complexity of functions", + Run: func(pass *analysis.Pass) (any, error) { + issues := runGoCyclo(pass, settings) - if len(issues) == 0 { - return nil, nil - } - - mu.Lock() - resIssues = append(resIssues, issues...) - mu.Unlock() + if len(issues) == 0 { + return nil, nil + } - return nil, nil - }, - } + mu.Lock() + resIssues = append(resIssues, issues...) + mu.Unlock() - return goanalysis.NewLinter( - linterName, - "Computes and checks the cyclomatic complexity of functions", - []*analysis.Analyzer{analyzer}, - nil, - ).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return resIssues - }).WithLoadMode(goanalysis.LoadModeSyntax) + return nil, nil + }, + }). + WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }). + WithLoadMode(goanalysis.LoadModeSyntax) } func runGoCyclo(pass *analysis.Pass, settings *config.GoCycloSettings) []goanalysis.Issue { diff --git a/pkg/golinters/godot/godot.go b/pkg/golinters/godot/godot.go index 04e86211de33..e83495128e4c 100644 --- a/pkg/golinters/godot/godot.go +++ b/pkg/golinters/godot/godot.go @@ -10,8 +10,6 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) -const linterName = "godot" - func New(settings *config.GodotSettings) *goanalysis.Linter { var dotSettings godot.Settings @@ -26,25 +24,20 @@ func New(settings *config.GodotSettings) *goanalysis.Linter { dotSettings.Scope = cmp.Or(dotSettings.Scope, godot.DeclScope) - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - err := runGodot(pass, dotSettings) - if err != nil { - return nil, err - } - - return nil, nil - }, - } - - return goanalysis.NewLinter( - linterName, - "Check if comments end in a period", - []*analysis.Analyzer{analyzer}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: "godot", + Doc: "Check if comments end in a period", + Run: func(pass *analysis.Pass) (any, error) { + err := runGodot(pass, dotSettings) + if err != nil { + return nil, err + } + + return nil, nil + }, + }). + WithLoadMode(goanalysis.LoadModeSyntax) } func runGodot(pass *analysis.Pass, settings godot.Settings) error { diff --git a/pkg/golinters/godox/godox.go b/pkg/golinters/godox/godox.go index e734c691b3da..8ab144e754a1 100644 --- a/pkg/golinters/godox/godox.go +++ b/pkg/golinters/godox/godox.go @@ -11,23 +11,16 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) -const linterName = "godox" - func New(settings *config.GodoxSettings) *goanalysis.Linter { - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - return run(pass, settings), nil - }, - } - - return goanalysis.NewLinter( - linterName, - "Detects usage of FIXME, TODO and other keywords inside comments", - []*analysis.Analyzer{analyzer}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: "godox", + Doc: "Detects usage of FIXME, TODO and other keywords inside comments", + Run: func(pass *analysis.Pass) (any, error) { + return run(pass, settings), nil + }, + }). + WithLoadMode(goanalysis.LoadModeSyntax) } func run(pass *analysis.Pass, settings *config.GodoxSettings) error { diff --git a/pkg/golinters/gofmt/gofmt.go b/pkg/golinters/gofmt/gofmt.go index 63b690018ecd..04de51efc0f1 100644 --- a/pkg/golinters/gofmt/gofmt.go +++ b/pkg/golinters/gofmt/gofmt.go @@ -1,8 +1,6 @@ package gofmt import ( - "golang.org/x/tools/go/analysis" - "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" "github.com/golangci/golangci-lint/v2/pkg/goformatters" @@ -10,19 +8,14 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/golinters/internal" ) -const linterName = "gofmt" - func New(settings *config.GoFmtSettings) *goanalysis.Linter { - a := goformatters.NewAnalyzer( - internal.LinterLogger.Child(linterName), - "Checks if the code is formatted according to 'gofmt' command.", - gofmtbase.New(settings), - ) - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer( + goformatters.NewAnalyzer( + internal.LinterLogger.Child(gofmtbase.Name), + "Check if the code is formatted according to 'gofmt' command.", + gofmtbase.New(settings), + ), + ). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/gofumpt/gofumpt.go b/pkg/golinters/gofumpt/gofumpt.go index d799be7a39fd..1ee7c833a321 100644 --- a/pkg/golinters/gofumpt/gofumpt.go +++ b/pkg/golinters/gofumpt/gofumpt.go @@ -1,8 +1,6 @@ package gofumpt import ( - "golang.org/x/tools/go/analysis" - "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" "github.com/golangci/golangci-lint/v2/pkg/goformatters" @@ -10,19 +8,14 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/golinters/internal" ) -const linterName = "gofumpt" - func New(settings *config.GoFumptSettings) *goanalysis.Linter { - a := goformatters.NewAnalyzer( - internal.LinterLogger.Child(linterName), - "Checks if code and import statements are formatted, with additional rules.", - gofumptbase.New(settings, settings.LangVersion), - ) - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer( + goformatters.NewAnalyzer( + internal.LinterLogger.Child(gofumptbase.Name), + "Check if code and import statements are formatted, with additional rules.", + gofumptbase.New(settings, settings.LangVersion), + ), + ). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/goheader/goheader.go b/pkg/golinters/goheader/goheader.go index e03d3277d2c7..0634dbd4288f 100644 --- a/pkg/golinters/goheader/goheader.go +++ b/pkg/golinters/goheader/goheader.go @@ -23,25 +23,20 @@ func New(settings *config.GoHeaderSettings, replacer *strings.Replacer) *goanaly } } - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - err := runGoHeader(pass, conf) - if err != nil { - return nil, err - } - - return nil, nil - }, - } - - return goanalysis.NewLinter( - linterName, - "Checks if file header matches to pattern", - []*analysis.Analyzer{analyzer}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: linterName, + Doc: "Check if file header matches to pattern", + Run: func(pass *analysis.Pass) (any, error) { + err := runGoHeader(pass, conf) + if err != nil { + return nil, err + } + + return nil, nil + }, + }). + WithLoadMode(goanalysis.LoadModeSyntax) } func runGoHeader(pass *analysis.Pass, conf *goheader.Configuration) error { diff --git a/pkg/golinters/goimports/goimports.go b/pkg/golinters/goimports/goimports.go index 3aa8cde56a94..b3b9b5800b8d 100644 --- a/pkg/golinters/goimports/goimports.go +++ b/pkg/golinters/goimports/goimports.go @@ -1,8 +1,6 @@ package goimports import ( - "golang.org/x/tools/go/analysis" - "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" "github.com/golangci/golangci-lint/v2/pkg/goformatters" @@ -10,19 +8,14 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/golinters/internal" ) -const linterName = "goimports" - func New(settings *config.GoImportsSettings) *goanalysis.Linter { - a := goformatters.NewAnalyzer( - internal.LinterLogger.Child(linterName), - "Checks if the code and import statements are formatted according to the 'goimports' command.", - goimportsbase.New(settings), - ) - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer( + goformatters.NewAnalyzer( + internal.LinterLogger.Child(goimportsbase.Name), + "Checks if the code and import statements are formatted according to the 'goimports' command.", + goimportsbase.New(settings), + ), + ). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/golines/golines.go b/pkg/golinters/golines/golines.go index 0b3acc53bb40..0a32971dee1d 100644 --- a/pkg/golinters/golines/golines.go +++ b/pkg/golinters/golines/golines.go @@ -1,8 +1,6 @@ package golines import ( - "golang.org/x/tools/go/analysis" - "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" "github.com/golangci/golangci-lint/v2/pkg/goformatters" @@ -10,19 +8,14 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/golinters/internal" ) -const linterName = "golines" - func New(settings *config.GoLinesSettings) *goanalysis.Linter { - a := goformatters.NewAnalyzer( - internal.LinterLogger.Child(linterName), - "Checks if code is formatted, and fixes long lines", - golinesbase.New(settings), - ) - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer( + goformatters.NewAnalyzer( + internal.LinterLogger.Child(golinesbase.Name), + "Checks if code is formatted, and fixes long lines", + golinesbase.New(settings), + ), + ). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/gomoddirectives/gomoddirectives.go b/pkg/golinters/gomoddirectives/gomoddirectives.go index 86f94e2560ea..e11313a62b9c 100644 --- a/pkg/golinters/gomoddirectives/gomoddirectives.go +++ b/pkg/golinters/gomoddirectives/gomoddirectives.go @@ -50,38 +50,37 @@ func New(settings *config.GoModDirectivesSettings) *goanalysis.Linter { } analyzer := &analysis.Analyzer{ - Name: goanalysis.TheOnlyAnalyzerName, - Doc: goanalysis.TheOnlyanalyzerDoc, + Name: linterName, + Doc: "Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod.", Run: goanalysis.DummyRun, } - return goanalysis.NewLinter( - linterName, - "Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod.", - []*analysis.Analyzer{analyzer}, - nil, - ).WithContextSetter(func(lintCtx *linter.Context) { - analyzer.Run = func(pass *analysis.Pass) (any, error) { - once.Do(func() { - results, err := gomoddirectives.AnalyzePass(pass, opts) - if err != nil { - lintCtx.Log.Warnf("running %s failed: %s: "+ - "if you are not using go modules it is suggested to disable this linter", linterName, err) - return - } + return goanalysis. + NewLinterFromAnalyzer(analyzer). + WithContextSetter(func(lintCtx *linter.Context) { + analyzer.Run = func(pass *analysis.Pass) (any, error) { + once.Do(func() { + results, err := gomoddirectives.AnalyzePass(pass, opts) + if err != nil { + lintCtx.Log.Warnf("running %s failed: %s: "+ + "if you are not using go modules it is suggested to disable this linter", linterName, err) + return + } - for _, p := range results { - issues = append(issues, goanalysis.NewIssue(&result.Issue{ - FromLinter: linterName, - Pos: p.Start, - Text: p.Reason, - }, pass)) - } - }) + for _, p := range results { + issues = append(issues, goanalysis.NewIssue(&result.Issue{ + FromLinter: linterName, + Pos: p.Start, + Text: p.Reason, + }, pass)) + } + }) - return nil, nil - } - }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return issues - }).WithLoadMode(goanalysis.LoadModeSyntax) + return nil, nil + } + }). + WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return issues + }). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/gomodguard/gomodguard.go b/pkg/golinters/gomodguard/gomodguard.go index e38a6c9b90e4..502610341342 100644 --- a/pkg/golinters/gomodguard/gomodguard.go +++ b/pkg/golinters/gomodguard/gomodguard.go @@ -13,12 +13,7 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/result" ) -const ( - 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." -) +const linterName = "gomodguard" func New(settings *config.GoModGuardSettings) *goanalysis.Linter { var issues []goanalysis.Issue @@ -54,41 +49,41 @@ func New(settings *config.GoModGuardSettings) *goanalysis.Linter { } analyzer := &analysis.Analyzer{ - Name: goanalysis.TheOnlyAnalyzerName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: goanalysis.DummyRun, + Name: linterName, + Doc: "Allow and blocklist linter for direct Go module dependencies. " + + "This is different from depguard where there are different block " + + "types for example version constraints and module recommendations.", + Run: goanalysis.DummyRun, } - return goanalysis.NewLinter( - name, - desc, - []*analysis.Analyzer{analyzer}, - nil, - ).WithContextSetter(func(lintCtx *linter.Context) { - processor, err := gomodguard.NewProcessor(processorCfg) - if err != nil { - lintCtx.Log.Warnf("running gomodguard failed: %s: if you are not using go modules "+ - "it is suggested to disable this linter", err) - return - } + return goanalysis.NewLinterFromAnalyzer(analyzer). + WithContextSetter(func(lintCtx *linter.Context) { + processor, err := gomodguard.NewProcessor(processorCfg) + if err != nil { + lintCtx.Log.Warnf("running gomodguard failed: %s: if you are not using go modules "+ + "it is suggested to disable this linter", err) + return + } - analyzer.Run = func(pass *analysis.Pass) (any, error) { - gomodguardIssues := processor.ProcessFiles(internal.GetGoFileNames(pass)) + analyzer.Run = func(pass *analysis.Pass) (any, error) { + gomodguardIssues := processor.ProcessFiles(internal.GetGoFileNames(pass)) - mu.Lock() - defer mu.Unlock() + mu.Lock() + defer mu.Unlock() - for _, gomodguardIssue := range gomodguardIssues { - issues = append(issues, goanalysis.NewIssue(&result.Issue{ - FromLinter: name, - Pos: gomodguardIssue.Position, - Text: gomodguardIssue.Reason, - }, pass)) - } + for _, gomodguardIssue := range gomodguardIssues { + issues = append(issues, goanalysis.NewIssue(&result.Issue{ + FromLinter: linterName, + Pos: gomodguardIssue.Position, + Text: gomodguardIssue.Reason, + }, pass)) + } - return nil, nil - } - }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return issues - }).WithLoadMode(goanalysis.LoadModeSyntax) + return nil, nil + } + }). + WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return issues + }). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/goprintffuncname/goprintffuncname.go b/pkg/golinters/goprintffuncname/goprintffuncname.go index b1436347806c..a56dce8e05df 100644 --- a/pkg/golinters/goprintffuncname/goprintffuncname.go +++ b/pkg/golinters/goprintffuncname/goprintffuncname.go @@ -2,18 +2,12 @@ package goprintffuncname import ( "github.com/golangci/go-printf-func-name/pkg/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := analyzer.Analyzer - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(analyzer.Analyzer). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/gosec/gosec.go b/pkg/golinters/gosec/gosec.go index 95b445e87038..e38de1ee20e5 100644 --- a/pkg/golinters/gosec/gosec.go +++ b/pkg/golinters/gosec/gosec.go @@ -50,34 +50,33 @@ func New(settings *config.GoSecSettings) *goanalysis.Linter { analyzer := &analysis.Analyzer{ Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, + Doc: "Inspects source code for security problems", Run: goanalysis.DummyRun, } - return goanalysis.NewLinter( - linterName, - "Inspects source code for security problems", - []*analysis.Analyzer{analyzer}, - nil, - ).WithContextSetter(func(lintCtx *linter.Context) { - analyzer.Run = func(pass *analysis.Pass) (any, error) { - // The `gosecAnalyzer` is here because of concurrency issue. - gosecAnalyzer := gosec.NewAnalyzer(conf, true, false, false, settings.Concurrency, logger) + return goanalysis. + NewLinterFromAnalyzer(analyzer). + WithContextSetter(func(lintCtx *linter.Context) { + analyzer.Run = func(pass *analysis.Pass) (any, error) { + // The `gosecAnalyzer` is here because of concurrency issue. + gosecAnalyzer := gosec.NewAnalyzer(conf, true, false, false, settings.Concurrency, logger) - gosecAnalyzer.LoadRules(ruleDefinitions.RulesInfo()) - gosecAnalyzer.LoadAnalyzers(analyzerDefinitions.AnalyzersInfo()) + gosecAnalyzer.LoadRules(ruleDefinitions.RulesInfo()) + gosecAnalyzer.LoadAnalyzers(analyzerDefinitions.AnalyzersInfo()) - issues := runGoSec(lintCtx, pass, settings, gosecAnalyzer) + issues := runGoSec(lintCtx, pass, settings, gosecAnalyzer) - mu.Lock() - resIssues = append(resIssues, issues...) - mu.Unlock() + mu.Lock() + resIssues = append(resIssues, issues...) + mu.Unlock() - return nil, nil - } - }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return resIssues - }).WithLoadMode(goanalysis.LoadModeTypesInfo) + return nil, nil + } + }). + WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }). + WithLoadMode(goanalysis.LoadModeTypesInfo) } func runGoSec(lintCtx *linter.Context, pass *analysis.Pass, settings *config.GoSecSettings, analyzer *gosec.Analyzer) []goanalysis.Issue { diff --git a/pkg/golinters/gosmopolitan/gosmopolitan.go b/pkg/golinters/gosmopolitan/gosmopolitan.go index 6c574403f694..76261abe1450 100644 --- a/pkg/golinters/gosmopolitan/gosmopolitan.go +++ b/pkg/golinters/gosmopolitan/gosmopolitan.go @@ -4,18 +4,16 @@ import ( "strings" "github.com/xen0n/gosmopolitan" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.GosmopolitanSettings) *goanalysis.Linter { - a := gosmopolitan.NewAnalyzer() + var cfg map[string]any - cfg := map[string]map[string]any{} if settings != nil { - cfg[a.Name] = map[string]any{ + cfg = map[string]any{ "allowtimelocal": settings.AllowTimeLocal, "escapehatches": strings.Join(settings.EscapeHatches, ","), "watchforscripts": strings.Join(settings.WatchForScripts, ","), @@ -25,10 +23,8 @@ func New(settings *config.GosmopolitanSettings) *goanalysis.Linter { } } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(gosmopolitan.NewAnalyzer()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/grouper/grouper.go b/pkg/golinters/grouper/grouper.go index 853e2d3e7f70..ed3601617d9a 100644 --- a/pkg/golinters/grouper/grouper.go +++ b/pkg/golinters/grouper/grouper.go @@ -2,18 +2,16 @@ package grouper import ( grouper "github.com/leonklingele/grouper/pkg/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.GrouperSettings) *goanalysis.Linter { - a := grouper.New() + var cfg map[string]any - cfg := map[string]map[string]any{} if settings != nil { - cfg[a.Name] = map[string]any{ + cfg = map[string]any{ "const-require-single-const": settings.ConstRequireSingleConst, "const-require-grouping": settings.ConstRequireGrouping, "import-require-single-import": settings.ImportRequireSingleImport, @@ -24,11 +22,9 @@ func New(settings *config.GrouperSettings) *goanalysis.Linter { "var-require-grouping": settings.VarRequireGrouping, } } - - return goanalysis.NewLinter( - a.Name, - "Analyze expression groups.", - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(grouper.New()). + WithDesc("Analyze expression groups."). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/importas/importas.go b/pkg/golinters/importas/importas.go index a86db68ce04e..fa7a54300e29 100644 --- a/pkg/golinters/importas/importas.go +++ b/pkg/golinters/importas/importas.go @@ -6,7 +6,6 @@ import ( "strings" "github.com/julz/importas" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -16,55 +15,53 @@ import ( func New(settings *config.ImportAsSettings) *goanalysis.Linter { analyzer := importas.Analyzer - return goanalysis.NewLinter( - analyzer.Name, - analyzer.Doc, - []*analysis.Analyzer{analyzer}, - nil, - ).WithContextSetter(func(lintCtx *linter.Context) { - if settings == nil { - return - } - if len(settings.Alias) == 0 { - lintCtx.Log.Infof("importas settings found, but no aliases listed. List aliases under alias: key.") - } - - if err := analyzer.Flags.Set("no-unaliased", strconv.FormatBool(settings.NoUnaliased)); err != nil { - lintCtx.Log.Errorf("failed to parse configuration: %v", err) - } - - if err := analyzer.Flags.Set("no-extra-aliases", strconv.FormatBool(settings.NoExtraAliases)); err != nil { - 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 + return goanalysis. + NewLinterFromAnalyzer(analyzer). + WithContextSetter(func(lintCtx *linter.Context) { + if settings == nil { + return } - - 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 + if len(settings.Alias) == 0 { + lintCtx.Log.Infof("importas settings found, but no aliases listed. List aliases under alias: key.") } - // Skips the duplication check when: - // - the alias is empty. - // - the alias is a regular expression replacement pattern (ie. contains `$`). - v, ok := uniqAliases[a.Alias] - if ok && a.Alias != "" && !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 + if err := analyzer.Flags.Set("no-unaliased", strconv.FormatBool(settings.NoUnaliased)); err != nil { + lintCtx.Log.Errorf("failed to parse configuration: %v", err) } - err := analyzer.Flags.Set("alias", fmt.Sprintf("%s:%s", a.Pkg, a.Alias)) - if err != nil { + if err := analyzer.Flags.Set("no-extra-aliases", strconv.FormatBool(settings.NoExtraAliases)); err != nil { lintCtx.Log.Errorf("failed to parse configuration: %v", err) } - } - }).WithLoadMode(goanalysis.LoadModeTypesInfo) + + 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 + } + + // Skips the duplication check when: + // - the alias is empty. + // - the alias is a regular expression replacement pattern (ie. contains `$`). + v, ok := uniqAliases[a.Alias] + if ok && a.Alias != "" && !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) + } + } + }). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/inamedparam/inamedparam.go b/pkg/golinters/inamedparam/inamedparam.go index 0a67c970deca..ecb6f7e5024f 100644 --- a/pkg/golinters/inamedparam/inamedparam.go +++ b/pkg/golinters/inamedparam/inamedparam.go @@ -2,29 +2,22 @@ package inamedparam import ( "github.com/macabu/inamedparam" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.INamedParamSettings) *goanalysis.Linter { - a := inamedparam.Analyzer - - var cfg map[string]map[string]any + var cfg map[string]any if settings != nil { - cfg = map[string]map[string]any{ - a.Name: { - "skip-single-param": settings.SkipSingleParam, - }, + cfg = map[string]any{ + "skip-single-param": settings.SkipSingleParam, } } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(inamedparam.Analyzer). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/ineffassign/ineffassign.go b/pkg/golinters/ineffassign/ineffassign.go index bbe01ba1f37a..2c0119f1032f 100644 --- a/pkg/golinters/ineffassign/ineffassign.go +++ b/pkg/golinters/ineffassign/ineffassign.go @@ -2,18 +2,13 @@ package ineffassign import ( "github.com/gordonklaus/ineffassign/pkg/ineffassign" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := ineffassign.Analyzer - - return goanalysis.NewLinter( - a.Name, - "Detects when assignments to existing variables are not used", - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(ineffassign.Analyzer). + WithDesc("Detects when assignments to existing variables are not used"). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/interfacebloat/interfacebloat.go b/pkg/golinters/interfacebloat/interfacebloat.go index fbafb3ac7343..f2e187423278 100644 --- a/pkg/golinters/interfacebloat/interfacebloat.go +++ b/pkg/golinters/interfacebloat/interfacebloat.go @@ -2,28 +2,22 @@ package interfacebloat import ( "github.com/sashamelentyev/interfacebloat/pkg/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.InterfaceBloatSettings) *goanalysis.Linter { - a := analyzer.New() + var cfg map[string]any - var cfg map[string]map[string]any if settings != nil { - cfg = map[string]map[string]any{ - a.Name: { - analyzer.InterfaceMaxMethodsFlag: settings.Max, - }, + cfg = map[string]any{ + analyzer.InterfaceMaxMethodsFlag: settings.Max, } } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(analyzer.New()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/intrange/intrange.go b/pkg/golinters/intrange/intrange.go index c75be9b63446..1ff02964cbe5 100644 --- a/pkg/golinters/intrange/intrange.go +++ b/pkg/golinters/intrange/intrange.go @@ -2,18 +2,12 @@ package intrange import ( "github.com/ckaznocha/intrange" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := intrange.Analyzer - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(intrange.Analyzer). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/ireturn/ireturn.go b/pkg/golinters/ireturn/ireturn.go index 44c28700b370..b9cce0001842 100644 --- a/pkg/golinters/ireturn/ireturn.go +++ b/pkg/golinters/ireturn/ireturn.go @@ -4,28 +4,24 @@ import ( "strings" "github.com/butuzov/ireturn/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.IreturnSettings) *goanalysis.Linter { - a := analyzer.NewAnalyzer() + var cfg map[string]any - cfg := map[string]map[string]any{} if settings != nil { - cfg[a.Name] = map[string]any{ + cfg = map[string]any{ "allow": strings.Join(settings.Allow, ","), "reject": strings.Join(settings.Reject, ","), "nonolint": true, } } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(analyzer.NewAnalyzer()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/lll/lll.go b/pkg/golinters/lll/lll.go index eb435baa754c..c8e6717dea82 100644 --- a/pkg/golinters/lll/lll.go +++ b/pkg/golinters/lll/lll.go @@ -15,30 +15,23 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) -const linterName = "lll" - const goCommentDirectivePrefix = "//go:" func New(settings *config.LllSettings) *goanalysis.Linter { - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - err := runLll(pass, settings) - if err != nil { - return nil, err - } - - return nil, nil - }, - } - - return goanalysis.NewLinter( - linterName, - "Reports long lines", - []*analysis.Analyzer{analyzer}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: "lll", + Doc: "Reports long lines", + Run: func(pass *analysis.Pass) (any, error) { + err := runLll(pass, settings) + if err != nil { + return nil, err + } + + return nil, nil + }, + }). + WithLoadMode(goanalysis.LoadModeSyntax) } func runLll(pass *analysis.Pass, settings *config.LllSettings) error { diff --git a/pkg/golinters/loggercheck/loggercheck.go b/pkg/golinters/loggercheck/loggercheck.go index a5dd4da48cd6..b9a6efa75fad 100644 --- a/pkg/golinters/loggercheck/loggercheck.go +++ b/pkg/golinters/loggercheck/loggercheck.go @@ -2,7 +2,6 @@ package loggercheck import ( "github.com/timonwong/loggercheck" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -37,11 +36,7 @@ func New(settings *config.LoggerCheckSettings) *goanalysis.Linter { } } - analyzer := loggercheck.NewAnalyzer(opts...) - return goanalysis.NewLinter( - analyzer.Name, - analyzer.Doc, - []*analysis.Analyzer{analyzer}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(loggercheck.NewAnalyzer(opts...)). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/maintidx/maintidx.go b/pkg/golinters/maintidx/maintidx.go index 4e541f888dfa..f2076c8ab030 100644 --- a/pkg/golinters/maintidx/maintidx.go +++ b/pkg/golinters/maintidx/maintidx.go @@ -2,29 +2,22 @@ package maintidx import ( "github.com/yagipy/maintidx" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.MaintIdxSettings) *goanalysis.Linter { - analyzer := maintidx.Analyzer - - cfg := map[string]map[string]any{ - analyzer.Name: {"under": 20}, + cfg := map[string]any{ + "under": 20, } if settings != nil { - cfg[analyzer.Name] = map[string]any{ - "under": settings.Under, - } + cfg["under"] = settings.Under } - return goanalysis.NewLinter( - analyzer.Name, - analyzer.Doc, - []*analysis.Analyzer{analyzer}, - cfg, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(maintidx.Analyzer). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/makezero/makezero.go b/pkg/golinters/makezero/makezero.go index 8b86f120679e..5ee298d99f4e 100644 --- a/pkg/golinters/makezero/makezero.go +++ b/pkg/golinters/makezero/makezero.go @@ -10,28 +10,21 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) -const linterName = "makezero" - func New(settings *config.MakezeroSettings) *goanalysis.Linter { - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - err := runMakeZero(pass, settings) - if err != nil { - return nil, err - } - - return nil, nil - }, - } - - return goanalysis.NewLinter( - linterName, - "Finds slice declarations with non-zero initial length", - []*analysis.Analyzer{analyzer}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: "makezero", + Doc: "Find slice declarations with non-zero initial length", + Run: func(pass *analysis.Pass) (any, error) { + err := runMakeZero(pass, settings) + if err != nil { + return nil, err + } + + return nil, nil + }, + }). + WithLoadMode(goanalysis.LoadModeTypesInfo) } func runMakeZero(pass *analysis.Pass, settings *config.MakezeroSettings) error { diff --git a/pkg/golinters/mirror/mirror.go b/pkg/golinters/mirror/mirror.go index 9badb0c1ed68..07cfe25e4e44 100644 --- a/pkg/golinters/mirror/mirror.go +++ b/pkg/golinters/mirror/mirror.go @@ -2,29 +2,22 @@ package mirror import ( "github.com/butuzov/mirror" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := mirror.NewAnalyzer() - // 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) - linterCfg := map[string]map[string]any{ - a.Name: { - "with-tests": true, - }, + cfg := map[string]any{ + "with-tests": true, } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - linterCfg, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(mirror.NewAnalyzer()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/misspell/misspell.go b/pkg/golinters/misspell/misspell.go index 9a170c9537b7..cbf378505b47 100644 --- a/pkg/golinters/misspell/misspell.go +++ b/pkg/golinters/misspell/misspell.go @@ -23,27 +23,22 @@ func New(settings *config.MisspellSettings) *goanalysis.Linter { internal.LinterLogger.Fatalf("%s: %v", linterName, err) } - a := &analysis.Analyzer{ - Name: linterName, - Doc: "Finds commonly misspelled English words", - Run: func(pass *analysis.Pass) (any, error) { - for _, file := range pass.Files { - err := runMisspellOnFile(pass, file, replacer, settings.Mode) - if err != nil { - return nil, err + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: linterName, + Doc: "Finds commonly misspelled English words", + Run: func(pass *analysis.Pass) (any, error) { + for _, file := range pass.Files { + err := runMisspellOnFile(pass, file, replacer, settings.Mode) + if err != nil { + return nil, err + } } - } - return nil, nil - }, - } - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return nil, nil + }, + }). + WithLoadMode(goanalysis.LoadModeSyntax) } func createMisspellReplacer(settings *config.MisspellSettings) (*misspell.Replacer, error) { diff --git a/pkg/golinters/mnd/mnd.go b/pkg/golinters/mnd/mnd.go index 52521e92dd15..07174c899f57 100644 --- a/pkg/golinters/mnd/mnd.go +++ b/pkg/golinters/mnd/mnd.go @@ -2,18 +2,15 @@ package mnd import ( mnd "github.com/tommy-muehle/go-mnd/v2" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.MndSettings) *goanalysis.Linter { - a := mnd.Analyzer + cfg := map[string]any{} - var linterCfg map[string]map[string]any if settings != nil { - cfg := make(map[string]any) if len(settings.Checks) > 0 { cfg["checks"] = settings.Checks } @@ -26,16 +23,11 @@ func New(settings *config.MndSettings) *goanalysis.Linter { if len(settings.IgnoredFunctions) > 0 { cfg["ignored-functions"] = settings.IgnoredFunctions } - - linterCfg = map[string]map[string]any{ - a.Name: cfg, - } } - return goanalysis.NewLinter( - a.Name, - "An analyzer to detect magic numbers.", - []*analysis.Analyzer{a}, - linterCfg, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(mnd.Analyzer). + WithDesc("An analyzer to detect magic numbers."). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/musttag/musttag.go b/pkg/golinters/musttag/musttag.go index 030707327b7f..d17df9c2b8d9 100644 --- a/pkg/golinters/musttag/musttag.go +++ b/pkg/golinters/musttag/musttag.go @@ -2,7 +2,6 @@ package musttag import ( "go-simpler.org/musttag" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -21,9 +20,7 @@ func New(settings *config.MustTagSettings) *goanalysis.Linter { } } - a := musttag.New(funcs...) - return goanalysis. - NewLinter(a.Name, a.Doc, []*analysis.Analyzer{a}, nil). + NewLinterFromAnalyzer(musttag.New(funcs...)). WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/nakedret/nakedret.go b/pkg/golinters/nakedret/nakedret.go index 1b769acd8c8d..90053a1aab98 100644 --- a/pkg/golinters/nakedret/nakedret.go +++ b/pkg/golinters/nakedret/nakedret.go @@ -2,7 +2,6 @@ package nakedret import ( "github.com/alexkohler/nakedret/v2" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -16,12 +15,7 @@ func New(settings *config.NakedretSettings) *goanalysis.Linter { cfg.MaxLength = settings.MaxFuncLines } - a := nakedret.NakedReturnAnalyzer(cfg) - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(nakedret.NakedReturnAnalyzer(cfg)). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/nestif/nestif.go b/pkg/golinters/nestif/nestif.go index 1a6b55cafc22..e5823723c83a 100644 --- a/pkg/golinters/nestif/nestif.go +++ b/pkg/golinters/nestif/nestif.go @@ -8,25 +8,18 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) -const linterName = "nestif" - func New(settings *config.NestifSettings) *goanalysis.Linter { - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - runNestIf(pass, settings) - - return nil, nil - }, - } - - return goanalysis.NewLinter( - linterName, - "Reports deeply nested if statements", - []*analysis.Analyzer{analyzer}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: "nestif", + Doc: "Reports deeply nested if statements", + Run: func(pass *analysis.Pass) (any, error) { + runNestIf(pass, settings) + + return nil, nil + }, + }). + WithLoadMode(goanalysis.LoadModeSyntax) } func runNestIf(pass *analysis.Pass, settings *config.NestifSettings) { diff --git a/pkg/golinters/nilerr/nilerr.go b/pkg/golinters/nilerr/nilerr.go index 9345b945be11..fa5dcdc259fc 100644 --- a/pkg/golinters/nilerr/nilerr.go +++ b/pkg/golinters/nilerr/nilerr.go @@ -2,18 +2,13 @@ package nilerr import ( "github.com/gostaticanalysis/nilerr" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := nilerr.Analyzer - - return goanalysis.NewLinter( - a.Name, - "Finds the code that returns nil even if it checks that the error is not nil.", - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(nilerr.Analyzer). + WithDesc("Find the code that returns nil even if it checks that the error is not nil."). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/nilnesserr/nilnesserr.go b/pkg/golinters/nilnesserr/nilnesserr.go index b54992e29bb5..95eaf94abe25 100644 --- a/pkg/golinters/nilnesserr/nilnesserr.go +++ b/pkg/golinters/nilnesserr/nilnesserr.go @@ -2,22 +2,18 @@ package nilnesserr import ( "github.com/alingse/nilnesserr" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" "github.com/golangci/golangci-lint/v2/pkg/golinters/internal" ) func New() *goanalysis.Linter { - a, err := nilnesserr.NewAnalyzer(nilnesserr.LinterSetting{}) + analyzer, err := nilnesserr.NewAnalyzer(nilnesserr.LinterSetting{}) if err != nil { internal.LinterLogger.Fatalf("nilnesserr: create analyzer: %v", err) } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(analyzer). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/nilnil/nilnil.go b/pkg/golinters/nilnil/nilnil.go index 5f42e24c96fc..4936a6b84c8f 100644 --- a/pkg/golinters/nilnil/nilnil.go +++ b/pkg/golinters/nilnil/nilnil.go @@ -2,33 +2,28 @@ package nilnil import ( "github.com/Antonboom/nilnil/pkg/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.NilNilSettings) *goanalysis.Linter { - a := analyzer.New() + var cfg map[string]any - cfg := make(map[string]map[string]any) if settings != nil { - cfg[a.Name] = map[string]any{ + cfg = map[string]any{ "detect-opposite": settings.DetectOpposite, } if b := settings.OnlyTwo; b != nil { - cfg[a.Name]["only-two"] = *b + cfg["only-two"] = *b } if len(settings.CheckedTypes) != 0 { - cfg[a.Name]["checked-types"] = settings.CheckedTypes + cfg["checked-types"] = settings.CheckedTypes } } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ). + return goanalysis. + NewLinterFromAnalyzer(analyzer.New()). + WithConfig(cfg). WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/nlreturn/nlreturn.go b/pkg/golinters/nlreturn/nlreturn.go index ce2130c52c81..7b7ab745ad7b 100644 --- a/pkg/golinters/nlreturn/nlreturn.go +++ b/pkg/golinters/nlreturn/nlreturn.go @@ -2,26 +2,22 @@ package nlreturn import ( "github.com/ssgreg/nlreturn/v2/pkg/nlreturn" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.NlreturnSettings) *goanalysis.Linter { - a := nlreturn.NewAnalyzer() + var cfg map[string]any - cfg := map[string]map[string]any{} if settings != nil { - cfg[a.Name] = map[string]any{ + cfg = map[string]any{ "block-size": settings.BlockSize, } } - - return goanalysis.NewLinter( - a.Name, - "nlreturn checks for a new line before return and branch statements to increase code clarity", - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(nlreturn.NewAnalyzer()). + WithDesc("Checks for a new line before return and branch statements to increase code clarity"). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/noctx/noctx.go b/pkg/golinters/noctx/noctx.go index 18391d4b5581..c3e5be104262 100644 --- a/pkg/golinters/noctx/noctx.go +++ b/pkg/golinters/noctx/noctx.go @@ -2,18 +2,13 @@ package noctx import ( "github.com/sonatard/noctx" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := noctx.Analyzer - - return goanalysis.NewLinter( - a.Name, - "Detects function and method with missing usage of context.Context", - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(noctx.Analyzer). + WithDesc("Detects function and method with missing usage of context.Context"). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/nolintlint/nolintlint.go b/pkg/golinters/nolintlint/nolintlint.go index f19b8324c295..37f9cb96aac7 100644 --- a/pkg/golinters/nolintlint/nolintlint.go +++ b/pkg/golinters/nolintlint/nolintlint.go @@ -35,33 +35,29 @@ func New(settings *config.NoLintLintSettings) *goanalysis.Linter { internal.LinterLogger.Fatalf("%s: create analyzer: %v", nolintlint.LinterName, err) } - analyzer := &analysis.Analyzer{ - Name: nolintlint.LinterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - issues, err := lnt.Run(pass) - if err != nil { - return nil, fmt.Errorf("linter failed to run: %w", err) - } + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: nolintlint.LinterName, + Doc: "Reports ill-formed or insufficient nolint directives", + Run: func(pass *analysis.Pass) (any, error) { + issues, err := lnt.Run(pass) + if err != nil { + return nil, fmt.Errorf("linter failed to run: %w", err) + } + + if len(issues) == 0 { + return nil, nil + } + + mu.Lock() + resIssues = append(resIssues, issues...) + mu.Unlock() - if len(issues) == 0 { return nil, nil - } - - mu.Lock() - resIssues = append(resIssues, issues...) - mu.Unlock() - - return nil, nil - }, - } - - return goanalysis.NewLinter( - nolintlint.LinterName, - "Reports ill-formed or insufficient nolint directives", - []*analysis.Analyzer{analyzer}, - nil, - ).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return resIssues - }).WithLoadMode(goanalysis.LoadModeSyntax) + }, + }). + WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/nonamedreturns/nonamedreturns.go b/pkg/golinters/nonamedreturns/nonamedreturns.go index 91354f6a4492..4149ef818e20 100644 --- a/pkg/golinters/nonamedreturns/nonamedreturns.go +++ b/pkg/golinters/nonamedreturns/nonamedreturns.go @@ -2,28 +2,22 @@ package nonamedreturns import ( "github.com/firefart/nonamedreturns/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.NoNamedReturnsSettings) *goanalysis.Linter { - a := analyzer.Analyzer + var cfg map[string]any - var cfg map[string]map[string]any if settings != nil { - cfg = map[string]map[string]any{ - a.Name: { - analyzer.FlagReportErrorInDefer: settings.ReportErrorInDefer, - }, + cfg = map[string]any{ + analyzer.FlagReportErrorInDefer: settings.ReportErrorInDefer, } } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(analyzer.Analyzer). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/nosprintfhostport/nosprintfhostport.go b/pkg/golinters/nosprintfhostport/nosprintfhostport.go index cca70680cf6c..f8ca26b738c9 100644 --- a/pkg/golinters/nosprintfhostport/nosprintfhostport.go +++ b/pkg/golinters/nosprintfhostport/nosprintfhostport.go @@ -2,18 +2,12 @@ package nosprintfhostport import ( "github.com/stbenjam/no-sprintf-host-port/pkg/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := analyzer.Analyzer - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(analyzer.Analyzer). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/paralleltest/paralleltest.go b/pkg/golinters/paralleltest/paralleltest.go index 8c811ca511af..f3eac2e05afb 100644 --- a/pkg/golinters/paralleltest/paralleltest.go +++ b/pkg/golinters/paralleltest/paralleltest.go @@ -2,33 +2,28 @@ package paralleltest import ( "github.com/kunwardeep/paralleltest/pkg/paralleltest" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.ParallelTestSettings) *goanalysis.Linter { - a := paralleltest.NewAnalyzer() + var cfg map[string]any - var cfg map[string]map[string]any if settings != nil { - d := map[string]any{ + cfg = map[string]any{ "i": settings.IgnoreMissing, "ignoremissingsubtests": settings.IgnoreMissingSubtests, } if config.IsGoGreaterThanOrEqual(settings.Go, "1.22") { - d["ignoreloopVar"] = true + cfg["ignoreloopVar"] = true } - - cfg = map[string]map[string]any{a.Name: d} } - return goanalysis.NewLinter( - a.Name, - "Detects missing usage of t.Parallel() method in your Go test", - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(paralleltest.NewAnalyzer()). + WithDesc("Detects missing usage of t.Parallel() method in your Go test"). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/perfsprint/perfsprint.go b/pkg/golinters/perfsprint/perfsprint.go index f870ee00115a..9684c27c6639 100644 --- a/pkg/golinters/perfsprint/perfsprint.go +++ b/pkg/golinters/perfsprint/perfsprint.go @@ -2,41 +2,36 @@ package perfsprint import ( "github.com/catenacyber/perfsprint/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.PerfSprintSettings) *goanalysis.Linter { - a := analyzer.New() - - cfg := map[string]map[string]any{ - a.Name: {"fiximports": false}, + cfg := map[string]any{ + "fiximports": false, } if settings != nil { // NOTE: The option `ignore-tests` is not handled because it should be managed with `linters.exclusions.rules` - cfg[a.Name]["integer-format"] = settings.IntegerFormat - cfg[a.Name]["int-conversion"] = settings.IntConversion + cfg["integer-format"] = settings.IntegerFormat + cfg["int-conversion"] = settings.IntConversion - cfg[a.Name]["error-format"] = settings.ErrorFormat - cfg[a.Name]["err-error"] = settings.ErrError - cfg[a.Name]["errorf"] = settings.ErrorF + cfg["error-format"] = settings.ErrorFormat + cfg["err-error"] = settings.ErrError + cfg["errorf"] = settings.ErrorF - cfg[a.Name]["string-format"] = settings.StringFormat - cfg[a.Name]["sprintf1"] = settings.SprintF1 - cfg[a.Name]["strconcat"] = settings.StrConcat + cfg["string-format"] = settings.StringFormat + cfg["sprintf1"] = settings.SprintF1 + cfg["strconcat"] = settings.StrConcat - cfg[a.Name]["bool-format"] = settings.BoolFormat - cfg[a.Name]["hex-format"] = settings.HexFormat + cfg["bool-format"] = settings.BoolFormat + cfg["hex-format"] = settings.HexFormat } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(analyzer.New()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/prealloc/prealloc.go b/pkg/golinters/prealloc/prealloc.go index 1ceba6007ce0..66890ad5bc61 100644 --- a/pkg/golinters/prealloc/prealloc.go +++ b/pkg/golinters/prealloc/prealloc.go @@ -11,25 +11,18 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/golinters/internal" ) -const linterName = "prealloc" - func New(settings *config.PreallocSettings) *goanalysis.Linter { - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - runPreAlloc(pass, settings) - - return nil, nil - }, - } - - return goanalysis.NewLinter( - linterName, - "Finds slice declarations that could potentially be pre-allocated", - []*analysis.Analyzer{analyzer}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: "prealloc", + Doc: "Find slice declarations that could potentially be pre-allocated", + Run: func(pass *analysis.Pass) (any, error) { + runPreAlloc(pass, settings) + + return nil, nil + }, + }). + WithLoadMode(goanalysis.LoadModeSyntax) } func runPreAlloc(pass *analysis.Pass, settings *config.PreallocSettings) { diff --git a/pkg/golinters/predeclared/predeclared.go b/pkg/golinters/predeclared/predeclared.go index 9bde9d2f3baa..8f2be53c4fc1 100644 --- a/pkg/golinters/predeclared/predeclared.go +++ b/pkg/golinters/predeclared/predeclared.go @@ -4,25 +4,23 @@ import ( "strings" "github.com/nishanths/predeclared/passes/predeclared" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.PredeclaredSettings) *goanalysis.Linter { - a := predeclared.Analyzer + var cfg map[string]any - var cfg map[string]map[string]any if settings != nil { - cfg = map[string]map[string]any{ - a.Name: { - predeclared.IgnoreFlag: strings.Join(settings.Ignore, ","), - predeclared.QualifiedFlag: settings.Qualified, - }, + cfg = map[string]any{ + predeclared.IgnoreFlag: strings.Join(settings.Ignore, ","), + predeclared.QualifiedFlag: settings.Qualified, } } - return goanalysis.NewLinter(a.Name, a.Doc, []*analysis.Analyzer{a}, cfg). + return goanalysis. + NewLinterFromAnalyzer(predeclared.Analyzer). + WithConfig(cfg). WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/promlinter/promlinter.go b/pkg/golinters/promlinter/promlinter.go index ab2c9c569dea..2cb59cbe6f1a 100644 --- a/pkg/golinters/promlinter/promlinter.go +++ b/pkg/golinters/promlinter/promlinter.go @@ -27,32 +27,28 @@ func New(settings *config.PromlinterSettings) *goanalysis.Linter { } } - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - issues := runPromLinter(pass, promSettings) + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: linterName, + Doc: "Check Prometheus metrics naming via promlint", + Run: func(pass *analysis.Pass) (any, error) { + issues := runPromLinter(pass, promSettings) - if len(issues) == 0 { - return nil, nil - } - - mu.Lock() - resIssues = append(resIssues, issues...) - mu.Unlock() + if len(issues) == 0 { + return nil, nil + } - return nil, nil - }, - } + mu.Lock() + resIssues = append(resIssues, issues...) + mu.Unlock() - return goanalysis.NewLinter( - linterName, - "Check Prometheus metrics naming via promlint", - []*analysis.Analyzer{analyzer}, - nil, - ).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return resIssues - }).WithLoadMode(goanalysis.LoadModeSyntax) + return nil, nil + }, + }). + WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }). + WithLoadMode(goanalysis.LoadModeSyntax) } func runPromLinter(pass *analysis.Pass, promSettings promlinter.Setting) []goanalysis.Issue { diff --git a/pkg/golinters/protogetter/protogetter.go b/pkg/golinters/protogetter/protogetter.go index c13c98af5792..bee5da263915 100644 --- a/pkg/golinters/protogetter/protogetter.go +++ b/pkg/golinters/protogetter/protogetter.go @@ -2,7 +2,6 @@ package protogetter import ( "github.com/ghostiam/protogetter" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -10,6 +9,7 @@ import ( func New(settings *config.ProtoGetterSettings) *goanalysis.Linter { var cfg protogetter.Config + if settings != nil { cfg = protogetter.Config{ SkipGeneratedBy: settings.SkipGeneratedBy, @@ -19,12 +19,7 @@ func New(settings *config.ProtoGetterSettings) *goanalysis.Linter { } } - a := protogetter.NewAnalyzer(&cfg) - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(protogetter.NewAnalyzer(&cfg)). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/reassign/reassign.go b/pkg/golinters/reassign/reassign.go index 7d9f84285b89..35e661cae84b 100644 --- a/pkg/golinters/reassign/reassign.go +++ b/pkg/golinters/reassign/reassign.go @@ -5,28 +5,22 @@ import ( "strings" "github.com/curioswitch/go-reassign" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.ReassignSettings) *goanalysis.Linter { - a := reassign.NewAnalyzer() + var cfg map[string]any - var cfg map[string]map[string]any if settings != nil && len(settings.Patterns) > 0 { - cfg = map[string]map[string]any{ - a.Name: { - reassign.FlagPattern: fmt.Sprintf("^(%s)$", strings.Join(settings.Patterns, "|")), - }, + cfg = map[string]any{ + reassign.FlagPattern: fmt.Sprintf("^(%s)$", strings.Join(settings.Patterns, "|")), } } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(reassign.NewAnalyzer()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/recvcheck/recvcheck.go b/pkg/golinters/recvcheck/recvcheck.go index ed1eb0b78765..76db48f93979 100644 --- a/pkg/golinters/recvcheck/recvcheck.go +++ b/pkg/golinters/recvcheck/recvcheck.go @@ -2,7 +2,6 @@ package recvcheck import ( "github.com/raeperd/recvcheck" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -16,12 +15,7 @@ func New(settings *config.RecvcheckSettings) *goanalysis.Linter { cfg.Exclusions = settings.Exclusions } - a := recvcheck.NewAnalyzer(cfg) - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(recvcheck.NewAnalyzer(cfg)). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/revive/revive.go b/pkg/golinters/revive/revive.go index 5f9b3a90ace1..32b42ba8314d 100644 --- a/pkg/golinters/revive/revive.go +++ b/pkg/golinters/revive/revive.go @@ -38,42 +38,41 @@ func New(settings *config.ReviveSettings) *goanalysis.Linter { var resIssues []goanalysis.Issue analyzer := &analysis.Analyzer{ - Name: goanalysis.TheOnlyAnalyzerName, - Doc: goanalysis.TheOnlyanalyzerDoc, + Name: linterName, + Doc: "Fast, configurable, extensible, flexible, and beautiful linter for Go. Drop-in replacement of golint.", Run: goanalysis.DummyRun, } - return goanalysis.NewLinter( - linterName, - "Fast, configurable, extensible, flexible, and beautiful linter for Go. Drop-in replacement of golint.", - []*analysis.Analyzer{analyzer}, - nil, - ).WithContextSetter(func(lintCtx *linter.Context) { - w, err := newWrapper(settings) - if err != nil { - lintCtx.Log.Errorf("setup revive: %v", err) - return - } - - analyzer.Run = func(pass *analysis.Pass) (any, error) { - issues, err := w.run(pass) + return goanalysis. + NewLinterFromAnalyzer(analyzer). + WithContextSetter(func(lintCtx *linter.Context) { + w, err := newWrapper(settings) if err != nil { - return nil, err + lintCtx.Log.Errorf("setup revive: %v", err) + return } - if len(issues) == 0 { - return nil, nil - } + analyzer.Run = func(pass *analysis.Pass) (any, error) { + issues, err := w.run(pass) + if err != nil { + return nil, err + } - mu.Lock() - resIssues = append(resIssues, issues...) - mu.Unlock() + if len(issues) == 0 { + return nil, nil + } - return nil, nil - } - }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return resIssues - }).WithLoadMode(goanalysis.LoadModeSyntax) + mu.Lock() + resIssues = append(resIssues, issues...) + mu.Unlock() + + return nil, nil + } + }). + WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }). + WithLoadMode(goanalysis.LoadModeSyntax) } type wrapper struct { diff --git a/pkg/golinters/rowserrcheck/rowserrcheck.go b/pkg/golinters/rowserrcheck/rowserrcheck.go index 2bd975ddf28f..de0fe4da917e 100644 --- a/pkg/golinters/rowserrcheck/rowserrcheck.go +++ b/pkg/golinters/rowserrcheck/rowserrcheck.go @@ -2,7 +2,6 @@ package rowserrcheck import ( "github.com/jingyugao/rowserrcheck/passes/rowserr" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -10,16 +9,13 @@ import ( func New(settings *config.RowsErrCheckSettings) *goanalysis.Linter { var pkgs []string + if settings != nil { pkgs = settings.Packages } - a := rowserr.NewAnalyzer(pkgs...) - - return goanalysis.NewLinter( - a.Name, - "checks whether Rows.Err of rows is checked successfully", - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(rowserr.NewAnalyzer(pkgs...)). + WithDesc("checks whether Rows.Err of rows is checked successfully"). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/sloglint/sloglint.go b/pkg/golinters/sloglint/sloglint.go index 021157dd66b7..891f1fcfdbdf 100644 --- a/pkg/golinters/sloglint/sloglint.go +++ b/pkg/golinters/sloglint/sloglint.go @@ -2,7 +2,6 @@ package sloglint import ( "go-simpler.org/sloglint" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -10,6 +9,7 @@ import ( func New(settings *config.SlogLintSettings) *goanalysis.Linter { var opts *sloglint.Options + if settings != nil { opts = &sloglint.Options{ NoMixedArgs: settings.NoMixedArgs, @@ -26,9 +26,7 @@ func New(settings *config.SlogLintSettings) *goanalysis.Linter { } } - a := sloglint.New(opts) - return goanalysis. - NewLinter(a.Name, a.Doc, []*analysis.Analyzer{a}, nil). + NewLinterFromAnalyzer(sloglint.New(opts)). WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/spancheck/spancheck.go b/pkg/golinters/spancheck/spancheck.go index 264623058b1e..345c36277447 100644 --- a/pkg/golinters/spancheck/spancheck.go +++ b/pkg/golinters/spancheck/spancheck.go @@ -2,7 +2,6 @@ package spancheck import ( "github.com/jjti/go-spancheck" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -25,9 +24,7 @@ func New(settings *config.SpancheckSettings) *goanalysis.Linter { } } - a := spancheck.NewAnalyzerWithConfig(cfg) - return goanalysis. - NewLinter(a.Name, a.Doc, []*analysis.Analyzer{a}, nil). + NewLinterFromAnalyzer(spancheck.NewAnalyzerWithConfig(cfg)). WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/sqlclosecheck/sqlclosecheck.go b/pkg/golinters/sqlclosecheck/sqlclosecheck.go index 7f7e70c71401..4c970cc5295d 100644 --- a/pkg/golinters/sqlclosecheck/sqlclosecheck.go +++ b/pkg/golinters/sqlclosecheck/sqlclosecheck.go @@ -2,18 +2,12 @@ package sqlclosecheck import ( "github.com/ryanrolds/sqlclosecheck/pkg/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := analyzer.NewAnalyzer() - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(analyzer.NewAnalyzer()). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/swaggo/swaggo.go b/pkg/golinters/swaggo/swaggo.go index 8c4eec8e448d..98f7a6bef4dc 100644 --- a/pkg/golinters/swaggo/swaggo.go +++ b/pkg/golinters/swaggo/swaggo.go @@ -1,23 +1,20 @@ package swaggo import ( - "golang.org/x/tools/go/analysis" - "github.com/golangci/golangci-lint/v2/pkg/goanalysis" "github.com/golangci/golangci-lint/v2/pkg/goformatters" "github.com/golangci/golangci-lint/v2/pkg/goformatters/swaggo" "github.com/golangci/golangci-lint/v2/pkg/golinters/internal" ) -const linterName = "swaggo" - func New() *goanalysis.Linter { - a := goformatters.NewAnalyzer( - internal.LinterLogger.Child(linterName), - "Check if swaggo comments are formatted", - swaggo.New(), - ) - - return goanalysis.NewLinter(a.Name, a.Doc, []*analysis.Analyzer{a}, nil). + return goanalysis. + NewLinterFromAnalyzer( + goformatters.NewAnalyzer( + internal.LinterLogger.Child(swaggo.Name), + "Check if swaggo comments are formatted", + swaggo.New(), + ), + ). WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/tagalign/tagalign.go b/pkg/golinters/tagalign/tagalign.go index 412d69b937ef..eba51311c0cf 100644 --- a/pkg/golinters/tagalign/tagalign.go +++ b/pkg/golinters/tagalign/tagalign.go @@ -2,7 +2,6 @@ package tagalign import ( "github.com/4meepo/tagalign" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -24,12 +23,7 @@ func New(settings *config.TagAlignSettings) *goanalysis.Linter { } } - analyzer := tagalign.NewAnalyzer(options...) - - return goanalysis.NewLinter( - analyzer.Name, - analyzer.Doc, - []*analysis.Analyzer{analyzer}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(tagalign.NewAnalyzer(options...)). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/tagliatelle/tagliatelle.go b/pkg/golinters/tagliatelle/tagliatelle.go index f6357e0e3747..89ebf6c2f4df 100644 --- a/pkg/golinters/tagliatelle/tagliatelle.go +++ b/pkg/golinters/tagliatelle/tagliatelle.go @@ -2,7 +2,6 @@ package tagliatelle import ( "github.com/ldez/tagliatelle" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -42,14 +41,9 @@ func New(settings *config.TagliatelleSettings) *goanalysis.Linter { } } - a := tagliatelle.New(cfg) - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(tagliatelle.New(cfg)). + WithLoadMode(goanalysis.LoadModeTypesInfo) } func toExtendedRules(src map[string]config.TagliatelleExtendedRule) map[string]tagliatelle.ExtendedRule { diff --git a/pkg/golinters/testableexamples/testableexamples.go b/pkg/golinters/testableexamples/testableexamples.go index 38334a096237..45fdc900e2c3 100644 --- a/pkg/golinters/testableexamples/testableexamples.go +++ b/pkg/golinters/testableexamples/testableexamples.go @@ -2,18 +2,12 @@ package testableexamples import ( "github.com/maratori/testableexamples/pkg/testableexamples" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := testableexamples.NewAnalyzer() - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(testableexamples.NewAnalyzer()). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/testifylint/testifylint.go b/pkg/golinters/testifylint/testifylint.go index b19471c1ea05..bb5eac0e451e 100644 --- a/pkg/golinters/testifylint/testifylint.go +++ b/pkg/golinters/testifylint/testifylint.go @@ -2,18 +2,16 @@ package testifylint import ( "github.com/Antonboom/testifylint/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.TestifylintSettings) *goanalysis.Linter { - a := analyzer.New() + var cfg map[string]any - cfg := make(map[string]map[string]any) if settings != nil { - cfg[a.Name] = map[string]any{ + cfg = map[string]any{ "enable-all": settings.EnableAll, "disable-all": settings.DisableAll, @@ -23,30 +21,28 @@ func New(settings *config.TestifylintSettings) *goanalysis.Linter { "go-require.ignore-http-handlers": settings.GoRequire.IgnoreHTTPHandlers, } if len(settings.EnabledCheckers) > 0 { - cfg[a.Name]["enable"] = settings.EnabledCheckers + cfg["enable"] = settings.EnabledCheckers } if len(settings.DisabledCheckers) > 0 { - cfg[a.Name]["disable"] = settings.DisabledCheckers + cfg["disable"] = settings.DisabledCheckers } if b := settings.Formatter.CheckFormatString; b != nil { - cfg[a.Name]["formatter.check-format-string"] = *b + cfg["formatter.check-format-string"] = *b } if p := settings.ExpectedActual.ExpVarPattern; p != "" { - cfg[a.Name]["expected-actual.pattern"] = p + cfg["expected-actual.pattern"] = p } if p := settings.RequireError.FnPattern; p != "" { - cfg[a.Name]["require-error.fn-pattern"] = p + cfg["require-error.fn-pattern"] = p } if m := settings.SuiteExtraAssertCall.Mode; m != "" { - cfg[a.Name]["suite-extra-assert-call.mode"] = m + cfg["suite-extra-assert-call.mode"] = m } } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(analyzer.New()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/testpackage/testpackage.go b/pkg/golinters/testpackage/testpackage.go index ddd5ce95cd15..39c333f1b56d 100644 --- a/pkg/golinters/testpackage/testpackage.go +++ b/pkg/golinters/testpackage/testpackage.go @@ -4,25 +4,23 @@ import ( "strings" "github.com/maratori/testpackage/pkg/testpackage" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.TestpackageSettings) *goanalysis.Linter { - a := testpackage.NewAnalyzer() + var cfg map[string]any - var cfg map[string]map[string]any if settings != nil { - cfg = map[string]map[string]any{ - a.Name: { - testpackage.SkipRegexpFlagName: settings.SkipRegexp, - testpackage.AllowPackagesFlagName: strings.Join(settings.AllowPackages, ","), - }, + cfg = map[string]any{ + testpackage.SkipRegexpFlagName: settings.SkipRegexp, + testpackage.AllowPackagesFlagName: strings.Join(settings.AllowPackages, ","), } } - return goanalysis.NewLinter(a.Name, a.Doc, []*analysis.Analyzer{a}, cfg). + return goanalysis. + NewLinterFromAnalyzer(testpackage.NewAnalyzer()). + WithConfig(cfg). WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/thelper/thelper.go b/pkg/golinters/thelper/thelper.go index d9058582d83c..77090c5f8b15 100644 --- a/pkg/golinters/thelper/thelper.go +++ b/pkg/golinters/thelper/thelper.go @@ -6,7 +6,6 @@ import ( "strings" "github.com/kulti/thelper/pkg/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -14,8 +13,6 @@ import ( ) func New(settings *config.ThelperSettings) *goanalysis.Linter { - a := analyzer.NewAnalyzer() - opts := map[string]struct{}{ "t_name": {}, "t_begin": {}, @@ -47,18 +44,14 @@ func New(settings *config.ThelperSettings) *goanalysis.Linter { args := slices.Collect(maps.Keys(opts)) - cfg := map[string]map[string]any{ - a.Name: { - "checks": strings.Join(args, ","), - }, + cfg := map[string]any{ + "checks": strings.Join(args, ","), } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(analyzer.NewAnalyzer()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeTypesInfo) } func applyTHelperOptions(o config.ThelperOptions, prefix string, opts map[string]struct{}) { diff --git a/pkg/golinters/tparallel/tparallel.go b/pkg/golinters/tparallel/tparallel.go index f3ce2fcf7975..480ef3b1e92b 100644 --- a/pkg/golinters/tparallel/tparallel.go +++ b/pkg/golinters/tparallel/tparallel.go @@ -2,17 +2,12 @@ package tparallel import ( "github.com/moricho/tparallel" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := tparallel.Analyzer - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(tparallel.Analyzer). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/typecheck.go b/pkg/golinters/typecheck.go index ad51e8d00f90..db29f7c18394 100644 --- a/pkg/golinters/typecheck.go +++ b/pkg/golinters/typecheck.go @@ -7,18 +7,11 @@ import ( ) func NewTypecheck() *goanalysis.Linter { - const linterName = "typecheck" - - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: goanalysis.DummyRun, - } - - return goanalysis.NewLinter( - linterName, - "Like the front-end of a Go compiler, parses and type-checks Go code", - []*analysis.Analyzer{analyzer}, - nil, - ).WithLoadMode(goanalysis.LoadModeNone) + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: "typecheck", + Doc: "Like the front-end of a Go compiler, parses and type-checks Go code", + Run: goanalysis.DummyRun, + }). + WithLoadMode(goanalysis.LoadModeNone) } diff --git a/pkg/golinters/unconvert/unconvert.go b/pkg/golinters/unconvert/unconvert.go index d48cf5175ad4..c9b3f75dd169 100644 --- a/pkg/golinters/unconvert/unconvert.go +++ b/pkg/golinters/unconvert/unconvert.go @@ -21,32 +21,28 @@ func New(settings *config.UnconvertSettings) *goanalysis.Linter { unconvert.SetFastMath(settings.FastMath) unconvert.SetSafe(settings.Safe) - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: func(pass *analysis.Pass) (any, error) { - issues := runUnconvert(pass) + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: linterName, + Doc: "Remove unnecessary type conversions", + Run: func(pass *analysis.Pass) (any, error) { + issues := runUnconvert(pass) - if len(issues) == 0 { - return nil, nil - } - - mu.Lock() - resIssues = append(resIssues, issues...) - mu.Unlock() + if len(issues) == 0 { + return nil, nil + } - return nil, nil - }, - } + mu.Lock() + resIssues = append(resIssues, issues...) + mu.Unlock() - return goanalysis.NewLinter( - linterName, - "Remove unnecessary type conversions", - []*analysis.Analyzer{analyzer}, - nil, - ).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { - return resIssues - }).WithLoadMode(goanalysis.LoadModeTypesInfo) + return nil, nil + }, + }). + WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + return resIssues + }). + WithLoadMode(goanalysis.LoadModeTypesInfo) } func runUnconvert(pass *analysis.Pass) []goanalysis.Issue { diff --git a/pkg/golinters/unparam/unparam.go b/pkg/golinters/unparam/unparam.go index 5a9bc8a5e473..b6cb2668b076 100644 --- a/pkg/golinters/unparam/unparam.go +++ b/pkg/golinters/unparam/unparam.go @@ -10,29 +10,22 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) -const linterName = "unparam" - func New(settings *config.UnparamSettings) *goanalysis.Linter { - analyzer := &analysis.Analyzer{ - Name: linterName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Requires: []*analysis.Analyzer{buildssa.Analyzer}, - Run: func(pass *analysis.Pass) (any, error) { - err := runUnparam(pass, settings) - if err != nil { - return nil, err - } - - return nil, nil - }, - } - - return goanalysis.NewLinter( - linterName, - "Reports unused function parameters", - []*analysis.Analyzer{analyzer}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(&analysis.Analyzer{ + Name: "unparam", + Doc: "Reports unused function parameters", + Requires: []*analysis.Analyzer{buildssa.Analyzer}, + Run: func(pass *analysis.Pass) (any, error) { + err := runUnparam(pass, settings) + if err != nil { + return nil, err + } + + return nil, nil + }, + }). + WithLoadMode(goanalysis.LoadModeTypesInfo) } func runUnparam(pass *analysis.Pass, settings *config.UnparamSettings) error { diff --git a/pkg/golinters/usestdlibvars/usestdlibvars.go b/pkg/golinters/usestdlibvars/usestdlibvars.go index f0b5f5420d00..9342c4ccd7a3 100644 --- a/pkg/golinters/usestdlibvars/usestdlibvars.go +++ b/pkg/golinters/usestdlibvars/usestdlibvars.go @@ -2,18 +2,16 @@ package usestdlibvars import ( "github.com/sashamelentyev/usestdlibvars/pkg/analyzer" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.UseStdlibVarsSettings) *goanalysis.Linter { - a := analyzer.New() + var cfg map[string]any - cfg := make(map[string]map[string]any) if settings != nil { - cfg[a.Name] = map[string]any{ + cfg = map[string]any{ analyzer.ConstantKindFlag: settings.ConstantKind, analyzer.CryptoHashFlag: settings.CryptoHash, analyzer.HTTPMethodFlag: settings.HTTPMethod, @@ -29,10 +27,8 @@ func New(settings *config.UseStdlibVarsSettings) *goanalysis.Linter { } } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(analyzer.New()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/usetesting/usetesting.go b/pkg/golinters/usetesting/usetesting.go index 5dfa9f11ad54..7371cc28eb01 100644 --- a/pkg/golinters/usetesting/usetesting.go +++ b/pkg/golinters/usetesting/usetesting.go @@ -2,18 +2,16 @@ package usetesting import ( "github.com/ldez/usetesting" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.UseTestingSettings) *goanalysis.Linter { - a := usetesting.NewAnalyzer() + var cfg map[string]any - cfg := make(map[string]map[string]any) if settings != nil { - cfg[a.Name] = map[string]any{ + cfg = map[string]any{ "contextbackground": settings.ContextBackground, "contexttodo": settings.ContextTodo, "oschdir": settings.OSChdir, @@ -24,10 +22,8 @@ func New(settings *config.UseTestingSettings) *goanalysis.Linter { } } - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - cfg, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(usetesting.NewAnalyzer()). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/varnamelen/varnamelen.go b/pkg/golinters/varnamelen/varnamelen.go index dbd8005ee0d1..a19d7987ddcd 100644 --- a/pkg/golinters/varnamelen/varnamelen.go +++ b/pkg/golinters/varnamelen/varnamelen.go @@ -5,15 +5,13 @@ import ( "strings" "github.com/blizzy78/varnamelen" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New(settings *config.VarnamelenSettings) *goanalysis.Linter { - analyzer := varnamelen.NewAnalyzer() - cfg := map[string]map[string]any{} + var cfg map[string]any if settings != nil { vnlCfg := map[string]any{ @@ -30,17 +28,15 @@ func New(settings *config.VarnamelenSettings) *goanalysis.Linter { if settings.MaxDistance > 0 { vnlCfg["maxDistance"] = strconv.Itoa(settings.MaxDistance) } + if settings.MinNameLength > 0 { vnlCfg["minNameLength"] = strconv.Itoa(settings.MinNameLength) } - - cfg[analyzer.Name] = vnlCfg } - return goanalysis.NewLinter( - analyzer.Name, - "checks that the length of a variable's name matches its scope", - []*analysis.Analyzer{analyzer}, - cfg, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(varnamelen.NewAnalyzer()). + WithDesc("checks that the length of a variable's name matches its scope"). + WithConfig(cfg). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/wastedassign/wastedassign.go b/pkg/golinters/wastedassign/wastedassign.go index 6599f7d4dace..d103a8d5a55b 100644 --- a/pkg/golinters/wastedassign/wastedassign.go +++ b/pkg/golinters/wastedassign/wastedassign.go @@ -2,18 +2,13 @@ package wastedassign import ( "github.com/sanposhiho/wastedassign/v2" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := wastedassign.Analyzer - - return goanalysis.NewLinter( - a.Name, - "Finds wasted assignment statements", - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(wastedassign.Analyzer). + WithDesc("Finds wasted assignment statements"). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/whitespace/whitespace.go b/pkg/golinters/whitespace/whitespace.go index cd7fda1ce0d0..bf03e1d8088b 100644 --- a/pkg/golinters/whitespace/whitespace.go +++ b/pkg/golinters/whitespace/whitespace.go @@ -2,7 +2,6 @@ package whitespace import ( "github.com/ultraware/whitespace" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -17,12 +16,7 @@ func New(settings *config.WhitespaceSettings) *goanalysis.Linter { } } - a := whitespace.NewAnalyzer(&wsSettings) - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(whitespace.NewAnalyzer(&wsSettings)). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/wrapcheck/wrapcheck.go b/pkg/golinters/wrapcheck/wrapcheck.go index 8a4427f7d368..c29c509a80fd 100644 --- a/pkg/golinters/wrapcheck/wrapcheck.go +++ b/pkg/golinters/wrapcheck/wrapcheck.go @@ -2,7 +2,6 @@ package wrapcheck import ( "github.com/tomarrell/wrapcheck/v2/wrapcheck" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -29,12 +28,7 @@ func New(settings *config.WrapcheckSettings) *goanalysis.Linter { } } - a := wrapcheck.NewAnalyzer(cfg) - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(wrapcheck.NewAnalyzer(cfg)). + WithLoadMode(goanalysis.LoadModeTypesInfo) } diff --git a/pkg/golinters/wsl/wsl.go b/pkg/golinters/wsl/wsl.go index 12148627eb5b..c71706f5c1d3 100644 --- a/pkg/golinters/wsl/wsl.go +++ b/pkg/golinters/wsl/wsl.go @@ -2,7 +2,6 @@ package wsl import ( "github.com/bombsimon/wsl/v4" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" @@ -10,6 +9,7 @@ import ( func New(settings *config.WSLSettings) *goanalysis.Linter { var conf *wsl.Configuration + if settings != nil { conf = &wsl.Configuration{ StrictAppend: settings.StrictAppend, @@ -30,12 +30,7 @@ func New(settings *config.WSLSettings) *goanalysis.Linter { } } - a := wsl.NewAnalyzer(conf) - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeSyntax) + return goanalysis. + NewLinterFromAnalyzer(wsl.NewAnalyzer(conf)). + WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/zerologlint/zerologlint.go b/pkg/golinters/zerologlint/zerologlint.go index 0daf0d48a4d6..46832da96c8b 100644 --- a/pkg/golinters/zerologlint/zerologlint.go +++ b/pkg/golinters/zerologlint/zerologlint.go @@ -2,18 +2,12 @@ package zerologlint import ( "github.com/ykadowak/zerologlint" - "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) func New() *goanalysis.Linter { - a := zerologlint.Analyzer - - return goanalysis.NewLinter( - a.Name, - a.Doc, - []*analysis.Analyzer{a}, - nil, - ).WithLoadMode(goanalysis.LoadModeTypesInfo) + return goanalysis. + NewLinterFromAnalyzer(zerologlint.Analyzer). + WithLoadMode(goanalysis.LoadModeTypesInfo) } From 736980cd0ec2a08b7cf88666a3e4c9665a250b71 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Wed, 14 May 2025 12:41:42 +0200 Subject: [PATCH 114/152] dev: remove AUR publishing (#5799) --- .goreleaser.yml | 72 ------------------------------------------------- 1 file changed, 72 deletions(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index 98346da5f7fd..b8bba3bea74f 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -140,78 +140,6 @@ brews: # source_repo: "https://push.chocolatey.org/" # goamd64: v1 -aurs: - - description: Fast linters runner for Go. - skip_upload: false - homepage: https://golangci.com - provides: - - "golangci-lint-bin" - maintainers: - - "Fernandez Ludovic " - license: GPL-3.0 - private_key: "{{ .Env.AUR_KEY }}" - git_url: "ssh://aur@aur.archlinux.org/golangci-lint-bin.git" - commit_author: - name: golangci-releaser - email: 65486276+golangci-releaser@users.noreply.github.com - package: |- - local x86_64=amd64 i686=386 aarch64=arm64 armv6h=armv6 armv7h=armv7 - cd "golangci-lint-${pkgver}-linux-${!CARCH}" - - # bin - install -Dm755 "./golangci-lint" "${pkgdir}/usr/bin/golangci-lint" - - # license - install -Dm644 "./LICENSE" "${pkgdir}/usr/share/licenses/golangci-lint/LICENSE" - - # completions - mkdir -p "${pkgdir}/usr/share/bash-completion/completions/" - mkdir -p "${pkgdir}/usr/share/zsh/site-functions/" - mkdir -p "${pkgdir}/usr/share/fish/vendor_completions.d/" - ./golangci-lint completion bash | install -Dm644 /dev/stdin "${pkgdir}/usr/share/bash-completion/completions/golangci-lint" - ./golangci-lint completion zsh | install -Dm644 /dev/stdin "${pkgdir}/usr/share/zsh/site-functions/_golangci-lint" - ./golangci-lint completion fish | install -Dm644 /dev/stdin "${pkgdir}/usr/share/fish/vendor_completions.d/golangci-lint.fish" - -aur_sources: - - description: Fast linters runner for Go. - skip_upload: false - homepage: https://golangci.com - provides: - - "golangci-lint" - maintainers: - - "Fernandez Ludovic " - license: GPL-3.0 - private_key: "{{ .Env.AUR_KEY }}" - git_url: "ssh://aur@aur.archlinux.org/golangci-lint.git" - commit_author: - name: golangci-releaser - email: 65486276+golangci-releaser@users.noreply.github.com - build: |- - local _commit _flags - _commit=$(bsdcat "${pkgname}_${pkgver}.tar.gz" | git get-tar-commit-id) - _flags=( - -X=main.version="$pkgver" - -X=main.commit="${_commit::7}" - -X=main.date="$(date -u -d "@${SOURCE_DATE_EPOCH}" +'%FT%TZ')" - -linkmode=external - ) - export CGO_ENABLED=1 - export CGO_CFLAGS="${CFLAGS}" - export CGO_CPPFLAGS="$CPPFLAGS" - export CGO_CXXFLAGS="$CXXFLAGS" - export CGO_LDFLAGS="${LDFLAGS}" - export GOFLAGS='-buildmode=pie -trimpath -modcacherw' - - go build -o "$pkgname" -ldflags="${_flags[*]}" ./cmd/"$pkgname" - ./"$pkgname" completion bash > completion.bash - ./"$pkgname" completion zsh > completion.zsh - ./"$pkgname" completion fish > completion.fish - package: |- - install -Dm755 "$pkgname" -t "$pkgdir"/usr/bin - install -Dm644 completion.bash "$pkgdir"/usr/share/bash-completion/completions/"$pkgname" - install -Dm644 completion.zsh "$pkgdir"/usr/share/zsh/site-functions/_"$pkgname" - install -Dm644 completion.fish "$pkgdir"/usr/share/fish/vendor_completions.d/"$pkgname".fish - snapcrafts: - summary: Fast linters runner for Go. description: | From 522c98c0bb57d46f2b6960867adb320da50a9b31 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Wed, 14 May 2025 21:43:06 +0200 Subject: [PATCH 115/152] dev: restore aur-bin (#5803) --- .goreleaser.yml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/.goreleaser.yml b/.goreleaser.yml index b8bba3bea74f..d40fb1a4a034 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -140,6 +140,38 @@ brews: # source_repo: "https://push.chocolatey.org/" # goamd64: v1 +aurs: + - description: Fast linters runner for Go. + skip_upload: false + homepage: https://golangci.com + provides: + - "golangci-lint-bin" + maintainers: + - "Fernandez Ludovic " + license: GPL-3.0 + private_key: "{{ .Env.AUR_KEY }}" + git_url: "ssh://aur@aur.archlinux.org/golangci-lint-bin.git" + commit_author: + name: golangci-releaser + email: 65486276+golangci-releaser@users.noreply.github.com + package: |- + local x86_64=amd64 i686=386 aarch64=arm64 armv6h=armv6 armv7h=armv7 + cd "golangci-lint-${pkgver}-linux-${!CARCH}" + + # bin + install -Dm755 "./golangci-lint" "${pkgdir}/usr/bin/golangci-lint" + + # license + install -Dm644 "./LICENSE" "${pkgdir}/usr/share/licenses/golangci-lint/LICENSE" + + # completions + mkdir -p "${pkgdir}/usr/share/bash-completion/completions/" + mkdir -p "${pkgdir}/usr/share/zsh/site-functions/" + mkdir -p "${pkgdir}/usr/share/fish/vendor_completions.d/" + ./golangci-lint completion bash | install -Dm644 /dev/stdin "${pkgdir}/usr/share/bash-completion/completions/golangci-lint" + ./golangci-lint completion zsh | install -Dm644 /dev/stdin "${pkgdir}/usr/share/zsh/site-functions/_golangci-lint" + ./golangci-lint completion fish | install -Dm644 /dev/stdin "${pkgdir}/usr/share/fish/vendor_completions.d/golangci-lint.fish" + snapcrafts: - summary: Fast linters runner for Go. description: | From 37932d1812d56aff9409ddde35e779a5ebfc854b Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Wed, 14 May 2025 21:45:30 +0200 Subject: [PATCH 116/152] chore: remove dead code (#5801) --- pkg/golinters/dupl/dupl.go | 2 +- pkg/golinters/errcheck/errcheck.go | 6 +++--- pkg/golinters/gochecknoinits/gochecknoinits.go | 2 +- pkg/golinters/gocognit/gocognit.go | 2 +- pkg/golinters/goconst/goconst.go | 6 +++--- pkg/golinters/gocyclo/gocyclo.go | 2 +- pkg/golinters/internal/util.go | 3 +-- pkg/golinters/prealloc/prealloc.go | 2 +- 8 files changed, 12 insertions(+), 13 deletions(-) diff --git a/pkg/golinters/dupl/dupl.go b/pkg/golinters/dupl/dupl.go index 654c795ff696..6d5323a8bad4 100644 --- a/pkg/golinters/dupl/dupl.go +++ b/pkg/golinters/dupl/dupl.go @@ -70,7 +70,7 @@ func runDupl(pass *analysis.Pass, settings *config.DuplSettings) ([]goanalysis.I dupl := fmt.Sprintf("%s:%d-%d", toFilename, i.To.LineStart(), i.To.LineEnd()) text := fmt.Sprintf("%d-%d lines are duplicate of %s", i.From.LineStart(), i.From.LineEnd(), - internal.FormatCode(dupl, nil)) + internal.FormatCode(dupl)) res = append(res, goanalysis.NewIssue(&result.Issue{ Pos: token.Position{ diff --git a/pkg/golinters/errcheck/errcheck.go b/pkg/golinters/errcheck/errcheck.go index c3c813d4f828..2e2136caa2ea 100644 --- a/pkg/golinters/errcheck/errcheck.go +++ b/pkg/golinters/errcheck/errcheck.go @@ -37,7 +37,7 @@ func New(settings *config.ErrcheckSettings) *goanalysis.Linter { checker.Tags = lintCtx.Cfg.Run.BuildTags analyzer.Run = func(pass *analysis.Pass) (any, error) { - issues := runErrCheck(lintCtx, pass, checker) + issues := runErrCheck(pass, checker) if len(issues) == 0 { return nil, nil @@ -56,7 +56,7 @@ func New(settings *config.ErrcheckSettings) *goanalysis.Linter { WithLoadMode(goanalysis.LoadModeTypesInfo) } -func runErrCheck(lintCtx *linter.Context, pass *analysis.Pass, checker *errcheck.Checker) []goanalysis.Issue { +func runErrCheck(pass *analysis.Pass, checker *errcheck.Checker) []goanalysis.Issue { pkg := &packages.Package{ Fset: pass.Fset, Syntax: pass.Files, @@ -77,7 +77,7 @@ func runErrCheck(lintCtx *linter.Context, pass *analysis.Pass, checker *errcheck if err.FuncName != "" { code := cmp.Or(err.SelectorName, err.FuncName) - text = fmt.Sprintf("Error return value of %s is not checked", internal.FormatCode(code, lintCtx.Cfg)) + text = fmt.Sprintf("Error return value of %s is not checked", internal.FormatCode(code)) } issues[i] = goanalysis.NewIssue( diff --git a/pkg/golinters/gochecknoinits/gochecknoinits.go b/pkg/golinters/gochecknoinits/gochecknoinits.go index c027aa8ab928..9158ee07da55 100644 --- a/pkg/golinters/gochecknoinits/gochecknoinits.go +++ b/pkg/golinters/gochecknoinits/gochecknoinits.go @@ -40,7 +40,7 @@ func run(pass *analysis.Pass) (any, error) { fnName := funcDecl.Name.Name if fnName == "init" && funcDecl.Recv.NumFields() == 0 { - pass.Reportf(funcDecl.Pos(), "don't use %s function", internal.FormatCode(fnName, nil)) + pass.Reportf(funcDecl.Pos(), "don't use %s function", internal.FormatCode(fnName)) } }) diff --git a/pkg/golinters/gocognit/gocognit.go b/pkg/golinters/gocognit/gocognit.go index e60bcfb17080..e72a9bdfe67a 100644 --- a/pkg/golinters/gocognit/gocognit.go +++ b/pkg/golinters/gocognit/gocognit.go @@ -67,7 +67,7 @@ func runGocognit(pass *analysis.Pass, settings *config.GocognitSettings) []goana issues = append(issues, goanalysis.NewIssue(&result.Issue{ Pos: s.Pos, Text: fmt.Sprintf("cognitive complexity %d of func %s is high (> %d)", - s.Complexity, internal.FormatCode(s.FuncName, nil), settings.MinComplexity), + s.Complexity, internal.FormatCode(s.FuncName), settings.MinComplexity), FromLinter: linterName, }, pass)) } diff --git a/pkg/golinters/goconst/goconst.go b/pkg/golinters/goconst/goconst.go index f32a4c6575e2..5a44d4a5ce3a 100644 --- a/pkg/golinters/goconst/goconst.go +++ b/pkg/golinters/goconst/goconst.go @@ -85,17 +85,17 @@ func runGoconst(pass *analysis.Pass, settings *config.GoConstSettings) ([]goanal switch { case issue.OccurrencesCount > 0: - text = fmt.Sprintf("string %s has %d occurrences", internal.FormatCode(issue.Str, nil), issue.OccurrencesCount) + text = fmt.Sprintf("string %s has %d occurrences", internal.FormatCode(issue.Str), issue.OccurrencesCount) if issue.MatchingConst == "" { text += ", make it a constant" } else { - text += fmt.Sprintf(", but such constant %s already exists", internal.FormatCode(issue.MatchingConst, nil)) + text += fmt.Sprintf(", but such constant %s already exists", internal.FormatCode(issue.MatchingConst)) } case issue.DuplicateConst != "": text = fmt.Sprintf("This constant is a duplicate of %s at %s", - internal.FormatCode(issue.DuplicateConst, nil), + internal.FormatCode(issue.DuplicateConst), issue.DuplicatePos.String()) default: diff --git a/pkg/golinters/gocyclo/gocyclo.go b/pkg/golinters/gocyclo/gocyclo.go index 514194709385..17b868d4972a 100644 --- a/pkg/golinters/gocyclo/gocyclo.go +++ b/pkg/golinters/gocyclo/gocyclo.go @@ -59,7 +59,7 @@ func runGoCyclo(pass *analysis.Pass, settings *config.GoCycloSettings) []goanaly for _, s := range stats { text := fmt.Sprintf("cyclomatic complexity %d of func %s is high (> %d)", - s.Complexity, internal.FormatCode(s.FuncName, nil), settings.MinComplexity) + s.Complexity, internal.FormatCode(s.FuncName), settings.MinComplexity) issues = append(issues, goanalysis.NewIssue(&result.Issue{ Pos: s.Pos, diff --git a/pkg/golinters/internal/util.go b/pkg/golinters/internal/util.go index 2e5fb29f91c9..86137cf66081 100644 --- a/pkg/golinters/internal/util.go +++ b/pkg/golinters/internal/util.go @@ -6,11 +6,10 @@ import ( "golang.org/x/tools/go/analysis" - "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) -func FormatCode(code string, _ *config.Config) string { +func FormatCode(code string) string { if strings.Contains(code, "`") { return code // TODO: properly escape or remove } diff --git a/pkg/golinters/prealloc/prealloc.go b/pkg/golinters/prealloc/prealloc.go index 66890ad5bc61..c750df990459 100644 --- a/pkg/golinters/prealloc/prealloc.go +++ b/pkg/golinters/prealloc/prealloc.go @@ -31,7 +31,7 @@ func runPreAlloc(pass *analysis.Pass, settings *config.PreallocSettings) { for _, hint := range hints { pass.Report(analysis.Diagnostic{ Pos: hint.Pos, - Message: fmt.Sprintf("Consider pre-allocating %s", internal.FormatCode(hint.DeclaredSliceName, nil)), + Message: fmt.Sprintf("Consider pre-allocating %s", internal.FormatCode(hint.DeclaredSliceName)), }) } } From deee4e75cd912954538449a2f35d795ea04545ce Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Thu, 15 May 2025 11:23:02 +0200 Subject: [PATCH 117/152] errcheck: add verbose option (#5802) --- .golangci.next.reference.yml | 4 ++++ jsonschema/golangci.next.jsonschema.json | 5 +++++ pkg/config/linters_settings.go | 1 + pkg/golinters/errcheck/errcheck.go | 7 +++++-- 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index ff015539fabb..9801a5c3ff87 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -408,6 +408,10 @@ linters: - io.Copy(*bytes.Buffer) - io.Copy(os.Stdout) + # Display function signature instead of selector. + # Default: false + verbose: true + errchkjson: # With check-error-free-encoding set to true, errchkjson does warn about errors # from json encoding functions that are safe to be ignored, diff --git a/jsonschema/golangci.next.jsonschema.json b/jsonschema/golangci.next.jsonschema.json index 9da8ac328072..e98d54dc4dc4 100644 --- a/jsonschema/golangci.next.jsonschema.json +++ b/jsonschema/golangci.next.jsonschema.json @@ -1115,6 +1115,11 @@ "description": "To disable the errcheck built-in exclude list", "type": "boolean", "default": false + }, + "verbose": { + "description": "Display function signature instead of selector", + "type": "boolean", + "default": false } } }, diff --git a/pkg/config/linters_settings.go b/pkg/config/linters_settings.go index 065abfab47c1..cadb4a765914 100644 --- a/pkg/config/linters_settings.go +++ b/pkg/config/linters_settings.go @@ -372,6 +372,7 @@ type ErrcheckSettings struct { CheckTypeAssertions bool `mapstructure:"check-type-assertions"` CheckAssignToBlank bool `mapstructure:"check-blank"` ExcludeFunctions []string `mapstructure:"exclude-functions"` + Verbose bool `mapstructure:"verbose"` } type ErrChkJSONSettings struct { diff --git a/pkg/golinters/errcheck/errcheck.go b/pkg/golinters/errcheck/errcheck.go index 2e2136caa2ea..ae34a53ef62c 100644 --- a/pkg/golinters/errcheck/errcheck.go +++ b/pkg/golinters/errcheck/errcheck.go @@ -37,7 +37,7 @@ func New(settings *config.ErrcheckSettings) *goanalysis.Linter { checker.Tags = lintCtx.Cfg.Run.BuildTags analyzer.Run = func(pass *analysis.Pass) (any, error) { - issues := runErrCheck(pass, checker) + issues := runErrCheck(pass, checker, settings.Verbose) if len(issues) == 0 { return nil, nil @@ -56,7 +56,7 @@ func New(settings *config.ErrcheckSettings) *goanalysis.Linter { WithLoadMode(goanalysis.LoadModeTypesInfo) } -func runErrCheck(pass *analysis.Pass, checker *errcheck.Checker) []goanalysis.Issue { +func runErrCheck(pass *analysis.Pass, checker *errcheck.Checker, verbose bool) []goanalysis.Issue { pkg := &packages.Package{ Fset: pass.Fset, Syntax: pass.Files, @@ -76,6 +76,9 @@ func runErrCheck(pass *analysis.Pass, checker *errcheck.Checker) []goanalysis.Is if err.FuncName != "" { code := cmp.Or(err.SelectorName, err.FuncName) + if verbose { + code = err.FuncName + } text = fmt.Sprintf("Error return value of %s is not checked", internal.FormatCode(code)) } From ccf16f7213cccce4c6e5d5896a18e148e4392b81 Mon Sep 17 00:00:00 2001 From: Takeo Kasai <73113050+take0fit@users.noreply.github.com> Date: Fri, 16 May 2025 04:36:37 +0900 Subject: [PATCH 118/152] docs: fix revive defer rule configuration (#5804) Co-authored-by: Fernandez Ludovic --- .golangci.reference.yml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.golangci.reference.yml b/.golangci.reference.yml index 37866ff00f2c..6aad45d89868 100644 --- a/.golangci.reference.yml +++ b/.golangci.reference.yml @@ -2300,12 +2300,11 @@ linters: disabled: false exclude: [""] arguments: - - "call-chain" - - "loop" - - "method-call" - - "recover" - - "immediate-recover" - - "return" + - - "call-chain" + - "loop" + - "method-call" + - "recover" + - "return" # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#dot-imports - name: dot-imports severity: warning From f5f2c1654bc47cbde49e6849acc9e2b30da2fda0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 18 May 2025 23:40:52 +0200 Subject: [PATCH 119/152] build(deps): bump github.com/Abirdcfly/dupword from 0.1.3 to 0.1.4 (#5809) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ca6b23a4880b..ad7a63bd6abc 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( 4d63.com/gocheckcompilerdirectives v1.3.0 4d63.com/gochecknoglobals v0.2.2 github.com/4meepo/tagalign v1.4.2 - github.com/Abirdcfly/dupword v0.1.3 + github.com/Abirdcfly/dupword v0.1.4 github.com/Antonboom/errname v1.1.0 github.com/Antonboom/nilnil v1.1.0 github.com/Antonboom/testifylint v1.6.1 diff --git a/go.sum b/go.sum index 6c6f2bf9639b..0cb2e8b15c54 100644 --- a/go.sum +++ b/go.sum @@ -37,8 +37,8 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/4meepo/tagalign v1.4.2 h1:0hcLHPGMjDyM1gHG58cS73aQF8J4TdVR96TZViorO9E= github.com/4meepo/tagalign v1.4.2/go.mod h1:+p4aMyFM+ra7nb41CnFG6aSDXqRxU/w1VQqScKqDARI= -github.com/Abirdcfly/dupword v0.1.3 h1:9Pa1NuAsZvpFPi9Pqkd93I7LIYRURj+A//dFd5tgBeE= -github.com/Abirdcfly/dupword v0.1.3/go.mod h1:8VbB2t7e10KRNdwTVoxdBaxla6avbhGzb8sCTygUMhw= +github.com/Abirdcfly/dupword v0.1.4 h1:jxqkdgO0L7FSwq4fMu3d+fAA1E3bBQAtl4utA3tcQZM= +github.com/Abirdcfly/dupword v0.1.4/go.mod h1:s+BFMuL/I4YSiFv29snqyjwzDp4b65W2Kvy+PKzZ6cw= github.com/Antonboom/errname v1.1.0 h1:A+ucvdpMwlo/myWrkHEUEBWc/xuXdud23S8tmTb/oAE= github.com/Antonboom/errname v1.1.0/go.mod h1:O1NMrzgUcVBGIfi3xlVuvX8Q/VP/73sseCaAppfjqZw= github.com/Antonboom/nilnil v1.1.0 h1:jGxJxjgYS3VUUtOTNk8Z1icwT5ESpLH/426fjmQG+ng= From 66fc278beb5bae9ccce66711ee1223efc56aef69 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 18 May 2025 23:41:08 +0200 Subject: [PATCH 120/152] build(deps): bump github.com/uudashr/iface from 1.3.1 to 1.3.2 (#5810) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ad7a63bd6abc..0f444d56424b 100644 --- a/go.mod +++ b/go.mod @@ -119,7 +119,7 @@ require ( github.com/ultraware/funlen v0.2.0 github.com/ultraware/whitespace v0.2.0 github.com/uudashr/gocognit v1.2.0 - github.com/uudashr/iface v1.3.1 + github.com/uudashr/iface v1.3.2 github.com/valyala/quicktemplate v1.8.0 github.com/xen0n/gosmopolitan v1.3.0 github.com/yagipy/maintidx v1.0.0 diff --git a/go.sum b/go.sum index 0cb2e8b15c54..0873061afebd 100644 --- a/go.sum +++ b/go.sum @@ -598,8 +598,8 @@ github.com/ultraware/whitespace v0.2.0 h1:TYowo2m9Nfj1baEQBjuHzvMRbp19i+RCcRYrSW github.com/ultraware/whitespace v0.2.0/go.mod h1:XcP1RLD81eV4BW8UhQlpaR+SDc2givTvyI8a586WjW8= github.com/uudashr/gocognit v1.2.0 h1:3BU9aMr1xbhPlvJLSydKwdLN3tEUUrzPSSM8S4hDYRA= github.com/uudashr/gocognit v1.2.0/go.mod h1:k/DdKPI6XBZO1q7HgoV2juESI2/Ofj9AcHPZhBBdrTU= -github.com/uudashr/iface v1.3.1 h1:bA51vmVx1UIhiIsQFSNq6GZ6VPTk3WNMZgRiCe9R29U= -github.com/uudashr/iface v1.3.1/go.mod h1:4QvspiRd3JLPAEXBQ9AiZpLbJlrWWgRChOKDJEuQTdg= +github.com/uudashr/iface v1.3.2 h1:viQ7WtLvznR+Z4H+IP/fqhqPl3UF9Y2aj6wTeHF6X+Y= +github.com/uudashr/iface v1.3.2/go.mod h1:i/H4cfRMPe0izticV8Yz0g6/zcsh5xXlvthrdh1kqcY= 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/quicktemplate v1.8.0 h1:zU0tjbIqTRgKQzFY1L42zq0qR3eh4WoQQdIdqCysW5k= From 58036ddeefcfc8814b9787742a6985b13d02c4b0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 18 May 2025 23:42:58 +0200 Subject: [PATCH 121/152] build(deps): bump github.com/alecthomas/chroma/v2 from 2.17.2 to 2.18.0 (#5812) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 0f444d56424b..f4c0b3ced505 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1 github.com/OpenPeeDeeP/depguard/v2 v2.2.1 - github.com/alecthomas/chroma/v2 v2.17.2 + github.com/alecthomas/chroma/v2 v2.18.0 github.com/alecthomas/go-check-sumtype v0.3.1 github.com/alexkohler/nakedret/v2 v2.0.6 github.com/alexkohler/prealloc v1.0.0 diff --git a/go.sum b/go.sum index 0873061afebd..cf2b6fbc84a9 100644 --- a/go.sum +++ b/go.sum @@ -59,8 +59,8 @@ github.com/OpenPeeDeeP/depguard/v2 v2.2.1 h1:vckeWVESWp6Qog7UZSARNqfu/cZqvki8zsu github.com/OpenPeeDeeP/depguard/v2 v2.2.1/go.mod h1:q4DKzC4UcVaAvcfd41CZh0PWpGgzrVxUYBlgKNGquUo= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= -github.com/alecthomas/chroma/v2 v2.17.2 h1:Rm81SCZ2mPoH+Q8ZCc/9YvzPUN/E7HgPiPJD8SLV6GI= -github.com/alecthomas/chroma/v2 v2.17.2/go.mod h1:RVX6AvYm4VfYe/zsk7mjHueLDZor3aWCNE14TFlepBk= +github.com/alecthomas/chroma/v2 v2.18.0 h1:6h53Q4hW83SuF+jcsp7CVhLsMozzvQvO8HBbKQW+gn4= +github.com/alecthomas/chroma/v2 v2.18.0/go.mod h1:RVX6AvYm4VfYe/zsk7mjHueLDZor3aWCNE14TFlepBk= github.com/alecthomas/go-check-sumtype v0.3.1 h1:u9aUvbGINJxLVXiFvHUlPEaD7VDULsrxJb4Aq31NLkU= github.com/alecthomas/go-check-sumtype v0.3.1/go.mod h1:A8TSiN3UPRw3laIgWEUOHHLPa6/r9MtoigdlP5h3K/E= github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= From 8e38a6ef025ba738f23ca4a34d6d86eec0d99a72 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 May 2025 00:21:15 +0200 Subject: [PATCH 122/152] build(deps): bump github.com/manuelarte/embeddedstructfieldcheck from 0.2.1 to 0.3.0 (#5811) Co-authored-by: Fernandez Ludovic --- .golangci.next.reference.yml | 5 + go.mod | 2 +- go.sum | 4 +- jsonschema/golangci.next.jsonschema.json | 14 ++ pkg/config/linters_settings.go | 161 +++++++++--------- .../embeddedstructfieldcheck.go | 12 +- .../embeddedstructfieldcheck_comments.go | 2 +- .../embeddedstructfieldcheck_mutex.go | 29 ++++ .../embeddedstructfieldcheck_mutex.yml | 6 + .../embeddedstructfieldcheck_simple.go | 2 +- .../embeddedstructfieldcheck_special_cases.go | 2 +- pkg/lint/lintersdb/builder_linter.go | 2 +- 12 files changed, 155 insertions(+), 86 deletions(-) create mode 100644 pkg/golinters/embeddedstructfieldcheck/testdata/embeddedstructfieldcheck_mutex.go create mode 100644 pkg/golinters/embeddedstructfieldcheck/testdata/embeddedstructfieldcheck_mutex.yml diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index 9801a5c3ff87..8a4fc69e22b1 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -385,6 +385,11 @@ linters: ignore: - "0C0C" + embeddedstructfieldcheck: + # Checks that sync.Mutex and sync.RWMutex are not used as embedded fields. + # Default: false + forbid-mutex: true + errcheck: # Report about not checking of errors in type assertions: `a := b.(MyStruct)`. # Such cases aren't reported by default. diff --git a/go.mod b/go.mod index f4c0b3ced505..7a1711e4277a 100644 --- a/go.mod +++ b/go.mod @@ -74,7 +74,7 @@ require ( github.com/ldez/usetesting v0.4.3 github.com/leonklingele/grouper v1.1.2 github.com/macabu/inamedparam v0.2.0 - github.com/manuelarte/embeddedstructfieldcheck v0.2.1 + github.com/manuelarte/embeddedstructfieldcheck v0.3.0 github.com/manuelarte/funcorder v0.5.0 github.com/maratori/testableexamples v1.0.0 github.com/maratori/testpackage v1.1.1 diff --git a/go.sum b/go.sum index cf2b6fbc84a9..ba8cde2b19d6 100644 --- a/go.sum +++ b/go.sum @@ -391,8 +391,8 @@ github.com/macabu/inamedparam v0.2.0 h1:VyPYpOc10nkhI2qeNUdh3Zket4fcZjEWe35poddB github.com/macabu/inamedparam v0.2.0/go.mod h1:+Pee9/YfGe5LJ62pYXqB89lJ+0k5bsR8Wgz/C0Zlq3U= github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/manuelarte/embeddedstructfieldcheck v0.2.1 h1:oKexdVGs8Jy31IzOD/EMKfZmgogFhAaDbHb1o0qmA1Q= -github.com/manuelarte/embeddedstructfieldcheck v0.2.1/go.mod h1:LSo/IQpPfx1dXMcX4ibZCYA7Yy6ayZHIaOGM70+1Wy8= +github.com/manuelarte/embeddedstructfieldcheck v0.3.0 h1:VhGqK8gANDvFYDxQkjPbv7/gDJtsGU9k6qj/hC2hgso= +github.com/manuelarte/embeddedstructfieldcheck v0.3.0/go.mod h1:LSo/IQpPfx1dXMcX4ibZCYA7Yy6ayZHIaOGM70+1Wy8= github.com/manuelarte/funcorder v0.5.0 h1:llMuHXXbg7tD0i/LNw8vGnkDTHFpTnWqKPI85Rknc+8= github.com/manuelarte/funcorder v0.5.0/go.mod h1:Yt3CiUQthSBMBxjShjdXMexmzpP8YGvGLjrxJNkO2hA= github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI= diff --git a/jsonschema/golangci.next.jsonschema.json b/jsonschema/golangci.next.jsonschema.json index e98d54dc4dc4..ef1c956ef1c4 100644 --- a/jsonschema/golangci.next.jsonschema.json +++ b/jsonschema/golangci.next.jsonschema.json @@ -1089,6 +1089,17 @@ } } }, + "embeddedstructfieldcheckSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "forbid-mutex": { + "description": "Checks that sync.Mutex and sync.RWMutex are not used as embedded fields.", + "type": "boolean", + "default": false + } + } + }, "errcheckSettings": { "type": "object", "additionalProperties": false, @@ -4356,6 +4367,9 @@ "dupl": { "$ref": "#/definitions/settings/definitions/duplSettings" }, + "embeddedstructfieldcheck": { + "$ref": "#/definitions/settings/definitions/embeddedstructfieldcheckSettings" + }, "errcheck": { "$ref": "#/definitions/settings/definitions/errcheckSettings" }, diff --git a/pkg/config/linters_settings.go b/pkg/config/linters_settings.go index cadb4a765914..2398186d3812 100644 --- a/pkg/config/linters_settings.go +++ b/pkg/config/linters_settings.go @@ -205,84 +205,85 @@ var defaultLintersSettings = LintersSettings{ type LintersSettings struct { FormatterSettings `mapstructure:"-"` - Asasalint AsasalintSettings `mapstructure:"asasalint"` - BiDiChk BiDiChkSettings `mapstructure:"bidichk"` - CopyLoopVar CopyLoopVarSettings `mapstructure:"copyloopvar"` - Cyclop CyclopSettings `mapstructure:"cyclop"` - Decorder DecorderSettings `mapstructure:"decorder"` - Depguard DepGuardSettings `mapstructure:"depguard"` - Dogsled DogsledSettings `mapstructure:"dogsled"` - Dupl DuplSettings `mapstructure:"dupl"` - DupWord DupWordSettings `mapstructure:"dupword"` - Errcheck ErrcheckSettings `mapstructure:"errcheck"` - ErrChkJSON ErrChkJSONSettings `mapstructure:"errchkjson"` - ErrorLint ErrorLintSettings `mapstructure:"errorlint"` - Exhaustive ExhaustiveSettings `mapstructure:"exhaustive"` - Exhaustruct ExhaustructSettings `mapstructure:"exhaustruct"` - Fatcontext FatcontextSettings `mapstructure:"fatcontext"` - Forbidigo ForbidigoSettings `mapstructure:"forbidigo"` - FuncOrder FuncOrderSettings `mapstructure:"funcorder"` - Funlen FunlenSettings `mapstructure:"funlen"` - GinkgoLinter GinkgoLinterSettings `mapstructure:"ginkgolinter"` - Gocognit GocognitSettings `mapstructure:"gocognit"` - GoChecksumType GoChecksumTypeSettings `mapstructure:"gochecksumtype"` - Goconst GoConstSettings `mapstructure:"goconst"` - Gocritic GoCriticSettings `mapstructure:"gocritic"` - Gocyclo GoCycloSettings `mapstructure:"gocyclo"` - Godot GodotSettings `mapstructure:"godot"` - Godox GodoxSettings `mapstructure:"godox"` - Goheader GoHeaderSettings `mapstructure:"goheader"` - GoModDirectives GoModDirectivesSettings `mapstructure:"gomoddirectives"` - Gomodguard GoModGuardSettings `mapstructure:"gomodguard"` - Gosec GoSecSettings `mapstructure:"gosec"` - Gosmopolitan GosmopolitanSettings `mapstructure:"gosmopolitan"` - Govet GovetSettings `mapstructure:"govet"` - Grouper GrouperSettings `mapstructure:"grouper"` - Iface IfaceSettings `mapstructure:"iface"` - ImportAs ImportAsSettings `mapstructure:"importas"` - Inamedparam INamedParamSettings `mapstructure:"inamedparam"` - InterfaceBloat InterfaceBloatSettings `mapstructure:"interfacebloat"` - Ireturn IreturnSettings `mapstructure:"ireturn"` - Lll LllSettings `mapstructure:"lll"` - LoggerCheck LoggerCheckSettings `mapstructure:"loggercheck"` - MaintIdx MaintIdxSettings `mapstructure:"maintidx"` - Makezero MakezeroSettings `mapstructure:"makezero"` - Misspell MisspellSettings `mapstructure:"misspell"` - Mnd MndSettings `mapstructure:"mnd"` - MustTag MustTagSettings `mapstructure:"musttag"` - Nakedret NakedretSettings `mapstructure:"nakedret"` - Nestif NestifSettings `mapstructure:"nestif"` - NilNil NilNilSettings `mapstructure:"nilnil"` - Nlreturn NlreturnSettings `mapstructure:"nlreturn"` - NoLintLint NoLintLintSettings `mapstructure:"nolintlint"` - NoNamedReturns NoNamedReturnsSettings `mapstructure:"nonamedreturns"` - ParallelTest ParallelTestSettings `mapstructure:"paralleltest"` - PerfSprint PerfSprintSettings `mapstructure:"perfsprint"` - Prealloc PreallocSettings `mapstructure:"prealloc"` - Predeclared PredeclaredSettings `mapstructure:"predeclared"` - Promlinter PromlinterSettings `mapstructure:"promlinter"` - ProtoGetter ProtoGetterSettings `mapstructure:"protogetter"` - Reassign ReassignSettings `mapstructure:"reassign"` - Recvcheck RecvcheckSettings `mapstructure:"recvcheck"` - Revive ReviveSettings `mapstructure:"revive"` - RowsErrCheck RowsErrCheckSettings `mapstructure:"rowserrcheck"` - SlogLint SlogLintSettings `mapstructure:"sloglint"` - Spancheck SpancheckSettings `mapstructure:"spancheck"` - Staticcheck StaticCheckSettings `mapstructure:"staticcheck"` - TagAlign TagAlignSettings `mapstructure:"tagalign"` - Tagliatelle TagliatelleSettings `mapstructure:"tagliatelle"` - Testifylint TestifylintSettings `mapstructure:"testifylint"` - Testpackage TestpackageSettings `mapstructure:"testpackage"` - Thelper ThelperSettings `mapstructure:"thelper"` - Unconvert UnconvertSettings `mapstructure:"unconvert"` - Unparam UnparamSettings `mapstructure:"unparam"` - Unused UnusedSettings `mapstructure:"unused"` - UseStdlibVars UseStdlibVarsSettings `mapstructure:"usestdlibvars"` - UseTesting UseTestingSettings `mapstructure:"usetesting"` - Varnamelen VarnamelenSettings `mapstructure:"varnamelen"` - Whitespace WhitespaceSettings `mapstructure:"whitespace"` - Wrapcheck WrapcheckSettings `mapstructure:"wrapcheck"` - WSL WSLSettings `mapstructure:"wsl"` + Asasalint AsasalintSettings `mapstructure:"asasalint"` + BiDiChk BiDiChkSettings `mapstructure:"bidichk"` + CopyLoopVar CopyLoopVarSettings `mapstructure:"copyloopvar"` + Cyclop CyclopSettings `mapstructure:"cyclop"` + Decorder DecorderSettings `mapstructure:"decorder"` + Depguard DepGuardSettings `mapstructure:"depguard"` + Dogsled DogsledSettings `mapstructure:"dogsled"` + Dupl DuplSettings `mapstructure:"dupl"` + DupWord DupWordSettings `mapstructure:"dupword"` + EmbeddedStructFieldCheck EmbeddedStructFieldCheckSettings `mapstructure:"embeddedstructfieldcheck"` + Errcheck ErrcheckSettings `mapstructure:"errcheck"` + ErrChkJSON ErrChkJSONSettings `mapstructure:"errchkjson"` + ErrorLint ErrorLintSettings `mapstructure:"errorlint"` + Exhaustive ExhaustiveSettings `mapstructure:"exhaustive"` + Exhaustruct ExhaustructSettings `mapstructure:"exhaustruct"` + Fatcontext FatcontextSettings `mapstructure:"fatcontext"` + Forbidigo ForbidigoSettings `mapstructure:"forbidigo"` + FuncOrder FuncOrderSettings `mapstructure:"funcorder"` + Funlen FunlenSettings `mapstructure:"funlen"` + GinkgoLinter GinkgoLinterSettings `mapstructure:"ginkgolinter"` + Gocognit GocognitSettings `mapstructure:"gocognit"` + GoChecksumType GoChecksumTypeSettings `mapstructure:"gochecksumtype"` + Goconst GoConstSettings `mapstructure:"goconst"` + Gocritic GoCriticSettings `mapstructure:"gocritic"` + Gocyclo GoCycloSettings `mapstructure:"gocyclo"` + Godot GodotSettings `mapstructure:"godot"` + Godox GodoxSettings `mapstructure:"godox"` + Goheader GoHeaderSettings `mapstructure:"goheader"` + GoModDirectives GoModDirectivesSettings `mapstructure:"gomoddirectives"` + Gomodguard GoModGuardSettings `mapstructure:"gomodguard"` + Gosec GoSecSettings `mapstructure:"gosec"` + Gosmopolitan GosmopolitanSettings `mapstructure:"gosmopolitan"` + Govet GovetSettings `mapstructure:"govet"` + Grouper GrouperSettings `mapstructure:"grouper"` + Iface IfaceSettings `mapstructure:"iface"` + ImportAs ImportAsSettings `mapstructure:"importas"` + Inamedparam INamedParamSettings `mapstructure:"inamedparam"` + InterfaceBloat InterfaceBloatSettings `mapstructure:"interfacebloat"` + Ireturn IreturnSettings `mapstructure:"ireturn"` + Lll LllSettings `mapstructure:"lll"` + LoggerCheck LoggerCheckSettings `mapstructure:"loggercheck"` + MaintIdx MaintIdxSettings `mapstructure:"maintidx"` + Makezero MakezeroSettings `mapstructure:"makezero"` + Misspell MisspellSettings `mapstructure:"misspell"` + Mnd MndSettings `mapstructure:"mnd"` + MustTag MustTagSettings `mapstructure:"musttag"` + Nakedret NakedretSettings `mapstructure:"nakedret"` + Nestif NestifSettings `mapstructure:"nestif"` + NilNil NilNilSettings `mapstructure:"nilnil"` + Nlreturn NlreturnSettings `mapstructure:"nlreturn"` + NoLintLint NoLintLintSettings `mapstructure:"nolintlint"` + NoNamedReturns NoNamedReturnsSettings `mapstructure:"nonamedreturns"` + ParallelTest ParallelTestSettings `mapstructure:"paralleltest"` + PerfSprint PerfSprintSettings `mapstructure:"perfsprint"` + Prealloc PreallocSettings `mapstructure:"prealloc"` + Predeclared PredeclaredSettings `mapstructure:"predeclared"` + Promlinter PromlinterSettings `mapstructure:"promlinter"` + ProtoGetter ProtoGetterSettings `mapstructure:"protogetter"` + Reassign ReassignSettings `mapstructure:"reassign"` + Recvcheck RecvcheckSettings `mapstructure:"recvcheck"` + Revive ReviveSettings `mapstructure:"revive"` + RowsErrCheck RowsErrCheckSettings `mapstructure:"rowserrcheck"` + SlogLint SlogLintSettings `mapstructure:"sloglint"` + Spancheck SpancheckSettings `mapstructure:"spancheck"` + Staticcheck StaticCheckSettings `mapstructure:"staticcheck"` + TagAlign TagAlignSettings `mapstructure:"tagalign"` + Tagliatelle TagliatelleSettings `mapstructure:"tagliatelle"` + Testifylint TestifylintSettings `mapstructure:"testifylint"` + Testpackage TestpackageSettings `mapstructure:"testpackage"` + Thelper ThelperSettings `mapstructure:"thelper"` + Unconvert UnconvertSettings `mapstructure:"unconvert"` + Unparam UnparamSettings `mapstructure:"unparam"` + Unused UnusedSettings `mapstructure:"unused"` + UseStdlibVars UseStdlibVarsSettings `mapstructure:"usestdlibvars"` + UseTesting UseTestingSettings `mapstructure:"usetesting"` + Varnamelen VarnamelenSettings `mapstructure:"varnamelen"` + Whitespace WhitespaceSettings `mapstructure:"whitespace"` + Wrapcheck WrapcheckSettings `mapstructure:"wrapcheck"` + WSL WSLSettings `mapstructure:"wsl"` Custom map[string]CustomLinterSettings `mapstructure:"custom"` } @@ -367,6 +368,10 @@ type DupWordSettings struct { Ignore []string `mapstructure:"ignore"` } +type EmbeddedStructFieldCheckSettings struct { + ForbidMutex bool `mapstructure:"forbid-mutex"` +} + type ErrcheckSettings struct { DisableDefaultExclusions bool `mapstructure:"disable-default-exclusions"` CheckTypeAssertions bool `mapstructure:"check-type-assertions"` diff --git a/pkg/golinters/embeddedstructfieldcheck/embeddedstructfieldcheck.go b/pkg/golinters/embeddedstructfieldcheck/embeddedstructfieldcheck.go index 0932ac4fed66..c9df5038c064 100644 --- a/pkg/golinters/embeddedstructfieldcheck/embeddedstructfieldcheck.go +++ b/pkg/golinters/embeddedstructfieldcheck/embeddedstructfieldcheck.go @@ -3,11 +3,21 @@ package embeddedstructfieldcheck import ( "github.com/manuelarte/embeddedstructfieldcheck/analyzer" + "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" ) -func New() *goanalysis.Linter { +func New(settings *config.EmbeddedStructFieldCheckSettings) *goanalysis.Linter { + var cfg map[string]any + + if settings != nil { + cfg = map[string]any{ + analyzer.ForbidMutexName: settings.ForbidMutex, + } + } + return goanalysis. NewLinterFromAnalyzer(analyzer.NewAnalyzer()). + WithConfig(cfg). WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/pkg/golinters/embeddedstructfieldcheck/testdata/embeddedstructfieldcheck_comments.go b/pkg/golinters/embeddedstructfieldcheck/testdata/embeddedstructfieldcheck_comments.go index 12a6a4fa1ddf..8dd119ede62a 100644 --- a/pkg/golinters/embeddedstructfieldcheck/testdata/embeddedstructfieldcheck_comments.go +++ b/pkg/golinters/embeddedstructfieldcheck/testdata/embeddedstructfieldcheck_comments.go @@ -1,5 +1,5 @@ //golangcitest:args -Eembeddedstructfieldcheck -package simple +package testdata import "time" diff --git a/pkg/golinters/embeddedstructfieldcheck/testdata/embeddedstructfieldcheck_mutex.go b/pkg/golinters/embeddedstructfieldcheck/testdata/embeddedstructfieldcheck_mutex.go new file mode 100644 index 000000000000..e0a586ef6f02 --- /dev/null +++ b/pkg/golinters/embeddedstructfieldcheck/testdata/embeddedstructfieldcheck_mutex.go @@ -0,0 +1,29 @@ +//golangcitest:args -Eembeddedstructfieldcheck +//golangcitest:config_path testdata/embeddedstructfieldcheck_mutex.yml +package testdata + +import "sync" + +type MutextEmbedded struct { + sync.Mutex // want `sync.Mutex should not be embedded` +} + +type MutextNotEmbedded struct { + mu sync.Mutex +} + +type PointerMutextEmbedded struct { + *sync.Mutex // want `sync.Mutex should not be embedded` +} + +type RWMutextEmbedded struct { + sync.RWMutex // want `sync.RWMutex should not be embedded` +} + +type RWMutextNotEmbedded struct { + mu sync.RWMutex +} + +type PointerRWMutextEmbedded struct { + *sync.RWMutex // want `sync.RWMutex should not be embedded` +} diff --git a/pkg/golinters/embeddedstructfieldcheck/testdata/embeddedstructfieldcheck_mutex.yml b/pkg/golinters/embeddedstructfieldcheck/testdata/embeddedstructfieldcheck_mutex.yml new file mode 100644 index 000000000000..ff5e68bc81e3 --- /dev/null +++ b/pkg/golinters/embeddedstructfieldcheck/testdata/embeddedstructfieldcheck_mutex.yml @@ -0,0 +1,6 @@ +version: "2" + +linters: + settings: + embeddedstructfieldcheck: + forbid-mutex: true diff --git a/pkg/golinters/embeddedstructfieldcheck/testdata/embeddedstructfieldcheck_simple.go b/pkg/golinters/embeddedstructfieldcheck/testdata/embeddedstructfieldcheck_simple.go index 47b155e5f52a..da13d29c95f7 100644 --- a/pkg/golinters/embeddedstructfieldcheck/testdata/embeddedstructfieldcheck_simple.go +++ b/pkg/golinters/embeddedstructfieldcheck/testdata/embeddedstructfieldcheck_simple.go @@ -1,5 +1,5 @@ //golangcitest:args -Eembeddedstructfieldcheck -package simple +package testdata import ( "context" diff --git a/pkg/golinters/embeddedstructfieldcheck/testdata/embeddedstructfieldcheck_special_cases.go b/pkg/golinters/embeddedstructfieldcheck/testdata/embeddedstructfieldcheck_special_cases.go index 95b5356b5824..b9ae5f3e187c 100644 --- a/pkg/golinters/embeddedstructfieldcheck/testdata/embeddedstructfieldcheck_special_cases.go +++ b/pkg/golinters/embeddedstructfieldcheck/testdata/embeddedstructfieldcheck_special_cases.go @@ -1,5 +1,5 @@ //golangcitest:args -Eembeddedstructfieldcheck -package simple +package testdata import "time" diff --git a/pkg/lint/lintersdb/builder_linter.go b/pkg/lint/lintersdb/builder_linter.go index 37f18bdc9eae..48a64375f53c 100644 --- a/pkg/lint/lintersdb/builder_linter.go +++ b/pkg/lint/lintersdb/builder_linter.go @@ -213,7 +213,7 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { WithLoadForGoAnalysis(). WithURL("https://github.com/charithe/durationcheck"), - linter.NewConfig(embeddedstructfieldcheck.New()). + linter.NewConfig(embeddedstructfieldcheck.New(&cfg.Linters.Settings.EmbeddedStructFieldCheck)). WithSince("v2.2.0"). WithURL("https://github.com/manuelarte/embeddedstructfieldcheck"), From f40f9d70b29e63faa798e685c7024383d536640a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 May 2025 00:21:49 +0200 Subject: [PATCH 123/152] build(deps): bump github.com/golangci/misspell from 0.6.0 to 0.7.0 (#5813) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7a1711e4277a..cdc954f4ad7b 100644 --- a/go.mod +++ b/go.mod @@ -48,7 +48,7 @@ require ( github.com/golangci/go-printf-func-name v0.1.0 github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95 - github.com/golangci/misspell v0.6.0 + github.com/golangci/misspell v0.7.0 github.com/golangci/plugin-module-register v0.1.1 github.com/golangci/revgrep v0.8.0 github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e diff --git a/go.sum b/go.sum index ba8cde2b19d6..41ec9620c99d 100644 --- a/go.sum +++ b/go.sum @@ -257,8 +257,8 @@ github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d h1:viFft9sS/dxoYY0a github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d/go.mod h1:ivJ9QDg0XucIkmwhzCDsqcnxxlDStoTl89jDMIoNxKY= github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95 h1:AkK+w9FZBXlU/xUmBtSJN1+tAI4FIvy5WtnUnY8e4p8= github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95/go.mod h1:k9mmcyWKSTMcPPvQUCfRWWQ9VHJ1U9Dc0R7kaXAgtnQ= -github.com/golangci/misspell v0.6.0 h1:JCle2HUTNWirNlDIAUO44hUsKhOFqGPoC4LZxlaSXDs= -github.com/golangci/misspell v0.6.0/go.mod h1:keMNyY6R9isGaSAu+4Q8NMBwMPkh15Gtc8UCVoDtAWo= +github.com/golangci/misspell v0.7.0 h1:4GOHr/T1lTW0hhR4tgaaV1WS/lJ+ncvYCoFKmqJsj0c= +github.com/golangci/misspell v0.7.0/go.mod h1:WZyyI2P3hxPY2UVHs3cS8YcllAeyfquQcKfdeE9AFVg= github.com/golangci/plugin-module-register v0.1.1 h1:TCmesur25LnyJkpsVrupv1Cdzo+2f7zX0H6Jkw1Ol6c= github.com/golangci/plugin-module-register v0.1.1/go.mod h1:TTpqoB6KkwOJMV8u7+NyXMrkwwESJLOkfl9TxR1DGFc= github.com/golangci/revgrep v0.8.0 h1:EZBctwbVd0aMeRnNUsFogoyayvKHyxlV3CdUA46FX2s= From 48d1da459b3ebd905519d870bfb15b12890fb544 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 May 2025 00:22:12 +0200 Subject: [PATCH 124/152] build(deps): bump the linter-testdata group across 2 directories with 2 updates (#5814) Co-authored-by: Fernandez Ludovic --- pkg/golinters/arangolint/testdata/go.mod | 10 +++++----- pkg/golinters/arangolint/testdata/go.sum | 21 +++++++++++---------- pkg/golinters/exptostd/testdata/go.mod | 4 ++-- pkg/golinters/exptostd/testdata/go.sum | 4 ++-- pkg/golinters/ginkgolinter/testdata/go.mod | 8 ++++---- pkg/golinters/ginkgolinter/testdata/go.sum | 16 ++++++++-------- pkg/golinters/gomodguard/testdata/go.mod | 4 ++-- pkg/golinters/gomodguard/testdata/go.sum | 2 ++ pkg/golinters/protogetter/testdata/go.mod | 8 ++++---- pkg/golinters/protogetter/testdata/go.sum | 16 ++++++++-------- pkg/golinters/zerologlint/testdata/go.mod | 2 +- pkg/golinters/zerologlint/testdata/go.sum | 4 ++-- 12 files changed, 51 insertions(+), 48 deletions(-) diff --git a/pkg/golinters/arangolint/testdata/go.mod b/pkg/golinters/arangolint/testdata/go.mod index c9d56c70228d..0fb1fc8b4a4e 100644 --- a/pkg/golinters/arangolint/testdata/go.mod +++ b/pkg/golinters/arangolint/testdata/go.mod @@ -9,11 +9,11 @@ require ( github.com/dchest/siphash v1.2.3 // indirect github.com/google/uuid v1.6.0 // indirect github.com/kkdai/maglev v0.2.0 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/rs/zerolog v1.33.0 // indirect - golang.org/x/net v0.33.0 // indirect - golang.org/x/sys v0.28.0 // indirect - golang.org/x/text v0.21.0 // indirect + github.com/rs/zerolog v1.34.0 // indirect + golang.org/x/net v0.40.0 // indirect + golang.org/x/sys v0.33.0 // indirect + golang.org/x/text v0.25.0 // indirect ) diff --git a/pkg/golinters/arangolint/testdata/go.sum b/pkg/golinters/arangolint/testdata/go.sum index 9f27a49c38c8..69d72038590d 100644 --- a/pkg/golinters/arangolint/testdata/go.sum +++ b/pkg/golinters/arangolint/testdata/go.sum @@ -14,8 +14,9 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/kkdai/maglev v0.2.0 h1:w6DCW0kAA6fstZqXkrBrlgIC3jeIRXkjOYea/m6EK/Y= github.com/kkdai/maglev v0.2.0/go.mod h1:d+mt8Lmt3uqi9aRb/BnPjzD0fy+ETs1vVXiGRnqHVZ4= -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-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= @@ -24,22 +25,22 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= -github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= +github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= +github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 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= -golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= -golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= +golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= 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.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/pkg/golinters/exptostd/testdata/go.mod b/pkg/golinters/exptostd/testdata/go.mod index 5261142a3036..3bd4f2c04ce5 100644 --- a/pkg/golinters/exptostd/testdata/go.mod +++ b/pkg/golinters/exptostd/testdata/go.mod @@ -1,5 +1,5 @@ module exptostd -go 1.22.0 +go 1.23.0 -require golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 +require golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 diff --git a/pkg/golinters/exptostd/testdata/go.sum b/pkg/golinters/exptostd/testdata/go.sum index c487fae960b3..2fbef45b9043 100644 --- a/pkg/golinters/exptostd/testdata/go.sum +++ b/pkg/golinters/exptostd/testdata/go.sum @@ -1,2 +1,2 @@ -golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 h1:1UoZQm6f0P/ZO0w1Ri+f+ifG/gXhegadRdwBIXEFWDo= -golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= +golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 h1:y5zboxd6LQAqYIhHnB48p0ByQ/GnQx2BE33L8BOHQkI= +golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ= diff --git a/pkg/golinters/ginkgolinter/testdata/go.mod b/pkg/golinters/ginkgolinter/testdata/go.mod index fe2cc945898c..ede5795987b6 100644 --- a/pkg/golinters/ginkgolinter/testdata/go.mod +++ b/pkg/golinters/ginkgolinter/testdata/go.mod @@ -13,9 +13,9 @@ require ( github.com/google/go-cmp v0.7.0 // indirect github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect go.uber.org/automaxprocs v1.6.0 // indirect - golang.org/x/net v0.37.0 // indirect - golang.org/x/sys v0.32.0 // indirect - golang.org/x/text v0.23.0 // indirect - golang.org/x/tools v0.31.0 // indirect + golang.org/x/net v0.40.0 // indirect + golang.org/x/sys v0.33.0 // indirect + golang.org/x/text v0.25.0 // indirect + golang.org/x/tools v0.33.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/pkg/golinters/ginkgolinter/testdata/go.sum b/pkg/golinters/ginkgolinter/testdata/go.sum index 0acd79618257..bbd84ab067c2 100644 --- a/pkg/golinters/ginkgolinter/testdata/go.sum +++ b/pkg/golinters/ginkgolinter/testdata/go.sum @@ -24,14 +24,14 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= -golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= -golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= -golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= -golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= -golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU= -golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ= +golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= +golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= +golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= +golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/pkg/golinters/gomodguard/testdata/go.mod b/pkg/golinters/gomodguard/testdata/go.mod index ab174ed19807..c5512cba7f95 100644 --- a/pkg/golinters/gomodguard/testdata/go.mod +++ b/pkg/golinters/gomodguard/testdata/go.mod @@ -1,8 +1,8 @@ module gomodguard -go 1.22.0 +go 1.23.0 require ( - golang.org/x/mod v0.22.0 + golang.org/x/mod v0.24.0 gopkg.in/yaml.v3 v3.0.1 ) diff --git a/pkg/golinters/gomodguard/testdata/go.sum b/pkg/golinters/gomodguard/testdata/go.sum index 7c483c93b9e0..5dce74976ef5 100644 --- a/pkg/golinters/gomodguard/testdata/go.sum +++ b/pkg/golinters/gomodguard/testdata/go.sum @@ -1,5 +1,7 @@ golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= +golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= 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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/pkg/golinters/protogetter/testdata/go.mod b/pkg/golinters/protogetter/testdata/go.mod index 0cca1725136e..894a03ffa01e 100644 --- a/pkg/golinters/protogetter/testdata/go.mod +++ b/pkg/golinters/protogetter/testdata/go.mod @@ -3,13 +3,13 @@ module protogetter go 1.23.0 require ( - google.golang.org/grpc v1.72.0 + google.golang.org/grpc v1.72.1 google.golang.org/protobuf v1.36.6 ) require ( - golang.org/x/net v0.38.0 // indirect - golang.org/x/sys v0.31.0 // indirect - golang.org/x/text v0.23.0 // indirect + golang.org/x/net v0.40.0 // indirect + golang.org/x/sys v0.33.0 // indirect + golang.org/x/text v0.25.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a // indirect ) diff --git a/pkg/golinters/protogetter/testdata/go.sum b/pkg/golinters/protogetter/testdata/go.sum index 11d34e556344..99952097dc15 100644 --- a/pkg/golinters/protogetter/testdata/go.sum +++ b/pkg/golinters/protogetter/testdata/go.sum @@ -20,15 +20,15 @@ go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= -golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= -golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= +golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a h1:51aaUVRocpvUOSQKM6Q7VuoaktNIaMCLuhZB6DKksq4= google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a/go.mod h1:uRxBH1mhmO8PGhU89cMcHaXKZqO+OfakD8QQO0oYwlQ= -google.golang.org/grpc v1.72.0 h1:S7UkcVa60b5AAQTaO6ZKamFp1zMZSU0fGDK2WZLbBnM= -google.golang.org/grpc v1.72.0/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= +google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA= +google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= diff --git a/pkg/golinters/zerologlint/testdata/go.mod b/pkg/golinters/zerologlint/testdata/go.mod index 42508c71c705..6e255ef19b13 100644 --- a/pkg/golinters/zerologlint/testdata/go.mod +++ b/pkg/golinters/zerologlint/testdata/go.mod @@ -7,5 +7,5 @@ require github.com/rs/zerolog v1.34.0 require ( github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - golang.org/x/sys v0.31.0 // indirect + golang.org/x/sys v0.33.0 // indirect ) diff --git a/pkg/golinters/zerologlint/testdata/go.sum b/pkg/golinters/zerologlint/testdata/go.sum index 4c01b0c5ed90..3b0d10eedda7 100644 --- a/pkg/golinters/zerologlint/testdata/go.sum +++ b/pkg/golinters/zerologlint/testdata/go.sum @@ -14,5 +14,5 @@ github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6 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.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= From 1c222b488bbc2c0ae2cad8423a24b8452f2fc3a9 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Mon, 19 May 2025 22:46:51 +0200 Subject: [PATCH 125/152] dev: consistent version (#5817) --- cmd/golangci-lint/main.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cmd/golangci-lint/main.go b/cmd/golangci-lint/main.go index f7f3091dc653..acb09cd8c0be 100644 --- a/cmd/golangci-lint/main.go +++ b/cmd/golangci-lint/main.go @@ -4,7 +4,9 @@ import ( "cmp" "fmt" "os" + "regexp" "runtime/debug" + "strings" "github.com/golangci/golangci-lint/v2/pkg/commands" "github.com/golangci/golangci-lint/v2/pkg/exitcodes" @@ -23,7 +25,7 @@ func main() { info := createBuildInfo() if err := commands.Execute(info); err != nil { - _, _ = fmt.Fprintf(os.Stderr, "Failed executing command with error: %v\n", err) + _, _ = fmt.Fprintf(os.Stderr, "The command is terminated due to an error: %v\n", err) os.Exit(exitcodes.Failure) } } @@ -49,6 +51,11 @@ func createBuildInfo() commands.BuildInfo { info.Version = buildInfo.Main.Version + matched, _ := regexp.MatchString(`v\d+\.\d+\.\d+`, buildInfo.Main.Version) + if matched { + info.Version = strings.TrimPrefix(buildInfo.Main.Version, "v") + } + var revision string var modified string for _, setting := range buildInfo.Settings { From 79fb722b27d3ecb1b68ce759e14b32da1b15f4ed Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Mon, 19 May 2025 22:47:11 +0200 Subject: [PATCH 126/152] docs: add description for linters.default sets (#5818) --- .golangci.next.reference.yml | 10 ++++++---- .golangci.reference.yml | 8 +++++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index 8a4fc69e22b1..fa205ce7596f 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -10,12 +10,15 @@ version: "2" linters: # Default set of linters. - # The value can be: `standard`, `all`, `none`, or `fast`. + # The value can be: + # - `standard`: https://golangci-lint.run/usage/linters/#enabled-by-default + # - `all`: enables all linters by default. + # - `none`: disables all linters by default. + # - `fast`: enables only linters considered as "fast" (`golangci-lint help linters --json | jq '[ .[] | select(.fast==true) ] | map(.name)'`). # Default: standard default: all # Enable specific linter. - # https://golangci-lint.run/usage/linters/#enabled-by-default enable: - arangolint - asasalint @@ -124,8 +127,7 @@ linters: - wsl - zerologlint - # Disable specific linter. - # https://golangci-lint.run/usage/linters/#disabled-by-default + # Disable specific linters. disable: - arangolint - asasalint diff --git a/.golangci.reference.yml b/.golangci.reference.yml index 6aad45d89868..38b1d26ed729 100644 --- a/.golangci.reference.yml +++ b/.golangci.reference.yml @@ -10,12 +10,15 @@ version: "2" linters: # Default set of linters. - # The value can be: `standard`, `all`, `none`, or `fast`. + # The value can be: + # - `standard`: https://golangci-lint.run/usage/linters/#enabled-by-default + # - `all`: enables all linters by default. + # - `none`: disables all linters by default. + # - `fast`: enables only linters considered as "fast" (`golangci-lint help linters --json | jq '[ .[] | select(.fast==true) ] | map(.name)'`). # Default: standard default: all # Enable specific linter. - # https://golangci-lint.run/usage/linters/#enabled-by-default enable: - asasalint - asciicheck @@ -123,7 +126,6 @@ linters: - zerologlint # Disable specific linter. - # https://golangci-lint.run/usage/linters/#disabled-by-default disable: - asasalint - asciicheck From 36ddc0e035ac1892701dbff8c64980959b5f8f1c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 May 2025 20:25:19 +0200 Subject: [PATCH 127/152] build(deps): bump github.com/uudashr/iface from 1.3.2 to 1.4.0 (#5820) Co-authored-by: Fernandez Ludovic --- .golangci.next.reference.yml | 1 + go.mod | 2 +- go.sum | 4 +- jsonschema/golangci.next.jsonschema.json | 3 +- pkg/golinters/iface/iface.go | 8 +- pkg/golinters/iface/testdata/iface_all.go | 8 +- pkg/golinters/iface/testdata/iface_cgo.go | 4 +- pkg/golinters/iface/testdata/iface_default.go | 4 +- .../iface/testdata/iface_identical.go | 4 +- pkg/golinters/iface/testdata/iface_opaque.go | 2 +- .../iface/testdata/iface_unexported.go | 84 +++++++++++++++++++ .../iface/testdata/iface_unexported.yml | 7 ++ pkg/golinters/iface/testdata/iface_unused.go | 6 +- 13 files changed, 116 insertions(+), 21 deletions(-) create mode 100644 pkg/golinters/iface/testdata/iface_unexported.go create mode 100644 pkg/golinters/iface/testdata/iface_unexported.yml diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index fa205ce7596f..4c8e1615682b 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -1795,6 +1795,7 @@ linters: - identical # Identifies interfaces in the same package that have identical method sets. - unused # Identifies interfaces that are not used anywhere in the same package where the interface is defined. - opaque # Identifies functions that return interfaces, but the actual returned value is always a single concrete implementation. + - unexported # Identifies interfaces that are not exported but are used in exported functions or methods. settings: unused: # List of packages path to exclude from the check. diff --git a/go.mod b/go.mod index cdc954f4ad7b..03810322d94d 100644 --- a/go.mod +++ b/go.mod @@ -119,7 +119,7 @@ require ( github.com/ultraware/funlen v0.2.0 github.com/ultraware/whitespace v0.2.0 github.com/uudashr/gocognit v1.2.0 - github.com/uudashr/iface v1.3.2 + github.com/uudashr/iface v1.4.0 github.com/valyala/quicktemplate v1.8.0 github.com/xen0n/gosmopolitan v1.3.0 github.com/yagipy/maintidx v1.0.0 diff --git a/go.sum b/go.sum index 41ec9620c99d..2c8a91e0c1b7 100644 --- a/go.sum +++ b/go.sum @@ -598,8 +598,8 @@ github.com/ultraware/whitespace v0.2.0 h1:TYowo2m9Nfj1baEQBjuHzvMRbp19i+RCcRYrSW github.com/ultraware/whitespace v0.2.0/go.mod h1:XcP1RLD81eV4BW8UhQlpaR+SDc2givTvyI8a586WjW8= github.com/uudashr/gocognit v1.2.0 h1:3BU9aMr1xbhPlvJLSydKwdLN3tEUUrzPSSM8S4hDYRA= github.com/uudashr/gocognit v1.2.0/go.mod h1:k/DdKPI6XBZO1q7HgoV2juESI2/Ofj9AcHPZhBBdrTU= -github.com/uudashr/iface v1.3.2 h1:viQ7WtLvznR+Z4H+IP/fqhqPl3UF9Y2aj6wTeHF6X+Y= -github.com/uudashr/iface v1.3.2/go.mod h1:i/H4cfRMPe0izticV8Yz0g6/zcsh5xXlvthrdh1kqcY= +github.com/uudashr/iface v1.4.0 h1:ImZ+1oEJPXvjap7nK0md7gA9RRH7PMp4vliaLkJ2+cg= +github.com/uudashr/iface v1.4.0/go.mod h1:i/H4cfRMPe0izticV8Yz0g6/zcsh5xXlvthrdh1kqcY= 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/quicktemplate v1.8.0 h1:zU0tjbIqTRgKQzFY1L42zq0qR3eh4WoQQdIdqCysW5k= diff --git a/jsonschema/golangci.next.jsonschema.json b/jsonschema/golangci.next.jsonschema.json index ef1c956ef1c4..1bd33923a5de 100644 --- a/jsonschema/golangci.next.jsonschema.json +++ b/jsonschema/golangci.next.jsonschema.json @@ -661,7 +661,8 @@ "enum": [ "identical", "unused", - "opaque" + "opaque", + "unexported" ] }, "tagliatelle-cases": { diff --git a/pkg/golinters/iface/iface.go b/pkg/golinters/iface/iface.go index a3c2816d4385..0a4a38abc931 100644 --- a/pkg/golinters/iface/iface.go +++ b/pkg/golinters/iface/iface.go @@ -5,6 +5,7 @@ import ( "github.com/uudashr/iface/identical" "github.com/uudashr/iface/opaque" + "github.com/uudashr/iface/unexported" "github.com/uudashr/iface/unused" "golang.org/x/tools/go/analysis" @@ -28,9 +29,10 @@ func New(settings *config.IfaceSettings) *goanalysis.Linter { func analyzersFromSettings(settings *config.IfaceSettings) []*analysis.Analyzer { allAnalyzers := map[string]*analysis.Analyzer{ - "identical": identical.Analyzer, - "unused": unused.Analyzer, - "opaque": opaque.Analyzer, + "identical": identical.Analyzer, + "unused": unused.Analyzer, + "opaque": opaque.Analyzer, + "unexported": unexported.Analyzer, } if settings == nil || len(settings.Enable) == 0 { diff --git a/pkg/golinters/iface/testdata/iface_all.go b/pkg/golinters/iface/testdata/iface_all.go index 3a6f912a1d2a..3dd95cdc24bf 100644 --- a/pkg/golinters/iface/testdata/iface_all.go +++ b/pkg/golinters/iface/testdata/iface_all.go @@ -6,11 +6,11 @@ import "fmt" // identical -type Pinger interface { // want "identical: interface Pinger contains identical methods or type constraints from another interface, causing redundancy" +type Pinger interface { // want "identical: interface 'Pinger' contains identical methods or type constraints with another interface, causing redundancy" Ping() error } -type Healthcheck interface { // want "identical: interface Healthcheck contains identical methods or type constraints from another interface, causing redundancy" +type Healthcheck interface { // want "identical: interface 'Healthcheck' contains identical methods or type constraints with another interface, causing redundancy" Ping() error } @@ -28,7 +28,7 @@ func (s server) Serve() error { return nil } -func NewServer(addr string) Server { // want "opaque: NewServer function return Server interface at the 1st result, abstract a single concrete implementation of \\*server" +func NewServer(addr string) Server { // want "opaque: 'NewServer' function return 'Server' interface at the 1st result, abstract a single concrete implementation of '\\*server'" return &server{addr: addr} } @@ -39,7 +39,7 @@ type User struct { Name string } -type UserRepository interface { // want "unused: interface UserRepository is declared but not used within the package" +type UserRepository interface { // want "unused: interface 'UserRepository' is declared but not used within the package" UserOf(id string) (*User, error) } diff --git a/pkg/golinters/iface/testdata/iface_cgo.go b/pkg/golinters/iface/testdata/iface_cgo.go index 43ef0216a036..16a9944854f0 100644 --- a/pkg/golinters/iface/testdata/iface_cgo.go +++ b/pkg/golinters/iface/testdata/iface_cgo.go @@ -24,11 +24,11 @@ func _() { // identical -type Pinger interface { // want "identical: interface Pinger contains identical methods or type constraints from another interface, causing redundancy" +type Pinger interface { // want "identical: interface 'Pinger' contains identical methods or type constraints with another interface, causing redundancy" Ping() error } -type Healthcheck interface { // want "identical: interface Healthcheck contains identical methods or type constraints from another interface, causing redundancy" +type Healthcheck interface { // want "identical: interface 'Healthcheck' contains identical methods or type constraints with another interface, causing redundancy" Ping() error } diff --git a/pkg/golinters/iface/testdata/iface_default.go b/pkg/golinters/iface/testdata/iface_default.go index 34117389738b..d0344b36c58f 100644 --- a/pkg/golinters/iface/testdata/iface_default.go +++ b/pkg/golinters/iface/testdata/iface_default.go @@ -5,11 +5,11 @@ import "fmt" // identical -type Pinger interface { // want "identical: interface Pinger contains identical methods or type constraints from another interface, causing redundancy" +type Pinger interface { // want "identical: interface 'Pinger' contains identical methods or type constraints with another interface, causing redundancy" Ping() error } -type Healthcheck interface { // want "identical: interface Healthcheck contains identical methods or type constraints from another interface, causing redundancy" +type Healthcheck interface { // want "identical: interface 'Healthcheck' contains identical methods or type constraints with another interface, causing redundancy" Ping() error } diff --git a/pkg/golinters/iface/testdata/iface_identical.go b/pkg/golinters/iface/testdata/iface_identical.go index 821aff7bd41e..c8a2de4818bb 100644 --- a/pkg/golinters/iface/testdata/iface_identical.go +++ b/pkg/golinters/iface/testdata/iface_identical.go @@ -6,11 +6,11 @@ import "fmt" // identical -type Pinger interface { // want "identical: interface Pinger contains identical methods or type constraints from another interface, causing redundancy" +type Pinger interface { // want "identical: interface 'Pinger' contains identical methods or type constraints with another interface, causing redundancy" Ping() error } -type Healthcheck interface { // want "identical: interface Healthcheck contains identical methods or type constraints from another interface, causing redundancy" +type Healthcheck interface { // want "identical: interface 'Healthcheck' contains identical methods or type constraints with another interface, causing redundancy" Ping() error } diff --git a/pkg/golinters/iface/testdata/iface_opaque.go b/pkg/golinters/iface/testdata/iface_opaque.go index b7ebeddc600f..8610a3fa05c1 100644 --- a/pkg/golinters/iface/testdata/iface_opaque.go +++ b/pkg/golinters/iface/testdata/iface_opaque.go @@ -28,7 +28,7 @@ func (s server) Serve() error { return nil } -func NewServer(addr string) Server { // want "opaque: NewServer function return Server interface at the 1st result, abstract a single concrete implementation of \\*server" +func NewServer(addr string) Server { // want "opaque: 'NewServer' function return 'Server' interface at the 1st result, abstract a single concrete implementation of '\\*server'" return &server{addr: addr} } diff --git a/pkg/golinters/iface/testdata/iface_unexported.go b/pkg/golinters/iface/testdata/iface_unexported.go new file mode 100644 index 000000000000..01a4f210f9f7 --- /dev/null +++ b/pkg/golinters/iface/testdata/iface_unexported.go @@ -0,0 +1,84 @@ +//golangcitest:args -Eiface +//golangcitest:config_path testdata/iface_unexported.yml +package testdata + +import "fmt" + +// identical + +type Pinger interface { + Ping() error +} + +type Healthcheck interface { + Ping() error +} + +// opaque + +type Server interface { + Serve() error +} + +type server struct { + addr string +} + +func (s server) Serve() error { + return nil +} + +func NewServer(addr string) Server { + return &server{addr: addr} +} + +// unused + +type User struct { + ID string + Name string +} + +type UserRepository interface { + UserOf(id string) (*User, error) +} + +type UserRepositorySQL struct { +} + +func (r *UserRepositorySQL) UserOf(id string) (*User, error) { + return nil, nil +} + +type Granter interface { + Grant(permission string) error +} + +func AllowAll(g Granter) error { + return g.Grant("all") +} + +type Allower interface { + Allow(permission string) error +} + +func Allow(x any) { + _ = x.(Allower) + fmt.Println("allow") +} + +// unexported + +type unexportedReader interface { + Read([]byte) (int, error) +} + +func ReadAll(r unexportedReader) ([]byte, error) { // want "unexported interface 'unexportedReader' used as parameter in exported function 'ReadAll'" + buf := make([]byte, 1024) + _, err := r.Read(buf) + return buf, err +} + +func NewUnexportedReader() unexportedReader { // want "unexported interface 'unexportedReader' used as return value in exported function 'NewUnexportedReader'" + return nil // stub +} diff --git a/pkg/golinters/iface/testdata/iface_unexported.yml b/pkg/golinters/iface/testdata/iface_unexported.yml new file mode 100644 index 000000000000..cc0a84c0aa1e --- /dev/null +++ b/pkg/golinters/iface/testdata/iface_unexported.yml @@ -0,0 +1,7 @@ +version: "2" + +linters: + settings: + iface: + enable: + - unexported diff --git a/pkg/golinters/iface/testdata/iface_unused.go b/pkg/golinters/iface/testdata/iface_unused.go index b75fdc8964c6..58e5ffdbaf25 100644 --- a/pkg/golinters/iface/testdata/iface_unused.go +++ b/pkg/golinters/iface/testdata/iface_unused.go @@ -6,11 +6,11 @@ import "fmt" // identical -type Pinger interface { // want "unused: interface Pinger is declared but not used within the package" +type Pinger interface { // want "unused: interface 'Pinger' is declared but not used within the package" Ping() error } -type Healthcheck interface { // want "unused: interface Healthcheck is declared but not used within the package" +type Healthcheck interface { // want "unused: interface 'Healthcheck' is declared but not used within the package" Ping() error } @@ -39,7 +39,7 @@ type User struct { Name string } -type UserRepository interface { // want "unused: interface UserRepository is declared but not used within the package" +type UserRepository interface { // want "unused: interface 'UserRepository' is declared but not used within the package" UserOf(id string) (*User, error) } From a6d5fa62302cb8cf02d436d3ae79f9f9152abade Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Wed, 21 May 2025 21:47:19 +0200 Subject: [PATCH 128/152] docs: improve typecheck FAQ (#5821) Co-authored-by: Simon Sawert --- docs/src/docs/welcome/faq.mdx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/src/docs/welcome/faq.mdx b/docs/src/docs/welcome/faq.mdx index 46e57aacdbaa..62109ac5afb7 100644 --- a/docs/src/docs/welcome/faq.mdx +++ b/docs/src/docs/welcome/faq.mdx @@ -33,7 +33,7 @@ it's just a way to identify, parse, and display compiling errors (produced by th 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. +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, @@ -45,10 +45,11 @@ If there are `typecheck` errors, golangci-lint will not be able to produce other 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 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. +- [ ] If you are using private repositories/dependencies, ensure the [Go proxy](https://go.dev/ref/mod#module-proxy) (`GOPROXY`) and [checksum database](https://go.dev/ref/mod#checksum-database) (`GOSUMDB`) are right and/or your git configuration. ## Why is it not possible to skip/ignore `typecheck` errors? From b6459b0483d0df3987684c1f732f2293c2486428 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Wed, 21 May 2025 23:02:00 +0200 Subject: [PATCH 129/152] docs: note about plugin system (#5822) --- docs/src/docs/contributing/new-linters.mdx | 2 +- docs/src/docs/plugins/go-plugins.mdx | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/src/docs/contributing/new-linters.mdx b/docs/src/docs/contributing/new-linters.mdx index 1e22d714a896..57654e887f89 100644 --- a/docs/src/docs/contributing/new-linters.mdx +++ b/docs/src/docs/contributing/new-linters.mdx @@ -43,5 +43,5 @@ Typically, these linters can't be open-sourced or too specific. Such linters can be added through 2 plugin systems: -1. [Module Plugin System](/plugins/module-plugins) +1. [Module Plugin System](/plugins/module-plugins) (Recommended) 2. [Go Plugin System](/plugins/go-plugins) diff --git a/docs/src/docs/plugins/go-plugins.mdx b/docs/src/docs/plugins/go-plugins.mdx index ce742b9bc62c..bf05d1fc92b4 100644 --- a/docs/src/docs/plugins/go-plugins.mdx +++ b/docs/src/docs/plugins/go-plugins.mdx @@ -2,6 +2,10 @@ title: Go Plugin System --- +**We recommend using [Module Plugin System](/plugins/module-plugins) instead of the Go Plugin System.** + +--- + Private linters can be added through [Go's plugin system](https://pkg.go.dev/plugin). For a private linter (which acts as a plugin) to work properly, From 8eab120d6baa9675be6076ccd4a1549f76a8e736 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 23 May 2025 01:05:02 +0200 Subject: [PATCH 130/152] build(deps): bump github.com/jgautheron/goconst from 1.8.1 to 1.8.2 (#5825) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 03810322d94d..b6c4dcfee25d 100644 --- a/go.mod +++ b/go.mod @@ -57,7 +57,7 @@ require ( github.com/gostaticanalysis/forcetypeassert v0.2.0 github.com/gostaticanalysis/nilerr v0.1.1 github.com/hashicorp/go-version v1.7.0 - github.com/jgautheron/goconst v1.8.1 + github.com/jgautheron/goconst v1.8.2 github.com/jingyugao/rowserrcheck v1.1.1 github.com/jjti/go-spancheck v0.6.5 github.com/julz/importas v0.2.0 diff --git a/go.sum b/go.sum index 2c8a91e0c1b7..6e693c71c7a1 100644 --- a/go.sum +++ b/go.sum @@ -331,8 +331,8 @@ github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSo github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= 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.8.1 h1:PPqCYp3K/xlOj5JmIe6O1Mj6r1DbkdbLtR3AJuZo414= -github.com/jgautheron/goconst v1.8.1/go.mod h1:A0oxgBCHy55NQn6sYpO7UdnA9p+h7cPtoOZUmvNIako= +github.com/jgautheron/goconst v1.8.2 h1:y0XF7X8CikZ93fSNT6WBTb/NElBu9IjaY7CCYQrCMX4= +github.com/jgautheron/goconst v1.8.2/go.mod h1:A0oxgBCHy55NQn6sYpO7UdnA9p+h7cPtoOZUmvNIako= 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/jjti/go-spancheck v0.6.5 h1:lmi7pKxa37oKYIMScialXUK6hP3iY5F1gu+mLBPgYB8= From cd315cdc3f54583194ae286000bde5df6222f839 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Sat, 24 May 2025 11:35:43 +0200 Subject: [PATCH 131/152] fix: write the input to stdout when using stdin and there are no changes (#5827) --- .golangci.next.reference.yml | 1 + pkg/goformat/runner.go | 43 +++++++++++++++++++++++++++--------- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index 4c8e1615682b..d372c128b82d 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -4088,6 +4088,7 @@ formatters: # Default: lax generated: strict # Which file paths to exclude. + # This option is ignored when using `--stdin` as the path is unknown. # Default: [] paths: - ".*\\.my\\.go$" diff --git a/pkg/goformat/runner.go b/pkg/goformat/runner.go index fa1d1acc3019..f87626158179 100644 --- a/pkg/goformat/runner.go +++ b/pkg/goformat/runner.go @@ -57,7 +57,7 @@ func (c *Runner) Run(paths []string) error { } if c.opts.stdin { - return c.process("", savedStdout, os.Stdin) + return c.formatStdIn("", savedStdout, os.Stdin) } for _, path := range paths { @@ -121,15 +121,6 @@ func (c *Runner) process(path string, stdout io.Writer, in io.Reader) error { output := c.metaFormatter.Format(path, input) - if c.opts.stdin { - _, err = stdout.Write(output) - if err != nil { - return err - } - - return nil - } - if bytes.Equal(input, output) { return nil } @@ -168,6 +159,38 @@ func (c *Runner) process(path string, stdout io.Writer, in io.Reader) error { return os.WriteFile(path, output, perms) } +func (c *Runner) formatStdIn(path string, stdout io.Writer, in io.Reader) error { + input, err := io.ReadAll(in) + if err != nil { + return err + } + + match, err := c.matcher.IsGeneratedFile(path, input) + if err != nil { + return err + } + + if match { + // If the file is generated, + // the input should be written to the stdout to avoid emptied the file. + _, err = stdout.Write(input) + if err != nil { + return err + } + + return nil + } + + output := c.metaFormatter.Format(path, input) + + _, err = stdout.Write(output) + if err != nil { + return err + } + + return nil +} + func (c *Runner) setOutputToDevNull() { devNull, err := os.Open(os.DevNull) if err != nil { From ee5054adbef639ee2b48f42668d8e9fb01e99dcc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 24 May 2025 12:48:30 +0200 Subject: [PATCH 132/152] build(deps): bump github.com/santhosh-tekuri/jsonschema/v6 from 6.0.1 to 6.0.2 (#5829) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b6c4dcfee25d..a266a80067f0 100644 --- a/go.mod +++ b/go.mod @@ -95,7 +95,7 @@ require ( github.com/ryancurrah/gomodguard v1.4.1 github.com/ryanrolds/sqlclosecheck v0.5.1 github.com/sanposhiho/wastedassign/v2 v2.1.0 - github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 + github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 github.com/sashamelentyev/interfacebloat v1.1.0 github.com/sashamelentyev/usestdlibvars v1.28.0 github.com/securego/gosec/v2 v2.22.4 diff --git a/go.sum b/go.sum index 6e693c71c7a1..5940dc688322 100644 --- a/go.sum +++ b/go.sum @@ -513,8 +513,8 @@ github.com/ryanrolds/sqlclosecheck v0.5.1 h1:dibWW826u0P8jNLsLN+En7+RqWWTYrjCB9f github.com/ryanrolds/sqlclosecheck v0.5.1/go.mod h1:2g3dUjoS6AL4huFdv6wn55WpLIDjY7ZgUR4J8HOO/XQ= github.com/sanposhiho/wastedassign/v2 v2.1.0 h1:crurBF7fJKIORrV85u9UUpePDYGWnwvv3+A96WvwXT0= github.com/sanposhiho/wastedassign/v2 v2.1.0/go.mod h1:+oSmSC+9bQ+VUAxA66nBb0Z7N8CK7mscKTDYC6aIek4= -github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw= -github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= +github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEVZGK7IN2kJkjTuQ= +github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= 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.28.0 h1:jZnudE2zKCtYlGzLVreNp5pmCdOxXUzwsMDBkR21cyQ= From e7c45898cada168d6f2c98e309974d8405d49635 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 24 May 2025 16:01:13 +0200 Subject: [PATCH 133/152] build(deps): bump github.com/sashamelentyev/usestdlibvars from 1.28.0 to 1.29.0 (#5828) Co-authored-by: Fernandez Ludovic --- .golangci.next.reference.yml | 3 +++ go.mod | 2 +- go.sum | 4 ++-- jsonschema/golangci.next.jsonschema.json | 5 +++++ pkg/config/linters_settings.go | 1 + .../testdata/usestdlibvars_non_default.go | 10 +++++++++- .../testdata/usestdlibvars_non_default.yml | 1 + pkg/golinters/usestdlibvars/usestdlibvars.go | 1 + 8 files changed, 23 insertions(+), 4 deletions(-) diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index d372c128b82d..36af28206aa1 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -3616,6 +3616,9 @@ linters: # Suggest the use of http.StatusXX. # Default: true http-status-code: false + # Suggest the use of time.Month in time.Date. + # Default: false + time-date-month: true # Suggest the use of time.Weekday.String(). # Default: true time-weekday: true diff --git a/go.mod b/go.mod index a266a80067f0..95776f35e674 100644 --- a/go.mod +++ b/go.mod @@ -97,7 +97,7 @@ require ( github.com/sanposhiho/wastedassign/v2 v2.1.0 github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 github.com/sashamelentyev/interfacebloat v1.1.0 - github.com/sashamelentyev/usestdlibvars v1.28.0 + github.com/sashamelentyev/usestdlibvars v1.29.0 github.com/securego/gosec/v2 v2.22.4 github.com/shirou/gopsutil/v4 v4.25.4 github.com/sirupsen/logrus v1.9.3 diff --git a/go.sum b/go.sum index 5940dc688322..240f74257922 100644 --- a/go.sum +++ b/go.sum @@ -517,8 +517,8 @@ github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEV github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= 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.28.0 h1:jZnudE2zKCtYlGzLVreNp5pmCdOxXUzwsMDBkR21cyQ= -github.com/sashamelentyev/usestdlibvars v1.28.0/go.mod h1:9nl0jgOfHKWNFS43Ojw0i7aRoS4j6EBye3YBhmAIRF8= +github.com/sashamelentyev/usestdlibvars v1.29.0 h1:8J0MoRrw4/NAXtjQqTHrbW9NN+3iMf7Knkq057v4XOQ= +github.com/sashamelentyev/usestdlibvars v1.29.0/go.mod h1:8PpnjHMk5VdeWlVb4wCdrB8PNbLqZ3wBZTZWkrpZZL8= github.com/securego/gosec/v2 v2.22.4 h1:21VdNGcKicFSv6rUDBc0cEtEl7lWyCKZxKIm0iwvrIM= github.com/securego/gosec/v2 v2.22.4/go.mod h1:ww5Yie7KJ3AH8XZQTletkW5zOmIse6FACs/Ys8VR3qE= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= diff --git a/jsonschema/golangci.next.jsonschema.json b/jsonschema/golangci.next.jsonschema.json index 1bd33923a5de..a84a30121f38 100644 --- a/jsonschema/golangci.next.jsonschema.json +++ b/jsonschema/golangci.next.jsonschema.json @@ -3728,6 +3728,11 @@ "type": "boolean", "default": false }, + "time-date-month": { + "description": "Suggest the use of time.Month in time.Date.", + "type": "boolean", + "default": false + }, "crypto-hash": { "description": "Suggest the use of crypto.Hash.String().", "type": "boolean", diff --git a/pkg/config/linters_settings.go b/pkg/config/linters_settings.go index 2398186d3812..e2838d808acb 100644 --- a/pkg/config/linters_settings.go +++ b/pkg/config/linters_settings.go @@ -934,6 +934,7 @@ type UseStdlibVarsSettings struct { SQLIsolationLevel bool `mapstructure:"sql-isolation-level"` TLSSignatureScheme bool `mapstructure:"tls-signature-scheme"` ConstantKind bool `mapstructure:"constant-kind"` + TimeDateMonth bool `mapstructure:"time-date-month"` } type UseTestingSettings struct { diff --git a/pkg/golinters/usestdlibvars/testdata/usestdlibvars_non_default.go b/pkg/golinters/usestdlibvars/testdata/usestdlibvars_non_default.go index 14f4a93a6b3c..9eee473f0d6d 100644 --- a/pkg/golinters/usestdlibvars/testdata/usestdlibvars_non_default.go +++ b/pkg/golinters/usestdlibvars/testdata/usestdlibvars_non_default.go @@ -2,7 +2,10 @@ //golangcitest:config_path testdata/usestdlibvars_non_default.yml package testdata -import "net/http" +import ( + "net/http" + "time" +) func _200() { _ = 200 @@ -52,3 +55,8 @@ const ( _ = "ECDSAWithP256AndSHA256" // want `"ECDSAWithP256AndSHA256" can be replaced by tls\.ECDSAWithP256AndSHA256\.String\(\)` _ = "ECDSAWithP384AndSHA384" // want `"ECDSAWithP384AndSHA384" can be replaced by tls\.ECDSAWithP384AndSHA384\.String\(\)` ) + +func _() { + var _ = time.Date(2023, 1, 2, 3, 4, 5, 0, time.UTC) // want `"1" can be replaced by time\.January` + var _ = time.Date(2023, 10, 2, 3, 4, 5, 0, time.UTC) // want `"10" can be replaced by time\.October` +} diff --git a/pkg/golinters/usestdlibvars/testdata/usestdlibvars_non_default.yml b/pkg/golinters/usestdlibvars/testdata/usestdlibvars_non_default.yml index 8100af59cdb1..d2942621daee 100644 --- a/pkg/golinters/usestdlibvars/testdata/usestdlibvars_non_default.yml +++ b/pkg/golinters/usestdlibvars/testdata/usestdlibvars_non_default.yml @@ -13,3 +13,4 @@ linters: sql-isolation-level: true tls-signature-scheme: true constant-kind: true + time-date-month: true diff --git a/pkg/golinters/usestdlibvars/usestdlibvars.go b/pkg/golinters/usestdlibvars/usestdlibvars.go index 9342c4ccd7a3..e4a900ff6465 100644 --- a/pkg/golinters/usestdlibvars/usestdlibvars.go +++ b/pkg/golinters/usestdlibvars/usestdlibvars.go @@ -24,6 +24,7 @@ func New(settings *config.UseStdlibVarsSettings) *goanalysis.Linter { analyzer.TimeMonthFlag: settings.TimeMonth, analyzer.TimeWeekdayFlag: settings.TimeWeekday, analyzer.TLSSignatureSchemeFlag: settings.TLSSignatureScheme, + analyzer.TimeDateMonthFlag: settings.TimeDateMonth, } } From 156db1d836e664439e1dbf181948ddd66e156374 Mon Sep 17 00:00:00 2001 From: ccoVeille <3875889+ccoVeille@users.noreply.github.com> Date: Tue, 27 May 2025 12:02:00 +0200 Subject: [PATCH 134/152] fix: error message when trying to migrate a migrated config (#5836) Co-authored-by: Fernandez Ludovic --- pkg/commands/migrate.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/commands/migrate.go b/pkg/commands/migrate.go index 7c73209ed180..78e7842bed04 100644 --- a/pkg/commands/migrate.go +++ b/pkg/commands/migrate.go @@ -81,10 +81,6 @@ func newMigrateCommand(log logutils.Log, info BuildInfo) *migrateCommand { } func (c *migrateCommand) execute(_ *cobra.Command, _ []string) error { - if c.cfg.Version != "" { - return fmt.Errorf("configuration version is already set: %s", c.cfg.Version) - } - srcPath := c.viper.ConfigFileUsed() if srcPath == "" { c.log.Warnf("No config file detected") @@ -141,6 +137,10 @@ func (c *migrateCommand) preRunE(cmd *cobra.Command, _ []string) error { return fmt.Errorf("unsupported format: %s", c.opts.format) } + if c.cfg.Version != "" { + return fmt.Errorf("configuration version is already set: %s", c.cfg.Version) + } + if c.opts.skipValidation { return nil } From d4bc40ed76ec038911cb56bacdbae38565dd3f8f Mon Sep 17 00:00:00 2001 From: ccoVeille <3875889+ccoVeille@users.noreply.github.com> Date: Tue, 27 May 2025 12:02:31 +0200 Subject: [PATCH 135/152] fix: formatters CLI flags help message (#5835) --- pkg/commands/formatters.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/commands/formatters.go b/pkg/commands/formatters.go index a3fafd1d25c9..22a9914ae2ff 100644 --- a/pkg/commands/formatters.go +++ b/pkg/commands/formatters.go @@ -59,7 +59,8 @@ func newFormattersCommand(logger logutils.Log) *formattersCommand { fs.SortFlags = false // sort them as they are defined here setupConfigFileFlagSet(fs, &c.opts.LoaderOptions) - setupLintersFlagSet(c.viper, fs) + + setupFormattersFlagSet(c.viper, fs) fs.BoolVar(&c.opts.JSON, "json", false, color.GreenString("Display as JSON")) From b9510d7a4edbd5d9c821075fb56d5d426dae8783 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 May 2025 14:15:47 +0200 Subject: [PATCH 136/152] build(deps): bump github.com/golangci/plugin-module-register from 0.1.1 to 0.1.2 (#5838) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 95776f35e674..c4850ff4f3bb 100644 --- a/go.mod +++ b/go.mod @@ -49,7 +49,7 @@ require ( github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95 github.com/golangci/misspell v0.7.0 - github.com/golangci/plugin-module-register v0.1.1 + github.com/golangci/plugin-module-register v0.1.2 github.com/golangci/revgrep v0.8.0 github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e diff --git a/go.sum b/go.sum index 240f74257922..64adaf104e62 100644 --- a/go.sum +++ b/go.sum @@ -259,8 +259,8 @@ github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95 h1:AkK+w9FZBXlU/x github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95/go.mod h1:k9mmcyWKSTMcPPvQUCfRWWQ9VHJ1U9Dc0R7kaXAgtnQ= github.com/golangci/misspell v0.7.0 h1:4GOHr/T1lTW0hhR4tgaaV1WS/lJ+ncvYCoFKmqJsj0c= github.com/golangci/misspell v0.7.0/go.mod h1:WZyyI2P3hxPY2UVHs3cS8YcllAeyfquQcKfdeE9AFVg= -github.com/golangci/plugin-module-register v0.1.1 h1:TCmesur25LnyJkpsVrupv1Cdzo+2f7zX0H6Jkw1Ol6c= -github.com/golangci/plugin-module-register v0.1.1/go.mod h1:TTpqoB6KkwOJMV8u7+NyXMrkwwESJLOkfl9TxR1DGFc= +github.com/golangci/plugin-module-register v0.1.2 h1:e5WM6PO6NIAEcij3B053CohVp3HIYbzSuP53UAYgOpg= +github.com/golangci/plugin-module-register v0.1.2/go.mod h1:1+QGTsKBvAIvPvoY/os+G5eoqxWn70HYDm2uvUyGuVw= github.com/golangci/revgrep v0.8.0 h1:EZBctwbVd0aMeRnNUsFogoyayvKHyxlV3CdUA46FX2s= github.com/golangci/revgrep v0.8.0/go.mod h1:U4R/s9dlXZsg8uJmaR1GrloUr14D7qDl8gi2iPXJH8k= github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e h1:ai0EfmVYE2bRA5htgAG9r7s3tHsfjIhN98WshBTJ9jM= From 10525556561539351fb38b679be789900ba00c29 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 May 2025 14:35:40 +0200 Subject: [PATCH 137/152] build(deps): bump github.com/mgechev/revive from 1.9.0 to 1.10.0 (#5837) Co-authored-by: Fernandez Ludovic --- .golangci.next.reference.yml | 17 +++- go.mod | 5 +- go.sum | 16 +--- jsonschema/golangci.next.jsonschema.json | 3 + pkg/golinters/revive/revive.go | 102 ++++++++++++----------- 5 files changed, 78 insertions(+), 65 deletions(-) diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index 36af28206aa1..0e8609212c6b 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -2589,7 +2589,7 @@ linters: severity: warning disabled: false exclude: [""] - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#redundant-test-main-exit + # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#redundant-test-main-exit - name: redundant-test-main-exit severity: warning disabled: false @@ -2629,6 +2629,11 @@ linters: exclude: [""] arguments: - "preserve-scope" + # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#time-date + - name: time-date + severity: warning + disabled: false + exclude: [""] # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#time-equal - name: time-equal severity: warning @@ -2669,6 +2674,11 @@ linters: arguments: - "fmt.Printf" - "myFunction" + # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#unnecessary-format + - name: unnecessary-format + severity: warning + disabled: false + exclude: [""] # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#unnecessary-stmt - name: unnecessary-stmt severity: warning @@ -2703,6 +2713,11 @@ linters: severity: warning disabled: false exclude: [""] + # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#use-fmt-print + - name: use-fmt-print + severity: warning + disabled: false + exclude: [""] # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#useless-break - name: useless-break severity: warning diff --git a/go.mod b/go.mod index c4850ff4f3bb..20488af3e2eb 100644 --- a/go.mod +++ b/go.mod @@ -80,7 +80,7 @@ require ( github.com/maratori/testpackage v1.1.1 github.com/matoous/godox v1.1.0 github.com/mattn/go-colorable v0.1.14 - github.com/mgechev/revive v1.9.0 + github.com/mgechev/revive v1.10.0 github.com/mitchellh/go-homedir v1.1.0 github.com/moricho/tparallel v0.3.2 github.com/nakabonne/nestif v0.3.1 @@ -141,6 +141,7 @@ require ( ) require ( + codeberg.org/chavacava/garif v0.2.0 // indirect github.com/Masterminds/semver/v3 v3.3.1 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect @@ -150,7 +151,6 @@ require ( github.com/charmbracelet/x/ansi v0.8.0 // indirect github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect github.com/charmbracelet/x/term v0.2.1 // indirect - github.com/chavacava/garif v0.1.0 // indirect github.com/dave/dst v0.27.3 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dlclark/regexp2 v1.11.5 // indirect @@ -184,7 +184,6 @@ require ( github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/muesli/termenv v0.16.0 // indirect - github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect diff --git a/go.sum b/go.sum index 64adaf104e62..732d7ef4d6af 100644 --- a/go.sum +++ b/go.sum @@ -34,6 +34,8 @@ 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= +codeberg.org/chavacava/garif v0.2.0 h1:F0tVjhYbuOCnvNcU3YSpO6b3Waw6Bimy4K0mM8y6MfY= +codeberg.org/chavacava/garif v0.2.0/go.mod h1:P2BPbVbT4QcvLZrORc2T29szK3xEOlnl0GiPTJmEqBQ= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/4meepo/tagalign v1.4.2 h1:0hcLHPGMjDyM1gHG58cS73aQF8J4TdVR96TZViorO9E= github.com/4meepo/tagalign v1.4.2/go.mod h1:+p4aMyFM+ra7nb41CnFG6aSDXqRxU/w1VQqScKqDARI= @@ -125,8 +127,6 @@ github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0G github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= -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= @@ -407,13 +407,12 @@ github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHP github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= 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/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= 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/mgechev/revive v1.9.0 h1:8LaA62XIKrb8lM6VsBSQ92slt/o92z5+hTw3CmrvSrM= -github.com/mgechev/revive v1.9.0/go.mod h1:LAPq3+MgOf7GcL5PlWIkHb0PT7XH4NuC2LdWymhb9Mo= +github.com/mgechev/revive v1.10.0 h1:x2oJsd7yrDp0mC6IgZqSKBTjSUC9Zk5Ob2WfBwZic2I= +github.com/mgechev/revive v1.10.0/go.mod h1:1MRO9zUV7Yukhqh/nGRKSaw6xC5XDzPWPja5GMPWoSE= 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/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -437,8 +436,6 @@ github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= github.com/nunnatsa/ginkgolinter v0.19.1 h1:mjwbOlDQxZi9Cal+KfbEJTCz327OLNfwNvoZ70NJ+c4= github.com/nunnatsa/ginkgolinter v0.19.1/go.mod h1:jkQ3naZDmxaZMXPWaS9rblH+i+GWXQCaS/JFIWcOH2s= -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.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus= github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8= github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y= @@ -557,17 +554,12 @@ github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8B github.com/stbenjam/no-sprintf-host-port v0.2.0/go.mod h1:eL0bQ9PasS0hsyTyfTjjG+E80QIyPnBVQbYZyv20Jfk= 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/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 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= 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.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= diff --git a/jsonschema/golangci.next.jsonschema.json b/jsonschema/golangci.next.jsonschema.json index a84a30121f38..70fa57bdad74 100644 --- a/jsonschema/golangci.next.jsonschema.json +++ b/jsonschema/golangci.next.jsonschema.json @@ -638,6 +638,7 @@ "string-of-int", "struct-tag", "superfluous-else", + "time-date", "time-equal", "time-naming", "unchecked-type-assertion", @@ -645,12 +646,14 @@ "unexported-naming", "unexported-return", "unhandled-error", + "unnecessary-format", "unnecessary-stmt", "unreachable-code", "unused-parameter", "unused-receiver", "use-any", "use-errors-new", + "use-fmt-print", "useless-break", "var-declaration", "var-naming", diff --git a/pkg/golinters/revive/revive.go b/pkg/golinters/revive/revive.go index 32b42ba8314d..01eccd537d9e 100644 --- a/pkg/golinters/revive/revive.go +++ b/pkg/golinters/revive/revive.go @@ -152,7 +152,7 @@ func (w *wrapper) toIssue(pass *analysis.Pass, failure *lint.Failure) goanalysis f := pass.Fset.File(token.Pos(failure.Position.Start.Offset)) // Skip cgo files because the positions are wrong. - if failure.GetFilename() == f.Name() { + if failure.Filename() == f.Name() { issue.SuggestedFixes = []analysis.SuggestedFix{{ TextEdits: []analysis.TextEdit{{ Pos: f.LineStart(failure.Position.Start.Line), @@ -269,7 +269,7 @@ func safeTomlSlice(r []any) []any { } // This element is not exported by revive, so we need copy the code. -// Extracted from https://github.com/mgechev/revive/blob/v1.6.0/config/config.go#L16 +// Extracted from https://github.com/mgechev/revive/blob/v1.10.0/config/config.go#L16 var defaultRules = []lint.Rule{ &rule.VarDeclarationsRule{}, &rule.PackageCommentsRule{}, @@ -297,66 +297,70 @@ var defaultRules = []lint.Rule{ } var allRules = append([]lint.Rule{ + &rule.AddConstantRule{}, &rule.ArgumentsLimitRule{}, - &rule.CyclomaticRule{}, - &rule.FileHeaderRule{}, + &rule.AtomicRule{}, + &rule.BannedCharsRule{}, + &rule.BareReturnRule{}, + &rule.BoolLiteralRule{}, + &rule.CallToGCRule{}, + &rule.CognitiveComplexityRule{}, + &rule.CommentsDensityRule{}, + &rule.CommentSpacingsRule{}, &rule.ConfusingNamingRule{}, - &rule.GetReturnRule{}, - &rule.ModifiesParamRule{}, &rule.ConfusingResultsRule{}, - &rule.DeepExitRule{}, - &rule.AddConstantRule{}, - &rule.FlagParamRule{}, - &rule.UnnecessaryStmtRule{}, - &rule.StructTagRule{}, - &rule.ModifiesValRecRule{}, &rule.ConstantLogicalExprRule{}, - &rule.BoolLiteralRule{}, - &rule.ImportsBlocklistRule{}, - &rule.FunctionResultsLimitRule{}, - &rule.MaxPublicStructsRule{}, - &rule.RangeValInClosureRule{}, - &rule.RangeValAddress{}, - &rule.WaitGroupByValueRule{}, - &rule.AtomicRule{}, - &rule.EmptyLinesRule{}, - &rule.LineLengthLimitRule{}, - &rule.CallToGCRule{}, + &rule.CyclomaticRule{}, + &rule.DataRaceRule{}, + &rule.DeepExitRule{}, + &rule.DeferRule{}, &rule.DuplicatedImportsRule{}, - &rule.ImportShadowingRule{}, - &rule.BareReturnRule{}, - &rule.UnusedReceiverRule{}, - &rule.UnhandledErrorRule{}, - &rule.CognitiveComplexityRule{}, - &rule.StringOfIntRule{}, - &rule.StringFormatRule{}, &rule.EarlyReturnRule{}, - &rule.UnconditionalRecursionRule{}, - &rule.IdenticalBranchesRule{}, - &rule.DeferRule{}, - &rule.UnexportedNamingRule{}, - &rule.FunctionLength{}, - &rule.NestedStructs{}, - &rule.UselessBreak{}, - &rule.UncheckedTypeAssertionRule{}, - &rule.TimeEqualRule{}, - &rule.BannedCharsRule{}, - &rule.OptimizeOperandsOrderRule{}, - &rule.UseAnyRule{}, - &rule.DataRaceRule{}, - &rule.CommentSpacingsRule{}, - &rule.IfReturnRule{}, - &rule.RedundantImportAlias{}, - &rule.ImportAliasNamingRule{}, + &rule.EmptyLinesRule{}, &rule.EnforceMapStyleRule{}, &rule.EnforceRepeatedArgTypeStyleRule{}, &rule.EnforceSliceStyleRule{}, - &rule.MaxControlNestingRule{}, - &rule.CommentsDensityRule{}, + &rule.FileHeaderRule{}, &rule.FileLengthLimitRule{}, &rule.FilenameFormatRule{}, + &rule.FlagParamRule{}, + &rule.FunctionLength{}, + &rule.FunctionResultsLimitRule{}, + &rule.GetReturnRule{}, + &rule.IdenticalBranchesRule{}, + &rule.IfReturnRule{}, + &rule.ImportAliasNamingRule{}, + &rule.ImportsBlocklistRule{}, + &rule.ImportShadowingRule{}, + &rule.LineLengthLimitRule{}, + &rule.MaxControlNestingRule{}, + &rule.MaxPublicStructsRule{}, + &rule.ModifiesParamRule{}, + &rule.ModifiesValRecRule{}, + &rule.NestedStructs{}, + &rule.OptimizeOperandsOrderRule{}, + &rule.RangeValAddress{}, + &rule.RangeValInClosureRule{}, &rule.RedundantBuildTagRule{}, + &rule.RedundantImportAlias{}, + &rule.RedundantTestMainExitRule{}, + &rule.StringFormatRule{}, + &rule.StringOfIntRule{}, + &rule.StructTagRule{}, + &rule.TimeDateRule{}, + &rule.TimeEqualRule{}, + &rule.UncheckedTypeAssertionRule{}, + &rule.UnconditionalRecursionRule{}, + &rule.UnexportedNamingRule{}, + &rule.UnhandledErrorRule{}, + &rule.UnnecessaryFormatRule{}, + &rule.UnnecessaryStmtRule{}, + &rule.UnusedReceiverRule{}, + &rule.UseAnyRule{}, &rule.UseErrorsNewRule{}, + &rule.UseFmtPrintRule{}, + &rule.UselessBreak{}, + &rule.WaitGroupByValueRule{}, }, defaultRules...) const defaultConfidence = 0.8 From 2a63ebc12fd4c8a31c281cffa31671c161461fb7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 May 2025 15:25:32 +0200 Subject: [PATCH 138/152] build(deps): bump github.com/Abirdcfly/dupword from 0.1.4 to 0.1.5 (#5839) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 20488af3e2eb..c6c93663922d 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( 4d63.com/gocheckcompilerdirectives v1.3.0 4d63.com/gochecknoglobals v0.2.2 github.com/4meepo/tagalign v1.4.2 - github.com/Abirdcfly/dupword v0.1.4 + github.com/Abirdcfly/dupword v0.1.5 github.com/Antonboom/errname v1.1.0 github.com/Antonboom/nilnil v1.1.0 github.com/Antonboom/testifylint v1.6.1 diff --git a/go.sum b/go.sum index 732d7ef4d6af..20b0065770d8 100644 --- a/go.sum +++ b/go.sum @@ -39,8 +39,8 @@ codeberg.org/chavacava/garif v0.2.0/go.mod h1:P2BPbVbT4QcvLZrORc2T29szK3xEOlnl0G dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/4meepo/tagalign v1.4.2 h1:0hcLHPGMjDyM1gHG58cS73aQF8J4TdVR96TZViorO9E= github.com/4meepo/tagalign v1.4.2/go.mod h1:+p4aMyFM+ra7nb41CnFG6aSDXqRxU/w1VQqScKqDARI= -github.com/Abirdcfly/dupword v0.1.4 h1:jxqkdgO0L7FSwq4fMu3d+fAA1E3bBQAtl4utA3tcQZM= -github.com/Abirdcfly/dupword v0.1.4/go.mod h1:s+BFMuL/I4YSiFv29snqyjwzDp4b65W2Kvy+PKzZ6cw= +github.com/Abirdcfly/dupword v0.1.5 h1:beKz0j4wOOwehuExCSdJiN8yqBbzBfVDCrEPkiW6LK4= +github.com/Abirdcfly/dupword v0.1.5/go.mod h1:s+BFMuL/I4YSiFv29snqyjwzDp4b65W2Kvy+PKzZ6cw= github.com/Antonboom/errname v1.1.0 h1:A+ucvdpMwlo/myWrkHEUEBWc/xuXdud23S8tmTb/oAE= github.com/Antonboom/errname v1.1.0/go.mod h1:O1NMrzgUcVBGIfi3xlVuvX8Q/VP/73sseCaAppfjqZw= github.com/Antonboom/nilnil v1.1.0 h1:jGxJxjgYS3VUUtOTNk8Z1icwT5ESpLH/426fjmQG+ng= From f80cb324fc10936ee32ec1ea07154893b1ed9385 Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Wed, 28 May 2025 15:47:59 +0200 Subject: [PATCH 139/152] chore: improve pull request template --- .github/PULL_REQUEST_TEMPLATE.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index be686a73c8c7..9bfa6efaef42 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -8,3 +8,12 @@ The updates happen at least automatically once a week (Sunday 11am UTC). No pull requests to update a linter will be accepted unless you are the author of the linter AND specific changes are required. --> + + From 0bcafa0850bd0ac1aeaa440f4684838e2fb5cf49 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 May 2025 17:09:22 +0200 Subject: [PATCH 140/152] build(deps): bump github.com/Abirdcfly/dupword from 0.1.5 to 0.1.6 (#5841) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c6c93663922d..cf3c581a5fba 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( 4d63.com/gocheckcompilerdirectives v1.3.0 4d63.com/gochecknoglobals v0.2.2 github.com/4meepo/tagalign v1.4.2 - github.com/Abirdcfly/dupword v0.1.5 + github.com/Abirdcfly/dupword v0.1.6 github.com/Antonboom/errname v1.1.0 github.com/Antonboom/nilnil v1.1.0 github.com/Antonboom/testifylint v1.6.1 diff --git a/go.sum b/go.sum index 20b0065770d8..55ffdf91c2e4 100644 --- a/go.sum +++ b/go.sum @@ -39,8 +39,8 @@ codeberg.org/chavacava/garif v0.2.0/go.mod h1:P2BPbVbT4QcvLZrORc2T29szK3xEOlnl0G dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/4meepo/tagalign v1.4.2 h1:0hcLHPGMjDyM1gHG58cS73aQF8J4TdVR96TZViorO9E= github.com/4meepo/tagalign v1.4.2/go.mod h1:+p4aMyFM+ra7nb41CnFG6aSDXqRxU/w1VQqScKqDARI= -github.com/Abirdcfly/dupword v0.1.5 h1:beKz0j4wOOwehuExCSdJiN8yqBbzBfVDCrEPkiW6LK4= -github.com/Abirdcfly/dupword v0.1.5/go.mod h1:s+BFMuL/I4YSiFv29snqyjwzDp4b65W2Kvy+PKzZ6cw= +github.com/Abirdcfly/dupword v0.1.6 h1:qeL6u0442RPRe3mcaLcbaCi2/Y/hOcdtw6DE9odjz9c= +github.com/Abirdcfly/dupword v0.1.6/go.mod h1:s+BFMuL/I4YSiFv29snqyjwzDp4b65W2Kvy+PKzZ6cw= github.com/Antonboom/errname v1.1.0 h1:A+ucvdpMwlo/myWrkHEUEBWc/xuXdud23S8tmTb/oAE= github.com/Antonboom/errname v1.1.0/go.mod h1:O1NMrzgUcVBGIfi3xlVuvX8Q/VP/73sseCaAppfjqZw= github.com/Antonboom/nilnil v1.1.0 h1:jGxJxjgYS3VUUtOTNk8Z1icwT5ESpLH/426fjmQG+ng= From f54365bc92856d453f8c7c4684022b5d4efa0cb1 Mon Sep 17 00:00:00 2001 From: Alwx Date: Fri, 30 May 2025 00:08:39 +0300 Subject: [PATCH 141/152] Add noinlineerr linter (#5826) --- .golangci.next.reference.yml | 2 + go.mod | 1 + go.sum | 2 + jsonschema/golangci.next.jsonschema.json | 1 + pkg/golinters/noinlineerr/noinlineerr.go | 13 +++ .../noinlineerr_integration_test.go | 19 ++++ .../testdata/fix/in/noinlineerr.go | 59 +++++++++++++ .../testdata/fix/out/noinlineerr.go | 59 +++++++++++++ .../noinlineerr/testdata/noinlineerr.go | 87 +++++++++++++++++++ pkg/lint/lintersdb/builder_linter.go | 6 ++ 10 files changed, 249 insertions(+) create mode 100644 pkg/golinters/noinlineerr/noinlineerr.go create mode 100644 pkg/golinters/noinlineerr/noinlineerr_integration_test.go create mode 100644 pkg/golinters/noinlineerr/testdata/fix/in/noinlineerr.go create mode 100644 pkg/golinters/noinlineerr/testdata/fix/out/noinlineerr.go create mode 100644 pkg/golinters/noinlineerr/testdata/noinlineerr.go diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index 0e8609212c6b..abc9c060efbe 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -91,6 +91,7 @@ linters: - nilnil - nlreturn - noctx + - noinlineerr - nolintlint - nonamedreturns - nosprintfhostport @@ -200,6 +201,7 @@ linters: - nilnil - nlreturn - noctx + - noinlineerr - nolintlint - nonamedreturns - nosprintfhostport diff --git a/go.mod b/go.mod index cf3c581a5fba..6f084bed2675 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( 4d63.com/gochecknoglobals v0.2.2 github.com/4meepo/tagalign v1.4.2 github.com/Abirdcfly/dupword v0.1.6 + github.com/AlwxSin/noinlineerr v1.0.3 github.com/Antonboom/errname v1.1.0 github.com/Antonboom/nilnil v1.1.0 github.com/Antonboom/testifylint v1.6.1 diff --git a/go.sum b/go.sum index 55ffdf91c2e4..0a4e0d2587b0 100644 --- a/go.sum +++ b/go.sum @@ -41,6 +41,8 @@ github.com/4meepo/tagalign v1.4.2 h1:0hcLHPGMjDyM1gHG58cS73aQF8J4TdVR96TZViorO9E github.com/4meepo/tagalign v1.4.2/go.mod h1:+p4aMyFM+ra7nb41CnFG6aSDXqRxU/w1VQqScKqDARI= github.com/Abirdcfly/dupword v0.1.6 h1:qeL6u0442RPRe3mcaLcbaCi2/Y/hOcdtw6DE9odjz9c= github.com/Abirdcfly/dupword v0.1.6/go.mod h1:s+BFMuL/I4YSiFv29snqyjwzDp4b65W2Kvy+PKzZ6cw= +github.com/AlwxSin/noinlineerr v1.0.3 h1:9b5edChzzwX30BuBci13LHVZHF5q7hW9qtrs+wJdDog= +github.com/AlwxSin/noinlineerr v1.0.3/go.mod h1:+QgkkoYrMH7RHvcdxdlI7vYYEdgeoFOVjU9sUhw/rQc= github.com/Antonboom/errname v1.1.0 h1:A+ucvdpMwlo/myWrkHEUEBWc/xuXdud23S8tmTb/oAE= github.com/Antonboom/errname v1.1.0/go.mod h1:O1NMrzgUcVBGIfi3xlVuvX8Q/VP/73sseCaAppfjqZw= github.com/Antonboom/nilnil v1.1.0 h1:jGxJxjgYS3VUUtOTNk8Z1icwT5ESpLH/426fjmQG+ng= diff --git a/jsonschema/golangci.next.jsonschema.json b/jsonschema/golangci.next.jsonschema.json index 70fa57bdad74..a12cb912b569 100644 --- a/jsonschema/golangci.next.jsonschema.json +++ b/jsonschema/golangci.next.jsonschema.json @@ -794,6 +794,7 @@ "nilnil", "nlreturn", "noctx", + "noinlineerr", "nolintlint", "nonamedreturns", "nosprintfhostport", diff --git a/pkg/golinters/noinlineerr/noinlineerr.go b/pkg/golinters/noinlineerr/noinlineerr.go new file mode 100644 index 000000000000..4f9f82eb4d0c --- /dev/null +++ b/pkg/golinters/noinlineerr/noinlineerr.go @@ -0,0 +1,13 @@ +package noinlineerr + +import ( + "github.com/AlwxSin/noinlineerr" + + "github.com/golangci/golangci-lint/v2/pkg/goanalysis" +) + +func New() *goanalysis.Linter { + return goanalysis. + NewLinterFromAnalyzer(noinlineerr.NewAnalyzer()). + WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/pkg/golinters/noinlineerr/noinlineerr_integration_test.go b/pkg/golinters/noinlineerr/noinlineerr_integration_test.go new file mode 100644 index 000000000000..3b14450932a1 --- /dev/null +++ b/pkg/golinters/noinlineerr/noinlineerr_integration_test.go @@ -0,0 +1,19 @@ +package noinlineerr + +import ( + "testing" + + "github.com/golangci/golangci-lint/v2/test/testshared/integration" +) + +func TestFromTestdata(t *testing.T) { + integration.RunTestdata(t) +} + +func TestFix(t *testing.T) { + integration.RunFix(t) +} + +func TestFixPathPrefix(t *testing.T) { + integration.RunFixPathPrefix(t) +} diff --git a/pkg/golinters/noinlineerr/testdata/fix/in/noinlineerr.go b/pkg/golinters/noinlineerr/testdata/fix/in/noinlineerr.go new file mode 100644 index 000000000000..62c90bd98017 --- /dev/null +++ b/pkg/golinters/noinlineerr/testdata/fix/in/noinlineerr.go @@ -0,0 +1,59 @@ +//golangcitest:args -Enoinlineerr +//golangcitest:expected_exitcode 0 +package testdata + +type MyAliasErr error + +type MyCustomError struct{} + +func (mc *MyCustomError) Error() string { + return "error" +} + +func doSomething() error { + return nil +} + +func doSmthManyArgs(a, b, c, d int) error { + return nil +} + +func doSmthMultipleReturn() (bool, error) { + return false, nil +} + +func doMyAliasErr() MyAliasErr { + return nil +} + +func doMyCustomErr() *MyCustomError { + return &MyCustomError{} +} + +func invalid() error { + err := doSomething() + if err != nil { + return err + } + + err = doSmthManyArgs(0, + 0, + 0, + 0, + ) + if err != nil { + return err + } + + err = doMyAliasErr() + if err != nil { + return err + } + + err = doMyCustomErr() + if err != nil { + return err + } + + return nil +} diff --git a/pkg/golinters/noinlineerr/testdata/fix/out/noinlineerr.go b/pkg/golinters/noinlineerr/testdata/fix/out/noinlineerr.go new file mode 100644 index 000000000000..62c90bd98017 --- /dev/null +++ b/pkg/golinters/noinlineerr/testdata/fix/out/noinlineerr.go @@ -0,0 +1,59 @@ +//golangcitest:args -Enoinlineerr +//golangcitest:expected_exitcode 0 +package testdata + +type MyAliasErr error + +type MyCustomError struct{} + +func (mc *MyCustomError) Error() string { + return "error" +} + +func doSomething() error { + return nil +} + +func doSmthManyArgs(a, b, c, d int) error { + return nil +} + +func doSmthMultipleReturn() (bool, error) { + return false, nil +} + +func doMyAliasErr() MyAliasErr { + return nil +} + +func doMyCustomErr() *MyCustomError { + return &MyCustomError{} +} + +func invalid() error { + err := doSomething() + if err != nil { + return err + } + + err = doSmthManyArgs(0, + 0, + 0, + 0, + ) + if err != nil { + return err + } + + err = doMyAliasErr() + if err != nil { + return err + } + + err = doMyCustomErr() + if err != nil { + return err + } + + return nil +} diff --git a/pkg/golinters/noinlineerr/testdata/noinlineerr.go b/pkg/golinters/noinlineerr/testdata/noinlineerr.go new file mode 100644 index 000000000000..3bf739b7d1c3 --- /dev/null +++ b/pkg/golinters/noinlineerr/testdata/noinlineerr.go @@ -0,0 +1,87 @@ +//golangcitest:args -Enoinlineerr +package testdata + +import ( + "fmt" + "strconv" +) + +type MyAliasErr error + +type MyCustomError struct {} + +func (mc *MyCustomError) Error() string { + return "error" +} + +func doSomething() error { + return nil +} + +func doSmthManyArgs(a, b, c, d int) error { + return nil +} + +func doSmthMultipleReturn() (bool, error) { + return false, nil +} + +func doMyAliasErr() MyAliasErr { + return nil +} + +func doMyCustomErr() *MyCustomError { + return &MyCustomError{} +} + +func valid() error { + err := doSomething() // ok + if err != nil { + return err + } + + err = doSmthManyArgs(0, 0, 0, 0) // ok + if err != nil { + return err + } + + _, err = doSmthMultipleReturn() // ok + if err != nil { + return err + } + + if ok, _ := strconv.ParseBool("1"); ok { + fmt.Println("ok") + } + + return nil +} + +func invalid() error { + if err := doSomething(); err != nil { // want "avoid inline error handling using `if err := ...; err != nil`; use plain assignment `err := ...`" + return err + } + + if err := doSmthManyArgs(0, // want "avoid inline error handling using `if err := ...; err != nil`; use plain assignment `err := ...`" + 0, + 0, + 0, + ); err != nil { + return err + } + + if _, err := doSmthMultipleReturn(); err != nil { // want "avoid inline error handling using `if err := ...; err != nil`; use plain assignment `err := ...`" + _ = false + return err + } + + if err := doMyAliasErr(); err != nil { // want "avoid inline error handling using `if err := ...; err != nil`; use plain assignment `err := ...`" + return err + } + + if err := doMyCustomErr(); err != nil { // want "avoid inline error handling using `if err := ...; err != nil`; use plain assignment `err := ...`" + return err + } + + return nil +} diff --git a/pkg/lint/lintersdb/builder_linter.go b/pkg/lint/lintersdb/builder_linter.go index 48a64375f53c..734aab63cd1c 100644 --- a/pkg/lint/lintersdb/builder_linter.go +++ b/pkg/lint/lintersdb/builder_linter.go @@ -79,6 +79,7 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/golinters/nilnil" "github.com/golangci/golangci-lint/v2/pkg/golinters/nlreturn" "github.com/golangci/golangci-lint/v2/pkg/golinters/noctx" + "github.com/golangci/golangci-lint/v2/pkg/golinters/noinlineerr" "github.com/golangci/golangci-lint/v2/pkg/golinters/nolintlint" "github.com/golangci/golangci-lint/v2/pkg/golinters/nonamedreturns" "github.com/golangci/golangci-lint/v2/pkg/golinters/nosprintfhostport" @@ -511,6 +512,11 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { WithLoadForGoAnalysis(). WithURL("https://github.com/sonatard/noctx"), + linter.NewConfig(noinlineerr.New()). + WithSince("v2.2.0"). + WithLoadForGoAnalysis(). + WithURL("https://github.com/AlwxSin/noinlineerr"), + linter.NewConfig(nonamedreturns.New(&cfg.Linters.Settings.NoNamedReturns)). WithSince("v1.46.0"). WithLoadForGoAnalysis(). From 026567f803379eaab587112aabbbdcaf49e6fb8d Mon Sep 17 00:00:00 2001 From: Oleksandr Redko Date: Sat, 31 May 2025 02:12:14 +0300 Subject: [PATCH 142/152] dev: some simplifications (#5843) --- .../internal/migrate/migrate_linter_names.go | 14 ++++---------- pkg/goformatters/internal/diff.go | 5 +---- pkg/golinters/govet/govet_test.go | 2 +- pkg/golinters/tagliatelle/tagliatelle.go | 6 +++--- pkg/report/log.go | 3 ++- pkg/result/processors/base_rule.go | 9 ++------- pkg/result/processors/nolint_filter.go | 3 +-- test/testshared/integration/run.go | 3 ++- test/testshared/runner.go | 7 +++---- 9 files changed, 19 insertions(+), 33 deletions(-) diff --git a/pkg/commands/internal/migrate/migrate_linter_names.go b/pkg/commands/internal/migrate/migrate_linter_names.go index da003e9af77d..bbb178ab3846 100644 --- a/pkg/commands/internal/migrate/migrate_linter_names.go +++ b/pkg/commands/internal/migrate/migrate_linter_names.go @@ -749,11 +749,8 @@ func allEnabled(old versionone.Linters, linters []LinterInfo) []LinterInfo { var results []LinterInfo for _, linter := range linters { - for _, name := range old.Enable { - if linter.isName(name) { - results = append(results, linter) - break - } + if slices.ContainsFunc(old.Enable, linter.isName) { + results = append(results, linter) } } @@ -764,11 +761,8 @@ func allDisabled(old versionone.Linters, linters []LinterInfo) []LinterInfo { var results []LinterInfo for _, linter := range linters { - for _, name := range old.Disable { - if linter.isName(name) { - results = append(results, linter) - break - } + if slices.ContainsFunc(old.Disable, linter.isName) { + results = append(results, linter) } } diff --git a/pkg/goformatters/internal/diff.go b/pkg/goformatters/internal/diff.go index 7b9f80bc4228..fcec87bb8bbd 100644 --- a/pkg/goformatters/internal/diff.go +++ b/pkg/goformatters/internal/diff.go @@ -250,10 +250,7 @@ func ExtractDiagnosticFromPatch( } func toDiagnostic(ft *token.File, change Change, adjLine int) analysis.Diagnostic { - from := change.From + adjLine - if from > ft.LineCount() { - from = ft.LineCount() - } + from := min(change.From+adjLine, ft.LineCount()) start := ft.LineStart(from) diff --git a/pkg/golinters/govet/govet_test.go b/pkg/golinters/govet/govet_test.go index ec7072795f74..794ef6ece9db 100644 --- a/pkg/golinters/govet/govet_test.go +++ b/pkg/golinters/govet/govet_test.go @@ -18,7 +18,7 @@ import ( func TestGovet(t *testing.T) { // Checking that every default analyzer is in "all analyzers" list. - checkList := append([]*analysis.Analyzer{}, defaultAnalyzers...) + checkList := slices.Clone(defaultAnalyzers) checkList = append(checkList, shadow.Analyzer) // special case, used in analyzersFromConfig for _, defaultAnalyzer := range checkList { diff --git a/pkg/golinters/tagliatelle/tagliatelle.go b/pkg/golinters/tagliatelle/tagliatelle.go index 89ebf6c2f4df..e12cc9e82062 100644 --- a/pkg/golinters/tagliatelle/tagliatelle.go +++ b/pkg/golinters/tagliatelle/tagliatelle.go @@ -1,6 +1,8 @@ package tagliatelle import ( + "maps" + "github.com/ldez/tagliatelle" "github.com/golangci/golangci-lint/v2/pkg/config" @@ -19,9 +21,7 @@ func New(settings *config.TagliatelleSettings) *goanalysis.Linter { } if settings != nil { - for k, v := range settings.Case.Rules { - cfg.Rules[k] = v - } + maps.Copy(cfg.Rules, settings.Case.Rules) cfg.ExtendedRules = toExtendedRules(settings.Case.ExtendedRules) cfg.UseFieldName = settings.Case.UseFieldName diff --git a/pkg/report/log.go b/pkg/report/log.go index ad096415123f..c964af559379 100644 --- a/pkg/report/log.go +++ b/pkg/report/log.go @@ -2,6 +2,7 @@ package report import ( "fmt" + "slices" "strings" "github.com/golangci/golangci-lint/v2/pkg/logutils" @@ -50,7 +51,7 @@ func (lw LogWrapper) Infof(format string, args ...any) { func (lw LogWrapper) Child(name string) logutils.Log { c := lw c.origLog = lw.origLog.Child(name) - c.tags = append([]string{}, lw.tags...) + c.tags = slices.Clone(lw.tags) c.tags = append(c.tags, name) return c } diff --git a/pkg/result/processors/base_rule.go b/pkg/result/processors/base_rule.go index 607886ef1f39..46886624848a 100644 --- a/pkg/result/processors/base_rule.go +++ b/pkg/result/processors/base_rule.go @@ -2,6 +2,7 @@ package processors import ( "regexp" + "slices" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/fsutils" @@ -73,13 +74,7 @@ func (r *baseRule) match(issue *result.Issue, lines *fsutils.LineCache, log logu } func (r *baseRule) matchLinter(issue *result.Issue) bool { - for _, linter := range r.linters { - if linter == issue.FromLinter { - return true - } - } - - return false + return slices.Contains(r.linters, issue.FromLinter) } func (r *baseRule) matchSource(issue *result.Issue, lineCache *fsutils.LineCache, log logutils.Log) bool { diff --git a/pkg/result/processors/nolint_filter.go b/pkg/result/processors/nolint_filter.go index 96fd6403ec45..e17fd7ad2521 100644 --- a/pkg/result/processors/nolint_filter.go +++ b/pkg/result/processors/nolint_filter.go @@ -185,8 +185,7 @@ func (p *NolintFilter) buildIgnoredRangesForFile(f *ast.File, fset *token.FileSe ast.Walk(&e, f) // TODO: merge all ranges: there are repeated ranges - allRanges := append([]ignoredRange{}, inlineRanges...) - allRanges = append(allRanges, e.expandedRanges...) + allRanges := slices.Concat(inlineRanges, e.expandedRanges) return allRanges } diff --git a/test/testshared/integration/run.go b/test/testshared/integration/run.go index cd0b4ca97076..f1add865fb54 100644 --- a/test/testshared/integration/run.go +++ b/test/testshared/integration/run.go @@ -4,6 +4,7 @@ import ( "os" "os/exec" "path/filepath" + "slices" "strings" "testing" "time" @@ -70,7 +71,7 @@ func testOneSource(t *testing.T, log *logutils.StderrLog, binPath, sourcePath st } for _, addArg := range []string{"", "-Etypecheck"} { - caseArgs := append([]string{}, args...) + caseArgs := slices.Clone(args) if addArg != "" { caseArgs = append(caseArgs, addArg) diff --git a/test/testshared/runner.go b/test/testshared/runner.go index c516ad9a181a..69bb8bac80a7 100644 --- a/test/testshared/runner.go +++ b/test/testshared/runner.go @@ -4,6 +4,7 @@ import ( "os" "os/exec" "path/filepath" + "slices" "strings" "sync" "syscall" @@ -286,10 +287,8 @@ func (r *RunnerResult) ExpectNoIssues() { func (r *RunnerResult) ExpectExitCode(possibleCodes ...int) *RunnerResult { r.tb.Helper() - for _, pc := range possibleCodes { - if pc == r.exitCode { - return r - } + if slices.Contains(possibleCodes, r.exitCode) { + return r } assert.Fail(r.tb, "invalid exit code", "exit code (%d) must be one of %v: %s", r.exitCode, possibleCodes, r.output) From a029aba99bd0f85a622492cfcbdeffc8b58740a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Skytt=C3=A4?= Date: Sun, 1 Jun 2025 11:47:57 +0300 Subject: [PATCH 143/152] dev: improve comments (#5846) --- pkg/goanalysis/pkgerrors/parse.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/goanalysis/pkgerrors/parse.go b/pkg/goanalysis/pkgerrors/parse.go index 8c49a55929ed..2fe1fb529fa4 100644 --- a/pkg/goanalysis/pkgerrors/parse.go +++ b/pkg/goanalysis/pkgerrors/parse.go @@ -26,7 +26,7 @@ func parseError(srcErr packages.Error) (*result.Issue, error) { } func parseErrorPosition(pos string) (*token.Position, error) { - // file:line(:colon) + // file:line(:column) parts := strings.Split(pos, ":") if len(parts) == 1 { return nil, errors.New("no colons") @@ -39,7 +39,7 @@ func parseErrorPosition(pos string) (*token.Position, error) { } var column int - if len(parts) == 3 { // no column + if len(parts) == 3 { // got column column, err = strconv.Atoi(parts[2]) if err != nil { return nil, fmt.Errorf("failed to parse column from %q: %w", parts[2], err) From a02b91e66f7ba7aaba3b4f22d7e9dc4aa44ab9ad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Jun 2025 14:24:25 +0200 Subject: [PATCH 144/152] build(deps): bump github.com/shirou/gopsutil/v4 from 4.25.4 to 4.25.5 (#5849) --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 6f084bed2675..c4b63fa87ff7 100644 --- a/go.mod +++ b/go.mod @@ -100,7 +100,7 @@ require ( github.com/sashamelentyev/interfacebloat v1.1.0 github.com/sashamelentyev/usestdlibvars v1.29.0 github.com/securego/gosec/v2 v2.22.4 - github.com/shirou/gopsutil/v4 v4.25.4 + github.com/shirou/gopsutil/v4 v4.25.5 github.com/sirupsen/logrus v1.9.3 github.com/sivchari/containedctx v1.0.3 github.com/sonatard/noctx v0.3.3 @@ -155,7 +155,7 @@ require ( github.com/dave/dst v0.27.3 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dlclark/regexp2 v1.11.5 // indirect - github.com/ebitengine/purego v0.8.2 // indirect + github.com/ebitengine/purego v0.8.4 // 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 diff --git a/go.sum b/go.sum index 0a4e0d2587b0..182e746f2b29 100644 --- a/go.sum +++ b/go.sum @@ -152,8 +152,8 @@ github.com/denis-tingaikin/go-header v0.5.0 h1:SRdnP5ZKvcO9KKRP1KJrhFR3RrlGuD+42 github.com/denis-tingaikin/go-header v0.5.0/go.mod h1:mMenU5bWrok6Wl2UsZjy+1okegmwQ3UgWl4V1D8gjlY= github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ= github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/ebitengine/purego v0.8.2 h1:jPPGWs2sZ1UgOSgD2bClL0MJIqu58nOmIcBuXr62z1I= -github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= +github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw= +github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= 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= @@ -522,8 +522,8 @@ github.com/securego/gosec/v2 v2.22.4 h1:21VdNGcKicFSv6rUDBc0cEtEl7lWyCKZxKIm0iwv github.com/securego/gosec/v2 v2.22.4/go.mod h1:ww5Yie7KJ3AH8XZQTletkW5zOmIse6FACs/Ys8VR3qE= 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/shirou/gopsutil/v4 v4.25.4 h1:cdtFO363VEOOFrUCjZRh4XVJkb548lyF0q0uTeMqYPw= -github.com/shirou/gopsutil/v4 v4.25.4/go.mod h1:xbuxyoZj+UsgnZrENu3lQivsngRR5BdjbJwf2fv4szA= +github.com/shirou/gopsutil/v4 v4.25.5 h1:rtd9piuSMGeU8g1RMXjZs9y9luK5BwtnG7dZaQUJAsc= +github.com/shirou/gopsutil/v4 v4.25.5/go.mod h1:PfybzyydfZcN+JMMjkF6Zb8Mq1A/VcogFFg7hj50W9c= 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= From 69479c6d0edbf16f6277fcecfcea79263d3a6f94 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Jun 2025 14:25:16 +0200 Subject: [PATCH 145/152] build(deps): bump the linter-testdata group across 4 directories with 4 updates (#5850) --- pkg/golinters/ginkgolinter/testdata/go.mod | 2 +- pkg/golinters/ginkgolinter/testdata/go.sum | 4 ++-- pkg/golinters/loggercheck/testdata/go.mod | 2 +- pkg/golinters/loggercheck/testdata/go.sum | 4 ++-- pkg/golinters/protogetter/testdata/go.mod | 2 +- pkg/golinters/protogetter/testdata/go.sum | 4 ++-- pkg/golinters/spancheck/testdata/go.mod | 8 ++++---- pkg/golinters/spancheck/testdata/go.sum | 16 ++++++++-------- 8 files changed, 21 insertions(+), 21 deletions(-) diff --git a/pkg/golinters/ginkgolinter/testdata/go.mod b/pkg/golinters/ginkgolinter/testdata/go.mod index ede5795987b6..078968acadbb 100644 --- a/pkg/golinters/ginkgolinter/testdata/go.mod +++ b/pkg/golinters/ginkgolinter/testdata/go.mod @@ -8,7 +8,7 @@ require ( ) require ( - github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/logr v1.4.3 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect diff --git a/pkg/golinters/ginkgolinter/testdata/go.sum b/pkg/golinters/ginkgolinter/testdata/go.sum index bbd84ab067c2..29f1ee9e9a59 100644 --- a/pkg/golinters/ginkgolinter/testdata/go.sum +++ b/pkg/golinters/ginkgolinter/testdata/go.sum @@ -1,7 +1,7 @@ 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.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= diff --git a/pkg/golinters/loggercheck/testdata/go.mod b/pkg/golinters/loggercheck/testdata/go.mod index 985fff765d4b..0df788c08b62 100644 --- a/pkg/golinters/loggercheck/testdata/go.mod +++ b/pkg/golinters/loggercheck/testdata/go.mod @@ -4,7 +4,7 @@ go 1.21.0 require ( github.com/go-kit/log v0.2.1 - github.com/go-logr/logr v1.4.2 + github.com/go-logr/logr v1.4.3 go.uber.org/zap v1.27.0 k8s.io/klog/v2 v2.130.1 ) diff --git a/pkg/golinters/loggercheck/testdata/go.sum b/pkg/golinters/loggercheck/testdata/go.sum index 5a316ccca990..dd912496e496 100644 --- a/pkg/golinters/loggercheck/testdata/go.sum +++ b/pkg/golinters/loggercheck/testdata/go.sum @@ -4,8 +4,8 @@ github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= diff --git a/pkg/golinters/protogetter/testdata/go.mod b/pkg/golinters/protogetter/testdata/go.mod index 894a03ffa01e..ac7bf891a2f6 100644 --- a/pkg/golinters/protogetter/testdata/go.mod +++ b/pkg/golinters/protogetter/testdata/go.mod @@ -3,7 +3,7 @@ module protogetter go 1.23.0 require ( - google.golang.org/grpc v1.72.1 + google.golang.org/grpc v1.72.2 google.golang.org/protobuf v1.36.6 ) diff --git a/pkg/golinters/protogetter/testdata/go.sum b/pkg/golinters/protogetter/testdata/go.sum index 99952097dc15..88c148026714 100644 --- a/pkg/golinters/protogetter/testdata/go.sum +++ b/pkg/golinters/protogetter/testdata/go.sum @@ -28,7 +28,7 @@ golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a h1:51aaUVRocpvUOSQKM6Q7VuoaktNIaMCLuhZB6DKksq4= google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a/go.mod h1:uRxBH1mhmO8PGhU89cMcHaXKZqO+OfakD8QQO0oYwlQ= -google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA= -google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= +google.golang.org/grpc v1.72.2 h1:TdbGzwb82ty4OusHWepvFWGLgIbNo1/SUynEN0ssqv8= +google.golang.org/grpc v1.72.2/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= diff --git a/pkg/golinters/spancheck/testdata/go.mod b/pkg/golinters/spancheck/testdata/go.mod index df3444491ace..256ae9e1b2a9 100644 --- a/pkg/golinters/spancheck/testdata/go.mod +++ b/pkg/golinters/spancheck/testdata/go.mod @@ -3,13 +3,13 @@ module spancheck go 1.23.0 require ( - go.opentelemetry.io/otel v1.35.0 - go.opentelemetry.io/otel/trace v1.35.0 + go.opentelemetry.io/otel v1.36.0 + go.opentelemetry.io/otel/trace v1.36.0 ) require ( - github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/otel/metric v1.35.0 // indirect + go.opentelemetry.io/otel/metric v1.36.0 // indirect ) diff --git a/pkg/golinters/spancheck/testdata/go.sum b/pkg/golinters/spancheck/testdata/go.sum index 98e72be93493..da8e1100881e 100644 --- a/pkg/golinters/spancheck/testdata/go.sum +++ b/pkg/golinters/spancheck/testdata/go.sum @@ -1,8 +1,8 @@ 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.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/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.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= @@ -13,11 +13,11 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= -go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= -go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= -go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= -go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= -go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= +go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= +go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= +go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE= +go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= +go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= +go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 59936083e6a18b8b1e539f0a3e100d12795c027b Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Mon, 2 Jun 2025 11:04:10 +0200 Subject: [PATCH 146/152] docs: improve module plugin explanation (#5851) --- docs/src/docs/plugins/module-plugins.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/docs/plugins/module-plugins.mdx b/docs/src/docs/plugins/module-plugins.mdx index 9fa36766ebb6..f6e4ad77d2c1 100644 --- a/docs/src/docs/plugins/module-plugins.mdx +++ b/docs/src/docs/plugins/module-plugins.mdx @@ -9,7 +9,7 @@ An example linter can be found at [here](https://github.com/golangci/example-plu - Define your building configuration into `.custom-gcl.yml`. - Run the command `golangci-lint custom` (or `golangci-lint custom -v` to have logs). - Define the plugin inside the `linters.settings.custom` section with the type `module`. -- Run your custom version of golangci-lint. +- Run the resulting custom binary of golangci-lint (`./custom-gcl` by default). Requirements: - Go From aa988352ff5b86f88095d95f03c2223ff54a666f Mon Sep 17 00:00:00 2001 From: Oleksandr Redko Date: Mon, 2 Jun 2025 14:45:24 +0300 Subject: [PATCH 147/152] dev: display list of staticcheck checks in debug (#5853) --- pkg/golinters/staticcheck/staticcheck.go | 36 ++++++++++++++++++++---- pkg/logutils/logutils.go | 11 ++++---- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/pkg/golinters/staticcheck/staticcheck.go b/pkg/golinters/staticcheck/staticcheck.go index 1ec39244c100..7aae52870cbb 100644 --- a/pkg/golinters/staticcheck/staticcheck.go +++ b/pkg/golinters/staticcheck/staticcheck.go @@ -15,6 +15,12 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" + "github.com/golangci/golangci-lint/v2/pkg/logutils" +) + +var ( + debugf = logutils.Debug(logutils.DebugKeyStaticcheck) + isDebug = logutils.HaveDebugTag(logutils.DebugKeyStaticcheck) ) func New(settings *config.StaticCheckSettings) *goanalysis.Linter { @@ -29,6 +35,21 @@ func New(settings *config.StaticCheckSettings) *goanalysis.Linter { analyzers := setupAnalyzers(allAnalyzers, cfg.Checks) + if isDebug { + allAnalyzerNames := extractAnalyzerNames(allAnalyzers) + slices.Sort(allAnalyzerNames) + debugf("All available checks (%d): %s", len(allAnalyzers), strings.Join(allAnalyzerNames, ",")) + + var cfgAnalyzerNames []string + for _, a := range analyzers { + cfgAnalyzerNames = append(cfgAnalyzerNames, a.Name) + } + slices.Sort(cfgAnalyzerNames) + debugf("Enabled by config checks (%d): %s", len(analyzers), strings.Join(cfgAnalyzerNames, ",")) + + debugf("staticcheck configuration: %#v", cfg) + } + return goanalysis.NewLinter( "staticcheck", "It's the set of rules from staticcheck.", @@ -107,12 +128,7 @@ func normalizeList(list []string) []string { } func setupAnalyzers(src []*lint.Analyzer, checks []string) []*analysis.Analyzer { - var names []string - for _, a := range src { - names = append(names, a.Analyzer.Name) - } - - filter := filterAnalyzerNames(names, checks) + filter := filterAnalyzerNames(extractAnalyzerNames(src), checks) var ret []*analysis.Analyzer for _, a := range src { @@ -124,6 +140,14 @@ func setupAnalyzers(src []*lint.Analyzer, checks []string) []*analysis.Analyzer return ret } +func extractAnalyzerNames(analyzers []*lint.Analyzer) []string { + var names []string + for _, a := range analyzers { + names = append(names, a.Analyzer.Name) + } + return names +} + // https://github.com/dominikh/go-tools/blob/9bf17c0388a65710524ba04c2d821469e639fdc2/lintcmd/lint.go#L437-L477 // //nolint:gocritic // Keep the original source code. diff --git a/pkg/logutils/logutils.go b/pkg/logutils/logutils.go index 0ee48a3664bd..e417ac4b738d 100644 --- a/pkg/logutils/logutils.go +++ b/pkg/logutils/logutils.go @@ -79,11 +79,12 @@ const ( // Linters. const ( - DebugKeyForbidigo = "forbidigo" // Debugs `forbidigo` linter. - DebugKeyGoCritic = "gocritic" // Debugs `gocritic` linter. - DebugKeyGovet = "govet" // Debugs `govet` linter. - DebugKeyLinter = "linter" - DebugKeyRevive = "revive" // Debugs `revive` linter. + DebugKeyForbidigo = "forbidigo" // Debugs `forbidigo` linter. + DebugKeyGoCritic = "gocritic" // Debugs `gocritic` linter. + DebugKeyGovet = "govet" // Debugs `govet` linter. + DebugKeyLinter = "linter" + DebugKeyRevive = "revive" // Debugs `revive` linter. + DebugKeyStaticcheck = "staticcheck" // Debugs `staticcheck` linter. ) func getEnabledDebugs() map[string]bool { From c24d5d16f0ce4f571606f6aa5617ddccedbd99a6 Mon Sep 17 00:00:00 2001 From: Oleksandr Redko Date: Mon, 2 Jun 2025 14:46:53 +0300 Subject: [PATCH 148/152] dev: correct debug log for default rules in revive (#5852) --- pkg/golinters/revive/revive.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/golinters/revive/revive.go b/pkg/golinters/revive/revive.go index 01eccd537d9e..b06b5de8aa28 100644 --- a/pkg/golinters/revive/revive.go +++ b/pkg/golinters/revive/revive.go @@ -436,7 +436,7 @@ func displayRules(conf *lint.Config) { slices.Sort(enabledRules) debugf("All available rules (%d): %s.", len(allRules), strings.Join(extractRulesName(allRules), ", ")) - debugf("Default rules (%d): %s.", len(allRules), strings.Join(extractRulesName(allRules), ", ")) + debugf("Default rules (%d): %s.", len(defaultRules), strings.Join(extractRulesName(defaultRules), ", ")) debugf("Enabled by config rules (%d): %s.", len(enabledRules), strings.Join(enabledRules, ", ")) debugf("revive configuration: %#v", conf) From f8514979dbc8f9e5192530f88f9a24351eec4614 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Mon, 2 Jun 2025 21:54:29 +0200 Subject: [PATCH 149/152] dev: use slice of pointers (#5854) --- docs/src/docs/contributing/architecture.mdx | 2 +- pkg/commands/run.go | 6 +-- pkg/goanalysis/issue.go | 8 +-- pkg/goanalysis/linter.go | 8 +-- pkg/goanalysis/metalinter.go | 6 +-- pkg/goanalysis/pkgerrors/errors.go | 6 +-- pkg/goanalysis/runner.go | 6 +-- pkg/goanalysis/runners.go | 35 ++++++------- pkg/goanalysis/runners_cache.go | 43 ++++++++-------- pkg/golinters/dupl/dupl.go | 8 +-- pkg/golinters/errcheck/errcheck.go | 8 +-- .../gochecksumtype/gochecksumtype.go | 8 +-- pkg/golinters/gocognit/gocognit.go | 8 +-- pkg/golinters/goconst/goconst.go | 8 +-- pkg/golinters/gocyclo/gocyclo.go | 8 +-- .../gomoddirectives/gomoddirectives.go | 4 +- pkg/golinters/gomodguard/gomodguard.go | 4 +- pkg/golinters/gosec/gosec.go | 8 +-- .../nolintlint/internal/nolintlint.go | 4 +- .../nolintlint/internal/nolintlint_test.go | 22 ++++---- pkg/golinters/nolintlint/nolintlint.go | 4 +- pkg/golinters/promlinter/promlinter.go | 8 +-- pkg/golinters/revive/revive.go | 10 ++-- pkg/golinters/unconvert/unconvert.go | 8 +-- pkg/golinters/unused/unused.go | 8 +-- pkg/lint/linter/linter.go | 4 +- pkg/lint/runner.go | 18 +++---- pkg/printers/checkstyle.go | 5 +- pkg/printers/checkstyle_test.go | 2 +- pkg/printers/codeclimate.go | 6 +-- pkg/printers/codeclimate_test.go | 2 +- pkg/printers/html.go | 16 +++--- pkg/printers/html_test.go | 2 +- pkg/printers/json.go | 6 +-- pkg/printers/json_test.go | 2 +- pkg/printers/junitxml.go | 23 ++++----- pkg/printers/junitxml_test.go | 2 +- pkg/printers/printer.go | 4 +- pkg/printers/printer_test.go | 8 +-- pkg/printers/sarif.go | 6 +-- pkg/printers/sarif_test.go | 2 +- pkg/printers/tab.go | 6 +-- pkg/printers/tab_test.go | 2 +- pkg/printers/teamcity.go | 6 +-- pkg/printers/teamcity_test.go | 2 +- pkg/printers/text.go | 10 ++-- pkg/printers/text_test.go | 2 +- pkg/result/issue.go | 4 +- pkg/result/processors/cgo.go | 2 +- pkg/result/processors/diff.go | 2 +- .../exclusion_generated_file_filter.go | 2 +- pkg/result/processors/exclusion_paths.go | 2 +- pkg/result/processors/exclusion_paths_test.go | 48 +++++++++--------- pkg/result/processors/exclusion_rules.go | 2 +- pkg/result/processors/exclusion_rules_test.go | 12 ++--- pkg/result/processors/filename_unadjuster.go | 2 +- pkg/result/processors/fixer.go | 10 ++-- pkg/result/processors/invalid_issue.go | 2 +- pkg/result/processors/invalid_issue_test.go | 28 +++++------ pkg/result/processors/issues.go | 50 +++++++++---------- pkg/result/processors/max_from_linter.go | 2 +- .../processors/max_per_file_from_linter.go | 2 +- .../max_per_file_from_linter_test.go | 4 +- pkg/result/processors/max_same_issues.go | 2 +- pkg/result/processors/max_same_issues_test.go | 4 +- pkg/result/processors/nolint_filter.go | 4 +- pkg/result/processors/nolint_filter_test.go | 20 ++++---- pkg/result/processors/path_absoluter.go | 2 +- pkg/result/processors/path_prettifier.go | 2 +- pkg/result/processors/path_prettifier_test.go | 14 +++--- pkg/result/processors/path_relativity.go | 2 +- pkg/result/processors/path_shortener.go | 2 +- pkg/result/processors/processor.go | 2 +- pkg/result/processors/processor_test.go | 14 +++--- pkg/result/processors/severity.go | 2 +- pkg/result/processors/severity_test.go | 10 ++-- pkg/result/processors/sort_results.go | 6 +-- pkg/result/processors/sort_results_test.go | 14 +++--- pkg/result/processors/source_code.go | 2 +- pkg/result/processors/uniq_by_line.go | 2 +- pkg/result/processors/uniq_by_line_test.go | 4 +- .../website/expand_templates/thanks_test.go | 2 +- 82 files changed, 329 insertions(+), 339 deletions(-) diff --git a/docs/src/docs/contributing/architecture.mdx b/docs/src/docs/contributing/architecture.mdx index e9df647556da..e398db57e4e8 100644 --- a/docs/src/docs/contributing/architecture.mdx +++ b/docs/src/docs/contributing/architecture.mdx @@ -222,7 +222,7 @@ The abstraction is simple: ```go title=pkg/result/processors/processor.go type Processor interface { - Process(issues []result.Issue) ([]result.Issue, error) + Process(issues []*result.Issue) ([]*result.Issue, error) Name() string Finish() } diff --git a/pkg/commands/run.go b/pkg/commands/run.go index 53902eafac24..4e2d3b1b984a 100644 --- a/pkg/commands/run.go +++ b/pkg/commands/run.go @@ -376,7 +376,7 @@ func (c *runCommand) runAndPrint(ctx context.Context) error { } // runAnalysis executes the linters that have been enabled in the configuration. -func (c *runCommand) runAnalysis(ctx context.Context) ([]result.Issue, error) { +func (c *runCommand) runAnalysis(ctx context.Context) ([]*result.Issue, error) { lintersToRun, err := c.dbManager.GetOptimizedLinters() if err != nil { return nil, err @@ -408,7 +408,7 @@ func (c *runCommand) setOutputToDevNull() (savedStdout, savedStderr *os.File) { return } -func (c *runCommand) setExitCodeIfIssuesFound(issues []result.Issue) { +func (c *runCommand) setExitCodeIfIssuesFound(issues []*result.Issue) { if len(issues) != 0 { c.exitCode = c.cfg.Run.ExitCodeIfIssuesFound } @@ -433,7 +433,7 @@ func (c *runCommand) printDeprecatedLinterMessages(enabledLinters map[string]*li } } -func (c *runCommand) printStats(issues []result.Issue) { +func (c *runCommand) printStats(issues []*result.Issue) { if !c.cfg.Output.ShowStats { return } diff --git a/pkg/goanalysis/issue.go b/pkg/goanalysis/issue.go index c41702595c55..88a59e53dbc9 100644 --- a/pkg/goanalysis/issue.go +++ b/pkg/goanalysis/issue.go @@ -9,13 +9,13 @@ import ( ) type Issue struct { - result.Issue + *result.Issue Pass *analysis.Pass } -func NewIssue(issue *result.Issue, pass *analysis.Pass) Issue { - return Issue{ - Issue: *issue, +func NewIssue(issue *result.Issue, pass *analysis.Pass) *Issue { + return &Issue{ + Issue: issue, Pass: pass, } } diff --git a/pkg/goanalysis/linter.go b/pkg/goanalysis/linter.go index 53f5b7bae455..29bd841a85c6 100644 --- a/pkg/goanalysis/linter.go +++ b/pkg/goanalysis/linter.go @@ -40,7 +40,7 @@ type Linter struct { name, desc string analyzers []*analysis.Analyzer cfg map[string]map[string]any - issuesReporter func(*linter.Context) []Issue + issuesReporter func(*linter.Context) []*Issue contextSetter func(*linter.Context) loadMode LoadMode needUseOriginalPackages bool @@ -54,7 +54,7 @@ func NewLinterFromAnalyzer(analyzer *analysis.Analyzer) *Linter { return NewLinter(analyzer.Name, analyzer.Doc, []*analysis.Analyzer{analyzer}, nil) } -func (lnt *Linter) Run(_ context.Context, lintCtx *linter.Context) ([]result.Issue, error) { +func (lnt *Linter) Run(_ context.Context, lintCtx *linter.Context) ([]*result.Issue, error) { if err := lnt.preRun(lintCtx); err != nil { return nil, err } @@ -93,7 +93,7 @@ func (lnt *Linter) WithLoadMode(loadMode LoadMode) *Linter { return lnt } -func (lnt *Linter) WithIssuesReporter(r func(*linter.Context) []Issue) *Linter { +func (lnt *Linter) WithIssuesReporter(r func(*linter.Context) []*Issue) *Linter { lnt.issuesReporter = r return lnt } @@ -193,7 +193,7 @@ func (lnt *Linter) useOriginalPackages() bool { return lnt.needUseOriginalPackages } -func (lnt *Linter) reportIssues(lintCtx *linter.Context) []Issue { +func (lnt *Linter) reportIssues(lintCtx *linter.Context) []*Issue { if lnt.issuesReporter != nil { return lnt.issuesReporter(lintCtx) } diff --git a/pkg/goanalysis/metalinter.go b/pkg/goanalysis/metalinter.go index 4db143baddb3..b9a210a66fc8 100644 --- a/pkg/goanalysis/metalinter.go +++ b/pkg/goanalysis/metalinter.go @@ -21,7 +21,7 @@ func NewMetaLinter(linters []*Linter) *MetaLinter { return ml } -func (ml MetaLinter) Run(_ context.Context, lintCtx *linter.Context) ([]result.Issue, error) { +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, fmt.Errorf("failed to pre-run %s: %w", l.Name(), err) @@ -65,8 +65,8 @@ func (MetaLinter) useOriginalPackages() bool { return false // `unused` can't be run by this metalinter } -func (ml MetaLinter) reportIssues(lintCtx *linter.Context) []Issue { - var ret []Issue +func (ml MetaLinter) reportIssues(lintCtx *linter.Context) []*Issue { + var ret []*Issue for _, lnt := range ml.linters { if lnt.issuesReporter != nil { ret = append(ret, lnt.issuesReporter(lintCtx)...) diff --git a/pkg/goanalysis/pkgerrors/errors.go b/pkg/goanalysis/pkgerrors/errors.go index 587e72720e98..062a8f43aeff 100644 --- a/pkg/goanalysis/pkgerrors/errors.go +++ b/pkg/goanalysis/pkgerrors/errors.go @@ -18,8 +18,8 @@ func (e *IllTypedError) Error() string { return fmt.Sprintf("IllTypedError: errors in package: %v", e.Pkg.Errors) } -func BuildIssuesFromIllTypedError(errs []error, lintCtx *linter.Context) ([]result.Issue, error) { - var issues []result.Issue +func BuildIssuesFromIllTypedError(errs []error, lintCtx *linter.Context) ([]*result.Issue, error) { + var issues []*result.Issue uniqReportedIssues := map[string]bool{} var other error @@ -43,7 +43,7 @@ func BuildIssuesFromIllTypedError(errs []error, lintCtx *linter.Context) ([]resu lintCtx.Log.Errorf("typechecking error: %s", err.Msg) } else { issue.Pkg = ill.Pkg // to save to cache later - issues = append(issues, *issue) + issues = append(issues, issue) } } } diff --git a/pkg/goanalysis/runner.go b/pkg/goanalysis/runner.go index 808c9d2ad68c..6cc0a7077109 100644 --- a/pkg/goanalysis/runner.go +++ b/pkg/goanalysis/runner.go @@ -76,7 +76,7 @@ func newRunner(prefix string, logger logutils.Log, pkgCache *cache.Cache, loadGu // It provides most of the logic for the main functions of both the // singlechecker and the multi-analysis commands. // It returns the appropriate exit code. -func (r *runner) run(analyzers []*analysis.Analyzer, initialPackages []*packages.Package) ([]Diagnostic, +func (r *runner) run(analyzers []*analysis.Analyzer, initialPackages []*packages.Package) ([]*Diagnostic, []error, map[*analysis.Pass]*packages.Package, ) { debugf("Analyzing %d packages on load mode %s", len(initialPackages), r.loadMode) @@ -275,7 +275,7 @@ func (r *runner) analyze(pkgs []*packages.Package, analyzers []*analysis.Analyze return rootActions } -func extractDiagnostics(roots []*action) (retDiags []Diagnostic, retErrors []error) { +func extractDiagnostics(roots []*action) (retDiags []*Diagnostic, retErrors []error) { extracted := make(map[*action]bool) var extract func(*action) var visitAll func(actions []*action) @@ -322,7 +322,7 @@ func extractDiagnostics(roots []*action) (retDiags []Diagnostic, retErrors []err } seen[k] = true - retDiag := Diagnostic{ + retDiag := &Diagnostic{ File: file, Diagnostic: diag, Analyzer: act.Analyzer, diff --git a/pkg/goanalysis/runners.go b/pkg/goanalysis/runners.go index fe8d8fe854d3..bcbc0033ef9a 100644 --- a/pkg/goanalysis/runners.go +++ b/pkg/goanalysis/runners.go @@ -3,6 +3,7 @@ package goanalysis import ( "fmt" "go/token" + "slices" "strings" "golang.org/x/tools/go/analysis" @@ -20,11 +21,11 @@ type runAnalyzersConfig interface { getLinterNameForDiagnostic(*Diagnostic) string getAnalyzers() []*analysis.Analyzer useOriginalPackages() bool - reportIssues(*linter.Context) []Issue + reportIssues(*linter.Context) []*Issue getLoadMode() LoadMode } -func runAnalyzers(cfg runAnalyzersConfig, lintCtx *linter.Context) ([]result.Issue, error) { +func runAnalyzers(cfg runAnalyzersConfig, lintCtx *linter.Context) ([]*result.Issue, error) { log := lintCtx.Log.Child(logutils.DebugKeyGoAnalysis) sw := timeutils.NewStopwatch("analyzers", log) @@ -56,18 +57,19 @@ func runAnalyzers(cfg runAnalyzersConfig, lintCtx *linter.Context) ([]result.Iss } }() - buildAllIssues := func() []result.Issue { - var retIssues []result.Issue + buildAllIssues := func() []*result.Issue { + var retIssues []*result.Issue + reportedIssues := cfg.reportIssues(lintCtx) - for i := range reportedIssues { - issue := &reportedIssues[i].Issue - if issue.Pkg == nil { - issue.Pkg = passToPkg[reportedIssues[i].Pass] + for _, reportedIssue := range reportedIssues { + if reportedIssue.Pkg == nil { + reportedIssue.Pkg = passToPkg[reportedIssue.Pass] } - retIssues = append(retIssues, *issue) + + retIssues = append(retIssues, reportedIssue.Issue) } - retIssues = append(retIssues, buildIssues(diags, cfg.getLinterNameForDiagnostic)...) - return retIssues + + return slices.Concat(retIssues, buildIssues(diags, cfg.getLinterNameForDiagnostic)) } errIssues, err := pkgerrors.BuildIssuesFromIllTypedError(errs, lintCtx) @@ -81,11 +83,10 @@ func runAnalyzers(cfg runAnalyzersConfig, lintCtx *linter.Context) ([]result.Iss return issues, nil } -func buildIssues(diags []Diagnostic, linterNameBuilder func(diag *Diagnostic) string) []result.Issue { - var issues []result.Issue +func buildIssues(diags []*Diagnostic, linterNameBuilder func(diag *Diagnostic) string) []*result.Issue { + var issues []*result.Issue - for i := range diags { - diag := &diags[i] + for _, diag := range diags { linterName := linterNameBuilder(diag) var text string @@ -126,7 +127,7 @@ func buildIssues(diags []Diagnostic, linterNameBuilder func(diag *Diagnostic) st suggestedFixes = append(suggestedFixes, nsf) } - issues = append(issues, result.Issue{ + issues = append(issues, &result.Issue{ FromLinter: linterName, Text: text, Pos: diag.Position, @@ -142,7 +143,7 @@ func buildIssues(diags []Diagnostic, linterNameBuilder func(diag *Diagnostic) st relatedPos = diag.Position } - issues = append(issues, result.Issue{ + issues = append(issues, &result.Issue{ FromLinter: linterName, Text: fmt.Sprintf("%s(related information): %s", diag.Analyzer.Name, info.Message), Pos: relatedPos, diff --git a/pkg/goanalysis/runners_cache.go b/pkg/goanalysis/runners_cache.go index 9673197c9ec9..5cd8a6b1ccd4 100644 --- a/pkg/goanalysis/runners_cache.go +++ b/pkg/goanalysis/runners_cache.go @@ -17,13 +17,12 @@ import ( ) 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 { - i := &issues[ind] - perPkgIssues[i.Pkg] = append(perPkgIssues[i.Pkg], *i) + perPkgIssues := map[*packages.Package][]*result.Issue{} + for _, issue := range issues { + perPkgIssues[issue.Pkg] = append(perPkgIssues[issue.Pkg], issue) } var savedIssuesCount int64 = 0 @@ -34,23 +33,22 @@ func saveIssuesToCache(allPkgs []*packages.Package, pkgsFromCache map[*packages. wg.Add(workerCount) pkgCh := make(chan *packages.Package, len(allPkgs)) - for i := 0; i < workerCount; i++ { + for range workerCount { go func() { defer wg.Done() for pkg := range pkgCh { pkgIssues := perPkgIssues[pkg] encodedIssues := make([]EncodingIssue, 0, len(pkgIssues)) - for ind := range pkgIssues { - i := &pkgIssues[ind] + for _, issue := range pkgIssues { encodedIssues = append(encodedIssues, EncodingIssue{ - FromLinter: i.FromLinter, - Text: i.Text, - Severity: i.Severity, - Pos: i.Pos, - LineRange: i.LineRange, - SuggestedFixes: i.SuggestedFixes, - ExpectNoLint: i.ExpectNoLint, - ExpectedNoLintLinter: i.ExpectedNoLintLinter, + FromLinter: issue.FromLinter, + Text: issue.Text, + Severity: issue.Severity, + Pos: issue.Pos, + LineRange: issue.LineRange, + SuggestedFixes: issue.SuggestedFixes, + ExpectNoLint: issue.ExpectNoLint, + ExpectedNoLintLinter: issue.ExpectedNoLintLinter, }) } @@ -81,12 +79,12 @@ func saveIssuesToCache(allPkgs []*packages.Package, pkgsFromCache map[*packages. func loadIssuesFromCache(pkgs []*packages.Package, lintCtx *linter.Context, analyzers []*analysis.Analyzer, -) (issuesFromCache []result.Issue, pkgsFromCache map[*packages.Package]bool) { +) (issuesFromCache []*result.Issue, pkgsFromCache map[*packages.Package]bool) { startedAt := time.Now() lintResKey := getIssuesCacheKey(analyzers) type cacheRes struct { - issues []result.Issue + issues []*result.Issue loadErr error } pkgToCacheRes := make(map[*packages.Package]*cacheRes, len(pkgs)) @@ -103,7 +101,7 @@ func loadIssuesFromCache(pkgs []*packages.Package, lintCtx *linter.Context, go func() { defer wg.Done() for pkg := range pkgCh { - var pkgIssues []EncodingIssue + var pkgIssues []*EncodingIssue err := lintCtx.PkgCache.Get(pkg, cache.HashModeNeedAllDeps, lintResKey, &pkgIssues) cacheRes := pkgToCacheRes[pkg] cacheRes.loadErr = err @@ -114,10 +112,9 @@ func loadIssuesFromCache(pkgs []*packages.Package, lintCtx *linter.Context, continue } - issues := make([]result.Issue, 0, len(pkgIssues)) - for i := range pkgIssues { - issue := &pkgIssues[i] - issues = append(issues, result.Issue{ + issues := make([]*result.Issue, 0, len(pkgIssues)) + for _, issue := range pkgIssues { + issues = append(issues, &result.Issue{ FromLinter: issue.FromLinter, Text: issue.Text, Severity: issue.Severity, diff --git a/pkg/golinters/dupl/dupl.go b/pkg/golinters/dupl/dupl.go index 6d5323a8bad4..0b6b3a162c2e 100644 --- a/pkg/golinters/dupl/dupl.go +++ b/pkg/golinters/dupl/dupl.go @@ -20,7 +20,7 @@ const linterName = "dupl" func New(settings *config.DuplSettings) *goanalysis.Linter { var mu sync.Mutex - var resIssues []goanalysis.Issue + var resIssues []*goanalysis.Issue return goanalysis. NewLinterFromAnalyzer(&analysis.Analyzer{ @@ -43,13 +43,13 @@ func New(settings *config.DuplSettings) *goanalysis.Linter { return nil, nil }, }). - WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + WithIssuesReporter(func(*linter.Context) []*goanalysis.Issue { return resIssues }). WithLoadMode(goanalysis.LoadModeSyntax) } -func runDupl(pass *analysis.Pass, settings *config.DuplSettings) ([]goanalysis.Issue, error) { +func runDupl(pass *analysis.Pass, settings *config.DuplSettings) ([]*goanalysis.Issue, error) { issues, err := duplAPI.Run(internal.GetGoFileNames(pass), settings.Threshold) if err != nil { return nil, err @@ -59,7 +59,7 @@ func runDupl(pass *analysis.Pass, settings *config.DuplSettings) ([]goanalysis.I return nil, nil } - res := make([]goanalysis.Issue, 0, len(issues)) + res := make([]*goanalysis.Issue, 0, len(issues)) for _, i := range issues { toFilename, err := fsutils.ShortestRelPath(i.To.Filename(), "") diff --git a/pkg/golinters/errcheck/errcheck.go b/pkg/golinters/errcheck/errcheck.go index ae34a53ef62c..6bd473845c3f 100644 --- a/pkg/golinters/errcheck/errcheck.go +++ b/pkg/golinters/errcheck/errcheck.go @@ -21,7 +21,7 @@ const linterName = "errcheck" func New(settings *config.ErrcheckSettings) *goanalysis.Linter { var mu sync.Mutex - var resIssues []goanalysis.Issue + var resIssues []*goanalysis.Issue analyzer := &analysis.Analyzer{ Name: linterName, @@ -50,13 +50,13 @@ func New(settings *config.ErrcheckSettings) *goanalysis.Linter { return nil, nil } }). - WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + WithIssuesReporter(func(*linter.Context) []*goanalysis.Issue { return resIssues }). WithLoadMode(goanalysis.LoadModeTypesInfo) } -func runErrCheck(pass *analysis.Pass, checker *errcheck.Checker, verbose bool) []goanalysis.Issue { +func runErrCheck(pass *analysis.Pass, checker *errcheck.Checker, verbose bool) []*goanalysis.Issue { pkg := &packages.Package{ Fset: pass.Fset, Syntax: pass.Files, @@ -69,7 +69,7 @@ func runErrCheck(pass *analysis.Pass, checker *errcheck.Checker, verbose bool) [ return nil } - issues := make([]goanalysis.Issue, len(lintIssues.UncheckedErrors)) + issues := make([]*goanalysis.Issue, len(lintIssues.UncheckedErrors)) for i, err := range lintIssues.UncheckedErrors { text := "Error return value is not checked" diff --git a/pkg/golinters/gochecksumtype/gochecksumtype.go b/pkg/golinters/gochecksumtype/gochecksumtype.go index 85be045dfa8a..825975f14570 100644 --- a/pkg/golinters/gochecksumtype/gochecksumtype.go +++ b/pkg/golinters/gochecksumtype/gochecksumtype.go @@ -18,7 +18,7 @@ const linterName = "gochecksumtype" func New(settings *config.GoChecksumTypeSettings) *goanalysis.Linter { var mu sync.Mutex - var resIssues []goanalysis.Issue + var resIssues []*goanalysis.Issue return goanalysis. NewLinterFromAnalyzer(&analysis.Analyzer{ @@ -41,14 +41,14 @@ func New(settings *config.GoChecksumTypeSettings) *goanalysis.Linter { return nil, nil }, }). - WithIssuesReporter(func(_ *linter.Context) []goanalysis.Issue { + WithIssuesReporter(func(_ *linter.Context) []*goanalysis.Issue { return resIssues }). WithLoadMode(goanalysis.LoadModeTypesInfo) } -func runGoCheckSumType(pass *analysis.Pass, settings *config.GoChecksumTypeSettings) ([]goanalysis.Issue, error) { - var resIssues []goanalysis.Issue +func runGoCheckSumType(pass *analysis.Pass, settings *config.GoChecksumTypeSettings) ([]*goanalysis.Issue, error) { + var resIssues []*goanalysis.Issue pkg := &packages.Package{ Fset: pass.Fset, diff --git a/pkg/golinters/gocognit/gocognit.go b/pkg/golinters/gocognit/gocognit.go index e72a9bdfe67a..b17912c0a649 100644 --- a/pkg/golinters/gocognit/gocognit.go +++ b/pkg/golinters/gocognit/gocognit.go @@ -19,7 +19,7 @@ const linterName = "gocognit" func New(settings *config.GocognitSettings) *goanalysis.Linter { var mu sync.Mutex - var resIssues []goanalysis.Issue + var resIssues []*goanalysis.Issue return goanalysis. NewLinterFromAnalyzer(&analysis.Analyzer{ @@ -39,13 +39,13 @@ func New(settings *config.GocognitSettings) *goanalysis.Linter { return nil, nil }, }). - WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + WithIssuesReporter(func(*linter.Context) []*goanalysis.Issue { return resIssues }). WithLoadMode(goanalysis.LoadModeSyntax) } -func runGocognit(pass *analysis.Pass, settings *config.GocognitSettings) []goanalysis.Issue { +func runGocognit(pass *analysis.Pass, settings *config.GocognitSettings) []*goanalysis.Issue { var stats []gocognit.Stat for _, f := range pass.Files { stats = gocognit.ComplexityStats(f, pass.Fset, stats) @@ -58,7 +58,7 @@ func runGocognit(pass *analysis.Pass, settings *config.GocognitSettings) []goana return stats[i].Complexity > stats[j].Complexity }) - issues := make([]goanalysis.Issue, 0, len(stats)) + issues := make([]*goanalysis.Issue, 0, len(stats)) for _, s := range stats { if s.Complexity <= settings.MinComplexity { break // Break as the stats is already sorted from greatest to least diff --git a/pkg/golinters/goconst/goconst.go b/pkg/golinters/goconst/goconst.go index 5a44d4a5ce3a..b58d860c6eda 100644 --- a/pkg/golinters/goconst/goconst.go +++ b/pkg/golinters/goconst/goconst.go @@ -18,7 +18,7 @@ const linterName = "goconst" func New(settings *config.GoConstSettings) *goanalysis.Linter { var mu sync.Mutex - var resIssues []goanalysis.Issue + var resIssues []*goanalysis.Issue return goanalysis. NewLinterFromAnalyzer(&analysis.Analyzer{ @@ -41,13 +41,13 @@ func New(settings *config.GoConstSettings) *goanalysis.Linter { return nil, nil }, }). - WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + WithIssuesReporter(func(*linter.Context) []*goanalysis.Issue { return resIssues }). WithLoadMode(goanalysis.LoadModeTypesInfo) } -func runGoconst(pass *analysis.Pass, settings *config.GoConstSettings) ([]goanalysis.Issue, error) { +func runGoconst(pass *analysis.Pass, settings *config.GoConstSettings) ([]*goanalysis.Issue, error) { cfg := goconstAPI.Config{ IgnoreStrings: settings.IgnoreStringValues, MatchWithConstants: settings.MatchWithConstants, @@ -77,7 +77,7 @@ func runGoconst(pass *analysis.Pass, settings *config.GoConstSettings) ([]goanal return nil, nil } - res := make([]goanalysis.Issue, 0, len(lintIssues)) + res := make([]*goanalysis.Issue, 0, len(lintIssues)) for i := range lintIssues { issue := &lintIssues[i] diff --git a/pkg/golinters/gocyclo/gocyclo.go b/pkg/golinters/gocyclo/gocyclo.go index 17b868d4972a..de0374607c06 100644 --- a/pkg/golinters/gocyclo/gocyclo.go +++ b/pkg/golinters/gocyclo/gocyclo.go @@ -18,7 +18,7 @@ const linterName = "gocyclo" func New(settings *config.GoCycloSettings) *goanalysis.Linter { var mu sync.Mutex - var resIssues []goanalysis.Issue + var resIssues []*goanalysis.Issue return goanalysis. NewLinterFromAnalyzer(&analysis.Analyzer{ @@ -38,13 +38,13 @@ func New(settings *config.GoCycloSettings) *goanalysis.Linter { return nil, nil }, }). - WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + WithIssuesReporter(func(*linter.Context) []*goanalysis.Issue { return resIssues }). WithLoadMode(goanalysis.LoadModeSyntax) } -func runGoCyclo(pass *analysis.Pass, settings *config.GoCycloSettings) []goanalysis.Issue { +func runGoCyclo(pass *analysis.Pass, settings *config.GoCycloSettings) []*goanalysis.Issue { var stats gocyclo.Stats for _, f := range pass.Files { stats = gocyclo.AnalyzeASTFile(f, pass.Fset, stats) @@ -55,7 +55,7 @@ func runGoCyclo(pass *analysis.Pass, settings *config.GoCycloSettings) []goanaly stats = stats.SortAndFilter(-1, settings.MinComplexity) - issues := make([]goanalysis.Issue, 0, len(stats)) + issues := make([]*goanalysis.Issue, 0, len(stats)) for _, s := range stats { text := fmt.Sprintf("cyclomatic complexity %d of func %s is high (> %d)", diff --git a/pkg/golinters/gomoddirectives/gomoddirectives.go b/pkg/golinters/gomoddirectives/gomoddirectives.go index e11313a62b9c..dd6656fb6cb6 100644 --- a/pkg/golinters/gomoddirectives/gomoddirectives.go +++ b/pkg/golinters/gomoddirectives/gomoddirectives.go @@ -17,7 +17,7 @@ import ( const linterName = "gomoddirectives" func New(settings *config.GoModDirectivesSettings) *goanalysis.Linter { - var issues []goanalysis.Issue + var issues []*goanalysis.Issue var once sync.Once var opts gomoddirectives.Options @@ -79,7 +79,7 @@ func New(settings *config.GoModDirectivesSettings) *goanalysis.Linter { return nil, nil } }). - WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + WithIssuesReporter(func(*linter.Context) []*goanalysis.Issue { return issues }). WithLoadMode(goanalysis.LoadModeSyntax) diff --git a/pkg/golinters/gomodguard/gomodguard.go b/pkg/golinters/gomodguard/gomodguard.go index 502610341342..7d16f57b3a5c 100644 --- a/pkg/golinters/gomodguard/gomodguard.go +++ b/pkg/golinters/gomodguard/gomodguard.go @@ -16,7 +16,7 @@ import ( const linterName = "gomodguard" func New(settings *config.GoModGuardSettings) *goanalysis.Linter { - var issues []goanalysis.Issue + var issues []*goanalysis.Issue var mu sync.Mutex processorCfg := &gomodguard.Configuration{} @@ -82,7 +82,7 @@ func New(settings *config.GoModGuardSettings) *goanalysis.Linter { return nil, nil } }). - WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + WithIssuesReporter(func(*linter.Context) []*goanalysis.Issue { return issues }). WithLoadMode(goanalysis.LoadModeSyntax) diff --git a/pkg/golinters/gosec/gosec.go b/pkg/golinters/gosec/gosec.go index e38de1ee20e5..66d229295a3f 100644 --- a/pkg/golinters/gosec/gosec.go +++ b/pkg/golinters/gosec/gosec.go @@ -26,7 +26,7 @@ const linterName = "gosec" func New(settings *config.GoSecSettings) *goanalysis.Linter { var mu sync.Mutex - var resIssues []goanalysis.Issue + var resIssues []*goanalysis.Issue conf := gosec.NewConfig() @@ -73,13 +73,13 @@ func New(settings *config.GoSecSettings) *goanalysis.Linter { return nil, nil } }). - WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + WithIssuesReporter(func(*linter.Context) []*goanalysis.Issue { return resIssues }). WithLoadMode(goanalysis.LoadModeTypesInfo) } -func runGoSec(lintCtx *linter.Context, pass *analysis.Pass, settings *config.GoSecSettings, analyzer *gosec.Analyzer) []goanalysis.Issue { +func runGoSec(lintCtx *linter.Context, pass *analysis.Pass, settings *config.GoSecSettings, analyzer *gosec.Analyzer) []*goanalysis.Issue { pkg := &packages.Package{ Fset: pass.Fset, Syntax: pass.Files, @@ -107,7 +107,7 @@ func runGoSec(lintCtx *linter.Context, pass *analysis.Pass, settings *config.GoS secIssues = filterIssues(secIssues, severity, confidence) - issues := make([]goanalysis.Issue, 0, len(secIssues)) + issues := make([]*goanalysis.Issue, 0, len(secIssues)) for _, i := range secIssues { text := fmt.Sprintf("%s: %s", i.RuleID, i.What) diff --git a/pkg/golinters/nolintlint/internal/nolintlint.go b/pkg/golinters/nolintlint/internal/nolintlint.go index 2be7c5c144ea..a20161405f1c 100644 --- a/pkg/golinters/nolintlint/internal/nolintlint.go +++ b/pkg/golinters/nolintlint/internal/nolintlint.go @@ -55,8 +55,8 @@ var ( ) //nolint:funlen,gocyclo // the function is going to be refactored in the future -func (l Linter) Run(pass *analysis.Pass) ([]goanalysis.Issue, error) { - var issues []goanalysis.Issue +func (l Linter) Run(pass *analysis.Pass) ([]*goanalysis.Issue, error) { + var issues []*goanalysis.Issue for _, file := range pass.Files { for _, c := range file.Comments { diff --git a/pkg/golinters/nolintlint/internal/nolintlint_test.go b/pkg/golinters/nolintlint/internal/nolintlint_test.go index 788d6b5a84dd..b534fbf89511 100644 --- a/pkg/golinters/nolintlint/internal/nolintlint_test.go +++ b/pkg/golinters/nolintlint/internal/nolintlint_test.go @@ -19,7 +19,7 @@ func TestLinter_Run(t *testing.T) { needs Needs excludes []string contents string - expected []result.Issue + expected []*result.Issue }{ { desc: "when no explanation is provided", @@ -36,7 +36,7 @@ func foo() { other() //nolintother } `, - expected: []result.Issue{ + expected: []*result.Issue{ { FromLinter: "nolintlint", Text: "directive `//nolint` should provide explanation such as `//nolint // this is why`", @@ -69,7 +69,7 @@ func foo() { //nolint:dupl func foo() {} `, - expected: []result.Issue{{ + expected: []*result.Issue{{ FromLinter: "nolintlint", Text: "directive `//nolint:dupl` should provide explanation such as `//nolint:dupl // this is why`", Pos: token.Position{Filename: "testing.go", Offset: 47, Line: 5, Column: 1}, @@ -97,7 +97,7 @@ func foo() { bad() //nolint // because } `, - expected: []result.Issue{ + expected: []*result.Issue{ { FromLinter: "nolintlint", Text: "directive `//nolint` should mention specific linter such as `//nolint:my-linter`", @@ -120,7 +120,7 @@ func foo() { good() //nolint } `, - expected: []result.Issue{ + expected: []*result.Issue{ { FromLinter: "nolintlint", Text: "directive `// nolint` should be written without leading space as `//nolint`", @@ -158,7 +158,7 @@ func foo() { good() //nolint: linter1, linter2 } `, - expected: []result.Issue{{ + expected: []*result.Issue{{ FromLinter: "nolintlint", Text: "directive `//nolint:linter1 linter2` should match `//nolint[:] [// ]`", Pos: token.Position{Filename: "testing.go", Offset: 71, Line: 5, Column: 9}, @@ -183,7 +183,7 @@ func foo() { bad() //nolint } `, - expected: []result.Issue{{ + expected: []*result.Issue{{ FromLinter: "nolintlint", Text: "directive `//nolint` is unused", Pos: token.Position{Filename: "testing.go", Offset: 34, Line: 4, Column: 9}, @@ -205,7 +205,7 @@ func foo() { bad() //nolint:somelinter } `, - expected: []result.Issue{{ + expected: []*result.Issue{{ FromLinter: "nolintlint", Text: "directive `//nolint:somelinter` is unused for linter \"somelinter\"", Pos: token.Position{Filename: "testing.go", Offset: 34, Line: 4, Column: 9}, @@ -229,7 +229,7 @@ func foo() { bad() } `, - expected: []result.Issue{{ + expected: []*result.Issue{{ FromLinter: "nolintlint", Text: "directive `//nolint:somelinter` is unused for linter \"somelinter\"", Pos: token.Position{Filename: "testing.go", Offset: 13, Line: 3, Column: 1}, @@ -252,7 +252,7 @@ func foo() { bad() //nolint:linter1,linter2 } `, - expected: []result.Issue{ + expected: []*result.Issue{ { FromLinter: "nolintlint", Text: "directive `//nolint:linter1,linter2` is unused for linter \"linter1\"", @@ -289,7 +289,7 @@ func foo() { analysisIssues, err := linter.Run(pass) require.NoError(t, err) - var issues []result.Issue + var issues []*result.Issue for _, i := range analysisIssues { issues = append(issues, i.Issue) } diff --git a/pkg/golinters/nolintlint/nolintlint.go b/pkg/golinters/nolintlint/nolintlint.go index 37f9cb96aac7..6f3d373063f8 100644 --- a/pkg/golinters/nolintlint/nolintlint.go +++ b/pkg/golinters/nolintlint/nolintlint.go @@ -17,7 +17,7 @@ const LinterName = nolintlint.LinterName func New(settings *config.NoLintLintSettings) *goanalysis.Linter { var mu sync.Mutex - var resIssues []goanalysis.Issue + var resIssues []*goanalysis.Issue var needs nolintlint.Needs if settings.RequireExplanation { @@ -56,7 +56,7 @@ func New(settings *config.NoLintLintSettings) *goanalysis.Linter { return nil, nil }, }). - WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + WithIssuesReporter(func(*linter.Context) []*goanalysis.Issue { return resIssues }). WithLoadMode(goanalysis.LoadModeSyntax) diff --git a/pkg/golinters/promlinter/promlinter.go b/pkg/golinters/promlinter/promlinter.go index 2cb59cbe6f1a..491409f4ef7a 100644 --- a/pkg/golinters/promlinter/promlinter.go +++ b/pkg/golinters/promlinter/promlinter.go @@ -17,7 +17,7 @@ const linterName = "promlinter" func New(settings *config.PromlinterSettings) *goanalysis.Linter { var mu sync.Mutex - var resIssues []goanalysis.Issue + var resIssues []*goanalysis.Issue var promSettings promlinter.Setting if settings != nil { @@ -45,20 +45,20 @@ func New(settings *config.PromlinterSettings) *goanalysis.Linter { return nil, nil }, }). - WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + WithIssuesReporter(func(*linter.Context) []*goanalysis.Issue { return resIssues }). WithLoadMode(goanalysis.LoadModeSyntax) } -func runPromLinter(pass *analysis.Pass, promSettings promlinter.Setting) []goanalysis.Issue { +func runPromLinter(pass *analysis.Pass, promSettings promlinter.Setting) []*goanalysis.Issue { lintIssues := promlinter.RunLint(pass.Fset, pass.Files, promSettings) if len(lintIssues) == 0 { return nil } - issues := make([]goanalysis.Issue, len(lintIssues)) + issues := make([]*goanalysis.Issue, len(lintIssues)) for k, i := range lintIssues { issue := result.Issue{ Pos: i.Pos, diff --git a/pkg/golinters/revive/revive.go b/pkg/golinters/revive/revive.go index b06b5de8aa28..3e13c516fa12 100644 --- a/pkg/golinters/revive/revive.go +++ b/pkg/golinters/revive/revive.go @@ -35,7 +35,7 @@ var ( func New(settings *config.ReviveSettings) *goanalysis.Linter { var mu sync.Mutex - var resIssues []goanalysis.Issue + var resIssues []*goanalysis.Issue analyzer := &analysis.Analyzer{ Name: linterName, @@ -69,7 +69,7 @@ func New(settings *config.ReviveSettings) *goanalysis.Linter { return nil, nil } }). - WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + WithIssuesReporter(func(*linter.Context) []*goanalysis.Issue { return resIssues }). WithLoadMode(goanalysis.LoadModeSyntax) @@ -106,7 +106,7 @@ func newWrapper(settings *config.ReviveSettings) (*wrapper, error) { }, nil } -func (w *wrapper) run(pass *analysis.Pass) ([]goanalysis.Issue, error) { +func (w *wrapper) run(pass *analysis.Pass) ([]*goanalysis.Issue, error) { packages := [][]string{internal.GetGoFileNames(pass)} failures, err := w.revive.Lint(packages, w.lintingRules, *w.conf) @@ -114,7 +114,7 @@ func (w *wrapper) run(pass *analysis.Pass) ([]goanalysis.Issue, error) { return nil, err } - var issues []goanalysis.Issue + var issues []*goanalysis.Issue for failure := range failures { if failure.Confidence < w.conf.Confidence { continue @@ -126,7 +126,7 @@ func (w *wrapper) run(pass *analysis.Pass) ([]goanalysis.Issue, error) { return issues, nil } -func (w *wrapper) toIssue(pass *analysis.Pass, failure *lint.Failure) goanalysis.Issue { +func (w *wrapper) toIssue(pass *analysis.Pass, failure *lint.Failure) *goanalysis.Issue { lineRangeTo := failure.Position.End.Line if failure.RuleName == (&rule.ExportedRule{}).Name() { lineRangeTo = failure.Position.Start.Line diff --git a/pkg/golinters/unconvert/unconvert.go b/pkg/golinters/unconvert/unconvert.go index c9b3f75dd169..593dfbe96e63 100644 --- a/pkg/golinters/unconvert/unconvert.go +++ b/pkg/golinters/unconvert/unconvert.go @@ -16,7 +16,7 @@ const linterName = "unconvert" func New(settings *config.UnconvertSettings) *goanalysis.Linter { var mu sync.Mutex - var resIssues []goanalysis.Issue + var resIssues []*goanalysis.Issue unconvert.SetFastMath(settings.FastMath) unconvert.SetSafe(settings.Safe) @@ -39,16 +39,16 @@ func New(settings *config.UnconvertSettings) *goanalysis.Linter { return nil, nil }, }). - WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { + WithIssuesReporter(func(*linter.Context) []*goanalysis.Issue { return resIssues }). WithLoadMode(goanalysis.LoadModeTypesInfo) } -func runUnconvert(pass *analysis.Pass) []goanalysis.Issue { +func runUnconvert(pass *analysis.Pass) []*goanalysis.Issue { positions := unconvert.Run(pass) - var issues []goanalysis.Issue + var issues []*goanalysis.Issue for _, position := range positions { issues = append(issues, goanalysis.NewIssue(&result.Issue{ Pos: position, diff --git a/pkg/golinters/unused/unused.go b/pkg/golinters/unused/unused.go index 375962259676..c0f4657dcc26 100644 --- a/pkg/golinters/unused/unused.go +++ b/pkg/golinters/unused/unused.go @@ -20,7 +20,7 @@ const linterName = "unused" func New(settings *config.UnusedSettings) *goanalysis.Linter { var mu sync.Mutex - var resIssues []goanalysis.Issue + var resIssues []*goanalysis.Issue analyzer := &analysis.Analyzer{ Name: linterName, @@ -45,12 +45,12 @@ func New(settings *config.UnusedSettings) *goanalysis.Linter { "Checks Go code for unused constants, variables, functions and types", []*analysis.Analyzer{analyzer}, nil, - ).WithIssuesReporter(func(_ *linter.Context) []goanalysis.Issue { + ).WithIssuesReporter(func(_ *linter.Context) []*goanalysis.Issue { return resIssues }).WithLoadMode(goanalysis.LoadModeTypesInfo) } -func runUnused(pass *analysis.Pass, cfg *config.UnusedSettings) []goanalysis.Issue { +func runUnused(pass *analysis.Pass, cfg *config.UnusedSettings) []*goanalysis.Issue { res := getUnusedResults(pass, cfg) used := make(map[string]bool) @@ -58,7 +58,7 @@ func runUnused(pass *analysis.Pass, cfg *config.UnusedSettings) []goanalysis.Iss used[fmt.Sprintf("%s %d %s", obj.Position.Filename, obj.Position.Line, obj.Name)] = true } - var issues []goanalysis.Issue + var issues []*goanalysis.Issue // Inspired by https://github.com/dominikh/go-tools/blob/d694aadcb1f50c2d8ac0a1dd06217ebb9f654764/lintcmd/lint.go#L177-L197 for _, object := range res.Unused { diff --git a/pkg/lint/linter/linter.go b/pkg/lint/linter/linter.go index 7f68545cf159..e6b484efbb05 100644 --- a/pkg/lint/linter/linter.go +++ b/pkg/lint/linter/linter.go @@ -8,7 +8,7 @@ import ( ) type Linter interface { - Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) + Run(ctx context.Context, lintCtx *Context) ([]*result.Issue, error) Name() string Desc() string } @@ -43,7 +43,7 @@ func NewNoopDeprecated(name string, cfg *config.Config, level DeprecationLevel) return noop } -func (n Noop) Run(_ context.Context, lintCtx *Context) ([]result.Issue, error) { +func (n Noop) Run(_ context.Context, lintCtx *Context) ([]*result.Issue, error) { if n.reason == "" { return nil, nil } diff --git a/pkg/lint/runner.go b/pkg/lint/runner.go index 5ede9b24dae5..5cc46feb101d 100644 --- a/pkg/lint/runner.go +++ b/pkg/lint/runner.go @@ -118,17 +118,17 @@ func NewRunner(log logutils.Log, cfg *config.Config, goenv *goutil.Env, }, nil } -func (r *Runner) Run(ctx context.Context, linters []*linter.Config) ([]result.Issue, error) { +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 + issues []*result.Issue ) for _, lc := range linters { - linterIssues, err := timeutils.TrackStage(sw, lc.Name(), func() ([]result.Issue, error) { + linterIssues, err := timeutils.TrackStage(sw, lc.Name(), func() ([]*result.Issue, error) { return r.runLinterSafe(ctx, r.lintCtx, lc) }) if err != nil { @@ -146,7 +146,7 @@ func (r *Runner) Run(ctx context.Context, linters []*linter.Config) ([]result.Is func (r *Runner) runLinterSafe(ctx context.Context, lintCtx *linter.Context, lc *linter.Config, -) (ret []result.Issue, err error) { +) (ret []*result.Issue, err error) { defer func() { if panicData := recover(); panicData != nil { if pe, ok := panicData.(*errorutil.PanicError); ok { @@ -185,13 +185,13 @@ func (r *Runner) runLinterSafe(ctx context.Context, lintCtx *linter.Context, return issues, nil } -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 statPerProcessor := map[string]processorStat{} - var outIssues []result.Issue + var outIssues []*result.Issue if len(inIssues) != 0 { issuesBefore += len(inIssues) outIssues = r.processIssues(inIssues, sw, statPerProcessor) @@ -225,9 +225,9 @@ func (r *Runner) printPerProcessorStat(stat map[string]processorStat) { } } -func (r *Runner) processIssues(issues []result.Issue, sw *timeutils.Stopwatch, statPerProcessor map[string]processorStat) []result.Issue { +func (r *Runner) processIssues(issues []*result.Issue, sw *timeutils.Stopwatch, statPerProcessor map[string]processorStat) []*result.Issue { for _, p := range r.Processors { - newIssues, err := timeutils.TrackStage(sw, p.Name(), func() ([]result.Issue, error) { + newIssues, err := timeutils.TrackStage(sw, p.Name(), func() ([]*result.Issue, error) { return p.Process(issues) }) @@ -243,7 +243,7 @@ func (r *Runner) processIssues(issues []result.Issue, sw *timeutils.Stopwatch, s // This is required by JSON serialization if issues == nil { - issues = []result.Issue{} + issues = []*result.Issue{} } } diff --git a/pkg/printers/checkstyle.go b/pkg/printers/checkstyle.go index 5a60554bdb62..c3869bd39d9d 100644 --- a/pkg/printers/checkstyle.go +++ b/pkg/printers/checkstyle.go @@ -37,15 +37,14 @@ func NewCheckstyle(log logutils.Log, w io.Writer) *Checkstyle { } } -func (p *Checkstyle) Print(issues []result.Issue) error { +func (p *Checkstyle) Print(issues []*result.Issue) error { out := checkstyleOutput{ Version: "5.0", } files := map[string]*checkstyleFile{} - for i := range issues { - issue := &issues[i] + for _, issue := range issues { file, ok := files[issue.FilePath()] if !ok { file = &checkstyleFile{ diff --git a/pkg/printers/checkstyle_test.go b/pkg/printers/checkstyle_test.go index f087a79b83b0..5c8781e388fb 100644 --- a/pkg/printers/checkstyle_test.go +++ b/pkg/printers/checkstyle_test.go @@ -14,7 +14,7 @@ import ( ) func TestCheckstyle_Print(t *testing.T) { - issues := []result.Issue{ + issues := []*result.Issue{ { FromLinter: "linter-a", Severity: "warning", diff --git a/pkg/printers/codeclimate.go b/pkg/printers/codeclimate.go index 872d860d3ba4..e2eded608fb9 100644 --- a/pkg/printers/codeclimate.go +++ b/pkg/printers/codeclimate.go @@ -30,12 +30,10 @@ func NewCodeClimate(log logutils.Log, w io.Writer) *CodeClimate { } } -func (p *CodeClimate) Print(issues []result.Issue) error { +func (p *CodeClimate) Print(issues []*result.Issue) error { ccIssues := make([]codeClimateIssue, 0, len(issues)) - for i := range issues { - issue := issues[i] - + for _, issue := range issues { ccIssue := codeClimateIssue{ Description: issue.Description(), CheckName: issue.FromLinter, diff --git a/pkg/printers/codeclimate_test.go b/pkg/printers/codeclimate_test.go index 28fd281c4548..159dd86e37ae 100644 --- a/pkg/printers/codeclimate_test.go +++ b/pkg/printers/codeclimate_test.go @@ -13,7 +13,7 @@ import ( ) func TestCodeClimate_Print(t *testing.T) { - issues := []result.Issue{ + issues := []*result.Issue{ { FromLinter: "linter-a", Severity: "minor", diff --git a/pkg/printers/html.go b/pkg/printers/html.go index 0f99bb7ff8ce..1f6ed18344b0 100644 --- a/pkg/printers/html.go +++ b/pkg/printers/html.go @@ -132,20 +132,20 @@ func NewHTML(w io.Writer) *HTML { return &HTML{w: w} } -func (p HTML) Print(issues []result.Issue) error { +func (p HTML) Print(issues []*result.Issue) error { var htmlIssues []htmlIssue - for i := range issues { - pos := fmt.Sprintf("%s:%d", issues[i].FilePath(), issues[i].Line()) - if issues[i].Pos.Column != 0 { - pos += fmt.Sprintf(":%d", issues[i].Pos.Column) + for _, issue := range issues { + pos := fmt.Sprintf("%s:%d", issue.FilePath(), issue.Line()) + if issue.Pos.Column != 0 { + pos += fmt.Sprintf(":%d", issue.Pos.Column) } htmlIssues = append(htmlIssues, htmlIssue{ - Title: strings.TrimSpace(issues[i].Text), + Title: strings.TrimSpace(issue.Text), Pos: pos, - Linter: issues[i].FromLinter, - Code: strings.Join(issues[i].SourceLines, "\n"), + Linter: issue.FromLinter, + Code: strings.Join(issue.SourceLines, "\n"), }) } diff --git a/pkg/printers/html_test.go b/pkg/printers/html_test.go index 3964d81ddeaf..17db307509c2 100644 --- a/pkg/printers/html_test.go +++ b/pkg/printers/html_test.go @@ -118,7 +118,7 @@ const expectedHTML = ` ` func TestHTML_Print(t *testing.T) { - issues := []result.Issue{ + issues := []*result.Issue{ { FromLinter: "linter-a", Severity: "warning", diff --git a/pkg/printers/json.go b/pkg/printers/json.go index 64fd33c7bae5..97354081c903 100644 --- a/pkg/printers/json.go +++ b/pkg/printers/json.go @@ -22,17 +22,17 @@ func NewJSON(w io.Writer, rd *report.Data) *JSON { } type JSONResult struct { - Issues []result.Issue + Issues []*result.Issue Report *report.Data } -func (p JSON) Print(issues []result.Issue) error { +func (p JSON) Print(issues []*result.Issue) error { res := JSONResult{ Issues: issues, Report: p.rd, } if res.Issues == nil { - res.Issues = []result.Issue{} + res.Issues = []*result.Issue{} } return json.NewEncoder(p.w).Encode(res) diff --git a/pkg/printers/json_test.go b/pkg/printers/json_test.go index 001c283ee611..50c67f995fe1 100644 --- a/pkg/printers/json_test.go +++ b/pkg/printers/json_test.go @@ -12,7 +12,7 @@ import ( ) func TestJSON_Print(t *testing.T) { - issues := []result.Issue{ + issues := []*result.Issue{ { FromLinter: "linter-a", Severity: "warning", diff --git a/pkg/printers/junitxml.go b/pkg/printers/junitxml.go index 708f83e5a860..b040e746703c 100644 --- a/pkg/printers/junitxml.go +++ b/pkg/printers/junitxml.go @@ -27,31 +27,30 @@ func NewJUnitXML(w io.Writer, extended bool) *JUnitXML { } } -func (p JUnitXML) Print(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 { - i := &issues[ind] - suiteName := i.FilePath() + for _, issue := range issues { + suiteName := issue.FilePath() testSuite := suites[suiteName] - testSuite.Suite = i.FilePath() + testSuite.Suite = issue.FilePath() testSuite.Tests++ testSuite.Failures++ tc := testCaseXML{ - Name: i.FromLinter, - ClassName: i.Pos.String(), + Name: issue.FromLinter, + ClassName: issue.Pos.String(), Failure: failureXML{ - Type: i.Severity, - Message: i.Pos.String() + ": " + i.Text, + Type: issue.Severity, + Message: issue.Pos.String() + ": " + issue.Text, Content: fmt.Sprintf("%s: %s\nCategory: %s\nFile: %s\nLine: %d\nDetails: %s", - i.Severity, i.Text, i.FromLinter, i.Pos.Filename, i.Pos.Line, strings.Join(i.SourceLines, "\n")), + issue.Severity, issue.Text, issue.FromLinter, issue.Pos.Filename, issue.Pos.Line, strings.Join(issue.SourceLines, "\n")), }, } if p.extended { - tc.File = i.Pos.Filename - tc.Line = i.Pos.Line + tc.File = issue.Pos.Filename + tc.Line = issue.Pos.Line } testSuite.TestCases = append(testSuite.TestCases, tc) diff --git a/pkg/printers/junitxml_test.go b/pkg/printers/junitxml_test.go index 7a429e546f46..90a365e79870 100644 --- a/pkg/printers/junitxml_test.go +++ b/pkg/printers/junitxml_test.go @@ -12,7 +12,7 @@ import ( ) func TestJUnitXML_Print(t *testing.T) { - issues := []result.Issue{ + issues := []*result.Issue{ { FromLinter: "linter-a", Severity: "warning", diff --git a/pkg/printers/printer.go b/pkg/printers/printer.go index 575bba75f1d5..bb3eab6205e8 100644 --- a/pkg/printers/printer.go +++ b/pkg/printers/printer.go @@ -23,7 +23,7 @@ const ( const defaultFileMode = 0o644 type issuePrinter interface { - Print(issues []result.Issue) error + Print(issues []*result.Issue) error } // Printer prints issues. @@ -63,7 +63,7 @@ func NewPrinter(log logutils.Log, cfg *config.Formats, reportData *report.Data, // Print prints issues based on the formats defined. // //nolint:gocyclo,funlen // the complexity is related to the number of formats. -func (c *Printer) Print(issues []result.Issue) error { +func (c *Printer) Print(issues []*result.Issue) error { if c.cfg.IsEmpty() { c.cfg.Text.Path = outputStdOut } diff --git a/pkg/printers/printer_test.go b/pkg/printers/printer_test.go index 850ee94a097b..6b3737f16688 100644 --- a/pkg/printers/printer_test.go +++ b/pkg/printers/printer_test.go @@ -29,7 +29,7 @@ func unmarshalFile(t *testing.T, filename string, v any) { func TestPrinter_Print_stdout(t *testing.T) { logger := logutils.NewStderrLog("skip") - var issues []result.Issue + var issues []*result.Issue unmarshalFile(t, "in-issues.json", &issues) data := &report.Data{} @@ -86,7 +86,7 @@ func TestPrinter_Print_stdout(t *testing.T) { func TestPrinter_Print_stderr(t *testing.T) { logger := logutils.NewStderrLog("skip") - var issues []result.Issue + var issues []*result.Issue unmarshalFile(t, "in-issues.json", &issues) data := &report.Data{} @@ -122,7 +122,7 @@ func TestPrinter_Print_stderr(t *testing.T) { func TestPrinter_Print_file(t *testing.T) { logger := logutils.NewStderrLog("skip") - var issues []result.Issue + var issues []*result.Issue unmarshalFile(t, "in-issues.json", &issues) data := &report.Data{} @@ -165,7 +165,7 @@ func TestPrinter_Print_file(t *testing.T) { func TestPrinter_Print_multiple(t *testing.T) { logger := logutils.NewStderrLog("skip") - var issues []result.Issue + var issues []*result.Issue unmarshalFile(t, "in-issues.json", &issues) data := &report.Data{} diff --git a/pkg/printers/sarif.go b/pkg/printers/sarif.go index e8d8c64f7da3..e1caf179a821 100644 --- a/pkg/printers/sarif.go +++ b/pkg/printers/sarif.go @@ -36,14 +36,12 @@ func NewSarif(log logutils.Log, w io.Writer) *Sarif { } } -func (p *Sarif) Print(issues []result.Issue) error { +func (p *Sarif) Print(issues []*result.Issue) error { run := sarifRun{} run.Tool.Driver.Name = "golangci-lint" run.Results = make([]sarifResult, 0) - for i := range issues { - issue := issues[i] - + for _, issue := range issues { sr := sarifResult{ RuleID: issue.FromLinter, Level: p.sanitizer.Sanitize(issue.Severity), diff --git a/pkg/printers/sarif_test.go b/pkg/printers/sarif_test.go index f6ddf4d81f07..400bb25bed37 100644 --- a/pkg/printers/sarif_test.go +++ b/pkg/printers/sarif_test.go @@ -13,7 +13,7 @@ import ( ) func TestSarif_Print(t *testing.T) { - issues := []result.Issue{ + issues := []*result.Issue{ { FromLinter: "linter-a", Severity: "warning", diff --git a/pkg/printers/tab.go b/pkg/printers/tab.go index 0d14593e5950..8edbb05e11fe 100644 --- a/pkg/printers/tab.go +++ b/pkg/printers/tab.go @@ -40,11 +40,11 @@ func (p *Tab) SprintfColored(ca color.Attribute, format string, args ...any) str return c.Sprintf(format, args...) } -func (p *Tab) Print(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 { - p.printIssue(&issues[i], w) + for _, issue := range issues { + p.printIssue(issue, w) } if err := w.Flush(); err != nil { diff --git a/pkg/printers/tab_test.go b/pkg/printers/tab_test.go index f8e47f84b2b1..1920334753e8 100644 --- a/pkg/printers/tab_test.go +++ b/pkg/printers/tab_test.go @@ -22,7 +22,7 @@ func TestTab_Print(t *testing.T) { }) color.NoColor = false - issues := []result.Issue{ + issues := []*result.Issue{ { FromLinter: "linter-a", Severity: "warning", diff --git a/pkg/printers/teamcity.go b/pkg/printers/teamcity.go index a85307729d05..36114fedfc57 100644 --- a/pkg/printers/teamcity.go +++ b/pkg/printers/teamcity.go @@ -48,12 +48,10 @@ func NewTeamCity(log logutils.Log, w io.Writer) *TeamCity { } } -func (p *TeamCity) Print(issues []result.Issue) error { +func (p *TeamCity) Print(issues []*result.Issue) error { uniqLinters := map[string]struct{}{} - for i := range issues { - issue := issues[i] - + for _, issue := range issues { _, ok := uniqLinters[issue.FromLinter] if !ok { inspectionType := InspectionType{ diff --git a/pkg/printers/teamcity_test.go b/pkg/printers/teamcity_test.go index eda415670273..121a0519eb48 100644 --- a/pkg/printers/teamcity_test.go +++ b/pkg/printers/teamcity_test.go @@ -13,7 +13,7 @@ import ( ) func TestTeamCity_Print(t *testing.T) { - issues := []result.Issue{ + issues := []*result.Issue{ { FromLinter: "linter-a", Severity: "WARNING", diff --git a/pkg/printers/text.go b/pkg/printers/text.go index 545679fb7b45..eb9297615be2 100644 --- a/pkg/printers/text.go +++ b/pkg/printers/text.go @@ -42,16 +42,16 @@ func (p *Text) SprintfColored(ca color.Attribute, format string, args ...any) st return c.Sprintf(format, args...) } -func (p *Text) Print(issues []result.Issue) error { - for i := range issues { - p.printIssue(&issues[i]) +func (p *Text) Print(issues []*result.Issue) error { + for _, issue := range issues { + p.printIssue(issue) if !p.printIssuedLine { continue } - p.printSourceCode(&issues[i]) - p.printUnderLinePointer(&issues[i]) + p.printSourceCode(issue) + p.printUnderLinePointer(issue) } return nil diff --git a/pkg/printers/text_test.go b/pkg/printers/text_test.go index 4a1c39483526..4aa784ee4457 100644 --- a/pkg/printers/text_test.go +++ b/pkg/printers/text_test.go @@ -22,7 +22,7 @@ func TestText_Print(t *testing.T) { }) color.NoColor = false - issues := []result.Issue{ + issues := []*result.Issue{ { FromLinter: "linter-a", Severity: "warning", diff --git a/pkg/result/issue.go b/pkg/result/issue.go index 86a4ef3b7369..2587ffff2cc7 100644 --- a/pkg/result/issue.go +++ b/pkg/result/issue.go @@ -32,7 +32,7 @@ type Issue struct { // HunkPos is used only when golangci-lint is run over a diff HunkPos int `json:",omitempty"` - // If we know how to fix the issue we can provide replacement lines + // If we know how to fix the issue, we can provide replacement lines SuggestedFixes []analysis.SuggestedFix `json:",omitempty"` // If we are expecting a nolint (because this is from nolintlint), record the expected linter @@ -42,7 +42,7 @@ type Issue struct { // Only for Diff processor needs. WorkingDirectoryRelativePath string `json:"-"` - // Only for processor that need relative paths evaluation. + // Only for processors that need relative paths evaluation. RelativePath string `json:"-"` } diff --git a/pkg/result/processors/cgo.go b/pkg/result/processors/cgo.go index dea3801e2c8a..4cc7b57dbf05 100644 --- a/pkg/result/processors/cgo.go +++ b/pkg/result/processors/cgo.go @@ -31,7 +31,7 @@ func (*Cgo) Name() string { return "cgo" } -func (p *Cgo) Process(issues []result.Issue) ([]result.Issue, error) { +func (p *Cgo) Process(issues []*result.Issue) ([]*result.Issue, error) { return filterIssuesErr(issues, p.shouldPassIssue) } diff --git a/pkg/result/processors/diff.go b/pkg/result/processors/diff.go index a84caf7b686a..15574ff0d374 100644 --- a/pkg/result/processors/diff.go +++ b/pkg/result/processors/diff.go @@ -48,7 +48,7 @@ func (*Diff) Name() string { return "diff" } -func (p *Diff) Process(issues []result.Issue) ([]result.Issue, error) { +func (p *Diff) Process(issues []*result.Issue) ([]*result.Issue, error) { if !p.onlyNew && p.fromRev == "" && p.fromMergeBase == "" && p.patchFilePath == "" && p.patch == "" { return issues, nil } diff --git a/pkg/result/processors/exclusion_generated_file_filter.go b/pkg/result/processors/exclusion_generated_file_filter.go index 6cbde3aedf58..d76ec3184f86 100644 --- a/pkg/result/processors/exclusion_generated_file_filter.go +++ b/pkg/result/processors/exclusion_generated_file_filter.go @@ -40,7 +40,7 @@ func (*GeneratedFileFilter) Name() string { return "generated_file_filter" } -func (p *GeneratedFileFilter) Process(issues []result.Issue) ([]result.Issue, error) { +func (p *GeneratedFileFilter) Process(issues []*result.Issue) ([]*result.Issue, error) { if p.mode == config.GeneratedModeDisable { return issues, nil } diff --git a/pkg/result/processors/exclusion_paths.go b/pkg/result/processors/exclusion_paths.go index 90c5f522f8bd..acf13edd0797 100644 --- a/pkg/result/processors/exclusion_paths.go +++ b/pkg/result/processors/exclusion_paths.go @@ -68,7 +68,7 @@ func (*ExclusionPaths) Name() string { return "exclusion_paths" } -func (p *ExclusionPaths) Process(issues []result.Issue) ([]result.Issue, error) { +func (p *ExclusionPaths) Process(issues []*result.Issue) ([]*result.Issue, error) { if len(p.pathPatterns) == 0 && len(p.pathExceptPatterns) == 0 { return issues, nil } diff --git a/pkg/result/processors/exclusion_paths_test.go b/pkg/result/processors/exclusion_paths_test.go index deac410ab366..bfd19af13e65 100644 --- a/pkg/result/processors/exclusion_paths_test.go +++ b/pkg/result/processors/exclusion_paths_test.go @@ -19,22 +19,22 @@ func TestExclusionPaths_Process(t *testing.T) { testCases := []struct { desc string cfg *config.LinterExclusions - issues []result.Issue - expected []result.Issue + issues []*result.Issue + expected []*result.Issue }{ { desc: "paths: word", cfg: &config.LinterExclusions{ Paths: []string{"foo"}, }, - issues: []result.Issue{ + issues: []*result.Issue{ {RelativePath: "foo.go"}, {RelativePath: "foo/foo.go"}, {RelativePath: "foo/bar.go"}, {RelativePath: "bar/foo.go"}, {RelativePath: "bar/bar.go"}, }, - expected: []result.Issue{ + expected: []*result.Issue{ {RelativePath: "bar/bar.go"}, }, }, @@ -43,14 +43,14 @@ func TestExclusionPaths_Process(t *testing.T) { cfg: &config.LinterExclusions{ Paths: []string{"^foo"}, }, - issues: []result.Issue{ + issues: []*result.Issue{ {RelativePath: filepath.FromSlash("foo.go")}, {RelativePath: filepath.FromSlash("foo/foo.go")}, {RelativePath: filepath.FromSlash("foo/bar.go")}, {RelativePath: filepath.FromSlash("bar/foo.go")}, {RelativePath: filepath.FromSlash("bar/bar.go")}, }, - expected: []result.Issue{ + expected: []*result.Issue{ {RelativePath: filepath.FromSlash("bar/foo.go")}, {RelativePath: filepath.FromSlash("bar/bar.go")}, }, @@ -60,14 +60,14 @@ func TestExclusionPaths_Process(t *testing.T) { cfg: &config.LinterExclusions{ Paths: []string{"^foo/"}, }, - issues: []result.Issue{ + issues: []*result.Issue{ {RelativePath: filepath.FromSlash("foo.go")}, {RelativePath: filepath.FromSlash("foo/foo.go")}, {RelativePath: filepath.FromSlash("foo/bar.go")}, {RelativePath: filepath.FromSlash("bar/foo.go")}, {RelativePath: filepath.FromSlash("bar/bar.go")}, }, - expected: []result.Issue{ + expected: []*result.Issue{ {RelativePath: filepath.FromSlash("foo.go")}, {RelativePath: filepath.FromSlash("bar/foo.go")}, {RelativePath: filepath.FromSlash("bar/bar.go")}, @@ -78,22 +78,22 @@ func TestExclusionPaths_Process(t *testing.T) { cfg: &config.LinterExclusions{ Paths: []string{"c/d.go"}, }, - issues: []result.Issue{ + issues: []*result.Issue{ {RelativePath: filepath.FromSlash("a/b/c/d.go")}, {RelativePath: filepath.FromSlash("c/d.go")}, }, - expected: []result.Issue{}, + expected: []*result.Issue{}, }, { desc: "paths: same suffix with constrained expression", cfg: &config.LinterExclusions{ Paths: []string{"^c/d.go"}, }, - issues: []result.Issue{ + issues: []*result.Issue{ {RelativePath: filepath.FromSlash("a/b/c/d.go")}, {RelativePath: filepath.FromSlash("c/d.go")}, }, - expected: []result.Issue{ + expected: []*result.Issue{ {RelativePath: filepath.FromSlash("a/b/c/d.go")}, }, }, @@ -106,11 +106,11 @@ func TestExclusionPaths_Process(t *testing.T) { `^c/d.go`, }, }, - issues: []result.Issue{ + issues: []*result.Issue{ {RelativePath: filepath.FromSlash("a/b/c/d.go")}, {RelativePath: filepath.FromSlash("c/d.go")}, }, - expected: []result.Issue{ + expected: []*result.Issue{ {RelativePath: filepath.FromSlash("a/b/c/d.go")}, }, }, @@ -119,7 +119,7 @@ func TestExclusionPaths_Process(t *testing.T) { cfg: &config.LinterExclusions{ PathsExcept: []string{`^base/c/.*$`}, }, - issues: []result.Issue{ + issues: []*result.Issue{ {RelativePath: filepath.FromSlash("base/a/file.go")}, {RelativePath: filepath.FromSlash("base/b/file.go")}, {RelativePath: filepath.FromSlash("base/c/file.go")}, @@ -127,7 +127,7 @@ func TestExclusionPaths_Process(t *testing.T) { {RelativePath: filepath.FromSlash("base/c/b/file.go")}, {RelativePath: filepath.FromSlash("base/d/file.go")}, }, - expected: []result.Issue{ + expected: []*result.Issue{ {RelativePath: filepath.FromSlash("base/c/file.go")}, {RelativePath: filepath.FromSlash("base/c/a/file.go")}, {RelativePath: filepath.FromSlash("base/c/b/file.go")}, @@ -142,7 +142,7 @@ func TestExclusionPaths_Process(t *testing.T) { `^base/c/.*$`, }, }, - issues: []result.Issue{ + issues: []*result.Issue{ {RelativePath: filepath.FromSlash("base/a/file.go")}, {RelativePath: filepath.FromSlash("base/b/file.go")}, {RelativePath: filepath.FromSlash("base/c/file.go")}, @@ -150,7 +150,7 @@ func TestExclusionPaths_Process(t *testing.T) { {RelativePath: filepath.FromSlash("base/c/b/file.go")}, {RelativePath: filepath.FromSlash("base/d/file.go")}, }, - expected: []result.Issue{ + expected: []*result.Issue{ {RelativePath: filepath.FromSlash("base/c/file.go")}, {RelativePath: filepath.FromSlash("base/c/a/file.go")}, {RelativePath: filepath.FromSlash("base/c/b/file.go")}, @@ -164,7 +164,7 @@ func TestExclusionPaths_Process(t *testing.T) { `^base/c/.*$`, }, }, - issues: []result.Issue{ + issues: []*result.Issue{ {RelativePath: filepath.FromSlash("base/a/file.go")}, {RelativePath: filepath.FromSlash("base/b/file.go")}, {RelativePath: filepath.FromSlash("base/c/file.go")}, @@ -173,7 +173,7 @@ func TestExclusionPaths_Process(t *testing.T) { {RelativePath: filepath.FromSlash("base/d/file.go")}, {RelativePath: filepath.FromSlash("base/e/file.go")}, }, - expected: []result.Issue{ + expected: []*result.Issue{ {RelativePath: filepath.FromSlash("base/c/file.go")}, {RelativePath: filepath.FromSlash("base/c/a/file.go")}, {RelativePath: filepath.FromSlash("base/c/b/file.go")}, @@ -186,7 +186,7 @@ func TestExclusionPaths_Process(t *testing.T) { Paths: []string{"^base/b/"}, PathsExcept: []string{`^base/c/.*$`}, }, - issues: []result.Issue{ + issues: []*result.Issue{ {RelativePath: filepath.FromSlash("base/a/file.go")}, {RelativePath: filepath.FromSlash("base/b/file.go")}, {RelativePath: filepath.FromSlash("base/c/file.go")}, @@ -194,7 +194,7 @@ func TestExclusionPaths_Process(t *testing.T) { {RelativePath: filepath.FromSlash("base/c/b/file.go")}, {RelativePath: filepath.FromSlash("base/d/file.go")}, }, - expected: []result.Issue{ + expected: []*result.Issue{ {RelativePath: filepath.FromSlash("base/c/file.go")}, {RelativePath: filepath.FromSlash("base/c/a/file.go")}, {RelativePath: filepath.FromSlash("base/c/b/file.go")}, @@ -206,7 +206,7 @@ func TestExclusionPaths_Process(t *testing.T) { Paths: []string{"^base/c/a/"}, PathsExcept: []string{`^base/c/.*$`}, }, - issues: []result.Issue{ + issues: []*result.Issue{ {RelativePath: filepath.FromSlash("base/a/file.go")}, {RelativePath: filepath.FromSlash("base/b/file.go")}, {RelativePath: filepath.FromSlash("base/c/file.go")}, @@ -214,7 +214,7 @@ func TestExclusionPaths_Process(t *testing.T) { {RelativePath: filepath.FromSlash("base/c/b/file.go")}, {RelativePath: filepath.FromSlash("base/d/file.go")}, }, - expected: []result.Issue{ + expected: []*result.Issue{ {RelativePath: filepath.FromSlash("base/c/file.go")}, {RelativePath: filepath.FromSlash("base/c/b/file.go")}, }, diff --git a/pkg/result/processors/exclusion_rules.go b/pkg/result/processors/exclusion_rules.go index 064921ae607a..2b5221a89085 100644 --- a/pkg/result/processors/exclusion_rules.go +++ b/pkg/result/processors/exclusion_rules.go @@ -49,7 +49,7 @@ func (*ExclusionRules) Name() string { return "exclusion_rules" } -func (p *ExclusionRules) Process(issues []result.Issue) ([]result.Issue, error) { +func (p *ExclusionRules) Process(issues []*result.Issue) ([]*result.Issue, error) { if len(p.rules) == 0 { return issues, nil } diff --git a/pkg/result/processors/exclusion_rules_test.go b/pkg/result/processors/exclusion_rules_test.go index 5657f45ed7a3..6f78ee2d2b3e 100644 --- a/pkg/result/processors/exclusion_rules_test.go +++ b/pkg/result/processors/exclusion_rules_test.go @@ -63,7 +63,7 @@ func TestExclusionRules_Process_multiple(t *testing.T) { {Path: filepath.FromSlash("testdata/exclusion_rules/exclusion_rules.go"), Line: 3, Linter: "lll"}, } - var issues []result.Issue + var issues []*result.Issue for _, c := range cases { issues = append(issues, newIssueFromIssueTestCase(c)) } @@ -105,9 +105,9 @@ func TestExclusionRules_Process_text(t *testing.T) { p := NewExclusionRules(nil, lines, cfg) texts := []string{"exclude", "1", "", "exclud", "notexclude"} - var issues []result.Issue + var issues []*result.Issue for _, t := range texts { - issues = append(issues, result.Issue{ + issues = append(issues, &result.Issue{ Text: t, FromLinter: "linter", }) @@ -178,7 +178,7 @@ func TestExclusionRules_Process_caseSensitive_multiple(t *testing.T) { {Path: filepath.FromSlash("testdata/exclusion_rules/case_sensitive.go"), Line: 3, Linter: "lll"}, } - var issues []result.Issue + var issues []*result.Issue for _, c := range cases { issues = append(issues, newIssueFromIssueTestCase(c)) } @@ -225,9 +225,9 @@ func TestExclusionRules_Process_caseSensitive_text(t *testing.T) { texts := []string{"exclude", "excLude", "1", "", "exclud", "notexclude"} - var issues []result.Issue + var issues []*result.Issue for _, t := range texts { - issues = append(issues, result.Issue{ + issues = append(issues, &result.Issue{ Text: t, FromLinter: "linter", }) diff --git a/pkg/result/processors/filename_unadjuster.go b/pkg/result/processors/filename_unadjuster.go index a3cdd8e6ed7c..e39601d5a4a4 100644 --- a/pkg/result/processors/filename_unadjuster.go +++ b/pkg/result/processors/filename_unadjuster.go @@ -66,7 +66,7 @@ func (*FilenameUnadjuster) Name() string { return "filename_unadjuster" } -func (p *FilenameUnadjuster) Process(issues []result.Issue) ([]result.Issue, error) { +func (p *FilenameUnadjuster) Process(issues []*result.Issue) ([]*result.Issue, error) { return transformIssues(issues, func(issue *result.Issue) *result.Issue { mapper := p.m[issue.FilePath()] if mapper == nil { diff --git a/pkg/result/processors/fixer.go b/pkg/result/processors/fixer.go index d2beaa0ebafe..ce33b27fb276 100644 --- a/pkg/result/processors/fixer.go +++ b/pkg/result/processors/fixer.go @@ -56,14 +56,14 @@ func (Fixer) Name() string { return "fixer" } -func (p Fixer) Process(issues []result.Issue) ([]result.Issue, error) { +func (p Fixer) Process(issues []*result.Issue) ([]*result.Issue, error) { if !p.cfg.Issues.NeedFix { return issues, nil } p.log.Infof("Applying suggested fixes") - notFixableIssues, err := timeutils.TrackStage(p.sw, "all", func() ([]result.Issue, error) { + notFixableIssues, err := timeutils.TrackStage(p.sw, "all", func() ([]*result.Issue, error) { return p.process(issues) }) if err != nil { @@ -76,13 +76,13 @@ func (p Fixer) Process(issues []result.Issue) ([]result.Issue, error) { } //nolint:funlen,gocyclo // This function should not be split. -func (p Fixer) process(issues []result.Issue) ([]result.Issue, error) { +func (p Fixer) process(issues []*result.Issue) ([]*result.Issue, error) { // filenames / linters / edits editsByLinter := make(map[string]map[string][]diff.Edit) formatters := []string{gofumpt.Name, goimports.Name, gofmt.Name, gci.Name, golines.Name, swaggo.Name} - var notFixableIssues []result.Issue + var notFixableIssues []*result.Issue toBeFormattedFiles := make(map[string]struct{}) @@ -94,7 +94,7 @@ func (p Fixer) process(issues []result.Issue) ([]result.Issue, error) { continue } - if issue.SuggestedFixes == nil || skipNoTextEdit(&issue) { + if issue.SuggestedFixes == nil || skipNoTextEdit(issue) { notFixableIssues = append(notFixableIssues, issue) continue } diff --git a/pkg/result/processors/invalid_issue.go b/pkg/result/processors/invalid_issue.go index a7f45d408333..fa1b19e82c17 100644 --- a/pkg/result/processors/invalid_issue.go +++ b/pkg/result/processors/invalid_issue.go @@ -24,7 +24,7 @@ func (InvalidIssue) Name() string { return "invalid_issue" } -func (p InvalidIssue) Process(issues []result.Issue) ([]result.Issue, error) { +func (p InvalidIssue) Process(issues []*result.Issue) ([]*result.Issue, error) { tcIssues := filterIssuesUnsafe(issues, func(issue *result.Issue) bool { return issue.FromLinter == typeCheckName }) diff --git a/pkg/result/processors/invalid_issue_test.go b/pkg/result/processors/invalid_issue_test.go index 32628c336d31..c685551a9673 100644 --- a/pkg/result/processors/invalid_issue_test.go +++ b/pkg/result/processors/invalid_issue_test.go @@ -19,21 +19,21 @@ func TestInvalidIssue_Process(t *testing.T) { testCases := []struct { desc string - issues []result.Issue - expected []result.Issue + issues []*result.Issue + expected []*result.Issue }{ { desc: "typecheck", - issues: []result.Issue{ + issues: []*result.Issue{ {FromLinter: "typecheck"}, }, - expected: []result.Issue{ + expected: []*result.Issue{ {FromLinter: "typecheck"}, }, }, { desc: "keep only typecheck issues if any exist", - issues: []result.Issue{ + issues: []*result.Issue{ {FromLinter: "typecheck"}, { FromLinter: "example", @@ -42,13 +42,13 @@ func TestInvalidIssue_Process(t *testing.T) { }, }, }, - expected: []result.Issue{ + expected: []*result.Issue{ {FromLinter: "typecheck"}, }, }, { desc: "Go file", - issues: []result.Issue{ + issues: []*result.Issue{ { FromLinter: "example", Pos: token.Position{ @@ -56,7 +56,7 @@ func TestInvalidIssue_Process(t *testing.T) { }, }, }, - expected: []result.Issue{ + expected: []*result.Issue{ { FromLinter: "example", Pos: token.Position{ @@ -67,7 +67,7 @@ func TestInvalidIssue_Process(t *testing.T) { }, { desc: "go.mod", - issues: []result.Issue{ + issues: []*result.Issue{ { FromLinter: "example", Pos: token.Position{ @@ -75,7 +75,7 @@ func TestInvalidIssue_Process(t *testing.T) { }, }, }, - expected: []result.Issue{ + expected: []*result.Issue{ { FromLinter: "example", Pos: token.Position{ @@ -86,7 +86,7 @@ func TestInvalidIssue_Process(t *testing.T) { }, { desc: "non Go file", - issues: []result.Issue{ + issues: []*result.Issue{ { FromLinter: "example", Pos: token.Position{ @@ -94,11 +94,11 @@ func TestInvalidIssue_Process(t *testing.T) { }, }, }, - expected: []result.Issue{}, + expected: []*result.Issue{}, }, { desc: "no filename", - issues: []result.Issue{ + issues: []*result.Issue{ { FromLinter: "example", Pos: token.Position{ @@ -106,7 +106,7 @@ func TestInvalidIssue_Process(t *testing.T) { }, }, }, - expected: []result.Issue{}, + expected: []*result.Issue{}, }, } diff --git a/pkg/result/processors/issues.go b/pkg/result/processors/issues.go index 1e76291c77a1..cc4deeb5267e 100644 --- a/pkg/result/processors/issues.go +++ b/pkg/result/processors/issues.go @@ -6,62 +6,62 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/result" ) -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 issues[i].FromLinter == typeCheckName { +func filterIssues(issues []*result.Issue, filter func(issue *result.Issue) bool) []*result.Issue { + retIssues := make([]*result.Issue, 0, len(issues)) + for _, issue := range issues { + if issue.FromLinter == typeCheckName { // don't hide typechecking errors in generated files: users expect to see why the project isn't compiling - retIssues = append(retIssues, issues[i]) + retIssues = append(retIssues, issue) continue } - if filter(&issues[i]) { - retIssues = append(retIssues, issues[i]) + if filter(issue) { + retIssues = append(retIssues, issue) } } return retIssues } -func filterIssuesUnsafe(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]) { - retIssues = append(retIssues, issues[i]) +func filterIssuesUnsafe(issues []*result.Issue, filter func(issue *result.Issue) bool) []*result.Issue { + retIssues := make([]*result.Issue, 0, len(issues)) + for _, issue := range issues { + if filter(issue) { + retIssues = append(retIssues, issue) } } return retIssues } -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 { - if issues[i].FromLinter == typeCheckName { +func filterIssuesErr(issues []*result.Issue, filter func(issue *result.Issue) (bool, error)) ([]*result.Issue, error) { + retIssues := make([]*result.Issue, 0, len(issues)) + for _, issue := range issues { + if issue.FromLinter == typeCheckName { // don't hide typechecking errors in generated files: users expect to see why the project isn't compiling - retIssues = append(retIssues, issues[i]) + retIssues = append(retIssues, issue) continue } - ok, err := filter(&issues[i]) + ok, err := filter(issue) if err != nil { - return nil, fmt.Errorf("can't filter issue %#v: %w", issues[i], err) + return nil, fmt.Errorf("can't filter issue %#v: %w", issue, err) } if ok { - retIssues = append(retIssues, issues[i]) + retIssues = append(retIssues, issue) } } return retIssues, nil } -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 { - newIssue := transform(&issues[i]) +func transformIssues(issues []*result.Issue, transform func(issue *result.Issue) *result.Issue) []*result.Issue { + retIssues := make([]*result.Issue, 0, len(issues)) + for _, issue := range issues { + newIssue := transform(issue) if newIssue != nil { - retIssues = append(retIssues, *newIssue) + retIssues = append(retIssues, newIssue) } } diff --git a/pkg/result/processors/max_from_linter.go b/pkg/result/processors/max_from_linter.go index dec9f3e7f13a..bc7572f2ccaf 100644 --- a/pkg/result/processors/max_from_linter.go +++ b/pkg/result/processors/max_from_linter.go @@ -29,7 +29,7 @@ func (*MaxFromLinter) Name() string { return "max_from_linter" } -func (p *MaxFromLinter) Process(issues []result.Issue) ([]result.Issue, error) { +func (p *MaxFromLinter) Process(issues []*result.Issue) ([]*result.Issue, error) { if p.limit <= 0 { // no limit return issues, nil } diff --git a/pkg/result/processors/max_per_file_from_linter.go b/pkg/result/processors/max_per_file_from_linter.go index 2608c22e22ab..b04b92ea7a7f 100644 --- a/pkg/result/processors/max_per_file_from_linter.go +++ b/pkg/result/processors/max_per_file_from_linter.go @@ -40,7 +40,7 @@ func (*MaxPerFileFromLinter) Name() string { return "max_per_file_from_linter" } -func (p *MaxPerFileFromLinter) Process(issues []result.Issue) ([]result.Issue, error) { +func (p *MaxPerFileFromLinter) Process(issues []*result.Issue) ([]*result.Issue, error) { return filterIssuesUnsafe(issues, func(issue *result.Issue) bool { limit := p.maxPerFileFromLinterConfig[issue.FromLinter] if limit == 0 { diff --git a/pkg/result/processors/max_per_file_from_linter_test.go b/pkg/result/processors/max_per_file_from_linter_test.go index c5bc7ebc1e8b..a886b47c75f0 100644 --- a/pkg/result/processors/max_per_file_from_linter_test.go +++ b/pkg/result/processors/max_per_file_from_linter_test.go @@ -7,8 +7,8 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/result" ) -func newFromLinterIssue(linterName string) result.Issue { - return result.Issue{ +func newFromLinterIssue(linterName string) *result.Issue { + return &result.Issue{ FromLinter: linterName, } } diff --git a/pkg/result/processors/max_same_issues.go b/pkg/result/processors/max_same_issues.go index 06e87586e171..ba22cf31fb62 100644 --- a/pkg/result/processors/max_same_issues.go +++ b/pkg/result/processors/max_same_issues.go @@ -31,7 +31,7 @@ func (*MaxSameIssues) Name() string { return "max_same_issues" } -func (p *MaxSameIssues) Process(issues []result.Issue) ([]result.Issue, error) { +func (p *MaxSameIssues) Process(issues []*result.Issue) ([]*result.Issue, error) { if p.limit <= 0 { // no limit return issues, nil } diff --git a/pkg/result/processors/max_same_issues_test.go b/pkg/result/processors/max_same_issues_test.go index 574059ebbb41..8eb7de0e39a8 100644 --- a/pkg/result/processors/max_same_issues_test.go +++ b/pkg/result/processors/max_same_issues_test.go @@ -10,10 +10,10 @@ import ( func TestMaxSameIssues(t *testing.T) { p := NewMaxSameIssues(1, logutils.NewStderrLog(logutils.DebugKeyEmpty), &config.Config{}) - i1 := result.Issue{ + i1 := &result.Issue{ Text: "1", } - i2 := result.Issue{ + i2 := &result.Issue{ Text: "2", } diff --git a/pkg/result/processors/nolint_filter.go b/pkg/result/processors/nolint_filter.go index e17fd7ad2521..bd2a09abea43 100644 --- a/pkg/result/processors/nolint_filter.go +++ b/pkg/result/processors/nolint_filter.go @@ -91,7 +91,7 @@ func (*NolintFilter) Name() string { return "nolint_filter" } -func (p *NolintFilter) Process(issues []result.Issue) ([]result.Issue, error) { +func (p *NolintFilter) Process(issues []*result.Issue) ([]*result.Issue, error) { // put nolintlint issues last because we process other issues first to determine which nolint directives are unused sort.Stable(sortWithNolintlintLast(issues)) return filterIssuesErr(issues, p.shouldPassIssue) @@ -299,7 +299,7 @@ func (e *rangeExpander) Visit(node ast.Node) ast.Visitor { } // put nolintlint last -type sortWithNolintlintLast []result.Issue +type sortWithNolintlintLast []*result.Issue func (issues sortWithNolintlintLast) Len() int { return len(issues) diff --git a/pkg/result/processors/nolint_filter_test.go b/pkg/result/processors/nolint_filter_test.go index 79dc6c1ce4bb..c620875aba98 100644 --- a/pkg/result/processors/nolint_filter_test.go +++ b/pkg/result/processors/nolint_filter_test.go @@ -16,8 +16,8 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/result" ) -func newNolintFileIssue(line int, fromLinter string) result.Issue { - return result.Issue{ +func newNolintFileIssue(line int, fromLinter string) *result.Issue { + return &result.Issue{ Pos: token.Position{ Filename: filepath.FromSlash("testdata/nolint_filter/nolint.go"), Line: line, @@ -26,7 +26,7 @@ func newNolintFileIssue(line int, fromLinter string) result.Issue { } } -func newNolint2FileIssue(line int) result.Issue { +func newNolint2FileIssue(line int) *result.Issue { i := newNolintFileIssue(line, "errcheck") i.Pos.Filename = filepath.FromSlash("testdata/nolint_filter/nolint2.go") return i @@ -126,7 +126,7 @@ func TestTestNolintFilter_Process(t *testing.T) { func TestNolintFilter_Process_invalidLinterName(t *testing.T) { fileName := filepath.FromSlash("testdata/nolint_filter/bad_names.go") - issues := []result.Issue{ + issues := []*result.Issue{ { Pos: token.Position{ Filename: fileName, @@ -161,7 +161,7 @@ func TestNolintFilter_Process_invalidLinterName(t *testing.T) { func TestNolintFilter_Process_invalidLinterNameWithViolationOnTheSameLine(t *testing.T) { log := getMockLog() log.On("Warnf", "Found unknown linters in //nolint directives: %s", "foobar") - issues := []result.Issue{ + issues := []*result.Issue{ { Pos: token.Position{ Filename: filepath.FromSlash("testdata/nolint_filter/apply_to_unknown.go"), @@ -246,14 +246,14 @@ func TestNolintFilter_Process_wholeFile(t *testing.T) { p := newTestNolintFilter(getMockLog()) defer p.Finish() - processAssertEmpty(t, p, result.Issue{ + processAssertEmpty(t, p, &result.Issue{ Pos: token.Position{ Filename: fileName, Line: 9, }, FromLinter: "errcheck", }) - processAssertSame(t, p, result.Issue{ + processAssertSame(t, p, &result.Issue{ Pos: token.Position{ Filename: fileName, Line: 14, @@ -284,7 +284,7 @@ func TestNolintFilter_Process_unused(t *testing.T) { } // the issue below is the nolintlint issue that would be generated for the test file - nolintlintIssueMisspell := result.Issue{ + nolintlintIssueMisspell := &result.Issue{ Pos: token.Position{ Filename: fileName, Line: 3, @@ -295,7 +295,7 @@ func TestNolintFilter_Process_unused(t *testing.T) { } // the issue below is another nolintlint issue that would be generated for the test file - nolintlintIssueMisspellUnusedOK := result.Issue{ + nolintlintIssueMisspellUnusedOK := &result.Issue{ Pos: token.Position{ Filename: fileName, Line: 5, @@ -323,7 +323,7 @@ func TestNolintFilter_Process_unused(t *testing.T) { p := createProcessor(t, log, []string{"misspell", "nolintlint"}) defer p.Finish() - processAssertEmpty(t, p, []result.Issue{{ + processAssertEmpty(t, p, []*result.Issue{{ Pos: token.Position{ Filename: fileName, Line: 3, diff --git a/pkg/result/processors/path_absoluter.go b/pkg/result/processors/path_absoluter.go index 99f3de42a2cd..240cedf8eaf4 100644 --- a/pkg/result/processors/path_absoluter.go +++ b/pkg/result/processors/path_absoluter.go @@ -22,7 +22,7 @@ func (*PathAbsoluter) Name() string { return "path_absoluter" } -func (p *PathAbsoluter) Process(issues []result.Issue) ([]result.Issue, error) { +func (p *PathAbsoluter) Process(issues []*result.Issue) ([]*result.Issue, error) { return transformIssues(issues, func(issue *result.Issue) *result.Issue { if filepath.IsAbs(issue.FilePath()) { return issue diff --git a/pkg/result/processors/path_prettifier.go b/pkg/result/processors/path_prettifier.go index cb6ef8ebc27d..94dfbab370ab 100644 --- a/pkg/result/processors/path_prettifier.go +++ b/pkg/result/processors/path_prettifier.go @@ -30,7 +30,7 @@ func (*PathPrettifier) Name() string { return "path_prettifier" } -func (p *PathPrettifier) Process(issues []result.Issue) ([]result.Issue, error) { +func (p *PathPrettifier) Process(issues []*result.Issue) ([]*result.Issue, error) { if p.cfg.PathMode == fsutils.OutputPathModeAbsolute { return issues, nil } diff --git a/pkg/result/processors/path_prettifier_test.go b/pkg/result/processors/path_prettifier_test.go index 824509712ef7..2f403d46a327 100644 --- a/pkg/result/processors/path_prettifier_test.go +++ b/pkg/result/processors/path_prettifier_test.go @@ -13,15 +13,15 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/result" ) -func newPPIssue(fn, rp string) result.Issue { - return result.Issue{ +func newPPIssue(fn, rp string) *result.Issue { + return &result.Issue{ Pos: token.Position{Filename: filepath.FromSlash(fn)}, RelativePath: filepath.FromSlash(rp), } } func TestPathPrettifier_Process(t *testing.T) { - paths := func(ps ...string) (issues []result.Issue) { + paths := func(ps ...string) (issues []*result.Issue) { for _, p := range ps { issues = append(issues, newPPIssue("test", p)) } @@ -30,12 +30,12 @@ func TestPathPrettifier_Process(t *testing.T) { for _, tt := range []struct { name, prefix string - issues, want []result.Issue + issues, want []*result.Issue }{ { name: "empty prefix", issues: paths("some/path", "cool"), - want: []result.Issue{ + want: []*result.Issue{ newPPIssue("some/path", "some/path"), newPPIssue("cool", "cool"), }, @@ -44,7 +44,7 @@ func TestPathPrettifier_Process(t *testing.T) { name: "prefix", prefix: "ok", issues: paths("some/path", "cool"), - want: []result.Issue{ + want: []*result.Issue{ newPPIssue("ok/some/path", "some/path"), newPPIssue("ok/cool", "cool"), }, @@ -53,7 +53,7 @@ func TestPathPrettifier_Process(t *testing.T) { name: "prefix slashed", prefix: "ok/", issues: paths("some/path", "cool"), - want: []result.Issue{ + want: []*result.Issue{ newPPIssue("ok/some/path", "some/path"), newPPIssue("ok/cool", "cool"), }, diff --git a/pkg/result/processors/path_relativity.go b/pkg/result/processors/path_relativity.go index 8b2958a4a308..c68662c7bb1f 100644 --- a/pkg/result/processors/path_relativity.go +++ b/pkg/result/processors/path_relativity.go @@ -36,7 +36,7 @@ func (*PathRelativity) Name() string { return "path_relativity" } -func (p *PathRelativity) Process(issues []result.Issue) ([]result.Issue, error) { +func (p *PathRelativity) Process(issues []*result.Issue) ([]*result.Issue, error) { return transformIssues(issues, func(issue *result.Issue) *result.Issue { newIssue := *issue diff --git a/pkg/result/processors/path_shortener.go b/pkg/result/processors/path_shortener.go index 7a14c39c972e..23df4f02cc20 100644 --- a/pkg/result/processors/path_shortener.go +++ b/pkg/result/processors/path_shortener.go @@ -29,7 +29,7 @@ func (PathShortener) Name() string { return "path_shortener" } -func (p PathShortener) Process(issues []result.Issue) ([]result.Issue, error) { +func (p PathShortener) Process(issues []*result.Issue) ([]*result.Issue, error) { return transformIssues(issues, func(issue *result.Issue) *result.Issue { newIssue := issue newIssue.Text = strings.ReplaceAll(newIssue.Text, p.wd+"/", "") diff --git a/pkg/result/processors/processor.go b/pkg/result/processors/processor.go index 1976d6e44ad9..f5603c94dc75 100644 --- a/pkg/result/processors/processor.go +++ b/pkg/result/processors/processor.go @@ -7,7 +7,7 @@ import ( const typeCheckName = "typecheck" type Processor interface { - Process(issues []result.Issue) ([]result.Issue, error) + Process(issues []*result.Issue) ([]*result.Issue, error) Name() string Finish() } diff --git a/pkg/result/processors/processor_test.go b/pkg/result/processors/processor_test.go index 41bb78a7b3ae..95fdb5f81445 100644 --- a/pkg/result/processors/processor_test.go +++ b/pkg/result/processors/processor_test.go @@ -18,8 +18,8 @@ type issueTestCase struct { Severity string } -func newIssueFromIssueTestCase(c issueTestCase) result.Issue { - return result.Issue{ +func newIssueFromIssueTestCase(c issueTestCase) *result.Issue { + return &result.Issue{ Text: c.Text, FromLinter: c.Linter, Severity: c.Severity, @@ -31,13 +31,13 @@ func newIssueFromIssueTestCase(c issueTestCase) result.Issue { } } -func newIssueFromTextTestCase(text string) result.Issue { - return result.Issue{ +func newIssueFromTextTestCase(text string) *result.Issue { + return &result.Issue{ Text: text, } } -func process(t *testing.T, p Processor, issues ...result.Issue) []result.Issue { +func process(t *testing.T, p Processor, issues ...*result.Issue) []*result.Issue { t.Helper() processedIssues, err := p.Process(issues) @@ -45,14 +45,14 @@ func process(t *testing.T, p Processor, issues ...result.Issue) []result.Issue { return processedIssues } -func processAssertSame(t *testing.T, p Processor, issues ...result.Issue) { +func processAssertSame(t *testing.T, p Processor, issues ...*result.Issue) { t.Helper() processedIssues := process(t, p, issues...) assert.Equal(t, issues, processedIssues) } -func processAssertEmpty(t *testing.T, p Processor, issues ...result.Issue) { +func processAssertEmpty(t *testing.T, p Processor, issues ...*result.Issue) { t.Helper() processedIssues := process(t, p, issues...) diff --git a/pkg/result/processors/severity.go b/pkg/result/processors/severity.go index 035ca80c4e1d..33c3997f8889 100644 --- a/pkg/result/processors/severity.go +++ b/pkg/result/processors/severity.go @@ -43,7 +43,7 @@ func NewSeverity(log logutils.Log, lines *fsutils.LineCache, cfg *config.Severit func (p *Severity) Name() string { return p.name } -func (p *Severity) Process(issues []result.Issue) ([]result.Issue, error) { +func (p *Severity) Process(issues []*result.Issue) ([]*result.Issue, error) { if len(p.rules) == 0 && p.defaultSeverity == "" { return issues, nil } diff --git a/pkg/result/processors/severity_test.go b/pkg/result/processors/severity_test.go index 0774f0b1d517..a5c50d0011cc 100644 --- a/pkg/result/processors/severity_test.go +++ b/pkg/result/processors/severity_test.go @@ -92,7 +92,7 @@ func TestSeverity_multiple(t *testing.T) { {Path: "empty.go", Text: "empty", Linter: "empty"}, } - var issues []result.Issue + var issues []*result.Issue for _, c := range cases { issues = append(issues, newIssueFromIssueTestCase(c)) } @@ -141,9 +141,9 @@ func TestSeverity_text(t *testing.T) { p := NewSeverity(nil, nil, opts) texts := []string{"seveRity", "1", "", "serverit", "notseverity"} - var issues []result.Issue + var issues []*result.Issue for _, t := range texts { - issues = append(issues, result.Issue{ + issues = append(issues, &result.Issue{ Text: t, FromLinter: "linter", }) @@ -176,7 +176,7 @@ func TestSeverity_onlyDefault(t *testing.T) { {Path: "empty.go", Text: "empty", Linter: "empty"}, } - var issues []result.Issue + var issues []*result.Issue for _, c := range cases { issues = append(issues, newIssueFromIssueTestCase(c)) } @@ -230,7 +230,7 @@ func TestSeverity_caseSensitive(t *testing.T) { {Path: "e.go", Text: "ssL", Linter: "gosec"}, } - var issues []result.Issue + var issues []*result.Issue for _, c := range cases { issues = append(issues, newIssueFromIssueTestCase(c)) } diff --git a/pkg/result/processors/sort_results.go b/pkg/result/processors/sort_results.go index 033eca9a4374..8ba06bccfd10 100644 --- a/pkg/result/processors/sort_results.go +++ b/pkg/result/processors/sort_results.go @@ -54,7 +54,7 @@ func NewSortResults(cfg *config.Output) *SortResults { func (SortResults) Name() string { return "sort_results" } // Process is performing sorting of the result issues. -func (p SortResults) Process(issues []result.Issue) ([]result.Issue, error) { +func (p SortResults) Process(issues []*result.Issue) ([]*result.Issue, error) { if len(p.cfg.SortOrder) == 0 { p.cfg.SortOrder = []string{orderNameLinter, orderNameFile} } @@ -72,8 +72,8 @@ func (p SortResults) Process(issues []result.Issue) ([]result.Issue, error) { comp := mergeComparators(cmps...) - slices.SortFunc(issues, func(a, b result.Issue) int { - return comp(&a, &b) + slices.SortFunc(issues, func(a, b *result.Issue) int { + return comp(a, b) }) return issues, nil diff --git a/pkg/result/processors/sort_results_test.go b/pkg/result/processors/sort_results_test.go index fcfd824c8eb1..dc097cc967de 100644 --- a/pkg/result/processors/sort_results_test.go +++ b/pkg/result/processors/sort_results_test.go @@ -12,7 +12,7 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/result" ) -var issues = []result.Issue{ +var issues = []*result.Issue{ { FromLinter: "b", Severity: "medium", @@ -50,7 +50,7 @@ var issues = []result.Issue{ }, } -var extraSeverityIssues = []result.Issue{ +var extraSeverityIssues = []*result.Issue{ { FromLinter: "c", Severity: "error", @@ -72,16 +72,16 @@ var extraSeverityIssues = []result.Issue{ } type compareTestCase struct { - a, b result.Issue + a, b *result.Issue expected int } func testCompareValues(t *testing.T, cmp issueComparator, name string, tests []compareTestCase) { - for i, test := range tests { //nolint:gocritic // To ignore rangeValCopy rule + for i, test := range tests { t.Run(fmt.Sprintf("%s(%d)", name, i), func(t *testing.T) { t.Parallel() - res := cmp(&test.a, &test.b) + res := cmp(test.a, test.b) assert.Equal(t, compToString(test.expected), compToString(res)) }) @@ -210,7 +210,7 @@ func Test_numericCompare(t *testing.T) { } func TestSortResults_Process(t *testing.T) { - tests := make([]result.Issue, len(issues)) + tests := make([]*result.Issue, len(issues)) copy(tests, issues) cfg := &config.Output{} @@ -219,7 +219,7 @@ func TestSortResults_Process(t *testing.T) { results, err := sr.Process(tests) require.NoError(t, err) - assert.Equal(t, []result.Issue{issues[1], issues[0], issues[3], issues[2]}, results) + assert.Equal(t, []*result.Issue{issues[1], issues[0], issues[3], issues[2]}, results) } func compToString(c int) string { diff --git a/pkg/result/processors/source_code.go b/pkg/result/processors/source_code.go index 1096269c8176..d4e82643c0d9 100644 --- a/pkg/result/processors/source_code.go +++ b/pkg/result/processors/source_code.go @@ -31,7 +31,7 @@ func (SourceCode) Name() string { return "source_code" } -func (p SourceCode) Process(issues []result.Issue) ([]result.Issue, error) { +func (p SourceCode) Process(issues []*result.Issue) ([]*result.Issue, error) { return transformIssues(issues, p.transform), nil } diff --git a/pkg/result/processors/uniq_by_line.go b/pkg/result/processors/uniq_by_line.go index 113b5814ad16..953496355b09 100644 --- a/pkg/result/processors/uniq_by_line.go +++ b/pkg/result/processors/uniq_by_line.go @@ -25,7 +25,7 @@ func (*UniqByLine) Name() string { return "uniq_by_line" } -func (p *UniqByLine) Process(issues []result.Issue) ([]result.Issue, error) { +func (p *UniqByLine) Process(issues []*result.Issue) ([]*result.Issue, error) { if !p.enabled { return issues, nil } diff --git a/pkg/result/processors/uniq_by_line_test.go b/pkg/result/processors/uniq_by_line_test.go index dadca6a9afa1..d623c2e62569 100644 --- a/pkg/result/processors/uniq_by_line_test.go +++ b/pkg/result/processors/uniq_by_line_test.go @@ -7,8 +7,8 @@ import ( "github.com/golangci/golangci-lint/v2/pkg/result" ) -func newULIssue(file string, line int) result.Issue { - return result.Issue{ +func newULIssue(file string, line int) *result.Issue { + return &result.Issue{ Pos: token.Position{ Filename: file, Line: line, diff --git a/scripts/website/expand_templates/thanks_test.go b/scripts/website/expand_templates/thanks_test.go index 6af152336e99..7caa7e28c49f 100644 --- a/scripts/website/expand_templates/thanks_test.go +++ b/scripts/website/expand_templates/thanks_test.go @@ -14,7 +14,7 @@ type FakeLinter struct { name string } -func (*FakeLinter) Run(_ context.Context, _ *linter.Context) ([]result.Issue, error) { +func (*FakeLinter) Run(_ context.Context, _ *linter.Context) ([]*result.Issue, error) { return nil, nil } From 6cd10a9c28ba3deb731901b5b5293263ff5ff650 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Mon, 2 Jun 2025 21:54:51 +0200 Subject: [PATCH 150/152] dev: handle linter major versions (#5848) --- pkg/goanalysis/linter.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/pkg/goanalysis/linter.go b/pkg/goanalysis/linter.go index 29bd841a85c6..153e538b5820 100644 --- a/pkg/goanalysis/linter.go +++ b/pkg/goanalysis/linter.go @@ -76,6 +76,25 @@ func (lnt *Linter) WithDesc(desc string) *Linter { return lnt } +func (lnt *Linter) WithVersion(v int) *Linter { + if v == 0 { + return lnt + } + + for _, analyzer := range lnt.analyzers { + if lnt.name != analyzer.Name { + continue + } + + // The analyzer name should be the same as the linter name to avoid displaying the name inside the reports. + analyzer.Name = fmt.Sprintf("%s_v%d", analyzer.Name, v) + } + + lnt.name = fmt.Sprintf("%s_v%d", lnt.name, v) + + return lnt +} + func (lnt *Linter) WithConfig(cfg map[string]any) *Linter { if len(cfg) == 0 { return lnt From 75b18f9695e8c882d3a6401d84dfae5239407604 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Wed, 4 Jun 2025 11:37:56 +0200 Subject: [PATCH 151/152] feat: deprecate print-resources-usage flag (#5860) --- pkg/commands/run.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/commands/run.go b/pkg/commands/run.go index 4e2d3b1b984a..1864559f9fc3 100644 --- a/pkg/commands/run.go +++ b/pkg/commands/run.go @@ -584,6 +584,7 @@ func setupConfigFileFlagSet(fs *pflag.FlagSet, cfg *config.LoaderOptions) { 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.MarkDeprecated("print-resources-usage", "use --verbose instead") 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")) From a25cd63879d2252bcee283c5aca0c737ff6ff801 Mon Sep 17 00:00:00 2001 From: Oleksandr Redko Date: Wed, 4 Jun 2025 13:29:30 +0300 Subject: [PATCH 152/152] docs: add a note about `GL_DEBUG=staticcheck` (#5861) --- .golangci.next.reference.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index abc9c060efbe..96559b4ec4e1 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -2850,6 +2850,7 @@ linters: http-status-code-whitelist: [ "200", "400", "404", "500" ] # SAxxxx checks in https://staticcheck.dev/docs/configuration/options/#checks # Example (to disable some checks): [ "all", "-SA1000", "-SA1001"] + # Run `GL_DEBUG=staticcheck golangci-lint run --enable=staticcheck` to see all available checks and enabled by config checks. # Default: ["all", "-ST1000", "-ST1003", "-ST1016", "-ST1020", "-ST1021", "-ST1022"] checks: # Invalid regular expression.