Skip to content

Commit a804c3b

Browse files
stefanhausteincopybara-github
authored andcommitted
Add kotlin/native-compatible map support, gated by the generate properties option.
Also adjust the generic field type for "fieldNameList" property NSArray access to repeated fields. PiperOrigin-RevId: 745923366
1 parent 54b1470 commit a804c3b

File tree

5 files changed

+99
-10
lines changed

5 files changed

+99
-10
lines changed

protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_field.cc

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,25 @@ std::string GetStorageType(const FieldDescriptor* descriptor) {
9494
}
9595
}
9696

97+
std::string GetGenericType(const FieldDescriptor* descriptor) {
98+
switch (GetJavaType(descriptor)) {
99+
case JAVATYPE_INT:
100+
case JAVATYPE_LONG:
101+
case JAVATYPE_FLOAT:
102+
case JAVATYPE_DOUBLE:
103+
case JAVATYPE_BOOLEAN:
104+
return "NSNumber *";
105+
case JAVATYPE_STRING:
106+
return "NSString *";
107+
case JAVATYPE_BYTES:
108+
return "ComGoogleProtobufByteString *";
109+
case JAVATYPE_ENUM:
110+
return ClassName(descriptor->enum_type()) + " *";
111+
case JAVATYPE_MESSAGE:
112+
return ClassName(descriptor->message_type()) + " *";
113+
}
114+
}
115+
97116
std::string GetNonNullType(const FieldDescriptor* descriptor) {
98117
switch (GetJavaType(descriptor)) {
99118
case JAVATYPE_INT:
@@ -136,6 +155,7 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
136155
(*variables)["parameter_type"] = GetParameterType(descriptor);
137156
(*variables)["storage_type"] = GetStorageType(descriptor);
138157
(*variables)["nonnull_type"] = GetNonNullType(descriptor);
158+
(*variables)["generic_type"] = GetGenericType(descriptor);
139159
(*variables)["field_name"] = GetFieldName(descriptor);
140160
(*variables)["flags"] = GetFieldFlags(descriptor);
141161
(*variables)["field_type"] = GetFieldTypeEnumValue(descriptor);
@@ -426,7 +446,7 @@ void RepeatedFieldGenerator::GenerateMessageOrBuilderProtocol(
426446
"@property (readonly, getter=Get$capitalized_name$Count)"
427447
" jint $camelcase_name$Count;\n"
428448
"@property (readonly, getter=Get$capitalized_name$Array)"
429-
" NSArray<$storage_type$> *$camelcase_name$List;\n"
449+
" NSArray<$generic_type$> *$camelcase_name$List;\n"
430450
"- ($nonnull_type$)get$capitalized_name$Index:(int)index;\n");
431451
}
432452
}
@@ -466,8 +486,10 @@ MapFieldGenerator::MapFieldGenerator(
466486
value_field_ = entry_message->FindFieldByName("value");
467487

468488
variables_["key_storage_type"] = GetStorageType(key_field_);
489+
variables_["key_generic_type"] = GetStorageType(key_field_);
469490
variables_["key_parameter_type"] = GetParameterType(key_field_);
470491
variables_["key_descriptor_type"] = GetFieldTypeEnumValue(key_field_);
492+
variables_["value_generic_type"] = GetGenericType(value_field_);
471493
variables_["value_nonnull_type"] = GetNonNullType(value_field_);
472494
variables_["value_parameter_type"] = GetParameterType(value_field_);
473495
variables_["value_descriptor_type"] = GetFieldTypeEnumValue(value_field_);
@@ -501,6 +523,31 @@ void MapFieldGenerator::GenerateFieldBuilderHeader(io::Printer* printer) const {
501523
"*)put$capitalized_name$With$key_parameter_type$:"
502524
"($key_storage_type$)key with$value_parameter_type$:"
503525
"($value_nonnull_type$)value;\n");
526+
527+
if (IsGenerateProperties(descriptor_->file())) {
528+
printer->Print(
529+
variables_,
530+
"- (nonnull $classname$_Builder *)put$capitalized_name$:"
531+
"($key_nonnull_type$)key value:($value_nonnull_type$)value;\n");
532+
}
533+
}
534+
535+
void MapFieldGenerator::GenerateFieldSource(io::Printer* printer) const {
536+
if (IsGenerateProperties(descriptor_->file())) {
537+
printer->Print(
538+
variables_,
539+
"\n"
540+
"@dynamic $camelcase_name$Map;\n");
541+
}
542+
}
543+
544+
void MapFieldGenerator::GenerateFieldBuilderSource(io::Printer* printer) const {
545+
if (IsGenerateProperties(descriptor_->file())) {
546+
printer->Print(
547+
variables_,
548+
"\n"
549+
"@dynamic $camelcase_name$Map;\n");
550+
}
504551
}
505552

