honnef.co/go/tools@v0.5.0-0.dev.0.20240520180541-dcae280a5e87/staticcheck/sa6006/sa6006.go (about) 1 package sa6006 2 3 import ( 4 "go/ast" 5 6 "honnef.co/go/tools/analysis/code" 7 "honnef.co/go/tools/analysis/lint" 8 "honnef.co/go/tools/analysis/report" 9 "honnef.co/go/tools/pattern" 10 11 "golang.org/x/tools/go/analysis" 12 "golang.org/x/tools/go/analysis/passes/inspect" 13 ) 14 15 var SCAnalyzer = lint.InitializeAnalyzer(&lint.Analyzer{ 16 Analyzer: &analysis.Analyzer{ 17 Name: "SA6006", 18 Run: run, 19 Requires: []*analysis.Analyzer{inspect.Analyzer}, 20 }, 21 Doc: &lint.Documentation{ 22 Title: `Using io.WriteString to write \'[]byte\'`, 23 Text: `Using io.WriteString to write a slice of bytes, as in 24 25 io.WriteString(w, string(b)) 26 27 is both unnecessary and inefficient. Converting from \'[]byte\' to \'string\' 28 has to allocate and copy the data, and we could simply use \'w.Write(b)\' 29 instead.`, 30 31 Since: "Unreleased", 32 }, 33 }) 34 35 var Analyzer = SCAnalyzer.Analyzer 36 37 var ioWriteStringConversion = pattern.MustParse(`(CallExpr (Symbol "io.WriteString") [_ (CallExpr (Builtin "string") [arg])])`) 38 39 func run(pass *analysis.Pass) (interface{}, error) { 40 fn := func(node ast.Node) { 41 m, ok := code.Match(pass, ioWriteStringConversion, node) 42 if !ok { 43 return 44 } 45 if !code.IsOfStringConvertibleByteSlice(pass, m.State["arg"].(ast.Expr)) { 46 return 47 } 48 report.Report(pass, node, "use io.Writer.Write instead of converting from []byte to string to use io.WriteString") 49 } 50 code.Preorder(pass, fn, (*ast.CallExpr)(nil)) 51 52 return nil, nil 53 }