src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

fakereflect.go (2710B)


      1 package fakereflect
      2 
      3 import (
      4 	"fmt"
      5 	"go/types"
      6 	"reflect"
      7 )
      8 
      9 type TypeAndCanAddr struct {
     10 	Type    types.Type
     11 	canAddr bool
     12 }
     13 
     14 type StructField struct {
     15 	Index     []int
     16 	Name      string
     17 	Anonymous bool
     18 	Tag       reflect.StructTag
     19 	f         *types.Var
     20 	Type      TypeAndCanAddr
     21 }
     22 
     23 func (sf StructField) IsExported() bool { return sf.f.Exported() }
     24 
     25 func (t TypeAndCanAddr) Field(i int) StructField {
     26 	st := t.Type.Underlying().(*types.Struct)
     27 	f := st.Field(i)
     28 	return StructField{
     29 		f:         f,
     30 		Index:     []int{i},
     31 		Name:      f.Name(),
     32 		Anonymous: f.Anonymous(),
     33 		Tag:       reflect.StructTag(st.Tag(i)),
     34 		Type: TypeAndCanAddr{
     35 			Type:    f.Type(),
     36 			canAddr: t.canAddr,
     37 		},
     38 	}
     39 }
     40 
     41 func (t TypeAndCanAddr) FieldByIndex(index []int) StructField {
     42 	f := t.Field(index[0])
     43 	for _, idx := range index[1:] {
     44 		f = f.Type.Field(idx)
     45 	}
     46 	f.Index = index
     47 	return f
     48 }
     49 
     50 func PtrTo(t TypeAndCanAddr) TypeAndCanAddr {
     51 	// Note that we don't care about canAddr here because it's irrelevant to all uses of PtrTo
     52 	return TypeAndCanAddr{Type: types.NewPointer(t.Type)}
     53 }
     54 
     55 func (t TypeAndCanAddr) CanAddr() bool { return t.canAddr }
     56 
     57 func (t TypeAndCanAddr) Implements(ityp *types.Interface) bool {
     58 	return types.Implements(t.Type, ityp)
     59 }
     60 
     61 func (t TypeAndCanAddr) IsSlice() bool {
     62 	_, ok := t.Type.Underlying().(*types.Slice)
     63 	return ok
     64 }
     65 
     66 func (t TypeAndCanAddr) IsArray() bool {
     67 	_, ok := t.Type.Underlying().(*types.Array)
     68 	return ok
     69 }
     70 
     71 func (t TypeAndCanAddr) IsPtr() bool {
     72 	_, ok := t.Type.Underlying().(*types.Pointer)
     73 	return ok
     74 }
     75 
     76 func (t TypeAndCanAddr) IsInterface() bool {
     77 	_, ok := t.Type.Underlying().(*types.Interface)
     78 	return ok
     79 }
     80 
     81 func (t TypeAndCanAddr) IsStruct() bool {
     82 	_, ok := t.Type.Underlying().(*types.Struct)
     83 	return ok
     84 }
     85 
     86 func (t TypeAndCanAddr) Name() string {
     87 	named, ok := types.Unalias(t.Type).(*types.Named)
     88 	if !ok {
     89 		return ""
     90 	}
     91 	return named.Obj().Name()
     92 }
     93 
     94 func (t TypeAndCanAddr) NumField() int {
     95 	return t.Type.Underlying().(*types.Struct).NumFields()
     96 }
     97 
     98 func (t TypeAndCanAddr) String() string {
     99 	return t.Type.String()
    100 }
    101 
    102 func (t TypeAndCanAddr) Key() TypeAndCanAddr {
    103 	return TypeAndCanAddr{Type: t.Type.Underlying().(*types.Map).Key()}
    104 }
    105 
    106 func (t TypeAndCanAddr) Elem() TypeAndCanAddr {
    107 	switch typ := t.Type.Underlying().(type) {
    108 	case *types.Pointer:
    109 		return TypeAndCanAddr{
    110 			Type:    typ.Elem(),
    111 			canAddr: true,
    112 		}
    113 	case *types.Slice:
    114 		return TypeAndCanAddr{
    115 			Type:    typ.Elem(),
    116 			canAddr: true,
    117 		}
    118 	case *types.Array:
    119 		return TypeAndCanAddr{
    120 			Type:    typ.Elem(),
    121 			canAddr: t.canAddr,
    122 		}
    123 	case *types.Map:
    124 		return TypeAndCanAddr{
    125 			Type:    typ.Elem(),
    126 			canAddr: false,
    127 		}
    128 	default:
    129 		panic(fmt.Sprintf("unhandled type %T", typ))
    130 	}
    131 }