1 // Copyright 2023 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 // Package printf defines an Analyzer that checks consistency 6 // of Printf format strings and arguments. 7 // 8 // # Analyzer printf 9 // 10 // printf: check consistency of Printf format strings and arguments 11 // 12 // The check applies to calls of the formatting functions such as 13 // [fmt.Printf] and [fmt.Sprintf], as well as any detected wrappers of 14 // those functions such as [log.Printf]. It reports a variety of 15 // mistakes such as syntax errors in the format string and mismatches 16 // (of number and type) between the verbs and their arguments. 17 // 18 // See the documentation of the fmt package for the complete set of 19 // format operators and their operand types. 20 // 21 // # Examples 22 // 23 // The %d format operator requires an integer operand. 24 // Here it is incorrectly applied to a string: 25 // 26 // fmt.Printf("%d", "hello") // fmt.Printf format %d has arg "hello" of wrong type string 27 // 28 // A call to Printf must have as many operands as there are "verbs" in 29 // the format string, not too few: 30 // 31 // fmt.Printf("%d") // fmt.Printf format reads arg 1, but call has 0 args 32 // 33 // nor too many: 34 // 35 // fmt.Printf("%d", 1, 2) // fmt.Printf call needs 1 arg, but has 2 args 36 // 37 // Explicit argument indexes must be no greater than the number of 38 // arguments: 39 // 40 // fmt.Printf("%[3]d", 1, 2) // fmt.Printf call has invalid argument index 3 41 // 42 // The checker also uses a heuristic to report calls to Print-like 43 // functions that appear to have been intended for their Printf-like 44 // counterpart: 45 // 46 // log.Print("%d", 123) // log.Print call has possible formatting directive %d 47 // 48 // # Inferred printf wrappers 49 // 50 // Functions that delegate their arguments to fmt.Printf are 51 // considered "printf wrappers"; calls to them are subject to the same 52 // checking. In this example, logf is a printf wrapper: 53 // 54 // func logf(level int, format string, args ...any) { 55 // if enabled(level) { 56 // log.Printf(format, args...) 57 // } 58 // } 59 // 60 // logf(3, "invalid request: %v") // logf format reads arg 1, but call has 0 args 61 // 62 // To enable printf checking on a function that is not found by this 63 // analyzer's heuristics (for example, because control is obscured by 64 // dynamic method calls), insert a bogus call: 65 // 66 // func MyPrintf(format string, args ...any) { 67 // if false { 68 // _ = fmt.Sprintf(format, args...) // enable printf checking 69 // } 70 // ... 71 // } 72 // 73 // # Specifying printf wrappers by flag 74 // 75 // The -funcs flag specifies a comma-separated list of names of 76 // additional known formatting functions or methods. (This legacy flag 77 // is rarely used due to the automatic inference described above.) 78 // 79 // If the name contains a period, it must denote a specific function 80 // using one of the following forms: 81 // 82 // dir/pkg.Function 83 // dir/pkg.Type.Method 84 // (*dir/pkg.Type).Method 85 // 86 // Otherwise the name is interpreted as a case-insensitive unqualified 87 // identifier such as "errorf". Either way, if a listed name ends in f, the 88 // function is assumed to be Printf-like, taking a format string before the 89 // argument list. Otherwise it is assumed to be Print-like, taking a list 90 // of arguments with no format string. 91 package printf 92