Path: blob/main/vendor/github.com/google/go-cmp/cmp/internal/function/func.go
2898 views
// Copyright 2017, The Go Authors. All rights reserved.1// Use of this source code is governed by a BSD-style2// license that can be found in the LICENSE file.34// Package function provides functionality for identifying function types.5package function67import (8"reflect"9"regexp"10"runtime"11"strings"12)1314type funcType int1516const (17_ funcType = iota1819tbFunc // func(T) bool20ttbFunc // func(T, T) bool21ttiFunc // func(T, T) int22trbFunc // func(T, R) bool23tibFunc // func(T, I) bool24trFunc // func(T) R2526Equal = ttbFunc // func(T, T) bool27EqualAssignable = tibFunc // func(T, I) bool; encapsulates func(T, T) bool28Transformer = trFunc // func(T) R29ValueFilter = ttbFunc // func(T, T) bool30Less = ttbFunc // func(T, T) bool31Compare = ttiFunc // func(T, T) int32ValuePredicate = tbFunc // func(T) bool33KeyValuePredicate = trbFunc // func(T, R) bool34)3536var boolType = reflect.TypeOf(true)37var intType = reflect.TypeOf(0)3839// IsType reports whether the reflect.Type is of the specified function type.40func IsType(t reflect.Type, ft funcType) bool {41if t == nil || t.Kind() != reflect.Func || t.IsVariadic() {42return false43}44ni, no := t.NumIn(), t.NumOut()45switch ft {46case tbFunc: // func(T) bool47if ni == 1 && no == 1 && t.Out(0) == boolType {48return true49}50case ttbFunc: // func(T, T) bool51if ni == 2 && no == 1 && t.In(0) == t.In(1) && t.Out(0) == boolType {52return true53}54case ttiFunc: // func(T, T) int55if ni == 2 && no == 1 && t.In(0) == t.In(1) && t.Out(0) == intType {56return true57}58case trbFunc: // func(T, R) bool59if ni == 2 && no == 1 && t.Out(0) == boolType {60return true61}62case tibFunc: // func(T, I) bool63if ni == 2 && no == 1 && t.In(0).AssignableTo(t.In(1)) && t.Out(0) == boolType {64return true65}66case trFunc: // func(T) R67if ni == 1 && no == 1 {68return true69}70}71return false72}7374var lastIdentRx = regexp.MustCompile(`[_\p{L}][_\p{L}\p{N}]*$`)7576// NameOf returns the name of the function value.77func NameOf(v reflect.Value) string {78fnc := runtime.FuncForPC(v.Pointer())79if fnc == nil {80return "<unknown>"81}82fullName := fnc.Name() // e.g., "long/path/name/mypkg.(*MyType).(long/path/name/mypkg.myMethod)-fm"8384// Method closures have a "-fm" suffix.85fullName = strings.TrimSuffix(fullName, "-fm")8687var name string88for len(fullName) > 0 {89inParen := strings.HasSuffix(fullName, ")")90fullName = strings.TrimSuffix(fullName, ")")9192s := lastIdentRx.FindString(fullName)93if s == "" {94break95}96name = s + "." + name97fullName = strings.TrimSuffix(fullName, s)9899if i := strings.LastIndexByte(fullName, '('); inParen && i >= 0 {100fullName = fullName[:i]101}102fullName = strings.TrimSuffix(fullName, ".")103}104return strings.TrimSuffix(name, ".")105}106107108