Skip to content

Commit 281fdad

Browse files
committed
feat: Initial commit
0 parents  commit 281fdad

File tree

14 files changed

+538
-0
lines changed

14 files changed

+538
-0
lines changed

.github/dependabot.yaml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
---
2+
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
3+
version: 2
4+
updates:
5+
- package-ecosystem: "github-actions"
6+
directory: "/"
7+
schedule:
8+
interval: "weekly"
9+
day: "sunday"
10+
labels:
11+
- dependencies
12+
commit-message:
13+
prefix: "[PF-2]"
14+
include: "scope"
15+
groups:
16+
minor:
17+
patterns:
18+
- "*"
19+
update-types:
20+
- "minor"
21+
- "patch"
22+
- package-ecosystem: "gomod"
23+
directory: "."
24+
schedule:
25+
interval: "weekly"
26+
day: "sunday"
27+
labels:
28+
- dependencies
29+
commit-message:
30+
prefix: "[PF-2]"
31+
include: "scope"
32+
groups:
33+
minor:
34+
patterns:
35+
- "*"
36+
update-types:
37+
- "minor"
38+
- "patch"

.github/workflows/go-library.yml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: Go library
2+
3+
on: [push]
4+
5+
concurrency:
6+
# Grouped by ref (branch/tag name) not to cancel other jobs running for other feature branches
7+
group: lib_${{ github.ref }}
8+
# > cancel any currently running job or workflow in the same concurrency group
9+
# in case of multiple pushes to the same branch, we just need the latest, so cancel all previous
10+
cancel-in-progress: true
11+
12+
env:
13+
go-version: 1.22
14+
15+
jobs:
16+
lint-and-test:
17+
runs-on: ubuntu-latest
18+
19+
steps:
20+
- name: Checkout
21+
uses: actions/checkout@v4
22+
23+
- name: Install Go ${{ env.go-version }}
24+
uses: actions/setup-go@v5
25+
with:
26+
go-version: ${{ env.go-version }}
27+
cache: true
28+
29+
- name: Build Go ${{ env.go-version }}
30+
run: go build ./...
31+
32+
- name: Run golangci-lint
33+
uses: golangci/golangci-lint-action@v4
34+
with:
35+
args: --timeout=3m --modules-download-mode=readonly --go ${{ env.go-version }}
36+
skip-cache: true
37+
38+
- name: build
39+
run: make build
40+
41+
- name: test
42+
run: make test
43+
44+
- name: run
45+
run: make run
46+
47+
- name: SonarCloud Scan
48+
uses: SonarSource/sonarcloud-github-action@v2.1.1
49+
env:
50+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
51+
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# go
2+
build
3+
coverage.out

Makefile

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Makefile
2+
3+
all: lint test
4+
5+
lint:
6+
@golangci-lint --version
7+
golangci-lint run ./...
8+
9+
test:
10+
go clean -testcache
11+
go test -v ./... -race -covermode=atomic -coverprofile=coverage.out -timeout=20m
12+
@go tool cover -func coverage.out
13+
14+
gen:
15+
## Generating...
16+
@go generate ./...
17+
18+
.PHONY: build
19+
build:
20+
go build -o ./build/main ./cmd/main.go
21+
22+
run:
23+
./build/main -json cmd/testdata/t.json

README.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# codegen
2+
3+
This is a code generator for golang to generate code for test boilerplate code.
4+
5+
## Usage
6+
7+
Define the following main program in your golang project.
8+
```go
9+
package main
10+
11+
import (
12+
"github.com/goflink/codegen/pkg/gen"
13+
)
14+
15+
func main() {
16+
codegen := &gen.CodeGenerator{
17+
JsonFile: "./example.json",
18+
CodeFile: "example_generated.go",
19+
Struct: exampleStruct,
20+
PackageName: "home",
21+
ImportCode: `import (
22+
"github.com/fr12k/home"
23+
)`,
24+
StructDefintion: "var responseHome =",
25+
}
26+
27+
codegen.WriteStructFile()
28+
}
29+
```
30+
31+
Then in the unit test just add the following go instruction.
32+
```go
33+
//go:generate go get github.com/fr12k/codegen
34+
//go:generate go run main.go
35+
//go:generate go fmt example_generated.go
36+
//go:generate go mod tidy
37+
```
38+

cmd/main.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
6+
"github.com/fr12k/codegen/pkg/gen"
7+
)
8+
9+
type v struct {
10+
Name string `json:"name"`
11+
}
12+
13+
func main() {
14+
v := &v{}
15+
16+
jsonFile := flag.String("json", "", "json file")
17+
18+
flag.Parse()
19+
20+
codegen := &gen.CodeGenerator{
21+
JsonFile: *jsonFile,
22+
CodeFile: "example_generated.go",
23+
Struct: v,
24+
PackageName: "home",
25+
ImportCode: `import (
26+
"github.com/fr12k/home"
27+
)`,
28+
StructDefintion: "var responseHome =",
29+
}
30+
31+
codegen.WriteStructFile()
32+
}

