.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / honnef.co / go / tools@v0.1.1 / analysis / facts / generated.go
1 package facts
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 Generated = &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 }