pax_global_header00006660000000000000000000000064137221665600014522gustar00rootroot0000000000000052 comment=2abe0ee856a1cfbca4a3327861b51d9c1c1a8592 jennifer-1.4.1/000077500000000000000000000000001372216656000133255ustar00rootroot00000000000000jennifer-1.4.1/.gitignore000066400000000000000000000004601372216656000153150ustar00rootroot00000000000000*.iml # Compiled Object files, Static and Dynamic libs (Shared Objects) *.o *.a *.so # Folders _obj _test # Architecture specific extensions/prefixes *.[568vq] [568vq].out *.cgo1.go *.cgo2.c _cgo_defun.c _cgo_gotypes.go _cgo_export.* _testmain.go *.exe *.test *.prof .DS_Store .idea/ coverage.out jennifer-1.4.1/.travis.yml000066400000000000000000000004031372216656000154330ustar00rootroot00000000000000language: go go: - 1.x notificaitons: email: recipients: dave@brophy.uk on_failure: always install: - go get -u github.com/dave/courtney - go get -t -v ./... script: - courtney -e after_success: - bash <(curl -s https://codecov.io/bash) jennifer-1.4.1/LICENSE000066400000000000000000000020551372216656000143340ustar00rootroot00000000000000MIT 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. jennifer-1.4.1/README.md000066400000000000000000000626431372216656000146170ustar00rootroot00000000000000[![Build Status](https://travis-ci.org/dave/jennifer.svg?branch=master)](https://travis-ci.org/dave/jennifer) [![Go Report Card](https://goreportcard.com/badge/github.com/dave/jennifer)](https://goreportcard.com/report/github.com/dave/jennifer) [![codecov](https://img.shields.io/badge/codecov-100%25-brightgreen.svg)](https://codecov.io/gh/dave/jennifer) ![stability-stable](https://img.shields.io/badge/stability-stable-brightgreen.svg) [![Sourcegraph](https://sourcegraph.com/github.com/dave/jennifer/-/badge.svg)](https://sourcegraph.com/github.com/dave/jennifer?badge) # Jennifer Jennifer is a code generator for Go. ```go package main import ( "fmt" . "github.com/dave/jennifer/jen" ) func main() { f := NewFile("main") f.Func().Id("main").Params().Block( Qual("fmt", "Println").Call(Lit("Hello, world")), ) fmt.Printf("%#v", f) } ``` Output: ```go package main import "fmt" func main() { fmt.Println("Hello, world") } ``` ### Install ``` go get -u github.com/dave/jennifer/jen ``` ### Need help? If you get stuck, have a question, would like a code review, or just want a chat: I'm happy to help! Feel free to open an issue, email me or mention @dave in your PR. ### Examples Jennifer has a comprehensive suite of examples - see [godoc](https://godoc.org/github.com/dave/jennifer/jen#pkg-examples) for an index. Here's some examples of jennifer being used in the real-world: * [genjen](genjen/render.go) (which generates much of jennifer, using data in [data.go](genjen/data.go)) * [zerogen](https://github.com/mrsinham/zerogen/blob/master/generator.go) * [go-contentful-generator](https://github.com/nicolai86/go-contentful-generator) ### Rendering For testing, a File or Statement can be rendered with the fmt package using the %#v verb. ```go c := Id("a").Call(Lit("b")) fmt.Printf("%#v", c) // Output: // a("b") ``` This is not recommended for use in production because any error will cause a panic. For production use, [File.Render](#render) or [File.Save](#save) are preferred. # Identifiers **Identifiers** [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) ### Id Id renders an identifier. ```go c := If(Id("i").Op("==").Id("j")).Block( Return(Id("i")), ) fmt.Printf("%#v", c) // Output: // if i == j { // return i // } ``` ### Dot Dot renders a period followed by an identifier. Use for fields and selectors. ```go c := Qual("a.b/c", "Foo").Call().Dot("Bar").Index(Lit(0)).Dot("Baz") fmt.Printf("%#v", c) // Output: // c.Foo().Bar[0].Baz ``` ### Qual Qual renders a qualified identifier. ```go c := Qual("encoding/gob", "NewEncoder").Call() fmt.Printf("%#v", c) // Output: // gob.NewEncoder() ``` 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. ```go f := NewFilePath("a.b/c") f.Func().Id("init").Params().Block( Qual("a.b/c", "Foo").Call().Comment("Local package - name is omitted."), Qual("d.e/f", "Bar").Call().Comment("Import is automatically added."), Qual("g.h/f", "Baz").Call().Comment("Colliding package name is renamed."), ) fmt.Printf("%#v", f) // Output: // package c // // import ( // f "d.e/f" // f1 "g.h/f" // ) // // func init() { // Foo() // Local package - name is omitted. // f.Bar() // Import is automatically added. // f1.Baz() // Colliding package name is 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). ### List List renders a comma separated list. Use for multiple return functions. ```go c := List(Id("a"), Err()).Op(":=").Id("b").Call() fmt.Printf("%#v", c) // Output: // a, err := b() ``` # Keywords [Identifiers](#identifiers) **Keywords** [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) Simple keywords, predeclared identifiers and built-in functions are self explanatory: | Construct | Name | | ---------------- | ---- | | Keywords | Break, Chan, Const, Continue, Default, Defer, Else, Fallthrough, Func, Go, Goto, Range, Select, Type, Var | | Functions | Append, Cap, Close, Complex, Copy, Delete, Imag, Len, Make, New, Panic, Print, Println, Real, Recover | | Types | Bool, Byte, Complex64, Complex128, Error, Float32, Float64, Int, Int8, Int16, Int32, Int64, Rune, String, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr | | Constants | True, False, Iota, Nil | | Helpers | Err | Built-in functions take a list of parameters and render them appropriately: ```go c := Id("a").Op("=").Append(Id("a"), Id("b").Op("...")) fmt.Printf("%#v", c) // Output: // a = append(a, b...) ``` Special cases for [If, For](#if-for), [Interface, Struct](#interface-struct), [Switch, Case](#switch-select), [Return](#return) and [Map](#map) are explained below. # Operators [Identifiers](#identifiers) [Keywords](#keywords) **Operators** [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) Op renders the provided operator / token. ```go c := Id("a").Op(":=").Id("b").Call() fmt.Printf("%#v", c) // Output: // a := b() ``` ```go c := Id("a").Op("=").Op("*").Id("b") fmt.Printf("%#v", c) // Output: // a = *b ``` ```go c := Id("a").Call(Id("b").Op("...")) fmt.Printf("%#v", c) // Output: // a(b...) ``` ```go c := If(Parens(Id("a").Op("||").Id("b")).Op("&&").Id("c")).Block() fmt.Printf("%#v", c) // Output: // if (a || b) && c { // } ``` # Braces [Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) **Braces** [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) Several methods render curly braces, summarized below: | Name | Prefix | Separator | Example | | ------------------------------ | ------------ | --------- | -------------------------------------| | [Block](#block) | | `\n` | `func a() { ... }` or `if a { ... }` | | [Interface](#interface-struct) | `interface` | `\n` | `interface { ... }` | | [Struct](#interface-struct) | `struct` | `\n` | `struct { ... }` | | [Values](#values) | | `,` | `[]int{1, 2}` or `A{B: "c"}` | ### Block Block renders a statement list enclosed by curly braces. Use for code blocks. ```go c := Func().Id("foo").Params().String().Block( Id("a").Op("=").Id("b"), Id("b").Op("++"), Return(Id("b")), ) fmt.Printf("%#v", c) // Output: // func foo() string { // a = b // b++ // return b // } ``` ```go c := If(Id("a").Op(">").Lit(10)).Block( Id("a").Op("=").Id("a").Op("/").Lit(2), ) fmt.Printf("%#v", c) // Output: // if a > 10 { // a = a / 2 // } ``` A special case applies when used directly after Case or Default, where the braces are omitted. This allows use in switch and select statements. [See example](#switch-select). ### Interface, Struct Interface and Struct render the keyword followed by a statement list enclosed by curly braces. ```go c := Var().Id("a").Interface() fmt.Printf("%#v", c) // Output: // var a interface{} ``` ```go c := Type().Id("a").Interface( Id("b").Params().String(), ) fmt.Printf("%#v", c) // Output: // type a interface { // b() string // } ``` ```go c := Id("c").Op(":=").Make(Chan().Struct()) fmt.Printf("%#v", c) // Output: // c := make(chan struct{}) ``` ```go c := Type().Id("foo").Struct( List(Id("x"), Id("y")).Int(), Id("u").Float32(), ) fmt.Printf("%#v", c) // Output: // type foo struct { // x, y int // u float32 // } ``` # Parentheses [Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) **Parentheses** [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) Several methods output parenthesis, summarized below: | Name | Prefix | Separator | Example | | ----------------- | ------ | --------- | --------------------------------- | | [Call](#call) | | `,` | `fmt.Println(b, c)` | | [Params](#params) | | `,` | `func (a *A) Foo(i int) { ... }` | | [Defs](#defs) | | `\n` | `const ( ... )` | | [Parens](#parens) | | | `[]byte(s)` or `a / (b + c)` | | [Assert](#assert) | `.` | | `s, ok := i.(string)` | ### Call Call renders a comma separated list enclosed by parenthesis. Use for function calls. ```go c := Qual("fmt", "Printf").Call( Lit("%#v: %T\n"), Id("a"), Id("b"), ) fmt.Printf("%#v", c) // Output: // fmt.Printf("%#v: %T\n", a, b) ``` ### Params Params renders a comma separated list enclosed by parenthesis. Use for function parameters and method receivers. ```go c := Func().Params( Id("a").Id("A"), ).Id("foo").Params( Id("b"), Id("c").String(), ).String().Block( Return(Id("b").Op("+").Id("c")), ) fmt.Printf("%#v", c) // Output: // func (a A) foo(b, c string) string { // return b + c // } ``` ### Defs Defs renders a statement list enclosed in parenthesis. Use for definition lists. ```go c := Const().Defs( Id("a").Op("=").Lit("a"), Id("b").Op("=").Lit("b"), ) fmt.Printf("%#v", c) // Output: // const ( // a = "a" // b = "b" // ) ``` ### Parens Parens renders a single item in parenthesis. Use for type conversion or to specify evaluation order. ```go c := Id("b").Op(":=").Index().Byte().Parens(Id("s")) fmt.Printf("%#v", c) // Output: // b := []byte(s) ``` ```go c := Id("a").Op("/").Parens(Id("b").Op("+").Id("c")) fmt.Printf("%#v", c) // Output: // a / (b + c) ``` ### Assert Assert renders a period followed by a single item enclosed by parenthesis. Use for type assertions. ```go c := List(Id("b"), Id("ok")).Op(":=").Id("a").Assert(Bool()) fmt.Printf("%#v", c) // Output: // b, ok := a.(bool) ``` # Control flow [Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) **Control flow** [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) ### If, For If and For render the keyword followed by a semicolon separated list. ```go c := If( Err().Op(":=").Id("a").Call(), Err().Op("!=").Nil(), ).Block( Return(Err()), ) fmt.Printf("%#v", c) // Output: // if err := a(); err != nil { // return err // } ``` ```go c := For( Id("i").Op(":=").Lit(0), Id("i").Op("<").Lit(10), Id("i").Op("++"), ).Block( Qual("fmt", "Println").Call(Id("i")), ) fmt.Printf("%#v", c) // Output: // for i := 0; i < 10; i++ { // fmt.Println(i) // } ``` ### Switch, Select Switch, Select, Case and Block are used to build switch or select statements: ```go c := Switch(Id("value").Dot("Kind").Call()).Block( Case(Qual("reflect", "Float32"), Qual("reflect", "Float64")).Block( Return(Lit("float")), ), Case(Qual("reflect", "Bool")).Block( Return(Lit("bool")), ), Case(Qual("reflect", "Uintptr")).Block( Fallthrough(), ), Default().Block( Return(Lit("none")), ), ) fmt.Printf("%#v", c) // Output: // switch value.Kind() { // case reflect.Float32, reflect.Float64: // return "float" // case reflect.Bool: // return "bool" // case reflect.Uintptr: // fallthrough // default: // return "none" // } ``` ### Return Return renders the keyword followed by a comma separated list. ```go c := Return(Id("a"), Id("b")) fmt.Printf("%#v", c) // Output: // return a, b ``` # Collections [Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) **Collections** [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) ### Map Map renders the keyword followed by a single item enclosed by square brackets. Use for map definitions. ```go c := Id("a").Op(":=").Map(String()).String().Values() fmt.Printf("%#v", c) // Output: // a := map[string]string{} ``` ### Index Index renders a colon separated list enclosed by square brackets. Use for array / slice indexes and definitions. ```go c := Var().Id("a").Index().String() fmt.Printf("%#v", c) // Output: // var a []string ``` ```go c := Id("a").Op(":=").Id("b").Index(Lit(0), Lit(1)) fmt.Printf("%#v", c) // Output: // a := b[0:1] ``` ```go c := Id("a").Op(":=").Id("b").Index(Lit(1), Empty()) fmt.Printf("%#v", c) // Output: // a := b[1:] ``` ### Values Values renders a comma separated list enclosed by curly braces. Use for slice or composite literals. ```go c := Index().String().Values(Lit("a"), Lit("b")) fmt.Printf("%#v", c) // Output: // []string{"a", "b"} ``` Dict renders as key/value pairs. Use with Values for map or composite literals. ```go c := Map(String()).String().Values(Dict{ Lit("a"): Lit("b"), Lit("c"): Lit("d"), }) fmt.Printf("%#v", c) // Output: // map[string]string{ // "a": "b", // "c": "d", // } ``` ```go c := Op("&").Id("Person").Values(Dict{ Id("Age"): Lit(1), Id("Name"): Lit("a"), }) fmt.Printf("%#v", c) // Output: // &Person{ // Age: 1, // Name: "a", // } ``` DictFunc executes a func(Dict) to generate the value. ```go c := Id("a").Op(":=").Map(String()).String().Values(DictFunc(func(d Dict) { d[Lit("a")] = Lit("b") d[Lit("c")] = Lit("d") })) fmt.Printf("%#v", c) // Output: // a := map[string]string{ // "a": "b", // "c": "d", // } ``` Note: the items are ordered by key when rendered to ensure repeatable code. # Literals [Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) **Literals** [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) ### Lit 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. ```go c := Id("a").Op(":=").Lit("a") fmt.Printf("%#v", c) // Output: // a := "a" ``` ```go c := Id("a").Op(":=").Lit(1.5) fmt.Printf("%#v", c) // Output: // a := 1.5 ``` LitFunc generates the value to render by executing the provided function. ```go c := Id("a").Op(":=").LitFunc(func() interface{} { return 1 + 1 }) fmt.Printf("%#v", c) // Output: // a := 2 ``` For the default constant types (bool, int, float64, string, complex128), Lit will render the untyped constant. | Code | Output | | ------------- | ---------- | | `Lit(true)` | `true` | | `Lit(1)` | `1` | | `Lit(1.0)` | `1.0` | | `Lit("foo")` | `"foo"` | | `Lit(0 + 1i)` | `(0 + 1i)` | For all other built-in types (float32, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr, complex64), Lit will also render the type. | Code | Output | | ------------------------ | ------------------- | | `Lit(float32(1))` | `float32(1)` | | `Lit(int16(1))` | `int16(1)` | | `Lit(uint8(0x1))` | `uint8(0x1)` | | `Lit(complex64(0 + 1i))` | `complex64(0 + 1i)` | The built-in alias types byte and rune need a special case. LitRune and LitByte render rune and byte literals. | Code | Output | | ------------------------ | ----------- | | `LitRune('x')` | `'x'` | | `LitByte(byte(0x1))` | `byte(0x1)` | # Comments [Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) **Comments** [Helpers](#helpers) [Misc](#misc) [File](#file) ### Comment Comment adds a comment. If the provided string contains a newline, the comment is formatted in multiline style. ```go f := NewFile("a") f.Comment("Foo returns the string \"foo\"") f.Func().Id("Foo").Params().String().Block( Return(Lit("foo")).Comment("return the string foo"), ) fmt.Printf("%#v", f) // Output: // package a // // // Foo returns the string "foo" // func Foo() string { // return "foo" // return the string foo // } ``` ```go c := Comment("a\nb") fmt.Printf("%#v", c) // Output: // /* // a // b // */ ``` If the comment string starts with "//" or "/*", the automatic formatting is disabled and the string is rendered directly. ```go c := Id("foo").Call(Comment("/* inline */")).Comment("//no-space") fmt.Printf("%#v", c) // Output: // foo( /* inline */ ) //no-space ``` ### Commentf Commentf adds a comment, using a format string and a list of parameters. ```go name := "foo" val := "bar" c := Id(name).Op(":=").Lit(val).Commentf("%s is the string \"%s\"", name, val) fmt.Printf("%#v", c) // Output: // foo := "bar" // foo is the string "bar" ``` # Helpers [Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) **Helpers** [Misc](#misc) [File](#file) ### Func methods All constructs that accept a variadic list of items are paired with GroupFunc functions that accept a func(*Group). Use for embedding logic. ```go c := Id("numbers").Op(":=").Index().Int().ValuesFunc(func(g *Group) { for i := 0; i <= 5; i++ { g.Lit(i) } }) fmt.Printf("%#v", c) // Output: // numbers := []int{0, 1, 2, 3, 4, 5} ``` ```go increment := true name := "a" c := Func().Id("a").Params().BlockFunc(func(g *Group) { g.Id(name).Op("=").Lit(1) if increment { g.Id(name).Op("++") } else { g.Id(name).Op("--") } }) fmt.Printf("%#v", c) // Output: // func a() { // a = 1 // a++ // } ``` ### Add Add appends the provided items to the statement. ```go ptr := Op("*") c := Id("a").Op("=").Add(ptr).Id("b") fmt.Printf("%#v", c) // Output: // a = *b ``` ```go a := Id("a") i := Int() c := Var().Add(a, i) fmt.Printf("%#v", c) // Output: // var a int ``` ### Do Do calls the provided function with the statement as a parameter. Use for embedding logic. ```go f := func(name string, isMap bool) *Statement { return Id(name).Op(":=").Do(func(s *Statement) { if isMap { s.Map(String()).String() } else { s.Index().String() } }).Values() } fmt.Printf("%#v\n%#v", f("a", true), f("b", false)) // Output: // a := map[string]string{} // b := []string{} ``` # Misc [Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) **Misc** [File](#file) ### Tag Tag renders a struct tag ```go c := Type().Id("foo").Struct( Id("A").String().Tag(map[string]string{"json": "a"}), Id("B").Int().Tag(map[string]string{"json": "b", "bar": "baz"}), ) fmt.Printf("%#v", c) // Output: // type foo struct { // A string `json:"a"` // B int `bar:"baz" json:"b"` // } ``` Note: the items are ordered by key when rendered to ensure repeatable code. ### Null Null adds a null item. Null items render nothing and are not followed by a separator in lists. In lists, nil will produce the same effect. ```go c := Func().Id("foo").Params( nil, Id("s").String(), Null(), Id("i").Int(), ).Block() fmt.Printf("%#v", c) // Output: // func foo(s string, i int) {} ``` ### Empty Empty adds an empty item. Empty items render nothing but are followed by a separator in lists. ```go c := Id("a").Op(":=").Id("b").Index(Lit(1), Empty()) fmt.Printf("%#v", c) // Output: // a := b[1:] ``` ### Line Line inserts a blank line. ### Clone Be careful when passing *Statement. Consider the following... ```go a := Id("a") c := Block( a.Call(), a.Call(), ) fmt.Printf("%#v", c) // Output: // { // a()() // a()() // } ``` Id("a") returns a *Statement, which the Call() method appends to twice. To avoid this, use Clone. Clone makes a copy of the Statement, so further tokens can be appended without affecting the original. ```go a := Id("a") c := Block( a.Clone().Call(), a.Clone().Call(), ) fmt.Printf("%#v", c) // Output: // { // a() // a() // } ``` ### Cgo The cgo "C" pseudo-package is a special case, and always renders without a package alias. The import can be added with `Qual`, `Anon` or by supplying a preamble. The preamble is added with `File.CgoPreamble` which has the same semantics as [Comment](#comments). If a preamble is provided, the import is separated, and preceded by the preamble. ```go f := NewFile("a") f.CgoPreamble(`#include #include void myprint(char* s) { printf("%s\n", s); } `) f.Func().Id("init").Params().Block( Id("cs").Op(":=").Qual("C", "CString").Call(Lit("Hello from stdio\n")), Qual("C", "myprint").Call(Id("cs")), Qual("C", "free").Call(Qual("unsafe", "Pointer").Parens(Id("cs"))), ) fmt.Printf("%#v", f) // Output: // package a // // import "unsafe" // // /* // #include // #include // // void myprint(char* s) { // printf("%s\n", s); // } // */ // import "C" // // func init() { // cs := C.CString("Hello from stdio\n") // C.myprint(cs) // C.free(unsafe.Pointer(cs)) // } ``` # File [Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) **File** File represents a single source file. Package imports are managed automaticaly by File. ### NewFile NewFile Creates a new file, with the specified package name. ### NewFilePath NewFilePath creates a new file while specifying the package path - the package name is inferred from the path. ### NewFilePathName NewFilePathName creates a new file with the specified package path and name. ```go f := NewFilePathName("a.b/c", "main") f.Func().Id("main").Params().Block( Qual("a.b/c", "Foo").Call(), ) fmt.Printf("%#v", f) // Output: // package main // // func main() { // Foo() // } ``` ### Save Save renders the file and saves to the filename provided. ### Render Render renders the file to the provided writer. ```go f := NewFile("a") f.Func().Id("main").Params().Block() buf := &bytes.Buffer{} err := f.Render(buf) if err != nil { fmt.Println(err.Error()) } else { fmt.Println(buf.String()) } // Output: // package a // // func main() {} ``` ### Anon Anon adds an anonymous import. ```go f := NewFile("c") f.Anon("a") f.Func().Id("init").Params().Block() fmt.Printf("%#v", f) // Output: // package c // // import _ "a" // // func init() {} ``` ### ImportName 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. ```go f := NewFile("main") // package a should use name "a" f.ImportName("github.com/foo/a", "a") // package b is not used in the code so will not be included f.ImportName("github.com/foo/b", "b") f.Func().Id("main").Params().Block( Qual("github.com/foo/a", "A").Call(), ) fmt.Printf("%#v", f) // Output: // package main // // import "github.com/foo/a" // // func main() { // a.A() // } ``` ### ImportNames 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. ### ImportAlias ImportAlias provides the alias for a package path that should be used in the import block. A period can be used to force a dot-import. ```go f := NewFile("main") // package a should be aliased to "b" f.ImportAlias("github.com/foo/a", "b") // package c is not used in the code so will not be included f.ImportAlias("github.com/foo/c", "c") f.Func().Id("main").Params().Block( Qual("github.com/foo/a", "A").Call(), ) fmt.Printf("%#v", f) // Output: // package main // // import b "github.com/foo/a" // // func main() { // b.A() // } ``` ### Comments PackageComment adds a comment to the top of the file, above the package keyword. 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. CanonicalPath adds a canonical import path annotation to the package clause. ```go f := NewFile("c") f.CanonicalPath = "d.e/f" f.HeaderComment("Code generated by...") f.PackageComment("Package c implements...") f.Func().Id("init").Params().Block() fmt.Printf("%#v", f) // Output: // // Code generated by... // // // Package c implements... // package c // import "d.e/f" // // func init() {} ``` CgoPreamble adds a cgo preamble comment that is rendered directly before the "C" pseudo-package import. ### PackagePrefix If you're worried about generated package aliases conflicting with local variable names, you can set a prefix here. Package foo becomes {prefix}_foo. ```go f := NewFile("a") f.PackagePrefix = "pkg" f.Func().Id("main").Params().Block( Qual("b.c/d", "E").Call(), ) fmt.Printf("%#v", f) // Output: // package a // // import pkg_d "b.c/d" // // func main() { // pkg_d.E() // } ``` jennifer-1.4.1/README.md.tpl000066400000000000000000000317161372216656000154120ustar00rootroot00000000000000[![Build Status](https://travis-ci.org/dave/jennifer.svg?branch=master)](https://travis-ci.org/dave/jennifer) [![Go Report Card](https://goreportcard.com/badge/github.com/dave/jennifer)](https://goreportcard.com/report/github.com/dave/jennifer) [![codecov](https://img.shields.io/badge/codecov-100%25-brightgreen.svg)](https://codecov.io/gh/dave/jennifer) ![stability-stable](https://img.shields.io/badge/stability-stable-brightgreen.svg) [![Sourcegraph](https://sourcegraph.com/github.com/dave/jennifer/-/badge.svg)](https://sourcegraph.com/github.com/dave/jennifer?badge) # Jennifer Jennifer is a code generator for Go. ```go package main import ( "fmt" . "github.com/dave/jennifer/jen" ) func main() {{ "ExampleNewFile" | code }} ``` Output: ```go {{ "ExampleNewFile" | output }} ``` ### Install ``` go get -u github.com/dave/jennifer/jen ``` ### Need help? If you get stuck, have a question, would like a code review, or just want a chat: I'm happy to help! Feel free to open an issue, email me or mention @dave in your PR. ### Examples Jennifer has a comprehensive suite of examples - see [godoc](https://godoc.org/github.com/dave/jennifer/jen#pkg-examples) for an index. Here's some examples of jennifer being used in the real-world: * [genjen](genjen/render.go) (which generates much of jennifer, using data in [data.go](genjen/data.go)) * [zerogen](https://github.com/mrsinham/zerogen/blob/master/generator.go) * [go-contentful-generator](https://github.com/nicolai86/go-contentful-generator) ### Rendering For testing, a File or Statement can be rendered with the fmt package using the %#v verb. {{ "ExampleCall_fmt" | example }} This is not recommended for use in production because any error will cause a panic. For production use, [File.Render](#render) or [File.Save](#save) are preferred. # Identifiers **Identifiers** [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) ### Id {{ "Id" | doc }} {{ "ExampleId" | example }} ### Dot {{ "Dot" | doc }} {{ "ExampleDot" | example }} ### Qual {{ "Qual[0]" | doc }} {{ "ExampleQual" | example }} {{ "Qual[1:4]" | doc }} {{ "ExampleQual_file" | example }} {{ "Qual[4:]" | doc }} ### List {{ "List" | doc }} {{ "ExampleList" | example }} # Keywords [Identifiers](#identifiers) **Keywords** [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) Simple keywords, predeclared identifiers and built-in functions are self explanatory: | Construct | Name | | ---------------- | ---- | | Keywords | Break, Chan, Const, Continue, Default, Defer, Else, Fallthrough, Func, Go, Goto, Range, Select, Type, Var | | Functions | Append, Cap, Close, Complex, Copy, Delete, Imag, Len, Make, New, Panic, Print, Println, Real, Recover | | Types | Bool, Byte, Complex64, Complex128, Error, Float32, Float64, Int, Int8, Int16, Int32, Int64, Rune, String, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr | | Constants | True, False, Iota, Nil | | Helpers | Err | Built-in functions take a list of parameters and render them appropriately: {{ "ExampleAppend_more" | example }} Special cases for [If, For](#if-for), [Interface, Struct](#interface-struct), [Switch, Case](#switch-select), [Return](#return) and [Map](#map) are explained below. # Operators [Identifiers](#identifiers) [Keywords](#keywords) **Operators** [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) {{ "Op" | doc }} {{ "ExampleOp" | example }} {{ "ExampleOp_star" | example }} {{ "ExampleOp_variadic" | example }} {{ "ExampleOp_complex_conditions" | example }} # Braces [Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) **Braces** [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) Several methods render curly braces, summarized below: | Name | Prefix | Separator | Example | | ------------------------------ | ------------ | --------- | -------------------------------------| | [Block](#block) | | `\n` | `func a() { ... }` or `if a { ... }` | | [Interface](#interface-struct) | `interface` | `\n` | `interface { ... }` | | [Struct](#interface-struct) | `struct` | `\n` | `struct { ... }` | | [Values](#values) | | `,` | `[]int{1, 2}` or `A{B: "c"}` | ### Block {{ "Block[:2]" | doc }} {{ "ExampleBlock" | example }} {{ "ExampleBlock_if" | example }} {{ "Block[2:]" | doc }} [See example](#switch-select). ### Interface, Struct Interface and Struct render the keyword followed by a statement list enclosed by curly braces. {{ "ExampleInterface_empty" | example }} {{ "ExampleInterface" | example }} {{ "ExampleStruct_empty" | example }} {{ "ExampleStruct" | example }} # Parentheses [Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) **Parentheses** [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) Several methods output parenthesis, summarized below: | Name | Prefix | Separator | Example | | ----------------- | ------ | --------- | --------------------------------- | | [Call](#call) | | `,` | `fmt.Println(b, c)` | | [Params](#params) | | `,` | `func (a *A) Foo(i int) { ... }` | | [Defs](#defs) | | `\n` | `const ( ... )` | | [Parens](#parens) | | | `[]byte(s)` or `a / (b + c)` | | [Assert](#assert) | `.` | | `s, ok := i.(string)` | ### Call {{ "Call" | doc }} {{ "ExampleCall" | example }} ### Params {{ "Params" | doc }} {{ "ExampleParams" | example }} ### Defs {{ "Defs" | doc }} {{ "ExampleDefs" | example }} ### Parens {{ "Parens" | doc }} {{ "ExampleParens" | example }} {{ "ExampleParens_order" | example }} ### Assert {{ "Assert" | doc }} {{ "ExampleAssert" | example }} # Control flow [Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) **Control flow** [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) ### If, For If and For render the keyword followed by a semicolon separated list. {{ "ExampleIf" | example }} {{ "ExampleFor" | example }} ### Switch, Select Switch, Select, Case and Block are used to build switch or select statements: {{ "ExampleSwitch" | example }} ### Return {{ "Return" | doc }} {{ "ExampleReturn" | example }} # Collections [Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) **Collections** [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) ### Map {{ "Map" | doc }} {{ "ExampleMap" | example }} ### Index {{ "Index" | doc }} {{ "ExampleIndex" | example }} {{ "ExampleIndex_index" | example }} {{ "ExampleIndex_empty" | example }} ### Values {{ "Values" | doc }} {{ "ExampleValues" | example }} {{ "Dict" | doc }} {{ "ExampleValues_dict_multiple" | example }} {{ "ExampleValues_dict_composite" | example }} {{ "DictFunc[0]" | doc }} {{ "ExampleDictFunc" | example }} Note: the items are ordered by key when rendered to ensure repeatable code. # Literals [Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) **Literals** [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) ### Lit {{ "Lit" | doc }} {{ "ExampleLit" | example }} {{ "ExampleLit_float" | example }} {{ "LitFunc[1:2]" | doc }} {{ "ExampleLitFunc" | example }} For the default constant types (bool, int, float64, string, complex128), Lit will render the untyped constant. | Code | Output | | ------------- | ---------- | | `Lit(true)` | `true` | | `Lit(1)` | `1` | | `Lit(1.0)` | `1.0` | | `Lit("foo")` | `"foo"` | | `Lit(0 + 1i)` | `(0 + 1i)` | For all other built-in types (float32, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr, complex64), Lit will also render the type. | Code | Output | | ------------------------ | ------------------- | | `Lit(float32(1))` | `float32(1)` | | `Lit(int16(1))` | `int16(1)` | | `Lit(uint8(0x1))` | `uint8(0x1)` | | `Lit(complex64(0 + 1i))` | `complex64(0 + 1i)` | The built-in alias types byte and rune need a special case. LitRune and LitByte render rune and byte literals. | Code | Output | | ------------------------ | ----------- | | `LitRune('x')` | `'x'` | | `LitByte(byte(0x1))` | `byte(0x1)` | # Comments [Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) **Comments** [Helpers](#helpers) [Misc](#misc) [File](#file) ### Comment {{ "Comment[:2]" | doc }} {{ "ExampleComment" | example }} {{ "ExampleComment_multiline" | example }} {{ "Comment[2:]" | doc }} {{ "ExampleComment_formatting_disabled" | example }} ### Commentf {{ "Commentf[0]" | doc }} {{ "ExampleCommentf" | example }} # Helpers [Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) **Helpers** [Misc](#misc) [File](#file) ### Func methods All constructs that accept a variadic list of items are paired with GroupFunc functions that accept a func(*Group). Use for embedding logic. {{ "ExampleValuesFunc" | example }} {{ "ExampleBlockFunc" | example }} ### Add {{ "Add" | doc }} {{ "ExampleAdd" | example }} {{ "ExampleAdd_var" | example }} ### Do {{ "Do" | doc }} {{ "ExampleDo" | example }} # Misc [Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) **Misc** [File](#file) ### Tag {{ "Tag" | doc }} {{ "ExampleTag" | example }} Note: the items are ordered by key when rendered to ensure repeatable code. ### Null {{ "Null" | doc }} In lists, nil will produce the same effect. {{ "ExampleNull_and_nil" | example }} ### Empty {{ "Empty" | doc }} {{ "ExampleEmpty" | example }} ### Line {{ "Line" | doc }} ### Clone Be careful when passing *Statement. Consider the following... {{ "ExampleStatement_Clone_broken" | example }} Id("a") returns a *Statement, which the Call() method appends to twice. To avoid this, use Clone. {{ "Statement.Clone" | doc }} {{ "ExampleStatement_Clone_fixed" | example }} ### Cgo The cgo "C" pseudo-package is a special case, and always renders without a package alias. The import can be added with `Qual`, `Anon` or by supplying a preamble. The preamble is added with `File.CgoPreamble` which has the same semantics as [Comment](#comments). If a preamble is provided, the import is separated, and preceded by the preamble. {{ "ExampleFile_CgoPreamble" | example }} # File [Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) **File** {{ "File" | doc }} ### NewFile {{ "NewFile" | doc }} ### NewFilePath {{ "NewFilePath" | doc }} ### NewFilePathName {{ "NewFilePathName" | doc }} {{ "ExampleNewFilePathName" | example }} ### Save {{ "File.Save" | doc }} ### Render {{ "File.Render" | doc }} {{ "ExampleFile_Render" | example }} ### Anon {{ "File.Anon" | doc }} {{ "ExampleFile_Anon" | example }} ### ImportName {{ "File.ImportName" | doc }} {{ "ExampleFile_ImportName" | example }} ### ImportNames {{ "File.ImportNames" | doc }} ### ImportAlias {{ "File.ImportAlias" | doc }} {{ "ExampleFile_ImportAlias" | example }} ### Comments {{ "File.PackageComment" | doc }} {{ "File.HeaderComment" | doc }} {{ "File.CanonicalPath" | doc }} {{ "ExampleFile_HeaderAndPackageComments" | example }} {{ "File.CgoPreamble" | doc }} ### PackagePrefix {{ "File.PackagePrefix" | doc }} {{ "ExampleFile_PackagePrefix" | example }} jennifer-1.4.1/genjen/000077500000000000000000000000001372216656000145735ustar00rootroot00000000000000jennifer-1.4.1/genjen/data.go000066400000000000000000000201321372216656000160310ustar00rootroot00000000000000package main var keywords = []string{"break", "default", "func", "select", "chan", "else", "const", "fallthrough", "type", "continue", "var", "goto", "defer", "go", "range"} var identifiers = []string{"bool", "byte", "complex64", "complex128", "error", "float32", "float64", "int", "int8", "int16", "int32", "int64", "rune", "string", "uint", "uint8", "uint16", "uint32", "uint64", "uintptr", "true", "false", "iota", "nil", "err"} var groups = []struct { name string // name of the function / method comment string // comment appended to name variadic bool // is the parameter variadic? opening string // opening token closing string // closing token separator string // separator token multi bool // items are always on multiple lines parameters []string // parameter names preventFunc bool // prevent the fooFunc function/method }{ { name: "Parens", comment: "renders a single item in parenthesis. Use for type conversion or to specify evaluation order.", variadic: false, opening: "(", closing: ")", separator: "", parameters: []string{"item"}, }, { name: "List", comment: "renders a comma separated list. Use for multiple return functions.", variadic: true, opening: "", closing: "", separator: ",", parameters: []string{"items"}, }, { name: "Values", comment: "renders a comma separated list enclosed by curly braces. Use for slice or composite literals.", variadic: true, opening: "{", closing: "}", separator: ",", parameters: []string{"values"}, }, { name: "Index", comment: "renders a colon separated list enclosed by square brackets. Use for array / slice indexes and definitions.", variadic: true, opening: "[", closing: "]", separator: ":", parameters: []string{"items"}, }, { name: "Block", comment: "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.", variadic: true, opening: "{", closing: "}", multi: true, parameters: []string{"statements"}, }, { name: "Defs", comment: "renders a statement list enclosed in parenthesis. Use for definition lists.", variadic: true, opening: "(", closing: ")", multi: true, parameters: []string{"definitions"}, }, { name: "Call", comment: "renders a comma separated list enclosed by parenthesis. Use for function calls.", variadic: true, opening: "(", closing: ")", separator: ",", parameters: []string{"params"}, }, { name: "Params", comment: "renders a comma separated list enclosed by parenthesis. Use for function parameters and method receivers.", variadic: true, opening: "(", closing: ")", separator: ",", parameters: []string{"params"}, }, { name: "Assert", comment: "renders a period followed by a single item enclosed by parenthesis. Use for type assertions.", variadic: false, opening: ".(", closing: ")", separator: "", parameters: []string{"typ"}, }, { name: "Map", comment: "renders the keyword followed by a single item enclosed by square brackets. Use for map definitions.", variadic: false, opening: "map[", closing: "]", separator: "", parameters: []string{"typ"}, }, { name: "If", comment: "renders the keyword followed by a semicolon separated list.", variadic: true, opening: "if ", closing: "", separator: ";", parameters: []string{"conditions"}, }, { name: "Return", comment: "renders the keyword followed by a comma separated list.", variadic: true, opening: "return ", closing: "", separator: ",", parameters: []string{"results"}, }, { name: "For", comment: "renders the keyword followed by a semicolon separated list.", variadic: true, opening: "for ", closing: "", separator: ";", parameters: []string{"conditions"}, }, { name: "Switch", comment: "renders the keyword followed by a semicolon separated list.", variadic: true, opening: "switch ", closing: "", separator: ";", parameters: []string{"conditions"}, }, { name: "Interface", comment: "renders the keyword followed by a method list enclosed by curly braces.", variadic: true, opening: "interface{", closing: "}", multi: true, parameters: []string{"methods"}, }, { name: "Struct", comment: "renders the keyword followed by a field list enclosed by curly braces.", variadic: true, opening: "struct{", closing: "}", multi: true, parameters: []string{"fields"}, }, { name: "Case", comment: "renders the keyword followed by a comma separated list.", variadic: true, opening: "case ", closing: ":", separator: ",", parameters: []string{"cases"}, }, { name: "Append", comment: "renders the append built-in function.", variadic: true, opening: "append(", closing: ")", separator: ",", parameters: []string{"args"}, }, { name: "Cap", comment: "renders the cap built-in function.", variadic: false, opening: "cap(", closing: ")", separator: ",", parameters: []string{"v"}, }, { name: "Close", comment: "renders the close built-in function.", variadic: false, opening: "close(", closing: ")", separator: ",", parameters: []string{"c"}, }, { name: "Complex", comment: "renders the complex built-in function.", variadic: false, opening: "complex(", closing: ")", separator: ",", parameters: []string{"r", "i"}, }, { name: "Copy", comment: "renders the copy built-in function.", variadic: false, opening: "copy(", closing: ")", separator: ",", parameters: []string{"dst", "src"}, }, { name: "Delete", comment: "renders the delete built-in function.", variadic: false, opening: "delete(", closing: ")", separator: ",", parameters: []string{"m", "key"}, }, { name: "Imag", comment: "renders the imag built-in function.", variadic: false, opening: "imag(", closing: ")", separator: ",", parameters: []string{"c"}, }, { name: "Len", comment: "renders the len built-in function.", variadic: false, opening: "len(", closing: ")", separator: ",", parameters: []string{"v"}, }, { name: "Make", comment: "renders the make built-in function. The final parameter of the make function is optional, so it is represented by a variadic parameter list.", variadic: true, opening: "make(", closing: ")", separator: ",", parameters: []string{"args"}, preventFunc: true, // the underlying function is not variadic, so we prevent the MakeFunc variation }, { name: "New", comment: "renders the new built-in function.", variadic: false, opening: "new(", closing: ")", separator: ",", parameters: []string{"typ"}, }, { name: "Panic", comment: "renders the panic built-in function.", variadic: false, opening: "panic(", closing: ")", separator: ",", parameters: []string{"v"}, }, { name: "Print", comment: "renders the print built-in function.", variadic: true, opening: "print(", closing: ")", separator: ",", parameters: []string{"args"}, }, { name: "Println", comment: "renders the println built-in function.", variadic: true, opening: "println(", closing: ")", separator: ",", parameters: []string{"args"}, }, { name: "Real", comment: "renders the real built-in function.", variadic: false, opening: "real(", closing: ")", separator: ",", parameters: []string{"c"}, }, { name: "Recover", comment: "renders the recover built-in function.", variadic: false, opening: "recover(", closing: ")", separator: ",", parameters: []string{}, }, } jennifer-1.4.1/genjen/main.go000066400000000000000000000003731372216656000160510ustar00rootroot00000000000000package main import ( "bytes" "io/ioutil" ) func main() { // notest buf := &bytes.Buffer{} if err := render(buf); err != nil { panic(err) } if err := ioutil.WriteFile("./jen/generated.go", buf.Bytes(), 0644); err != nil { panic(err) } } jennifer-1.4.1/genjen/render.go000066400000000000000000000133401372216656000164020ustar00rootroot00000000000000package main import ( "io" "strings" . "github.com/dave/jennifer/jen" ) func render(w io.Writer) error { file := NewFile("jen") file.HeaderComment("This file is generated - do not edit.") file.Line() for _, b := range groups { b := b // b used in closures comment := Commentf("%s %s", b.name, b.comment) if b.variadic && len(b.parameters) > 1 { panic("should not have variadic function with multiple params") } var variadic Code if b.variadic { variadic = Op("...") } var funcParams []Code var callParams []Code for _, name := range b.parameters { funcParams = append(funcParams, Id(name).Add(variadic).Id("Code")) callParams = append(callParams, Id(name).Add(variadic)) } addFunctionAndGroupMethod( file, b.name, comment, funcParams, callParams, false, ) /* // func (s *Statement) () *Statement { g := &Group{ items: []Code{}|, name: "", open: "", close: "", separator: "", multi: , } *s = append(*s, g) return s } */ file.Add(comment) file.Func().Params( Id("s").Op("*").Id("Statement"), ).Id(b.name).Params( funcParams..., ).Op("*").Id("Statement").Block( Id("g").Op(":=").Op("&").Id("Group").Values(Dict{ Id("items"): Do(func(s *Statement) { if b.variadic { s.Id(b.parameters[0]) } else { s.Index().Id("Code").ValuesFunc(func(g *Group) { for _, name := range b.parameters { g.Id(name) } }) } }), Id("name"): Lit(strings.ToLower(b.name)), Id("open"): Lit(b.opening), Id("close"): Lit(b.closing), Id("separator"): Lit(b.separator), Id("multi"): Lit(b.multi), }), Op("*").Id("s").Op("=").Append(Op("*").Id("s"), Id("g")), Return(Id("s")), ) if b.variadic && !b.preventFunc { funcName := b.name + "Func" funcComment := Commentf("%sFunc %s", b.name, b.comment) funcFuncParams := []Code{Id("f").Func().Params(Op("*").Id("Group"))} funcCallParams := []Code{Id("f")} addFunctionAndGroupMethod( file, funcName, funcComment, funcFuncParams, funcCallParams, false, ) /* // func (s *Statement) (f func(*Group)) *Statement { g := &Group{ name: "", open: "", close: "", separator: "", multi: , } f(g) *s = append(*s, g) return s } */ file.Add(funcComment) file.Func().Params( Id("s").Op("*").Id("Statement"), ).Id(funcName).Params( funcFuncParams..., ).Op("*").Id("Statement").Block( Id("g").Op(":=").Op("&").Id("Group").Values(Dict{ Id("name"): Lit(strings.ToLower(b.name)), Id("open"): Lit(b.opening), Id("close"): Lit(b.closing), Id("separator"): Lit(b.separator), Id("multi"): Lit(b.multi), }), Id("f").Call(Id("g")), Op("*").Id("s").Op("=").Append(Op("*").Id("s"), Id("g")), Return(Id("s")), ) } } type tkn struct { token string name string tokenType string tokenDesc string } tokens := []tkn{} for _, v := range identifiers { tokens = append(tokens, tkn{ token: v, name: strings.ToUpper(v[:1]) + v[1:], tokenType: "identifierToken", tokenDesc: "identifier", }) } for _, v := range keywords { tokens = append(tokens, tkn{ token: v, name: strings.ToUpper(v[:1]) + v[1:], tokenType: "keywordToken", tokenDesc: "keyword", }) } for i, t := range tokens { t := t // used in closures comment := Commentf( "%s renders the %s %s.", t.name, t.token, t.tokenDesc, ) addFunctionAndGroupMethod( file, t.name, comment, nil, nil, i != 0, // only enforce test coverage on one item ) /* // func (s *Statement) () *Statement { t := token{ typ: , content: "", } *s = append(*s, t) return s } */ file.Add(comment) file.Func().Params( Id("s").Op("*").Id("Statement"), ).Id(t.name).Params().Op("*").Id("Statement").Block( Do(func(s *Statement) { if i != 0 { // only enforce test coverage on one item s.Comment("notest") } }), Id("t").Op(":=").Id("token").Values(Dict{ Id("typ"): Id(t.tokenType), Id("content"): Lit(t.token), }), Op("*").Id("s").Op("=").Append(Op("*").Id("s"), Id("t")), Return(Id("s")), ) } return file.Render(w) } // For each method on *Statement, this generates a package level // function and a method on *Group, both with the same name. func addFunctionAndGroupMethod( file *File, name string, comment *Statement, funcParams []Code, callParams []Code, notest bool, ) { /* // func () *Statement { return newStatement().() } */ file.Add(comment) file.Func().Id(name).Params(funcParams...).Op("*").Id("Statement").Block( Do(func(s *Statement) { if notest { // only enforce test coverage on one item s.Comment("notest") } }), Return(Id("newStatement").Call().Dot(name).Call(callParams...)), ) /* // func (g *Group) () *Statement { s := () g.items = append(g.items, s) return s } */ file.Add(comment) file.Func().Params( Id("g").Op("*").Id("Group"), ).Id(name).Params(funcParams...).Op("*").Id("Statement").Block( Do(func(s *Statement) { if notest { // only enforce test coverage on one item s.Comment("notest") } }), Id("s").Op(":=").Id(name).Params(callParams...), Id("g").Dot("items").Op("=").Append(Id("g").Dot("items"), Id("s")), Return(Id("s")), ) } jennifer-1.4.1/genjen/render_test.go000066400000000000000000000015441372216656000174440ustar00rootroot00000000000000package main import ( "io/ioutil" "regexp" "testing" "bytes" ) func TestRender(t *testing.T) { buf := &bytes.Buffer{} if err := render(buf); err != nil { t.Fatal(err.Error()) } generatedString := buf.String() existingFilePath := "../jen/generated.go" existingBytes, err := ioutil.ReadFile(existingFilePath) if err != nil { t.Fatal(err.Error()) } existingString := string(existingBytes) // The "goimports" tool will often re-order the imports, so this is a // kludge to remove it before comparing. This is not ideal! importsRegex := regexp.MustCompile(`(?ms:\nimport \(\n.*\n\)\n)`) generatedString = importsRegex.ReplaceAllString(generatedString, "-") existingString = importsRegex.ReplaceAllString(existingString, "-") if generatedString != existingString { t.Fatalf("Generated code is not what is present:\n%s", generatedString) } } jennifer-1.4.1/gennames/000077500000000000000000000000001372216656000151225ustar00rootroot00000000000000jennifer-1.4.1/gennames/README.md000066400000000000000000000036371372216656000164120ustar00rootroot00000000000000# gennames For large projects, it may be useful to generate an index of package names for commonly used packages. The index of names can be added to each generated file using `File.ImportNames`. The `gennames` command is used internally to generate the list of standard library package names. ### Usage ``` Usage of gennames: -filter string Regex to filter paths (operates on full path including vendor directory) (default ".*") -name string Name of the variable to define (default "PackageNames") -novendor Exclude packages in vendor directories -output string Output filename to write (default "./package-names.go") -package string Package name in generated file (default "main") -path string Path to pass to go list command (default "all") -standard Use standard library packages ``` ### Path Supply a `path` to pass to the `go list` command. You may use the wildcard `/...` to recursively return packages, but it's worth remembering that vendored packages are not returned by this method unless the path itself is a vendored path. Use `all` to return all packages in your `GOPATH` (including vendored packages), however remember this may take some time for a large `GOPATH`. ### Filter Supply a regex `filter` to limit the packages that are returned by the `go list` command. The filter operates on the full vendored package path (e.g. `github.com/foo/bar/vendor/github.com/baz/qux`), however the package path added to the index is unvendored (e.g. `github.com/baz/qux`). ### Examples ``` gennames -filter "foo|bar" ``` Create a file named `package-names.go` with `package main` listing the names of all packages with paths containing `foo` or `bar`. ``` gennames -output "foo/names.go" -package "foo" -path "github.com/foo/bar/vendor/..." ``` Create a file named `foo/names.go` with `package foo` listing the names of all packages that are vendored inside `github.com/foo/bar`. jennifer-1.4.1/gennames/hints.go000066400000000000000000000060031372216656000165750ustar00rootroot00000000000000package main import ( "fmt" "go/build" "io" "os/exec" "strings" "regexp" "path/filepath" . "github.com/dave/jennifer/jen" ) func hints(w io.Writer, pkg, name, goListPath, filter string, standard, novendor bool) error { // notest file := NewFile(pkg) file.HeaderComment("This file is generated - do not edit.") file.Line() packages, err := getPackages(goListPath, filter, standard, novendor) if err != nil { return err } /* // contains package name hints var = map[string]string{ ... } */ file.Commentf("%s contains package name hints", name) file.Var().Id(name).Op("=").Map(String()).String().Values(DictFunc(func(d Dict) { for path, name := range packages { d[Lit(path)] = Lit(name) } })) return file.Render(w) } func getPackages(goListPath, filter string, standard, novendor bool) (map[string]string, error) { // notest r, err := regexp.Compile(filter) if err != nil { return nil, err } cmd := exec.Command("go", "list", "-e", "-f", "{{ .Standard }} {{ .ImportPath }} {{ .Name }}", goListPath) cmd.Env = []string{ fmt.Sprintf("GOPATH=%s", build.Default.GOPATH), fmt.Sprintf("GOROOT=%s", build.Default.GOROOT), } if standard { cmd.Dir = filepath.Join(build.Default.GOROOT, "src") } else { cmd.Dir = filepath.Join(build.Default.GOPATH, "src") } b, err := cmd.Output() if err != nil { if x, ok := err.(*exec.ExitError); ok { return nil, fmt.Errorf("go list command returned an error - %s: %s", err.Error(), string(x.Stderr)) } return nil, fmt.Errorf("go list command returned an error: %s", err.Error()) } all := strings.Split(strings.TrimSpace(string(b)), "\n") packages := map[string]string{} for _, j := range all { parts := strings.Split(j, " ") isStandard := parts[0] == "true" if isStandard != standard { continue } path := parts[1] name := parts[2] if novendor && hasVendor(path) { continue } if name == "main" { continue } if !r.MatchString(path) { continue } path = unvendorPath(path) if packages[path] != "" { continue } packages[path] = name } return packages, nil } func unvendorPath(path string) string { // notest i, ok := findVendor(path) if !ok { return path } return path[i+len("vendor/"):] } // FindVendor looks for the last non-terminating "vendor" path element in the given import path. // If there isn't one, FindVendor returns ok=false. // Otherwise, FindVendor returns ok=true and the index of the "vendor". // Copied from cmd/go/internal/load func findVendor(path string) (index int, ok bool) { // notest // Two cases, depending on internal at start of string or not. // The order matters: we must return the index of the final element, // because the final one is where the effective import path starts. switch { case strings.Contains(path, "/vendor/"): return strings.LastIndex(path, "/vendor/") + 1, true case strings.HasPrefix(path, "vendor/"): return 0, true } return 0, false } func hasVendor(path string) bool { // notest _, v := findVendor(path) return v } jennifer-1.4.1/gennames/main.go000066400000000000000000000016661372216656000164060ustar00rootroot00000000000000package main import ( "bytes" "flag" "io/ioutil" "log" ) func main() { // notest var out = flag.String("output", "./package-names.go", "Output filename to write") var pkg = flag.String("package", "main", "Package name in generated file") var name = flag.String("name", "PackageNames", "Name of the variable to define") var filter = flag.String("filter", ".*", "Regex to filter paths (operates on full path including vendor directory)") var standard = flag.Bool("standard", false, "Use standard library packages") var novendor = flag.Bool("novendor", false, "Exclude packages in vendor directories") var goListPath = flag.String("path", "all", "Path to pass to go list command") flag.Parse() buf := &bytes.Buffer{} if err := hints(buf, *pkg, *name, *goListPath, *filter, *standard, *novendor); err != nil { log.Fatal(err.Error()) } if err := ioutil.WriteFile(*out, buf.Bytes(), 0644); err != nil { log.Fatal(err.Error()) } } jennifer-1.4.1/go.mod000066400000000000000000000000511372216656000144270ustar00rootroot00000000000000module github.com/dave/jennifer go 1.15 jennifer-1.4.1/jen/000077500000000000000000000000001372216656000141015ustar00rootroot00000000000000jennifer-1.4.1/jen/add.go000066400000000000000000000006721372216656000151650ustar00rootroot00000000000000package 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 } jennifer-1.4.1/jen/comments.go000066400000000000000000000063151372216656000162620ustar00rootroot00000000000000package 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 } jennifer-1.4.1/jen/custom.go000066400000000000000000000037311372216656000157460ustar00rootroot00000000000000package 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 } jennifer-1.4.1/jen/dict.go000066400000000000000000000030521372216656000153530ustar00rootroot00000000000000package 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 } jennifer-1.4.1/jen/do.go000066400000000000000000000010561372216656000150340ustar00rootroot00000000000000package 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 } jennifer-1.4.1/jen/examples_test.go000066400000000000000000000672641372216656000173240ustar00rootroot00000000000000package jen_test import ( "fmt" "bytes" . "github.com/dave/jennifer/jen" ) func ExampleCaseBug() { c := Switch(Id("a")).Block( Case(Lit(1)).Block( Var().Id("i").Int(), Var().Id("j").Int(), ), ) fmt.Printf("%#v", c) // Output: // switch a { // case 1: // var i int // var j int // } } func ExampleCustom() { multiLineCall := Options{ Close: ")", Multi: true, Open: "(", Separator: ",", } c := Id("foo").Custom(multiLineCall, Lit("a"), Lit("b"), Lit("c")) fmt.Printf("%#v", c) // Output: // foo( // "a", // "b", // "c", // ) } func ExampleCustomFunc() { multiLineCall := Options{ Close: ")", Multi: true, Open: "(", Separator: ",", } c := Id("foo").CustomFunc(multiLineCall, func(g *Group) { g.Lit("a") g.Lit("b") g.Lit("c") }) fmt.Printf("%#v", c) // Output: // foo( // "a", // "b", // "c", // ) } func ExampleFile_ImportName_conflict() { f := NewFile("main") // We provide a hint that package foo/a should use name "a", but because package bar/a already // registers the required name, foo/a is aliased. f.ImportName("github.com/foo/a", "a") f.Func().Id("main").Params().Block( Qual("github.com/bar/a", "Bar").Call(), Qual("github.com/foo/a", "Foo").Call(), ) fmt.Printf("%#v", f) // Output: // package main // // import ( // a "github.com/bar/a" // a1 "github.com/foo/a" // ) // // func main() { // a.Bar() // a1.Foo() // } } func ExampleFile_ImportAlias_conflict() { f := NewFile("main") // We provide a hint that package foo/a should use alias "b", but because package bar/b already // registers the required name, foo/a is aliased using the requested alias as a base. f.ImportName("github.com/foo/a", "b") f.Func().Id("main").Params().Block( Qual("github.com/bar/b", "Bar").Call(), Qual("github.com/foo/a", "Foo").Call(), ) fmt.Printf("%#v", f) // Output: // package main // // import ( // b "github.com/bar/b" // b1 "github.com/foo/a" // ) // // func main() { // b.Bar() // b1.Foo() // } } func ExampleFile_ImportName() { f := NewFile("main") // package a should use name "a" f.ImportName("github.com/foo/a", "a") // package b is not used in the code so will not be included f.ImportName("github.com/foo/b", "b") f.Func().Id("main").Params().Block( Qual("github.com/foo/a", "A").Call(), ) fmt.Printf("%#v", f) // Output: // package main // // import "github.com/foo/a" // // func main() { // a.A() // } } func ExampleFile_ImportNames() { // package a should use name "a", package b is not used in the code so will not be included names := map[string]string{ "github.com/foo/a": "a", "github.com/foo/b": "b", } f := NewFile("main") f.ImportNames(names) f.Func().Id("main").Params().Block( Qual("github.com/foo/a", "A").Call(), ) fmt.Printf("%#v", f) // Output: // package main // // import "github.com/foo/a" // // func main() { // a.A() // } } func ExampleFile_ImportAlias() { f := NewFile("main") // package a should be aliased to "b" f.ImportAlias("github.com/foo/a", "b") // package c is not used in the code so will not be included f.ImportAlias("github.com/foo/c", "c") f.Func().Id("main").Params().Block( Qual("github.com/foo/a", "A").Call(), ) fmt.Printf("%#v", f) // Output: // package main // // import b "github.com/foo/a" // // func main() { // b.A() // } } func ExampleFile_ImportAliasDot() { f := NewFile("main") // package a should be a dot-import f.ImportAlias("github.com/foo/a", ".") // package b should be a dot-import f.ImportAlias("github.com/foo/b", ".") // package c is not used in the code so will not be included f.ImportAlias("github.com/foo/c", ".") f.Func().Id("main").Params().Block( Qual("github.com/foo/a", "A").Call(), Qual("github.com/foo/b", "B").Call(), ) fmt.Printf("%#v", f) // Output: // package main // // import ( // . "github.com/foo/a" // . "github.com/foo/b" // ) // // func main() { // A() // B() // } } func ExampleFile_CgoPreamble() { f := NewFile("a") f.CgoPreamble(`#include #include void myprint(char* s) { printf("%s\n", s); } `) f.Func().Id("init").Params().Block( Id("cs").Op(":=").Qual("C", "CString").Call(Lit("Hello from stdio\n")), Qual("C", "myprint").Call(Id("cs")), Qual("C", "free").Call(Qual("unsafe", "Pointer").Parens(Id("cs"))), ) fmt.Printf("%#v", f) // Output: // package a // // import "unsafe" // // /* // #include // #include // // void myprint(char* s) { // printf("%s\n", s); // } // */ // import "C" // // func init() { // cs := C.CString("Hello from stdio\n") // C.myprint(cs) // C.free(unsafe.Pointer(cs)) // } } func ExampleFile_CgoPreamble_anon() { f := NewFile("a") f.CgoPreamble(`#include `) f.Func().Id("init").Params().Block( Qual("foo.bar/a", "A"), Qual("foo.bar/b", "B"), ) fmt.Printf("%#v", f) // Output: // package a // // import ( // a "foo.bar/a" // b "foo.bar/b" // ) // // // #include // import "C" // // func init() { // a.A // b.B // } } func ExampleFile_CgoPreamble_no_preamble() { f := NewFile("a") f.Func().Id("init").Params().Block( Qual("C", "Foo").Call(), Qual("fmt", "Print").Call(), ) fmt.Printf("%#v", f) // Output: // package a // // import ( // "C" // "fmt" // ) // // func init() { // C.Foo() // fmt.Print() // } } func ExampleFile_CgoPreamble_no_preamble_single() { f := NewFile("a") f.Func().Id("init").Params().Block( Qual("C", "Foo").Call(), ) fmt.Printf("%#v", f) // Output: // package a // // import "C" // // func init() { // C.Foo() // } } func ExampleFile_CgoPreamble_no_preamble_single_anon() { f := NewFile("a") f.Anon("C") f.Func().Id("init").Params().Block() fmt.Printf("%#v", f) // Output: // package a // // import "C" // // func init() {} } func ExampleFile_CgoPreamble_no_preamble_anon() { f := NewFile("a") f.Anon("C") f.Func().Id("init").Params().Block( Qual("fmt", "Print").Call(), ) fmt.Printf("%#v", f) // Output: // package a // // import ( // "C" // "fmt" // ) // // func init() { // fmt.Print() // } } func ExampleOp_complex_conditions() { c := If(Parens(Id("a").Op("||").Id("b")).Op("&&").Id("c")).Block() fmt.Printf("%#v", c) // Output: // if (a || b) && c { // } } func ExampleLit_bool_true() { c := Lit(true) fmt.Printf("%#v", c) // Output: // true } func ExampleLit_bool_false() { c := Lit(false) fmt.Printf("%#v", c) // Output: // false } func ExampleLit_byte() { // Lit can't tell the difference between byte and uint8. Use LitByte to // render byte literals. c := Lit(byte(0x1)) fmt.Printf("%#v", c) // Output: // uint8(0x1) } func ExampleLit_complex64() { c := Lit(complex64(0 + 0i)) fmt.Printf("%#v", c) // Output: // complex64(0 + 0i) } func ExampleLit_complex128() { c := Lit(0 + 0i) fmt.Printf("%#v", c) // Output: // (0 + 0i) } func ExampleLit_float32() { c := Lit(float32(1)) fmt.Printf("%#v", c) // Output: // float32(1) } func ExampleLit_float64_one_point_zero() { c := Lit(1.0) fmt.Printf("%#v", c) // Output: // 1.0 } func ExampleLit_float64_zero() { c := Lit(0.0) fmt.Printf("%#v", c) // Output: // 0.0 } func ExampleLit_float64_negative() { c := Lit(-0.1) fmt.Printf("%#v", c) // Output: // -0.1 } func ExampleLit_float64_negative_whole() { c := Lit(-1.0) fmt.Printf("%#v", c) // Output: // -1.0 } func ExampleLit_int() { c := Lit(1) fmt.Printf("%#v", c) // Output: // 1 } func ExampleLit_int8() { c := Lit(int8(1)) fmt.Printf("%#v", c) // Output: // int8(1) } func ExampleLit_int16() { c := Lit(int16(1)) fmt.Printf("%#v", c) // Output: // int16(1) } func ExampleLit_int32() { c := Lit(int32(1)) fmt.Printf("%#v", c) // Output: // int32(1) } func ExampleLit_int64() { c := Lit(int64(1)) fmt.Printf("%#v", c) // Output: // int64(1) } func ExampleLit_uint() { c := Lit(uint(0x1)) fmt.Printf("%#v", c) // Output: // uint(0x1) } func ExampleLit_uint8() { c := Lit(uint8(0x1)) fmt.Printf("%#v", c) // Output: // uint8(0x1) } func ExampleLit_uint16() { c := Lit(uint16(0x1)) fmt.Printf("%#v", c) // Output: // uint16(0x1) } func ExampleLit_uint32() { c := Lit(uint32(0x1)) fmt.Printf("%#v", c) // Output: // uint32(0x1) } func ExampleLit_uint64() { c := Lit(uint64(0x1)) fmt.Printf("%#v", c) // Output: // uint64(0x1) } func ExampleLit_uintptr() { c := Lit(uintptr(0x1)) fmt.Printf("%#v", c) // Output: // uintptr(0x1) } func ExampleLit_rune() { // Lit can't tell the difference between rune and int32. Use LitRune to // render rune literals. c := Lit('x') fmt.Printf("%#v", c) // Output: // int32(120) } func ExampleLitRune() { c := LitRune('x') fmt.Printf("%#v", c) // Output: // 'x' } func ExampleLitRuneFunc() { c := LitRuneFunc(func() rune { return '\t' }) fmt.Printf("%#v", c) // Output: // '\t' } func ExampleLitByte() { c := LitByte(byte(1)) fmt.Printf("%#v", c) // Output: // byte(0x1) } func ExampleLitByteFunc() { c := LitByteFunc(func() byte { return byte(2) }) fmt.Printf("%#v", c) // Output: // byte(0x2) } func ExampleLit_string() { c := Lit("foo") fmt.Printf("%#v", c) // Output: // "foo" } func ExampleValues_dict_single() { c := Map(String()).String().Values(Dict{ Lit("a"): Lit("b"), }) fmt.Printf("%#v", c) // Output: // map[string]string{"a": "b"} } func ExampleValues_dict_multiple() { c := Map(String()).String().Values(Dict{ Lit("a"): Lit("b"), Lit("c"): Lit("d"), }) fmt.Printf("%#v", c) // Output: // map[string]string{ // "a": "b", // "c": "d", // } } func ExampleValues_dict_composite() { c := Op("&").Id("Person").Values(Dict{ Id("Age"): Lit(1), Id("Name"): Lit("a"), }) fmt.Printf("%#v", c) // Output: // &Person{ // Age: 1, // Name: "a", // } } func ExampleAdd() { ptr := Op("*") c := Id("a").Op("=").Add(ptr).Id("b") fmt.Printf("%#v", c) // Output: // a = *b } func ExampleAdd_var() { a := Id("a") i := Int() c := Var().Add(a, i) fmt.Printf("%#v", c) // Output: // var a int } func ExampleAppend() { c := Append(Id("a"), Id("b")) fmt.Printf("%#v", c) // Output: // append(a, b) } func ExampleAppend_more() { c := Id("a").Op("=").Append(Id("a"), Id("b").Op("...")) fmt.Printf("%#v", c) // Output: // a = append(a, b...) } func ExampleAssert() { c := List(Id("b"), Id("ok")).Op(":=").Id("a").Assert(Bool()) fmt.Printf("%#v", c) // Output: // b, ok := a.(bool) } func ExampleBlock() { c := Func().Id("foo").Params().String().Block( Id("a").Op("=").Id("b"), Id("b").Op("++"), Return(Id("b")), ) fmt.Printf("%#v", c) // Output: // func foo() string { // a = b // b++ // return b // } } func ExampleBlock_if() { c := If(Id("a").Op(">").Lit(10)).Block( Id("a").Op("=").Id("a").Op("/").Lit(2), ) fmt.Printf("%#v", c) // Output: // if a > 10 { // a = a / 2 // } } func ExampleValuesFunc() { c := Id("numbers").Op(":=").Index().Int().ValuesFunc(func(g *Group) { for i := 0; i <= 5; i++ { g.Lit(i) } }) fmt.Printf("%#v", c) // Output: // numbers := []int{0, 1, 2, 3, 4, 5} } func ExampleBlockFunc() { increment := true name := "a" c := Func().Id("a").Params().BlockFunc(func(g *Group) { g.Id(name).Op("=").Lit(1) if increment { g.Id(name).Op("++") } else { g.Id(name).Op("--") } }) fmt.Printf("%#v", c) // Output: // func a() { // a = 1 // a++ // } } func ExampleBool() { c := Var().Id("b").Bool() fmt.Printf("%#v", c) // Output: // var b bool } func ExampleBreak() { c := For( Id("i").Op(":=").Lit(0), Id("i").Op("<").Lit(10), Id("i").Op("++"), ).Block( If(Id("i").Op(">").Lit(5)).Block( Break(), ), ) fmt.Printf("%#v", c) // Output: // for i := 0; i < 10; i++ { // if i > 5 { // break // } // } } func ExampleByte() { c := Id("b").Op(":=").Id("a").Assert(Byte()) fmt.Printf("%#v", c) // Output: // b := a.(byte) } func ExampleCall() { c := Qual("fmt", "Printf").Call( Lit("%#v: %T\n"), Id("a"), Id("b"), ) fmt.Printf("%#v", c) // Output: // fmt.Printf("%#v: %T\n", a, b) } func ExampleCall_fmt() { c := Id("a").Call(Lit("b")) fmt.Printf("%#v", c) // Output: // a("b") } func ExampleCallFunc() { f := func(name string, second string) { c := Id("foo").CallFunc(func(g *Group) { g.Id(name) if second != "" { g.Lit(second) } }) fmt.Printf("%#v\n", c) } f("a", "b") f("c", "") // Output: // foo(a, "b") // foo(c) } func ExampleCap() { c := Id("i").Op(":=").Cap(Id("v")) fmt.Printf("%#v", c) // Output: // i := cap(v) } func ExampleCase() { c := Switch(Id("person")).Block( Case(Id("John"), Id("Peter")).Block( Return(Lit("male")), ), Case(Id("Gill")).Block( Return(Lit("female")), ), ) fmt.Printf("%#v", c) // Output: // switch person { // case John, Peter: // return "male" // case Gill: // return "female" // } } func ExampleBlock_case() { c := Select().Block( Case(Op("<-").Id("done")).Block( Return(Nil()), ), Case(List(Err(), Id("open")).Op(":=").Op("<-").Id("fail")).Block( If(Op("!").Id("open")).Block( Return(Err()), ), ), ) fmt.Printf("%#v", c) // Output: // select { // case <-done: // return nil // case err, open := <-fail: // if !open { // return err // } // } } func ExampleBlockFunc_case() { preventExitOnError := true c := Select().Block( Case(Op("<-").Id("done")).Block( Return(Nil()), ), Case(Err().Op(":=").Op("<-").Id("fail")).BlockFunc(func(g *Group) { if !preventExitOnError { g.Return(Err()) } else { g.Qual("fmt", "Println").Call(Err()) } }), ) fmt.Printf("%#v", c) // Output: // select { // case <-done: // return nil // case err := <-fail: // fmt.Println(err) // } } func ExampleCaseFunc() { samIsMale := false c := Switch(Id("person")).Block( CaseFunc(func(g *Group) { g.Id("John") g.Id("Peter") if samIsMale { g.Id("Sam") } }).Block( Return(Lit("male")), ), CaseFunc(func(g *Group) { g.Id("Gill") if !samIsMale { g.Id("Sam") } }).Block( Return(Lit("female")), ), ) fmt.Printf("%#v", c) // Output: // switch person { // case John, Peter: // return "male" // case Gill, Sam: // return "female" // } } func ExampleChan() { c := Func().Id("init").Params().Block( Id("c").Op(":=").Make(Chan().Qual("os", "Signal"), Lit(1)), Qual("os/signal", "Notify").Call(Id("c"), Qual("os", "Interrupt")), Qual("os/signal", "Notify").Call(Id("c"), Qual("syscall", "SIGTERM")), Go().Func().Params().Block( Op("<-").Id("c"), Id("cancel").Call(), ).Call(), ) fmt.Printf("%#v", c) // Output: // func init() { // c := make(chan os.Signal, 1) // signal.Notify(c, os.Interrupt) // signal.Notify(c, syscall.SIGTERM) // go func() { // <-c // cancel() // }() // } } func ExampleClose() { c := Block( Id("ch").Op(":=").Make(Chan().Struct()), Go().Func().Params().Block( Op("<-").Id("ch"), Qual("fmt", "Println").Call(Lit("done.")), ).Call(), Close(Id("ch")), ) fmt.Printf("%#v", c) // Output: // { // ch := make(chan struct{}) // go func() { // <-ch // fmt.Println("done.") // }() // close(ch) // } } func ExampleComment() { f := NewFile("a") f.Comment("Foo returns the string \"foo\"") f.Func().Id("Foo").Params().String().Block( Return(Lit("foo")).Comment("return the string foo"), ) fmt.Printf("%#v", f) // Output: // package a // // // Foo returns the string "foo" // func Foo() string { // return "foo" // return the string foo // } } func ExampleComment_multiline() { c := Comment("a\nb") fmt.Printf("%#v", c) // Output: // /* // a // b // */ } func ExampleComment_formatting_disabled() { c := Id("foo").Call(Comment("/* inline */")).Comment("//no-space") fmt.Printf("%#v", c) // Output: // foo( /* inline */ ) //no-space } func ExampleCommentf() { name := "foo" val := "bar" c := Id(name).Op(":=").Lit(val).Commentf("%s is the string \"%s\"", name, val) fmt.Printf("%#v", c) // Output: // foo := "bar" // foo is the string "bar" } func ExampleComplex() { c := Func().Id("main").Params().Block( Id("c1").Op(":=").Lit(1+3.75i), Id("c2").Op(":=").Complex(Lit(1), Lit(3.75)), Qual("fmt", "Println").Call(Id("c1").Op("==").Id("c2")), ) fmt.Printf("%#v", c) // Output: // func main() { // c1 := (1 + 3.75i) // c2 := complex(1, 3.75) // fmt.Println(c1 == c2) // } } func ExampleComplex128() { c := Func().Id("main").Params().Block( Var().Id("c").Complex128(), Id("c").Op("=").Lit(1+2i), Qual("fmt", "Println").Call(Id("c")), ) fmt.Printf("%#v", c) // Output: // func main() { // var c complex128 // c = (1 + 2i) // fmt.Println(c) // } } func ExampleComplex64() { c := Func().Id("main").Params().Block( Var().Id("c64").Complex64(), Id("c64").Op("=").Complex(Lit(5), Float32().Parens(Lit(2))), Qual("fmt", "Printf").Call(Lit("%T\n"), Id("c64")), ) fmt.Printf("%#v", c) // Output: // func main() { // var c64 complex64 // c64 = complex(5, float32(2)) // fmt.Printf("%T\n", c64) // } } func ExampleParams() { c := Func().Params( Id("a").Id("A"), ).Id("foo").Params( Id("b"), Id("c").String(), ).String().Block( Return(Id("b").Op("+").Id("c")), ) fmt.Printf("%#v", c) // Output: // func (a A) foo(b, c string) string { // return b + c // } } func ExampleIndex() { c := Var().Id("a").Index().String() fmt.Printf("%#v", c) // Output: // var a []string } func ExampleIndex_index() { c := Id("a").Op(":=").Id("b").Index(Lit(0), Lit(1)) fmt.Printf("%#v", c) // Output: // a := b[0:1] } func ExampleIndex_empty() { c := Id("a").Op(":=").Id("b").Index(Lit(1), Empty()) fmt.Printf("%#v", c) // Output: // a := b[1:] } func ExampleOp() { c := Id("a").Op(":=").Id("b").Call() fmt.Printf("%#v", c) // Output: // a := b() } func ExampleOp_star() { c := Id("a").Op("=").Op("*").Id("b") fmt.Printf("%#v", c) // Output: // a = *b } func ExampleOp_variadic() { c := Id("a").Call(Id("b").Op("...")) fmt.Printf("%#v", c) // Output: // a(b...) } func ExampleNewFilePath() { f := NewFilePath("a.b/c") f.Func().Id("init").Params().Block( Qual("a.b/c", "Foo").Call().Comment("Local package - alias is omitted."), Qual("d.e/f", "Bar").Call().Comment("Import is automatically added."), Qual("g.h/f", "Baz").Call().Comment("Colliding package name is automatically renamed."), ) fmt.Printf("%#v", f) // Output: // package c // // import ( // f "d.e/f" // f1 "g.h/f" // ) // // func init() { // Foo() // Local package - alias is omitted. // f.Bar() // Import is automatically added. // f1.Baz() // Colliding package name is automatically renamed. // } } func ExampleStruct_empty() { c := Id("c").Op(":=").Make(Chan().Struct()) fmt.Printf("%#v", c) // Output: // c := make(chan struct{}) } func ExampleStruct() { c := Type().Id("foo").Struct( List(Id("x"), Id("y")).Int(), Id("u").Float32(), ) fmt.Printf("%#v", c) // Output: // type foo struct { // x, y int // u float32 // } } func ExampleDefer() { c := Defer().Id("foo").Call() fmt.Printf("%#v", c) // Output: // defer foo() } func ExampleGoto() { c := Goto().Id("Outer") fmt.Printf("%#v", c) // Output: // goto Outer } func ExampleStatement_Clone_broken() { a := Id("a") c := Block( a.Call(), a.Call(), ) fmt.Printf("%#v", c) // Output: // { // a()() // a()() // } } func ExampleStatement_Clone_fixed() { a := Id("a") c := Block( a.Clone().Call(), a.Clone().Call(), ) fmt.Printf("%#v", c) // Output: // { // a() // a() // } } func ExampleFile_Render() { f := NewFile("a") f.Func().Id("main").Params().Block() buf := &bytes.Buffer{} err := f.Render(buf) if err != nil { fmt.Println(err.Error()) } else { fmt.Println(buf.String()) } // Output: // package a // // func main() {} } func ExampleLit() { c := Id("a").Op(":=").Lit("a") fmt.Printf("%#v", c) // Output: // a := "a" } func ExampleLit_float() { c := Id("a").Op(":=").Lit(1.5) fmt.Printf("%#v", c) // Output: // a := 1.5 } func ExampleLitFunc() { c := Id("a").Op(":=").LitFunc(func() interface{} { return 1 + 1 }) fmt.Printf("%#v", c) // Output: // a := 2 } func ExampleDot() { c := Qual("a.b/c", "Foo").Call().Dot("Bar").Index(Lit(0)).Dot("Baz") fmt.Printf("%#v", c) // Output: // c.Foo().Bar[0].Baz } func ExampleList() { c := List(Id("a"), Err()).Op(":=").Id("b").Call() fmt.Printf("%#v", c) // Output: // a, err := b() } func ExampleQual() { c := Qual("encoding/gob", "NewEncoder").Call() fmt.Printf("%#v", c) // Output: // gob.NewEncoder() } func ExampleQual_file() { f := NewFilePath("a.b/c") f.Func().Id("init").Params().Block( Qual("a.b/c", "Foo").Call().Comment("Local package - name is omitted."), Qual("d.e/f", "Bar").Call().Comment("Import is automatically added."), Qual("g.h/f", "Baz").Call().Comment("Colliding package name is renamed."), ) fmt.Printf("%#v", f) // Output: // package c // // import ( // f "d.e/f" // f1 "g.h/f" // ) // // func init() { // Foo() // Local package - name is omitted. // f.Bar() // Import is automatically added. // f1.Baz() // Colliding package name is renamed. // } } func ExampleQual_local() { f := NewFilePath("a.b/c") f.Func().Id("main").Params().Block( Qual("a.b/c", "D").Call(), ) fmt.Printf("%#v", f) // Output: // package c // // func main() { // D() // } } func ExampleId() { c := If(Id("i").Op("==").Id("j")).Block( Return(Id("i")), ) fmt.Printf("%#v", c) // Output: // if i == j { // return i // } } func ExampleErr() { c := If( Err().Op(":=").Id("foo").Call(), Err().Op("!=").Nil(), ).Block( Return(Err()), ) fmt.Printf("%#v", c) // Output: // if err := foo(); err != nil { // return err // } } func ExampleSwitch() { c := Switch(Id("value").Dot("Kind").Call()).Block( Case(Qual("reflect", "Float32"), Qual("reflect", "Float64")).Block( Return(Lit("float")), ), Case(Qual("reflect", "Bool")).Block( Return(Lit("bool")), ), Case(Qual("reflect", "Uintptr")).Block( Fallthrough(), ), Default().Block( Return(Lit("none")), ), ) fmt.Printf("%#v", c) // Output: // switch value.Kind() { // case reflect.Float32, reflect.Float64: // return "float" // case reflect.Bool: // return "bool" // case reflect.Uintptr: // fallthrough // default: // return "none" // } } func ExampleTag() { c := Type().Id("foo").Struct( Id("A").String().Tag(map[string]string{"json": "a"}), Id("B").Int().Tag(map[string]string{"json": "b", "bar": "baz"}), ) fmt.Printf("%#v", c) // Output: // type foo struct { // A string `json:"a"` // B int `bar:"baz" json:"b"` // } } func ExampleNull_and_nil() { c := Func().Id("foo").Params( nil, Id("s").String(), Null(), Id("i").Int(), ).Block() fmt.Printf("%#v", c) // Output: // func foo(s string, i int) {} } func ExampleNull_index() { c := Id("a").Op(":=").Id("b").Index(Lit(1), Null()) fmt.Printf("%#v", c) // Output: // a := b[1] } func ExampleEmpty() { c := Id("a").Op(":=").Id("b").Index(Lit(1), Empty()) fmt.Printf("%#v", c) // Output: // a := b[1:] } func ExampleBlock_complex() { collection := func(name string, key Code, value Code) *Statement { if key == nil { // slice return Var().Id(name).Index().Add(value) } else { // map return Var().Id(name).Map(key).Add(value) } } c := Func().Id("main").Params().Block( collection("foo", nil, String()), collection("bar", String(), Int()), ) fmt.Printf("%#v", c) // Output: // func main() { // var foo []string // var bar map[string]int // } } func ExampleFunc_declaration() { c := Func().Id("a").Params().Block() fmt.Printf("%#v", c) // Output: // func a() {} } func ExampleFunc_literal() { c := Id("a").Op(":=").Func().Params().Block() fmt.Printf("%#v", c) // Output: // a := func() {} } func ExampleInterface() { c := Type().Id("a").Interface( Id("b").Params().String(), ) fmt.Printf("%#v", c) // Output: // type a interface { // b() string // } } func ExampleInterface_empty() { c := Var().Id("a").Interface() fmt.Printf("%#v", c) // Output: // var a interface{} } func ExampleParens() { c := Id("b").Op(":=").Index().Byte().Parens(Id("s")) fmt.Printf("%#v", c) // Output: // b := []byte(s) } func ExampleParens_order() { c := Id("a").Op("/").Parens(Id("b").Op("+").Id("c")) fmt.Printf("%#v", c) // Output: // a / (b + c) } func ExampleValues() { c := Index().String().Values(Lit("a"), Lit("b")) fmt.Printf("%#v", c) // Output: // []string{"a", "b"} } func ExampleDo() { f := func(name string, isMap bool) *Statement { return Id(name).Op(":=").Do(func(s *Statement) { if isMap { s.Map(String()).String() } else { s.Index().String() } }).Values() } fmt.Printf("%#v\n%#v", f("a", true), f("b", false)) // Output: // a := map[string]string{} // b := []string{} } func ExampleReturn() { c := Return(Id("a"), Id("b")) fmt.Printf("%#v", c) // Output: // return a, b } func ExampleMap() { c := Id("a").Op(":=").Map(String()).String().Values() fmt.Printf("%#v", c) // Output: // a := map[string]string{} } func ExampleDict() { c := Id("a").Op(":=").Map(String()).String().Values(Dict{ Lit("a"): Lit("b"), Lit("c"): Lit("d"), }) fmt.Printf("%#v", c) // Output: // a := map[string]string{ // "a": "b", // "c": "d", // } } func ExampleDict_nil() { c := Id("a").Op(":=").Map(String()).String().Values() fmt.Printf("%#v", c) // Output: // a := map[string]string{} } func ExampleDictFunc() { c := Id("a").Op(":=").Map(String()).String().Values(DictFunc(func(d Dict) { d[Lit("a")] = Lit("b") d[Lit("c")] = Lit("d") })) fmt.Printf("%#v", c) // Output: // a := map[string]string{ // "a": "b", // "c": "d", // } } func ExampleDefs() { c := Const().Defs( Id("a").Op("=").Lit("a"), Id("b").Op("=").Lit("b"), ) fmt.Printf("%#v", c) // Output: // const ( // a = "a" // b = "b" // ) } func ExampleIf() { c := If( Err().Op(":=").Id("a").Call(), Err().Op("!=").Nil(), ).Block( Return(Err()), ) fmt.Printf("%#v", c) // Output: // if err := a(); err != nil { // return err // } } func ExampleId_local() { c := Id("a").Op(":=").Lit(1) fmt.Printf("%#v", c) // Output: // a := 1 } func ExampleId_select() { c := Id("a").Dot("b").Dot("c").Call() fmt.Printf("%#v", c) // Output: // a.b.c() } func ExampleId_remote() { f := NewFile("main") f.Func().Id("main").Params().Block( Qual("fmt", "Println").Call( Lit("Hello, world"), ), ) fmt.Printf("%#v", f) // Output: // package main // // import "fmt" // // func main() { // fmt.Println("Hello, world") // } } func ExampleFor() { c := For( Id("i").Op(":=").Lit(0), Id("i").Op("<").Lit(10), Id("i").Op("++"), ).Block( Qual("fmt", "Println").Call(Id("i")), ) fmt.Printf("%#v", c) // Output: // for i := 0; i < 10; i++ { // fmt.Println(i) // } } func ExampleNewFile() { f := NewFile("main") f.Func().Id("main").Params().Block( Qual("fmt", "Println").Call(Lit("Hello, world")), ) fmt.Printf("%#v", f) // Output: // package main // // import "fmt" // // func main() { // fmt.Println("Hello, world") // } } func ExampleNewFilePathName() { f := NewFilePathName("a.b/c", "main") f.Func().Id("main").Params().Block( Qual("a.b/c", "Foo").Call(), ) fmt.Printf("%#v", f) // Output: // package main // // func main() { // Foo() // } } func ExampleFile_HeaderAndPackageComments() { f := NewFile("c") f.CanonicalPath = "d.e/f" f.HeaderComment("Code generated by...") f.PackageComment("Package c implements...") f.Func().Id("init").Params().Block() fmt.Printf("%#v", f) // Output: // // Code generated by... // // // Package c implements... // package c // import "d.e/f" // // func init() {} } func ExampleFile_Anon() { f := NewFile("c") f.Anon("a") f.Func().Id("init").Params().Block() fmt.Printf("%#v", f) // Output: // package c // // import _ "a" // // func init() {} } func ExampleFile_PackagePrefix() { f := NewFile("a") f.PackagePrefix = "pkg" f.Func().Id("main").Params().Block( Qual("b.c/d", "E").Call(), ) fmt.Printf("%#v", f) // Output: // package a // // import pkg_d "b.c/d" // // func main() { // pkg_d.E() // } } jennifer-1.4.1/jen/file.go000066400000000000000000000157001372216656000153520ustar00rootroot00000000000000package jen import ( "bytes" "fmt" "regexp" "strings" "unicode" "unicode/utf8" ) // 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. A // period can be used to force a dot-import. 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 } func (f *File) isValidAlias(alias string) bool { // multiple dot-imports are ok if alias == "." { return true } // 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) isDotImport(path string) bool { if id, ok := f.hints[path]; ok { return id.name == "." && id.alias } return false } 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, "") // can't have a first digit, per Go identifier rules, so just skip them for firstRune, runeLen := utf8.DecodeRuneInString(alias); unicode.IsDigit(firstRune); firstRune, runeLen = utf8.DecodeRuneInString(alias) { alias = alias[runeLen:] } // If path part was all digits, we may be left with an empty string. In this case use "pkg" as the alias. if alias == "" { alias = "pkg" } return alias } jennifer-1.4.1/jen/file_test.go000066400000000000000000000022101372216656000164010ustar00rootroot00000000000000package jen import ( "fmt" "testing" ) func TestGuessAlias(t *testing.T) { data := map[string]string{ "A": "a", "a": "a", "a$": "a", "a/b": "b", "a/b/c": "c", "a/b/c-d": "cd", "a/b/c-d/": "cd", "a.b": "ab", "a/b.c": "bc", "a/b-c.d": "bcd", "a/bb-ccc.dddd": "bbcccdddd", "a/foo-go": "foogo", "123a": "a", "a/321a.b": "ab", "a/123": "pkg", } for path, expected := range data { if guessAlias(path) != expected { fmt.Printf("guessAlias test failed %s should return %s but got %s\n", path, expected, guessAlias(path)) t.Fail() } } } func TestValidAlias(t *testing.T) { data := map[string]bool{ "a": true, // ok "b": false, // already registered "go": false, // keyword "int": false, // predeclared "err": false, // common name } f := NewFile("test") f.register("b") for alias, expected := range data { if f.isValidAlias(alias) != expected { fmt.Printf("isValidAlias test failed %s should return %t but got %t\n", alias, expected, f.isValidAlias(alias)) t.Fail() } } } jennifer-1.4.1/jen/generated.go000066400000000000000000001411451372216656000163740ustar00rootroot00000000000000// 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 } jennifer-1.4.1/jen/generated_test.go000066400000000000000000000350671372216656000174400ustar00rootroot00000000000000package jen_test import ( "testing" . "github.com/dave/jennifer/jen" ) var gencases = []tc{ { desc: `bool group`, code: BlockFunc(func(g *Group) { g.Bool() }), expect: `{ bool }`, }, { desc: `recover func`, code: Recover(), expect: `recover()`, }, { desc: `recover statement`, code: Null().Recover(), expect: `recover()`, }, { desc: `recover group`, code: BlockFunc(func(g *Group) { g.Recover() }), expect: `{ recover() }`, }, { desc: `real func`, code: Real(Id("a")), expect: `real(a)`, }, { desc: `real statement`, code: Null().Real(Id("a")), expect: `real(a)`, }, { desc: `real group`, code: BlockFunc(func(g *Group) { g.Real(Id("a")) }), expect: `{ real(a) }`, }, { desc: `printlnfunc func`, code: PrintlnFunc(func(g *Group) { g.Id("a") }), expect: `println(a)`, }, { desc: `printlnfunc statement`, code: Null().PrintlnFunc(func(g *Group) { g.Id("a") }), expect: `println(a)`, }, { desc: `printlnfunc group`, code: BlockFunc(func(bg *Group) { bg.PrintlnFunc(func(pg *Group) { pg.Id("a") }) }), expect: `{ println(a) }`, }, { desc: `println func`, code: Println(Id("a")), expect: `println(a)`, }, { desc: `println statement`, code: Null().Println(Id("a")), expect: `println(a)`, }, { desc: `println group`, code: BlockFunc(func(g *Group) { g.Println(Id("a")) }), expect: `{ println(a) }`, }, { desc: `printfunc func`, code: PrintFunc(func(g *Group) { g.Id("a") }), expect: `print(a)`, }, { desc: `printfunc statement`, code: Null().PrintFunc(func(g *Group) { g.Id("a") }), expect: `print(a)`, }, { desc: `printfunc group`, code: BlockFunc(func(bg *Group) { bg.PrintFunc(func(pg *Group) { pg.Id("a") }) }), expect: `{ print(a) }`, }, { desc: `print func`, code: Print(Id("a")), expect: `print(a)`, }, { desc: `print statement`, code: Null().Print(Id("a")), expect: `print(a)`, }, { desc: `print group`, code: BlockFunc(func(g *Group) { g.Print(Id("a")) }), expect: `{ print(a) }`, }, { desc: `panic func`, code: Panic(Id("a")), expect: `panic(a)`, }, { desc: `panic statement`, code: Null().Panic(Id("a")), expect: `panic(a)`, }, { desc: `panic group`, code: BlockFunc(func(g *Group) { g.Panic(Id("a")) }), expect: `{ panic(a) }`, }, { desc: `new func`, code: New(Id("a")), expect: `new(a)`, }, { desc: `new statement`, code: Id("a").Op(":=").New(Id("a")), expect: `a := new(a)`, }, { desc: `new group`, code: BlockFunc(func(g *Group) { g.New(Id("a")) }), expect: `{ new(a) }`, }, { desc: `make func`, code: Make(Id("a")), expect: `make(a)`, }, { desc: `make statement`, code: Id("a").Op(":=").Make(Id("a")), expect: `a := make(a)`, }, { desc: `make group`, code: BlockFunc(func(g *Group) { g.Make(Id("a")) }), expect: `{ make(a) }`, }, { desc: `len func`, code: Len(Id("a")), expect: `len(a)`, }, { desc: `len statement`, code: Id("a").Op(":=").Len(Id("a")), expect: `a := len(a)`, }, { desc: `len group`, code: BlockFunc(func(g *Group) { g.Len(Id("a")) }), expect: `{ len(a) }`, }, { desc: `imag func`, code: Imag(Id("a")), expect: `imag(a)`, }, { desc: `imag statement`, code: Id("a").Op(":=").Imag(Id("a")), expect: `a := imag(a)`, }, { desc: `imag group`, code: BlockFunc(func(g *Group) { g.Imag(Id("a")) }), expect: `{ imag(a) }`, }, { desc: `delete func`, code: Delete(Id("a"), Id("b")), expect: `delete(a, b)`, }, { desc: `delete statement`, code: Null().Delete(Id("a"), Id("b")), expect: `delete(a, b)`, }, { desc: `delete group`, code: BlockFunc(func(g *Group) { g.Delete(Id("a"), Id("b")) }), expect: `{ delete(a, b) }`, }, { desc: `copy func`, code: Copy(Id("a"), Id("b")), expect: `copy(a, b)`, }, { desc: `copy statement`, code: Id("a").Op(":=").Copy(Id("a"), Id("b")), expect: `a := copy(a, b)`, }, { desc: `copy group`, code: BlockFunc(func(g *Group) { g.Copy(Id("a"), Id("b")) }), expect: `{ copy(a, b) }`, }, { desc: `complex func`, code: Complex(Id("a"), Id("b")), expect: `complex(a, b)`, }, { desc: `complex statement`, code: Id("a").Op(":=").Complex(Id("a"), Id("b")), expect: `a := complex(a, b)`, }, { desc: `complex group`, code: BlockFunc(func(g *Group) { g.Complex(Id("a"), Id("b")) }), expect: `{ complex(a, b) }`, }, { desc: `close group`, code: BlockFunc(func(g *Group) { g.Close(Id("a")) }), expect: `{ close(a) }`, }, { desc: `cap func`, code: Cap(Id("a")), expect: `cap(a)`, }, { desc: `cap statement`, code: Id("a").Op(":=").Cap(Id("b")), expect: `a := cap(b)`, }, { desc: `cap group`, code: BlockFunc(func(g *Group) { g.Cap(Id("a")) }), expect: `{ cap(a) }`, }, { desc: `append group`, code: BlockFunc(func(g *Group) { g.Append(Id("a")) }), expect: `{ append(a) }`, }, { desc: `appendfunc statement`, code: Id("a").Op("=").AppendFunc(func(ag *Group) { ag.Id("a") }), expect: `a = append(a)`, }, { desc: `appendfunc func`, code: AppendFunc(func(ag *Group) { ag.Id("a") }), expect: `append(a)`, }, { desc: `appendfunc group`, code: BlockFunc(func(bg *Group) { bg.AppendFunc(func(ag *Group) { ag.Id("a") }) }), expect: `{ append(a) }`, }, { desc: `casefunc group`, code: Switch().BlockFunc(func(g *Group) { g.CaseFunc(func(g *Group) { g.Id("a") }).Block() }), expect: `switch { case a: }`, }, { desc: `case group`, code: Switch().BlockFunc(func(g *Group) { g.Case(Id("a")).Block() }), expect: `switch { case a: }`, }, { desc: `structfunc statement`, code: Id("a").Op(":=").StructFunc(func(g *Group) {}).Values(), expect: `a := struct{}{}`, }, { desc: `structfunc group`, // Don't do this! ListFunc used to kludge Group.Struct usage // without syntax error. code: Id("a").Op(":=").ListFunc(func(g *Group) { g.StructFunc(func(g *Group) {}) }).Values(), expect: `a := struct{}{}`, }, { desc: `structfunc func`, code: Id("a").Op(":=").Add(StructFunc(func(g *Group) {})).Values(), expect: `a := struct{}{}`, }, { desc: `struct group`, // Don't do this! ListFunc used to kludge Group.Struct usage // without syntax error. code: Id("a").Op(":=").ListFunc(func(g *Group) { g.Struct() }).Values(), expect: `a := struct{}{}`, }, { desc: `struct func`, code: Id("a").Op(":=").Add(Struct()).Values(), expect: `a := struct{}{}`, }, { desc: `interfacefunc func`, code: Id("a").Assert(InterfaceFunc(func(g *Group) { g.Id("a").Call().Int() g.Id("b").Call().Int() })), expect: `a.(interface{ a() int b() int })`, }, { desc: `interfacefunc statement`, code: Id("a").Assert(Null().InterfaceFunc(func(g *Group) { g.Id("a").Call().Int() g.Id("b").Call().Int() })), expect: `a.(interface{ a() int b() int })`, }, { desc: `interfacefunc group`, // Don't do this! ListFunc used to kludge Group.InterfaceFunc usage // without syntax error. code: Id("a").Assert(ListFunc(func(lg *Group) { lg.InterfaceFunc(func(ig *Group) { ig.Id("a").Call().Int() ig.Id("b").Call().Int() }) })), expect: `a.(interface{ a() int b() int })`, }, { desc: `interface func`, code: Interface().Parens(Id("a")), expect: `interface{}(a)`, }, { desc: `interface group`, code: BlockFunc(func(g *Group) { g.Interface().Parens(Id("a")) }), expect: `{ interface{}(a) }`, }, { desc: `interface statement`, code: Null().Interface().Parens(Id("a")), expect: `interface{}(a)`, }, { desc: `switchfunc func`, code: SwitchFunc(func(rg *Group) { rg.Id("a") }).Block(), expect: `switch a {}`, }, { desc: `switchfunc statement`, code: Null().SwitchFunc(func(rg *Group) { rg.Id("a") }).Block(), expect: `switch a { }`, }, { desc: `switchfunc group`, code: BlockFunc(func(bg *Group) { bg.SwitchFunc(func(rg *Group) { rg.Id("a") }).Block() }), expect: `{ switch a { } }`, }, { desc: `switch group`, code: BlockFunc(func(bg *Group) { bg.Switch().Block() }), expect: `{ switch { } }`, }, { desc: `forfunc func`, code: ForFunc(func(rg *Group) { rg.Id("a") }).Block(), expect: `for a {}`, }, { desc: `forfunc statement`, code: Null().ForFunc(func(rg *Group) { rg.Id("a") }).Block(), expect: `for a { }`, }, { desc: `forfunc group`, code: BlockFunc(func(bg *Group) { bg.ForFunc(func(rg *Group) { rg.Id("a") }).Block() }), expect: `{ for a { } }`, }, { desc: `for group`, code: BlockFunc(func(g *Group) { g.For(Id("a")).Block() }), expect: `{ for a {} }`, }, { desc: `returnfunc func`, code: ReturnFunc(func(rg *Group) { rg.Lit(1) rg.Lit(2) }), expect: `return 1, 2`, }, { desc: `returnfunc statement`, code: Empty().ReturnFunc(func(rg *Group) { rg.Lit(1) rg.Lit(2) }), expect: `return 1, 2`, }, { desc: `returnfunc group`, code: BlockFunc(func(bg *Group) { bg.ReturnFunc(func(rg *Group) { rg.Lit(1) rg.Lit(2) }) }), expect: `{ return 1, 2 }`, }, { desc: `return group`, code: BlockFunc(func(g *Group) { g.Return() }), expect: `{ return }`, }, { desc: `iffunc group`, code: BlockFunc(func(bg *Group) { bg.IfFunc(func(ig *Group) { ig.Id("a") }).Block() }), expect: `{ if a {} }`, }, { desc: `iffunc func`, code: IfFunc(func(ig *Group) { ig.Id("a") }).Block(), expect: `if a {}`, }, { desc: `iffunc statement`, code: Null().IfFunc(func(ig *Group) { ig.Id("a") }).Block(), expect: `if a {}`, }, { desc: `if group`, code: BlockFunc(func(g *Group) { g.If(Id("a")).Block() }), expect: `{ if a {} }`, }, { desc: `map group`, code: BlockFunc(func(g *Group) { g.Map(Int()).Int().Values(Dict{Lit(1): Lit(1)}) }), expect: `{ map[int]int{1:1} }`, }, { desc: `assert group`, // Don't do this! ListFunc used to kludge Group.Assert usage without // syntax error. code: Id("a").ListFunc(func(g *Group) { g.Assert(Id("b")) }), expect: `a.(b)`, }, { desc: `assert func`, code: Id("a").Add(Assert(Id("b"))), expect: `a.(b)`, }, { desc: `paramsfunc group`, // Don't do this! ListFunc used to kludge Group.ParamsFunc usage without // syntax error. code: Id("a").ListFunc(func(lg *Group) { lg.ParamsFunc(func(cg *Group) { cg.Lit(1) }) }), expect: `a(1)`, }, { desc: `paramsfunc func`, code: Id("a").Add(ParamsFunc(func(g *Group) { g.Lit(1) })), expect: `a(1)`, }, { desc: `paramsfunc statement`, code: Id("a").ParamsFunc(func(g *Group) { g.Lit(1) }), expect: `a(1)`, }, { desc: `params group`, // Don't do this! ListFunc used to kludge Group.Params usage without // syntax error. code: Id("a").ListFunc(func(g *Group) { g.Params(Lit(1)) }), expect: `a(1)`, }, { desc: `params func`, code: Id("a").Add(Params(Lit(1))), expect: `a(1)`, }, { desc: `callfunc group`, // Don't do this! ListFunc used to kludge Group.CallFunc usage without // syntax error. code: Id("a").ListFunc(func(lg *Group) { lg.CallFunc(func(cg *Group) { cg.Lit(1) }) }), expect: `a(1)`, }, { desc: `callfunc func`, code: Id("a").Add(CallFunc(func(g *Group) { g.Lit(1) })), expect: `a(1)`, }, { desc: `call group`, // Don't do this! ListFunc used to kludge Group.Call usage without // syntax error. code: Id("a").ListFunc(func(g *Group) { g.Call(Lit(1)) }), expect: `a(1)`, }, { desc: `call func`, code: Id("a").Add(Call(Lit(1))), expect: `a(1)`, }, { desc: `defsfunc statement`, code: Const().DefsFunc(func(g *Group) { g.Id("a").Op("=").Lit(1) }), expect: `const ( a = 1 )`, }, { desc: `defsfunc func`, code: Const().Add(DefsFunc(func(g *Group) { g.Id("a").Op("=").Lit(1) })), expect: `const ( a = 1 )`, }, { desc: `defsfunc group`, // Don't do this! ListFunc used to kludge Group.DefsFunc usage without // syntax error. code: Const().ListFunc(func(lg *Group) { lg.DefsFunc(func(dg *Group) { dg.Id("a").Op("=").Lit(1) }) }), expect: `const ( a = 1 )`, }, { desc: `defs group`, // Don't do this! ListFunc used to kludge Group.Defs usage without // syntax error. code: Const().ListFunc(func(g *Group) { g.Defs(Id("a").Op("=").Lit(1)) }), expect: `const ( a = 1 )`, }, { desc: `defs func`, code: Const().Add(Defs(Id("a").Op("=").Lit(1))), expect: `const ( a = 1 )`, }, { desc: `blockfunc group`, code: BlockFunc(func(g *Group) { g.BlockFunc(func(g *Group) {}) }), expect: `{{}}`, }, { desc: `block group`, code: BlockFunc(func(g *Group) { g.Block() }), expect: `{{}}`, }, { desc: `indexfunc group`, code: BlockFunc(func(g *Group) { g.IndexFunc(func(g *Group) { g.Lit(1) }).Int().Values(Lit(1)) }), expect: `{[1]int{1}}`, }, { desc: `indexfunc statement`, code: Id("a").IndexFunc(func(g *Group) { g.Lit(1) }), expect: `a[1]`, }, { desc: `indexfunc func`, code: Id("a").Add(IndexFunc(func(g *Group) { g.Lit(1) })), expect: `a[1]`, }, { desc: `index group`, code: BlockFunc(func(g *Group) { g.Index(Lit(1)).Int().Values(Lit(1)) }), expect: `{[1]int{1}}`, }, { desc: `index func`, code: Id("a").Add(Index(Lit(1))), expect: `a[1]`, }, { desc: `valuesfunc func`, code: ValuesFunc(func(vg *Group) { vg.Lit(1) }), expect: `{1}`, }, { desc: `valuesfunc group`, code: BlockFunc(func(bg *Group) { bg.ValuesFunc(func(vg *Group) { vg.Lit(1) }) }), expect: `{ {1} }`, }, { desc: `values group`, code: BlockFunc(func(g *Group) { g.Values(Lit(1)) }), expect: `{ {1} }`, }, { desc: `listfunc statement`, code: Add(Null()).ListFunc(func(lg *Group) { lg.Id("a") lg.Id("b") }).Op("=").Id("c"), expect: `a, b = c`, }, { desc: `listfunc func`, code: ListFunc(func(lg *Group) { lg.Id("a") lg.Id("b") }).Op("=").Id("c"), expect: `a, b = c`, }, { desc: `listfunc group`, code: BlockFunc(func(bg *Group) { bg.ListFunc(func(lg *Group) { lg.Id("a") lg.Id("b") }).Op("=").Id("c") }), expect: `{ a, b = c }`, }, { desc: `list group`, code: BlockFunc(func(g *Group) { g.List(Id("a"), Id("b")).Op("=").Id("c") }), expect: `{ a, b = c }`, }, { desc: `parens func`, code: Parens(Lit(1)), expect: `(1)`, }, { desc: `parens group`, code: BlockFunc(func(g *Group) { g.Parens(Lit(1)) }), expect: `{ (1) }`, }, } func TestGen(t *testing.T) { caseTester(t, gencases) } jennifer-1.4.1/jen/group.go000066400000000000000000000073461372216656000155760ustar00rootroot00000000000000package 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 pt, ok := code.(token); ok && pt.typ == packageToken { // Special case for package tokens in Qual groups - for dot-imports, the package token // will be null, so will not render and will not be registered in the imports block. // This ensures all packageTokens that are rendered are registered. f.register(pt.content.(string)) } 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 { return g.RenderWithFile(writer, NewFile("")) } // 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() } // RenderWithFile renders the Group to the provided writer, using imports from the provided file. func (g *Group) RenderWithFile(writer io.Writer, file *File) error { buf := &bytes.Buffer{} if err := g.render(file, 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 } jennifer-1.4.1/jen/group_test.go000066400000000000000000000010141372216656000166170ustar00rootroot00000000000000package jen_test import ( "bytes" "testing" . "github.com/dave/jennifer/jen" ) func TestGroup_Render(t *testing.T) { file := NewFile("main") file.ImportAlias("fmt", "fmtalias") var g *Group BlockFunc(func(group *Group) { g = group }) g.Qual("fmt", "Errorf").Call(Lit("error")) expect := `{ fmtalias.Errorf("error") }` var got bytes.Buffer err := g.RenderWithFile(&got, file) if err != nil { t.Fatal(err) } if got.String() != expect { t.Fatalf("Got: %v, expect: %v", got.String(), expect) } } jennifer-1.4.1/jen/hints.go000066400000000000000000000306521372216656000155630ustar00rootroot00000000000000// 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", } jennifer-1.4.1/jen/jen.go000066400000000000000000000103261372216656000152060ustar00rootroot00000000000000// 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 } jennifer-1.4.1/jen/jen_test.go000066400000000000000000000230451372216656000162470ustar00rootroot00000000000000package jen_test import ( "fmt" "go/format" "strings" "testing" . "github.com/dave/jennifer/jen" ) var o1 = Options{ Close: ")", Multi: true, Open: "(", Separator: ",", } var o2 = Options{ Close: "", Multi: false, Open: "", Separator: ",", } var cases = []tc{ { desc: `scientific notation`, code: Lit(1e3), expect: `1000.0`, }, { desc: `big float`, code: Lit(1000000.0), expect: `1e+06`, }, { desc: `lit float whole numbers`, code: Index().Float64().Values(Lit(-10.0), Lit(-2.0), Lit(-1.0), Lit(0.0), Lit(1.0), Lit(2.0), Lit(10.0)), expect: "[]float64{-10.0, -2.0, -1.0, 0.0, 1.0, 2.0, 10.0}", }, { desc: `custom func group`, code: ListFunc(func(g *Group) { g.CustomFunc(o2, func(g *Group) { g.Id("a") g.Id("b") g.Id("c") }) }).Op("=").Id("foo").Call(), expect: `a, b, c = foo()`, }, { desc: `custom group`, code: ListFunc(func(g *Group) { g.Custom(o2, Id("a"), Id("b"), Id("c")) }).Op("=").Id("foo").Call(), expect: `a, b, c = foo()`, }, { desc: `custom function`, code: Id("foo").Add(Custom(o1, Lit("a"), Lit("b"), Lit("c"))), expect: `foo( "a", "b", "c", )`, }, { desc: `custom function`, code: Id("foo").Add(Custom(o1, Lit("a"), Lit("b"), Lit("c"))), expect: `foo( "a", "b", "c", )`, }, { desc: `line statement`, code: Block(Lit(1).Line(), Lit(2)), expect: `{ 1 2 }`, }, { desc: `line func`, code: Block(Lit(1), Line(), Lit(2)), expect: `{ 1 2 }`, }, { desc: `line group`, code: BlockFunc(func(g *Group) { g.Id("a") g.Line() g.Id("b") }), expect: `{ a b }`, }, { desc: `op group`, code: BlockFunc(func(g *Group) { g.Op("*").Id("a") }), expect: `{*a}`, }, { desc: `empty group`, code: BlockFunc(func(g *Group) { g.Empty() }), expect: `{ }`, }, { desc: `null group`, code: BlockFunc(func(g *Group) { g.Null() }), expect: `{}`, }, { desc: `tag no backquote`, code: Tag(map[string]string{"a": "`b`"}), expect: "\"a:\\\"`b`\\\"\"", }, { desc: `tag null`, code: Tag(map[string]string{}), expect: ``, }, { desc: `litrunefunc group`, code: BlockFunc(func(g *Group) { g.LitByteFunc(func() byte { return byte(0xab) }) }), expect: `{byte(0xab)}`, }, { desc: `litbyte group`, code: BlockFunc(func(g *Group) { g.LitByte(byte(0xab)) }), expect: `{byte(0xab)}`, }, { desc: `litrunefunc group`, code: BlockFunc(func(g *Group) { g.LitRuneFunc(func() rune { return 'a' }) }), expect: `{'a'}`, }, { desc: `litrune group`, code: BlockFunc(func(g *Group) { g.LitRune('a') }), expect: `{'a'}`, }, { desc: `litfunc group`, code: BlockFunc(func(g *Group) { g.LitFunc(func() interface{} { return 1 + 1 }) }), expect: `{2}`, }, { desc: `litfunc func`, code: LitFunc(func() interface{} { return 1 + 1 }), expect: `2`, }, { desc: `group all null`, code: List(Null(), Null()), expect: ``, }, { desc: `do group`, code: BlockFunc(func(g *Group) { g.Do(func(s *Statement) { s.Lit(1) }) }), expect: `{1}`, }, { desc: `do func`, code: Do(func(s *Statement) { s.Lit(1) }), expect: `1`, }, { desc: `dict empty`, code: Values(Dict{}), expect: `{}`, }, { desc: `dict null`, code: Values(Dict{Null(): Null()}), expect: `{}`, }, { desc: `commentf group`, code: BlockFunc(func(g *Group) { g.Commentf("%d", 1) }), expect: `{ // 1 }`, }, { desc: `commentf func`, code: Commentf("%d", 1), expect: `// 1`, }, { desc: `add func`, code: Add(Lit(1)), expect: `1`, }, { desc: `add group`, code: BlockFunc(func(g *Group) { g.Add(Lit(1)) }), expect: `{1}`, }, { desc: `empty block`, code: Block(), expect: `{}`, }, { desc: `string literal`, code: Lit("a"), expect: `"a"`, }, { desc: `int literal`, code: Lit(1), expect: `1`, }, { desc: `simple id`, code: Id("a"), expect: `a`, }, { desc: `foreign id`, code: Qual("x.y/z", "a"), expect: `z.a`, expectImports: map[string]string{ "x.y/z": "z", }, }, { desc: `var decl`, code: Var().Id("a").Op("=").Lit("b"), expect: `var a = "b"`, }, { desc: `short var decl`, code: Id("a").Op(":=").Lit("b"), expect: `a := "b"`, }, { desc: `simple if`, code: If(Id("a").Op("==").Lit("b")).Block(), expect: `if a == "b" {}`, }, { desc: `simple if`, code: If(Id("a").Op("==").Lit("b")).Block( Id("a").Op("++"), ), expect: `if a == "b" { a++ }`, }, { desc: `pointer`, code: Op("*").Id("a"), expect: `*a`, }, { desc: `address`, code: Op("&").Id("a"), expect: `&a`, }, { desc: `simple call`, code: Id("a").Call( Lit("b"), Lit("c"), ), expect: `a("b", "c")`, }, { desc: `call fmt.Sprintf`, code: Qual("fmt", "Sprintf").Call( Lit("b"), Id("c"), ), expect: `fmt.Sprintf("b", c)`, }, { desc: `slices`, code: Id("a").Index( Lit(1), Empty(), ), expect: `a[1:]`, }, { desc: `return`, code: Return(Id("a")), expect: `return a`, }, { desc: `double return`, code: Return(Id("a"), Id("b")), expect: `return a, b`, }, { desc: `func`, code: Func().Id("a").Params( Id("a").String(), ).Block( Return(Id("a")), ), expect: `func a(a string){ return a }`, }, { desc: `built in func`, code: New(Id("a")), expect: `new(a)`, }, { desc: `multip`, code: Id("a").Op("*").Id("b"), expect: `a * b`, }, { desc: `multip ptr`, code: Id("a").Op("*").Op("*").Id("b"), expect: `a * *b`, }, { desc: `field`, code: Id("a").Dot("b"), expect: `a.b`, }, { desc: `method`, code: Id("a").Dot("b").Call(Id("c"), Id("d")), expect: `a.b(c, d)`, }, { desc: `if else`, code: If(Id("a").Op("==").Lit(1)).Block( Id("b").Op("=").Lit(1), ).Else().If(Id("a").Op("==").Lit(2)).Block( Id("b").Op("=").Lit(2), ).Else().Block( Id("b").Op("=").Lit(3), ), expect: `if a == 1 { b = 1 } else if a == 2 { b = 2 } else { b = 3 }`, }, { desc: `literal array`, code: Index().String().Values(Lit("a"), Lit("b")), expect: `[]string{"a", "b"}`, }, { desc: `comment`, code: Comment("a"), expect: `// a`, }, { desc: `null`, code: Id("a").Params(Id("b"), Null(), Id("c")), expect: `a(b, c)`, }, { desc: `map literal single`, code: Id("a").Values(Dict{ Id("b"): Id("c"), }), expect: `a{b: c}`, }, { desc: `map literal null`, code: Id("a").Values(Dict{ Null(): Id("c"), Id("b"): Null(), Id("b"): Id("c"), }), expect: `a{b: c}`, }, { desc: `map literal multiple`, code: Id("a").Values(Dict{ Id("b"): Id("c"), Id("d"): Id("e"), }), expect: `a{ b: c, d: e, }`, }, { desc: `map literal func single`, code: Id("a").Values(DictFunc(func(d Dict) { d[Id("b")] = Id("c") })), expect: `a{b: c}`, }, { desc: `map literal func single null`, code: Id("a").Values(DictFunc(func(d Dict) { d[Null()] = Id("c") d[Id("b")] = Null() d[Id("b")] = Id("c") })), expect: `a{b: c}`, }, { desc: `map literal func multiple`, code: Id("a").Values(DictFunc(func(d Dict) { d[Id("b")] = Id("c") d[Id("d")] = Id("e") })), expect: `a{ b: c, d: e, }`, }, { desc: `literal func`, code: Id("a").Op(":=").LitFunc(func() interface{} { return "b" }), expect: `a := "b"`, }, { desc: `dot`, code: Id("a").Dot("b").Dot("c"), expect: `a.b.c`, }, { desc: `do`, code: Id("a").Do(func(s *Statement) { s.Dot("b") }), expect: `a.b`, }, { desc: `tags should be ordered`, code: Tag(map[string]string{"z": "1", "a": "2"}), expect: "`a:\"2\" z:\"1\"`", }, { desc: `dict should be ordered`, code: Map(String()).Int().Values(Dict{Id("z"): Lit(1), Id("a"): Lit(2)}), expect: `map[string]int{ a:2, z:1, }`, }, } func TestJen(t *testing.T) { caseTester(t, cases) } func caseTester(t *testing.T, cases []tc) { for i, c := range cases { onlyTest := "" if onlyTest != "" && c.desc != onlyTest { continue } rendered := fmt.Sprintf("%#v", c.code) expected, err := format.Source([]byte(c.expect)) if err != nil { panic(fmt.Sprintf("Error formatting expected source in test case %d. Description: %s\nError:\n%s", i, c.desc, err)) } if strings.TrimSpace(string(rendered)) != strings.TrimSpace(string(expected)) { t.Errorf("Test case %d failed. Description: %s\nExpected:\n%s\nOutput:\n%s", i, c.desc, expected, rendered) } //if c.expectImports != nil { // f := FromContext(ctx) // if !reflect.DeepEqual(f.Imports, c.expectImports) { // t.Errorf("Test case %d failed. Description: %s\nImports expected:\n%s\nOutput:\n%s", i, c.desc, c.expectImports, f.Imports) // } //} } } // a test case type tc struct { // path path string // description for locating the test case desc string // code to generate code Code // expected generated source expect string // expected imports expectImports map[string]string } func TestNilStatement(t *testing.T) { var s *Statement c := Func().Id("a").Params( s, ) got := fmt.Sprintf("%#v", c) expect := "func a()" if got != expect { t.Fatalf("Got: %s, expect: %s", got, expect) } } func TestNilGroup(t *testing.T) { var g *Group c := Func().Id("a").Params( g, ) got := fmt.Sprintf("%#v", c) expect := "func a()" if got != expect { t.Fatalf("Got: %s, expect: %s", got, expect) } } func TestGroup_GoString(t *testing.T) { BlockFunc(func(g *Group) { g.Lit(1) got := fmt.Sprintf("%#v", g) expect := "{\n\t1\n}" if got != expect { t.Fatalf("Got: %s, expect: %s", got, expect) } }) } jennifer-1.4.1/jen/lit.go000066400000000000000000000110771372216656000152260ustar00rootroot00000000000000package 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 } jennifer-1.4.1/jen/reserved.go000066400000000000000000000015701372216656000162520ustar00rootroot00000000000000package jen 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", } // IsReservedWord returns if this is a reserved word in go func IsReservedWord(alias string) bool { for _, name := range reserved { if alias == name { return true } } return false } jennifer-1.4.1/jen/statement.go000066400000000000000000000040671372216656000164430ustar00rootroot00000000000000package 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 { return s.RenderWithFile(writer, NewFile("")) } // 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() } // RenderWithFile renders the Statement to the provided writer, using imports from the provided file. func (s *Statement) RenderWithFile(writer io.Writer, file *File) error { buf := &bytes.Buffer{} if err := s.render(file, 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 } jennifer-1.4.1/jen/statement_test.go000066400000000000000000000010471372216656000174750ustar00rootroot00000000000000package jen_test import ( "bytes" "testing" . "github.com/dave/jennifer/jen" ) func TestStatement_Render(t *testing.T) { file := NewFile("main") file.ImportAlias("fmt", "fmtalias") statement := file.Func().Id("main").Params().Block( Qual("fmt", "Println").Call(Lit("something")), ) expect := `func main() { fmtalias.Println("something") }` var got bytes.Buffer err := statement.RenderWithFile(&got, file) if err != nil { t.Fatal(err) } if got.String() != expect { t.Fatalf("Got: %v, expect: %v", got.String(), expect) } } jennifer-1.4.1/jen/tag.go000066400000000000000000000023021372216656000152000ustar00rootroot00000000000000package 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 } jennifer-1.4.1/jen/tokens.go000066400000000000000000000203441372216656000157360ustar00rootroot00000000000000package 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 a dot-import or the local package path return f.isDotImport(t.content.(string)) || 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 } jennifer-1.4.1/jennifer.go000066400000000000000000000006571372216656000154640ustar00rootroot00000000000000// Package jennifer is a code generator for Go package jennifer //go:generate go get github.com/dave/jennifer/genjen //go:generate genjen //go:generate go get github.com/dave/jennifer/gennames //go:generate gennames -output "jen/hints.go" -package "jen" -name "standardLibraryHints" -standard -novendor -path "./..." //go:generate go get github.com/dave/rebecca/cmd/becca //go:generate becca -package=github.com/dave/jennifer/jen