50fbc2eec2
* CI: use staticcheck for linting This commit switches the linter for Go code from golint to staticcheck. Golint has been deprecated since last year and staticcheck is a recommended replacement. Signed-off-by: Lucas Servén Marín <lserven@gmail.com> * revendor Signed-off-by: Lucas Servén Marín <lserven@gmail.com> * cmd,pkg: fix lint warnings Signed-off-by: Lucas Servén Marín <lserven@gmail.com>
132 lines
2.6 KiB
Go
132 lines
2.6 KiB
Go
package fakereflect
|
|
|
|
import (
|
|
"fmt"
|
|
"go/types"
|
|
"reflect"
|
|
)
|
|
|
|
type TypeAndCanAddr struct {
|
|
Type types.Type
|
|
canAddr bool
|
|
}
|
|
|
|
type StructField struct {
|
|
Index []int
|
|
Name string
|
|
Anonymous bool
|
|
Tag reflect.StructTag
|
|
f *types.Var
|
|
Type TypeAndCanAddr
|
|
}
|
|
|
|
func (sf StructField) IsExported() bool { return sf.f.Exported() }
|
|
|
|
func (t TypeAndCanAddr) Field(i int) StructField {
|
|
st := t.Type.Underlying().(*types.Struct)
|
|
f := st.Field(i)
|
|
return StructField{
|
|
f: f,
|
|
Index: []int{i},
|
|
Name: f.Name(),
|
|
Anonymous: f.Anonymous(),
|
|
Tag: reflect.StructTag(st.Tag(i)),
|
|
Type: TypeAndCanAddr{
|
|
Type: f.Type(),
|
|
canAddr: t.canAddr,
|
|
},
|
|
}
|
|
}
|
|
|
|
func (t TypeAndCanAddr) FieldByIndex(index []int) StructField {
|
|
f := t.Field(index[0])
|
|
for _, idx := range index[1:] {
|
|
f = f.Type.Field(idx)
|
|
}
|
|
f.Index = index
|
|
return f
|
|
}
|
|
|
|
func PtrTo(t TypeAndCanAddr) TypeAndCanAddr {
|
|
// Note that we don't care about canAddr here because it's irrelevant to all uses of PtrTo
|
|
return TypeAndCanAddr{Type: types.NewPointer(t.Type)}
|
|
}
|
|
|
|
func (t TypeAndCanAddr) CanAddr() bool { return t.canAddr }
|
|
|
|
func (t TypeAndCanAddr) Implements(ityp *types.Interface) bool {
|
|
return types.Implements(t.Type, ityp)
|
|
}
|
|
|
|
func (t TypeAndCanAddr) IsSlice() bool {
|
|
_, ok := t.Type.Underlying().(*types.Slice)
|
|
return ok
|
|
}
|
|
|
|
func (t TypeAndCanAddr) IsArray() bool {
|
|
_, ok := t.Type.Underlying().(*types.Array)
|
|
return ok
|
|
}
|
|
|
|
func (t TypeAndCanAddr) IsPtr() bool {
|
|
_, ok := t.Type.Underlying().(*types.Pointer)
|
|
return ok
|
|
}
|
|
|
|
func (t TypeAndCanAddr) IsInterface() bool {
|
|
_, ok := t.Type.Underlying().(*types.Interface)
|
|
return ok
|
|
}
|
|
|
|
func (t TypeAndCanAddr) IsStruct() bool {
|
|
_, ok := t.Type.Underlying().(*types.Struct)
|
|
return ok
|
|
}
|
|
|
|
func (t TypeAndCanAddr) Name() string {
|
|
named, ok := t.Type.(*types.Named)
|
|
if !ok {
|
|
return ""
|
|
}
|
|
return named.Obj().Name()
|
|
}
|
|
|
|
func (t TypeAndCanAddr) NumField() int {
|
|
return t.Type.Underlying().(*types.Struct).NumFields()
|
|
}
|
|
|
|
func (t TypeAndCanAddr) String() string {
|
|
return t.Type.String()
|
|
}
|
|
|
|
func (t TypeAndCanAddr) Key() TypeAndCanAddr {
|
|
return TypeAndCanAddr{Type: t.Type.Underlying().(*types.Map).Key()}
|
|
}
|
|
|
|
func (t TypeAndCanAddr) Elem() TypeAndCanAddr {
|
|
switch typ := t.Type.Underlying().(type) {
|
|
case *types.Pointer:
|
|
return TypeAndCanAddr{
|
|
Type: typ.Elem(),
|
|
canAddr: true,
|
|
}
|
|
case *types.Slice:
|
|
return TypeAndCanAddr{
|
|
Type: typ.Elem(),
|
|
canAddr: true,
|
|
}
|
|
case *types.Array:
|
|
return TypeAndCanAddr{
|
|
Type: typ.Elem(),
|
|
canAddr: t.canAddr,
|
|
}
|
|
case *types.Map:
|
|
return TypeAndCanAddr{
|
|
Type: typ.Elem(),
|
|
canAddr: false,
|
|
}
|
|
default:
|
|
panic(fmt.Sprintf("unhandled type %T", typ))
|
|
}
|
|
}
|