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