From e519c62f827a5f354c9253419c2fb5c230622311 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Fri, 22 Sep 2023 10:35:07 -0700 Subject: [PATCH] Improve .NET debugging of Protobuf messages (#13838) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generated .NET protobuf messages override `ToString` and return JSON. By default, the .NET debugger displays the result from `ToString` and wraps it in curly braces, e.g. `{{ "Message": "Hello world" }}`. The double curly braces is an ugly result. People expecting JSON here are confused. This PR adds a [DebuggerDisplayAttribute](https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.debuggerdisplayattribute?view=net-7.0) to generated messages. The attribute tells the debugger to not quote the ToString value with `nq`. Before: ![image](https://github.com/protocolbuffers/protobuf/assets/303201/b1cc5f45-4064-4ba0-b266-8894ca0f35c8) After: ![image](https://github.com/protocolbuffers/protobuf/assets/303201/70f6ffc0-9421-428d-bc22-ead7aa82c37f) I haven't touched the protoc compiler in a long time. I'm guessing I need to build it and then run it to regenerate the checked-in code. I don't suppose someone else could do that? It would save me a lot of time 😬 Closes #13838 COPYBARA_INTEGRATE_REVIEW=https://github.com/protocolbuffers/protobuf/pull/13838 from JamesNK:jamesnk/csharp-message-debuggerdisplay 5222b82cf96a4cbfb9ab0dcc2b815dccc5b309a0 PiperOrigin-RevId: 567659327 --- .../compiler/csharp/csharp_message.cc | 436 +++++++++--------- 1 file changed, 220 insertions(+), 216 deletions(-) diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc index 7e14836ac2..5862257617 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message.cc @@ -64,18 +64,16 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor, } } -MessageGenerator::~MessageGenerator() { -} +MessageGenerator::~MessageGenerator() {} -std::string MessageGenerator::class_name() { - return descriptor_->name(); -} +std::string MessageGenerator::class_name() { return descriptor_->name(); } std::string MessageGenerator::full_class_name() { return GetClassName(descriptor_); } -const std::vector& MessageGenerator::fields_by_number() { +const std::vector& +MessageGenerator::fields_by_number() { return fields_by_number_; } @@ -101,13 +99,13 @@ void MessageGenerator::Generate(io::Printer* printer) { AddSerializableAttribute(printer); printer->Print( - vars, - "$access_level$ sealed partial class $class_name$ : "); + "[global::System.Diagnostics.DebuggerDisplayAttribute(\"{ToString(),nq}" + "\")]\n"); + printer->Print(vars, "$access_level$ sealed partial class $class_name$ : "); if (has_extension_ranges_) { printer->Print(vars, "pb::IExtendableMessage<$class_name$>\n"); - } - else { + } else { printer->Print(vars, "pb::IMessage<$class_name$>\n"); } printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n"); @@ -119,16 +117,19 @@ void MessageGenerator::Generate(io::Printer* printer) { // All static fields and properties printer->Print( vars, - "private static readonly pb::MessageParser<$class_name$> _parser = new pb::MessageParser<$class_name$>(() => new $class_name$());\n"); + "private static readonly pb::MessageParser<$class_name$> _parser = new " + "pb::MessageParser<$class_name$>(() => new $class_name$());\n"); - printer->Print( - "private pb::UnknownFieldSet _unknownFields;\n"); + printer->Print("private pb::UnknownFieldSet _unknownFields;\n"); if (has_extension_ranges_) { if (IsDescriptorProto(descriptor_->file())) { - printer->Print(vars, "internal pb::ExtensionSet<$class_name$> _extensions;\n"); // CustomOptions compatibility + printer->Print(vars, + // CustomOptions compatibility + "internal pb::ExtensionSet<$class_name$> _extensions;\n"); } else { - printer->Print(vars, "private pb::ExtensionSet<$class_name$> _extensions;\n"); + printer->Print(vars, + "private pb::ExtensionSet<$class_name$> _extensions;\n"); } // a read-only property for fast @@ -140,17 +141,19 @@ void MessageGenerator::Generate(io::Printer* printer) { for (int i = 0; i < has_bit_field_count_; i++) { // don't use arrays since all arrays are heap allocated, saving allocations - // use ints instead of bytes since bytes lack bitwise operators, saving casts + // use ints instead of bytes since bytes lack bitwise operators, saving + // casts printer->Print("private int _hasBits$i$;\n", "i", absl::StrCat(i)); } WriteGeneratedCodeAttributes(printer); - printer->Print( - vars, - "public static pb::MessageParser<$class_name$> Parser { get { return _parser; } }\n\n"); + printer->Print(vars, + "public static pb::MessageParser<$class_name$> Parser { get { " + "return _parser; } }\n\n"); - // Access the message descriptor via the relevant file descriptor or containing message descriptor. + // Access the message descriptor via the relevant file descriptor or + // containing message descriptor. if (!descriptor_->containing_type()) { vars["descriptor_accessor"] = absl::StrCat(GetReflectionClassName(descriptor_->file()), @@ -162,28 +165,25 @@ void MessageGenerator::Generate(io::Printer* printer) { } WriteGeneratedCodeAttributes(printer); - printer->Print( - vars, - "public static pbr::MessageDescriptor Descriptor {\n" - " get { return $descriptor_accessor$; }\n" - "}\n" - "\n"); + printer->Print(vars, + "public static pbr::MessageDescriptor Descriptor {\n" + " get { return $descriptor_accessor$; }\n" + "}\n" + "\n"); WriteGeneratedCodeAttributes(printer); - printer->Print( - vars, - "pbr::MessageDescriptor pb::IMessage.Descriptor {\n" - " get { return Descriptor; }\n" - "}\n" - "\n"); + printer->Print(vars, + "pbr::MessageDescriptor pb::IMessage.Descriptor {\n" + " get { return Descriptor; }\n" + "}\n" + "\n"); // Parameterless constructor and partial OnConstruction method. WriteGeneratedCodeAttributes(printer); - printer->Print( - vars, - "public $class_name$() {\n" - " OnConstruction();\n" - "}\n\n" - "partial void OnConstruction();\n\n"); + printer->Print(vars, + "public $class_name$() {\n" + " OnConstruction();\n" + "}\n\n" + "partial void OnConstruction();\n\n"); GenerateCloningCode(printer); GenerateFreezingCode(printer); @@ -194,11 +194,11 @@ void MessageGenerator::Generate(io::Printer* printer) { // Rats: we lose the debug comment here :( printer->Print( - "/// Field number for the \"$field_name$\" field.\n" - "public const int $field_constant_name$ = $index$;\n", - "field_name", fieldDescriptor->name(), - "field_constant_name", GetFieldConstantName(fieldDescriptor), - "index", absl::StrCat(fieldDescriptor->number())); + "/// Field number for the \"$field_name$\" field.\n" + "public const int $field_constant_name$ = $index$;\n", + "field_name", fieldDescriptor->name(), "field_constant_name", + GetFieldConstantName(fieldDescriptor), "index", + absl::StrCat(fieldDescriptor->number())); std::unique_ptr generator( CreateFieldGeneratorInternal(fieldDescriptor)); generator->GenerateMembers(printer); @@ -211,39 +211,37 @@ void MessageGenerator::Generate(io::Printer* printer) { vars["name"] = UnderscoresToCamelCase(oneof->name(), false); vars["property_name"] = UnderscoresToCamelCase(oneof->name(), true); vars["original_name"] = oneof->name(); - printer->Print( - vars, - "private object $name$_;\n" - "/// Enum of possible cases for the \"$original_name$\" oneof.\n" - "public enum $property_name$OneofCase {\n"); + printer->Print(vars, + "private object $name$_;\n" + "/// Enum of possible cases for the " + "\"$original_name$\" oneof.\n" + "public enum $property_name$OneofCase {\n"); printer->Indent(); printer->Print("None = 0,\n"); for (int j = 0; j < oneof->field_count(); j++) { const FieldDescriptor* field = oneof->field(j); - printer->Print("$oneof_case_name$ = $index$,\n", - "oneof_case_name", GetOneofCaseName(field), - "index", absl::StrCat(field->number())); + printer->Print("$oneof_case_name$ = $index$,\n", "oneof_case_name", + GetOneofCaseName(field), "index", + absl::StrCat(field->number())); } printer->Outdent(); printer->Print("}\n"); // TODO: Should we put the oneof .proto comments here? // It's unclear exactly where they should go. - printer->Print( - vars, - "private $property_name$OneofCase $name$Case_ = $property_name$OneofCase.None;\n"); + printer->Print(vars, + "private $property_name$OneofCase $name$Case_ = " + "$property_name$OneofCase.None;\n"); WriteGeneratedCodeAttributes(printer); - printer->Print( - vars, - "public $property_name$OneofCase $property_name$Case {\n" - " get { return $name$Case_; }\n" - "}\n\n"); + printer->Print(vars, + "public $property_name$OneofCase $property_name$Case {\n" + " get { return $name$Case_; }\n" + "}\n\n"); WriteGeneratedCodeAttributes(printer); - printer->Print( - vars, - "public void Clear$property_name$() {\n" - " $name$Case_ = $property_name$OneofCase.None;\n" - " $name$_ = null;\n" - "}\n\n"); + printer->Print(vars, + "public void Clear$property_name$() {\n" + " $name$Case_ = $property_name$OneofCase.None;\n" + " $name$_ = null;\n" + "}\n\n"); } // Standard methods @@ -290,10 +288,10 @@ void MessageGenerator::Generate(io::Printer* printer) { // Nested messages and enums if (HasNestedGeneratedTypes()) { - printer->Print( - vars, - "#region Nested types\n" - "/// Container for nested types declared in the $class_name$ message type.\n"); + printer->Print(vars, + "#region Nested types\n" + "/// Container for nested types declared in the " + "$class_name$ message type.\n"); WriteGeneratedCodeAttributes(printer); printer->Print("public static partial class Types {\n"); printer->Indent(); @@ -304,35 +302,36 @@ void MessageGenerator::Generate(io::Printer* printer) { for (int i = 0; i < descriptor_->nested_type_count(); i++) { // Don't generate nested types for maps... if (!IsMapEntryMessage(descriptor_->nested_type(i))) { - MessageGenerator messageGenerator( - descriptor_->nested_type(i), this->options()); + MessageGenerator messageGenerator(descriptor_->nested_type(i), + this->options()); messageGenerator.Generate(printer); } } printer->Outdent(); - printer->Print("}\n" - "#endregion\n" - "\n"); + printer->Print( + "}\n" + "#endregion\n" + "\n"); } if (descriptor_->extension_count() > 0) { - printer->Print( - vars, - "#region Extensions\n" - "/// Container for extensions for other messages declared in the $class_name$ message type.\n"); + printer->Print(vars, + "#region Extensions\n" + "/// Container for extensions for other messages " + "declared in the $class_name$ message type.\n"); WriteGeneratedCodeAttributes(printer); printer->Print("public static partial class Extensions {\n"); printer->Indent(); for (int i = 0; i < descriptor_->extension_count(); i++) { std::unique_ptr generator( - CreateFieldGeneratorInternal(descriptor_->extension(i))); + CreateFieldGeneratorInternal(descriptor_->extension(i))); generator->GenerateExtensionCode(printer); } printer->Outdent(); printer->Print( - "}\n" - "#endregion\n" - "\n"); + "}\n" + "#endregion\n" + "\n"); } printer->Outdent(); @@ -340,10 +339,9 @@ void MessageGenerator::Generate(io::Printer* printer) { printer->Print("\n"); } -// Helper to work out whether we need to generate a class to hold nested types/enums. -// Only tricky because we don't want to generate map entry types. -bool MessageGenerator::HasNestedGeneratedTypes() -{ +// Helper to work out whether we need to generate a class to hold nested +// types/enums. Only tricky because we don't want to generate map entry types. +bool MessageGenerator::HasNestedGeneratedTypes() { if (descriptor_->enum_type_count() > 0) { return true; } @@ -359,9 +357,7 @@ void MessageGenerator::GenerateCloningCode(io::Printer* printer) { absl::flat_hash_map vars; WriteGeneratedCodeAttributes(printer); vars["class_name"] = class_name(); - printer->Print( - vars, - "public $class_name$($class_name$ other) : this() {\n"); + printer->Print(vars, "public $class_name$($class_name$ other) : this() {\n"); printer->Indent(); for (int i = 0; i < has_bit_field_count_; i++) { printer->Print("_hasBits$i$ = other._hasBits$i$;\n", "i", absl::StrCat(i)); @@ -372,7 +368,8 @@ void MessageGenerator::GenerateCloningCode(io::Printer* printer) { if (field->real_containing_oneof()) { continue; } - std::unique_ptr generator(CreateFieldGeneratorInternal(field)); + std::unique_ptr generator( + CreateFieldGeneratorInternal(field)); generator->GenerateCloningCode(printer); } // Clone just the right field for each real oneof @@ -384,11 +381,11 @@ void MessageGenerator::GenerateCloningCode(io::Printer* printer) { printer->Indent(); for (int j = 0; j < oneof->field_count(); j++) { const FieldDescriptor* field = oneof->field(j); - std::unique_ptr generator(CreateFieldGeneratorInternal(field)); + std::unique_ptr generator( + CreateFieldGeneratorInternal(field)); vars["oneof_case_name"] = GetOneofCaseName(field); - printer->Print( - vars, - "case $property_name$OneofCase.$oneof_case_name$:\n"); + printer->Print(vars, + "case $property_name$OneofCase.$oneof_case_name$:\n"); printer->Indent(); generator->GenerateCloningCode(printer); printer->Print("break;\n"); @@ -409,15 +406,13 @@ void MessageGenerator::GenerateCloningCode(io::Printer* printer) { printer->Print("}\n\n"); WriteGeneratedCodeAttributes(printer); - printer->Print( - vars, - "public $class_name$ Clone() {\n" - " return new $class_name$(this);\n" - "}\n\n"); + printer->Print(vars, + "public $class_name$ Clone() {\n" + " return new $class_name$(this);\n" + "}\n\n"); } -void MessageGenerator::GenerateFreezingCode(io::Printer* printer) { -} +void MessageGenerator::GenerateFreezingCode(io::Printer* printer) {} void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) { absl::flat_hash_map vars; @@ -444,62 +439,66 @@ void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) { CreateFieldGeneratorInternal(descriptor_->field(i))); generator->WriteEquals(printer); } - for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) { - printer->Print("if ($property_name$Case != other.$property_name$Case) return false;\n", - "property_name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); - } - if (has_extension_ranges_) { - printer->Print( - "if (!Equals(_extensions, other._extensions)) {\n" - " return false;\n" - "}\n"); - } - printer->Outdent(); + for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) { printer->Print( - " return Equals(_unknownFields, other._unknownFields);\n" - "}\n\n"); + "if ($property_name$Case != other.$property_name$Case) return false;\n", + "property_name", + UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); + } + if (has_extension_ranges_) { + printer->Print( + "if (!Equals(_extensions, other._extensions)) {\n" + " return false;\n" + "}\n"); + } + printer->Outdent(); + printer->Print( + " return Equals(_unknownFields, other._unknownFields);\n" + "}\n\n"); - // GetHashCode - // Start with a non-zero value to easily distinguish between null and "empty" messages. - WriteGeneratedCodeAttributes(printer); + // GetHashCode + // Start with a non-zero value to easily distinguish between null and "empty" + // messages. + WriteGeneratedCodeAttributes(printer); + printer->Print( + "public override int GetHashCode() {\n" + " int hash = 1;\n"); + printer->Indent(); + for (int i = 0; i < descriptor_->field_count(); i++) { + std::unique_ptr generator( + CreateFieldGeneratorInternal(descriptor_->field(i))); + generator->WriteHash(printer); + } + for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) { + printer->Print( + "hash ^= (int) $name$Case_;\n", "name", + UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false)); + } + if (has_extension_ranges_) { printer->Print( - "public override int GetHashCode() {\n" - " int hash = 1;\n"); - printer->Indent(); - for (int i = 0; i < descriptor_->field_count(); i++) { - std::unique_ptr generator( - CreateFieldGeneratorInternal(descriptor_->field(i))); - generator->WriteHash(printer); - } - for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) { - printer->Print("hash ^= (int) $name$Case_;\n", - "name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false)); - } - if (has_extension_ranges_) { - printer->Print( "if (_extensions != null) {\n" " hash ^= _extensions.GetHashCode();\n" "}\n"); - } - printer->Print( - "if (_unknownFields != null) {\n" - " hash ^= _unknownFields.GetHashCode();\n" - "}\n" - "return hash;\n"); - printer->Outdent(); - printer->Print("}\n\n"); + } + printer->Print( + "if (_unknownFields != null) {\n" + " hash ^= _unknownFields.GetHashCode();\n" + "}\n" + "return hash;\n"); + printer->Outdent(); + printer->Print("}\n\n"); - WriteGeneratedCodeAttributes(printer); - printer->Print( - "public override string ToString() {\n" - " return pb::JsonFormatter.ToDiagnosticString(this);\n" - "}\n\n"); + WriteGeneratedCodeAttributes(printer); + printer->Print( + "public override string ToString() {\n" + " return pb::JsonFormatter.ToDiagnosticString(this);\n" + "}\n\n"); } -void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer) { +void MessageGenerator::GenerateMessageSerializationMethods( + io::Printer* printer) { WriteGeneratedCodeAttributes(printer); - printer->Print( - "public void WriteTo(pb::CodedOutputStream output) {\n"); + printer->Print("public void WriteTo(pb::CodedOutputStream output) {\n"); printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n"); printer->Indent(); printer->Print("output.WriteRawMessage(this);\n"); @@ -513,7 +512,9 @@ void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer) printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n"); WriteGeneratedCodeAttributes(printer); - printer->Print("void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {\n"); + printer->Print( + "void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) " + "{\n"); printer->Indent(); GenerateWriteToBody(printer, true); printer->Outdent(); @@ -521,8 +522,7 @@ void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer) printer->Print("#endif\n\n"); WriteGeneratedCodeAttributes(printer); - printer->Print( - "public int CalculateSize() {\n"); + printer->Print("public int CalculateSize() {\n"); printer->Indent(); printer->Print("int size = 0;\n"); for (int i = 0; i < descriptor_->field_count(); i++) { @@ -533,50 +533,47 @@ void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer) if (has_extension_ranges_) { printer->Print( - "if (_extensions != null) {\n" - " size += _extensions.CalculateSize();\n" - "}\n"); + "if (_extensions != null) {\n" + " size += _extensions.CalculateSize();\n" + "}\n"); } printer->Print( - "if (_unknownFields != null) {\n" - " size += _unknownFields.CalculateSize();\n" - "}\n"); + "if (_unknownFields != null) {\n" + " size += _unknownFields.CalculateSize();\n" + "}\n"); printer->Print("return size;\n"); printer->Outdent(); printer->Print("}\n\n"); } -void MessageGenerator::GenerateWriteToBody(io::Printer* printer, bool use_write_context) { +void MessageGenerator::GenerateWriteToBody(io::Printer* printer, + bool use_write_context) { // Serialize all the fields for (int i = 0; i < fields_by_number().size(); i++) { std::unique_ptr generator( - CreateFieldGeneratorInternal(fields_by_number()[i])); + CreateFieldGeneratorInternal(fields_by_number()[i])); generator->GenerateSerializationCode(printer, use_write_context); } if (has_extension_ranges_) { // Serialize extensions - printer->Print( - use_write_context - ? "if (_extensions != null) {\n" - " _extensions.WriteTo(ref output);\n" - "}\n" - : "if (_extensions != null) {\n" - " _extensions.WriteTo(output);\n" - "}\n"); + printer->Print(use_write_context ? "if (_extensions != null) {\n" + " _extensions.WriteTo(ref output);\n" + "}\n" + : "if (_extensions != null) {\n" + " _extensions.WriteTo(output);\n" + "}\n"); } // Serialize unknown fields - printer->Print( - use_write_context - ? "if (_unknownFields != null) {\n" - " _unknownFields.WriteTo(ref output);\n" - "}\n" - : "if (_unknownFields != null) {\n" - " _unknownFields.WriteTo(output);\n" - "}\n"); + printer->Print(use_write_context ? "if (_unknownFields != null) {\n" + " _unknownFields.WriteTo(ref output);\n" + "}\n" + : "if (_unknownFields != null) {\n" + " _unknownFields.WriteTo(output);\n" + "}\n"); // TODO: Memoize size of frozen messages? } @@ -589,21 +586,20 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) { vars["class_name"] = class_name(); WriteGeneratedCodeAttributes(printer); - printer->Print( - vars, - "public void MergeFrom($class_name$ other) {\n"); + printer->Print(vars, "public void MergeFrom($class_name$ other) {\n"); printer->Indent(); printer->Print( - "if (other == null) {\n" - " return;\n" - "}\n"); + "if (other == null) {\n" + " return;\n" + "}\n"); // Merge non-oneof fields, treating optional proto3 fields as normal fields for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); if (field->real_containing_oneof()) { continue; } - std::unique_ptr generator(CreateFieldGeneratorInternal(field)); + std::unique_ptr generator( + CreateFieldGeneratorInternal(field)); generator->GenerateMergingCode(printer); } // Merge oneof fields (for non-synthetic oneofs) @@ -616,11 +612,11 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) { for (int j = 0; j < oneof->field_count(); j++) { const FieldDescriptor* field = oneof->field(j); vars["oneof_case_name"] = GetOneofCaseName(field); - printer->Print( - vars, - "case $property_name$OneofCase.$oneof_case_name$:\n"); + printer->Print(vars, + "case $property_name$OneofCase.$oneof_case_name$:\n"); printer->Indent(); - std::unique_ptr generator(CreateFieldGeneratorInternal(field)); + std::unique_ptr generator( + CreateFieldGeneratorInternal(field)); generator->GenerateMergingCode(printer); printer->Print("break;\n"); printer->Outdent(); @@ -630,12 +626,14 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) { } // Merge extensions if (has_extension_ranges_) { - printer->Print("pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions);\n"); + printer->Print( + "pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions);\n"); } // Merge unknown fields. printer->Print( - "_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);\n"); + "_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, " + "other._unknownFields);\n"); printer->Outdent(); printer->Print("}\n\n"); @@ -655,23 +653,25 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) { printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n"); WriteGeneratedCodeAttributes(printer); - printer->Print("void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {\n"); + printer->Print( + "void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) " + "{\n"); printer->Indent(); GenerateMainParseLoop(printer, true); printer->Outdent(); - printer->Print("}\n"); // method + printer->Print("}\n"); // method printer->Print("#endif\n\n"); - } -void MessageGenerator::GenerateMainParseLoop(io::Printer* printer, bool use_parse_context) { +void MessageGenerator::GenerateMainParseLoop(io::Printer* printer, + bool use_parse_context) { absl::flat_hash_map vars; vars["maybe_ref_input"] = use_parse_context ? "ref input" : "input"; printer->Print( - "uint tag;\n" - "while ((tag = input.ReadTag()) != 0) {\n" - " switch(tag) {\n"); + "uint tag;\n" + "while ((tag = input.ReadTag()) != 0) {\n" + " switch(tag) {\n"); printer->Indent(); printer->Indent(); if (end_tag_ != 0) { @@ -682,35 +682,37 @@ void MessageGenerator::GenerateMainParseLoop(io::Printer* printer, bool use_pars } if (has_extension_ranges_) { printer->Print(vars, - "default:\n" - " if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, $maybe_ref_input$)) {\n" - " _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, $maybe_ref_input$);\n" - " }\n" - " break;\n"); + "default:\n" + " if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, " + "$maybe_ref_input$)) {\n" + " _unknownFields = " + "pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, " + "$maybe_ref_input$);\n" + " }\n" + " break;\n"); } else { - printer->Print(vars, - "default:\n" - " _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, $maybe_ref_input$);\n" - " break;\n"); + printer->Print( + vars, + "default:\n" + " _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, " + "$maybe_ref_input$);\n" + " break;\n"); } for (int i = 0; i < fields_by_number().size(); i++) { const FieldDescriptor* field = fields_by_number()[i]; internal::WireFormatLite::WireType wt = internal::WireFormat::WireTypeForFieldType(field->type()); uint32_t tag = internal::WireFormatLite::MakeTag(field->number(), wt); - // Handle both packed and unpacked repeated fields with the same Read*Array call; - // the two generated cases are the packed and unpacked tags. + // Handle both packed and unpacked repeated fields with the same Read*Array + // call; the two generated cases are the packed and unpacked tags. // TODO: Check that is_packable is equivalent to // is_repeated && wt in { VARINT, FIXED32, FIXED64 }. // It looks like it is... if (field->is_packable()) { - printer->Print( - "case $packed_tag$:\n", - "packed_tag", - absl::StrCat( - internal::WireFormatLite::MakeTag( - field->number(), - internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED))); + printer->Print("case $packed_tag$:\n", "packed_tag", + absl::StrCat(internal::WireFormatLite::MakeTag( + field->number(), + internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED))); } printer->Print("case $tag$: {\n", "tag", absl::StrCat(tag)); @@ -723,12 +725,13 @@ void MessageGenerator::GenerateMainParseLoop(io::Printer* printer, bool use_pars printer->Print("}\n"); } printer->Outdent(); - printer->Print("}\n"); // switch + printer->Print("}\n"); // switch printer->Outdent(); - printer->Print("}\n"); // while + printer->Print("}\n"); // while } -// it's a waste of space to track presence for all values, so we only track them if they're not nullable +// it's a waste of space to track presence for all values, so we only track them +// if they're not nullable int MessageGenerator::GetPresenceIndex(const FieldDescriptor* descriptor) { if (!RequiresPresenceBit(descriptor)) { return -1; @@ -751,7 +754,8 @@ int MessageGenerator::GetPresenceIndex(const FieldDescriptor* descriptor) { FieldGeneratorBase* MessageGenerator::CreateFieldGeneratorInternal( const FieldDescriptor* descriptor) { - return CreateFieldGenerator(descriptor, GetPresenceIndex(descriptor), this->options()); + return CreateFieldGenerator(descriptor, GetPresenceIndex(descriptor), + this->options()); } } // namespace csharp