Skip to content

Commit

Permalink
feat: Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
fr12k committed Mar 22, 2024
0 parents commit b583fbb
Show file tree
Hide file tree
Showing 14 changed files with 536 additions and 0 deletions.
38 changes: 38 additions & 0 deletions .github/dependabot.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "sunday"
labels:
- dependencies
commit-message:
prefix: "[PF-2]"
include: "scope"
groups:
minor:
patterns:
- "*"
update-types:
- "minor"
- "patch"
- package-ecosystem: "gomod"
directory: "."
schedule:
interval: "weekly"
day: "sunday"
labels:
- dependencies
commit-message:
prefix: "[PF-2]"
include: "scope"
groups:
minor:
patterns:
- "*"
update-types:
- "minor"
- "patch"
51 changes: 51 additions & 0 deletions .github/workflows/go-library.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: Go library

on: [push]

concurrency:
# Grouped by ref (branch/tag name) not to cancel other jobs running for other feature branches
group: lib_${{ github.ref }}
# > cancel any currently running job or workflow in the same concurrency group
# in case of multiple pushes to the same branch, we just need the latest, so cancel all previous
cancel-in-progress: true

env:
go-version: 1.22

jobs:
lint-and-test:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install Go ${{ env.go-version }}
uses: actions/setup-go@v5
with:
go-version: ${{ env.go-version }}
cache: true

- name: Build Go ${{ env.go-version }}
run: go build ./...

- name: Run golangci-lint
uses: golangci/golangci-lint-action@v4
with:
args: --timeout=3m --modules-download-mode=readonly --go ${{ env.go-version }}
skip-cache: true

- name: build
run: make build

- name: test
run: make test

- name: run
run: make run

- name: SonarCloud Scan
uses: SonarSource/[email protected]
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# go
build
coverage.out
23 changes: 23 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Makefile

all: lint test

lint:
@golangci-lint --version
golangci-lint run ./...

test:
go clean -testcache
go test -v ./... -race -covermode=atomic -coverprofile=coverage.out -timeout=20m
@go tool cover -func coverage.out

gen:
## Generating...
@go generate ./...

.PHONY: build
build:
go build -o ./build/main ./cmd/main.go

run:
./build/main -json cmd/testdata/t.json
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# codegen

This is a code generator for golang to generate code for test boilerplate code.

## Usage

Define the following main program in your golang project.
```go
package main

import (
"github.com/goflink/codegen/pkg/gen"
)

func main() {
codegen := &gen.CodeGenerator{
JsonFile: "./example.json",
CodeFile: "example_generated.go",
Struct: exampleStruct,
PackageName: "home",
ImportCode: `import (
"github.com/fr12k/home"
)`,
StructDefintion: "var responseHome =",
}

codegen.WriteStructFile()
}
```

Then in the unit test just add the following go instruction.
```go
//go:generate go run main.go
//go:generate go fmt example_generated.go
```

32 changes: 32 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package main

import (
"flag"

"github.com/fr12k/codegen/pkg/gen"
)

type v struct {
Name string `json:"name"`
}

func main() {
v := &v{}

jsonFile := flag.String("json", "", "json file")

flag.Parse()

codegen := &gen.CodeGenerator{
JsonFile: *jsonFile,
CodeFile: "example_generated.go",
Struct: v,
PackageName: "home",
ImportCode: `import (
"github.com/fr12k/home"
)`,
StructDefintion: "var responseHome =",
}

codegen.WriteStructFile()
}
14 changes: 14 additions & 0 deletions cmd/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package main

import (
"os"
"testing"
)

func TestMainFunc(t *testing.T) {
os.Args = []string{"cmd", "-json", "./testdata/t.json"}
defer func() {
os.Remove("./example_generated.go")
}()
main()
}
3 changes: 3 additions & 0 deletions cmd/testdata/t.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"name": "jquery.iframe-transport.js"
}
14 changes: 14 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module github.com/fr12k/codegen

go 1.22.1

require (
github.com/gdexlab/go-render v1.0.1
github.com/stretchr/testify v1.9.0
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
12 changes: 12 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gdexlab/go-render v1.0.1 h1:rxqB3vo5s4n1kF0ySmoNeSPRYkEsyHgln4jFIQY7v0U=
github.com/gdexlab/go-render v1.0.1/go.mod h1:wRi5nW2qfjiGj4mPukH4UV0IknS1cHD4VgFTmJX5JzM=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
43 changes: 43 additions & 0 deletions pkg/gen/file_util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package gen

import (
"os"
)

var setup = func(name string) (File, error) {
file, err := os.Create(name)
if err != nil {
return nil, err
}
return &RealFile{file}, nil
}

// File represents an interface for file operations.
type File interface {
WriteString(s string) (n int, err error)
Close() error
}

type RealFile struct {
*os.File
}

// MockFile is a mock implementation of the File interface for testing.
type MockFile struct {
WriteStringFunc func(s string) (n int, err error)
CloseFunc func() error
}

// Write mocks the Write method.
func (m *MockFile) WriteString(s string) (n int, err error) {
return m.WriteStringFunc(s)
}

// Close mocks the Close method.
func (m *MockFile) Close() error {
return m.CloseFunc()
}

func Create(name string) (File, error) {
return setup(name)
}
78 changes: 78 additions & 0 deletions pkg/gen/generate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package gen

import (
"encoding/json"
"fmt"
"os"
"regexp"

"github.com/gdexlab/go-render/render"
)

// AsStructCode generates a struct code from a json file
func AsStructCode(file string, d any) string {
jsonStr, err := os.ReadFile(file)
if err != nil {
panic(err)
}

err = json.Unmarshal(jsonStr, d)
if err != nil {
panic(err)
}
output := render.AsCode(d)

// format nils as runable code e.g. (&render.innerStruct)(nil), -> nil,
re := regexp.MustCompile(`\([*&\w]*.[\w]*\)\(nil\)`)
output = re.ReplaceAllString(output, "nil")

// format struct fields on new lines
re = regexp.MustCompile(`({|, )`)
output = re.ReplaceAllString(output, "$1\n")

// Define the regular expression pattern
pattern := `(?m)(\"(?:[^\"\\]|\\.)*\")`

// Compile the regular expression
re = regexp.MustCompile(pattern)

// Replace new lines within quoted strings with spaces
output = re.ReplaceAllStringFunc(output, func(match string) string {
return regexp.MustCompile(`\n`).ReplaceAllString(match, "")
})

return output
}

type CodeGenerator struct {
JsonFile string
PackageName string
CodeFile string
ImportCode string
StructDefintion string
Struct any
}

func (c *CodeGenerator) WriteStructFile() {
fmt.Printf("Generating %s\n", c.CodeFile)

result := AsStructCode(c.JsonFile, c.Struct)

f, err := Create(c.CodeFile)
if err != nil {
panic(err)
}
defer f.Close()

_, err = f.WriteString(fmt.Sprintf(`package %s
// Code generated by %s DO NOT EDIT.
%s
%s%s`, c.PackageName, c.CodeFile, c.ImportCode, c.StructDefintion, result))
if err != nil {
panic(err)
}
}


Loading

0 comments on commit b583fbb

Please sign in to comment.