github.com/songshiyun/revive@v1.1.5-0.20220323112655-f8433a19b3c5/rule/atomic.go (about) 1 package rule 2 3 import ( 4 "go/ast" 5 "go/token" 6 "go/types" 7 8 "github.com/songshiyun/revive/lint" 9 ) 10 11 // AtomicRule lints given else constructs. 12 type AtomicRule struct{} 13 14 // Apply applies the rule to given file. 15 func (r *AtomicRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { 16 var failures []lint.Failure 17 walker := atomic{ 18 pkgTypesInfo: file.Pkg.TypesInfo, 19 onFailure: func(failure lint.Failure) { 20 failures = append(failures, failure) 21 }, 22 } 23 24 ast.Walk(walker, file.AST) 25 26 return failures 27 } 28 29 // Name returns the rule name. 30 func (r *AtomicRule) Name() string { 31 return "atomic" 32 } 33 34 type atomic struct { 35 pkgTypesInfo *types.Info 36 onFailure func(lint.Failure) 37 } 38 39 func (w atomic) Visit(node ast.Node) ast.Visitor { 40 n, ok := node.(*ast.AssignStmt) 41 if !ok { 42 return w 43 } 44 45 if len(n.Lhs) != len(n.Rhs) { 46 return nil // skip assignment sub-tree 47 } 48 if len(n.Lhs) == 1 && n.Tok == token.DEFINE { 49 return nil // skip assignment sub-tree 50 } 51 52 for i, right := range n.Rhs { 53 call, ok := right.(*ast.CallExpr) 54 if !ok { 55 continue 56 } 57 sel, ok := call.Fun.(*ast.SelectorExpr) 58 if !ok { 59 continue 60 } 61 pkgIdent, _ := sel.X.(*ast.Ident) 62 if w.pkgTypesInfo != nil { 63 pkgName, ok := w.pkgTypesInfo.Uses[pkgIdent].(*types.PkgName) 64 if !ok || pkgName.Imported().Path() != "sync/atomic" { 65 continue 66 } 67 } 68 69 switch sel.Sel.Name { 70 case "AddInt32", "AddInt64", "AddUint32", "AddUint64", "AddUintptr": 71 left := n.Lhs[i] 72 if len(call.Args) != 2 { 73 continue 74 } 75 arg := call.Args[0] 76 broken := false 77 78 if uarg, ok := arg.(*ast.UnaryExpr); ok && uarg.Op == token.AND { 79 broken = gofmt(left) == gofmt(uarg.X) 80 } else if star, ok := left.(*ast.StarExpr); ok { 81 broken = gofmt(star.X) == gofmt(arg) 82 } 83 84 if broken { 85 w.onFailure(lint.Failure{ 86 Confidence: 1, 87 Failure: "direct assignment to atomic value", 88 Node: n, 89 }) 90 } 91 } 92 } 93 return w 94 }