ソースを参照

Down-integrate internal changes to github. (#5566)

* Down-integrate internal changes to github.

* fix csharp conformance test

* add comments in conformance.proto for text format

* fix comments

* fix comments, re-generated csharp file

* fix comments, re-generated csharp file
Yilun Chong 6 年 前
コミット
cb95a7f6a8

+ 24 - 8
conformance/ConformanceJava.java

@@ -1,16 +1,17 @@
-import com.google.protobuf.ByteString;
 import com.google.protobuf.AbstractMessage;
-import com.google.protobuf.Parser;
+import com.google.protobuf.ByteString;
 import com.google.protobuf.CodedInputStream;
-import com.google.protobuf.conformance.Conformance;
-import com.google.protobuf.InvalidProtocolBufferException;
-import com.google.protobuf_test_messages.proto3.TestMessagesProto3;
-import com.google.protobuf_test_messages.proto3.TestMessagesProto3.TestAllTypesProto3;
-import com.google.protobuf_test_messages.proto2.TestMessagesProto2;
-import com.google.protobuf_test_messages.proto2.TestMessagesProto2.TestAllTypesProto2;
 import com.google.protobuf.ExtensionRegistry;
+import com.google.protobuf.InvalidProtocolBufferException;
+import com.google.protobuf.Parser;
+import com.google.protobuf.TextFormat;
+import com.google.protobuf.conformance.Conformance;
 import com.google.protobuf.util.JsonFormat;
 import com.google.protobuf.util.JsonFormat.TypeRegistry;
+import com.google.protobuf_test_messages.proto2.TestMessagesProto2;
+import com.google.protobuf_test_messages.proto2.TestMessagesProto2.TestAllTypesProto2;
+import com.google.protobuf_test_messages.proto3.TestMessagesProto3;
+import com.google.protobuf_test_messages.proto3.TestMessagesProto3.TestAllTypesProto3;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 
@@ -247,6 +248,17 @@ class ConformanceJava {
         }
         break;
       }
+      case TEXT_PAYLOAD: {
+        try {
+          TestMessagesProto3.TestAllTypesProto3.Builder builder =
+              TestMessagesProto3.TestAllTypesProto3.newBuilder();
+          TextFormat.merge(request.getTextPayload(), builder);
+          testMessage = builder.build();
+        } catch (TextFormat.ParseException e) {
+          return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build();
+        }
+        break;
+      }
       case PAYLOAD_NOT_SET: {
         throw new RuntimeException("Request didn't have payload.");
       }
@@ -274,6 +286,10 @@ class ConformanceJava {
               e.getMessage()).build();
         }
 
+      case TEXT_FORMAT:
+        return Conformance.ConformanceResponse.newBuilder().setTextPayload(
+            TextFormat.printToString(testMessage)).build();
+
       default: {
         throw new RuntimeException("Unexpected request output.");
       }

+ 12 - 0
conformance/conformance.proto

@@ -56,6 +56,7 @@ enum WireFormat {
   PROTOBUF = 1;
   JSON = 2;
   JSPB = 3;  // Google internal only. Opensource testees just skip it.
+  TEXT_FORMAT = 4;
 }
 
 enum TestCategory {
@@ -70,8 +71,14 @@ enum TestCategory {
   JSON_IGNORE_UNKNOWN_PARSING_TEST = 3;
   // Test jspb wire format. Google internal only. Opensource testees just skip it.
   JSPB_TEST = 4;
+  // Test text format. For cpp, java and python, testees can already deal with 
+  // this type. Testees of other languages can simply skip it.
+  TEXT_FORMAT_TEST = 5;
 }
 
+// The conformance runner will request a list of failures as the first request.
+// This will be known by message_type == "conformance.FailureSet", a conformance
+// test should return a serialized FailureSet in protobuf_payload.
 message FailureSet {
   repeated string failure = 1;
 }
@@ -94,6 +101,7 @@ message ConformanceRequest {
     string json_payload = 2;
     // Google internal only.  Opensource testees just skip it.
     string jspb_payload = 7;
+    string text_payload = 8;
   }
 
   // Which format should the testee serialize its message to?
@@ -149,6 +157,10 @@ message ConformanceResponse {
     // serialize to JSPB and set it in this field. JSPB is google internal only
     // format. Opensource testees can just skip it.
     string jspb_payload = 7;
+
+    // If the input was successfully parsed and the requested output was
+    // TEXT_FORMAT, serialize to TEXT_FORMAT and set it in this field.
+    string text_payload = 8;
   }
 }
 

