Skip to content

Commit 00ed579

Browse files
committed
refs #5 codegenを実装した
1 parent 84cb0ca commit 00ed579

File tree

10 files changed

+420
-60
lines changed

10 files changed

+420
-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

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
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+
MaterializedViewOptions protogen.GoIdent
32+
}{
33+
MaterializedViewOptions: protogen.GoImportPath("github.com/averak/protobq").Ident("MaterializedViewOptions"),
34+
}
35+
)
36+
37+
type CodeGenerator struct {
38+
plugin *protogen.Plugin
39+
file *protogen.File
40+
}
41+
42+
func NewCodeGenerator(plugin *protogen.Plugin, file *protogen.File) *CodeGenerator {
43+
return &CodeGenerator{
44+
plugin: plugin,
45+
file: file,
46+
}
47+
}
48+
49+
func (g CodeGenerator) Gen() error {
50+
if !g.shouldGenerate() {
51+
return nil
52+
}
53+
54+
filename := g.file.GeneratedFilenamePrefix + ".protobq.go"
55+
gf := g.plugin.NewGeneratedFile(filename, g.file.GoImportPath)
56+
57+
{ // generate file header
58+
info, _ := debug.ReadBuildInfo()
59+
gf.P("// Code generated by ", info.Path, ". DO NOT EDIT.")
60+
gf.P("// source: ", g.file.Desc.Path())
61+
gf.P()
62+
gf.P("package ", g.file.GoPackageName)
63+
gf.P()
64+
}
65+
{ // generate materialized view schema
66+
for _, msg := range g.file.Messages {
67+
if !g.isMaterializedViewSchema(msg) {
68+
continue
69+
}
70+
71+
gf.P("func (mv *", msg.GoIdent.GoName, ") Options() ", protobqIdents.MaterializedViewOptions, " {")
72+
gf.P(" ext, _ := ", protoIdents.GetExtension, "(mv.ProtoReflect().Descriptor().Options(), ", internalIdents.E_MaterializedView, ").(*", internalIdents.MaterializedView, ")")
73+
gf.P(" return ", protobqIdents.MaterializedViewOptions, "{")
74+
gf.P(" EnableRefresh: ext.GetEnableRefresh(),")
75+
gf.P(" RefreshInterval: ", timeIdents.Duration, "(ext.GetRefreshIntervalMinutes()) * time.Minute,")
76+
gf.P(" }")
77+
gf.P("}")
78+
gf.P()
79+
}
80+
}
81+
return nil
82+
}
83+
84+
func (g CodeGenerator) shouldGenerate() bool {
85+
for _, msg := range g.file.Messages {
86+
if g.isMaterializedViewSchema(msg) {
87+
return true
88+
}
89+
}
90+
return false
91+
}
92+
93+
func (g CodeGenerator) isMaterializedViewSchema(msg *protogen.Message) bool {
94+
opts := msg.Desc.Options()
95+
if opts == nil {
96+
return false
97+
}
98+
99+
ext, ok := proto.GetExtension(opts, protobq.E_MaterializedView).(*protobq.MaterializedView)
100+
if !ok {
101+
return false
102+
}
103+
return ext.GetIsMaterializedView()
104+
}

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

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

0 commit comments

Comments
 (0)