func init() { … } var doc … var Analyzer … type Kind … const KindNone … const KindPrint … const KindPrintf … const KindErrorf … func (kind Kind) String() string { … } type Result … // Kind reports whether fn behaves like fmt.Print or fmt.Printf. func (r *Result) Kind(fn *types.Func) Kind { … } type isWrapper … func (f *isWrapper) AFact() { … } func (f *isWrapper) String() string { … } func run(pass *analysis.Pass) (interface{ … } type printfWrapper … type printfCaller … // maybePrintfWrapper decides whether decl (a declared function) may be a wrapper // around a fmt.Printf or fmt.Print function. If so it returns a printfWrapper // function describing the declaration. Later processing will analyze the // graph of potential printf wrappers to pick out the ones that are true wrappers. // A function may be a Printf or Print wrapper if its last argument is ...interface{}. // If the next-to-last argument is a string, then this may be a Printf wrapper. // Otherwise it may be a Print wrapper. func maybePrintfWrapper(info *types.Info, decl ast.Decl) *printfWrapper { … } // findPrintfLike scans the entire package to find printf-like functions. func findPrintfLike(pass *analysis.Pass, res *Result) (interface{ … } func match(info *types.Info, arg ast.Expr, param *types.Var) bool { … } // checkPrintfFwd checks that a printf-forwarding wrapper is forwarding correctly. // It diagnoses writing fmt.Printf(format, args) instead of fmt.Printf(format, args...). func checkPrintfFwd(pass *analysis.Pass, w *printfWrapper, call *ast.CallExpr, kind Kind, res *Result) { … } var isPrint … // formatStringIndex returns the index of the format string (the last // non-variadic parameter) within the given printf-like call // expression, or -1 if unknown. func formatStringIndex(pass *analysis.Pass, call *ast.CallExpr) int { … } // stringConstantExpr returns expression's string constant value. // // ("", false) is returned if expression isn't a string // constant. func stringConstantExpr(pass *analysis.Pass, expr ast.Expr) (string, bool) { … } // checkCall triggers the print-specific checks if the call invokes a print function. func checkCall(pass *analysis.Pass) { … } func printfNameAndKind(pass *analysis.Pass, call *ast.CallExpr) (fn *types.Func, kind Kind) { … } // isFormatter reports whether t could satisfy fmt.Formatter. // The only interface method to look for is "Format(State, rune)". func isFormatter(typ types.Type) bool { … } type formatState … // checkPrintf checks a call to a formatted print routine such as Printf. func checkPrintf(pass *analysis.Pass, kind Kind, call *ast.CallExpr, fn *types.Func) { … } // parseFlags accepts any printf flags. func (s *formatState) parseFlags() { … } // scanNum advances through a decimal number if present. func (s *formatState) scanNum() { … } // parseIndex scans an index expression. It returns false if there is a syntax error. func (s *formatState) parseIndex() bool { … } // parseNum scans a width or precision (or *). It returns false if there's a bad index expression. func (s *formatState) parseNum() bool { … } // parsePrecision scans for a precision. It returns false if there's a bad index expression. func (s *formatState) parsePrecision() bool { … } // parsePrintfVerb looks the formatting directive that begins the format string // and returns a formatState that encodes what the directive wants, without looking // at the actual arguments present in the call. The result is nil if there is an error. func parsePrintfVerb(pass *analysis.Pass, call *ast.CallExpr, name, format string, firstArg, argNum int) *formatState { … } type printfArgType … const argBool … const argInt … const argRune … const argString … const argFloat … const argComplex … const argPointer … const argError … const anyType … type printVerb … const noFlag … const numFlag … const sharpNumFlag … const allFlags … var printVerbs … // okPrintfArg compares the formatState to the arguments actually present, // reporting any discrepancies it can discern. If the final argument is ellipsissed, // there's little it can do for that. func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, state *formatState) (ok bool) { … } // recursiveStringer reports whether the argument e is a potential // recursive call to stringer or is an error, such as t and &t in these examples: // // func (t *T) String() string { printf("%s", t) } // func (t T) Error() string { printf("%s", t) } // func (t T) String() string { printf("%s", &t) } func recursiveStringer(pass *analysis.Pass, e ast.Expr) (string, bool) { … } // isStringer reports whether the method signature matches the String() definition in fmt.Stringer. func isStringer(sig *types.Signature) bool { … } // isFunctionValue reports whether the expression is a function as opposed to a function call. // It is almost always a mistake to print a function value. func isFunctionValue(pass *analysis.Pass, e ast.Expr) bool { … } // argCanBeChecked reports whether the specified argument is statically present; // it may be beyond the list of arguments or in a terminal slice... argument, which // means we can't see it. func argCanBeChecked(pass *analysis.Pass, call *ast.CallExpr, formatArg int, state *formatState) bool { … } var printFormatRE … const flagsRE … const indexOptRE … const numOptRE … const verbRE … // checkPrint checks a call to an unformatted print routine such as Println. func checkPrint(pass *analysis.Pass, call *ast.CallExpr, fn *types.Func) { … } // count(n, what) returns "1 what" or "N whats" // (assuming the plural of what is whats). func count(n int, what string) string { … } type stringSet … func (ss stringSet) String() string { … } func (ss stringSet) Set(flag string) error { … } var suppressNonconstants …