Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make provide's errors more expressive for fx.Annotate-ed functions #844

Merged
merged 7 commits into from Feb 22, 2022
2 changes: 2 additions & 0 deletions annotated.go
Expand Up @@ -264,6 +264,7 @@ type annotated struct {
ParamTags []string
ResultTags []string
As [][]reflect.Type
FuncPtr uintptr
}

func (ann annotated) String() string {
Expand Down Expand Up @@ -302,6 +303,7 @@ func (ann *annotated) Build() (interface{}, error) {

newFnType := reflect.FuncOf(paramTypes, resultTypes, false)
origFn := reflect.ValueOf(ann.Target)
ann.FuncPtr = origFn.Pointer()
newFn := reflect.MakeFunc(newFnType, func(args []reflect.Value) []reflect.Value {
args = remapParams(args)
var results []reflect.Value
Expand Down
16 changes: 16 additions & 0 deletions annotated_test.go
Expand Up @@ -787,6 +787,22 @@ func TestAnnotate(t *testing.T) {
defer app.RequireStart().RequireStop()
})

t.Run("provide an already provided function using Annotate", func(t *testing.T) {
t.Parallel()

app := NewForTest(t,
fx.Provide(fx.Annotate(newA, fx.ResultTags(`name:"a"`))),
fx.Provide(fx.Annotate(newA, fx.ResultTags(`name:"a"`))),
fx.Invoke(
fx.Annotate(newB, fx.ParamTags(`name:"a"`)),
),
)
err := app.Err()
require.Error(t, err)
assert.Contains(t, err.Error(), "already provided")
assert.Contains(t, err.Error(), "\"go.uber.org/fx_test\".TestAnnotate.func1")
})

t.Run("specify more ParamTags than Params", func(t *testing.T) {
t.Parallel()

Expand Down
1 change: 1 addition & 0 deletions provide.go
Expand Up @@ -109,6 +109,7 @@ func runProvide(c container, p provide, opts ...dig.ProvideOption) error {
return fmt.Errorf("fx.Provide(%v) from:\n%+vFailed: %v", constructor, p.Stack, err)
}

opts = append(opts, dig.LocationForPC(constructor.FuncPtr))
if err := c.Provide(ctor, opts...); err != nil {
return fmt.Errorf("fx.Provide(%v) from:\n%+vFailed: %v", constructor, p.Stack, err)
}
Expand Down