Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 1 | // Copyright 2018 The Go Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style |
| 3 | // license that can be found in the LICENSE file. |
| 4 | |
| 5 | package internal_gengo |
| 6 | |
| 7 | import ( |
| 8 | "fmt" |
| 9 | "math" |
Joe Tsai | 24ceb2b | 2018-12-04 22:53:56 -0800 | [diff] [blame] | 10 | "os" |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 11 | "reflect" |
| 12 | "strconv" |
| 13 | "strings" |
| 14 | |
| 15 | "github.com/golang/protobuf/v2/protogen" |
| 16 | "github.com/golang/protobuf/v2/reflect/protoreflect" |
| 17 | ) |
| 18 | |
| 19 | // TODO: Remove this flag. |
Joe Tsai | 24ceb2b | 2018-12-04 22:53:56 -0800 | [diff] [blame] | 20 | // Remember to remove the copy in internal/protogen/goldentest. |
| 21 | var enableReflectFlag = os.Getenv("PROTOC_GEN_GO_ENABLE_REFLECT") != "" |
| 22 | |
| 23 | func enableReflection(f *protogen.File) bool { |
| 24 | return enableReflectFlag || isDescriptor(f) |
| 25 | } |
| 26 | |
| 27 | // TODO: Remove special-casing for descriptor proto. |
| 28 | func isDescriptor(f *protogen.File) bool { |
| 29 | return f.Desc.Path() == "google/protobuf/descriptor.proto" && f.Desc.Package() == "google.protobuf" |
| 30 | } |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 31 | |
| 32 | // minimumVersion is minimum version of the v2 proto package that is required. |
| 33 | // This is incremented every time the generated code relies on some property |
| 34 | // in the proto package that was introduced in a later version. |
| 35 | const minimumVersion = 0 |
| 36 | |
| 37 | const ( |
| 38 | protoimplPackage = protogen.GoImportPath("github.com/golang/protobuf/v2/runtime/protoimpl") |
| 39 | protoreflectPackage = protogen.GoImportPath("github.com/golang/protobuf/v2/reflect/protoreflect") |
| 40 | prototypePackage = protogen.GoImportPath("github.com/golang/protobuf/v2/reflect/prototype") |
| 41 | ) |
| 42 | |
| 43 | // TODO: Add support for proto options. |
| 44 | |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 45 | func genReflectInitFunction(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo) { |
Joe Tsai | 24ceb2b | 2018-12-04 22:53:56 -0800 | [diff] [blame] | 46 | if !enableReflection(f.File) { |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 47 | return |
| 48 | } |
| 49 | |
Joe Tsai | 9667c48 | 2018-12-05 15:42:52 -0800 | [diff] [blame] | 50 | if len(f.allEnums)+len(f.allMessages)+len(f.allExtensions)+len(f.Services) == 0 { |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 51 | return |
| 52 | } |
| 53 | |
| 54 | g.P("func init() {") |
| 55 | |
| 56 | // TODO: Fix up file imports to reference a protoreflect.FileDescriptor |
| 57 | // in a remote dependency. Since we cannot yet rely on the existence of |
| 58 | // a variable containing the file descriptor, we find a random message or |
| 59 | // enum the package and see if we can ascend to the parent file descriptor. |
| 60 | |
| 61 | fileDescVar := fileDescVarName(f) |
| 62 | enumTypesVar := enumTypesVarName(f) |
| 63 | enumDescsVar := enumDescsVarName(f) |
| 64 | messageTypesVar := messageTypesVarName(f) |
| 65 | messageDescsVar := messageDescsVarName(f) |
| 66 | |
| 67 | // Populate all declarations for messages and enums. |
| 68 | // These are not declared in the literals to avoid an initialization loop. |
| 69 | if enums := f.Enums; len(enums) > 0 { |
Joe Tsai | 9667c48 | 2018-12-05 15:42:52 -0800 | [diff] [blame] | 70 | i := f.allEnumsByPtr[enums[0]] |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 71 | g.P(fileDescVar, ".Enums = ", enumDescsVar, "[", i, ":", i+len(enums), "]") |
| 72 | } |
| 73 | if messages := f.Messages; len(messages) > 0 { |
Joe Tsai | 9667c48 | 2018-12-05 15:42:52 -0800 | [diff] [blame] | 74 | i := f.allMessagesByPtr[messages[0]] |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 75 | g.P(fileDescVar, ".Messages = ", messageDescsVar, "[", i, ":", i+len(messages), "]") |
| 76 | } |
Joe Tsai | 9667c48 | 2018-12-05 15:42:52 -0800 | [diff] [blame] | 77 | for i, message := range f.allMessages { |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 78 | if enums := message.Enums; len(enums) > 0 { |
Joe Tsai | 9667c48 | 2018-12-05 15:42:52 -0800 | [diff] [blame] | 79 | j := f.allEnumsByPtr[enums[0]] |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 80 | g.P(messageDescsVar, "[", i, "].Enums = ", enumDescsVar, "[", j, ":", j+len(enums), "]") |
| 81 | } |
| 82 | if messages := message.Messages; len(messages) > 0 { |
Joe Tsai | 9667c48 | 2018-12-05 15:42:52 -0800 | [diff] [blame] | 83 | j := f.allMessagesByPtr[messages[0]] |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 84 | g.P(messageDescsVar, "[", i, "].Messages = ", messageDescsVar, "[", j, ":", j+len(messages), "]") |
| 85 | } |
| 86 | } |
| 87 | |
| 88 | // Populate all dependencies for messages and enums. |
| 89 | // |
| 90 | // Externally defined enums and messages may or may not support the |
| 91 | // v2 protobuf reflection interfaces. The EnumTypeOf and MessageTypeOf |
| 92 | // helper functions checks for compliance and derives a v2 type from the |
| 93 | // legacy v1 enum or message if necessary. |
Joe Tsai | 9667c48 | 2018-12-05 15:42:52 -0800 | [diff] [blame] | 94 | for i, message := range f.allMessages { |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 95 | for j, field := range message.Fields { |
| 96 | fieldSel := fmt.Sprintf("[%d].Fields[%d]", i, j) |
| 97 | if et := field.EnumType; et != nil { |
Joe Tsai | 9667c48 | 2018-12-05 15:42:52 -0800 | [diff] [blame] | 98 | idx, ok := f.allEnumsByPtr[et] |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 99 | if ok { |
| 100 | // Locally defined enums are found in the type array. |
| 101 | g.P(messageDescsVar, fieldSel, ".EnumType = ", enumTypesVar, "[", idx, "]") |
| 102 | } else { |
| 103 | // Externally defined enums may need special handling. |
| 104 | g.P(messageDescsVar, fieldSel, ".EnumType = ", protoimplPackage.Ident("X"), ".EnumTypeOf(", et.GoIdent, "(0))") |
| 105 | } |
| 106 | } |
| 107 | if mt := field.MessageType; mt != nil { |
Joe Tsai | 9667c48 | 2018-12-05 15:42:52 -0800 | [diff] [blame] | 108 | idx, ok := f.allMessagesByPtr[mt] |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 109 | if ok { |
| 110 | if mt.Desc.IsMapEntry() { |
| 111 | // Map entry types have no Go type generated for them. |
| 112 | g.P(messageDescsVar, fieldSel, ".MessageType = ", messageDescsVar, "[", idx, "].Reference()") |
| 113 | } else { |
| 114 | // Locally defined messages are found in the type array. |
| 115 | g.P(messageDescsVar, fieldSel, ".MessageType = ", messageTypesVar, "[", idx, "].Type") |
| 116 | } |
| 117 | } else { |
| 118 | // Externally defined messages may need special handling. |
| 119 | g.P(messageDescsVar, fieldSel, ".MessageType = ", protoimplPackage.Ident("X"), ".MessageTypeOf((*", mt.GoIdent, ")(nil))") |
| 120 | } |
| 121 | } |
| 122 | } |
| 123 | } |
| 124 | // TODO: Fix up extension dependencies. |
| 125 | // TODO: Fix up method dependencies. |
| 126 | |
| 127 | // Construct the file descriptor. |
| 128 | g.P("var err error") |
| 129 | g.P(f.GoDescriptorIdent, ", err = ", prototypePackage.Ident("NewFile"), "(&", fileDescVarName(f), ")") |
| 130 | g.P("if err != nil { panic(err) }") |
| 131 | |
| 132 | // TODO: Add v2 registration and stop v1 registration in genInitFunction. |
| 133 | |
Joe Tsai | a4cbffe | 2018-12-06 13:01:52 -0800 | [diff] [blame] | 134 | // The descriptor proto needs to register the option types with the |
| 135 | // prototype so that the package can properly handle those option types. |
| 136 | if isDescriptor(f.File) { |
| 137 | for _, m := range f.allMessages { |
| 138 | name := m.GoIdent.GoName |
| 139 | if strings.HasSuffix(name, "Options") { |
| 140 | g.P(prototypePackage.Ident("X"), ".Register", name, "((*", name, ")(nil))") |
| 141 | } |
| 142 | } |
| 143 | } |
| 144 | |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 145 | g.P("}") |
| 146 | } |
| 147 | |
| 148 | func genReflectFileDescriptor(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo) { |
Joe Tsai | 24ceb2b | 2018-12-04 22:53:56 -0800 | [diff] [blame] | 149 | if !enableReflection(f.File) { |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 150 | return |
| 151 | } |
| 152 | |
| 153 | // Emit a static check that enforces a minimum version of the proto package. |
| 154 | g.P("const _ = ", protoimplPackage.Ident("EnforceVersion"), "(", protoimplPackage.Ident("Version"), " - ", minimumVersion, ")") |
| 155 | |
| 156 | g.P("var ", f.GoDescriptorIdent, " ", protoreflectPackage.Ident("FileDescriptor")) |
| 157 | g.P() |
| 158 | |
| 159 | // Generate literal for file descriptor. |
| 160 | fileDescVar := fileDescVarName(f) |
| 161 | g.P("var ", fileDescVar, " = ", prototypePackage.Ident("File"), "{") |
| 162 | g.P("Syntax: ", protoreflectPackage.Ident(f.Desc.Syntax().GoString()), ",") |
| 163 | g.P("Path: ", strconv.Quote(f.Desc.Path()), ",") |
| 164 | g.P("Package: ", strconv.Quote(string(f.Desc.Package())), ",") |
| 165 | if imps := f.Desc.Imports(); imps.Len() > 0 { |
| 166 | g.P("Imports: ", "[]", protoreflectPackage.Ident("FileImport"), "{") |
| 167 | for i := 0; i < imps.Len(); i++ { |
| 168 | imp := imps.Get(i) |
| 169 | path := strconv.Quote(imp.Path()) |
| 170 | pkg := strconv.Quote(string(imp.Package())) |
| 171 | var isPublic, isWeak string |
| 172 | if imp.IsPublic { |
| 173 | isPublic = ", IsPublic: true" |
| 174 | } |
| 175 | if imp.IsWeak { |
| 176 | isWeak = ", IsWeak: true" |
| 177 | } |
| 178 | // NOTE: FileDescriptor may be updated later by init. |
| 179 | g.P("{FileDescriptor: ", prototypePackage.Ident("PlaceholderFile"), "(", path, ", ", pkg, ")", isPublic, isWeak, "},") |
| 180 | } |
| 181 | g.P("},") |
| 182 | } |
| 183 | // NOTE: Messages, Enums, Extensions, and Services are populated by init. |
| 184 | g.P("}") |
| 185 | |
| 186 | // Generate literals for enum descriptors. |
Joe Tsai | 9667c48 | 2018-12-05 15:42:52 -0800 | [diff] [blame] | 187 | if len(f.allEnums) > 0 { |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 188 | enumTypesVar := enumTypesVarName(f) |
| 189 | enumDescsVar := enumDescsVarName(f) |
Joe Tsai | 9667c48 | 2018-12-05 15:42:52 -0800 | [diff] [blame] | 190 | g.P("var ", enumTypesVar, " = [", len(f.allEnums), "]", protoreflectPackage.Ident("EnumType"), "{") |
| 191 | for i, enum := range f.allEnums { |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 192 | g.P(prototypePackage.Ident("GoEnum"), "(") |
| 193 | g.P(enumDescsVar, "[", i, "].Reference(),") |
Damien Neil | a8593ba | 2019-01-08 16:18:07 -0800 | [diff] [blame] | 194 | g.P("func(_ ", protoreflectPackage.Ident("EnumType"), ", n ", protoreflectPackage.Ident("EnumNumber"), ") ", protoreflectPackage.Ident("Enum"), " {") |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 195 | g.P("return ", enum.GoIdent, "(n)") |
| 196 | g.P("},") |
| 197 | g.P("),") |
| 198 | } |
| 199 | g.P("}") |
| 200 | |
Joe Tsai | 9667c48 | 2018-12-05 15:42:52 -0800 | [diff] [blame] | 201 | g.P("var ", enumDescsVar, " = [", len(f.allEnums), "]", prototypePackage.Ident("Enum"), "{") |
| 202 | for _, enum := range f.allEnums { |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 203 | g.P("{") |
| 204 | g.P("Name: ", strconv.Quote(string(enum.Desc.Name())), ",") |
| 205 | g.P("Values: []", prototypePackage.Ident("EnumValue"), "{") |
| 206 | for _, value := range enum.Values { |
| 207 | g.P("{Name: ", strconv.Quote(string(value.Desc.Name())), ", Number: ", value.Desc.Number(), "},") |
| 208 | } |
| 209 | g.P("},") |
Joe Tsai | bce82b8 | 2018-12-06 09:39:03 -0800 | [diff] [blame] | 210 | if resvNames := enum.Desc.ReservedNames(); resvNames.Len() > 0 { |
| 211 | var ss []string |
| 212 | for i := 0; i < resvNames.Len(); i++ { |
| 213 | s := resvNames.Get(i) |
| 214 | ss = append(ss, strconv.Quote(string(s))) |
| 215 | } |
| 216 | g.P("ReservedNames: []", protoreflectPackage.Ident("Name"), "{", strings.Join(ss, ","), "},") |
| 217 | } |
| 218 | if resvRanges := enum.Desc.ReservedRanges(); resvRanges.Len() > 0 { |
| 219 | var ss []string |
| 220 | for i := 0; i < resvRanges.Len(); i++ { |
| 221 | r := resvRanges.Get(i) |
| 222 | ss = append(ss, fmt.Sprintf("{%d,%d}", r[0], r[1])) |
| 223 | } |
| 224 | g.P("ReservedRanges: [][2]", protoreflectPackage.Ident("EnumNumber"), "{", strings.Join(ss, ","), "},") |
| 225 | } |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 226 | g.P("},") |
| 227 | } |
| 228 | g.P("}") |
| 229 | } |
| 230 | |
| 231 | // Generate literals for message descriptors. |
Joe Tsai | 9667c48 | 2018-12-05 15:42:52 -0800 | [diff] [blame] | 232 | if len(f.allMessages) > 0 { |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 233 | messageTypesVar := messageTypesVarName(f) |
| 234 | messageDescsVar := messageDescsVarName(f) |
Joe Tsai | 9667c48 | 2018-12-05 15:42:52 -0800 | [diff] [blame] | 235 | g.P("var ", messageTypesVar, " = [", len(f.allMessages), "]", protoimplPackage.Ident("MessageType"), "{") |
| 236 | for i, message := range f.allMessages { |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 237 | if message.Desc.IsMapEntry() { |
| 238 | // Map entry types have no Go type generated for them. |
| 239 | g.P("{ /* no message type for ", message.GoIdent, " */ },") |
| 240 | continue |
| 241 | } |
| 242 | g.P("{Type: ", prototypePackage.Ident("GoMessage"), "(") |
| 243 | g.P(messageDescsVar, "[", i, "].Reference(),") |
Joe Tsai | 3bc7d6f | 2019-01-09 02:57:13 -0800 | [diff] [blame] | 244 | g.P("func(", protoreflectPackage.Ident("MessageType"), ") ", protoreflectPackage.Ident("Message"), " {") |
| 245 | g.P("return ", shadowTypeName(message.GoIdent), "{new(", message.GoIdent, ")}") |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 246 | g.P("},") |
| 247 | g.P(")},") |
| 248 | } |
| 249 | g.P("}") |
| 250 | |
Joe Tsai | 9667c48 | 2018-12-05 15:42:52 -0800 | [diff] [blame] | 251 | g.P("var ", messageDescsVar, " = [", len(f.allMessages), "]", prototypePackage.Ident("Message"), "{") |
| 252 | for _, message := range f.allMessages { |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 253 | g.P("{") |
| 254 | g.P("Name: ", strconv.Quote(string(message.Desc.Name())), ",") |
| 255 | if fields := message.Desc.Fields(); fields.Len() > 0 { |
| 256 | g.P("Fields: []", prototypePackage.Ident("Field"), "{") |
| 257 | for i := 0; i < fields.Len(); i++ { |
| 258 | field := fields.Get(i) |
| 259 | g.P("{") |
| 260 | g.P("Name: ", strconv.Quote(string(field.Name())), ",") |
| 261 | g.P("Number: ", field.Number(), ",") |
| 262 | g.P("Cardinality: ", protoreflectPackage.Ident(field.Cardinality().GoString()), ",") |
| 263 | g.P("Kind: ", protoreflectPackage.Ident(field.Kind().GoString()), ",") |
Joe Tsai | bce82b8 | 2018-12-06 09:39:03 -0800 | [diff] [blame] | 264 | if field.HasJSONName() { |
| 265 | g.P("JSONName: ", strconv.Quote(field.JSONName()), ",") |
| 266 | } |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 267 | if field.HasDefault() { |
| 268 | v := field.Default().Interface() |
| 269 | typeName := reflect.TypeOf(v).Name() |
| 270 | valLit := fmt.Sprint(v) |
| 271 | switch v.(type) { |
| 272 | case protoreflect.EnumNumber: |
| 273 | typeName = "string" |
| 274 | valLit = strconv.Quote(string(field.DefaultEnumValue().Name())) |
| 275 | case float32, float64: |
| 276 | switch f := field.Default().Float(); { |
| 277 | case math.IsInf(f, -1): |
| 278 | valLit = g.QualifiedGoIdent(mathPackage.Ident("Inf")) + "(-1)" |
| 279 | case math.IsInf(f, +1): |
| 280 | valLit = g.QualifiedGoIdent(mathPackage.Ident("Inf")) + "(+1)" |
| 281 | case math.IsNaN(f): |
| 282 | valLit = g.QualifiedGoIdent(mathPackage.Ident("NaN")) + "()" |
| 283 | } |
| 284 | case string, []byte: |
| 285 | valLit = fmt.Sprintf("%q", v) |
| 286 | } |
| 287 | g.P("Default: ", protoreflectPackage.Ident("ValueOf"), "(", typeName, "(", valLit, ")),") |
| 288 | } |
| 289 | if oneof := field.OneofType(); oneof != nil { |
| 290 | g.P("OneofName: ", strconv.Quote(string(oneof.Name())), ",") |
| 291 | } |
Damien Neil | 232ea15 | 2018-12-10 15:14:36 -0800 | [diff] [blame] | 292 | if field.IsPacked() { |
| 293 | g.P("IsPacked: ", prototypePackage.Ident("True"), ",") |
| 294 | } else { |
| 295 | g.P("IsPacked: ", prototypePackage.Ident("False"), ",") |
| 296 | } |
| 297 | if field.IsWeak() { |
| 298 | g.P("IsWeak: true,") |
| 299 | } |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 300 | // NOTE: MessageType and EnumType are populated by init. |
| 301 | g.P("},") |
| 302 | } |
| 303 | g.P("},") |
| 304 | } |
| 305 | if oneofs := message.Desc.Oneofs(); oneofs.Len() > 0 { |
| 306 | g.P("Oneofs: []", prototypePackage.Ident("Oneof"), "{") |
| 307 | for i := 0; i < oneofs.Len(); i++ { |
| 308 | oneof := oneofs.Get(i) |
| 309 | g.P("{Name: ", strconv.Quote(string(oneof.Name())), "},") |
| 310 | } |
| 311 | g.P("},") |
| 312 | } |
Joe Tsai | bce82b8 | 2018-12-06 09:39:03 -0800 | [diff] [blame] | 313 | if resvNames := message.Desc.ReservedNames(); resvNames.Len() > 0 { |
| 314 | var ss []string |
| 315 | for i := 0; i < resvNames.Len(); i++ { |
| 316 | s := resvNames.Get(i) |
| 317 | ss = append(ss, strconv.Quote(string(s))) |
| 318 | } |
| 319 | g.P("ReservedNames: []", protoreflectPackage.Ident("Name"), "{", strings.Join(ss, ","), "},") |
| 320 | } |
| 321 | if resvRanges := message.Desc.ReservedRanges(); resvRanges.Len() > 0 { |
| 322 | var ss []string |
| 323 | for i := 0; i < resvRanges.Len(); i++ { |
| 324 | r := resvRanges.Get(i) |
| 325 | ss = append(ss, fmt.Sprintf("{%d,%d}", r[0], r[1])) |
| 326 | } |
| 327 | g.P("ReservedRanges: [][2]", protoreflectPackage.Ident("FieldNumber"), "{", strings.Join(ss, ","), "},") |
| 328 | } |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 329 | if extRanges := message.Desc.ExtensionRanges(); extRanges.Len() > 0 { |
| 330 | var ss []string |
| 331 | for i := 0; i < extRanges.Len(); i++ { |
| 332 | r := extRanges.Get(i) |
| 333 | ss = append(ss, fmt.Sprintf("{%d,%d}", r[0], r[1])) |
| 334 | } |
| 335 | g.P("ExtensionRanges: [][2]", protoreflectPackage.Ident("FieldNumber"), "{", strings.Join(ss, ","), "},") |
| 336 | } |
Damien Neil | 232ea15 | 2018-12-10 15:14:36 -0800 | [diff] [blame] | 337 | if message.Desc.IsMapEntry() { |
| 338 | g.P("IsMapEntry: true,") |
| 339 | } |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 340 | // NOTE: Messages, Enums, and Extensions are populated by init. |
| 341 | g.P("},") |
| 342 | } |
| 343 | g.P("}") |
| 344 | } |
| 345 | |
| 346 | // TODO: Add support for extensions. |
| 347 | // TODO: Add support for services. |
| 348 | } |
| 349 | |
| 350 | func genReflectEnum(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, enum *protogen.Enum) { |
Joe Tsai | 24ceb2b | 2018-12-04 22:53:56 -0800 | [diff] [blame] | 351 | if !enableReflection(f.File) { |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 352 | return |
| 353 | } |
| 354 | |
Joe Tsai | 9667c48 | 2018-12-05 15:42:52 -0800 | [diff] [blame] | 355 | idx := f.allEnumsByPtr[enum] |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 356 | typesVar := enumTypesVarName(f) |
Damien Neil | a8593ba | 2019-01-08 16:18:07 -0800 | [diff] [blame] | 357 | g.P("func (e ", enum.GoIdent, ") Type() ", protoreflectPackage.Ident("EnumType"), " {") |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 358 | g.P("return ", typesVar, "[", idx, "]") |
| 359 | g.P("}") |
Damien Neil | a8593ba | 2019-01-08 16:18:07 -0800 | [diff] [blame] | 360 | g.P("func (e ", enum.GoIdent, ") Number() ", protoreflectPackage.Ident("EnumNumber"), " {") |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 361 | g.P("return ", protoreflectPackage.Ident("EnumNumber"), "(e)") |
| 362 | g.P("}") |
| 363 | } |
| 364 | |
| 365 | func genReflectMessage(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, message *protogen.Message) { |
Joe Tsai | 24ceb2b | 2018-12-04 22:53:56 -0800 | [diff] [blame] | 366 | if !enableReflection(f.File) { |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 367 | return |
| 368 | } |
| 369 | |
| 370 | shadowType := shadowTypeName(message.GoIdent) |
| 371 | g.P("type ", shadowType, " struct{m *", message.GoIdent, "}") |
| 372 | g.P() |
| 373 | |
Joe Tsai | 9667c48 | 2018-12-05 15:42:52 -0800 | [diff] [blame] | 374 | idx := f.allMessagesByPtr[message] |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 375 | typesVar := messageTypesVarName(f) |
| 376 | g.P("func (m *", message.GoIdent, ") ProtoReflect() ", protoreflectPackage.Ident("Message"), " {") |
| 377 | g.P("return ", shadowType, "{m}") |
| 378 | g.P("}") |
| 379 | g.P("func (m ", shadowType, ") Type() ", protoreflectPackage.Ident("MessageType"), " {") |
| 380 | g.P("return ", typesVar, "[", idx, "].Type") |
| 381 | g.P("}") |
| 382 | g.P("func (m ", shadowType, ") KnownFields() ", protoreflectPackage.Ident("KnownFields"), " {") |
| 383 | g.P("return ", typesVar, "[", idx, "].KnownFieldsOf(m.m)") |
| 384 | g.P("}") |
| 385 | g.P("func (m ", shadowType, ") UnknownFields() ", protoreflectPackage.Ident("UnknownFields"), " {") |
| 386 | g.P("return ", typesVar, "[", idx, "].UnknownFieldsOf(m.m)") |
| 387 | g.P("}") |
| 388 | g.P("func (m ", shadowType, ") Interface() ", protoreflectPackage.Ident("ProtoMessage"), " {") |
| 389 | g.P("return m.m") |
| 390 | g.P("}") |
Joe Tsai | b6405bd | 2018-11-15 14:44:37 -0800 | [diff] [blame] | 391 | g.P() |
| 392 | } |
| 393 | |
| 394 | func fileDescVarName(f *fileInfo) string { |
| 395 | return "xxx_" + f.GoDescriptorIdent.GoName + "_FileDesc" |
| 396 | } |
| 397 | func enumTypesVarName(f *fileInfo) string { |
| 398 | return "xxx_" + f.GoDescriptorIdent.GoName + "_EnumTypes" |
| 399 | } |
| 400 | func enumDescsVarName(f *fileInfo) string { |
| 401 | return "xxx_" + f.GoDescriptorIdent.GoName + "_EnumDescs" |
| 402 | } |
| 403 | func messageTypesVarName(f *fileInfo) string { |
| 404 | return "xxx_" + f.GoDescriptorIdent.GoName + "_MessageTypes" |
| 405 | } |
| 406 | func messageDescsVarName(f *fileInfo) string { |
| 407 | return "xxx_" + f.GoDescriptorIdent.GoName + "_MessageDescs" |
| 408 | } |
| 409 | func extensionDescsVarName(f *fileInfo) string { |
| 410 | return "xxx_" + f.GoDescriptorIdent.GoName + "_ExtensionDescs" |
| 411 | } |
| 412 | func shadowTypeName(ident protogen.GoIdent) string { |
| 413 | return "xxx_" + ident.GoName |
| 414 | } |