+ 17 - 1
conformance/conformance_cpp.cc

@@ -36,6 +36,7 @@
 #include <google/protobuf/test_messages_proto3.pb.h>
 #include <google/protobuf/test_messages_proto2.pb.h>
 #include <google/protobuf/message.h>
+#include <google/protobuf/text_format.h>
 #include <google/protobuf/util/json_util.h>
 #include <google/protobuf/util/type_resolver_util.h>
 
@@ -45,14 +46,15 @@ using google::protobuf::Descriptor;
 using google::protobuf::DescriptorPool;
 using google::protobuf::Message;
 using google::protobuf::MessageFactory;
+using google::protobuf::TextFormat;
 using google::protobuf::util::BinaryToJsonString;
 using google::protobuf::util::JsonParseOptions;
 using google::protobuf::util::JsonToBinaryString;
 using google::protobuf::util::NewTypeResolverForDescriptorPool;
 using google::protobuf::util::Status;
 using google::protobuf::util::TypeResolver;
-using protobuf_test_messages::proto3::TestAllTypesProto3;
 using protobuf_test_messages::proto2::TestAllTypesProto2;
+using protobuf_test_messages::proto3::TestAllTypesProto3;
 using std::string;
 
 static const char kTypeUrlPrefix[] = "type.googleapis.com";
@@ -163,6 +165,14 @@ void DoTest(const ConformanceRequest& request, ConformanceResponse* response) {
       break;
     }
 
+    case ConformanceRequest::kTextPayload: {
+      if (!TextFormat::ParseFromString(request.text_payload(), test_message)) {
+        response->set_parse_error("Parse error");
+        return;
+      }
+      break;
+    }
+
     case ConformanceRequest::PAYLOAD_NOT_SET:
       GOOGLE_LOG(FATAL) << "Request didn't have payload.";
       break;
@@ -203,6 +213,12 @@ void DoTest(const ConformanceRequest& request, ConformanceResponse* response) {
       break;
     }
 
+    case conformance::TEXT_FORMAT: {
+      GOOGLE_CHECK(TextFormat::PrintToString(*test_message,
+                                             response->mutable_text_payload()));
+      break;
+    }
+
     default:
       GOOGLE_LOG(FATAL) << "Unknown output format: "
                         << request.requested_output_format();

+ 11 - 0
conformance/conformance_python.py

@@ -44,6 +44,7 @@ from google.protobuf import json_format
 from google.protobuf import message
 from google.protobuf import test_messages_proto3_pb2
 from google.protobuf import test_messages_proto2_pb2
+from google.protobuf import text_format
 import conformance_pb2
 
 sys.stdout = os.fdopen(sys.stdout.fileno(), 'wb', 0)
@@ -136,6 +137,13 @@ def do_test(request):
         response.parse_error = str(e)
         return response
 
+    elif request.WhichOneof('payload') == 'text_payload':
+      try:
+        text_format.Parse(request.text_payload, test_message)
+      except Exception as e:
+        response.parse_error = str(e)
+        return response
+
     else:
       raise ProtocolError("Request didn't have payload.")
 
@@ -152,6 +160,9 @@ def do_test(request):
         response.serialize_error = str(e)
         return response
 
+    elif request.requested_output_format == conformance_pb2.TEXT_FORMAT:
+      response.text_payload = text_format.MessageToString(test_message)
+
   except Exception as e:
     response.runtime_error = str(e)
 

