deepcopy.go 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925
  1. /*
  2. Copyright 2015 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package generators
  14. import (
  15. "fmt"
  16. "io"
  17. "path/filepath"
  18. "sort"
  19. "strings"
  20. "k8s.io/gengo/args"
  21. "k8s.io/gengo/examples/set-gen/sets"
  22. "k8s.io/gengo/generator"
  23. "k8s.io/gengo/namer"
  24. "k8s.io/gengo/types"
  25. "k8s.io/klog"
  26. )
  27. // CustomArgs is used tby the go2idl framework to pass args specific to this
  28. // generator.
  29. type CustomArgs struct {
  30. BoundingDirs []string // Only deal with types rooted under these dirs.
  31. }
  32. // This is the comment tag that carries parameters for deep-copy generation.
  33. const (
  34. tagEnabledName = "k8s:deepcopy-gen"
  35. interfacesTagName = tagEnabledName + ":interfaces"
  36. interfacesNonPointerTagName = tagEnabledName + ":nonpointer-interfaces" // attach the DeepCopy<Interface> methods to the
  37. )
  38. // Known values for the comment tag.
  39. const tagValuePackage = "package"
  40. // enabledTagValue holds parameters from a tagName tag.
  41. type enabledTagValue struct {
  42. value string
  43. register bool
  44. }
  45. func extractEnabledTypeTag(t *types.Type) *enabledTagValue {
  46. comments := append(append([]string{}, t.SecondClosestCommentLines...), t.CommentLines...)
  47. return extractEnabledTag(comments)
  48. }
  49. func extractEnabledTag(comments []string) *enabledTagValue {
  50. tagVals := types.ExtractCommentTags("+", comments)[tagEnabledName]
  51. if tagVals == nil {
  52. // No match for the tag.
  53. return nil
  54. }
  55. // If there are multiple values, abort.
  56. if len(tagVals) > 1 {
  57. klog.Fatalf("Found %d %s tags: %q", len(tagVals), tagEnabledName, tagVals)
  58. }
  59. // If we got here we are returning something.
  60. tag := &enabledTagValue{}
  61. // Get the primary value.
  62. parts := strings.Split(tagVals[0], ",")
  63. if len(parts) >= 1 {
  64. tag.value = parts[0]
  65. }
  66. // Parse extra arguments.
  67. parts = parts[1:]
  68. for i := range parts {
  69. kv := strings.SplitN(parts[i], "=", 2)
  70. k := kv[0]
  71. v := ""
  72. if len(kv) == 2 {
  73. v = kv[1]
  74. }
  75. switch k {
  76. case "register":
  77. if v != "false" {
  78. tag.register = true
  79. }
  80. default:
  81. klog.Fatalf("Unsupported %s param: %q", tagEnabledName, parts[i])
  82. }
  83. }
  84. return tag
  85. }
  86. // TODO: This is created only to reduce number of changes in a single PR.
  87. // Remove it and use PublicNamer instead.
  88. func deepCopyNamer() *namer.NameStrategy {
  89. return &namer.NameStrategy{
  90. Join: func(pre string, in []string, post string) string {
  91. return strings.Join(in, "_")
  92. },
  93. PrependPackageNames: 1,
  94. }
  95. }
  96. // NameSystems returns the name system used by the generators in this package.
  97. func NameSystems() namer.NameSystems {
  98. return namer.NameSystems{
  99. "public": deepCopyNamer(),
  100. "raw": namer.NewRawNamer("", nil),
  101. }
  102. }
  103. // DefaultNameSystem returns the default name system for ordering the types to be
  104. // processed by the generators in this package.
  105. func DefaultNameSystem() string {
  106. return "public"
  107. }
  108. func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages {
  109. boilerplate, err := arguments.LoadGoBoilerplate()
  110. if err != nil {
  111. klog.Fatalf("Failed loading boilerplate: %v", err)
  112. }
  113. inputs := sets.NewString(context.Inputs...)
  114. packages := generator.Packages{}
  115. header := append([]byte(fmt.Sprintf("// +build !%s\n\n", arguments.GeneratedBuildTag)), boilerplate...)
  116. boundingDirs := []string{}
  117. if customArgs, ok := arguments.CustomArgs.(*CustomArgs); ok {
  118. if customArgs.BoundingDirs == nil {
  119. customArgs.BoundingDirs = context.Inputs
  120. }
  121. for i := range customArgs.BoundingDirs {
  122. // Strip any trailing slashes - they are not exactly "correct" but
  123. // this is friendlier.
  124. boundingDirs = append(boundingDirs, strings.TrimRight(customArgs.BoundingDirs[i], "/"))
  125. }
  126. }
  127. for i := range inputs {
  128. klog.V(5).Infof("Considering pkg %q", i)
  129. pkg := context.Universe[i]
  130. if pkg == nil {
  131. // If the input had no Go files, for example.
  132. continue
  133. }
  134. ptag := extractEnabledTag(pkg.Comments)
  135. ptagValue := ""
  136. ptagRegister := false
  137. if ptag != nil {
  138. ptagValue = ptag.value
  139. if ptagValue != tagValuePackage {
  140. klog.Fatalf("Package %v: unsupported %s value: %q", i, tagEnabledName, ptagValue)
  141. }
  142. ptagRegister = ptag.register
  143. klog.V(5).Infof(" tag.value: %q, tag.register: %t", ptagValue, ptagRegister)
  144. } else {
  145. klog.V(5).Infof(" no tag")
  146. }
  147. // If the pkg-scoped tag says to generate, we can skip scanning types.
  148. pkgNeedsGeneration := (ptagValue == tagValuePackage)
  149. if !pkgNeedsGeneration {
  150. // If the pkg-scoped tag did not exist, scan all types for one that
  151. // explicitly wants generation.
  152. for _, t := range pkg.Types {
  153. klog.V(5).Infof(" considering type %q", t.Name.String())
  154. ttag := extractEnabledTypeTag(t)
  155. if ttag != nil && ttag.value == "true" {
  156. klog.V(5).Infof(" tag=true")
  157. if !copyableType(t) {
  158. klog.Fatalf("Type %v requests deepcopy generation but is not copyable", t)
  159. }
  160. pkgNeedsGeneration = true
  161. break
  162. }
  163. }
  164. }
  165. if pkgNeedsGeneration {
  166. klog.V(3).Infof("Package %q needs generation", i)
  167. path := pkg.Path
  168. // if the source path is within a /vendor/ directory (for example,
  169. // k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/apis/meta/v1), allow
  170. // generation to output to the proper relative path (under vendor).
  171. // Otherwise, the generator will create the file in the wrong location
  172. // in the output directory.
  173. // TODO: build a more fundamental concept in gengo for dealing with modifications
  174. // to vendored packages.
  175. if strings.HasPrefix(pkg.SourcePath, arguments.OutputBase) {
  176. expandedPath := strings.TrimPrefix(pkg.SourcePath, arguments.OutputBase)
  177. if strings.Contains(expandedPath, "/vendor/") {
  178. path = expandedPath
  179. }
  180. }
  181. packages = append(packages,
  182. &generator.DefaultPackage{
  183. PackageName: strings.Split(filepath.Base(pkg.Path), ".")[0],
  184. PackagePath: path,
  185. HeaderText: header,
  186. GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
  187. return []generator.Generator{
  188. NewGenDeepCopy(arguments.OutputFileBaseName, pkg.Path, boundingDirs, (ptagValue == tagValuePackage), ptagRegister),
  189. }
  190. },
  191. FilterFunc: func(c *generator.Context, t *types.Type) bool {
  192. return t.Name.Package == pkg.Path
  193. },
  194. })
  195. }
  196. }
  197. return packages
  198. }
  199. // genDeepCopy produces a file with autogenerated deep-copy functions.
  200. type genDeepCopy struct {
  201. generator.DefaultGen
  202. targetPackage string
  203. boundingDirs []string
  204. allTypes bool
  205. registerTypes bool
  206. imports namer.ImportTracker
  207. typesForInit []*types.Type
  208. }
  209. func NewGenDeepCopy(sanitizedName, targetPackage string, boundingDirs []string, allTypes, registerTypes bool) generator.Generator {
  210. return &genDeepCopy{
  211. DefaultGen: generator.DefaultGen{
  212. OptionalName: sanitizedName,
  213. },
  214. targetPackage: targetPackage,
  215. boundingDirs: boundingDirs,
  216. allTypes: allTypes,
  217. registerTypes: registerTypes,
  218. imports: generator.NewImportTracker(),
  219. typesForInit: make([]*types.Type, 0),
  220. }
  221. }
  222. func (g *genDeepCopy) Namers(c *generator.Context) namer.NameSystems {
  223. // Have the raw namer for this file track what it imports.
  224. return namer.NameSystems{
  225. "raw": namer.NewRawNamer(g.targetPackage, g.imports),
  226. }
  227. }
  228. func (g *genDeepCopy) Filter(c *generator.Context, t *types.Type) bool {
  229. // Filter out types not being processed or not copyable within the package.
  230. enabled := g.allTypes
  231. if !enabled {
  232. ttag := extractEnabledTypeTag(t)
  233. if ttag != nil && ttag.value == "true" {
  234. enabled = true
  235. }
  236. }
  237. if !enabled {
  238. return false
  239. }
  240. if !copyableType(t) {
  241. klog.V(2).Infof("Type %v is not copyable", t)
  242. return false
  243. }
  244. klog.V(4).Infof("Type %v is copyable", t)
  245. g.typesForInit = append(g.typesForInit, t)
  246. return true
  247. }
  248. func (g *genDeepCopy) copyableAndInBounds(t *types.Type) bool {
  249. if !copyableType(t) {
  250. return false
  251. }
  252. // Only packages within the restricted range can be processed.
  253. if !isRootedUnder(t.Name.Package, g.boundingDirs) {
  254. return false
  255. }
  256. return true
  257. }
  258. // deepCopyMethod returns the signature of a DeepCopy() method, nil or an error
  259. // if the type does not match. This allows more efficient deep copy
  260. // implementations to be defined by the type's author. The correct signature
  261. // for a type T is:
  262. // func (t T) DeepCopy() T
  263. // or:
  264. // func (t *T) DeepCopy() *T
  265. func deepCopyMethod(t *types.Type) (*types.Signature, error) {
  266. f, found := t.Methods["DeepCopy"]
  267. if !found {
  268. return nil, nil
  269. }
  270. if len(f.Signature.Parameters) != 0 {
  271. return nil, fmt.Errorf("type %v: invalid DeepCopy signature, expected no parameters", t)
  272. }
  273. if len(f.Signature.Results) != 1 {
  274. return nil, fmt.Errorf("type %v: invalid DeepCopy signature, expected exactly one result", t)
  275. }
  276. ptrResult := f.Signature.Results[0].Kind == types.Pointer && f.Signature.Results[0].Elem.Name == t.Name
  277. nonPtrResult := f.Signature.Results[0].Name == t.Name
  278. if !ptrResult && !nonPtrResult {
  279. return nil, fmt.Errorf("type %v: invalid DeepCopy signature, expected to return %s or *%s", t, t.Name.Name, t.Name.Name)
  280. }
  281. ptrRcvr := f.Signature.Receiver != nil && f.Signature.Receiver.Kind == types.Pointer && f.Signature.Receiver.Elem.Name == t.Name
  282. nonPtrRcvr := f.Signature.Receiver != nil && f.Signature.Receiver.Name == t.Name
  283. if ptrRcvr && !ptrResult {
  284. return nil, fmt.Errorf("type %v: invalid DeepCopy signature, expected a *%s result for a *%s receiver", t, t.Name.Name, t.Name.Name)
  285. }
  286. if nonPtrRcvr && !nonPtrResult {
  287. return nil, fmt.Errorf("type %v: invalid DeepCopy signature, expected a %s result for a %s receiver", t, t.Name.Name, t.Name.Name)
  288. }
  289. return f.Signature, nil
  290. }
  291. // deepCopyMethodOrDie returns the signatrue of a DeepCopy method, nil or calls klog.Fatalf
  292. // if the type does not match.
  293. func deepCopyMethodOrDie(t *types.Type) *types.Signature {
  294. ret, err := deepCopyMethod(t)
  295. if err != nil {
  296. klog.Fatal(err)
  297. }
  298. return ret
  299. }
  300. // deepCopyIntoMethod returns the signature of a DeepCopyInto() method, nil or an error
  301. // if the type is wrong. DeepCopyInto allows more efficient deep copy
  302. // implementations to be defined by the type's author. The correct signature
  303. // for a type T is:
  304. // func (t T) DeepCopyInto(t *T)
  305. // or:
  306. // func (t *T) DeepCopyInto(t *T)
  307. func deepCopyIntoMethod(t *types.Type) (*types.Signature, error) {
  308. f, found := t.Methods["DeepCopyInto"]
  309. if !found {
  310. return nil, nil
  311. }
  312. if len(f.Signature.Parameters) != 1 {
  313. return nil, fmt.Errorf("type %v: invalid DeepCopy signature, expected exactly one parameter", t)
  314. }
  315. if len(f.Signature.Results) != 0 {
  316. return nil, fmt.Errorf("type %v: invalid DeepCopy signature, expected no result type", t)
  317. }
  318. ptrParam := f.Signature.Parameters[0].Kind == types.Pointer && f.Signature.Parameters[0].Elem.Name == t.Name
  319. if !ptrParam {
  320. return nil, fmt.Errorf("type %v: invalid DeepCopy signature, expected parameter of type *%s", t, t.Name.Name)
  321. }
  322. ptrRcvr := f.Signature.Receiver != nil && f.Signature.Receiver.Kind == types.Pointer && f.Signature.Receiver.Elem.Name == t.Name
  323. nonPtrRcvr := f.Signature.Receiver != nil && f.Signature.Receiver.Name == t.Name
  324. if !ptrRcvr && !nonPtrRcvr {
  325. // this should never happen
  326. return nil, fmt.Errorf("type %v: invalid DeepCopy signature, expected a receiver of type %s or *%s", t, t.Name.Name, t.Name.Name)
  327. }
  328. return f.Signature, nil
  329. }
  330. // deepCopyIntoMethodOrDie returns the signature of a DeepCopyInto() method, nil or calls klog.Fatalf
  331. // if the type is wrong.
  332. func deepCopyIntoMethodOrDie(t *types.Type) *types.Signature {
  333. ret, err := deepCopyIntoMethod(t)
  334. if err != nil {
  335. klog.Fatal(err)
  336. }
  337. return ret
  338. }
  339. func isRootedUnder(pkg string, roots []string) bool {
  340. // Add trailing / to avoid false matches, e.g. foo/bar vs foo/barn. This
  341. // assumes that bounding dirs do not have trailing slashes.
  342. pkg = pkg + "/"
  343. for _, root := range roots {
  344. if strings.HasPrefix(pkg, root+"/") {
  345. return true
  346. }
  347. }
  348. return false
  349. }
  350. func copyableType(t *types.Type) bool {
  351. // If the type opts out of copy-generation, stop.
  352. ttag := extractEnabledTypeTag(t)
  353. if ttag != nil && ttag.value == "false" {
  354. return false
  355. }
  356. // Filter out private types.
  357. if namer.IsPrivateGoName(t.Name.Name) {
  358. return false
  359. }
  360. if t.Kind == types.Alias {
  361. // if the underlying built-in is not deepcopy-able, deepcopy is opt-in through definition of custom methods.
  362. // Note that aliases of builtins, maps, slices can have deepcopy methods.
  363. if deepCopyMethodOrDie(t) != nil || deepCopyIntoMethodOrDie(t) != nil {
  364. return true
  365. } else {
  366. return t.Underlying.Kind != types.Builtin || copyableType(t.Underlying)
  367. }
  368. }
  369. if t.Kind != types.Struct {
  370. return false
  371. }
  372. return true
  373. }
  374. func underlyingType(t *types.Type) *types.Type {
  375. for t.Kind == types.Alias {
  376. t = t.Underlying
  377. }
  378. return t
  379. }
  380. func (g *genDeepCopy) isOtherPackage(pkg string) bool {
  381. if pkg == g.targetPackage {
  382. return false
  383. }
  384. if strings.HasSuffix(pkg, "\""+g.targetPackage+"\"") {
  385. return false
  386. }
  387. return true
  388. }
  389. func (g *genDeepCopy) Imports(c *generator.Context) (imports []string) {
  390. importLines := []string{}
  391. for _, singleImport := range g.imports.ImportLines() {
  392. if g.isOtherPackage(singleImport) {
  393. importLines = append(importLines, singleImport)
  394. }
  395. }
  396. return importLines
  397. }
  398. func argsFromType(ts ...*types.Type) generator.Args {
  399. a := generator.Args{
  400. "type": ts[0],
  401. }
  402. for i, t := range ts {
  403. a[fmt.Sprintf("type%d", i+1)] = t
  404. }
  405. return a
  406. }
  407. func (g *genDeepCopy) Init(c *generator.Context, w io.Writer) error {
  408. return nil
  409. }
  410. func (g *genDeepCopy) needsGeneration(t *types.Type) bool {
  411. tag := extractEnabledTypeTag(t)
  412. tv := ""
  413. if tag != nil {
  414. tv = tag.value
  415. if tv != "true" && tv != "false" {
  416. klog.Fatalf("Type %v: unsupported %s value: %q", t, tagEnabledName, tag.value)
  417. }
  418. }
  419. if g.allTypes && tv == "false" {
  420. // The whole package is being generated, but this type has opted out.
  421. klog.V(5).Infof("Not generating for type %v because type opted out", t)
  422. return false
  423. }
  424. if !g.allTypes && tv != "true" {
  425. // The whole package is NOT being generated, and this type has NOT opted in.
  426. klog.V(5).Infof("Not generating for type %v because type did not opt in", t)
  427. return false
  428. }
  429. return true
  430. }
  431. func extractInterfacesTag(t *types.Type) []string {
  432. var result []string
  433. comments := append(append([]string{}, t.SecondClosestCommentLines...), t.CommentLines...)
  434. values := types.ExtractCommentTags("+", comments)[interfacesTagName]
  435. for _, v := range values {
  436. if len(v) == 0 {
  437. continue
  438. }
  439. intfs := strings.Split(v, ",")
  440. for _, intf := range intfs {
  441. if intf == "" {
  442. continue
  443. }
  444. result = append(result, intf)
  445. }
  446. }
  447. return result
  448. }
  449. func extractNonPointerInterfaces(t *types.Type) (bool, error) {
  450. comments := append(append([]string{}, t.SecondClosestCommentLines...), t.CommentLines...)
  451. values := types.ExtractCommentTags("+", comments)[interfacesNonPointerTagName]
  452. if len(values) == 0 {
  453. return false, nil
  454. }
  455. result := values[0] == "true"
  456. for _, v := range values {
  457. if v == "true" != result {
  458. return false, fmt.Errorf("contradicting %v value %q found to previous value %v", interfacesNonPointerTagName, v, result)
  459. }
  460. }
  461. return result, nil
  462. }
  463. func (g *genDeepCopy) deepCopyableInterfacesInner(c *generator.Context, t *types.Type) ([]*types.Type, error) {
  464. if t.Kind != types.Struct {
  465. return nil, nil
  466. }
  467. intfs := extractInterfacesTag(t)
  468. var ts []*types.Type
  469. for _, intf := range intfs {
  470. t := types.ParseFullyQualifiedName(intf)
  471. c.AddDir(t.Package)
  472. intfT := c.Universe.Type(t)
  473. if intfT == nil {
  474. return nil, fmt.Errorf("unknown type %q in %s tag of type %s", intf, interfacesTagName, intfT)
  475. }
  476. if intfT.Kind != types.Interface {
  477. return nil, fmt.Errorf("type %q in %s tag of type %s is not an interface, but: %q", intf, interfacesTagName, t, intfT.Kind)
  478. }
  479. g.imports.AddType(intfT)
  480. ts = append(ts, intfT)
  481. }
  482. return ts, nil
  483. }
  484. // deepCopyableInterfaces returns the interface types to implement and whether they apply to a non-pointer receiver.
  485. func (g *genDeepCopy) deepCopyableInterfaces(c *generator.Context, t *types.Type) ([]*types.Type, bool, error) {
  486. ts, err := g.deepCopyableInterfacesInner(c, t)
  487. if err != nil {
  488. return nil, false, err
  489. }
  490. set := map[string]*types.Type{}
  491. for _, t := range ts {
  492. set[t.String()] = t
  493. }
  494. result := []*types.Type{}
  495. for _, t := range set {
  496. result = append(result, t)
  497. }
  498. TypeSlice(result).Sort() // we need a stable sorting because it determines the order in generation
  499. nonPointerReceiver, err := extractNonPointerInterfaces(t)
  500. if err != nil {
  501. return nil, false, err
  502. }
  503. return result, nonPointerReceiver, nil
  504. }
  505. type TypeSlice []*types.Type
  506. func (s TypeSlice) Len() int { return len(s) }
  507. func (s TypeSlice) Less(i, j int) bool { return s[i].String() < s[j].String() }
  508. func (s TypeSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
  509. func (s TypeSlice) Sort() { sort.Sort(s) }
  510. func (g *genDeepCopy) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
  511. if !g.needsGeneration(t) {
  512. return nil
  513. }
  514. klog.V(5).Infof("Generating deepcopy function for type %v", t)
  515. sw := generator.NewSnippetWriter(w, c, "$", "$")
  516. args := argsFromType(t)
  517. if deepCopyIntoMethodOrDie(t) == nil {
  518. sw.Do("// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\n", args)
  519. if isReference(t) {
  520. sw.Do("func (in $.type|raw$) DeepCopyInto(out *$.type|raw$) {\n", args)
  521. sw.Do("{in:=&in\n", nil)
  522. } else {
  523. sw.Do("func (in *$.type|raw$) DeepCopyInto(out *$.type|raw$) {\n", args)
  524. }
  525. if deepCopyMethodOrDie(t) != nil {
  526. if t.Methods["DeepCopy"].Signature.Receiver.Kind == types.Pointer {
  527. sw.Do("clone := in.DeepCopy()\n", nil)
  528. sw.Do("*out = *clone\n", nil)
  529. } else {
  530. sw.Do("*out = in.DeepCopy()\n", nil)
  531. }
  532. sw.Do("return\n", nil)
  533. } else {
  534. g.generateFor(t, sw)
  535. sw.Do("return\n", nil)
  536. }
  537. if isReference(t) {
  538. sw.Do("}\n", nil)
  539. }
  540. sw.Do("}\n\n", nil)
  541. }
  542. if deepCopyMethodOrDie(t) == nil {
  543. sw.Do("// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new $.type|raw$.\n", args)
  544. if isReference(t) {
  545. sw.Do("func (in $.type|raw$) DeepCopy() $.type|raw$ {\n", args)
  546. } else {
  547. sw.Do("func (in *$.type|raw$) DeepCopy() *$.type|raw$ {\n", args)
  548. }
  549. sw.Do("if in == nil { return nil }\n", nil)
  550. sw.Do("out := new($.type|raw$)\n", args)
  551. sw.Do("in.DeepCopyInto(out)\n", nil)
  552. if isReference(t) {
  553. sw.Do("return *out\n", nil)
  554. } else {
  555. sw.Do("return out\n", nil)
  556. }
  557. sw.Do("}\n\n", nil)
  558. }
  559. intfs, nonPointerReceiver, err := g.deepCopyableInterfaces(c, t)
  560. if err != nil {
  561. return err
  562. }
  563. for _, intf := range intfs {
  564. sw.Do(fmt.Sprintf("// DeepCopy%s is an autogenerated deepcopy function, copying the receiver, creating a new $.type2|raw$.\n", intf.Name.Name), argsFromType(t, intf))
  565. if nonPointerReceiver {
  566. sw.Do(fmt.Sprintf("func (in $.type|raw$) DeepCopy%s() $.type2|raw$ {\n", intf.Name.Name), argsFromType(t, intf))
  567. sw.Do("return *in.DeepCopy()", nil)
  568. sw.Do("}\n\n", nil)
  569. } else {
  570. sw.Do(fmt.Sprintf("func (in *$.type|raw$) DeepCopy%s() $.type2|raw$ {\n", intf.Name.Name), argsFromType(t, intf))
  571. sw.Do("if c := in.DeepCopy(); c != nil {\n", nil)
  572. sw.Do("return c\n", nil)
  573. sw.Do("}\n", nil)
  574. sw.Do("return nil\n", nil)
  575. sw.Do("}\n\n", nil)
  576. }
  577. }
  578. return sw.Error()
  579. }
  580. // isReference return true for pointer, maps, slices and aliases of those.
  581. func isReference(t *types.Type) bool {
  582. if t.Kind == types.Pointer || t.Kind == types.Map || t.Kind == types.Slice {
  583. return true
  584. }
  585. return t.Kind == types.Alias && isReference(underlyingType(t))
  586. }
  587. // we use the system of shadowing 'in' and 'out' so that the same code is valid
  588. // at any nesting level. This makes the autogenerator easy to understand, and
  589. // the compiler shouldn't care.
  590. func (g *genDeepCopy) generateFor(t *types.Type, sw *generator.SnippetWriter) {
  591. // derive inner types if t is an alias. We call the do* methods below with the alias type.
  592. // basic rule: generate according to inner type, but construct objects with the alias type.
  593. ut := underlyingType(t)
  594. var f func(*types.Type, *generator.SnippetWriter)
  595. switch ut.Kind {
  596. case types.Builtin:
  597. f = g.doBuiltin
  598. case types.Map:
  599. f = g.doMap
  600. case types.Slice:
  601. f = g.doSlice
  602. case types.Struct:
  603. f = g.doStruct
  604. case types.Pointer:
  605. f = g.doPointer
  606. case types.Interface:
  607. // interfaces are handled in-line in the other cases
  608. klog.Fatalf("Hit an interface type %v. This should never happen.", t)
  609. case types.Alias:
  610. // can never happen because we branch on the underlying type which is never an alias
  611. klog.Fatalf("Hit an alias type %v. This should never happen.", t)
  612. default:
  613. klog.Fatalf("Hit an unsupported type %v.", t)
  614. }
  615. f(t, sw)
  616. }
  617. // doBuiltin generates code for a builtin or an alias to a builtin. The generated code is
  618. // is the same for both cases, i.e. it's the code for the underlying type.
  619. func (g *genDeepCopy) doBuiltin(t *types.Type, sw *generator.SnippetWriter) {
  620. if deepCopyMethodOrDie(t) != nil || deepCopyIntoMethodOrDie(t) != nil {
  621. sw.Do("*out = in.DeepCopy()\n", nil)
  622. return
  623. }
  624. sw.Do("*out = *in\n", nil)
  625. }
  626. // doMap generates code for a map or an alias to a map. The generated code is
  627. // is the same for both cases, i.e. it's the code for the underlying type.
  628. func (g *genDeepCopy) doMap(t *types.Type, sw *generator.SnippetWriter) {
  629. ut := underlyingType(t)
  630. uet := underlyingType(ut.Elem)
  631. if deepCopyMethodOrDie(t) != nil || deepCopyIntoMethodOrDie(t) != nil {
  632. sw.Do("*out = in.DeepCopy()\n", nil)
  633. return
  634. }
  635. if !ut.Key.IsAssignable() {
  636. klog.Fatalf("Hit an unsupported type %v for: %v", uet, t)
  637. }
  638. sw.Do("*out = make($.|raw$, len(*in))\n", t)
  639. sw.Do("for key, val := range *in {\n", nil)
  640. dc, dci := deepCopyMethodOrDie(ut.Elem), deepCopyIntoMethodOrDie(ut.Elem)
  641. switch {
  642. case dc != nil || dci != nil:
  643. // Note: a DeepCopy exists because it is added if DeepCopyInto is manually defined
  644. leftPointer := ut.Elem.Kind == types.Pointer
  645. rightPointer := !isReference(ut.Elem)
  646. if dc != nil {
  647. rightPointer = dc.Results[0].Kind == types.Pointer
  648. }
  649. if leftPointer == rightPointer {
  650. sw.Do("(*out)[key] = val.DeepCopy()\n", nil)
  651. } else if leftPointer {
  652. sw.Do("x := val.DeepCopy()\n", nil)
  653. sw.Do("(*out)[key] = &x\n", nil)
  654. } else {
  655. sw.Do("(*out)[key] = *val.DeepCopy()\n", nil)
  656. }
  657. case ut.Elem.IsAnonymousStruct(): // not uet here because it needs type cast
  658. sw.Do("(*out)[key] = val\n", nil)
  659. case uet.IsAssignable():
  660. sw.Do("(*out)[key] = val\n", nil)
  661. case uet.Kind == types.Interface:
  662. // Note: do not generate code that won't compile as `DeepCopyinterface{}()` is not a valid function
  663. if uet.Name.Name == "interface{}" {
  664. klog.Fatalf("DeepCopy of %q is unsupported. Instead, use named interfaces with DeepCopy<named-interface> as one of the methods.", uet.Name.Name)
  665. }
  666. sw.Do("if val == nil {(*out)[key]=nil} else {\n", nil)
  667. // Note: if t.Elem has been an alias "J" of an interface "I" in Go, we will see it
  668. // as kind Interface of name "J" here, i.e. generate val.DeepCopyJ(). The golang
  669. // parser does not give us the underlying interface name. So we cannot do any better.
  670. sw.Do(fmt.Sprintf("(*out)[key] = val.DeepCopy%s()\n", uet.Name.Name), nil)
  671. sw.Do("}\n", nil)
  672. case uet.Kind == types.Slice || uet.Kind == types.Map || uet.Kind == types.Pointer:
  673. sw.Do("var outVal $.|raw$\n", uet)
  674. sw.Do("if val == nil { (*out)[key] = nil } else {\n", nil)
  675. sw.Do("in, out := &val, &outVal\n", uet)
  676. g.generateFor(ut.Elem, sw)
  677. sw.Do("}\n", nil)
  678. sw.Do("(*out)[key] = outVal\n", nil)
  679. case uet.Kind == types.Struct:
  680. sw.Do("(*out)[key] = *val.DeepCopy()\n", uet)
  681. default:
  682. klog.Fatalf("Hit an unsupported type %v for %v", uet, t)
  683. }
  684. sw.Do("}\n", nil)
  685. }
  686. // doSlice generates code for a slice or an alias to a slice. The generated code is
  687. // is the same for both cases, i.e. it's the code for the underlying type.
  688. func (g *genDeepCopy) doSlice(t *types.Type, sw *generator.SnippetWriter) {
  689. ut := underlyingType(t)
  690. uet := underlyingType(ut.Elem)
  691. if deepCopyMethodOrDie(t) != nil || deepCopyIntoMethodOrDie(t) != nil {
  692. sw.Do("*out = in.DeepCopy()\n", nil)
  693. return
  694. }
  695. sw.Do("*out = make($.|raw$, len(*in))\n", t)
  696. if deepCopyMethodOrDie(ut.Elem) != nil || deepCopyIntoMethodOrDie(ut.Elem) != nil {
  697. sw.Do("for i := range *in {\n", nil)
  698. // Note: a DeepCopyInto exists because it is added if DeepCopy is manually defined
  699. sw.Do("(*in)[i].DeepCopyInto(&(*out)[i])\n", nil)
  700. sw.Do("}\n", nil)
  701. } else if uet.Kind == types.Builtin || uet.IsAssignable() {
  702. sw.Do("copy(*out, *in)\n", nil)
  703. } else {
  704. sw.Do("for i := range *in {\n", nil)
  705. if uet.Kind == types.Slice || uet.Kind == types.Map || uet.Kind == types.Pointer || deepCopyMethodOrDie(ut.Elem) != nil || deepCopyIntoMethodOrDie(ut.Elem) != nil {
  706. sw.Do("if (*in)[i] != nil {\n", nil)
  707. sw.Do("in, out := &(*in)[i], &(*out)[i]\n", nil)
  708. g.generateFor(ut.Elem, sw)
  709. sw.Do("}\n", nil)
  710. } else if uet.Kind == types.Interface {
  711. // Note: do not generate code that won't compile as `DeepCopyinterface{}()` is not a valid function
  712. if uet.Name.Name == "interface{}" {
  713. klog.Fatalf("DeepCopy of %q is unsupported. Instead, use named interfaces with DeepCopy<named-interface> as one of the methods.", uet.Name.Name)
  714. }
  715. sw.Do("if (*in)[i] != nil {\n", nil)
  716. // Note: if t.Elem has been an alias "J" of an interface "I" in Go, we will see it
  717. // as kind Interface of name "J" here, i.e. generate val.DeepCopyJ(). The golang
  718. // parser does not give us the underlying interface name. So we cannot do any better.
  719. sw.Do(fmt.Sprintf("(*out)[i] = (*in)[i].DeepCopy%s()\n", uet.Name.Name), nil)
  720. sw.Do("}\n", nil)
  721. } else if uet.Kind == types.Struct {
  722. sw.Do("(*in)[i].DeepCopyInto(&(*out)[i])\n", nil)
  723. } else {
  724. klog.Fatalf("Hit an unsupported type %v for %v", uet, t)
  725. }
  726. sw.Do("}\n", nil)
  727. }
  728. }
  729. // doStruct generates code for a struct or an alias to a struct. The generated code is
  730. // is the same for both cases, i.e. it's the code for the underlying type.
  731. func (g *genDeepCopy) doStruct(t *types.Type, sw *generator.SnippetWriter) {
  732. ut := underlyingType(t)
  733. if deepCopyMethodOrDie(t) != nil || deepCopyIntoMethodOrDie(t) != nil {
  734. sw.Do("*out = in.DeepCopy()\n", nil)
  735. return
  736. }
  737. // Simple copy covers a lot of cases.
  738. sw.Do("*out = *in\n", nil)
  739. // Now fix-up fields as needed.
  740. for _, m := range ut.Members {
  741. ft := m.Type
  742. uft := underlyingType(ft)
  743. args := generator.Args{
  744. "type": ft,
  745. "kind": ft.Kind,
  746. "name": m.Name,
  747. }
  748. dc, dci := deepCopyMethodOrDie(ft), deepCopyIntoMethodOrDie(ft)
  749. switch {
  750. case dc != nil || dci != nil:
  751. // Note: a DeepCopyInto exists because it is added if DeepCopy is manually defined
  752. leftPointer := ft.Kind == types.Pointer
  753. rightPointer := !isReference(ft)
  754. if dc != nil {
  755. rightPointer = dc.Results[0].Kind == types.Pointer
  756. }
  757. if leftPointer == rightPointer {
  758. sw.Do("out.$.name$ = in.$.name$.DeepCopy()\n", args)
  759. } else if leftPointer {
  760. sw.Do("x := in.$.name$.DeepCopy()\n", args)
  761. sw.Do("out.$.name$ = = &x\n", args)
  762. } else {
  763. sw.Do("in.$.name$.DeepCopyInto(&out.$.name$)\n", args)
  764. }
  765. case uft.Kind == types.Builtin:
  766. // the initial *out = *in was enough
  767. case uft.Kind == types.Map, uft.Kind == types.Slice, uft.Kind == types.Pointer:
  768. // Fixup non-nil reference-semantic types.
  769. sw.Do("if in.$.name$ != nil {\n", args)
  770. sw.Do("in, out := &in.$.name$, &out.$.name$\n", args)
  771. g.generateFor(ft, sw)
  772. sw.Do("}\n", nil)
  773. case uft.Kind == types.Struct:
  774. if ft.IsAssignable() {
  775. sw.Do("out.$.name$ = in.$.name$\n", args)
  776. } else {
  777. sw.Do("in.$.name$.DeepCopyInto(&out.$.name$)\n", args)
  778. }
  779. case uft.Kind == types.Interface:
  780. // Note: do not generate code that won't compile as `DeepCopyinterface{}()` is not a valid function
  781. if uft.Name.Name == "interface{}" {
  782. klog.Fatalf("DeepCopy of %q is unsupported. Instead, use named interfaces with DeepCopy<named-interface> as one of the methods.", uft.Name.Name)
  783. }
  784. sw.Do("if in.$.name$ != nil {\n", args)
  785. // Note: if t.Elem has been an alias "J" of an interface "I" in Go, we will see it
  786. // as kind Interface of name "J" here, i.e. generate val.DeepCopyJ(). The golang
  787. // parser does not give us the underlying interface name. So we cannot do any better.
  788. sw.Do(fmt.Sprintf("out.$.name$ = in.$.name$.DeepCopy%s()\n", uft.Name.Name), args)
  789. sw.Do("}\n", nil)
  790. default:
  791. klog.Fatalf("Hit an unsupported type %v for %v, from %v", uft, ft, t)
  792. }
  793. }
  794. }
  795. // doPointer generates code for a pointer or an alias to a pointer. The generated code is
  796. // is the same for both cases, i.e. it's the code for the underlying type.
  797. func (g *genDeepCopy) doPointer(t *types.Type, sw *generator.SnippetWriter) {
  798. ut := underlyingType(t)
  799. uet := underlyingType(ut.Elem)
  800. dc, dci := deepCopyMethodOrDie(ut.Elem), deepCopyIntoMethodOrDie(ut.Elem)
  801. switch {
  802. case dc != nil || dci != nil:
  803. rightPointer := !isReference(ut.Elem)
  804. if dc != nil {
  805. rightPointer = dc.Results[0].Kind == types.Pointer
  806. }
  807. if rightPointer {
  808. sw.Do("*out = (*in).DeepCopy()\n", nil)
  809. } else {
  810. sw.Do("x := (*in).DeepCopy()\n", nil)
  811. sw.Do("*out = &x\n", nil)
  812. }
  813. case uet.IsAssignable():
  814. sw.Do("*out = new($.Elem|raw$)\n", ut)
  815. sw.Do("**out = **in", nil)
  816. case uet.Kind == types.Map, uet.Kind == types.Slice, uet.Kind == types.Pointer:
  817. sw.Do("*out = new($.Elem|raw$)\n", ut)
  818. sw.Do("if **in != nil {\n", nil)
  819. sw.Do("in, out := *in, *out\n", nil)
  820. g.generateFor(uet, sw)
  821. sw.Do("}\n", nil)
  822. case uet.Kind == types.Struct:
  823. sw.Do("*out = new($.Elem|raw$)\n", ut)
  824. sw.Do("(*in).DeepCopyInto(*out)\n", nil)
  825. default:
  826. klog.Fatalf("Hit an unsupported type %v for %v", uet, t)
  827. }
  828. }