github.com/Johnny2210/revive@v1.0.8-0.20210625134200-febf37ccd0f5/rule/call-to-gc.go (about) 1 package rule 2 3 import ( 4 "go/ast" 5 6 "github.com/mgechev/revive/lint" 7 ) 8 9 // CallToGCRule lints calls to the garbage collector. 10 type CallToGCRule struct{} 11 12 // Apply applies the rule to given file. 13 func (r *CallToGCRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { 14 var failures []lint.Failure 15 onFailure := func(failure lint.Failure) { 16 failures = append(failures, failure) 17 } 18 19 var gcTriggeringFunctions = map[string]map[string]bool{ 20 "runtime": {"GC": true}, 21 } 22 23 w := lintCallToGC{onFailure, gcTriggeringFunctions} 24 ast.Walk(w, file.AST) 25 26 return failures 27 } 28 29 // Name returns the rule name. 30 func (r *CallToGCRule) Name() string { 31 return "call-to-gc" 32 } 33 34 type lintCallToGC struct { 35 onFailure func(lint.Failure) 36 gcTriggeringFunctions map[string]map[string]bool 37 } 38 39 func (w lintCallToGC) Visit(node ast.Node) ast.Visitor { 40 ce, ok := node.(*ast.CallExpr) 41 if !ok { 42 return w // nothing to do, the node is not a call 43 } 44 45 fc, ok := ce.Fun.(*ast.SelectorExpr) 46 if !ok { 47 return nil // nothing to do, the call is not of the form pkg.func(...) 48 } 49 50 id, ok := fc.X.(*ast.Ident) 51 52 if !ok { 53 return nil // in case X is not an id (it should be!) 54 } 55 56 fn := fc.Sel.Name 57 pkg := id.Name 58 if !w.gcTriggeringFunctions[pkg][fn] { 59 return nil // it isn't a call to a GC triggering function 60 } 61 62 w.onFailure(lint.Failure{ 63 Confidence: 1, 64 Node: node, 65 Category: "bad practice", 66 Failure: "explicit call to the garbage collector", 67 }) 68 69 return w 70 }