implements.go 2.0 KB

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