deepcopy.go 29 KB

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