mirror of
				https://github.com/mgechev/revive.git
				synced 2025-10-30 23:37:49 +02:00 
			
		
		
		
	Allow to customize user functions in rule error-strings (#703)
				
					
				
			* Allow to customize user functions in rule `error-strings` * Rollback the Available Rules table format in README * adds memoization of the rule's configuration Co-authored-by: chavacava <salvadorcavadini+github@gmail.com>
This commit is contained in:
		| @@ -350,6 +350,8 @@ enableAllRules = true | ||||
|     Arguments = [7] | ||||
| [rule.function-result-limit] | ||||
|     Arguments = [3] | ||||
| [rule.error-strings] | ||||
|     Arguments = ["mypackage.Error"] | ||||
| ``` | ||||
|  | ||||
| ### Default Configuration | ||||
| @@ -410,7 +412,6 @@ warningCode = 0 | ||||
| ## Available Rules | ||||
|  | ||||
| List of all available rules. The rules ported from `golint` are left unchanged and indicated in the `golint` column. | ||||
|  | ||||
| | Name                  | Config | Description                                                      | `golint` | Typed | | ||||
| | --------------------- | :----: | :--------------------------------------------------------------- | :------: | :---: | | ||||
| | [`context-keys-type`](./RULES_DESCRIPTIONS.md#context-key-types)   |  n/a   | Disallows the usage of basic types in `context.WithValue`.       |   yes    |  yes  | | ||||
| @@ -423,7 +424,7 @@ List of all available rules. The rules ported from `golint` are left unchanged a | ||||
| | [`context-as-argument`](./RULES_DESCRIPTIONS.md#context-as-argument) |  n/a   | `context.Context` should be the first argument of a function.    |   yes    |  no   | | ||||
| | [`dot-imports`](./RULES_DESCRIPTIONS.md#dot-imports)         |  n/a   | Forbids `.` imports.                                             |   yes    |  no   | | ||||
| | [`error-return`](./RULES_DESCRIPTIONS.md#error-return)        |  n/a   | The error return parameter should be last.                       |   yes    |  no   | | ||||
| | [`error-strings`](./RULES_DESCRIPTIONS.md#error-strings)       |  n/a   | Conventions around error strings.                                |   yes    |  no   | | ||||
| | [`error-strings`](./RULES_DESCRIPTIONS.md#error-strings)       |  []string   | Conventions around error strings.                                |   yes    |  no   | | ||||
| | [`error-naming`](./RULES_DESCRIPTIONS.md#error-naming)        |  n/a   | Naming of error variables.                                       |   yes    |  no   | | ||||
| | [`exported`](./RULES_DESCRIPTIONS.md#exported)            |  []string   | Naming and commenting conventions on exported symbols.           |   yes    |  no   | | ||||
| | [`if-return`](./RULES_DESCRIPTIONS.md#if-return)           |  n/a   | Redundant if when returning an error.                            |   no    |  no   | | ||||
|   | ||||
| @@ -4,6 +4,8 @@ import ( | ||||
| 	"go/ast" | ||||
| 	"go/token" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
| 	"unicode" | ||||
| 	"unicode/utf8" | ||||
|  | ||||
| @@ -11,13 +13,20 @@ import ( | ||||
| ) | ||||
|  | ||||
| // ErrorStringsRule lints given else constructs. | ||||
| type ErrorStringsRule struct{} | ||||
| type ErrorStringsRule struct { | ||||
| 	errorFunctions map[string]map[string]struct{} | ||||
| 	sync.Mutex | ||||
| } | ||||
|  | ||||
| // Apply applies the rule to given file. | ||||
| func (*ErrorStringsRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { | ||||
| 	var failures []lint.Failure | ||||
| func (r *ErrorStringsRule) configure(arguments lint.Arguments) { | ||||
| 	r.Lock() | ||||
| 	defer r.Unlock() | ||||
|  | ||||
| 	errorFunctions := map[string]map[string]struct{}{ | ||||
| 	if r.errorFunctions != nil { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	r.errorFunctions = map[string]map[string]struct{}{ | ||||
| 		"fmt": { | ||||
| 			"Errorf": {}, | ||||
| 		}, | ||||
| @@ -31,11 +40,33 @@ func (*ErrorStringsRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	var invalidCustomFunctions []string | ||||
| 	for _, argument := range arguments { | ||||
| 		if functionName, ok := argument.(string); ok { | ||||
| 			fields := strings.Split(strings.TrimSpace(functionName), ".") | ||||
| 			if len(fields) != 2 || len(fields[0]) == 0 || len(fields[1]) == 0 { | ||||
| 				invalidCustomFunctions = append(invalidCustomFunctions, functionName) | ||||
| 				continue | ||||
| 			} | ||||
| 			r.errorFunctions[fields[0]] = map[string]struct{}{fields[1]: {}} | ||||
| 		} | ||||
| 	} | ||||
| 	if len(invalidCustomFunctions) != 0 { | ||||
| 		panic("found invalid custom function: " + strings.Join(invalidCustomFunctions, ",")) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Apply applies the rule to given file. | ||||
| func (r *ErrorStringsRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { | ||||
| 	var failures []lint.Failure | ||||
|  | ||||
| 	r.configure(arguments) | ||||
|  | ||||
| 	fileAst := file.AST | ||||
| 	walker := lintErrorStrings{ | ||||
| 		file:           file, | ||||
| 		fileAst:        fileAst, | ||||
| 		errorFunctions: errorFunctions, | ||||
| 		errorFunctions: r.errorFunctions, | ||||
| 		onFailure: func(failure lint.Failure) { | ||||
| 			failures = append(failures, failure) | ||||
| 		}, | ||||
|   | ||||
							
								
								
									
										15
									
								
								test/error-strings-custom-functions_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								test/error-strings-custom-functions_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| package test | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/mgechev/revive/lint" | ||||
| 	"github.com/mgechev/revive/rule" | ||||
| ) | ||||
|  | ||||
| func TestErrorStringsWithCustomFunctions(t *testing.T) { | ||||
| 	args := []interface{}{"pkgErrors.Wrap"} | ||||
| 	testRule(t, "error-strings-with-custom-functions", &rule.ErrorStringsRule{}, &lint.RuleConfig{ | ||||
| 		Arguments: args, | ||||
| 	}) | ||||
| } | ||||
							
								
								
									
										12
									
								
								testdata/error-strings-with-custom-functions.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								testdata/error-strings-with-custom-functions.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| package fixtures | ||||
|  | ||||
| import ( | ||||
| 	pkgErrors "github.com/pkg/errors" | ||||
| ) | ||||
|  | ||||
| // Check for the error strings themselves. | ||||
|  | ||||
| func errorsStrings(x int) error { | ||||
| 	var err error | ||||
| 	return pkgErrors.Wrap(err, "This %d is too low") // MATCH /error strings should not be capitalized or end with punctuation or a newline/ | ||||
| } | ||||
		Reference in New Issue
	
	Block a user