github.com/jd-ly/tools@v0.5.7/internal/apidiff/messageset.go (about) 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 }