Skip to content

Commit

Permalink
Revert "Implement a dig.As ProvideOption (#233)" (#251)
Browse files Browse the repository at this point in the history
This reverts #233 until we resolve discussion on it so that we don't
accidentally release it.

Reopens #197
  • Loading branch information
abhinav authored Nov 14, 2019
1 parent 8a567bf commit 4fb70ce
Show file tree
Hide file tree
Showing 11 changed files with 55 additions and 439 deletions.
130 changes: 21 additions & 109 deletions dig.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,19 +62,12 @@ func (f optionFunc) applyOption(c *Container) { f(c) }
type provideOptions struct {
Name string
Group string
As []interface{}
}

func (o *provideOptions) Validate() error {
if len(o.Group) > 0 {
if len(o.Name) > 0 {
return fmt.Errorf(
"cannot use named values with value groups: name:%q provided with group:%q", o.Name, o.Group)
}
if len(o.As) > 0 {
return fmt.Errorf(
"cannot use dig.As with value groups: dig.As provided with group:%q", o.Group)
}
if len(o.Group) > 0 && len(o.Name) > 0 {
return fmt.Errorf(
"cannot use named values with value groups: name:%q provided with group:%q", o.Name, o.Group)
}

// Names must be representable inside a backquoted string. The only
Expand All @@ -87,23 +80,6 @@ func (o *provideOptions) Validate() error {
if strings.ContainsRune(o.Group, '`') {
return fmt.Errorf("invalid dig.Group(%q): group names cannot contain backquotes", o.Group)
}

for _, i := range o.As {
t := reflect.TypeOf(i)

if t == nil {
return fmt.Errorf("invalid dig.As(nil): argument must be a pointer to an interface")
}

if t.Kind() != reflect.Ptr {
return fmt.Errorf("invalid dig.As(%v): argument must be a pointer to an interface", t)
}

pointingTo := t.Elem()
if pointingTo.Kind() != reflect.Interface {
return fmt.Errorf("invalid dig.As(*%v): argument must be a pointer to an interface", pointingTo)
}
}
return nil
}

Expand Down Expand Up @@ -151,55 +127,6 @@ func Group(group string) ProvideOption {
})
}

// As is a ProvideOption that specifies that the value produced by the
// constructor implements one or more other interfaces.
//
// As expects one or more pointers to the implemented interfaces. Values
// produced by constructors will be made available in the container as
// implementations of all of those interfaces.
//
// For example, the following will make the buffer available in the container
// as io.Reader and io.Writer.
//
// c.Provide(newBuffer, dig.As(new(io.Reader), new(io.Writer)))
//
// That is, the above is equivalent to the following.
//
// c.Provide(func(...) (*bytes.Buffer, io.Reader, io.Writer) {
// b := newBuffer(...)
// return b, b, b
// })
//
// If used with dig.Name, the type produced by the constructor and the types
// specified with dig.As will all use the same name. For example,
//
// c.Provide(newFile, dig.As(new(io.Reader)), dig.Name("temp"))
//
// The above is equivalent to the following.
//
// type Result struct {
// dig.Out
//
// File *os.File `name:"temp"`
// Reader io.Reader `name:"temp"`
// }
//
// c.Provide(func(...) Result {
// f := newFile(...)
// return Result{
// File: f,
// Reader: f,
// }
// })
//
// This option cannot be provided for constructors which produce result
// objects.
func As(i ...interface{}) ProvideOption {
return provideOptionFunc(func(opts *provideOptions) {
opts.As = append(opts.As, i...)
})
}

// An InvokeOption modifies the default behavior of Invoke. It's included for
// future functionality; currently, there are no concrete implementations.
type InvokeOption interface {
Expand Down Expand Up @@ -497,7 +424,6 @@ func (c *Container) provide(ctor interface{}, opts provideOptions) error {
nodeOptions{
ResultName: opts.Name,
ResultGroup: opts.Group,
ResultAs: opts.As,
},
)
if err != nil {
Expand Down Expand Up @@ -609,23 +535,30 @@ func (cv connectionVisitor) Visit(res result) resultVisitor {
path := strings.Join(cv.currentResultPath, ".")

switch r := res.(type) {

case resultSingle:
k := key{name: r.Name, t: r.Type}
if err := cv.checkKey(k, path); err != nil {
*cv.err = err

if conflict, ok := cv.keyPaths[k]; ok {
*cv.err = fmt.Errorf(
"cannot provide %v from %v: already provided by %v",
k, path, conflict)
return nil
}
cv.keyPaths[k] = path
for _, asType := range r.As {
k := key{name: r.Name, t: asType}
if err := cv.checkKey(k, path); err != nil {
*cv.err = err
return nil

if ps := cv.c.providers[k]; len(ps) > 0 {
cons := make([]string, len(ps))
for i, p := range ps {
cons[i] = fmt.Sprint(p.Location())
}
cv.keyPaths[k] = path

*cv.err = fmt.Errorf(
"cannot provide %v from %v: already provided by %v",
k, path, strings.Join(cons, "; "))
return nil
}

cv.keyPaths[k] = path

case resultGrouped:
// we don't really care about the path for this since conflicts are
// okay for group results. We'll track it for the sake of having a
Expand All @@ -637,25 +570,6 @@ func (cv connectionVisitor) Visit(res result) resultVisitor {
return cv
}

func (cv connectionVisitor) checkKey(k key, path string) error {
if conflict, ok := cv.keyPaths[k]; ok {
return fmt.Errorf(
"cannot provide %v from %v: already provided by %v",
k, path, conflict)
}
if ps := cv.c.providers[k]; len(ps) > 0 {
cons := make([]string, len(ps))
for i, p := range ps {
cons[i] = fmt.Sprint(p.Location())
}

return fmt.Errorf(
"cannot provide %v from %v: already provided by %v",
k, path, strings.Join(cons, "; "))
}
return nil
}

// node is a node in the dependency graph. Each node maps to a single
// constructor provided by the user.
//
Expand Down Expand Up @@ -684,10 +598,9 @@ type node struct {

type nodeOptions struct {
// If specified, all values produced by this node have the provided name
// belong to the specified value group or implement any of the interfaces.
// or belong to the specified value group
ResultName string
ResultGroup string
ResultAs []interface{}
}

func newNode(ctor interface{}, opts nodeOptions) (*node, error) {
Expand All @@ -705,7 +618,6 @@ func newNode(ctor interface{}, opts nodeOptions) (*node, error) {
resultOptions{
Name: opts.ResultName,
Group: opts.ResultGroup,
As: opts.ResultAs,
},
)
if err != nil {
Expand Down
Loading

0 comments on commit 4fb70ce

Please sign in to comment.