.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / honnef.co / go / tools@v0.1.1 / analysis / facts / deprecated.go
1 package facts
2
3 import (
4         "go/ast"
5         "go/token"
6         "go/types"
7         "reflect"
8         "strings"
9
10         "golang.org/x/tools/go/analysis"
11 )
12
13 type IsDeprecated struct{ Msg string }
14
15 func (*IsDeprecated) AFact()           {}
16 func (d *IsDeprecated) String() string { return "Deprecated: " + d.Msg }
17
18 type DeprecatedResult struct {
19         Objects  map[types.Object]*IsDeprecated
20         Packages map[*types.Package]*IsDeprecated
21 }
22
23 var Deprecated = &analysis.Analyzer{
24         Name:       "fact_deprecated",
25         Doc:        "Mark deprecated objects",
26         Run:        deprecated,
27         FactTypes:  []analysis.Fact{(*IsDeprecated)(nil)},
28         ResultType: reflect.TypeOf(DeprecatedResult{}),
29 }
30
31 func deprecated(pass *analysis.Pass) (interface{}, error) {
32         var names []*ast.Ident
33
34         extractDeprecatedMessage := func(docs []*ast.CommentGroup) string {
35                 for _, doc := range docs {
36                         if doc == nil {
37                                 continue
38                         }
39                         parts := strings.Split(doc.Text(), "\n\n")
40                         for _, part := range parts {
41                                 if !strings.HasPrefix(part, "Deprecated: ") {
42                                         continue
43                                 }
44                                 alt := part[len("Deprecated: "):]
45                                 alt = strings.Replace(alt, "\n", " ", -1)
46                                 return alt
47                         }
48                 }
49                 return ""
50         }
51         doDocs := func(names []*ast.Ident, docs []*ast.CommentGroup) {
52                 alt := extractDeprecatedMessage(docs)
53                 if alt == "" {
54                         return
55                 }
56
57                 for _, name := range names {
58                         obj := pass.TypesInfo.ObjectOf(name)
59                         pass.ExportObjectFact(obj, &IsDeprecated{alt})
60                 }
61         }
62
63         var docs []*ast.CommentGroup
64         for _, f := range pass.Files {
65                 docs = append(docs, f.Doc)
66         }
67         if alt := extractDeprecatedMessage(docs); alt != "" {
68                 // Don't mark package syscall as deprecated, even though
69                 // it is. A lot of people still use it for simple
70                 // constants like SIGKILL, and I am not comfortable
71                 // telling them to use x/sys for that.
72                 if pass.Pkg.Path() != "syscall" {
73                         pass.ExportPackageFact(&IsDeprecated{alt})
74                 }
75         }
76
77         docs = docs[:0]
78         for _, f := range pass.Files {
79                 fn := func(node ast.Node) bool {
80                         if node == nil {
81                                 return true
82                         }
83                         var ret bool
84                         switch node := node.(type) {
85                         case *ast.GenDecl:
86                                 switch node.Tok {
87                                 case token.TYPE, token.CONST, token.VAR:
88                                         docs = append(docs, node.Doc)
89                                         return true
90                                 default:
91                                         return false
92                                 }
93                         case *ast.FuncDecl:
94                                 docs = append(docs, node.Doc)
95                                 names = []*ast.Ident{node.Name}
96                                 ret = false
97                         case *ast.TypeSpec:
98                                 docs = append(docs, node.Doc)
99                                 names = []*ast.Ident{node.Name}
100                                 ret = true
101                         case *ast.ValueSpec:
102                                 docs = append(docs, node.Doc)
103                                 names = node.Names
104                                 ret = false
105                         case *ast.File:
106                                 return true
107                         case *ast.StructType:
108                                 for _, field := range node.Fields.List {
109                                         doDocs(field.Names, []*ast.CommentGroup{field.Doc})
110                                 }
111                                 return false
112                         case *ast.InterfaceType:
113                                 for _, field := range node.Methods.List {
114                                         doDocs(field.Names, []*ast.CommentGroup{field.Doc})
115                                 }
116                                 return false
117                         default:
118                                 return false
119                         }
120                         if len(names) == 0 || len(docs) == 0 {
121                                 return ret
122                         }
123                         doDocs(names, docs)
124
125                         docs = docs[:0]
126                         names = nil
127                         return ret
128                 }
129                 ast.Inspect(f, fn)
130         }
131
132         out := DeprecatedResult{
133                 Objects:  map[types.Object]*IsDeprecated{},
134                 Packages: map[*types.Package]*IsDeprecated{},
135         }
136
137         for _, fact := range pass.AllObjectFacts() {
138                 out.Objects[fact.Object] = fact.Fact.(*IsDeprecated)
139         }
140         for _, fact := range pass.AllPackageFacts() {
141                 out.Packages[fact.Package] = fact.Fact.(*IsDeprecated)
142         }
143
144         return out, nil
145 }