Skip to content

Commit 1c7344e

Browse files
authored
Add more granular checks when checking error cuddling (#198)
1 parent 5384b8c commit 1c7344e

File tree

3 files changed

+204
-17
lines changed

3 files changed

+204
-17
lines changed

testdata/src/default_config/err/err.go

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package testpkg
22

3-
import "errors"
3+
import (
4+
"errors"
5+
"fmt"
6+
)
47

58
func fn1() {
69
err := errors.New("x") // want +1 `unnecessary whitespace \(err\)`
@@ -127,3 +130,87 @@ LABEL:
127130
panic(err)
128131
}
129132
}
133+
134+
func aFunctionThatCanFail() error {
135+
return nil
136+
}
137+
138+
func fn10() error {
139+
withContext := func(err error) error {
140+
return fmt.Errorf("some error, %w", err)
141+
}
142+
143+
if err := aFunctionThatCanFail(); err != nil {
144+
return withContext(err)
145+
}
146+
147+
return nil
148+
}
149+
150+
func fn11() error {
151+
err := fmt.Errorf("some error, %w", err)
152+
153+
if err := aFunctionThatCanFail(); err != nil {
154+
return err
155+
}
156+
157+
return nil
158+
}
159+
160+
func fn12(err error) error {
161+
withContext := func(err error) error {
162+
return fmt.Errorf("some error, %w", err)
163+
}
164+
165+
if err != nil {
166+
return withContext(err)
167+
}
168+
169+
return nil
170+
}
171+
172+
func fn13() error {
173+
err := func(err error) error {
174+
return fmt.Errorf("some error, %w", err)
175+
}
176+
177+
if err != nil {
178+
return err
179+
}
180+
181+
return nil
182+
}
183+
184+
func fn14(err error) error {
185+
var withContext = func(err error) error {
186+
return fmt.Errorf("some error, %w", err)
187+
}
188+
189+
if err != nil {
190+
return withContext(err)
191+
}
192+
193+
return nil
194+
}
195+
196+
func fn15(err error) error {
197+
withContext := func(err error) error {
198+
return fmt.Errorf("some error, %w", err)
199+
}(nil) // want +1 `unnecessary whitespace \(err\)`
200+
201+
if withContext != nil {
202+
return withContext(err)
203+
}
204+
205+
return nil
206+
}
207+
208+
func fn16(err error) error {
209+
var notErr = fmt.Errorf("some error, %w", err)
210+
211+
if err != nil {
212+
return notErr
213+
}
214+
215+
return nil
216+
}

testdata/src/default_config/err/err.go.golden

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package testpkg
22

3-
import "errors"
3+
import (
4+
"errors"
5+
"fmt"
6+
)
47

58
func fn1() {
69
err := errors.New("x") // want +1 `unnecessary whitespace \(err\)`
@@ -124,3 +127,87 @@ LABEL:
124127
panic(err)
125128
}
126129
}
130+
131+
func aFunctionThatCanFail() error {
132+
return nil
133+
}
134+
135+
func fn10() error {
136+
withContext := func(err error) error {
137+
return fmt.Errorf("some error, %w", err)
138+
}
139+
140+
if err := aFunctionThatCanFail(); err != nil {
141+
return withContext(err)
142+
}
143+
144+
return nil
145+
}
146+
147+
func fn11() error {
148+
err := fmt.Errorf("some error, %w", err)
149+
150+
if err := aFunctionThatCanFail(); err != nil {
151+
return err
152+
}
153+
154+
return nil
155+
}
156+
157+
func fn12(err error) error {
158+
withContext := func(err error) error {
159+
return fmt.Errorf("some error, %w", err)
160+
}
161+
162+
if err != nil {
163+
return withContext(err)
164+
}
165+
166+
return nil
167+
}
168+
169+
func fn13() error {
170+
err := func(err error) error {
171+
return fmt.Errorf("some error, %w", err)
172+
}
173+
174+
if err != nil {
175+
return err
176+
}
177+
178+
return nil
179+
}
180+
181+
func fn14(err error) error {
182+
var withContext = func(err error) error {
183+
return fmt.Errorf("some error, %w", err)
184+
}
185+
186+
if err != nil {
187+
return withContext(err)
188+
}
189+
190+
return nil
191+
}
192+
193+
func fn15(err error) error {
194+
withContext := func(err error) error {
195+
return fmt.Errorf("some error, %w", err)
196+
}(nil) // want +1 `unnecessary whitespace \(err\)`
197+
if withContext != nil {
198+
return withContext(err)
199+
}
200+
201+
return nil
202+
}
203+
204+
func fn16(err error) error {
205+
var notErr = fmt.Errorf("some error, %w", err)
206+
207+
if err != nil {
208+
return notErr
209+
}
210+
211+
return nil
212+
}
213+

