goprotobuf: Fix handling of publicly imported enum types.
R=r
CC=golang-dev
https://codereview.appspot.com/12436045
diff --git a/protoc-gen-go/generator/generator.go b/protoc-gen-go/generator/generator.go
index 7fff0fa..5097ea5 100644
--- a/protoc-gen-go/generator/generator.go
+++ b/protoc-gen-go/generator/generator.go
@@ -377,12 +377,17 @@
}
type constOrVarSymbol struct {
- sym string
- typ string // either "const" or "var"
+ sym string
+ typ string // either "const" or "var"
+ cast string // if non-empty, a type cast is required (used for enums)
}
func (cs constOrVarSymbol) GenerateAlias(g *Generator, pkg string) {
- g.P(cs.typ, " ", cs.sym, " = ", pkg, ".", cs.sym)
+ v := pkg + "." + cs.sym
+ if cs.cast != "" {
+ v = cs.cast + "(" + v + ")"
+ }
+ g.P(cs.typ, " ", cs.sym, " = ", v)
}
// Object is an interface abstracting the abilities shared by enums, messages, extensions and imported objects.
@@ -1157,7 +1162,7 @@
name := ccPrefix + *e.Name
g.P(name, " ", ccTypeName, " = ", e.Number)
- g.file.addExport(enum, constOrVarSymbol{name, "const"})
+ g.file.addExport(enum, constOrVarSymbol{name, "const", ccTypeName})
}
g.Out()
g.P(")")
@@ -1255,9 +1260,18 @@
case descriptor.FieldDescriptorProto_TYPE_ENUM:
// For enums we need to provide the integer constant.
obj := g.ObjectNamed(field.GetTypeName())
+ if id, ok := obj.(*ImportedDescriptor); ok {
+ // It is an enum that was publicly imported.
+ // We need the underlying type.
+ obj = id.o
+ }
enum, ok := obj.(*EnumDescriptor)
if !ok {
- g.Fail("enum type inconsistent for", CamelCaseSlice(obj.TypeName()))
+ log.Printf("obj is a %T", obj)
+ if id, ok := obj.(*ImportedDescriptor); ok {
+ log.Printf("id.o is a %T", id.o)
+ }
+ g.Fail("unknown enum type", CamelCaseSlice(obj.TypeName()))
}
defaultValue = enum.integerValueAsString(defaultValue)
}
@@ -1268,6 +1282,9 @@
// We avoid using obj.PackageName(), because we want to use the
// original (proto-world) package name.
obj := g.ObjectNamed(field.GetTypeName())
+ if id, ok := obj.(*ImportedDescriptor); ok {
+ obj = id.o
+ }
enum = ",enum="
if pkg := obj.File().GetPackage(); pkg != "" {
enum += pkg + "."
@@ -1541,15 +1558,21 @@
case *field.Type == descriptor.FieldDescriptorProto_TYPE_ENUM:
// Must be an enum. Need to construct the prefixed name.
obj := g.ObjectNamed(field.GetTypeName())
- enum, ok := obj.(*EnumDescriptor)
- if !ok {
- log.Print("don't know how to generate constant for", fieldname)
+ var enum *EnumDescriptor
+ if id, ok := obj.(*ImportedDescriptor); ok {
+ // The enum type has been publicly imported.
+ enum, _ = id.o.(*EnumDescriptor)
+ } else {
+ enum, _ = obj.(*EnumDescriptor)
+ }
+ if enum == nil {
+ log.Printf("don't know how to generate constant for %s", fieldname)
continue
}
- def = g.DefaultPackageName(enum) + enum.prefix() + def
+ def = g.DefaultPackageName(obj) + enum.prefix() + def
}
g.P(kind, fieldname, " ", typename, " = ", def)
- g.file.addExport(message, constOrVarSymbol{fieldname, kind})
+ g.file.addExport(message, constOrVarSymbol{fieldname, kind, ""})
}
g.P()
@@ -1701,7 +1724,7 @@
g.P("}")
g.P()
- g.file.addExport(ext, constOrVarSymbol{ccTypeName, "var"})
+ g.file.addExport(ext, constOrVarSymbol{ccTypeName, "var", ""})
}
func (g *Generator) generateInitFunction() {
diff --git a/protoc-gen-go/testdata/imp2.proto b/protoc-gen-go/testdata/imp2.proto
index 62dad2b..f2f3c1a 100644
--- a/protoc-gen-go/testdata/imp2.proto
+++ b/protoc-gen-go/testdata/imp2.proto
@@ -33,3 +33,8 @@
message PubliclyImportedMessage {
optional int64 field = 1;
}
+
+enum PubliclyImportedEnum {
+ GLASSES = 1;
+ HAIR = 2;
+}
diff --git a/protoc-gen-go/testdata/my_test/test.proto b/protoc-gen-go/testdata/my_test/test.proto
index d26e20c..478e697 100644
--- a/protoc-gen-go/testdata/my_test/test.proto
+++ b/protoc-gen-go/testdata/my_test/test.proto
@@ -66,9 +66,10 @@
optional int32 group_field = 9;
}
- // This foreign message type is in imp2.proto,
+ // These foreign types are in imp2.proto,
// which is publicly imported by imp.proto.
// optional imp.PubliclyImportedMessage pub = 10;
+// optional imp.PubliclyImportedEnum pub_enum = 13 [default=HAIR];
optional int32 reset = 12;