github.com/prysmaticlabs/prysm@v1.4.4/tools/analyzers/comparesame/analyzer.go (about) 1 // Package comparesame implements a static analyzer to ensure that code does not contain 2 // comparisons of identical expressions. 3 package comparesame 4 5 import ( 6 "bytes" 7 "errors" 8 "go/ast" 9 "go/printer" 10 "go/token" 11 12 "golang.org/x/tools/go/analysis" 13 "golang.org/x/tools/go/analysis/passes/inspect" 14 "golang.org/x/tools/go/ast/inspector" 15 ) 16 17 // Doc explaining the tool. 18 const Doc = "Tool to detect comparison (==, !=, >=, <=, >, <) of identical expressions." 19 20 const messageTemplate = "Boolean expression has identical expressions on both sides. The result is always %v." 21 22 // Analyzer runs static analysis. 23 var Analyzer = &analysis.Analyzer{ 24 Name: "comparesame", 25 Doc: Doc, 26 Requires: []*analysis.Analyzer{inspect.Analyzer}, 27 Run: run, 28 } 29 30 func run(pass *analysis.Pass) (interface{}, error) { 31 inspection, ok := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) 32 if !ok { 33 return nil, errors.New("analyzer is not type *inspector.Inspector") 34 } 35 36 nodeFilter := []ast.Node{ 37 (*ast.BinaryExpr)(nil), 38 } 39 40 inspection.Preorder(nodeFilter, func(node ast.Node) { 41 expr, ok := node.(*ast.BinaryExpr) 42 if !ok { 43 return 44 } 45 46 switch expr.Op { 47 case token.EQL, token.NEQ, token.GEQ, token.LEQ, token.GTR, token.LSS: 48 var xBuf, yBuf bytes.Buffer 49 if err := printer.Fprint(&xBuf, pass.Fset, expr.X); err != nil { 50 pass.Reportf(expr.X.Pos(), err.Error()) 51 } 52 if err := printer.Fprint(&yBuf, pass.Fset, expr.Y); err != nil { 53 pass.Reportf(expr.Y.Pos(), err.Error()) 54 } 55 if xBuf.String() == yBuf.String() { 56 switch expr.Op { 57 case token.EQL, token.NEQ, token.GEQ, token.LEQ: 58 pass.Reportf(expr.OpPos, messageTemplate, true) 59 case token.GTR, token.LSS: 60 pass.Reportf(expr.OpPos, messageTemplate, false) 61 } 62 } 63 } 64 }) 65 66 return nil, nil 67 }