11 "golang.org/x/tools/go/analysis"
16 // A list of known generators we can detect
18 Unknown Generator = iota
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.")
34 func isGenerated(path string) (Generator, bool) {
35 f, err := os.Open(path)
40 br := bufio.NewReader(f)
42 s, err := br.ReadBytes('\n')
43 if err != nil && err != io.EOF {
46 s = bytes.TrimSuffix(s, crnl)
47 s = bytes.TrimSuffix(s, nl)
48 if bytes.HasPrefix(s, prefix) && bytes.HasSuffix(s, suffix) {
49 text := string(s[len(prefix) : len(s)-len(suffix)])
55 case "by protoc-gen-go.":
56 return ProtocGenGo, true
58 if strings.HasPrefix(text, `by "stringer `) {
61 if strings.HasPrefix(text, `by goyacc `) {
67 if bytes.Equal(s, oldCgo) {
77 var Generated = &analysis.Analyzer{
79 Doc: "annotate file names that have been code generated",
80 Run: func(pass *analysis.Pass) (interface{}, error) {
81 m := map[string]Generator{}
82 for _, f := range pass.Files {
83 path := pass.Fset.PositionFor(f.Pos(), false).Filename
84 g, ok := isGenerated(path)
91 RunDespiteErrors: true,
92 ResultType: reflect.TypeOf(map[string]Generator{}),