diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index b9c41a3..69eb30c 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,16 +1,18 @@ name: golangci-lint + on: push: branches: - main - - master pull_request: + branches: + - main permissions: contents: read env: - GOLANGCI_LINT_VERSION: v1.61 + GOLANGCI_LINT_VERSION: v2.4 CGO_ENABLED: 0 jobs: @@ -22,7 +24,7 @@ jobs: name: lint runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-go@v5 with: go-version: ${{ matrix.go }} @@ -35,6 +37,6 @@ jobs: git diff --exit-code go.sum - name: golangci-lint - uses: golangci/golangci-lint-action@v6 + uses: golangci/golangci-lint-action@v8 with: version: ${{ env.GOLANGCI_LINT_VERSION }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1f811ee..d3d5af4 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,10 +1,12 @@ name: Tests + on: push: branches: - main - - master pull_request: + branches: + - main permissions: contents: read @@ -21,7 +23,7 @@ jobs: os: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-go@v5 with: go-version: ${{ matrix.go-version }} diff --git a/.golangci.yml b/.golangci.yml index 789bc7e..e5845b6 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,12 +1,19 @@ +version: "2" + +formatters: + enable: + - gci + - gofumpt + linters: - disable-all: true + default: none enable: - asasalint - asciicheck - bidichk - containedctx - contextcheck -# - copyloopvar + - copyloopvar - cyclop - dogsled - dupl @@ -19,7 +26,6 @@ linters: - fatcontext - forbidigo - funlen - - gci - gocheckcompilerdirectives - gochecknoglobals - gochecknoinits @@ -29,20 +35,16 @@ linters: - gocyclo - godot - godox - - gofmt - - gofumpt - - goimports - gomoddirectives - gomodguard - goprintffuncname - gosec - - gosimple - govet - importas - inamedparam - ineffassign - interfacebloat -# - intrange + - intrange - ireturn - loggercheck - maintidx @@ -61,10 +63,8 @@ linters: - reassign - revive - staticcheck - - stylecheck - tagalign - tagliatelle - - tenv - testableexamples - testifylint - thelper @@ -76,33 +76,25 @@ linters: - wastedassign - whitespace - wrapcheck - - wsl + - wsl_v5 -linters-settings: - stylecheck: - checks: ['*', '-ST1000'] - cyclop: - max-complexity: 15 + settings: + cyclop: + max-complexity: 15 + staticcheck: + checks: + - '*' + - -ST1000 + exclusions: + warn-unused: true + presets: + - comments + rules: + - linters: + - gochecknoglobals + path: pkg/analyzer/analyzer.go + text: Analyzer is a global variable issues: - exclude-use-default: false max-issues-per-linter: 0 max-same-issues: 0 - exclude-rules: - - linters: - - revive - text: "package-comments: should have a package comment" - - linters: - - revive - text: "exported: .+ should have comment or be unexported" - - path: pkg/analyzer/analyzer.go - linters: - - gochecknoglobals - text: "Analyzer is a global variable" - -output: - show-stats: true - sort-results: true - sort-order: - - linter - - file diff --git a/go.mod b/go.mod index 8e0ab8f..8fd40c9 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,10 @@ module github.com/golangci/go-printf-func-name -go 1.22.0 +go 1.23.0 -require golang.org/x/tools v0.26.0 +require golang.org/x/tools v0.36.0 require ( - golang.org/x/mod v0.21.0 // indirect - golang.org/x/sync v0.8.0 // indirect + golang.org/x/mod v0.27.0 // indirect + golang.org/x/sync v0.16.0 // indirect ) diff --git a/go.sum b/go.sum index 486c8d4..e1a8435 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,8 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= -golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= +golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= +golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= +golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= +golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= diff --git a/pkg/analyzer/analyzer.go b/pkg/analyzer/analyzer.go index bce4b24..0b41500 100644 --- a/pkg/analyzer/analyzer.go +++ b/pkg/analyzer/analyzer.go @@ -16,7 +16,7 @@ var Analyzer = &analysis.Analyzer{ Requires: []*analysis.Analyzer{inspect.Analyzer}, } -func run(pass *analysis.Pass) (interface{}, error) { +func run(pass *analysis.Pass) (any, error) { insp := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) nodeFilter := []ast.Node{ @@ -44,24 +44,21 @@ func run(pass *analysis.Pass) (interface{}, error) { return } - if formatParamNames := params[len(params)-2].Names; len(formatParamNames) == 0 || formatParamNames[len(formatParamNames)-1].Name != "format" { + formatParamNames := params[len(params)-2].Names + if len(formatParamNames) == 0 || formatParamNames[len(formatParamNames)-1].Name != "format" { return } argsParamType, ok := params[len(params)-1].Type.(*ast.Ellipsis) - if !ok { // args are not ellipsis (...args) + if !ok { + // args are not ellipsis (...args) return } - elementType, ok := argsParamType.Elt.(*ast.InterfaceType) - if !ok { // args are not of interface type, but we need interface{} + if !isAny(argsParamType) { return } - if elementType.Methods != nil && len(elementType.Methods.List) != 0 { - return // has >= 1 method in interface, but we need an empty interface "interface{}" - } - if strings.HasSuffix(funcDecl.Name.Name, "f") { return } @@ -72,3 +69,22 @@ func run(pass *analysis.Pass) (interface{}, error) { return nil, nil } + +func isAny(ell *ast.Ellipsis) bool { + switch elt := ell.Elt.(type) { + case *ast.InterfaceType: + if elt.Methods != nil && len(elt.Methods.List) != 0 { + // has >= 1 method in interface, but we need an empty interface "interface{}" + return false + } + + return true + + case *ast.Ident: + if elt.Name == "any" { + return true + } + } + + return false +} diff --git a/testdata/src/p/p.go b/testdata/src/p/p.go index ef764c2..84ae1b7 100644 --- a/testdata/src/p/p.go +++ b/testdata/src/p/p.go @@ -28,3 +28,9 @@ func prinfLikeFunc(format string, args ...interface{}) {} // want "printf-like f func prinfLikeFuncWithExtraArgs1(extraArg, format string, args ...interface{}) {} // want "printf-like formatting function" func prinfLikeFuncWithExtraArgs2(extraArg int, format string, args ...interface{}) {} // want "printf-like formatting function" + +func prinfLikeFuncAny(format string, args ...any) {} // want "printf-like formatting function" + +func prinfLikeFuncWithExtraArgs1Any(extraArg, format string, args ...any) {} // want "printf-like formatting function" + +func prinfLikeFuncWithExtraArgs2Any(extraArg int, format string, args ...any) {} // want "printf-like formatting function"