...
1 package genaip
2
3 import (
4 "fmt"
5
6 "google.golang.org/genproto/googleapis/api/annotations"
7 "google.golang.org/protobuf/compiler/protogen"
8 "google.golang.org/protobuf/proto"
9 "google.golang.org/protobuf/reflect/protoreflect"
10 "google.golang.org/protobuf/reflect/protoregistry"
11 )
12
13
14 const PluginName = "protoc-gen-go-aip"
15
16 const generatedFilenameSuffix = "_aip.go"
17
18 type Config struct {
19 IncludeResourceDefinitions bool
20 }
21
22
23 func Run(gen *protogen.Plugin, config Config) error {
24 var files protoregistry.Files
25 for _, file := range gen.Files {
26 if err := files.RegisterFile(file.Desc); err != nil {
27 return err
28 }
29 }
30 for _, file := range gen.Files {
31 file := file
32 if !file.Generate {
33 continue
34 }
35 g := newGeneratedFile(gen, file)
36 g.Skip()
37 var rangeErr error
38 rangeResourcesInFile(
39 file.Desc,
40 func(resource *annotations.ResourceDescriptor, extension protoreflect.ExtensionType) bool {
41 if !config.IncludeResourceDefinitions && extension == annotations.E_ResourceDefinition {
42 return true
43 }
44 g.Unskip()
45 if err := (resourceNameCodeGenerator{
46 resource: resource,
47 files: &files,
48 file: file,
49 }).GenerateCode(g); err != nil {
50 rangeErr = err
51 return false
52 }
53 return true
54 },
55 )
56 if rangeErr != nil {
57 return rangeErr
58 }
59 }
60 return nil
61 }
62
63 func newGeneratedFile(gen *protogen.Plugin, file *protogen.File) *protogen.GeneratedFile {
64 g := gen.NewGeneratedFile(file.GeneratedFilenamePrefix+generatedFilenameSuffix, file.GoImportPath)
65 g.P("// Code generated by ", PluginName, ". DO NOT EDIT.")
66 g.P("//")
67 g.P("// versions:")
68 g.P("// \t", PluginName, " ", PluginVersion)
69 g.P("// \tprotoc ", getProtocVersion(gen))
70 g.P("// source: ", file.Desc.Path())
71 g.P()
72 g.P("package ", file.GoPackageName)
73 return g
74 }
75
76 func getProtocVersion(gen *protogen.Plugin) string {
77 if v := gen.Request.GetCompilerVersion(); v != nil {
78 return fmt.Sprintf("v%v.%v.%v", v.GetMajor(), v.GetMinor(), v.GetPatch())
79 }
80 return "(unknown)"
81 }
82
83 func rangeResourcesInFile(
84 file protoreflect.FileDescriptor,
85 fn func(resource *annotations.ResourceDescriptor, extension protoreflect.ExtensionType) bool,
86 ) {
87 for _, resource := range proto.GetExtension(
88 file.Options(), annotations.E_ResourceDefinition,
89 ).([]*annotations.ResourceDescriptor) {
90 if !fn(resource, annotations.E_ResourceDefinition) {
91 return
92 }
93 }
94 for i := 0; i < file.Messages().Len(); i++ {
95 resource := proto.GetExtension(
96 file.Messages().Get(i).Options(), annotations.E_Resource,
97 ).(*annotations.ResourceDescriptor)
98 if resource == nil {
99 continue
100 }
101 if !fn(resource, annotations.E_Resource) {
102 return
103 }
104 }
105 }
106
View as plain text