wsl.go

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ func (w *WSL) checkCuddlingMaxAllowed(
297297
// If we don't have any statements above, we only care about potential error
298298
// cuddling (for if statements) so check that.
299299
if numStmtsAbove == 0 {
300-
w.checkError(numStmtsAbove, stmt, previousNode, previousIdents, cursor)
300+
w.checkError(numStmtsAbove, stmt, previousNode, cursor)
301301
return
302302
}
303303

@@ -593,7 +593,6 @@ func (w *WSL) checkError(
593593
stmtsAbove int,
594594
ifStmt ast.Node,
595595
previousNode ast.Node,
596-
previousIdents []*ast.Ident,
597596
cursor *Cursor,
598597
) {
599598
if _, ok := w.config.Checks[CheckErr]; !ok {
@@ -612,6 +611,18 @@ func (w *WSL) checkError(
612611
return
613612
}
614613

614+
// If we actually have statements above we can't possibly need to remove any
615+
// empty lines.
616+
if stmtsAbove > 0 {
617+
return
618+
}
619+
620+
// If the error checking has an init condition (e.g. if err := f();) we
621+
// don't want to check cuddling since the error is now assigned on this row.
622+
if stmt.Init != nil {
623+
return
624+
}
625+
615626
// The condition must be a binary expression (X OP Y)
616627
binaryExpr, ok := stmt.Cond.(*ast.BinaryExpr)
617628
if !ok {
@@ -643,22 +654,25 @@ func (w *WSL) checkError(
643654
return
644655
}
645656

646-
// Previous node must be assign or decl where the error was actually
647-
// defined.
648-
_, isAssign := previousNode.(*ast.AssignStmt)
649-
_, isDecl := previousNode.(*ast.DeclStmt)
650-
651-
if !isAssign && !isDecl {
652-
return
657+
previousIdents := []*ast.Ident{}
658+
if assign, ok := previousNode.(*ast.AssignStmt); ok {
659+
for _, lhs := range assign.Lhs {
660+
previousIdents = append(previousIdents, identsFromNode(lhs, true)...)
661+
}
653662
}
654663

655-
// If there are no statements above or the statement above doesn't contain
656-
// any idents there can't be any error to cuddle.
657-
if stmtsAbove > 0 || len(previousIdents) == 0 {
658-
return
664+
if decl, ok := previousNode.(*ast.DeclStmt); ok {
665+
if genDecl, ok := decl.Decl.(*ast.GenDecl); ok {
666+
for _, spec := range genDecl.Specs {
667+
if vs, ok := spec.(*ast.ValueSpec); ok {
668+
previousIdents = append(previousIdents, vs.Names...)
669+
}
670+
}
671+
}
659672
}
660673

661-
// Ensure that the error was defined on the line above.
674+
// Ensure that the error checked on this line was assigned or declared in
675+
// the previous statement.
662676
if len(identIntersection([]*ast.Ident{xIdent}, previousIdents)) == 0 {
663677
return
664678
}
@@ -780,7 +794,6 @@ func (w *WSL) checkIf(stmt *ast.IfStmt, cursor *Cursor, isElse bool) {
780794
w.numberOfStatementsAbove(cursor),
781795
stmt,
782796
previousNode,
783-
identsFromNode(previousNode, true),
784797
cursor,
785798
)
786799
}

0 commit comments

Comments
 (0)