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/message.h> |
36 | |
37 | #include <algorithm> |
38 | #include <cstdint> |
39 | #include <map> |
40 | #include <memory> |
41 | #include <vector> |
42 | |
43 | #include <google/protobuf/io/coded_stream.h> |
44 | #include <google/protobuf/io/printer.h> |
45 | #include <google/protobuf/wire_format.h> |
46 | #include <google/protobuf/stubs/strutil.h> |
47 | #include <google/protobuf/stubs/substitute.h> |
48 | #include <google/protobuf/compiler/java/context.h> |
49 | #include <google/protobuf/compiler/java/doc_comment.h> |
50 | #include <google/protobuf/compiler/java/enum.h> |
51 | #include <google/protobuf/compiler/java/extension.h> |
52 | #include <google/protobuf/compiler/java/generator_factory.h> |
53 | #include <google/protobuf/compiler/java/helpers.h> |
54 | #include <google/protobuf/compiler/java/message_builder.h> |
55 | #include <google/protobuf/compiler/java/message_builder_lite.h> |
56 | #include <google/protobuf/compiler/java/name_resolver.h> |
57 | #include <google/protobuf/descriptor.pb.h> |
58 | |
59 | // Must be last. |
60 | #include <google/protobuf/port_def.inc> |
61 | |
62 | namespace google { |
63 | namespace protobuf { |
64 | namespace compiler { |
65 | namespace java { |
66 | |
67 | using internal::WireFormat; |
68 | using internal::WireFormatLite; |
69 | |
70 | namespace { |
71 | std::string MapValueImmutableClassdName(const Descriptor* descriptor, |
72 | ClassNameResolver* name_resolver) { |
73 | const FieldDescriptor* value_field = descriptor->map_value(); |
74 | GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type()); |
75 | return name_resolver->GetImmutableClassName(descriptor: value_field->message_type()); |
76 | } |
77 | } // namespace |
78 | |
79 | // =================================================================== |
80 | |
81 | MessageGenerator::MessageGenerator(const Descriptor* descriptor) |
82 | : descriptor_(descriptor) { |
83 | for (int i = 0; i < descriptor_->field_count(); i++) { |
84 | if (IsRealOneof(descriptor: descriptor_->field(index: i))) { |
85 | oneofs_.insert(x: descriptor_->field(index: i)->containing_oneof()); |
86 | } |
87 | } |
88 | } |
89 | |
90 | MessageGenerator::~MessageGenerator() {} |
91 | |
92 | // =================================================================== |
93 | ImmutableMessageGenerator::ImmutableMessageGenerator( |
94 | const Descriptor* descriptor, Context* context) |
95 | : MessageGenerator(descriptor), |
96 | context_(context), |
97 | name_resolver_(context->GetNameResolver()), |
98 | field_generators_(descriptor, context_) { |
99 | GOOGLE_CHECK(HasDescriptorMethods(descriptor->file(), context->EnforceLite())) |
100 | << "Generator factory error: A non-lite message generator is used to " |
101 | "generate lite messages." ; |
102 | } |
103 | |
104 | ImmutableMessageGenerator::~ImmutableMessageGenerator() {} |
105 | |
106 | void ImmutableMessageGenerator::GenerateStaticVariables( |
107 | io::Printer* printer, int* bytecode_estimate) { |
108 | // Because descriptor.proto (com.google.protobuf.DescriptorProtos) is |
109 | // used in the construction of descriptors, we have a tricky bootstrapping |
110 | // problem. To help control static initialization order, we make sure all |
111 | // descriptors and other static data that depends on them are members of |
112 | // the outermost class in the file. This way, they will be initialized in |
113 | // a deterministic order. |
114 | |
115 | std::map<std::string, std::string> vars; |
116 | vars["identifier" ] = UniqueFileScopeIdentifier(descriptor: descriptor_); |
117 | vars["index" ] = StrCat(a: descriptor_->index()); |
118 | vars["classname" ] = name_resolver_->GetImmutableClassName(descriptor: descriptor_); |
119 | if (descriptor_->containing_type() != NULL) { |
120 | vars["parent" ] = UniqueFileScopeIdentifier(descriptor: descriptor_->containing_type()); |
121 | } |
122 | if (MultipleJavaFiles(descriptor: descriptor_->file(), /* immutable = */ true)) { |
123 | // We can only make these package-private since the classes that use them |
124 | // are in separate files. |
125 | vars["private" ] = "" ; |
126 | } else { |
127 | vars["private" ] = "private " ; |
128 | } |
129 | if (*bytecode_estimate <= kMaxStaticSize) { |
130 | vars["final" ] = "final " ; |
131 | } else { |
132 | vars["final" ] = "" ; |
133 | } |
134 | |
135 | // The descriptor for this type. |
136 | printer->Print( |
137 | variables: vars, |
138 | // TODO(teboring): final needs to be added back. The way to fix it is to |
139 | // generate methods that can construct the types, and then still declare |
140 | // the types, and then init them in clinit with the new method calls. |
141 | text: "$private$static $final$com.google.protobuf.Descriptors.Descriptor\n" |
142 | " internal_$identifier$_descriptor;\n" ); |
143 | *bytecode_estimate += 30; |
144 | |
145 | // And the FieldAccessorTable. |
146 | GenerateFieldAccessorTable(printer, bytecode_estimate); |
147 | |
148 | // Generate static members for all nested types. |
149 | for (int i = 0; i < descriptor_->nested_type_count(); i++) { |
150 | // TODO(kenton): Reuse MessageGenerator objects? |
151 | ImmutableMessageGenerator(descriptor_->nested_type(index: i), context_) |
152 | .GenerateStaticVariables(printer, bytecode_estimate); |
153 | } |
154 | } |
155 | |
156 | int ImmutableMessageGenerator::GenerateStaticVariableInitializers( |
157 | io::Printer* printer) { |
158 | int bytecode_estimate = 0; |
159 | std::map<std::string, std::string> vars; |
160 | vars["identifier" ] = UniqueFileScopeIdentifier(descriptor: descriptor_); |
161 | vars["index" ] = StrCat(a: descriptor_->index()); |
162 | vars["classname" ] = name_resolver_->GetImmutableClassName(descriptor: descriptor_); |
163 | if (descriptor_->containing_type() != NULL) { |
164 | vars["parent" ] = UniqueFileScopeIdentifier(descriptor: descriptor_->containing_type()); |
165 | } |
166 | |
167 | // The descriptor for this type. |
168 | if (descriptor_->containing_type() == NULL) { |
169 | printer->Print(variables: vars, |
170 | text: "internal_$identifier$_descriptor =\n" |
171 | " getDescriptor().getMessageTypes().get($index$);\n" ); |
172 | bytecode_estimate += 30; |
173 | } else { |
174 | printer->Print( |
175 | variables: vars, |
176 | text: "internal_$identifier$_descriptor =\n" |
177 | " internal_$parent$_descriptor.getNestedTypes().get($index$);\n" ); |
178 | bytecode_estimate += 30; |
179 | } |
180 | |
181 | // And the FieldAccessorTable. |
182 | bytecode_estimate += GenerateFieldAccessorTableInitializer(printer); |
183 | |
184 | // Generate static member initializers for all nested types. |
185 | for (int i = 0; i < descriptor_->nested_type_count(); i++) { |
186 | // TODO(kenton): Reuse MessageGenerator objects? |
187 | bytecode_estimate += |
188 | ImmutableMessageGenerator(descriptor_->nested_type(index: i), context_) |
189 | .GenerateStaticVariableInitializers(printer); |
190 | } |
191 | return bytecode_estimate; |
192 | } |
193 | |
194 | void ImmutableMessageGenerator::GenerateFieldAccessorTable( |
195 | io::Printer* printer, int* bytecode_estimate) { |
196 | std::map<std::string, std::string> vars; |
197 | vars["identifier" ] = UniqueFileScopeIdentifier(descriptor: descriptor_); |
198 | if (MultipleJavaFiles(descriptor: descriptor_->file(), /* immutable = */ true)) { |
199 | // We can only make these package-private since the classes that use them |
200 | // are in separate files. |
201 | vars["private" ] = "" ; |
202 | } else { |
203 | vars["private" ] = "private " ; |
204 | } |
205 | if (*bytecode_estimate <= kMaxStaticSize) { |
206 | vars["final" ] = "final " ; |
207 | } else { |
208 | vars["final" ] = "" ; |
209 | } |
210 | vars["ver" ] = GeneratedCodeVersionSuffix(); |
211 | printer->Print( |
212 | variables: vars, |
213 | text: "$private$static $final$\n" |
214 | " com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n" |
215 | " internal_$identifier$_fieldAccessorTable;\n" ); |
216 | |
217 | // The following bytecode_estimate calculation logic must stay in sync with |
218 | // the similar logic in the GenerateFieldAccessorTableInitializer method below |
219 | // to make sure that the generated static final fields are initialized in the |
220 | // static initialization block directly. |
221 | // |
222 | // 6 bytes per field and oneof |
223 | *bytecode_estimate += |
224 | 10 + 6 * descriptor_->field_count() + 6 * descriptor_->oneof_decl_count(); |
225 | } |
226 | |
227 | int ImmutableMessageGenerator::GenerateFieldAccessorTableInitializer( |
228 | io::Printer* printer) { |
229 | int bytecode_estimate = 10; |
230 | printer->Print( |
231 | text: "internal_$identifier$_fieldAccessorTable = new\n" |
232 | " com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable(\n" |
233 | " internal_$identifier$_descriptor,\n" |
234 | " new java.lang.String[] { " , |
235 | args: "identifier" , args: UniqueFileScopeIdentifier(descriptor: descriptor_), args: "ver" , |
236 | args: GeneratedCodeVersionSuffix()); |
237 | // All the bytecode_estimate calculation logic in this method must stay in |
238 | // sync with the similar logic in the GenerateFieldAccessorTable method |
239 | // above. See the corresponding comment in GenerateFieldAccessorTable for |
240 | // details. |
241 | for (int i = 0; i < descriptor_->field_count(); i++) { |
242 | const FieldDescriptor* field = descriptor_->field(index: i); |
243 | const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); |
244 | bytecode_estimate += 6; |
245 | printer->Print(text: "\"$field_name$\", " , args: "field_name" , args: info->capitalized_name); |
246 | } |
247 | // We reproduce synthetic oneofs here since proto reflection needs these. |
248 | for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { |
249 | const OneofDescriptor* oneof = descriptor_->oneof_decl(index: i); |
250 | const OneofGeneratorInfo* info = context_->GetOneofGeneratorInfo(oneof); |
251 | bytecode_estimate += 6; |
252 | printer->Print(text: "\"$oneof_name$\", " , args: "oneof_name" , args: info->capitalized_name); |
253 | } |
254 | printer->Print(text: "});\n" ); |
255 | return bytecode_estimate; |
256 | } |
257 | |
258 | // =================================================================== |
259 | |
260 | void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) { |
261 | MaybePrintGeneratedAnnotation(context: context_, printer, descriptor: descriptor_, |
262 | /* immutable = */ true, suffix: "OrBuilder" ); |
263 | if (descriptor_->extension_range_count() > 0) { |
264 | printer->Print( |
265 | text: "$deprecation$public interface ${$$classname$OrBuilder$}$ extends\n" |
266 | " $extra_interfaces$\n" |
267 | " com.google.protobuf.GeneratedMessage$ver$.\n" |
268 | " ExtendableMessageOrBuilder<$classname$> {\n" , |
269 | args: "deprecation" , |
270 | args: descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "" , |
271 | args: "extra_interfaces" , args: ExtraMessageOrBuilderInterfaces(descriptor: descriptor_), |
272 | args: "classname" , args: descriptor_->name(), args: "{" , args: "" , args: "}" , args: "" , args: "ver" , |
273 | args: GeneratedCodeVersionSuffix()); |
274 | } else { |
275 | printer->Print( |
276 | text: "$deprecation$public interface ${$$classname$OrBuilder$}$ extends\n" |
277 | " $extra_interfaces$\n" |
278 | " com.google.protobuf.MessageOrBuilder {\n" , |
279 | args: "deprecation" , |
280 | args: descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "" , |
281 | args: "extra_interfaces" , args: ExtraMessageOrBuilderInterfaces(descriptor: descriptor_), |
282 | args: "classname" , args: descriptor_->name(), args: "{" , args: "" , args: "}" , args: "" ); |
283 | } |
284 | printer->Annotate(begin_varname: "{" , end_varname: "}" , descriptor: descriptor_); |
285 | |
286 | printer->Indent(); |
287 | for (int i = 0; i < descriptor_->field_count(); i++) { |
288 | printer->Print(text: "\n" ); |
289 | field_generators_.get(field: descriptor_->field(index: i)) |
290 | .GenerateInterfaceMembers(printer); |
291 | } |
292 | for (auto oneof : oneofs_) { |
293 | printer->Print( |
294 | text: "\n" |
295 | "public $classname$.$oneof_capitalized_name$Case " |
296 | "get$oneof_capitalized_name$Case();\n" , |
297 | args: "oneof_capitalized_name" , |
298 | args: context_->GetOneofGeneratorInfo(oneof)->capitalized_name, args: "classname" , |
299 | args: context_->GetNameResolver()->GetImmutableClassName(descriptor: descriptor_)); |
300 | } |
301 | printer->Outdent(); |
302 | |
303 | printer->Print(text: "}\n" ); |
304 | } |
305 | |
306 | // =================================================================== |
307 | |
308 | void ImmutableMessageGenerator::Generate(io::Printer* printer) { |
309 | bool is_own_file = IsOwnFile(descriptor: descriptor_, /* immutable = */ true); |
310 | |
311 | std::map<std::string, std::string> variables; |
312 | variables["static" ] = is_own_file ? "" : "static " ; |
313 | variables["classname" ] = descriptor_->name(); |
314 | variables["extra_interfaces" ] = ExtraMessageInterfaces(descriptor: descriptor_); |
315 | variables["ver" ] = GeneratedCodeVersionSuffix(); |
316 | variables["deprecation" ] = |
317 | descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "" ; |
318 | |
319 | WriteMessageDocComment(printer, message: descriptor_); |
320 | MaybePrintGeneratedAnnotation(context: context_, printer, descriptor: descriptor_, |
321 | /* immutable = */ true); |
322 | // The builder_type stores the super type name of the nested Builder class. |
323 | std::string builder_type; |
324 | if (descriptor_->extension_range_count() > 0) { |
325 | printer->Print( |
326 | variables, |
327 | text: "$deprecation$public $static$final class $classname$ extends\n" ); |
328 | printer->Annotate(varname: "classname" , descriptor: descriptor_); |
329 | printer->Print( |
330 | variables, |
331 | text: " com.google.protobuf.GeneratedMessage$ver$.ExtendableMessage<\n" |
332 | " $classname$> implements\n" |
333 | " $extra_interfaces$\n" |
334 | " $classname$OrBuilder {\n" ); |
335 | builder_type = strings::Substitute( |
336 | format: "com.google.protobuf.GeneratedMessage$1.ExtendableBuilder<$0, ?>" , |
337 | arg0: name_resolver_->GetImmutableClassName(descriptor: descriptor_), |
338 | arg1: GeneratedCodeVersionSuffix()); |
339 | } else { |
340 | printer->Print( |
341 | variables, |
342 | text: "$deprecation$public $static$final class $classname$ extends\n" ); |
343 | printer->Annotate(varname: "classname" , descriptor: descriptor_); |
344 | printer->Print(variables, |
345 | text: " com.google.protobuf.GeneratedMessage$ver$ implements\n" |
346 | " $extra_interfaces$\n" |
347 | " $classname$OrBuilder {\n" ); |
348 | builder_type = |
349 | strings::Substitute(format: "com.google.protobuf.GeneratedMessage$0.Builder<?>" , |
350 | arg0: GeneratedCodeVersionSuffix()); |
351 | } |
352 | printer->Print(text: "private static final long serialVersionUID = 0L;\n" ); |
353 | |
354 | printer->Indent(); |
355 | // Using builder_type, instead of Builder, prevents the Builder class from |
356 | // being loaded into PermGen space when the default instance is created. |
357 | // This optimizes the PermGen space usage for clients that do not modify |
358 | // messages. |
359 | printer->Print( |
360 | text: "// Use $classname$.newBuilder() to construct.\n" |
361 | "private $classname$($buildertype$ builder) {\n" |
362 | " super(builder);\n" |
363 | "}\n" , |
364 | args: "classname" , args: descriptor_->name(), args: "buildertype" , args: builder_type); |
365 | printer->Print(text: "private $classname$() {\n" , args: "classname" , args: descriptor_->name()); |
366 | printer->Indent(); |
367 | GenerateInitializers(printer); |
368 | printer->Outdent(); |
369 | printer->Print( |
370 | text: "}\n" |
371 | "\n" ); |
372 | |
373 | printer->Print(variables, |
374 | text: "@java.lang.Override\n" |
375 | "@SuppressWarnings({\"unused\"})\n" |
376 | "protected java.lang.Object newInstance(\n" |
377 | " UnusedPrivateParameter unused) {\n" |
378 | " return new $classname$();\n" |
379 | "}\n" |
380 | "\n" ); |
381 | |
382 | printer->Print( |
383 | text: "@java.lang.Override\n" |
384 | "public final com.google.protobuf.UnknownFieldSet\n" |
385 | "getUnknownFields() {\n" |
386 | " return this.unknownFields;\n" |
387 | "}\n" ); |
388 | |
389 | if (context_->HasGeneratedMethods(descriptor: descriptor_)) { |
390 | GenerateParsingConstructor(printer); |
391 | } |
392 | |
393 | GenerateDescriptorMethods(printer); |
394 | |
395 | // Nested types |
396 | for (int i = 0; i < descriptor_->enum_type_count(); i++) { |
397 | EnumGenerator(descriptor_->enum_type(index: i), true, context_).Generate(printer); |
398 | } |
399 | |
400 | for (int i = 0; i < descriptor_->nested_type_count(); i++) { |
401 | // Don't generate Java classes for map entry messages. |
402 | if (IsMapEntry(descriptor: descriptor_->nested_type(index: i))) continue; |
403 | ImmutableMessageGenerator messageGenerator(descriptor_->nested_type(index: i), |
404 | context_); |
405 | messageGenerator.GenerateInterface(printer); |
406 | messageGenerator.Generate(printer); |
407 | } |
408 | |
409 | // Integers for bit fields. |
410 | int totalBits = 0; |
411 | for (int i = 0; i < descriptor_->field_count(); i++) { |
412 | totalBits += |
413 | field_generators_.get(field: descriptor_->field(index: i)).GetNumBitsForMessage(); |
414 | } |
415 | int totalInts = (totalBits + 31) / 32; |
416 | for (int i = 0; i < totalInts; i++) { |
417 | printer->Print(text: "private int $bit_field_name$;\n" , args: "bit_field_name" , |
418 | args: GetBitFieldName(index: i)); |
419 | } |
420 | |
421 | // oneof |
422 | std::map<std::string, std::string> vars; |
423 | for (auto oneof : oneofs_) { |
424 | vars["oneof_name" ] = context_->GetOneofGeneratorInfo(oneof)->name; |
425 | vars["oneof_capitalized_name" ] = |
426 | context_->GetOneofGeneratorInfo(oneof)->capitalized_name; |
427 | vars["oneof_index" ] = StrCat(a: (oneof)->index()); |
428 | // oneofCase_ and oneof_ |
429 | printer->Print(variables: vars, |
430 | text: "private int $oneof_name$Case_ = 0;\n" |
431 | "private java.lang.Object $oneof_name$_;\n" ); |
432 | // OneofCase enum |
433 | printer->Print( |
434 | variables: vars, |
435 | text: "public enum $oneof_capitalized_name$Case\n" |
436 | // TODO(dweis): Remove EnumLite when we want to break compatibility with |
437 | // 3.x users |
438 | " implements com.google.protobuf.Internal.EnumLite,\n" |
439 | " com.google.protobuf.AbstractMessage.InternalOneOfEnum {\n" ); |
440 | printer->Indent(); |
441 | for (int j = 0; j < (oneof)->field_count(); j++) { |
442 | const FieldDescriptor* field = (oneof)->field(index: j); |
443 | printer->Print( |
444 | text: "$deprecation$$field_name$($field_number$),\n" , args: "deprecation" , |
445 | args: field->options().deprecated() ? "@java.lang.Deprecated " : "" , |
446 | args: "field_name" , args: ToUpper(s: field->name()), args: "field_number" , |
447 | args: StrCat(a: field->number())); |
448 | } |
449 | printer->Print(text: "$cap_oneof_name$_NOT_SET(0);\n" , args: "cap_oneof_name" , |
450 | args: ToUpper(s: vars["oneof_name" ])); |
451 | printer->Print(variables: vars, |
452 | text: "private final int value;\n" |
453 | "private $oneof_capitalized_name$Case(int value) {\n" |
454 | " this.value = value;\n" |
455 | "}\n" ); |
456 | printer->Print( |
457 | variables: vars, |
458 | text: "/**\n" |
459 | " * @param value The number of the enum to look for.\n" |
460 | " * @return The enum associated with the given number.\n" |
461 | " * @deprecated Use {@link #forNumber(int)} instead.\n" |
462 | " */\n" |
463 | "@java.lang.Deprecated\n" |
464 | "public static $oneof_capitalized_name$Case valueOf(int value) {\n" |
465 | " return forNumber(value);\n" |
466 | "}\n" |
467 | "\n" |
468 | "public static $oneof_capitalized_name$Case forNumber(int value) {\n" |
469 | " switch (value) {\n" ); |
470 | for (int j = 0; j < (oneof)->field_count(); j++) { |
471 | const FieldDescriptor* field = (oneof)->field(index: j); |
472 | printer->Print(text: " case $field_number$: return $field_name$;\n" , |
473 | args: "field_number" , args: StrCat(a: field->number()), |
474 | args: "field_name" , args: ToUpper(s: field->name())); |
475 | } |
476 | printer->Print( |
477 | text: " case 0: return $cap_oneof_name$_NOT_SET;\n" |
478 | " default: return null;\n" |
479 | " }\n" |
480 | "}\n" |
481 | "public int getNumber() {\n" |
482 | " return this.value;\n" |
483 | "}\n" , |
484 | args: "cap_oneof_name" , args: ToUpper(s: vars["oneof_name" ])); |
485 | printer->Outdent(); |
486 | printer->Print(text: "};\n\n" ); |
487 | // oneofCase() |
488 | printer->Print(variables: vars, |
489 | text: "public $oneof_capitalized_name$Case\n" |
490 | "get$oneof_capitalized_name$Case() {\n" |
491 | " return $oneof_capitalized_name$Case.forNumber(\n" |
492 | " $oneof_name$Case_);\n" |
493 | "}\n" |
494 | "\n" ); |
495 | } |
496 | |
497 | if (IsAnyMessage(descriptor: descriptor_)) { |
498 | GenerateAnyMethods(printer); |
499 | } |
500 | |
501 | // Fields |
502 | for (int i = 0; i < descriptor_->field_count(); i++) { |
503 | printer->Print(text: "public static final int $constant_name$ = $number$;\n" , |
504 | args: "constant_name" , args: FieldConstantName(field: descriptor_->field(index: i)), |
505 | args: "number" , args: StrCat(a: descriptor_->field(index: i)->number())); |
506 | printer->Annotate(varname: "constant_name" , descriptor: descriptor_->field(index: i)); |
507 | field_generators_.get(field: descriptor_->field(index: i)).GenerateMembers(printer); |
508 | printer->Print(text: "\n" ); |
509 | } |
510 | |
511 | if (context_->HasGeneratedMethods(descriptor: descriptor_)) { |
512 | GenerateIsInitialized(printer); |
513 | GenerateMessageSerializationMethods(printer); |
514 | GenerateEqualsAndHashCode(printer); |
515 | } |
516 | |
517 | |
518 | GenerateParseFromMethods(printer); |
519 | GenerateBuilder(printer); |
520 | |
521 | printer->Print( |
522 | text: "\n" |
523 | "// @@protoc_insertion_point(class_scope:$full_name$)\n" , |
524 | args: "full_name" , args: descriptor_->full_name()); |
525 | |
526 | // Carefully initialize the default instance in such a way that it doesn't |
527 | // conflict with other initialization. |
528 | printer->Print(text: "private static final $classname$ DEFAULT_INSTANCE;\n" , |
529 | args: "classname" , |
530 | args: name_resolver_->GetImmutableClassName(descriptor: descriptor_)); |
531 | printer->Print( |
532 | text: "static {\n" |
533 | " DEFAULT_INSTANCE = new $classname$();\n" |
534 | "}\n" |
535 | "\n" , |
536 | args: "classname" , args: name_resolver_->GetImmutableClassName(descriptor: descriptor_)); |
537 | |
538 | printer->Print( |
539 | text: "public static $classname$ getDefaultInstance() {\n" |
540 | " return DEFAULT_INSTANCE;\n" |
541 | "}\n" |
542 | "\n" , |
543 | args: "classname" , args: name_resolver_->GetImmutableClassName(descriptor: descriptor_)); |
544 | |
545 | // 'of' method for Wrappers |
546 | if (IsWrappersProtoFile(descriptor: descriptor_->file())) { |
547 | printer->Print( |
548 | text: "public static $classname$ of($field_type$ value) {\n" |
549 | " return newBuilder().setValue(value).build();\n" |
550 | "}\n" |
551 | "\n" , |
552 | args: "classname" , args: name_resolver_->GetImmutableClassName(descriptor: descriptor_), |
553 | args: "field_type" , args: PrimitiveTypeName(type: GetJavaType(field: descriptor_->field(index: 0)))); |
554 | } |
555 | |
556 | GenerateParser(printer); |
557 | |
558 | printer->Print( |
559 | text: "@java.lang.Override\n" |
560 | "public $classname$ getDefaultInstanceForType() {\n" |
561 | " return DEFAULT_INSTANCE;\n" |
562 | "}\n" |
563 | "\n" , |
564 | args: "classname" , args: name_resolver_->GetImmutableClassName(descriptor: descriptor_)); |
565 | |
566 | // Extensions must be declared after the DEFAULT_INSTANCE is initialized |
567 | // because the DEFAULT_INSTANCE is used by the extension to lazily retrieve |
568 | // the outer class's FileDescriptor. |
569 | for (int i = 0; i < descriptor_->extension_count(); i++) { |
570 | ImmutableExtensionGenerator(descriptor_->extension(index: i), context_) |
571 | .Generate(printer); |
572 | } |
573 | |
574 | printer->Outdent(); |
575 | printer->Print(text: "}\n\n" ); |
576 | } |
577 | |
578 | // =================================================================== |
579 | |
580 | void ImmutableMessageGenerator::GenerateMessageSerializationMethods( |
581 | io::Printer* printer) { |
582 | std::unique_ptr<const FieldDescriptor*[]> sorted_fields( |
583 | SortFieldsByNumber(descriptor: descriptor_)); |
584 | |
585 | std::vector<const Descriptor::ExtensionRange*> sorted_extensions; |
586 | sorted_extensions.reserve(n: descriptor_->extension_range_count()); |
587 | for (int i = 0; i < descriptor_->extension_range_count(); ++i) { |
588 | sorted_extensions.push_back(x: descriptor_->extension_range(index: i)); |
589 | } |
590 | std::sort(first: sorted_extensions.begin(), last: sorted_extensions.end(), |
591 | comp: ExtensionRangeOrdering()); |
592 | printer->Print( |
593 | text: "@java.lang.Override\n" |
594 | "public void writeTo(com.google.protobuf.CodedOutputStream output)\n" |
595 | " throws java.io.IOException {\n" ); |
596 | printer->Indent(); |
597 | |
598 | if (HasPackedFields(descriptor: descriptor_)) { |
599 | // writeTo(CodedOutputStream output) might be invoked without |
600 | // getSerializedSize() ever being called, but we need the memoized |
601 | // sizes in case this message has packed fields. Rather than emit checks |
602 | // for each packed field, just call getSerializedSize() up front. In most |
603 | // cases, getSerializedSize() will have already been called anyway by one |
604 | // of the wrapper writeTo() methods, making this call cheap. |
605 | printer->Print(text: "getSerializedSize();\n" ); |
606 | } |
607 | |
608 | if (descriptor_->extension_range_count() > 0) { |
609 | if (descriptor_->options().message_set_wire_format()) { |
610 | printer->Print( |
611 | text: "com.google.protobuf.GeneratedMessage$ver$\n" |
612 | " .ExtendableMessage<$classname$>.ExtensionWriter\n" |
613 | " extensionWriter = newMessageSetExtensionWriter();\n" , |
614 | args: "classname" , args: name_resolver_->GetImmutableClassName(descriptor: descriptor_), |
615 | args: "ver" , args: GeneratedCodeVersionSuffix()); |
616 | } else { |
617 | printer->Print( |
618 | text: "com.google.protobuf.GeneratedMessage$ver$\n" |
619 | " .ExtendableMessage<$classname$>.ExtensionWriter\n" |
620 | " extensionWriter = newExtensionWriter();\n" , |
621 | args: "classname" , args: name_resolver_->GetImmutableClassName(descriptor: descriptor_), |
622 | args: "ver" , args: GeneratedCodeVersionSuffix()); |
623 | } |
624 | } |
625 | |
626 | // Merge the fields and the extension ranges, both sorted by field number. |
627 | for (int i = 0, j = 0; |
628 | i < descriptor_->field_count() || j < sorted_extensions.size();) { |
629 | if (i == descriptor_->field_count()) { |
630 | GenerateSerializeOneExtensionRange(printer, range: sorted_extensions[j++]); |
631 | } else if (j == sorted_extensions.size()) { |
632 | GenerateSerializeOneField(printer, field: sorted_fields[i++]); |
633 | } else if (sorted_fields[i]->number() < sorted_extensions[j]->start) { |
634 | GenerateSerializeOneField(printer, field: sorted_fields[i++]); |
635 | } else { |
636 | GenerateSerializeOneExtensionRange(printer, range: sorted_extensions[j++]); |
637 | } |
638 | } |
639 | |
640 | if (descriptor_->options().message_set_wire_format()) { |
641 | printer->Print(text: "unknownFields.writeAsMessageSetTo(output);\n" ); |
642 | } else { |
643 | printer->Print(text: "unknownFields.writeTo(output);\n" ); |
644 | } |
645 | |
646 | printer->Outdent(); |
647 | printer->Print( |
648 | text: "}\n" |
649 | "\n" |
650 | "@java.lang.Override\n" |
651 | "public int getSerializedSize() {\n" |
652 | " int size = memoizedSize;\n" |
653 | " if (size != -1) return size;\n" |
654 | "\n" ); |
655 | printer->Indent(); |
656 | |
657 | printer->Print(text: "size = 0;\n" ); |
658 | |
659 | for (int i = 0; i < descriptor_->field_count(); i++) { |
660 | field_generators_.get(field: sorted_fields[i]).GenerateSerializedSizeCode(printer); |
661 | } |
662 | |
663 | if (descriptor_->extension_range_count() > 0) { |
664 | if (descriptor_->options().message_set_wire_format()) { |
665 | printer->Print(text: "size += extensionsSerializedSizeAsMessageSet();\n" ); |
666 | } else { |
667 | printer->Print(text: "size += extensionsSerializedSize();\n" ); |
668 | } |
669 | } |
670 | |
671 | if (descriptor_->options().message_set_wire_format()) { |
672 | printer->Print(text: "size += unknownFields.getSerializedSizeAsMessageSet();\n" ); |
673 | } else { |
674 | printer->Print(text: "size += unknownFields.getSerializedSize();\n" ); |
675 | } |
676 | |
677 | printer->Print( |
678 | text: "memoizedSize = size;\n" |
679 | "return size;\n" ); |
680 | |
681 | printer->Outdent(); |
682 | printer->Print( |
683 | text: "}\n" |
684 | "\n" ); |
685 | } |
686 | |
687 | void ImmutableMessageGenerator::GenerateParseFromMethods(io::Printer* printer) { |
688 | // Note: These are separate from GenerateMessageSerializationMethods() |
689 | // because they need to be generated even for messages that are optimized |
690 | // for code size. |
691 | printer->Print( |
692 | text: "public static $classname$ parseFrom(\n" |
693 | " java.nio.ByteBuffer data)\n" |
694 | " throws com.google.protobuf.InvalidProtocolBufferException {\n" |
695 | " return PARSER.parseFrom(data);\n" |
696 | "}\n" |
697 | "public static $classname$ parseFrom(\n" |
698 | " java.nio.ByteBuffer data,\n" |
699 | " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" |
700 | " throws com.google.protobuf.InvalidProtocolBufferException {\n" |
701 | " return PARSER.parseFrom(data, extensionRegistry);\n" |
702 | "}\n" |
703 | "public static $classname$ parseFrom(\n" |
704 | " com.google.protobuf.ByteString data)\n" |
705 | " throws com.google.protobuf.InvalidProtocolBufferException {\n" |
706 | " return PARSER.parseFrom(data);\n" |
707 | "}\n" |
708 | "public static $classname$ parseFrom(\n" |
709 | " com.google.protobuf.ByteString data,\n" |
710 | " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" |
711 | " throws com.google.protobuf.InvalidProtocolBufferException {\n" |
712 | " return PARSER.parseFrom(data, extensionRegistry);\n" |
713 | "}\n" |
714 | "public static $classname$ parseFrom(byte[] data)\n" |
715 | " throws com.google.protobuf.InvalidProtocolBufferException {\n" |
716 | " return PARSER.parseFrom(data);\n" |
717 | "}\n" |
718 | "public static $classname$ parseFrom(\n" |
719 | " byte[] data,\n" |
720 | " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" |
721 | " throws com.google.protobuf.InvalidProtocolBufferException {\n" |
722 | " return PARSER.parseFrom(data, extensionRegistry);\n" |
723 | "}\n" |
724 | "public static $classname$ parseFrom(java.io.InputStream input)\n" |
725 | " throws java.io.IOException {\n" |
726 | " return com.google.protobuf.GeneratedMessage$ver$\n" |
727 | " .parseWithIOException(PARSER, input);\n" |
728 | "}\n" |
729 | "public static $classname$ parseFrom(\n" |
730 | " java.io.InputStream input,\n" |
731 | " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" |
732 | " throws java.io.IOException {\n" |
733 | " return com.google.protobuf.GeneratedMessage$ver$\n" |
734 | " .parseWithIOException(PARSER, input, extensionRegistry);\n" |
735 | "}\n" |
736 | "public static $classname$ parseDelimitedFrom(java.io.InputStream " |
737 | "input)\n" |
738 | " throws java.io.IOException {\n" |
739 | " return com.google.protobuf.GeneratedMessage$ver$\n" |
740 | " .parseDelimitedWithIOException(PARSER, input);\n" |
741 | "}\n" |
742 | "public static $classname$ parseDelimitedFrom(\n" |
743 | " java.io.InputStream input,\n" |
744 | " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" |
745 | " throws java.io.IOException {\n" |
746 | " return com.google.protobuf.GeneratedMessage$ver$\n" |
747 | " .parseDelimitedWithIOException(PARSER, input, " |
748 | "extensionRegistry);\n" |
749 | "}\n" |
750 | "public static $classname$ parseFrom(\n" |
751 | " com.google.protobuf.CodedInputStream input)\n" |
752 | " throws java.io.IOException {\n" |
753 | " return com.google.protobuf.GeneratedMessage$ver$\n" |
754 | " .parseWithIOException(PARSER, input);\n" |
755 | "}\n" |
756 | "public static $classname$ parseFrom(\n" |
757 | " com.google.protobuf.CodedInputStream input,\n" |
758 | " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" |
759 | " throws java.io.IOException {\n" |
760 | " return com.google.protobuf.GeneratedMessage$ver$\n" |
761 | " .parseWithIOException(PARSER, input, extensionRegistry);\n" |
762 | "}\n" |
763 | "\n" , |
764 | args: "classname" , args: name_resolver_->GetImmutableClassName(descriptor: descriptor_), args: "ver" , |
765 | args: GeneratedCodeVersionSuffix()); |
766 | } |
767 | |
768 | void ImmutableMessageGenerator::GenerateSerializeOneField( |
769 | io::Printer* printer, const FieldDescriptor* field) { |
770 | field_generators_.get(field).GenerateSerializationCode(printer); |
771 | } |
772 | |
773 | void ImmutableMessageGenerator::GenerateSerializeOneExtensionRange( |
774 | io::Printer* printer, const Descriptor::ExtensionRange* range) { |
775 | printer->Print(text: "extensionWriter.writeUntil($end$, output);\n" , args: "end" , |
776 | args: StrCat(a: range->end)); |
777 | } |
778 | |
779 | // =================================================================== |
780 | |
781 | void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) { |
782 | // LITE_RUNTIME implements this at the GeneratedMessageLite level. |
783 | printer->Print( |
784 | text: "@java.lang.Override\n" |
785 | "public Builder newBuilderForType() { return newBuilder(); }\n" ); |
786 | |
787 | printer->Print( |
788 | text: "public static Builder newBuilder() {\n" |
789 | " return DEFAULT_INSTANCE.toBuilder();\n" |
790 | "}\n" |
791 | "public static Builder newBuilder($classname$ prototype) {\n" |
792 | " return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);\n" |
793 | "}\n" |
794 | "@java.lang.Override\n" |
795 | "public Builder toBuilder() {\n" |
796 | " return this == DEFAULT_INSTANCE\n" |
797 | " ? new Builder() : new Builder().mergeFrom(this);\n" |
798 | "}\n" |
799 | "\n" , |
800 | args: "classname" , args: name_resolver_->GetImmutableClassName(descriptor: descriptor_)); |
801 | |
802 | printer->Print( |
803 | text: "@java.lang.Override\n" |
804 | "protected Builder newBuilderForType(\n" |
805 | " com.google.protobuf.GeneratedMessage$ver$.BuilderParent parent) {\n" |
806 | " Builder builder = new Builder(parent);\n" |
807 | " return builder;\n" |
808 | "}\n" , |
809 | args: "ver" , args: GeneratedCodeVersionSuffix()); |
810 | |
811 | MessageBuilderGenerator builderGenerator(descriptor_, context_); |
812 | builderGenerator.Generate(printer); |
813 | } |
814 | |
815 | void ImmutableMessageGenerator::GenerateDescriptorMethods( |
816 | io::Printer* printer) { |
817 | if (!descriptor_->options().no_standard_descriptor_accessor()) { |
818 | printer->Print( |
819 | text: "public static final com.google.protobuf.Descriptors.Descriptor\n" |
820 | " getDescriptor() {\n" |
821 | " return $fileclass$.internal_$identifier$_descriptor;\n" |
822 | "}\n" |
823 | "\n" , |
824 | args: "fileclass" , args: name_resolver_->GetImmutableClassName(descriptor: descriptor_->file()), |
825 | args: "identifier" , args: UniqueFileScopeIdentifier(descriptor: descriptor_)); |
826 | } |
827 | std::vector<const FieldDescriptor*> map_fields; |
828 | for (int i = 0; i < descriptor_->field_count(); i++) { |
829 | const FieldDescriptor* field = descriptor_->field(index: i); |
830 | if (GetJavaType(field) == JAVATYPE_MESSAGE && |
831 | IsMapEntry(descriptor: field->message_type())) { |
832 | map_fields.push_back(x: field); |
833 | } |
834 | } |
835 | if (!map_fields.empty()) { |
836 | printer->Print( |
837 | text: "@SuppressWarnings({\"rawtypes\"})\n" |
838 | "@java.lang.Override\n" |
839 | "protected com.google.protobuf.MapField internalGetMapField(\n" |
840 | " int number) {\n" |
841 | " switch (number) {\n" ); |
842 | printer->Indent(); |
843 | printer->Indent(); |
844 | for (int i = 0; i < map_fields.size(); ++i) { |
845 | const FieldDescriptor* field = map_fields[i]; |
846 | const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); |
847 | printer->Print( |
848 | text: "case $number$:\n" |
849 | " return internalGet$capitalized_name$();\n" , |
850 | args: "number" , args: StrCat(a: field->number()), args: "capitalized_name" , |
851 | args: info->capitalized_name); |
852 | } |
853 | printer->Print( |
854 | text: "default:\n" |
855 | " throw new RuntimeException(\n" |
856 | " \"Invalid map field number: \" + number);\n" ); |
857 | printer->Outdent(); |
858 | printer->Outdent(); |
859 | printer->Print( |
860 | text: " }\n" |
861 | "}\n" ); |
862 | } |
863 | printer->Print( |
864 | text: "@java.lang.Override\n" |
865 | "protected com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n" |
866 | " internalGetFieldAccessorTable() {\n" |
867 | " return $fileclass$.internal_$identifier$_fieldAccessorTable\n" |
868 | " .ensureFieldAccessorsInitialized(\n" |
869 | " $classname$.class, $classname$.Builder.class);\n" |
870 | "}\n" |
871 | "\n" , |
872 | args: "classname" , args: name_resolver_->GetImmutableClassName(descriptor: descriptor_), |
873 | args: "fileclass" , args: name_resolver_->GetImmutableClassName(descriptor: descriptor_->file()), |
874 | args: "identifier" , args: UniqueFileScopeIdentifier(descriptor: descriptor_), args: "ver" , |
875 | args: GeneratedCodeVersionSuffix()); |
876 | } |
877 | |
878 | // =================================================================== |
879 | |
880 | void ImmutableMessageGenerator::GenerateIsInitialized(io::Printer* printer) { |
881 | // Memoizes whether the protocol buffer is fully initialized (has all |
882 | // required fields). -1 means not yet computed. 0 means false and 1 means |
883 | // true. |
884 | printer->Print(text: "private byte memoizedIsInitialized = -1;\n" ); |
885 | printer->Print( |
886 | text: "@java.lang.Override\n" |
887 | "public final boolean isInitialized() {\n" ); |
888 | printer->Indent(); |
889 | |
890 | // Don't directly compare to -1 to avoid an Android x86 JIT bug. |
891 | printer->Print( |
892 | text: "byte isInitialized = memoizedIsInitialized;\n" |
893 | "if (isInitialized == 1) return true;\n" |
894 | "if (isInitialized == 0) return false;\n" |
895 | "\n" ); |
896 | |
897 | // Check that all required fields in this message are set. |
898 | // TODO(kenton): We can optimize this when we switch to putting all the |
899 | // "has" fields into a single bitfield. |
900 | for (int i = 0; i < descriptor_->field_count(); i++) { |
901 | const FieldDescriptor* field = descriptor_->field(index: i); |
902 | const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); |
903 | |
904 | if (field->is_required()) { |
905 | printer->Print( |
906 | text: "if (!has$name$()) {\n" |
907 | " memoizedIsInitialized = 0;\n" |
908 | " return false;\n" |
909 | "}\n" , |
910 | args: "name" , args: info->capitalized_name); |
911 | } |
912 | } |
913 | |
914 | // Now check that all embedded messages are initialized. |
915 | for (int i = 0; i < descriptor_->field_count(); i++) { |
916 | const FieldDescriptor* field = descriptor_->field(index: i); |
917 | const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); |
918 | if (GetJavaType(field) == JAVATYPE_MESSAGE && |
919 | HasRequiredFields(descriptor: field->message_type())) { |
920 | switch (field->label()) { |
921 | case FieldDescriptor::LABEL_REQUIRED: |
922 | printer->Print( |
923 | text: "if (!get$name$().isInitialized()) {\n" |
924 | " memoizedIsInitialized = 0;\n" |
925 | " return false;\n" |
926 | "}\n" , |
927 | args: "type" , |
928 | args: name_resolver_->GetImmutableClassName(descriptor: field->message_type()), |
929 | args: "name" , args: info->capitalized_name); |
930 | break; |
931 | case FieldDescriptor::LABEL_OPTIONAL: |
932 | printer->Print( |
933 | text: "if (has$name$()) {\n" |
934 | " if (!get$name$().isInitialized()) {\n" |
935 | " memoizedIsInitialized = 0;\n" |
936 | " return false;\n" |
937 | " }\n" |
938 | "}\n" , |
939 | args: "name" , args: info->capitalized_name); |
940 | break; |
941 | case FieldDescriptor::LABEL_REPEATED: |
942 | if (IsMapEntry(descriptor: field->message_type())) { |
943 | printer->Print( |
944 | text: "for ($type$ item : get$name$Map().values()) {\n" |
945 | " if (!item.isInitialized()) {\n" |
946 | " memoizedIsInitialized = 0;\n" |
947 | " return false;\n" |
948 | " }\n" |
949 | "}\n" , |
950 | args: "type" , |
951 | args: MapValueImmutableClassdName(descriptor: field->message_type(), |
952 | name_resolver: name_resolver_), |
953 | args: "name" , args: info->capitalized_name); |
954 | } else { |
955 | printer->Print( |
956 | text: "for (int i = 0; i < get$name$Count(); i++) {\n" |
957 | " if (!get$name$(i).isInitialized()) {\n" |
958 | " memoizedIsInitialized = 0;\n" |
959 | " return false;\n" |
960 | " }\n" |
961 | "}\n" , |
962 | args: "type" , |
963 | args: name_resolver_->GetImmutableClassName(descriptor: field->message_type()), |
964 | args: "name" , args: info->capitalized_name); |
965 | } |
966 | break; |
967 | } |
968 | } |
969 | } |
970 | |
971 | if (descriptor_->extension_range_count() > 0) { |
972 | printer->Print( |
973 | text: "if (!extensionsAreInitialized()) {\n" |
974 | " memoizedIsInitialized = 0;\n" |
975 | " return false;\n" |
976 | "}\n" ); |
977 | } |
978 | |
979 | printer->Outdent(); |
980 | |
981 | printer->Print(text: " memoizedIsInitialized = 1;\n" ); |
982 | |
983 | printer->Print( |
984 | text: " return true;\n" |
985 | "}\n" |
986 | "\n" ); |
987 | } |
988 | |
989 | // =================================================================== |
990 | |
991 | namespace { |
992 | bool CheckHasBitsForEqualsAndHashCode(const FieldDescriptor* field) { |
993 | if (field->is_repeated()) { |
994 | return false; |
995 | } |
996 | if (HasHasbit(descriptor: field)) { |
997 | return true; |
998 | } |
999 | return GetJavaType(field) == JAVATYPE_MESSAGE && !IsRealOneof(descriptor: field); |
1000 | } |
1001 | } // namespace |
1002 | |
1003 | void ImmutableMessageGenerator::GenerateEqualsAndHashCode( |
1004 | io::Printer* printer) { |
1005 | printer->Print( |
1006 | text: "@java.lang.Override\n" |
1007 | "public boolean equals(" ); |
1008 | printer->Print(text: "final java.lang.Object obj) {\n" ); |
1009 | printer->Indent(); |
1010 | printer->Print( |
1011 | text: "if (obj == this) {\n" |
1012 | " return true;\n" |
1013 | "}\n" |
1014 | "if (!(obj instanceof $classname$)) {\n" |
1015 | " return super.equals(obj);\n" |
1016 | "}\n" |
1017 | "$classname$ other = ($classname$) obj;\n" |
1018 | "\n" , |
1019 | args: "classname" , args: name_resolver_->GetImmutableClassName(descriptor: descriptor_)); |
1020 | |
1021 | for (int i = 0; i < descriptor_->field_count(); i++) { |
1022 | const FieldDescriptor* field = descriptor_->field(index: i); |
1023 | if (!IsRealOneof(descriptor: field)) { |
1024 | const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); |
1025 | bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field); |
1026 | if (check_has_bits) { |
1027 | printer->Print( |
1028 | text: "if (has$name$() != other.has$name$()) return false;\n" |
1029 | "if (has$name$()) {\n" , |
1030 | args: "name" , args: info->capitalized_name); |
1031 | printer->Indent(); |
1032 | } |
1033 | field_generators_.get(field).GenerateEqualsCode(printer); |
1034 | if (check_has_bits) { |
1035 | printer->Outdent(); |
1036 | printer->Print(text: "}\n" ); |
1037 | } |
1038 | } |
1039 | } |
1040 | |
1041 | // Compare oneofs. |
1042 | for (auto oneof : oneofs_) { |
1043 | printer->Print( |
1044 | text: "if (!get$oneof_capitalized_name$Case().equals(" |
1045 | "other.get$oneof_capitalized_name$Case())) return false;\n" , |
1046 | args: "oneof_capitalized_name" , |
1047 | args: context_->GetOneofGeneratorInfo(oneof)->capitalized_name); |
1048 | printer->Print(text: "switch ($oneof_name$Case_) {\n" , args: "oneof_name" , |
1049 | args: context_->GetOneofGeneratorInfo(oneof)->name); |
1050 | printer->Indent(); |
1051 | for (int j = 0; j < (oneof)->field_count(); j++) { |
1052 | const FieldDescriptor* field = (oneof)->field(index: j); |
1053 | printer->Print(text: "case $field_number$:\n" , args: "field_number" , |
1054 | args: StrCat(a: field->number())); |
1055 | printer->Indent(); |
1056 | field_generators_.get(field).GenerateEqualsCode(printer); |
1057 | printer->Print(text: "break;\n" ); |
1058 | printer->Outdent(); |
1059 | } |
1060 | printer->Print( |
1061 | text: "case 0:\n" |
1062 | "default:\n" ); |
1063 | printer->Outdent(); |
1064 | printer->Print(text: "}\n" ); |
1065 | } |
1066 | |
1067 | // Always consider unknown fields for equality. This will sometimes return |
1068 | // false for non-canonical ordering when running in LITE_RUNTIME but it's |
1069 | // the best we can do. |
1070 | printer->Print( |
1071 | text: "if (!unknownFields.equals(other.unknownFields)) return false;\n" ); |
1072 | if (descriptor_->extension_range_count() > 0) { |
1073 | printer->Print( |
1074 | text: "if (!getExtensionFields().equals(other.getExtensionFields()))\n" |
1075 | " return false;\n" ); |
1076 | } |
1077 | printer->Print(text: "return true;\n" ); |
1078 | printer->Outdent(); |
1079 | printer->Print( |
1080 | text: "}\n" |
1081 | "\n" ); |
1082 | |
1083 | printer->Print( |
1084 | text: "@java.lang.Override\n" |
1085 | "public int hashCode() {\n" ); |
1086 | printer->Indent(); |
1087 | printer->Print(text: "if (memoizedHashCode != 0) {\n" ); |
1088 | printer->Indent(); |
1089 | printer->Print(text: "return memoizedHashCode;\n" ); |
1090 | printer->Outdent(); |
1091 | printer->Print( |
1092 | text: "}\n" |
1093 | "int hash = 41;\n" ); |
1094 | |
1095 | // If we output a getDescriptor() method, use that as it is more efficient. |
1096 | if (descriptor_->options().no_standard_descriptor_accessor()) { |
1097 | printer->Print(text: "hash = (19 * hash) + getDescriptorForType().hashCode();\n" ); |
1098 | } else { |
1099 | printer->Print(text: "hash = (19 * hash) + getDescriptor().hashCode();\n" ); |
1100 | } |
1101 | |
1102 | // hashCode non-oneofs. |
1103 | for (int i = 0; i < descriptor_->field_count(); i++) { |
1104 | const FieldDescriptor* field = descriptor_->field(index: i); |
1105 | if (!IsRealOneof(descriptor: field)) { |
1106 | const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); |
1107 | bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field); |
1108 | if (check_has_bits) { |
1109 | printer->Print(text: "if (has$name$()) {\n" , args: "name" , args: info->capitalized_name); |
1110 | printer->Indent(); |
1111 | } |
1112 | field_generators_.get(field).GenerateHashCode(printer); |
1113 | if (check_has_bits) { |
1114 | printer->Outdent(); |
1115 | printer->Print(text: "}\n" ); |
1116 | } |
1117 | } |
1118 | } |
1119 | |
1120 | // hashCode oneofs. |
1121 | for (auto oneof : oneofs_) { |
1122 | printer->Print(text: "switch ($oneof_name$Case_) {\n" , args: "oneof_name" , |
1123 | args: context_->GetOneofGeneratorInfo(oneof)->name); |
1124 | printer->Indent(); |
1125 | for (int j = 0; j < (oneof)->field_count(); j++) { |
1126 | const FieldDescriptor* field = (oneof)->field(index: j); |
1127 | printer->Print(text: "case $field_number$:\n" , args: "field_number" , |
1128 | args: StrCat(a: field->number())); |
1129 | printer->Indent(); |
1130 | field_generators_.get(field).GenerateHashCode(printer); |
1131 | printer->Print(text: "break;\n" ); |
1132 | printer->Outdent(); |
1133 | } |
1134 | printer->Print( |
1135 | text: "case 0:\n" |
1136 | "default:\n" ); |
1137 | printer->Outdent(); |
1138 | printer->Print(text: "}\n" ); |
1139 | } |
1140 | |
1141 | if (descriptor_->extension_range_count() > 0) { |
1142 | printer->Print(text: "hash = hashFields(hash, getExtensionFields());\n" ); |
1143 | } |
1144 | |
1145 | printer->Print(text: "hash = (29 * hash) + unknownFields.hashCode();\n" ); |
1146 | printer->Print( |
1147 | text: "memoizedHashCode = hash;\n" |
1148 | "return hash;\n" ); |
1149 | printer->Outdent(); |
1150 | printer->Print( |
1151 | text: "}\n" |
1152 | "\n" ); |
1153 | } |
1154 | |
1155 | // =================================================================== |
1156 | |
1157 | void ImmutableMessageGenerator::GenerateExtensionRegistrationCode( |
1158 | io::Printer* printer) { |
1159 | for (int i = 0; i < descriptor_->extension_count(); i++) { |
1160 | ImmutableExtensionGenerator(descriptor_->extension(index: i), context_) |
1161 | .GenerateRegistrationCode(printer); |
1162 | } |
1163 | |
1164 | for (int i = 0; i < descriptor_->nested_type_count(); i++) { |
1165 | ImmutableMessageGenerator(descriptor_->nested_type(index: i), context_) |
1166 | .GenerateExtensionRegistrationCode(printer); |
1167 | } |
1168 | } |
1169 | |
1170 | // =================================================================== |
1171 | void ImmutableMessageGenerator::GenerateParsingConstructor( |
1172 | io::Printer* printer) { |
1173 | std::unique_ptr<const FieldDescriptor*[]> sorted_fields( |
1174 | SortFieldsByNumber(descriptor: descriptor_)); |
1175 | |
1176 | printer->Print( |
1177 | text: "private $classname$(\n" |
1178 | " com.google.protobuf.CodedInputStream input,\n" |
1179 | " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" |
1180 | " throws com.google.protobuf.InvalidProtocolBufferException {\n" , |
1181 | args: "classname" , args: descriptor_->name()); |
1182 | printer->Indent(); |
1183 | |
1184 | // Initialize all fields to default. |
1185 | printer->Print( |
1186 | text: "this();\n" |
1187 | "if (extensionRegistry == null) {\n" |
1188 | " throw new java.lang.NullPointerException();\n" |
1189 | "}\n" ); |
1190 | |
1191 | // Use builder bits to track mutable repeated fields. |
1192 | int totalBuilderBits = 0; |
1193 | for (int i = 0; i < descriptor_->field_count(); i++) { |
1194 | const ImmutableFieldGenerator& field = |
1195 | field_generators_.get(field: descriptor_->field(index: i)); |
1196 | totalBuilderBits += field.GetNumBitsForBuilder(); |
1197 | } |
1198 | int totalBuilderInts = (totalBuilderBits + 31) / 32; |
1199 | for (int i = 0; i < totalBuilderInts; i++) { |
1200 | printer->Print(text: "int mutable_$bit_field_name$ = 0;\n" , args: "bit_field_name" , |
1201 | args: GetBitFieldName(index: i)); |
1202 | } |
1203 | |
1204 | printer->Print( |
1205 | text: "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n" |
1206 | " com.google.protobuf.UnknownFieldSet.newBuilder();\n" ); |
1207 | |
1208 | printer->Print(text: "try {\n" ); |
1209 | printer->Indent(); |
1210 | |
1211 | printer->Print( |
1212 | text: "boolean done = false;\n" |
1213 | "while (!done) {\n" ); |
1214 | printer->Indent(); |
1215 | |
1216 | printer->Print( |
1217 | text: "int tag = input.readTag();\n" |
1218 | "switch (tag) {\n" ); |
1219 | printer->Indent(); |
1220 | |
1221 | printer->Print( |
1222 | text: "case 0:\n" // zero signals EOF / limit reached |
1223 | " done = true;\n" |
1224 | " break;\n" ); |
1225 | |
1226 | for (int i = 0; i < descriptor_->field_count(); i++) { |
1227 | const FieldDescriptor* field = sorted_fields[i]; |
1228 | uint32_t tag = WireFormatLite::MakeTag( |
1229 | field_number: field->number(), type: WireFormat::WireTypeForFieldType(type: field->type())); |
1230 | |
1231 | printer->Print(text: "case $tag$: {\n" , args: "tag" , |
1232 | args: StrCat(a: static_cast<int32_t>(tag))); |
1233 | printer->Indent(); |
1234 | |
1235 | field_generators_.get(field).GenerateParsingCode(printer); |
1236 | |
1237 | printer->Outdent(); |
1238 | printer->Print( |
1239 | text: " break;\n" |
1240 | "}\n" ); |
1241 | |
1242 | if (field->is_packable()) { |
1243 | // To make packed = true wire compatible, we generate parsing code from a |
1244 | // packed version of this field regardless of field->options().packed(). |
1245 | uint32_t packed_tag = WireFormatLite::MakeTag( |
1246 | field_number: field->number(), type: WireFormatLite::WIRETYPE_LENGTH_DELIMITED); |
1247 | printer->Print(text: "case $tag$: {\n" , args: "tag" , |
1248 | args: StrCat(a: static_cast<int32_t>(packed_tag))); |
1249 | printer->Indent(); |
1250 | |
1251 | field_generators_.get(field).GenerateParsingCodeFromPacked(printer); |
1252 | |
1253 | printer->Outdent(); |
1254 | printer->Print( |
1255 | text: " break;\n" |
1256 | "}\n" ); |
1257 | } |
1258 | } |
1259 | |
1260 | printer->Print( |
1261 | text: "default: {\n" |
1262 | " if (!parseUnknownField(\n" |
1263 | " input, unknownFields, extensionRegistry, tag)) {\n" |
1264 | " done = true;\n" // it's an endgroup tag |
1265 | " }\n" |
1266 | " break;\n" |
1267 | "}\n" ); |
1268 | |
1269 | printer->Outdent(); |
1270 | printer->Outdent(); |
1271 | printer->Print( |
1272 | text: " }\n" // switch (tag) |
1273 | "}\n" ); // while (!done) |
1274 | |
1275 | printer->Outdent(); |
1276 | printer->Print( |
1277 | text: "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n" |
1278 | " throw e.setUnfinishedMessage(this);\n" |
1279 | "} catch (com.google.protobuf.UninitializedMessageException e) {\n" |
1280 | " throw " |
1281 | "e.asInvalidProtocolBufferException().setUnfinishedMessage(this);\n" |
1282 | "} catch (java.io.IOException e) {\n" |
1283 | " throw new com.google.protobuf.InvalidProtocolBufferException(\n" |
1284 | " e).setUnfinishedMessage(this);\n" |
1285 | "} finally {\n" ); |
1286 | printer->Indent(); |
1287 | |
1288 | // Make repeated field list immutable. |
1289 | for (int i = 0; i < descriptor_->field_count(); i++) { |
1290 | const FieldDescriptor* field = sorted_fields[i]; |
1291 | field_generators_.get(field).GenerateParsingDoneCode(printer); |
1292 | } |
1293 | |
1294 | // Make unknown fields immutable. |
1295 | printer->Print(text: "this.unknownFields = unknownFields.build();\n" ); |
1296 | |
1297 | // Make extensions immutable. |
1298 | printer->Print(text: "makeExtensionsImmutable();\n" ); |
1299 | |
1300 | printer->Outdent(); |
1301 | printer->Outdent(); |
1302 | printer->Print( |
1303 | text: " }\n" // finally |
1304 | "}\n" ); |
1305 | } |
1306 | |
1307 | // =================================================================== |
1308 | void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) { |
1309 | printer->Print( |
1310 | text: "$visibility$ static final com.google.protobuf.Parser<$classname$>\n" |
1311 | " PARSER = new com.google.protobuf.AbstractParser<$classname$>() {\n" , |
1312 | args: "visibility" , |
1313 | args: ExposePublicParser(descriptor: descriptor_->file()) ? "@java.lang.Deprecated public" |
1314 | : "private" , |
1315 | args: "classname" , args: descriptor_->name()); |
1316 | printer->Indent(); |
1317 | printer->Print( |
1318 | text: "@java.lang.Override\n" |
1319 | "public $classname$ parsePartialFrom(\n" |
1320 | " com.google.protobuf.CodedInputStream input,\n" |
1321 | " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" |
1322 | " throws com.google.protobuf.InvalidProtocolBufferException {\n" , |
1323 | args: "classname" , args: descriptor_->name()); |
1324 | if (context_->HasGeneratedMethods(descriptor: descriptor_)) { |
1325 | printer->Print(text: " return new $classname$(input, extensionRegistry);\n" , |
1326 | args: "classname" , args: descriptor_->name()); |
1327 | } else { |
1328 | // When parsing constructor isn't generated, use builder to parse |
1329 | // messages. Note, will fallback to use reflection based mergeFieldFrom() |
1330 | // in AbstractMessage.Builder. |
1331 | printer->Indent(); |
1332 | printer->Print( |
1333 | text: "Builder builder = newBuilder();\n" |
1334 | "try {\n" |
1335 | " builder.mergeFrom(input, extensionRegistry);\n" |
1336 | "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n" |
1337 | " throw e.setUnfinishedMessage(builder.buildPartial());\n" |
1338 | "} catch (java.io.IOException e) {\n" |
1339 | " throw new com.google.protobuf.InvalidProtocolBufferException(\n" |
1340 | " e.getMessage()).setUnfinishedMessage(\n" |
1341 | " builder.buildPartial());\n" |
1342 | "}\n" |
1343 | "return builder.buildPartial();\n" ); |
1344 | printer->Outdent(); |
1345 | } |
1346 | printer->Print(text: "}\n" ); |
1347 | printer->Outdent(); |
1348 | printer->Print( |
1349 | text: "};\n" |
1350 | "\n" ); |
1351 | |
1352 | printer->Print( |
1353 | text: "public static com.google.protobuf.Parser<$classname$> parser() {\n" |
1354 | " return PARSER;\n" |
1355 | "}\n" |
1356 | "\n" |
1357 | "@java.lang.Override\n" |
1358 | "public com.google.protobuf.Parser<$classname$> getParserForType() {\n" |
1359 | " return PARSER;\n" |
1360 | "}\n" |
1361 | "\n" , |
1362 | args: "classname" , args: descriptor_->name()); |
1363 | } |
1364 | |
1365 | // =================================================================== |
1366 | void ImmutableMessageGenerator::GenerateInitializers(io::Printer* printer) { |
1367 | for (int i = 0; i < descriptor_->field_count(); i++) { |
1368 | if (!IsRealOneof(descriptor: descriptor_->field(index: i))) { |
1369 | field_generators_.get(field: descriptor_->field(index: i)) |
1370 | .GenerateInitializationCode(printer); |
1371 | } |
1372 | } |
1373 | } |
1374 | |
1375 | // =================================================================== |
1376 | void ImmutableMessageGenerator::GenerateMutableCopy(io::Printer* printer) { |
1377 | printer->Print( |
1378 | text: "protected com.google.protobuf.MutableMessage\n" |
1379 | " internalMutableDefault() {\n" |
1380 | " return MutableDefaultLoader.get();\n" |
1381 | "}\n" |
1382 | "\n" |
1383 | "private static final class MutableDefaultLoader {\n" |
1384 | " private static final java.lang.Object defaultOrRuntimeException;\n" |
1385 | " static {\n" |
1386 | " java.lang.Object local;\n" |
1387 | " try {\n" |
1388 | " local = internalMutableDefault(\"$mutable_name$\");\n" |
1389 | " } catch (java.lang.RuntimeException e) {\n" |
1390 | " local = e;\n" |
1391 | " }\n" |
1392 | " defaultOrRuntimeException = local;\n" |
1393 | " }\n" |
1394 | "\n" |
1395 | " private MutableDefaultLoader() {}\n" |
1396 | "\n" |
1397 | " public static com.google.protobuf.MutableMessage get() {\n" |
1398 | " if (defaultOrRuntimeException\n" |
1399 | " instanceof java.lang.RuntimeException) {\n" |
1400 | " throw (java.lang.RuntimeException) defaultOrRuntimeException;\n" |
1401 | " }\n" |
1402 | " return\n" |
1403 | " (com.google.protobuf.MutableMessage) " |
1404 | "defaultOrRuntimeException;\n" |
1405 | " }\n" |
1406 | "}\n" , |
1407 | args: "mutable_name" , args: name_resolver_->GetJavaMutableClassName(descriptor: descriptor_)); |
1408 | } |
1409 | |
1410 | void ImmutableMessageGenerator::GenerateKotlinDsl(io::Printer* printer) const { |
1411 | printer->Print( |
1412 | text: "@kotlin.OptIn" |
1413 | "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" |
1414 | "@com.google.protobuf.kotlin.ProtoDslMarker\n" ); |
1415 | printer->Print( |
1416 | text: "class Dsl private constructor(\n" |
1417 | " private val _builder: $message$.Builder\n" |
1418 | ") {\n" |
1419 | " companion object {\n" |
1420 | " @kotlin.jvm.JvmSynthetic\n" |
1421 | " @kotlin.PublishedApi\n" |
1422 | " internal fun _create(builder: $message$.Builder): Dsl = " |
1423 | "Dsl(builder)\n" |
1424 | " }\n" |
1425 | "\n" |
1426 | " @kotlin.jvm.JvmSynthetic\n" |
1427 | " @kotlin.PublishedApi\n" |
1428 | " internal fun _build(): $message$ = _builder.build()\n" , |
1429 | args: "message" , args: name_resolver_->GetClassName(descriptor: descriptor_, immutable: true)); |
1430 | |
1431 | printer->Indent(); |
1432 | |
1433 | for (int i = 0; i < descriptor_->field_count(); i++) { |
1434 | printer->Print(text: "\n" ); |
1435 | field_generators_.get(field: descriptor_->field(index: i)) |
1436 | .GenerateKotlinDslMembers(printer); |
1437 | } |
1438 | |
1439 | for (auto oneof : oneofs_) { |
1440 | printer->Print( |
1441 | text: "val $oneof_name$Case: $message$.$oneof_capitalized_name$Case\n" |
1442 | " @JvmName(\"get$oneof_capitalized_name$Case\")\n" |
1443 | " get() = _builder.get$oneof_capitalized_name$Case()\n\n" |
1444 | "fun clear$oneof_capitalized_name$() {\n" |
1445 | " _builder.clear$oneof_capitalized_name$()\n" |
1446 | "}\n" , |
1447 | args: "oneof_name" , args: context_->GetOneofGeneratorInfo(oneof)->name, |
1448 | args: "oneof_capitalized_name" , |
1449 | args: context_->GetOneofGeneratorInfo(oneof)->capitalized_name, args: "message" , |
1450 | args: name_resolver_->GetClassName(descriptor: descriptor_, immutable: true)); |
1451 | } |
1452 | |
1453 | if (descriptor_->extension_range_count() > 0) { |
1454 | GenerateKotlinExtensions(printer); |
1455 | } |
1456 | |
1457 | printer->Outdent(); |
1458 | printer->Print(text: "}\n" ); |
1459 | } |
1460 | |
1461 | void ImmutableMessageGenerator::GenerateKotlinMembers( |
1462 | io::Printer* printer) const { |
1463 | printer->Print( |
1464 | text: "@kotlin.jvm.JvmName(\"-initialize$camelcase_name$\")\n" |
1465 | "inline fun $camelcase_name$(block: $message_kt$.Dsl.() -> " |
1466 | "kotlin.Unit): " |
1467 | "$message$ " |
1468 | "=\n" |
1469 | " $message_kt$.Dsl._create($message$.newBuilder()).apply { block() " |
1470 | "}._build()\n" , |
1471 | args: "camelcase_name" , args: name_resolver_->GetKotlinFactoryName(descriptor: descriptor_), |
1472 | args: "message_kt" , args: name_resolver_->GetKotlinExtensionsClassName(descriptor: descriptor_), |
1473 | args: "message" , args: name_resolver_->GetClassName(descriptor: descriptor_, immutable: true)); |
1474 | |
1475 | printer->Print(text: "object $name$Kt {\n" , args: "name" , args: descriptor_->name()); |
1476 | printer->Indent(); |
1477 | GenerateKotlinDsl(printer); |
1478 | for (int i = 0; i < descriptor_->nested_type_count(); i++) { |
1479 | if (IsMapEntry(descriptor: descriptor_->nested_type(index: i))) continue; |
1480 | ImmutableMessageGenerator(descriptor_->nested_type(index: i), context_) |
1481 | .GenerateKotlinMembers(printer); |
1482 | } |
1483 | printer->Outdent(); |
1484 | printer->Print(text: "}\n" ); |
1485 | } |
1486 | |
1487 | void ImmutableMessageGenerator::GenerateTopLevelKotlinMembers( |
1488 | io::Printer* printer) const { |
1489 | printer->Print( |
1490 | text: "@kotlin.jvm.JvmSynthetic\n" |
1491 | "inline fun $message$.copy(block: $message_kt$.Dsl.() -> " |
1492 | "kotlin.Unit): " |
1493 | "$message$ =\n" |
1494 | " $message_kt$.Dsl._create(this.toBuilder()).apply { block() " |
1495 | "}._build()\n\n" , |
1496 | args: "message" , args: name_resolver_->GetClassName(descriptor: descriptor_, immutable: true), args: "message_kt" , |
1497 | args: name_resolver_->GetKotlinExtensionsClassName(descriptor: descriptor_)); |
1498 | |
1499 | for (int i = 0; i < descriptor_->nested_type_count(); i++) { |
1500 | if (IsMapEntry(descriptor: descriptor_->nested_type(index: i))) continue; |
1501 | ImmutableMessageGenerator(descriptor_->nested_type(index: i), context_) |
1502 | .GenerateTopLevelKotlinMembers(printer); |
1503 | } |
1504 | |
1505 | GenerateKotlinOrNull(printer); |
1506 | } |
1507 | |
1508 | void ImmutableMessageGenerator::GenerateKotlinOrNull(io::Printer* printer) const { |
1509 | for (int i = 0; i < descriptor_->field_count(); i++) { |
1510 | const FieldDescriptor* field = descriptor_->field(index: i); |
1511 | if (field->has_presence() && GetJavaType(field) == JAVATYPE_MESSAGE) { |
1512 | printer->Print( |
1513 | text: "val $full_classname$OrBuilder.$camelcase_name$OrNull: $full_name$?\n" |
1514 | " get() = if (has$name$()) get$name$() else null\n\n" , |
1515 | args: "full_classname" , args: name_resolver_->GetClassName(descriptor: descriptor_, immutable: true), |
1516 | args: "camelcase_name" , args: context_->GetFieldGeneratorInfo(field)->name, |
1517 | args: "full_name" , |
1518 | args: name_resolver_->GetImmutableClassName(descriptor: field->message_type()), args: "name" , |
1519 | args: context_->GetFieldGeneratorInfo(field)->capitalized_name); |
1520 | } |
1521 | } |
1522 | } |
1523 | |
1524 | void ImmutableMessageGenerator::GenerateKotlinExtensions( |
1525 | io::Printer* printer) const { |
1526 | std::string message_name = name_resolver_->GetClassName(descriptor: descriptor_, immutable: true); |
1527 | |
1528 | printer->Print( |
1529 | text: "@Suppress(\"UNCHECKED_CAST\")\n" |
1530 | "@kotlin.jvm.JvmSynthetic\n" |
1531 | "operator fun <T : kotlin.Any> get(extension: " |
1532 | "com.google.protobuf.ExtensionLite<$message$, T>): T {\n" |
1533 | " return if (extension.isRepeated) {\n" |
1534 | " get(extension as com.google.protobuf.ExtensionLite<$message$, " |
1535 | "List<*>>) as T\n" |
1536 | " } else {\n" |
1537 | " _builder.getExtension(extension)\n" |
1538 | " }\n" |
1539 | "}\n\n" , |
1540 | args: "message" , args: message_name); |
1541 | |
1542 | printer->Print( |
1543 | text: "@kotlin.jvm.JvmSynthetic\n" |
1544 | "@kotlin.OptIn" |
1545 | "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" |
1546 | "@kotlin.jvm.JvmName(\"-getRepeatedExtension\")\n" |
1547 | "operator fun <E : kotlin.Any> get(\n" |
1548 | " extension: com.google.protobuf.ExtensionLite<$message$, List<E>>\n" |
1549 | "): com.google.protobuf.kotlin.ExtensionList<E, $message$> {\n" |
1550 | " return com.google.protobuf.kotlin.ExtensionList(extension, " |
1551 | "_builder.getExtension(extension))\n" |
1552 | "}\n\n" , |
1553 | args: "message" , args: message_name); |
1554 | |
1555 | printer->Print( |
1556 | text: "@kotlin.jvm.JvmSynthetic\n" |
1557 | "operator fun contains(extension: " |
1558 | "com.google.protobuf.ExtensionLite<$message$, *>): " |
1559 | "Boolean {\n" |
1560 | " return _builder.hasExtension(extension)\n" |
1561 | "}\n\n" , |
1562 | args: "message" , args: message_name); |
1563 | |
1564 | printer->Print( |
1565 | text: "@kotlin.jvm.JvmSynthetic\n" |
1566 | "fun clear(extension: " |
1567 | "com.google.protobuf.ExtensionLite<$message$, *>) " |
1568 | "{\n" |
1569 | " _builder.clearExtension(extension)\n" |
1570 | "}\n\n" , |
1571 | args: "message" , args: message_name); |
1572 | |
1573 | printer->Print( |
1574 | text: "@kotlin.jvm.JvmSynthetic\n" |
1575 | "@kotlin.PublishedApi\n" |
1576 | "internal fun <T : kotlin.Any> setExtension(extension: " |
1577 | "com.google.protobuf.ExtensionLite<$message$, T>, " |
1578 | "value: T) {\n" |
1579 | " _builder.setExtension(extension, value)\n" |
1580 | "}\n\n" , |
1581 | args: "message" , args: message_name); |
1582 | |
1583 | printer->Print( |
1584 | text: "@kotlin.jvm.JvmSynthetic\n" |
1585 | "@Suppress(\"NOTHING_TO_INLINE\")\n" |
1586 | "inline operator fun <T : Comparable<T>> set(\n" |
1587 | " extension: com.google.protobuf.ExtensionLite<$message$, T>,\n" |
1588 | " value: T\n" |
1589 | ") {\n" |
1590 | " setExtension(extension, value)\n" |
1591 | "}\n\n" , |
1592 | args: "message" , args: message_name); |
1593 | |
1594 | printer->Print( |
1595 | text: "@kotlin.jvm.JvmSynthetic\n" |
1596 | "@Suppress(\"NOTHING_TO_INLINE\")\n" |
1597 | "inline operator fun set(\n" |
1598 | " extension: com.google.protobuf.ExtensionLite<$message$, " |
1599 | "com.google.protobuf.ByteString>,\n" |
1600 | " value: com.google.protobuf.ByteString\n" |
1601 | ") {\n" |
1602 | " setExtension(extension, value)\n" |
1603 | "}\n\n" , |
1604 | args: "message" , args: message_name); |
1605 | |
1606 | printer->Print( |
1607 | text: "@kotlin.jvm.JvmSynthetic\n" |
1608 | "@Suppress(\"NOTHING_TO_INLINE\")\n" |
1609 | "inline operator fun <T : com.google.protobuf.MessageLite> set(\n" |
1610 | " extension: com.google.protobuf.ExtensionLite<$message$, T>,\n" |
1611 | " value: T\n" |
1612 | ") {\n" |
1613 | " setExtension(extension, value)\n" |
1614 | "}\n\n" , |
1615 | args: "message" , args: message_name); |
1616 | |
1617 | printer->Print( |
1618 | text: "@kotlin.jvm.JvmSynthetic\n" |
1619 | "fun <E : kotlin.Any> com.google.protobuf.kotlin.ExtensionList<E, " |
1620 | "$message$>.add(value: E) {\n" |
1621 | " _builder.addExtension(this.extension, value)\n" |
1622 | "}\n\n" , |
1623 | args: "message" , args: message_name); |
1624 | |
1625 | printer->Print( |
1626 | text: "@kotlin.jvm.JvmSynthetic\n" |
1627 | "@Suppress(\"NOTHING_TO_INLINE\")\n" |
1628 | "inline operator fun <E : kotlin.Any> " |
1629 | "com.google.protobuf.kotlin.ExtensionList<E, " |
1630 | "$message$>.plusAssign" |
1631 | "(value: E) {\n" |
1632 | " add(value)\n" |
1633 | "}\n\n" , |
1634 | args: "message" , args: message_name); |
1635 | |
1636 | printer->Print( |
1637 | text: "@kotlin.jvm.JvmSynthetic\n" |
1638 | "fun <E : kotlin.Any> com.google.protobuf.kotlin.ExtensionList<E, " |
1639 | "$message$>.addAll(values: Iterable<E>) {\n" |
1640 | " for (value in values) {\n" |
1641 | " add(value)\n" |
1642 | " }\n" |
1643 | "}\n\n" , |
1644 | args: "message" , args: message_name); |
1645 | |
1646 | printer->Print( |
1647 | text: "@kotlin.jvm.JvmSynthetic\n" |
1648 | "@Suppress(\"NOTHING_TO_INLINE\")\n" |
1649 | "inline operator fun <E : kotlin.Any> " |
1650 | "com.google.protobuf.kotlin.ExtensionList<E, " |
1651 | "$message$>.plusAssign(values: " |
1652 | "Iterable<E>) {\n" |
1653 | " addAll(values)\n" |
1654 | "}\n\n" , |
1655 | args: "message" , args: message_name); |
1656 | |
1657 | printer->Print( |
1658 | text: "@kotlin.jvm.JvmSynthetic\n" |
1659 | "operator fun <E : kotlin.Any> " |
1660 | "com.google.protobuf.kotlin.ExtensionList<E, " |
1661 | "$message$>.set(index: Int, value: " |
1662 | "E) {\n" |
1663 | " _builder.setExtension(this.extension, index, value)\n" |
1664 | "}\n\n" , |
1665 | args: "message" , args: message_name); |
1666 | |
1667 | printer->Print( |
1668 | text: "@kotlin.jvm.JvmSynthetic\n" |
1669 | "@Suppress(\"NOTHING_TO_INLINE\")\n" |
1670 | "inline fun com.google.protobuf.kotlin.ExtensionList<*, " |
1671 | "$message$>.clear() {\n" |
1672 | " clear(extension)\n" |
1673 | "}\n\n" , |
1674 | args: "message" , args: message_name); |
1675 | } |
1676 | |
1677 | void ImmutableMessageGenerator::GenerateAnyMethods(io::Printer* printer) { |
1678 | printer->Print( |
1679 | text: "private static String getTypeUrl(\n" |
1680 | " java.lang.String typeUrlPrefix,\n" |
1681 | " com.google.protobuf.Descriptors.Descriptor descriptor) {\n" |
1682 | " return typeUrlPrefix.endsWith(\"/\")\n" |
1683 | " ? typeUrlPrefix + descriptor.getFullName()\n" |
1684 | " : typeUrlPrefix + \"/\" + descriptor.getFullName();\n" |
1685 | "}\n" |
1686 | "\n" |
1687 | "private static String getTypeNameFromTypeUrl(\n" |
1688 | " java.lang.String typeUrl) {\n" |
1689 | " int pos = typeUrl.lastIndexOf('/');\n" |
1690 | " return pos == -1 ? \"\" : typeUrl.substring(pos + 1);\n" |
1691 | "}\n" |
1692 | "\n" |
1693 | "public static <T extends com.google.protobuf.Message> Any pack(\n" |
1694 | " T message) {\n" |
1695 | " return Any.newBuilder()\n" |
1696 | " .setTypeUrl(getTypeUrl(\"type.googleapis.com\",\n" |
1697 | " message.getDescriptorForType()))\n" |
1698 | " .setValue(message.toByteString())\n" |
1699 | " .build();\n" |
1700 | "}\n" |
1701 | "\n" |
1702 | "/**\n" |
1703 | " * Packs a message using the given type URL prefix. The type URL will\n" |
1704 | " * be constructed by concatenating the message type's full name to the\n" |
1705 | " * prefix with an optional \"/\" separator if the prefix doesn't end\n" |
1706 | " * with \"/\" already.\n" |
1707 | " */\n" |
1708 | "public static <T extends com.google.protobuf.Message> Any pack(\n" |
1709 | " T message, java.lang.String typeUrlPrefix) {\n" |
1710 | " return Any.newBuilder()\n" |
1711 | " .setTypeUrl(getTypeUrl(typeUrlPrefix,\n" |
1712 | " message.getDescriptorForType()))\n" |
1713 | " .setValue(message.toByteString())\n" |
1714 | " .build();\n" |
1715 | "}\n" |
1716 | "\n" |
1717 | "public <T extends com.google.protobuf.Message> boolean is(\n" |
1718 | " java.lang.Class<T> clazz) {\n" |
1719 | " T defaultInstance =\n" |
1720 | " com.google.protobuf.Internal.getDefaultInstance(clazz);\n" |
1721 | " return getTypeNameFromTypeUrl(getTypeUrl()).equals(\n" |
1722 | " defaultInstance.getDescriptorForType().getFullName());\n" |
1723 | "}\n" |
1724 | "\n" |
1725 | "private volatile com.google.protobuf.Message cachedUnpackValue;\n" |
1726 | "\n" |
1727 | "@java.lang.SuppressWarnings(\"unchecked\")\n" |
1728 | "public <T extends com.google.protobuf.Message> T unpack(\n" |
1729 | " java.lang.Class<T> clazz)\n" |
1730 | " throws com.google.protobuf.InvalidProtocolBufferException {\n" |
1731 | " boolean invalidClazz = false;\n" |
1732 | " if (cachedUnpackValue != null) {\n" |
1733 | " if (cachedUnpackValue.getClass() == clazz) {\n" |
1734 | " return (T) cachedUnpackValue;\n" |
1735 | " }\n" |
1736 | " invalidClazz = true;\n" |
1737 | " }\n" |
1738 | " if (invalidClazz || !is(clazz)) {\n" |
1739 | " throw new com.google.protobuf.InvalidProtocolBufferException(\n" |
1740 | " \"Type of the Any message does not match the given class.\");\n" |
1741 | " }\n" |
1742 | " T defaultInstance =\n" |
1743 | " com.google.protobuf.Internal.getDefaultInstance(clazz);\n" |
1744 | " T result = (T) defaultInstance.getParserForType()\n" |
1745 | " .parseFrom(getValue());\n" |
1746 | " cachedUnpackValue = result;\n" |
1747 | " return result;\n" |
1748 | "}\n" ); |
1749 | } |
1750 | |
1751 | } // namespace java |
1752 | } // namespace compiler |
1753 | } // namespace protobuf |
1754 | } // namespace google |
1755 | |
1756 | #include <google/protobuf/port_undef.inc> |
1757 | |