Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: golangci/golangci-lint
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.54.2
Choose a base ref
...
head repository: golangci/golangci-lint
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v1.55.0
Choose a head ref

Commits on Aug 21, 2023

  1. docs: Update documentation and assets (#4035)

    Co-authored-by: Fernandez Ludovic <ldez@users.noreply.github.com>
    golangci-releaser and ldez authored Aug 21, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    a73cda1 View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    75b6a08 View commit details

Commits on Aug 27, 2023

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    f4b0ca7 View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    663d002 View commit details
  3. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    5b40213 View commit details

Commits on Aug 29, 2023

  1. docs: fix a typo (#4048)

    alexandear authored Aug 29, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    547bca2 View commit details

Commits on Aug 31, 2023

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    4b72aa5 View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    a69976a View commit details

Commits on Sep 2, 2023

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    2858394 View commit details

Commits on Sep 4, 2023

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    c65ab4b View commit details

Commits on Sep 6, 2023

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    f18d712 View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    28d88a1 View commit details
  3. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    cc02271 View commit details

Commits on Sep 7, 2023

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    865b93a View commit details
  2. build(deps): bump github.com/ryanrolds/sqlclosecheck from 0.4.0 to 0.…

    …5.1 (#4071)
    
    Co-authored-by: Fernandez Ludovic <ldez@users.noreply.github.com>
    dependabot[bot] and ldez authored Sep 7, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    b673fb7 View commit details

Commits on Sep 9, 2023

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    3c34799 View commit details

Commits on Sep 10, 2023

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    22c6434 View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    452410c View commit details

Commits on Sep 11, 2023

  1. build(deps): bump golang.org/x/oauth2 from 0.11.0 to 0.12.0 in /scrip…

    …ts/gen_github_action_config (#4079)
    dependabot[bot] authored Sep 11, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    efb52af View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    fd06dca View commit details

Commits on Sep 13, 2023

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    41bfce9 View commit details

Commits on Sep 18, 2023

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    615a52b View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    0704271 View commit details
  3. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    b974c30 View commit details
  4. build(deps): bump github.com/mgechev/revive from 1.3.3 to 1.3.4 (#4087)

    Co-authored-by: Fernandez Ludovic <ldez@users.noreply.github.com>
    dependabot[bot] and ldez authored Sep 18, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    eeb2088 View commit details
  5. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    b74ffbb View commit details
  6. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    47d7785 View commit details
  7. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    ea3dbf1 View commit details

Commits on Sep 24, 2023

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    c6eae6c View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    c9956e8 View commit details

Commits on Sep 25, 2023

  1. build(deps): bump github.com/Abirdcfly/dupword from 0.0.12 to 0.0.13 (#…

    …4104)
    
    Co-authored-by: Fernandez Ludovic <ldez@users.noreply.github.com>
    Abirdcfly and ldez authored Sep 25, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    95edd30 View commit details

Commits on Sep 27, 2023

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    88a40c6 View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    dafe146 View commit details

Commits on Oct 3, 2023

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    1af49e3 View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    e641317 View commit details

Commits on Oct 5, 2023

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    be034aa View commit details

Commits on Oct 6, 2023

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    fe268f4 View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    6dbe5c5 View commit details

Commits on Oct 7, 2023

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    3d8ae00 View commit details

Commits on Oct 8, 2023

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    dd58dd5 View commit details

Commits on Oct 9, 2023

  1. build(deps): bump github.com/nunnatsa/ginkgolinter from 0.13.5 to 0.1…

    …4.0 (#4117)
    
    Co-authored-by: Fernandez Ludovic <ldez@users.noreply.github.com>
    dependabot[bot] and ldez authored Oct 9, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    0e82ef5 View commit details
  2. build(deps): bump github.com/securego/gosec/v2 from 2.17.0 to 2.18.0 (#…

    …4120)
    
    Co-authored-by: Fernandez Ludovic <ldez@users.noreply.github.com>
    dependabot[bot] and ldez authored Oct 9, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    823f02d View commit details
  3. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    2d5d29f View commit details
  4. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    8c178d3 View commit details
  5. feat: add gochecksumtype linter (#3671)

    Co-authored-by: Fernandez Ludovic <ldez@users.noreply.github.com>
    alecthomas and ldez authored Oct 9, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    69d6cc9 View commit details
  6. unused: support passing in options (#4086)

    Co-authored-by: Fernandez Ludovic <ldez@users.noreply.github.com>
    fatanugraha and ldez authored Oct 9, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    bce3dfd View commit details
  7. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    2b73b3a View commit details

Commits on Oct 11, 2023

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    4b83e50 View commit details

Commits on Oct 12, 2023

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    6cd1bfd View commit details
  2. govet: add appends analyzer (#4127)

    Co-authored-by: Fernandez Ludovic <ldez@users.noreply.github.com>
    Antonboom and ldez authored Oct 12, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    6491317 View commit details
Showing with 2,159 additions and 524 deletions.
  1. +1 −1 .github/contributors/generate.ts
  2. +172 −29 .github/peril/package-lock.json
  3. +1 −1 .github/workflows/codeql.yaml
  4. +1 −1 .github/workflows/documentation.yml
  5. +1 −1 .github/workflows/post-release.yml
  6. +1 −1 .github/workflows/pr-extra.yml
  7. +8 −10 .github/workflows/pr.yml
  8. +6 −6 .github/workflows/tag.yml
  9. +141 −10 .golangci.reference.yml
  10. +1 −8 .golangci.yml
  11. +9 −1 .pre-commit-hooks.yaml
  12. +14 −0 CHANGELOG.md
  13. +94 −92 README.md
  14. +4 −4 assets/github-action-config.json
  15. +161 −147 docs/package-lock.json
  16. +1 −1 docs/package.json
  17. +10 −0 docs/src/docs/usage/false-positives.mdx
  18. +34 −28 go.mod
  19. +76 −61 go.sum
  20. +2 −2 pkg/commands/root.go
  21. +1 −1 pkg/config/issues.go
  22. +57 −7 pkg/config/linters_settings.go
  23. +1 −0 pkg/golinters/dupword.go
  24. +8 −7 pkg/golinters/ginkgolinter.go
  25. +80 −0 pkg/golinters/gochecksumtype.go
  26. +2 −7 pkg/golinters/gocritic_test.go
  27. +3 −2 pkg/golinters/gofmt_test.go
  28. +5 −1 pkg/golinters/govet.go
  29. +19 −0 pkg/golinters/inamedparam.go
  30. +19 −0 pkg/golinters/perfsprint.go
  31. +59 −0 pkg/golinters/protogetter.go
  32. +6 −2 pkg/golinters/revive.go
  33. +27 −0 pkg/golinters/sloglint.go
  34. +36 −0 pkg/golinters/testifylint.go
  35. +37 −19 pkg/golinters/unused.go
  36. +43 −6 pkg/lint/lintersdb/manager.go
  37. +1 −1 pkg/logutils/logutils.go
  38. +2 −1 pkg/result/processors/autogenerated_exclude_test.go
  39. +2 −1 pkg/result/processors/identifier_marker_test.go
  40. +4 −4 pkg/result/processors/nolint_test.go
  41. +1 −1 pkg/result/processors/path_prefixer_test.go
  42. +2 −1 pkg/result/processors/processor_test.go
  43. +2 −1 pkg/result/processors/skip_files_test.go
  44. +4 −9 pkg/result/processors/sort_results_test.go
  45. +2 −2 scripts/gen_github_action_config/go.mod
  46. +4 −4 scripts/gen_github_action_config/go.sum
  47. +1 −0 test/linters_test.go
  48. +2 −1 test/ruleguard/dup.go
  49. +2 −1 test/ruleguard/rangeExprCopy.go
  50. +2 −1 test/ruleguard/strings_simplify.go
  51. +3 −3 test/run_test.go
  52. +4 −0 test/testdata/configs/dupword_ignore_the.yml
  53. +3 −0 test/testdata/configs/sloglint_args_on_sep_lines.yml
  54. +3 −0 test/testdata/configs/sloglint_attr_only.yml
  55. +3 −0 test/testdata/configs/sloglint_kv_only.yml
  56. +3 −0 test/testdata/configs/sloglint_no_raw_keys.yml
  57. +16 −0 test/testdata/dupword_ignore_the.go
  58. +1 −1 test/testdata/forbidigo_example.go
  59. +1 −1 test/testdata/gochecknoglobals.go
  60. +38 −0 test/testdata/gochecksumtype.go
  61. +29 −0 test/testdata/inamedparam.go
  62. +8 −8 test/testdata/nonamedreturns_custom.go
  63. +49 −0 test/testdata/perfsprint.go
  64. +16 −0 test/testdata/protogetter/go.mod
  65. +20 −0 test/testdata/protogetter/go.sum
  66. +23 −0 test/testdata/protogetter/proto/test.go
  67. +315 −0 test/testdata/protogetter/proto/test.pb.go
  68. +26 −0 test/testdata/protogetter/proto/test.proto
  69. +109 −0 test/testdata/protogetter/proto/test_grpc.pb.go
  70. +151 −0 test/testdata/protogetter/protogetter.go
  71. +13 −0 test/testdata/sloglint.go
  72. +17 −0 test/testdata/sloglint_args_on_sep_lines.go
  73. +13 −0 test/testdata/sloglint_attr_only.go
  74. +13 −0 test/testdata/sloglint_kv_only.go
  75. +21 −0 test/testdata/sloglint_no_raw_keys.go
  76. +3 −3 test/testdata/sqlclosecheck.go
  77. +62 −0 test/testdata/testifylint.go
  78. +8 −8 test/testshared/directives_test.go
  79. +1 −1 test/testshared/runner.go
  80. +5 −5 tools/go.mod
  81. +10 −10 tools/go.sum
2 changes: 1 addition & 1 deletion .github/contributors/generate.ts
Original file line number Diff line number Diff line change
@@ -124,7 +124,7 @@ const main = async () => {
fossabot: true,
golangcibot: true,
kortschak: true,
"golanci-releaser": true,
"golangci-releaser": true,
}

const res: DataJSON = {
201 changes: 172 additions & 29 deletions .github/peril/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .github/workflows/codeql.yaml
Original file line number Diff line number Diff line change
@@ -33,7 +33,7 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
2 changes: 1 addition & 1 deletion .github/workflows/documentation.yml
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@ jobs:

steps:
- name: Check out code
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0

2 changes: 1 addition & 1 deletion .github/workflows/post-release.yml
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GOLANGCI_LINT_TOKEN }}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v4
with:
2 changes: 1 addition & 1 deletion .github/workflows/pr-extra.yml
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ jobs:
name: Vulnerability scanner
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: actions/setup-go@v4
with:
# https://github.com/actions/setup-go#supported-version-syntax
18 changes: 8 additions & 10 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
@@ -22,7 +22,7 @@ jobs:
# - 1.18rc1 -> 1.18.0-rc.1
go-version: ${{ env.GO_VERSION }}
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Check go mod
run: |
go mod tidy
@@ -33,19 +33,17 @@ jobs:
golangci-lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v4
with:
# https://github.com/actions/setup-go#supported-version-syntax
# ex:
# - 1.18beta1 -> 1.18.0-beta.1
# - 1.18rc1 -> 1.18.0-rc.1
# TODO(ldez) must be changed after the first release of golangci-lint with go1.21
# go-version: ${{ env.GO_VERSION }}
go-version: '1.20'
go-version: ${{ env.GO_VERSION }}
- name: lint
uses: golangci/golangci-lint-action@v3.6.0
uses: golangci/golangci-lint-action@v3.7.0
with:
version: latest
# skip cache because of flaky behaviors
@@ -56,7 +54,7 @@ jobs:
needs: golangci-lint # run after golangci-lint action to not produce duplicated errors
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v4
with:
@@ -72,7 +70,7 @@ jobs:
needs: golangci-lint # run after golangci-lint action to not produce duplicated errors
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v4
with:
@@ -93,7 +91,7 @@ jobs:
- '1.20'
- '1.21'
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v4
with:
@@ -115,7 +113,7 @@ jobs:
needs: golangci-lint # run after golangci-lint action to not produce duplicated errors
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Unshallow
run: git fetch --prune --unshallow
- name: Install Go
12 changes: 6 additions & 6 deletions .github/workflows/tag.yml
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v4
with:
@@ -21,7 +21,7 @@ jobs:
run: git fetch --prune --unshallow

- name: Create release
uses: goreleaser/goreleaser-action@v4
uses: goreleaser/goreleaser-action@v5
with:
version: latest
args: release --clean
@@ -37,7 +37,7 @@ jobs:
- Dockerfile: build/Dockerfile
- Dockerfile: build/alpine.Dockerfile
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Install Go
uses: actions/setup-go@v4
@@ -73,16 +73,16 @@ jobs:
fi
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3

- name: Login do docker.io
run: docker login -u golangci -p ${{ secrets.GOLANGCI_LINT_DOCKER_TOKEN }}

- name: Build and publish ${{ matrix.target.Dockerfile }}
uses: docker/build-push-action@v4
uses: docker/build-push-action@v5
with:
context: .
file: ${{ matrix.target.Dockerfile }}
151 changes: 141 additions & 10 deletions .golangci.reference.yml
Original file line number Diff line number Diff line change
@@ -235,9 +235,13 @@ linters-settings:
# If this list is not empty, only the words defined in this list will be detected.
# Default: []
keywords:
- "the"
- "and"
- "a"
- "the"
- "and"
- "a"
# Keywords used to ignore detection.
# Default: []
ignore:
- "0C0C"

errcheck:
# Report about not checking of errors in type assertions: `a := b.(MyStruct)`.
@@ -452,6 +456,10 @@ linters-settings:
# Default: false
suppress-async-assertion: true

# Suppress warning for comparing values from different types, like int32 and uint32
# Default: false
suppress-type-compare-assertion: true

# Trigger warning for ginkgo focus containers like FDescribe, FContext, FWhen or FIt
# Default: false
forbid-focus-container: true
@@ -836,7 +844,7 @@ linters-settings:
- G304 # File path provided as taint input
- G305 # File traversal when extracting zip/tar archive
- G306 # Poor file permissions used when writing to a new file
- G307 # Deferring a method which returns an error
- G307 # Poor file permissions used when creating a file with os.Create
- G401 # Detect the usage of DES, RC4, MD5 or SHA1
- G402 # Look for bad TLS connection settings
- G403 # Ensure minimum RSA key length of 2048 bits
@@ -847,6 +855,7 @@ linters-settings:
- G504 # Import blocklist: net/http/cgi
- G505 # Import blocklist: crypto/sha1
- G601 # Implicit memory aliasing of items from a range statement
- G602 # Slice access out of bounds

# To specify a set of rules to explicitly exclude.
# Available rules: https://github.com/securego/gosec#available-rules
@@ -875,7 +884,7 @@ linters-settings:
- G304 # File path provided as taint input
- G305 # File traversal when extracting zip/tar archive
- G306 # Poor file permissions used when writing to a new file
- G307 # Deferring a method which returns an error
- G307 # Poor file permissions used when creating a file with os.Create
- G401 # Detect the usage of DES, RC4, MD5 or SHA1
- G402 # Look for bad TLS connection settings
- G403 # Ensure minimum RSA key length of 2048 bits
@@ -886,6 +895,7 @@ linters-settings:
- G504 # Import blocklist: net/http/cgi
- G505 # Import blocklist: crypto/sha1
- G601 # Implicit memory aliasing of items from a range statement
- G602 # Slice access out of bounds

# Exclude generated files
# Default: false
@@ -1034,24 +1044,33 @@ linters-settings:
strict: true
unusedresult:
# Comma-separated list of functions whose results must be used
# (in addition to defaults context.WithCancel,context.WithDeadline,context.WithTimeout,context.WithValue,
# errors.New,fmt.Errorf,fmt.Sprint,fmt.Sprintf,sort.Reverse)
# Default []
# (in addition to default:
# context.WithCancel, context.WithDeadline, context.WithTimeout, context.WithValue, errors.New, fmt.Errorf,
# fmt.Sprint, fmt.Sprintf, sort.Reverse
# ).
# Default: []
funcs:
- pkg.MyFunc
# Comma-separated list of names of methods of type func() string whose results must be used
# (in addition to default Error,String)
# Default []
# Default: []
stringmethods:
- MyMethod

# Disable all analyzers.
# Default: false
disable-all: true
# Enable analyzers by name (in addition to default).
# Enable analyzers by name.
# (in addition to default:
# appends, asmdecl, assign, atomic, bools, buildtag, cgocall, composites, copylocks, defers, directive, errorsas,
# framepointer, httpresponse, ifaceassert, loopclosure, lostcancel, nilfunc, printf, shift, sigchanyzer, slog,
# stdmethods, stringintconv, structtag, testinggoroutine, tests, timeformat, unmarshal, unreachable, unsafeptr,
# unusedresult
# ).
# Run `go tool vet help` to see all analyzers.
# Default: []
enable:
- appends
- asmdecl
- assign
- atomic
@@ -1096,9 +1115,14 @@ linters-settings:
# Default: false
enable-all: true
# Disable analyzers by name.
# (in addition to default
# atomicalign, deepequalerrors, fieldalignment, findcall, nilness, reflectvaluecompare, shadow, sortslice,
# timeformat, unusedwrite
# ).
# Run `go tool vet help` to see all analyzers.
# Default: []
disable:
- appends
- asmdecl
- assign
- atomic
@@ -1263,6 +1287,7 @@ linters-settings:
- k8s.io/klog/v2.InfoS # package level exported functions
- (github.com/go-logr/logr.Logger).Error # "Methods"
- (*go.uber.org/zap.SugaredLogger).With # Also "Methods", but with a pointer receiver

maintidx:
# Show functions with maintainability index lower than N.
# A high index indicates better maintainability (it's kind of the opposite of complexity).
@@ -1529,6 +1554,8 @@ linters-settings:
- name: early-return
severity: warning
disabled: false
arguments:
- "preserveScope"
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#empty-block
- name: empty-block
severity: warning
@@ -1537,6 +1564,12 @@ linters-settings:
- name: empty-lines
severity: warning
disabled: false
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#enforce-map-style
- name: enforce-map-style
severity: warning
disabled: false
arguments:
- "make"
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#error-naming
- name: error-naming
severity: warning
@@ -1558,6 +1591,7 @@ linters-settings:
severity: warning
disabled: false
arguments:
- "preserveScope"
- "checkPrivateReceivers"
- "sayRepetitiveInsteadOfStutters"
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#file-header
@@ -1600,6 +1634,14 @@ linters-settings:
- name: indent-error-flow
severity: warning
disabled: false
arguments:
- "preserveScope"
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#import-alias-naming
- name: import-alias-naming
severity: warning
disabled: false
arguments:
- "^[a-z][a-z0-9]{0,}$"
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#imports-blacklist
- name: imports-blacklist
severity: warning
@@ -1657,6 +1699,10 @@ linters-settings:
- name: receiver-naming
severity: warning
disabled: false
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#redundant-import-alias
- name: redundant-import-alias
severity: warning
disabled: false
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#redefines-builtin-id
- name: redefines-builtin-id
severity: warning
@@ -1690,6 +1736,8 @@ linters-settings:
- name: superfluous-else
severity: warning
disabled: false
arguments:
- "preserveScope"
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#time-equal
- name: time-equal
severity: warning
@@ -1705,6 +1753,7 @@ linters-settings:
arguments:
- [ "ID" ] # AllowList
- [ "VM" ] # DenyList
- - upperCaseConst: true
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#var-declaration
- name: var-declaration
severity: warning
@@ -1740,10 +1789,14 @@ linters-settings:
- name: unused-parameter
severity: warning
disabled: false
arguments:
- allowRegex: "^_"
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unused-receiver
- name: unused-receiver
severity: warning
disabled: false
arguments:
- allowRegex: "^_"
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#useless-break
- name: useless-break
severity: warning
@@ -1759,6 +1812,20 @@ linters-settings:
packages:
- github.com/jmoiron/sqlx

sloglint:
# Enforce using key-value pairs only (incompatible with attr-only).
# Default: false
kv-only: true
# Enforce using attributes only (incompatible with kv-only).
# Default: false
attr-only: true
# Enforce using constants instead of raw keys.
# Default: false
no-raw-keys: true
# Enforce putting arguments on separate lines.
# Default: false
args-on-sep-lines: true

staticcheck:
# Deprecated: use the global `run.go` instead.
go: "1.15"
@@ -1848,6 +1915,35 @@ linters-settings:
# Default: false
all: false

testifylint:
# Enable all checkers.
# Default: false
enable-all: true
# Enable specific checkers.
# https://github.com/Antonboom/testifylint#checkers
# Default: ["bool-compare", "compares", "empty", "error-is-as", "error-nil", "expected-actual", "float-compare", "len", "require-error", "suite-dont-use-pkg", "suite-extra-assert-call"]
enable:
- bool-compare
- compares
- empty
- error-is-as
- error-nil
- expected-actual
- float-compare
- len
- require-error
- suite-dont-use-pkg
- suite-extra-assert-call
- suite-thelper
expected-actual:
# Regexp for expected variable name.
# Default: (^(exp(ected)?|want(ed)?)([A-Z]\w*)?$)|(^(\w*[a-z])?(Exp(ected)?|Want(ed)?)$)
pattern: ^expected
suite-extra-assert-call:
# To require or remove extra Assert() call?
# Default: remove
mode: require

testpackage:
# Regexp pattern to skip files.
# Default: "(export|internal)_test\\.go"
@@ -1949,6 +2045,29 @@ linters-settings:
# Default: false
check-exported: true

unused:
# Mark all struct fields that have been written to as used.
# Default: true
field-writes-are-uses: false
# Treat IncDec statement (e.g. `i++` or `i--`) as both read and write operation instead of just write.
# Default: false
post-statements-are-reads: true
# Mark all exported identifiers as used.
# Default: true
exported-is-used: false
# Mark all exported fields as used.
# default: true
exported-fields-are-used: false
# Mark all function parameters as used.
# default: true
parameters-are-used: false
# Mark all local variables as used.
# default: true
local-variables-are-used: false
# Mark all identifiers inside generated files as used.
# Default: true
generated-is-used: false

varcheck:
# Check usage of exported fields and variables.
# Default: false
@@ -2147,6 +2266,7 @@ linters:
- gocheckcompilerdirectives
- gochecknoglobals
- gochecknoinits
- gochecksumtype
- gocognit
- goconst
- gocritic
@@ -2170,6 +2290,7 @@ linters:
- grouper
- ifshort
- importas
- inamedparam
- ineffassign
- interfacebloat
- interfacer
@@ -2193,13 +2314,16 @@ linters:
- nosnakecase
- nosprintfhostport
- paralleltest
- perfsprint
- prealloc
- predeclared
- promlinter
- protogetter
- reassign
- revive
- rowserrcheck
- scopelint
- sloglint
- sqlclosecheck
- staticcheck
- structcheck
@@ -2208,6 +2332,7 @@ linters:
- tagliatelle
- tenv
- testableexamples
- testifylint
- testpackage
- thelper
- tparallel
@@ -2261,6 +2386,7 @@ linters:
- gocheckcompilerdirectives
- gochecknoglobals
- gochecknoinits
- gochecksumtype
- gocognit
- goconst
- gocritic
@@ -2284,6 +2410,7 @@ linters:
- grouper
- ifshort
- importas
- inamedparam
- ineffassign
- interfacebloat
- interfacer
@@ -2307,13 +2434,16 @@ linters:
- nosnakecase
- nosprintfhostport
- paralleltest
- perfsprint
- prealloc
- predeclared
- promlinter
- protogetter
- reassign
- revive
- rowserrcheck
- scopelint
- sloglint
- sqlclosecheck
- staticcheck
- structcheck
@@ -2322,6 +2452,7 @@ linters:
- tagliatelle
- tenv
- testableexamples
- testifylint
- testpackage
- thelper
- tparallel
9 changes: 1 addition & 8 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
linters-settings:
depguard:
# old configuration. TODO(ldez): must be removed
list-type: denylist
packages:
# logging is allowed only by logutils.Log, logrus
# is allowed to use only in logutils package
- github.com/sirupsen/logrus
packages-with-error-message:
- github.com/sirupsen/logrus: "logging is allowed only by logutils.Log"
# new configuration
rules:
logger:
@@ -92,6 +84,7 @@ linters:
- errcheck
- exportloopref
- funlen
- gocheckcompilerdirectives
- gochecknoinits
- goconst
- gocritic
10 changes: 9 additions & 1 deletion .pre-commit-hooks.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
- id: golangci-lint
name: golangci-lint
description: Fast linters runner for Go.
description: Fast linters runner for Go. Note that only modified files are linted, so linters like 'unused' that need to scan all files won't work as expected.
entry: golangci-lint run --new-from-rev HEAD --fix
types: [go]
language: golang
require_serial: true
pass_filenames: false
- id: golangci-lint-full
name: golangci-lint-full
description: Fast linters runner for Go. Runs on all files in the repo. Use this hook if you use pre-commit in CI.
entry: golangci-lint run --fix
types: [go]
language: golang
require_serial: true
pass_filenames: false
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -2,6 +2,20 @@ Follow the news and releases on [Mastodon](https://fosstodon.org/@golangcilint)

There is the most valuable changes log:

### v1.54.2

1. updated linters:
* `errname`: from 0.1.10 to 0.1.12
* `ginkgolinter`: from 0.13.3 to 0.13.5
* `go-errorlint`: from 1.4.3 to 1.4.4
* `godot`: from 1.4.11 to 1.4.14
* `gosec`: from 2.16.0 to 2.17.0
* `musttag`: from 0.7.1 to 0.7.2
* `nilnil`: from 0.1.5 to 0.1.7
* `staticcheck`: from 0.4.3 to 0.4.5
* `usestdlibvars`: from 1.23.0 to 1.24.0
* `govet`: add missing `directive` and `slog` passes

### v1.54.1

1. updated linters:
186 changes: 94 additions & 92 deletions README.md

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions assets/github-action-config.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"MinorVersionToConfig": {
"latest": {
"TargetVersion": "v1.54.1",
"AssetURL": "https://github.com/golangci/golangci-lint/releases/download/v1.54.1/golangci-lint-1.54.1-linux-amd64.tar.gz"
"TargetVersion": "v1.54.2",
"AssetURL": "https://github.com/golangci/golangci-lint/releases/download/v1.54.2/golangci-lint-1.54.2-linux-amd64.tar.gz"
},
"v1.10": {
"Error": "golangci-lint version 'v1.10' isn't supported: we support only v1.14.0 and later versions"
@@ -186,8 +186,8 @@
"AssetURL": "https://github.com/golangci/golangci-lint/releases/download/v1.53.3/golangci-lint-1.53.3-linux-amd64.tar.gz"
},
"v1.54": {
"TargetVersion": "v1.54.1",
"AssetURL": "https://github.com/golangci/golangci-lint/releases/download/v1.54.1/golangci-lint-1.54.1-linux-amd64.tar.gz"
"TargetVersion": "v1.54.2",
"AssetURL": "https://github.com/golangci/golangci-lint/releases/download/v1.54.2/golangci-lint-1.54.2-linux-amd64.tar.gz"
},
"v1.6": {
"Error": "golangci-lint version 'v1.6' isn't supported: we support only v1.14.0 and later versions"
308 changes: 161 additions & 147 deletions docs/package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/package.json
Original file line number Diff line number Diff line change
@@ -35,7 +35,7 @@
"gatsby-transformer-sharp": "^4.21.0",
"gatsby-transformer-yaml": "^4.25.0",
"polished": "^4.2.2",
"postcss": "^8.4.20",
"postcss": "^8.4.31",
"prism-react-renderer": "^1.3.5",
"prop-types": "^15.8.1",
"puppeteer": "^13.7.0",
10 changes: 10 additions & 0 deletions docs/src/docs/usage/false-positives.mdx
Original file line number Diff line number Diff line change
@@ -53,6 +53,16 @@ issues:
text: "mnd: Magic number: 9"
```

In the following example, all the reports from the linters (`linters`) that originated from the source (`source`) are excluded:

```yml
issues:
exclude-rules:
- linters:
- lll
source: "^//go:generate "
```

In the following example, all the reports that contains the text (`text`) in the path (`path`) are excluded:

```yml
62 changes: 34 additions & 28 deletions go.mod
Original file line number Diff line number Diff line change
@@ -5,14 +5,16 @@ go 1.20
require (
4d63.com/gocheckcompilerdirectives v1.2.1
4d63.com/gochecknoglobals v0.2.1
github.com/4meepo/tagalign v1.3.2
github.com/Abirdcfly/dupword v0.0.12
github.com/4meepo/tagalign v1.3.3
github.com/Abirdcfly/dupword v0.0.13
github.com/Antonboom/errname v0.1.12
github.com/Antonboom/nilnil v0.1.7
github.com/Antonboom/testifylint v0.2.3
github.com/BurntSushi/toml v1.3.2
github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24
github.com/GaijinEntertainment/go-exhaustruct/v3 v3.1.0
github.com/OpenPeeDeeP/depguard/v2 v2.1.0
github.com/alecthomas/go-check-sumtype v0.1.3
github.com/alexkohler/nakedret/v2 v2.0.2
github.com/alexkohler/prealloc v1.0.0
github.com/alingse/asasalint v0.0.11
@@ -21,37 +23,39 @@ require (
github.com/bkielbasa/cyclop v1.2.1
github.com/blizzy78/varnamelen v0.8.0
github.com/bombsimon/wsl/v3 v3.4.0
github.com/breml/bidichk v0.2.4
github.com/breml/errchkjson v0.3.1
github.com/butuzov/ireturn v0.2.0
github.com/breml/bidichk v0.2.7
github.com/breml/errchkjson v0.3.6
github.com/butuzov/ireturn v0.2.1
github.com/butuzov/mirror v1.1.0
github.com/catenacyber/perfsprint v0.2.0
github.com/charithe/durationcheck v0.0.10
github.com/curioswitch/go-reassign v0.2.0
github.com/daixiang0/gci v0.11.0
github.com/daixiang0/gci v0.11.2
github.com/denis-tingaikin/go-header v0.4.3
github.com/esimonov/ifshort v1.0.4
github.com/fatih/color v1.15.0
github.com/firefart/nonamedreturns v1.0.4
github.com/fzipp/gocyclo v0.6.0
github.com/ghostiam/protogetter v0.2.3
github.com/go-critic/go-critic v0.9.0
github.com/go-xmlfmt/xmlfmt v1.1.2
github.com/gofrs/flock v0.8.1
github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2
github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a
github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe
github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2
github.com/golangci/gofmt v0.0.0-20231018234816-f50ced29576e
github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0
github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca
github.com/golangci/misspell v0.4.1
github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6
github.com/golangci/revgrep v0.5.0
github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4
github.com/gordonklaus/ineffassign v0.0.0-20230610083614-0e73809eb601
github.com/gostaticanalysis/forcetypeassert v0.1.0
github.com/gostaticanalysis/nilerr v0.1.1
github.com/hashicorp/go-multierror v1.1.1
github.com/hashicorp/go-version v1.6.0
github.com/hexops/gotextdiff v1.0.3
github.com/jgautheron/goconst v1.5.1
github.com/jgautheron/goconst v1.6.0
github.com/jingyugao/rowserrcheck v1.1.1
github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af
github.com/julz/importas v0.1.0
@@ -64,30 +68,31 @@ require (
github.com/ldez/tagliatelle v0.5.0
github.com/leonklingele/grouper v1.1.1
github.com/lufeee/execinquery v1.2.1
github.com/macabu/inamedparam v0.1.2
github.com/maratori/testableexamples v1.0.0
github.com/maratori/testpackage v1.1.1
github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26
github.com/mattn/go-colorable v0.1.13
github.com/mbilski/exhaustivestruct v1.2.0
github.com/mgechev/revive v1.3.2
github.com/mgechev/revive v1.3.4
github.com/mitchellh/go-homedir v1.1.0
github.com/mitchellh/go-ps v1.0.0
github.com/mitchellh/mapstructure v1.5.0
github.com/moricho/tparallel v0.3.1
github.com/nakabonne/nestif v0.3.1
github.com/nishanths/exhaustive v0.11.0
github.com/nishanths/predeclared v0.2.2
github.com/nunnatsa/ginkgolinter v0.13.5
github.com/polyfloyd/go-errorlint v1.4.4
github.com/nunnatsa/ginkgolinter v0.14.0
github.com/polyfloyd/go-errorlint v1.4.5
github.com/quasilyte/go-ruleguard/dsl v0.3.22
github.com/ryancurrah/gomodguard v1.3.0
github.com/ryanrolds/sqlclosecheck v0.4.0
github.com/ryanrolds/sqlclosecheck v0.5.1
github.com/sanposhiho/wastedassign/v2 v2.0.7
github.com/sashamelentyev/interfacebloat v1.1.0
github.com/sashamelentyev/usestdlibvars v1.24.0
github.com/securego/gosec/v2 v2.17.0
github.com/securego/gosec/v2 v2.18.1
github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c
github.com/shirou/gopsutil/v3 v3.23.7
github.com/shirou/gopsutil/v3 v3.23.9
github.com/sirupsen/logrus v1.9.3
github.com/sivchari/containedctx v1.0.3
github.com/sivchari/nosnakecase v1.7.0
@@ -101,25 +106,26 @@ require (
github.com/stbenjam/no-sprintf-host-port v0.1.1
github.com/stretchr/testify v1.8.4
github.com/tdakkota/asciicheck v0.2.0
github.com/tetafro/godot v1.4.14
github.com/tetafro/godot v1.4.15
github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966
github.com/timonwong/loggercheck v0.9.4
github.com/tomarrell/wrapcheck/v2 v2.8.1
github.com/tommy-muehle/go-mnd/v2 v2.5.1
github.com/ultraware/funlen v0.1.0
github.com/ultraware/whitespace v0.0.5
github.com/uudashr/gocognit v1.0.7
github.com/uudashr/gocognit v1.1.2
github.com/valyala/quicktemplate v1.7.0
github.com/xen0n/gosmopolitan v1.2.1
github.com/xen0n/gosmopolitan v1.2.2
github.com/yagipy/maintidx v1.0.0
github.com/yeya24/promlinter v0.2.0
github.com/ykadowak/zerologlint v0.1.3
gitlab.com/bosi/decorder v0.4.0
gitlab.com/bosi/decorder v0.4.1
go-simpler.org/sloglint v0.1.2
go.tmz.dev/musttag v0.7.2
golang.org/x/exp v0.0.0-20230510235704-dd950f8aeaea
golang.org/x/tools v0.12.0
golang.org/x/tools v0.14.0
gopkg.in/yaml.v3 v3.0.1
honnef.co/go/tools v0.4.5
honnef.co/go/tools v0.4.6
mvdan.cc/gofumpt v0.5.0
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed
mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d
@@ -130,7 +136,7 @@ require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/ccojocar/zxcvbn-go v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/chavacava/garif v0.0.0-20230227094218-b8c73b2037b8 // indirect
github.com/chavacava/garif v0.1.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/ettle/strcase v0.1.1 // indirect
github.com/fatih/structtag v1.2.0 // indirect
@@ -177,18 +183,18 @@ require (
github.com/stretchr/objx v0.5.0 // indirect
github.com/subosito/gotenv v1.4.1 // indirect
github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c // indirect
github.com/tklauser/go-sysconf v0.3.11 // indirect
github.com/tklauser/numcpus v0.6.0 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.24.0 // indirect
golang.org/x/exp/typeparams v0.0.0-20230307190834-24139beb5833 // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.11.0 // indirect
golang.org/x/text v0.12.0 // indirect
golang.org/x/mod v0.13.0 // indirect
golang.org/x/sync v0.4.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
137 changes: 76 additions & 61 deletions go.sum

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions pkg/commands/root.go
Original file line number Diff line number Diff line change
@@ -149,10 +149,10 @@ func (e *Executor) needVersionOption() bool {
}

func initRootFlagSet(fs *pflag.FlagSet, cfg *config.Config, needVersionOption bool) {
fs.BoolVarP(&cfg.Run.IsVerbose, "verbose", "v", false, wh("verbose output"))
fs.BoolVarP(&cfg.Run.IsVerbose, "verbose", "v", false, wh("Verbose output"))

var silent bool
fs.BoolVarP(&silent, "silent", "s", false, wh("disables congrats outputs"))
fs.BoolVarP(&silent, "silent", "s", false, wh("Disables congrats outputs"))
if err := fs.MarkHidden("silent"); err != nil {
panic(err)
}
2 changes: 1 addition & 1 deletion pkg/config/issues.go
Original file line number Diff line number Diff line change
@@ -54,7 +54,7 @@ var DefaultExcludePatterns = []ExcludePattern{
},
{
ID: "EXC0008",
Pattern: "(G104|G307)",
Pattern: "(G104)",
Linter: "gosec",
Why: "Duplicated errcheck checks",
},
64 changes: 57 additions & 7 deletions pkg/config/linters_settings.go
Original file line number Diff line number Diff line change
@@ -113,6 +113,12 @@ var defaultLintersSettings = LintersSettings{
Ignore: "",
Qualified: false,
},
SlogLint: SlogLintSettings{
KVOnly: false,
AttrOnly: false,
NoRawKeys: false,
ArgsOnSepLines: false,
},
TagAlign: TagAlignSettings{
Align: true,
Sort: true,
@@ -126,6 +132,15 @@ var defaultLintersSettings = LintersSettings{
Unparam: UnparamSettings{
Algo: "cha",
},
Unused: UnusedSettings{
FieldWritesAreUses: true,
PostStatementsAreReads: false,
ExportedIsUsed: true,
ExportedFieldsAreUsed: true,
ParametersAreUsed: true,
LocalVariablesAreUsed: true,
GeneratedIsUsed: true,
},
UseStdlibVars: UseStdlibVarsSettings{
HTTPMethod: true,
HTTPStatusCode: true,
@@ -213,15 +228,18 @@ type LintersSettings struct {
Reassign ReassignSettings
Revive ReviveSettings
RowsErrCheck RowsErrCheckSettings
SlogLint SlogLintSettings
Staticcheck StaticCheckSettings
Structcheck StructCheckSettings
Stylecheck StaticCheckSettings
TagAlign TagAlignSettings
Tagliatelle TagliatelleSettings
Testifylint TestifylintSettings
Tenv TenvSettings
Testpackage TestpackageSettings
Thelper ThelperSettings
Unparam UnparamSettings
Unused UnusedSettings
UseStdlibVars UseStdlibVarsSettings
Varcheck VarCheckSettings
Varnamelen VarnamelenSettings
@@ -292,6 +310,7 @@ type DuplSettings struct {

type DupWordSettings struct {
Keywords []string `mapstructure:"keywords"`
Ignore []string `mapstructure:"ignore"`
}

type ErrcheckSettings struct {
@@ -393,13 +412,14 @@ type GciSettings struct {
}

type GinkgoLinterSettings struct {
SuppressLenAssertion bool `mapstructure:"suppress-len-assertion"`
SuppressNilAssertion bool `mapstructure:"suppress-nil-assertion"`
SuppressErrAssertion bool `mapstructure:"suppress-err-assertion"`
SuppressCompareAssertion bool `mapstructure:"suppress-compare-assertion"`
SuppressAsyncAssertion bool `mapstructure:"suppress-async-assertion"`
ForbidFocusContainer bool `mapstructure:"forbid-focus-container"`
AllowHaveLenZero bool `mapstructure:"allow-havelen-zero"`
SuppressLenAssertion bool `mapstructure:"suppress-len-assertion"`
SuppressNilAssertion bool `mapstructure:"suppress-nil-assertion"`
SuppressErrAssertion bool `mapstructure:"suppress-err-assertion"`
SuppressCompareAssertion bool `mapstructure:"suppress-compare-assertion"`
SuppressAsyncAssertion bool `mapstructure:"suppress-async-assertion"`
SuppressTypeCompareWarning bool `mapstructure:"suppress-type-compare-assertion"`
ForbidFocusContainer bool `mapstructure:"forbid-focus-container"`
AllowHaveLenZero bool `mapstructure:"allow-havelen-zero"`
}

type GocognitSettings struct {
@@ -704,6 +724,13 @@ type RowsErrCheckSettings struct {
Packages []string
}

type SlogLintSettings struct {
KVOnly bool `mapstructure:"kv-only"`
AttrOnly bool `mapstructure:"attr-only"`
NoRawKeys bool `mapstructure:"no-raw-keys"`
ArgsOnSepLines bool `mapstructure:"args-on-sep-lines"`
}

type StaticCheckSettings struct {
// Deprecated: use the global `run.go` instead.
GoVersion string `mapstructure:"go"`
@@ -736,6 +763,19 @@ type TagliatelleSettings struct {
}
}

type TestifylintSettings struct {
EnableAll bool `mapstructure:"enable-all"`
EnabledCheckers []string `mapstructure:"enable"`

ExpectedActual struct {
ExpVarPattern string `mapstructure:"pattern"`
} `mapstructure:"expected-actual"`

SuiteExtraAssertCall struct {
Mode string `mapstructure:"mode"`
} `mapstructure:"suite-extra-assert-call"`
}

type TestpackageSettings struct {
SkipRegexp string `mapstructure:"skip-regexp"`
AllowPackages []string `mapstructure:"allow-packages"`
@@ -778,6 +818,16 @@ type UnparamSettings struct {
Algo string
}

type UnusedSettings struct {
FieldWritesAreUses bool `mapstructure:"field-writes-are-uses"`
PostStatementsAreReads bool `mapstructure:"post-statements-are-reads"`
ExportedIsUsed bool `mapstructure:"exported-is-used"`
ExportedFieldsAreUsed bool `mapstructure:"exported-fields-are-used"`
ParametersAreUsed bool `mapstructure:"parameters-are-used"`
LocalVariablesAreUsed bool `mapstructure:"local-variables-are-used"`
GeneratedIsUsed bool `mapstructure:"generated-is-used"`
}

type VarCheckSettings struct {
CheckExportedFields bool `mapstructure:"exported-fields"`
}
1 change: 1 addition & 0 deletions pkg/golinters/dupword.go
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@ func NewDupWord(setting *config.DupWordSettings) *goanalysis.Linter {
if setting != nil {
cfgMap[a.Name] = map[string]any{
"keyword": strings.Join(setting.Keywords, ","),
"ignore": strings.Join(setting.Ignore, ","),
}
}

15 changes: 8 additions & 7 deletions pkg/golinters/ginkgolinter.go
Original file line number Diff line number Diff line change
@@ -14,13 +14,14 @@ func NewGinkgoLinter(cfg *config.GinkgoLinterSettings) *goanalysis.Linter {
cfgMap := make(map[string]map[string]any)
if cfg != nil {
cfgMap[a.Name] = map[string]any{
"suppress-len-assertion": cfg.SuppressLenAssertion,
"suppress-nil-assertion": cfg.SuppressNilAssertion,
"suppress-err-assertion": cfg.SuppressErrAssertion,
"suppress-compare-assertion": cfg.SuppressCompareAssertion,
"suppress-async-assertion": cfg.SuppressAsyncAssertion,
"forbid-focus-container": cfg.ForbidFocusContainer,
"allow-havelen-0": cfg.AllowHaveLenZero,
"suppress-len-assertion": cfg.SuppressLenAssertion,
"suppress-nil-assertion": cfg.SuppressNilAssertion,
"suppress-err-assertion": cfg.SuppressErrAssertion,
"suppress-compare-assertion": cfg.SuppressCompareAssertion,
"suppress-async-assertion": cfg.SuppressAsyncAssertion,
"suppress-type-compare-assertion": cfg.SuppressTypeCompareWarning,
"forbid-focus-container": cfg.ForbidFocusContainer,
"allow-havelen-0": cfg.AllowHaveLenZero,
}
}

80 changes: 80 additions & 0 deletions pkg/golinters/gochecksumtype.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package golinters

import (
"strings"
"sync"

gochecksumtype "github.com/alecthomas/go-check-sumtype"
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/packages"

"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
"github.com/golangci/golangci-lint/pkg/lint/linter"
"github.com/golangci/golangci-lint/pkg/result"
)

const goCheckSumTypeName = "gochecksumtype"

func NewGoCheckSumType() *goanalysis.Linter {
var mu sync.Mutex
var resIssues []goanalysis.Issue

analyzer := &analysis.Analyzer{
Name: goCheckSumTypeName,
Doc: goanalysis.TheOnlyanalyzerDoc,
Run: func(pass *analysis.Pass) (any, error) {
issues, err := runGoCheckSumType(pass)
if err != nil {
return nil, err
}

if len(issues) == 0 {
return nil, nil
}

mu.Lock()
resIssues = append(resIssues, issues...)
mu.Unlock()

return nil, nil
},
}

return goanalysis.NewLinter(
goCheckSumTypeName,
`Run exhaustiveness checks on Go "sum types"`,
[]*analysis.Analyzer{analyzer},
nil,
).WithIssuesReporter(func(ctx *linter.Context) []goanalysis.Issue {
return resIssues
}).WithLoadMode(goanalysis.LoadModeTypesInfo)
}

func runGoCheckSumType(pass *analysis.Pass) ([]goanalysis.Issue, error) {
var resIssues []goanalysis.Issue

pkg := &packages.Package{
Fset: pass.Fset,
Syntax: pass.Files,
Types: pass.Pkg,
TypesInfo: pass.TypesInfo,
}

var unknownError error
errors := gochecksumtype.Run([]*packages.Package{pkg})
for _, err := range errors {
err, ok := err.(gochecksumtype.Error)
if !ok {
unknownError = err
continue
}

resIssues = append(resIssues, goanalysis.NewIssue(&result.Issue{
FromLinter: goCheckSumTypeName,
Text: strings.TrimPrefix(err.Error(), err.Pos().String()+": "),
Pos: err.Pos(),
}, pass))
}

return resIssues, unknownError
}
9 changes: 2 additions & 7 deletions pkg/golinters/gocritic_test.go
Original file line number Diff line number Diff line change
@@ -2,7 +2,6 @@ package golinters

import (
"log"
"sort"
"testing"

"github.com/stretchr/testify/assert"
@@ -16,9 +15,7 @@ func Test_intersectStringSlice(t *testing.T) {

s3 := intersectStringSlice(s1, s2)

sort.Strings(s3)

assert.Equal(t, s3, []string{"experimental", "opinionated"})
assert.ElementsMatch(t, []string{"experimental", "opinionated"}, s3)
}

func Test_filterByDisableTags(t *testing.T) {
@@ -29,9 +26,7 @@ func Test_filterByDisableTags(t *testing.T) {

filterEnabledChecks := settingsWrapper.filterByDisableTags(enabledChecks, disabledTags)

sort.Strings(filterEnabledChecks)

assert.Equal(t, []string{"appendAssign", "caseOrder"}, filterEnabledChecks)
assert.ElementsMatch(t, filterEnabledChecks, []string{"appendAssign", "caseOrder"})
}

type tLog struct{}
5 changes: 3 additions & 2 deletions pkg/golinters/gofmt_test.go
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ import (
diffpkg "github.com/sourcegraph/go-diff/diff"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"

"github.com/golangci/golangci-lint/pkg/logutils"
"github.com/golangci/golangci-lint/pkg/result"
@@ -14,10 +15,10 @@ import (
func testDiffProducesChanges(t *testing.T, log logutils.Log, diff string, expectedChanges ...Change) {
diffs, err := diffpkg.ParseMultiFileDiff([]byte(diff))
if err != nil {
assert.NoError(t, err)
require.NoError(t, err)
}

assert.Len(t, diffs, 1)
require.Len(t, diffs, 1)
hunks := diffs[0].Hunks
assert.NotEmpty(t, hunks)

6 changes: 5 additions & 1 deletion pkg/golinters/govet.go
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ package golinters

import (
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/appends"
"golang.org/x/tools/go/analysis/passes/asmdecl"
"golang.org/x/tools/go/analysis/passes/assign"
"golang.org/x/tools/go/analysis/passes/atomic"
@@ -53,6 +54,7 @@ import (

var (
allAnalyzers = []*analysis.Analyzer{
appends.Analyzer,
asmdecl.Analyzer,
assign.Analyzer,
atomic.Analyzer,
@@ -95,8 +97,9 @@ var (
unusedwrite.Analyzer,
}

// https://github.com/golang/go/blob/c19c4c566c63818dfd059b352e52c4710eecf14d/src/cmd/vet/main.go#L47-L78
// https://github.com/golang/go/blob/b56645a87b28840a180d64077877cb46570b4176/src/cmd/vet/main.go#L49-L81
defaultAnalyzers = []*analysis.Analyzer{
appends.Analyzer,
asmdecl.Analyzer,
assign.Analyzer,
atomic.Analyzer,
@@ -105,6 +108,7 @@ var (
cgocall.Analyzer,
composite.Analyzer,
copylock.Analyzer,
defers.Analyzer,
directive.Analyzer,
errorsas.Analyzer,
framepointer.Analyzer,
19 changes: 19 additions & 0 deletions pkg/golinters/inamedparam.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package golinters

import (
"github.com/macabu/inamedparam"
"golang.org/x/tools/go/analysis"

"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
)

func NewINamedParam() *goanalysis.Linter {
a := inamedparam.Analyzer

return goanalysis.NewLinter(
a.Name,
a.Doc,
[]*analysis.Analyzer{a},
nil,
).WithLoadMode(goanalysis.LoadModeSyntax)
}
19 changes: 19 additions & 0 deletions pkg/golinters/perfsprint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package golinters

import (
"github.com/catenacyber/perfsprint/analyzer"
"golang.org/x/tools/go/analysis"

"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
)

func NewPerfSprint() *goanalysis.Linter {
a := analyzer.Analyzer

return goanalysis.NewLinter(
a.Name,
a.Doc,
[]*analysis.Analyzer{a},
nil,
).WithLoadMode(goanalysis.LoadModeTypesInfo)
}
59 changes: 59 additions & 0 deletions pkg/golinters/protogetter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package golinters

import (
"sync"

"github.com/ghostiam/protogetter"
"golang.org/x/tools/go/analysis"

"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
"github.com/golangci/golangci-lint/pkg/lint/linter"
"github.com/golangci/golangci-lint/pkg/result"
)

func NewProtoGetter() *goanalysis.Linter {
var mu sync.Mutex
var resIssues []goanalysis.Issue

a := protogetter.NewAnalyzer()
a.Run = func(pass *analysis.Pass) (any, error) {
pgIssues := protogetter.Run(pass, protogetter.GolangciLintMode)

issues := make([]goanalysis.Issue, len(pgIssues))
for i, issue := range pgIssues {
report := &result.Issue{
FromLinter: a.Name,
Pos: issue.Pos,
Text: issue.Message,
Replacement: &result.Replacement{
Inline: &result.InlineFix{
StartCol: issue.InlineFix.StartCol,
Length: issue.InlineFix.Length,
NewString: issue.InlineFix.NewString,
},
},
}

issues[i] = goanalysis.NewIssue(report, pass)
}

if len(issues) == 0 {
return nil, nil
}

mu.Lock()
resIssues = append(resIssues, issues...)
mu.Unlock()

return nil, nil
}

return goanalysis.NewLinter(
a.Name,
a.Doc,
[]*analysis.Analyzer{a},
nil,
).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue {
return resIssues
}).WithLoadMode(goanalysis.LoadModeTypesInfo)
}
8 changes: 6 additions & 2 deletions pkg/golinters/revive.go
Original file line number Diff line number Diff line change
@@ -247,7 +247,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.3.0/config/config.go#L15
// Extracted from https://github.com/mgechev/revive/blob/v1.3.4/config/config.go#L15
var defaultRules = []lint.Rule{
&rule.VarDeclarationsRule{},
&rule.PackageCommentsRule{},
@@ -267,7 +267,6 @@ var defaultRules = []lint.Rule{
&rule.TimeNamingRule{},
&rule.ContextKeysType{},
&rule.ContextAsArgumentRule{},
&rule.IfReturnRule{},
&rule.EmptyBlockRule{},
&rule.SuperfluousElseRule{},
&rule.UnusedParamRule{},
@@ -317,12 +316,17 @@ var allRules = append([]lint.Rule{
&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.EnforceMapStyleRule{},
}, defaultRules...)

const defaultConfidence = 0.8
27 changes: 27 additions & 0 deletions pkg/golinters/sloglint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package golinters

import (
"go-simpler.org/sloglint"
"golang.org/x/tools/go/analysis"

"github.com/golangci/golangci-lint/pkg/config"
"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
)

func NewSlogLint(settings *config.SlogLintSettings) *goanalysis.Linter {
var opts *sloglint.Options
if settings != nil {
opts = &sloglint.Options{
KVOnly: settings.KVOnly,
AttrOnly: settings.AttrOnly,
NoRawKeys: settings.NoRawKeys,
ArgsOnSepLines: settings.ArgsOnSepLines,
}
}

a := sloglint.New(opts)

return goanalysis.
NewLinter(a.Name, a.Doc, []*analysis.Analyzer{a}, nil).
WithLoadMode(goanalysis.LoadModeTypesInfo)
}
36 changes: 36 additions & 0 deletions pkg/golinters/testifylint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package golinters

import (
"github.com/Antonboom/testifylint/analyzer"
"golang.org/x/tools/go/analysis"

"github.com/golangci/golangci-lint/pkg/config"
"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
)

func NewTestifylint(settings *config.TestifylintSettings) *goanalysis.Linter {
a := analyzer.New()

cfg := make(map[string]map[string]any)
if settings != nil {
cfg[a.Name] = map[string]any{
"enable-all": settings.EnableAll,
}
if len(settings.EnabledCheckers) > 0 {
cfg[a.Name]["enable"] = settings.EnabledCheckers
}
if p := settings.ExpectedActual.ExpVarPattern; p != "" {
cfg[a.Name]["expected-actual.pattern"] = p
}
if m := settings.SuiteExtraAssertCall.Mode; m != "" {
cfg[a.Name]["suite-extra-assert-call.mode"] = m
}
}

return goanalysis.NewLinter(
a.Name,
a.Doc,
[]*analysis.Analyzer{a},
cfg,
).WithLoadMode(goanalysis.LoadModeTypesInfo)
}
56 changes: 37 additions & 19 deletions pkg/golinters/unused.go
Original file line number Diff line number Diff line change
@@ -5,6 +5,9 @@ import (
"sync"

"golang.org/x/tools/go/analysis"
"honnef.co/go/tools/analysis/facts/directives"
"honnef.co/go/tools/analysis/facts/generated"
"honnef.co/go/tools/analysis/lint"
"honnef.co/go/tools/unused"

"github.com/golangci/golangci-lint/pkg/config"
@@ -15,11 +18,7 @@ import (

const unusedName = "unused"

type UnusedSettings struct {
GoVersion string
}

func NewUnused(settings *config.StaticCheckSettings) *goanalysis.Linter {
func NewUnused(settings *config.UnusedSettings, scSettings *config.StaticCheckSettings) *goanalysis.Linter {
var mu sync.Mutex
var resIssues []goanalysis.Issue

@@ -28,11 +27,7 @@ func NewUnused(settings *config.StaticCheckSettings) *goanalysis.Linter {
Doc: unused.Analyzer.Analyzer.Doc,
Requires: unused.Analyzer.Analyzer.Requires,
Run: func(pass *analysis.Pass) (any, error) {
issues, err := runUnused(pass)
if err != nil {
return nil, err
}

issues := runUnused(pass, settings)
if len(issues) == 0 {
return nil, nil
}
@@ -45,7 +40,7 @@ func NewUnused(settings *config.StaticCheckSettings) *goanalysis.Linter {
},
}

setAnalyzerGoVersion(analyzer, getGoVersion(settings))
setAnalyzerGoVersion(analyzer, getGoVersion(scSettings))

return goanalysis.NewLinter(
unusedName,
@@ -57,21 +52,18 @@ func NewUnused(settings *config.StaticCheckSettings) *goanalysis.Linter {
}).WithLoadMode(goanalysis.LoadModeTypesInfo)
}

func runUnused(pass *analysis.Pass) ([]goanalysis.Issue, error) {
res, err := unused.Analyzer.Analyzer.Run(pass)
if err != nil {
return nil, err
}
func runUnused(pass *analysis.Pass, cfg *config.UnusedSettings) []goanalysis.Issue {
res := getUnusedResults(pass, cfg)

used := make(map[string]bool)
for _, obj := range res.(unused.Result).Used {
for _, obj := range res.Used {
used[fmt.Sprintf("%s %d %s", obj.Position.Filename, obj.Position.Line, obj.Name)] = true
}

var issues []goanalysis.Issue

// Inspired by https://github.com/dominikh/go-tools/blob/d694aadcb1f50c2d8ac0a1dd06217ebb9f654764/lintcmd/lint.go#L177-L197
for _, object := range res.(unused.Result).Unused {
for _, object := range res.Unused {
if object.Kind == "type param" {
continue
}
@@ -90,5 +82,31 @@ func runUnused(pass *analysis.Pass) ([]goanalysis.Issue, error) {
issues = append(issues, issue)
}

return issues, nil
return issues
}

func getUnusedResults(pass *analysis.Pass, settings *config.UnusedSettings) unused.Result {
opts := unused.Options{
FieldWritesAreUses: settings.FieldWritesAreUses,
PostStatementsAreReads: settings.PostStatementsAreReads,
ExportedIsUsed: settings.ExportedIsUsed,
ExportedFieldsAreUsed: settings.ExportedFieldsAreUsed,
ParametersAreUsed: settings.ParametersAreUsed,
LocalVariablesAreUsed: settings.LocalVariablesAreUsed,
GeneratedIsUsed: settings.GeneratedIsUsed,
}

// ref: https://github.com/dominikh/go-tools/blob/4ec1f474ca6c0feb8e10a8fcca4ab95f5b5b9881/internal/cmd/unused/unused.go#L68
nodes := unused.Graph(pass.Fset,
pass.Files,
pass.Pkg,
pass.TypesInfo,
pass.ResultOf[directives.Analyzer].([]lint.Directive),
pass.ResultOf[generated.Analyzer].(map[string]generated.Generator),
opts,
)

sg := unused.SerializedGraph{}
sg.Merge(nodes)
return sg.Results()
}
49 changes: 43 additions & 6 deletions pkg/lint/lintersdb/manager.go
Original file line number Diff line number Diff line change
@@ -127,16 +127,18 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
reassignCfg *config.ReassignSettings
reviveCfg *config.ReviveSettings
rowserrcheckCfg *config.RowsErrCheckSettings
sloglintCfg *config.SlogLintSettings
staticcheckCfg *config.StaticCheckSettings
structcheckCfg *config.StructCheckSettings
stylecheckCfg *config.StaticCheckSettings
tagalignCfg *config.TagAlignSettings
tagliatelleCfg *config.TagliatelleSettings
tenvCfg *config.TenvSettings
testifylintCfg *config.TestifylintSettings
testpackageCfg *config.TestpackageSettings
thelperCfg *config.ThelperSettings
unparamCfg *config.UnparamSettings
unusedCfg *config.StaticCheckSettings
unusedCfg *config.UnusedSettings
usestdlibvars *config.UseStdlibVarsSettings
varcheckCfg *config.VarCheckSettings
varnamelenCfg *config.VarnamelenSettings
@@ -207,16 +209,18 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
reassignCfg = &m.cfg.LintersSettings.Reassign
reviveCfg = &m.cfg.LintersSettings.Revive
rowserrcheckCfg = &m.cfg.LintersSettings.RowsErrCheck
sloglintCfg = &m.cfg.LintersSettings.SlogLint
staticcheckCfg = &m.cfg.LintersSettings.Staticcheck
structcheckCfg = &m.cfg.LintersSettings.Structcheck
stylecheckCfg = &m.cfg.LintersSettings.Stylecheck
tagalignCfg = &m.cfg.LintersSettings.TagAlign
tagliatelleCfg = &m.cfg.LintersSettings.Tagliatelle
tenvCfg = &m.cfg.LintersSettings.Tenv
testifylintCfg = &m.cfg.LintersSettings.Testifylint
testpackageCfg = &m.cfg.LintersSettings.Testpackage
thelperCfg = &m.cfg.LintersSettings.Thelper
unparamCfg = &m.cfg.LintersSettings.Unparam
unusedCfg = new(config.StaticCheckSettings)
unusedCfg = &m.cfg.LintersSettings.Unused
usestdlibvars = &m.cfg.LintersSettings.UseStdlibVars
varcheckCfg = &m.cfg.LintersSettings.Varcheck
varnamelenCfg = &m.cfg.LintersSettings.Varnamelen
@@ -245,9 +249,6 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
if stylecheckCfg != nil && stylecheckCfg.GoVersion != "" {
stylecheckCfg.GoVersion = trimGoVersion(m.cfg.Run.Go)
}
if unusedCfg != nil && unusedCfg.GoVersion == "" {
unusedCfg.GoVersion = trimGoVersion(m.cfg.Run.Go)
}
}

const megacheckName = "megacheck"
@@ -439,6 +440,12 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
WithSince("v1.12.0").
WithPresets(linter.PresetStyle),

linter.NewConfig(golinters.NewGoCheckSumType()).
WithSince("v1.55.0").
WithPresets(linter.PresetBugs).
WithLoadForGoAnalysis().
WithURL("https://github.com/alecthomas/go-check-sumtype"),

linter.NewConfig(golinters.NewGocognit(gocognitCfg)).
WithSince("v1.20.0").
WithPresets(linter.PresetComplexity).
@@ -573,6 +580,11 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
WithLoadForGoAnalysis().
WithURL("https://github.com/julz/importas"),

linter.NewConfig(golinters.NewINamedParam()).
WithSince("v1.55.0").
WithPresets(linter.PresetStyle).
WithURL("https://github.com/macabu/inamedparam"),

linter.NewConfig(golinters.NewIneffassign()).
WithEnabledByDefault().
WithSince("v1.0.0").
@@ -700,6 +712,12 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
WithPresets(linter.PresetStyle, linter.PresetTest).
WithURL("https://github.com/kunwardeep/paralleltest"),

linter.NewConfig(golinters.NewPerfSprint()).
WithSince("v1.55.0").
WithLoadForGoAnalysis().
WithPresets(linter.PresetPerformance).
WithURL("https://github.com/catenacyber/perfsprint"),

linter.NewConfig(golinters.NewPreAlloc(preallocCfg)).
WithSince("v1.19.0").
WithPresets(linter.PresetPerformance).
@@ -715,6 +733,13 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
WithPresets(linter.PresetStyle).
WithURL("https://github.com/yeya24/promlinter"),

linter.NewConfig(golinters.NewProtoGetter()).
WithSince("v1.55.0").
WithPresets(linter.PresetBugs).
WithLoadForGoAnalysis().
WithAutoFix().
WithURL("https://github.com/ghostiam/protogetter"),

linter.NewConfig(golinters.NewReassign(reassignCfg)).
WithSince("1.49.0").
WithPresets(linter.PresetBugs).
@@ -733,6 +758,12 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
WithPresets(linter.PresetBugs, linter.PresetSQL).
WithURL("https://github.com/jingyugao/rowserrcheck"),

linter.NewConfig(golinters.NewSlogLint(sloglintCfg)).
WithSince("v1.55.0").
WithLoadForGoAnalysis().
WithPresets(linter.PresetStyle, linter.PresetFormatting).
WithURL("https://github.com/go-simpler/sloglint"),

linter.NewConfig(golinters.NewScopelint()).
WithSince("v1.12.0").
WithPresets(linter.PresetBugs).
@@ -788,6 +819,12 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
WithPresets(linter.PresetTest).
WithURL("https://github.com/maratori/testableexamples"),

linter.NewConfig(golinters.NewTestifylint(testifylintCfg)).
WithSince("v1.55.0").
WithPresets(linter.PresetTest, linter.PresetBugs).
WithLoadForGoAnalysis().
WithURL("https://github.com/Antonboom/testifylint"),

linter.NewConfig(golinters.NewTestpackage(testpackageCfg)).
WithSince("v1.25.0").
WithPresets(linter.PresetStyle, linter.PresetTest).
@@ -825,7 +862,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
WithLoadForGoAnalysis().
WithURL("https://github.com/mvdan/unparam"),

linter.NewConfig(golinters.NewUnused(unusedCfg)).
linter.NewConfig(golinters.NewUnused(unusedCfg, staticcheckCfg)).
WithEnabledByDefault().
WithSince("v1.20.0").
WithLoadForGoAnalysis().
2 changes: 1 addition & 1 deletion pkg/logutils/logutils.go
Original file line number Diff line number Diff line change
@@ -59,7 +59,7 @@ const (
DebugKeyGoCritic = "gocritic" // Debugs `go-critic` linter.
DebugKeyMegacheck = "megacheck" // Debugs `staticcheck` related linters.
DebugKeyNolint = "nolint" // Debugs a filter excluding issues by `//nolint` comments.
DebugKeyRevive = "revive" // Debugs `revice` linter.
DebugKeyRevive = "revive" // Debugs `revive` linter.
)

func getEnabledDebugs() map[string]bool {
3 changes: 2 additions & 1 deletion pkg/result/processors/autogenerated_exclude_test.go
3 changes: 2 additions & 1 deletion pkg/result/processors/identifier_marker_test.go
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@ import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/golangci/golangci-lint/pkg/result"
)
@@ -50,7 +51,7 @@ func TestIdentifierMarker(t *testing.T) {

for _, c := range cases {
out, err := p.Process([]result.Issue{{Text: c.in}})
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, []result.Issue{{Text: c.out}}, out)
}
}
8 changes: 4 additions & 4 deletions pkg/result/processors/nolint_test.go
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@ import (

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"

"github.com/golangci/golangci-lint/pkg/config"
"github.com/golangci/golangci-lint/pkg/golinters"
@@ -173,9 +174,8 @@ func TestNolintInvalidLinterNameWithViolationOnTheSameLine(t *testing.T) {
processedIssues, err := p.Process(issues)
p.Finish()

assert.Len(t, processedIssues, 1)
require.NoError(t, err)
assert.Equal(t, issues, processedIssues)
assert.NoError(t, err)
}

func TestNolintAliases(t *testing.T) {
@@ -288,7 +288,7 @@ func TestNolintUnused(t *testing.T) {
enabledLintersSet := lintersdb.NewEnabledSet(dbManager, lintersdb.NewValidator(dbManager), enabledSetLog, cfg)

enabledLintersMap, err := enabledLintersSet.GetEnabledLintersMap()
assert.NoError(t, err)
require.NoError(t, err)

return NewNolint(log, dbManager, enabledLintersMap)
}
@@ -351,7 +351,7 @@ func TestNolintUnused(t *testing.T) {
enabledLintersSet := lintersdb.NewEnabledSet(dbManager, lintersdb.NewValidator(dbManager), enabledSetLog, cfg)

enabledLintersMap, err := enabledLintersSet.GetEnabledLintersMap()
assert.NoError(t, err)
require.NoError(t, err)
p := NewNolint(log, dbManager, enabledLintersMap)
defer p.Finish()

2 changes: 1 addition & 1 deletion pkg/result/processors/path_prefixer_test.go
Original file line number Diff line number Diff line change
@@ -47,7 +47,7 @@ func TestPathPrefixer_Process(t *testing.T) {
got, err := p.Process(tt.issues)
require.NoError(t, err)

assert.Equal(t, got, tt.want)
assert.Equal(t, tt.want, got)
})
}
}
3 changes: 2 additions & 1 deletion pkg/result/processors/processor_test.go
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@ import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/golangci/golangci-lint/pkg/result"
)
@@ -38,7 +39,7 @@ func process(t *testing.T, p Processor, issues ...result.Issue) []result.Issue {
t.Helper()

processedIssues, err := p.Process(issues)
assert.NoError(t, err)
require.NoError(t, err)
return processedIssues
}

3 changes: 2 additions & 1 deletion pkg/result/processors/skip_files_test.go
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@ import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/golangci/golangci-lint/pkg/result"
)
@@ -21,7 +22,7 @@ func newFileIssue(file string) result.Issue {

func newTestSkipFiles(t *testing.T, patterns ...string) *SkipFiles {
p, err := NewSkipFiles(patterns, "")
assert.NoError(t, err)
require.NoError(t, err)
return p
}

13 changes: 4 additions & 9 deletions pkg/result/processors/sort_results_test.go
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/golangci/golangci-lint/pkg/config"
"github.com/golangci/golangci-lint/pkg/result"
@@ -158,25 +159,19 @@ func TestNoSorting(t *testing.T) {
var sr = NewSortResults(&config.Config{})

results, err := sr.Process(tests)
require.NoError(t, err)
assert.Equal(t, tests, results)
assert.Nil(t, err, nil)
}

func TestSorting(t *testing.T) {
var tests = make([]result.Issue, len(issues))
copy(tests, issues)

var expected = make([]result.Issue, len(issues))
expected[0] = issues[3]
expected[1] = issues[2]
expected[2] = issues[1]
expected[3] = issues[0]

var cfg = config.Config{}
cfg.Output.SortResults = true
var sr = NewSortResults(&cfg)

results, err := sr.Process(tests)
assert.Equal(t, results, expected)
assert.Nil(t, err, nil)
require.NoError(t, err)
assert.Equal(t, []result.Issue{issues[3], issues[2], issues[1], issues[0]}, results)
}
4 changes: 2 additions & 2 deletions scripts/gen_github_action_config/go.mod
Original file line number Diff line number Diff line change
@@ -4,13 +4,13 @@ go 1.19

require (
github.com/shurcooL/githubv4 v0.0.0-20230215024106-420ad0987b9b
golang.org/x/oauth2 v0.11.0
golang.org/x/oauth2 v0.13.0
)

require (
github.com/golang/protobuf v1.5.3 // indirect
github.com/shurcooL/graphql v0.0.0-20220606043923-3cf50f8a0a29 // indirect
golang.org/x/net v0.14.0 // indirect
golang.org/x/net v0.17.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.31.0 // indirect
)
8 changes: 4 additions & 4 deletions scripts/gen_github_action_config/go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions test/linters_test.go
Original file line number Diff line number Diff line change
@@ -32,6 +32,7 @@ func TestSourcesFromTestdataSubDir(t *testing.T) {
"loggercheck",
"ginkgolinter",
"zerologlint",
"protogetter",
}

for _, dir := range subDirs {
3 changes: 2 additions & 1 deletion test/ruleguard/dup.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// go:build ruleguard
//go:build ruleguard

package ruleguard

import "github.com/quasilyte/go-ruleguard/dsl"
3 changes: 2 additions & 1 deletion test/ruleguard/rangeExprCopy.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// go:build ruleguard
//go:build ruleguard

package ruleguard

import (
3 changes: 2 additions & 1 deletion test/ruleguard/strings_simplify.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// go:build ruleguard
//go:build ruleguard

package ruleguard

import "github.com/quasilyte/go-ruleguard/dsl"
6 changes: 3 additions & 3 deletions test/run_test.go
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ import (
"path/filepath"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
_ "github.com/valyala/quicktemplate"

"github.com/golangci/golangci-lint/pkg/exitcodes"
@@ -536,7 +536,7 @@ func TestEnabledPresetsAreNotDuplicated(t *testing.T) {
func TestAbsPathDirAnalysis(t *testing.T) {
dir := filepath.Join("testdata_etc", "abspath") // abs paths don't work with testdata dir
absDir, err := filepath.Abs(dir)
assert.NoError(t, err)
require.NoError(t, err)

testshared.NewRunnerBuilder(t).
WithNoConfig().
@@ -555,7 +555,7 @@ func TestAbsPathDirAnalysis(t *testing.T) {
func TestAbsPathFileAnalysis(t *testing.T) {
dir := filepath.Join("testdata_etc", "abspath", "with_issue.go") // abs paths don't work with testdata dir
absDir, err := filepath.Abs(dir)
assert.NoError(t, err)
require.NoError(t, err)

testshared.NewRunnerBuilder(t).
WithNoConfig().
4 changes: 4 additions & 0 deletions test/testdata/configs/dupword_ignore_the.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
linters-settings:
dupword:
ignore:
- "the"
3 changes: 3 additions & 0 deletions test/testdata/configs/sloglint_args_on_sep_lines.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
linters-settings:
sloglint:
args-on-sep-lines: true
3 changes: 3 additions & 0 deletions test/testdata/configs/sloglint_attr_only.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
linters-settings:
sloglint:
attr-only: true
3 changes: 3 additions & 0 deletions test/testdata/configs/sloglint_kv_only.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
linters-settings:
sloglint:
kv-only: true
3 changes: 3 additions & 0 deletions test/testdata/configs/sloglint_no_raw_keys.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
linters-settings:
sloglint:
no-raw-keys: true
16 changes: 16 additions & 0 deletions test/testdata/dupword_ignore_the.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//golangcitest:args -Edupword
//golangcitest:config_path testdata/configs/dupword_ignore_the.yml
package testdata

import "fmt"

func duplicateWordInComments() {
// this line include duplicated word the the
fmt.Println("hello")
}

func duplicateWordInStr() {
a := "this line include duplicate word and and" // want `Duplicate words \(and\) found`
b := "print the\n the line, print the the \n\t the line. and and" // want `Duplicate words \(and\) found`
fmt.Println(a, b)
}
2 changes: 1 addition & 1 deletion test/testdata/forbidigo_example.go
Original file line number Diff line number Diff line change
@@ -10,6 +10,6 @@ import (

func Forbidigo() {
fmt.Printf("too noisy!!!") // want "use of `fmt\\.Printf` forbidden by pattern `fmt\\\\.Print\\.\\*`"
fmt2.Printf("too noisy!!!") // Not detected because analyze-types is false by default for backward compatbility.
fmt2.Printf("too noisy!!!") // Not detected because analyze-types is false by default for backward compatibility.
time.Sleep(time.Nanosecond) // want "no sleeping!"
}
2 changes: 1 addition & 1 deletion test/testdata/gochecknoglobals.go
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ import (
)

var noGlobalsVar int // want "noGlobalsVar is a global variable"
var ErrSomeType = errors.New("test that global erorrs aren't warned")
var ErrSomeType = errors.New("test that global errors aren't warned")

var (
OnlyDigites = regexp.MustCompile(`^\d+$`)
38 changes: 38 additions & 0 deletions test/testdata/gochecksumtype.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//golangcitest:args -Egochecksumtype
package testdata

import (
"log"
)

//sumtype:decl
type SumType interface{ isSumType() }

//sumtype:decl
type One struct{} // want "type 'One' is not an interface"

func (One) isSumType() {}

type Two struct{}

func (Two) isSumType() {}

func sumTypeTest() {
var sum SumType = One{}
switch sum.(type) { // want "exhaustiveness check failed for sum type.*SumType.*missing cases for Two"
case One:
}

switch sum.(type) { // want "exhaustiveness check failed for sum type.*SumType.*missing cases for Two"
case One:
default:
panic("??")
}

log.Println("??")

switch sum.(type) {
case One:
case Two:
}
}
29 changes: 29 additions & 0 deletions test/testdata/inamedparam.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//golangcitest:args -Einamedparam
package testdata

import "context"

type tStruct struct {
a int
}

type Doer interface {
Do() string
}

type NamedParam interface {
Void()

NoArgs() string

WithName(ctx context.Context, number int, toggle bool, tStruct *tStruct, doer Doer) (bool, error)

WithoutName(
context.Context, // want "interface method WithoutName must have named param for type context.Context"
int, // want "interface method WithoutName must have named param for type int"
bool, // want "interface method WithoutName must have named param for type bool"
tStruct, // want "interface method WithoutName must have named param for type tStruct"
Doer, // want "interface method WithoutName must have named param for type Doer"
struct{ b bool }, // want "interface method WithoutName must have all named params"
)
}
16 changes: 8 additions & 8 deletions test/testdata/nonamedreturns_custom.go
Original file line number Diff line number Diff line change
@@ -56,21 +56,21 @@ var (
)

// this should not match as the implementation does not need named parameters (see below)
type funcDefintion func(arg1, arg2 interface{}) (num int, err error)
type funcDefinition func(arg1, arg2 interface{}) (num int, err error)

func funcDefintionImpl(arg1, arg2 interface{}) (int, error) {
func funcDefinitionImpl(arg1, arg2 interface{}) (int, error) {
return 0, nil
}

func funcDefintionImpl2(arg1, arg2 interface{}) (num int, err error) { // want `named return "num" with type "int" found`
func funcDefinitionImpl2(arg1, arg2 interface{}) (num int, err error) { // want `named return "num" with type "int" found`
return 0, nil
}

func funcDefintionImpl3(arg1, arg2 interface{}) (num int, _ error) { // want `named return "num" with type "int" found`
func funcDefinitionImpl3(arg1, arg2 interface{}) (num int, _ error) { // want `named return "num" with type "int" found`
return 0, nil
}

func funcDefintionImpl4(arg1, arg2 interface{}) (_ int, _ error) {
func funcDefinitionImpl4(arg1, arg2 interface{}) (_ int, _ error) {
return 0, nil
}

@@ -88,12 +88,12 @@ func test() {
a := funcVar()
_ = a

var function funcDefintion
function = funcDefintionImpl
var function funcDefinition
function = funcDefinitionImpl
i, err := function("", "")
_ = i
_ = err
function = funcDefintionImpl2
function = funcDefinitionImpl2
i, err = function("", "")
_ = i
_ = err
49 changes: 49 additions & 0 deletions test/testdata/perfsprint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//golangcitest:args -Eperfsprint
package testdata

import "fmt"

func TestPerfsprint() {
var (
s string
err error
b bool
i int
i64 int64
ui uint
)

fmt.Sprintf("%s", s) // want "fmt.Sprintf can be replaced with just using the string"
fmt.Sprint(s) // want "fmt.Sprint can be replaced with just using the string"
fmt.Sprintf("%s", err) // want "fmt.Sprintf can be replaced with err.Error()"
fmt.Sprint(err) // want "fmt.Sprint can be replaced with err.Error()"
fmt.Sprintf("%t", b) // want "fmt.Sprintf can be replaced with faster strconv.FormatBool"
fmt.Sprint(b) // want "fmt.Sprint can be replaced with faster strconv.FormatBool"
fmt.Sprintf("%d", i) // want "fmt.Sprintf can be replaced with faster strconv.Itoa"
fmt.Sprint(i) // want "fmt.Sprint can be replaced with faster strconv.Itoa"
fmt.Sprintf("%d", i64) // want "fmt.Sprintf can be replaced with faster strconv.FormatInt"
fmt.Sprint(i64) // want "fmt.Sprint can be replaced with faster strconv.FormatInt"
fmt.Sprintf("%d", ui) // want "fmt.Sprintf can be replaced with faster strconv.FormatUint"
fmt.Sprint(ui) // want "fmt.Sprint can be replaced with faster strconv.FormatUint"
fmt.Sprintf("%x", []byte{'a'}) // want "fmt.Sprintf can be replaced with faster hex.EncodeToString"

fmt.Sprint("test", 42)
fmt.Sprint(42, 42)
fmt.Sprintf("test")
fmt.Sprintf("%v")
fmt.Sprintf("%d")
fmt.Sprintf("%d", 42, 42)
fmt.Sprintf("%#d", 42)
fmt.Sprintf("value %d", 42)
fmt.Sprintf("val%d", 42)
fmt.Sprintf("%s %v", "hello", "world")
fmt.Sprintf("%#v", 42)
fmt.Sprintf("%T", struct{ string }{})
fmt.Sprintf("%%v", 42)
fmt.Sprintf("%3d", 42)
fmt.Sprintf("% d", 42)
fmt.Sprintf("%-10d", 42)
fmt.Sprintf("%[2]d %[1]d\n", 11, 22)
fmt.Sprintf("%[3]*.[2]*[1]f", 12.0, 2, 6)
fmt.Sprintf("%d %d %#[1]x %#x", 16, 17)
}
16 changes: 16 additions & 0 deletions test/testdata/protogetter/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module protogetter

go 1.19

require (
google.golang.org/grpc v1.57.0
google.golang.org/protobuf v1.31.0
)

require (
github.com/golang/protobuf v1.5.3 // indirect
golang.org/x/net v0.9.0 // indirect
golang.org/x/sys v0.7.0 // indirect
golang.org/x/text v0.9.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 // indirect
)
20 changes: 20 additions & 0 deletions test/testdata/protogetter/go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions test/testdata/protogetter/proto/test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package proto

func (x *Embedded) CustomMethod() interface{} {
return nil
}

type Other struct {
}

func (x *Other) MyMethod(certs *Test) *Embedded {
return nil
}

func (x *Test) Equal(v *Test) bool {
return false
}

func (x *Embedded) SetS(s string) {
x.S = s
}

func (x *Embedded) SetMap(_ map[string]string) {
}
315 changes: 315 additions & 0 deletions test/testdata/protogetter/proto/test.pb.go
26 changes: 26 additions & 0 deletions test/testdata/protogetter/proto/test.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
syntax = "proto3";

option go_package = "github.com/ghostiam/protogetter/testdata/proto";

message Test {
double d = 1;
float f = 2;
int32 i32 = 3;
int64 i64 = 4;
uint32 u32 = 5;
uint64 u64 = 6;
bool t = 7;
bytes b = 8;
string s = 9;
Embedded embedded = 10;
repeated Embedded repeated_embeddeds = 11;
}

message Embedded {
string s = 1;
Embedded embedded = 2;
}

service Testing {
rpc call(Test) returns (Test);
}
109 changes: 109 additions & 0 deletions test/testdata/protogetter/proto/test_grpc.pb.go
151 changes: 151 additions & 0 deletions test/testdata/protogetter/protogetter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
//golangcitest:args -Eprotogetter
package protogetter

import (
"fmt"

"protogetter/proto"
)

type Test struct {
Embedded *proto.Embedded
}

func testInvalid(t *proto.Test) {
func(...interface{}) {}(t.B, t.D) // want `avoid direct access to proto field t\.B, use t\.GetB\(\) instead`
func(...interface{}) {}(t.GetB(), t.D) // want `avoid direct access to proto field t\.D, use t\.GetD\(\) instead`
func(...interface{}) {}(t.B, t.GetD()) // want `avoid direct access to proto field t\.B, use t\.GetB\(\) instead`

_ = t.D // want `avoid direct access to proto field t\.D, use t\.GetD\(\) instead`
_ = t.F // want `avoid direct access to proto field t\.F, use t\.GetF\(\) instead`
_ = t.I32 // want `avoid direct access to proto field t\.I32, use t\.GetI32\(\) instead`
_ = t.I64 // want `avoid direct access to proto field t\.I64, use t\.GetI64\(\) instead`
_ = t.U32 // want `avoid direct access to proto field t\.U32, use t\.GetU32\(\) instead`
_ = t.U64 // want `avoid direct access to proto field t\.U64, use t\.GetU64\(\) instead`
_ = t.T // want `avoid direct access to proto field t\.T, use t\.GetT\(\) instead`
_ = t.B // want `avoid direct access to proto field t\.B, use t\.GetB\(\) instead`
_ = t.S // want `avoid direct access to proto field t\.S, use t\.GetS\(\) instead`
_ = t.Embedded // want `avoid direct access to proto field t\.Embedded, use t\.GetEmbedded\(\) instead`
_ = t.Embedded.S // want `avoid direct access to proto field t\.Embedded\.S, use t\.GetEmbedded\(\)\.GetS\(\) instead`
_ = t.GetEmbedded().S // want `avoid direct access to proto field t\.GetEmbedded\(\)\.S, use t\.GetEmbedded\(\)\.GetS\(\) instead`
_ = t.Embedded.Embedded // want `avoid direct access to proto field t\.Embedded\.Embedded, use t\.GetEmbedded\(\)\.GetEmbedded\(\) instead`
_ = t.GetEmbedded().Embedded // want `avoid direct access to proto field t\.GetEmbedded\(\)\.Embedded, use t\.GetEmbedded\(\)\.GetEmbedded\(\) instead`
_ = t.Embedded.Embedded.S // want `avoid direct access to proto field t\.Embedded\.Embedded\.S, use t\.GetEmbedded\(\)\.GetEmbedded\(\).GetS\(\) instead`
_ = t.GetEmbedded().GetEmbedded().S // want `avoid direct access to proto field t\.GetEmbedded\(\)\.GetEmbedded\(\)\.S, use t\.GetEmbedded\(\)\.GetEmbedded\(\)\.GetS\(\) instead`
_ = t.RepeatedEmbeddeds // want `avoid direct access to proto field t\.RepeatedEmbeddeds, use t\.GetRepeatedEmbeddeds\(\) instead`
_ = t.RepeatedEmbeddeds[0] // want `avoid direct access to proto field t\.RepeatedEmbeddeds, use t\.GetRepeatedEmbeddeds\(\) instead`
_ = t.RepeatedEmbeddeds[0].S // want `avoid direct access to proto field t\.RepeatedEmbeddeds\[0\]\.S, use t\.GetRepeatedEmbeddeds\(\)\[0\]\.GetS\(\) instead`
_ = t.GetRepeatedEmbeddeds()[0].S // want `avoid direct access to proto field t\.GetRepeatedEmbeddeds\(\)\[0\]\.S, use t\.GetRepeatedEmbeddeds\(\)\[0\]\.GetS\(\) instead`
_ = t.RepeatedEmbeddeds[0].Embedded // want `avoid direct access to proto field t\.RepeatedEmbeddeds\[0\]\.Embedded, use t\.GetRepeatedEmbeddeds\(\)\[0\]\.GetEmbedded\(\) instead`
_ = t.GetRepeatedEmbeddeds()[0].Embedded // want `avoid direct access to proto field t\.GetRepeatedEmbeddeds\(\)\[0\]\.Embedded, use t\.GetRepeatedEmbeddeds\(\)\[0\]\.GetEmbedded\(\) instead`
_ = t.RepeatedEmbeddeds[0].Embedded.S // want `avoid direct access to proto field t\.RepeatedEmbeddeds\[0\]\.Embedded\.S, use t\.GetRepeatedEmbeddeds\(\)\[0\].GetEmbedded\(\).GetS\(\) instead`
_ = t.GetRepeatedEmbeddeds()[0].GetEmbedded().S // want `avoid direct access to proto field t\.GetRepeatedEmbeddeds\(\)\[0\].GetEmbedded\(\).S, use t\.GetRepeatedEmbeddeds\(\)\[0\].GetEmbedded\(\).GetS\(\) instead`
_ = t.RepeatedEmbeddeds[t.I64].Embedded.S // want `avoid direct access to proto field t\.RepeatedEmbeddeds\[t.I64\]\.Embedded\.S, use t\.GetRepeatedEmbeddeds\(\)\[t\.GetI64\(\)\].GetEmbedded\(\).GetS\(\) instead`
_ = t.GetRepeatedEmbeddeds()[t.I64].GetEmbedded().S // want `avoid direct access to proto field t\.GetRepeatedEmbeddeds\(\)\[t\.I64\]\.GetEmbedded\(\)\.S, use t\.GetRepeatedEmbeddeds\(\)\[t\.GetI64\(\)\]\.GetEmbedded\(\).GetS\(\) instead`

var many []*proto.Test
manyIndex := 42

_ = many[0].T // want `avoid direct access to proto field many\[0\]\.T, use many\[0\]\.GetT\(\) instead`
_ = many[1].Embedded.S // want `avoid direct access to proto field many\[1\]\.Embedded\.S, use many\[1\]\.GetEmbedded\(\)\.GetS\(\) instead`
_ = many[2].GetEmbedded().S // want `avoid direct access to proto field many\[2\]\.GetEmbedded\(\)\.S, use many\[2\].GetEmbedded\(\)\.GetS\(\) instead`
_ = many[3].Embedded.Embedded.S // want `avoid direct access to proto field many\[3\]\.Embedded\.Embedded\.S, use many\[3\].GetEmbedded\(\)\.GetEmbedded\(\)\.GetS\(\) instead`
_ = many[manyIndex].S // want `avoid direct access to proto field many\[manyIndex\]\.S, use many\[manyIndex\]\.GetS\(\) instead`

test := many[0].Embedded.S == "" || t.Embedded.CustomMethod() == nil || t.S == "" || t.Embedded == nil // want `avoid direct access to proto field many\[0\]\.Embedded\.S, use many\[0\]\.GetEmbedded\(\).GetS\(\) instead`
_ = test

other := proto.Other{}
_ = other.MyMethod(nil).S // want `avoid direct access to proto field other\.MyMethod\(nil\)\.S, use other\.MyMethod\(nil\)\.GetS\(\) instead`

ems := t.RepeatedEmbeddeds // want `avoid direct access to proto field t\.RepeatedEmbeddeds, use t\.GetRepeatedEmbeddeds\(\) instead`
_ = ems[len(ems)-1].S // want `avoid direct access to proto field ems\[len\(ems\)-1\]\.S, use ems\[len\(ems\)-1\]\.GetS\(\) instead`

ch := make(chan string)
ch <- t.S // want `avoid direct access to proto field t\.S, use t\.GetS\(\) instead`

for _, v := range t.RepeatedEmbeddeds { // want `avoid direct access to proto field t\.RepeatedEmbeddeds, use t\.GetRepeatedEmbeddeds\(\) instead`
_ = v
}

fn := func(...interface{}) bool { return false }
fn((*proto.Test)(nil).S) // want `avoid direct access to proto field \(\*proto\.Test\)\(nil\)\.S, use \(\*proto\.Test\)\(nil\)\.GetS\(\) instead`

var ptrs *[]proto.Test
_ = (*ptrs)[42].RepeatedEmbeddeds // want `avoid direct access to proto field \(\*ptrs\)\[42\]\.RepeatedEmbeddeds, use \(\*ptrs\)\[42\].GetRepeatedEmbeddeds\(\) instead`
_ = (*ptrs)[t.I64].RepeatedEmbeddeds // want `avoid direct access to proto field \(\*ptrs\)\[t\.I64\]\.RepeatedEmbeddeds, use \(\*ptrs\)\[t\.GetI64\(\)\].GetRepeatedEmbeddeds\(\) instead`

var anyType interface{}
_ = anyType.(*proto.Test).S // want `avoid direct access to proto field anyType\.\(\*proto\.Test\)\.S, use anyType\.\(\*proto\.Test\)\.GetS\(\) instead`

t.Embedded.SetS("test") // want `avoid direct access to proto field t\.Embedded\.SetS\("test"\), use t\.GetEmbedded\(\)\.SetS\("test"\) instead`
t.Embedded.SetMap(map[string]string{"test": "test"}) // want `avoid direct access to proto field t\.Embedded\.SetMap\(map\[string\]string{"test": "test"}\), use t\.GetEmbedded\(\)\.SetMap\(map\[string\]string{"test": "test"}\) instead`
}

func testValid(t *proto.Test) {
func(...interface{}) {}(t.GetB(), t.GetD())
func(...interface{}) {}(&t.B, &t.D)

_, t.T = true, true
_, t.T, _ = true, true, false
_, _, t.T = true, true, false
t.T, _ = true, true
t.D = 2
t.I32++
t.I32 += 2

fmt.Scanf("Test", &t.S, &t.B, &t.T)

t.D = 1.0
t.F = 1.0
t.I32 = 1
t.I64 = 1
t.U32 = 1
t.U64 = 1
t.T = true
t.B = []byte{1}
t.S = "1"
t.Embedded = &proto.Embedded{}
t.Embedded.S = "1"
t.GetEmbedded().S = "1"
t.Embedded.Embedded = &proto.Embedded{}
t.GetEmbedded().Embedded = &proto.Embedded{}
t.Embedded.Embedded.S = "1"
t.GetEmbedded().GetEmbedded().S = "1"
t.RepeatedEmbeddeds = []*proto.Embedded{{S: "1"}}

_ = t.GetD()
_ = t.GetF()
_ = t.GetI32()
_ = t.GetI64()
_ = t.GetU32()
_ = t.GetU64()
_ = t.GetT()
_ = t.GetB()
_ = t.GetS()
_ = t.GetEmbedded()
_ = t.GetEmbedded().GetS()
_ = t.GetEmbedded().GetEmbedded()
_ = t.GetEmbedded().GetEmbedded().GetS()
_ = t.GetRepeatedEmbeddeds()
_ = t.GetRepeatedEmbeddeds()[0]
_ = t.GetRepeatedEmbeddeds()[0].GetS()
_ = t.GetRepeatedEmbeddeds()[0].GetEmbedded()
_ = t.GetRepeatedEmbeddeds()[0].GetEmbedded().GetS()

other := proto.Other{}
other.MyMethod(nil).CustomMethod()
other.MyMethod(nil).GetS()

var tt Test
_ = tt.Embedded.GetS()
_ = tt.Embedded.GetEmbedded().GetS()

ems := t.GetRepeatedEmbeddeds()
_ = ems[len(ems)-1].GetS()

ch := make(chan string)
ch <- t.GetS()

t.Equal(&proto.Test{S: "test", I64: 42})
}
13 changes: 13 additions & 0 deletions test/testdata/sloglint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//go:build go1.21

//golangcitest:args -Esloglint
package testdata

import "log/slog"

func test() {
slog.Info("msg", "foo", 1, "bar", 2)
slog.Info("msg", slog.Int("foo", 1), slog.Int("bar", 2))

slog.Info("msg", "foo", 1, slog.Int("bar", 2)) // want `key-value pairs and attributes should not be mixed`
}
17 changes: 17 additions & 0 deletions test/testdata/sloglint_args_on_sep_lines.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//go:build go1.21

//golangcitest:args -Esloglint
//golangcitest:config_path testdata/configs/sloglint_args_on_sep_lines.yml
package testdata

import "log/slog"

func test() {
slog.Info("msg", "foo", 1)
slog.Info("msg",
"foo", 1,
"bar", 2,
)

slog.Info("msg", "foo", 1, "bar", 2) // want `arguments should be put on separate lines`
}
13 changes: 13 additions & 0 deletions test/testdata/sloglint_attr_only.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//go:build go1.21

//golangcitest:args -Esloglint
//golangcitest:config_path testdata/configs/sloglint_attr_only.yml
package testdata

import "log/slog"

func test() {
slog.Info("msg", slog.Int("foo", 1), slog.Int("bar", 2))

slog.Info("msg", "foo", 1, "bar", 2) // want `key-value pairs should not be used`
}
13 changes: 13 additions & 0 deletions test/testdata/sloglint_kv_only.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//go:build go1.21

//golangcitest:args -Esloglint
//golangcitest:config_path testdata/configs/sloglint_kv_only.yml
package testdata

import "log/slog"

func test() {
slog.Info("msg", "foo", 1, "bar", 2)

slog.Info("msg", slog.Int("foo", 1), slog.Int("bar", 2)) // want `attributes should not be used`
}
21 changes: 21 additions & 0 deletions test/testdata/sloglint_no_raw_keys.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//go:build go1.21

//golangcitest:args -Esloglint
//golangcitest:config_path testdata/configs/sloglint_no_raw_keys.yml
package testdata

import "log/slog"

const foo = "foo"

func Foo(value int) slog.Attr {
return slog.Int("foo", value)
}

func test() {
slog.Info("msg", foo, 1)
slog.Info("msg", Foo(1))

slog.Info("msg", "foo", 1) // want `raw keys should not be used`
slog.Info("msg", slog.Int("foo", 1)) // want `raw keys should not be used`
}
6 changes: 3 additions & 3 deletions test/testdata/sqlclosecheck.go
Original file line number Diff line number Diff line change
@@ -68,7 +68,7 @@ func rowsCorrectDefer() {
}

func rowsMissingClose() {
rows, err := db.QueryContext(ctx, "SELECT name FROM users WHERE age=?", age) // want "Rows/Stmt was not closed"
rows, err := db.QueryContext(ctx, "SELECT name FROM users WHERE age=?", age) // want "Rows/Stmt/NamedStmt was not closed"
if err != nil {
log.Fatal(err)
}
@@ -91,7 +91,7 @@ func rowsMissingClose() {
}

func rowsMissingCloseG[T ~int64](db *sql.DB, a T) {
rows, _ := db.Query("select id from tb") // want "Rows/Stmt was not closed"
rows, _ := db.Query("select id from tb") // want "Rows/Stmt/NamedStmt was not closed"
for rows.Next() {
// ...
}
@@ -208,7 +208,7 @@ func stmtCorrectDefer() {

func stmtMissingClose() {
// In normal use, create one Stmt when your process starts.
stmt, err := db.PrepareContext(ctx, "SELECT username FROM users WHERE id = ?") // want "Rows/Stmt was not closed"
stmt, err := db.PrepareContext(ctx, "SELECT username FROM users WHERE id = ?") // want "Rows/Stmt/NamedStmt was not closed"
if err != nil {
log.Fatal(err)
}
62 changes: 62 additions & 0 deletions test/testdata/testifylint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//golangcitest:args -Etestifylint
package testdata

import (
"io"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
)

func TestTestifylint(t *testing.T) {
var (
predicate bool
resultInt int
resultFloat float64
arr []string
err error
)

assert.Equal(t, predicate, true) // want "bool-compare: use assert\\.True"
assert.True(t, resultInt == 1) // want "compares: use assert\\.Equal"
assert.Equal(t, len(arr), 0) // want "empty: use assert\\.Empty"
assert.Error(t, err, io.EOF) // want "error-is-as: invalid usage of assert\\.Error, use assert\\.ErrorIs instead"
assert.Nil(t, err) // want "error-nil: use assert\\.NoError"
assert.Equal(t, resultInt, 42) // want "expected-actual: need to reverse actual and expected values"
assert.Equal(t, resultFloat, 42.42) // want "float-compare: use assert\\.InEpsilon \\(or InDelta\\)"
assert.Equal(t, len(arr), 10) // want "len: use assert\\.Len"

assert.True(t, predicate)
assert.Equal(t, resultInt, 1) // want "expected-actual: need to reverse actual and expected values"
assert.Empty(t, arr)
assert.ErrorIs(t, err, io.EOF) // want "require-error: for error assertions use require"
assert.NoError(t, err) // want "require-error: for error assertions use require"
assert.Equal(t, 42, resultInt)
assert.InEpsilon(t, 42.42, resultFloat, 0.0001)
assert.Len(t, arr, 10)

require.ErrorIs(t, err, io.EOF)
require.NoError(t, err)

t.Run("formatted", func(t *testing.T) {
assert.Equal(t, predicate, true, "message") // want "bool-compare: use assert\\.True"
assert.Equal(t, predicate, true, "message %d", 42) // want "bool-compare: use assert\\.True"
assert.Equalf(t, predicate, true, "message") // want "bool-compare: use assert\\.Truef"
assert.Equalf(t, predicate, true, "message %d", 42) // want "bool-compare: use assert\\.Truef"
})
}

type SuiteExample struct {
suite.Suite
}

func TestSuiteExample(t *testing.T) {
suite.Run(t, new(SuiteExample))
}

func (s *SuiteExample) TestAll() {
var b bool
s.Assert().True(b) // want "suite-extra-assert-call: need to simplify the assertion to s\\.True"
}
16 changes: 8 additions & 8 deletions test/testshared/directives_test.go
Original file line number Diff line number Diff line change
@@ -30,42 +30,42 @@ func Test_evaluateBuildTags(t *testing.T) {
assert assert.BoolAssertionFunc
}{
{
desc: "",
desc: "old build tag syntax, version inside the range",
tag: "// +build go1.18",
assert: assert.True,
},
{
desc: "",
desc: "old build tag syntax, version outside the range",
tag: "// +build go1.42",
assert: assert.False,
},
{
desc: "",
desc: "version inside the range",
tag: "//go:build go1.18",
assert: assert.True,
},
{
desc: "",
desc: "version outside the range",
tag: "//go:build go1.42",
assert: assert.False,
},
{
desc: "",
desc: "supported OS",
tag: "//go:build " + runtime.GOOS,
assert: assert.True,
},
{
desc: "",
desc: "negate unsupported OS",
tag: "//go:build !wondiws",
assert: assert.True,
},
{
desc: "",
desc: "unsupported OS",
tag: "//go:build wondiws",
assert: assert.False,
},
{
desc: "",
desc: "version inside the range and supported OS",
tag: "//go:build go1.18 && " + runtime.GOOS,
assert: assert.True,
},
2 changes: 1 addition & 1 deletion test/testshared/runner.go
Original file line number Diff line number Diff line change
@@ -349,7 +349,7 @@ func InstallGolangciLint(tb testing.TB) string {
tb.Log(string(output))
}

assert.NoError(tb, err, "Can't go install golangci-lint %s", string(output))
require.NoError(tb, err, "Can't go install golangci-lint %s", string(output))
}

abs, err := filepath.Abs(defaultBinaryName())
10 changes: 5 additions & 5 deletions tools/go.mod
Original file line number Diff line number Diff line change
@@ -199,15 +199,15 @@ require (
go.mongodb.org/mongo-driver v1.11.3 // indirect
go.opencensus.io v0.24.0 // indirect
gocloud.dev v0.29.0 // indirect
golang.org/x/crypto v0.9.0 // indirect
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect
golang.org/x/mod v0.10.0 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/oauth2 v0.7.0 // indirect
golang.org/x/sync v0.2.0 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/term v0.8.0 // indirect
golang.org/x/text v0.9.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/term v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.7.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
Loading