mirror of
https://github.com/mgechev/revive.git
synced 2025-02-03 13:11:25 +02:00
call-to-gc (new rule) (#90)
This commit is contained in:
parent
ad7df7dc37
commit
55fe366696
@ -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{})
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user