+ 11 - 0
conformance/conformance_test.cc

@@ -85,6 +85,11 @@ ConformanceTestSuite::ConformanceRequestSetting::ConformanceRequestSetting(
       break;
     }
 
+    case conformance::TEXT_FORMAT: {
+      request_.set_text_payload(input);
+      break;
+    }
+
     default:
       GOOGLE_LOG(FATAL) << "Unspecified input format";
   }
@@ -131,6 +136,8 @@ string ConformanceTestSuite::ConformanceRequestSetting::
       return "ProtobufInput";
     case conformance::JSON:
       return "JsonInput";
+    case conformance::TEXT_FORMAT:
+      return "TextFormatInput";
     default:
       GOOGLE_LOG(FATAL) << "Unspecified output format";
   }
@@ -144,6 +151,8 @@ string ConformanceTestSuite::ConformanceRequestSetting::
       return "ProtobufOutput";
     case conformance::JSON:
       return "JsonOutput";
+    case conformance::TEXT_FORMAT:
+      return "TextFormatOutput";
     default:
       GOOGLE_LOG(FATAL) << "Unspecified output format";
   }
@@ -341,6 +350,8 @@ string ConformanceTestSuite::WireFormatToString(
       return "JSON";
     case conformance::JSPB:
       return "JSPB";
+    case conformance::TEXT_FORMAT:
+      return "TEXT_FORMAT";
     case conformance::UNSPECIFIED:
       return "UNSPECIFIED";
     default:

+ 99 - 20
csharp/src/Google.Protobuf.Conformance/Conformance.cs

@@ -25,31 +25,33 @@ namespace Conformance {
       byte[] descriptorData = global::System.Convert.FromBase64String(
           string.Concat(
             "ChFjb25mb3JtYW5jZS5wcm90bxILY29uZm9ybWFuY2UiHQoKRmFpbHVyZVNl",
-            "dBIPCgdmYWlsdXJlGAEgAygJIq0CChJDb25mb3JtYW5jZVJlcXVlc3QSGgoQ",
+            "dBIPCgdmYWlsdXJlGAEgAygJIsUCChJDb25mb3JtYW5jZVJlcXVlc3QSGgoQ",
             "cHJvdG9idWZfcGF5bG9hZBgBIAEoDEgAEhYKDGpzb25fcGF5bG9hZBgCIAEo",
-            "CUgAEhYKDGpzcGJfcGF5bG9hZBgHIAEoCUgAEjgKF3JlcXVlc3RlZF9vdXRw",
-            "dXRfZm9ybWF0GAMgASgOMhcuY29uZm9ybWFuY2UuV2lyZUZvcm1hdBIUCgxt",
-            "ZXNzYWdlX3R5cGUYBCABKAkSMAoNdGVzdF9jYXRlZ29yeRgFIAEoDjIZLmNv",
-            "bmZvcm1hbmNlLlRlc3RDYXRlZ29yeRI+ChVqc3BiX2VuY29kaW5nX29wdGlv",
-            "bnMYBiABKAsyHy5jb25mb3JtYW5jZS5Kc3BiRW5jb2RpbmdDb25maWdCCQoH",
-            "cGF5bG9hZCLJAQoTQ29uZm9ybWFuY2VSZXNwb25zZRIVCgtwYXJzZV9lcnJv",
-            "chgBIAEoCUgAEhkKD3NlcmlhbGl6ZV9lcnJvchgGIAEoCUgAEhcKDXJ1bnRp",
-            "bWVfZXJyb3IYAiABKAlIABIaChBwcm90b2J1Zl9wYXlsb2FkGAMgASgMSAAS",
-            "FgoManNvbl9wYXlsb2FkGAQgASgJSAASEQoHc2tpcHBlZBgFIAEoCUgAEhYK",
-            "DGpzcGJfcGF5bG9hZBgHIAEoCUgAQggKBnJlc3VsdCI3ChJKc3BiRW5jb2Rp",
-            "bmdDb25maWcSIQoZdXNlX2pzcGJfYXJyYXlfYW55X2Zvcm1hdBgBIAEoCCo/",
-            "CgpXaXJlRm9ybWF0Eg8KC1VOU1BFQ0lGSUVEEAASDAoIUFJPVE9CVUYQARII",
-            "CgRKU09OEAISCAoESlNQQhADKnkKDFRlc3RDYXRlZ29yeRIUChBVTlNQRUNJ",
-            "RklFRF9URVNUEAASDwoLQklOQVJZX1RFU1QQARINCglKU09OX1RFU1QQAhIk",
-            "CiBKU09OX0lHTk9SRV9VTktOT1dOX1BBUlNJTkdfVEVTVBADEg0KCUpTUEJf",
-            "VEVTVBAEQiEKH2NvbS5nb29nbGUucHJvdG9idWYuY29uZm9ybWFuY2ViBnBy",
-            "b3RvMw=="));
+            "CUgAEhYKDGpzcGJfcGF5bG9hZBgHIAEoCUgAEhYKDHRleHRfcGF5bG9hZBgI",
+            "IAEoCUgAEjgKF3JlcXVlc3RlZF9vdXRwdXRfZm9ybWF0GAMgASgOMhcuY29u",
+            "Zm9ybWFuY2UuV2lyZUZvcm1hdBIUCgxtZXNzYWdlX3R5cGUYBCABKAkSMAoN",
+            "dGVzdF9jYXRlZ29yeRgFIAEoDjIZLmNvbmZvcm1hbmNlLlRlc3RDYXRlZ29y",
+            "eRI+ChVqc3BiX2VuY29kaW5nX29wdGlvbnMYBiABKAsyHy5jb25mb3JtYW5j",
+            "ZS5Kc3BiRW5jb2RpbmdDb25maWdCCQoHcGF5bG9hZCLhAQoTQ29uZm9ybWFu",
+            "Y2VSZXNwb25zZRIVCgtwYXJzZV9lcnJvchgBIAEoCUgAEhkKD3NlcmlhbGl6",
+            "ZV9lcnJvchgGIAEoCUgAEhcKDXJ1bnRpbWVfZXJyb3IYAiABKAlIABIaChBw",
+            "cm90b2J1Zl9wYXlsb2FkGAMgASgMSAASFgoManNvbl9wYXlsb2FkGAQgASgJ",
+            "SAASEQoHc2tpcHBlZBgFIAEoCUgAEhYKDGpzcGJfcGF5bG9hZBgHIAEoCUgA",
+            "EhYKDHRleHRfcGF5bG9hZBgIIAEoCUgAQggKBnJlc3VsdCI3ChJKc3BiRW5j",
+            "b2RpbmdDb25maWcSIQoZdXNlX2pzcGJfYXJyYXlfYW55X2Zvcm1hdBgBIAEo",
+            "CCpQCgpXaXJlRm9ybWF0Eg8KC1VOU1BFQ0lGSUVEEAASDAoIUFJPVE9CVUYQ",
+            "ARIICgRKU09OEAISCAoESlNQQhADEg8KC1RFWFRfRk9STUFUEAQqjwEKDFRl",
+            "c3RDYXRlZ29yeRIUChBVTlNQRUNJRklFRF9URVNUEAASDwoLQklOQVJZX1RF",
+            "U1QQARINCglKU09OX1RFU1QQAhIkCiBKU09OX0lHTk9SRV9VTktOT1dOX1BB",
+            "UlNJTkdfVEVTVBADEg0KCUpTUEJfVEVTVBAEEhQKEFRFWFRfRk9STUFUX1RF",
+            "U1QQBUIhCh9jb20uZ29vZ2xlLnByb3RvYnVmLmNvbmZvcm1hbmNlYgZwcm90",
+            "bzM="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { },
           new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Conformance.WireFormat), typeof(global::Conformance.TestCategory), }, new pbr::GeneratedClrTypeInfo[] {
             new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.FailureSet), global::Conformance.FailureSet.Parser, new[]{ "Failure" }, null, null, null),
