internal/wire: factor out common code in solve (#98)
- Fixed a bug when a interface is bind to a value wire would fail to record it is used. - Also rename ProvidedType.ConcreteType to Type since it doesn't necessarily returns a concrete type. Fixes #72
This commit is contained in:
@@ -114,8 +114,8 @@ dfs:
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
switch pv := set.For(curr.t); {
|
pv := set.For(curr.t)
|
||||||
case pv.IsNil():
|
if pv.IsNil() {
|
||||||
if curr.from == nil {
|
if curr.from == nil {
|
||||||
ec.add(fmt.Errorf("no provider found for %s, output of injector", types.TypeString(curr.t, nil)))
|
ec.add(fmt.Errorf("no provider found for %s, output of injector", types.TypeString(curr.t, nil)))
|
||||||
index.Set(curr.t, errAbort)
|
index.Set(curr.t, errAbort)
|
||||||
@@ -129,33 +129,25 @@ dfs:
|
|||||||
ec.add(errors.New(sb.String()))
|
ec.add(errors.New(sb.String()))
|
||||||
index.Set(curr.t, errAbort)
|
index.Set(curr.t, errAbort)
|
||||||
continue
|
continue
|
||||||
case pv.IsArg():
|
}
|
||||||
src := set.srcMap.At(curr.t).(*providerSetSrc)
|
src := set.srcMap.At(curr.t).(*providerSetSrc)
|
||||||
used = append(used, src)
|
used = append(used, src)
|
||||||
if concrete := pv.ConcreteType(); !types.Identical(concrete, curr.t) {
|
if concrete := pv.Type(); !types.Identical(concrete, curr.t) {
|
||||||
// Interface binding.
|
// Interface binding does not create a call.
|
||||||
i := index.At(concrete)
|
i := index.At(concrete)
|
||||||
if i == nil {
|
if i == nil {
|
||||||
stk = append(stk, curr, frame{t: concrete, from: curr.t, up: &curr})
|
stk = append(stk, curr, frame{t: concrete, from: curr.t, up: &curr})
|
||||||
continue
|
|
||||||
}
|
|
||||||
index.Set(curr.t, i)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
case pv.IsProvider():
|
|
||||||
p := pv.Provider()
|
|
||||||
src := set.srcMap.At(curr.t).(*providerSetSrc)
|
|
||||||
used = append(used, src)
|
|
||||||
if concrete := pv.ConcreteType(); !types.Identical(concrete, curr.t) {
|
|
||||||
// Interface binding. Don't create a call ourselves.
|
|
||||||
i := index.At(concrete)
|
|
||||||
if i == nil {
|
|
||||||
stk = append(stk, curr, frame{t: concrete, from: curr.t, up: &curr})
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
index.Set(curr.t, i)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
index.Set(curr.t, i)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
switch pv := set.For(curr.t); {
|
||||||
|
case pv.IsArg():
|
||||||
|
// Continue, already added to stk.
|
||||||
|
case pv.IsProvider():
|
||||||
|
p := pv.Provider()
|
||||||
// Ensure that all argument types have been visited. If not, push them
|
// Ensure that all argument types have been visited. If not, push them
|
||||||
// on the stack in reverse order so that calls are added in argument
|
// on the stack in reverse order so that calls are added in argument
|
||||||
// order.
|
// order.
|
||||||
@@ -204,18 +196,6 @@ dfs:
|
|||||||
})
|
})
|
||||||
case pv.IsValue():
|
case pv.IsValue():
|
||||||
v := pv.Value()
|
v := pv.Value()
|
||||||
if !types.Identical(v.Out, curr.t) {
|
|
||||||
// Interface binding. Don't create a call ourselves.
|
|
||||||
i := index.At(v.Out)
|
|
||||||
if i == nil {
|
|
||||||
stk = append(stk, curr, frame{t: v.Out, from: curr.t, up: &curr})
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
index.Set(curr.t, i)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
src := set.srcMap.At(curr.t).(*providerSetSrc)
|
|
||||||
used = append(used, src)
|
|
||||||
index.Set(curr.t, given.Len()+len(calls))
|
index.Set(curr.t, given.Len()+len(calls))
|
||||||
calls = append(calls, call{
|
calls = append(calls, call{
|
||||||
kind: valueExpr,
|
kind: valueExpr,
|
||||||
|
|||||||
@@ -939,8 +939,14 @@ func (pt ProvidedType) IsNil() bool {
|
|||||||
return pt.p == nil && pt.v == nil && pt.a == nil
|
return pt.p == nil && pt.v == nil && pt.a == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConcreteType returns the concrete type that was provided.
|
// Type returns the output type.
|
||||||
func (pt ProvidedType) ConcreteType() types.Type {
|
//
|
||||||
|
// - For a function provider, this is the first return value type.
|
||||||
|
// - For a struct provider, this is either the struct type or the pointer type
|
||||||
|
// whose element type is the struct type.
|
||||||
|
// - For a value, this is the type of the expression.
|
||||||
|
// - For an argument, this is the type of the argument.
|
||||||
|
func (pt ProvidedType) Type() types.Type {
|
||||||
return pt.t
|
return pt.t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
20
internal/wire/testdata/BindInterfaceWithValue/foo/foo.go
vendored
Normal file
20
internal/wire/testdata/BindInterfaceWithValue/foo/foo.go
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// Copyright 2018 The Wire Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
w := inject()
|
||||||
|
w.Write([]byte("Hello, World!"))
|
||||||
|
}
|
||||||
32
internal/wire/testdata/BindInterfaceWithValue/foo/wire.go
vendored
Normal file
32
internal/wire/testdata/BindInterfaceWithValue/foo/wire.go
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
// Copyright 2018 The Wire Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
//+build wireinject
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/google/wire"
|
||||||
|
)
|
||||||
|
|
||||||
|
func inject() io.Writer {
|
||||||
|
wire.Build(
|
||||||
|
wire.Value(os.Stdout),
|
||||||
|
wire.Bind(new(io.Writer), new(os.File)),
|
||||||
|
)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
1
internal/wire/testdata/BindInterfaceWithValue/pkg
vendored
Normal file
1
internal/wire/testdata/BindInterfaceWithValue/pkg
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
example.com/foo
|
||||||
1
internal/wire/testdata/BindInterfaceWithValue/want/program_out.txt
vendored
Normal file
1
internal/wire/testdata/BindInterfaceWithValue/want/program_out.txt
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Hello, World!
|
||||||
22
internal/wire/testdata/BindInterfaceWithValue/want/wire_gen.go
vendored
Normal file
22
internal/wire/testdata/BindInterfaceWithValue/want/wire_gen.go
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
// Code generated by Wire. DO NOT EDIT.
|
||||||
|
|
||||||
|
//go:generate wire
|
||||||
|
//+build !wireinject
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Injectors from wire.go:
|
||||||
|
|
||||||
|
func inject() io.Writer {
|
||||||
|
file := _wireFileValue
|
||||||
|
return file
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_wireFileValue = os.Stdout
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user