From 1479c7ab1b72346df56b95816a58234ba2ceb9cd Mon Sep 17 00:00:00 2001 From: Max Cai Date: Tue, 24 Sep 2013 17:40:37 +0100 Subject: [PATCH] Implement enum_style=java option. This javanano_out command line option creates a container interface at the normal place where the enum constants would reside, per enum definition. The java_multiple_files flag would now affect the file- scope enums with the shells. If the flag is true then file-scope container interfaces are created in their own files. Change-Id: Id52258fcff8d3dee9db8f3d8022147a811bf3565 --- java/README.txt | 17 +++++-- .../java/com/google/protobuf/NanoTest.java | 13 +++++ .../compiler/javanano/javanano_enum.cc | 41 +++++++++++----- .../compiler/javanano/javanano_file.cc | 15 ++++++ .../compiler/javanano/javanano_helpers.cc | 28 ++++++++--- .../unittest_enum_class_multiple_nano.proto | 48 +++++++++++++++++++ .../protobuf/unittest_enum_class_nano.proto | 48 +++++++++++++++++++ 7 files changed, 187 insertions(+), 23 deletions(-) create mode 100644 src/google/protobuf/unittest_enum_class_multiple_nano.proto create mode 100644 src/google/protobuf/unittest_enum_class_nano.proto diff --git a/java/README.txt b/java/README.txt index 9728f48e4c..e2e698e168 100644 --- a/java/README.txt +++ b/java/README.txt @@ -93,8 +93,9 @@ Micro version The runtime and generated code for MICRO_RUNTIME is smaller because it does not include support for the descriptor and reflection, and enums are generated as integer constants in -the parent message or the file's outer class. Also, not -currently supported are packed repeated elements or +the parent message or the file's outer class, with no +protection against invalid values set to enum fields. Also, +not currently supported are packed repeated elements or extensions. To create a jar file for the runtime and run tests invoke @@ -409,12 +410,20 @@ Nano version ============================ Nano is even smaller than micro, especially in the number of generated -functions. It is like micro except: +functions. It is like micro: + +- No support for descriptors and reflection; +- Enum constants are integers with no protection against invalid + values set to enum fields. + +Except: - Setter/getter/hazzer/clearer functions are opt-in. - If not opted in, has state is not available. Serialization outputs - all fields not equal to their default. (See important implications + all fields not equal to their default. (See important implications below.) +- Enum constants can be generated into container interfaces bearing + the enum's name (so the referencing code is in Java style). - CodedInputStreamMicro is renamed to CodedInputByteBufferNano and can only take byte[] (not InputStream). - Similar rename from CodedOutputStreamMicro to diff --git a/java/src/test/java/com/google/protobuf/NanoTest.java b/java/src/test/java/com/google/protobuf/NanoTest.java index fb6cccb2ff..848361953b 100644 --- a/java/src/test/java/com/google/protobuf/NanoTest.java +++ b/java/src/test/java/com/google/protobuf/NanoTest.java @@ -31,8 +31,11 @@ package com.google.protobuf; import com.google.protobuf.nano.CodedInputByteBufferNano; +import com.google.protobuf.nano.EnumClassNanoMultiple; +import com.google.protobuf.nano.EnumClassNanos; import com.google.protobuf.nano.Extensions; import com.google.protobuf.nano.Extensions.AnotherMessage; +import com.google.protobuf.nano.FileScopeEnumMultiple; import com.google.protobuf.nano.FileScopeEnumRefNano; import com.google.protobuf.nano.InternalNano; import com.google.protobuf.nano.MessageNano; @@ -2391,6 +2394,16 @@ public class NanoTest extends TestCase { assertEquals(0, newMsg.id); } + public void testNanoJavaEnumStyle() throws Exception { + EnumClassNanos.EnumClassNano msg = new EnumClassNanos.EnumClassNano(); + assertEquals(EnumClassNanos.FileScopeEnum.ONE, msg.one); + assertEquals(EnumClassNanos.EnumClassNano.MessageScopeEnum.TWO, msg.two); + + EnumClassNanoMultiple msg2 = new EnumClassNanoMultiple(); + assertEquals(FileScopeEnumMultiple.THREE, msg2.three); + assertEquals(EnumClassNanoMultiple.MessageScopeEnumMultiple.FOUR, msg2.four); + } + /** * Tests that fields with a default value of NaN are not serialized when * set to NaN. This is a special case as NaN != NaN, so normal equality diff --git a/src/google/protobuf/compiler/javanano/javanano_enum.cc b/src/google/protobuf/compiler/javanano/javanano_enum.cc index 634943b6ee..18f688ac07 100644 --- a/src/google/protobuf/compiler/javanano/javanano_enum.cc +++ b/src/google/protobuf/compiler/javanano/javanano_enum.cc @@ -68,25 +68,40 @@ EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, const Params& par EnumGenerator::~EnumGenerator() {} void EnumGenerator::Generate(io::Printer* printer) { - printer->Print("// enum $classname$\n", "classname", descriptor_->name()); - for (int i = 0; i < canonical_values_.size(); i++) { - map vars; - vars["name"] = RenameJavaKeywords(canonical_values_[i]->name()); - vars["canonical_value"] = SimpleItoa(canonical_values_[i]->number()); - printer->Print(vars, - "public static final int $name$ = $canonical_value$;\n"); + printer->Print( + "// enum $classname$\n", + "classname", descriptor_->name()); + + // Start of container interface + bool use_shell_class = params_.java_enum_style(); + if (use_shell_class) { + printer->Print( + "public interface $classname$ {\n", + "classname", RenameJavaKeywords(descriptor_->name())); + printer->Indent(); } - // ----------------------------------------------------------------- + // Canonical values + for (int i = 0; i < canonical_values_.size(); i++) { + printer->Print( + "public static final int $name$ = $canonical_value$;\n", + "name", RenameJavaKeywords(canonical_values_[i]->name()), + "canonical_value", SimpleItoa(canonical_values_[i]->number())); + } + // Aliases for (int i = 0; i < aliases_.size(); i++) { - map vars; - vars["name"] = RenameJavaKeywords(aliases_[i].value->name()); - vars["canonical_name"] = aliases_[i].canonical_value->name(); - printer->Print(vars, - "public static final int $name$ = $canonical_name$;\n"); + printer->Print( + "public static final int $name$ = $canonical_name$;\n", + "name", RenameJavaKeywords(aliases_[i].value->name()), + "canonical_name", RenameJavaKeywords(aliases_[i].canonical_value->name())); } + // End of container interface + if (use_shell_class) { + printer->Outdent(); + printer->Print("}\n"); + } printer->Print("\n"); } diff --git a/src/google/protobuf/compiler/javanano/javanano_file.cc b/src/google/protobuf/compiler/javanano/javanano_file.cc index 1a7b2a74d0..75d0e44f09 100644 --- a/src/google/protobuf/compiler/javanano/javanano_file.cc +++ b/src/google/protobuf/compiler/javanano/javanano_file.cc @@ -138,6 +138,13 @@ bool FileGenerator::Validate(string* error) { found_conflict = true; } } + if (params_.java_enum_style()) { + for (int i = 0; !found_conflict && i < file_->enum_type_count(); i++) { + if (file_->enum_type(i)->name() == classname_) { + found_conflict = true; + } + } + } if (found_conflict) { error->assign(file_->name()); error->append( @@ -237,6 +244,14 @@ void FileGenerator::GenerateSiblings(const string& package_dir, file_->message_type(i), output_directory, file_list, params_); } + + if (params_.java_enum_style()) { + for (int i = 0; i < file_->enum_type_count(); i++) { + GenerateSibling(package_dir, java_package_, + file_->enum_type(i), + output_directory, file_list, params_); + } + } } } diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.cc b/src/google/protobuf/compiler/javanano/javanano_helpers.cc index 630ecd10cd..c4241653f0 100644 --- a/src/google/protobuf/compiler/javanano/javanano_helpers.cc +++ b/src/google/protobuf/compiler/javanano/javanano_helpers.cc @@ -197,12 +197,23 @@ string FileJavaPackage(const Params& params, const FileDescriptor* file) { } bool IsOuterClassNeeded(const Params& params, const FileDescriptor* file) { - // Enums and extensions need the outer class as the scope. - if (file->enum_type_count() != 0 || file->extension_count() != 0) { + // If java_multiple_files is false, the outer class is always needed. + if (!params.java_multiple_files(file->name())) { return true; } - // Messages need the outer class only if java_multiple_files is false. - return !params.java_multiple_files(file->name()); + + // File-scope extensions need the outer class as the scope. + if (file->extension_count() != 0) { + return true; + } + + // If container interfaces are not generated, file-scope enums need the + // outer class as the scope. + if (file->enum_type_count() != 0 && !params.java_enum_style()) { + return true; + } + + return false; } string ToJavaName(const Params& params, const string& name, bool is_class, @@ -228,9 +239,14 @@ string ClassName(const Params& params, const FileDescriptor* descriptor) { } string ClassName(const Params& params, const EnumDescriptor* descriptor) { - // An enum's class name is the enclosing message's class name or the outer - // class name. const Descriptor* parent = descriptor->containing_type(); + // When using Java enum style, an enum's class name contains the enum name. + // Use the standard ToJavaName translation. + if (params.java_enum_style()) { + return ToJavaName(params, descriptor->name(), true, parent, + descriptor->file()); + } + // Otherwise the enum members are accessed from the enclosing class. if (parent != NULL) { return ClassName(params, parent); } else { diff --git a/src/google/protobuf/unittest_enum_class_multiple_nano.proto b/src/google/protobuf/unittest_enum_class_multiple_nano.proto new file mode 100644 index 0000000000..8adb75609f --- /dev/null +++ b/src/google/protobuf/unittest_enum_class_multiple_nano.proto @@ -0,0 +1,48 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: maxtroy@google.com (Max Cai) + +package protobuf_unittest; + +option java_package = "com.google.protobuf.nano"; +option java_multiple_files = true; + +enum FileScopeEnumMultiple { + THREE = 3; +} + +message EnumClassNanoMultiple { + enum MessageScopeEnumMultiple { + FOUR = 4; + } + optional FileScopeEnumMultiple three = 3 [ default = THREE ]; + optional MessageScopeEnumMultiple four = 4 [ default = FOUR ]; +} diff --git a/src/google/protobuf/unittest_enum_class_nano.proto b/src/google/protobuf/unittest_enum_class_nano.proto new file mode 100644 index 0000000000..3727d68d7a --- /dev/null +++ b/src/google/protobuf/unittest_enum_class_nano.proto @@ -0,0 +1,48 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: maxtroy@google.com (Max Cai) + +package protobuf_unittest; + +option java_package = "com.google.protobuf.nano"; +option java_outer_classname = "EnumClassNanos"; + +enum FileScopeEnum { + ONE = 1; +} + +message EnumClassNano { + enum MessageScopeEnum { + TWO = 2; + } + optional FileScopeEnum one = 1 [ default = ONE ]; + optional MessageScopeEnum two = 2 [ default = TWO ]; +}