Skip to content

Commit aa65f26

Browse files
author
lianghuan
committed
Initial commit
1 parent 7eb99bc commit aa65f26

35 files changed

+8254
-2
lines changed

gen/gen.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package gen
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"path/filepath"
7+
"strings"
8+
9+
"github.com/go-spring/gs-gen/gen/generator"
10+
"github.com/go-spring/gs-gen/gen/generator/golang"
11+
"github.com/go-spring/gs-gen/lib/parser"
12+
)
13+
14+
func init() {
15+
generator.RegisterGenerator("go", &golang.Generator{})
16+
}
17+
18+
func Gen(language string, config *generator.Config) error {
19+
g, ok := generator.GetGenerator(language)
20+
if !ok {
21+
return fmt.Errorf("unsupported language: %s", language)
22+
}
23+
files, meta, err := parse(config.ProjectDir)
24+
if err != nil {
25+
return err
26+
}
27+
if meta == nil {
28+
return fmt.Errorf("no meta file")
29+
}
30+
if len(files) == 0 {
31+
return fmt.Errorf("no idl file")
32+
}
33+
if err = parser.Verify(files, meta); err != nil {
34+
return err
35+
}
36+
return g.Gen(config, files, meta)
37+
}
38+
39+
func parse(dir string) (files map[string]parser.Document, meta *parser.MetaInfo, err error) {
40+
files = make(map[string]parser.Document)
41+
entries, err := os.ReadDir(dir)
42+
if err != nil {
43+
return nil, nil, err
44+
}
45+
for _, e := range entries {
46+
if e.IsDir() {
47+
continue
48+
}
49+
fileName := e.Name()
50+
51+
if fileName == "meta.json" {
52+
if meta, err = parseMeta(dir, fileName); err != nil {
53+
return nil, nil, err
54+
}
55+
continue
56+
}
57+
58+
if !strings.HasSuffix(fileName, ".idl") {
59+
continue
60+
}
61+
62+
var doc parser.Document
63+
doc, err = parseFile(dir, fileName)
64+
if err != nil {
65+
return nil, nil, err
66+
}
67+
files[fileName] = doc
68+
}
69+
return
70+
}
71+
72+
func parseMeta(dir string, fileName string) (*parser.MetaInfo, error) {
73+
fileName = filepath.Join(dir, fileName)
74+
b, err := os.ReadFile(fileName)
75+
if err != nil {
76+
return nil, err
77+
}
78+
return parser.ParseMeta(string(b))
79+
}
80+
81+
func parseFile(dir string, fileName string) (parser.Document, error) {
82+
fileName = filepath.Join(dir, fileName)
83+
b, err := os.ReadFile(fileName)
84+
if err != nil {
85+
return parser.Document{}, err
86+
}
87+
return parser.Parse(string(b))
88+
}

gen/gen_test.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+
"os/exec"
8+
"path/filepath"
9+
"testing"
10+
11+
"github.com/go-spring/gs-gen/gen/generator"
12+
)
13+
14+
func TestGen(t *testing.T) {
15+
root := "testdata"
16+
entries, err := os.ReadDir(root)
17+
if err != nil {
18+
t.Fatal(err)
19+
}
20+
for _, e := range entries {
21+
if !e.IsDir() {
22+
continue
23+
}
24+
dir := filepath.Join(root, e.Name())
25+
testProject(t, dir)
26+
}
27+
}
28+
29+
func testProject(t *testing.T, dir string) {
30+
b, err := os.ReadFile(filepath.Join(dir, "test.json"))
31+
if err != nil {
32+
t.Fatal(err)
33+
}
34+
35+
var m map[string]struct {
36+
Server bool
37+
}
38+
if err = json.Unmarshal(b, &m); err != nil {
39+
t.Fatal(err)
40+
}
41+
42+
idlDir := filepath.Join(dir, "idl")
43+
for lang, c := range m {
44+
projectDir := filepath.Join(dir, lang)
45+
46+
if c.Server {
47+
dstDir := filepath.Join(projectDir, "server")
48+
copyFiles(t, idlDir, dstDir)
49+
config := &generator.Config{
50+
ProjectDir: dstDir,
51+
Version: "v0.0.0",
52+
Server: true,
53+
}
54+
if err = Gen(lang, config); err != nil {
55+
t.Fatal(err)
56+
}
57+
}
58+
}
59+
}
60+
61+
func copyFiles(t *testing.T, srcDir, dstDir string) {
62+
srcDir, err := filepath.Abs(srcDir)
63+
if err != nil {
64+
t.Fatal(err)
65+
}
66+
dstDir, err = filepath.Abs(dstDir)
67+
if err != nil {
68+
t.Fatal(err)
69+
}
70+
srcDir = filepath.Join(srcDir, "*")
71+
72+
script := fmt.Sprintf("cp %s %s", srcDir, dstDir)
73+
cmd := exec.Command("/bin/bash", "-c", script)
74+
b, err := cmd.CombinedOutput()
75+
if err != nil {
76+
t.Fatalf("%s: %s", err, b)
77+
}
78+
}

