Skip to content

Commit 9b15f3f

Browse files
mfederowiczchavacavaalexandear
authoredDec 11, 2024
refactor: replace panic with error in rules (#1126)
Co-authored-by: chavacava <salvadorcavadini+github@gmail.com> Co-authored-by: Oleksandr Redko <oleksandr.red+github@gmail.com>
1 parent 10d9697 commit 9b15f3f

35 files changed

+514
-239
lines changed
 

‎lint/linter.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ func (l *Linter) Lint(packages [][]string, ruleSet []Rule, config Config) (<-cha
106106
for n := range packages {
107107
go func(pkg []string, gover *goversion.Version) {
108108
if err := l.lintPackage(pkg, gover, ruleSet, config, failures); err != nil {
109-
fmt.Fprintln(os.Stderr, err)
109+
fmt.Fprintln(os.Stderr, "error during linting: "+err.Error())
110110
os.Exit(1)
111111
}
112112
wg.Done()

‎rule/add_constant.go

+8-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package rule
22

33
import (
4+
"errors"
45
"fmt"
56
"go/ast"
67
"regexp"
@@ -45,7 +46,7 @@ func (r *AddConstantRule) Apply(file *lint.File, arguments lint.Arguments) []lin
4546
var configureErr error
4647
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
4748
if configureErr != nil {
48-
return []lint.Failure{lint.NewInternalFailure(configureErr.Error())}
49+
return newInternalFailureError(configureErr)
4950
}
5051

5152
var failures []lint.Failure
@@ -232,35 +233,35 @@ func (r *AddConstantRule) configure(arguments lint.Arguments) error {
232233
}
233234
list, ok := v.(string)
234235
if !ok {
235-
fmt.Errorf("invalid argument to the add-constant rule, string expected. Got '%v' (%T)", v, v)
236+
return fmt.Errorf("invalid argument to the add-constant rule, string expected. Got '%v' (%T)", v, v)
236237
}
237238
r.allowList.add(kind, list)
238239
case "maxLitCount":
239240
sl, ok := v.(string)
240241
if !ok {
241-
fmt.Errorf("invalid argument to the add-constant rule, expecting string representation of an integer. Got '%v' (%T)", v, v)
242+
return fmt.Errorf("invalid argument to the add-constant rule, expecting string representation of an integer. Got '%v' (%T)", v, v)
242243
}
243244

244245
limit, err := strconv.Atoi(sl)
245246
if err != nil {
246-
fmt.Errorf("invalid argument to the add-constant rule, expecting string representation of an integer. Got '%v'", v)
247+
return fmt.Errorf("invalid argument to the add-constant rule, expecting string representation of an integer. Got '%v'", v)
247248
}
248249
r.strLitLimit = limit
249250
case "ignoreFuncs":
250251
excludes, ok := v.(string)
251252
if !ok {
252-
fmt.Errorf("invalid argument to the ignoreFuncs parameter of add-constant rule, string expected. Got '%v' (%T)", v, v)
253+
return fmt.Errorf("invalid argument to the ignoreFuncs parameter of add-constant rule, string expected. Got '%v' (%T)", v, v)
253254
}
254255

255256
for _, exclude := range strings.Split(excludes, ",") {
256257
exclude = strings.Trim(exclude, " ")
257258
if exclude == "" {
258-
fmt.Errorf("invalid argument to the ignoreFuncs parameter of add-constant rule, expected regular expression must not be empty.")
259+
return errors.New("invalid argument to the ignoreFuncs parameter of add-constant rule, expected regular expression must not be empty")
259260
}
260261

261262
exp, err := regexp.Compile(exclude)
262263
if err != nil {
263-
fmt.Errorf("invalid argument to the ignoreFuncs parameter of add-constant rule: regexp %q does not compile: %v", exclude, err)
264+
return fmt.Errorf("invalid argument to the ignoreFuncs parameter of add-constant rule: regexp %q does not compile: %w", exclude, err)
264265
}
265266

266267
r.ignoreFunctions = append(r.ignoreFunctions, exp)

‎rule/argument_limit.go

+11-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package rule
22

33
import (
4+
"errors"
45
"fmt"
56
"go/ast"
67
"sync"
@@ -17,22 +18,28 @@ type ArgumentsLimitRule struct {
1718

1819
const defaultArgumentsLimit = 8
1920

20-
func (r *ArgumentsLimitRule) configure(arguments lint.Arguments) {
21+
func (r *ArgumentsLimitRule) configure(arguments lint.Arguments) error {
2122
if len(arguments) < 1 {
2223
r.max = defaultArgumentsLimit
23-
return
24+
return nil
2425
}
2526

2627
maxArguments, ok := arguments[0].(int64) // Alt. non panicking version
2728
if !ok {
28-
panic(`invalid value passed as argument number to the "argument-limit" rule`)
29+
return errors.New(`invalid value passed as argument number to the "argument-limit" rule`)
2930
}
3031
r.max = int(maxArguments)
32+
return nil
3133
}
3234

3335
// Apply applies the rule to given file.
3436
func (r *ArgumentsLimitRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
35-
r.configureOnce.Do(func() { r.configure(arguments) })
37+
var configureErr error
38+
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
39+
40+
if configureErr != nil {
41+
return newInternalFailureError(configureErr)
42+
}
3643

3744
var failures []lint.Failure
3845

‎rule/banned_characters.go

+21-7
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,30 @@ type BannedCharsRule struct {
1818

1919
const bannedCharsRuleName = "banned-characters"
2020

21-
func (r *BannedCharsRule) configure(arguments lint.Arguments) {
21+
func (r *BannedCharsRule) configure(arguments lint.Arguments) error {
2222
if len(arguments) > 0 {
23-
checkNumberOfArguments(1, arguments, bannedCharsRuleName)
24-
r.bannedCharList = r.getBannedCharsList(arguments)
23+
err := checkNumberOfArguments(1, arguments, bannedCharsRuleName)
24+
if err != nil {
25+
return err
26+
}
27+
list, err := r.getBannedCharsList(arguments)
28+
if err != nil {
29+
return err
30+
}
31+
32+
r.bannedCharList = list
2533
}
34+
return nil
2635
}
2736

2837
// Apply applied the rule to the given file.
2938
func (r *BannedCharsRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
30-
r.configureOnce.Do(func() { r.configure(arguments) })
39+
var configureErr error
40+
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
41+
42+
if configureErr != nil {
43+
return newInternalFailureError(configureErr)
44+
}
3145

3246
var failures []lint.Failure
3347
onFailure := func(failure lint.Failure) {
@@ -49,17 +63,17 @@ func (*BannedCharsRule) Name() string {
4963
}
5064

5165
// getBannedCharsList converts arguments into the banned characters list
52-
func (r *BannedCharsRule) getBannedCharsList(args lint.Arguments) []string {
66+
func (r *BannedCharsRule) getBannedCharsList(args lint.Arguments) ([]string, error) {
5367
var bannedChars []string
5468
for _, char := range args {
5569
charStr, ok := char.(string)
5670
if !ok {
57-
panic(fmt.Sprintf("Invalid argument for the %s rule: expecting a string, got %T", r.Name(), char))
71+
return nil, fmt.Errorf("invalid argument for the %s rule: expecting a string, got %T", r.Name(), char)
5872
}
5973
bannedChars = append(bannedChars, charStr)
6074
}
6175

62-
return bannedChars
76+
return bannedChars, nil
6377
}
6478

6579
type lintBannedCharsRule struct {

‎rule/cognitive_complexity.go

+10-4
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,29 @@ type CognitiveComplexityRule struct {
1919

2020
const defaultMaxCognitiveComplexity = 7
2121

22-
func (r *CognitiveComplexityRule) configure(arguments lint.Arguments) {
22+
func (r *CognitiveComplexityRule) configure(arguments lint.Arguments) error {
2323
if len(arguments) < 1 {
2424
r.maxComplexity = defaultMaxCognitiveComplexity
25-
return
25+
return nil
2626
}
2727

2828
complexity, ok := arguments[0].(int64)
2929
if !ok {
30-
panic(fmt.Sprintf("invalid argument type for cognitive-complexity, expected int64, got %T", arguments[0]))
30+
return fmt.Errorf("invalid argument type for cognitive-complexity, expected int64, got %T", arguments[0])
3131
}
3232

3333
r.maxComplexity = int(complexity)
34+
return nil
3435
}
3536

3637
// Apply applies the rule to given file.
3738
func (r *CognitiveComplexityRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
38-
r.configureOnce.Do(func() { r.configure(arguments) })
39+
var configureErr error
40+
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
41+
42+
if configureErr != nil {
43+
return newInternalFailureError(configureErr)
44+
}
3945

4046
var failures []lint.Failure
4147

‎rule/comment_spacings.go

+10-4
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,26 @@ type CommentSpacingsRule struct {
1616
configureOnce sync.Once
1717
}
1818

19-
func (r *CommentSpacingsRule) configure(arguments lint.Arguments) {
19+
func (r *CommentSpacingsRule) configure(arguments lint.Arguments) error {
2020
r.allowList = []string{}
2121
for _, arg := range arguments {
2222
allow, ok := arg.(string) // Alt. non panicking version
2323
if !ok {
24-
panic(fmt.Sprintf("invalid argument %v for %s; expected string but got %T", arg, r.Name(), arg))
24+
return fmt.Errorf("invalid argument %v for %s; expected string but got %T", arg, r.Name(), arg)
2525
}
2626
r.allowList = append(r.allowList, `//`+allow)
2727
}
28+
return nil
2829
}
2930

3031
// Apply the rule.
31-
func (r *CommentSpacingsRule) Apply(file *lint.File, args lint.Arguments) []lint.Failure {
32-
r.configureOnce.Do(func() { r.configure(args) })
32+
func (r *CommentSpacingsRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
33+
var configureErr error
34+
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
35+
36+
if configureErr != nil {
37+
return newInternalFailureError(configureErr)
38+
}
3339

3440
var failures []lint.Failure
3541

‎rule/comments_density.go

+10-4
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,29 @@ type CommentsDensityRule struct {
1818

1919
const defaultMinimumCommentsPercentage = 0
2020

21-
func (r *CommentsDensityRule) configure(arguments lint.Arguments) {
21+
func (r *CommentsDensityRule) configure(arguments lint.Arguments) error {
2222
if len(arguments) < 1 {
2323
r.minimumCommentsDensity = defaultMinimumCommentsPercentage
24-
return
24+
return nil
2525
}
2626

2727
var ok bool
2828
r.minimumCommentsDensity, ok = arguments[0].(int64)
2929
if !ok {
30-
panic(fmt.Sprintf("invalid argument for %q rule: argument should be an int, got %T", r.Name(), arguments[0]))
30+
return fmt.Errorf("invalid argument for %q rule: argument should be an int, got %T", r.Name(), arguments[0])
3131
}
32+
return nil
3233
}
3334

3435
// Apply applies the rule to given file.
3536
func (r *CommentsDensityRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
36-
r.configureOnce.Do(func() { r.configure(arguments) })
37+
var configureErr error
38+
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
3739

40+
if configureErr != nil {
41+
return newInternalFailureError(configureErr)
42+
}
43+
3844
commentsLines := countDocLines(file.AST.Comments)
3945
statementsCount := countStatements(file.AST)
4046
density := (float32(commentsLines) / float32(statementsCount+commentsLines)) * 100

‎rule/context_as_argument.go

+19-9
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,13 @@ type ContextAsArgumentRule struct {
1717
}
1818

1919
// Apply applies the rule to given file.
20-
func (r *ContextAsArgumentRule) Apply(file *lint.File, args lint.Arguments) []lint.Failure {
21-
r.configureOnce.Do(func() { r.configure(args) })
20+
func (r *ContextAsArgumentRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
21+
var configureErr error
22+
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
23+
24+
if configureErr != nil {
25+
return newInternalFailureError(configureErr)
26+
}
2227

2328
var failures []lint.Failure
2429
for _, decl := range file.AST.Decls {
@@ -59,27 +64,32 @@ func (*ContextAsArgumentRule) Name() string {
5964
return "context-as-argument"
6065
}
6166

62-
func (r *ContextAsArgumentRule) configure(arguments lint.Arguments) {
63-
r.allowTypes = r.getAllowTypesFromArguments(arguments)
67+
func (r *ContextAsArgumentRule) configure(arguments lint.Arguments) error {
68+
types, err := r.getAllowTypesFromArguments(arguments)
69+
if err != nil {
70+
return err
71+
}
72+
r.allowTypes = types
73+
return nil
6474
}
6575

66-
func (r *ContextAsArgumentRule) getAllowTypesFromArguments(args lint.Arguments) map[string]struct{} {
76+
func (r *ContextAsArgumentRule) getAllowTypesFromArguments(args lint.Arguments) (map[string]struct{}, error) {
6777
allowTypesBefore := []string{}
6878
if len(args) >= 1 {
6979
argKV, ok := args[0].(map[string]any)
7080
if !ok {
71-
panic(fmt.Sprintf("Invalid argument to the context-as-argument rule. Expecting a k,v map, got %T", args[0]))
81+
return nil, fmt.Errorf("invalid argument to the context-as-argument rule. Expecting a k,v map, got %T", args[0])
7282
}
7383
for k, v := range argKV {
7484
switch k {
7585
case "allowTypesBefore":
7686
typesBefore, ok := v.(string)
7787
if !ok {
78-
panic(fmt.Sprintf("Invalid argument to the context-as-argument.allowTypesBefore rule. Expecting a string, got %T", v))
88+
return nil, fmt.Errorf("invalid argument to the context-as-argument.allowTypesBefore rule. Expecting a string, got %T", v)
7989
}
8090
allowTypesBefore = append(allowTypesBefore, strings.Split(typesBefore, ",")...)
8191
default:
82-
panic(fmt.Sprintf("Invalid argument to the context-as-argument rule. Unrecognized key %s", k))
92+
return nil, fmt.Errorf("invalid argument to the context-as-argument rule. Unrecognized key %s", k)
8393
}
8494
}
8595
}
@@ -90,5 +100,5 @@ func (r *ContextAsArgumentRule) getAllowTypesFromArguments(args lint.Arguments)
90100
}
91101

92102
result["context.Context"] = struct{}{} // context.Context is always allowed before another context.Context
93-
return result
103+
return result, nil
94104
}

‎rule/cyclomatic.go

+10-4
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,28 @@ type CyclomaticRule struct {
2020

2121
const defaultMaxCyclomaticComplexity = 10
2222

23-
func (r *CyclomaticRule) configure(arguments lint.Arguments) {
23+
func (r *CyclomaticRule) configure(arguments lint.Arguments) error {
2424
if len(arguments) < 1 {
2525
r.maxComplexity = defaultMaxCyclomaticComplexity
26-
return
26+
return nil
2727
}
2828

2929
complexity, ok := arguments[0].(int64) // Alt. non panicking version
3030
if !ok {
31-
panic(fmt.Sprintf("invalid argument for cyclomatic complexity; expected int but got %T", arguments[0]))
31+
return fmt.Errorf("invalid argument for cyclomatic complexity; expected int but got %T", arguments[0])
3232
}
3333
r.maxComplexity = int(complexity)
34+
return nil
3435
}
3536

3637
// Apply applies the rule to given file.
3738
func (r *CyclomaticRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
38-
r.configureOnce.Do(func() { r.configure(arguments) })
39+
var configureErr error
40+
r.configureOnce.Do(func() { configureErr = r.configure(arguments) })
41+
42+
if configureErr != nil {
43+
return newInternalFailureError(configureErr)
44+
}
3945

4046
var failures []lint.Failure
4147
for _, decl := range file.AST.Decls {

0 commit comments

Comments
 (0)