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  }