• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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