sets.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  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 has the generators for the set-gen utility.
  14. package generators
  15. import (
  16. "io"
  17. "k8s.io/gengo/args"
  18. "k8s.io/gengo/generator"
  19. "k8s.io/gengo/namer"
  20. "k8s.io/gengo/types"
  21. "k8s.io/klog"
  22. )
  23. // NameSystems returns the name system used by the generators in this package.
  24. func NameSystems() namer.NameSystems {
  25. return namer.NameSystems{
  26. "public": namer.NewPublicNamer(0),
  27. "private": namer.NewPrivateNamer(0),
  28. "raw": namer.NewRawNamer("", nil),
  29. }
  30. }
  31. // DefaultNameSystem returns the default name system for ordering the types to be
  32. // processed by the generators in this package.
  33. func DefaultNameSystem() string {
  34. return "public"
  35. }
  36. // Packages makes the sets package definition.
  37. func Packages(_ *generator.Context, arguments *args.GeneratorArgs) generator.Packages {
  38. boilerplate, err := arguments.LoadGoBoilerplate()
  39. if err != nil {
  40. klog.Fatalf("Failed loading boilerplate: %v", err)
  41. }
  42. return generator.Packages{&generator.DefaultPackage{
  43. PackageName: "sets",
  44. PackagePath: arguments.OutputPackagePath,
  45. HeaderText: boilerplate,
  46. PackageDocumentation: []byte(
  47. `// Package sets has auto-generated set types.
  48. `),
  49. // GeneratorFunc returns a list of generators. Each generator makes a
  50. // single file.
  51. GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
  52. generators = []generator.Generator{
  53. // Always generate a "doc.go" file.
  54. generator.DefaultGen{OptionalName: "doc"},
  55. // Make a separate file for the Empty type, since it's shared by every type.
  56. generator.DefaultGen{
  57. OptionalName: "empty",
  58. OptionalBody: []byte(emptyTypeDecl),
  59. },
  60. }
  61. // Since we want a file per type that we generate a set for, we
  62. // have to provide a function for this.
  63. for _, t := range c.Order {
  64. generators = append(generators, &genSet{
  65. DefaultGen: generator.DefaultGen{
  66. // Use the privatized version of the
  67. // type name as the file name.
  68. //
  69. // TODO: make a namer that converts
  70. // camelCase to '-' separation for file
  71. // names?
  72. OptionalName: c.Namers["private"].Name(t),
  73. },
  74. outputPackage: arguments.OutputPackagePath,
  75. typeToMatch: t,
  76. imports: generator.NewImportTracker(),
  77. })
  78. }
  79. return generators
  80. },
  81. FilterFunc: func(c *generator.Context, t *types.Type) bool {
  82. // It would be reasonable to filter by the type's package here.
  83. // It might be necessary if your input directory has a big
  84. // import graph.
  85. switch t.Kind {
  86. case types.Map, types.Slice, types.Pointer:
  87. // These types can't be keys in a map.
  88. return false
  89. case types.Builtin:
  90. return true
  91. case types.Struct:
  92. // Only some structs can be keys in a map. This is triggered by the line
  93. // // +genset
  94. // or
  95. // // +genset=true
  96. return extractBoolTagOrDie("genset", t.CommentLines) == true
  97. }
  98. return false
  99. },
  100. }}
  101. }
  102. // genSet produces a file with a set for a single type.
  103. type genSet struct {
  104. generator.DefaultGen
  105. outputPackage string
  106. typeToMatch *types.Type
  107. imports namer.ImportTracker
  108. }
  109. // Filter ignores all but one type because we're making a single file per type.
  110. func (g *genSet) Filter(c *generator.Context, t *types.Type) bool { return t == g.typeToMatch }
  111. func (g *genSet) Namers(c *generator.Context) namer.NameSystems {
  112. return namer.NameSystems{
  113. "raw": namer.NewRawNamer(g.outputPackage, g.imports),
  114. }
  115. }
  116. func (g *genSet) Imports(c *generator.Context) (imports []string) {
  117. return append(g.imports.ImportLines(), "reflect", "sort")
  118. }
  119. // args constructs arguments for templates. Usage:
  120. // g.args(t, "key1", value1, "key2", value2, ...)
  121. //
  122. // 't' is loaded with the key 'type'.
  123. //
  124. // We could use t directly as the argument, but doing it this way makes it easy
  125. // to mix in additional parameters. This feature is not used in this set
  126. // generator, but is present as an example.
  127. func (g *genSet) args(t *types.Type, kv ...interface{}) interface{} {
  128. m := map[interface{}]interface{}{"type": t}
  129. for i := 0; i < len(kv)/2; i++ {
  130. m[kv[i*2]] = kv[i*2+1]
  131. }
  132. return m
  133. }
  134. // GenerateType makes the body of a file implementing a set for type t.
  135. func (g *genSet) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
  136. sw := generator.NewSnippetWriter(w, c, "$", "$")
  137. sw.Do(setCode, g.args(t))
  138. sw.Do("func less$.type|public$(lhs, rhs $.type|raw$) bool {\n", g.args(t))
  139. g.lessBody(sw, t)
  140. sw.Do("}\n", g.args(t))
  141. return sw.Error()
  142. }
  143. func (g *genSet) lessBody(sw *generator.SnippetWriter, t *types.Type) {
  144. // TODO: make this recursive, handle pointers and multiple nested structs...
  145. switch t.Kind {
  146. case types.Struct:
  147. for _, m := range types.FlattenMembers(t.Members) {
  148. sw.Do("if lhs.$.Name$ < rhs.$.Name$ { return true }\n", m)
  149. sw.Do("if lhs.$.Name$ > rhs.$.Name$ { return false }\n", m)
  150. }
  151. sw.Do("return false\n", nil)
  152. default:
  153. sw.Do("return lhs < rhs\n", nil)
  154. }
  155. }
  156. // written to the "empty.go" file.
  157. var emptyTypeDecl = `
  158. // Empty is public since it is used by some internal API objects for conversions between external
  159. // string arrays and internal sets, and conversion logic requires public types today.
  160. type Empty struct{}
  161. `
  162. // Written for every type. If you've never used text/template before:
  163. // $.type$ refers to the source type; |public means to
  164. // call the function giving the public name, |raw the raw type name.
  165. var setCode = `// sets.$.type|public$ is a set of $.type|raw$s, implemented via map[$.type|raw$]struct{} for minimal memory consumption.
  166. type $.type|public$ map[$.type|raw$]Empty
  167. // New$.type|public$ creates a $.type|public$ from a list of values.
  168. func New$.type|public$(items ...$.type|raw$) $.type|public$ {
  169. ss := $.type|public${}
  170. ss.Insert(items...)
  171. return ss
  172. }
  173. // $.type|public$KeySet creates a $.type|public$ from a keys of a map[$.type|raw$](? extends interface{}).
  174. // If the value passed in is not actually a map, this will panic.
  175. func $.type|public$KeySet(theMap interface{}) $.type|public$ {
  176. v := reflect.ValueOf(theMap)
  177. ret := $.type|public${}
  178. for _, keyValue := range v.MapKeys() {
  179. ret.Insert(keyValue.Interface().($.type|raw$))
  180. }
  181. return ret
  182. }
  183. // Insert adds items to the set.
  184. func (s $.type|public$) Insert(items ...$.type|raw$) {
  185. for _, item := range items {
  186. s[item] = Empty{}
  187. }
  188. }
  189. // Delete removes all items from the set.
  190. func (s $.type|public$) Delete(items ...$.type|raw$) {
  191. for _, item := range items {
  192. delete(s, item)
  193. }
  194. }
  195. // Has returns true if and only if item is contained in the set.
  196. func (s $.type|public$) Has(item $.type|raw$) bool {
  197. _, contained := s[item]
  198. return contained
  199. }
  200. // HasAll returns true if and only if all items are contained in the set.
  201. func (s $.type|public$) HasAll(items ...$.type|raw$) bool {
  202. for _, item := range items {
  203. if !s.Has(item) {
  204. return false
  205. }
  206. }
  207. return true
  208. }
  209. // HasAny returns true if any items are contained in the set.
  210. func (s $.type|public$) HasAny(items ...$.type|raw$) bool {
  211. for _, item := range items {
  212. if s.Has(item) {
  213. return true
  214. }
  215. }
  216. return false
  217. }
  218. // Difference returns a set of objects that are not in s2
  219. // For example:
  220. // s1 = {a1, a2, a3}
  221. // s2 = {a1, a2, a4, a5}
  222. // s1.Difference(s2) = {a3}
  223. // s2.Difference(s1) = {a4, a5}
  224. func (s $.type|public$) Difference(s2 $.type|public$) $.type|public$ {
  225. result := New$.type|public$()
  226. for key := range s {
  227. if !s2.Has(key) {
  228. result.Insert(key)
  229. }
  230. }
  231. return result
  232. }
  233. // Union returns a new set which includes items in either s1 or s2.
  234. // For example:
  235. // s1 = {a1, a2}
  236. // s2 = {a3, a4}
  237. // s1.Union(s2) = {a1, a2, a3, a4}
  238. // s2.Union(s1) = {a1, a2, a3, a4}
  239. func (s1 $.type|public$) Union(s2 $.type|public$) $.type|public$ {
  240. result := New$.type|public$()
  241. for key := range s1 {
  242. result.Insert(key)
  243. }
  244. for key := range s2 {
  245. result.Insert(key)
  246. }
  247. return result
  248. }
  249. // Intersection returns a new set which includes the item in BOTH s1 and s2
  250. // For example:
  251. // s1 = {a1, a2}
  252. // s2 = {a2, a3}
  253. // s1.Intersection(s2) = {a2}
  254. func (s1 $.type|public$) Intersection(s2 $.type|public$) $.type|public$ {
  255. var walk, other $.type|public$
  256. result := New$.type|public$()
  257. if s1.Len() < s2.Len() {
  258. walk = s1
  259. other = s2
  260. } else {
  261. walk = s2
  262. other = s1
  263. }
  264. for key := range walk {
  265. if other.Has(key) {
  266. result.Insert(key)
  267. }
  268. }
  269. return result
  270. }
  271. // IsSuperset returns true if and only if s1 is a superset of s2.
  272. func (s1 $.type|public$) IsSuperset(s2 $.type|public$) bool {
  273. for item := range s2 {
  274. if !s1.Has(item) {
  275. return false
  276. }
  277. }
  278. return true
  279. }
  280. // Equal returns true if and only if s1 is equal (as a set) to s2.
  281. // Two sets are equal if their membership is identical.
  282. // (In practice, this means same elements, order doesn't matter)
  283. func (s1 $.type|public$) Equal(s2 $.type|public$) bool {
  284. return len(s1) == len(s2) && s1.IsSuperset(s2)
  285. }
  286. type sortableSliceOf$.type|public$ []$.type|raw$
  287. func (s sortableSliceOf$.type|public$) Len() int { return len(s) }
  288. func (s sortableSliceOf$.type|public$) Less(i, j int) bool { return less$.type|public$(s[i], s[j]) }
  289. func (s sortableSliceOf$.type|public$) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
  290. // List returns the contents as a sorted $.type|raw$ slice.
  291. func (s $.type|public$) List() []$.type|raw$ {
  292. res := make(sortableSliceOf$.type|public$, 0, len(s))
  293. for key := range s {
  294. res = append(res, key)
  295. }
  296. sort.Sort(res)
  297. return []$.type|raw$(res)
  298. }
  299. // UnsortedList returns the slice with contents in random order.
  300. func (s $.type|public$) UnsortedList() []$.type|raw$ {
  301. res :=make([]$.type|raw$, 0, len(s))
  302. for key := range s {
  303. res = append(res, key)
  304. }
  305. return res
  306. }
  307. // Returns a single element from the set.
  308. func (s $.type|public$) PopAny() ($.type|raw$, bool) {
  309. for key := range s {
  310. s.Delete(key)
  311. return key, true
  312. }
  313. var zeroValue $.type|raw$
  314. return zeroValue, false
  315. }
  316. // Len returns the size of the set.
  317. func (s $.type|public$) Len() int {
  318. return len(s)
  319. }
  320. `