cmd/main_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package main
2+
3+
import (
4+
"os"
5+
"testing"
6+
)
7+
8+
func TestMainFunc(t *testing.T) {
9+
os.Args = []string{"cmd", "-json", "./testdata/t.json"}
10+
defer func() {
11+
os.Remove("./example_generated.go")
12+
}()
13+
main()
14+
}

cmd/testdata/t.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"name": "jquery.iframe-transport.js"
3+
}

go.mod

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
module github.com/fr12k/codegen
2+
3+
go 1.22.1
4+
5+
require (
6+
github.com/gdexlab/go-render v1.0.1
7+
github.com/stretchr/testify v1.9.0
8+
)
9+
10+
require (
11+
github.com/davecgh/go-spew v1.1.1 // indirect
12+
github.com/pmezard/go-difflib v1.0.0 // indirect
13+
gopkg.in/yaml.v3 v3.0.1 // indirect
14+
)

go.sum

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
2+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/gdexlab/go-render v1.0.1 h1:rxqB3vo5s4n1kF0ySmoNeSPRYkEsyHgln4jFIQY7v0U=
4+
github.com/gdexlab/go-render v1.0.1/go.mod h1:wRi5nW2qfjiGj4mPukH4UV0IknS1cHD4VgFTmJX5JzM=
5+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
6+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
7+
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
8+
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
9+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
10+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
11+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
12+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

pkg/gen/file_util.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package gen
2+
3+
import (
4+
"os"
5+
)
6+
7+
var setup = func(name string) (File, error) {
8+
file, err := os.Create(name)
9+
if err != nil {
10+
return nil, err
11+
}
12+
return &RealFile{file}, nil
13+
}
14+
15+
// File represents an interface for file operations.
16+
type File interface {
17+
WriteString(s string) (n int, err error)
18+
Close() error
19+
}
20+
21+
type RealFile struct {
22+
*os.File
23+
}
24+
25+
// MockFile is a mock implementation of the File interface for testing.
26+
type MockFile struct {
27+
WriteStringFunc func(s string) (n int, err error)
28+
CloseFunc func() error
29+
}
30+
31+
// Write mocks the Write method.
32+
func (m *MockFile) WriteString(s string) (n int, err error) {
33+
return m.WriteStringFunc(s)
34+
}
35+
36+
// Close mocks the Close method.
37+
func (m *MockFile) Close() error {
38+
return m.CloseFunc()
39+
}
40+
41+
func Create(name string) (File, error) {
42+
return setup(name)
43+
}

pkg/gen/generate.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package gen
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"os"
7+
"regexp"
8+
9+
"github.com/gdexlab/go-render/render"
10+
)
11+
12+
// AsStructCode generates a struct code from a json file
13+
func AsStructCode(file string, d any) string {
14+
jsonStr, err := os.ReadFile(file)
15+
if err != nil {
16+
panic(err)
17+
}
18+
19+
err = json.Unmarshal(jsonStr, d)
20+
if err != nil {
21+
panic(err)
22+
}
23+
output := render.AsCode(d)
24+
25+
// format nils as runable code e.g. (&render.innerStruct)(nil), -> nil,
26+
re := regexp.MustCompile(`\([*&\w]*.[\w]*\)\(nil\)`)
27+
output = re.ReplaceAllString(output, "nil")
28+
29+
// format struct fields on new lines
30+
re = regexp.MustCompile(`({|, )`)
31+
output = re.ReplaceAllString(output, "$1\n")
32+
33+
// Define the regular expression pattern
34+
pattern := `(?m)(\"(?:[^\"\\]|\\.)*\")`
35+
36+
// Compile the regular expression
37+
re = regexp.MustCompile(pattern)
38+
39+
// Replace new lines within quoted strings with spaces
40+
output = re.ReplaceAllStringFunc(output, func(match string) string {
41+
return regexp.MustCompile(`\n`).ReplaceAllString(match, "")
42+
})
43+
44+
return output
45+
}
46+
47+
type CodeGenerator struct {
48+
JsonFile string
49+
PackageName string
50+
CodeFile string
51+
ImportCode string
52+
StructDefintion string
53+
Struct any
54+
}
55+
56+
func (c *CodeGenerator) WriteStructFile() {
57+
fmt.Printf("Generating %s\n", c.CodeFile)
58+
59+
result := AsStructCode(c.JsonFile, c.Struct)
60+
61+
f, err := Create(c.CodeFile)
62+
if err != nil {
63+
panic(err)
64+
}
65+
defer f.Close()
66+
67+
_, err = f.WriteString(fmt.Sprintf(`package %s
68+
// Code generated by %s DO NOT EDIT.
69+
70+
%s
71+
72+
%s%s`, c.PackageName, c.CodeFile, c.ImportCode, c.StructDefintion, result))
73+
if err != nil {
74+
panic(err)
75+
}
76+
}
77+
78+

0 commit comments

Comments
 (0)