github.com/songzhibin97/gkit@v1.2.13/parser/parse_pb/model.go (about) 1 package parse_pb 2 3 import ( 4 "fmt" 5 "strconv" 6 "strings" 7 "text/template" 8 9 "github.com/emicklei/proto" 10 "github.com/songzhibin97/gkit/cache/buffer" 11 "github.com/songzhibin97/gkit/options" 12 ) 13 14 type ( 15 ParseMessage func(m *Message) 16 ParseService func(server *Server) 17 // CheckFunc func(p *PbParseGo) error 18 ) 19 20 type PbParseGo struct { 21 PkgName string // PkgName: 包名 22 FilePath string // FilePath: 文件的路径 23 Server map[string]*Server // Server: 服务器信息 24 Message map[string]*Message // Message: 消息信息 25 Note map[string]*Note // Note: 注释信息 26 Enums map[string]*Enum // Enums: 枚举类型 27 //Server []*Server // Server: 解析出来function的信息 28 //Message []*Message // Message: 解析出struct的信息 29 //Note []*Note // Note: 其他注释 30 //Enums []*Enum // Enum: 解析出enum的信息 31 Metas map[string]string // Metas: 其他元信息 32 ParseMessages []ParseMessage 33 ParseServices []ParseService 34 } 35 36 // CreatePbParseGo 创建 PbParseGo 37 func CreatePbParseGo() *PbParseGo { 38 return &PbParseGo{} 39 } 40 41 type Note struct { 42 IsUse bool // 判断作用域, 如果是 struct中 或者 func中代表已经使用 43 *proto.Comment 44 } 45 46 type Server struct { 47 Offset int // Offset: 函数起始位置 48 Name string // Name: 函数名 49 ServerName string // ServerName: server name 通过 parseFunc 绑定 50 Method string // Method: method 通过 parseFunc 绑定 51 Router string // Router: router 通过 parseFunc 绑定 52 InputParameter string // InputParameter: 入参 53 OutputParameter string // OutputParameter: 出参 54 Doc []string // Doc: 函数注释信息,可以通过自定义的 parseFunc 去进行解析 55 Notes []*proto.Comment // Notes: 函数中的注释信息,用于埋点打桩 56 } 57 58 // CreateServer 创建Server 59 func CreateServer(name string, offset int, inputParameter string, outputParameter string) *Server { 60 return &Server{ 61 Offset: offset, 62 Name: name, 63 InputParameter: inputParameter, 64 OutputParameter: outputParameter, 65 } 66 } 67 68 // Message Message对应struct 69 type Message struct { 70 Offset int // Offset: message起始点 71 Name string // Name: struct name 72 Files []*File // Files: 字段信息 73 Notes []*proto.Comment // Notes: struct的注释信息,用于埋点打桩 74 } 75 76 func CreateMessage(name string, offset int) *Message { 77 return &Message{ 78 Name: name, 79 Offset: offset, 80 } 81 } 82 83 func (m *Message) AddFiles(files ...*File) { 84 m.Files = append(m.Files, files...) 85 } 86 87 // File 字段信息 88 type File struct { 89 Name string // Name: 字段名 90 TypeGo string // TypeGo: 字段的原始类型 91 TypePB string // TypePB: 字段在proto中的类型 92 } 93 94 // CreateFile 创建字段信息 95 func CreateFile(name string, tGo string, tPb string) *File { 96 if name != "" { 97 name = strings.ToTitle(string(name[0])) + name[1:] 98 } 99 100 return &File{ 101 Name: name, 102 TypeGo: tGo, 103 TypePB: tPb, 104 } 105 } 106 107 // addParseStruct 添加自定义解析struct内容 108 func (p *PbParseGo) addParseMessage(parseMessage ...ParseMessage) { 109 p.ParseMessages = append(p.ParseMessages, parseMessage...) 110 } 111 112 // addParseFunc 添加自定义解析Func 113 func (p *PbParseGo) addParseService(parseService ...ParseService) { 114 p.ParseServices = append(p.ParseServices, parseService...) 115 } 116 117 // AddServers 添加server信息 118 func (p *PbParseGo) AddServers(servers ...*Server) { 119 if p.Server == nil { 120 p.Server = make(map[string]*Server) 121 } 122 for _, server := range servers { 123 p.Server[server.Name] = server 124 } 125 } 126 127 // AddMessages 添加message信息 128 func (p *PbParseGo) AddMessages(messages ...*Message) { 129 if p.Message == nil { 130 p.Message = make(map[string]*Message) 131 } 132 for _, message := range messages { 133 p.Message[message.Name] = message 134 } 135 } 136 137 func (p *PbParseGo) AddNode(nodes ...*Note) { 138 if p.Note == nil { 139 p.Note = make(map[string]*Note) 140 } 141 for _, node := range nodes { 142 p.Note[strconv.Itoa(node.Position.Offset)] = node 143 } 144 } 145 146 // AddEnum 添加枚举类型 147 func (p *PbParseGo) AddEnum(enums ...*Enum) { 148 if p.Enums == nil { 149 p.Enums = make(map[string]*Enum) 150 } 151 for _, e := range enums { 152 p.Enums[e.Name] = e 153 } 154 } 155 156 type Enum struct { 157 Offset int // Offset: 函数起始位置 158 Name string // Name: 类型名称 159 Elements map[string]*EnumElement 160 } 161 162 // CreateEnum 创建枚举类型 163 func CreateEnum(name string, offset int) *Enum { 164 return &Enum{ 165 Name: name, 166 Offset: offset, 167 } 168 } 169 170 type EnumElement struct { 171 Offset int // Offset: 函数起始位置 172 Name string // Name: 类型名称 173 Index int // Index: 索引 174 } 175 176 func (e *Enum) AddElem(name string, offset int, index int) { 177 if e.Elements == nil { 178 e.Elements = make(map[string]*EnumElement) 179 } 180 e.Elements[name] = &EnumElement{ 181 Name: name, 182 Offset: offset, 183 Index: index, 184 } 185 } 186 187 func (p *PbParseGo) parseMessage(ms *proto.Message, prefix string) { 188 ret := CreateMessage(prefix+ms.Name, ms.Position.Offset) 189 // note 190 if ms.Comment != nil { 191 ret.Notes = append(ret.Notes, ms.Comment) 192 } 193 for _, element := range ms.Elements { 194 switch v := element.(type) { 195 case *proto.NormalField: 196 // 正常的字段 197 if v.Repeated { 198 ret.AddFiles(CreateFile(v.Name, fmt.Sprintf("[]%s", PbTypeToGo(v.Type)), fmt.Sprintf("require %s", v.Type))) 199 } else { 200 ret.AddFiles(CreateFile(v.Name, PbTypeToGo(v.Type), v.Type)) 201 } 202 203 case *proto.MapField: 204 keyType := v.KeyType 205 valueType := v.Field.Type 206 ret.AddFiles(CreateFile(v.Field.Name, fmt.Sprintf("map[%s]%s", 207 PbTypeToGo(keyType), PbTypeToGo(valueType)), fmt.Sprintf("<%s,%s>", keyType, valueType))) 208 case *proto.Message: 209 p.parseMessage(v, ms.Name+prefix) 210 case *proto.Enum: 211 ret.AddFiles(CreateFile(v.Name, v.Name, "enum")) 212 p.parseEnum(v, ms.Name+prefix) 213 } 214 } 215 for _, f := range p.ParseMessages { 216 f(ret) 217 } 218 p.AddMessages(ret) 219 } 220 221 func (p *PbParseGo) parseService(sv *proto.Service) { 222 for _, element := range sv.Elements { 223 switch v := element.(type) { 224 case *proto.RPC: 225 funcName := v.Name 226 reqType := v.RequestType 227 retType := v.ReturnsType 228 server := CreateServer(funcName, v.Position.Offset, PbTypeToGo(reqType), PbTypeToGo(retType)) 229 if sv.Comment != nil { 230 server.Notes = append(server.Notes, sv.Comment) 231 for _, doc := range sv.Comment.Lines { 232 server.Doc = append(server.Doc, doc) 233 } 234 for _, f := range p.ParseServices { 235 f(server) 236 } 237 } 238 p.AddServers(server) 239 } 240 } 241 } 242 243 func (p *PbParseGo) PackageName() string { 244 return p.PkgName 245 } 246 247 func (p *PbParseGo) Generate() string { 248 temp := `package {{.PkgName}} 249 // type{{range .Enums}} 250 type {{.Name}} int32 251 {{ $Type := .Name}}const({{range $index, $Elem := .Elements}} 252 {{$Elem.Name}} {{ $Type }} = {{$Elem.Index}}{{end}} 253 ) 254 {{end}} 255 256 // struct{{range .Message}} 257 type {{.Name}} struct { 258 {{range $index, $Message :=.Files}} {{$Message.Name}} {{$Message.TypeGo}} 259 {{end}}} 260 {{end}} 261 262 // function{{range .Server}} 263 func {{.Name }} ({{.InputParameter}}) {{.OutputParameter}} { 264 panic("Realize Me") 265 } 266 {{end}} 267 ` 268 tmpl, err := template.New("GeneratePB").Funcs(template.FuncMap{"addOne": addOne}).Parse(temp) 269 if err != nil { 270 return "" 271 } 272 b := buffer.NewIoBuffer(1024) 273 err = tmpl.Execute(b, p) 274 if err != nil { 275 return "" 276 } 277 return b.String() 278 } 279 280 func (p *PbParseGo) parseEnum(sv *proto.Enum, prefix string) { 281 282 enum := CreateEnum(prefix+sv.Name, sv.Position.Offset) 283 for _, element := range sv.Elements { 284 switch v := element.(type) { 285 case *proto.EnumField: 286 enum.AddElem(v.Name, v.Position.Offset, v.Integer) 287 } 288 } 289 p.AddEnum(enum) 290 } 291 292 // AddParseMessage 添加自定义解析message 293 func AddParseMessage(parseMessages ...ParseMessage) options.Option { 294 return func(o interface{}) { 295 o.(*PbParseGo).addParseMessage(parseMessages...) 296 } 297 } 298 299 // AddParseService 添加自定义解析service 300 func AddParseService(parseServices ...ParseService) options.Option { 301 return func(o interface{}) { 302 o.(*PbParseGo).addParseService(parseServices...) 303 } 304 }