| 2505 | } |
| 2506 | |
| 2507 | func (g *Generator) generateExtension(ext *ExtensionDescriptor) { |
| 2508 | ccTypeName := ext.DescName() |
| 2509 | |
| 2510 | extObj := g.ObjectNamed(*ext.Extendee) |
| 2511 | var extDesc *Descriptor |
| 2512 | if id, ok := extObj.(*ImportedDescriptor); ok { |
| 2513 | // This is extending a publicly imported message. |
| 2514 | // We need the underlying type for goTag. |
| 2515 | extDesc = id.o.(*Descriptor) |
| 2516 | } else { |
| 2517 | extDesc = extObj.(*Descriptor) |
| 2518 | } |
| 2519 | extendedType := "*" + g.TypeName(extObj) // always use the original |
| 2520 | field := ext.FieldDescriptorProto |
| 2521 | fieldType, wireType := g.GoType(ext.parent, field) |
| 2522 | tag := g.goTag(extDesc, field, wireType) |
| 2523 | g.RecordTypeUse(*ext.Extendee) |
| 2524 | if n := ext.FieldDescriptorProto.TypeName; n != nil { |
| 2525 | // foreign extension type |
| 2526 | g.RecordTypeUse(*n) |
| 2527 | } |
| 2528 | |
| 2529 | typeName := ext.TypeName() |
| 2530 | |
| 2531 | // Special case for proto2 message sets: If this extension is extending |
| 2532 | // proto2.bridge.MessageSet, and its final name component is "message_set_extension", |
| 2533 | // then drop that last component. |
| 2534 | // |
| 2535 | // TODO: This should be implemented in the text formatter rather than the generator. |
| 2536 | // In addition, the situation for when to apply this special case is implemented |
| 2537 | // differently in other languages: |
| 2538 | // https://github.com/google/protobuf/blob/aff10976/src/google/protobuf/text_format.cc#L1560 |
| 2539 | if extDesc.GetOptions().GetMessageSetWireFormat() && typeName[len(typeName)-1] == "message_set_extension" { |
| 2540 | typeName = typeName[:len(typeName)-1] |
| 2541 | } |
| 2542 | |
| 2543 | // For text formatting, the package must be exactly what the .proto file declares, |
| 2544 | // ignoring overrides such as the go_package option, and with no dot/underscore mapping. |
| 2545 | extName := strings.Join(typeName, ".") |
| 2546 | if g.file.Package != nil { |
| 2547 | extName = *g.file.Package + "." + extName |
| 2548 | } |
| 2549 | |
| 2550 | g.P("var ", ccTypeName, " = &", g.Pkg["proto"], ".ExtensionDesc{") |
| 2551 | g.P("ExtendedType: (", extendedType, ")(nil),") |
| 2552 | g.P("ExtensionType: (", fieldType, ")(nil),") |
| 2553 | g.P("Field: ", field.Number, ",") |
| 2554 | g.P(`Name: "`, extName, `",`) |
| 2555 | g.P("Tag: ", tag, ",") |
| 2556 | g.P(`Filename: "`, g.file.GetName(), `",`) |
| 2557 | |
| 2558 | g.P("}") |
| 2559 | g.P() |
| 2560 | |
| 2561 | g.addInitf("%s.RegisterExtension(%s)", g.Pkg["proto"], ext.DescName()) |
| 2562 | |
| 2563 | g.file.addExport(ext, constOrVarSymbol{ccTypeName, "var", ""}) |
| 2564 | } |