src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

st1008.go (1763B)


      1 package st1008
      2 
      3 import (
      4 	"go/types"
      5 
      6 	"honnef.co/go/tools/analysis/lint"
      7 	"honnef.co/go/tools/analysis/report"
      8 	"honnef.co/go/tools/internal/passes/buildir"
      9 
     10 	"golang.org/x/tools/go/analysis"
     11 )
     12 
     13 var SCAnalyzer = lint.InitializeAnalyzer(&lint.Analyzer{
     14 	Analyzer: &analysis.Analyzer{
     15 		Name:     "ST1008",
     16 		Run:      run,
     17 		Requires: []*analysis.Analyzer{buildir.Analyzer},
     18 	},
     19 	Doc: &lint.RawDocumentation{
     20 		Title:   `A function's error value should be its last return value`,
     21 		Text:    `A function's error value should be its last return value.`,
     22 		Since:   `2019.1`,
     23 		MergeIf: lint.MergeIfAny,
     24 	},
     25 })
     26 
     27 var Analyzer = SCAnalyzer.Analyzer
     28 
     29 func run(pass *analysis.Pass) (any, error) {
     30 fnLoop:
     31 	for _, fn := range pass.ResultOf[buildir.Analyzer].(*buildir.IR).SrcFuncs {
     32 		sig := fn.Type().(*types.Signature)
     33 		rets := sig.Results()
     34 		if rets == nil || rets.Len() < 2 {
     35 			continue
     36 		}
     37 
     38 		if types.Unalias(rets.At(rets.Len()-1).Type()) == types.Universe.Lookup("error").Type() {
     39 			// Last return type is error. If the function also returns
     40 			// errors in other positions, that's fine.
     41 			continue
     42 		}
     43 
     44 		if rets.Len() >= 2 &&
     45 			types.Unalias(rets.At(rets.Len()-1).Type()) == types.Universe.Lookup("bool").Type() &&
     46 			types.Unalias(rets.At(rets.Len()-2).Type()) == types.Universe.Lookup("error").Type() {
     47 			// Accept (..., error, bool) and assume it's a comma-ok function. It's not clear whether the bool should come last or not for these kinds of functions.
     48 			continue
     49 		}
     50 		for i := rets.Len() - 2; i >= 0; i-- {
     51 			if types.Unalias(rets.At(i).Type()) == types.Universe.Lookup("error").Type() {
     52 				report.Report(pass, rets.At(i), "error should be returned as the last argument", report.ShortRange())
     53 				continue fnLoop
     54 			}
     55 		}
     56 	}
     57 	return nil, nil
     58 }