GoPLS Viewer

Home|gopls/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
8package apidiff
9
10import (
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.
22type 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.
27func (m messageSetadd(obj types.Objectpartmsg string) {
28    s := m[obj]
29    if s == nil {
30        s = map[string]string{}
31        m[obj] = s
32    }
33    if fok := s[part]; ok && f != msg {
34        fmt.Printf("! second, different message for obj %s, part %q\n"objpart)
35        fmt.Printf("  first:  %s\n"f)
36        fmt.Printf("  second: %s\n"msg)
37    }
38    s[part] = msg
39}
40
41func (m messageSetcollect() []string {
42    var s []string
43    for objparts := range m {
44        // Format each object name relative to its own package.
45        objstring := objectString(obj)
46        for partmsg := range parts {
47            var p string
48
49            if strings.HasPrefix(part",") {
50                p = objstring + part
51            } else {
52                p = dotjoin(objstringpart)
53            }
54            s = append(sp+": "+msg)
55        }
56    }
57    sort.Strings(s)
58    return s
59}
60
61func objectString(obj types.Objectstring {
62    if fok := 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"tnobj.Name())
70        }
71    }
72    return obj.Name()
73}
74
75func dotjoin(s1s2 stringstring {
76    if s1 == "" {
77        return s2
78    }
79    if s2 == "" {
80        return s1
81    }
82    return s1 + "." + s2
83}
84
MembersX
messageSet.add
messageSet.collect.m
messageSet.collect.RangeStmt_1286.obj
messageSet.collect.RangeStmt_1286.BlockStmt.objstring
messageSet.collect.RangeStmt_1286.BlockStmt.RangeStmt_1407.part
dotjoin.s2
messageSet
messageSet.collect.s
messageSet.collect.RangeStmt_1286.parts
objectString
objectString.BlockStmt.BlockStmt.tn
dotjoin.s1
messageSet.add.msg
messageSet.add.obj
messageSet.collect.RangeStmt_1286.BlockStmt.RangeStmt_1407.msg
messageSet.collect.RangeStmt_1286.BlockStmt.RangeStmt_1407.BlockStmt.p
dotjoin
messageSet.add.m
messageSet.collect
objectString.obj
objectString.BlockStmt.recv
messageSet.add.part
Members
X