Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201105173854-bc9fc8d8c4bc / internal / apidiff / messageset.go
1 // TODO: show that two-non-empty dotjoin can happen, by using an anon struct as a field type
2 // TODO: don't report removed/changed methods for both value and pointer method sets?
3
4 package apidiff
5
6 import (
7         "fmt"
8         "go/types"
9         "sort"
10         "strings"
11 )
12
13 // There can be at most one message for each object or part thereof.
14 // Parts include interface methods and struct fields.
15 //
16 // The part thing is necessary. Method (Func) objects have sufficient info, but field
17 // Vars do not: they just have a field name and a type, without the enclosing struct.
18 type messageSet map[types.Object]map[string]string
19
20 // Add a message for obj and part, overwriting a previous message
21 // (shouldn't happen).
22 // obj is required but part can be empty.
23 func (m messageSet) add(obj types.Object, part, msg string) {
24         s := m[obj]
25         if s == nil {
26                 s = map[string]string{}
27                 m[obj] = s
28         }
29         if f, ok := s[part]; ok && f != msg {
30                 fmt.Printf("! second, different message for obj %s, part %q\n", obj, part)
31                 fmt.Printf("  first:  %s\n", f)
32                 fmt.Printf("  second: %s\n", msg)
33         }
34         s[part] = msg
35 }
36
37 func (m messageSet) collect() []string {
38         var s []string
39         for obj, parts := range m {
40                 // Format each object name relative to its own package.
41                 objstring := objectString(obj)
42                 for part, msg := range parts {
43                         var p string
44
45                         if strings.HasPrefix(part, ",") {
46                                 p = objstring + part
47                         } else {
48                                 p = dotjoin(objstring, part)
49                         }
50                         s = append(s, p+": "+msg)
51                 }
52         }
53         sort.Strings(s)
54         return s
55 }
56
57 func objectString(obj types.Object) string {
58         if f, ok := obj.(*types.Func); ok {
59                 sig := f.Type().(*types.Signature)
60                 if recv := sig.Recv(); recv != nil {
61                         tn := types.TypeString(recv.Type(), types.RelativeTo(obj.Pkg()))
62                         if tn[0] == '*' {
63                                 tn = "(" + tn + ")"
64                         }
65                         return fmt.Sprintf("%s.%s", tn, obj.Name())
66                 }
67         }
68         return obj.Name()
69 }
70
71 func dotjoin(s1, s2 string) string {
72         if s1 == "" {
73                 return s2
74         }
75         if s2 == "" {
76                 return s1
77         }
78         return s1 + "." + s2
79 }