From d8531513ae9a8994a74b7e8663d3814dbb613f6b Mon Sep 17 00:00:00 2001 From: Ilya Dmitrichenko Date: Tue, 9 Oct 2018 20:32:13 +0100 Subject: [PATCH] Code generator to update `--node-type` to `--max-pods` mapping --- Gopkg.lock | 8 +- Gopkg.toml | 4 + pkg/nodebootstrap/maxpods.go | 196 +- pkg/nodebootstrap/maxpods_generate.go | 55 + pkg/nodebootstrap/userdata.go | 1 + vendor/github.com/dave/jennifer/LICENSE | 21 + vendor/github.com/dave/jennifer/jen/add.go | 19 + .../github.com/dave/jennifer/jen/comments.go | 108 + vendor/github.com/dave/jennifer/jen/custom.go | 61 + vendor/github.com/dave/jennifer/jen/dict.go | 81 + vendor/github.com/dave/jennifer/jen/do.go | 22 + vendor/github.com/dave/jennifer/jen/file.go | 250 ++ .../github.com/dave/jennifer/jen/generated.go | 2274 +++++++++++++++++ vendor/github.com/dave/jennifer/jen/group.go | 136 + vendor/github.com/dave/jennifer/jen/hints.go | 273 ++ vendor/github.com/dave/jennifer/jen/jen.go | 168 ++ vendor/github.com/dave/jennifer/jen/lit.go | 154 ++ .../github.com/dave/jennifer/jen/statement.go | 96 + vendor/github.com/dave/jennifer/jen/tag.go | 76 + vendor/github.com/dave/jennifer/jen/tokens.go | 301 +++ 20 files changed, 4248 insertions(+), 56 deletions(-) create mode 100644 pkg/nodebootstrap/maxpods_generate.go create mode 100644 vendor/github.com/dave/jennifer/LICENSE create mode 100644 vendor/github.com/dave/jennifer/jen/add.go create mode 100644 vendor/github.com/dave/jennifer/jen/comments.go create mode 100644 vendor/github.com/dave/jennifer/jen/custom.go create mode 100644 vendor/github.com/dave/jennifer/jen/dict.go create mode 100644 vendor/github.com/dave/jennifer/jen/do.go create mode 100644 vendor/github.com/dave/jennifer/jen/file.go create mode 100644 vendor/github.com/dave/jennifer/jen/generated.go create mode 100644 vendor/github.com/dave/jennifer/jen/group.go create mode 100644 vendor/github.com/dave/jennifer/jen/hints.go create mode 100644 vendor/github.com/dave/jennifer/jen/jen.go create mode 100644 vendor/github.com/dave/jennifer/jen/lit.go create mode 100644 vendor/github.com/dave/jennifer/jen/statement.go create mode 100644 vendor/github.com/dave/jennifer/jen/tag.go create mode 100644 vendor/github.com/dave/jennifer/jen/tokens.go diff --git a/Gopkg.lock b/Gopkg.lock index 0f90b96881..6a63c4bb09 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -65,6 +65,12 @@ revision = "2ee87856327ba09384cabd113bc6b5d174e9ec0f" version = "v3.5.1" +[[projects]] + name = "github.com/dave/jennifer" + packages = ["jen"] + revision = "e2c46c587b5f3cf3dec985fd8f7e8232f9e40ac9" + version = "v1.1.0" + [[projects]] name = "github.com/davecgh/go-spew" packages = ["spew"] @@ -708,6 +714,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "8f37a710e990af75161acb22465c3557aaa81950a4935935f55b4c733e234901" + inputs-digest = "2deb095b484a2de5dadeb081b93b75e7efbfef3a3a1c4cd008cd21ce24f41dc4" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 30c6f04451..3f9709098b 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -82,3 +82,7 @@ required = [ source = "https://github.com/errordeveloper/goformation" # revision = "1358de5008ca15a213cc432549977e09cd4d2beb" branch = "pin-eksctl" + +[[constraint]] + name = "github.com/dave/jennifer" + version = "v1.1.0" \ No newline at end of file diff --git a/pkg/nodebootstrap/maxpods.go b/pkg/nodebootstrap/maxpods.go index 136d122676..ba96277596 100644 --- a/pkg/nodebootstrap/maxpods.go +++ b/pkg/nodebootstrap/maxpods.go @@ -1,59 +1,145 @@ package nodebootstrap +// Generated from https://raw.github.com/awslabs/amazon-eks-ami/master/files/eni-max-pods.txt var maxPodsPerNodeType = map[string]int{ - "c4.large": 29, - "c4.xlarge": 58, - "c4.2xlarge": 58, - "c4.4xlarge": 234, - "c4.8xlarge": 234, - "c5.large": 29, - "c5.xlarge": 58, - "c5.2xlarge": 58, - "c5.4xlarge": 234, - "c5.9xlarge": 234, - "c5.18xlarge": 737, - "i3.large": 29, - "i3.xlarge": 58, - "i3.2xlarge": 58, - "i3.4xlarge": 234, - "i3.8xlarge": 234, - "i3.16xlarge": 737, - "m3.medium": 12, - "m3.large": 29, - "m3.xlarge": 58, - "m3.2xlarge": 118, - "m4.large": 20, - "m4.xlarge": 58, - "m4.2xlarge": 58, - "m4.4xlarge": 234, - "m4.10xlarge": 234, - "m5.large": 29, - "m5.xlarge": 58, - "m5.2xlarge": 58, - "m5.4xlarge": 234, - "m5.12xlarge": 234, - "m5.24xlarge": 737, - "p2.xlarge": 58, - "p2.8xlarge": 234, - "p2.16xlarge": 234, - "p3.2xlarge": 58, - "p3.8xlarge": 234, - "p3.16xlarge": 234, - "r3.xlarge": 58, - "r3.2xlarge": 58, - "r3.4xlarge": 234, - "r3.8xlarge": 234, - "r4.large": 29, - "r4.xlarge": 58, - "r4.2xlarge": 58, - "r4.4xlarge": 234, - "r4.8xlarge": 234, - "r4.16xlarge": 737, - "t2.small": 8, - "t2.medium": 17, - "t2.large": 35, - "t2.xlarge": 44, - "t2.2xlarge": 44, - "x1.16xlarge": 234, - "x1.32xlarge": 234, + "c1.medium": 12, + "c1.xlarge": 58, + "c3.2xlarge": 58, + "c3.4xlarge": 234, + "c3.8xlarge": 234, + "c3.large": 29, + "c3.xlarge": 58, + "c4.2xlarge": 58, + "c4.4xlarge": 234, + "c4.8xlarge": 234, + "c4.large": 29, + "c4.xlarge": 58, + "c5.18xlarge": 737, + "c5.2xlarge": 58, + "c5.4xlarge": 234, + "c5.9xlarge": 234, + "c5.large": 29, + "c5.xlarge": 58, + "c5d.18xlarge": 737, + "c5d.2xlarge": 58, + "c5d.4xlarge": 234, + "c5d.9xlarge": 234, + "c5d.large": 29, + "c5d.xlarge": 58, + "cc2.8xlarge": 234, + "cr1.8xlarge": 234, + "d2.2xlarge": 58, + "d2.4xlarge": 234, + "d2.8xlarge": 234, + "d2.xlarge": 58, + "f1.16xlarge": 394, + "f1.2xlarge": 58, + "g2.2xlarge": 58, + "g2.8xlarge": 234, + "g3.16xlarge": 737, + "g3.4xlarge": 234, + "g3.8xlarge": 234, + "h1.16xlarge": 737, + "h1.2xlarge": 58, + "h1.4xlarge": 234, + "h1.8xlarge": 234, + "hs1.8xlarge": 234, + "i2.2xlarge": 58, + "i2.4xlarge": 234, + "i2.8xlarge": 234, + "i2.xlarge": 58, + "i3.16xlarge": 737, + "i3.2xlarge": 58, + "i3.4xlarge": 234, + "i3.8xlarge": 234, + "i3.large": 29, + "i3.metal": 737, + "i3.xlarge": 58, + "m1.large": 29, + "m1.medium": 12, + "m1.small": 8, + "m1.xlarge": 58, + "m2.2xlarge": 118, + "m2.4xlarge": 234, + "m2.xlarge": 58, + "m3.2xlarge": 118, + "m3.large": 29, + "m3.medium": 12, + "m3.xlarge": 58, + "m4.10xlarge": 234, + "m4.16xlarge": 234, + "m4.2xlarge": 58, + "m4.4xlarge": 234, + "m4.large": 20, + "m4.xlarge": 58, + "m5.12xlarge": 234, + "m5.24xlarge": 737, + "m5.2xlarge": 58, + "m5.4xlarge": 234, + "m5.large": 29, + "m5.xlarge": 58, + "m5d.12xlarge": 234, + "m5d.24xlarge": 737, + "m5d.2xlarge": 58, + "m5d.4xlarge": 234, + "m5d.large": 29, + "m5d.xlarge": 58, + "p2.16xlarge": 234, + "p2.8xlarge": 234, + "p2.xlarge": 58, + "p3.16xlarge": 234, + "p3.2xlarge": 58, + "p3.8xlarge": 234, + "r3.2xlarge": 58, + "r3.4xlarge": 234, + "r3.8xlarge": 234, + "r3.large": 29, + "r3.xlarge": 58, + "r4.16xlarge": 737, + "r4.2xlarge": 58, + "r4.4xlarge": 234, + "r4.8xlarge": 234, + "r4.large": 29, + "r4.xlarge": 58, + "r5.12xlarge": 234, + "r5.24xlarge": 737, + "r5.2xlarge": 58, + "r5.4xlarge": 234, + "r5.large": 29, + "r5.xlarge": 58, + "r5d.12xlarge": 234, + "r5d.24xlarge": 737, + "r5d.2xlarge": 58, + "r5d.4xlarge": 234, + "r5d.large": 29, + "r5d.xlarge": 58, + "t1.micro": 4, + "t2.2xlarge": 44, + "t2.large": 35, + "t2.medium": 17, + "t2.micro": 4, + "t2.nano": 4, + "t2.small": 8, + "t2.xlarge": 44, + "t3.2xlarge": 44, + "t3.large": 35, + "t3.medium": 17, + "t3.micro": 4, + "t3.nano": 4, + "t3.small": 8, + "t3.xlarge": 44, + "x1.16xlarge": 234, + "x1.32xlarge": 234, + "x1e.16xlarge": 234, + "x1e.2xlarge": 58, + "x1e.32xlarge": 234, + "x1e.4xlarge": 58, + "x1e.8xlarge": 58, + "x1e.xlarge": 29, + "z1d.12xlarge": 737, + "z1d.2xlarge": 58, + "z1d.3xlarge": 234, + "z1d.6xlarge": 234, + "z1d.large": 29, + "z1d.xlarge": 58, } diff --git a/pkg/nodebootstrap/maxpods_generate.go b/pkg/nodebootstrap/maxpods_generate.go new file mode 100644 index 0000000000..7a52267d39 --- /dev/null +++ b/pkg/nodebootstrap/maxpods_generate.go @@ -0,0 +1,55 @@ +//+build ignore + +package main + +import ( + "io/ioutil" + "log" + "strconv" + "strings" + + "net/http" + + . "github.com/dave/jennifer/jen" +) + +const maxPodsPerNodeTypeSourceText = "https://raw.github.com/awslabs/amazon-eks-ami/master/files/eni-max-pods.txt" + +func main() { + f := NewFile("nodebootstrap") + + f.Comment("Generated from " + maxPodsPerNodeTypeSourceText) + + d := Dict{} + + resp, err := http.Get(maxPodsPerNodeTypeSourceText) + if err != nil { + log.Fatal(err.Error()) + } + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Fatal(err.Error()) + } + + for _, line := range strings.Split(string(body), "\n") { + if !strings.HasPrefix(line, "#") { + parts := strings.Split(line, " ") + if len(parts) == 2 { + k := Lit(parts[0]) + v, err := strconv.Atoi(parts[1]) + if err != nil { + log.Fatal(err.Error()) + } + d[k] = Lit(v) + } + } + } + + f.Var().Id("maxPodsPerNodeType").Op("="). + Map(String()).Int().Values(d) + + if err := f.Save("maxpods.go"); err != nil { + log.Fatal(err.Error()) + } +} diff --git a/pkg/nodebootstrap/userdata.go b/pkg/nodebootstrap/userdata.go index 35a040aa24..66b6a851da 100644 --- a/pkg/nodebootstrap/userdata.go +++ b/pkg/nodebootstrap/userdata.go @@ -16,6 +16,7 @@ import ( ) //go:generate ${GOPATH}/bin/go-bindata -pkg ${GOPACKAGE} -prefix assets -modtime 1 -o assets.go assets +//go:generate go run ./maxpods_generate.go const ( configDir = "/etc/eksctl/" diff --git a/vendor/github.com/dave/jennifer/LICENSE b/vendor/github.com/dave/jennifer/LICENSE new file mode 100644 index 0000000000..17ab1cede8 --- /dev/null +++ b/vendor/github.com/dave/jennifer/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 David Brophy + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/dave/jennifer/jen/add.go b/vendor/github.com/dave/jennifer/jen/add.go new file mode 100644 index 0000000000..2efb3f6da2 --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/add.go @@ -0,0 +1,19 @@ +package jen + +// Add appends the provided items to the statement. +func Add(code ...Code) *Statement { + return newStatement().Add(code...) +} + +// Add appends the provided items to the statement. +func (g *Group) Add(code ...Code) *Statement { + s := Add(code...) + g.items = append(g.items, s) + return s +} + +// Add appends the provided items to the statement. +func (s *Statement) Add(code ...Code) *Statement { + *s = append(*s, code...) + return s +} diff --git a/vendor/github.com/dave/jennifer/jen/comments.go b/vendor/github.com/dave/jennifer/jen/comments.go new file mode 100644 index 0000000000..886e885b49 --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/comments.go @@ -0,0 +1,108 @@ +package jen + +import ( + "fmt" + "io" + "strings" +) + +// Comment adds a comment. If the provided string contains a newline, the +// comment is formatted in multiline style. If the comment string starts +// with "//" or "/*", the automatic formatting is disabled and the string is +// rendered directly. +func Comment(str string) *Statement { + return newStatement().Comment(str) +} + +// Comment adds a comment. If the provided string contains a newline, the +// comment is formatted in multiline style. If the comment string starts +// with "//" or "/*", the automatic formatting is disabled and the string is +// rendered directly. +func (g *Group) Comment(str string) *Statement { + s := Comment(str) + g.items = append(g.items, s) + return s +} + +// Comment adds a comment. If the provided string contains a newline, the +// comment is formatted in multiline style. If the comment string starts +// with "//" or "/*", the automatic formatting is disabled and the string is +// rendered directly. +func (s *Statement) Comment(str string) *Statement { + c := comment{ + comment: str, + } + *s = append(*s, c) + return s +} + +// Commentf adds a comment, using a format string and a list of parameters. If +// the provided string contains a newline, the comment is formatted in +// multiline style. If the comment string starts with "//" or "/*", the +// automatic formatting is disabled and the string is rendered directly. +func Commentf(format string, a ...interface{}) *Statement { + return newStatement().Commentf(format, a...) +} + +// Commentf adds a comment, using a format string and a list of parameters. If +// the provided string contains a newline, the comment is formatted in +// multiline style. If the comment string starts with "//" or "/*", the +// automatic formatting is disabled and the string is rendered directly. +func (g *Group) Commentf(format string, a ...interface{}) *Statement { + s := Commentf(format, a...) + g.items = append(g.items, s) + return s +} + +// Commentf adds a comment, using a format string and a list of parameters. If +// the provided string contains a newline, the comment is formatted in +// multiline style. If the comment string starts with "//" or "/*", the +// automatic formatting is disabled and the string is rendered directly. +func (s *Statement) Commentf(format string, a ...interface{}) *Statement { + c := comment{ + comment: fmt.Sprintf(format, a...), + } + *s = append(*s, c) + return s +} + +type comment struct { + comment string +} + +func (c comment) isNull(f *File) bool { + return false +} + +func (c comment) render(f *File, w io.Writer, s *Statement) error { + if strings.HasPrefix(c.comment, "//") || strings.HasPrefix(c.comment, "/*") { + // automatic formatting disabled. + if _, err := w.Write([]byte(c.comment)); err != nil { + return err + } + return nil + } + if strings.Contains(c.comment, "\n") { + if _, err := w.Write([]byte("/*\n")); err != nil { + return err + } + } else { + if _, err := w.Write([]byte("// ")); err != nil { + return err + } + } + if _, err := w.Write([]byte(c.comment)); err != nil { + return err + } + if strings.Contains(c.comment, "\n") { + if !strings.HasSuffix(c.comment, "\n") { + if _, err := w.Write([]byte("\n")); err != nil { + return err + } + } + if _, err := w.Write([]byte("*/")); err != nil { + return err + } + } + return nil +} diff --git a/vendor/github.com/dave/jennifer/jen/custom.go b/vendor/github.com/dave/jennifer/jen/custom.go new file mode 100644 index 0000000000..4966a07029 --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/custom.go @@ -0,0 +1,61 @@ +package jen + +// Options specifies options for the Custom method +type Options struct { + Open string + Close string + Separator string + Multi bool +} + +// Custom renders a customized statement list. Pass in options to specify multi-line, and tokens for open, close, separator. +func Custom(options Options, statements ...Code) *Statement { + return newStatement().Custom(options, statements...) +} + +// Custom renders a customized statement list. Pass in options to specify multi-line, and tokens for open, close, separator. +func (g *Group) Custom(options Options, statements ...Code) *Statement { + s := Custom(options, statements...) + g.items = append(g.items, s) + return s +} + +// Custom renders a customized statement list. Pass in options to specify multi-line, and tokens for open, close, separator. +func (s *Statement) Custom(options Options, statements ...Code) *Statement { + g := &Group{ + close: options.Close, + items: statements, + multi: options.Multi, + name: "custom", + open: options.Open, + separator: options.Separator, + } + *s = append(*s, g) + return s +} + +// CustomFunc renders a customized statement list. Pass in options to specify multi-line, and tokens for open, close, separator. +func CustomFunc(options Options, f func(*Group)) *Statement { + return newStatement().CustomFunc(options, f) +} + +// CustomFunc renders a customized statement list. Pass in options to specify multi-line, and tokens for open, close, separator. +func (g *Group) CustomFunc(options Options, f func(*Group)) *Statement { + s := CustomFunc(options, f) + g.items = append(g.items, s) + return s +} + +// CustomFunc renders a customized statement list. Pass in options to specify multi-line, and tokens for open, close, separator. +func (s *Statement) CustomFunc(options Options, f func(*Group)) *Statement { + g := &Group{ + close: options.Close, + multi: options.Multi, + name: "custom", + open: options.Open, + separator: options.Separator, + } + f(g) + *s = append(*s, g) + return s +} diff --git a/vendor/github.com/dave/jennifer/jen/dict.go b/vendor/github.com/dave/jennifer/jen/dict.go new file mode 100644 index 0000000000..260cf928ae --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/dict.go @@ -0,0 +1,81 @@ +package jen + +import ( + "bytes" + "io" + "sort" +) + +// Dict renders as key/value pairs. Use with Values for map or composite +// literals. +type Dict map[Code]Code + +// DictFunc executes a func(Dict) to generate the value. Use with Values for +// map or composite literals. +func DictFunc(f func(Dict)) Dict { + d := Dict{} + f(d) + return d +} + +func (d Dict) render(f *File, w io.Writer, s *Statement) error { + first := true + // must order keys to ensure repeatable source + type kv struct { + k Code + v Code + } + lookup := map[string]kv{} + keys := []string{} + for k, v := range d { + if k.isNull(f) || v.isNull(f) { + continue + } + buf := &bytes.Buffer{} + if err := k.render(f, buf, nil); err != nil { + return err + } + keys = append(keys, buf.String()) + lookup[buf.String()] = kv{k: k, v: v} + } + sort.Strings(keys) + for _, key := range keys { + k := lookup[key].k + v := lookup[key].v + if first && len(keys) > 1 { + if _, err := w.Write([]byte("\n")); err != nil { + return err + } + first = false + } + if err := k.render(f, w, nil); err != nil { + return err + } + if _, err := w.Write([]byte(":")); err != nil { + return err + } + if err := v.render(f, w, nil); err != nil { + return err + } + if len(keys) > 1 { + if _, err := w.Write([]byte(",\n")); err != nil { + return err + } + } + } + return nil +} + +func (d Dict) isNull(f *File) bool { + if d == nil || len(d) == 0 { + return true + } + for k, v := range d { + if !k.isNull(f) && !v.isNull(f) { + // if any of the key/value pairs are both not null, the Dict is not + // null + return false + } + } + return true +} diff --git a/vendor/github.com/dave/jennifer/jen/do.go b/vendor/github.com/dave/jennifer/jen/do.go new file mode 100644 index 0000000000..c1bceab5ab --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/do.go @@ -0,0 +1,22 @@ +package jen + +// Do calls the provided function with the statement as a parameter. Use for +// embedding logic. +func Do(f func(*Statement)) *Statement { + return newStatement().Do(f) +} + +// Do calls the provided function with the statement as a parameter. Use for +// embedding logic. +func (g *Group) Do(f func(*Statement)) *Statement { + s := Do(f) + g.items = append(g.items, s) + return s +} + +// Do calls the provided function with the statement as a parameter. Use for +// embedding logic. +func (s *Statement) Do(f func(*Statement)) *Statement { + f(s) + return s +} diff --git a/vendor/github.com/dave/jennifer/jen/file.go b/vendor/github.com/dave/jennifer/jen/file.go new file mode 100644 index 0000000000..2ee775066c --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/file.go @@ -0,0 +1,250 @@ +package jen + +import ( + "bytes" + "fmt" + "regexp" + "strings" +) + +// NewFile Creates a new file, with the specified package name. +func NewFile(packageName string) *File { + return &File{ + Group: &Group{ + multi: true, + }, + name: packageName, + imports: map[string]importdef{}, + hints: map[string]importdef{}, + } +} + +// NewFilePath creates a new file while specifying the package path - the +// package name is inferred from the path. +func NewFilePath(packagePath string) *File { + return &File{ + Group: &Group{ + multi: true, + }, + name: guessAlias(packagePath), + path: packagePath, + imports: map[string]importdef{}, + hints: map[string]importdef{}, + } +} + +// NewFilePathName creates a new file with the specified package path and name. +func NewFilePathName(packagePath, packageName string) *File { + return &File{ + Group: &Group{ + multi: true, + }, + name: packageName, + path: packagePath, + imports: map[string]importdef{}, + hints: map[string]importdef{}, + } +} + +// File represents a single source file. Package imports are managed +// automaticaly by File. +type File struct { + *Group + name string + path string + imports map[string]importdef + hints map[string]importdef + comments []string + headers []string + cgoPreamble []string + // If you're worried about generated package aliases conflicting with local variable names, you + // can set a prefix here. Package foo becomes {prefix}_foo. + PackagePrefix string + // CanonicalPath adds a canonical import path annotation to the package clause. + CanonicalPath string +} + +// importdef is used to differentiate packages where we know the package name from packages where the +// import is aliased. If alias == false, then name is the actual package name, and the import will be +// rendered without an alias. If used == false, the import has not been used in code yet and should be +// excluded from the import block. +type importdef struct { + name string + alias bool +} + +// HeaderComment adds a comment to the top of the file, above any package +// comments. A blank line is rendered below the header comments, ensuring +// header comments are not included in the package doc. +func (f *File) HeaderComment(comment string) { + f.headers = append(f.headers, comment) +} + +// PackageComment adds a comment to the top of the file, above the package +// keyword. +func (f *File) PackageComment(comment string) { + f.comments = append(f.comments, comment) +} + +// CgoPreamble adds a cgo preamble comment that is rendered directly before the "C" pseudo-package +// import. +func (f *File) CgoPreamble(comment string) { + f.cgoPreamble = append(f.cgoPreamble, comment) +} + +// Anon adds an anonymous import. +func (f *File) Anon(paths ...string) { + for _, p := range paths { + f.imports[p] = importdef{name: "_", alias: true} + } +} + +// ImportName provides the package name for a path. If specified, the alias will be omitted from the +// import block. This is optional. If not specified, a sensible package name is used based on the path +// and this is added as an alias in the import block. +func (f *File) ImportName(path, name string) { + f.hints[path] = importdef{name: name, alias: false} +} + +// ImportNames allows multiple names to be imported as a map. Use the [gennames](gennames) command to +// automatically generate a go file containing a map of a selection of package names. +func (f *File) ImportNames(names map[string]string) { + for path, name := range names { + f.hints[path] = importdef{name: name, alias: false} + } +} + +// ImportAlias provides the alias for a package path that should be used in the import block. +func (f *File) ImportAlias(path, alias string) { + f.hints[path] = importdef{name: alias, alias: true} +} + +func (f *File) isLocal(path string) bool { + return f.path == path +} + +var reserved = []string{ + /* keywords */ + "break", "default", "func", "interface", "select", "case", "defer", "go", "map", "struct", "chan", "else", "goto", "package", "switch", "const", "fallthrough", "if", "range", "type", "continue", "for", "import", "return", "var", + /* predeclared */ + "bool", "byte", "complex64", "complex128", "error", "float32", "float64", "int", "int8", "int16", "int32", "int64", "rune", "string", "uint", "uint8", "uint16", "uint32", "uint64", "uintptr", "true", "false", "iota", "nil", "append", "cap", "close", "complex", "copy", "delete", "imag", "len", "make", "new", "panic", "print", "println", "real", "recover", + /* common variables */ + "err", +} + +func isReservedWord(alias string) bool { + for _, name := range reserved { + if alias == name { + return true + } + } + return false +} + +func (f *File) isValidAlias(alias string) bool { + // the import alias is invalid if it's a reserved word + if isReservedWord(alias) { + return false + } + // the import alias is invalid if it's already been registered + for _, v := range f.imports { + if alias == v.name { + return false + } + } + return true +} + +func (f *File) register(path string) string { + if f.isLocal(path) { + // notest + // should never get here becasue in Qual the packageToken will be null, + // so render will never be called. + return "" + } + + // if the path has been registered previously, simply return the name + def := f.imports[path] + if def.name != "" && def.name != "_" { + return def.name + } + + // special case for "C" pseudo-package + if path == "C" { + f.imports["C"] = importdef{name: "C", alias: false} + return "C" + } + + var name string + var alias bool + + if hint := f.hints[path]; hint.name != "" { + // look up the path in the list of provided package names and aliases by ImportName / ImportAlias + name = hint.name + alias = hint.alias + } else if standardLibraryHints[path] != "" { + // look up the path in the list of standard library packages + name = standardLibraryHints[path] + alias = false + } else { + // if a hint is not found for the package, guess the alias from the package path + name = guessAlias(path) + alias = true + } + + // If the name is invalid or has been registered already, make it unique by appending a number + unique := name + i := 0 + for !f.isValidAlias(unique) { + i++ + unique = fmt.Sprintf("%s%d", name, i) + } + + // If we've changed the name to make it unique, it should definitely be an alias + if unique != name { + alias = true + } + + // Only add a prefix if the name is an alias + if f.PackagePrefix != "" && alias { + unique = f.PackagePrefix + "_" + unique + } + + // Register the eventual name + f.imports[path] = importdef{name: unique, alias: alias} + + return unique +} + +// GoString renders the File for testing. Any error will cause a panic. +func (f *File) GoString() string { + buf := &bytes.Buffer{} + if err := f.Render(buf); err != nil { + panic(err) + } + return buf.String() +} + +func guessAlias(path string) string { + alias := path + + if strings.HasSuffix(alias, "/") { + // training slashes are usually tolerated, so we can get rid of one if + // it exists + alias = alias[:len(alias)-1] + } + + if strings.Contains(alias, "/") { + // if the path contains a "/", use the last part + alias = alias[strings.LastIndex(alias, "/")+1:] + } + + // alias should be lower case + alias = strings.ToLower(alias) + + // alias should now only contain alphanumerics + importsRegex := regexp.MustCompile(`[^a-z0-9]`) + alias = importsRegex.ReplaceAllString(alias, "") + + return alias +} diff --git a/vendor/github.com/dave/jennifer/jen/generated.go b/vendor/github.com/dave/jennifer/jen/generated.go new file mode 100644 index 0000000000..3983cf97c8 --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/generated.go @@ -0,0 +1,2274 @@ +// This file is generated - do not edit. + +package jen + +// Parens renders a single item in parenthesis. Use for type conversion or to specify evaluation order. +func Parens(item Code) *Statement { + return newStatement().Parens(item) +} + +// Parens renders a single item in parenthesis. Use for type conversion or to specify evaluation order. +func (g *Group) Parens(item Code) *Statement { + s := Parens(item) + g.items = append(g.items, s) + return s +} + +// Parens renders a single item in parenthesis. Use for type conversion or to specify evaluation order. +func (s *Statement) Parens(item Code) *Statement { + g := &Group{ + close: ")", + items: []Code{item}, + multi: false, + name: "parens", + open: "(", + separator: "", + } + *s = append(*s, g) + return s +} + +// List renders a comma separated list. Use for multiple return functions. +func List(items ...Code) *Statement { + return newStatement().List(items...) +} + +// List renders a comma separated list. Use for multiple return functions. +func (g *Group) List(items ...Code) *Statement { + s := List(items...) + g.items = append(g.items, s) + return s +} + +// List renders a comma separated list. Use for multiple return functions. +func (s *Statement) List(items ...Code) *Statement { + g := &Group{ + close: "", + items: items, + multi: false, + name: "list", + open: "", + separator: ",", + } + *s = append(*s, g) + return s +} + +// ListFunc renders a comma separated list. Use for multiple return functions. +func ListFunc(f func(*Group)) *Statement { + return newStatement().ListFunc(f) +} + +// ListFunc renders a comma separated list. Use for multiple return functions. +func (g *Group) ListFunc(f func(*Group)) *Statement { + s := ListFunc(f) + g.items = append(g.items, s) + return s +} + +// ListFunc renders a comma separated list. Use for multiple return functions. +func (s *Statement) ListFunc(f func(*Group)) *Statement { + g := &Group{ + close: "", + multi: false, + name: "list", + open: "", + separator: ",", + } + f(g) + *s = append(*s, g) + return s +} + +// Values renders a comma separated list enclosed by curly braces. Use for slice or composite literals. +func Values(values ...Code) *Statement { + return newStatement().Values(values...) +} + +// Values renders a comma separated list enclosed by curly braces. Use for slice or composite literals. +func (g *Group) Values(values ...Code) *Statement { + s := Values(values...) + g.items = append(g.items, s) + return s +} + +// Values renders a comma separated list enclosed by curly braces. Use for slice or composite literals. +func (s *Statement) Values(values ...Code) *Statement { + g := &Group{ + close: "}", + items: values, + multi: false, + name: "values", + open: "{", + separator: ",", + } + *s = append(*s, g) + return s +} + +// ValuesFunc renders a comma separated list enclosed by curly braces. Use for slice or composite literals. +func ValuesFunc(f func(*Group)) *Statement { + return newStatement().ValuesFunc(f) +} + +// ValuesFunc renders a comma separated list enclosed by curly braces. Use for slice or composite literals. +func (g *Group) ValuesFunc(f func(*Group)) *Statement { + s := ValuesFunc(f) + g.items = append(g.items, s) + return s +} + +// ValuesFunc renders a comma separated list enclosed by curly braces. Use for slice or composite literals. +func (s *Statement) ValuesFunc(f func(*Group)) *Statement { + g := &Group{ + close: "}", + multi: false, + name: "values", + open: "{", + separator: ",", + } + f(g) + *s = append(*s, g) + return s +} + +// Index renders a colon separated list enclosed by square brackets. Use for array / slice indexes and definitions. +func Index(items ...Code) *Statement { + return newStatement().Index(items...) +} + +// Index renders a colon separated list enclosed by square brackets. Use for array / slice indexes and definitions. +func (g *Group) Index(items ...Code) *Statement { + s := Index(items...) + g.items = append(g.items, s) + return s +} + +// Index renders a colon separated list enclosed by square brackets. Use for array / slice indexes and definitions. +func (s *Statement) Index(items ...Code) *Statement { + g := &Group{ + close: "]", + items: items, + multi: false, + name: "index", + open: "[", + separator: ":", + } + *s = append(*s, g) + return s +} + +// IndexFunc renders a colon separated list enclosed by square brackets. Use for array / slice indexes and definitions. +func IndexFunc(f func(*Group)) *Statement { + return newStatement().IndexFunc(f) +} + +// IndexFunc renders a colon separated list enclosed by square brackets. Use for array / slice indexes and definitions. +func (g *Group) IndexFunc(f func(*Group)) *Statement { + s := IndexFunc(f) + g.items = append(g.items, s) + return s +} + +// IndexFunc renders a colon separated list enclosed by square brackets. Use for array / slice indexes and definitions. +func (s *Statement) IndexFunc(f func(*Group)) *Statement { + g := &Group{ + close: "]", + multi: false, + name: "index", + open: "[", + separator: ":", + } + f(g) + *s = append(*s, g) + return s +} + +// Block renders a statement list enclosed by curly braces. Use for code blocks. A special case applies when used directly after Case or Default, where the braces are omitted. This allows use in switch and select statements. +func Block(statements ...Code) *Statement { + return newStatement().Block(statements...) +} + +// Block renders a statement list enclosed by curly braces. Use for code blocks. A special case applies when used directly after Case or Default, where the braces are omitted. This allows use in switch and select statements. +func (g *Group) Block(statements ...Code) *Statement { + s := Block(statements...) + g.items = append(g.items, s) + return s +} + +// Block renders a statement list enclosed by curly braces. Use for code blocks. A special case applies when used directly after Case or Default, where the braces are omitted. This allows use in switch and select statements. +func (s *Statement) Block(statements ...Code) *Statement { + g := &Group{ + close: "}", + items: statements, + multi: true, + name: "block", + open: "{", + separator: "", + } + *s = append(*s, g) + return s +} + +// BlockFunc renders a statement list enclosed by curly braces. Use for code blocks. A special case applies when used directly after Case or Default, where the braces are omitted. This allows use in switch and select statements. +func BlockFunc(f func(*Group)) *Statement { + return newStatement().BlockFunc(f) +} + +// BlockFunc renders a statement list enclosed by curly braces. Use for code blocks. A special case applies when used directly after Case or Default, where the braces are omitted. This allows use in switch and select statements. +func (g *Group) BlockFunc(f func(*Group)) *Statement { + s := BlockFunc(f) + g.items = append(g.items, s) + return s +} + +// BlockFunc renders a statement list enclosed by curly braces. Use for code blocks. A special case applies when used directly after Case or Default, where the braces are omitted. This allows use in switch and select statements. +func (s *Statement) BlockFunc(f func(*Group)) *Statement { + g := &Group{ + close: "}", + multi: true, + name: "block", + open: "{", + separator: "", + } + f(g) + *s = append(*s, g) + return s +} + +// Defs renders a statement list enclosed in parenthesis. Use for definition lists. +func Defs(definitions ...Code) *Statement { + return newStatement().Defs(definitions...) +} + +// Defs renders a statement list enclosed in parenthesis. Use for definition lists. +func (g *Group) Defs(definitions ...Code) *Statement { + s := Defs(definitions...) + g.items = append(g.items, s) + return s +} + +// Defs renders a statement list enclosed in parenthesis. Use for definition lists. +func (s *Statement) Defs(definitions ...Code) *Statement { + g := &Group{ + close: ")", + items: definitions, + multi: true, + name: "defs", + open: "(", + separator: "", + } + *s = append(*s, g) + return s +} + +// DefsFunc renders a statement list enclosed in parenthesis. Use for definition lists. +func DefsFunc(f func(*Group)) *Statement { + return newStatement().DefsFunc(f) +} + +// DefsFunc renders a statement list enclosed in parenthesis. Use for definition lists. +func (g *Group) DefsFunc(f func(*Group)) *Statement { + s := DefsFunc(f) + g.items = append(g.items, s) + return s +} + +// DefsFunc renders a statement list enclosed in parenthesis. Use for definition lists. +func (s *Statement) DefsFunc(f func(*Group)) *Statement { + g := &Group{ + close: ")", + multi: true, + name: "defs", + open: "(", + separator: "", + } + f(g) + *s = append(*s, g) + return s +} + +// Call renders a comma separated list enclosed by parenthesis. Use for function calls. +func Call(params ...Code) *Statement { + return newStatement().Call(params...) +} + +// Call renders a comma separated list enclosed by parenthesis. Use for function calls. +func (g *Group) Call(params ...Code) *Statement { + s := Call(params...) + g.items = append(g.items, s) + return s +} + +// Call renders a comma separated list enclosed by parenthesis. Use for function calls. +func (s *Statement) Call(params ...Code) *Statement { + g := &Group{ + close: ")", + items: params, + multi: false, + name: "call", + open: "(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// CallFunc renders a comma separated list enclosed by parenthesis. Use for function calls. +func CallFunc(f func(*Group)) *Statement { + return newStatement().CallFunc(f) +} + +// CallFunc renders a comma separated list enclosed by parenthesis. Use for function calls. +func (g *Group) CallFunc(f func(*Group)) *Statement { + s := CallFunc(f) + g.items = append(g.items, s) + return s +} + +// CallFunc renders a comma separated list enclosed by parenthesis. Use for function calls. +func (s *Statement) CallFunc(f func(*Group)) *Statement { + g := &Group{ + close: ")", + multi: false, + name: "call", + open: "(", + separator: ",", + } + f(g) + *s = append(*s, g) + return s +} + +// Params renders a comma separated list enclosed by parenthesis. Use for function parameters and method receivers. +func Params(params ...Code) *Statement { + return newStatement().Params(params...) +} + +// Params renders a comma separated list enclosed by parenthesis. Use for function parameters and method receivers. +func (g *Group) Params(params ...Code) *Statement { + s := Params(params...) + g.items = append(g.items, s) + return s +} + +// Params renders a comma separated list enclosed by parenthesis. Use for function parameters and method receivers. +func (s *Statement) Params(params ...Code) *Statement { + g := &Group{ + close: ")", + items: params, + multi: false, + name: "params", + open: "(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// ParamsFunc renders a comma separated list enclosed by parenthesis. Use for function parameters and method receivers. +func ParamsFunc(f func(*Group)) *Statement { + return newStatement().ParamsFunc(f) +} + +// ParamsFunc renders a comma separated list enclosed by parenthesis. Use for function parameters and method receivers. +func (g *Group) ParamsFunc(f func(*Group)) *Statement { + s := ParamsFunc(f) + g.items = append(g.items, s) + return s +} + +// ParamsFunc renders a comma separated list enclosed by parenthesis. Use for function parameters and method receivers. +func (s *Statement) ParamsFunc(f func(*Group)) *Statement { + g := &Group{ + close: ")", + multi: false, + name: "params", + open: "(", + separator: ",", + } + f(g) + *s = append(*s, g) + return s +} + +// Assert renders a period followed by a single item enclosed by parenthesis. Use for type assertions. +func Assert(typ Code) *Statement { + return newStatement().Assert(typ) +} + +// Assert renders a period followed by a single item enclosed by parenthesis. Use for type assertions. +func (g *Group) Assert(typ Code) *Statement { + s := Assert(typ) + g.items = append(g.items, s) + return s +} + +// Assert renders a period followed by a single item enclosed by parenthesis. Use for type assertions. +func (s *Statement) Assert(typ Code) *Statement { + g := &Group{ + close: ")", + items: []Code{typ}, + multi: false, + name: "assert", + open: ".(", + separator: "", + } + *s = append(*s, g) + return s +} + +// Map renders the keyword followed by a single item enclosed by square brackets. Use for map definitions. +func Map(typ Code) *Statement { + return newStatement().Map(typ) +} + +// Map renders the keyword followed by a single item enclosed by square brackets. Use for map definitions. +func (g *Group) Map(typ Code) *Statement { + s := Map(typ) + g.items = append(g.items, s) + return s +} + +// Map renders the keyword followed by a single item enclosed by square brackets. Use for map definitions. +func (s *Statement) Map(typ Code) *Statement { + g := &Group{ + close: "]", + items: []Code{typ}, + multi: false, + name: "map", + open: "map[", + separator: "", + } + *s = append(*s, g) + return s +} + +// If renders the keyword followed by a semicolon separated list. +func If(conditions ...Code) *Statement { + return newStatement().If(conditions...) +} + +// If renders the keyword followed by a semicolon separated list. +func (g *Group) If(conditions ...Code) *Statement { + s := If(conditions...) + g.items = append(g.items, s) + return s +} + +// If renders the keyword followed by a semicolon separated list. +func (s *Statement) If(conditions ...Code) *Statement { + g := &Group{ + close: "", + items: conditions, + multi: false, + name: "if", + open: "if ", + separator: ";", + } + *s = append(*s, g) + return s +} + +// IfFunc renders the keyword followed by a semicolon separated list. +func IfFunc(f func(*Group)) *Statement { + return newStatement().IfFunc(f) +} + +// IfFunc renders the keyword followed by a semicolon separated list. +func (g *Group) IfFunc(f func(*Group)) *Statement { + s := IfFunc(f) + g.items = append(g.items, s) + return s +} + +// IfFunc renders the keyword followed by a semicolon separated list. +func (s *Statement) IfFunc(f func(*Group)) *Statement { + g := &Group{ + close: "", + multi: false, + name: "if", + open: "if ", + separator: ";", + } + f(g) + *s = append(*s, g) + return s +} + +// Return renders the keyword followed by a comma separated list. +func Return(results ...Code) *Statement { + return newStatement().Return(results...) +} + +// Return renders the keyword followed by a comma separated list. +func (g *Group) Return(results ...Code) *Statement { + s := Return(results...) + g.items = append(g.items, s) + return s +} + +// Return renders the keyword followed by a comma separated list. +func (s *Statement) Return(results ...Code) *Statement { + g := &Group{ + close: "", + items: results, + multi: false, + name: "return", + open: "return ", + separator: ",", + } + *s = append(*s, g) + return s +} + +// ReturnFunc renders the keyword followed by a comma separated list. +func ReturnFunc(f func(*Group)) *Statement { + return newStatement().ReturnFunc(f) +} + +// ReturnFunc renders the keyword followed by a comma separated list. +func (g *Group) ReturnFunc(f func(*Group)) *Statement { + s := ReturnFunc(f) + g.items = append(g.items, s) + return s +} + +// ReturnFunc renders the keyword followed by a comma separated list. +func (s *Statement) ReturnFunc(f func(*Group)) *Statement { + g := &Group{ + close: "", + multi: false, + name: "return", + open: "return ", + separator: ",", + } + f(g) + *s = append(*s, g) + return s +} + +// For renders the keyword followed by a semicolon separated list. +func For(conditions ...Code) *Statement { + return newStatement().For(conditions...) +} + +// For renders the keyword followed by a semicolon separated list. +func (g *Group) For(conditions ...Code) *Statement { + s := For(conditions...) + g.items = append(g.items, s) + return s +} + +// For renders the keyword followed by a semicolon separated list. +func (s *Statement) For(conditions ...Code) *Statement { + g := &Group{ + close: "", + items: conditions, + multi: false, + name: "for", + open: "for ", + separator: ";", + } + *s = append(*s, g) + return s +} + +// ForFunc renders the keyword followed by a semicolon separated list. +func ForFunc(f func(*Group)) *Statement { + return newStatement().ForFunc(f) +} + +// ForFunc renders the keyword followed by a semicolon separated list. +func (g *Group) ForFunc(f func(*Group)) *Statement { + s := ForFunc(f) + g.items = append(g.items, s) + return s +} + +// ForFunc renders the keyword followed by a semicolon separated list. +func (s *Statement) ForFunc(f func(*Group)) *Statement { + g := &Group{ + close: "", + multi: false, + name: "for", + open: "for ", + separator: ";", + } + f(g) + *s = append(*s, g) + return s +} + +// Switch renders the keyword followed by a semicolon separated list. +func Switch(conditions ...Code) *Statement { + return newStatement().Switch(conditions...) +} + +// Switch renders the keyword followed by a semicolon separated list. +func (g *Group) Switch(conditions ...Code) *Statement { + s := Switch(conditions...) + g.items = append(g.items, s) + return s +} + +// Switch renders the keyword followed by a semicolon separated list. +func (s *Statement) Switch(conditions ...Code) *Statement { + g := &Group{ + close: "", + items: conditions, + multi: false, + name: "switch", + open: "switch ", + separator: ";", + } + *s = append(*s, g) + return s +} + +// SwitchFunc renders the keyword followed by a semicolon separated list. +func SwitchFunc(f func(*Group)) *Statement { + return newStatement().SwitchFunc(f) +} + +// SwitchFunc renders the keyword followed by a semicolon separated list. +func (g *Group) SwitchFunc(f func(*Group)) *Statement { + s := SwitchFunc(f) + g.items = append(g.items, s) + return s +} + +// SwitchFunc renders the keyword followed by a semicolon separated list. +func (s *Statement) SwitchFunc(f func(*Group)) *Statement { + g := &Group{ + close: "", + multi: false, + name: "switch", + open: "switch ", + separator: ";", + } + f(g) + *s = append(*s, g) + return s +} + +// Interface renders the keyword followed by a method list enclosed by curly braces. +func Interface(methods ...Code) *Statement { + return newStatement().Interface(methods...) +} + +// Interface renders the keyword followed by a method list enclosed by curly braces. +func (g *Group) Interface(methods ...Code) *Statement { + s := Interface(methods...) + g.items = append(g.items, s) + return s +} + +// Interface renders the keyword followed by a method list enclosed by curly braces. +func (s *Statement) Interface(methods ...Code) *Statement { + g := &Group{ + close: "}", + items: methods, + multi: true, + name: "interface", + open: "interface{", + separator: "", + } + *s = append(*s, g) + return s +} + +// InterfaceFunc renders the keyword followed by a method list enclosed by curly braces. +func InterfaceFunc(f func(*Group)) *Statement { + return newStatement().InterfaceFunc(f) +} + +// InterfaceFunc renders the keyword followed by a method list enclosed by curly braces. +func (g *Group) InterfaceFunc(f func(*Group)) *Statement { + s := InterfaceFunc(f) + g.items = append(g.items, s) + return s +} + +// InterfaceFunc renders the keyword followed by a method list enclosed by curly braces. +func (s *Statement) InterfaceFunc(f func(*Group)) *Statement { + g := &Group{ + close: "}", + multi: true, + name: "interface", + open: "interface{", + separator: "", + } + f(g) + *s = append(*s, g) + return s +} + +// Struct renders the keyword followed by a field list enclosed by curly braces. +func Struct(fields ...Code) *Statement { + return newStatement().Struct(fields...) +} + +// Struct renders the keyword followed by a field list enclosed by curly braces. +func (g *Group) Struct(fields ...Code) *Statement { + s := Struct(fields...) + g.items = append(g.items, s) + return s +} + +// Struct renders the keyword followed by a field list enclosed by curly braces. +func (s *Statement) Struct(fields ...Code) *Statement { + g := &Group{ + close: "}", + items: fields, + multi: true, + name: "struct", + open: "struct{", + separator: "", + } + *s = append(*s, g) + return s +} + +// StructFunc renders the keyword followed by a field list enclosed by curly braces. +func StructFunc(f func(*Group)) *Statement { + return newStatement().StructFunc(f) +} + +// StructFunc renders the keyword followed by a field list enclosed by curly braces. +func (g *Group) StructFunc(f func(*Group)) *Statement { + s := StructFunc(f) + g.items = append(g.items, s) + return s +} + +// StructFunc renders the keyword followed by a field list enclosed by curly braces. +func (s *Statement) StructFunc(f func(*Group)) *Statement { + g := &Group{ + close: "}", + multi: true, + name: "struct", + open: "struct{", + separator: "", + } + f(g) + *s = append(*s, g) + return s +} + +// Case renders the keyword followed by a comma separated list. +func Case(cases ...Code) *Statement { + return newStatement().Case(cases...) +} + +// Case renders the keyword followed by a comma separated list. +func (g *Group) Case(cases ...Code) *Statement { + s := Case(cases...) + g.items = append(g.items, s) + return s +} + +// Case renders the keyword followed by a comma separated list. +func (s *Statement) Case(cases ...Code) *Statement { + g := &Group{ + close: ":", + items: cases, + multi: false, + name: "case", + open: "case ", + separator: ",", + } + *s = append(*s, g) + return s +} + +// CaseFunc renders the keyword followed by a comma separated list. +func CaseFunc(f func(*Group)) *Statement { + return newStatement().CaseFunc(f) +} + +// CaseFunc renders the keyword followed by a comma separated list. +func (g *Group) CaseFunc(f func(*Group)) *Statement { + s := CaseFunc(f) + g.items = append(g.items, s) + return s +} + +// CaseFunc renders the keyword followed by a comma separated list. +func (s *Statement) CaseFunc(f func(*Group)) *Statement { + g := &Group{ + close: ":", + multi: false, + name: "case", + open: "case ", + separator: ",", + } + f(g) + *s = append(*s, g) + return s +} + +// Append renders the append built-in function. +func Append(args ...Code) *Statement { + return newStatement().Append(args...) +} + +// Append renders the append built-in function. +func (g *Group) Append(args ...Code) *Statement { + s := Append(args...) + g.items = append(g.items, s) + return s +} + +// Append renders the append built-in function. +func (s *Statement) Append(args ...Code) *Statement { + g := &Group{ + close: ")", + items: args, + multi: false, + name: "append", + open: "append(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// AppendFunc renders the append built-in function. +func AppendFunc(f func(*Group)) *Statement { + return newStatement().AppendFunc(f) +} + +// AppendFunc renders the append built-in function. +func (g *Group) AppendFunc(f func(*Group)) *Statement { + s := AppendFunc(f) + g.items = append(g.items, s) + return s +} + +// AppendFunc renders the append built-in function. +func (s *Statement) AppendFunc(f func(*Group)) *Statement { + g := &Group{ + close: ")", + multi: false, + name: "append", + open: "append(", + separator: ",", + } + f(g) + *s = append(*s, g) + return s +} + +// Cap renders the cap built-in function. +func Cap(v Code) *Statement { + return newStatement().Cap(v) +} + +// Cap renders the cap built-in function. +func (g *Group) Cap(v Code) *Statement { + s := Cap(v) + g.items = append(g.items, s) + return s +} + +// Cap renders the cap built-in function. +func (s *Statement) Cap(v Code) *Statement { + g := &Group{ + close: ")", + items: []Code{v}, + multi: false, + name: "cap", + open: "cap(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// Close renders the close built-in function. +func Close(c Code) *Statement { + return newStatement().Close(c) +} + +// Close renders the close built-in function. +func (g *Group) Close(c Code) *Statement { + s := Close(c) + g.items = append(g.items, s) + return s +} + +// Close renders the close built-in function. +func (s *Statement) Close(c Code) *Statement { + g := &Group{ + close: ")", + items: []Code{c}, + multi: false, + name: "close", + open: "close(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// Complex renders the complex built-in function. +func Complex(r Code, i Code) *Statement { + return newStatement().Complex(r, i) +} + +// Complex renders the complex built-in function. +func (g *Group) Complex(r Code, i Code) *Statement { + s := Complex(r, i) + g.items = append(g.items, s) + return s +} + +// Complex renders the complex built-in function. +func (s *Statement) Complex(r Code, i Code) *Statement { + g := &Group{ + close: ")", + items: []Code{r, i}, + multi: false, + name: "complex", + open: "complex(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// Copy renders the copy built-in function. +func Copy(dst Code, src Code) *Statement { + return newStatement().Copy(dst, src) +} + +// Copy renders the copy built-in function. +func (g *Group) Copy(dst Code, src Code) *Statement { + s := Copy(dst, src) + g.items = append(g.items, s) + return s +} + +// Copy renders the copy built-in function. +func (s *Statement) Copy(dst Code, src Code) *Statement { + g := &Group{ + close: ")", + items: []Code{dst, src}, + multi: false, + name: "copy", + open: "copy(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// Delete renders the delete built-in function. +func Delete(m Code, key Code) *Statement { + return newStatement().Delete(m, key) +} + +// Delete renders the delete built-in function. +func (g *Group) Delete(m Code, key Code) *Statement { + s := Delete(m, key) + g.items = append(g.items, s) + return s +} + +// Delete renders the delete built-in function. +func (s *Statement) Delete(m Code, key Code) *Statement { + g := &Group{ + close: ")", + items: []Code{m, key}, + multi: false, + name: "delete", + open: "delete(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// Imag renders the imag built-in function. +func Imag(c Code) *Statement { + return newStatement().Imag(c) +} + +// Imag renders the imag built-in function. +func (g *Group) Imag(c Code) *Statement { + s := Imag(c) + g.items = append(g.items, s) + return s +} + +// Imag renders the imag built-in function. +func (s *Statement) Imag(c Code) *Statement { + g := &Group{ + close: ")", + items: []Code{c}, + multi: false, + name: "imag", + open: "imag(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// Len renders the len built-in function. +func Len(v Code) *Statement { + return newStatement().Len(v) +} + +// Len renders the len built-in function. +func (g *Group) Len(v Code) *Statement { + s := Len(v) + g.items = append(g.items, s) + return s +} + +// Len renders the len built-in function. +func (s *Statement) Len(v Code) *Statement { + g := &Group{ + close: ")", + items: []Code{v}, + multi: false, + name: "len", + open: "len(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// Make renders the make built-in function. The final parameter of the make function is optional, so it is represented by a variadic parameter list. +func Make(args ...Code) *Statement { + return newStatement().Make(args...) +} + +// Make renders the make built-in function. The final parameter of the make function is optional, so it is represented by a variadic parameter list. +func (g *Group) Make(args ...Code) *Statement { + s := Make(args...) + g.items = append(g.items, s) + return s +} + +// Make renders the make built-in function. The final parameter of the make function is optional, so it is represented by a variadic parameter list. +func (s *Statement) Make(args ...Code) *Statement { + g := &Group{ + close: ")", + items: args, + multi: false, + name: "make", + open: "make(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// New renders the new built-in function. +func New(typ Code) *Statement { + return newStatement().New(typ) +} + +// New renders the new built-in function. +func (g *Group) New(typ Code) *Statement { + s := New(typ) + g.items = append(g.items, s) + return s +} + +// New renders the new built-in function. +func (s *Statement) New(typ Code) *Statement { + g := &Group{ + close: ")", + items: []Code{typ}, + multi: false, + name: "new", + open: "new(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// Panic renders the panic built-in function. +func Panic(v Code) *Statement { + return newStatement().Panic(v) +} + +// Panic renders the panic built-in function. +func (g *Group) Panic(v Code) *Statement { + s := Panic(v) + g.items = append(g.items, s) + return s +} + +// Panic renders the panic built-in function. +func (s *Statement) Panic(v Code) *Statement { + g := &Group{ + close: ")", + items: []Code{v}, + multi: false, + name: "panic", + open: "panic(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// Print renders the print built-in function. +func Print(args ...Code) *Statement { + return newStatement().Print(args...) +} + +// Print renders the print built-in function. +func (g *Group) Print(args ...Code) *Statement { + s := Print(args...) + g.items = append(g.items, s) + return s +} + +// Print renders the print built-in function. +func (s *Statement) Print(args ...Code) *Statement { + g := &Group{ + close: ")", + items: args, + multi: false, + name: "print", + open: "print(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// PrintFunc renders the print built-in function. +func PrintFunc(f func(*Group)) *Statement { + return newStatement().PrintFunc(f) +} + +// PrintFunc renders the print built-in function. +func (g *Group) PrintFunc(f func(*Group)) *Statement { + s := PrintFunc(f) + g.items = append(g.items, s) + return s +} + +// PrintFunc renders the print built-in function. +func (s *Statement) PrintFunc(f func(*Group)) *Statement { + g := &Group{ + close: ")", + multi: false, + name: "print", + open: "print(", + separator: ",", + } + f(g) + *s = append(*s, g) + return s +} + +// Println renders the println built-in function. +func Println(args ...Code) *Statement { + return newStatement().Println(args...) +} + +// Println renders the println built-in function. +func (g *Group) Println(args ...Code) *Statement { + s := Println(args...) + g.items = append(g.items, s) + return s +} + +// Println renders the println built-in function. +func (s *Statement) Println(args ...Code) *Statement { + g := &Group{ + close: ")", + items: args, + multi: false, + name: "println", + open: "println(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// PrintlnFunc renders the println built-in function. +func PrintlnFunc(f func(*Group)) *Statement { + return newStatement().PrintlnFunc(f) +} + +// PrintlnFunc renders the println built-in function. +func (g *Group) PrintlnFunc(f func(*Group)) *Statement { + s := PrintlnFunc(f) + g.items = append(g.items, s) + return s +} + +// PrintlnFunc renders the println built-in function. +func (s *Statement) PrintlnFunc(f func(*Group)) *Statement { + g := &Group{ + close: ")", + multi: false, + name: "println", + open: "println(", + separator: ",", + } + f(g) + *s = append(*s, g) + return s +} + +// Real renders the real built-in function. +func Real(c Code) *Statement { + return newStatement().Real(c) +} + +// Real renders the real built-in function. +func (g *Group) Real(c Code) *Statement { + s := Real(c) + g.items = append(g.items, s) + return s +} + +// Real renders the real built-in function. +func (s *Statement) Real(c Code) *Statement { + g := &Group{ + close: ")", + items: []Code{c}, + multi: false, + name: "real", + open: "real(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// Recover renders the recover built-in function. +func Recover() *Statement { + return newStatement().Recover() +} + +// Recover renders the recover built-in function. +func (g *Group) Recover() *Statement { + s := Recover() + g.items = append(g.items, s) + return s +} + +// Recover renders the recover built-in function. +func (s *Statement) Recover() *Statement { + g := &Group{ + close: ")", + items: []Code{}, + multi: false, + name: "recover", + open: "recover(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// Bool renders the bool identifier. +func Bool() *Statement { + return newStatement().Bool() +} + +// Bool renders the bool identifier. +func (g *Group) Bool() *Statement { + s := Bool() + g.items = append(g.items, s) + return s +} + +// Bool renders the bool identifier. +func (s *Statement) Bool() *Statement { + t := token{ + content: "bool", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Byte renders the byte identifier. +func Byte() *Statement { + // notest + return newStatement().Byte() +} + +// Byte renders the byte identifier. +func (g *Group) Byte() *Statement { + // notest + s := Byte() + g.items = append(g.items, s) + return s +} + +// Byte renders the byte identifier. +func (s *Statement) Byte() *Statement { + // notest + t := token{ + content: "byte", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Complex64 renders the complex64 identifier. +func Complex64() *Statement { + // notest + return newStatement().Complex64() +} + +// Complex64 renders the complex64 identifier. +func (g *Group) Complex64() *Statement { + // notest + s := Complex64() + g.items = append(g.items, s) + return s +} + +// Complex64 renders the complex64 identifier. +func (s *Statement) Complex64() *Statement { + // notest + t := token{ + content: "complex64", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Complex128 renders the complex128 identifier. +func Complex128() *Statement { + // notest + return newStatement().Complex128() +} + +// Complex128 renders the complex128 identifier. +func (g *Group) Complex128() *Statement { + // notest + s := Complex128() + g.items = append(g.items, s) + return s +} + +// Complex128 renders the complex128 identifier. +func (s *Statement) Complex128() *Statement { + // notest + t := token{ + content: "complex128", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Error renders the error identifier. +func Error() *Statement { + // notest + return newStatement().Error() +} + +// Error renders the error identifier. +func (g *Group) Error() *Statement { + // notest + s := Error() + g.items = append(g.items, s) + return s +} + +// Error renders the error identifier. +func (s *Statement) Error() *Statement { + // notest + t := token{ + content: "error", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Float32 renders the float32 identifier. +func Float32() *Statement { + // notest + return newStatement().Float32() +} + +// Float32 renders the float32 identifier. +func (g *Group) Float32() *Statement { + // notest + s := Float32() + g.items = append(g.items, s) + return s +} + +// Float32 renders the float32 identifier. +func (s *Statement) Float32() *Statement { + // notest + t := token{ + content: "float32", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Float64 renders the float64 identifier. +func Float64() *Statement { + // notest + return newStatement().Float64() +} + +// Float64 renders the float64 identifier. +func (g *Group) Float64() *Statement { + // notest + s := Float64() + g.items = append(g.items, s) + return s +} + +// Float64 renders the float64 identifier. +func (s *Statement) Float64() *Statement { + // notest + t := token{ + content: "float64", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Int renders the int identifier. +func Int() *Statement { + // notest + return newStatement().Int() +} + +// Int renders the int identifier. +func (g *Group) Int() *Statement { + // notest + s := Int() + g.items = append(g.items, s) + return s +} + +// Int renders the int identifier. +func (s *Statement) Int() *Statement { + // notest + t := token{ + content: "int", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Int8 renders the int8 identifier. +func Int8() *Statement { + // notest + return newStatement().Int8() +} + +// Int8 renders the int8 identifier. +func (g *Group) Int8() *Statement { + // notest + s := Int8() + g.items = append(g.items, s) + return s +} + +// Int8 renders the int8 identifier. +func (s *Statement) Int8() *Statement { + // notest + t := token{ + content: "int8", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Int16 renders the int16 identifier. +func Int16() *Statement { + // notest + return newStatement().Int16() +} + +// Int16 renders the int16 identifier. +func (g *Group) Int16() *Statement { + // notest + s := Int16() + g.items = append(g.items, s) + return s +} + +// Int16 renders the int16 identifier. +func (s *Statement) Int16() *Statement { + // notest + t := token{ + content: "int16", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Int32 renders the int32 identifier. +func Int32() *Statement { + // notest + return newStatement().Int32() +} + +// Int32 renders the int32 identifier. +func (g *Group) Int32() *Statement { + // notest + s := Int32() + g.items = append(g.items, s) + return s +} + +// Int32 renders the int32 identifier. +func (s *Statement) Int32() *Statement { + // notest + t := token{ + content: "int32", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Int64 renders the int64 identifier. +func Int64() *Statement { + // notest + return newStatement().Int64() +} + +// Int64 renders the int64 identifier. +func (g *Group) Int64() *Statement { + // notest + s := Int64() + g.items = append(g.items, s) + return s +} + +// Int64 renders the int64 identifier. +func (s *Statement) Int64() *Statement { + // notest + t := token{ + content: "int64", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Rune renders the rune identifier. +func Rune() *Statement { + // notest + return newStatement().Rune() +} + +// Rune renders the rune identifier. +func (g *Group) Rune() *Statement { + // notest + s := Rune() + g.items = append(g.items, s) + return s +} + +// Rune renders the rune identifier. +func (s *Statement) Rune() *Statement { + // notest + t := token{ + content: "rune", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// String renders the string identifier. +func String() *Statement { + // notest + return newStatement().String() +} + +// String renders the string identifier. +func (g *Group) String() *Statement { + // notest + s := String() + g.items = append(g.items, s) + return s +} + +// String renders the string identifier. +func (s *Statement) String() *Statement { + // notest + t := token{ + content: "string", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Uint renders the uint identifier. +func Uint() *Statement { + // notest + return newStatement().Uint() +} + +// Uint renders the uint identifier. +func (g *Group) Uint() *Statement { + // notest + s := Uint() + g.items = append(g.items, s) + return s +} + +// Uint renders the uint identifier. +func (s *Statement) Uint() *Statement { + // notest + t := token{ + content: "uint", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Uint8 renders the uint8 identifier. +func Uint8() *Statement { + // notest + return newStatement().Uint8() +} + +// Uint8 renders the uint8 identifier. +func (g *Group) Uint8() *Statement { + // notest + s := Uint8() + g.items = append(g.items, s) + return s +} + +// Uint8 renders the uint8 identifier. +func (s *Statement) Uint8() *Statement { + // notest + t := token{ + content: "uint8", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Uint16 renders the uint16 identifier. +func Uint16() *Statement { + // notest + return newStatement().Uint16() +} + +// Uint16 renders the uint16 identifier. +func (g *Group) Uint16() *Statement { + // notest + s := Uint16() + g.items = append(g.items, s) + return s +} + +// Uint16 renders the uint16 identifier. +func (s *Statement) Uint16() *Statement { + // notest + t := token{ + content: "uint16", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Uint32 renders the uint32 identifier. +func Uint32() *Statement { + // notest + return newStatement().Uint32() +} + +// Uint32 renders the uint32 identifier. +func (g *Group) Uint32() *Statement { + // notest + s := Uint32() + g.items = append(g.items, s) + return s +} + +// Uint32 renders the uint32 identifier. +func (s *Statement) Uint32() *Statement { + // notest + t := token{ + content: "uint32", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Uint64 renders the uint64 identifier. +func Uint64() *Statement { + // notest + return newStatement().Uint64() +} + +// Uint64 renders the uint64 identifier. +func (g *Group) Uint64() *Statement { + // notest + s := Uint64() + g.items = append(g.items, s) + return s +} + +// Uint64 renders the uint64 identifier. +func (s *Statement) Uint64() *Statement { + // notest + t := token{ + content: "uint64", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Uintptr renders the uintptr identifier. +func Uintptr() *Statement { + // notest + return newStatement().Uintptr() +} + +// Uintptr renders the uintptr identifier. +func (g *Group) Uintptr() *Statement { + // notest + s := Uintptr() + g.items = append(g.items, s) + return s +} + +// Uintptr renders the uintptr identifier. +func (s *Statement) Uintptr() *Statement { + // notest + t := token{ + content: "uintptr", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// True renders the true identifier. +func True() *Statement { + // notest + return newStatement().True() +} + +// True renders the true identifier. +func (g *Group) True() *Statement { + // notest + s := True() + g.items = append(g.items, s) + return s +} + +// True renders the true identifier. +func (s *Statement) True() *Statement { + // notest + t := token{ + content: "true", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// False renders the false identifier. +func False() *Statement { + // notest + return newStatement().False() +} + +// False renders the false identifier. +func (g *Group) False() *Statement { + // notest + s := False() + g.items = append(g.items, s) + return s +} + +// False renders the false identifier. +func (s *Statement) False() *Statement { + // notest + t := token{ + content: "false", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Iota renders the iota identifier. +func Iota() *Statement { + // notest + return newStatement().Iota() +} + +// Iota renders the iota identifier. +func (g *Group) Iota() *Statement { + // notest + s := Iota() + g.items = append(g.items, s) + return s +} + +// Iota renders the iota identifier. +func (s *Statement) Iota() *Statement { + // notest + t := token{ + content: "iota", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Nil renders the nil identifier. +func Nil() *Statement { + // notest + return newStatement().Nil() +} + +// Nil renders the nil identifier. +func (g *Group) Nil() *Statement { + // notest + s := Nil() + g.items = append(g.items, s) + return s +} + +// Nil renders the nil identifier. +func (s *Statement) Nil() *Statement { + // notest + t := token{ + content: "nil", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Err renders the err identifier. +func Err() *Statement { + // notest + return newStatement().Err() +} + +// Err renders the err identifier. +func (g *Group) Err() *Statement { + // notest + s := Err() + g.items = append(g.items, s) + return s +} + +// Err renders the err identifier. +func (s *Statement) Err() *Statement { + // notest + t := token{ + content: "err", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Break renders the break keyword. +func Break() *Statement { + // notest + return newStatement().Break() +} + +// Break renders the break keyword. +func (g *Group) Break() *Statement { + // notest + s := Break() + g.items = append(g.items, s) + return s +} + +// Break renders the break keyword. +func (s *Statement) Break() *Statement { + // notest + t := token{ + content: "break", + typ: keywordToken, + } + *s = append(*s, t) + return s +} + +// Default renders the default keyword. +func Default() *Statement { + // notest + return newStatement().Default() +} + +// Default renders the default keyword. +func (g *Group) Default() *Statement { + // notest + s := Default() + g.items = append(g.items, s) + return s +} + +// Default renders the default keyword. +func (s *Statement) Default() *Statement { + // notest + t := token{ + content: "default", + typ: keywordToken, + } + *s = append(*s, t) + return s +} + +// Func renders the func keyword. +func Func() *Statement { + // notest + return newStatement().Func() +} + +// Func renders the func keyword. +func (g *Group) Func() *Statement { + // notest + s := Func() + g.items = append(g.items, s) + return s +} + +// Func renders the func keyword. +func (s *Statement) Func() *Statement { + // notest + t := token{ + content: "func", + typ: keywordToken, + } + *s = append(*s, t) + return s +} + +// Select renders the select keyword. +func Select() *Statement { + // notest + return newStatement().Select() +} + +// Select renders the select keyword. +func (g *Group) Select() *Statement { + // notest + s := Select() + g.items = append(g.items, s) + return s +} + +// Select renders the select keyword. +func (s *Statement) Select() *Statement { + // notest + t := token{ + content: "select", + typ: keywordToken, + } + *s = append(*s, t) + return s +} + +// Chan renders the chan keyword. +func Chan() *Statement { + // notest + return newStatement().Chan() +} + +// Chan renders the chan keyword. +func (g *Group) Chan() *Statement { + // notest + s := Chan() + g.items = append(g.items, s) + return s +} + +// Chan renders the chan keyword. +func (s *Statement) Chan() *Statement { + // notest + t := token{ + content: "chan", + typ: keywordToken, + } + *s = append(*s, t) + return s +} + +// Else renders the else keyword. +func Else() *Statement { + // notest + return newStatement().Else() +} + +// Else renders the else keyword. +func (g *Group) Else() *Statement { + // notest + s := Else() + g.items = append(g.items, s) + return s +} + +// Else renders the else keyword. +func (s *Statement) Else() *Statement { + // notest + t := token{ + content: "else", + typ: keywordToken, + } + *s = append(*s, t) + return s +} + +// Const renders the const keyword. +func Const() *Statement { + // notest + return newStatement().Const() +} + +// Const renders the const keyword. +func (g *Group) Const() *Statement { + // notest + s := Const() + g.items = append(g.items, s) + return s +} + +// Const renders the const keyword. +func (s *Statement) Const() *Statement { + // notest + t := token{ + content: "const", + typ: keywordToken, + } + *s = append(*s, t) + return s +} + +// Fallthrough renders the fallthrough keyword. +func Fallthrough() *Statement { + // notest + return newStatement().Fallthrough() +} + +// Fallthrough renders the fallthrough keyword. +func (g *Group) Fallthrough() *Statement { + // notest + s := Fallthrough() + g.items = append(g.items, s) + return s +} + +// Fallthrough renders the fallthrough keyword. +func (s *Statement) Fallthrough() *Statement { + // notest + t := token{ + content: "fallthrough", + typ: keywordToken, + } + *s = append(*s, t) + return s +} + +// Type renders the type keyword. +func Type() *Statement { + // notest + return newStatement().Type() +} + +// Type renders the type keyword. +func (g *Group) Type() *Statement { + // notest + s := Type() + g.items = append(g.items, s) + return s +} + +// Type renders the type keyword. +func (s *Statement) Type() *Statement { + // notest + t := token{ + content: "type", + typ: keywordToken, + } + *s = append(*s, t) + return s +} + +// Continue renders the continue keyword. +func Continue() *Statement { + // notest + return newStatement().Continue() +} + +// Continue renders the continue keyword. +func (g *Group) Continue() *Statement { + // notest + s := Continue() + g.items = append(g.items, s) + return s +} + +// Continue renders the continue keyword. +func (s *Statement) Continue() *Statement { + // notest + t := token{ + content: "continue", + typ: keywordToken, + } + *s = append(*s, t) + return s +} + +// Var renders the var keyword. +func Var() *Statement { + // notest + return newStatement().Var() +} + +// Var renders the var keyword. +func (g *Group) Var() *Statement { + // notest + s := Var() + g.items = append(g.items, s) + return s +} + +// Var renders the var keyword. +func (s *Statement) Var() *Statement { + // notest + t := token{ + content: "var", + typ: keywordToken, + } + *s = append(*s, t) + return s +} + +// Goto renders the goto keyword. +func Goto() *Statement { + // notest + return newStatement().Goto() +} + +// Goto renders the goto keyword. +func (g *Group) Goto() *Statement { + // notest + s := Goto() + g.items = append(g.items, s) + return s +} + +// Goto renders the goto keyword. +func (s *Statement) Goto() *Statement { + // notest + t := token{ + content: "goto", + typ: keywordToken, + } + *s = append(*s, t) + return s +} + +// Defer renders the defer keyword. +func Defer() *Statement { + // notest + return newStatement().Defer() +} + +// Defer renders the defer keyword. +func (g *Group) Defer() *Statement { + // notest + s := Defer() + g.items = append(g.items, s) + return s +} + +// Defer renders the defer keyword. +func (s *Statement) Defer() *Statement { + // notest + t := token{ + content: "defer", + typ: keywordToken, + } + *s = append(*s, t) + return s +} + +// Go renders the go keyword. +func Go() *Statement { + // notest + return newStatement().Go() +} + +// Go renders the go keyword. +func (g *Group) Go() *Statement { + // notest + s := Go() + g.items = append(g.items, s) + return s +} + +// Go renders the go keyword. +func (s *Statement) Go() *Statement { + // notest + t := token{ + content: "go", + typ: keywordToken, + } + *s = append(*s, t) + return s +} + +// Range renders the range keyword. +func Range() *Statement { + // notest + return newStatement().Range() +} + +// Range renders the range keyword. +func (g *Group) Range() *Statement { + // notest + s := Range() + g.items = append(g.items, s) + return s +} + +// Range renders the range keyword. +func (s *Statement) Range() *Statement { + // notest + t := token{ + content: "range", + typ: keywordToken, + } + *s = append(*s, t) + return s +} diff --git a/vendor/github.com/dave/jennifer/jen/group.go b/vendor/github.com/dave/jennifer/jen/group.go new file mode 100644 index 0000000000..821bb36492 --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/group.go @@ -0,0 +1,136 @@ +package jen + +import ( + "bytes" + "fmt" + "go/format" + "io" +) + +// Group represents a list of Code items, separated by tokens with an optional +// open and close token. +type Group struct { + name string + items []Code + open string + close string + separator string + multi bool +} + +func (g *Group) isNull(f *File) bool { + if g == nil { + return true + } + if g.open != "" || g.close != "" { + return false + } + for _, c := range g.items { + if !c.isNull(f) { + return false + } + } + return true +} + +func (g *Group) render(f *File, w io.Writer, s *Statement) error { + if g.name == "block" && s != nil { + // Special CaseBlock format for then the previous item in the statement + // is a Case group or the default keyword. + prev := s.previous(g) + grp, isGrp := prev.(*Group) + tkn, isTkn := prev.(token) + if isGrp && grp.name == "case" || isTkn && tkn.content == "default" { + g.open = "" + g.close = "" + } + } + if g.open != "" { + if _, err := w.Write([]byte(g.open)); err != nil { + return err + } + } + isNull, err := g.renderItems(f, w) + if err != nil { + return err + } + if !isNull && g.multi && g.close != "" { + // For multi-line blocks with a closing token, we insert a new line after the last item (but + // not if all items were null). This is to ensure that if the statement finishes with a comment, + // the closing token is not commented out. + s := "\n" + if g.separator == "," { + // We also insert add trailing comma if the separator was ",". + s = ",\n" + } + if _, err := w.Write([]byte(s)); err != nil { + return err + } + } + if g.close != "" { + if _, err := w.Write([]byte(g.close)); err != nil { + return err + } + } + return nil +} + +func (g *Group) renderItems(f *File, w io.Writer) (isNull bool, err error) { + first := true + for _, code := range g.items { + if code == nil || code.isNull(f) { + // Null() token produces no output but also + // no separator. Empty() token products no + // output but adds a separator. + continue + } + if g.name == "values" { + if _, ok := code.(Dict); ok && len(g.items) > 1 { + panic("Error in Values: if Dict is used, must be one item only") + } + } + if !first && g.separator != "" { + // The separator token is added before each non-null item, but not before the first item. + if _, err := w.Write([]byte(g.separator)); err != nil { + return false, err + } + } + if g.multi { + // For multi-line blocks, we insert a new line before each non-null item. + if _, err := w.Write([]byte("\n")); err != nil { + return false, err + } + } + if err := code.render(f, w, nil); err != nil { + return false, err + } + first = false + } + return first, nil +} + +// Render renders the Group to the provided writer. +func (g *Group) Render(writer io.Writer) error { + f := NewFile("") + buf := &bytes.Buffer{} + if err := g.render(f, buf, nil); err != nil { + return err + } + b, err := format.Source(buf.Bytes()) + if err != nil { + return fmt.Errorf("Error %s while formatting source:\n%s", err, buf.String()) + } + if _, err := writer.Write(b); err != nil { + return err + } + return nil +} + +// GoString renders the Group for testing. Any error will cause a panic. +func (g *Group) GoString() string { + buf := bytes.Buffer{} + if err := g.Render(&buf); err != nil { + panic(err) + } + return buf.String() +} diff --git a/vendor/github.com/dave/jennifer/jen/hints.go b/vendor/github.com/dave/jennifer/jen/hints.go new file mode 100644 index 0000000000..7bc307a659 --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/hints.go @@ -0,0 +1,273 @@ +// This file is generated - do not edit. + +package jen + +// standardLibraryHints contains package name hints +var standardLibraryHints = map[string]string{ + "archive/tar": "tar", + "archive/zip": "zip", + "bufio": "bufio", + "builtin": "builtin", + "bytes": "bytes", + "cmd/asm/internal/arch": "arch", + "cmd/asm/internal/asm": "asm", + "cmd/asm/internal/flags": "flags", + "cmd/asm/internal/lex": "lex", + "cmd/compile/internal/amd64": "amd64", + "cmd/compile/internal/arm": "arm", + "cmd/compile/internal/arm64": "arm64", + "cmd/compile/internal/gc": "gc", + "cmd/compile/internal/mips": "mips", + "cmd/compile/internal/mips64": "mips64", + "cmd/compile/internal/ppc64": "ppc64", + "cmd/compile/internal/s390x": "s390x", + "cmd/compile/internal/ssa": "ssa", + "cmd/compile/internal/syntax": "syntax", + "cmd/compile/internal/test": "test", + "cmd/compile/internal/types": "types", + "cmd/compile/internal/wasm": "wasm", + "cmd/compile/internal/x86": "x86", + "cmd/go/internal/base": "base", + "cmd/go/internal/bug": "bug", + "cmd/go/internal/cache": "cache", + "cmd/go/internal/cfg": "cfg", + "cmd/go/internal/clean": "clean", + "cmd/go/internal/cmdflag": "cmdflag", + "cmd/go/internal/dirhash": "dirhash", + "cmd/go/internal/doc": "doc", + "cmd/go/internal/envcmd": "envcmd", + "cmd/go/internal/fix": "fix", + "cmd/go/internal/fmtcmd": "fmtcmd", + "cmd/go/internal/generate": "generate", + "cmd/go/internal/get": "get", + "cmd/go/internal/help": "help", + "cmd/go/internal/imports": "imports", + "cmd/go/internal/list": "list", + "cmd/go/internal/load": "load", + "cmd/go/internal/modcmd": "modcmd", + "cmd/go/internal/modconv": "modconv", + "cmd/go/internal/modfetch": "modfetch", + "cmd/go/internal/modfetch/codehost": "codehost", + "cmd/go/internal/modfile": "modfile", + "cmd/go/internal/modget": "modget", + "cmd/go/internal/modinfo": "modinfo", + "cmd/go/internal/modload": "modload", + "cmd/go/internal/module": "module", + "cmd/go/internal/mvs": "mvs", + "cmd/go/internal/par": "par", + "cmd/go/internal/run": "run", + "cmd/go/internal/search": "search", + "cmd/go/internal/semver": "semver", + "cmd/go/internal/str": "str", + "cmd/go/internal/test": "test", + "cmd/go/internal/tool": "tool", + "cmd/go/internal/txtar": "txtar", + "cmd/go/internal/version": "version", + "cmd/go/internal/vet": "vet", + "cmd/go/internal/web": "web", + "cmd/go/internal/web2": "web2", + "cmd/go/internal/webtest": "webtest", + "cmd/go/internal/work": "work", + "cmd/internal/bio": "bio", + "cmd/internal/browser": "browser", + "cmd/internal/buildid": "buildid", + "cmd/internal/dwarf": "dwarf", + "cmd/internal/edit": "edit", + "cmd/internal/gcprog": "gcprog", + "cmd/internal/goobj": "goobj", + "cmd/internal/obj": "obj", + "cmd/internal/obj/arm": "arm", + "cmd/internal/obj/arm64": "arm64", + "cmd/internal/obj/mips": "mips", + "cmd/internal/obj/ppc64": "ppc64", + "cmd/internal/obj/s390x": "s390x", + "cmd/internal/obj/wasm": "wasm", + "cmd/internal/obj/x86": "x86", + "cmd/internal/objabi": "objabi", + "cmd/internal/objfile": "objfile", + "cmd/internal/src": "src", + "cmd/internal/sys": "sys", + "cmd/internal/test2json": "test2json", + "cmd/link/internal/amd64": "amd64", + "cmd/link/internal/arm": "arm", + "cmd/link/internal/arm64": "arm64", + "cmd/link/internal/ld": "ld", + "cmd/link/internal/loadelf": "loadelf", + "cmd/link/internal/loadmacho": "loadmacho", + "cmd/link/internal/loadpe": "loadpe", + "cmd/link/internal/mips": "mips", + "cmd/link/internal/mips64": "mips64", + "cmd/link/internal/objfile": "objfile", + "cmd/link/internal/ppc64": "ppc64", + "cmd/link/internal/s390x": "s390x", + "cmd/link/internal/sym": "sym", + "cmd/link/internal/wasm": "wasm", + "cmd/link/internal/x86": "x86", + "cmd/vet/internal/cfg": "cfg", + "cmd/vet/internal/whitelist": "whitelist", + "compress/bzip2": "bzip2", + "compress/flate": "flate", + "compress/gzip": "gzip", + "compress/lzw": "lzw", + "compress/zlib": "zlib", + "container/heap": "heap", + "container/list": "list", + "container/ring": "ring", + "context": "context", + "crypto": "crypto", + "crypto/aes": "aes", + "crypto/cipher": "cipher", + "crypto/des": "des", + "crypto/dsa": "dsa", + "crypto/ecdsa": "ecdsa", + "crypto/elliptic": "elliptic", + "crypto/hmac": "hmac", + "crypto/internal/randutil": "randutil", + "crypto/internal/subtle": "subtle", + "crypto/md5": "md5", + "crypto/rand": "rand", + "crypto/rc4": "rc4", + "crypto/rsa": "rsa", + "crypto/sha1": "sha1", + "crypto/sha256": "sha256", + "crypto/sha512": "sha512", + "crypto/subtle": "subtle", + "crypto/tls": "tls", + "crypto/x509": "x509", + "crypto/x509/pkix": "pkix", + "database/sql": "sql", + "database/sql/driver": "driver", + "debug/dwarf": "dwarf", + "debug/elf": "elf", + "debug/gosym": "gosym", + "debug/macho": "macho", + "debug/pe": "pe", + "debug/plan9obj": "plan9obj", + "encoding": "encoding", + "encoding/ascii85": "ascii85", + "encoding/asn1": "asn1", + "encoding/base32": "base32", + "encoding/base64": "base64", + "encoding/binary": "binary", + "encoding/csv": "csv", + "encoding/gob": "gob", + "encoding/hex": "hex", + "encoding/json": "json", + "encoding/pem": "pem", + "encoding/xml": "xml", + "errors": "errors", + "expvar": "expvar", + "flag": "flag", + "fmt": "fmt", + "go/ast": "ast", + "go/build": "build", + "go/constant": "constant", + "go/doc": "doc", + "go/format": "format", + "go/importer": "importer", + "go/internal/gccgoimporter": "gccgoimporter", + "go/internal/gcimporter": "gcimporter", + "go/internal/srcimporter": "srcimporter", + "go/parser": "parser", + "go/printer": "printer", + "go/scanner": "scanner", + "go/token": "token", + "go/types": "types", + "hash": "hash", + "hash/adler32": "adler32", + "hash/crc32": "crc32", + "hash/crc64": "crc64", + "hash/fnv": "fnv", + "html": "html", + "html/template": "template", + "image": "image", + "image/color": "color", + "image/color/palette": "palette", + "image/draw": "draw", + "image/gif": "gif", + "image/internal/imageutil": "imageutil", + "image/jpeg": "jpeg", + "image/png": "png", + "index/suffixarray": "suffixarray", + "internal/bytealg": "bytealg", + "internal/cpu": "cpu", + "internal/nettrace": "nettrace", + "internal/poll": "poll", + "internal/race": "race", + "internal/singleflight": "singleflight", + "internal/syscall/unix": "unix", + "internal/syscall/windows": "windows", + "internal/syscall/windows/registry": "registry", + "internal/syscall/windows/sysdll": "sysdll", + "internal/testenv": "testenv", + "internal/testlog": "testlog", + "internal/trace": "trace", + "io": "io", + "io/ioutil": "ioutil", + "log": "log", + "log/syslog": "syslog", + "math": "math", + "math/big": "big", + "math/bits": "bits", + "math/cmplx": "cmplx", + "math/rand": "rand", + "mime": "mime", + "mime/multipart": "multipart", + "mime/quotedprintable": "quotedprintable", + "net": "net", + "net/http": "http", + "net/http/cgi": "cgi", + "net/http/cookiejar": "cookiejar", + "net/http/fcgi": "fcgi", + "net/http/httptest": "httptest", + "net/http/httptrace": "httptrace", + "net/http/httputil": "httputil", + "net/http/internal": "internal", + "net/http/pprof": "pprof", + "net/internal/socktest": "socktest", + "net/mail": "mail", + "net/rpc": "rpc", + "net/rpc/jsonrpc": "jsonrpc", + "net/smtp": "smtp", + "net/textproto": "textproto", + "net/url": "url", + "os": "os", + "os/exec": "exec", + "os/signal": "signal", + "os/signal/internal/pty": "pty", + "os/user": "user", + "path": "path", + "path/filepath": "filepath", + "plugin": "plugin", + "reflect": "reflect", + "regexp": "regexp", + "regexp/syntax": "syntax", + "runtime": "runtime", + "runtime/cgo": "cgo", + "runtime/debug": "debug", + "runtime/internal/atomic": "atomic", + "runtime/internal/sys": "sys", + "runtime/pprof": "pprof", + "runtime/pprof/internal/profile": "profile", + "runtime/race": "race", + "runtime/trace": "trace", + "sort": "sort", + "strconv": "strconv", + "strings": "strings", + "sync": "sync", + "sync/atomic": "atomic", + "syscall": "syscall", + "testing": "testing", + "testing/internal/testdeps": "testdeps", + "testing/iotest": "iotest", + "testing/quick": "quick", + "text/scanner": "scanner", + "text/tabwriter": "tabwriter", + "text/template": "template", + "text/template/parse": "parse", + "time": "time", + "unicode": "unicode", + "unicode/utf16": "utf16", + "unicode/utf8": "utf8", + "unsafe": "unsafe", +} diff --git a/vendor/github.com/dave/jennifer/jen/jen.go b/vendor/github.com/dave/jennifer/jen/jen.go new file mode 100644 index 0000000000..4cf480a14f --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/jen.go @@ -0,0 +1,168 @@ +// Package jen is a code generator for Go +package jen + +import ( + "bytes" + "fmt" + "go/format" + "io" + "io/ioutil" + "sort" + "strconv" +) + +// Code represents an item of code that can be rendered. +type Code interface { + render(f *File, w io.Writer, s *Statement) error + isNull(f *File) bool +} + +// Save renders the file and saves to the filename provided. +func (f *File) Save(filename string) error { + // notest + buf := &bytes.Buffer{} + if err := f.Render(buf); err != nil { + return err + } + if err := ioutil.WriteFile(filename, buf.Bytes(), 0644); err != nil { + return err + } + return nil +} + +// Render renders the file to the provided writer. +func (f *File) Render(w io.Writer) error { + body := &bytes.Buffer{} + if err := f.render(f, body, nil); err != nil { + return err + } + source := &bytes.Buffer{} + if len(f.headers) > 0 { + for _, c := range f.headers { + if err := Comment(c).render(f, source, nil); err != nil { + return err + } + if _, err := fmt.Fprint(source, "\n"); err != nil { + return err + } + } + // Append an extra newline so that header comments don't get lumped in + // with package comments. + if _, err := fmt.Fprint(source, "\n"); err != nil { + return err + } + } + for _, c := range f.comments { + if err := Comment(c).render(f, source, nil); err != nil { + return err + } + if _, err := fmt.Fprint(source, "\n"); err != nil { + return err + } + } + if _, err := fmt.Fprintf(source, "package %s", f.name); err != nil { + return err + } + if f.CanonicalPath != "" { + if _, err := fmt.Fprintf(source, " // import %q", f.CanonicalPath); err != nil { + return err + } + } + if _, err := fmt.Fprint(source, "\n\n"); err != nil { + return err + } + if err := f.renderImports(source); err != nil { + return err + } + if _, err := source.Write(body.Bytes()); err != nil { + return err + } + formatted, err := format.Source(source.Bytes()) + if err != nil { + return fmt.Errorf("Error %s while formatting source:\n%s", err, source.String()) + } + if _, err := w.Write(formatted); err != nil { + return err + } + return nil +} + +func (f *File) renderImports(source io.Writer) error { + + // Render the "C" import if it's been used in a `Qual`, `Anon` or if there's a preamble comment + hasCgo := f.imports["C"].name != "" || len(f.cgoPreamble) > 0 + + // Only separate the import from the main imports block if there's a preamble + separateCgo := hasCgo && len(f.cgoPreamble) > 0 + + filtered := map[string]importdef{} + for path, def := range f.imports { + // filter out the "C" pseudo-package so it's not rendered in a block with the other + // imports, but only if it is accompanied by a preamble comment + if path == "C" && separateCgo { + continue + } + filtered[path] = def + } + + if len(filtered) == 1 { + for path, def := range filtered { + if def.alias && path != "C" { + // "C" package should be rendered without alias even when used as an anonymous import + // (e.g. should never have an underscore). + if _, err := fmt.Fprintf(source, "import %s %s\n\n", def.name, strconv.Quote(path)); err != nil { + return err + } + } else { + if _, err := fmt.Fprintf(source, "import %s\n\n", strconv.Quote(path)); err != nil { + return err + } + } + } + } else if len(filtered) > 1 { + if _, err := fmt.Fprint(source, "import (\n"); err != nil { + return err + } + // We must sort the imports to ensure repeatable + // source. + paths := []string{} + for path := range filtered { + paths = append(paths, path) + } + sort.Strings(paths) + for _, path := range paths { + def := filtered[path] + if def.alias && path != "C" { + // "C" package should be rendered without alias even when used as an anonymous import + // (e.g. should never have an underscore). + if _, err := fmt.Fprintf(source, "%s %s\n", def.name, strconv.Quote(path)); err != nil { + return err + } + + } else { + if _, err := fmt.Fprintf(source, "%s\n", strconv.Quote(path)); err != nil { + return err + } + } + } + if _, err := fmt.Fprint(source, ")\n\n"); err != nil { + return err + } + } + + if separateCgo { + for _, c := range f.cgoPreamble { + if err := Comment(c).render(f, source, nil); err != nil { + return err + } + if _, err := fmt.Fprint(source, "\n"); err != nil { + return err + } + } + if _, err := fmt.Fprint(source, "import \"C\"\n\n"); err != nil { + return err + } + } + + return nil +} diff --git a/vendor/github.com/dave/jennifer/jen/lit.go b/vendor/github.com/dave/jennifer/jen/lit.go new file mode 100644 index 0000000000..9791f1d2cb --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/lit.go @@ -0,0 +1,154 @@ +package jen + +// Lit renders a literal. Lit supports only built-in types (bool, string, int, complex128, float64, +// float32, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr and complex64). +// Passing any other type will panic. +func Lit(v interface{}) *Statement { + return newStatement().Lit(v) +} + +// Lit renders a literal. Lit supports only built-in types (bool, string, int, complex128, float64, +// float32, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr and complex64). +// Passing any other type will panic. +func (g *Group) Lit(v interface{}) *Statement { + s := Lit(v) + g.items = append(g.items, s) + return s +} + +// Lit renders a literal. Lit supports only built-in types (bool, string, int, complex128, float64, +// float32, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr and complex64). +// Passing any other type will panic. +func (s *Statement) Lit(v interface{}) *Statement { + t := token{ + typ: literalToken, + content: v, + } + *s = append(*s, t) + return s +} + +// LitFunc renders a literal. LitFunc generates the value to render by executing the provided +// function. LitFunc supports only built-in types (bool, string, int, complex128, float64, float32, +// int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr and complex64). +// Returning any other type will panic. +func LitFunc(f func() interface{}) *Statement { + return newStatement().LitFunc(f) +} + +// LitFunc renders a literal. LitFunc generates the value to render by executing the provided +// function. LitFunc supports only built-in types (bool, string, int, complex128, float64, float32, +// int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr and complex64). +// Returning any other type will panic. +func (g *Group) LitFunc(f func() interface{}) *Statement { + s := LitFunc(f) + g.items = append(g.items, s) + return s +} + +// LitFunc renders a literal. LitFunc generates the value to render by executing the provided +// function. LitFunc supports only built-in types (bool, string, int, complex128, float64, float32, +// int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr and complex64). +// Returning any other type will panic. +func (s *Statement) LitFunc(f func() interface{}) *Statement { + t := token{ + typ: literalToken, + content: f(), + } + *s = append(*s, t) + return s +} + +// LitRune renders a rune literal. +func LitRune(v rune) *Statement { + return newStatement().LitRune(v) +} + +// LitRune renders a rune literal. +func (g *Group) LitRune(v rune) *Statement { + s := LitRune(v) + g.items = append(g.items, s) + return s +} + +// LitRune renders a rune literal. +func (s *Statement) LitRune(v rune) *Statement { + t := token{ + typ: literalRuneToken, + content: v, + } + *s = append(*s, t) + return s +} + +// LitRuneFunc renders a rune literal. LitRuneFunc generates the value to +// render by executing the provided function. +func LitRuneFunc(f func() rune) *Statement { + return newStatement().LitRuneFunc(f) +} + +// LitRuneFunc renders a rune literal. LitRuneFunc generates the value to +// render by executing the provided function. +func (g *Group) LitRuneFunc(f func() rune) *Statement { + s := LitRuneFunc(f) + g.items = append(g.items, s) + return s +} + +// LitRuneFunc renders a rune literal. LitRuneFunc generates the value to +// render by executing the provided function. +func (s *Statement) LitRuneFunc(f func() rune) *Statement { + t := token{ + typ: literalRuneToken, + content: f(), + } + *s = append(*s, t) + return s +} + +// LitByte renders a byte literal. +func LitByte(v byte) *Statement { + return newStatement().LitByte(v) +} + +// LitByte renders a byte literal. +func (g *Group) LitByte(v byte) *Statement { + s := LitByte(v) + g.items = append(g.items, s) + return s +} + +// LitByte renders a byte literal. +func (s *Statement) LitByte(v byte) *Statement { + t := token{ + typ: literalByteToken, + content: v, + } + *s = append(*s, t) + return s +} + +// LitByteFunc renders a byte literal. LitByteFunc generates the value to +// render by executing the provided function. +func LitByteFunc(f func() byte) *Statement { + return newStatement().LitByteFunc(f) +} + +// LitByteFunc renders a byte literal. LitByteFunc generates the value to +// render by executing the provided function. +func (g *Group) LitByteFunc(f func() byte) *Statement { + s := LitByteFunc(f) + g.items = append(g.items, s) + return s +} + +// LitByteFunc renders a byte literal. LitByteFunc generates the value to +// render by executing the provided function. +func (s *Statement) LitByteFunc(f func() byte) *Statement { + t := token{ + typ: literalByteToken, + content: f(), + } + *s = append(*s, t) + return s +} diff --git a/vendor/github.com/dave/jennifer/jen/statement.go b/vendor/github.com/dave/jennifer/jen/statement.go new file mode 100644 index 0000000000..41f14b11cd --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/statement.go @@ -0,0 +1,96 @@ +package jen + +import ( + "bytes" + "fmt" + "go/format" + "io" +) + +// Statement represents a simple list of code items. When rendered the items +// are separated by spaces. +type Statement []Code + +func newStatement() *Statement { + return &Statement{} +} + +// Clone makes a copy of the Statement, so further tokens can be appended +// without affecting the original. +func (s *Statement) Clone() *Statement { + return &Statement{s} +} + +func (s *Statement) previous(c Code) Code { + index := -1 + for i, item := range *s { + if item == c { + index = i + break + } + } + if index > 0 { + return (*s)[index-1] + } + return nil +} + +func (s *Statement) isNull(f *File) bool { + if s == nil { + return true + } + for _, c := range *s { + if !c.isNull(f) { + return false + } + } + return true +} + +func (s *Statement) render(f *File, w io.Writer, _ *Statement) error { + first := true + for _, code := range *s { + if code == nil || code.isNull(f) { + // Null() token produces no output but also + // no separator. Empty() token products no + // output but adds a separator. + continue + } + if !first { + if _, err := w.Write([]byte(" ")); err != nil { + return err + } + } + if err := code.render(f, w, s); err != nil { + return err + } + first = false + } + return nil +} + +// Render renders the Statement to the provided writer. +func (s *Statement) Render(writer io.Writer) error { + f := NewFile("") + buf := &bytes.Buffer{} + if err := s.render(f, buf, nil); err != nil { + return err + } + b, err := format.Source(buf.Bytes()) + if err != nil { + return fmt.Errorf("Error %s while formatting source:\n%s", err, buf.String()) + } + if _, err := writer.Write(b); err != nil { + return err + } + return nil +} + +// GoString renders the Statement for testing. Any error will cause a panic. +func (s *Statement) GoString() string { + buf := bytes.Buffer{} + if err := s.Render(&buf); err != nil { + panic(err) + } + return buf.String() +} diff --git a/vendor/github.com/dave/jennifer/jen/tag.go b/vendor/github.com/dave/jennifer/jen/tag.go new file mode 100644 index 0000000000..ad99aafdfa --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/tag.go @@ -0,0 +1,76 @@ +package jen + +import ( + "fmt" + "io" + "sort" + "strconv" +) + +// Tag renders a struct tag +func Tag(items map[string]string) *Statement { + return newStatement().Tag(items) +} + +// Tag renders a struct tag +func (g *Group) Tag(items map[string]string) *Statement { + // notest + // don't think this can ever be used in valid code? + s := Tag(items) + g.items = append(g.items, s) + return s +} + +// Tag renders a struct tag +func (s *Statement) Tag(items map[string]string) *Statement { + c := tag{ + items: items, + } + *s = append(*s, c) + return s +} + +type tag struct { + items map[string]string +} + +func (t tag) isNull(f *File) bool { + return len(t.items) == 0 +} + +func (t tag) render(f *File, w io.Writer, s *Statement) error { + + if t.isNull(f) { + // notest + // render won't be called if t is null + return nil + } + + var str string + + var sorted []string + for k := range t.items { + sorted = append(sorted, k) + } + sort.Strings(sorted) + + for _, k := range sorted { + v := t.items[k] + if len(str) > 0 { + str += " " + } + str += fmt.Sprintf(`%s:"%s"`, k, v) + } + + if strconv.CanBackquote(str) { + str = "`" + str + "`" + } else { + str = strconv.Quote(str) + } + + if _, err := w.Write([]byte(str)); err != nil { + return err + } + + return nil +} diff --git a/vendor/github.com/dave/jennifer/jen/tokens.go b/vendor/github.com/dave/jennifer/jen/tokens.go new file mode 100644 index 0000000000..328f36a03d --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/tokens.go @@ -0,0 +1,301 @@ +package jen + +import ( + "fmt" + "io" + "strconv" + "strings" +) + +type tokenType string + +const ( + packageToken tokenType = "package" + identifierToken tokenType = "identifier" + qualifiedToken tokenType = "qualified" + keywordToken tokenType = "keyword" + operatorToken tokenType = "operator" + delimiterToken tokenType = "delimiter" + literalToken tokenType = "literal" + literalRuneToken tokenType = "literal_rune" + literalByteToken tokenType = "literal_byte" + nullToken tokenType = "null" + layoutToken tokenType = "layout" +) + +type token struct { + typ tokenType + content interface{} +} + +func (t token) isNull(f *File) bool { + if t.typ == packageToken { + // package token is null if the path is the local package path + return f.isLocal(t.content.(string)) + } + return t.typ == nullToken +} + +func (t token) render(f *File, w io.Writer, s *Statement) error { + switch t.typ { + case literalToken: + var out string + switch t.content.(type) { + case bool, string, int, complex128: + // default constant types can be left bare + out = fmt.Sprintf("%#v", t.content) + case float64: + out = fmt.Sprintf("%#v", t.content) + if !strings.Contains(out, ".") && !strings.Contains(out, "e") { + // If the formatted value is not in scientific notation, and does not have a dot, then + // we add ".0". Otherwise it will be interpreted as an int. + // See: + // https://github.com/dave/jennifer/issues/39 + // https://github.com/golang/go/issues/26363 + out += ".0" + } + case float32, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr: + // other built-in types need specific type info + out = fmt.Sprintf("%T(%#v)", t.content, t.content) + case complex64: + // fmt package already renders parenthesis for complex64 + out = fmt.Sprintf("%T%#v", t.content, t.content) + default: + panic(fmt.Sprintf("unsupported type for literal: %T", t.content)) + } + if _, err := w.Write([]byte(out)); err != nil { + return err + } + case literalRuneToken: + if _, err := w.Write([]byte(strconv.QuoteRune(t.content.(rune)))); err != nil { + return err + } + case literalByteToken: + if _, err := w.Write([]byte(fmt.Sprintf("byte(%#v)", t.content))); err != nil { + return err + } + case keywordToken, operatorToken, layoutToken, delimiterToken: + if _, err := w.Write([]byte(fmt.Sprintf("%s", t.content))); err != nil { + return err + } + if t.content.(string) == "default" { + // Special case for Default, which must always be followed by a colon + if _, err := w.Write([]byte(":")); err != nil { + return err + } + } + case packageToken: + path := t.content.(string) + alias := f.register(path) + if _, err := w.Write([]byte(alias)); err != nil { + return err + } + case identifierToken: + if _, err := w.Write([]byte(t.content.(string))); err != nil { + return err + } + case nullToken: // notest + // do nothing (should never render a null token) + } + return nil +} + +// Null adds a null item. Null items render nothing and are not followed by a +// separator in lists. +func Null() *Statement { + return newStatement().Null() +} + +// Null adds a null item. Null items render nothing and are not followed by a +// separator in lists. +func (g *Group) Null() *Statement { + s := Null() + g.items = append(g.items, s) + return s +} + +// Null adds a null item. Null items render nothing and are not followed by a +// separator in lists. +func (s *Statement) Null() *Statement { + t := token{ + typ: nullToken, + } + *s = append(*s, t) + return s +} + +// Empty adds an empty item. Empty items render nothing but are followed by a +// separator in lists. +func Empty() *Statement { + return newStatement().Empty() +} + +// Empty adds an empty item. Empty items render nothing but are followed by a +// separator in lists. +func (g *Group) Empty() *Statement { + s := Empty() + g.items = append(g.items, s) + return s +} + +// Empty adds an empty item. Empty items render nothing but are followed by a +// separator in lists. +func (s *Statement) Empty() *Statement { + t := token{ + typ: operatorToken, + content: "", + } + *s = append(*s, t) + return s +} + +// Op renders the provided operator / token. +func Op(op string) *Statement { + return newStatement().Op(op) +} + +// Op renders the provided operator / token. +func (g *Group) Op(op string) *Statement { + s := Op(op) + g.items = append(g.items, s) + return s +} + +// Op renders the provided operator / token. +func (s *Statement) Op(op string) *Statement { + t := token{ + typ: operatorToken, + content: op, + } + *s = append(*s, t) + return s +} + +// Dot renders a period followed by an identifier. Use for fields and selectors. +func Dot(name string) *Statement { + // notest + // don't think this can be used in valid code? + return newStatement().Dot(name) +} + +// Dot renders a period followed by an identifier. Use for fields and selectors. +func (g *Group) Dot(name string) *Statement { + // notest + // don't think this can be used in valid code? + s := Dot(name) + g.items = append(g.items, s) + return s +} + +// Dot renders a period followed by an identifier. Use for fields and selectors. +func (s *Statement) Dot(name string) *Statement { + d := token{ + typ: delimiterToken, + content: ".", + } + t := token{ + typ: identifierToken, + content: name, + } + *s = append(*s, d, t) + return s +} + +// Id renders an identifier. +func Id(name string) *Statement { + return newStatement().Id(name) +} + +// Id renders an identifier. +func (g *Group) Id(name string) *Statement { + s := Id(name) + g.items = append(g.items, s) + return s +} + +// Id renders an identifier. +func (s *Statement) Id(name string) *Statement { + t := token{ + typ: identifierToken, + content: name, + } + *s = append(*s, t) + return s +} + +// Qual renders a qualified identifier. Imports are automatically added when +// used with a File. If the path matches the local path, the package name is +// omitted. If package names conflict they are automatically renamed. Note that +// it is not possible to reliably determine the package name given an arbitrary +// package path, so a sensible name is guessed from the path and added as an +// alias. The names of all standard library packages are known so these do not +// need to be aliased. If more control is needed of the aliases, see +// [File.ImportName](#importname) or [File.ImportAlias](#importalias). +func Qual(path, name string) *Statement { + return newStatement().Qual(path, name) +} + +// Qual renders a qualified identifier. Imports are automatically added when +// used with a File. If the path matches the local path, the package name is +// omitted. If package names conflict they are automatically renamed. Note that +// it is not possible to reliably determine the package name given an arbitrary +// package path, so a sensible name is guessed from the path and added as an +// alias. The names of all standard library packages are known so these do not +// need to be aliased. If more control is needed of the aliases, see +// [File.ImportName](#importname) or [File.ImportAlias](#importalias). +func (g *Group) Qual(path, name string) *Statement { + s := Qual(path, name) + g.items = append(g.items, s) + return s +} + +// Qual renders a qualified identifier. Imports are automatically added when +// used with a File. If the path matches the local path, the package name is +// omitted. If package names conflict they are automatically renamed. Note that +// it is not possible to reliably determine the package name given an arbitrary +// package path, so a sensible name is guessed from the path and added as an +// alias. The names of all standard library packages are known so these do not +// need to be aliased. If more control is needed of the aliases, see +// [File.ImportName](#importname) or [File.ImportAlias](#importalias). +func (s *Statement) Qual(path, name string) *Statement { + g := &Group{ + close: "", + items: []Code{ + token{ + typ: packageToken, + content: path, + }, + token{ + typ: identifierToken, + content: name, + }, + }, + name: "qual", + open: "", + separator: ".", + } + *s = append(*s, g) + return s +} + +// Line inserts a blank line. +func Line() *Statement { + return newStatement().Line() +} + +// Line inserts a blank line. +func (g *Group) Line() *Statement { + s := Line() + g.items = append(g.items, s) + return s +} + +// Line inserts a blank line. +func (s *Statement) Line() *Statement { + t := token{ + typ: layoutToken, + content: "\n", + } + *s = append(*s, t) + return s +}