@@ -3,6 +3,7 @@ package main
33import (
44 "errors"
55 "fmt"
6+ "regexp"
67 "strings"
78
89 "google.golang.org/protobuf/types/descriptorpb"
@@ -33,44 +34,77 @@ func (b *contentBuilder) build(protoFile *descriptorpb.FileDescriptorProto) (str
3334}
3435
3536func (b * contentBuilder ) buildMessage (message * descriptorpb.DescriptorProto , level int ) {
36- b .output .WriteString (buildIndent (level ) + "message " + message .GetName () + " {\n " )
37+ fmt .Fprintf (b .output , "%smessage %s {\n " , buildIndent (level ), message .GetName ())
38+ debts := []string (nil )
3739 for _ , field := range message .GetField () {
38- b .buildField (field , level + 1 )
40+ debts = append ( debts , b .buildField (field , level + 1 ) )
3941 }
40- b .output .WriteString (buildIndent (level ) + "}\n " )
42+ b .payDebts (debts , level + 1 )
43+ fmt .Fprintf (b .output , "%s}\n " , buildIndent (level ))
4144}
4245
43- func (b * contentBuilder ) buildField (field * descriptorpb.FieldDescriptorProto , level int ) {
44- fieldType := strings .ToLower (strings .TrimPrefix (field .GetType ().String (), "TYPE_" ))
45- if field .GetType () == descriptorpb .FieldDescriptorProto_TYPE_MESSAGE {
46- fieldType = b .buildFieldType (field .GetTypeName (), level )
47- }
48- b .output .WriteString (buildIndent (level ))
49- b .buildFieldLabel (field .GetLabel ())
50- fmt .Fprintf (b .output , "%s %s = %d;\n " , fieldType , field .GetName (), field .GetNumber ())
46+ func (b * contentBuilder ) buildField (field * descriptorpb.FieldDescriptorProto , level int ) string {
47+ fieldType , debt := b .getFieldType (field )
48+ fmt .Fprintf (b .output , "%s%s%s %s = %d;\n " ,
49+ buildIndent (level ),
50+ b .getLabelPrefix (field .GetLabel ()),
51+ fieldType ,
52+ field .GetName (),
53+ field .GetNumber (),
54+ )
55+ return debt
5156}
5257
53- func (b * contentBuilder ) buildFieldType (typeName string , level int ) string {
54- if b .messageEncoding == "json" {
55- if typeName , ok := wktMapping [typeName ]; ok {
56- return typeName
57- }
58+ func (b * contentBuilder ) getFieldType (field * descriptorpb.FieldDescriptorProto ) (string , string ) {
59+ if field .GetType () != descriptorpb .FieldDescriptorProto_TYPE_MESSAGE {
60+ return strings .ToLower (strings .TrimPrefix (field .GetType ().String (), "TYPE_" )), ""
5861 }
59-
60- b .output .WriteString ("\n " )
61- b .buildMessage (b .messageTypes [typeName ], level )
62- b .output .WriteString ("\n " )
63- return typeName [strings .LastIndexByte (typeName , '.' )+ 1 :]
62+ fullMessageName := field .GetTypeName ()
63+ wkt := wktMapping [fullMessageName ]
64+ if b .messageEncoding == "json" && wkt != "" {
65+ return wkt , ""
66+ }
67+ return getLocalName (fullMessageName ), fullMessageName
6468}
6569
66- func (b * contentBuilder ) buildFieldLabel (label descriptorpb.FieldDescriptorProto_Label ) {
70+ func (b * contentBuilder ) getLabelPrefix (label descriptorpb.FieldDescriptorProto_Label ) string {
6771 if label == descriptorpb .FieldDescriptorProto_LABEL_REPEATED {
68- b .output .WriteString ("repeated " )
69- } else if b .schemaSyntax == "proto2" {
70- b .output .WriteString (strings .ToLower (strings .TrimPrefix (label .String (), "LABEL_" )) + " " )
72+ return "repeated "
73+ }
74+ if b .schemaSyntax == "proto2" {
75+ return strings .ToLower (strings .TrimPrefix (label .String (), "LABEL_" )) + " "
7176 }
77+ return ""
78+ }
79+
80+ func (b * contentBuilder ) payDebts (debts []string , level int ) {
81+ payedDebts := make (map [string ]bool )
82+ for _ , debt := range debts {
83+ if debt != "" && ! payedDebts [debt ] {
84+ b .payDebt (debt , level )
85+ payedDebts [debt ] = true
86+ }
87+ }
88+ }
89+
90+ func (b * contentBuilder ) payDebt (debt string , level int ) {
91+ message := b .messageTypes [debt ]
92+ defer func (originalName * string ) { message .Name = originalName }(message .Name )
93+ localName := getLocalName (debt )
94+ message .Name = & localName
95+ b .output .WriteString ("\n " )
96+ b .buildMessage (message , level )
7297}
7398
7499func buildIndent (level int ) string {
75100 return strings .Repeat (" " , level )
76101}
102+
103+ var localNamePattern = regexp .MustCompile (`\..` )
104+
105+ func getLocalName (fullMessageName string ) string {
106+ return localNamePattern .ReplaceAllStringFunc (
107+ fullMessageName ,
108+ func (s string ) string { return strings .ToUpper (s [1 :]) },
109+ )
110+ }
0 commit comments