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 46 namespace google { 47 namespace protobuf { 48 namespace compiler { 49 namespace csharp { 50 51 MessageFieldGenerator::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 59 MessageFieldGenerator::~MessageFieldGenerator() { 60 61 } 62 63 void 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 79 void 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 90 void 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 100 void 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 109 void 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 117 void MessageFieldGenerator::WriteHash(io::Printer* printer) { 118 printer->Print( 119 variables_, 120 "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n"); 121 } 122 void MessageFieldGenerator::WriteEquals(io::Printer* printer) { 123 printer->Print( 124 variables_, 125 "if (!object.Equals($property_name$, other.$property_name$)) return false;\n"); 126 } 127 void 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 134 void MessageFieldGenerator::GenerateCloningCode(io::Printer* printer) { 135 printer->Print(variables_, 136 "$property_name$ = other.$has_property_check$ ? other.$property_name$.Clone() : null;\n"); 137 } 138 139 void MessageFieldGenerator::GenerateFreezingCode(io::Printer* printer) { 140 } 141 142 void MessageFieldGenerator::GenerateCodecCode(io::Printer* printer) { 143 printer->Print( 144 variables_, 145 "pb::FieldCodec.ForMessage($tag$, $type_name$.Parser)"); 146 } 147 148 MessageOneofFieldGenerator::MessageOneofFieldGenerator( 149 const FieldDescriptor* descriptor, 150 int fieldOrdinal, 151 const Options *options) 152 : MessageFieldGenerator(descriptor, fieldOrdinal, options) { 153 SetCommonOneofFieldVariables(&variables_); 154 } 155 156 MessageOneofFieldGenerator::~MessageOneofFieldGenerator() { 157 158 } 159 160 void 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 174 void 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 186 void MessageOneofFieldGenerator::WriteToString(io::Printer* printer) { 187 printer->Print( 188 variables_, 189 "PrintField(\"$descriptor_name$\", $has_property_check$, $oneof_name$_, writer);\n"); 190 } 191 192 void 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