src

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

sa4001.go (1573B)


      1 package sa4001
      2 
      3 import (
      4 	"go/ast"
      5 	"regexp"
      6 
      7 	"honnef.co/go/tools/analysis/code"
      8 	"honnef.co/go/tools/analysis/lint"
      9 	"honnef.co/go/tools/analysis/report"
     10 	"honnef.co/go/tools/pattern"
     11 
     12 	"golang.org/x/tools/go/analysis"
     13 	"golang.org/x/tools/go/analysis/passes/inspect"
     14 )
     15 
     16 var SCAnalyzer = lint.InitializeAnalyzer(&lint.Analyzer{
     17 	Analyzer: &analysis.Analyzer{
     18 		Name:     "SA4001",
     19 		Run:      run,
     20 		Requires: []*analysis.Analyzer{inspect.Analyzer},
     21 	},
     22 	Doc: &lint.RawDocumentation{
     23 		Title:    `\'&*x\' gets simplified to \'x\', it does not copy \'x\'`,
     24 		Since:    "2017.1",
     25 		Severity: lint.SeverityWarning,
     26 		MergeIf:  lint.MergeIfAny,
     27 	},
     28 })
     29 
     30 var Analyzer = SCAnalyzer.Analyzer
     31 
     32 var (
     33 	// cgo produces code like fn(&*_Cvar_kSomeCallbacks) which we don't
     34 	// want to flag.
     35 	cgoIdent               = regexp.MustCompile(`^_C(func|var)_.+$`)
     36 	checkIneffectiveCopyQ1 = pattern.MustParse(`(UnaryExpr "&" (StarExpr obj))`)
     37 	checkIneffectiveCopyQ2 = pattern.MustParse(`(StarExpr (UnaryExpr "&" _))`)
     38 )
     39 
     40 func run(pass *analysis.Pass) (any, error) {
     41 	fn := func(node ast.Node) {
     42 		if m, ok := code.Match(pass, checkIneffectiveCopyQ1, node); ok {
     43 			if ident, ok := m.State["obj"].(*ast.Ident); !ok || !cgoIdent.MatchString(ident.Name) {
     44 				report.Report(pass, node, "&*x will be simplified to x. It will not copy x.")
     45 			}
     46 		} else if _, ok := code.Match(pass, checkIneffectiveCopyQ2, node); ok {
     47 			report.Report(pass, node, "*&x will be simplified to x. It will not copy x.")
     48 		}
     49 	}
     50 	code.Preorder(pass, fn, (*ast.UnaryExpr)(nil), (*ast.StarExpr)(nil))
     51 	return nil, nil
     52 }