github.com/c-darwin/mobile@v0.0.0-20160313183840-ff625c46f7c9/bind/types.go (about) 1 // Copyright 2015 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 package bind 6 7 import ( 8 "go/types" 9 "log" 10 ) 11 12 type ifaceSummary struct { 13 iface *types.Interface 14 callable []*types.Func 15 implementable bool 16 } 17 18 func makeIfaceSummary(iface *types.Interface) ifaceSummary { 19 summary := ifaceSummary{ 20 iface: iface, 21 implementable: true, 22 } 23 methodset := types.NewMethodSet(iface) 24 for i := 0; i < methodset.Len(); i++ { 25 obj := methodset.At(i).Obj() 26 if !obj.Exported() { 27 summary.implementable = false 28 continue 29 } 30 m, ok := obj.(*types.Func) 31 if !ok { 32 log.Panicf("unexpected methodset obj: %s (%T)", obj, obj) 33 } 34 if !isImplementable(m.Type().(*types.Signature)) { 35 summary.implementable = false 36 } 37 if isCallable(m) { 38 summary.callable = append(summary.callable, m) 39 } 40 } 41 return summary 42 } 43 44 func isCallable(t *types.Func) bool { 45 // TODO(crawshaw): functions that are not implementable from 46 // another language may still be callable (for example, a 47 // returned value with an unexported type can be treated as 48 // an opaque value by the caller). This restriction could be 49 // lifted. 50 return isImplementable(t.Type().(*types.Signature)) 51 } 52 53 func isImplementable(sig *types.Signature) bool { 54 params := sig.Params() 55 for i := 0; i < params.Len(); i++ { 56 if !isExported(params.At(i).Type()) { 57 return false 58 } 59 } 60 res := sig.Results() 61 for i := 0; i < res.Len(); i++ { 62 if !isExported(res.At(i).Type()) { 63 return false 64 } 65 } 66 return true 67 } 68 69 func exportedMethodSet(T types.Type) []*types.Func { 70 var methods []*types.Func 71 methodset := types.NewMethodSet(T) 72 for i := 0; i < methodset.Len(); i++ { 73 obj := methodset.At(i).Obj() 74 if !obj.Exported() { 75 continue 76 } 77 switch obj := obj.(type) { 78 case *types.Func: 79 methods = append(methods, obj) 80 default: 81 log.Panicf("unexpected methodset obj: %s", obj) 82 } 83 } 84 return methods 85 } 86 87 func exportedFields(T *types.Struct) []*types.Var { 88 var fields []*types.Var 89 for i := 0; i < T.NumFields(); i++ { 90 f := T.Field(i) 91 if !f.Exported() { 92 continue 93 } 94 fields = append(fields, f) 95 } 96 return fields 97 } 98 99 func isErrorType(t types.Type) bool { 100 return types.Identical(t, types.Universe.Lookup("error").Type()) 101 } 102 103 func isExported(t types.Type) bool { 104 if isErrorType(t) { 105 return true 106 } 107 switch t := t.(type) { 108 case *types.Basic: 109 return true 110 case *types.Named: 111 return t.Obj().Exported() 112 case *types.Pointer: 113 return isExported(t.Elem()) 114 default: 115 return true 116 } 117 }