1 // Copyright 2017, 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.md file.
5 // Package function provides functionality for identifying function types.
20 tbFunc // func(T) bool
21 ttbFunc // func(T, T) bool
22 trbFunc // func(T, R) bool
23 tibFunc // func(T, I) bool
26 Equal = ttbFunc // func(T, T) bool
27 EqualAssignable = tibFunc // func(T, I) bool; encapsulates func(T, T) bool
28 Transformer = trFunc // func(T) R
29 ValueFilter = ttbFunc // func(T, T) bool
30 Less = ttbFunc // func(T, T) bool
31 ValuePredicate = tbFunc // func(T) bool
32 KeyValuePredicate = trbFunc // func(T, R) bool
35 var boolType = reflect.TypeOf(true)
37 // IsType reports whether the reflect.Type is of the specified function type.
38 func IsType(t reflect.Type, ft funcType) bool {
39 if t == nil || t.Kind() != reflect.Func || t.IsVariadic() {
42 ni, no := t.NumIn(), t.NumOut()
44 case tbFunc: // func(T) bool
45 if ni == 1 && no == 1 && t.Out(0) == boolType {
48 case ttbFunc: // func(T, T) bool
49 if ni == 2 && no == 1 && t.In(0) == t.In(1) && t.Out(0) == boolType {
52 case trbFunc: // func(T, R) bool
53 if ni == 2 && no == 1 && t.Out(0) == boolType {
56 case tibFunc: // func(T, I) bool
57 if ni == 2 && no == 1 && t.In(0).AssignableTo(t.In(1)) && t.Out(0) == boolType {
60 case trFunc: // func(T) R
61 if ni == 1 && no == 1 {
68 var lastIdentRx = regexp.MustCompile(`[_\p{L}][_\p{L}\p{N}]*$`)
70 // NameOf returns the name of the function value.
71 func NameOf(v reflect.Value) string {
72 fnc := runtime.FuncForPC(v.Pointer())
76 fullName := fnc.Name() // e.g., "long/path/name/mypkg.(*MyType).(long/path/name/mypkg.myMethod)-fm"
78 // Method closures have a "-fm" suffix.
79 fullName = strings.TrimSuffix(fullName, "-fm")
82 for len(fullName) > 0 {
83 inParen := strings.HasSuffix(fullName, ")")
84 fullName = strings.TrimSuffix(fullName, ")")
86 s := lastIdentRx.FindString(fullName)
91 fullName = strings.TrimSuffix(fullName, s)
93 if i := strings.LastIndexByte(fullName, '('); inParen && i >= 0 {
94 fullName = fullName[:i]
96 fullName = strings.TrimSuffix(fullName, ".")
98 return strings.TrimSuffix(name, ".")