reflect.go 1.6 KB

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