github.com/prysmaticlabs/prysm@v1.4.4/tools/analyzers/slicedirect/analyzer.go (about)

     1  // Package slicedirect implements a static analyzer to ensure that code does not contain
     2  // applications of [:] on expressions which are already slices.
     3  package slicedirect
     4  
     5  import (
     6  	"errors"
     7  	"go/ast"
     8  	"go/types"
     9  
    10  	"golang.org/x/tools/go/analysis"
    11  	"golang.org/x/tools/go/analysis/passes/inspect"
    12  	"golang.org/x/tools/go/ast/inspector"
    13  )
    14  
    15  // Doc explaining the tool.
    16  const Doc = "Tool to detect unnecessary slice-to-slice conversion by applying [:] to a slice expression."
    17  
    18  // Analyzer runs static analysis.
    19  var Analyzer = &analysis.Analyzer{
    20  	Name:     "slicedirect",
    21  	Doc:      Doc,
    22  	Requires: []*analysis.Analyzer{inspect.Analyzer},
    23  	Run:      run,
    24  }
    25  
    26  func run(pass *analysis.Pass) (interface{}, error) {
    27  	inspection, ok := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
    28  	if !ok {
    29  		return nil, errors.New("analyzer is not type *inspector.Inspector")
    30  	}
    31  
    32  	nodeFilter := []ast.Node{
    33  		(*ast.SliceExpr)(nil),
    34  	}
    35  
    36  	typeInfo := types.Info{Types: make(map[ast.Expr]types.TypeAndValue)}
    37  
    38  	inspection.Preorder(nodeFilter, func(node ast.Node) {
    39  		sliceExpr, ok := node.(*ast.SliceExpr)
    40  		if !ok {
    41  			return
    42  		}
    43  
    44  		if err := types.CheckExpr(pass.Fset, pass.Pkg, sliceExpr.X.Pos(), sliceExpr.X, &typeInfo); err != nil {
    45  			return
    46  		}
    47  
    48  		if sliceExpr.Low != nil || sliceExpr.High != nil {
    49  			return
    50  		}
    51  
    52  		switch x := typeInfo.Types[sliceExpr.X].Type.(type) {
    53  		case *types.Slice:
    54  			pass.Reportf(sliceExpr.Pos(), "Expression is already a slice.")
    55  		case *types.Basic:
    56  			if x.String() == "string" {
    57  				pass.Reportf(sliceExpr.Pos(), "Expression is already a slice.")
    58  			}
    59  		}
    60  	})
    61  
    62  	return nil, nil
    63  }