├── .github
├── actions
│ └── setup
│ │ └── action.yml
└── workflows
│ ├── ci.yml
│ └── release.yml
├── .gitignore
├── .goreleaser.yaml
├── LICENSE
├── README.md
├── cmd
├── root.go
└── version.go
├── go.mod
├── go.sum
├── internal
└── mingo
│ ├── decl.go
│ ├── expr.go
│ ├── file.go
│ ├── func.go
│ ├── mingo.go
│ ├── mingo_test.go
│ ├── stmt.go
│ └── testdata
│ ├── const
│ ├── expected
│ └── main.go
│ ├── for
│ ├── expected
│ └── main.go
│ ├── func
│ ├── expected
│ └── main.go
│ ├── generic
│ ├── expected
│ └── main.go
│ ├── go
│ ├── expected
│ └── main.go
│ ├── goto
│ ├── expected
│ └── main.go
│ ├── if
│ ├── expected
│ └── main.go
│ ├── incdec
│ ├── expected
│ └── main.go
│ ├── interface
│ ├── expected
│ └── main.go
│ ├── range
│ ├── expected
│ └── main.go
│ ├── slice
│ ├── expected
│ └── main.go
│ ├── struct
│ ├── expected
│ └── main.go
│ ├── switch
│ ├── expected
│ └── main.go
│ └── var
│ ├── expected
│ └── main.go
└── main.go
/.github/actions/setup/action.yml:
--------------------------------------------------------------------------------
1 | name: Setup
2 |
3 | runs:
4 | using: composite
5 | steps:
6 | - uses: actions/setup-go@v4
7 | with:
8 | go-version-file: go.mod
9 | cache: true
10 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: ci
2 |
3 | on:
4 | push:
5 |
6 | jobs:
7 | test:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - name: Checkout
11 | uses: actions/checkout@v4
12 | - name: Setup
13 | uses: ./.github/actions/setup
14 | - name: Test
15 | run: go test ./... -race -coverprofile=coverage.out -covermode=atomic
16 |
17 | build:
18 | runs-on: ubuntu-latest
19 | steps:
20 | - name: Checkout
21 | uses: actions/checkout@v4
22 | - name: Setup
23 | uses: ./.github/actions/setup
24 | - name: Build
25 | run: go build .
26 |
27 | lint:
28 | runs-on: ubuntu-latest
29 | steps:
30 | - name: Checkout
31 | uses: actions/checkout@v4
32 | - name: Setup
33 | uses: ./.github/actions/setup
34 | - name: Lint
35 | uses: golangci/golangci-lint-action@v4
36 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | on:
4 | push:
5 | tags:
6 | - "v*"
7 |
8 | jobs:
9 | release:
10 | runs-on: ubuntu-latest
11 | permissions:
12 | contents: write
13 | steps:
14 | - name: Checkout
15 | uses: actions/checkout@v4
16 | with:
17 | fetch-depth: 0
18 | - name: Setup
19 | uses: ./.github/actions/setup
20 | - name: Release
21 | uses: goreleaser/goreleaser-action@v4
22 | with:
23 | args: release --clean
24 | env:
25 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
26 | TAP_GITHUB_TOKEN: ${{ secrets.TAP_GITHUB_TOKEN }}
27 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /mingo
2 |
--------------------------------------------------------------------------------
/.goreleaser.yaml:
--------------------------------------------------------------------------------
1 | before:
2 | hooks:
3 | - go mod tidy
4 | builds:
5 | - ldflags:
6 | - -s -w -X github.com/koki-develop/mingo/cmd.version=v{{.Version}}
7 | env:
8 | - CGO_ENABLED=0
9 | goos:
10 | - linux
11 | - windows
12 | - darwin
13 |
14 | archives:
15 | - format: tar.gz
16 | name_template: >-
17 | {{ .ProjectName }}_
18 | {{- title .Os }}_
19 | {{- if eq .Arch "amd64" }}x86_64
20 | {{- else if eq .Arch "386" }}i386
21 | {{- else }}{{ .Arch }}{{ end }}
22 | {{- if .Arm }}v{{ .Arm }}{{ end }}
23 | format_overrides:
24 | - goos: windows
25 | format: zip
26 | checksum:
27 | name_template: 'checksums.txt'
28 | snapshot:
29 | name_template: "{{ incpatch .Version }}-next"
30 | changelog:
31 | sort: asc
32 | filters:
33 | exclude:
34 | - '^docs:'
35 | - '^test:'
36 |
37 | brews:
38 | - repository:
39 | owner: koki-develop
40 | name: homebrew-tap
41 | token: "{{ .Env.TAP_GITHUB_TOKEN }}"
42 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Koki Sato
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
mingo
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Go also wants to be minified.
12 |
13 |
14 | ## Contents
15 |
16 | - [Contents](#contents)
17 | - [Installation](#installation)
18 | - [Homebrew Tap](#homebrew-tap)
19 | - [`go install`](#go-install)
20 | - [Releases](#releases)
21 | - [Usage](#usage)
22 | - [Example](#example)
23 | - [LICENSE](#license)
24 |
25 | ## Installation
26 |
27 | ### Homebrew Tap
28 |
29 | ```console
30 | $ brew install koki-develop/tap/mingo
31 | ```
32 |
33 | ### `go install`
34 |
35 | ```console
36 | $ go install github.com/koki-develop/mingo@latest
37 | ```
38 |
39 | ### Releases
40 |
41 | Download the binary from the [releases page](https://github.com/koki-develop/mingo/releases/latest).
42 |
43 | ## Usage
44 |
45 | ```console
46 | $ mingo --help
47 | Go language also wants to be minified.
48 |
49 | Usage:
50 | mingo [flags] [files]...
51 |
52 | Flags:
53 | -h, --help help for mingo
54 | -v, --version version for mingo
55 | -w, --write write result to (source) file instead of stdout
56 | ```
57 |
58 | ### Example
59 |
60 | ```go
61 | // main.go
62 | package main
63 |
64 | import "fmt"
65 |
66 | func fib(n int) int {
67 | if n <= 1 {
68 | return n
69 | }
70 | return fib(n-1) + fib(n-2)
71 | }
72 |
73 | func main() {
74 | n := 10
75 | for i := 0; i < n; i++ {
76 | fmt.Println(fib(i))
77 | }
78 | }
79 | ```
80 |
81 | ```console
82 | $ mingo main.go
83 | ```
84 |
85 | ```go
86 | package main;import "fmt";func fib(n int)int{if n<=1{return n};return fib(n-1)+fib(n-2)};func main(){n:=10;for i:=0;i 1 {
40 | sb.WriteString("(")
41 | } else {
42 | sb.WriteString(" ")
43 | }
44 |
45 | for i, n := range decl.Specs {
46 | n := n.(*ast.ImportSpec)
47 |
48 | if i > 0 {
49 | sb.WriteString(";")
50 | }
51 | if n.Name != nil {
52 | sb.WriteString(fmt.Sprintf("%s %s", n.Name.Name, n.Path.Value))
53 | } else {
54 | sb.WriteString(n.Path.Value)
55 | }
56 | }
57 |
58 | if len(decl.Specs) > 1 {
59 | sb.WriteString(")")
60 | }
61 | sb.WriteString(";")
62 | return sb.String()
63 | }
64 |
65 | func (m *mingo) stringifyConstDecl(decl *ast.GenDecl) string {
66 | sb := new(strings.Builder)
67 | sb.WriteString("const")
68 |
69 | if len(decl.Specs) > 1 {
70 | sb.WriteString("(")
71 | } else {
72 | sb.WriteString(" ")
73 | }
74 |
75 | for i, spec := range decl.Specs {
76 | spec := spec.(*ast.ValueSpec)
77 |
78 | if i > 0 {
79 | sb.WriteString(";")
80 | }
81 | for j, name := range spec.Names {
82 | if j > 0 {
83 | sb.WriteString(",")
84 | }
85 | sb.WriteString(name.Name)
86 | }
87 |
88 | if spec.Type != nil {
89 | sb.WriteString(" ")
90 | sb.WriteString(m.stringifyExpr(spec.Type))
91 | }
92 |
93 | if spec.Values != nil {
94 | sb.WriteString("=")
95 | for k, value := range spec.Values {
96 | if k > 0 {
97 | sb.WriteString(",")
98 | }
99 | sb.WriteString(m.stringifyExpr(value))
100 | }
101 | }
102 | }
103 |
104 | if len(decl.Specs) > 1 {
105 | sb.WriteString(")")
106 | }
107 | sb.WriteString(";")
108 | return sb.String()
109 | }
110 |
111 | func (m *mingo) stringifyVarDecl(decl *ast.GenDecl) string {
112 | sb := new(strings.Builder)
113 |
114 | if decl.Doc != nil {
115 | for _, cmt := range decl.Doc.List {
116 | if strings.HasPrefix(cmt.Text, "//go:embed ") {
117 | fmt.Fprintf(sb, "\n%s\n", cmt.Text)
118 | }
119 | }
120 | }
121 |
122 | sb.WriteString("var")
123 |
124 | if len(decl.Specs) > 1 {
125 | sb.WriteString("(")
126 | } else {
127 | sb.WriteString(" ")
128 | }
129 |
130 | for i, spec := range decl.Specs {
131 | spec := spec.(*ast.ValueSpec)
132 |
133 | if i > 0 {
134 | sb.WriteString(";")
135 | }
136 | for j, name := range spec.Names {
137 | if j > 0 {
138 | sb.WriteString(",")
139 | }
140 |
141 | if spec.Doc != nil {
142 | for _, cmt := range spec.Doc.List {
143 | if strings.HasPrefix(cmt.Text, "//go:embed ") {
144 | fmt.Fprintf(sb, "\n%s\n", cmt.Text)
145 | }
146 | }
147 | }
148 | sb.WriteString(name.Name)
149 | }
150 |
151 | if spec.Type != nil {
152 | sb.WriteString(" ")
153 | sb.WriteString(m.stringifyExpr(spec.Type))
154 | }
155 |
156 | if spec.Values != nil {
157 | sb.WriteString("=")
158 | for k, value := range spec.Values {
159 | if k > 0 {
160 | sb.WriteString(",")
161 | }
162 | sb.WriteString(m.stringifyExpr(value))
163 | }
164 | }
165 | }
166 |
167 | if len(decl.Specs) > 1 {
168 | sb.WriteString(")")
169 | }
170 | sb.WriteString(";")
171 | return sb.String()
172 | }
173 |
174 | func (m *mingo) stringifyTypeSpec(decl *ast.GenDecl) string {
175 | sb := new(strings.Builder)
176 |
177 | for _, n := range decl.Specs {
178 | n := n.(*ast.TypeSpec)
179 |
180 | sb.WriteString(fmt.Sprintf("type %s", n.Name.Name))
181 | if n.TypeParams != nil {
182 | sb.WriteString(m.stringifyFuncTypeParams(n.TypeParams))
183 | }
184 | if n.Assign != 0 {
185 | sb.WriteString("=")
186 | } else {
187 | sb.WriteString(" ")
188 | }
189 | sb.WriteString(m.stringifyExpr(n.Type))
190 | sb.WriteString(";")
191 | }
192 |
193 | return sb.String()
194 | }
195 |
--------------------------------------------------------------------------------
/internal/mingo/expr.go:
--------------------------------------------------------------------------------
1 | package mingo
2 |
3 | import (
4 | "fmt"
5 | "go/ast"
6 | "strings"
7 | )
8 |
9 | func (m *mingo) stringifyExpr(expr ast.Expr) string {
10 | switch x := expr.(type) {
11 | case *ast.BasicLit:
12 | return m.stringifyBasicLit(x)
13 | case *ast.CallExpr:
14 | return m.stringifyCallExpr(x)
15 | case *ast.SelectorExpr:
16 | return m.stringifySelectExpr(x)
17 | case *ast.StarExpr:
18 | return m.stringifyStarExpr(x)
19 | case *ast.ArrayType:
20 | return m.stringifyArrayType(x)
21 | case *ast.Ellipsis:
22 | return m.stringifyEllipsis(x)
23 | case *ast.FuncLit:
24 | return m.stringifyFuncLit(x)
25 | case *ast.BinaryExpr:
26 | return m.stringifyBinaryExpr(x)
27 | case *ast.SliceExpr:
28 | return m.stringifySliceExpr(x)
29 | case *ast.UnaryExpr:
30 | return m.stringifyUnaryExpr(x)
31 | case *ast.CompositeLit:
32 | return m.stringifyCompositeLit(x)
33 | case *ast.ParenExpr:
34 | return m.stringifyParenExpr(x)
35 | case *ast.IndexExpr:
36 | return m.stringifyIndexExpr(x)
37 | case *ast.KeyValueExpr:
38 | return m.stringifyKeyValueExpr(x)
39 | case *ast.TypeAssertExpr:
40 | return m.stringifyTypeAssertExpr(x)
41 | case *ast.ChanType:
42 | return m.stringifyChanType(x)
43 | case *ast.MapType:
44 | return m.stringifyMapType(x)
45 | case *ast.InterfaceType:
46 | return m.stringifyInterfaceType(x)
47 | case *ast.StructType:
48 | return m.stringifyStructType(x)
49 | case *ast.FuncType:
50 | return m.stringifyFuncType(x)
51 | case *ast.IndexListExpr:
52 | return m.stringifyIndexListExpr(x)
53 | case nil:
54 | return ""
55 | }
56 |
57 | return expr.(*ast.Ident).Name
58 | }
59 |
60 | func (m *mingo) stringifyIndexListExpr(expr *ast.IndexListExpr) string {
61 | sb := new(strings.Builder)
62 |
63 | sb.WriteString(m.stringifyExpr(expr.X))
64 | sb.WriteString("[")
65 | for i, index := range expr.Indices {
66 | if i > 0 {
67 | sb.WriteString(",")
68 | }
69 | sb.WriteString(m.stringifyExpr(index))
70 | }
71 | sb.WriteString("]")
72 |
73 | return sb.String()
74 | }
75 |
76 | func (m *mingo) stringifySelectExpr(expr *ast.SelectorExpr) string {
77 | switch x := expr.X.(type) {
78 | case *ast.SelectorExpr:
79 | return fmt.Sprintf("%s.%s", m.stringifySelectExpr(x), expr.Sel.Name)
80 | default:
81 | return fmt.Sprintf("%s.%s", m.stringifyExpr(expr.X), expr.Sel.Name)
82 | }
83 | }
84 |
85 | func (m *mingo) stringifyBasicLit(lit *ast.BasicLit) string {
86 | return lit.Value
87 | }
88 |
89 | func (m *mingo) stringifyCallExpr(expr *ast.CallExpr) string {
90 | sb := new(strings.Builder)
91 |
92 | sb.WriteString(m.stringifyExpr(expr.Fun))
93 | sb.WriteString("(")
94 | for i, arg := range expr.Args {
95 | if i > 0 {
96 | sb.WriteString(",")
97 | }
98 | sb.WriteString(m.stringifyExpr(arg))
99 | }
100 |
101 | if expr.Ellipsis.IsValid() {
102 | sb.WriteString("...")
103 | }
104 |
105 | sb.WriteString(")")
106 |
107 | return sb.String()
108 | }
109 |
110 | func (m *mingo) stringifyStarExpr(expr *ast.StarExpr) string {
111 | return fmt.Sprintf("*%s", m.stringifyExpr(expr.X))
112 | }
113 |
114 | func (m *mingo) stringifyArrayType(expr *ast.ArrayType) string {
115 | return fmt.Sprintf("[]%s", m.stringifyExpr(expr.Elt))
116 | }
117 |
118 | func (m *mingo) stringifyEllipsis(expr *ast.Ellipsis) string {
119 | return fmt.Sprintf("...%s", m.stringifyExpr(expr.Elt))
120 | }
121 |
122 | func (m *mingo) stringifyFuncLit(expr *ast.FuncLit) string {
123 | sb := new(strings.Builder)
124 | sb.WriteString(m.stringifyFuncType(expr.Type))
125 | sb.WriteString(m.stringifyBlockStmt(expr.Body))
126 |
127 | return sb.String()
128 | }
129 |
130 | func (m *mingo) stringifyBinaryExpr(expr *ast.BinaryExpr) string {
131 | return fmt.Sprintf("%s%s%s", m.stringifyExpr(expr.X), expr.Op.String(), m.stringifyExpr(expr.Y))
132 | }
133 |
134 | func (m *mingo) stringifySliceExpr(expr *ast.SliceExpr) string {
135 | sb := new(strings.Builder)
136 |
137 | sb.WriteString(m.stringifyExpr(expr.X))
138 | sb.WriteString("[")
139 | if expr.Low != nil {
140 | sb.WriteString(m.stringifyExpr(expr.Low))
141 | }
142 | sb.WriteString(":")
143 | if expr.High != nil {
144 | sb.WriteString(m.stringifyExpr(expr.High))
145 | }
146 | if expr.Max != nil {
147 | sb.WriteString(":")
148 | sb.WriteString(m.stringifyExpr(expr.Max))
149 | }
150 | sb.WriteString("]")
151 |
152 | return sb.String()
153 | }
154 |
155 | func (m *mingo) stringifyUnaryExpr(expr *ast.UnaryExpr) string {
156 | return fmt.Sprintf("%s%s", expr.Op.String(), m.stringifyExpr(expr.X))
157 | }
158 |
159 | func (m *mingo) stringifyCompositeLit(expr *ast.CompositeLit) string {
160 | sb := new(strings.Builder)
161 |
162 | sb.WriteString(m.stringifyExpr(expr.Type))
163 | sb.WriteString("{")
164 | for i, elt := range expr.Elts {
165 | if i > 0 {
166 | sb.WriteString(",")
167 | }
168 | sb.WriteString(m.stringifyExpr(elt))
169 | }
170 | sb.WriteString("}")
171 |
172 | return sb.String()
173 | }
174 |
175 | func (m *mingo) stringifyParenExpr(expr *ast.ParenExpr) string {
176 | return fmt.Sprintf("(%s)", m.stringifyExpr(expr.X))
177 | }
178 |
179 | func (m *mingo) stringifyIndexExpr(expr *ast.IndexExpr) string {
180 | return fmt.Sprintf("%s[%s]", m.stringifyExpr(expr.X), m.stringifyExpr(expr.Index))
181 | }
182 |
183 | func (m *mingo) stringifyKeyValueExpr(expr *ast.KeyValueExpr) string {
184 | return fmt.Sprintf("%s:%s", m.stringifyExpr(expr.Key), m.stringifyExpr(expr.Value))
185 | }
186 |
187 | func (m *mingo) stringifyTypeAssertExpr(expr *ast.TypeAssertExpr) string {
188 | if expr.Type == nil {
189 | return fmt.Sprintf("%s.(type)", m.stringifyExpr(expr.X))
190 | } else {
191 | return fmt.Sprintf("%s.(%s)", m.stringifyExpr(expr.X), m.stringifyExpr(expr.Type))
192 | }
193 | }
194 |
195 | func (m *mingo) stringifyChanType(expr *ast.ChanType) string {
196 | sb := new(strings.Builder)
197 |
198 | if expr.Dir == ast.RECV {
199 | sb.WriteString("<-")
200 | }
201 | sb.WriteString("chan ")
202 | sb.WriteString(m.stringifyExpr(expr.Value))
203 |
204 | return sb.String()
205 | }
206 |
207 | func (m *mingo) stringifyMapType(expr *ast.MapType) string {
208 | return fmt.Sprintf("map[%s]%s", m.stringifyExpr(expr.Key), m.stringifyExpr(expr.Value))
209 | }
210 |
211 | func (m *mingo) stringifyInterfaceType(expr *ast.InterfaceType) string {
212 | sb := new(strings.Builder)
213 |
214 | sb.WriteString("interface{")
215 | for i, field := range expr.Methods.List {
216 | if i > 0 {
217 | sb.WriteString(";")
218 | }
219 | for _, name := range field.Names {
220 | sb.WriteString(name.Name)
221 | }
222 | if f, ok := field.Type.(*ast.FuncType); ok {
223 | sb.WriteString(m.stringifyFuncTypeParams(f.TypeParams))
224 | sb.WriteString(m.stringifyFuncParams(f.Params))
225 | sb.WriteString(m.stringifyFuncResults(f.Results))
226 | } else {
227 | sb.WriteString(m.stringifyExpr(field.Type))
228 | }
229 | }
230 | sb.WriteString("}")
231 |
232 | return sb.String()
233 | }
234 |
235 | func (m *mingo) stringifyStructType(expr *ast.StructType) string {
236 | sb := new(strings.Builder)
237 |
238 | sb.WriteString("struct{")
239 | for i, field := range expr.Fields.List {
240 | if i > 0 {
241 | sb.WriteString(";")
242 | }
243 | for j, name := range field.Names {
244 | if j > 0 {
245 | sb.WriteString(",")
246 | }
247 | sb.WriteString(name.Name)
248 | }
249 | if len(field.Names) > 0 {
250 | sb.WriteString(" ")
251 | }
252 | sb.WriteString(m.stringifyExpr(field.Type))
253 |
254 | if field.Tag != nil {
255 | sb.WriteString(" ")
256 | sb.WriteString(field.Tag.Value)
257 | }
258 | }
259 | sb.WriteString("}")
260 |
261 | return sb.String()
262 | }
263 |
264 | func (m *mingo) stringifyFuncType(expr *ast.FuncType) string {
265 | sb := new(strings.Builder)
266 |
267 | sb.WriteString("func")
268 | sb.WriteString(m.stringifyFuncTypeParams(expr.TypeParams))
269 | sb.WriteString(m.stringifyFuncParams(expr.Params))
270 | sb.WriteString(m.stringifyFuncResults(expr.Results))
271 |
272 | return sb.String()
273 | }
274 |
--------------------------------------------------------------------------------
/internal/mingo/file.go:
--------------------------------------------------------------------------------
1 | package mingo
2 |
3 | import (
4 | "fmt"
5 | "go/ast"
6 | )
7 |
8 | func (m *mingo) stringifyFile(n *ast.File) string {
9 | return fmt.Sprintf("package %s;", n.Name.Name)
10 | }
11 |
--------------------------------------------------------------------------------
/internal/mingo/func.go:
--------------------------------------------------------------------------------
1 | package mingo
2 |
3 | import (
4 | "fmt"
5 | "go/ast"
6 | "strings"
7 | )
8 |
9 | func (m *mingo) stringifyFuncDecl(n *ast.FuncDecl) string {
10 | sb := new(strings.Builder)
11 |
12 | sb.WriteString("func")
13 |
14 | if n.Recv != nil {
15 | sb.WriteString(m.stringifyFuncParams(n.Recv))
16 | } else {
17 | sb.WriteString(" ")
18 | }
19 |
20 | fmt.Fprintf(sb, "%s", n.Name.Name)
21 |
22 | sb.WriteString(m.stringifyFuncTypeParams(n.Type.TypeParams))
23 | sb.WriteString(m.stringifyFuncParams(n.Type.Params))
24 | sb.WriteString(m.stringifyFuncResults(n.Type.Results))
25 | sb.WriteString(m.stringifyBlockStmt(n.Body))
26 |
27 | sb.WriteString(";")
28 | return sb.String()
29 | }
30 |
31 | func (m *mingo) stringifyFuncTypeParams(params *ast.FieldList) string {
32 | if params == nil {
33 | return ""
34 | }
35 |
36 | sb := new(strings.Builder)
37 |
38 | sb.WriteString("[")
39 | for i, param := range params.List {
40 | if i > 0 {
41 | sb.WriteString(",")
42 | }
43 | for j, name := range param.Names {
44 | if j > 0 {
45 | sb.WriteString(",")
46 | }
47 | sb.WriteString(name.Name)
48 | }
49 | if len(param.Names) > 0 {
50 | sb.WriteString(" ")
51 | }
52 | sb.WriteString(m.stringifyExpr(param.Type))
53 | }
54 | sb.WriteString("]")
55 |
56 | return sb.String()
57 | }
58 |
59 | func (m *mingo) stringifyFuncParams(params *ast.FieldList) string {
60 | sb := new(strings.Builder)
61 |
62 | sb.WriteString("(")
63 |
64 | for i, arg := range params.List {
65 | if i > 0 {
66 | sb.WriteString(",")
67 | }
68 | for j, name := range arg.Names {
69 | if j > 0 {
70 | sb.WriteString(",")
71 | }
72 | sb.WriteString(name.Name)
73 | }
74 |
75 | if len(arg.Names) > 0 {
76 | sb.WriteString(" ")
77 | }
78 |
79 | sb.WriteString(m.stringifyExpr(arg.Type))
80 | }
81 |
82 | sb.WriteString(")")
83 | return sb.String()
84 | }
85 |
86 | func (m *mingo) stringifyFuncResults(results *ast.FieldList) string {
87 | if results == nil {
88 | return ""
89 | }
90 |
91 | sb := new(strings.Builder)
92 | rb := new(strings.Builder)
93 |
94 | needParens := false
95 | if len(results.List) > 1 {
96 | needParens = true
97 | }
98 |
99 | for i, rslt := range results.List {
100 | if i > 0 {
101 | rb.WriteString(",")
102 | }
103 |
104 | for j, name := range rslt.Names {
105 | needParens = true
106 | if j > 0 {
107 | rb.WriteString(",")
108 | }
109 | rb.WriteString(name.Name)
110 | rb.WriteString(" ")
111 | }
112 |
113 | rb.WriteString(m.stringifyExpr(rslt.Type))
114 | }
115 |
116 | if needParens {
117 | sb.WriteString("(")
118 | }
119 | sb.WriteString(rb.String())
120 | if needParens {
121 | sb.WriteString(")")
122 | }
123 |
124 | return sb.String()
125 | }
126 |
--------------------------------------------------------------------------------
/internal/mingo/mingo.go:
--------------------------------------------------------------------------------
1 | package mingo
2 |
3 | import (
4 | "bytes"
5 | "fmt"
6 | "go/format"
7 | "go/parser"
8 | "go/token"
9 | "strings"
10 | )
11 |
12 | func Minify(filename string, src []byte) ([]byte, error) {
13 | if s, err := format.Source(src); err != nil {
14 | return nil, err
15 | } else {
16 | src = s
17 | }
18 |
19 | fset := token.NewFileSet()
20 | m := &mingo{fileSet: fset}
21 | return m.Minify(filename, src)
22 | }
23 |
24 | type mingo struct {
25 | fileSet *token.FileSet
26 | }
27 |
28 | func (m *mingo) Minify(filename string, src []byte) ([]byte, error) {
29 | file, err := parser.ParseFile(m.fileSet, filename, string(src), parser.ParseComments)
30 | if err != nil {
31 | return nil, err
32 | }
33 |
34 | b := new(bytes.Buffer)
35 |
36 | for _, cg := range file.Comments {
37 | for _, c := range cg.List {
38 | dirs := []string{"//go:build ", "// +build ", "//go:generate "}
39 | for _, prefix := range dirs {
40 | if strings.HasPrefix(c.Text, prefix) {
41 | fmt.Fprintln(b, c.Text)
42 | }
43 | }
44 | }
45 | }
46 |
47 | fmt.Fprint(b, m.stringifyFile(file))
48 | for _, decl := range file.Decls {
49 | fmt.Fprint(b, m.stringifyDecl(decl))
50 | }
51 |
52 | return b.Bytes(), nil
53 | }
54 |
--------------------------------------------------------------------------------
/internal/mingo/mingo_test.go:
--------------------------------------------------------------------------------
1 | package mingo
2 |
3 | import (
4 | "embed"
5 | "fmt"
6 | "go/format"
7 | "testing"
8 |
9 | "github.com/stretchr/testify/assert"
10 | )
11 |
12 | //go:embed testdata
13 | var testdata embed.FS
14 |
15 | func Test_Minify(t *testing.T) {
16 | dirs, err := testdata.ReadDir("testdata")
17 | if err != nil {
18 | t.Fatal(err)
19 | }
20 |
21 | for _, dir := range dirs {
22 | t.Run(dir.Name(), func(t *testing.T) {
23 | src, err := testdata.ReadFile(fmt.Sprintf("testdata/%s/main.go", dir.Name()))
24 | if err != nil {
25 | t.Fatal(err)
26 | }
27 |
28 | want, err := testdata.ReadFile(fmt.Sprintf("testdata/%s/expected", dir.Name()))
29 | if err != nil {
30 | t.Fatal(err)
31 | }
32 |
33 | got, err := Minify("main.go", src)
34 | assert.NoError(t, err)
35 | assert.Equal(t, string(want), string(got))
36 |
37 | // check syntax
38 | _, err = format.Source([]byte(got))
39 | assert.NoError(t, err)
40 | })
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/internal/mingo/stmt.go:
--------------------------------------------------------------------------------
1 | package mingo
2 |
3 | import (
4 | "fmt"
5 | "go/ast"
6 | "go/token"
7 | "strings"
8 | )
9 |
10 | func (m *mingo) stringifyStmt(stmt ast.Stmt) string {
11 | switch x := stmt.(type) {
12 | case *ast.ReturnStmt:
13 | return m.stringifyReturnStmt(x)
14 | case *ast.AssignStmt:
15 | return m.stringifyAssignStmt(x)
16 | case *ast.IfStmt:
17 | return m.stringifyIfStmt(x)
18 | case *ast.BlockStmt:
19 | return m.stringifyBlockStmt(x)
20 | case *ast.ExprStmt:
21 | return m.stringifyExprStmt(x)
22 | case *ast.DeclStmt:
23 | return m.stringifyDeclStmt(x)
24 | case *ast.DeferStmt:
25 | return m.stringifyDeferStmt(x)
26 | case *ast.GoStmt:
27 | return m.stringifyGoStmt(x)
28 | case *ast.LabeledStmt:
29 | return m.stringifyLabeledStmt(x)
30 | case *ast.SwitchStmt:
31 | return m.stringifySwitchStmt(x)
32 | case *ast.SelectStmt:
33 | return m.stringifySelectStmt(x)
34 | case *ast.ForStmt:
35 | return m.stringifyForStmt(x)
36 | case *ast.RangeStmt:
37 | return m.stringifyRangeStmt(x)
38 | case *ast.BranchStmt:
39 | return m.stringifyBranchStmt(x)
40 | case *ast.EmptyStmt:
41 | return m.stringifyEmptyStmt(x)
42 | case *ast.IncDecStmt:
43 | return m.stringifyIncDecStmt(x)
44 | case *ast.SendStmt:
45 | return m.stringifySendStmt(x)
46 | case *ast.CaseClause:
47 | return m.stringifyCaseCaluse(x)
48 | case *ast.CommClause:
49 | return m.stringifyCommClause(x)
50 | case *ast.TypeSwitchStmt:
51 | return m.stringifyTypeSwitchStmt(x)
52 | default:
53 | panic(fmt.Sprintf("unhandled stmt: %#v", x))
54 | }
55 | }
56 |
57 | func (m *mingo) stringifyBlockStmt(stmt *ast.BlockStmt) string {
58 | sb := new(strings.Builder)
59 |
60 | sb.WriteString("{")
61 | for i, child := range stmt.List {
62 | sb.WriteString(m.stringifyStmt(child))
63 |
64 | if _, ok := child.(*ast.DeclStmt); !ok {
65 | if i < len(stmt.List)-1 {
66 | sb.WriteString(";")
67 | }
68 | }
69 | }
70 | sb.WriteString("}")
71 | return sb.String()
72 | }
73 |
74 | func (m *mingo) stringifyReturnStmt(stmt *ast.ReturnStmt) string {
75 | sb := new(strings.Builder)
76 |
77 | sb.WriteString("return")
78 | if len(stmt.Results) > 0 {
79 | sb.WriteString(" ")
80 | }
81 |
82 | for i, expr := range stmt.Results {
83 | if i > 0 {
84 | sb.WriteString(",")
85 | }
86 | sb.WriteString(m.stringifyExpr(expr))
87 | }
88 |
89 | return sb.String()
90 | }
91 |
92 | func (m *mingo) stringifyAssignStmt(stmt *ast.AssignStmt) string {
93 | sb := new(strings.Builder)
94 |
95 | for i, expr := range stmt.Lhs {
96 | if i > 0 {
97 | sb.WriteString(",")
98 | }
99 | sb.WriteString(m.stringifyExpr(expr))
100 | }
101 | if stmt.Tok == token.DEFINE {
102 | sb.WriteString(":=")
103 | } else {
104 | sb.WriteString("=")
105 | }
106 | for i, expr := range stmt.Rhs {
107 | if i > 0 {
108 | sb.WriteString(",")
109 | }
110 | sb.WriteString(m.stringifyExpr(expr))
111 | }
112 |
113 | return sb.String()
114 | }
115 |
116 | func (m *mingo) stringifyIfStmt(stmt *ast.IfStmt) string {
117 | sb := new(strings.Builder)
118 |
119 | sb.WriteString("if ")
120 | sb.WriteString(m.stringifyIfStmtBody(stmt))
121 |
122 | return sb.String()
123 | }
124 |
125 | func (m *mingo) stringifyElseIfStmt(stmt *ast.IfStmt) string {
126 | sb := new(strings.Builder)
127 |
128 | sb.WriteString("else if ")
129 | sb.WriteString(m.stringifyIfStmtBody(stmt))
130 |
131 | return sb.String()
132 | }
133 |
134 | func (m *mingo) stringifyIfStmtBody(stmt *ast.IfStmt) string {
135 | sb := new(strings.Builder)
136 |
137 | if stmt.Init != nil {
138 | sb.WriteString(m.stringifyStmt(stmt.Init))
139 | sb.WriteString(";")
140 | }
141 | if stmt.Cond != nil {
142 | sb.WriteString(m.stringifyExpr(stmt.Cond))
143 | }
144 | if stmt.Body != nil {
145 | sb.WriteString(m.stringifyBlockStmt(stmt.Body))
146 | }
147 | if stmt.Else != nil {
148 | if ifstmt, ok := stmt.Else.(*ast.IfStmt); ok {
149 | sb.WriteString(m.stringifyElseIfStmt(ifstmt))
150 | } else {
151 | sb.WriteString("else")
152 | sb.WriteString(m.stringifyStmt(stmt.Else))
153 | }
154 | }
155 |
156 | return sb.String()
157 | }
158 |
159 | func (m *mingo) stringifyExprStmt(stmt *ast.ExprStmt) string {
160 | sb := new(strings.Builder)
161 | sb.WriteString(m.stringifyExpr(stmt.X))
162 |
163 | return sb.String()
164 | }
165 |
166 | func (m *mingo) stringifyDeclStmt(stmt *ast.DeclStmt) string {
167 | sb := new(strings.Builder)
168 | sb.WriteString(m.stringifyDecl(stmt.Decl))
169 |
170 | return sb.String()
171 | }
172 |
173 | func (m *mingo) stringifyDeferStmt(stmt *ast.DeferStmt) string {
174 | sb := new(strings.Builder)
175 | sb.WriteString("defer ")
176 | sb.WriteString(m.stringifyExpr(stmt.Call))
177 |
178 | return sb.String()
179 | }
180 |
181 | func (m *mingo) stringifyGoStmt(stmt *ast.GoStmt) string {
182 | sb := new(strings.Builder)
183 | sb.WriteString("go ")
184 | sb.WriteString(m.stringifyExpr(stmt.Call))
185 |
186 | return sb.String()
187 | }
188 |
189 | func (m *mingo) stringifyLabeledStmt(stmt *ast.LabeledStmt) string {
190 | sb := new(strings.Builder)
191 | sb.WriteString(fmt.Sprintf("%s:", stmt.Label.Name))
192 | sb.WriteString(m.stringifyStmt(stmt.Stmt))
193 |
194 | return sb.String()
195 | }
196 |
197 | func (m *mingo) stringifySwitchStmt(stmt *ast.SwitchStmt) string {
198 | sb := new(strings.Builder)
199 | sb.WriteString("switch ")
200 | if stmt.Init != nil {
201 | sb.WriteString(m.stringifyStmt(stmt.Init))
202 | sb.WriteString(";")
203 | }
204 | if stmt.Tag != nil {
205 | sb.WriteString(m.stringifyExpr(stmt.Tag))
206 | }
207 | if stmt.Body != nil {
208 | sb.WriteString(m.stringifyBlockStmt(stmt.Body))
209 | }
210 |
211 | return sb.String()
212 | }
213 |
214 | func (m *mingo) stringifySelectStmt(stmt *ast.SelectStmt) string {
215 | sb := new(strings.Builder)
216 | sb.WriteString("select ")
217 | sb.WriteString(m.stringifyBlockStmt(stmt.Body))
218 |
219 | return sb.String()
220 | }
221 |
222 | func (m *mingo) stringifyForStmt(stmt *ast.ForStmt) string {
223 | sb := new(strings.Builder)
224 | sb.WriteString("for ")
225 |
226 | if stmt.Init != nil {
227 | sb.WriteString(m.stringifyStmt(stmt.Init))
228 | }
229 | if stmt.Init != nil || stmt.Post != nil {
230 | sb.WriteString(";")
231 | }
232 | if stmt.Cond != nil {
233 | sb.WriteString(m.stringifyExpr(stmt.Cond))
234 | }
235 | if stmt.Init != nil || stmt.Post != nil {
236 | sb.WriteString(";")
237 | }
238 | if stmt.Post != nil {
239 | sb.WriteString(m.stringifyStmt(stmt.Post))
240 | }
241 | sb.WriteString(m.stringifyBlockStmt(stmt.Body))
242 |
243 | return sb.String()
244 | }
245 |
246 | func (m *mingo) stringifyRangeStmt(stmt *ast.RangeStmt) string {
247 | sb := new(strings.Builder)
248 | sb.WriteString("for ")
249 |
250 | needAssign := false
251 | if stmt.Key != nil {
252 | needAssign = true
253 | sb.WriteString(m.stringifyExpr(stmt.Key))
254 | }
255 | if stmt.Value != nil {
256 | needAssign = true
257 | sb.WriteString(",")
258 | sb.WriteString(m.stringifyExpr(stmt.Value))
259 | }
260 |
261 | if needAssign {
262 | sb.WriteString(":=")
263 | }
264 |
265 | sb.WriteString("range ")
266 | sb.WriteString(m.stringifyExpr(stmt.X))
267 | sb.WriteString(m.stringifyBlockStmt(stmt.Body))
268 |
269 | return sb.String()
270 | }
271 |
272 | func (m *mingo) stringifyBranchStmt(stmt *ast.BranchStmt) string {
273 | sb := new(strings.Builder)
274 | sb.WriteString(stmt.Tok.String())
275 | if stmt.Label != nil {
276 | sb.WriteString(" ")
277 | sb.WriteString(stmt.Label.Name)
278 | }
279 | return sb.String()
280 | }
281 |
282 | func (m *mingo) stringifyEmptyStmt(_ *ast.EmptyStmt) string {
283 | return ""
284 | }
285 |
286 | func (m *mingo) stringifyIncDecStmt(stmt *ast.IncDecStmt) string {
287 | sb := new(strings.Builder)
288 | sb.WriteString(m.stringifyExpr(stmt.X))
289 | sb.WriteString(stmt.Tok.String())
290 |
291 | return sb.String()
292 | }
293 |
294 | func (m *mingo) stringifySendStmt(stmt *ast.SendStmt) string {
295 | sb := new(strings.Builder)
296 | sb.WriteString(m.stringifyExpr(stmt.Chan))
297 | sb.WriteString("<-")
298 | sb.WriteString(m.stringifyExpr(stmt.Value))
299 |
300 | return sb.String()
301 | }
302 |
303 | func (m *mingo) stringifyCaseCaluse(stmt *ast.CaseClause) string {
304 | sb := new(strings.Builder)
305 |
306 | if len(stmt.List) > 0 {
307 | sb.WriteString("case ")
308 | for i, expr := range stmt.List {
309 | if i > 0 {
310 | sb.WriteString(",")
311 | }
312 | sb.WriteString(m.stringifyExpr(expr))
313 | }
314 | sb.WriteString(":")
315 | } else {
316 | sb.WriteString("default:")
317 | }
318 | for i, child := range stmt.Body {
319 | sb.WriteString(m.stringifyStmt(child))
320 | if i < len(stmt.Body)-1 {
321 | sb.WriteString(";")
322 | }
323 | }
324 |
325 | return sb.String()
326 | }
327 |
328 | func (m *mingo) stringifyCommClause(stmt *ast.CommClause) string {
329 | sb := new(strings.Builder)
330 |
331 | if stmt.Comm != nil {
332 | sb.WriteString("case ")
333 | sb.WriteString(m.stringifyStmt(stmt.Comm))
334 | sb.WriteString(":")
335 | } else {
336 | sb.WriteString("default:")
337 | }
338 | for _, stmt := range stmt.Body {
339 | sb.WriteString(m.stringifyStmt(stmt))
340 | sb.WriteString(";")
341 | }
342 |
343 | return sb.String()
344 | }
345 |
346 | func (m *mingo) stringifyTypeSwitchStmt(stmt *ast.TypeSwitchStmt) string {
347 | sb := new(strings.Builder)
348 | sb.WriteString("switch ")
349 | if stmt.Init != nil {
350 | sb.WriteString(m.stringifyStmt(stmt.Init))
351 | sb.WriteString(";")
352 | }
353 | if stmt.Assign != nil {
354 | sb.WriteString(m.stringifyStmt(stmt.Assign))
355 | }
356 | if stmt.Body != nil {
357 | sb.WriteString(m.stringifyBlockStmt(stmt.Body))
358 | }
359 |
360 | return sb.String()
361 | }
362 |
--------------------------------------------------------------------------------
/internal/mingo/testdata/const/expected:
--------------------------------------------------------------------------------
1 | package main;const(A=1;B int=2;C,D int=3,4;E,F,G=3,4,5);const(_=iota;a;b;c);const w=1;const x int=2;const y,z=3,4;func main(){const a=1;const b,c=2,3;const(d=4;e=5);};
--------------------------------------------------------------------------------
/internal/mingo/testdata/const/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | const (
4 | A = 1
5 | B int = 2
6 | C, D int = 3, 4
7 | E, F, G = 3, 4, 5
8 | )
9 |
10 | const (
11 | _ = iota
12 | a
13 | b
14 | c
15 | )
16 |
17 | const w = 1
18 | const x int = 2
19 | const y, z = 3, 4
20 |
21 | func main() {
22 | const a = 1
23 | const b, c = 2, 3
24 | const (
25 | d = 4
26 | e = 5
27 | )
28 | }
29 |
--------------------------------------------------------------------------------
/internal/mingo/testdata/for/expected:
--------------------------------------------------------------------------------
1 | package main;func main(){for {break};for i:=0;i<10;i++{println(i)};for i:=0;i<10;{println(i);i++};for i:=0;;i++{if i>=10{break};println(i)};i:=0;for ;i<10;i++{println(i)};for i<20{println(i);i++};for true{break}};
--------------------------------------------------------------------------------
/internal/mingo/testdata/for/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {
4 | for {
5 | break
6 | }
7 |
8 | for i := 0; i < 10; i++ {
9 | println(i)
10 | }
11 |
12 | for i := 0; i < 10; {
13 | println(i)
14 | i++
15 | }
16 |
17 | for i := 0; ; i++ {
18 | if i >= 10 {
19 | break
20 | }
21 | println(i)
22 | }
23 |
24 | i := 0
25 | for ; i < 10; i++ {
26 | println(i)
27 | }
28 |
29 | for i < 20 {
30 | println(i)
31 | i++
32 | }
33 |
34 | for true {
35 | break
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/internal/mingo/testdata/func/expected:
--------------------------------------------------------------------------------
1 | package main;import "fmt";func hello(){func(){fmt.Println("Hello")}();func(s string){fmt.Printf("Hello, %s\n",s)}("world");if err:=func()error{return nil}();err!=nil{fmt.Println(err)}};func main(){go hello()};
--------------------------------------------------------------------------------
/internal/mingo/testdata/func/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func hello() {
6 | func() {
7 | fmt.Println("Hello")
8 | }()
9 |
10 | func(s string) {
11 | fmt.Printf("Hello, %s\n", s)
12 | }("world")
13 |
14 | if err := func() error {
15 | return nil
16 | }(); err != nil {
17 | fmt.Println(err)
18 | }
19 | }
20 |
21 | func main() {
22 | go hello()
23 | }
24 |
--------------------------------------------------------------------------------
/internal/mingo/testdata/generic/expected:
--------------------------------------------------------------------------------
1 | package main;import "fmt";func Ptr[T any](p T)*T{return &p};func Equals[T,U comparable](t T,u U)bool{return t==u};func Hoge[T comparable,U fmt.Stringer](s []T,e U)bool{return true};func main(){fmt.Println(Ptr(1))};
--------------------------------------------------------------------------------
/internal/mingo/testdata/generic/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func Ptr[T any](p T) *T {
6 | return &p
7 | }
8 |
9 | func Equals[T, U comparable](t T, u U) bool {
10 | return t == u
11 | }
12 |
13 | func Hoge[T comparable, U fmt.Stringer](s []T, e U) bool {
14 | return true
15 | }
16 |
17 | func main() {
18 | fmt.Println(Ptr(1))
19 | }
20 |
--------------------------------------------------------------------------------
/internal/mingo/testdata/go/expected:
--------------------------------------------------------------------------------
1 | package main;import("fmt";"time");func hello(){fmt.Println("Hello, 世界");time.Sleep(1*time.Second)};func main(){go func(){fmt.Println("Hello, 世界");time.Sleep(1*time.Second)}();go hello()};
--------------------------------------------------------------------------------
/internal/mingo/testdata/go/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "time"
6 | )
7 |
8 | func hello() {
9 | fmt.Println("Hello, 世界")
10 | time.Sleep(1 * time.Second)
11 | }
12 |
13 | func main() {
14 | go func() {
15 | fmt.Println("Hello, 世界")
16 | time.Sleep(1 * time.Second)
17 | }()
18 |
19 | go hello()
20 | }
21 |
--------------------------------------------------------------------------------
/internal/mingo/testdata/goto/expected:
--------------------------------------------------------------------------------
1 | package main;import "fmt";func main(){fmt.Println("A");goto label;fmt.Println("B");label:fmt.Println("C")};
--------------------------------------------------------------------------------
/internal/mingo/testdata/goto/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | fmt.Println("A")
7 | goto label
8 | fmt.Println("B")
9 | label:
10 | fmt.Println("C")
11 | }
12 |
--------------------------------------------------------------------------------
/internal/mingo/testdata/if/expected:
--------------------------------------------------------------------------------
1 | package main;import "fmt";func main(){if true{fmt.Println("TRUE");if true{fmt.Println("TRUE")}};if false{fmt.Println("TRUE")}else{fmt.Println("FALSE")};if false{fmt.Println("TRUE")}else if true{fmt.Println("TRUE")};if err:=run1();err!=nil{fmt.Println(err)};if _,err:=run2();err!=nil{fmt.Println(err)}};func run1()error{return nil};func run2()(string,error){return "",nil};
--------------------------------------------------------------------------------
/internal/mingo/testdata/if/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | if true {
7 | fmt.Println("TRUE")
8 | if true {
9 | fmt.Println("TRUE")
10 | }
11 | }
12 |
13 | if false {
14 | fmt.Println("TRUE")
15 | } else {
16 | fmt.Println("FALSE")
17 | }
18 |
19 | if false {
20 | fmt.Println("TRUE")
21 | } else if true {
22 | fmt.Println("TRUE")
23 | }
24 |
25 | if err := run1(); err != nil {
26 | fmt.Println(err)
27 | }
28 |
29 | if _, err := run2(); err != nil {
30 | fmt.Println(err)
31 | }
32 | }
33 |
34 | func run1() error {
35 | return nil
36 | }
37 |
38 | func run2() (string, error) {
39 | return "", nil
40 | }
41 |
--------------------------------------------------------------------------------
/internal/mingo/testdata/incdec/expected:
--------------------------------------------------------------------------------
1 | package main;import "fmt";func main(){i:=1;i++;i--;i++;fmt.Println(i)};
--------------------------------------------------------------------------------
/internal/mingo/testdata/incdec/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | i := 1
7 | i++
8 | i--
9 | i++
10 | fmt.Println(i)
11 | }
12 |
--------------------------------------------------------------------------------
/internal/mingo/testdata/interface/expected:
--------------------------------------------------------------------------------
1 | package main;type I1 interface{F1()string;F2()(string,error);F3()(s string,err error)};type I2 interface{I1;F4(s string);F5(string);F6(s1,s2 string);F7(s1 string,s2 string);F8(s1,s2 string,i int);F9(f func()string)};
--------------------------------------------------------------------------------
/internal/mingo/testdata/interface/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | type I1 interface {
4 | F1() string
5 | F2() (string, error)
6 | F3() (s string, err error)
7 | }
8 |
9 | type I2 interface {
10 | I1
11 |
12 | F4(s string)
13 | F5(string)
14 | F6(s1, s2 string)
15 | F7(s1 string, s2 string)
16 | F8(s1, s2 string, i int)
17 | F9(f func() string)
18 | }
19 |
--------------------------------------------------------------------------------
/internal/mingo/testdata/range/expected:
--------------------------------------------------------------------------------
1 | package main;func main(){for range 10{break};for i:=range 10{println(i)};for _,s:=range []string{"a","b","c"}{println(s)};for i,s:=range []string{"a","b","c"}{println(i,s)};for i:=range []string{"a","b","c"}{println(i)}};
--------------------------------------------------------------------------------
/internal/mingo/testdata/range/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {
4 | for range 10 {
5 | break
6 | }
7 |
8 | for i := range 10 {
9 | println(i)
10 | }
11 |
12 | for _, s := range []string{"a", "b", "c"} {
13 | println(s)
14 | }
15 |
16 | for i, s := range []string{"a", "b", "c"} {
17 | println(i, s)
18 | }
19 |
20 | for i := range []string{"a", "b", "c"} {
21 | println(i)
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/internal/mingo/testdata/slice/expected:
--------------------------------------------------------------------------------
1 | package main;import "fmt";func main(){s:=[]string{"A","B","C"};fmt.Println(s[0]);fmt.Println(s[0:1]);fmt.Println(s[0:]);fmt.Println(s[:1]);fmt.Println(s[:])};
--------------------------------------------------------------------------------
/internal/mingo/testdata/slice/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | s := []string{"A", "B", "C"}
7 |
8 | fmt.Println(s[0])
9 | fmt.Println(s[0:1])
10 | fmt.Println(s[0:])
11 | fmt.Println(s[:1])
12 | fmt.Println(s[:])
13 | }
14 |
--------------------------------------------------------------------------------
/internal/mingo/testdata/struct/expected:
--------------------------------------------------------------------------------
1 | package main;type S1 struct{S struct{A string;B int;C bool};F1 func()string;F2 func()(string,error);F3 func()(s string,err error)};type S2 struct{S1;A string;B int;C bool;a string;b int;c bool;F4 func(s string);F5 func(string);F6 func(s1,s2 string);F7 func(f1 func()string)};func main(){type S3 struct{S1;A string;B int;C bool};};
--------------------------------------------------------------------------------
/internal/mingo/testdata/struct/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | type S1 struct {
4 | S struct {
5 | A string
6 | B int
7 | C bool
8 | }
9 |
10 | F1 func() string
11 | F2 func() (string, error)
12 | F3 func() (s string, err error)
13 | }
14 |
15 | type S2 struct {
16 | S1
17 |
18 | A string
19 | B int
20 | C bool
21 |
22 | a string
23 | b int
24 | c bool
25 |
26 | F4 func(s string)
27 | F5 func(string)
28 | F6 func(s1, s2 string)
29 | F7 func(f1 func() string)
30 | }
31 |
32 | func main() {
33 | type S3 struct {
34 | S1
35 |
36 | A string
37 | B int
38 | C bool
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/internal/mingo/testdata/switch/expected:
--------------------------------------------------------------------------------
1 | package main;import "fmt";func main(){i:=0;switch i{case 0:fmt.Println("1");fmt.Println("2");fmt.Println("3");case 1,2:fmt.Println("4");fmt.Println("5");fmt.Println("6");default:fmt.Println("7");fmt.Println("8");fmt.Println("9")}};
--------------------------------------------------------------------------------
/internal/mingo/testdata/switch/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | i := 0
7 |
8 | switch i {
9 | case 0:
10 | fmt.Println("1")
11 | fmt.Println("2")
12 | fmt.Println("3")
13 | case 1, 2:
14 | fmt.Println("4")
15 | fmt.Println("5")
16 | fmt.Println("6")
17 | default:
18 | fmt.Println("7")
19 | fmt.Println("8")
20 | fmt.Println("9")
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/internal/mingo/testdata/var/expected:
--------------------------------------------------------------------------------
1 | package main;var(A=1;B int=2;C,D int=3,4;E,F,G=3,4,5);var w=1;var x int=2;var y,z=3,4;func main(){var a int=1;var b,c int=2,3;var(d=4;e=5);};
--------------------------------------------------------------------------------
/internal/mingo/testdata/var/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | var (
4 | A = 1
5 | B int = 2
6 | C, D int = 3, 4
7 | E, F, G = 3, 4, 5
8 | )
9 |
10 | var w = 1
11 | var x int = 2
12 | var y, z = 3, 4
13 |
14 | func main() {
15 | var a int = 1
16 | var b, c int = 2, 3
17 | var (
18 | d = 4
19 | e = 5
20 | )
21 | }
22 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "github.com/koki-develop/mingo/cmd"
5 | )
6 |
7 | func main() {
8 | cmd.Execute()
9 | }
10 |
--------------------------------------------------------------------------------