119 lines
2.3 KiB
Go
119 lines
2.3 KiB
Go
package notation
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"strings"
|
|
)
|
|
|
|
func funcBase(t reflect.Type) string {
|
|
args := func(num func() int, typ func(int) reflect.Type) []string {
|
|
t := make([]string, num())
|
|
for i := 0; i < num(); i++ {
|
|
t[i] = sprintType(typ(i))
|
|
}
|
|
|
|
return t
|
|
}
|
|
|
|
in := args(t.NumIn, t.In)
|
|
out := args(t.NumOut, t.Out)
|
|
|
|
var outs string
|
|
if len(out) == 1 {
|
|
outs = out[0]
|
|
} else if len(out) > 1 {
|
|
outs = fmt.Sprintf("(%s)", strings.Join(out, ", "))
|
|
}
|
|
|
|
var s string
|
|
if outs == "" {
|
|
s = fmt.Sprintf("(%s)", strings.Join(in, ", "))
|
|
} else {
|
|
s = fmt.Sprintf("(%s) %s", strings.Join(in, ", "), outs)
|
|
}
|
|
|
|
return s
|
|
}
|
|
|
|
func arrayType(t reflect.Type) string {
|
|
return fmt.Sprintf("[%d]%s", t.Len(), sprintType(t.Elem()))
|
|
}
|
|
|
|
func chanType(t reflect.Type) string {
|
|
var prefix string
|
|
switch t.ChanDir() {
|
|
case reflect.RecvDir:
|
|
prefix = "<-chan"
|
|
case reflect.SendDir:
|
|
prefix = "chan<-"
|
|
default:
|
|
prefix = "chan"
|
|
}
|
|
|
|
return fmt.Sprintf("%s %s", prefix, sprintType(t.Elem()))
|
|
}
|
|
|
|
func funcType(t reflect.Type) string {
|
|
return fmt.Sprintf("func%s", funcBase(t))
|
|
}
|
|
|
|
func interfaceType(t reflect.Type) string {
|
|
var m []string
|
|
for i := 0; i < t.NumMethod(); i++ {
|
|
method := t.Method(i)
|
|
m = append(m, fmt.Sprintf("%s%s", method.Name, funcBase(method.Type)))
|
|
}
|
|
|
|
return fmt.Sprintf("interface{%s}", strings.Join(m, "; "))
|
|
}
|
|
|
|
func mapType(t reflect.Type) string {
|
|
return fmt.Sprintf("map[%s]%s", sprintType(t.Key()), sprintType(t.Elem()))
|
|
}
|
|
|
|
func pointerType(t reflect.Type) string {
|
|
return fmt.Sprintf("*%s", sprintType(t.Elem()))
|
|
}
|
|
|
|
func listType(t reflect.Type) string {
|
|
return fmt.Sprintf("[]%s", sprintType(t.Elem()))
|
|
}
|
|
|
|
func structType(t reflect.Type) string {
|
|
f := make([]string, t.NumField())
|
|
for i := 0; i < t.NumField(); i++ {
|
|
fi := t.Field(i)
|
|
f[i] = fmt.Sprintf("%s %s", fi.Name, sprintType(fi.Type))
|
|
}
|
|
|
|
return fmt.Sprintf("struct{%s}", strings.Join(f, "; "))
|
|
}
|
|
|
|
func sprintType(t reflect.Type) string {
|
|
if t.Name() != "" {
|
|
return t.Name()
|
|
}
|
|
|
|
switch t.Kind() {
|
|
case reflect.Array:
|
|
return arrayType(t)
|
|
case reflect.Chan:
|
|
return chanType(t)
|
|
case reflect.Func:
|
|
return funcType(t)
|
|
case reflect.Interface:
|
|
return interfaceType(t)
|
|
case reflect.Map:
|
|
return mapType(t)
|
|
case reflect.Ptr:
|
|
return pointerType(t)
|
|
case reflect.Slice:
|
|
return listType(t)
|
|
case reflect.Struct:
|
|
return structType(t)
|
|
default:
|
|
return "<invalid>"
|
|
}
|
|
}
|