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?
13 // There can be at most one message for each object or part thereof.
14 // Parts include interface methods and struct fields.
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
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) {
26 s = map[string]string{}
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)
37 func (m messageSet) collect() []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 {
45 if strings.HasPrefix(part, ",") {
48 p = dotjoin(objstring, part)
50 s = append(s, p+": "+msg)
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()))
65 return fmt.Sprintf("%s.%s", tn, obj.Name())
71 func dotjoin(s1, s2 string) string {