Skip to content

Commit 5858990

Browse files
authored
Merge pull request #6 from averak/feature/5-gen-dtos
protoc-gen-protobqを実装した
2 parents 84cb0ca + 8244ad6 commit 5858990

File tree

10 files changed

+426
-60
lines changed

10 files changed

+426
-60
lines changed

Makefile

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
.PHONY: install-tools
22
install-tools:
3+
go install ./cmd/protoc-gen-protobq
34
go install github.com/bufbuild/buf/cmd/buf@v1.47.2
45
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
56

@@ -21,6 +22,6 @@ lint:
2122
# buf breaking --against '.git#branch=$(BREAKING_CHANGE_BASE_BRANCH)'
2223

2324
.PHONY: codegen
24-
codegen:
25-
find . -type f \( -name '*.pb.go' \) -delete
25+
codegen: install-tools
26+
find . -type f \( -name '*.pb.go' -or -name '*.protobq.go' \) -delete
2627
buf generate

buf.gen.yaml

+3
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,6 @@ plugins:
88
- remote: buf.build/protocolbuffers/go:v1.35.2
99
out: internal/protobuf
1010
opt: paths=source_relative
11+
- local: protoc-gen-protobq
12+
out: internal/protobuf
13+
opt: paths=source_relative

cmd/protoc-gen-protobq/main.go

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package main
2+
3+
import (
4+
"github.com/averak/protobq/internal"
5+
"google.golang.org/protobuf/compiler/protogen"
6+
)
7+
8+
func main() {
9+
protogen.Options{}.Run(func(plugin *protogen.Plugin) error {
10+
for _, file := range plugin.Files {
11+
if !file.Generate {
12+
continue
13+
}
14+
15+
g := internal.NewCodeGenerator(plugin, file)
16+
if err := g.Gen(); err != nil {
17+
return err
18+
}
19+
}
20+
return nil
21+
})
22+
}

internal/codegen.go

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package internal
2+
3+
import (
4+
"runtime/debug"
5+
6+
"github.com/averak/protobq/internal/protobuf/protobq"
7+
"google.golang.org/protobuf/compiler/protogen"
8+
"google.golang.org/protobuf/proto"
9+
)
10+
11+
//goland:noinspection GoSnakeCaseUsage
12+
var (
13+
timeIdents = struct {
14+
Duration protogen.GoIdent
15+
}{
16+
Duration: protogen.GoImportPath("time").Ident("Duration"),
17+
}
18+
protoIdents = struct {
19+
GetExtension protogen.GoIdent
20+
}{
21+
GetExtension: protogen.GoImportPath("google.golang.org/protobuf/proto").Ident("GetExtension"),
22+
}
23+
internalIdents = struct {
24+
MaterializedView protogen.GoIdent
25+
E_MaterializedView protogen.GoIdent
26+
}{
27+
MaterializedView: protogen.GoImportPath("github.com/averak/protobq/internal/protobuf/protobq").Ident("MaterializedView"),
28+
E_MaterializedView: protogen.GoImportPath("github.com/averak/protobq/internal/protobuf/protobq").Ident("E_MaterializedView"),
29+
}
30+
protobqIdents = struct {
31+
MaterializedView protogen.GoIdent
32+
MaterializedViewOptions protogen.GoIdent
33+
}{
34+
MaterializedView: protogen.GoImportPath("github.com/averak/protobq").Ident("MaterializedView"),
35+
MaterializedViewOptions: protogen.GoImportPath("github.com/averak/protobq").Ident("MaterializedViewOptions"),
36+
}
37+
)
38+
39+
type CodeGenerator struct {
40+
plugin *protogen.Plugin
41+
file *protogen.File
42+
}
43+
44+
func NewCodeGenerator(plugin *protogen.Plugin, file *protogen.File) *CodeGenerator {
45+
return &CodeGenerator{
46+
plugin: plugin,
47+
file: file,
48+
}
49+
}
50+
51+
func (g CodeGenerator) Gen() error {
52+
if !g.shouldGenerate() {
53+
return nil
54+
}
55+
56+
filename := g.file.GeneratedFilenamePrefix + ".protobq.go"
57+
gf := g.plugin.NewGeneratedFile(filename, g.file.GoImportPath)
58+
59+
{ // generate file header
60+
info, _ := debug.ReadBuildInfo()
61+
gf.P("// Code generated by ", info.Path, ". DO NOT EDIT.")
62+
gf.P("// source: ", g.file.Desc.Path())
63+
gf.P()
64+
gf.P("package ", g.file.GoPackageName)
65+
gf.P()
66+
}
67+
{ // generate materialized view schema
68+
for _, msg := range g.file.Messages {
69+
if !g.isMaterializedViewSchema(msg) {
70+
continue
71+
}
72+
73+
gf.P("var _ ", protobqIdents.MaterializedView, " = (*", msg.GoIdent.GoName, ")(nil)")
74+
gf.P()
75+
gf.P("func (mv *", msg.GoIdent.GoName, ") Options() ", protobqIdents.MaterializedViewOptions, " {")
76+
gf.P(" ext, _ := ", protoIdents.GetExtension, "(mv.ProtoReflect().Descriptor().Options(), ", internalIdents.E_MaterializedView, ").(*", internalIdents.MaterializedView, ")")
77+
gf.P(" return ", protobqIdents.MaterializedViewOptions, "{")
78+
gf.P(" EnableRefresh: ext.GetEnableRefresh(),")
79+
gf.P(" RefreshInterval: ", timeIdents.Duration, "(ext.GetRefreshIntervalMinutes()) * time.Minute,")
80+
gf.P(" }")
81+
gf.P("}")
82+
gf.P()
83+
}
84+
}
85+
return nil
86+
}
87+
88+
func (g CodeGenerator) shouldGenerate() bool {
89+
for _, msg := range g.file.Messages {
90+
if g.isMaterializedViewSchema(msg) {
91+
return true
92+
}
93+
}
94+
return false
95+
}
96+
97+
func (g CodeGenerator) isMaterializedViewSchema(msg *protogen.Message) bool {
98+
opts := msg.Desc.Options()
99+
if opts == nil {
100+
return false
101+
}
102+
103+
ext, ok := proto.GetExtension(opts, protobq.E_MaterializedView).(*protobq.MaterializedView)
104+
if !ok {
105+
return false
106+
}
107+
return ext.GetIsMaterializedView()
108+
}

internal/protobuf/example/example.pb.go

+165
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/protobuf/example/example.protobq.go

+21
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)