@@ -18,9 +18,13 @@ import (
1818 "golang.org/x/tools/go/ast/astutil"
1919 "google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo"
2020 "google.golang.org/protobuf/compiler/protogen"
21+ "google.golang.org/protobuf/types/descriptorpb"
2122 "google.golang.org/protobuf/types/pluginpb"
2223
24+ "github.com/golang/protobuf/proto"
25+
2326 "github.com/alta/protopatch/lint"
27+ "github.com/alta/protopatch/patch/gopb"
2428 "github.com/alta/protopatch/patch/ident"
2529)
2630
@@ -33,56 +37,166 @@ import (
3337// - (go.enum).name overrides the name of an enum type.
3438// - (go.value).name overrides the name of an enum value.
3539type Patcher struct {
36- gen * protogen.Plugin
37- fset * token.FileSet
38- filesByName map [string ]* ast.File
39- info * types.Info
40- packages []* Package
41- packagesByPath map [string ]* Package
42- packagesByName map [string ]* Package
43- renames map [protogen.GoIdent ]string
44- typeRenames map [protogen.GoIdent ]string
45- valueRenames map [protogen.GoIdent ]string
46- fieldRenames map [protogen.GoIdent ]string
47- methodRenames map [protogen.GoIdent ]string
48- objectRenames map [types.Object ]string
49- tags map [protogen.GoIdent ]string
50- fieldTags map [types.Object ]string
51- embeds map [protogen.GoIdent ]string
52- fieldEmbeds map [types.Object ]string
53- types map [protogen.GoIdent ]string
54- fieldTypes map [types.Object ]string
40+ gen * protogen.Plugin
41+ fset * token.FileSet
42+ filesByName map [string ]* ast.File
43+ info * types.Info
44+ packages []* Package
45+ packagesByPath map [string ]* Package
46+ packagesByName map [string ]* Package
47+ renames map [protogen.GoIdent ]string
48+ typeRenames map [protogen.GoIdent ]string
49+ valueRenames map [protogen.GoIdent ]string
50+ fieldRenames map [protogen.GoIdent ]string
51+ methodRenames map [protogen.GoIdent ]string
52+ objectRenames map [types.Object ]string
53+ tags map [protogen.GoIdent ]string
54+ fieldTags map [types.Object ]string
55+ embeds map [protogen.GoIdent ]string
56+ fieldEmbeds map [types.Object ]string
57+ types map [protogen.GoIdent ]string
58+ fieldTypes map [types.Object ]string
59+ processedMessages map [protogen.GoIdent ]bool
5560}
5661
5762// NewPatcher returns an initialized Patcher for gen.
5863func NewPatcher (gen * protogen.Plugin ) (* Patcher , error ) {
5964 p := & Patcher {
60- gen : gen ,
61- packagesByPath : make (map [string ]* Package ),
62- packagesByName : make (map [string ]* Package ),
63- renames : make (map [protogen.GoIdent ]string ),
64- typeRenames : make (map [protogen.GoIdent ]string ),
65- valueRenames : make (map [protogen.GoIdent ]string ),
66- fieldRenames : make (map [protogen.GoIdent ]string ),
67- methodRenames : make (map [protogen.GoIdent ]string ),
68- objectRenames : make (map [types.Object ]string ),
69- tags : make (map [protogen.GoIdent ]string ),
70- fieldTags : make (map [types.Object ]string ),
71- embeds : make (map [protogen.GoIdent ]string ),
72- fieldEmbeds : make (map [types.Object ]string ),
73- types : make (map [protogen.GoIdent ]string ),
74- fieldTypes : make (map [types.Object ]string ),
65+ gen : gen ,
66+ packagesByPath : make (map [string ]* Package ),
67+ packagesByName : make (map [string ]* Package ),
68+ renames : make (map [protogen.GoIdent ]string ),
69+ typeRenames : make (map [protogen.GoIdent ]string ),
70+ valueRenames : make (map [protogen.GoIdent ]string ),
71+ fieldRenames : make (map [protogen.GoIdent ]string ),
72+ methodRenames : make (map [protogen.GoIdent ]string ),
73+ objectRenames : make (map [types.Object ]string ),
74+ tags : make (map [protogen.GoIdent ]string ),
75+ fieldTags : make (map [types.Object ]string ),
76+ embeds : make (map [protogen.GoIdent ]string ),
77+ fieldEmbeds : make (map [types.Object ]string ),
78+ types : make (map [protogen.GoIdent ]string ),
79+ fieldTypes : make (map [types.Object ]string ),
80+ processedMessages : make (map [protogen.GoIdent ]bool ),
7581 }
7682 return p , p .scan ()
7783}
7884
85+ func getExtensionDesc (pb proto.Message , extname string ) (* proto.ExtensionDesc , error ) {
86+ desc := proto .RegisteredExtensions (pb )
87+ for _ , d := range desc {
88+ if d .Name == extname {
89+ return d , nil
90+ }
91+ }
92+ return nil , fmt .Errorf ("ExtensionDesc not found" )
93+ }
94+
95+ func getExtension (pb proto.Message , extname string ) (interface {}, error ) {
96+ d , err := getExtensionDesc (pb , extname )
97+ if err != nil {
98+ return nil , err
99+ }
100+ e , err := proto .GetExtension (pb , d )
101+ if err != nil {
102+ return nil , err
103+ }
104+ return e , err
105+ }
106+
79107func (p * Patcher ) scan () error {
80108 for _ , f := range p .gen .Files {
81109 p .scanFile (f )
82110 }
111+ for _ , f := range p .gen .Request .ProtoFile {
112+ found := false
113+ mident := protogen.GoIdent {GoName : "" , GoImportPath : "" }
114+ fident := protogen.GoIdent {GoName : "" , GoImportPath : "" }
115+ for _ , genFile := range p .gen .Files {
116+ if * f .Name == genFile .Desc .Path () {
117+ found = true
118+ mident = protogen.GoIdent {GoName : "" , GoImportPath : genFile .GoImportPath }
119+ fident = protogen.GoIdent {GoName : "" , GoImportPath : genFile .GoImportPath }
120+ break
121+ }
122+ }
123+ if ! found {
124+ panic ("Not found" )
125+ }
126+ for _ , m := range f .MessageType {
127+ mident .GoName = * m .Name
128+ if _ , ok := p .processedMessages [mident ]; ok {
129+ continue
130+ }
131+ nmident := protogen.GoIdent {GoName : "" , GoImportPath : mident .GoImportPath }
132+ nfident := protogen.GoIdent {GoName : "" , GoImportPath : mident .GoImportPath }
133+ for _ , nestedMsgType := range m .NestedType {
134+ nmident .GoName = mident .GoName + "_" + * nestedMsgType .Name
135+ for _ , msgfield := range nestedMsgType .Field {
136+ nfident .GoName = * msgfield .Name
137+ p .scanProtoField (nmident , nfident , msgfield )
138+ }
139+ }
140+
141+ for _ , msgfield := range m .Field {
142+ fident .GoName = * msgfield .Name
143+ p .scanProtoField (mident , fident , msgfield )
144+ }
145+ }
146+ }
147+
83148 return nil
84149}
85150
151+ func (p * Patcher ) scanProtoField (mident protogen.GoIdent , fident protogen.GoIdent , f * descriptorpb.FieldDescriptorProto ) {
152+ //m := f.Parent
153+ //o := f.Oneof
154+
155+ if f .TypeName == nil {
156+ log .Printf ("Typename not set" )
157+ return
158+ }
159+ fi , err := getExtension (f .GetOptions (), "go.field" )
160+ if err != nil {
161+ log .Printf ("go.field extension not found" , err )
162+ return
163+ }
164+ opts := fi .(* gopb.Options )
165+
166+ log .Printf ("Parent Message %v (%v), opts %v" , * f .Name , * f .TypeName , opts )
167+ // Embed field ?
168+ embed := false
169+ newName := ""
170+ if opts .GetEmbed () {
171+ switch {
172+ default :
173+ embed = true
174+ log .Printf ("Embed Set %v " , * f .Name , * f .TypeName )
175+ splitStrings := strings .Split ((* f .TypeName )[1 :], "." )
176+ newName = splitStrings [len (splitStrings )- 1 ]
177+ }
178+ }
179+ if newName != "" {
180+ if false {
181+ p .RenameType (fident , p .nameFor (mident )+ "_" + newName ) // Oneof wrapper struct
182+ p .RenameField (ident .WithChild (fident , fident .GoName ), newName , false ) // Oneof wrapper field (not embeddable)
183+ } else {
184+ p .RenameField (ident .WithChild (mident , fident .GoName ), newName , embed ) // Field
185+ childID := ident .WithChild (mident , fident .GoName )
186+ log .Printf ("child %v parent %v" , childID , mident .GoName )
187+ }
188+ p .RenameMethod (ident .WithChild (mident , "Get" + fident .GoName ), "Get" + newName ) // Getter
189+ } else {
190+ p .RenameField (ident .WithChild (mident , fident .GoName ), newName , embed ) // Field
191+ }
192+
193+ tags := opts .GetTags ()
194+ if tags != "" {
195+ log .Printf ("Tags Set identifier %v %v %v" , ident .WithChild (mident , fident .GoName ), * f .Name , * f .TypeName , tags )
196+ p .Tag (ident .WithChild (mident , fident .GoName ), tags ) // Field tags
197+ }
198+ }
199+
86200func (p * Patcher ) scanFile (f * protogen.File ) {
87201 log .Printf ("\n Scan proto:\t %s" , f .Desc .Path ())
88202
@@ -190,6 +304,7 @@ func (p *Patcher) scanMessage(m *protogen.Message, parent *protogen.Message) {
190304 opts := messageOptions (m )
191305 lints := fileLintOptions (m .Desc )
192306
307+ p .processedMessages [m .GoIdent ] = true
193308 // Rename message?
194309 newName := opts .GetName ()
195310 if newName == "" && parent != nil && p .isRenamed (parent .GoIdent ) {
0 commit comments