From 0b8579237336f221711a0aac42400eb31a58fed3 Mon Sep 17 00:00:00 2001 From: Brian Duff Date: Mon, 30 Sep 2013 20:49:13 -0700 Subject: Add reftypes field generator option. This option generates fields as reference types, and serializes based on nullness. Change-Id: Ic32e0eebff59d14016cc9a19e15a9bb08ae0bba5 Signed-off-by: Brian Duff --- .../compiler/javanano/javanano_enum_field.cc | 18 +++- .../compiler/javanano/javanano_generator.cc | 10 +- .../protobuf/compiler/javanano/javanano_helpers.cc | 4 + .../protobuf/compiler/javanano/javanano_params.h | 11 +- .../compiler/javanano/javanano_primitive_field.cc | 18 +++- .../protobuf/unittest_reference_types_nano.proto | 116 +++++++++++++++++++++ 6 files changed, 167 insertions(+), 10 deletions(-) create mode 100644 src/google/protobuf/unittest_reference_types_nano.proto (limited to 'src') diff --git a/src/google/protobuf/compiler/javanano/javanano_enum_field.cc b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc index b30b9fb..acb8dc2 100644 --- a/src/google/protobuf/compiler/javanano/javanano_enum_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc @@ -58,8 +58,16 @@ void SetEnumVariables(const Params& params, (*variables)["capitalized_name"] = RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor)); (*variables)["number"] = SimpleItoa(descriptor->number()); - (*variables)["type"] = "int"; - (*variables)["default"] = DefaultValue(params, descriptor); + if (params.use_reference_types_for_primitives() + && !descriptor->is_repeated()) { + (*variables)["type"] = "java.lang.Integer"; + (*variables)["default"] = "null"; + } else { + (*variables)["type"] = "int"; + (*variables)["default"] = DefaultValue(params, descriptor); + } + (*variables)["repeated_default"] = + "com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY"; (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor)); (*variables)["tag_size"] = SimpleItoa( internal::WireFormat::TagSize(descriptor->number(), descriptor->type())); @@ -81,7 +89,7 @@ EnumFieldGenerator::~EnumFieldGenerator() {} void EnumFieldGenerator:: GenerateMembers(io::Printer* printer) const { printer->Print(variables_, - "public int $name$ = $default$;\n"); + "public $type$ $name$ = $default$;\n"); if (params_.generate_has()) { printer->Print(variables_, @@ -233,7 +241,7 @@ RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {} void RepeatedEnumFieldGenerator:: GenerateMembers(io::Printer* printer) const { printer->Print(variables_, - "public int[] $name$ = com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY;\n"); + "public $type$[] $name$ = $repeated_default$;\n"); if (descriptor_->options().packed()) { printer->Print(variables_, "private int $name$MemoizedSerializedSize;\n"); @@ -243,7 +251,7 @@ GenerateMembers(io::Printer* printer) const { void RepeatedEnumFieldGenerator:: GenerateClearCode(io::Printer* printer) const { printer->Print(variables_, - "$name$ = com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY;\n"); + "$name$ = $repeated_default$;\n"); } void RepeatedEnumFieldGenerator:: diff --git a/src/google/protobuf/compiler/javanano/javanano_generator.cc b/src/google/protobuf/compiler/javanano/javanano_generator.cc index 8ba3f50..48c3a21 100644 --- a/src/google/protobuf/compiler/javanano/javanano_generator.cc +++ b/src/google/protobuf/compiler/javanano/javanano_generator.cc @@ -124,15 +124,21 @@ bool JavaNanoGenerator::Generate(const FileDescriptor* file, params.set_java_enum_style(options[i].second == "java"); } else if (options[i].first == "optional_field_style") { params.set_optional_field_accessors(options[i].second == "accessors"); + params.set_use_reference_types_for_primitives(options[i].second == "reftypes"); } else { *error = "Ignore unknown javanano generator option: " + options[i].first; } } // Check illegal parameter combinations - if (params.generate_has() && params.optional_field_accessors()) { + // Note: the enum-like optional_field_style generator param ensures + // that we can never have illegal combinations of field styles + // (e.g. reftypes and accessors can't be on at the same time). + if (params.generate_has() + && (params.optional_field_accessors() + || params.use_reference_types_for_primitives())) { error->assign("java_nano_generate_has=true cannot be used in conjunction" - " with optional_field_style=accessors"); + " with optional_field_style=accessors or optional_field_style=reftypes"); return false; } diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.cc b/src/google/protobuf/compiler/javanano/javanano_helpers.cc index c424165..ed6dbd7 100644 --- a/src/google/protobuf/compiler/javanano/javanano_helpers.cc +++ b/src/google/protobuf/compiler/javanano/javanano_helpers.cc @@ -357,6 +357,10 @@ string DefaultValue(const Params& params, const FieldDescriptor* field) { return EmptyArrayName(params, field); } + if (params.use_reference_types_for_primitives()) { + return "null"; + } + // Switch on cpp_type since we need to know which default_value_* method // of FieldDescriptor to call. switch (field->cpp_type()) { diff --git a/src/google/protobuf/compiler/javanano/javanano_params.h b/src/google/protobuf/compiler/javanano/javanano_params.h index 5be5ff9..6e5379c 100644 --- a/src/google/protobuf/compiler/javanano/javanano_params.h +++ b/src/google/protobuf/compiler/javanano/javanano_params.h @@ -60,6 +60,7 @@ class Params { bool generate_has_; bool java_enum_style_; bool optional_field_accessors_; + bool use_reference_types_for_primitives_; public: Params(const string & base_name) : @@ -69,7 +70,8 @@ class Params { store_unknown_fields_(false), generate_has_(false), java_enum_style_(false), - optional_field_accessors_(false) { + optional_field_accessors_(false), + use_reference_types_for_primitives_(false) { } const string& base_name() const { @@ -177,6 +179,13 @@ class Params { bool optional_field_accessors() const { return optional_field_accessors_; } + + void set_use_reference_types_for_primitives(bool value) { + use_reference_types_for_primitives_ = value; + } + bool use_reference_types_for_primitives() const { + return use_reference_types_for_primitives_; + } }; } // namespace javanano diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc index 69664d3..ec93cef 100644 --- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc @@ -245,7 +245,12 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params param (*variables)["capitalized_name"] = RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor)); (*variables)["number"] = SimpleItoa(descriptor->number()); - (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor)); + if (params.use_reference_types_for_primitives() + && !descriptor->is_repeated()) { + (*variables)["type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor)); + } else { + (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor)); + } (*variables)["default"] = DefaultValue(params, descriptor); (*variables)["default_constant"] = FieldDefaultConstantName(descriptor); // For C++-string types (string and bytes), we might need to have @@ -254,7 +259,8 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params param // once into a "private static final" field and re-use that from // then on. if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_STRING && - !descriptor->default_value_string().empty()) { + !descriptor->default_value_string().empty() && + !params.use_reference_types_for_primitives()) { string default_value; if (descriptor->type() == FieldDescriptor::TYPE_BYTES) { default_value = strings::Substitute( @@ -315,6 +321,7 @@ GenerateMembers(io::Printer* printer) const { printer->Print(variables_, "private static final $type$ $default_constant$ = $default_constant_value$;\n"); } + printer->Print(variables_, "public $type$ $name$ = $default_copy_if_needed$;\n"); @@ -348,6 +355,13 @@ GenerateMergingCode(io::Printer* printer) const { void PrimitiveFieldGenerator:: GenerateSerializationConditional(io::Printer* printer) const { + if (params_.use_reference_types_for_primitives()) { + // For reference type mode, serialize based on equality + // to null. + printer->Print(variables_, + "if (this.$name$ != null) {\n"); + return; + } if (params_.generate_has()) { printer->Print(variables_, "if (has$capitalized_name$ || "); diff --git a/src/google/protobuf/unittest_reference_types_nano.proto b/src/google/protobuf/unittest_reference_types_nano.proto new file mode 100644 index 0000000..2b24615 --- /dev/null +++ b/src/google/protobuf/unittest_reference_types_nano.proto @@ -0,0 +1,116 @@ +package protobuf_unittest; + +option java_package = "com.google.protobuf.nano"; +option java_outer_classname = "NanoReferenceTypes"; + +message TestAllTypesNano { + + enum NestedEnum { + FOO = 1; + BAR = 2; + BAZ = 3; + } + + message NestedMessage { + optional int32 foo = 1; + } + + // Singular + optional int32 optional_int32 = 1; + optional int64 optional_int64 = 2; + optional uint32 optional_uint32 = 3; + optional uint64 optional_uint64 = 4; + optional sint32 optional_sint32 = 5; + optional sint64 optional_sint64 = 6; + optional fixed32 optional_fixed32 = 7; + optional fixed64 optional_fixed64 = 8; + optional sfixed32 optional_sfixed32 = 9; + optional sfixed64 optional_sfixed64 = 10; + optional float optional_float = 11; + optional double optional_double = 12; + optional bool optional_bool = 13; + optional string optional_string = 14; + optional bytes optional_bytes = 15; + + optional group OptionalGroup = 16 { + optional int32 a = 17; + } + + optional NestedMessage optional_nested_message = 18; + + optional NestedEnum optional_nested_enum = 21; + + optional string optional_string_piece = 24 [ctype=STRING_PIECE]; + optional string optional_cord = 25 [ctype=CORD]; + + // Repeated + repeated int32 repeated_int32 = 31; + repeated int64 repeated_int64 = 32; + repeated uint32 repeated_uint32 = 33; + repeated uint64 repeated_uint64 = 34; + repeated sint32 repeated_sint32 = 35; + repeated sint64 repeated_sint64 = 36; + repeated fixed32 repeated_fixed32 = 37; + repeated fixed64 repeated_fixed64 = 38; + repeated sfixed32 repeated_sfixed32 = 39; + repeated sfixed64 repeated_sfixed64 = 40; + repeated float repeated_float = 41; + repeated double repeated_double = 42; + repeated bool repeated_bool = 43; + repeated string repeated_string = 44; + repeated bytes repeated_bytes = 45; + + repeated group RepeatedGroup = 46 { + optional int32 a = 47; + } + + repeated NestedMessage repeated_nested_message = 48; + + repeated NestedEnum repeated_nested_enum = 51; + + repeated string repeated_string_piece = 54 [ctype=STRING_PIECE]; + repeated string repeated_cord = 55 [ctype=CORD]; + + // Repeated packed + repeated int32 repeated_packed_int32 = 87 [packed=true]; + repeated sfixed64 repeated_packed_sfixed64 = 88 [packed=true]; + + repeated NestedEnum repeated_packed_nested_enum = 89 [packed=true]; + + // Singular with defaults + optional int32 default_int32 = 61 [default = 41 ]; + optional int64 default_int64 = 62 [default = 42 ]; + optional uint32 default_uint32 = 63 [default = 43 ]; + optional uint64 default_uint64 = 64 [default = 44 ]; + optional sint32 default_sint32 = 65 [default = -45 ]; + optional sint64 default_sint64 = 66 [default = 46 ]; + optional fixed32 default_fixed32 = 67 [default = 47 ]; + optional fixed64 default_fixed64 = 68 [default = 48 ]; + optional sfixed32 default_sfixed32 = 69 [default = 49 ]; + optional sfixed64 default_sfixed64 = 70 [default = -50 ]; + optional float default_float = 71 [default = 51.5 ]; + optional double default_double = 72 [default = 52e3 ]; + optional bool default_bool = 73 [default = true ]; + optional string default_string = 74 [default = "hello"]; + optional bytes default_bytes = 75 [default = "world"]; + + + optional float default_float_inf = 97 [default = inf]; + optional float default_float_neg_inf = 98 [default = -inf]; + optional float default_float_nan = 99 [default = nan]; + optional double default_double_inf = 100 [default = inf]; + optional double default_double_neg_inf = 101 [default = -inf]; + optional double default_double_nan = 102 [default = nan]; + +} + +message ForeignMessageNano { + optional int32 c = 1; +} + +enum ForeignEnumNano { + FOREIGN_NANO_FOO = 4; + FOREIGN_NANO_BAR = 5; + FOREIGN_NANO_BAZ = 6; +} + -- cgit v1.1