👔 next version: some linting

Former-commit-id: a102fbb90e2a8a8b09fcb9c9e0c370e4078b74d1
This commit is contained in:
Gerasimos (Makis) Maropoulos 2020-03-01 08:34:53 +02:00
parent 2756435446
commit 1c9b592088
9 changed files with 82 additions and 107 deletions

View File

@ -8,11 +8,13 @@ import (
"github.com/kataras/iris/v12/context" "github.com/kataras/iris/v12/context"
) )
type Binding struct { // binding contains the Dependency and the Input, it's the result of a function or struct + dependencies.
type binding struct {
Dependency *Dependency Dependency *Dependency
Input *Input Input *Input
} }
// Input contains the input reference of which a dependency is binded to.
type Input struct { type Input struct {
Index int // for func inputs Index int // for func inputs
StructFieldIndex []int // for struct fields in order to support embedded ones. StructFieldIndex []int // for struct fields in order to support embedded ones.
@ -32,7 +34,8 @@ func newInput(typ reflect.Type, index int, structFieldIndex []int) *Input {
return in return in
} }
func (b *Binding) String() string { // String returns the string representation of a binding.
func (b *binding) String() string {
index := fmt.Sprintf("%d", b.Input.Index) index := fmt.Sprintf("%d", b.Input.Index)
if len(b.Input.StructFieldIndex) > 0 { if len(b.Input.StructFieldIndex) > 0 {
for j, i := range b.Input.StructFieldIndex { for j, i := range b.Input.StructFieldIndex {
@ -47,7 +50,8 @@ func (b *Binding) String() string {
return fmt.Sprintf("[%s:%s] maps to [%s]", index, b.Input.Type.String(), b.Dependency) return fmt.Sprintf("[%s:%s] maps to [%s]", index, b.Input.Type.String(), b.Dependency)
} }
func (b *Binding) Equal(other *Binding) bool { // Equal compares "b" and "other" bindings and reports whether they are referring to the same values.
func (b *binding) Equal(other *binding) bool {
if b == nil { if b == nil {
return other == nil return other == nil
} }
@ -107,7 +111,7 @@ func matchDependency(dep *Dependency, in reflect.Type) bool {
return dep.DestType == nil || equalTypes(dep.DestType, in) return dep.DestType == nil || equalTypes(dep.DestType, in)
} }
func getBindingsFor(inputs []reflect.Type, deps []*Dependency, paramStartIndex int) (bindings []*Binding) { func getBindingsFor(inputs []reflect.Type, deps []*Dependency, paramStartIndex int) (bindings []*binding) {
bindedInput := make(map[int]struct{}) bindedInput := make(map[int]struct{})
// lastParamIndex is used to bind parameters correctly when: // lastParamIndex is used to bind parameters correctly when:
@ -170,7 +174,7 @@ func getBindingsFor(inputs []reflect.Type, deps []*Dependency, paramStartIndex i
d.OriginalValue = nil d.OriginalValue = nil
} }
bindings = append(bindings, &Binding{ bindings = append(bindings, &binding{
Dependency: d, Dependency: d,
Input: newInput(in, i, nil), Input: newInput(in, i, nil),
}) })
@ -201,7 +205,7 @@ func getBindingsFor(inputs []reflect.Type, deps []*Dependency, paramStartIndex i
return return
} }
func getBindingsForFunc(fn reflect.Value, dependencies []*Dependency, paramStartIndex int) []*Binding { func getBindingsForFunc(fn reflect.Value, dependencies []*Dependency, paramStartIndex int) []*binding {
fnTyp := fn.Type() fnTyp := fn.Type()
if !isFunc(fnTyp) { if !isFunc(fnTyp) {
panic("bindings: unresolved: not a func type") panic("bindings: unresolved: not a func type")
@ -221,7 +225,7 @@ func getBindingsForFunc(fn reflect.Value, dependencies []*Dependency, paramStart
return bindings return bindings
} }
func getBindingsForStruct(v reflect.Value, dependencies []*Dependency, paramStartIndex int, sorter Sorter) (bindings []*Binding) { func getBindingsForStruct(v reflect.Value, dependencies []*Dependency, paramStartIndex int, sorter Sorter) (bindings []*binding) {
typ := indirectType(v.Type()) typ := indirectType(v.Type())
if typ.Kind() != reflect.Struct { if typ.Kind() != reflect.Struct {
panic("bindings: unresolved: no struct type") panic("bindings: unresolved: no struct type")
@ -232,7 +236,7 @@ func getBindingsForStruct(v reflect.Value, dependencies []*Dependency, paramStar
nonZero := lookupNonZeroFieldValues(elem) nonZero := lookupNonZeroFieldValues(elem)
for _, f := range nonZero { for _, f := range nonZero {
// fmt.Printf("Controller [%s] | NonZero | Field Index: %v | Field Type: %s\n", typ, f.Index, f.Type) // fmt.Printf("Controller [%s] | NonZero | Field Index: %v | Field Type: %s\n", typ, f.Index, f.Type)
bindings = append(bindings, &Binding{ bindings = append(bindings, &binding{
Dependency: NewDependency(elem.FieldByIndex(f.Index).Interface()), Dependency: NewDependency(elem.FieldByIndex(f.Index).Interface()),
Input: newInput(f.Type, f.Index[0], f.Index), Input: newInput(f.Type, f.Index[0], f.Index),
}) })
@ -268,7 +272,7 @@ func getBindingsForStruct(v reflect.Value, dependencies []*Dependency, paramStar
binding.Input.StructFieldIndex = structFieldIndex binding.Input.StructFieldIndex = structFieldIndex
} }
// fmt.Printf("Controller [%s] | Binding Index: %v | Binding Type: %s\n", typ, binding.Input.StructFieldIndex, binding.Input.Type) // fmt.Printf("Controller [%s] | binding Index: %v | binding Type: %s\n", typ, binding.Input.StructFieldIndex, binding.Input.Type)
// fmt.Printf("Controller [%s] Set [%s] to struct field index: %v\n", typ.String(), binding.Input.Type.String(), structFieldIndex) // fmt.Printf("Controller [%s] Set [%s] to struct field index: %v\n", typ.String(), binding.Input.Type.String(), structFieldIndex)
} }
@ -280,8 +284,8 @@ func getBindingsForStruct(v reflect.Value, dependencies []*Dependency, paramStar
Builtin dynamic bindings. Builtin dynamic bindings.
*/ */
func paramBinding(index, paramIndex int, typ reflect.Type) *Binding { func paramBinding(index, paramIndex int, typ reflect.Type) *binding {
return &Binding{ return &binding{
Dependency: &Dependency{Handle: paramDependencyHandler(paramIndex), DestType: typ, Source: getSource()}, Dependency: &Dependency{Handle: paramDependencyHandler(paramIndex), DestType: typ, Source: getSource()},
Input: newInput(typ, index, nil), Input: newInput(typ, index, nil),
} }
@ -299,8 +303,8 @@ func paramDependencyHandler(paramIndex int) DependencyHandler {
// registered if input parameters are more than matched dependencies. // registered if input parameters are more than matched dependencies.
// It binds an input to a request body based on the request content-type header (JSON, XML, YAML, Query, Form). // It binds an input to a request body based on the request content-type header (JSON, XML, YAML, Query, Form).
func payloadBinding(index int, typ reflect.Type) *Binding { func payloadBinding(index int, typ reflect.Type) *binding {
return &Binding{ return &binding{
Dependency: &Dependency{ Dependency: &Dependency{
Handle: func(ctx context.Context, input *Input) (newValue reflect.Value, err error) { Handle: func(ctx context.Context, input *Input) (newValue reflect.Value, err error) {
wasPtr := input.Type.Kind() == reflect.Ptr wasPtr := input.Type.Kind() == reflect.Ptr

View File

@ -11,8 +11,14 @@ import (
"github.com/kataras/iris/v12/sessions" "github.com/kataras/iris/v12/sessions"
) )
func contextBinding(index int) *Binding { var (
return &Binding{ stdContextTyp = reflect.TypeOf((*stdContext.Context)(nil)).Elem()
sessionTyp = reflect.TypeOf((*sessions.Session)(nil))
timeTyp = reflect.TypeOf((*time.Time)(nil)).Elem()
)
func contextBinding(index int) *binding {
return &binding{
Dependency: BuiltinDependencies[0], Dependency: BuiltinDependencies[0],
Input: &Input{Type: BuiltinDependencies[0].DestType, Index: index}, Input: &Input{Type: BuiltinDependencies[0].DestType, Index: index},
} }
@ -64,55 +70,55 @@ func TestGetBindingsForFunc(t *testing.T) {
var tests = []struct { var tests = []struct {
Func interface{} Func interface{}
Expected []*Binding Expected []*binding
}{ }{
{ // 0 { // 0
Func: func(ctx context.Context) { Func: func(ctx context.Context) {
ctx.WriteString("t1") ctx.WriteString("t1")
}, },
Expected: []*Binding{contextBinding(0)}, Expected: []*binding{contextBinding(0)},
}, },
{ // 1 { // 1
Func: func(ctx context.Context) error { Func: func(ctx context.Context) error {
return fmt.Errorf("err1") return fmt.Errorf("err1")
}, },
Expected: []*Binding{contextBinding(0)}, Expected: []*binding{contextBinding(0)},
}, },
{ // 2 { // 2
Func: func(ctx context.Context) testResponse { Func: func(ctx context.Context) testResponse {
return testResponse{Name: "name"} return testResponse{Name: "name"}
}, },
Expected: []*Binding{contextBinding(0)}, Expected: []*binding{contextBinding(0)},
}, },
{ // 3 { // 3
Func: func(in testRequest) (testResponse, error) { Func: func(in testRequest) (testResponse, error) {
return testResponse{Name: "email of " + in.Email}, nil return testResponse{Name: "email of " + in.Email}, nil
}, },
Expected: []*Binding{{Dependency: deps[2], Input: &Input{Index: 0, Type: testRequestTyp}}}, Expected: []*binding{{Dependency: deps[2], Input: &Input{Index: 0, Type: testRequestTyp}}},
}, },
{ // 4 { // 4
Func: func(in testRequest) (testResponse, error) { Func: func(in testRequest) (testResponse, error) {
return testResponse{Name: "not valid "}, fmt.Errorf("invalid") return testResponse{Name: "not valid "}, fmt.Errorf("invalid")
}, },
Expected: []*Binding{{Dependency: deps[2], Input: &Input{Index: 0, Type: testRequestTyp}}}, Expected: []*binding{{Dependency: deps[2], Input: &Input{Index: 0, Type: testRequestTyp}}},
}, },
{ // 5 { // 5
Func: func(ctx context.Context, in testRequest) testResponse { Func: func(ctx context.Context, in testRequest) testResponse {
return testResponse{Name: "(with ctx) email of " + in.Email} return testResponse{Name: "(with ctx) email of " + in.Email}
}, },
Expected: []*Binding{contextBinding(0), {Dependency: deps[2], Input: &Input{Index: 1, Type: testRequestTyp}}}, Expected: []*binding{contextBinding(0), {Dependency: deps[2], Input: &Input{Index: 1, Type: testRequestTyp}}},
}, },
{ // 6 { // 6
Func: func(in testRequest, ctx context.Context) testResponse { // reversed. Func: func(in testRequest, ctx context.Context) testResponse { // reversed.
return testResponse{Name: "(with ctx) email of " + in.Email} return testResponse{Name: "(with ctx) email of " + in.Email}
}, },
Expected: []*Binding{{Dependency: deps[2], Input: &Input{Index: 0, Type: testRequestTyp}}, contextBinding(1)}, Expected: []*binding{{Dependency: deps[2], Input: &Input{Index: 0, Type: testRequestTyp}}, contextBinding(1)},
}, },
{ // 7 { // 7
Func: func(in testRequest, ctx context.Context, in2 string) testResponse { // reversed. Func: func(in testRequest, ctx context.Context, in2 string) testResponse { // reversed.
return testResponse{Name: "(with ctx) email of " + in.Email + "and in2: " + in2} return testResponse{Name: "(with ctx) email of " + in.Email + "and in2: " + in2}
}, },
Expected: []*Binding{ Expected: []*binding{
{ {
Dependency: deps[2], Dependency: deps[2],
Input: &Input{Index: 0, Type: testRequestTyp}, Input: &Input{Index: 0, Type: testRequestTyp},
@ -128,7 +134,7 @@ func TestGetBindingsForFunc(t *testing.T) {
Func: func(in testRequest, ctx context.Context, in2, in3 string) testResponse { // reversed. Func: func(in testRequest, ctx context.Context, in2, in3 string) testResponse { // reversed.
return testResponse{Name: "(with ctx) email of " + in.Email + " | in2: " + in2 + " in3: " + in3} return testResponse{Name: "(with ctx) email of " + in.Email + " | in2: " + in2 + " in3: " + in3}
}, },
Expected: []*Binding{ Expected: []*binding{
{ {
Dependency: deps[2], Dependency: deps[2],
Input: &Input{Index: 0, Type: testRequestTyp}, Input: &Input{Index: 0, Type: testRequestTyp},
@ -148,7 +154,7 @@ func TestGetBindingsForFunc(t *testing.T) {
Func: func(ctx context.Context, in testRequest, in2 testRequest2) testResponse { Func: func(ctx context.Context, in testRequest, in2 testRequest2) testResponse {
return testResponse{Name: fmt.Sprintf("(with ctx) email of %s and in2.Age %d", in.Email, in2.Age)} return testResponse{Name: fmt.Sprintf("(with ctx) email of %s and in2.Age %d", in.Email, in2.Age)}
}, },
Expected: []*Binding{ Expected: []*binding{
contextBinding(0), contextBinding(0),
{ {
Dependency: deps[2], Dependency: deps[2],
@ -170,7 +176,7 @@ func TestGetBindingsForFunc(t *testing.T) {
Func: func(userID string, age int) testResponse { Func: func(userID string, age int) testResponse {
return testResponse{Name: "in from path parameters"} return testResponse{Name: "in from path parameters"}
}, },
Expected: []*Binding{ Expected: []*binding{
paramBinding(0, 0, reflect.TypeOf("")), paramBinding(0, 0, reflect.TypeOf("")),
paramBinding(1, 1, reflect.TypeOf(0)), paramBinding(1, 1, reflect.TypeOf(0)),
}, },
@ -180,7 +186,7 @@ func TestGetBindingsForFunc(t *testing.T) {
Func: func(ctx stdContext.Context, s *sessions.Session, t time.Time) testResponse { Func: func(ctx stdContext.Context, s *sessions.Session, t time.Time) testResponse {
return testResponse{"from std context and session"} return testResponse{"from std context and session"}
}, },
Expected: []*Binding{ Expected: []*binding{
{ {
Dependency: NewDependency(BuiltinDependencies[1]), Dependency: NewDependency(BuiltinDependencies[1]),
Input: &Input{Index: 0, Type: stdContextTyp}, Input: &Input{Index: 0, Type: stdContextTyp},
@ -191,7 +197,7 @@ func TestGetBindingsForFunc(t *testing.T) {
}, },
{ {
Dependency: NewDependency(BuiltinDependencies[3]), Dependency: NewDependency(BuiltinDependencies[3]),
Input: &Input{Index: 2, Type: reflect.TypeOf(time.Time{})}, Input: &Input{Index: 2, Type: timeTyp},
}, },
}, },
}, },
@ -307,7 +313,7 @@ func TestBindingsForStruct(t *testing.T) {
}), }),
} }
var autoBindings = []*Binding{ var autoBindings = []*binding{
payloadBinding(0, reflect.TypeOf(embedded1{})), payloadBinding(0, reflect.TypeOf(embedded1{})),
payloadBinding(1, reflect.TypeOf(embedded2{})), payloadBinding(1, reflect.TypeOf(embedded2{})),
} }
@ -319,12 +325,12 @@ func TestBindingsForStruct(t *testing.T) {
var tests = []struct { var tests = []struct {
Value interface{} Value interface{}
Registered []*Dependency Registered []*Dependency
Expected []*Binding Expected []*binding
}{ }{
{ // 0. { // 0.
Value: &controller{}, Value: &controller{},
Registered: deps, Registered: deps,
Expected: []*Binding{ Expected: []*binding{
{ {
Dependency: deps[0], Dependency: deps[0],
Input: &Input{Index: 0, StructFieldIndex: []int{0}, Type: reflect.TypeOf("")}, Input: &Input{Index: 0, StructFieldIndex: []int{0}, Type: reflect.TypeOf("")},
@ -338,7 +344,7 @@ func TestBindingsForStruct(t *testing.T) {
// 1. test controller with pre-defined variables. // 1. test controller with pre-defined variables.
{ {
Value: &controller{Name: "name_struct", Service: new(serviceImpl)}, Value: &controller{Name: "name_struct", Service: new(serviceImpl)},
Expected: []*Binding{ Expected: []*binding{
{ {
Dependency: NewDependency("name_struct"), Dependency: NewDependency("name_struct"),
Input: &Input{Index: 0, StructFieldIndex: []int{0}, Type: reflect.TypeOf("")}, Input: &Input{Index: 0, StructFieldIndex: []int{0}, Type: reflect.TypeOf("")},
@ -354,7 +360,7 @@ func TestBindingsForStruct(t *testing.T) {
{ {
Value: &controller{Name: "name_struct", Service: new(serviceImpl)}, Value: &controller{Name: "name_struct", Service: new(serviceImpl)},
Registered: deps, Registered: deps,
Expected: []*Binding{ Expected: []*binding{
{ {
Dependency: NewDependency("name_struct"), Dependency: NewDependency("name_struct"),
Input: &Input{Index: 0, StructFieldIndex: []int{0}, Type: reflect.TypeOf("")}, Input: &Input{Index: 0, StructFieldIndex: []int{0}, Type: reflect.TypeOf("")},
@ -369,7 +375,7 @@ func TestBindingsForStruct(t *testing.T) {
{ {
Value: &controllerEmbeddingExported{}, Value: &controllerEmbeddingExported{},
Registered: depsForAnonymousEmbedded, Registered: depsForAnonymousEmbedded,
Expected: []*Binding{ Expected: []*binding{
{ {
Dependency: depsForAnonymousEmbedded[0], Dependency: depsForAnonymousEmbedded[0],
Input: &Input{Index: 0, StructFieldIndex: []int{0, 0}, Type: reflect.TypeOf(0)}, Input: &Input{Index: 0, StructFieldIndex: []int{0, 0}, Type: reflect.TypeOf(0)},
@ -384,7 +390,7 @@ func TestBindingsForStruct(t *testing.T) {
{ {
Value: &controllerEmbeddingUnexported{}, Value: &controllerEmbeddingUnexported{},
Registered: depsForAnonymousEmbedded, Registered: depsForAnonymousEmbedded,
Expected: []*Binding{ Expected: []*binding{
{ {
Dependency: depsForAnonymousEmbedded[0], Dependency: depsForAnonymousEmbedded[0],
Input: &Input{Index: 0, StructFieldIndex: []int{0, 0}, Type: reflect.TypeOf(0)}, Input: &Input{Index: 0, StructFieldIndex: []int{0, 0}, Type: reflect.TypeOf(0)},
@ -411,7 +417,7 @@ func TestBindingsForStruct(t *testing.T) {
{ {
Value: &controller2{}, Value: &controller2{},
Registered: depsForFieldsOfStruct, Registered: depsForFieldsOfStruct,
Expected: []*Binding{ Expected: []*binding{
{ {
Dependency: depsForFieldsOfStruct[0], Dependency: depsForFieldsOfStruct[0],
Input: &Input{Index: 0, StructFieldIndex: []int{0}, Type: reflect.TypeOf(embedded1{})}, Input: &Input{Index: 0, StructFieldIndex: []int{0}, Type: reflect.TypeOf(embedded1{})},
@ -426,7 +432,7 @@ func TestBindingsForStruct(t *testing.T) {
{ {
Value: &controller3{}, Value: &controller3{},
Registered: []*Dependency{depsForFieldsOfStruct[0]}, Registered: []*Dependency{depsForFieldsOfStruct[0]},
Expected: []*Binding{ Expected: []*binding{
{ {
Dependency: depsForFieldsOfStruct[0], Dependency: depsForFieldsOfStruct[0],
Input: &Input{Index: 0, StructFieldIndex: []int{0}, Type: reflect.TypeOf(embedded1{})}, Input: &Input{Index: 0, StructFieldIndex: []int{0}, Type: reflect.TypeOf(embedded1{})},
@ -437,7 +443,7 @@ func TestBindingsForStruct(t *testing.T) {
{ {
Value: &controller3{}, Value: &controller3{},
Registered: depsForFieldsOfStruct, Registered: depsForFieldsOfStruct,
Expected: []*Binding{ Expected: []*binding{
{ {
Dependency: depsForFieldsOfStruct[0], Dependency: depsForFieldsOfStruct[0],
Input: &Input{Index: 0, StructFieldIndex: []int{0}, Type: reflect.TypeOf(embedded1{})}, Input: &Input{Index: 0, StructFieldIndex: []int{0}, Type: reflect.TypeOf(embedded1{})},
@ -448,7 +454,7 @@ func TestBindingsForStruct(t *testing.T) {
{ {
Value: &controller{}, Value: &controller{},
Registered: depsInterfaces, Registered: depsInterfaces,
Expected: []*Binding{ Expected: []*binding{
{ {
Dependency: depsInterfaces[0], Dependency: depsInterfaces[0],
Input: &Input{Index: 0, StructFieldIndex: []int{0}, Type: reflect.TypeOf("")}, Input: &Input{Index: 0, StructFieldIndex: []int{0}, Type: reflect.TypeOf("")},

View File

@ -2,17 +2,12 @@ package hero
import ( import (
stdContext "context" stdContext "context"
"fmt"
"time" "time"
"github.com/kataras/iris/v12/context" "github.com/kataras/iris/v12/context"
"github.com/kataras/iris/v12/sessions" "github.com/kataras/iris/v12/sessions"
) )
func fatalf(format string, args ...interface{}) {
panic(fmt.Sprintf(format, args...))
}
// Default is the default container value which can be used for dependencies share. // Default is the default container value which can be used for dependencies share.
var Default = New() var Default = New()
@ -40,13 +35,15 @@ type Container struct {
GetErrorHandler func(context.Context) ErrorHandler // cannot be nil. GetErrorHandler func(context.Context) ErrorHandler // cannot be nil.
} }
// BuiltinDependencies is a list of builtin dependencies that are added on Container's initilization.
// Contains the iris context, standard context, iris sessions and time dependencies.
var BuiltinDependencies = []*Dependency{ var BuiltinDependencies = []*Dependency{
// iris context dependency. // iris context dependency.
NewDependency(func(ctx context.Context) context.Context { return ctx }), NewDependency(func(ctx context.Context) context.Context { return ctx }).Explicitly(),
// standard context dependency. // standard context dependency.
NewDependency(func(ctx context.Context) stdContext.Context { NewDependency(func(ctx context.Context) stdContext.Context {
return ctx.Request().Context() return ctx.Request().Context()
}), }).Explicitly(),
// iris session dependency. // iris session dependency.
NewDependency(func(ctx context.Context) *sessions.Session { NewDependency(func(ctx context.Context) *sessions.Session {
session := sessions.Get(ctx) session := sessions.Get(ctx)
@ -55,11 +52,11 @@ var BuiltinDependencies = []*Dependency{
} }
return session return session
}), }).Explicitly(),
// time.Time to time.Now dependency. // time.Time to time.Now dependency.
NewDependency(func(ctx context.Context) time.Time { NewDependency(func(ctx context.Context) time.Time {
return time.Now() return time.Now()
}), }).Explicitly(),
// payload and param bindings are dynamically allocated and declared at the end of the `binding` source file. // payload and param bindings are dynamically allocated and declared at the end of the `binding` source file.
} }
@ -161,6 +158,9 @@ func (c *Container) Handler(fn interface{}) context.Handler {
return makeHandler(fn, c) return makeHandler(fn, c)
} }
// Struct accepts a pointer to a struct value and returns a structure which
// contains bindings for the struct's fields and a method to
// extract a Handler from this struct's method.
func (c *Container) Struct(ptrValue interface{}) *Struct { func (c *Container) Struct(ptrValue interface{}) *Struct {
return makeStruct(ptrValue, c) return makeStruct(ptrValue, c)
} }

View File

@ -9,8 +9,11 @@ import (
) )
type ( type (
// DependencyHandler is the native function declaration which implementors should return a value match to an input.
DependencyHandler func(ctx context.Context, input *Input) (reflect.Value, error) DependencyHandler func(ctx context.Context, input *Input) (reflect.Value, error)
// Dependency describes the design-time dependency to be injected at serve time.
// Contains its source location, the dependency handler (provider) itself and information
// such as static for static struct values or explicit to bind a value to its exact DestType and not if just assignable to it (interfaces).
Dependency struct { Dependency struct {
OriginalValue interface{} // Used for debugging and for logging only. OriginalValue interface{} // Used for debugging and for logging only.
Source Source Source Source

View File

@ -9,6 +9,7 @@ import (
"strings" "strings"
) )
// Source describes where a dependency is located at the source code itself.
type Source struct { type Source struct {
File string File string
Line int Line int

View File

@ -8,12 +8,19 @@ import (
) )
type ( type (
// ErrorHandler describes an interface to handle errors per hero handler and its dependencies.
//
// Handles non-nil errors return from a hero handler or a controller's method (see `getBindingsFor` and `Handler`)
// the error may return from a request-scoped dependency too (see `Handler`).
ErrorHandler interface { ErrorHandler interface {
HandleError(context.Context, error) HandleError(context.Context, error)
} }
// ErrorHandlerFunc implements the `ErrorHandler`.
// It describes the type defnition for an error function handler.
ErrorHandlerFunc func(context.Context, error) ErrorHandlerFunc func(context.Context, error)
) )
// HandleError fires when a non-nil error returns from a request-scoped dependency at serve-time or the handler itself.
func (fn ErrorHandlerFunc) HandleError(ctx context.Context, err error) { func (fn ErrorHandlerFunc) HandleError(ctx context.Context, err error) {
fn(ctx, err) fn(ctx, err)
} }
@ -41,7 +48,7 @@ var (
ctx.StatusCode(DefaultErrStatusCode) ctx.StatusCode(DefaultErrStatusCode)
} }
ctx.WriteString(err.Error()) _, _ = ctx.WriteString(err.Error())
} }
ctx.StopExecution() ctx.StopExecution()

View File

@ -1,12 +1,9 @@
package hero package hero
import ( import (
stdContext "context"
"reflect" "reflect"
"time"
"github.com/kataras/iris/v12/context" "github.com/kataras/iris/v12/context"
"github.com/kataras/iris/v12/sessions"
) )
func valueOf(v interface{}) reflect.Value { func valueOf(v interface{}) reflect.Value {
@ -45,7 +42,6 @@ func isFunc(kindable interface{ Kind() reflect.Kind }) bool {
} }
var inputTyp = reflect.TypeOf((*Input)(nil)) var inputTyp = reflect.TypeOf((*Input)(nil))
var timeTyp = reflect.TypeOf((*time.Time)(nil)).Elem()
var errTyp = reflect.TypeOf((*error)(nil)).Elem() var errTyp = reflect.TypeOf((*error)(nil)).Elem()
@ -69,20 +65,6 @@ func isContext(typ reflect.Type) bool {
return typ.Implements(contextTyp) return typ.Implements(contextTyp)
} }
var stdContextTyp = reflect.TypeOf((*stdContext.Context)(nil)).Elem()
// isStdContext returns true if the "typ" is a type of standard Context.
func isStdContext(typ reflect.Type) bool {
return typ.Implements(stdContextTyp)
}
var sessionTyp = reflect.TypeOf((*sessions.Session)(nil))
// isStdContext returns true if the "typ" is a type of standard Context.
func isSession(typ reflect.Type) bool {
return typ == sessionTyp
}
var errorHandlerTyp = reflect.TypeOf((*ErrorHandler)(nil)).Elem() var errorHandlerTyp = reflect.TypeOf((*ErrorHandler)(nil)).Elem()
func isErrorHandler(typ reflect.Type) bool { func isErrorHandler(typ reflect.Type) bool {

View File

@ -31,11 +31,13 @@ var sortByNumMethods Sorter = func(t1 reflect.Type, t2 reflect.Type) bool {
return true return true
} }
// Struct keeps a record of a particular struct value injection.
// See `Container.Struct` and `mvc#Application.Handle` methods.
type Struct struct { type Struct struct {
ptrType reflect.Type ptrType reflect.Type
ptrValue reflect.Value // the original ptr struct value. ptrValue reflect.Value // the original ptr struct value.
elementType reflect.Type // the original struct type. elementType reflect.Type // the original struct type.
bindings []*Binding // struct field bindings. bindings []*binding // struct field bindings.
Container *Container Container *Container
Singleton bool Singleton bool
@ -102,6 +104,10 @@ func makeStruct(structPtr interface{}, c *Container) *Struct {
return s return s
} }
// Acquire returns a struct value based on the request.
// If the dependencies are all static then these are already set-ed at the initialization of this Struct
// and the same struct value instance will be returned, ignoring the Context. Otherwise
// a new struct value with filled fields by its pre-calculated bindings will be returned instead.
func (s *Struct) Acquire(ctx context.Context) (reflect.Value, error) { func (s *Struct) Acquire(ctx context.Context) (reflect.Value, error) {
if s.Singleton { if s.Singleton {
ctx.Values().Set(context.ControllerContextKey, s.ptrValue) ctx.Values().Set(context.ControllerContextKey, s.ptrValue)
@ -130,6 +136,8 @@ func (s *Struct) Acquire(ctx context.Context) (reflect.Value, error) {
return ctrl, nil return ctrl, nil
} }
// MethodHandler accepts a "methodName" that should be a valid an exported
// method of the struct and returns its converted Handler.
func (s *Struct) MethodHandler(methodName string) context.Handler { func (s *Struct) MethodHandler(methodName string) context.Handler {
m, ok := s.ptrValue.Type().MethodByName(methodName) m, ok := s.ptrValue.Type().MethodByName(methodName)
if !ok { if !ok {

View File

@ -2,15 +2,9 @@ package mvc
import ( import (
"reflect" "reflect"
"github.com/kataras/iris/v12/hero"
) )
var ( var baseControllerTyp = reflect.TypeOf((*BaseController)(nil)).Elem()
baseControllerTyp = reflect.TypeOf((*BaseController)(nil)).Elem()
errorHandlerTyp = reflect.TypeOf((*hero.ErrorHandler)(nil)).Elem()
errorTyp = reflect.TypeOf((*error)(nil)).Elem()
)
func isBaseController(ctrlTyp reflect.Type) bool { func isBaseController(ctrlTyp reflect.Type) bool {
return ctrlTyp.Implements(baseControllerTyp) return ctrlTyp.Implements(baseControllerTyp)
@ -26,33 +20,3 @@ func indirectType(typ reflect.Type) reflect.Type {
} }
return typ return typ
} }
func isErrorHandler(ctrlTyp reflect.Type) bool {
return ctrlTyp.Implements(errorHandlerTyp)
}
func hasErrorOutArgs(fn reflect.Method) bool {
n := fn.Type.NumOut()
if n == 0 {
return false
}
for i := 0; i < n; i++ {
if out := fn.Type.Out(i); out.Kind() == reflect.Interface {
if out.Implements(errorTyp) {
return true
}
}
}
return false
}
func getInputArgsFromFunc(funcTyp reflect.Type) []reflect.Type {
n := funcTyp.NumIn()
funcIn := make([]reflect.Type, n)
for i := 0; i < n; i++ {
funcIn[i] = funcTyp.In(i)
}
return funcIn
}