-            new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ConformanceRequest), global::Conformance.ConformanceRequest.Parser, new[]{ "ProtobufPayload", "JsonPayload", "JspbPayload", "RequestedOutputFormat", "MessageType", "TestCategory", "JspbEncodingOptions" }, new[]{ "Payload" }, null, null),
-            new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ConformanceResponse), global::Conformance.ConformanceResponse.Parser, new[]{ "ParseError", "SerializeError", "RuntimeError", "ProtobufPayload", "JsonPayload", "Skipped", "JspbPayload" }, new[]{ "Result" }, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ConformanceRequest), global::Conformance.ConformanceRequest.Parser, new[]{ "ProtobufPayload", "JsonPayload", "JspbPayload", "TextPayload", "RequestedOutputFormat", "MessageType", "TestCategory", "JspbEncodingOptions" }, new[]{ "Payload" }, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ConformanceResponse), global::Conformance.ConformanceResponse.Parser, new[]{ "ParseError", "SerializeError", "RuntimeError", "ProtobufPayload", "JsonPayload", "Skipped", "JspbPayload", "TextPayload" }, new[]{ "Result" }, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.JspbEncodingConfig), global::Conformance.JspbEncodingConfig.Parser, new[]{ "UseJspbArrayAnyFormat" }, null, null, null)
           }));
     }
