aboutsummaryrefslogtreecommitdiff
path: root/vendor/honnef.co/go/tools/unused/implements.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/honnef.co/go/tools/unused/implements.go')
-rw-r--r--vendor/honnef.co/go/tools/unused/implements.go82
1 files changed, 82 insertions, 0 deletions
diff --git a/vendor/honnef.co/go/tools/unused/implements.go b/vendor/honnef.co/go/tools/unused/implements.go
new file mode 100644
index 0000000..835baac
--- /dev/null
+++ b/vendor/honnef.co/go/tools/unused/implements.go
@@ -0,0 +1,82 @@
1package unused
2
3import "go/types"
4
5// lookupMethod returns the index of and method with matching package and name, or (-1, nil).
6func lookupMethod(T *types.Interface, pkg *types.Package, name string) (int, *types.Func) {
7 if name != "_" {
8 for i := 0; i < T.NumMethods(); i++ {
9 m := T.Method(i)
10 if sameId(m, pkg, name) {
11 return i, m
12 }
13 }
14 }
15 return -1, nil
16}
17
18func sameId(obj types.Object, pkg *types.Package, name string) bool {
19 // spec:
20 // "Two identifiers are different if they are spelled differently,
21 // or if they appear in different packages and are not exported.
22 // Otherwise, they are the same."
23 if name != obj.Name() {
24 return false
25 }
26 // obj.Name == name
27 if obj.Exported() {
28 return true
29 }
30 // not exported, so packages must be the same (pkg == nil for
31 // fields in Universe scope; this can only happen for types
32 // introduced via Eval)
33 if pkg == nil || obj.Pkg() == nil {
34 return pkg == obj.Pkg()
35 }
36 // pkg != nil && obj.pkg != nil
37 return pkg.Path() == obj.Pkg().Path()
38}
39
40func (g *Graph) implements(V types.Type, T *types.Interface, msV *types.MethodSet) ([]*types.Selection, bool) {
41 // fast path for common case
42 if T.Empty() {
43 return nil, true
44 }
45
46 if ityp, _ := V.Underlying().(*types.Interface); ityp != nil {
47 // TODO(dh): is this code reachable?
48 for i := 0; i < T.NumMethods(); i++ {
49 m := T.Method(i)
50 _, obj := lookupMethod(ityp, m.Pkg(), m.Name())
51 switch {
52 case obj == nil:
53 return nil, false
54 case !types.Identical(obj.Type(), m.Type()):
55 return nil, false
56 }
57 }
58 return nil, true
59 }
60
61 // A concrete type implements T if it implements all methods of T.
62 var sels []*types.Selection
63 for i := 0; i < T.NumMethods(); i++ {
64 m := T.Method(i)
65 sel := msV.Lookup(m.Pkg(), m.Name())
66 if sel == nil {
67 return nil, false
68 }
69
70 f, _ := sel.Obj().(*types.Func)
71 if f == nil {
72 return nil, false
73 }
74
75 if !types.Identical(f.Type(), m.Type()) {
76 return nil, false
77 }
78
79 sels = append(sels, sel)
80 }
81 return sels, true
82}