summaryrefslogtreecommitdiffstats
path: root/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/messageset.go
diff options
context:
space:
mode:
Diffstat (limited to 'dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/messageset.go')
-rw-r--r--dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/messageset.go79
1 files changed, 79 insertions, 0 deletions
diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/messageset.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/messageset.go
new file mode 100644
index 0000000..1354790
--- /dev/null
+++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/messageset.go
@@ -0,0 +1,79 @@
+// TODO: show that two-non-empty dotjoin can happen, by using an anon struct as a field type
+// TODO: don't report removed/changed methods for both value and pointer method sets?
+
+package apidiff
+
+import (
+ "fmt"
+ "go/types"
+ "sort"
+ "strings"
+)
+
+// There can be at most one message for each object or part thereof.
+// Parts include interface methods and struct fields.
+//
+// The part thing is necessary. Method (Func) objects have sufficient info, but field
+// Vars do not: they just have a field name and a type, without the enclosing struct.
+type messageSet map[types.Object]map[string]string
+
+// Add a message for obj and part, overwriting a previous message
+// (shouldn't happen).
+// obj is required but part can be empty.
+func (m messageSet) add(obj types.Object, part, msg string) {
+ s := m[obj]
+ if s == nil {
+ s = map[string]string{}
+ m[obj] = s
+ }
+ if f, ok := s[part]; ok && f != msg {
+ fmt.Printf("! second, different message for obj %s, part %q\n", obj, part)
+ fmt.Printf(" first: %s\n", f)
+ fmt.Printf(" second: %s\n", msg)
+ }
+ s[part] = msg
+}
+
+func (m messageSet) collect() []string {
+ var s []string
+ for obj, parts := range m {
+ // Format each object name relative to its own package.
+ objstring := objectString(obj)
+ for part, msg := range parts {
+ var p string
+
+ if strings.HasPrefix(part, ",") {
+ p = objstring + part
+ } else {
+ p = dotjoin(objstring, part)
+ }
+ s = append(s, p+": "+msg)
+ }
+ }
+ sort.Strings(s)
+ return s
+}
+
+func objectString(obj types.Object) string {
+ if f, ok := obj.(*types.Func); ok {
+ sig := f.Type().(*types.Signature)
+ if recv := sig.Recv(); recv != nil {
+ tn := types.TypeString(recv.Type(), types.RelativeTo(obj.Pkg()))
+ if tn[0] == '*' {
+ tn = "(" + tn + ")"
+ }
+ return fmt.Sprintf("%s.%s", tn, obj.Name())
+ }
+ }
+ return obj.Name()
+}
+
+func dotjoin(s1, s2 string) string {
+ if s1 == "" {
+ return s2
+ }
+ if s2 == "" {
+ return s1
+ }
+ return s1 + "." + s2
+}