506553
void MapFieldGenerator::GenerateMessageOrBuilderProtocol(
@@ -518,6 +565,14 @@ void MapFieldGenerator::GenerateMessageOrBuilderProtocol(
518565
"with$value_parameter_type$:($value_nonnull_type$)defaultValue;\n"
519566
"- ($value_nonnull_type$)get$capitalized_name$OrThrowWith"
520567
"$key_parameter_type$:($key_storage_type$)key;\n");
568+
569+
if (IsGenerateProperties(descriptor_->file())) {
570+
printer->Print(
571+
variables_,
572+
"@property (readonly, getter=Get$capitalized_name$Dict)"
573+
" NSDictionary<$key_generic_type$, $value_generic_type$>"
574+
" *$camelcase_name$Map;\n");
575+
}
521576
// clang-format on
522577
}
523578

protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_field.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,9 @@ class MapFieldGenerator : public FieldGenerator {
143143

144144
virtual ~MapFieldGenerator() { }
145145

146+
virtual void GenerateFieldSource(io::Printer* printer) const;
146147
virtual void GenerateFieldBuilderHeader(io::Printer* printer) const;
148+
virtual void GenerateFieldBuilderSource(io::Printer* printer) const;
147149
virtual void GenerateMessageOrBuilderProtocol(io::Printer* printer) const;
148150
virtual void GenerateDeclaration(io::Printer* printer) const;
149151
virtual void GenerateMapEntryFieldData(io::Printer *printer) const;

protobuf/runtime/src/com/google/protobuf/GeneratedMessage.mm

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,16 @@ static BOOL AddMapGetterMethod(Class cls, SEL sel, CGPFieldDescriptor *field) {
466466
return class_addMethod(cls, sel, imp, "@@:");
467467
}
468468

469+
static BOOL AddDictGetterMethod(Class cls, SEL sel, CGPFieldDescriptor *field) {
470+
size_t offset = CGPFieldGetOffset(field, cls);
471+
CGPFieldJavaType keyType = CGPFieldGetJavaType(CGPFieldMapKey(field));
472+
CGPFieldJavaType valueType = CGPFieldGetJavaType(CGPFieldMapValue(field));
473+
IMP imp = imp_implementationWithBlock(^id(id msg) {
474+
return CGPMapFieldAsDict(MAP_FIELD_PTR(msg, offset), keyType, valueType);
475+
});
476+
return class_addMethod(cls, sel, imp, "@@:");
477+
}
478+
469479
static BOOL AddClearMethod(Class cls, SEL sel, CGPFieldDescriptor *field) {
470480
IMP imp;
471481
size_t offset = CGPFieldGetOffset(field, cls);
@@ -1066,12 +1076,14 @@ static BOOL ResolveGetAccessor(Class cls, CGPDescriptor *descriptor, SEL sel, co
10661076
return AddCountMethod(cls, sel, field);
10671077
} else if (MatchesEnd(tail, "Map")) {
10681078
return AddMapGetterMethod(cls, sel, field);
1069-
} else if (Matches(&tail, "OrThrowWith", 11)
1070-
&& MatchesKeyword(&tail, CGPFieldMapKey(field)) && MatchesEnd(tail, ":")) {
1079+
} else if (MatchesEnd(tail, "Dict")) {
1080+
return AddDictGetterMethod(cls, sel, field);
1081+
} else if (Matches(&tail, "OrThrowWith", 11) &&
1082+
MatchesKeyword(&tail, CGPFieldMapKey(field)) && MatchesEnd(tail, ":")) {
10711083
return AddMapGetWithKeyMethod(cls, sel, field, false);
1072-
} else if (Matches(&tail2, "OrDefaultWith", 13)
1073-
&& MatchesKeyword(&tail2, CGPFieldMapKey(field)) && Matches(&tail2, ":with", 5)
1074-
&& MatchesKeyword(&tail2, CGPFieldMapValue(field)) && MatchesEnd(tail2, ":")) {
1084+
} else if (Matches(&tail2, "OrDefaultWith", 13) &&
1085+
MatchesKeyword(&tail2, CGPFieldMapKey(field)) && Matches(&tail2, ":with", 5) &&
1086+
MatchesKeyword(&tail2, CGPFieldMapValue(field)) && MatchesEnd(tail2, ":")) {
10751087
return AddMapGetWithKeyMethod(cls, sel, field, true);
10761088
}
10771089
} else if (CGPFieldIsRepeated(field)) {
@@ -1216,10 +1228,15 @@ static BOOL ResolvePutAccessor(Class cls, CGPDescriptor *descriptor, SEL sel, co
12161228
for (NSUInteger i = 0; i < count; ++i) {
12171229
CGPFieldDescriptor *field = fieldsBuf[i];
12181230
const char *tail = selName;
1219-
if (CGPFieldIsMap(field) && MatchesName(&tail, field) && Matches(&tail, "With", 4)
1220-
&& MatchesKeyword(&tail, CGPFieldMapKey(field)) && Matches(&tail, ":with", 5)
1221-
&& MatchesKeyword(&tail, CGPFieldMapValue(field)) && MatchesEnd(tail, ":")) {
1222-
return AddPutMethod(cls, sel, field);
1231+
if (CGPFieldIsMap(field) && MatchesName(&tail, field)) {
1232+
if (Matches(&tail, "With", 4) && MatchesKeyword(&tail, CGPFieldMapKey(field)) &&
1233+
Matches(&tail, ":with", 5) && MatchesKeyword(&tail, CGPFieldMapValue(field)) &&
1234+
MatchesEnd(tail, ":")) {
1235+
return AddPutMethod(cls, sel, field);
1236+
}
1237+
if (Matches(&tail, ":value", 6) && MatchesEnd(tail, ":")) {
1238+
return AddPutMethod(cls, sel, field);
1239+
}
12231240
}
12241241
}
12251242
return NO;

protobuf/runtime/src/com/google/protobuf/MapField.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,9 @@ void CGPMapFieldAssignFromList(
141141
id<JavaUtilMap> CGPMapFieldAsJavaMap(
142142
CGPMapField *field, CGPFieldJavaType keyType, CGPFieldJavaType valueType);
143143

144+
NSDictionary *CGPMapFieldAsDict(CGPMapField *field, CGPFieldJavaType keyType,
145+
CGPFieldJavaType valueType);
146+
144147
CF_EXTERN_C_END
145148

146149
#endif // __ComGoogleProtobufMapField_H__

protobuf/runtime/src/com/google/protobuf/MapField.m

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,18 @@ @interface CGPMapFieldMap : JavaUtilAbstractMap {
677677
return map;
678678
}
679679

680+
NSDictionary *CGPMapFieldAsDict(CGPMapField *field, CGPFieldJavaType keyType,
681+
CGPFieldJavaType valueType) {
682+
id<JavaUtilMap> map = CGPMapFieldAsJavaMap(field, keyType, valueType);
683+
// Alternatively, we could use a NSDict subclass here, similar to the "Java" map impl,
684+
// avoiding the copy -- or copy the underlying data from the underlying data structures directly.
685+
NSMutableDictionary *result = [[NSMutableDictionary alloc] init];
686+
for (id entry in map.entrySet) {
687+
result[[entry getKey]] = [entry getValue];
688+
}
689+
return result;
690+
}
691+
680692
@interface CGPMapFieldEntrySet : JavaUtilAbstractSet {
681693
@package
682694
CGPMapFieldMap *map_;

0 commit comments

Comments
 (0)