1// Protocol Buffers - Google's data interchange format 2// Copyright 2008 Google Inc. All rights reserved. 3// https://developers.google.com/protocol-buffers/ 4// 5// Redistribution and use in source and binary forms, with or without 6// modification, are permitted provided that the following conditions are 7// met: 8// 9// * Redistributions of source code must retain the above copyright 10// notice, this list of conditions and the following disclaimer. 11// * Redistributions in binary form must reproduce the above 12// copyright notice, this list of conditions and the following disclaimer 13// in the documentation and/or other materials provided with the 14// distribution. 15// * Neither the name of Google Inc. nor the names of its 16// contributors may be used to endorse or promote products derived from 17// this software without specific prior written permission. 18// 19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31#include <sstream> 32 33#include <google/protobuf/compiler/code_generator.h> 34#include <google/protobuf/compiler/plugin.h> 35#include <google/protobuf/descriptor.h> 36#include <google/protobuf/descriptor.pb.h> 37#include <google/protobuf/io/printer.h> 38#include <google/protobuf/io/zero_copy_stream.h> 39#include <google/protobuf/stubs/strutil.h> 40 41#include <google/protobuf/compiler/csharp/csharp_doc_comment.h> 42#include <google/protobuf/compiler/csharp/csharp_helpers.h> 43#include <google/protobuf/compiler/csharp/csharp_message_field.h> 44#include <google/protobuf/compiler/csharp/csharp_options.h> 45 46namespace google { 47namespace protobuf { 48namespace compiler { 49namespace csharp { 50 51MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor, 52 int fieldOrdinal, 53 const Options *options) 54 : FieldGeneratorBase(descriptor, fieldOrdinal, options) { 55 variables_["has_property_check"] = name() + "_ != null"; 56 variables_["has_not_property_check"] = name() + "_ == null"; 57} 58 59MessageFieldGenerator::~MessageFieldGenerator() { 60 61} 62 63void MessageFieldGenerator::GenerateMembers(io::Printer* printer) { 64 printer->Print( 65 variables_, 66 "private $type_name$ $name$_;\n"); 67 WritePropertyDocComment(printer, descriptor_); 68 AddDeprecatedFlag(printer); 69 printer->Print( 70 variables_, 71 "$access_level$ $type_name$ $property_name$ {\n" 72 " get { return $name$_; }\n" 73 " set {\n" 74 " $name$_ = value;\n" 75 " }\n" 76 "}\n"); 77} 78 79void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) { 80 printer->Print( 81 variables_, 82 "if (other.$has_property_check$) {\n" 83 " if ($has_not_property_check$) {\n" 84 " $name$_ = new $type_name$();\n" 85 " }\n" 86 " $property_name$.MergeFrom(other.$property_name$);\n" 87 "}\n"); 88} 89 90void MessageFieldGenerator::GenerateParsingCode(io::Printer* printer) { 91 printer->Print( 92 variables_, 93 "if ($has_not_property_check$) {\n" 94 " $name$_ = new $type_name$();\n" 95 "}\n" 96 // TODO(jonskeet): Do we really need merging behaviour like this? 97 "input.ReadMessage($name$_);\n"); // No need to support TYPE_GROUP... 98} 99 100void MessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) { 101 printer->Print( 102 variables_, 103 "if ($has_property_check$) {\n" 104 " output.WriteRawTag($tag_bytes$);\n" 105 " output.WriteMessage($property_name$);\n" 106 "}\n"); 107} 108 109void MessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { 110 printer->Print( 111 variables_, 112 "if ($has_property_check$) {\n" 113 " size += $tag_size$ + pb::CodedOutputStream.ComputeMessageSize($property_name$);\n" 114 "}\n"); 115} 116 117void MessageFieldGenerator::WriteHash(io::Printer* printer) { 118 printer->Print( 119 variables_, 120 "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n"); 121} 122void MessageFieldGenerator::WriteEquals(io::Printer* printer) { 123 printer->Print( 124 variables_, 125 "if (!object.Equals($property_name$, other.$property_name$)) return false;\n"); 126} 127void MessageFieldGenerator::WriteToString(io::Printer* printer) { 128 variables_["field_name"] = GetFieldName(descriptor_); 129 printer->Print( 130 variables_, 131 "PrintField(\"$field_name$\", has$property_name$, $name$_, writer);\n"); 132} 133 134void MessageFieldGenerator::GenerateCloningCode(io::Printer* printer) { 135 printer->Print(variables_, 136 "$property_name$ = other.$has_property_check$ ? other.$property_name$.Clone() : null;\n"); 137} 138 139void MessageFieldGenerator::GenerateFreezingCode(io::Printer* printer) { 140} 141 142void MessageFieldGenerator::GenerateCodecCode(io::Printer* printer) { 143 printer->Print( 144 variables_, 145 "pb::FieldCodec.ForMessage($tag$, $type_name$.Parser)"); 146} 147 148MessageOneofFieldGenerator::MessageOneofFieldGenerator( 149 const FieldDescriptor* descriptor, 150 int fieldOrdinal, 151 const Options *options) 152 : MessageFieldGenerator(descriptor, fieldOrdinal, options) { 153 SetCommonOneofFieldVariables(&variables_); 154} 155 156MessageOneofFieldGenerator::~MessageOneofFieldGenerator() { 157 158} 159 160void MessageOneofFieldGenerator::GenerateMembers(io::Printer* printer) { 161 WritePropertyDocComment(printer, descriptor_); 162 AddDeprecatedFlag(printer); 163 printer->Print( 164 variables_, 165 "$access_level$ $type_name$ $property_name$ {\n" 166 " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : null; }\n" 167 " set {\n" 168 " $oneof_name$_ = value;\n" 169 " $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n" 170 " }\n" 171 "}\n"); 172} 173 174void MessageOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { 175 // TODO(jonskeet): We may be able to do better than this 176 printer->Print( 177 variables_, 178 "$type_name$ subBuilder = new $type_name$();\n" 179 "if ($has_property_check$) {\n" 180 " subBuilder.MergeFrom($property_name$);\n" 181 "}\n" 182 "input.ReadMessage(subBuilder);\n" // No support of TYPE_GROUP 183 "$property_name$ = subBuilder;\n"); 184} 185 186void MessageOneofFieldGenerator::WriteToString(io::Printer* printer) { 187 printer->Print( 188 variables_, 189 "PrintField(\"$descriptor_name$\", $has_property_check$, $oneof_name$_, writer);\n"); 190} 191 192void MessageOneofFieldGenerator::GenerateCloningCode(io::Printer* printer) { 193 printer->Print(variables_, 194 "$property_name$ = other.$property_name$.Clone();\n"); 195} 196 197} // namespace csharp 198} // namespace compiler 199} // namespace protobuf 200} // namespace google 201