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 | // Author: kenton@google.com (Kenton Varda) |
32 | // Based on original Protocol Buffers design by |
33 | // Sanjay Ghemawat, Jeff Dean, and others. |
34 | |
35 | #include <google/protobuf/compiler/java/field.h> |
36 | |
37 | #include <memory> |
38 | |
39 | #include <google/protobuf/stubs/logging.h> |
40 | #include <google/protobuf/stubs/common.h> |
41 | #include <google/protobuf/io/printer.h> |
42 | #include <google/protobuf/stubs/strutil.h> |
43 | #include <google/protobuf/stubs/substitute.h> |
44 | #include <google/protobuf/compiler/java/context.h> |
45 | #include <google/protobuf/compiler/java/enum_field.h> |
46 | #include <google/protobuf/compiler/java/enum_field_lite.h> |
47 | #include <google/protobuf/compiler/java/helpers.h> |
48 | #include <google/protobuf/compiler/java/map_field.h> |
49 | #include <google/protobuf/compiler/java/map_field_lite.h> |
50 | #include <google/protobuf/compiler/java/message_field.h> |
51 | #include <google/protobuf/compiler/java/message_field_lite.h> |
52 | #include <google/protobuf/compiler/java/primitive_field.h> |
53 | #include <google/protobuf/compiler/java/primitive_field_lite.h> |
54 | #include <google/protobuf/compiler/java/string_field.h> |
55 | #include <google/protobuf/compiler/java/string_field_lite.h> |
56 | |
57 | |
58 | namespace google { |
59 | namespace protobuf { |
60 | namespace compiler { |
61 | namespace java { |
62 | |
63 | namespace { |
64 | |
65 | ImmutableFieldGenerator* MakeImmutableGenerator(const FieldDescriptor* field, |
66 | int messageBitIndex, |
67 | int builderBitIndex, |
68 | Context* context) { |
69 | if (field->is_repeated()) { |
70 | switch (GetJavaType(field)) { |
71 | case JAVATYPE_MESSAGE: |
72 | if (IsMapEntry(descriptor: field->message_type())) { |
73 | return new ImmutableMapFieldGenerator(field, messageBitIndex, |
74 | builderBitIndex, context); |
75 | } else { |
76 | return new RepeatedImmutableMessageFieldGenerator( |
77 | field, messageBitIndex, builderBitIndex, context); |
78 | } |
79 | case JAVATYPE_ENUM: |
80 | return new RepeatedImmutableEnumFieldGenerator( |
81 | field, messageBitIndex, builderBitIndex, context); |
82 | case JAVATYPE_STRING: |
83 | return new RepeatedImmutableStringFieldGenerator( |
84 | field, messageBitIndex, builderBitIndex, context); |
85 | default: |
86 | return new RepeatedImmutablePrimitiveFieldGenerator( |
87 | field, messageBitIndex, builderBitIndex, context); |
88 | } |
89 | } else { |
90 | if (IsRealOneof(descriptor: field)) { |
91 | switch (GetJavaType(field)) { |
92 | case JAVATYPE_MESSAGE: |
93 | return new ImmutableMessageOneofFieldGenerator( |
94 | field, messageBitIndex, builderBitIndex, context); |
95 | case JAVATYPE_ENUM: |
96 | return new ImmutableEnumOneofFieldGenerator(field, messageBitIndex, |
97 | builderBitIndex, context); |
98 | case JAVATYPE_STRING: |
99 | return new ImmutableStringOneofFieldGenerator( |
100 | field, messageBitIndex, builderBitIndex, context); |
101 | default: |
102 | return new ImmutablePrimitiveOneofFieldGenerator( |
103 | field, messageBitIndex, builderBitIndex, context); |
104 | } |
105 | } else { |
106 | switch (GetJavaType(field)) { |
107 | case JAVATYPE_MESSAGE: |
108 | return new ImmutableMessageFieldGenerator(field, messageBitIndex, |
109 | builderBitIndex, context); |
110 | case JAVATYPE_ENUM: |
111 | return new ImmutableEnumFieldGenerator(field, messageBitIndex, |
112 | builderBitIndex, context); |
113 | case JAVATYPE_STRING: |
114 | return new ImmutableStringFieldGenerator(field, messageBitIndex, |
115 | builderBitIndex, context); |
116 | default: |
117 | return new ImmutablePrimitiveFieldGenerator(field, messageBitIndex, |
118 | builderBitIndex, context); |
119 | } |
120 | } |
121 | } |
122 | } |
123 | |
124 | ImmutableFieldLiteGenerator* MakeImmutableLiteGenerator( |
125 | const FieldDescriptor* field, int messageBitIndex, Context* context) { |
126 | if (field->is_repeated()) { |
127 | switch (GetJavaType(field)) { |
128 | case JAVATYPE_MESSAGE: |
129 | if (IsMapEntry(descriptor: field->message_type())) { |
130 | return new ImmutableMapFieldLiteGenerator(field, messageBitIndex, |
131 | context); |
132 | } else { |
133 | return new RepeatedImmutableMessageFieldLiteGenerator( |
134 | field, messageBitIndex, context); |
135 | } |
136 | case JAVATYPE_ENUM: |
137 | return new RepeatedImmutableEnumFieldLiteGenerator( |
138 | field, messageBitIndex, context); |
139 | case JAVATYPE_STRING: |
140 | return new RepeatedImmutableStringFieldLiteGenerator( |
141 | field, messageBitIndex, context); |
142 | default: |
143 | return new RepeatedImmutablePrimitiveFieldLiteGenerator( |
144 | field, messageBitIndex, context); |
145 | } |
146 | } else { |
147 | if (IsRealOneof(descriptor: field)) { |
148 | switch (GetJavaType(field)) { |
149 | case JAVATYPE_MESSAGE: |
150 | return new ImmutableMessageOneofFieldLiteGenerator( |
151 | field, messageBitIndex, context); |
152 | case JAVATYPE_ENUM: |
153 | return new ImmutableEnumOneofFieldLiteGenerator( |
154 | field, messageBitIndex, context); |
155 | case JAVATYPE_STRING: |
156 | return new ImmutableStringOneofFieldLiteGenerator( |
157 | field, messageBitIndex, context); |
158 | default: |
159 | return new ImmutablePrimitiveOneofFieldLiteGenerator( |
160 | field, messageBitIndex, context); |
161 | } |
162 | } else { |
163 | switch (GetJavaType(field)) { |
164 | case JAVATYPE_MESSAGE: |
165 | return new ImmutableMessageFieldLiteGenerator(field, messageBitIndex, |
166 | context); |
167 | case JAVATYPE_ENUM: |
168 | return new ImmutableEnumFieldLiteGenerator(field, messageBitIndex, |
169 | context); |
170 | case JAVATYPE_STRING: |
171 | return new ImmutableStringFieldLiteGenerator(field, messageBitIndex, |
172 | context); |
173 | default: |
174 | return new ImmutablePrimitiveFieldLiteGenerator( |
175 | field, messageBitIndex, context); |
176 | } |
177 | } |
178 | } |
179 | } |
180 | |
181 | |
182 | static inline void ReportUnexpectedPackedFieldsCall(io::Printer* printer) { |
183 | // Reaching here indicates a bug. Cases are: |
184 | // - This FieldGenerator should support packing, |
185 | // but this method should be overridden. |
186 | // - This FieldGenerator doesn't support packing, and this method |
187 | // should never have been called. |
188 | GOOGLE_LOG(FATAL) << "GenerateParsingCodeFromPacked() " |
189 | << "called on field generator that does not support packing." ; |
190 | } |
191 | |
192 | } // namespace |
193 | |
194 | ImmutableFieldGenerator::~ImmutableFieldGenerator() {} |
195 | |
196 | void ImmutableFieldGenerator::GenerateParsingCodeFromPacked( |
197 | io::Printer* printer) const { |
198 | ReportUnexpectedPackedFieldsCall(printer); |
199 | } |
200 | |
201 | ImmutableFieldLiteGenerator::~ImmutableFieldLiteGenerator() {} |
202 | |
203 | // =================================================================== |
204 | |
205 | template <> |
206 | FieldGeneratorMap<ImmutableFieldGenerator>::FieldGeneratorMap( |
207 | const Descriptor* descriptor, Context* context) |
208 | : descriptor_(descriptor), field_generators_(descriptor->field_count()) { |
209 | // Construct all the FieldGenerators and assign them bit indices for their |
210 | // bit fields. |
211 | int messageBitIndex = 0; |
212 | int builderBitIndex = 0; |
213 | for (int i = 0; i < descriptor->field_count(); i++) { |
214 | ImmutableFieldGenerator* generator = MakeImmutableGenerator( |
215 | field: descriptor->field(index: i), messageBitIndex, builderBitIndex, context); |
216 | field_generators_[i].reset(p: generator); |
217 | messageBitIndex += generator->GetNumBitsForMessage(); |
218 | builderBitIndex += generator->GetNumBitsForBuilder(); |
219 | } |
220 | } |
221 | |
222 | template <> |
223 | FieldGeneratorMap<ImmutableFieldGenerator>::~FieldGeneratorMap() {} |
224 | |
225 | template <> |
226 | FieldGeneratorMap<ImmutableFieldLiteGenerator>::FieldGeneratorMap( |
227 | const Descriptor* descriptor, Context* context) |
228 | : descriptor_(descriptor), field_generators_(descriptor->field_count()) { |
229 | // Construct all the FieldGenerators and assign them bit indices for their |
230 | // bit fields. |
231 | int messageBitIndex = 0; |
232 | for (int i = 0; i < descriptor->field_count(); i++) { |
233 | ImmutableFieldLiteGenerator* generator = MakeImmutableLiteGenerator( |
234 | field: descriptor->field(index: i), messageBitIndex, context); |
235 | field_generators_[i].reset(p: generator); |
236 | messageBitIndex += generator->GetNumBitsForMessage(); |
237 | } |
238 | } |
239 | |
240 | template <> |
241 | FieldGeneratorMap<ImmutableFieldLiteGenerator>::~FieldGeneratorMap() {} |
242 | |
243 | |
244 | void SetCommonFieldVariables(const FieldDescriptor* descriptor, |
245 | const FieldGeneratorInfo* info, |
246 | std::map<std::string, std::string>* variables) { |
247 | (*variables)["field_name" ] = descriptor->name(); |
248 | (*variables)["name" ] = info->name; |
249 | (*variables)["classname" ] = descriptor->containing_type()->name(); |
250 | (*variables)["capitalized_name" ] = info->capitalized_name; |
251 | (*variables)["disambiguated_reason" ] = info->disambiguated_reason; |
252 | (*variables)["constant_name" ] = FieldConstantName(field: descriptor); |
253 | (*variables)["number" ] = StrCat(a: descriptor->number()); |
254 | (*variables)["kt_dsl_builder" ] = "_builder" ; |
255 | // These variables are placeholders to pick out the beginning and ends of |
256 | // identifiers for annotations (when doing so with existing variables would |
257 | // be ambiguous or impossible). They should never be set to anything but the |
258 | // empty string. |
259 | (*variables)["{" ] = "" ; |
260 | (*variables)["}" ] = "" ; |
261 | (*variables)["kt_name" ] = |
262 | IsForbiddenKotlin(field_name: info->name) ? info->name + "_" : info->name; |
263 | (*variables)["kt_capitalized_name" ] = IsForbiddenKotlin(field_name: info->name) |
264 | ? info->capitalized_name + "_" |
265 | : info->capitalized_name; |
266 | if (!descriptor->is_repeated()) { |
267 | (*variables)["annotation_field_type" ] = FieldTypeName(field_type: descriptor->type()); |
268 | } else if (GetJavaType(field: descriptor) == JAVATYPE_MESSAGE && |
269 | IsMapEntry(descriptor: descriptor->message_type())) { |
270 | (*variables)["annotation_field_type" ] = |
271 | std::string(FieldTypeName(field_type: descriptor->type())) + "MAP" ; |
272 | } else { |
273 | (*variables)["annotation_field_type" ] = |
274 | std::string(FieldTypeName(field_type: descriptor->type())) + "_LIST" ; |
275 | if (descriptor->is_packed()) { |
276 | (*variables)["annotation_field_type" ] = |
277 | (*variables)["annotation_field_type" ] + "_PACKED" ; |
278 | } |
279 | } |
280 | } |
281 | |
282 | void SetCommonOneofVariables(const FieldDescriptor* descriptor, |
283 | const OneofGeneratorInfo* info, |
284 | std::map<std::string, std::string>* variables) { |
285 | (*variables)["oneof_name" ] = info->name; |
286 | (*variables)["oneof_capitalized_name" ] = info->capitalized_name; |
287 | (*variables)["oneof_index" ] = |
288 | StrCat(a: descriptor->containing_oneof()->index()); |
289 | (*variables)["oneof_stored_type" ] = GetOneofStoredType(field: descriptor); |
290 | (*variables)["set_oneof_case_message" ] = |
291 | info->name + "Case_ = " + StrCat(a: descriptor->number()); |
292 | (*variables)["clear_oneof_case_message" ] = info->name + "Case_ = 0" ; |
293 | (*variables)["has_oneof_case_message" ] = |
294 | info->name + "Case_ == " + StrCat(a: descriptor->number()); |
295 | } |
296 | |
297 | void (const std::map<std::string, std::string>& variables, |
298 | io::Printer* printer) { |
299 | const std::map<std::string, std::string>::const_iterator it = |
300 | variables.find(x: "disambiguated_reason" ); |
301 | if (it != variables.end() && !it->second.empty()) { |
302 | printer->Print( |
303 | variables, |
304 | text: "// An alternative name is used for field \"$field_name$\" because:\n" |
305 | "// $disambiguated_reason$\n" ); |
306 | } |
307 | } |
308 | |
309 | } // namespace java |
310 | } // namespace compiler |
311 | } // namespace protobuf |
312 | } // namespace google |
313 | |