mirror of
https://github.com/kataras/iris.git
synced 2026-01-11 05:55:57 +00:00
mvc: struct field and method dependency logs on debug level. Read HISTORY.md
- remove Party.GetReporter - Read HISTORY.md
This commit is contained in:
@@ -16,8 +16,9 @@ type binding struct {
|
||||
|
||||
// Input contains the input reference of which a dependency is binded to.
|
||||
type Input struct {
|
||||
Index int // for func inputs
|
||||
StructFieldIndex []int // for struct fields in order to support embedded ones.
|
||||
Index int // for func inputs
|
||||
StructFieldIndex []int // for struct fields in order to support embedded ones.
|
||||
StructFieldName string // the struct field's name.
|
||||
Type reflect.Type
|
||||
|
||||
selfValue reflect.Value // reflect.ValueOf(*Input) cache.
|
||||
@@ -34,6 +35,12 @@ func newInput(typ reflect.Type, index int, structFieldIndex []int) *Input {
|
||||
return in
|
||||
}
|
||||
|
||||
func newStructFieldInput(f reflect.StructField) *Input {
|
||||
input := newInput(f.Type, f.Index[0], f.Index)
|
||||
input.StructFieldName = f.Name
|
||||
return input
|
||||
}
|
||||
|
||||
// String returns the string representation of a binding.
|
||||
func (b *binding) String() string {
|
||||
index := fmt.Sprintf("%d", b.Input.Index)
|
||||
@@ -261,7 +268,7 @@ func getBindingsForStruct(v reflect.Value, dependencies []*Dependency, paramsCou
|
||||
// fmt.Printf("Controller [%s] | NonZero | Field Index: %v | Field Type: %s\n", typ, f.Index, f.Type)
|
||||
bindings = append(bindings, &binding{
|
||||
Dependency: NewDependency(elem.FieldByIndex(f.Index).Interface()),
|
||||
Input: newInput(f.Type, f.Index[0], f.Index),
|
||||
Input: newStructFieldInput(f),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -299,9 +306,10 @@ func getBindingsForStruct(v reflect.Value, dependencies []*Dependency, paramsCou
|
||||
// fmt.Printf(""Controller [%s] | Binding: %s\n", typ, binding.String())
|
||||
|
||||
if len(binding.Input.StructFieldIndex) == 0 {
|
||||
// set correctly the input's field index.
|
||||
structFieldIndex := fields[binding.Input.Index].Index
|
||||
binding.Input.StructFieldIndex = structFieldIndex
|
||||
// set correctly the input's field index and name.
|
||||
f := fields[binding.Input.Index]
|
||||
binding.Input.StructFieldIndex = f.Index
|
||||
binding.Input.StructFieldName = f.Name
|
||||
}
|
||||
|
||||
// fmt.Printf("Controller [%s] | binding Index: %v | binding Type: %s\n", typ, binding.Input.StructFieldIndex, binding.Input.Type)
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/kataras/iris/v12/context"
|
||||
@@ -15,7 +16,7 @@ import (
|
||||
)
|
||||
|
||||
// Default is the default container value which can be used for dependencies share.
|
||||
var Default = New()
|
||||
var Default = New().WithLogger(golog.Default)
|
||||
|
||||
// Container contains and delivers the Dependencies that will be binded
|
||||
// to the controller(s) or handler(s) that can be created
|
||||
@@ -28,6 +29,10 @@ var Default = New()
|
||||
//
|
||||
// For a more high-level structure please take a look at the "mvc.go#Application".
|
||||
type Container struct {
|
||||
// Optional Logger to report dependencies and matched bindings
|
||||
// per struct, function and method.
|
||||
// By default it is set by the Party creator of this Container.
|
||||
Logger *golog.Logger
|
||||
// Sorter specifies how the inputs should be sorted before binded.
|
||||
// Defaults to sort by "thinnest" target empty interface.
|
||||
Sorter Sorter
|
||||
@@ -36,12 +41,83 @@ type Container struct {
|
||||
// GetErrorHandler should return a valid `ErrorHandler` to handle bindings AND handler dispatch errors.
|
||||
// Defaults to a functon which returns the `DefaultErrorHandler`.
|
||||
GetErrorHandler func(*context.Context) ErrorHandler // cannot be nil.
|
||||
// Reports contains an ordered list of information about bindings for further analysys and testing.
|
||||
Reports []*Report
|
||||
|
||||
// resultHandlers is a list of functions that serve the return struct value of a function handler.
|
||||
// Defaults to "defaultResultHandler" but it can be overridden.
|
||||
resultHandlers []func(next ResultHandler) ResultHandler
|
||||
}
|
||||
|
||||
// A Report holds meta information about dependency sources and target values per package,
|
||||
// struct, struct's fields, struct's method, package-level function or closure.
|
||||
// E.g. main -> (*UserController) -> HandleHTTPError.
|
||||
type Report struct {
|
||||
// The name is the last part of the name of a struct or its methods or a function.
|
||||
// Each name is splited by its package.struct.field or package.funcName or package.func.inlineFunc.
|
||||
Name string
|
||||
// If it's a struct or package or function
|
||||
// then it contains children reports of each one of its methods or input parameters
|
||||
// respectfully.
|
||||
Reports []*Report
|
||||
|
||||
Parent *Report
|
||||
Entries []ReportEntry
|
||||
}
|
||||
|
||||
// A ReportEntry holds the information about a binding.
|
||||
type ReportEntry struct {
|
||||
InputPosition int // struct field position or parameter position.
|
||||
InputFieldName string // if it's a struct field, then this is its type name (we can't get param names).
|
||||
InputFieldType reflect.Type // the input's type.
|
||||
DependencyValue interface{} // the dependency value binded to that InputPosition of Name.
|
||||
DependencyFile string // the file
|
||||
DependencyLine int // and line number of the dependency's value.
|
||||
}
|
||||
|
||||
func (r *Report) fill(bindings []*binding) {
|
||||
for _, b := range bindings {
|
||||
inputFieldName := b.Input.StructFieldName
|
||||
if inputFieldName == "" {
|
||||
// it's not a struct field, then type.
|
||||
inputFieldName = b.Input.Type.String()
|
||||
}
|
||||
// remove only the main one prefix.
|
||||
inputFieldName = strings.TrimPrefix(inputFieldName, "main.")
|
||||
|
||||
fieldName := inputFieldName
|
||||
switch fieldName {
|
||||
case "*context.Context":
|
||||
inputFieldName = strings.Replace(inputFieldName, "*context", "iris", 1)
|
||||
case "hero.Code", "hero.Result", "hero.View", "hero.Response":
|
||||
inputFieldName = strings.Replace(inputFieldName, "hero", "mvc", 1)
|
||||
}
|
||||
|
||||
entry := ReportEntry{
|
||||
InputPosition: b.Input.Index,
|
||||
InputFieldName: inputFieldName,
|
||||
InputFieldType: b.Input.Type,
|
||||
|
||||
DependencyValue: b.Dependency.OriginalValue,
|
||||
DependencyFile: b.Dependency.Source.File,
|
||||
DependencyLine: b.Dependency.Source.Line,
|
||||
}
|
||||
|
||||
r.Entries = append(r.Entries, entry)
|
||||
}
|
||||
}
|
||||
|
||||
// fillReport adds a report to the Reports field.
|
||||
func (c *Container) fillReport(fullName string, bindings []*binding) {
|
||||
// r := c.getReport(fullName)
|
||||
|
||||
r := &Report{
|
||||
Name: fullName,
|
||||
}
|
||||
r.fill(bindings)
|
||||
c.Reports = append(c.Reports, r)
|
||||
}
|
||||
|
||||
// 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{
|
||||
@@ -113,16 +189,24 @@ func New(dependencies ...interface{}) *Container {
|
||||
return c
|
||||
}
|
||||
|
||||
// WithLogger injects a logger to use to debug dependencies and bindings.
|
||||
func (c *Container) WithLogger(logger *golog.Logger) *Container {
|
||||
c.Logger = logger
|
||||
return c
|
||||
}
|
||||
|
||||
// Clone returns a new cloned container.
|
||||
// It copies the ErrorHandler, Dependencies and all Options from "c" receiver.
|
||||
func (c *Container) Clone() *Container {
|
||||
cloned := New()
|
||||
cloned.Logger = c.Logger
|
||||
cloned.GetErrorHandler = c.GetErrorHandler
|
||||
cloned.Sorter = c.Sorter
|
||||
clonedDeps := make([]*Dependency, len(c.Dependencies))
|
||||
copy(clonedDeps, c.Dependencies)
|
||||
cloned.Dependencies = clonedDeps
|
||||
cloned.resultHandlers = c.resultHandlers
|
||||
// Reports are not cloned.
|
||||
return cloned
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ func newSource(fn reflect.Value) Source {
|
||||
}
|
||||
|
||||
return Source{
|
||||
File: callerFileName,
|
||||
File: filepath.ToSlash(callerFileName),
|
||||
Line: callerLineNumber,
|
||||
Caller: callerName,
|
||||
}
|
||||
|
||||
@@ -82,6 +82,7 @@ func makeHandler(fn interface{}, c *Container, paramsCount int) context.Handler
|
||||
numIn := typ.NumIn()
|
||||
|
||||
bindings := getBindingsForFunc(v, c.Dependencies, paramsCount)
|
||||
c.fillReport(context.HandlerName(fn), bindings)
|
||||
|
||||
resultHandler := defaultResultHandler
|
||||
for i, lidx := 0, len(c.resultHandlers)-1; i <= lidx; i++ {
|
||||
|
||||
@@ -84,8 +84,8 @@ func makeStruct(structPtr interface{}, c *Container, partyParamsCount int) *Stru
|
||||
}
|
||||
|
||||
isErrHandler := isErrorHandler(typ)
|
||||
|
||||
newContainer := c.Clone()
|
||||
newContainer.fillReport(typ.String(), bindings)
|
||||
// Add the controller dependency itself as func dependency but with a known type which should be explicit binding
|
||||
// in order to keep its maximum priority.
|
||||
newContainer.Register(s.Acquire).Explicitly().DestType = typ
|
||||
|
||||
Reference in New Issue
Block a user