forked from kataras/iris
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreflect.go
58 lines (48 loc) · 1.63 KB
/
reflect.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package mvc
import (
"reflect"
"github.com/kataras/iris/v12/context"
)
var baseControllerTyp = reflect.TypeOf((*BaseController)(nil)).Elem()
func isBaseController(ctrlTyp reflect.Type) bool {
return ctrlTyp.Implements(baseControllerTyp)
}
// indirectType returns the value of a pointer-type "typ".
// If "typ" is a pointer, array, chan, map or slice it returns its Elem,
// otherwise returns the typ as it's.
func indirectType(typ reflect.Type) reflect.Type {
switch typ.Kind() {
case reflect.Ptr, reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
return typ.Elem()
}
return typ
}
func getSourceFileLine(ctrlType reflect.Type, m reflect.Method) (string, int) { // used for debug logs.
sourceFileName, sourceLineNumber := context.HandlerFileLineRel(m.Func)
if sourceFileName == "<autogenerated>" {
elem := indirectType(ctrlType)
for i, n := 0, elem.NumField(); i < n; i++ {
if f := elem.Field(i); f.Anonymous {
typ := indirectType(f.Type)
if typ.Kind() != reflect.Struct {
continue // field is not a struct.
}
// why we do that?
// because if the element is not Ptr
// then it's probably used as:
// type ctrl {
// BaseCtrl
// }
// but BaseCtrl has not the method, *BaseCtrl does:
// (c *BaseCtrl) HandleHTTPError(...)
// so we are creating a new temporary value ptr of that type
// and searching inside it for the method instead.
typ = reflect.New(typ).Type()
if embeddedMethod, ok := typ.MethodByName(m.Name); ok {
sourceFileName, sourceLineNumber = context.HandlerFileLineRel(embeddedMethod.Func)
}
}
}
}
return sourceFileName, sourceLineNumber
}