浏览代码

When no clear() is generated, still initialize fields.

https://android-review.googlesource.com/#/c/67890/ removed field
initialization from the ctor, making it just call clear() instead.

When I added the generate_clear option back (as part of the reftypes
compat mode) in https://android-review.googlesource.com/#/c/109530/,
I forgot to ensure that what clear() used to do was inlined in the
constructor.

This change fixes NPEs that are happening for users of
reftypes_compat_mode who rely on unset repeated fields being empty
arrays rather than null.

Change-Id: Idb58746c60f4a4054b7ebb5c3b0e76b16ff88184
Brian Duff 10 年之前
父节点
当前提交
fb96026b8d

+ 9 - 0
javanano/pom.xml

@@ -139,6 +139,15 @@
                   <arg value="--proto_path=src/test/java/com" />
                   <arg value="src/test/java/com/google/protobuf/nano/unittest_reference_types_nano.proto" />
                 </exec>
+                <exec executable="../src/protoc">
+                  <arg value="--javanano_out=
+                                  optional_field_style=reftypes_compat_mode,
+                                  generate_equals=true,
+                                  java_outer_classname=google/protobuf/nano/unittest_reference_types_nano.proto|NanoReferenceTypesCompat
+                                  :target/generated-test-sources" />
+                  <arg value="--proto_path=src/test/java/com" />
+                  <arg value="src/test/java/com/google/protobuf/nano/unittest_reference_types_nano.proto" />
+                </exec>
               </tasks>
               <testSourceRoot>target/generated-test-sources</testSourceRoot>
             </configuration>

+ 6 - 0
javanano/src/test/java/com/google/protobuf/nano/NanoTest.java

@@ -36,6 +36,7 @@ import com.google.protobuf.nano.NanoAccessorsOuterClass.TestNanoAccessors;
 import com.google.protobuf.nano.NanoHasOuterClass.TestAllTypesNanoHas;
 import com.google.protobuf.nano.NanoOuterClass.TestAllTypesNano;
 import com.google.protobuf.nano.UnittestRecursiveNano.RecursiveMessageNano;
+import com.google.protobuf.nano.NanoReferenceTypesCompat;
 import com.google.protobuf.nano.UnittestSimpleNano.SimpleMessageNano;
 import com.google.protobuf.nano.UnittestSingleNano.SingleMessageNano;
 import com.google.protobuf.nano.testext.Extensions;
@@ -4381,6 +4382,11 @@ public class NanoTest extends TestCase {
     assertMapSet(testMap.sfixed64ToSfixed64Field, int64Values, int64Values);
   }
 
+  public void testRepeatedFieldInitializedInReftypesCompatMode() {
+    NanoReferenceTypesCompat.TestAllTypesNano proto = new NanoReferenceTypesCompat.TestAllTypesNano();
+    assertNotNull(proto.repeatedString);
+  }
+
   private void assertRepeatedPackablesEqual(
       NanoRepeatedPackables.NonPacked nonPacked, NanoRepeatedPackables.Packed packed) {
     // Not using MessageNano.equals() -- that belongs to a separate test.

+ 20 - 12
src/google/protobuf/compiler/javanano/javanano_message.cc

@@ -288,14 +288,18 @@ void MessageGenerator::Generate(io::Printer* printer) {
     }
     printer->Print("}\n");
   } else {
+    printer->Print(
+      "\n"
+      "public $classname$() {\n",
+      "classname", descriptor_->name());
     if (params_.generate_clear()) {
-      printer->Print(
-        "\n"
-        "public $classname$() {\n"
-        "  clear();\n"
-        "}\n",
-        "classname", descriptor_->name());
+      printer->Print("  clear();\n");
+    } else {
+      printer->Indent();
+      GenerateFieldInitializers(printer);
+      printer->Outdent();
     }
+    printer->Print("}\n");
   }
 
   // Other methods in this class
@@ -495,6 +499,15 @@ void MessageGenerator::GenerateClear(io::Printer* printer) {
     "classname", descriptor_->name());
   printer->Indent();
 
+  GenerateFieldInitializers(printer);
+
+  printer->Outdent();
+  printer->Print(
+    "  return this;\n"
+    "}\n");
+}
+
+void MessageGenerator::GenerateFieldInitializers(io::Printer* printer) {
   // Clear bit fields.
   int totalInts = (field_generators_.total_bits() + 31) / 32;
   for (int i = 0; i < totalInts; i++) {
@@ -520,12 +533,7 @@ void MessageGenerator::GenerateClear(io::Printer* printer) {
   if (params_.store_unknown_fields()) {
     printer->Print("unknownFieldData = null;\n");
   }
-
-  printer->Outdent();
-  printer->Print(
-    "  cachedSize = -1;\n"
-    "  return this;\n"
-    "}\n");
+  printer->Print("cachedSize = -1;\n");
 }
 
 void MessageGenerator::GenerateEquals(io::Printer* printer) {

+ 1 - 0
src/google/protobuf/compiler/javanano/javanano_message.h

@@ -77,6 +77,7 @@ class MessageGenerator {
                                  const FieldDescriptor* field);
 
   void GenerateClear(io::Printer* printer);
+  void GenerateFieldInitializers(io::Printer* printer);
   void GenerateEquals(io::Printer* printer);
   void GenerateHashCode(io::Printer* printer);