diff --git a/internal/compiler/compiler.go b/internal/compiler/compiler.go index d140b40..02cbeaa 100644 --- a/internal/compiler/compiler.go +++ b/internal/compiler/compiler.go @@ -4,7 +4,10 @@ package compiler -import "reflect" +import ( + "errors" + "reflect" +) type ( Closer = func() error @@ -22,3 +25,5 @@ type ( Value reflect.Value } ) + +var ErrPanicked = errors.New("panicked") diff --git a/internal/compiler/constructor.go b/internal/compiler/constructor.go index 0b4e1c2..fc72994 100644 --- a/internal/compiler/constructor.go +++ b/internal/compiler/constructor.go @@ -61,7 +61,7 @@ func NewConstructor(fn any) (*Constructor, error) { return c, nil } -func (c *Constructor) Create(dependencies ...*Dependency) (reflect.Value, Closer, error) { +func (c *Constructor) Create(dependencies ...*Dependency) (_ reflect.Value, _ Closer, err error) { var args = make([]reflect.Value, 0, len(dependencies)) for i, dep := range dependencies { if c.vct && i == c.lin { @@ -75,7 +75,11 @@ func (c *Constructor) Create(dependencies ...*Dependency) (reflect.Value, Closer args = append(args, dep.Value) } - var out = c.val.Call(args) + var out []reflect.Value + if out, err = c.call(args); err != nil { + return reflect.Value{}, nil, err + } + switch c.beh { case behaviourValue: return out[0], nil, nil @@ -108,6 +112,16 @@ func (c *Constructor) Type() reflect.Type { return c.typ.Out(0) } +func (c *Constructor) call(args []reflect.Value) (_ []reflect.Value, err error) { + defer func() { + if recovered := recover(); recovered != nil { + err = fmt.Errorf("unable create because the constructor %w : %+v", ErrPanicked, recovered) + } + }() + + return c.val.Call(args), nil +} + func (c *Constructor) guessBehaviour() { switch { case c.typ == nil: diff --git a/internal/compiler/constructor_test.go b/internal/compiler/constructor_test.go index a6c8c7b..f570494 100644 --- a/internal/compiler/constructor_test.go +++ b/internal/compiler/constructor_test.go @@ -32,9 +32,12 @@ func TestConstructor(t *testing.T) { } ) - var closer = func() error { - return nil - } + var ( + closer = func() error { + return nil + } + oopsErr = errors.New("oops") + ) var testCases = []TestCase{{ Constructor: []string{}, @@ -47,6 +50,14 @@ func TestConstructor(t *testing.T) { return 0, 0, 0, 0 }, Error: compiler.ErrInvalidConstructor, + }, { + Constructor: func() int { + panic("oops") + }, + Result: &Result{ + Error: compiler.ErrPanicked, + }, + Type: reflect.TypeOf(0), }, { Constructor: func(a, b int) int { return a + b @@ -68,11 +79,11 @@ func TestConstructor(t *testing.T) { Type: reflect.TypeOf(1), }, { Constructor: func() (int, error) { - return 0, errors.New("oops") + return 0, oopsErr }, Dependencies: []*compiler.Dependency{}, Result: &Result{ - Error: errors.New("oops"), + Error: oopsErr, Value: reflect.ValueOf(0), }, Type: reflect.TypeOf(0), @@ -98,12 +109,12 @@ func TestConstructor(t *testing.T) { Type: reflect.TypeOf(0), }, { Constructor: func() (int, func() error, error) { - return 0, closer, errors.New("oops") + return 0, closer, oopsErr }, Dependencies: []*compiler.Dependency{}, Result: &Result{ Closer: closer, - Error: errors.New("oops"), + Error: oopsErr, Value: reflect.ValueOf(0), }, Type: reflect.TypeOf(0), @@ -164,9 +175,12 @@ func TestConstructor(t *testing.T) { }, "Dependencies not equal") var v, c, e = cmp.Create(testCase.Dependencies...) - require.Equal(t, testCase.Result.Error, e) - require.Equal(t, testCase.Result.Value.Interface(), v.Interface()) + if v.IsValid() { + require.Equal(t, testCase.Result.Value.Interface(), v.Interface()) + } + require.Equal(t, reflect.ValueOf(testCase.Result.Closer).Pointer(), reflect.ValueOf(c).Pointer()) + require.ErrorIs(t, e, testCase.Result.Error) }) } }