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 if len(s)-len(suffix) < len(prefix) {
53 text := string(s[len(prefix) : len(s)-len(suffix)])
59 case "by protoc-gen-go.":
60 return ProtocGenGo, true
62 if strings.HasPrefix(text, `by "stringer `) {
65 if strings.HasPrefix(text, `by goyacc `) {
71 if bytes.Equal(s, oldCgo) {
81 var Generated = &analysis.Analyzer{
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)
95 RunDespiteErrors: true,
96 ResultType: reflect.TypeOf(map[string]Generator{}),