1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7
8 #include "google/protobuf/compiler/objectivec/field.h"
9
10 #include <cstddef>
11 #include <string>
12 #include <vector>
13
14 #include "absl/container/btree_set.h"
15 #include "absl/container/flat_hash_map.h"
16 #include "absl/container/flat_hash_set.h"
17 #include "absl/log/absl_check.h"
18 #include "absl/log/absl_log.h"
19 #include "absl/strings/str_cat.h"
20 #include "absl/strings/string_view.h"
21 #include "google/protobuf/compiler/objectivec/enum_field.h"
22 #include "google/protobuf/compiler/objectivec/helpers.h"
23 #include "google/protobuf/compiler/objectivec/map_field.h"
24 #include "google/protobuf/compiler/objectivec/message_field.h"
25 #include "google/protobuf/compiler/objectivec/names.h"
26 #include "google/protobuf/compiler/objectivec/options.h"
27 #include "google/protobuf/compiler/objectivec/primitive_field.h"
28 #include "google/protobuf/descriptor.h"
29 #include "google/protobuf/io/printer.h"
30
31 namespace google {
32 namespace protobuf {
33 namespace compiler {
34 namespace objectivec {
35
36 namespace {
37
SetCommonFieldVariables(const FieldDescriptor * descriptor,absl::flat_hash_map<absl::string_view,std::string> * variables)38 void SetCommonFieldVariables(
39 const FieldDescriptor* descriptor,
40 absl::flat_hash_map<absl::string_view, std::string>* variables) {
41 std::string camel_case_name = FieldName(descriptor);
42 std::string raw_field_name;
43 if (internal::cpp::IsGroupLike(*descriptor)) {
44 raw_field_name = descriptor->message_type()->name();
45 } else {
46 raw_field_name = descriptor->name();
47 }
48 // The logic here has to match -[GGPBFieldDescriptor textFormatName].
49 const std::string un_camel_case_name(
50 UnCamelCaseFieldName(camel_case_name, descriptor));
51 const bool needs_custom_name = (raw_field_name != un_camel_case_name);
52
53 const std::string& classname = ClassName(descriptor->containing_type());
54 (*variables)["classname"] = classname;
55 (*variables)["name"] = camel_case_name;
56 const std::string& capitalized_name = FieldNameCapitalized(descriptor);
57 (*variables)["capitalized_name"] = capitalized_name;
58 (*variables)["raw_field_name"] = raw_field_name;
59 (*variables)["field_number_name"] =
60 absl::StrCat(classname, "_FieldNumber_", capitalized_name);
61 (*variables)["field_number"] = absl::StrCat(descriptor->number());
62 (*variables)["property_type"] = FieldObjCType(
63 descriptor, static_cast<FieldObjCTypeOptions>(
64 kFieldObjCTypeOptions_IncludeSpaceAfterBasicTypes |
65 kFieldObjCTypeOptions_IncludeSpaceBeforeStar));
66 (*variables)["storage_type"] = FieldObjCType(
67 descriptor, static_cast<FieldObjCTypeOptions>(
68 kFieldObjCTypeOptions_IncludeSpaceAfterBasicTypes |
69 kFieldObjCTypeOptions_OmitLightweightGenerics |
70 kFieldObjCTypeOptions_IncludeSpaceBeforeStar));
71 (*variables)["field_type"] = GetCapitalizedType(descriptor);
72 (*variables)["deprecated_attribute"] =
73 GetOptionalDeprecatedAttribute(descriptor);
74 std::vector<std::string> field_flags;
75 if (descriptor->is_repeated()) field_flags.push_back("GPBFieldRepeated");
76 if (descriptor->is_required()) field_flags.push_back("GPBFieldRequired");
77 if (descriptor->is_optional()) field_flags.push_back("GPBFieldOptional");
78 if (descriptor->is_packed()) field_flags.push_back("GPBFieldPacked");
79
80 // ObjC custom flags.
81 if (descriptor->has_default_value())
82 field_flags.push_back("GPBFieldHasDefaultValue");
83 if (needs_custom_name) field_flags.push_back("GPBFieldTextFormatNameCustom");
84 if (descriptor->type() == FieldDescriptor::TYPE_ENUM) {
85 field_flags.push_back("GPBFieldHasEnumDescriptor");
86 if (descriptor->enum_type()->is_closed()) {
87 field_flags.push_back("GPBFieldClosedEnum");
88 }
89 }
90 // It will clear on a zero value if...
91 // - not repeated/map
92 // - doesn't have presence
93 bool clear_on_zero =
94 (!descriptor->is_repeated() && !descriptor->has_presence());
95 if (clear_on_zero) {
96 field_flags.push_back("GPBFieldClearHasIvarOnZero");
97 }
98
99 (*variables)["fieldflags"] = BuildFlagsString(FLAGTYPE_FIELD, field_flags);
100
101 (*variables)["default"] = DefaultValue(descriptor);
102 (*variables)["default_name"] = GPBGenericValueFieldName(descriptor);
103
104 (*variables)["dataTypeSpecific_name"] = "clazz";
105 (*variables)["dataTypeSpecific_value"] = "Nil";
106
107 (*variables)["storage_offset_value"] = absl::StrCat(
108 "(uint32_t)offsetof(", classname, "__storage_, ", camel_case_name, ")");
109 (*variables)["storage_offset_comment"] = "";
110
111 // Clear some common things so they can be set just when needed.
112 (*variables)["storage_attribute"] = "";
113 }
114
HasNonZeroDefaultValue(const FieldDescriptor * field)115 bool HasNonZeroDefaultValue(const FieldDescriptor* field) {
116 // Repeated fields don't have defaults.
117 if (field->is_repeated()) {
118 return false;
119 }
120
121 // Some proto files set the default to the zero value, so make sure the value
122 // isn't the zero case instead of relying on has_default_value() to tell when
123 // non zero.
124 switch (field->cpp_type()) {
125 case FieldDescriptor::CPPTYPE_INT32:
126 return field->default_value_int32() != 0;
127 case FieldDescriptor::CPPTYPE_UINT32:
128 return field->default_value_uint32() != 0U;
129 case FieldDescriptor::CPPTYPE_INT64:
130 return field->default_value_int64() != 0LL;
131 case FieldDescriptor::CPPTYPE_UINT64:
132 return field->default_value_uint64() != 0ULL;
133 case FieldDescriptor::CPPTYPE_DOUBLE:
134 return field->default_value_double() != 0.0;
135 case FieldDescriptor::CPPTYPE_FLOAT:
136 return field->default_value_float() != 0.0f;
137 case FieldDescriptor::CPPTYPE_BOOL:
138 return field->default_value_bool();
139 case FieldDescriptor::CPPTYPE_STRING: {
140 return !field->default_value_string().empty();
141 }
142 case FieldDescriptor::CPPTYPE_ENUM:
143 // The default value for an enum field is the first enum value, so there
144 // even more reason we can't use has_default_value() for checking for
145 // zero.
146 return field->default_value_enum()->number() != 0;
147 case FieldDescriptor::CPPTYPE_MESSAGE:
148 return false;
149 }
150
151 // Some compilers report reaching end of function even though all cases of
152 // the enum are handed in the switch.
153 ABSL_LOG(FATAL) << "Can't get here.";
154 return false;
155 }
156
157 } // namespace
158
Make(const FieldDescriptor * field,const GenerationOptions & generation_options)159 FieldGenerator* FieldGenerator::Make(
160 const FieldDescriptor* field, const GenerationOptions& generation_options) {
161 if (field->is_repeated()) {
162 switch (GetObjectiveCType(field)) {
163 case OBJECTIVECTYPE_MESSAGE: {
164 if (field->is_map()) {
165 return new MapFieldGenerator(field, generation_options);
166 } else {
167 return new RepeatedMessageFieldGenerator(field, generation_options);
168 }
169 }
170 case OBJECTIVECTYPE_ENUM:
171 return new RepeatedEnumFieldGenerator(field, generation_options);
172 default:
173 return new RepeatedPrimitiveFieldGenerator(field, generation_options);
174 }
175 }
176
177 switch (GetObjectiveCType(field)) {
178 case OBJECTIVECTYPE_MESSAGE: {
179 return new MessageFieldGenerator(field, generation_options);
180 }
181 case OBJECTIVECTYPE_ENUM:
182 return new EnumFieldGenerator(field, generation_options);
183 default:
184 if (IsReferenceType(field)) {
185 return new PrimitiveObjFieldGenerator(field, generation_options);
186 } else {
187 return new PrimitiveFieldGenerator(field, generation_options);
188 }
189 }
190 }
191
FieldGenerator(const FieldDescriptor * descriptor,const GenerationOptions & generation_options)192 FieldGenerator::FieldGenerator(const FieldDescriptor* descriptor,
193 const GenerationOptions& generation_options)
194 : descriptor_(descriptor), generation_options_(generation_options) {
195 SetCommonFieldVariables(descriptor, &variables_);
196 }
197
GenerateFieldNumberConstant(io::Printer * printer) const198 void FieldGenerator::GenerateFieldNumberConstant(io::Printer* printer) const {
199 auto vars = printer->WithVars(variables_);
200 printer->Emit("$field_number_name$ = $field_number$,\n");
201 }
202
GenerateCFunctionDeclarations(io::Printer * printer) const203 void FieldGenerator::GenerateCFunctionDeclarations(io::Printer* printer) const {
204 // Nothing
205 }
206
GenerateCFunctionImplementations(io::Printer * printer) const207 void FieldGenerator::GenerateCFunctionImplementations(
208 io::Printer* printer) const {
209 // Nothing
210 }
211
DetermineForwardDeclarations(absl::btree_set<std::string> * fwd_decls,bool include_external_types) const212 void FieldGenerator::DetermineForwardDeclarations(
213 absl::btree_set<std::string>* fwd_decls,
214 bool include_external_types) const {
215 // Nothing
216 }
217
DetermineObjectiveCClassDefinitions(absl::btree_set<std::string> * fwd_decls) const218 void FieldGenerator::DetermineObjectiveCClassDefinitions(
219 absl::btree_set<std::string>* fwd_decls) const {
220 // Nothing
221 }
222
DetermineNeededFiles(absl::flat_hash_set<const FileDescriptor * > * deps) const223 void FieldGenerator::DetermineNeededFiles(
224 absl::flat_hash_set<const FileDescriptor*>* deps) const {
225 // Nothing
226 }
227
GenerateFieldDescription(io::Printer * printer,bool include_default) const228 void FieldGenerator::GenerateFieldDescription(io::Printer* printer,
229 bool include_default) const {
230 // Printed in the same order as the structure decl.
231 auto vars = printer->WithVars(variables_);
232 printer->Emit(
233 {{"prefix", include_default ? ".core" : ""},
234 {"maybe_default",
235 [&] {
236 if (include_default) {
237 printer->Emit(".defaultValue.$default_name$ = $default$,\n");
238 }
239 }}},
240 R"objc(
241 {
242 $maybe_default$,
243 $prefix$.name = "$name$",
244 $prefix$.dataTypeSpecific.$dataTypeSpecific_name$ = $dataTypeSpecific_value$,
245 $prefix$.number = $field_number_name$,
246 $prefix$.hasIndex = $has_index$,
247 $prefix$.offset = $storage_offset_value$,$storage_offset_comment$
248 $prefix$.flags = $fieldflags$,
249 $prefix$.dataType = GPBDataType$field_type$,
250 },
251 )objc");
252 }
253
SetRuntimeHasBit(int has_index)254 void FieldGenerator::SetRuntimeHasBit(int has_index) {
255 variables_["has_index"] = absl::StrCat(has_index);
256 }
257
SetNoHasBit()258 void FieldGenerator::SetNoHasBit() { variables_["has_index"] = "GPBNoHasBit"; }
259
ExtraRuntimeHasBitsNeeded() const260 int FieldGenerator::ExtraRuntimeHasBitsNeeded() const { return 0; }
261
SetExtraRuntimeHasBitsBase(int index_base)262 void FieldGenerator::SetExtraRuntimeHasBitsBase(int index_base) {
263 ABSL_LOG(FATAL)
264 << "Error: should have overridden SetExtraRuntimeHasBitsBase().";
265 }
266
SetOneofIndexBase(int index_base)267 void FieldGenerator::SetOneofIndexBase(int index_base) {
268 const OneofDescriptor* oneof = descriptor_->real_containing_oneof();
269 if (oneof != nullptr) {
270 int index = oneof->index() + index_base;
271 // Flip the sign to mark it as a oneof.
272 variables_["has_index"] = absl::StrCat(-index);
273 }
274 }
275
WantsHasProperty() const276 bool FieldGenerator::WantsHasProperty() const {
277 return descriptor_->has_presence() && !descriptor_->real_containing_oneof();
278 }
279
SingleFieldGenerator(const FieldDescriptor * descriptor,const GenerationOptions & generation_options)280 SingleFieldGenerator::SingleFieldGenerator(
281 const FieldDescriptor* descriptor,
282 const GenerationOptions& generation_options)
283 : FieldGenerator(descriptor, generation_options) {
284 // Nothing
285 }
286
GenerateFieldStorageDeclaration(io::Printer * printer) const287 void SingleFieldGenerator::GenerateFieldStorageDeclaration(
288 io::Printer* printer) const {
289 auto vars = printer->WithVars(variables_);
290 printer->Emit("$storage_type$$name$;\n");
291 }
292
GeneratePropertyDeclaration(io::Printer * printer) const293 void SingleFieldGenerator::GeneratePropertyDeclaration(
294 io::Printer* printer) const {
295 auto vars = printer->WithVars(variables_);
296 printer->Emit({{"comments",
297 [&] {
298 EmitCommentsString(printer, generation_options_,
299 descriptor_);
300 }}},
301 R"objc(
302 $comments$
303 @property(nonatomic, readwrite) $property_type$$name$$ deprecated_attribute$;
304 )objc");
305 if (WantsHasProperty()) {
306 printer->Emit(R"objc(
307 @property(nonatomic, readwrite) BOOL has$capitalized_name$$ deprecated_attribute$;
308 )objc");
309 }
310 printer->Emit("\n");
311 }
312
GeneratePropertyImplementation(io::Printer * printer) const313 void SingleFieldGenerator::GeneratePropertyImplementation(
314 io::Printer* printer) const {
315 auto vars = printer->WithVars(variables_);
316 if (WantsHasProperty()) {
317 printer->Emit("@dynamic has$capitalized_name$, $name$;\n");
318 } else {
319 printer->Emit("@dynamic $name$;\n");
320 }
321 }
322
RuntimeUsesHasBit() const323 bool SingleFieldGenerator::RuntimeUsesHasBit() const {
324 if (descriptor_->real_containing_oneof()) {
325 // The oneof tracks what is set instead.
326 return false;
327 }
328 return true;
329 }
330
ObjCObjFieldGenerator(const FieldDescriptor * descriptor,const GenerationOptions & generation_options)331 ObjCObjFieldGenerator::ObjCObjFieldGenerator(
332 const FieldDescriptor* descriptor,
333 const GenerationOptions& generation_options)
334 : SingleFieldGenerator(descriptor, generation_options) {
335 variables_["property_storage_attribute"] = "strong";
336 if (IsRetainedName(variables_["name"])) {
337 variables_["storage_attribute"] = " NS_RETURNS_NOT_RETAINED";
338 }
339 }
340
GenerateFieldStorageDeclaration(io::Printer * printer) const341 void ObjCObjFieldGenerator::GenerateFieldStorageDeclaration(
342 io::Printer* printer) const {
343 auto vars = printer->WithVars(variables_);
344 printer->Emit("$storage_type$$name$;\n");
345 }
346
GeneratePropertyDeclaration(io::Printer * printer) const347 void ObjCObjFieldGenerator::GeneratePropertyDeclaration(
348 io::Printer* printer) const {
349 // Differs from SingleFieldGenerator::GeneratePropertyDeclaration() in that
350 // it uses pointers and deals with Objective-C's rules around storage name
351 // conventions (init*, new*, etc.)
352
353 auto vars = printer->WithVars(variables_);
354 printer->Emit({{"comments",
355 [&] {
356 EmitCommentsString(printer, generation_options_,
357 descriptor_);
358 }}},
359 R"objc(
360 $comments$
361 @property(nonatomic, readwrite, $property_storage_attribute$, null_resettable) $property_type$$name$$storage_attribute$$ deprecated_attribute$;
362 )objc");
363 if (WantsHasProperty()) {
364 printer->Emit(R"objc(
365 /** Test to see if @c $name$ has been set. */
366 @property(nonatomic, readwrite) BOOL has$capitalized_name$$ deprecated_attribute$;
367 )objc");
368 }
369 if (IsInitName(variables_.find("name")->second)) {
370 // If property name starts with init we need to annotate it to get past ARC.
371 // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
372 printer->Emit(R"objc(
373 - ($property_type$)$name$ GPB_METHOD_FAMILY_NONE$ deprecated_attribute$;
374 )objc");
375 }
376 printer->Emit("\n");
377 }
378
RepeatedFieldGenerator(const FieldDescriptor * descriptor,const GenerationOptions & generation_options)379 RepeatedFieldGenerator::RepeatedFieldGenerator(
380 const FieldDescriptor* descriptor,
381 const GenerationOptions& generation_options)
382 : ObjCObjFieldGenerator(descriptor, generation_options) {}
383
GenerateFieldStorageDeclaration(io::Printer * printer) const384 void RepeatedFieldGenerator::GenerateFieldStorageDeclaration(
385 io::Printer* printer) const {
386 auto vars = printer->WithVars(variables_);
387 printer->Emit("$storage_type$$name$;\n");
388 }
389
GeneratePropertyImplementation(io::Printer * printer) const390 void RepeatedFieldGenerator::GeneratePropertyImplementation(
391 io::Printer* printer) const {
392 auto vars = printer->WithVars(variables_);
393 printer->Emit("@dynamic $name$, $name$_Count;\n");
394 }
395
GeneratePropertyDeclaration(io::Printer * printer) const396 void RepeatedFieldGenerator::GeneratePropertyDeclaration(
397 io::Printer* printer) const {
398 // Repeated fields don't need the has* properties, but they do expose a
399 // *Count (to check without autocreation). So for the field property we need
400 // the same logic as ObjCObjFieldGenerator::GeneratePropertyDeclaration() for
401 // dealing with needing Objective-C's rules around storage name conventions
402 // (init*, new*, etc.)
403
404 auto vars = printer->WithVars(variables_);
405 printer->Emit(
406 {{"comments",
407 [&] { EmitCommentsString(printer, generation_options_, descriptor_); }},
408 {"array_comment", [&] { EmitArrayComment(printer); }}},
409 R"objc(
410 $comments$
411 $array_comment$
412 @property(nonatomic, readwrite, strong, null_resettable) $property_type$$name$$storage_attribute$$ deprecated_attribute$;
413 /** The number of items in @c $name$ without causing the container to be created. */
414 @property(nonatomic, readonly) NSUInteger $name$_Count$ deprecated_attribute$;
415 )objc");
416 if (IsInitName(variables_.find("name")->second)) {
417 // If property name starts with init we need to annotate it to get past ARC.
418 // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
419 printer->Emit(R"objc(
420 - ($property_type$)$name$ GPB_METHOD_FAMILY_NONE$ deprecated_attribute$;
421 )objc");
422 }
423 printer->Emit("\n");
424 }
425
RuntimeUsesHasBit() const426 bool RepeatedFieldGenerator::RuntimeUsesHasBit() const {
427 return false; // The array (or map/dict) having anything is what is used.
428 }
429
EmitArrayComment(io::Printer * printer) const430 void RepeatedFieldGenerator::EmitArrayComment(io::Printer* printer) const {
431 // Nothing for the default
432 }
433
FieldGeneratorMap(const Descriptor * descriptor,const GenerationOptions & generation_options)434 FieldGeneratorMap::FieldGeneratorMap(
435 const Descriptor* descriptor, const GenerationOptions& generation_options)
436 : descriptor_(descriptor),
437 field_generators_(static_cast<size_t>(descriptor->field_count())) {
438 for (int i = 0; i < descriptor->field_count(); i++) {
439 field_generators_[i].reset(
440 FieldGenerator::Make(descriptor->field(i), generation_options));
441 }
442 }
443
get(const FieldDescriptor * field) const444 const FieldGenerator& FieldGeneratorMap::get(
445 const FieldDescriptor* field) const {
446 ABSL_CHECK_EQ(field->containing_type(), descriptor_);
447 return *field_generators_[field->index()];
448 }
449
CalculateHasBits()450 int FieldGeneratorMap::CalculateHasBits() {
451 int total_bits = 0;
452 for (int i = 0; i < descriptor_->field_count(); i++) {
453 if (field_generators_[i]->RuntimeUsesHasBit()) {
454 field_generators_[i]->SetRuntimeHasBit(total_bits);
455 ++total_bits;
456 } else {
457 field_generators_[i]->SetNoHasBit();
458 }
459 int extra_bits = field_generators_[i]->ExtraRuntimeHasBitsNeeded();
460 if (extra_bits) {
461 field_generators_[i]->SetExtraRuntimeHasBitsBase(total_bits);
462 total_bits += extra_bits;
463 }
464 }
465 return total_bits;
466 }
467
SetOneofIndexBase(int index_base)468 void FieldGeneratorMap::SetOneofIndexBase(int index_base) {
469 for (int i = 0; i < descriptor_->field_count(); i++) {
470 field_generators_[i]->SetOneofIndexBase(index_base);
471 }
472 }
473
DoesAnyFieldHaveNonZeroDefault() const474 bool FieldGeneratorMap::DoesAnyFieldHaveNonZeroDefault() const {
475 for (int i = 0; i < descriptor_->field_count(); i++) {
476 if (HasNonZeroDefaultValue(descriptor_->field(i))) {
477 return true;
478 }
479 }
480
481 return false;
482 }
483
484 } // namespace objectivec
485 } // namespace compiler
486 } // namespace protobuf
487 } // namespace google
488