Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / honnef.co / go / tools@v0.0.1-2020.1.5 / facts / deprecated.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/honnef.co/go/tools@v0.0.1-2020.1.5/facts/deprecated.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/honnef.co/go/tools@v0.0.1-2020.1.5/facts/deprecated.go
new file mode 100644 (file)
index 0000000..8587b0e
--- /dev/null
@@ -0,0 +1,144 @@
+package facts
+
+import (
+       "go/ast"
+       "go/token"
+       "go/types"
+       "reflect"
+       "strings"
+
+       "golang.org/x/tools/go/analysis"
+)
+
+type IsDeprecated struct{ Msg string }
+
+func (*IsDeprecated) AFact()           {}
+func (d *IsDeprecated) String() string { return "Deprecated: " + d.Msg }
+
+type DeprecatedResult struct {
+       Objects  map[types.Object]*IsDeprecated
+       Packages map[*types.Package]*IsDeprecated
+}
+
+var Deprecated = &analysis.Analyzer{
+       Name:       "fact_deprecated",
+       Doc:        "Mark deprecated objects",
+       Run:        deprecated,
+       FactTypes:  []analysis.Fact{(*IsDeprecated)(nil)},
+       ResultType: reflect.TypeOf(DeprecatedResult{}),
+}
+
+func deprecated(pass *analysis.Pass) (interface{}, error) {
+       var names []*ast.Ident
+
+       extractDeprecatedMessage := func(docs []*ast.CommentGroup) string {
+               for _, doc := range docs {
+                       if doc == nil {
+                               continue
+                       }
+                       parts := strings.Split(doc.Text(), "\n\n")
+                       last := parts[len(parts)-1]
+                       if !strings.HasPrefix(last, "Deprecated: ") {
+                               continue
+                       }
+                       alt := last[len("Deprecated: "):]
+                       alt = strings.Replace(alt, "\n", " ", -1)
+                       return alt
+               }
+               return ""
+       }
+       doDocs := func(names []*ast.Ident, docs []*ast.CommentGroup) {
+               alt := extractDeprecatedMessage(docs)
+               if alt == "" {
+                       return
+               }
+
+               for _, name := range names {
+                       obj := pass.TypesInfo.ObjectOf(name)
+                       pass.ExportObjectFact(obj, &IsDeprecated{alt})
+               }
+       }
+
+       var docs []*ast.CommentGroup
+       for _, f := range pass.Files {
+               docs = append(docs, f.Doc)
+       }
+       if alt := extractDeprecatedMessage(docs); alt != "" {
+               // Don't mark package syscall as deprecated, even though
+               // it is. A lot of people still use it for simple
+               // constants like SIGKILL, and I am not comfortable
+               // telling them to use x/sys for that.
+               if pass.Pkg.Path() != "syscall" {
+                       pass.ExportPackageFact(&IsDeprecated{alt})
+               }
+       }
+
+       docs = docs[:0]
+       for _, f := range pass.Files {
+               fn := func(node ast.Node) bool {
+                       if node == nil {
+                               return true
+                       }
+                       var ret bool
+                       switch node := node.(type) {
+                       case *ast.GenDecl:
+                               switch node.Tok {
+                               case token.TYPE, token.CONST, token.VAR:
+                                       docs = append(docs, node.Doc)
+                                       return true
+                               default:
+                                       return false
+                               }
+                       case *ast.FuncDecl:
+                               docs = append(docs, node.Doc)
+                               names = []*ast.Ident{node.Name}
+                               ret = false
+                       case *ast.TypeSpec:
+                               docs = append(docs, node.Doc)
+                               names = []*ast.Ident{node.Name}
+                               ret = true
+                       case *ast.ValueSpec:
+                               docs = append(docs, node.Doc)
+                               names = node.Names
+                               ret = false
+                       case *ast.File:
+                               return true
+                       case *ast.StructType:
+                               for _, field := range node.Fields.List {
+                                       doDocs(field.Names, []*ast.CommentGroup{field.Doc})
+                               }
+                               return false
+                       case *ast.InterfaceType:
+                               for _, field := range node.Methods.List {
+                                       doDocs(field.Names, []*ast.CommentGroup{field.Doc})
+                               }
+                               return false
+                       default:
+                               return false
+                       }
+                       if len(names) == 0 || len(docs) == 0 {
+                               return ret
+                       }
+                       doDocs(names, docs)
+
+                       docs = docs[:0]
+                       names = nil
+                       return ret
+               }
+               ast.Inspect(f, fn)
+       }
+
+       out := DeprecatedResult{
+               Objects:  map[types.Object]*IsDeprecated{},
+               Packages: map[*types.Package]*IsDeprecated{},
+       }
+
+       for _, fact := range pass.AllObjectFacts() {
+               out.Objects[fact.Object] = fact.Fact.(*IsDeprecated)
+       }
+       for _, fact := range pass.AllPackageFacts() {
+               out.Packages[fact.Package] = fact.Fact.(*IsDeprecated)
+       }
+
+       return out, nil
+}