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  }