@@ -65,6 +67,7 @@ namespace Conformance {
     /// Google internal only. Opensource testees just skip it.
     /// </summary>
     [pbr::OriginalName("JSPB")] Jspb = 3,
+    [pbr::OriginalName("TEXT_FORMAT")] TextFormat = 4,
   }
 
   public enum TestCategory {
@@ -89,11 +92,21 @@ namespace Conformance {
     /// Test jspb wire format. Google internal only. Opensource testees just skip it.
     /// </summary>
     [pbr::OriginalName("JSPB_TEST")] JspbTest = 4,
+    /// <summary>
+    /// Test text format. For cpp, java and python, testees can already deal with 
+    /// this type. Testees of other languages can simply skip it.
+    /// </summary>
+    [pbr::OriginalName("TEXT_FORMAT_TEST")] TextFormatTest = 5,
   }
 
   #endregion
 
   #region Messages
+  /// <summary>
+  /// The conformance runner will request a list of failures as the first request.
+  /// This will be known by message_type == "conformance.FailureSet", a conformance
+  /// test should return a serialized FailureSet in protobuf_payload.
+  /// </summary>
   public sealed partial class FailureSet : pb::IMessage<FailureSet> {
     private static readonly pb::MessageParser<FailureSet> _parser = new pb::MessageParser<FailureSet>(() => new FailureSet());
     private pb::UnknownFieldSet _unknownFields;
@@ -263,6 +276,9 @@ namespace Conformance {
         case PayloadOneofCase.JspbPayload:
           JspbPayload = other.JspbPayload;
           break;
+        case PayloadOneofCase.TextPayload:
+          TextPayload = other.TextPayload;
+          break;
       }
 
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
@@ -309,6 +325,17 @@ namespace Conformance {
       }
     }
 
+    /// <summary>Field number for the "text_payload" field.</summary>
+    public const int TextPayloadFieldNumber = 8;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public string TextPayload {
+      get { return payloadCase_ == PayloadOneofCase.TextPayload ? (string) payload_ : ""; }
+      set {
+        payload_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+        payloadCase_ = PayloadOneofCase.TextPayload;
+      }
+    }
+
     /// <summary>Field number for the "requested_output_format" field.</summary>
     public const int RequestedOutputFormatFieldNumber = 3;
     private global::Conformance.WireFormat requestedOutputFormat_ = 0;
@@ -376,6 +403,7 @@ namespace Conformance {
       ProtobufPayload = 1,
       JsonPayload = 2,
       JspbPayload = 7,
+      TextPayload = 8,
     }
     private PayloadOneofCase payloadCase_ = PayloadOneofCase.None;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -405,6 +433,7 @@ namespace Conformance {
       if (ProtobufPayload != other.ProtobufPayload) return false;
       if (JsonPayload != other.JsonPayload) return false;
       if (JspbPayload != other.JspbPayload) return false;
+      if (TextPayload != other.TextPayload) return false;
       if (RequestedOutputFormat != other.RequestedOutputFormat) return false;
       if (MessageType != other.MessageType) return false;
       if (TestCategory != other.TestCategory) return false;
@@ -419,6 +448,7 @@ namespace Conformance {
       if (payloadCase_ == PayloadOneofCase.ProtobufPayload) hash ^= ProtobufPayload.GetHashCode();
       if (payloadCase_ == PayloadOneofCase.JsonPayload) hash ^= JsonPayload.GetHashCode();
       if (payloadCase_ == PayloadOneofCase.JspbPayload) hash ^= JspbPayload.GetHashCode();
+      if (payloadCase_ == PayloadOneofCase.TextPayload) hash ^= TextPayload.GetHashCode();
       if (RequestedOutputFormat != 0) hash ^= RequestedOutputFormat.GetHashCode();
       if (MessageType.Length != 0) hash ^= MessageType.GetHashCode();
       if (TestCategory != 0) hash ^= TestCategory.GetHashCode();
@@ -465,6 +495,10 @@ namespace Conformance {
         output.WriteRawTag(58);
         output.WriteString(JspbPayload);
       }
+      if (payloadCase_ == PayloadOneofCase.TextPayload) {
+        output.WriteRawTag(66);
+        output.WriteString(TextPayload);
+      }
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
@@ -482,6 +516,9 @@ namespace Conformance {
       if (payloadCase_ == PayloadOneofCase.JspbPayload) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(JspbPayload);
       }
+      if (payloadCase_ == PayloadOneofCase.TextPayload) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(TextPayload);
+      }
       if (RequestedOutputFormat != 0) {
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) RequestedOutputFormat);
       }
