From d905abc052453beb548e309c476bceaac647507c Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Fri, 23 May 2025 17:19:46 +0200 Subject: [PATCH 1/3] chore: clean golangci-lint configuration --- .golangci.yml | 61 ++++++++--------------------------------- cmd/noinlineerr/main.go | 3 +- 2 files changed, 13 insertions(+), 51 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 02c853a..36b3155 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,6 +1,5 @@ version: "2" -run: - tests: true + linters: default: all disable: @@ -8,9 +7,6 @@ linters: - depguard - err113 - exhaustruct - - gochecknoglobals - - gochecknoinits - - godox - nlreturn - nonamedreturns - paralleltest @@ -18,7 +14,7 @@ linters: - testpackage - varnamelen - wrapcheck - - wsl + settings: cyclop: max-complexity: 30 @@ -70,9 +66,7 @@ linters: min-complexity: 30 godox: keywords: - - NOTE - - OPTIMIZE - - HACK + - FIXME govet: enable: - atomicalign @@ -80,13 +74,6 @@ linters: - shadow enable-all: false disable-all: false - settings: - printf: - funcs: - - (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof - - (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf - - (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf - - (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf ireturn: allow: - anon @@ -94,22 +81,12 @@ linters: - empty - stdlib - generic - - github.com/doug-martin/goqu/v9/exp.* - - github.com/AlwxSin/simplegen.SpecData - - github.com/99designs/gqlgen/graphql.Marshaler - - github.com/Khan/genqlient/graphql.Client - - utils.GenericSyncMap lll: line-length: 160 - tab-width: 1 misspell: locale: US - ignore-rules: - - someword mnd: ignored-functions: - - ^math\. - - ^http\.StatusText$ - ^strings\.SplitN nakedret: max-func-lines: 30 @@ -146,18 +123,15 @@ linters: whitespace: multi-if: false multi-func: false + exclusions: - generated: lax presets: - comments - common-false-positives - - legacy - std-error-handling rules: - - linters: - - lll - path: resolvers\.go - - linters: + - path: _test\.go + linters: - bodyclose - containedctx - contextcheck @@ -174,16 +148,11 @@ linters: - nilnil - unparam - gosmopolitan - path: _test\.go - paths: - - http/internal - - third_party$ - - builtin$ - - examples$ + + formatters: enable: - gci - - gofmt - gofumpt - goimports settings: @@ -191,17 +160,9 @@ formatters: sections: - standard - default - - prefix(noinlineerr) + - localmodule - blank - dot - gofmt: - simplify: true gofumpt: - module-path: noinlineerr - exclusions: - generated: lax - paths: - - http/internal - - third_party$ - - builtin$ - - examples$ + extra-rules: true + diff --git a/cmd/noinlineerr/main.go b/cmd/noinlineerr/main.go index 7d8a328..351620f 100644 --- a/cmd/noinlineerr/main.go +++ b/cmd/noinlineerr/main.go @@ -1,8 +1,9 @@ package main import ( - "github.com/AlwxSin/noinlineerr" "golang.org/x/tools/go/analysis/singlechecker" + + "github.com/AlwxSin/noinlineerr" ) func main() { From d60ac44f70f9785a0bbe85a8522c521c9c2b978a Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Fri, 23 May 2025 17:26:50 +0200 Subject: [PATCH 2/3] fix: typos --- noinlineerr.go | 6 +++--- testdata/src/a/main.go | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/noinlineerr.go b/noinlineerr.go index 5f0368e..33bd3c1 100644 --- a/noinlineerr.go +++ b/noinlineerr.go @@ -14,7 +14,7 @@ func NewAnalyzer() *analysis.Analyzer { return &analysis.Analyzer{ Name: "noinlineerr", - Doc: "Dissallows inline error handling using `if err := ...; err != nil", + Doc: "Disallows inline error handling using `if err := ...; err != nil`", Run: a.run, } } @@ -28,7 +28,7 @@ func (a *analyzer) run(pass *analysis.Pass) (any, error) { return true } - // check if the init cluase is an assignment + // check if the init clause is an assignment assignStmt, ok := ifStmt.Init.(*ast.AssignStmt) if !ok { return true @@ -50,7 +50,7 @@ func (a *analyzer) run(pass *analysis.Pass) (any, error) { // report usage of inline error assignment pass.Reportf( ident.Pos(), - "avoid inline error handling using `if err := ...; err != nil; use plain assignment `err := ...", + "avoid inline error handling using `if err := ...; err != nil`; use plain assignment `err := ...`", ) } return true diff --git a/testdata/src/a/main.go b/testdata/src/a/main.go index e94c573..cc70d30 100644 --- a/testdata/src/a/main.go +++ b/testdata/src/a/main.go @@ -31,11 +31,11 @@ func valid() error { } func invalid() error { - if err := doSomething(); err != nil { // want "avoid inline error handling using `if err := ...; err != nil; use plain assignment `err := ..." + if err := doSomething(); err != nil { // want "avoid inline error handling using `if err := ...; err != nil`; use plain assignment `err := ...`" return err } - if err := doSmthManyArgs(0, // want "avoid inline error handling using `if err := ...; err != nil; use plain assignment `err := ..." + if err := doSmthManyArgs(0, // want "avoid inline error handling using `if err := ...; err != nil`; use plain assignment `err := ...`" 0, 0, 0, @@ -43,7 +43,7 @@ func invalid() error { return err } - if _, err := doSmthMultipleReturn(); err != nil { // want "avoid inline error handling using `if err := ...; err != nil; use plain assignment `err := ..." + if _, err := doSmthMultipleReturn(); err != nil { // want "avoid inline error handling using `if err := ...; err != nil`; use plain assignment `err := ...`" _ = false return err } From 62b1c383e9bfad7643524be78e323c4ce1b7ea3c Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Fri, 23 May 2025 17:27:27 +0200 Subject: [PATCH 3/3] feat: use inspector --- noinlineerr.go | 83 ++++++++++++++++++++++++++------------------------ 1 file changed, 44 insertions(+), 39 deletions(-) diff --git a/noinlineerr.go b/noinlineerr.go index 33bd3c1..611b4d9 100644 --- a/noinlineerr.go +++ b/noinlineerr.go @@ -5,56 +5,61 @@ import ( "strings" "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/passes/inspect" + "golang.org/x/tools/go/ast/inspector" ) -type analyzer struct{} - func NewAnalyzer() *analysis.Analyzer { - a := &analyzer{} - return &analysis.Analyzer{ - Name: "noinlineerr", - Doc: "Disallows inline error handling using `if err := ...; err != nil`", - Run: a.run, + Name: "noinlineerr", + Doc: "Disallows inline error handling (`if err := ...; err != nil {`)", + Run: run, + Requires: []*analysis.Analyzer{inspect.Analyzer}, } } -func (a *analyzer) run(pass *analysis.Pass) (any, error) { - for _, file := range pass.Files { - ast.Inspect(file, func(n ast.Node) bool { - // look for if statements with an Init clause - ifStmt, ok := n.(*ast.IfStmt) - if !ok || ifStmt.Init == nil { - return true - } +func run(pass *analysis.Pass) (any, error) { + insp, ok := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) + if !ok { + return nil, nil //nolint:nilnil // nothing to return + } + + nodeFilter := []ast.Node{ + (*ast.IfStmt)(nil), + } - // check if the init clause is an assignment - assignStmt, ok := ifStmt.Init.(*ast.AssignStmt) + insp.Preorder(nodeFilter, func(n ast.Node) { + ifStmt, ok := n.(*ast.IfStmt) + if !ok || ifStmt.Init == nil { + return + } + + // check if the init clause is an assignment + assignStmt, ok := ifStmt.Init.(*ast.AssignStmt) + if !ok { + return + } + + // iterate over left-hand side variables of the assignment + for _, lhs := range assignStmt.Lhs { + ident, ok := lhs.(*ast.Ident) if !ok { - return true + continue } - // iterate over left-hand side variables of the assignment - for _, lhs := range assignStmt.Lhs { - ident, ok := lhs.(*ast.Ident) - if !ok { - continue - } - - // confirm type is error - obj := pass.TypesInfo.ObjectOf(ident) - if obj == nil || !strings.Contains(obj.Type().String(), "error") { - continue - } - - // report usage of inline error assignment - pass.Reportf( - ident.Pos(), - "avoid inline error handling using `if err := ...; err != nil`; use plain assignment `err := ...`", - ) + // confirm type is error + obj := pass.TypesInfo.ObjectOf(ident) + if obj == nil || !strings.Contains(obj.Type().String(), "error") { + continue } - return true - }) - } + + // report usage of inline error assignment + pass.Reportf( + ident.Pos(), + "avoid inline error handling using `if err := ...; err != nil`; use plain assignment `err := ...`", + ) + } + }) + return nil, nil //nolint:nilnil // nothing to return }