github.com/likebike/go--@v0.0.0-20190911215757-0bd925d16e96/go/src/cmd/vet/print.go (about)

     1  // Copyright 2010 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // This file contains the printf-checker.
     6  
     7  package main
     8  
     9  import (
    10  	"bytes"
    11  	"flag"
    12  	"fmt"
    13  	"go/ast"
    14  	"go/constant"
    15  	"go/token"
    16  	"go/types"
    17  	"regexp"
    18  	"strconv"
    19  	"strings"
    20  	"unicode/utf8"
    21  )
    22  
    23  var printfuncs = flag.String("printfuncs", "", "comma-separated list of print function names to check")
    24  
    25  func init() {
    26  	register("printf",
    27  		"check printf-like invocations",
    28  		checkFmtPrintfCall,
    29  		funcDecl, callExpr)
    30  }
    31  
    32  func initPrintFlags() {
    33  	if *printfuncs == "" {
    34  		return
    35  	}
    36  	for _, name := range strings.Split(*printfuncs, ",") {
    37  		if len(name) == 0 {
    38  			flag.Usage()
    39  		}
    40  
    41  		// Backwards compatibility: skip optional first argument
    42  		// index after the colon.
    43  		if colon := strings.LastIndex(name, ":"); colon > 0 {
    44  			name = name[:colon]
    45  		}
    46  
    47  		isPrint[strings.ToLower(name)] = true
    48  	}
    49  }
    50  
    51  // TODO(rsc): Incorporate user-defined printf wrappers again.
    52  // The general plan is to allow vet of one package P to output
    53  // additional information to supply to later vets of packages
    54  // importing P. Then vet of P can record a list of printf wrappers
    55  // and the later vet using P.Printf will find it in the list and check it.
    56  // That's not ready for Go 1.10.
    57  // When that does happen, uncomment the user-defined printf
    58  // wrapper tests in testdata/print.go.
    59  
    60  // isPrint records the print functions.
    61  // If a key ends in 'f' then it is assumed to be a formatted print.
    62  var isPrint = map[string]bool{
    63  	"fmt.Errorf":         true,
    64  	"fmt.Fprint":         true,
    65  	"fmt.Fprintf":        true,
    66  	"fmt.Fprintln":       true,
    67  	"fmt.Print":          true,
    68  	"fmt.Printf":         true,
    69  	"fmt.Println":        true,
    70  	"fmt.Sprint":         true,
    71  	"fmt.Sprintf":        true,
    72  	"fmt.Sprintln":       true,
    73  	"log.Fatal":          true,
    74  	"log.Fatalf":         true,
    75  	"log.Fatalln":        true,
    76  	"log.Logger.Fatal":   true,
    77  	"log.Logger.Fatalf":  true,
    78  	"log.Logger.Fatalln": true,
    79  	"log.Logger.Panic":   true,
    80  	"log.Logger.Panicf":  true,
    81  	"log.Logger.Panicln": true,
    82  	"log.Logger.Printf":  true,
    83  	"log.Logger.Println": true,
    84  	"log.Panic":          true,
    85  	"log.Panicf":         true,
    86  	"log.Panicln":        true,
    87  	"log.Print":          true,
    88  	"log.Printf":         true,
    89  	"log.Println":        true,
    90  	"testing.B.Error":    true,
    91  	"testing.B.Errorf":   true,
    92  	"testing.B.Fatal":    true,
    93  	"testing.B.Fatalf":   true,
    94  	"testing.B.Log":      true,
    95  	"testing.B.Logf":     true,
    96  	"testing.B.Skip":     true,
    97  	"testing.B.Skipf":    true,
    98  	"testing.T.Error":    true,
    99  	"testing.T.Errorf":   true,
   100  	"testing.T.Fatal":    true,
   101  	"testing.T.Fatalf":   true,
   102  	"testing.T.Log":      true,
   103  	"testing.T.Logf":     true,
   104  	"testing.T.Skip":     true,
   105  	"testing.T.Skipf":    true,
   106  	"testing.TB.Error":   true,
   107  	"testing.TB.Errorf":  true,
   108  	"testing.TB.Fatal":   true,
   109  	"testing.TB.Fatalf":  true,
   110  	"testing.TB.Log":     true,
   111  	"testing.TB.Logf":    true,
   112  	"testing.TB.Skip":    true,
   113  	"testing.TB.Skipf":   true,
   114  }
   115  
   116  // formatString returns the format string argument and its index within
   117  // the given printf-like call expression.
   118  //
   119  // The last parameter before variadic arguments is assumed to be
   120  // a format string.
   121  //
   122  // The first string literal or string constant is assumed to be a format string
   123  // if the call's signature cannot be determined.
   124  //
   125  // If it cannot find any format string parameter, it returns ("", -1).
   126  func formatString(f *File, call *ast.CallExpr) (format string, idx int) {
   127  	typ := f.pkg.types[call.Fun].Type
   128  	if typ != nil {
   129  		if sig, ok := typ.(*types.Signature); ok {
   130  			if !sig.Variadic() {
   131  				// Skip checking non-variadic functions.
   132  				return "", -1
   133  			}
   134  			idx := sig.Params().Len() - 2
   135  			if idx < 0 {
   136  				// Skip checking variadic functions without
   137  				// fixed arguments.
   138  				return "", -1
   139  			}
   140  			s, ok := stringConstantArg(f, call, idx)
   141  			if !ok {
   142  				// The last argument before variadic args isn't a string.
   143  				return "", -1
   144  			}
   145  			return s, idx
   146  		}
   147  	}
   148  
   149  	// Cannot determine call's signature. Fall back to scanning for the first
   150  	// string constant in the call.
   151  	for idx := range call.Args {
   152  		if s, ok := stringConstantArg(f, call, idx); ok {
   153  			return s, idx
   154  		}
   155  		if f.pkg.types[call.Args[idx]].Type == types.Typ[types.String] {
   156  			// Skip checking a call with a non-constant format
   157  			// string argument, since its contents are unavailable
   158  			// for validation.
   159  			return "", -1
   160  		}
   161  	}
   162  	return "", -1
   163  }
   164  
   165  // stringConstantArg returns call's string constant argument at the index idx.
   166  //
   167  // ("", false) is returned if call's argument at the index idx isn't a string
   168  // constant.
   169  func stringConstantArg(f *File, call *ast.CallExpr, idx int) (string, bool) {
   170  	if idx >= len(call.Args) {
   171  		return "", false
   172  	}
   173  	arg := call.Args[idx]
   174  	lit := f.pkg.types[arg].Value
   175  	if lit != nil && lit.Kind() == constant.String {
   176  		return constant.StringVal(lit), true
   177  	}
   178  	return "", false
   179  }
   180  
   181  // checkCall triggers the print-specific checks if the call invokes a print function.
   182  func checkFmtPrintfCall(f *File, node ast.Node) {
   183  	if f.pkg.typesPkg == nil {
   184  		// This check now requires type information.
   185  		return
   186  	}
   187  
   188  	if d, ok := node.(*ast.FuncDecl); ok && isStringer(f, d) {
   189  		// Remember we saw this.
   190  		if f.stringerPtrs == nil {
   191  			f.stringerPtrs = make(map[*ast.Object]bool)
   192  		}
   193  		if l := d.Recv.List; len(l) == 1 {
   194  			if n := l[0].Names; len(n) == 1 {
   195  				typ := f.pkg.types[l[0].Type]
   196  				_, ptrRecv := typ.Type.(*types.Pointer)
   197  				f.stringerPtrs[n[0].Obj] = ptrRecv
   198  			}
   199  		}
   200  		return
   201  	}
   202  
   203  	call, ok := node.(*ast.CallExpr)
   204  	if !ok {
   205  		return
   206  	}
   207  
   208  	// Construct name like pkg.Printf or pkg.Type.Printf for lookup.
   209  	var name string
   210  	switch x := call.Fun.(type) {
   211  	case *ast.Ident:
   212  		if fn, ok := f.pkg.uses[x].(*types.Func); ok {
   213  			var pkg string
   214  			if fn.Pkg() == nil || fn.Pkg() == f.pkg.typesPkg {
   215  				pkg = vcfg.ImportPath
   216  			} else {
   217  				pkg = fn.Pkg().Path()
   218  			}
   219  			name = pkg + "." + x.Name
   220  			break
   221  		}
   222  
   223  	case *ast.SelectorExpr:
   224  		// Check for "fmt.Printf".
   225  		if id, ok := x.X.(*ast.Ident); ok {
   226  			if pkgName, ok := f.pkg.uses[id].(*types.PkgName); ok {
   227  				name = pkgName.Imported().Path() + "." + x.Sel.Name
   228  				break
   229  			}
   230  		}
   231  
   232  		// Check for t.Logf where t is a *testing.T.
   233  		if sel := f.pkg.selectors[x]; sel != nil {
   234  			recv := sel.Recv()
   235  			if p, ok := recv.(*types.Pointer); ok {
   236  				recv = p.Elem()
   237  			}
   238  			if named, ok := recv.(*types.Named); ok {
   239  				obj := named.Obj()
   240  				var pkg string
   241  				if obj.Pkg() == nil || obj.Pkg() == f.pkg.typesPkg {
   242  					pkg = vcfg.ImportPath
   243  				} else {
   244  					pkg = obj.Pkg().Path()
   245  				}
   246  				name = pkg + "." + obj.Name() + "." + x.Sel.Name
   247  				break
   248  			}
   249  		}
   250  	}
   251  	if name == "" {
   252  		return
   253  	}
   254  
   255  	shortName := name[strings.LastIndex(name, ".")+1:]
   256  
   257  	_, ok = isPrint[name]
   258  	if !ok {
   259  		// Next look up just "printf", for use with -printfuncs.
   260  		_, ok = isPrint[strings.ToLower(shortName)]
   261  	}
   262  	if ok {
   263  		if strings.HasSuffix(name, "f") {
   264  			f.checkPrintf(call, shortName)
   265  		} else {
   266  			f.checkPrint(call, shortName)
   267  		}
   268  	}
   269  }
   270  
   271  // isStringer returns true if the provided declaration is a "String() string"
   272  // method, an implementation of fmt.Stringer.
   273  func isStringer(f *File, d *ast.FuncDecl) bool {
   274  	return d.Recv != nil && d.Name.Name == "String" && d.Type.Results != nil &&
   275  		len(d.Type.Params.List) == 0 && len(d.Type.Results.List) == 1 &&
   276  		f.pkg.types[d.Type.Results.List[0].Type].Type == types.Typ[types.String]
   277  }
   278  
   279  // isFormatter reports whether t satisfies fmt.Formatter.
   280  // Unlike fmt.Stringer, it's impossible to satisfy fmt.Formatter without importing fmt.
   281  func (f *File) isFormatter(t types.Type) bool {
   282  	return formatterType != nil && types.Implements(t, formatterType)
   283  }
   284  
   285  // formatState holds the parsed representation of a printf directive such as "%3.*[4]d".
   286  // It is constructed by parsePrintfVerb.
   287  type formatState struct {
   288  	verb     rune   // the format verb: 'd' for "%d"
   289  	format   string // the full format directive from % through verb, "%.3d".
   290  	name     string // Printf, Sprintf etc.
   291  	flags    []byte // the list of # + etc.
   292  	argNums  []int  // the successive argument numbers that are consumed, adjusted to refer to actual arg in call
   293  	firstArg int    // Index of first argument after the format in the Printf call.
   294  	// Used only during parse.
   295  	file         *File
   296  	call         *ast.CallExpr
   297  	argNum       int  // Which argument we're expecting to format now.
   298  	hasIndex     bool // Whether the argument is indexed.
   299  	indexPending bool // Whether we have an indexed argument that has not resolved.
   300  	nbytes       int  // number of bytes of the format string consumed.
   301  }
   302  
   303  // checkPrintf checks a call to a formatted print routine such as Printf.
   304  func (f *File) checkPrintf(call *ast.CallExpr, name string) {
   305  	format, idx := formatString(f, call)
   306  	if idx < 0 {
   307  		if *verbose {
   308  			f.Warn(call.Pos(), "can't check non-constant format in call to", name)
   309  		}
   310  		return
   311  	}
   312  
   313  	firstArg := idx + 1 // Arguments are immediately after format string.
   314  	if !strings.Contains(format, "%") {
   315  		if len(call.Args) > firstArg {
   316  			f.Badf(call.Pos(), "%s call has arguments but no formatting directives", name)
   317  		}
   318  		return
   319  	}
   320  	// Hard part: check formats against args.
   321  	argNum := firstArg
   322  	maxArgNum := firstArg
   323  	anyIndex := false
   324  	for i, w := 0, 0; i < len(format); i += w {
   325  		w = 1
   326  		if format[i] != '%' {
   327  			continue
   328  		}
   329  		state := f.parsePrintfVerb(call, name, format[i:], firstArg, argNum)
   330  		if state == nil {
   331  			return
   332  		}
   333  		w = len(state.format)
   334  		if !f.okPrintfArg(call, state) { // One error per format is enough.
   335  			return
   336  		}
   337  		if state.hasIndex {
   338  			anyIndex = true
   339  		}
   340  		if len(state.argNums) > 0 {
   341  			// Continue with the next sequential argument.
   342  			argNum = state.argNums[len(state.argNums)-1] + 1
   343  		}
   344  		for _, n := range state.argNums {
   345  			if n >= maxArgNum {
   346  				maxArgNum = n + 1
   347  			}
   348  		}
   349  	}
   350  	// Dotdotdot is hard.
   351  	if call.Ellipsis.IsValid() && maxArgNum >= len(call.Args)-1 {
   352  		return
   353  	}
   354  	// If any formats are indexed, extra arguments are ignored.
   355  	if anyIndex {
   356  		return
   357  	}
   358  	// There should be no leftover arguments.
   359  	if maxArgNum != len(call.Args) {
   360  		expect := maxArgNum - firstArg
   361  		numArgs := len(call.Args) - firstArg
   362  		f.Badf(call.Pos(), "%s call needs %v but has %v", name, count(expect, "arg"), count(numArgs, "arg"))
   363  	}
   364  }
   365  
   366  // parseFlags accepts any printf flags.
   367  func (s *formatState) parseFlags() {
   368  	for s.nbytes < len(s.format) {
   369  		switch c := s.format[s.nbytes]; c {
   370  		case '#', '0', '+', '-', ' ':
   371  			s.flags = append(s.flags, c)
   372  			s.nbytes++
   373  		default:
   374  			return
   375  		}
   376  	}
   377  }
   378  
   379  // scanNum advances through a decimal number if present.
   380  func (s *formatState) scanNum() {
   381  	for ; s.nbytes < len(s.format); s.nbytes++ {
   382  		c := s.format[s.nbytes]
   383  		if c < '0' || '9' < c {
   384  			return
   385  		}
   386  	}
   387  }
   388  
   389  // parseIndex scans an index expression. It returns false if there is a syntax error.
   390  func (s *formatState) parseIndex() bool {
   391  	if s.nbytes == len(s.format) || s.format[s.nbytes] != '[' {
   392  		return true
   393  	}
   394  	// Argument index present.
   395  	s.nbytes++ // skip '['
   396  	start := s.nbytes
   397  	s.scanNum()
   398  	ok := true
   399  	if s.nbytes == len(s.format) || s.nbytes == start || s.format[s.nbytes] != ']' {
   400  		ok = false
   401  		s.nbytes = strings.Index(s.format, "]")
   402  		if s.nbytes < 0 {
   403  			s.file.Badf(s.call.Pos(), "%s format %s is missing closing ]", s.name, s.format)
   404  			return false
   405  		}
   406  	}
   407  	arg32, err := strconv.ParseInt(s.format[start:s.nbytes], 10, 32)
   408  	if err != nil || !ok || arg32 <= 0 || arg32 > int64(len(s.call.Args)-s.firstArg) {
   409  		s.file.Badf(s.call.Pos(), "%s format has invalid argument index [%s]", s.name, s.format[start:s.nbytes])
   410  		return false
   411  	}
   412  	s.nbytes++ // skip ']'
   413  	arg := int(arg32)
   414  	arg += s.firstArg - 1 // We want to zero-index the actual arguments.
   415  	s.argNum = arg
   416  	s.hasIndex = true
   417  	s.indexPending = true
   418  	return true
   419  }
   420  
   421  // parseNum scans a width or precision (or *). It returns false if there's a bad index expression.
   422  func (s *formatState) parseNum() bool {
   423  	if s.nbytes < len(s.format) && s.format[s.nbytes] == '*' {
   424  		if s.indexPending { // Absorb it.
   425  			s.indexPending = false
   426  		}
   427  		s.nbytes++
   428  		s.argNums = append(s.argNums, s.argNum)
   429  		s.argNum++
   430  	} else {
   431  		s.scanNum()
   432  	}
   433  	return true
   434  }
   435  
   436  // parsePrecision scans for a precision. It returns false if there's a bad index expression.
   437  func (s *formatState) parsePrecision() bool {
   438  	// If there's a period, there may be a precision.
   439  	if s.nbytes < len(s.format) && s.format[s.nbytes] == '.' {
   440  		s.flags = append(s.flags, '.') // Treat precision as a flag.
   441  		s.nbytes++
   442  		if !s.parseIndex() {
   443  			return false
   444  		}
   445  		if !s.parseNum() {
   446  			return false
   447  		}
   448  	}
   449  	return true
   450  }
   451  
   452  // parsePrintfVerb looks the formatting directive that begins the format string
   453  // and returns a formatState that encodes what the directive wants, without looking
   454  // at the actual arguments present in the call. The result is nil if there is an error.
   455  func (f *File) parsePrintfVerb(call *ast.CallExpr, name, format string, firstArg, argNum int) *formatState {
   456  	state := &formatState{
   457  		format:   format,
   458  		name:     name,
   459  		flags:    make([]byte, 0, 5),
   460  		argNum:   argNum,
   461  		argNums:  make([]int, 0, 1),
   462  		nbytes:   1, // There's guaranteed to be a percent sign.
   463  		firstArg: firstArg,
   464  		file:     f,
   465  		call:     call,
   466  	}
   467  	// There may be flags.
   468  	state.parseFlags()
   469  	// There may be an index.
   470  	if !state.parseIndex() {
   471  		return nil
   472  	}
   473  	// There may be a width.
   474  	if !state.parseNum() {
   475  		return nil
   476  	}
   477  	// There may be a precision.
   478  	if !state.parsePrecision() {
   479  		return nil
   480  	}
   481  	// Now a verb, possibly prefixed by an index (which we may already have).
   482  	if !state.indexPending && !state.parseIndex() {
   483  		return nil
   484  	}
   485  	if state.nbytes == len(state.format) {
   486  		f.Badf(call.Pos(), "%s format %s is missing verb at end of string", name, state.format)
   487  		return nil
   488  	}
   489  	verb, w := utf8.DecodeRuneInString(state.format[state.nbytes:])
   490  	state.verb = verb
   491  	state.nbytes += w
   492  	if verb != '%' {
   493  		state.argNums = append(state.argNums, state.argNum)
   494  	}
   495  	state.format = state.format[:state.nbytes]
   496  	return state
   497  }
   498  
   499  // printfArgType encodes the types of expressions a printf verb accepts. It is a bitmask.
   500  type printfArgType int
   501  
   502  const (
   503  	argBool printfArgType = 1 << iota
   504  	argInt
   505  	argRune
   506  	argString
   507  	argFloat
   508  	argComplex
   509  	argPointer
   510  	anyType printfArgType = ^0
   511  )
   512  
   513  type printVerb struct {
   514  	verb  rune   // User may provide verb through Formatter; could be a rune.
   515  	flags string // known flags are all ASCII
   516  	typ   printfArgType
   517  }
   518  
   519  // Common flag sets for printf verbs.
   520  const (
   521  	noFlag       = ""
   522  	numFlag      = " -+.0"
   523  	sharpNumFlag = " -+.0#"
   524  	allFlags     = " -+.0#"
   525  )
   526  
   527  // printVerbs identifies which flags are known to printf for each verb.
   528  var printVerbs = []printVerb{
   529  	// '-' is a width modifier, always valid.
   530  	// '.' is a precision for float, max width for strings.
   531  	// '+' is required sign for numbers, Go format for %v.
   532  	// '#' is alternate format for several verbs.
   533  	// ' ' is spacer for numbers
   534  	{'%', noFlag, 0},
   535  	{'b', numFlag, argInt | argFloat | argComplex},
   536  	{'c', "-", argRune | argInt},
   537  	{'d', numFlag, argInt},
   538  	{'e', sharpNumFlag, argFloat | argComplex},
   539  	{'E', sharpNumFlag, argFloat | argComplex},
   540  	{'f', sharpNumFlag, argFloat | argComplex},
   541  	{'F', sharpNumFlag, argFloat | argComplex},
   542  	{'g', sharpNumFlag, argFloat | argComplex},
   543  	{'G', sharpNumFlag, argFloat | argComplex},
   544  	{'o', sharpNumFlag, argInt},
   545  	{'p', "-#", argPointer},
   546  	{'q', " -+.0#", argRune | argInt | argString},
   547  	{'s', " -+.0", argString},
   548  	{'t', "-", argBool},
   549  	{'T', "-", anyType},
   550  	{'U', "-#", argRune | argInt},
   551  	{'v', allFlags, anyType},
   552  	{'x', sharpNumFlag, argRune | argInt | argString},
   553  	{'X', sharpNumFlag, argRune | argInt | argString},
   554  }
   555  
   556  // okPrintfArg compares the formatState to the arguments actually present,
   557  // reporting any discrepancies it can discern. If the final argument is ellipsissed,
   558  // there's little it can do for that.
   559  func (f *File) okPrintfArg(call *ast.CallExpr, state *formatState) (ok bool) {
   560  	var v printVerb
   561  	found := false
   562  	// Linear scan is fast enough for a small list.
   563  	for _, v = range printVerbs {
   564  		if v.verb == state.verb {
   565  			found = true
   566  			break
   567  		}
   568  	}
   569  
   570  	// Does current arg implement fmt.Formatter?
   571  	formatter := false
   572  	if state.argNum < len(call.Args) {
   573  		if tv, ok := f.pkg.types[call.Args[state.argNum]]; ok {
   574  			formatter = f.isFormatter(tv.Type)
   575  		}
   576  	}
   577  
   578  	if !formatter {
   579  		if !found {
   580  			f.Badf(call.Pos(), "%s format %s has unknown verb %c", state.name, state.format, state.verb)
   581  			return false
   582  		}
   583  		for _, flag := range state.flags {
   584  			// TODO: Disable complaint about '0' for Go 1.10. To be fixed properly in 1.11.
   585  			// See issues 23598 and 23605.
   586  			if flag == '0' {
   587  				continue
   588  			}
   589  			if !strings.ContainsRune(v.flags, rune(flag)) {
   590  				f.Badf(call.Pos(), "%s format %s has unrecognized flag %c", state.name, state.format, flag)
   591  				return false
   592  			}
   593  		}
   594  	}
   595  	// Verb is good. If len(state.argNums)>trueArgs, we have something like %.*s and all
   596  	// but the final arg must be an integer.
   597  	trueArgs := 1
   598  	if state.verb == '%' {
   599  		trueArgs = 0
   600  	}
   601  	nargs := len(state.argNums)
   602  	for i := 0; i < nargs-trueArgs; i++ {
   603  		argNum := state.argNums[i]
   604  		if !f.argCanBeChecked(call, i, state) {
   605  			return
   606  		}
   607  		arg := call.Args[argNum]
   608  		if !f.matchArgType(argInt, nil, arg) {
   609  			f.Badf(call.Pos(), "%s format %s uses non-int %s as argument of *", state.name, state.format, f.gofmt(arg))
   610  			return false
   611  		}
   612  	}
   613  	if state.verb == '%' || formatter {
   614  		return true
   615  	}
   616  	argNum := state.argNums[len(state.argNums)-1]
   617  	if !f.argCanBeChecked(call, len(state.argNums)-1, state) {
   618  		return false
   619  	}
   620  	arg := call.Args[argNum]
   621  	if f.isFunctionValue(arg) && state.verb != 'p' && state.verb != 'T' {
   622  		f.Badf(call.Pos(), "%s format %s arg %s is a func value, not called", state.name, state.format, f.gofmt(arg))
   623  		return false
   624  	}
   625  	if !f.matchArgType(v.typ, nil, arg) {
   626  		typeString := ""
   627  		if typ := f.pkg.types[arg].Type; typ != nil {
   628  			typeString = typ.String()
   629  		}
   630  		f.Badf(call.Pos(), "%s format %s has arg %s of wrong type %s", state.name, state.format, f.gofmt(arg), typeString)
   631  		return false
   632  	}
   633  	if v.typ&argString != 0 && v.verb != 'T' && !bytes.Contains(state.flags, []byte{'#'}) && f.recursiveStringer(arg) {
   634  		f.Badf(call.Pos(), "%s format %s with arg %s causes recursive String method call", state.name, state.format, f.gofmt(arg))
   635  		return false
   636  	}
   637  	return true
   638  }
   639  
   640  // recursiveStringer reports whether the provided argument is r or &r for the
   641  // fmt.Stringer receiver identifier r.
   642  func (f *File) recursiveStringer(e ast.Expr) bool {
   643  	if len(f.stringerPtrs) == 0 {
   644  		return false
   645  	}
   646  	ptr := false
   647  	var obj *ast.Object
   648  	switch e := e.(type) {
   649  	case *ast.Ident:
   650  		obj = e.Obj
   651  	case *ast.UnaryExpr:
   652  		if id, ok := e.X.(*ast.Ident); ok && e.Op == token.AND {
   653  			obj = id.Obj
   654  			ptr = true
   655  		}
   656  	}
   657  
   658  	// It's unlikely to be a recursive stringer if it has a Format method.
   659  	if typ := f.pkg.types[e].Type; typ != nil {
   660  		// Not a perfect match; see issue 6259.
   661  		if f.hasMethod(typ, "Format") {
   662  			return false
   663  		}
   664  	}
   665  
   666  	// We compare the underlying Object, which checks that the identifier
   667  	// is the one we declared as the receiver for the String method in
   668  	// which this printf appears.
   669  	ptrRecv, exist := f.stringerPtrs[obj]
   670  	if !exist {
   671  		return false
   672  	}
   673  	// We also need to check that using &t when we declared String
   674  	// on (t *T) is ok; in such a case, the address is printed.
   675  	if ptr && ptrRecv {
   676  		return false
   677  	}
   678  	return true
   679  }
   680  
   681  // isFunctionValue reports whether the expression is a function as opposed to a function call.
   682  // It is almost always a mistake to print a function value.
   683  func (f *File) isFunctionValue(e ast.Expr) bool {
   684  	if typ := f.pkg.types[e].Type; typ != nil {
   685  		_, ok := typ.(*types.Signature)
   686  		return ok
   687  	}
   688  	return false
   689  }
   690  
   691  // argCanBeChecked reports whether the specified argument is statically present;
   692  // it may be beyond the list of arguments or in a terminal slice... argument, which
   693  // means we can't see it.
   694  func (f *File) argCanBeChecked(call *ast.CallExpr, formatArg int, state *formatState) bool {
   695  	argNum := state.argNums[formatArg]
   696  	if argNum <= 0 {
   697  		// Shouldn't happen, so catch it with prejudice.
   698  		panic("negative arg num")
   699  	}
   700  	if argNum < len(call.Args)-1 {
   701  		return true // Always OK.
   702  	}
   703  	if call.Ellipsis.IsValid() {
   704  		return false // We just can't tell; there could be many more arguments.
   705  	}
   706  	if argNum < len(call.Args) {
   707  		return true
   708  	}
   709  	// There are bad indexes in the format or there are fewer arguments than the format needs.
   710  	// This is the argument number relative to the format: Printf("%s", "hi") will give 1 for the "hi".
   711  	arg := argNum - state.firstArg + 1 // People think of arguments as 1-indexed.
   712  	f.Badf(call.Pos(), "%s format %s reads arg #%d, but call has only %v", state.name, state.format, arg, count(len(call.Args)-state.firstArg, "arg"))
   713  	return false
   714  }
   715  
   716  // printFormatRE is the regexp we match and report as a possible format string
   717  // in the first argument to unformatted prints like fmt.Print.
   718  // We exclude the space flag, so that printing a string like "x % y" is not reported as a format.
   719  var printFormatRE = regexp.MustCompile(`%` + flagsRE + numOptRE + `\.?` + numOptRE + indexOptRE + verbRE)
   720  
   721  const (
   722  	flagsRE    = `[+\-#]*`
   723  	indexOptRE = `(\[[0-9]+\])?`
   724  	numOptRE   = `([0-9]+|` + indexOptRE + `\*)?`
   725  	verbRE     = `[bcdefgopqstvxEFGUX]`
   726  )
   727  
   728  // checkPrint checks a call to an unformatted print routine such as Println.
   729  func (f *File) checkPrint(call *ast.CallExpr, name string) {
   730  	firstArg := 0
   731  	typ := f.pkg.types[call.Fun].Type
   732  	if typ == nil {
   733  		// Skip checking functions with unknown type.
   734  		return
   735  	}
   736  	if sig, ok := typ.(*types.Signature); ok {
   737  		if !sig.Variadic() {
   738  			// Skip checking non-variadic functions.
   739  			return
   740  		}
   741  		params := sig.Params()
   742  		firstArg = params.Len() - 1
   743  
   744  		typ := params.At(firstArg).Type()
   745  		typ = typ.(*types.Slice).Elem()
   746  		it, ok := typ.(*types.Interface)
   747  		if !ok || !it.Empty() {
   748  			// Skip variadic functions accepting non-interface{} args.
   749  			return
   750  		}
   751  	}
   752  	args := call.Args
   753  	if len(args) <= firstArg {
   754  		// Skip calls without variadic args.
   755  		return
   756  	}
   757  	args = args[firstArg:]
   758  
   759  	if firstArg == 0 {
   760  		if sel, ok := call.Args[0].(*ast.SelectorExpr); ok {
   761  			if x, ok := sel.X.(*ast.Ident); ok {
   762  				if x.Name == "os" && strings.HasPrefix(sel.Sel.Name, "Std") {
   763  					f.Badf(call.Pos(), "%s does not take io.Writer but has first arg %s", name, f.gofmt(call.Args[0]))
   764  				}
   765  			}
   766  		}
   767  	}
   768  
   769  	arg := args[0]
   770  	if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING {
   771  		// Ignore trailing % character in lit.Value.
   772  		// The % in "abc 0.0%" couldn't be a formatting directive.
   773  		s := strings.TrimSuffix(lit.Value, `%"`)
   774  		if strings.Contains(s, "%") {
   775  			m := printFormatRE.FindStringSubmatch(s)
   776  			if m != nil {
   777  				f.Badf(call.Pos(), "%s call has possible formatting directive %s", name, m[0])
   778  			}
   779  		}
   780  	}
   781  	if strings.HasSuffix(name, "ln") {
   782  		// The last item, if a string, should not have a newline.
   783  		arg = args[len(args)-1]
   784  		if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING {
   785  			str, _ := strconv.Unquote(lit.Value)
   786  			if strings.HasSuffix(str, "\n") {
   787  				f.Badf(call.Pos(), "%s arg list ends with redundant newline", name)
   788  			}
   789  		}
   790  	}
   791  	for _, arg := range args {
   792  		if f.isFunctionValue(arg) {
   793  			f.Badf(call.Pos(), "%s arg %s is a func value, not called", name, f.gofmt(arg))
   794  		}
   795  		if f.recursiveStringer(arg) {
   796  			f.Badf(call.Pos(), "%s arg %s causes recursive call to String method", name, f.gofmt(arg))
   797  		}
   798  	}
   799  }
   800  
   801  // count(n, what) returns "1 what" or "N whats"
   802  // (assuming the plural of what is whats).
   803  func count(n int, what string) string {
   804  	if n == 1 {
   805  		return "1 " + what
   806  	}
   807  	return fmt.Sprintf("%d %ss", n, what)
   808  }