refactor: minor simplification of getMethods

This commit is contained in:
Alec Thomas
2025-01-30 14:08:07 +11:00
parent 4be6ae6168
commit 5765c11522
2 changed files with 34 additions and 46 deletions
+1
View File
@@ -42,6 +42,7 @@ linters:
- copyloopvar - copyloopvar
- intrange - intrange
- execinquery - execinquery
- nakedret
linters-settings: linters-settings:
govet: govet:
+13 -26
View File
@@ -81,25 +81,26 @@ func getMethod(value reflect.Value, name string) reflect.Value {
// and any embedded fields. // and any embedded fields.
// //
// Returns a slice of bound methods that can be called directly. // Returns a slice of bound methods that can be called directly.
func getMethods(value reflect.Value, name string) []reflect.Value { func getMethods(value reflect.Value, name string) (methods []reflect.Value) {
// Traverses embedded fields of the struct
// starting from the given value to collect all possible receivers
// for the given method name.
var traverse func(value reflect.Value, receivers []reflect.Value) []reflect.Value
traverse = func(value reflect.Value, receivers []reflect.Value) []reflect.Value {
// Always consider the current value for hooks.
receivers = append(receivers, value)
if value.Kind() == reflect.Ptr { if value.Kind() == reflect.Ptr {
value = value.Elem() value = value.Elem()
} }
if !value.IsValid() {
return
}
if method := getMethod(value, name); method.IsValid() {
methods = append(methods, method)
}
if value.Kind() != reflect.Struct {
return
}
// If the current value is a struct, also consider embedded fields. // If the current value is a struct, also consider embedded fields.
// Two kinds of embedded fields are considered if they're exported: // Two kinds of embedded fields are considered if they're exported:
// //
// - standard Go embedded fields // - standard Go embedded fields
// - fields tagged with `embed:""` // - fields tagged with `embed:""`
if value.Kind() == reflect.Struct {
t := value.Type() t := value.Type()
for i := 0; i < value.NumField(); i++ { for i := 0; i < value.NumField(); i++ {
fieldValue := value.Field(i) fieldValue := value.Field(i)
@@ -114,24 +115,10 @@ func getMethods(value reflect.Value, name string) []reflect.Value {
_, isEmbedded := field.Tag.Lookup("embed") _, isEmbedded := field.Tag.Lookup("embed")
isEmbedded = isEmbedded || field.Anonymous isEmbedded = isEmbedded || field.Anonymous
if isEmbedded { if isEmbedded {
receivers = traverse(fieldValue, receivers) methods = append(methods, getMethods(fieldValue, name)...)
} }
} }
} return
return receivers
}
receivers := traverse(value, nil /* receivers */)
// Search all receivers for methods
var methods []reflect.Value
for _, receiver := range receivers {
if method := getMethod(receiver, name); method.IsValid() {
methods = append(methods, method)
}
}
return methods
} }
func callFunction(f reflect.Value, bindings bindings) error { func callFunction(f reflect.Value, bindings bindings) error {