honnef.co/go/tools@v0.5.0-0.dev.0.20240520180541-dcae280a5e87/analysis/facts/generated/generated.go (about) 1 package generated 2 3 import ( 4 "bufio" 5 "bytes" 6 "io" 7 "os" 8 "reflect" 9 "strings" 10 11 "golang.org/x/tools/go/analysis" 12 ) 13 14 type Generator int 15 16 // A list of known generators we can detect 17 const ( 18 Unknown Generator = iota 19 Goyacc 20 Cgo 21 Stringer 22 ProtocGenGo 23 ) 24 25 var ( 26 // used by cgo before Go 1.11 27 oldCgo = []byte("// Created by cgo - DO NOT EDIT") 28 prefix = []byte("// Code generated ") 29 suffix = []byte(" DO NOT EDIT.") 30 nl = []byte("\n") 31 crnl = []byte("\r\n") 32 ) 33 34 func isGenerated(path string) (Generator, bool) { 35 f, err := os.Open(path) 36 if err != nil { 37 return 0, false 38 } 39 defer f.Close() 40 br := bufio.NewReader(f) 41 for { 42 s, err := br.ReadBytes('\n') 43 if err != nil && err != io.EOF { 44 return 0, false 45 } 46 s = bytes.TrimSuffix(s, crnl) 47 s = bytes.TrimSuffix(s, nl) 48 if bytes.HasPrefix(s, prefix) && bytes.HasSuffix(s, suffix) { 49 if len(s)-len(suffix) < len(prefix) { 50 return Unknown, true 51 } 52 53 text := string(s[len(prefix) : len(s)-len(suffix)]) 54 switch text { 55 case "by goyacc.": 56 return Goyacc, true 57 case "by cmd/cgo;": 58 return Cgo, true 59 case "by protoc-gen-go.": 60 return ProtocGenGo, true 61 } 62 if strings.HasPrefix(text, `by "stringer `) { 63 return Stringer, true 64 } 65 if strings.HasPrefix(text, `by goyacc `) { 66 return Goyacc, true 67 } 68 69 return Unknown, true 70 } 71 if bytes.Equal(s, oldCgo) { 72 return Cgo, true 73 } 74 if err == io.EOF { 75 break 76 } 77 } 78 return 0, false 79 } 80 81 var Analyzer = &analysis.Analyzer{ 82 Name: "isgenerated", 83 Doc: "annotate file names that have been code generated", 84 Run: func(pass *analysis.Pass) (interface{}, error) { 85 m := map[string]Generator{} 86 for _, f := range pass.Files { 87 path := pass.Fset.PositionFor(f.Pos(), false).Filename 88 g, ok := isGenerated(path) 89 if ok { 90 m[path] = g 91 } 92 } 93 return m, nil 94 }, 95 RunDespiteErrors: true, 96 ResultType: reflect.TypeOf(map[string]Generator{}), 97 }