If enum aliases overlap in ObjC names skip generating the extras. Some protos have enum values of "FOO" and "Foo", which the ObjC generation then makes into the same thing. Just skip generating the enum element for the duplicate as it would be a compile error because of the name collision. The descriptors are still generated to support reflection and TextFormat more completely.
diff --git a/objectivec/Tests/GPBDescriptorTests.m b/objectivec/Tests/GPBDescriptorTests.m index d47cc30..46c1729 100644 --- a/objectivec/Tests/GPBDescriptorTests.m +++ b/objectivec/Tests/GPBDescriptorTests.m
@@ -244,7 +244,44 @@ XCTAssertTrue([descriptor getValue:&value forEnumName:enumName]); XCTAssertEqual(value, 2); XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:4], @"BAR2"); +} +- (void)testEnumAliasNameCollisions { + GPBEnumDescriptor *descriptor = TestEnumObjCNameCollision_EnumDescriptor(); + NSString *textFormatName; + int32_t value; + + XCTAssertEqual(descriptor.enumNameCount, 5U); + + XCTAssertEqualObjects([descriptor getEnumNameForIndex:0], @"TestEnumObjCNameCollision_Foo"); + textFormatName = [descriptor getEnumTextFormatNameForIndex:0]; + XCTAssertEqualObjects(textFormatName, @"FOO"); + XCTAssertTrue([descriptor getValue:&value forEnumTextFormatName:textFormatName]); + XCTAssertEqual(value, 1); + + XCTAssertEqualObjects([descriptor getEnumNameForIndex:1], @"TestEnumObjCNameCollision_Foo"); + textFormatName = [descriptor getEnumTextFormatNameForIndex:1]; + XCTAssertEqualObjects(textFormatName, @"foo"); + XCTAssertTrue([descriptor getValue:&value forEnumTextFormatName:textFormatName]); + XCTAssertEqual(value, 1); + + XCTAssertEqualObjects([descriptor getEnumNameForIndex:2], @"TestEnumObjCNameCollision_Bar"); + textFormatName = [descriptor getEnumTextFormatNameForIndex:2]; + XCTAssertEqualObjects(textFormatName, @"BAR"); + XCTAssertTrue([descriptor getValue:&value forEnumTextFormatName:textFormatName]); + XCTAssertEqual(value, 2); + + XCTAssertEqualObjects([descriptor getEnumNameForIndex:3], @"TestEnumObjCNameCollision_Mumble"); + textFormatName = [descriptor getEnumTextFormatNameForIndex:3]; + XCTAssertEqualObjects(textFormatName, @"mumble"); + XCTAssertTrue([descriptor getValue:&value forEnumTextFormatName:textFormatName]); + XCTAssertEqual(value, 2); + + XCTAssertEqualObjects([descriptor getEnumNameForIndex:4], @"TestEnumObjCNameCollision_Mumble"); + textFormatName = [descriptor getEnumTextFormatNameForIndex:4]; + XCTAssertEqualObjects(textFormatName, @"MUMBLE"); + XCTAssertTrue([descriptor getValue:&value forEnumTextFormatName:textFormatName]); + XCTAssertEqual(value, 2); } - (void)testEnumValueValidator {
diff --git a/objectivec/Tests/unittest_objc.proto b/objectivec/Tests/unittest_objc.proto index 1245ebe..91c2139 100644 --- a/objectivec/Tests/unittest_objc.proto +++ b/objectivec/Tests/unittest_objc.proto
@@ -867,3 +867,18 @@ message WKTRefereceMessage { optional google.protobuf.Any an_any = 1; } + +// This is in part a compile test, it ensures that when aliases end up with +// the same ObjC name, we drop them to avoid the duplication names. There +// is a test to ensure the descriptors are still generated to support +// reflection and TextFormat. +enum TestEnumObjCNameCollision { + option allow_alias = true; + + FOO = 1; + foo = 1; + + BAR = 2; + mumble = 2; + MUMBLE = 2; +}