@@ -530,6 +567,9 @@ namespace Conformance {
         case PayloadOneofCase.JspbPayload:
           JspbPayload = other.JspbPayload;
           break;
+        case PayloadOneofCase.TextPayload:
+          TextPayload = other.TextPayload;
+          break;
       }
 
       _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
@@ -576,6 +616,10 @@ namespace Conformance {
             JspbPayload = input.ReadString();
             break;
           }
+          case 66: {
+            TextPayload = input.ReadString();
+            break;
+          }
         }
       }
     }
@@ -632,6 +676,9 @@ namespace Conformance {
         case ResultOneofCase.JspbPayload:
           JspbPayload = other.JspbPayload;
           break;
+        case ResultOneofCase.TextPayload:
+          TextPayload = other.TextPayload;
+          break;
       }
 
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
@@ -753,6 +800,21 @@ namespace Conformance {
       }
     }
 
+    /// <summary>Field number for the "text_payload" field.</summary>
+    public const int TextPayloadFieldNumber = 8;
+    /// <summary>
+    /// If the input was successfully parsed and the requested output was
+    /// TEXT_FORMAT, serialize to TEXT_FORMAT and set it in this field.
+    /// </summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public string TextPayload {
+      get { return resultCase_ == ResultOneofCase.TextPayload ? (string) result_ : ""; }
+      set {
+        result_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+        resultCase_ = ResultOneofCase.TextPayload;
+      }
+    }
+
     private object result_;
     /// <summary>Enum of possible cases for the "result" oneof.</summary>
     public enum ResultOneofCase {
@@ -764,6 +826,7 @@ namespace Conformance {
       JsonPayload = 4,
       Skipped = 5,
       JspbPayload = 7,
+      TextPayload = 8,
     }
     private ResultOneofCase resultCase_ = ResultOneofCase.None;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -797,6 +860,7 @@ namespace Conformance {
       if (JsonPayload != other.JsonPayload) return false;
       if (Skipped != other.Skipped) return false;
       if (JspbPayload != other.JspbPayload) return false;
+      if (TextPayload != other.TextPayload) return false;
       if (ResultCase != other.ResultCase) return false;
       return Equals(_unknownFields, other._unknownFields);
     }
@@ -811,6 +875,7 @@ namespace Conformance {
       if (resultCase_ == ResultOneofCase.JsonPayload) hash ^= JsonPayload.GetHashCode();
       if (resultCase_ == ResultOneofCase.Skipped) hash ^= Skipped.GetHashCode();
       if (resultCase_ == ResultOneofCase.JspbPayload) hash ^= JspbPayload.GetHashCode();
+      if (resultCase_ == ResultOneofCase.TextPayload) hash ^= TextPayload.GetHashCode();
       hash ^= (int) resultCase_;
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
@@ -853,6 +918,10 @@ namespace Conformance {
         output.WriteRawTag(58);
         output.WriteString(JspbPayload);
       }
+      if (resultCase_ == ResultOneofCase.TextPayload) {
+        output.WriteRawTag(66);
+        output.WriteString(TextPayload);
+      }
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
@@ -882,6 +951,9 @@ namespace Conformance {
       if (resultCase_ == ResultOneofCase.JspbPayload) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(JspbPayload);
       }
+      if (resultCase_ == ResultOneofCase.TextPayload) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(TextPayload);
+      }
       if (_unknownFields != null) {
         size += _unknownFields.CalculateSize();
       }
@@ -915,6 +987,9 @@ namespace Conformance {
         case ResultOneofCase.JspbPayload:
           JspbPayload = other.JspbPayload;
           break;
+        case ResultOneofCase.TextPayload:
+          TextPayload = other.TextPayload;
+          break;
       }
 
       _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
@@ -958,6 +1033,10 @@ namespace Conformance {
             JspbPayload = input.ReadString();
             break;
           }
+          case 66: {
+            TextPayload = input.ReadString();
+            break;
+          }
         }
       }
     }

