Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 11 additions & 50 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -1,24 +1,20 @@
version: "2"
run:
tests: true

linters:
default: all
disable:
- decorder
- depguard
- err113
- exhaustruct
- gochecknoglobals
- gochecknoinits
- godox
- nlreturn
- nonamedreturns
- paralleltest
- recvcheck
- testpackage
- varnamelen
- wrapcheck
- wsl

settings:
cyclop:
max-complexity: 30
Expand Down Expand Up @@ -70,46 +66,27 @@ linters:
min-complexity: 30
godox:
keywords:
- NOTE
- OPTIMIZE
- HACK
- FIXME
govet:
enable:
- atomicalign
disable:
- 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
- error
- 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
Expand Down Expand Up @@ -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
Expand All @@ -174,34 +148,21 @@ linters:
- nilnil
- unparam
- gosmopolitan
path: _test\.go
paths:
- http/internal
- third_party$
- builtin$
- examples$


formatters:
enable:
- gci
- gofmt
- gofumpt
- goimports
settings:
gci:
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

3 changes: 2 additions & 1 deletion cmd/noinlineerr/main.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package main

import (
"github.com/AlwxSin/noinlineerr"
"golang.org/x/tools/go/analysis/singlechecker"

"github.com/AlwxSin/noinlineerr"
)

func main() {
Expand Down
83 changes: 44 additions & 39 deletions noinlineerr.go
Original file line number Diff line number Diff line change
Expand Up @@ -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: "Dissallows 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 cluase 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
}
6 changes: 3 additions & 3 deletions testdata/src/a/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,19 @@ 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,
); err != nil {
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
}
Expand Down