mirror of
				https://github.com/mgechev/revive.git
				synced 2025-10-30 23:37:49 +02:00 
			
		
		
		
	call-to-gc (new rule) (#90)
This commit is contained in:
		| @@ -47,6 +47,8 @@ Here's how `revive` is different from `golint`: | ||||
|     - [Friendly](#friendly) | ||||
|     - [Stylish](#stylish) | ||||
|     - [Default](#default) | ||||
|     - [Plain](#plain) | ||||
|     - [Unix](#unix) | ||||
|   - [Extensibility](#extensibility) | ||||
|     - [Custom Rule](#custom-rule) | ||||
|       - [Example](#example) | ||||
| @@ -278,6 +280,7 @@ List of all available rules. The rules ported from `golint` are left unchanged a | ||||
| | [`atomic`](./RULES_DESCRIPTIONS.md#atomic)              |  n/a   | Check for common mistaken usages of the `sync/atomic` package    |    no    |  no   | | ||||
| | [`empty-lines`](./RULES_DESCRIPTIONS.md#empty-lines)   | n/a | Warns when there are heading or trailing newlines in a block              |    no    |  no   | | ||||
| | [`line-lenght-limit`](./RULES_DESCRIPTIONS.md#line-lenght-limit)   | int    | Specifies the maximum number of characters in a line             |    no    |  no   | | ||||
| | [`call-to-gc`](./RULES_DESCRIPTIONS.md#call-to-gc)   | n/a    | Warns on explicit call to the garbage collector    |    no    |  no   | | ||||
|  | ||||
| ## Configurable rules | ||||
|  | ||||
|   | ||||
| @@ -9,6 +9,7 @@ List of all available rules. | ||||
|   - [atomic](#atomic) | ||||
|   - [blank-imports](#blank-imports) | ||||
|   - [bool-literal-in-expr](#bool-literal-in-expr) | ||||
|   - [call-to-gc](#call-to-gc) | ||||
|   - [confusing-naming](#confusing-naming) | ||||
|   - [confusing-results](#confusing-results) | ||||
|   - [constant-logical-expr](#constant-logical-expr) | ||||
| @@ -102,6 +103,14 @@ _Description_: Using Boolean literals (`true`, `false`) in logic expressions may | ||||
|  | ||||
| _Configuration_: N/A | ||||
|  | ||||
| ## call-to-gc | ||||
|  | ||||
| _Description_:  Explicitly invoking the garbage collector is, except for specific uses in benchmarking, very dubious. | ||||
|  | ||||
| The garbage collector can be configured through environment variables as described [here](https://golang.org/pkg/runtime/). | ||||
|  | ||||
| _Configuration_: N/A | ||||
|  | ||||
| ## confusing-naming | ||||
|  | ||||
| _Description_: Methods or fields of `struct` that have names different only by capitalization could be confusing. | ||||
|   | ||||
| @@ -72,6 +72,7 @@ var allRules = append([]lint.Rule{ | ||||
| 	&rule.AtomicRule{}, | ||||
| 	&rule.EmptyLinesRule{}, | ||||
| 	&rule.LineLengthLimitRule{}, | ||||
| 	&rule.CallToGCRule{}, | ||||
| }, defaultRules...) | ||||
|  | ||||
| var allFormatters = []lint.Formatter{ | ||||
|   | ||||
							
								
								
									
										17
									
								
								fixtures/call-to-gc.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								fixtures/call-to-gc.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| package fixtures | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"runtime" | ||||
| ) | ||||
|  | ||||
| func GC() { | ||||
| } | ||||
|  | ||||
| func foo() { | ||||
| 	fmt.Println("just testing") | ||||
| 	GC() | ||||
| 	fixtures.GC() | ||||
| 	runtime.Goexit() | ||||
| 	runtime.GC() // MATCH /explicit call to the garbage collector/ | ||||
| } | ||||
							
								
								
									
										70
									
								
								rule/call-to-gc.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								rule/call-to-gc.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | ||||
| package rule | ||||
|  | ||||
| import ( | ||||
| 	"go/ast" | ||||
|  | ||||
| 	"github.com/mgechev/revive/lint" | ||||
| ) | ||||
|  | ||||
| // CallToGCRule lints calls to the garbage collector. | ||||
| type CallToGCRule struct{} | ||||
|  | ||||
| // Apply applies the rule to given file. | ||||
| func (r *CallToGCRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { | ||||
| 	var failures []lint.Failure | ||||
| 	onFailure := func(failure lint.Failure) { | ||||
| 		failures = append(failures, failure) | ||||
| 	} | ||||
|  | ||||
| 	var gcTriggeringFunctions = map[string]map[string]bool{ | ||||
| 		"runtime": map[string]bool{"GC": true}, | ||||
| 	} | ||||
|  | ||||
| 	w := lintCallToGC{onFailure, gcTriggeringFunctions} | ||||
| 	ast.Walk(w, file.AST) | ||||
|  | ||||
| 	return failures | ||||
| } | ||||
|  | ||||
| // Name returns the rule name. | ||||
| func (r *CallToGCRule) Name() string { | ||||
| 	return "call-to-gc" | ||||
| } | ||||
|  | ||||
| type lintCallToGC struct { | ||||
| 	onFailure             func(lint.Failure) | ||||
| 	gcTriggeringFunctions map[string]map[string]bool | ||||
| } | ||||
|  | ||||
| func (w lintCallToGC) Visit(node ast.Node) ast.Visitor { | ||||
| 	ce, ok := node.(*ast.CallExpr) | ||||
| 	if !ok { | ||||
| 		return w // nothing to do, the node is not a call | ||||
| 	} | ||||
|  | ||||
| 	fc, ok := ce.Fun.(*ast.SelectorExpr) | ||||
| 	if !ok { | ||||
| 		return nil // nothing to do, the call is not of the form pkg.func(...) | ||||
| 	} | ||||
|  | ||||
| 	id, ok := fc.X.(*ast.Ident) | ||||
|  | ||||
| 	if !ok { | ||||
| 		return nil // in case X is not an id (it should be!) | ||||
| 	} | ||||
|  | ||||
| 	fn := fc.Sel.Name | ||||
| 	pkg := id.Name | ||||
| 	if !w.gcTriggeringFunctions[pkg][fn] { | ||||
| 		return nil // it isn't a call to a GC triggering function | ||||
| 	} | ||||
|  | ||||
| 	w.onFailure(lint.Failure{ | ||||
| 		Confidence: 1, | ||||
| 		Node:       node, | ||||
| 		Category:   "bad practice", | ||||
| 		Failure:    "explicit call to the garbage collector", | ||||
| 	}) | ||||
|  | ||||
| 	return w | ||||
| } | ||||
							
								
								
									
										12
									
								
								test/call-to-gc_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								test/call-to-gc_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| package test | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/mgechev/revive/rule" | ||||
| ) | ||||
|  | ||||
| // TestCallToGC test call-to-gc rule | ||||
| func TestCallToGC(t *testing.T) { | ||||
| 	testRule(t, "call-to-gc", &rule.CallToGCRule{}) | ||||
| } | ||||
		Reference in New Issue
	
	Block a user