goose: add goose.Value directive
Subsumes previous usage of goose.Optional. Reviewed-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Tuo Shan <shantuo@google.com>
This commit is contained in:
27
README.md
27
README.md
@@ -304,6 +304,33 @@ func injectFooBar() FooBar {
|
|||||||
|
|
||||||
And similarly if the injector needed a `*FooBar`.
|
And similarly if the injector needed a `*FooBar`.
|
||||||
|
|
||||||
|
### Binding Values
|
||||||
|
|
||||||
|
Occasionally, it is useful to bind a basic value (usually `nil`) to a type.
|
||||||
|
Instead of having injectors depend on a throwaway provider function, you can
|
||||||
|
add a value expression to a provider set.
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Foo int
|
||||||
|
|
||||||
|
func injectFoo() Foo {
|
||||||
|
panic(goose.Use(goose.Value(Foo(42))))
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The generated injector would look like this:
|
||||||
|
|
||||||
|
```go
|
||||||
|
func injectFoo() Foo {
|
||||||
|
foo := Foo(42)
|
||||||
|
return foo
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
It's important to note that the expression will be copied, so references to
|
||||||
|
variables will be evaluated during the call to the injector. goose will emit
|
||||||
|
an error if the expression calls any functions.
|
||||||
|
|
||||||
### Cleanup functions
|
### Cleanup functions
|
||||||
|
|
||||||
If a provider creates a value that needs to be cleaned up (e.g. closing a file),
|
If a provider creates a value that needs to be cleaned up (e.g. closing a file),
|
||||||
|
|||||||
@@ -132,6 +132,8 @@ func show(pkgs ...string) error {
|
|||||||
switch v := v.(type) {
|
switch v := v.(type) {
|
||||||
case *goose.Provider:
|
case *goose.Provider:
|
||||||
out[types.TypeString(t, nil)] = v.Pos
|
out[types.TypeString(t, nil)] = v.Pos
|
||||||
|
case *goose.Value:
|
||||||
|
out[types.TypeString(t, nil)] = v.Pos
|
||||||
case *goose.IfaceBinding:
|
case *goose.IfaceBinding:
|
||||||
out[types.TypeString(t, nil)] = v.Pos
|
out[types.TypeString(t, nil)] = v.Pos
|
||||||
default:
|
default:
|
||||||
@@ -150,7 +152,7 @@ func show(pkgs ...string) error {
|
|||||||
type outGroup struct {
|
type outGroup struct {
|
||||||
name string
|
name string
|
||||||
inputs *typeutil.Map // values are not important
|
inputs *typeutil.Map // values are not important
|
||||||
outputs *typeutil.Map // values are either *goose.Provider or *goose.IfaceBinding
|
outputs *typeutil.Map // values are *goose.Provider, *goose.Value, or *goose.IfaceBinding
|
||||||
}
|
}
|
||||||
|
|
||||||
// gather flattens a provider set into outputs grouped by the inputs
|
// gather flattens a provider set into outputs grouped by the inputs
|
||||||
@@ -180,6 +182,9 @@ func gather(info *goose.Info, key goose.ProviderSetID) (_ []outGroup, imports ma
|
|||||||
for _, b := range curr.Bindings {
|
for _, b := range curr.Bindings {
|
||||||
pm.Set(b.Iface, b)
|
pm.Set(b.Iface, b)
|
||||||
}
|
}
|
||||||
|
for _, v := range curr.Values {
|
||||||
|
pm.Set(v.Out, v)
|
||||||
|
}
|
||||||
for _, imp := range curr.Imports {
|
for _, imp := range curr.Imports {
|
||||||
next = append(next, imp)
|
next = append(next, imp)
|
||||||
}
|
}
|
||||||
@@ -253,6 +258,24 @@ func gather(info *goose.Info, key goose.ProviderSetID) (_ []outGroup, imports ma
|
|||||||
inputs: in,
|
inputs: in,
|
||||||
outputs: out,
|
outputs: out,
|
||||||
})
|
})
|
||||||
|
case *goose.Value:
|
||||||
|
for i := range groups {
|
||||||
|
if groups[i].inputs.Len() == 0 {
|
||||||
|
groups[i].outputs.Set(p.Out, p)
|
||||||
|
inputVisited.Set(p.Out, i)
|
||||||
|
continue dfs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
in := new(typeutil.Map)
|
||||||
|
in.SetHasher(hash)
|
||||||
|
out := new(typeutil.Map)
|
||||||
|
out.SetHasher(hash)
|
||||||
|
out.Set(p.Out, p)
|
||||||
|
inputVisited.Set(p.Out, len(groups))
|
||||||
|
groups = append(groups, outGroup{
|
||||||
|
inputs: in,
|
||||||
|
outputs: out,
|
||||||
|
})
|
||||||
case *goose.IfaceBinding:
|
case *goose.IfaceBinding:
|
||||||
i, ok := inputVisited.At(p.Provided).(int)
|
i, ok := inputVisited.At(p.Provided).(int)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|||||||
12
goose.go
12
goose.go
@@ -50,3 +50,15 @@ type Binding struct{}
|
|||||||
func Bind(iface, to interface{}) Binding {
|
func Bind(iface, to interface{}) Binding {
|
||||||
return Binding{}
|
return Binding{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A ProvidedValue is an expression that is copied to the generated injector.
|
||||||
|
type ProvidedValue struct{}
|
||||||
|
|
||||||
|
// Value binds an expression to provide the type of the expression.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// var MySet = goose.NewSet(goose.Value([]string(nil)))
|
||||||
|
func Value(interface{}) ProvidedValue {
|
||||||
|
return ProvidedValue{}
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,17 +16,34 @@ package goose
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"go/ast"
|
||||||
"go/token"
|
"go/token"
|
||||||
"go/types"
|
"go/types"
|
||||||
|
|
||||||
"golang.org/x/tools/go/types/typeutil"
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type callKind int
|
||||||
|
|
||||||
|
const (
|
||||||
|
funcProviderCall callKind = iota
|
||||||
|
structProvider
|
||||||
|
valueExpr
|
||||||
|
)
|
||||||
|
|
||||||
// A call represents a step of an injector function. It may be either a
|
// A call represents a step of an injector function. It may be either a
|
||||||
// function call or a composite struct literal, depending on the value
|
// function call or a composite struct literal, depending on the value
|
||||||
// of isStruct.
|
// of kind.
|
||||||
type call struct {
|
type call struct {
|
||||||
// importPath and name identify the provider to call.
|
// kind indicates the code pattern to use.
|
||||||
|
kind callKind
|
||||||
|
|
||||||
|
// out is the type this step produces.
|
||||||
|
out types.Type
|
||||||
|
|
||||||
|
// importPath and name identify the provider to call for kind ==
|
||||||
|
// funcProviderCall or the type to construct for kind ==
|
||||||
|
// structProvider.
|
||||||
importPath string
|
importPath string
|
||||||
name string
|
name string
|
||||||
|
|
||||||
@@ -34,24 +51,29 @@ type call struct {
|
|||||||
// a) one of the givens (args[i] < len(given)),
|
// a) one of the givens (args[i] < len(given)),
|
||||||
// b) the result of a previous provider call (args[i] >= len(given)), or
|
// b) the result of a previous provider call (args[i] >= len(given)), or
|
||||||
// c) the zero value for the type (args[i] == -1).
|
// c) the zero value for the type (args[i] == -1).
|
||||||
|
//
|
||||||
|
// This will be nil for kind == valueExpr.
|
||||||
args []int
|
args []int
|
||||||
|
|
||||||
// isStruct indicates whether this should generate a struct composite
|
|
||||||
// literal instead of a function call.
|
|
||||||
isStruct bool
|
|
||||||
|
|
||||||
// fieldNames maps the arguments to struct field names.
|
// fieldNames maps the arguments to struct field names.
|
||||||
// This will only be set if isStruct is true.
|
// This will only be set if kind == structProvider.
|
||||||
fieldNames []string
|
fieldNames []string
|
||||||
|
|
||||||
// ins is the list of types this call receives as arguments.
|
// ins is the list of types this call receives as arguments.
|
||||||
|
// This will be nil for kind == valueExpr.
|
||||||
ins []types.Type
|
ins []types.Type
|
||||||
// out is the type produced by this provider call.
|
|
||||||
out types.Type
|
// The following are only set for kind == funcProviderCall:
|
||||||
|
|
||||||
// hasCleanup is true if the provider call returns a cleanup function.
|
// hasCleanup is true if the provider call returns a cleanup function.
|
||||||
hasCleanup bool
|
hasCleanup bool
|
||||||
// hasErr is true if the provider call returns an error.
|
// hasErr is true if the provider call returns an error.
|
||||||
hasErr bool
|
hasErr bool
|
||||||
|
|
||||||
|
// The following are only set for kind == valueExpr:
|
||||||
|
|
||||||
|
valueExpr ast.Expr
|
||||||
|
valueTypeInfo *types.Info
|
||||||
}
|
}
|
||||||
|
|
||||||
// solve finds the sequence of calls required to produce an output type
|
// solve finds the sequence of calls required to produce an output type
|
||||||
@@ -97,50 +119,69 @@ func solve(fset *token.FileSet, out types.Type, given []types.Type, set *Provide
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p, _ := providers.At(typ).(*Provider)
|
switch p := providers.At(typ).(type) {
|
||||||
if p == nil {
|
case nil:
|
||||||
if len(trail) == 1 {
|
if len(trail) == 1 {
|
||||||
return fmt.Errorf("no provider found for %s (output of injector)", types.TypeString(typ, nil))
|
return fmt.Errorf("no provider found for %s (output of injector)", types.TypeString(typ, nil))
|
||||||
}
|
}
|
||||||
// TODO(light): Give name of provider.
|
// TODO(light): Give name of provider.
|
||||||
return fmt.Errorf("no provider found for %s (required by provider of %s)", types.TypeString(typ, nil), types.TypeString(trail[len(trail)-2].Type, nil))
|
return fmt.Errorf("no provider found for %s (required by provider of %s)", types.TypeString(typ, nil), types.TypeString(trail[len(trail)-2].Type, nil))
|
||||||
}
|
case *Provider:
|
||||||
if !types.Identical(p.Out, typ) {
|
if !types.Identical(p.Out, typ) {
|
||||||
// Interface binding. Don't create a call ourselves.
|
// Interface binding. Don't create a call ourselves.
|
||||||
if err := visit(append(trail, ProviderInput{Type: p.Out})); err != nil {
|
if err := visit(append(trail, ProviderInput{Type: p.Out})); err != nil {
|
||||||
return err
|
return err
|
||||||
|
}
|
||||||
|
index.Set(typ, index.At(p.Out))
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
index.Set(typ, index.At(p.Out))
|
for _, a := range p.Args {
|
||||||
return nil
|
// TODO(light): This will discard grown trail arrays.
|
||||||
}
|
if err := visit(append(trail, a)); err != nil {
|
||||||
for _, a := range p.Args {
|
return err
|
||||||
// TODO(light): This will discard grown trail arrays.
|
}
|
||||||
if err := visit(append(trail, a)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
}
|
args := make([]int, len(p.Args))
|
||||||
args := make([]int, len(p.Args))
|
ins := make([]types.Type, len(p.Args))
|
||||||
ins := make([]types.Type, len(p.Args))
|
for i := range p.Args {
|
||||||
for i := range p.Args {
|
ins[i] = p.Args[i].Type
|
||||||
ins[i] = p.Args[i].Type
|
args[i] = index.At(p.Args[i].Type).(int)
|
||||||
if x := index.At(p.Args[i].Type); x != nil {
|
|
||||||
args[i] = x.(int)
|
|
||||||
} else {
|
|
||||||
args[i] = -1
|
|
||||||
}
|
}
|
||||||
|
index.Set(typ, len(given)+len(calls))
|
||||||
|
kind := funcProviderCall
|
||||||
|
if p.IsStruct {
|
||||||
|
kind = structProvider
|
||||||
|
}
|
||||||
|
calls = append(calls, call{
|
||||||
|
kind: kind,
|
||||||
|
importPath: p.ImportPath,
|
||||||
|
name: p.Name,
|
||||||
|
args: args,
|
||||||
|
fieldNames: p.Fields,
|
||||||
|
ins: ins,
|
||||||
|
out: typ,
|
||||||
|
hasCleanup: p.HasCleanup,
|
||||||
|
hasErr: p.HasErr,
|
||||||
|
})
|
||||||
|
case *Value:
|
||||||
|
if !types.Identical(p.Out, typ) {
|
||||||
|
// Interface binding. Don't create a call ourselves.
|
||||||
|
if err := visit(append(trail, ProviderInput{Type: p.Out})); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
index.Set(typ, index.At(p.Out))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
index.Set(typ, len(given)+len(calls))
|
||||||
|
calls = append(calls, call{
|
||||||
|
kind: valueExpr,
|
||||||
|
out: typ,
|
||||||
|
valueExpr: p.expr,
|
||||||
|
valueTypeInfo: p.info,
|
||||||
|
})
|
||||||
|
default:
|
||||||
|
panic("unknown provider map value type")
|
||||||
}
|
}
|
||||||
index.Set(typ, len(given)+len(calls))
|
|
||||||
calls = append(calls, call{
|
|
||||||
importPath: p.ImportPath,
|
|
||||||
name: p.Name,
|
|
||||||
args: args,
|
|
||||||
isStruct: p.IsStruct,
|
|
||||||
fieldNames: p.Fields,
|
|
||||||
ins: ins,
|
|
||||||
out: typ,
|
|
||||||
hasCleanup: p.HasCleanup,
|
|
||||||
hasErr: p.HasErr,
|
|
||||||
})
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if err := visit([]ProviderInput{{Type: out}}); err != nil {
|
if err := visit([]ProviderInput{{Type: out}}); err != nil {
|
||||||
@@ -155,7 +196,7 @@ func buildProviderMap(fset *token.FileSet, set *ProviderSet) (*typeutil.Map, err
|
|||||||
set *ProviderSet
|
set *ProviderSet
|
||||||
}
|
}
|
||||||
|
|
||||||
providerMap := new(typeutil.Map) // to *Provider
|
providerMap := new(typeutil.Map) // to *Provider or *Value
|
||||||
setMap := new(typeutil.Map) // to *ProviderSet, for error messages
|
setMap := new(typeutil.Map) // to *ProviderSet, for error messages
|
||||||
var bindings []binding
|
var bindings []binding
|
||||||
visited := make(map[*ProviderSet]struct{})
|
visited := make(map[*ProviderSet]struct{})
|
||||||
@@ -175,6 +216,13 @@ func buildProviderMap(fset *token.FileSet, set *ProviderSet) (*typeutil.Map, err
|
|||||||
providerMap.Set(p.Out, p)
|
providerMap.Set(p.Out, p)
|
||||||
setMap.Set(p.Out, curr)
|
setMap.Set(p.Out, curr)
|
||||||
}
|
}
|
||||||
|
for _, v := range curr.Values {
|
||||||
|
if providerMap.At(v.Out) != nil {
|
||||||
|
return nil, bindingConflictError(fset, v.Pos, v.Out, setMap.At(v.Out).(*ProviderSet))
|
||||||
|
}
|
||||||
|
providerMap.Set(v.Out, v)
|
||||||
|
setMap.Set(v.Out, curr)
|
||||||
|
}
|
||||||
for _, b := range curr.Bindings {
|
for _, b := range curr.Bindings {
|
||||||
bindings = append(bindings, binding{
|
bindings = append(bindings, binding{
|
||||||
IfaceBinding: b,
|
IfaceBinding: b,
|
||||||
|
|||||||
@@ -244,15 +244,24 @@ func (g *gen) inject(fset *token.FileSet, name string, sig *types.Signature, set
|
|||||||
paramTypes[i] = types.TypeString(params.At(i).Type(), g.qualifyPkg)
|
paramTypes[i] = types.TypeString(params.At(i).Type(), g.qualifyPkg)
|
||||||
}
|
}
|
||||||
for _, c := range calls {
|
for _, c := range calls {
|
||||||
g.qualifyImport(c.importPath)
|
switch c.kind {
|
||||||
if !c.isStruct {
|
case funcProviderCall:
|
||||||
// Struct providers just omit zero-valued fields.
|
g.qualifyImport(c.importPath)
|
||||||
continue
|
for i := range c.args {
|
||||||
}
|
if c.args[i] == -1 {
|
||||||
for i := range c.args {
|
zeroValue(c.ins[i], g.qualifyPkg)
|
||||||
if c.args[i] == -1 {
|
}
|
||||||
zeroValue(c.ins[i], g.qualifyPkg)
|
|
||||||
}
|
}
|
||||||
|
case structProvider:
|
||||||
|
g.qualifyImport(c.importPath)
|
||||||
|
case valueExpr:
|
||||||
|
if err := accessibleFrom(c.valueTypeInfo, c.valueExpr, g.currPackage); err != nil {
|
||||||
|
// TODO(light): Display line number of value expression.
|
||||||
|
ts := types.TypeString(c.out, nil)
|
||||||
|
return fmt.Errorf("inject %s: value %s can't be used: %v", name, ts, err)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic("unknown kind")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
outTypeString := types.TypeString(outType, g.qualifyPkg)
|
outTypeString := types.TypeString(outType, g.qualifyPkg)
|
||||||
@@ -326,7 +335,8 @@ func (g *gen) inject(fset *token.FileSet, name string, sig *types.Signature, set
|
|||||||
g.p(", %s", errVar)
|
g.p(", %s", errVar)
|
||||||
}
|
}
|
||||||
g.p(" := ")
|
g.p(" := ")
|
||||||
if c.isStruct {
|
switch c.kind {
|
||||||
|
case structProvider:
|
||||||
if _, ok := c.out.(*types.Pointer); ok {
|
if _, ok := c.out.(*types.Pointer); ok {
|
||||||
g.p("&")
|
g.p("&")
|
||||||
}
|
}
|
||||||
@@ -345,7 +355,7 @@ func (g *gen) inject(fset *token.FileSet, name string, sig *types.Signature, set
|
|||||||
g.p(",\n")
|
g.p(",\n")
|
||||||
}
|
}
|
||||||
g.p("\t}\n")
|
g.p("\t}\n")
|
||||||
} else {
|
case funcProviderCall:
|
||||||
g.p("%s(", g.qualifiedID(c.importPath, c.name))
|
g.p("%s(", g.qualifiedID(c.importPath, c.name))
|
||||||
for j, a := range c.args {
|
for j, a := range c.args {
|
||||||
if j > 0 {
|
if j > 0 {
|
||||||
@@ -360,6 +370,11 @@ func (g *gen) inject(fset *token.FileSet, name string, sig *types.Signature, set
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
g.p(")\n")
|
g.p(")\n")
|
||||||
|
case valueExpr:
|
||||||
|
g.writeAST(fset, c.valueTypeInfo, c.valueExpr)
|
||||||
|
g.p("\n")
|
||||||
|
default:
|
||||||
|
panic("unknown kind")
|
||||||
}
|
}
|
||||||
if c.hasErr {
|
if c.hasErr {
|
||||||
g.p("\tif %s != nil {\n", errVar)
|
g.p("\tif %s != nil {\n", errVar)
|
||||||
@@ -656,6 +671,32 @@ func disambiguate(name string, collides func(string) bool) string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// accessibleFrom reports whether node can be copied to wantPkg without
|
||||||
|
// violating Go visibility rules.
|
||||||
|
func accessibleFrom(info *types.Info, node ast.Node, wantPkg string) error {
|
||||||
|
var unexportError error
|
||||||
|
ast.Inspect(node, func(node ast.Node) bool {
|
||||||
|
if unexportError != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
ident, ok := node.(*ast.Ident)
|
||||||
|
if !ok {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
obj := info.ObjectOf(ident)
|
||||||
|
if _, ok := obj.(*types.PkgName); ok {
|
||||||
|
// Local package names are fine, since we can just reimport them.
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if pkg := obj.Pkg(); pkg != nil && !ast.IsExported(ident.Name) && pkg.Path() != wantPkg {
|
||||||
|
unexportError = fmt.Errorf("uses unexported identifier %s", obj.Name())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return unexportError
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
errorType = types.Universe.Lookup("error").Type()
|
errorType = types.Universe.Lookup("error").Type()
|
||||||
cleanupType = types.NewSignature(nil, nil, nil, false)
|
cleanupType = types.NewSignature(nil, nil, nil, false)
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ type ProviderSet struct {
|
|||||||
|
|
||||||
Providers []*Provider
|
Providers []*Provider
|
||||||
Bindings []*IfaceBinding
|
Bindings []*IfaceBinding
|
||||||
|
Values []*Value
|
||||||
Imports []*ProviderSet
|
Imports []*ProviderSet
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,6 +101,21 @@ type ProviderInput struct {
|
|||||||
// TODO(light): Move field name into this struct.
|
// TODO(light): Move field name into this struct.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Value describes a value expression.
|
||||||
|
type Value struct {
|
||||||
|
// Pos is the source position of the expression defining this value.
|
||||||
|
Pos token.Pos
|
||||||
|
|
||||||
|
// Out is the type this value produces.
|
||||||
|
Out types.Type
|
||||||
|
|
||||||
|
// expr is the expression passed to goose.Value.
|
||||||
|
expr ast.Expr
|
||||||
|
|
||||||
|
// info is the type info for the expression.
|
||||||
|
info *types.Info
|
||||||
|
}
|
||||||
|
|
||||||
// Load finds all the provider sets in the given packages, as well as
|
// Load finds all the provider sets in the given packages, as well as
|
||||||
// the provider sets' transitive dependencies.
|
// the provider sets' transitive dependencies.
|
||||||
func Load(bctx *build.Context, wd string, pkgs []string) (*Info, error) {
|
func Load(bctx *build.Context, wd string, pkgs []string) (*Info, error) {
|
||||||
@@ -163,7 +179,7 @@ func (id ProviderSetID) String() string {
|
|||||||
// objectCache is a lazily evaluated mapping of objects to goose structures.
|
// objectCache is a lazily evaluated mapping of objects to goose structures.
|
||||||
type objectCache struct {
|
type objectCache struct {
|
||||||
prog *loader.Program
|
prog *loader.Program
|
||||||
objects map[objRef]interface{} // *Provider or *ProviderSet
|
objects map[objRef]interface{} // *Provider, *ProviderSet, *IfaceBinding, or *Value
|
||||||
}
|
}
|
||||||
|
|
||||||
type objRef struct {
|
type objRef struct {
|
||||||
@@ -179,7 +195,8 @@ func newObjectCache(prog *loader.Program) *objectCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get converts a Go object into a goose structure. It may return a
|
// get converts a Go object into a goose structure. It may return a
|
||||||
// *Provider, a structProviderPair, an *IfaceBinding, or a *ProviderSet.
|
// *Provider, a structProviderPair, an *IfaceBinding, a *ProviderSet,
|
||||||
|
// or a *Value.
|
||||||
func (oc *objectCache) get(obj types.Object) (interface{}, error) {
|
func (oc *objectCache) get(obj types.Object) (interface{}, error) {
|
||||||
ref := objRef{
|
ref := objRef{
|
||||||
importPath: obj.Pkg().Path(),
|
importPath: obj.Pkg().Path(),
|
||||||
@@ -239,8 +256,8 @@ func (oc *objectCache) varDecl(obj *types.Var) *ast.ValueSpec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// processExpr converts an expression into a goose structure. It may
|
// processExpr converts an expression into a goose structure. It may
|
||||||
// return a *Provider, a structProviderPair, an *IfaceBinding, or a
|
// return a *Provider, a structProviderPair, an *IfaceBinding, a
|
||||||
// *ProviderSet.
|
// *ProviderSet, or a *Value.
|
||||||
func (oc *objectCache) processExpr(pkg *loader.PackageInfo, expr ast.Expr) (interface{}, error) {
|
func (oc *objectCache) processExpr(pkg *loader.PackageInfo, expr ast.Expr) (interface{}, error) {
|
||||||
exprPos := oc.prog.Fset.Position(expr.Pos())
|
exprPos := oc.prog.Fset.Position(expr.Pos())
|
||||||
expr = astutil.Unparen(expr)
|
expr = astutil.Unparen(expr)
|
||||||
@@ -269,6 +286,12 @@ func (oc *objectCache) processExpr(pkg *loader.PackageInfo, expr ast.Expr) (inte
|
|||||||
return nil, fmt.Errorf("%v: %v", exprPos, err)
|
return nil, fmt.Errorf("%v: %v", exprPos, err)
|
||||||
}
|
}
|
||||||
return b, nil
|
return b, nil
|
||||||
|
case "Value":
|
||||||
|
v, err := processValue(oc.prog.Fset, &pkg.Info, call)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("%v: %v", exprPos, err)
|
||||||
|
}
|
||||||
|
return v, nil
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("%v: unknown pattern", exprPos)
|
return nil, fmt.Errorf("%v: unknown pattern", exprPos)
|
||||||
}
|
}
|
||||||
@@ -312,6 +335,8 @@ func (oc *objectCache) processNewSet(pkg *loader.PackageInfo, call *ast.CallExpr
|
|||||||
pset.Bindings = append(pset.Bindings, item)
|
pset.Bindings = append(pset.Bindings, item)
|
||||||
case structProviderPair:
|
case structProviderPair:
|
||||||
pset.Providers = append(pset.Providers, item.provider, item.ptrProvider)
|
pset.Providers = append(pset.Providers, item.provider, item.ptrProvider)
|
||||||
|
case *Value:
|
||||||
|
pset.Values = append(pset.Values, item)
|
||||||
default:
|
default:
|
||||||
panic("unknown item type")
|
panic("unknown item type")
|
||||||
}
|
}
|
||||||
@@ -471,6 +496,48 @@ func processBind(fset *token.FileSet, info *types.Info, call *ast.CallExpr) (*If
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// processValue creates a value from a goose.Value call.
|
||||||
|
func processValue(fset *token.FileSet, info *types.Info, call *ast.CallExpr) (*Value, error) {
|
||||||
|
// Assumes that call.Fun is goose.Value.
|
||||||
|
|
||||||
|
if len(call.Args) != 1 {
|
||||||
|
return nil, fmt.Errorf("%v: call to Value takes exactly one argument", fset.Position(call.Pos()))
|
||||||
|
}
|
||||||
|
ok := true
|
||||||
|
ast.Inspect(call.Args[0], func(node ast.Node) bool {
|
||||||
|
switch node.(type) {
|
||||||
|
case nil, *ast.ArrayType, *ast.BasicLit, *ast.BinaryExpr, *ast.ChanType, *ast.CompositeLit, *ast.FuncType, *ast.Ident, *ast.IndexExpr, *ast.InterfaceType, *ast.KeyValueExpr, *ast.MapType, *ast.ParenExpr, *ast.SelectorExpr, *ast.SliceExpr, *ast.StarExpr, *ast.StructType, *ast.TypeAssertExpr:
|
||||||
|
// Good!
|
||||||
|
case *ast.UnaryExpr:
|
||||||
|
expr := node.(*ast.UnaryExpr)
|
||||||
|
if expr.Op == token.ARROW {
|
||||||
|
ok = false
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case *ast.CallExpr:
|
||||||
|
// Only acceptable if it's a type conversion.
|
||||||
|
call := node.(*ast.CallExpr)
|
||||||
|
if _, isFunc := info.TypeOf(call.Fun).(*types.Signature); isFunc {
|
||||||
|
ok = false
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
ok = false
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("%v: argument to Value is too complex", fset.Position(call.Pos()))
|
||||||
|
}
|
||||||
|
return &Value{
|
||||||
|
Pos: call.Args[0].Pos(),
|
||||||
|
Out: info.TypeOf(call.Args[0]),
|
||||||
|
expr: call.Args[0],
|
||||||
|
info: info,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// isInjector checks whether a given function declaration is an
|
// isInjector checks whether a given function declaration is an
|
||||||
// injector template, returning the goose.Use call. It returns nil if
|
// injector template, returning the goose.Use call. It returns nil if
|
||||||
// the function is not an injector template.
|
// the function is not an injector template.
|
||||||
|
|||||||
21
internal/goose/testdata/ExportedValue/bar/bar.go
vendored
Normal file
21
internal/goose/testdata/ExportedValue/bar/bar.go
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
// Copyright 2018 Google LLC
|
||||||
|
//
|
||||||
|
// 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 bar
|
||||||
|
|
||||||
|
import "github.com/google/go-cloud/goose"
|
||||||
|
|
||||||
|
var Value = goose.Value(PublicMsg)
|
||||||
|
|
||||||
|
var PublicMsg = "Hello, World!"
|
||||||
21
internal/goose/testdata/ExportedValue/foo/foo.go
vendored
Normal file
21
internal/goose/testdata/ExportedValue/foo/foo.go
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
// Copyright 2018 Google LLC
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println(injectedMessage())
|
||||||
|
}
|
||||||
26
internal/goose/testdata/ExportedValue/foo/goose.go
vendored
Normal file
26
internal/goose/testdata/ExportedValue/foo/goose.go
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
// Copyright 2018 Google LLC
|
||||||
|
//
|
||||||
|
// 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 gooseinject
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bar"
|
||||||
|
"github.com/google/go-cloud/goose"
|
||||||
|
)
|
||||||
|
|
||||||
|
func injectedMessage() string {
|
||||||
|
panic(goose.Use(bar.Value))
|
||||||
|
}
|
||||||
1
internal/goose/testdata/ExportedValue/out.txt
vendored
Normal file
1
internal/goose/testdata/ExportedValue/out.txt
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Hello, World!
|
||||||
1
internal/goose/testdata/ExportedValue/pkg
vendored
Normal file
1
internal/goose/testdata/ExportedValue/pkg
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
foo
|
||||||
23
internal/goose/testdata/ExportedValueDifferentPackage/bar/bar.go
vendored
Normal file
23
internal/goose/testdata/ExportedValueDifferentPackage/bar/bar.go
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// Copyright 2018 Google LLC
|
||||||
|
//
|
||||||
|
// 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 bar
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/google/go-cloud/goose"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Value = goose.Value(os.Stdout)
|
||||||
21
internal/goose/testdata/ExportedValueDifferentPackage/foo/foo.go
vendored
Normal file
21
internal/goose/testdata/ExportedValueDifferentPackage/foo/foo.go
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
// Copyright 2018 Google LLC
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Fprintln(injectedFile(), "Hello, World!")
|
||||||
|
}
|
||||||
28
internal/goose/testdata/ExportedValueDifferentPackage/foo/goose.go
vendored
Normal file
28
internal/goose/testdata/ExportedValueDifferentPackage/foo/goose.go
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
// Copyright 2018 Google LLC
|
||||||
|
//
|
||||||
|
// 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 gooseinject
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"bar"
|
||||||
|
"github.com/google/go-cloud/goose"
|
||||||
|
)
|
||||||
|
|
||||||
|
func injectedFile() *os.File {
|
||||||
|
panic(goose.Use(bar.Value))
|
||||||
|
}
|
||||||
1
internal/goose/testdata/ExportedValueDifferentPackage/out.txt
vendored
Normal file
1
internal/goose/testdata/ExportedValueDifferentPackage/out.txt
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Hello, World!
|
||||||
1
internal/goose/testdata/ExportedValueDifferentPackage/pkg
vendored
Normal file
1
internal/goose/testdata/ExportedValueDifferentPackage/pkg
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
foo
|
||||||
21
internal/goose/testdata/NiladicValue/foo/foo.go
vendored
Normal file
21
internal/goose/testdata/NiladicValue/foo/foo.go
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
// Copyright 2018 Google LLC
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println(injectedMessage())
|
||||||
|
}
|
||||||
25
internal/goose/testdata/NiladicValue/foo/goose.go
vendored
Normal file
25
internal/goose/testdata/NiladicValue/foo/goose.go
vendored
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// Copyright 2018 Google LLC
|
||||||
|
//
|
||||||
|
// 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 gooseinject
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/google/go-cloud/goose"
|
||||||
|
)
|
||||||
|
|
||||||
|
func injectedMessage() string {
|
||||||
|
panic(goose.Use(goose.Value("Hello, World!")))
|
||||||
|
}
|
||||||
1
internal/goose/testdata/NiladicValue/out.txt
vendored
Normal file
1
internal/goose/testdata/NiladicValue/out.txt
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Hello, World!
|
||||||
1
internal/goose/testdata/NiladicValue/pkg
vendored
Normal file
1
internal/goose/testdata/NiladicValue/pkg
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
foo
|
||||||
21
internal/goose/testdata/UnexportedValue/bar/bar.go
vendored
Normal file
21
internal/goose/testdata/UnexportedValue/bar/bar.go
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
// Copyright 2018 Google LLC
|
||||||
|
//
|
||||||
|
// 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 bar
|
||||||
|
|
||||||
|
import "github.com/google/go-cloud/goose"
|
||||||
|
|
||||||
|
var Value = goose.Value(privateMsg)
|
||||||
|
|
||||||
|
var privateMsg = "Hello, World!"
|
||||||
21
internal/goose/testdata/UnexportedValue/foo/foo.go
vendored
Normal file
21
internal/goose/testdata/UnexportedValue/foo/foo.go
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
// Copyright 2018 Google LLC
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println(injectedMessage())
|
||||||
|
}
|
||||||
26
internal/goose/testdata/UnexportedValue/foo/goose.go
vendored
Normal file
26
internal/goose/testdata/UnexportedValue/foo/goose.go
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
// Copyright 2018 Google LLC
|
||||||
|
//
|
||||||
|
// 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 gooseinject
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bar"
|
||||||
|
"github.com/google/go-cloud/goose"
|
||||||
|
)
|
||||||
|
|
||||||
|
func injectedMessage() string {
|
||||||
|
panic(goose.Use(bar.Value))
|
||||||
|
}
|
||||||
1
internal/goose/testdata/UnexportedValue/out.txt
vendored
Normal file
1
internal/goose/testdata/UnexportedValue/out.txt
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ERROR
|
||||||
1
internal/goose/testdata/UnexportedValue/pkg
vendored
Normal file
1
internal/goose/testdata/UnexportedValue/pkg
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
foo
|
||||||
36
internal/goose/testdata/ValueChain/foo/foo.go
vendored
Normal file
36
internal/goose/testdata/ValueChain/foo/foo.go
vendored
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
// Copyright 2018 Google LLC
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/google/go-cloud/goose"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println(injectFooBar())
|
||||||
|
}
|
||||||
|
|
||||||
|
type Foo int
|
||||||
|
type FooBar int
|
||||||
|
|
||||||
|
var Set = goose.NewSet(
|
||||||
|
goose.Value(Foo(41)),
|
||||||
|
provideFooBar)
|
||||||
|
|
||||||
|
func provideFooBar(foo Foo) FooBar {
|
||||||
|
return FooBar(foo) + 1
|
||||||
|
}
|
||||||
25
internal/goose/testdata/ValueChain/foo/goose.go
vendored
Normal file
25
internal/goose/testdata/ValueChain/foo/goose.go
vendored
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// Copyright 2018 Google LLC
|
||||||
|
//
|
||||||
|
// 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 gooseinject
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/google/go-cloud/goose"
|
||||||
|
)
|
||||||
|
|
||||||
|
func injectFooBar() FooBar {
|
||||||
|
panic(goose.Use(Set))
|
||||||
|
}
|
||||||
1
internal/goose/testdata/ValueChain/out.txt
vendored
Normal file
1
internal/goose/testdata/ValueChain/out.txt
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
42
|
||||||
1
internal/goose/testdata/ValueChain/pkg
vendored
Normal file
1
internal/goose/testdata/ValueChain/pkg
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
foo
|
||||||
23
internal/goose/testdata/ValueConversion/foo/foo.go
vendored
Normal file
23
internal/goose/testdata/ValueConversion/foo/foo.go
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// Copyright 2018 Google LLC
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println(injectedMessage())
|
||||||
|
}
|
||||||
|
|
||||||
|
type Foo string
|
||||||
25
internal/goose/testdata/ValueConversion/foo/goose.go
vendored
Normal file
25
internal/goose/testdata/ValueConversion/foo/goose.go
vendored
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// Copyright 2018 Google LLC
|
||||||
|
//
|
||||||
|
// 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 gooseinject
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/google/go-cloud/goose"
|
||||||
|
)
|
||||||
|
|
||||||
|
func injectedMessage() Foo {
|
||||||
|
panic(goose.Use(goose.Value(Foo("Hello, World!"))))
|
||||||
|
}
|
||||||
1
internal/goose/testdata/ValueConversion/out.txt
vendored
Normal file
1
internal/goose/testdata/ValueConversion/out.txt
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Hello, World!
|
||||||
1
internal/goose/testdata/ValueConversion/pkg
vendored
Normal file
1
internal/goose/testdata/ValueConversion/pkg
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
foo
|
||||||
26
internal/goose/testdata/VarValue/foo/foo.go
vendored
Normal file
26
internal/goose/testdata/VarValue/foo/foo.go
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
// Copyright 2018 Google LLC
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Value should be deferred until function call.
|
||||||
|
msg = "Hello, World!"
|
||||||
|
|
||||||
|
fmt.Println(injectedMessage())
|
||||||
|
}
|
||||||
|
|
||||||
|
var msg string
|
||||||
25
internal/goose/testdata/VarValue/foo/goose.go
vendored
Normal file
25
internal/goose/testdata/VarValue/foo/goose.go
vendored
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// Copyright 2018 Google LLC
|
||||||
|
//
|
||||||
|
// 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 gooseinject
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/google/go-cloud/goose"
|
||||||
|
)
|
||||||
|
|
||||||
|
func injectedMessage() string {
|
||||||
|
panic(goose.Use(goose.Value(msg)))
|
||||||
|
}
|
||||||
1
internal/goose/testdata/VarValue/out.txt
vendored
Normal file
1
internal/goose/testdata/VarValue/out.txt
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Hello, World!
|
||||||
1
internal/goose/testdata/VarValue/pkg
vendored
Normal file
1
internal/goose/testdata/VarValue/pkg
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
foo
|
||||||
Reference in New Issue
Block a user