deepcopy.go 36 KB

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