gen/generator/generator.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package generator
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
7+
"github.com/go-spring/gs-gen/lib/parser"
8+
)
9+
10+
type Config struct {
11+
ProjectDir string
12+
Version string
13+
Server bool
14+
}
15+
16+
var generators = map[string]Generator{}
17+
18+
type Generator interface {
19+
Gen(config *Config, files map[string]parser.Document, meta *parser.MetaInfo) error
20+
}
21+
22+
func GetGenerator(language string) (Generator, bool) {
23+
g, ok := generators[language]
24+
return g, ok
25+
}
26+
27+
func RegisterGenerator(language string, g Generator) {
28+
if _, ok := generators[language]; ok {
29+
panic(fmt.Errorf("duplicate generator for %s", language))
30+
}
31+
generators[language] = g
32+
}
33+
34+
func GetType(files map[string]parser.Document, name string) *parser.Type {
35+
for _, doc := range files {
36+
for _, t := range doc.Types {
37+
if t.Name == name {
38+
return t
39+
}
40+
}
41+
}
42+
return nil
43+
}
44+
45+
func GetAnnotation(arr []parser.Annotation, name string) (parser.Annotation, bool) {
46+
for _, a := range arr {
47+
if a.Key == name {
48+
return a, true
49+
}
50+
}
51+
return parser.Annotation{}, false
52+
}
53+
54+
func ToPascal(s string) string {
55+
var sb strings.Builder
56+
parts := strings.Split(s, "_")
57+
for _, part := range parts {
58+
if part == "" {
59+
continue
60+
}
61+
c := part[0]
62+
if 'a' <= c && c <= 'z' {
63+
c = c - 'a' + 'A'
64+
}
65+
sb.WriteByte(c)
66+
if len(part) > 1 {
67+
sb.WriteString(part[1:])
68+
}
69+
}
70+
return sb.String()
71+
}

gen/generator/golang/client.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package golang
2+
3+
import (
4+
"github.com/go-spring/gs-gen/lib/parser"
5+
)
6+
7+
func (g *Generator) genClient(ctx Context, rpcs []*parser.RPC) error {
8+
return nil
9+
}

gen/generator/golang/main.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package golang
2+
3+
import (
4+
"sort"
5+
6+
"github.com/go-spring/gs-gen/gen/generator"
7+
"github.com/go-spring/gs-gen/lib/parser"
8+
)
9+
10+
type Context struct {
11+
config *generator.Config
12+
meta *parser.MetaInfo
13+
files map[string]parser.Document
14+
}
15+
16+
type Generator struct{}
17+
18+
func (g *Generator) Gen(config *generator.Config, files map[string]parser.Document, meta *parser.MetaInfo) error {
19+
ctx := Context{
20+
config: config,
21+
meta: meta,
22+
files: files,
23+
}
24+
25+
if err := g.genMeta(meta); err != nil {
26+
return err
27+
}
28+
29+
var rpcs []*parser.RPC
30+
for fileName, doc := range files {
31+
if err := g.genType(ctx, fileName, doc); err != nil {
32+
return err
33+
}
34+
for _, c := range doc.RPCs {
35+
rpcs = append(rpcs, c)
36+
}
37+
}
38+
39+
sort.Slice(rpcs, func(i, j int) bool {
40+
return rpcs[i].Name < rpcs[j].Name
41+
})
42+
43+
if config.Server {
44+
if err := g.genServer(ctx, rpcs); err != nil {
45+
return err
46+
}
47+
} else {
48+
if err := g.genClient(ctx, rpcs); err != nil {
49+
return err
50+
}
51+
}
52+
return nil
53+
}

gen/generator/golang/meta.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package golang
2+
3+
import (
4+
"github.com/go-spring/gs-gen/lib/parser"
5+
)
6+
7+
func (g *Generator) genMeta(meta *parser.MetaInfo) error {
8+
return nil
9+
}

0 commit comments

Comments
 (0)