• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
40 #include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
41 #include <google/protobuf/compiler/csharp/csharp_helpers.h>
42 #include <google/protobuf/compiler/csharp/csharp_options.h>
43 #include <google/protobuf/compiler/csharp/csharp_wrapper_field.h>
44 
45 namespace google {
46 namespace protobuf {
47 namespace compiler {
48 namespace csharp {
49 
WrapperFieldGenerator(const FieldDescriptor * descriptor,int fieldOrdinal,const Options * options)50 WrapperFieldGenerator::WrapperFieldGenerator(const FieldDescriptor* descriptor,
51                                        int fieldOrdinal, const Options *options)
52     : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
53   variables_["has_property_check"] = name() + "_ != null";
54   variables_["has_not_property_check"] = name() + "_ == null";
55   const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0);
56   is_value_type = wrapped_field->type() != FieldDescriptor::TYPE_STRING &&
57       wrapped_field->type() != FieldDescriptor::TYPE_BYTES;
58   if (is_value_type) {
59     variables_["nonnullable_type_name"] = type_name(wrapped_field);
60   }
61 }
62 
~WrapperFieldGenerator()63 WrapperFieldGenerator::~WrapperFieldGenerator() {
64 }
65 
GenerateMembers(io::Printer * printer)66 void WrapperFieldGenerator::GenerateMembers(io::Printer* printer) {
67   printer->Print(
68         variables_,
69         "private static readonly pb::FieldCodec<$type_name$> _single_$name$_codec = ");
70   GenerateCodecCode(printer);
71   printer->Print(
72     variables_,
73     ";\n"
74     "private $type_name$ $name$_;\n");
75   WritePropertyDocComment(printer, descriptor_);
76   AddDeprecatedFlag(printer);
77   printer->Print(
78     variables_,
79     "$access_level$ $type_name$ $property_name$ {\n"
80     "  get { return $name$_; }\n"
81     "  set {\n"
82     "    $name$_ = value;\n"
83     "  }\n"
84     "}\n");
85 }
86 
GenerateMergingCode(io::Printer * printer)87 void WrapperFieldGenerator::GenerateMergingCode(io::Printer* printer) {
88   printer->Print(
89     variables_,
90     "if (other.$has_property_check$) {\n"
91     "  if ($has_not_property_check$ || other.$property_name$ != $default_value$) {\n"
92     "    $property_name$ = other.$property_name$;\n"
93     "  }\n"
94     "}\n");
95 }
96 
GenerateParsingCode(io::Printer * printer)97 void WrapperFieldGenerator::GenerateParsingCode(io::Printer* printer) {
98   printer->Print(
99     variables_,
100     "$type_name$ value = _single_$name$_codec.Read(input);\n"
101     "if ($has_not_property_check$ || value != $default_value$) {\n"
102     "  $property_name$ = value;\n"
103     "}\n");
104 }
105 
GenerateSerializationCode(io::Printer * printer)106 void WrapperFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
107   printer->Print(
108     variables_,
109     "if ($has_property_check$) {\n"
110     "  _single_$name$_codec.WriteTagAndValue(output, $property_name$);\n"
111     "}\n");
112 }
113 
GenerateSerializedSizeCode(io::Printer * printer)114 void WrapperFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
115   printer->Print(
116     variables_,
117     "if ($has_property_check$) {\n"
118     "  size += _single_$name$_codec.CalculateSizeWithTag($property_name$);\n"
119     "}\n");
120 }
121 
WriteHash(io::Printer * printer)122 void WrapperFieldGenerator::WriteHash(io::Printer* printer) {
123   printer->Print(
124     variables_,
125     "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n");
126 }
127 
WriteEquals(io::Printer * printer)128 void WrapperFieldGenerator::WriteEquals(io::Printer* printer) {
129   printer->Print(
130     variables_,
131     "if ($property_name$ != other.$property_name$) return false;\n");
132 }
133 
WriteToString(io::Printer * printer)134 void WrapperFieldGenerator::WriteToString(io::Printer* printer) {
135   // TODO: Implement if we ever actually need it...
136 }
137 
GenerateCloningCode(io::Printer * printer)138 void WrapperFieldGenerator::GenerateCloningCode(io::Printer* printer) {
139   printer->Print(variables_,
140     "$property_name$ = other.$property_name$;\n");
141 }
142 
GenerateCodecCode(io::Printer * printer)143 void WrapperFieldGenerator::GenerateCodecCode(io::Printer* printer) {
144   if (is_value_type) {
145     printer->Print(
146       variables_,
147       "pb::FieldCodec.ForStructWrapper<$nonnullable_type_name$>($tag$)");
148   } else {
149     printer->Print(
150       variables_,
151       "pb::FieldCodec.ForClassWrapper<$type_name$>($tag$)");
152   }
153 }
154 
WrapperOneofFieldGenerator(const FieldDescriptor * descriptor,int fieldOrdinal,const Options * options)155 WrapperOneofFieldGenerator::WrapperOneofFieldGenerator(
156     const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
157     : WrapperFieldGenerator(descriptor, fieldOrdinal, options) {
158     SetCommonOneofFieldVariables(&variables_);
159 }
160 
~WrapperOneofFieldGenerator()161 WrapperOneofFieldGenerator::~WrapperOneofFieldGenerator() {
162 }
163 
GenerateMembers(io::Printer * printer)164 void WrapperOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
165   // Note: deliberately _oneof_$name$_codec, not _$oneof_name$_codec... we have one codec per field.
166   printer->Print(
167         variables_,
168         "private static readonly pb::FieldCodec<$type_name$> _oneof_$name$_codec = ");
169   GenerateCodecCode(printer);
170   printer->Print(";\n");
171   WritePropertyDocComment(printer, descriptor_);
172   AddDeprecatedFlag(printer);
173   printer->Print(
174     variables_,
175     "$access_level$ $type_name$ $property_name$ {\n"
176     "  get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : ($type_name$) null; }\n"
177     "  set {\n"
178     "    $oneof_name$_ = value;\n"
179     "    $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n"
180     "  }\n"
181     "}\n");
182 }
183 
GenerateParsingCode(io::Printer * printer)184 void WrapperOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
185   printer->Print(
186     variables_,
187     "$property_name$ = _oneof_$name$_codec.Read(input);\n");
188 }
189 
GenerateSerializationCode(io::Printer * printer)190 void WrapperOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
191   // TODO: I suspect this is wrong...
192   printer->Print(
193     variables_,
194     "if ($has_property_check$) {\n"
195     "  _oneof_$name$_codec.WriteTagAndValue(output, ($type_name$) $oneof_name$_);\n"
196     "}\n");
197 }
198 
GenerateSerializedSizeCode(io::Printer * printer)199 void WrapperOneofFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
200   // TODO: I suspect this is wrong...
201   printer->Print(
202     variables_,
203     "if ($has_property_check$) {\n"
204     "  size += _oneof_$name$_codec.CalculateSizeWithTag($property_name$);\n"
205     "}\n");
206 }
207 
208 }  // namespace csharp
209 }  // namespace compiler
210 }  // namespace protobuf
211 }  // namespace google
212