+ 12 - 11
js/test.proto

@@ -39,8 +39,7 @@ import "google/protobuf/descriptor.proto";
 
 package jspb.test;
 
-message Empty {
-}
+message Empty {}
 
 enum OuterEnum {
   FOO = 1;
@@ -137,12 +136,13 @@ message DefaultValues {
     E1 = 13;
     E2 = 77;
   }
-  optional string string_field = 1 [default="default<>\'\"abc"];
-  optional bool bool_field = 2 [default=true];
-  optional int64 int_field = 3 [default=11];
-  optional Enum enum_field = 4 [default=E1];
-  optional string empty_field = 6 [default=""];
-  optional bytes bytes_field = 8 [default="moo"]; // Base64 encoding is "bW9v"
+  optional string string_field = 1 [default = "default<>\'\"abc"];
+  optional bool bool_field = 2 [default = true];
+  optional int64 int_field = 3 [default = 11];
+  optional Enum enum_field = 4 [default = E1];
+  optional string empty_field = 6 [default = ""];
+  optional bytes bytes_field = 8
+      [default = "moo"];  // Base64 encoding is "bW9v"
 }
 
 message FloatingPointFields {
@@ -254,9 +254,9 @@ extend TestLastFieldBeforePivot {
 
 
 message Int64Types {
-  optional int64 int64_normal = 1 [jstype=JS_NORMAL];
-  optional sint64 int64_string = 2 [jstype=JS_STRING];
-  optional uint64 int64_number = 3 [jstype=JS_NUMBER];
+  optional int64 int64_normal = 1 [jstype = JS_NORMAL];
+  optional sint64 int64_string = 2 [jstype = JS_STRING];
+  optional uint64 int64_number = 3 [jstype = JS_NUMBER];
 
 }
 
@@ -297,3 +297,4 @@ message Deeply {
   }
 }
 
+

+ 34 - 17
src/google/protobuf/compiler/js/js_generator.cc

@@ -2847,52 +2847,69 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
   // Generate clearFoo() method for map fields, repeated fields, and other
   // fields with presence.
   if (field->is_map()) {
+    // clang-format off
     printer->Print(
-        "/** Clears values from the map. The map will be non-null. */\n"
+        "/**\n"
+        " * Clears values from the map. The map will be non-null."
+        "$returndoc$\n"
+        " */\n"
         "$class$.prototype.$clearername$ = function() {\n"
         "  this.$gettername$().clear();$returnvalue$\n"
         "};\n"
         "\n"
         "\n",
+        "returndoc", JSReturnDoc(options, field),
         "class", GetMessagePath(options, field->containing_type()),
-        "clearername", "clear" + JSGetterName(options, field), "gettername",
-        "get" + JSGetterName(options, field), "returnvalue",
-        JSReturnClause(field));
+        "clearername", "clear" + JSGetterName(options, field),
+        "gettername", "get" + JSGetterName(options, field),
+        "returnvalue", JSReturnClause(field));
+    // clang-format on
     printer->Annotate("clearername", field);
   } else if (field->is_repeated() ||
              (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
               !field->is_required())) {
     // Fields where we can delegate to the regular setter.
+    // clang-format off
     printer->Print(
-        "/** $jsdoc$ */\n"
+        "/**\n"
+        " * $jsdoc$$returndoc$\n"
+        " */\n"
         "$class$.prototype.$clearername$ = function() {\n"
         "  this.$settername$($clearedvalue$);$returnvalue$\n"
         "};\n"
         "\n"
         "\n",
-        "jsdoc",
-        field->is_repeated() ? "Clears the list making it empty but non-null."
-                             : "Clears the message field making it undefined.",
+       "jsdoc", field->is_repeated()
+           ? "Clears the list making it empty but non-null."
+           : "Clears the message field making it undefined.",
+        "returndoc", JSReturnDoc(options, field),
         "class", GetMessagePath(options, field->containing_type()),
-        "clearername", "clear" + JSGetterName(options, field), "settername",
-        "set" + JSGetterName(options, field), "clearedvalue",
-        (field->is_repeated() ? "[]" : "undefined"), "returnvalue",
-        JSReturnClause(field));
+        "clearername", "clear" + JSGetterName(options, field),
+        "settername", "set" + JSGetterName(options, field),
+        "clearedvalue", (field->is_repeated() ? "[]" : "undefined"),
+        "returnvalue", JSReturnClause(field));
+    // clang-format on
     printer->Annotate("clearername", field);
   } else if (HasFieldPresence(options, field)) {
     // Fields where we can't delegate to the regular setter because it doesn't
     // accept "undefined" as an argument.
+    // clang-format off
     printer->Print(
-        "/** Clears the field making it undefined. */\n"
+        "/**\n"
+        " * Clears the field making it undefined.$returndoc$\n"
+        " */\n"
         "$class$.prototype.$clearername$ = function() {\n"
         "  jspb.Message.set$maybeoneof$Field(this, "
         "$index$$maybeoneofgroup$, ",
+        "returndoc", JSReturnDoc(options, field),
         "class", GetMessagePath(options, field->containing_type()),
-        "clearername", "clear" + JSGetterName(options, field), "maybeoneof",
-        (field->containing_oneof() ? "Oneof" : ""), "maybeoneofgroup",
-        (field->containing_oneof() ? (", " + JSOneofArray(options, field))
-                                   : ""),
+        "clearername", "clear" + JSGetterName(options, field),
+        "maybeoneof", (field->containing_oneof() ? "Oneof" : ""),
+        "maybeoneofgroup", (field->containing_oneof()
+                            ? (", " + JSOneofArray(options, field))
+                            : ""),
         "index", JSFieldIndex(field));
+    // clang-format on
     printer->Annotate("clearername", field);
     printer->Print(
         "$clearedvalue$);$returnvalue$\n"