From ca29ed106fac28c2d00b5dd0fc6dcd3b07be0a8d Mon Sep 17 00:00:00 2001 From: Protobuf Team Bot Date: Fri, 24 Jan 2025 05:47:18 -0800 Subject: [PATCH] Objectivec: Refactor to use io::Printer::Sub. This allows us to use `io::Printer::Sub`'s more advanced features, like automatically adding references to symbols in output metadata. We need a new utility class because a lot of code in this generator depends on overwriting placeholders, as well as looking up existing ones. PiperOrigin-RevId: 719268162 --- .../compiler/objectivec/enum_field.cc | 33 +++--- .../protobuf/compiler/objectivec/field.cc | 108 +++++++++--------- .../protobuf/compiler/objectivec/field.h | 8 +- .../protobuf/compiler/objectivec/helpers.h | 46 ++++++++ .../protobuf/compiler/objectivec/map_field.cc | 19 +-- .../compiler/objectivec/message_field.cc | 15 ++- .../compiler/objectivec/primitive_field.cc | 8 +- 7 files changed, 144 insertions(+), 93 deletions(-) diff --git a/src/google/protobuf/compiler/objectivec/enum_field.cc b/src/google/protobuf/compiler/objectivec/enum_field.cc index a51bcb3978641..0de12e14a29d0 100644 --- a/src/google/protobuf/compiler/objectivec/enum_field.cc +++ b/src/google/protobuf/compiler/objectivec/enum_field.cc @@ -10,11 +10,11 @@ #include #include "absl/container/btree_set.h" -#include "absl/container/flat_hash_map.h" #include "absl/container/flat_hash_set.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "google/protobuf/compiler/objectivec/field.h" +#include "google/protobuf/compiler/objectivec/helpers.h" #include "google/protobuf/compiler/objectivec/names.h" #include "google/protobuf/compiler/objectivec/options.h" #include "google/protobuf/descriptor.h" @@ -27,13 +27,12 @@ namespace objectivec { namespace { -void SetEnumVariables( - const FieldDescriptor* descriptor, - const GenerationOptions& generation_options, - absl::flat_hash_map* variables) { +void SetEnumVariables(const FieldDescriptor* descriptor, + const GenerationOptions& generation_options, + SubstitutionMap& variables) { const std::string type = EnumName(descriptor->enum_type()); const std::string enum_desc_func = absl::StrCat(type, "_EnumDescriptor"); - (*variables)["enum_name"] = type; + variables.Set("enum_name", type); // When using fwd decls, for non repeated fields, if it was defined in a // different file, the property decls need to use "enum NAME" rather than just // "NAME" to support the forward declaration of the enums. @@ -41,16 +40,16 @@ void SetEnumVariables( !descriptor->is_repeated() && !IsProtobufLibraryBundledProtoFile(descriptor->enum_type()->file()) && (descriptor->file() != descriptor->enum_type()->file())) { - (*variables)["property_type"] = absl::StrCat("enum ", type, " "); + variables.Set("property_type", absl::StrCat("enum ", type, " ")); } - (*variables)["enum_verifier"] = absl::StrCat(type, "_IsValidValue"); - (*variables)["enum_desc_func"] = enum_desc_func; + variables.Set("enum_verifier", absl::StrCat(type, "_IsValidValue")); + variables.Set("enum_desc_func", enum_desc_func); - (*variables)["dataTypeSpecific_name"] = "enumDescFunc"; - (*variables)["dataTypeSpecific_value"] = enum_desc_func; + variables.Set("dataTypeSpecific_name", "enumDescFunc"); + variables.Set("dataTypeSpecific_value", enum_desc_func); const Descriptor* msg_descriptor = descriptor->containing_type(); - (*variables)["owning_message_class"] = ClassName(msg_descriptor); + variables.Set("owning_message_class", ClassName(msg_descriptor)); } } // namespace @@ -58,7 +57,7 @@ EnumFieldGenerator::EnumFieldGenerator( const FieldDescriptor* descriptor, const GenerationOptions& generation_options) : SingleFieldGenerator(descriptor, generation_options) { - SetEnumVariables(descriptor, generation_options, &variables_); + SetEnumVariables(descriptor, generation_options, variables_); } void EnumFieldGenerator::GenerateCFunctionDeclarations( @@ -67,7 +66,7 @@ void EnumFieldGenerator::GenerateCFunctionDeclarations( return; } - auto vars = printer->WithVars(variables_); + auto vars = variables_.Install(printer); printer->Emit(R"objc( /** * Fetches the raw value of a @c $owning_message_class$'s @c $name$ property, even @@ -90,7 +89,7 @@ void EnumFieldGenerator::GenerateCFunctionImplementations( return; } - auto vars = printer->WithVars(variables_); + auto vars = variables_.Install(printer); printer->Emit(R"objc( int32_t $owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message) { GPBDescriptor *descriptor = [$owning_message_class$ descriptor]; @@ -134,11 +133,11 @@ RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator( const FieldDescriptor* descriptor, const GenerationOptions& generation_options) : RepeatedFieldGenerator(descriptor, generation_options) { - SetEnumVariables(descriptor, generation_options, &variables_); + SetEnumVariables(descriptor, generation_options, variables_); } void RepeatedEnumFieldGenerator::EmitArrayComment(io::Printer* printer) const { - auto vars = printer->WithVars(variables_); + auto vars = variables_.Install(printer); printer->Emit(R"objc( // |$name$| contains |$enum_name$| )objc"); diff --git a/src/google/protobuf/compiler/objectivec/field.cc b/src/google/protobuf/compiler/objectivec/field.cc index 497b808fa615b..c6c826c686717 100644 --- a/src/google/protobuf/compiler/objectivec/field.cc +++ b/src/google/protobuf/compiler/objectivec/field.cc @@ -12,7 +12,6 @@ #include #include "absl/container/btree_set.h" -#include "absl/container/flat_hash_map.h" #include "absl/container/flat_hash_set.h" #include "absl/log/absl_check.h" #include "absl/log/absl_log.h" @@ -35,9 +34,8 @@ namespace objectivec { namespace { -void SetCommonFieldVariables( - const FieldDescriptor* descriptor, - absl::flat_hash_map* variables) { +void SetCommonFieldVariables(const FieldDescriptor* descriptor, + SubstitutionMap& variables) { std::string camel_case_name = FieldName(descriptor); std::string raw_field_name; if (internal::cpp::IsGroupLike(*descriptor)) { @@ -51,26 +49,31 @@ void SetCommonFieldVariables( const bool needs_custom_name = (raw_field_name != un_camel_case_name); const std::string& classname = ClassName(descriptor->containing_type()); - (*variables)["classname"] = classname; - (*variables)["name"] = camel_case_name; + variables.Set("classname", classname); + variables.Set("name", camel_case_name); + const std::string& capitalized_name = FieldNameCapitalized(descriptor); - (*variables)["capitalized_name"] = capitalized_name; - (*variables)["raw_field_name"] = raw_field_name; - (*variables)["field_number_name"] = - absl::StrCat(classname, "_FieldNumber_", capitalized_name); - (*variables)["field_number"] = absl::StrCat(descriptor->number()); - (*variables)["property_type"] = FieldObjCType( - descriptor, static_cast( - kFieldObjCTypeOptions_IncludeSpaceAfterBasicTypes | - kFieldObjCTypeOptions_IncludeSpaceBeforeStar)); - (*variables)["storage_type"] = FieldObjCType( - descriptor, static_cast( - kFieldObjCTypeOptions_IncludeSpaceAfterBasicTypes | - kFieldObjCTypeOptions_OmitLightweightGenerics | - kFieldObjCTypeOptions_IncludeSpaceBeforeStar)); - (*variables)["field_type"] = GetCapitalizedType(descriptor); - (*variables)["deprecated_attribute"] = - GetOptionalDeprecatedAttribute(descriptor); + variables.Set("capitalized_name", capitalized_name); + variables.Set("raw_field_name", raw_field_name); + variables.Set("field_number_name", + absl::StrCat(classname, "_FieldNumber_", capitalized_name)); + variables.Set("field_number", absl::StrCat(descriptor->number())); + variables.Set( + "property_type", + FieldObjCType(descriptor, + static_cast( + kFieldObjCTypeOptions_IncludeSpaceAfterBasicTypes | + kFieldObjCTypeOptions_IncludeSpaceBeforeStar))); + variables.Set( + "storage_type", + FieldObjCType(descriptor, + static_cast( + kFieldObjCTypeOptions_IncludeSpaceAfterBasicTypes | + kFieldObjCTypeOptions_OmitLightweightGenerics | + kFieldObjCTypeOptions_IncludeSpaceBeforeStar))); + variables.Set("field_type", GetCapitalizedType(descriptor)); + variables.Set("deprecated_attribute", + GetOptionalDeprecatedAttribute(descriptor)); std::vector field_flags; if (descriptor->is_repeated()) field_flags.push_back("GPBFieldRepeated"); if (descriptor->is_required()) field_flags.push_back("GPBFieldRequired"); @@ -96,20 +99,21 @@ void SetCommonFieldVariables( field_flags.push_back("GPBFieldClearHasIvarOnZero"); } - (*variables)["fieldflags"] = BuildFlagsString(FLAGTYPE_FIELD, field_flags); + variables.Set("fieldflags", BuildFlagsString(FLAGTYPE_FIELD, field_flags)); - (*variables)["default"] = DefaultValue(descriptor); - (*variables)["default_name"] = GPBGenericValueFieldName(descriptor); + variables.Set("default", DefaultValue(descriptor)); + variables.Set("default_name", GPBGenericValueFieldName(descriptor)); - (*variables)["dataTypeSpecific_name"] = "clazz"; - (*variables)["dataTypeSpecific_value"] = "Nil"; + variables.Set("dataTypeSpecific_name", "clazz"); + variables.Set("dataTypeSpecific_value", "Nil"); - (*variables)["storage_offset_value"] = absl::StrCat( - "(uint32_t)offsetof(", classname, "__storage_, ", camel_case_name, ")"); - (*variables)["storage_offset_comment"] = ""; + variables.Set("storage_offset_value", + absl::StrCat("(uint32_t)offsetof(", classname, "__storage_, ", + camel_case_name, ")")); + variables.Set("storage_offset_comment", ""); // Clear some common things so they can be set just when needed. - (*variables)["storage_attribute"] = ""; + variables.Set("storage_attribute", ""); } bool HasNonZeroDefaultValue(const FieldDescriptor* field) { @@ -192,11 +196,11 @@ FieldGenerator* FieldGenerator::Make( FieldGenerator::FieldGenerator(const FieldDescriptor* descriptor, const GenerationOptions& generation_options) : descriptor_(descriptor), generation_options_(generation_options) { - SetCommonFieldVariables(descriptor, &variables_); + SetCommonFieldVariables(descriptor, variables_); } void FieldGenerator::GenerateFieldNumberConstant(io::Printer* printer) const { - auto vars = printer->WithVars(variables_); + auto vars = variables_.Install(printer); printer->Emit("$field_number_name$ = $field_number$,\n"); } @@ -228,7 +232,7 @@ void FieldGenerator::DetermineNeededFiles( void FieldGenerator::GenerateFieldDescription(io::Printer* printer, bool include_default) const { // Printed in the same order as the structure decl. - auto vars = printer->WithVars(variables_); + auto vars = variables_.Install(printer); printer->Emit( {{"prefix", include_default ? ".core" : ""}, {"maybe_default", @@ -252,10 +256,12 @@ void FieldGenerator::GenerateFieldDescription(io::Printer* printer, } void FieldGenerator::SetRuntimeHasBit(int has_index) { - variables_["has_index"] = absl::StrCat(has_index); + variables_.Set("has_index", has_index); } -void FieldGenerator::SetNoHasBit() { variables_["has_index"] = "GPBNoHasBit"; } +void FieldGenerator::SetNoHasBit() { + variables_.Set("has_index", "GPBNoHasBit"); +} int FieldGenerator::ExtraRuntimeHasBitsNeeded() const { return 0; } @@ -269,7 +275,7 @@ void FieldGenerator::SetOneofIndexBase(int index_base) { if (oneof != nullptr) { int index = oneof->index() + index_base; // Flip the sign to mark it as a oneof. - variables_["has_index"] = absl::StrCat(-index); + variables_.Set("has_index", -index); } } @@ -286,13 +292,13 @@ SingleFieldGenerator::SingleFieldGenerator( void SingleFieldGenerator::GenerateFieldStorageDeclaration( io::Printer* printer) const { - auto vars = printer->WithVars(variables_); + auto vars = variables_.Install(printer); printer->Emit("$storage_type$$name$;\n"); } void SingleFieldGenerator::GeneratePropertyDeclaration( io::Printer* printer) const { - auto vars = printer->WithVars(variables_); + auto vars = variables_.Install(printer); printer->Emit({{"comments", [&] { EmitCommentsString(printer, generation_options_, @@ -312,7 +318,7 @@ void SingleFieldGenerator::GeneratePropertyDeclaration( void SingleFieldGenerator::GeneratePropertyImplementation( io::Printer* printer) const { - auto vars = printer->WithVars(variables_); + auto vars = variables_.Install(printer); if (WantsHasProperty()) { printer->Emit("@dynamic has$capitalized_name$, $name$;\n"); } else { @@ -332,15 +338,15 @@ ObjCObjFieldGenerator::ObjCObjFieldGenerator( const FieldDescriptor* descriptor, const GenerationOptions& generation_options) : SingleFieldGenerator(descriptor, generation_options) { - variables_["property_storage_attribute"] = "strong"; - if (IsRetainedName(variables_["name"])) { - variables_["storage_attribute"] = " NS_RETURNS_NOT_RETAINED"; + variables_.Set("property_storage_attribute", "strong"); + if (IsRetainedName(variable("name"))) { + variables_.Set("storage_attribute", " NS_RETURNS_NOT_RETAINED"); } } void ObjCObjFieldGenerator::GenerateFieldStorageDeclaration( io::Printer* printer) const { - auto vars = printer->WithVars(variables_); + auto vars = variables_.Install(printer); printer->Emit("$storage_type$$name$;\n"); } @@ -350,7 +356,7 @@ void ObjCObjFieldGenerator::GeneratePropertyDeclaration( // it uses pointers and deals with Objective-C's rules around storage name // conventions (init*, new*, etc.) - auto vars = printer->WithVars(variables_); + auto vars = variables_.Install(printer); printer->Emit({{"comments", [&] { EmitCommentsString(printer, generation_options_, @@ -366,7 +372,7 @@ void ObjCObjFieldGenerator::GeneratePropertyDeclaration( @property(nonatomic, readwrite) BOOL has$capitalized_name$$ deprecated_attribute$; )objc"); } - if (IsInitName(variables_.find("name")->second)) { + if (IsInitName(variable("name"))) { // If property name starts with init we need to annotate it to get past ARC. // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227 printer->Emit(R"objc( @@ -383,13 +389,13 @@ RepeatedFieldGenerator::RepeatedFieldGenerator( void RepeatedFieldGenerator::GenerateFieldStorageDeclaration( io::Printer* printer) const { - auto vars = printer->WithVars(variables_); + auto vars = variables_.Install(printer); printer->Emit("$storage_type$$name$;\n"); } void RepeatedFieldGenerator::GeneratePropertyImplementation( io::Printer* printer) const { - auto vars = printer->WithVars(variables_); + auto vars = variables_.Install(printer); printer->Emit("@dynamic $name$, $name$_Count;\n"); } @@ -401,7 +407,7 @@ void RepeatedFieldGenerator::GeneratePropertyDeclaration( // dealing with needing Objective-C's rules around storage name conventions // (init*, new*, etc.) - auto vars = printer->WithVars(variables_); + auto vars = variables_.Install(printer); printer->Emit( {{"comments", [&] { EmitCommentsString(printer, generation_options_, descriptor_); }}, @@ -413,7 +419,7 @@ void RepeatedFieldGenerator::GeneratePropertyDeclaration( /** The number of items in @c $name$ without causing the container to be created. */ @property(nonatomic, readonly) NSUInteger $name$_Count$ deprecated_attribute$; )objc"); - if (IsInitName(variables_.find("name")->second)) { + if (IsInitName(variable("name"))) { // If property name starts with init we need to annotate it to get past ARC. // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227 printer->Emit(R"objc( diff --git a/src/google/protobuf/compiler/objectivec/field.h b/src/google/protobuf/compiler/objectivec/field.h index 06e08e1f0a04b..428384312f654 100644 --- a/src/google/protobuf/compiler/objectivec/field.h +++ b/src/google/protobuf/compiler/objectivec/field.h @@ -13,10 +13,10 @@ #include #include "absl/container/btree_set.h" -#include "absl/container/flat_hash_map.h" #include "absl/container/flat_hash_set.h" #include "absl/strings/match.h" #include "absl/strings/string_view.h" +#include "google/protobuf/compiler/objectivec/helpers.h" #include "google/protobuf/compiler/objectivec/options.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/io/printer.h" @@ -70,8 +70,8 @@ class FieldGenerator { virtual void SetExtraRuntimeHasBitsBase(int index_base); void SetOneofIndexBase(int index_base); - std::string variable(const char* key) const { - return variables_.find(key)->second; + std::string variable(absl::string_view key) const { + return variables_.Value(key); } bool needs_textformat_name_support() const { @@ -89,7 +89,7 @@ class FieldGenerator { const FieldDescriptor* descriptor_; const GenerationOptions& generation_options_; - absl::flat_hash_map variables_; + SubstitutionMap variables_; }; class SingleFieldGenerator : public FieldGenerator { diff --git a/src/google/protobuf/compiler/objectivec/helpers.h b/src/google/protobuf/compiler/objectivec/helpers.h index edd0c1c096710..6d23542b9ee87 100644 --- a/src/google/protobuf/compiler/objectivec/helpers.h +++ b/src/google/protobuf/compiler/objectivec/helpers.h @@ -10,9 +10,13 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__ #define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__ +#include #include +#include #include +#include "absl/container/flat_hash_map.h" +#include "absl/log/absl_log.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "google/protobuf/compiler/objectivec/options.h" @@ -156,6 +160,48 @@ std::string GetOptionalDeprecatedAttribute( bool HasWKTWithObjCCategory(const FileDescriptor* file); bool IsWKTWithObjCCategory(const Descriptor* descriptor); +// A map of `io::Printer::Sub`s, where entries can be overwritten. +// +// This exists because `io::Printer::WithVars` only accepts a flat list of +// substitutions, and will break if there are any duplicated entries. At the +// same time, a lot of code in this generator depends on modifying, overwriting, +// and looking up variables in the list of substitutions. +class SubstitutionMap { + public: + SubstitutionMap() = default; + SubstitutionMap(const SubstitutionMap&) = delete; + SubstitutionMap& operator=(const SubstitutionMap&) = delete; + + auto Install(io::Printer* printer) const { return printer->WithVars(subs_); } + + std::string Value(absl::string_view key) const { + if (auto it = subs_map_.find(key); it != subs_map_.end()) { + return std::string(subs_.at(it->second).value()); + } + ABSL_LOG(FATAL) << " Unknown variable: " << key; + } + + // Sets or replaces a variable in the map. + // All arguments are forwarded to `io::Printer::Sub`. + template + void Set(std::string key, Args&&... args); + + private: + std::vector subs_; + absl::flat_hash_map subs_map_; +}; + +template +void SubstitutionMap::Set(std::string key, Args&&... args) { + if (auto [it, inserted] = subs_map_.try_emplace(key, subs_.size()); + !inserted) { + subs_[it->second] = + io::Printer::Sub(std::move(key), std::forward(args)...); + } else { + subs_.emplace_back(std::move(key), std::forward(args)...); + } +} + } // namespace objectivec } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/objectivec/map_field.cc b/src/google/protobuf/compiler/objectivec/map_field.cc index 27f4db69ab98e..3eaeae82d7229 100644 --- a/src/google/protobuf/compiler/objectivec/map_field.cc +++ b/src/google/protobuf/compiler/objectivec/map_field.cc @@ -40,16 +40,17 @@ MapFieldGenerator::MapFieldGenerator( FieldGenerator::Make(value_descriptor, generation_options)); // Pull over some variables_ from the value. - variables_["field_type"] = value_field_generator_->variable("field_type"); - variables_["default"] = value_field_generator_->variable("default"); - variables_["default_name"] = value_field_generator_->variable("default_name"); + variables_.Set("field_type", value_field_generator_->variable("field_type")); + variables_.Set("default", value_field_generator_->variable("default")); + variables_.Set("default_name", + value_field_generator_->variable("default_name")); // Build custom field flags. std::vector field_flags; field_flags.push_back( absl::StrCat("GPBFieldMapKey", GetCapitalizedType(key_descriptor))); // Pull over the current text format custom name values that was calculated. - if (absl::StrContains(variables_["fieldflags"], + if (absl::StrContains(variable("fieldflags"), "GPBFieldTextFormatNameCustom")) { field_flags.push_back("GPBFieldTextFormatNameCustom"); } @@ -66,12 +67,12 @@ MapFieldGenerator::MapFieldGenerator( } } - variables_["fieldflags"] = BuildFlagsString(FLAGTYPE_FIELD, field_flags); + variables_.Set("fieldflags", BuildFlagsString(FLAGTYPE_FIELD, field_flags)); - variables_["dataTypeSpecific_name"] = - value_field_generator_->variable("dataTypeSpecific_name"); - variables_["dataTypeSpecific_value"] = - value_field_generator_->variable("dataTypeSpecific_value"); + variables_.Set("dataTypeSpecific_name", + value_field_generator_->variable("dataTypeSpecific_name")); + variables_.Set("dataTypeSpecific_value", + value_field_generator_->variable("dataTypeSpecific_value")); } void MapFieldGenerator::EmitArrayComment(io::Printer* printer) const { diff --git a/src/google/protobuf/compiler/objectivec/message_field.cc b/src/google/protobuf/compiler/objectivec/message_field.cc index cac852cd93009..f13c3aab16b83 100644 --- a/src/google/protobuf/compiler/objectivec/message_field.cc +++ b/src/google/protobuf/compiler/objectivec/message_field.cc @@ -27,15 +27,14 @@ namespace objectivec { namespace { -void SetMessageVariables( - const FieldDescriptor* descriptor, - absl::flat_hash_map* variables) { +void SetMessageVariables(const FieldDescriptor* descriptor, + SubstitutionMap& variables) { const std::string& message_type = ClassName(descriptor->message_type()); const std::string& containing_class = ClassName(descriptor->containing_type()); - (*variables)["msg_type"] = message_type; - (*variables)["containing_class"] = containing_class; - (*variables)["dataTypeSpecific_value"] = ObjCClass(message_type); + variables.Set("msg_type", message_type); + variables.Set("containing_class", containing_class); + variables.Set("dataTypeSpecific_value", ObjCClass(message_type)); } } // namespace @@ -44,7 +43,7 @@ MessageFieldGenerator::MessageFieldGenerator( const FieldDescriptor* descriptor, const GenerationOptions& generation_options) : ObjCObjFieldGenerator(descriptor, generation_options) { - SetMessageVariables(descriptor, &variables_); + SetMessageVariables(descriptor, variables_); } void MessageFieldGenerator::DetermineForwardDeclarations( @@ -78,7 +77,7 @@ RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator( const FieldDescriptor* descriptor, const GenerationOptions& generation_options) : RepeatedFieldGenerator(descriptor, generation_options) { - SetMessageVariables(descriptor, &variables_); + SetMessageVariables(descriptor, variables_); } void RepeatedMessageFieldGenerator::DetermineForwardDeclarations( diff --git a/src/google/protobuf/compiler/objectivec/primitive_field.cc b/src/google/protobuf/compiler/objectivec/primitive_field.cc index b9428a85b1955..7a4b9cfa3071d 100644 --- a/src/google/protobuf/compiler/objectivec/primitive_field.cc +++ b/src/google/protobuf/compiler/objectivec/primitive_field.cc @@ -47,9 +47,9 @@ int PrimitiveFieldGenerator::ExtraRuntimeHasBitsNeeded() const { void PrimitiveFieldGenerator::SetExtraRuntimeHasBitsBase(int index_base) { if (GetObjectiveCType(descriptor_) == OBJECTIVECTYPE_BOOLEAN) { // Set into the offset the has bit to use for the actual value. - variables_["storage_offset_value"] = absl::StrCat(index_base); - variables_["storage_offset_comment"] = - " // Stored in _has_storage_ to save space."; + variables_.Set("storage_offset_value", absl::StrCat(index_base)); + variables_.Set("storage_offset_comment", + " // Stored in _has_storage_ to save space."); } } @@ -57,7 +57,7 @@ PrimitiveObjFieldGenerator::PrimitiveObjFieldGenerator( const FieldDescriptor* descriptor, const GenerationOptions& generation_options) : ObjCObjFieldGenerator(descriptor, generation_options) { - variables_["property_storage_attribute"] = "copy"; + variables_.Set("property_storage_attribute", "copy"); } RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(