diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 5cf03dad4d7..ac1c125609a 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -453,7 +453,7 @@ }, { "ImportPath": "github.com/container-storage-interface/spec/lib/go/csi/v0", - "Comment": "v0.1.0-5-g7ab01a9", + "Comment": "v0.1.0-19-g31c1670", "Rev": "31c167062b1a62a9810e4fd94d7c986113b490b8" }, { diff --git a/vendor/BUILD b/vendor/BUILD index 9ec7fc747e1..e061c5f8837 100644 --- a/vendor/BUILD +++ b/vendor/BUILD @@ -63,7 +63,7 @@ filegroup( "//vendor/github.com/cockroachdb/cmux:all-srcs", "//vendor/github.com/codedellemc/goscaleio:all-srcs", "//vendor/github.com/codegangsta/negroni:all-srcs", - "//vendor/github.com/container-storage-interface/spec/lib/go/csi:all-srcs", + "//vendor/github.com/container-storage-interface/spec/lib/go/csi/v0:all-srcs", "//vendor/github.com/containerd/console:all-srcs", "//vendor/github.com/containerd/containerd/api/services/containers/v1:all-srcs", "//vendor/github.com/containerd/containerd/api/services/tasks/v1:all-srcs", diff --git a/vendor/github.com/container-storage-interface/spec/lib/go/csi/BUILD b/vendor/github.com/container-storage-interface/spec/lib/go/csi/BUILD deleted file mode 100644 index a9bc214479e..00000000000 --- a/vendor/github.com/container-storage-interface/spec/lib/go/csi/BUILD +++ /dev/null @@ -1,16 +0,0 @@ -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//vendor/github.com/container-storage-interface/spec/lib/go/csi/v0:all-srcs", - ], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/vendor/k8s.io/gengo/args/args.go b/vendor/k8s.io/gengo/args/args.go index ad9a83480db..2f8680d1e0f 100644 --- a/vendor/k8s.io/gengo/args/args.go +++ b/vendor/k8s.io/gengo/args/args.go @@ -23,6 +23,7 @@ import ( "fmt" "io/ioutil" "os" + "path" "path/filepath" "strconv" "strings" @@ -40,10 +41,11 @@ import ( // before calling AddFlags. func Default() *GeneratorArgs { return &GeneratorArgs{ - OutputBase: DefaultSourceTree(), - GoHeaderFilePath: filepath.Join(DefaultSourceTree(), "k8s.io/gengo/boilerplate/boilerplate.go.txt"), - GeneratedBuildTag: "ignore_autogenerated", - defaultCommandLineFlags: true, + OutputBase: DefaultSourceTree(), + GoHeaderFilePath: filepath.Join(DefaultSourceTree(), "k8s.io/gengo/boilerplate/boilerplate.go.txt"), + GeneratedBuildTag: "ignore_autogenerated", + GeneratedByCommentTemplate: "// Code generated by GENERATOR_NAME. DO NOT EDIT.", + defaultCommandLineFlags: true, } } @@ -64,6 +66,11 @@ type GeneratorArgs struct { // Where to get copyright header text. GoHeaderFilePath string + // If GeneratedByCommentTemplate is set, generate a "Code generated by" comment + // below the bloilerplate, of the format defined by this string. + // Any instances of "GENERATOR_NAME" will be replaced with the name of the code generator. + GeneratedByCommentTemplate string + // If true, only verify, don't write anything. VerifyOnly bool @@ -103,6 +110,16 @@ func (g *GeneratorArgs) LoadGoBoilerplate() ([]byte, error) { return nil, err } b = bytes.Replace(b, []byte("YEAR"), []byte(strconv.Itoa(time.Now().Year())), -1) + + if g.GeneratedByCommentTemplate != "" { + if len(b) != 0 { + b = append(b, byte('\n')) + } + generatorName := path.Base(os.Args[0]) + generatedByComment := strings.Replace(g.GeneratedByCommentTemplate, "GENERATOR_NAME", generatorName, -1) + s := fmt.Sprintf("%s\n\n", generatedByComment) + b = append(b, []byte(s)...) + } return b, nil } diff --git a/vendor/k8s.io/gengo/examples/deepcopy-gen/generators/deepcopy.go b/vendor/k8s.io/gengo/examples/deepcopy-gen/generators/deepcopy.go index b132e772a19..b4ad80d8afd 100644 --- a/vendor/k8s.io/gengo/examples/deepcopy-gen/generators/deepcopy.go +++ b/vendor/k8s.io/gengo/examples/deepcopy-gen/generators/deepcopy.go @@ -129,10 +129,6 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat inputs := sets.NewString(context.Inputs...) packages := generator.Packages{} header := append([]byte(fmt.Sprintf("// +build !%s\n\n", arguments.GeneratedBuildTag)), boilerplate...) - header = append(header, []byte(` - // This file was autogenerated by deepcopy-gen. Do not edit it manually! - - `)...) boundingDirs := []string{} if customArgs, ok := arguments.CustomArgs.(*CustomArgs); ok { @@ -286,27 +282,99 @@ func (g *genDeepCopy) copyableAndInBounds(t *types.Type) bool { return true } -// hasDeepCopyMethod returns true if an appropriate DeepCopy() method is -// defined for the given type. This allows more efficient deep copy +// deepCopyMethod returns the signature of a DeepCopy() method, nil or an error +// if the type does not match. This allows more efficient deep copy // implementations to be defined by the type's author. The correct signature // for a type T is: // func (t T) DeepCopy() T // or: -// func (t *T) DeepCopy() T -func hasDeepCopyMethod(t *types.Type) bool { - for mn, mt := range t.Methods { - if mn != "DeepCopy" { - continue - } - if len(mt.Signature.Parameters) != 0 { - return false - } - if len(mt.Signature.Results) != 1 || mt.Signature.Results[0].Name != t.Name { - return false - } - return true +// func (t *T) DeepCopy() *T +func deepCopyMethod(t *types.Type) (*types.Signature, error) { + f, found := t.Methods["DeepCopy"] + if !found { + return nil, nil } - return false + if len(f.Signature.Parameters) != 0 { + return nil, fmt.Errorf("type %v: invalid DeepCopy signature, expected no parameters", t) + } + if len(f.Signature.Results) != 1 { + return nil, fmt.Errorf("type %v: invalid DeepCopy signature, expected exactly one result", t) + } + + ptrResult := f.Signature.Results[0].Kind == types.Pointer && f.Signature.Results[0].Elem.Name == t.Name + nonPtrResult := f.Signature.Results[0].Name == t.Name + + if !ptrResult && !nonPtrResult { + return nil, fmt.Errorf("type %v: invalid DeepCopy signature, expected to return %s or *%s", t, t.Name.Name, t.Name.Name) + } + + ptrRcvr := f.Signature.Receiver != nil && f.Signature.Receiver.Kind == types.Pointer && f.Signature.Receiver.Elem.Name == t.Name + nonPtrRcvr := f.Signature.Receiver != nil && f.Signature.Receiver.Name == t.Name + + if ptrRcvr && !ptrResult { + return nil, fmt.Errorf("type %v: invalid DeepCopy signature, expected a *%s result for a *%s receiver", t, t.Name.Name, t.Name.Name) + } + if nonPtrRcvr && !nonPtrResult { + return nil, fmt.Errorf("type %v: invalid DeepCopy signature, expected a %s result for a %s receiver", t, t.Name.Name, t.Name.Name) + } + + return f.Signature, nil +} + +// deepCopyMethodOrDie returns the signatrue of a DeepCopy method, nil or calls glog.Fatalf +// if the type does not match. +func deepCopyMethodOrDie(t *types.Type) *types.Signature { + ret, err := deepCopyMethod(t) + if err != nil { + glog.Fatal(err) + } + return ret +} + +// deepCopyIntoMethod returns the signature of a DeepCopyInto() method, nil or an error +// if the type is wrong. DeepCopyInto allows more efficient deep copy +// implementations to be defined by the type's author. The correct signature +// for a type T is: +// func (t T) DeepCopyInto(t *T) +// or: +// func (t *T) DeepCopyInto(t *T) +func deepCopyIntoMethod(t *types.Type) (*types.Signature, error) { + f, found := t.Methods["DeepCopyInto"] + if !found { + return nil, nil + } + if len(f.Signature.Parameters) != 1 { + return nil, fmt.Errorf("type %v: invalid DeepCopy signature, expected exactly one parameter", t) + } + if len(f.Signature.Results) != 0 { + return nil, fmt.Errorf("type %v: invalid DeepCopy signature, expected no result type", t) + } + + ptrParam := f.Signature.Parameters[0].Kind == types.Pointer && f.Signature.Parameters[0].Elem.Name == t.Name + + if !ptrParam { + return nil, fmt.Errorf("type %v: invalid DeepCopy signature, expected parameter of type *%s", t, t.Name.Name) + } + + ptrRcvr := f.Signature.Receiver != nil && f.Signature.Receiver.Kind == types.Pointer && f.Signature.Receiver.Elem.Name == t.Name + nonPtrRcvr := f.Signature.Receiver != nil && f.Signature.Receiver.Name == t.Name + + if !ptrRcvr && !nonPtrRcvr { + // this should never happen + return nil, fmt.Errorf("type %v: invalid DeepCopy signature, expected a receiver of type %s or *%s", t, t.Name.Name, t.Name.Name) + } + + return f.Signature, nil +} + +// deepCopyIntoMethodOrDie returns the signature of a DeepCopyInto() method, nil or calls glog.Fatalf +// if the type is wrong. +func deepCopyIntoMethodOrDie(t *types.Type) *types.Signature { + ret, err := deepCopyIntoMethod(t) + if err != nil { + glog.Fatal(err) + } + return ret } func isRootedUnder(pkg string, roots []string) bool { @@ -327,17 +395,36 @@ func copyableType(t *types.Type) bool { if ttag != nil && ttag.value == "false" { return false } - // TODO: Consider generating functions for other kinds too. - if t.Kind != types.Struct { - return false - } - // Also, filter out private types. + + // Filter out private types. if namer.IsPrivateGoName(t.Name.Name) { return false } + + if t.Kind == types.Alias { + // if the underlying built-in is not deepcopy-able, deepcopy is opt-in through definition of custom methods. + // Note that aliases of builtins, maps, slices can have deepcopy methods. + if deepCopyMethodOrDie(t) != nil || deepCopyIntoMethodOrDie(t) != nil { + return true + } else { + return t.Underlying.Kind != types.Builtin || copyableType(t.Underlying) + } + } + + if t.Kind != types.Struct { + return false + } + return true } +func underlyingType(t *types.Type) *types.Type { + for t.Kind == types.Alias { + t = t.Underlying + } + return t +} + func (g *genDeepCopy) isOtherPackage(pkg string) bool { if pkg == g.targetPackage { return false @@ -426,7 +513,7 @@ func extractNonPointerInterfaces(comments []string) (bool, error) { return result, nil } -func (g *genDeepCopy) deepCopyableInterfaces(c *generator.Context, t *types.Type) ([]*types.Type, error) { +func (g *genDeepCopy) deepCopyableInterfacesInner(c *generator.Context, t *types.Type) ([]*types.Type, error) { if t.Kind != types.Struct { return nil, nil } @@ -451,9 +538,9 @@ func (g *genDeepCopy) deepCopyableInterfaces(c *generator.Context, t *types.Type return ts, nil } -// DeepCopyableInterfaces returns the interface types to implement and whether they apply to a non-pointer receiver. -func (g *genDeepCopy) DeepCopyableInterfaces(c *generator.Context, t *types.Type) ([]*types.Type, bool, error) { - ts, err := g.deepCopyableInterfaces(c, t) +// deepCopyableInterfaces returns the interface types to implement and whether they apply to a non-pointer receiver. +func (g *genDeepCopy) deepCopyableInterfaces(c *generator.Context, t *types.Type) ([]*types.Type, bool, error) { + ts, err := g.deepCopyableInterfacesInner(c, t) if err != nil { return nil, false, err } @@ -494,12 +581,15 @@ func (g *genDeepCopy) GenerateType(c *generator.Context, t *types.Type, w io.Wri sw := generator.NewSnippetWriter(w, c, "$", "$") args := argsFromType(t) - _, foundDeepCopyInto := t.Methods["DeepCopyInto"] - _, foundDeepCopy := t.Methods["DeepCopy"] - if !foundDeepCopyInto { + if deepCopyIntoMethodOrDie(t) == nil { sw.Do("// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\n", args) - sw.Do("func (in *$.type|raw$) DeepCopyInto(out *$.type|raw$) {\n", args) - if foundDeepCopy { + if isReference(t) { + sw.Do("func (in $.type|raw$) DeepCopyInto(out *$.type|raw$) {\n", args) + sw.Do("{in:=&in\n", nil) + } else { + sw.Do("func (in *$.type|raw$) DeepCopyInto(out *$.type|raw$) {\n", args) + } + if deepCopyMethodOrDie(t) != nil { if t.Methods["DeepCopy"].Signature.Receiver.Kind == types.Pointer { sw.Do("clone := in.DeepCopy()\n", nil) sw.Do("*out = *clone\n", nil) @@ -511,20 +601,31 @@ func (g *genDeepCopy) GenerateType(c *generator.Context, t *types.Type, w io.Wri g.generateFor(t, sw) sw.Do("return\n", nil) } + if isReference(t) { + sw.Do("}\n", nil) + } sw.Do("}\n\n", nil) } - if !foundDeepCopy { + if deepCopyMethodOrDie(t) == nil { sw.Do("// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new $.type|raw$.\n", args) - sw.Do("func (in *$.type|raw$) DeepCopy() *$.type|raw$ {\n", args) + if isReference(t) { + sw.Do("func (in $.type|raw$) DeepCopy() $.type|raw$ {\n", args) + } else { + sw.Do("func (in *$.type|raw$) DeepCopy() *$.type|raw$ {\n", args) + } sw.Do("if in == nil { return nil }\n", nil) sw.Do("out := new($.type|raw$)\n", args) sw.Do("in.DeepCopyInto(out)\n", nil) - sw.Do("return out\n", nil) + if isReference(t) { + sw.Do("return *out\n", nil) + } else { + sw.Do("return out\n", nil) + } sw.Do("}\n\n", nil) } - intfs, nonPointerReceiver, err := g.DeepCopyableInterfaces(c, t) + intfs, nonPointerReceiver, err := g.deepCopyableInterfaces(c, t) if err != nil { return err } @@ -538,21 +639,33 @@ func (g *genDeepCopy) GenerateType(c *generator.Context, t *types.Type, w io.Wri sw.Do(fmt.Sprintf("func (in *$.type|raw$) DeepCopy%s() $.type2|raw$ {\n", intf.Name.Name), argsFromType(t, intf)) sw.Do("if c := in.DeepCopy(); c != nil {\n", nil) sw.Do("return c\n", nil) - sw.Do("} else {\n", nil) + sw.Do("}\n", nil) sw.Do("return nil\n", nil) - sw.Do("}}\n\n", nil) + sw.Do("}\n\n", nil) } } return sw.Error() } +// isReference return true for pointer, maps, slices and aliases of those. +func isReference(t *types.Type) bool { + if t.Kind == types.Pointer || t.Kind == types.Map || t.Kind == types.Slice { + return true + } + return t.Kind == types.Alias && isReference(underlyingType(t)) +} + // we use the system of shadowing 'in' and 'out' so that the same code is valid // at any nesting level. This makes the autogenerator easy to understand, and // the compiler shouldn't care. func (g *genDeepCopy) generateFor(t *types.Type, sw *generator.SnippetWriter) { + // derive inner types if t is an alias. We call the do* methods below with the alias type. + // basic rule: generate according to inner type, but construct objects with the alias type. + ut := underlyingType(t) + var f func(*types.Type, *generator.SnippetWriter) - switch t.Kind { + switch ut.Kind { case types.Builtin: f = g.doBuiltin case types.Map: @@ -561,110 +674,147 @@ func (g *genDeepCopy) generateFor(t *types.Type, sw *generator.SnippetWriter) { f = g.doSlice case types.Struct: f = g.doStruct - case types.Interface: - f = g.doInterface case types.Pointer: f = g.doPointer + case types.Interface: + // interfaces are handled in-line in the other cases + glog.Fatalf("Hit an interface type %v. This should never happen.", t) case types.Alias: - f = g.doAlias + // can never happen because we branch on the underlying type which is never an alias + glog.Fatalf("Hit an alias type %v. This should never happen.", t) default: f = g.doUnknown } f(t, sw) } +// doBuiltin generates code for a builtin or an alias to a builtin. The generated code is +// is the same for both cases, i.e. it's the code for the underlying type. func (g *genDeepCopy) doBuiltin(t *types.Type, sw *generator.SnippetWriter) { + if deepCopyMethodOrDie(t) != nil || deepCopyIntoMethodOrDie(t) != nil { + sw.Do("*out = in.DeepCopy()\n", nil) + return + } + sw.Do("*out = *in\n", nil) } +// doMap generates code for a map or an alias to a map. The generated code is +// is the same for both cases, i.e. it's the code for the underlying type. func (g *genDeepCopy) doMap(t *types.Type, sw *generator.SnippetWriter) { + ut := underlyingType(t) + uet := underlyingType(ut.Elem) + + if deepCopyMethodOrDie(t) != nil || deepCopyIntoMethodOrDie(t) != nil { + sw.Do("*out = in.DeepCopy()\n", nil) + return + } + sw.Do("*out = make($.|raw$, len(*in))\n", t) - if t.Key.IsAssignable() { + if ut.Key.IsAssignable() { + dc, dci := deepCopyMethodOrDie(ut.Elem), deepCopyIntoMethodOrDie(ut.Elem) switch { - case hasDeepCopyMethod(t.Elem): + case dc != nil || dci != nil: sw.Do("for key, val := range *in {\n", nil) - sw.Do("(*out)[key] = val.DeepCopy()\n", nil) + // Note: a DeepCopy exists because it is added if DeepCopyInto is manually defined + leftPointer := ut.Elem.Kind == types.Pointer + rightPointer := !isReference(ut.Elem) + if dc != nil { + rightPointer = dc.Results[0].Kind == types.Pointer + } + if leftPointer == rightPointer { + sw.Do("(*out)[key] = val.DeepCopy()\n", nil) + } else if leftPointer { + sw.Do("x := val.DeepCopy()\n", nil) + sw.Do("(*out)[key] = &x\n", nil) + } else { + sw.Do("(*out)[key] = *val.DeepCopy()\n", nil) + } sw.Do("}\n", nil) - case t.Elem.IsAnonymousStruct(): + case ut.Elem.IsAnonymousStruct(): // not uet here because it needs type cast sw.Do("for key := range *in {\n", nil) sw.Do("(*out)[key] = struct{}{}\n", nil) sw.Do("}\n", nil) - case t.Elem.IsAssignable(): + case uet.IsAssignable(): sw.Do("for key, val := range *in {\n", nil) sw.Do("(*out)[key] = val\n", nil) sw.Do("}\n", nil) - case t.Elem.Kind == types.Interface: + case uet.Kind == types.Interface: sw.Do("for key, val := range *in {\n", nil) sw.Do("if val == nil {(*out)[key]=nil} else {\n", nil) - sw.Do(fmt.Sprintf("(*out)[key] = val.DeepCopy%s()\n", t.Elem.Name.Name), t) + // Note: if t.Elem has been an alias "J" of an interface "I" in Go, we will see it + // as kind Interface of name "J" here, i.e. generate val.DeepCopyJ(). The golang + // parser does not give us the underlying interface name. So we cannot do any better. + sw.Do(fmt.Sprintf("(*out)[key] = val.DeepCopy%s()\n", uet.Name.Name), nil) sw.Do("}}\n", nil) default: sw.Do("for key, val := range *in {\n", nil) - if g.copyableAndInBounds(t.Elem) { - sw.Do("newVal := new($.|raw$)\n", t.Elem) + if g.copyableAndInBounds(uet) { + sw.Do("newVal := new($.|raw$)\n", ut.Elem) sw.Do("val.DeepCopyInto(newVal)\n", nil) sw.Do("(*out)[key] = *newVal\n", nil) - } else if t.Elem.Kind == types.Slice && t.Elem.Elem.Kind == types.Builtin { + } else if uet.Kind == types.Slice && underlyingType(uet.Elem).Kind == types.Builtin { sw.Do("if val==nil { (*out)[key]=nil } else {\n", nil) - sw.Do("(*out)[key] = make($.|raw$, len(val))\n", t.Elem) + sw.Do("(*out)[key] = make($.|raw$, len(val))\n", uet) sw.Do("copy((*out)[key], val)\n", nil) sw.Do("}\n", nil) - } else if t.Elem.Kind == types.Alias && t.Elem.Underlying.Kind == types.Slice && t.Elem.Underlying.Elem.Kind == types.Builtin { - sw.Do("(*out)[key] = make($.|raw$, len(val))\n", t.Elem) - sw.Do("copy((*out)[key], val)\n", nil) - } else if t.Elem.Kind == types.Pointer { + } else if uet.Kind == types.Pointer { sw.Do("if val==nil { (*out)[key]=nil } else {\n", nil) - sw.Do("(*out)[key] = new($.Elem|raw$)\n", t.Elem) + sw.Do("(*out)[key] = new($.Elem|raw$)\n", uet) sw.Do("val.DeepCopyInto((*out)[key])\n", nil) sw.Do("}\n", nil) } else { - sw.Do("(*out)[key] = *val.DeepCopy()\n", t.Elem) + sw.Do("(*out)[key] = *val.DeepCopy()\n", uet) } sw.Do("}\n", nil) } } else { // TODO: Implement it when necessary. sw.Do("for range *in {\n", nil) - sw.Do("// FIXME: Copying unassignable keys unsupported $.|raw$\n", t.Key) + sw.Do("// FIXME: Copying unassignable keys unsupported $.|raw$\n", ut.Key) sw.Do("}\n", nil) } } +// doSlice generates code for a slice or an alias to a slice. The generated code is +// is the same for both cases, i.e. it's the code for the underlying type. func (g *genDeepCopy) doSlice(t *types.Type, sw *generator.SnippetWriter) { - if hasDeepCopyMethod(t) { + ut := underlyingType(t) + uet := underlyingType(ut.Elem) + + if deepCopyMethodOrDie(t) != nil || deepCopyIntoMethodOrDie(t) != nil { sw.Do("*out = in.DeepCopy()\n", nil) return } sw.Do("*out = make($.|raw$, len(*in))\n", t) - if hasDeepCopyMethod(t.Elem) { + if deepCopyMethodOrDie(ut.Elem) != nil || deepCopyIntoMethodOrDie(ut.Elem) != nil { sw.Do("for i := range *in {\n", nil) - sw.Do("(*out)[i] = (*in)[i].DeepCopy()\n", nil) + // Note: a DeepCopyInto exists because it is added if DeepCopy is manually defined + sw.Do("(*in)[i].DeepCopyInto(&(*out)[i])\n", nil) sw.Do("}\n", nil) - } else if t.Elem.Kind == types.Builtin || t.Elem.IsAssignable() { + } else if uet.Kind == types.Builtin || uet.IsAssignable() { sw.Do("copy(*out, *in)\n", nil) } else { sw.Do("for i := range *in {\n", nil) - if t.Elem.Kind == types.Slice { + if uet.Kind == types.Slice || uet.Kind == types.Map || deepCopyMethodOrDie(ut.Elem) != nil || deepCopyIntoMethodOrDie(ut.Elem) != nil { sw.Do("if (*in)[i] != nil {\n", nil) sw.Do("in, out := &(*in)[i], &(*out)[i]\n", nil) - g.generateFor(t.Elem, sw) + g.generateFor(ut.Elem, sw) sw.Do("}\n", nil) - } else if hasDeepCopyMethod(t.Elem) { - sw.Do("(*out)[i] = (*in)[i].DeepCopy()\n", nil) - // REVISIT(sttts): the following is removed in master - //} else if t.Elem.IsAssignable() { - // sw.Do("(*out)[i] = (*in)[i]\n", nil) - } else if t.Elem.Kind == types.Interface { + } else if uet.Kind == types.Interface { sw.Do("if (*in)[i] == nil {(*out)[i]=nil} else {\n", nil) - sw.Do(fmt.Sprintf("(*out)[i] = (*in)[i].DeepCopy%s()\n", t.Elem.Name.Name), t) + // Note: if t.Elem has been an alias "J" of an interface "I" in Go, we will see it + // as kind Interface of name "J" here, i.e. generate val.DeepCopyJ(). The golang + // parser does not give us the underlying interface name. So we cannot do any better. + sw.Do(fmt.Sprintf("(*out)[i] = (*in)[i].DeepCopy%s()\n", uet.Name.Name), nil) sw.Do("}\n", nil) - } else if t.Elem.Kind == types.Pointer { + } else if uet.Kind == types.Pointer { sw.Do("if (*in)[i]==nil { (*out)[i]=nil } else {\n", nil) - sw.Do("(*out)[i] = new($.Elem|raw$)\n", t.Elem) + sw.Do("(*out)[i] = new($.Elem|raw$)\n", uet) sw.Do("(*in)[i].DeepCopyInto((*out)[i])\n", nil) sw.Do("}\n", nil) - } else if t.Elem.Kind == types.Struct { + } else if uet.Kind == types.Struct { sw.Do("(*in)[i].DeepCopyInto(&(*out)[i])\n", nil) } else { sw.Do("(*out)[i] = (*in)[i].DeepCopy()\n", nil) @@ -673,8 +823,12 @@ func (g *genDeepCopy) doSlice(t *types.Type, sw *generator.SnippetWriter) { } } +// doStruct generates code for a struct or an alias to a struct. The generated code is +// is the same for both cases, i.e. it's the code for the underlying type. func (g *genDeepCopy) doStruct(t *types.Type, sw *generator.SnippetWriter) { - if hasDeepCopyMethod(t) { + ut := underlyingType(t) + + if deepCopyMethodOrDie(t) != nil || deepCopyIntoMethodOrDie(t) != nil { sw.Do("*out = in.DeepCopy()\n", nil) return } @@ -683,48 +837,52 @@ func (g *genDeepCopy) doStruct(t *types.Type, sw *generator.SnippetWriter) { sw.Do("*out = *in\n", nil) // Now fix-up fields as needed. - for _, m := range t.Members { - t := m.Type - hasMethod := hasDeepCopyMethod(t) - if t.Kind == types.Alias { - copied := *t.Underlying - copied.Name = t.Name - t = &copied - } + for _, m := range ut.Members { + ft := m.Type + uft := underlyingType(ft) + args := generator.Args{ - "type": t, - "kind": t.Kind, + "type": ft, + "kind": ft.Kind, "name": m.Name, } - switch t.Kind { - case types.Builtin: - if hasMethod { - sw.Do("out.$.name$ = in.$.name$.DeepCopy()\n", args) + dc, dci := deepCopyMethodOrDie(ft), deepCopyIntoMethodOrDie(ft) + switch { + case dc != nil || dci != nil: + // Note: a DeepCopyInto exists because it is added if DeepCopy is manually defined + leftPointer := ft.Kind == types.Pointer + rightPointer := !isReference(ft) + if dc != nil { + rightPointer = dc.Results[0].Kind == types.Pointer } - // the initial *out = *in was enough - case types.Map, types.Slice, types.Pointer: - if hasMethod { - sw.Do("if in.$.name$ != nil {\n", args) + if leftPointer == rightPointer { sw.Do("out.$.name$ = in.$.name$.DeepCopy()\n", args) - sw.Do("}\n", nil) + } else if leftPointer { + sw.Do("x := in.$.name$.DeepCopy()\n", args) + sw.Do("out.$.name$ = = &x\n", args) } else { - // Fixup non-nil reference-semantic types. - sw.Do("if in.$.name$ != nil {\n", args) - sw.Do("in, out := &in.$.name$, &out.$.name$\n", args) - g.generateFor(t, sw) - sw.Do("}\n", nil) + sw.Do("in.$.name$.DeepCopyInto(&out.$.name$)\n", args) } - case types.Struct: - if hasMethod { - sw.Do("out.$.name$ = in.$.name$.DeepCopy()\n", args) - } else if t.IsAssignable() { + case uft.Kind == types.Builtin: + // the initial *out = *in was enough + case uft.Kind == types.Map, uft.Kind == types.Slice, uft.Kind == types.Pointer: + // Fixup non-nil reference-semantic types. + sw.Do("if in.$.name$ != nil {\n", args) + sw.Do("in, out := &in.$.name$, &out.$.name$\n", args) + g.generateFor(ft, sw) + sw.Do("}\n", nil) + case uft.Kind == types.Struct: + if ft.IsAssignable() { sw.Do("out.$.name$ = in.$.name$\n", args) } else { sw.Do("in.$.name$.DeepCopyInto(&out.$.name$)\n", args) } - case types.Interface: + case uft.Kind == types.Interface: sw.Do("if in.$.name$ == nil {out.$.name$=nil} else {\n", args) - sw.Do(fmt.Sprintf("out.$.name$ = in.$.name$.DeepCopy%s()\n", t.Name.Name), args) + // Note: if t.Elem has been an alias "J" of an interface "I" in Go, we will see it + // as kind Interface of name "J" here, i.e. generate val.DeepCopyJ(). The golang + // parser does not give us the underlying interface name. So we cannot do any better. + sw.Do(fmt.Sprintf("out.$.name$ = in.$.name$.DeepCopy%s()\n", uft.Name.Name), args) sw.Do("}\n", nil) default: sw.Do("out.$.name$ = in.$.name$.DeepCopy()\n", args) @@ -732,40 +890,44 @@ func (g *genDeepCopy) doStruct(t *types.Type, sw *generator.SnippetWriter) { } } -func (g *genDeepCopy) doInterface(t *types.Type, sw *generator.SnippetWriter) { - // TODO: Add support for interfaces. - g.doUnknown(t, sw) -} - +// doPointer generates code for a pointer or an alias to a pointer. The generated code is +// is the same for both cases, i.e. it's the code for the underlying type. func (g *genDeepCopy) doPointer(t *types.Type, sw *generator.SnippetWriter) { + ut := underlyingType(t) + uet := underlyingType(ut.Elem) + sw.Do("if *in == nil { *out = nil } else {\n", t) - if hasDeepCopyMethod(t.Elem) { - sw.Do("*out = new($.Elem|raw$)\n", t) - sw.Do("**out = (*in).DeepCopy()\n", nil) - } else if t.Elem.IsAssignable() { - sw.Do("*out = new($.Elem|raw$)\n", t) + dc, dci := deepCopyMethodOrDie(ut.Elem), deepCopyIntoMethodOrDie(ut.Elem) + if dc != nil || dci != nil { + rightPointer := !isReference(ut.Elem) + if dc != nil { + rightPointer = dc.Results[0].Kind == types.Pointer + } + if rightPointer { + sw.Do("*out = (*in).DeepCopy()\n", nil) + } else { + sw.Do("x := (*in).DeepCopy()\n", nil) + sw.Do("*out = &x\n", nil) + } + } else if uet.IsAssignable() { + sw.Do("*out = new($.Elem|raw$)\n", ut) sw.Do("**out = **in", nil) } else { - switch t.Elem.Kind { + switch uet.Kind { case types.Map, types.Slice: - sw.Do("*out = new($.Elem|raw$)\n", t) - sw.Do("if **in != nil {\n", t) + sw.Do("*out = new($.Elem|raw$)\n", ut) + sw.Do("if **in != nil {\n", nil) sw.Do("in, out := *in, *out\n", nil) - g.generateFor(t.Elem, sw) + g.generateFor(uet, sw) sw.Do("}\n", nil) default: - sw.Do("*out = new($.Elem|raw$)\n", t) + sw.Do("*out = new($.Elem|raw$)\n", ut) sw.Do("(*in).DeepCopyInto(*out)\n", nil) } } sw.Do("}", t) } -func (g *genDeepCopy) doAlias(t *types.Type, sw *generator.SnippetWriter) { - // TODO: Add support for aliases. - g.doUnknown(t, sw) -} - func (g *genDeepCopy) doUnknown(t *types.Type, sw *generator.SnippetWriter) { sw.Do("// FIXME: Type $.|raw$ is unsupported.\n", t) } diff --git a/vendor/k8s.io/gengo/examples/defaulter-gen/generators/defaulter.go b/vendor/k8s.io/gengo/examples/defaulter-gen/generators/defaulter.go index da6268639ef..6ab8676a24d 100644 --- a/vendor/k8s.io/gengo/examples/defaulter-gen/generators/defaulter.go +++ b/vendor/k8s.io/gengo/examples/defaulter-gen/generators/defaulter.go @@ -203,11 +203,6 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat packages := generator.Packages{} header := append([]byte(fmt.Sprintf("// +build !%s\n\n", arguments.GeneratedBuildTag)), boilerplate...) - header = append(header, []byte( - ` -// This file was autogenerated by defaulter-gen. Do not edit it manually! - -`)...) // Accumulate pre-existing default functions. // TODO: This is too ad-hoc. We need a better way. @@ -470,6 +465,9 @@ func (c *callTreeForType) build(t *types.Type, root bool) *callNode { case types.Slice, types.Array: if child := c.build(t.Elem, false); child != nil { child.index = true + if t.Elem.Kind == types.Pointer { + child.elem = true + } parent.children = append(parent.children, *child) } case types.Map: @@ -748,7 +746,7 @@ func (n *callNode) WriteMethod(varName string, depth int, ancestors []*callNode, "var": varName, } - isPointer := n.elem + isPointer := n.elem && !n.index if isPointer && len(ancestors) > 0 { sw.Do("if $.var$ != nil {\n", vars) } @@ -756,7 +754,12 @@ func (n *callNode) WriteMethod(varName string, depth int, ancestors []*callNode, switch { case n.index: sw.Do("for $.index$ := range $.var$ {\n", vars) - sw.Do("$.local$ := &$.var$[$.index$]\n", vars) + if n.elem { + sw.Do("$.local$ := $.var$[$.index$]\n", vars) + } else { + sw.Do("$.local$ := &$.var$[$.index$]\n", vars) + } + n.writeCalls(local, true, sw) for i := range n.children { n.children[i].WriteMethod(local, depth+1, append(ancestors, n), sw) diff --git a/vendor/k8s.io/gengo/examples/set-gen/generators/sets.go b/vendor/k8s.io/gengo/examples/set-gen/generators/sets.go index c570b0c0a4b..8c5b4184ba5 100644 --- a/vendor/k8s.io/gengo/examples/set-gen/generators/sets.go +++ b/vendor/k8s.io/gengo/examples/set-gen/generators/sets.go @@ -53,11 +53,7 @@ func Packages(_ *generator.Context, arguments *args.GeneratorArgs) generator.Pac return generator.Packages{&generator.DefaultPackage{ PackageName: "sets", PackagePath: arguments.OutputPackagePath, - HeaderText: append(boilerplate, []byte( - ` -// This file was autogenerated by set-gen. Do not edit it manually! - -`)...), + HeaderText: boilerplate, PackageDocumentation: []byte( `// Package sets has auto-generated set types. `), diff --git a/vendor/k8s.io/gengo/examples/set-gen/sets/byte.go b/vendor/k8s.io/gengo/examples/set-gen/sets/byte.go index 60144d181bd..766f4501e0f 100644 --- a/vendor/k8s.io/gengo/examples/set-gen/sets/byte.go +++ b/vendor/k8s.io/gengo/examples/set-gen/sets/byte.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was autogenerated by set-gen. Do not edit it manually! +// Code generated by set-gen. DO NOT EDIT. package sets diff --git a/vendor/k8s.io/gengo/examples/set-gen/sets/doc.go b/vendor/k8s.io/gengo/examples/set-gen/sets/doc.go index 28a6a7d5c72..b152a0bf00f 100644 --- a/vendor/k8s.io/gengo/examples/set-gen/sets/doc.go +++ b/vendor/k8s.io/gengo/examples/set-gen/sets/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was autogenerated by set-gen. Do not edit it manually! +// Code generated by set-gen. DO NOT EDIT. // Package sets has auto-generated set types. package sets diff --git a/vendor/k8s.io/gengo/examples/set-gen/sets/empty.go b/vendor/k8s.io/gengo/examples/set-gen/sets/empty.go index cd22b953aa6..e11e622c5ba 100644 --- a/vendor/k8s.io/gengo/examples/set-gen/sets/empty.go +++ b/vendor/k8s.io/gengo/examples/set-gen/sets/empty.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was autogenerated by set-gen. Do not edit it manually! +// Code generated by set-gen. DO NOT EDIT. package sets diff --git a/vendor/k8s.io/gengo/examples/set-gen/sets/int.go b/vendor/k8s.io/gengo/examples/set-gen/sets/int.go index 2b155e4e1c1..a0a513cd9b5 100644 --- a/vendor/k8s.io/gengo/examples/set-gen/sets/int.go +++ b/vendor/k8s.io/gengo/examples/set-gen/sets/int.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was autogenerated by set-gen. Do not edit it manually! +// Code generated by set-gen. DO NOT EDIT. package sets diff --git a/vendor/k8s.io/gengo/examples/set-gen/sets/int64.go b/vendor/k8s.io/gengo/examples/set-gen/sets/int64.go index 0137bca2bb3..9ca9af0c591 100644 --- a/vendor/k8s.io/gengo/examples/set-gen/sets/int64.go +++ b/vendor/k8s.io/gengo/examples/set-gen/sets/int64.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was autogenerated by set-gen. Do not edit it manually! +// Code generated by set-gen. DO NOT EDIT. package sets diff --git a/vendor/k8s.io/gengo/examples/set-gen/sets/string.go b/vendor/k8s.io/gengo/examples/set-gen/sets/string.go index ec72eea2511..ba00ad7df4e 100644 --- a/vendor/k8s.io/gengo/examples/set-gen/sets/string.go +++ b/vendor/k8s.io/gengo/examples/set-gen/sets/string.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This file was autogenerated by set-gen. Do not edit it manually! +// Code generated by set-gen. DO NOT EDIT. package sets diff --git a/vendor/k8s.io/gengo/namer/plural_namer.go b/vendor/k8s.io/gengo/namer/plural_namer.go index 81a55f6a75c..40bdcc6ccc2 100644 --- a/vendor/k8s.io/gengo/namer/plural_namer.go +++ b/vendor/k8s.io/gengo/namer/plural_namer.go @@ -22,6 +22,8 @@ import ( "k8s.io/gengo/types" ) +var consonants = "bcdfghjklmnpqrsttvwxyz" + type pluralNamer struct { // key is the case-sensitive type name, value is the case-insensitive // intended output. @@ -56,13 +58,63 @@ func (r *pluralNamer) Name(t *types.Type) string { if plural, ok = r.exceptions[singular]; ok { return r.finalize(plural) } - switch string(singular[len(singular)-1]) { - case "s", "x": - plural = singular + "es" - case "y": - plural = singular[:len(singular)-1] + "ies" + if len(singular) < 2 { + return r.finalize(plural) + } + + switch rune(singular[len(singular)-1]) { + case 's', 'x', 'z': + plural = esPlural(singular) + case 'y': + sl := rune(singular[len(singular)-2]) + if isConsonant(sl) { + plural = iesPlural(singular) + } else { + plural = sPlural(singular) + } + case 'h': + sl := rune(singular[len(singular)-2]) + if sl == 'c' || sl == 's' { + plural = esPlural(singular) + } else { + plural = sPlural(singular) + } + case 'e': + sl := rune(singular[len(singular)-2]) + if sl == 'f' { + plural = vesPlural(singular[:len(singular)-1]) + } else { + plural = sPlural(singular) + } + case 'f': + plural = vesPlural(singular) default: - plural = singular + "s" + plural = sPlural(singular) } return r.finalize(plural) } + +func iesPlural(singular string) string { + return singular[:len(singular)-1] + "ies" +} + +func vesPlural(singular string) string { + return singular[:len(singular)-1] + "ves" +} + +func esPlural(singular string) string { + return singular + "es" +} + +func sPlural(singular string) string { + return singular + "s" +} + +func isConsonant(char rune) bool { + for _, c := range consonants { + if char == c { + return true + } + } + return false +} diff --git a/vendor/k8s.io/gengo/parser/parse.go b/vendor/k8s.io/gengo/parser/parse.go index d2bfed30c59..865b430f787 100644 --- a/vendor/k8s.io/gengo/parser/parse.go +++ b/vendor/k8s.io/gengo/parser/parse.go @@ -578,7 +578,7 @@ func splitLines(str string) []string { } func tcFuncNameToName(in string) types.Name { - name := strings.TrimLeft(in, "func ") + name := strings.TrimPrefix(in, "func ") nameParts := strings.Split(name, "(") return tcNameToName(nameParts[0]) }