src

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

sa9002.go (1729B)


      1 package sa9002
      2 
      3 import (
      4 	"fmt"
      5 	"go/ast"
      6 	"strconv"
      7 
      8 	"honnef.co/go/tools/analysis/code"
      9 	"honnef.co/go/tools/analysis/edit"
     10 	"honnef.co/go/tools/analysis/lint"
     11 	"honnef.co/go/tools/analysis/report"
     12 	"honnef.co/go/tools/go/types/typeutil"
     13 
     14 	"golang.org/x/tools/go/analysis"
     15 	"golang.org/x/tools/go/analysis/passes/inspect"
     16 )
     17 
     18 var SCAnalyzer = lint.InitializeAnalyzer(&lint.Analyzer{
     19 	Analyzer: &analysis.Analyzer{
     20 		Name:     "SA9002",
     21 		Run:      run,
     22 		Requires: []*analysis.Analyzer{inspect.Analyzer},
     23 	},
     24 	Doc: &lint.RawDocumentation{
     25 		Title:    `Using a non-octal \'os.FileMode\' that looks like it was meant to be in octal.`,
     26 		Since:    "2017.1",
     27 		Severity: lint.SeverityWarning,
     28 		MergeIf:  lint.MergeIfAny,
     29 	},
     30 })
     31 
     32 var Analyzer = SCAnalyzer.Analyzer
     33 
     34 func run(pass *analysis.Pass) (any, error) {
     35 	fn := func(node ast.Node) {
     36 		call := node.(*ast.CallExpr)
     37 		for _, arg := range call.Args {
     38 			lit, ok := arg.(*ast.BasicLit)
     39 			if !ok {
     40 				continue
     41 			}
     42 			if !typeutil.IsTypeWithName(pass.TypesInfo.TypeOf(lit), "os.FileMode") &&
     43 				!typeutil.IsTypeWithName(pass.TypesInfo.TypeOf(lit), "io/fs.FileMode") {
     44 				continue
     45 			}
     46 			if len(lit.Value) == 3 &&
     47 				lit.Value[0] != '0' &&
     48 				lit.Value[0] >= '0' && lit.Value[0] <= '7' &&
     49 				lit.Value[1] >= '0' && lit.Value[1] <= '7' &&
     50 				lit.Value[2] >= '0' && lit.Value[2] <= '7' {
     51 
     52 				v, err := strconv.ParseInt(lit.Value, 10, 64)
     53 				if err != nil {
     54 					continue
     55 				}
     56 				report.Report(pass, arg, fmt.Sprintf("file mode '%s' evaluates to %#o; did you mean '0%s'?", lit.Value, v, lit.Value),
     57 					report.Fixes(edit.Fix("Fix octal literal", edit.ReplaceWithString(arg, "0"+lit.Value))))
     58 			}
     59 		}
     60 	}
     61 	code.Preorder(pass, fn, (*ast.CallExpr)(nil))
     62 	return nil, nil
     63 }