blob: d48171b0d82412d0af161b51bfec7897d19a6545 [file] [log] [blame]
temporal40ee5512008-07-10 02:12:20 +00001// Protocol Buffers - Google's data interchange format
kenton@google.com24bf56f2008-09-24 20:31:01 +00002// Copyright 2008 Google Inc. All rights reserved.
Feng Xiaoe4288622014-10-01 16:26:23 -07003// https://developers.google.com/protocol-buffers/
temporal40ee5512008-07-10 02:12:20 +00004//
kenton@google.com24bf56f2008-09-24 20:31:01 +00005// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
temporal40ee5512008-07-10 02:12:20 +00008//
kenton@google.com24bf56f2008-09-24 20:31:01 +00009// * 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.
temporal40ee5512008-07-10 02:12:20 +000018//
kenton@google.com24bf56f2008-09-24 20:31:01 +000019// 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.
temporal40ee5512008-07-10 02:12:20 +000030
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/cpp/cpp_file.h>
Feng Xiaoeee38b02015-08-22 18:25:48 -070036#include <map>
jieluo@google.com4de8f552014-07-18 00:47:59 +000037#include <memory>
Feng Xiao6ef984a2014-11-10 17:34:54 -080038#ifndef _SHARED_PTR_H
39#include <google/protobuf/stubs/shared_ptr.h>
40#endif
jieluo@google.com4de8f552014-07-18 00:47:59 +000041#include <set>
42
temporal40ee5512008-07-10 02:12:20 +000043#include <google/protobuf/compiler/cpp/cpp_enum.h>
44#include <google/protobuf/compiler/cpp/cpp_service.h>
45#include <google/protobuf/compiler/cpp/cpp_extension.h>
46#include <google/protobuf/compiler/cpp/cpp_helpers.h>
47#include <google/protobuf/compiler/cpp/cpp_message.h>
kenton@google.comfccb1462009-12-18 02:11:36 +000048#include <google/protobuf/compiler/cpp/cpp_field.h>
temporal40ee5512008-07-10 02:12:20 +000049#include <google/protobuf/io/printer.h>
50#include <google/protobuf/descriptor.pb.h>
51#include <google/protobuf/stubs/strutil.h>
52
53namespace google {
54namespace protobuf {
55namespace compiler {
56namespace cpp {
57
58// ===================================================================
59
jieluo@google.com4de8f552014-07-18 00:47:59 +000060FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
61 : file_(file),
62 message_generators_(
Feng Xiaof157a562014-11-14 11:50:31 -080063 new google::protobuf::scoped_ptr<MessageGenerator>[file->message_type_count()]),
jieluo@google.com4de8f552014-07-18 00:47:59 +000064 enum_generators_(
Feng Xiaof157a562014-11-14 11:50:31 -080065 new google::protobuf::scoped_ptr<EnumGenerator>[file->enum_type_count()]),
jieluo@google.com4de8f552014-07-18 00:47:59 +000066 service_generators_(
Feng Xiaof157a562014-11-14 11:50:31 -080067 new google::protobuf::scoped_ptr<ServiceGenerator>[file->service_count()]),
jieluo@google.com4de8f552014-07-18 00:47:59 +000068 extension_generators_(
Feng Xiaof157a562014-11-14 11:50:31 -080069 new google::protobuf::scoped_ptr<ExtensionGenerator>[file->extension_count()]),
jieluo@google.com4de8f552014-07-18 00:47:59 +000070 options_(options) {
temporal40ee5512008-07-10 02:12:20 +000071
72 for (int i = 0; i < file->message_type_count(); i++) {
73 message_generators_[i].reset(
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000074 new MessageGenerator(file->message_type(i), options));
temporal40ee5512008-07-10 02:12:20 +000075 }
76
77 for (int i = 0; i < file->enum_type_count(); i++) {
78 enum_generators_[i].reset(
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000079 new EnumGenerator(file->enum_type(i), options));
temporal40ee5512008-07-10 02:12:20 +000080 }
81
82 for (int i = 0; i < file->service_count(); i++) {
83 service_generators_[i].reset(
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000084 new ServiceGenerator(file->service(i), options));
temporal40ee5512008-07-10 02:12:20 +000085 }
86
87 for (int i = 0; i < file->extension_count(); i++) {
88 extension_generators_[i].reset(
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000089 new ExtensionGenerator(file->extension(i), options));
temporal40ee5512008-07-10 02:12:20 +000090 }
91
92 SplitStringUsing(file_->package(), ".", &package_parts_);
93}
94
95FileGenerator::~FileGenerator() {}
96
Jisi Liu3b3c8ab2016-03-30 11:39:59 -070097void FileGenerator::GenerateProtoHeader(io::Printer* printer,
98 const string& info_path) {
Feng Xiaoeee38b02015-08-22 18:25:48 -070099 if (!options_.proto_h) {
100 return;
101 }
102
103 string filename_identifier = FilenameIdentifier(file_->name());
104 GenerateTopHeaderGuard(printer, filename_identifier);
105
temporal40ee5512008-07-10 02:12:20 +0000106
Bo Yang5db21732015-05-21 14:28:59 -0700107 GenerateLibraryIncludes(printer);
Feng Xiaoeee38b02015-08-22 18:25:48 -0700108
109 for (int i = 0; i < file_->public_dependency_count(); i++) {
110 const FileDescriptor* dep = file_->public_dependency(i);
111 const char* extension = ".proto.h";
112 string dependency = StripProto(dep->name()) + extension;
113 printer->Print(
114 "#include \"$dependency$\" // IWYU pragma: export\n",
115 "dependency", dependency);
116 }
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000117
Jisi Liu3b3c8ab2016-03-30 11:39:59 -0700118 GenerateMetadataPragma(printer, info_path);
119
kenton@google.comfccb1462009-12-18 02:11:36 +0000120 printer->Print(
121 "// @@protoc_insertion_point(includes)\n");
122
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000123
Feng Xiaoeee38b02015-08-22 18:25:48 -0700124 GenerateForwardDeclarations(printer);
Feng Xiao6ef984a2014-11-10 17:34:54 -0800125
temporal40ee5512008-07-10 02:12:20 +0000126 // Open namespace.
127 GenerateNamespaceOpeners(printer);
128
Bo Yang5db21732015-05-21 14:28:59 -0700129 GenerateGlobalStateFunctionDeclarations(printer);
temporal40ee5512008-07-10 02:12:20 +0000130
131 printer->Print("\n");
132
Bo Yang5db21732015-05-21 14:28:59 -0700133 GenerateEnumDefinitions(printer);
temporal40ee5512008-07-10 02:12:20 +0000134
135 printer->Print(kThickSeparator);
136 printer->Print("\n");
137
Bo Yang5db21732015-05-21 14:28:59 -0700138 GenerateMessageDefinitions(printer);
temporal40ee5512008-07-10 02:12:20 +0000139
140 printer->Print("\n");
141 printer->Print(kThickSeparator);
142 printer->Print("\n");
143
Bo Yang5db21732015-05-21 14:28:59 -0700144 GenerateServiceDefinitions(printer);
temporal40ee5512008-07-10 02:12:20 +0000145
Bo Yang5db21732015-05-21 14:28:59 -0700146 GenerateExtensionIdentifiers(printer);
temporal40ee5512008-07-10 02:12:20 +0000147
148 printer->Print("\n");
149 printer->Print(kThickSeparator);
150 printer->Print("\n");
151
Bo Yang5db21732015-05-21 14:28:59 -0700152 GenerateInlineFunctionDefinitions(printer);
kenton@google.comfccb1462009-12-18 02:11:36 +0000153
Feng Xiaoeee38b02015-08-22 18:25:48 -0700154 printer->Print(
155 "\n"
156 "// @@protoc_insertion_point(namespace_scope)\n"
157 "\n");
158
temporal40ee5512008-07-10 02:12:20 +0000159 // Close up namespace.
160 GenerateNamespaceClosers(printer);
161
Bo Yang5db21732015-05-21 14:28:59 -0700162 // We need to specialize some templates in the ::google::protobuf namespace:
163 GenerateProto2NamespaceEnumSpecializations(printer);
kenton@google.com80b1d622009-07-29 01:13:20 +0000164
temporal40ee5512008-07-10 02:12:20 +0000165 printer->Print(
kenton@google.comfccb1462009-12-18 02:11:36 +0000166 "\n"
167 "// @@protoc_insertion_point(global_scope)\n"
168 "\n");
169
Feng Xiaoeee38b02015-08-22 18:25:48 -0700170 GenerateBottomHeaderGuard(printer, filename_identifier);
171}
172
Jisi Liu3b3c8ab2016-03-30 11:39:59 -0700173void FileGenerator::GeneratePBHeader(io::Printer* printer,
174 const string& info_path) {
Feng Xiaoeee38b02015-08-22 18:25:48 -0700175 string filename_identifier =
176 FilenameIdentifier(file_->name() + (options_.proto_h ? ".pb.h" : ""));
177 GenerateTopHeaderGuard(printer, filename_identifier);
178
179 if (options_.proto_h) {
180 printer->Print("#include \"$basename$.proto.h\" // IWYU pragma: export\n",
181 "basename", StripProto(file_->name()));
182 } else {
183 GenerateLibraryIncludes(printer);
184 }
185 GenerateDependencyIncludes(printer);
Jisi Liu3b3c8ab2016-03-30 11:39:59 -0700186 GenerateMetadataPragma(printer, info_path);
Feng Xiaoeee38b02015-08-22 18:25:48 -0700187
188 printer->Print(
189 "// @@protoc_insertion_point(includes)\n");
190
191
192
193 // Open namespace.
194 GenerateNamespaceOpeners(printer);
195
196 if (!options_.proto_h) {
197 GenerateGlobalStateFunctionDeclarations(printer);
198 GenerateMessageForwardDeclarations(printer);
199
200 printer->Print("\n");
201
202 GenerateEnumDefinitions(printer);
203
204 printer->Print(kThickSeparator);
205 printer->Print("\n");
206
207 GenerateMessageDefinitions(printer);
208
209 printer->Print("\n");
210 printer->Print(kThickSeparator);
211 printer->Print("\n");
212
213 GenerateServiceDefinitions(printer);
214
215 GenerateExtensionIdentifiers(printer);
216
217 printer->Print("\n");
218 printer->Print(kThickSeparator);
219 printer->Print("\n");
220
221 GenerateInlineFunctionDefinitions(printer);
222 }
223
224 printer->Print(
225 "\n"
226 "// @@protoc_insertion_point(namespace_scope)\n");
227
228 // Close up namespace.
229 GenerateNamespaceClosers(printer);
230
231 if (!options_.proto_h) {
232 // We need to specialize some templates in the ::google::protobuf namespace:
233 GenerateProto2NamespaceEnumSpecializations(printer);
234 }
235
236 printer->Print(
237 "\n"
238 "// @@protoc_insertion_point(global_scope)\n"
239 "\n");
240
241 GenerateBottomHeaderGuard(printer, filename_identifier);
temporal40ee5512008-07-10 02:12:20 +0000242}
243
244void FileGenerator::GenerateSource(io::Printer* printer) {
Jisi Liu3b3c8ab2016-03-30 11:39:59 -0700245 const bool use_system_include = IsWellKnownMessage(file_);
Feng Xiaoeee38b02015-08-22 18:25:48 -0700246 string header =
247 StripProto(file_->name()) + (options_.proto_h ? ".proto.h" : ".pb.h");
temporal40ee5512008-07-10 02:12:20 +0000248 printer->Print(
249 "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000250 "// source: $filename$\n"
temporal40ee5512008-07-10 02:12:20 +0000251 "\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000252 // The generated code calls accessors that might be deprecated. We don't
253 // want the compiler to warn in generated code.
254 "#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION\n"
Bo Yang1f0286a2015-12-04 13:18:44 -0800255 "#include $left$$header$$right$\n"
kenton@google.comc65c0412010-02-01 20:35:34 +0000256 "\n"
257 "#include <algorithm>\n" // for swap()
258 "\n"
pliard@google.com75575df2012-10-02 00:15:46 +0000259 "#include <google/protobuf/stubs/common.h>\n"
Feng Xiaoe841bac2015-12-11 17:09:20 -0800260 "#include <google/protobuf/stubs/port.h>\n"
kenton@google.comd37d46d2009-04-25 02:53:47 +0000261 "#include <google/protobuf/stubs/once.h>\n"
temporal40ee5512008-07-10 02:12:20 +0000262 "#include <google/protobuf/io/coded_stream.h>\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000263 "#include <google/protobuf/wire_format_lite_inl.h>\n",
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000264 "filename", file_->name(),
Bo Yang1f0286a2015-12-04 13:18:44 -0800265 "header", header,
Jisi Liu3b3c8ab2016-03-30 11:39:59 -0700266 "left", use_system_include ? "<" : "\"",
267 "right", use_system_include ? ">" : "\"");
temporal40ee5512008-07-10 02:12:20 +0000268
jieluo@google.com4de8f552014-07-18 00:47:59 +0000269 // Unknown fields implementation in lite mode uses StringOutputStream
270 if (!UseUnknownFieldSet(file_) && file_->message_type_count() > 0) {
271 printer->Print(
272 "#include <google/protobuf/io/zero_copy_stream_impl_lite.h>\n");
273 }
274
kenton@google.com80b1d622009-07-29 01:13:20 +0000275 if (HasDescriptorMethods(file_)) {
276 printer->Print(
277 "#include <google/protobuf/descriptor.h>\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000278 "#include <google/protobuf/generated_message_reflection.h>\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000279 "#include <google/protobuf/reflection_ops.h>\n"
280 "#include <google/protobuf/wire_format.h>\n");
281 }
282
Feng Xiaoeee38b02015-08-22 18:25:48 -0700283 if (options_.proto_h) {
284 // Use the smaller .proto.h files.
285 for (int i = 0; i < file_->dependency_count(); i++) {
286 const FileDescriptor* dep = file_->dependency(i);
287 const char* extension = ".proto.h";
288 string dependency = StripProto(dep->name()) + extension;
289 printer->Print(
290 "#include \"$dependency$\"\n",
291 "dependency", dependency);
292 }
293 }
294
kenton@google.comfccb1462009-12-18 02:11:36 +0000295 printer->Print(
296 "// @@protoc_insertion_point(includes)\n");
297
temporal40ee5512008-07-10 02:12:20 +0000298 GenerateNamespaceOpeners(printer);
299
kenton@google.com80b1d622009-07-29 01:13:20 +0000300 if (HasDescriptorMethods(file_)) {
temporal40ee5512008-07-10 02:12:20 +0000301 printer->Print(
kenton@google.com80b1d622009-07-29 01:13:20 +0000302 "\n"
303 "namespace {\n"
304 "\n");
305 for (int i = 0; i < file_->message_type_count(); i++) {
306 message_generators_[i]->GenerateDescriptorDeclarations(printer);
307 }
308 for (int i = 0; i < file_->enum_type_count(); i++) {
309 printer->Print(
310 "const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n",
311 "name", ClassName(file_->enum_type(i), false));
312 }
kenton@google.comfccb1462009-12-18 02:11:36 +0000313
314 if (HasGenericServices(file_)) {
315 for (int i = 0; i < file_->service_count(); i++) {
316 printer->Print(
317 "const ::google::protobuf::ServiceDescriptor* $name$_descriptor_ = NULL;\n",
318 "name", file_->service(i)->name());
319 }
kenton@google.com80b1d622009-07-29 01:13:20 +0000320 }
321
temporal40ee5512008-07-10 02:12:20 +0000322 printer->Print(
kenton@google.com80b1d622009-07-29 01:13:20 +0000323 "\n"
324 "} // namespace\n"
325 "\n");
temporal40ee5512008-07-10 02:12:20 +0000326 }
327
kenton@google.com80b1d622009-07-29 01:13:20 +0000328 // Define our externally-visible BuildDescriptors() function. (For the lite
329 // library, all this does is initialize default instances.)
temporal40ee5512008-07-10 02:12:20 +0000330 GenerateBuildDescriptors(printer);
331
332 // Generate enums.
333 for (int i = 0; i < file_->enum_type_count(); i++) {
334 enum_generators_[i]->GenerateMethods(printer);
335 }
336
337 // Generate classes.
338 for (int i = 0; i < file_->message_type_count(); i++) {
Feng Xiaof157a562014-11-14 11:50:31 -0800339 if (i == 0 && HasGeneratedMethods(file_)) {
340 printer->Print(
341 "\n"
342 "namespace {\n"
343 "\n"
344 "static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;\n"
345 "static void MergeFromFail(int line) {\n"
346 " GOOGLE_CHECK(false) << __FILE__ << \":\" << line;\n"
347 "}\n"
348 "\n"
349 "} // namespace\n"
350 "\n");
351 }
temporal40ee5512008-07-10 02:12:20 +0000352 printer->Print("\n");
353 printer->Print(kThickSeparator);
354 printer->Print("\n");
355 message_generators_[i]->GenerateClassMethods(printer);
Jisi Liu885b6122015-02-28 14:51:22 -0800356
357 printer->Print("#if PROTOBUF_INLINE_NOT_IN_HEADERS\n");
358 // Generate class inline methods.
359 message_generators_[i]->GenerateInlineMethods(printer,
360 /* is_inline = */ false);
361 printer->Print("#endif // PROTOBUF_INLINE_NOT_IN_HEADERS\n");
temporal40ee5512008-07-10 02:12:20 +0000362 }
363
kenton@google.comfccb1462009-12-18 02:11:36 +0000364 if (HasGenericServices(file_)) {
kenton@google.com80b1d622009-07-29 01:13:20 +0000365 // Generate services.
366 for (int i = 0; i < file_->service_count(); i++) {
367 if (i == 0) printer->Print("\n");
368 printer->Print(kThickSeparator);
369 printer->Print("\n");
370 service_generators_[i]->GenerateImplementation(printer);
371 }
temporal40ee5512008-07-10 02:12:20 +0000372 }
373
374 // Define extensions.
375 for (int i = 0; i < file_->extension_count(); i++) {
376 extension_generators_[i]->GenerateDefinition(printer);
377 }
378
kenton@google.comfccb1462009-12-18 02:11:36 +0000379 printer->Print(
380 "\n"
381 "// @@protoc_insertion_point(namespace_scope)\n");
382
temporal40ee5512008-07-10 02:12:20 +0000383 GenerateNamespaceClosers(printer);
kenton@google.comfccb1462009-12-18 02:11:36 +0000384
385 printer->Print(
386 "\n"
387 "// @@protoc_insertion_point(global_scope)\n");
temporal40ee5512008-07-10 02:12:20 +0000388}
389
Feng Xiaoeee38b02015-08-22 18:25:48 -0700390class FileGenerator::ForwardDeclarations {
391 public:
392 ~ForwardDeclarations() {
393 for (map<string, ForwardDeclarations *>::iterator it = namespaces_.begin(),
394 end = namespaces_.end();
395 it != end; ++it) {
396 delete it->second;
397 }
398 namespaces_.clear();
399 }
400
401 ForwardDeclarations* AddOrGetNamespace(const string& ns_name) {
402 ForwardDeclarations*& ns = namespaces_[ns_name];
403 if (ns == NULL) {
404 ns = new ForwardDeclarations;
405 }
406 return ns;
407 }
408
Jisi Liu3b3c8ab2016-03-30 11:39:59 -0700409 map<string, const Descriptor*>& classes() { return classes_; }
410 map<string, const EnumDescriptor*>& enums() { return enums_; }
Feng Xiaoeee38b02015-08-22 18:25:48 -0700411
412 void Print(io::Printer* printer) const {
Jisi Liu3b3c8ab2016-03-30 11:39:59 -0700413 for (map<string, const EnumDescriptor *>::const_iterator
414 it = enums_.begin(),
415 end = enums_.end();
Feng Xiaoeee38b02015-08-22 18:25:48 -0700416 it != end; ++it) {
Jisi Liu3b3c8ab2016-03-30 11:39:59 -0700417 printer->Print("enum $enumname$ : int;\n", "enumname", it->first);
418 printer->Annotate("enumname", it->second);
419 printer->Print("bool $enumname$_IsValid(int value);\n", "enumname",
420 it->first);
Feng Xiaoeee38b02015-08-22 18:25:48 -0700421 }
Jisi Liu3b3c8ab2016-03-30 11:39:59 -0700422 for (map<string, const Descriptor *>::const_iterator it = classes_.begin(),
423 end = classes_.end();
Feng Xiaoeee38b02015-08-22 18:25:48 -0700424 it != end; ++it) {
Jisi Liu3b3c8ab2016-03-30 11:39:59 -0700425 printer->Print("class $classname$;\n", "classname", it->first);
426 printer->Annotate("classname", it->second);
Feng Xiaoeee38b02015-08-22 18:25:48 -0700427 }
428 for (map<string, ForwardDeclarations *>::const_iterator
429 it = namespaces_.begin(),
430 end = namespaces_.end();
431 it != end; ++it) {
432 printer->Print("namespace $nsname$ {\n",
433 "nsname", it->first);
434 it->second->Print(printer);
435 printer->Print("} // namespace $nsname$\n",
436 "nsname", it->first);
437 }
438 }
439
440
441 private:
442 map<string, ForwardDeclarations*> namespaces_;
Jisi Liu3b3c8ab2016-03-30 11:39:59 -0700443 map<string, const Descriptor*> classes_;
444 map<string, const EnumDescriptor*> enums_;
Feng Xiaoeee38b02015-08-22 18:25:48 -0700445};
446
temporal40ee5512008-07-10 02:12:20 +0000447void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
kenton@google.comd37d46d2009-04-25 02:53:47 +0000448 // AddDescriptors() is a file-level procedure which adds the encoded
pliard@google.com6103d4e2012-05-04 11:16:09 +0000449 // FileDescriptorProto for this .proto file to the global DescriptorPool for
450 // generated files (DescriptorPool::generated_pool()). It either runs at
451 // static initialization time (by default) or when default_instance() is
452 // called for the first time (in LITE_RUNTIME mode with
453 // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER flag enabled). This procedure also
454 // constructs default instances and registers extensions.
temporal779f61c2008-08-13 03:15:00 +0000455 //
kenton@google.comd37d46d2009-04-25 02:53:47 +0000456 // Its sibling, AssignDescriptors(), actually pulls the compiled
457 // FileDescriptor from the DescriptorPool and uses it to populate all of
458 // the global variables which store pointers to the descriptor objects.
459 // It also constructs the reflection objects. It is called the first time
460 // anyone calls descriptor() or GetReflection() on one of the types defined
461 // in the file.
kenton@google.com24bf56f2008-09-24 20:31:01 +0000462
kenton@google.com80b1d622009-07-29 01:13:20 +0000463 // In optimize_for = LITE_RUNTIME mode, we don't generate AssignDescriptors()
464 // and we only use AddDescriptors() to allocate default instances.
465 if (HasDescriptorMethods(file_)) {
466 printer->Print(
467 "\n"
468 "void $assigndescriptorsname$() {\n",
469 "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
470 printer->Indent();
kenton@google.comd37d46d2009-04-25 02:53:47 +0000471
kenton@google.com80b1d622009-07-29 01:13:20 +0000472 // Make sure the file has found its way into the pool. If a descriptor
473 // is requested *during* static init then AddDescriptors() may not have
474 // been called yet, so we call it manually. Note that it's fine if
475 // AddDescriptors() is called multiple times.
476 printer->Print(
477 "$adddescriptorsname$();\n",
478 "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
kenton@google.comd37d46d2009-04-25 02:53:47 +0000479
kenton@google.com80b1d622009-07-29 01:13:20 +0000480 // Get the file's descriptor from the pool.
481 printer->Print(
482 "const ::google::protobuf::FileDescriptor* file =\n"
483 " ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(\n"
484 " \"$filename$\");\n"
485 // Note that this GOOGLE_CHECK is necessary to prevent a warning about "file"
486 // being unused when compiling an empty .proto file.
487 "GOOGLE_CHECK(file != NULL);\n",
488 "filename", file_->name());
kenton@google.comd37d46d2009-04-25 02:53:47 +0000489
kenton@google.com80b1d622009-07-29 01:13:20 +0000490 // Go through all the stuff defined in this file and generated code to
491 // assign the global descriptor pointers based on the file descriptor.
492 for (int i = 0; i < file_->message_type_count(); i++) {
493 message_generators_[i]->GenerateDescriptorInitializer(printer, i);
494 }
495 for (int i = 0; i < file_->enum_type_count(); i++) {
496 enum_generators_[i]->GenerateDescriptorInitializer(printer, i);
497 }
kenton@google.comfccb1462009-12-18 02:11:36 +0000498 if (HasGenericServices(file_)) {
499 for (int i = 0; i < file_->service_count(); i++) {
500 service_generators_[i]->GenerateDescriptorInitializer(printer, i);
501 }
kenton@google.com80b1d622009-07-29 01:13:20 +0000502 }
503
504 printer->Outdent();
505 printer->Print(
506 "}\n"
507 "\n");
508
509 // ---------------------------------------------------------------
510
511 // protobuf_AssignDescriptorsOnce(): The first time it is called, calls
512 // AssignDescriptors(). All later times, waits for the first call to
513 // complete and then returns.
514 printer->Print(
515 "namespace {\n"
516 "\n"
517 "GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);\n"
518 "inline void protobuf_AssignDescriptorsOnce() {\n"
519 " ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,\n"
520 " &$assigndescriptorsname$);\n"
521 "}\n"
522 "\n",
523 "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
524
525 // protobuf_RegisterTypes(): Calls
526 // MessageFactory::InternalRegisterGeneratedType() for each message type.
527 printer->Print(
528 "void protobuf_RegisterTypes(const ::std::string&) {\n"
529 " protobuf_AssignDescriptorsOnce();\n");
530 printer->Indent();
531
532 for (int i = 0; i < file_->message_type_count(); i++) {
533 message_generators_[i]->GenerateTypeRegistrations(printer);
534 }
535
536 printer->Outdent();
537 printer->Print(
538 "}\n"
539 "\n"
540 "} // namespace\n");
kenton@google.com24bf56f2008-09-24 20:31:01 +0000541 }
kenton@google.com24bf56f2008-09-24 20:31:01 +0000542
kenton@google.comd37d46d2009-04-25 02:53:47 +0000543 // -----------------------------------------------------------------
544
kenton@google.com63e646b2009-05-06 19:27:03 +0000545 // ShutdownFile(): Deletes descriptors, default instances, etc. on shutdown.
546 printer->Print(
547 "\n"
548 "void $shutdownfilename$() {\n",
549 "shutdownfilename", GlobalShutdownFileName(file_->name()));
550 printer->Indent();
551
552 for (int i = 0; i < file_->message_type_count(); i++) {
553 message_generators_[i]->GenerateShutdownCode(printer);
554 }
555
556 printer->Outdent();
557 printer->Print(
pliard@google.com6103d4e2012-05-04 11:16:09 +0000558 "}\n\n");
kenton@google.com63e646b2009-05-06 19:27:03 +0000559
560 // -----------------------------------------------------------------
561
kenton@google.comd37d46d2009-04-25 02:53:47 +0000562 // Now generate the AddDescriptors() function.
pliard@google.com6103d4e2012-05-04 11:16:09 +0000563 PrintHandlingOptionalStaticInitializers(
564 file_, printer,
565 // With static initializers.
566 // Note that we don't need any special synchronization in the following code
567 // because it is called at static init time before any threads exist.
kenton@google.comd37d46d2009-04-25 02:53:47 +0000568 "void $adddescriptorsname$() {\n"
temporal40ee5512008-07-10 02:12:20 +0000569 " static bool already_here = false;\n"
570 " if (already_here) return;\n"
571 " already_here = true;\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000572 " GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
573 "\n",
pliard@google.com6103d4e2012-05-04 11:16:09 +0000574 // Without.
575 "void $adddescriptorsname$_impl() {\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000576 " GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
577 "\n",
pliard@google.com6103d4e2012-05-04 11:16:09 +0000578 // Vars.
kenton@google.comd37d46d2009-04-25 02:53:47 +0000579 "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
pliard@google.com6103d4e2012-05-04 11:16:09 +0000580
temporal40ee5512008-07-10 02:12:20 +0000581 printer->Indent();
582
kenton@google.comd37d46d2009-04-25 02:53:47 +0000583 // Call the AddDescriptors() methods for all of our dependencies, to make
584 // sure they get added first.
temporal40ee5512008-07-10 02:12:20 +0000585 for (int i = 0; i < file_->dependency_count(); i++) {
586 const FileDescriptor* dependency = file_->dependency(i);
587 // Print the namespace prefix for the dependency.
jieluo@google.com4de8f552014-07-18 00:47:59 +0000588 string add_desc_name = QualifiedFileLevelSymbol(
589 dependency->package(), GlobalAddDescriptorsName(dependency->name()));
kenton@google.comd37d46d2009-04-25 02:53:47 +0000590 // Call its AddDescriptors function.
temporal40ee5512008-07-10 02:12:20 +0000591 printer->Print(
592 "$name$();\n",
jieluo@google.com4de8f552014-07-18 00:47:59 +0000593 "name", add_desc_name);
temporal40ee5512008-07-10 02:12:20 +0000594 }
595
kenton@google.com80b1d622009-07-29 01:13:20 +0000596 if (HasDescriptorMethods(file_)) {
597 // Embed the descriptor. We simply serialize the entire FileDescriptorProto
598 // and embed it as a string literal, which is parsed and built into real
599 // descriptors at initialization time.
600 FileDescriptorProto file_proto;
601 file_->CopyTo(&file_proto);
602 string file_data;
603 file_proto.SerializeToString(&file_data);
temporal40ee5512008-07-10 02:12:20 +0000604
Feng Xiaoeee38b02015-08-22 18:25:48 -0700605#ifdef _MSC_VER
606 bool breakdown_large_file = true;
607#else
608 bool breakdown_large_file = false;
609#endif
Qartar2fe6d7b2015-06-07 14:22:51 -0700610 // Workaround for MSVC: "Error C1091: compiler limit: string exceeds 65535
611 // bytes in length". Declare a static array of characters rather than use a
612 // string literal.
Feng Xiaoeee38b02015-08-22 18:25:48 -0700613 if (breakdown_large_file && file_data.size() > 65535) {
Brian Silverman21f3d372015-09-08 18:57:04 -0400614 // This has to be explicitly marked as a signed char because the generated
615 // code puts negative values in the array, and sometimes plain char is
616 // unsigned. That implicit narrowing conversion is not allowed in C++11.
617 // <http://stackoverflow.com/questions/4434140/narrowing-conversions-in-c0x-is-it-just-me-or-does-this-sound-like-a-breakin>
618 // has details on why.
Qartar2fe6d7b2015-06-07 14:22:51 -0700619 printer->Print(
Brian Silverman21f3d372015-09-08 18:57:04 -0400620 "static const signed char descriptor[] = {\n");
Qartar2fe6d7b2015-06-07 14:22:51 -0700621 printer->Indent();
temporal40ee5512008-07-10 02:12:20 +0000622
Qartar2fe6d7b2015-06-07 14:22:51 -0700623 // Only write 25 bytes per line.
624 static const int kBytesPerLine = 25;
625 for (int i = 0; i < file_data.size();) {
626 for (int j = 0; j < kBytesPerLine && i < file_data.size(); ++i, ++j) {
627 printer->Print(
Feng Xiaoeee38b02015-08-22 18:25:48 -0700628 "$char$, ",
629 "char", SimpleItoa(file_data[i]));
Qartar2fe6d7b2015-06-07 14:22:51 -0700630 }
631 printer->Print(
Feng Xiaoeee38b02015-08-22 18:25:48 -0700632 "\n");
Qartar2fe6d7b2015-06-07 14:22:51 -0700633 }
634
635 printer->Outdent();
636 printer->Print(
Feng Xiaoeee38b02015-08-22 18:25:48 -0700637 "};\n");
Qartar2fe6d7b2015-06-07 14:22:51 -0700638
639 printer->Print(
Feng Xiaoeee38b02015-08-22 18:25:48 -0700640 "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(descriptor, $size$);\n",
641 "size", SimpleItoa(file_data.size()));
Qartar2fe6d7b2015-06-07 14:22:51 -0700642
643 } else {
Qartar2fe6d7b2015-06-07 14:22:51 -0700644 printer->Print(
645 "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(");
Feng Xiaoeee38b02015-08-22 18:25:48 -0700646
Qartar2fe6d7b2015-06-07 14:22:51 -0700647 // Only write 40 bytes per line.
648 static const int kBytesPerLine = 40;
649 for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
650 printer->Print("\n \"$data$\"",
651 "data",
652 EscapeTrigraphs(
653 CEscape(file_data.substr(i, kBytesPerLine))));
Feng Xiaoeee38b02015-08-22 18:25:48 -0700654 }
655 printer->Print(
656 ", $size$);\n",
Qartar2fe6d7b2015-06-07 14:22:51 -0700657 "size", SimpleItoa(file_data.size()));
kenton@google.com80b1d622009-07-29 01:13:20 +0000658 }
kenton@google.com80b1d622009-07-29 01:13:20 +0000659
660 // Call MessageFactory::InternalRegisterGeneratedFile().
661 printer->Print(
662 "::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(\n"
663 " \"$filename$\", &protobuf_RegisterTypes);\n",
664 "filename", file_->name());
temporal40ee5512008-07-10 02:12:20 +0000665 }
kenton@google.comd37d46d2009-04-25 02:53:47 +0000666
667 // Allocate and initialize default instances. This can't be done lazily
668 // since default instances are returned by simple accessors and are used with
669 // extensions. Speaking of which, we also register extensions at this time.
670 for (int i = 0; i < file_->message_type_count(); i++) {
671 message_generators_[i]->GenerateDefaultInstanceAllocator(printer);
672 }
673 for (int i = 0; i < file_->extension_count(); i++) {
674 extension_generators_[i]->GenerateRegistration(printer);
675 }
676 for (int i = 0; i < file_->message_type_count(); i++) {
677 message_generators_[i]->GenerateDefaultInstanceInitializer(printer);
678 }
temporal40ee5512008-07-10 02:12:20 +0000679
kenton@google.com63e646b2009-05-06 19:27:03 +0000680 printer->Print(
681 "::google::protobuf::internal::OnShutdown(&$shutdownfilename$);\n",
682 "shutdownfilename", GlobalShutdownFileName(file_->name()));
683
temporal40ee5512008-07-10 02:12:20 +0000684 printer->Outdent();
temporal40ee5512008-07-10 02:12:20 +0000685 printer->Print(
686 "}\n"
pliard@google.com6103d4e2012-05-04 11:16:09 +0000687 "\n");
688
689 PrintHandlingOptionalStaticInitializers(
690 file_, printer,
691 // With static initializers.
kenton@google.comd37d46d2009-04-25 02:53:47 +0000692 "// Force AddDescriptors() to be called at static initialization time.\n"
temporal40ee5512008-07-10 02:12:20 +0000693 "struct StaticDescriptorInitializer_$filename$ {\n"
694 " StaticDescriptorInitializer_$filename$() {\n"
kenton@google.comd37d46d2009-04-25 02:53:47 +0000695 " $adddescriptorsname$();\n"
temporal40ee5512008-07-10 02:12:20 +0000696 " }\n"
pliard@google.com6103d4e2012-05-04 11:16:09 +0000697 "} static_descriptor_initializer_$filename$_;\n",
698 // Without.
pliard@google.coma269a2c2012-05-10 08:04:04 +0000699 "GOOGLE_PROTOBUF_DECLARE_ONCE($adddescriptorsname$_once_);\n"
pliard@google.com6103d4e2012-05-04 11:16:09 +0000700 "void $adddescriptorsname$() {\n"
xiaofeng@google.comd8331262013-07-30 18:35:45 +0000701 " ::google::protobuf::GoogleOnceInit(&$adddescriptorsname$_once_,\n"
pliard@google.com6103d4e2012-05-04 11:16:09 +0000702 " &$adddescriptorsname$_impl);\n"
703 "}\n",
704 // Vars.
kenton@google.comd37d46d2009-04-25 02:53:47 +0000705 "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
temporal40ee5512008-07-10 02:12:20 +0000706 "filename", FilenameIdentifier(file_->name()));
707}
708
709void FileGenerator::GenerateNamespaceOpeners(io::Printer* printer) {
710 if (package_parts_.size() > 0) printer->Print("\n");
711
712 for (int i = 0; i < package_parts_.size(); i++) {
713 printer->Print("namespace $part$ {\n",
714 "part", package_parts_[i]);
715 }
716}
717
718void FileGenerator::GenerateNamespaceClosers(io::Printer* printer) {
719 if (package_parts_.size() > 0) printer->Print("\n");
720
721 for (int i = package_parts_.size() - 1; i >= 0; i--) {
722 printer->Print("} // namespace $part$\n",
723 "part", package_parts_[i]);
724 }
725}
726
Feng Xiaoeee38b02015-08-22 18:25:48 -0700727void FileGenerator::GenerateForwardDeclarations(io::Printer* printer) {
728 ForwardDeclarations decls;
729 for (int i = 0; i < file_->dependency_count(); i++) {
730 FileGenerator dependency(file_->dependency(i), options_);
731 dependency.FillForwardDeclarations(&decls);
732 }
733 FillForwardDeclarations(&decls);
734 decls.Print(printer);
735}
736
737void FileGenerator::FillForwardDeclarations(ForwardDeclarations* decls) {
738 for (int i = 0; i < file_->public_dependency_count(); i++) {
739 FileGenerator dependency(file_->public_dependency(i), options_);
740 dependency.FillForwardDeclarations(decls);
741 }
742 for (int i = 0; i < package_parts_.size(); i++) {
743 decls = decls->AddOrGetNamespace(package_parts_[i]);
744 }
745 // Generate enum definitions.
746 for (int i = 0; i < file_->message_type_count(); i++) {
747 message_generators_[i]->FillEnumForwardDeclarations(&decls->enums());
748 }
749 for (int i = 0; i < file_->enum_type_count(); i++) {
750 enum_generators_[i]->FillForwardDeclaration(&decls->enums());
751 }
752 // Generate forward declarations of classes.
753 for (int i = 0; i < file_->message_type_count(); i++) {
754 message_generators_[i]->FillMessageForwardDeclarations(
755 &decls->classes());
756 }
757}
758
759void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer,
760 const string& filename_identifier) {
Bo Yang5db21732015-05-21 14:28:59 -0700761 // Generate top of header.
762 printer->Print(
763 "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
764 "// source: $filename$\n"
765 "\n"
766 "#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n"
767 "#define PROTOBUF_$filename_identifier$__INCLUDED\n"
768 "\n"
769 "#include <string>\n"
770 "\n",
771 "filename", file_->name(),
772 "filename_identifier", filename_identifier);
773}
774
Feng Xiaoeee38b02015-08-22 18:25:48 -0700775void FileGenerator::GenerateBottomHeaderGuard(
776 io::Printer* printer, const string& filename_identifier) {
Bo Yang5db21732015-05-21 14:28:59 -0700777 printer->Print(
778 "#endif // PROTOBUF_$filename_identifier$__INCLUDED\n",
779 "filename_identifier", filename_identifier);
780}
781
782void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) {
783
784 printer->Print(
785 "#include <google/protobuf/stubs/common.h>\n"
786 "\n");
787
788 // Verify the protobuf library header version is compatible with the protoc
789 // version before going any further.
790 printer->Print(
791 "#if GOOGLE_PROTOBUF_VERSION < $min_header_version$\n"
792 "#error This file was generated by a newer version of protoc which is\n"
793 "#error incompatible with your Protocol Buffer headers. Please update\n"
794 "#error your headers.\n"
795 "#endif\n"
796 "#if $protoc_version$ < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION\n"
797 "#error This file was generated by an older version of protoc which is\n"
798 "#error incompatible with your Protocol Buffer headers. Please\n"
799 "#error regenerate this file with a newer version of protoc.\n"
800 "#endif\n"
801 "\n",
802 "min_header_version",
803 SimpleItoa(protobuf::internal::kMinHeaderVersionForProtoc),
804 "protoc_version", SimpleItoa(GOOGLE_PROTOBUF_VERSION));
805
806 // OK, it's now safe to #include other files.
807 printer->Print(
808 "#include <google/protobuf/arena.h>\n"
809 "#include <google/protobuf/arenastring.h>\n"
810 "#include <google/protobuf/generated_message_util.h>\n");
811 if (UseUnknownFieldSet(file_)) {
812 printer->Print(
813 "#include <google/protobuf/metadata.h>\n");
814 }
815 if (file_->message_type_count() > 0) {
816 if (HasDescriptorMethods(file_)) {
817 printer->Print(
818 "#include <google/protobuf/message.h>\n");
819 } else {
820 printer->Print(
821 "#include <google/protobuf/message_lite.h>\n");
822 }
823 }
824 printer->Print(
825 "#include <google/protobuf/repeated_field.h>\n"
826 "#include <google/protobuf/extension_set.h>\n");
827 if (HasMapFields(file_)) {
828 printer->Print(
829 "#include <google/protobuf/map.h>\n");
830 if (HasDescriptorMethods(file_)) {
831 printer->Print(
832 "#include <google/protobuf/map_field_inl.h>\n");
833 } else {
834 printer->Print(
835 "#include <google/protobuf/map_field_lite.h>\n");
836 }
837 }
838
839 if (HasEnumDefinitions(file_)) {
840 if (HasDescriptorMethods(file_)) {
841 printer->Print(
842 "#include <google/protobuf/generated_enum_reflection.h>\n");
843 } else {
844 printer->Print(
845 "#include <google/protobuf/generated_enum_util.h>\n");
846 }
847 }
848
849 if (HasGenericServices(file_)) {
850 printer->Print(
851 "#include <google/protobuf/service.h>\n");
852 }
853
854 if (UseUnknownFieldSet(file_) && file_->message_type_count() > 0) {
855 printer->Print(
856 "#include <google/protobuf/unknown_field_set.h>\n");
857 }
858
859
860 if (IsAnyMessage(file_)) {
861 printer->Print(
Matthew Wu187cfc52015-10-22 16:09:56 -0700862 "#include <google/protobuf/any.h>\n");
Bo Yang5db21732015-05-21 14:28:59 -0700863 }
864}
865
Jisi Liu3b3c8ab2016-03-30 11:39:59 -0700866void FileGenerator::GenerateMetadataPragma(io::Printer* printer,
867 const string& info_path) {
868 if (!info_path.empty() && !options_.annotation_pragma_name.empty() &&
869 !options_.annotation_guard_name.empty()) {
870 printer->Print(
871 "#ifdef $guard$\n"
872 "#pragma $pragma$ \"$info_path$\"\n"
873 "#endif // $guard$\n",
874 "guard", options_.annotation_guard_name, "pragma",
875 options_.annotation_pragma_name, "info_path", info_path);
876 }
877}
878
Bo Yang5db21732015-05-21 14:28:59 -0700879void FileGenerator::GenerateDependencyIncludes(io::Printer* printer) {
880 set<string> public_import_names;
881 for (int i = 0; i < file_->public_dependency_count(); i++) {
882 public_import_names.insert(file_->public_dependency(i)->name());
883 }
884
885 for (int i = 0; i < file_->dependency_count(); i++) {
Jisi Liu3b3c8ab2016-03-30 11:39:59 -0700886 const bool use_system_include = IsWellKnownMessage(file_->dependency(i));
Bo Yang5db21732015-05-21 14:28:59 -0700887 const string& name = file_->dependency(i)->name();
888 bool public_import = (public_import_names.count(name) != 0);
889
Jisi Liu3b3c8ab2016-03-30 11:39:59 -0700890
Bo Yang5db21732015-05-21 14:28:59 -0700891 printer->Print(
Bo Yang1f0286a2015-12-04 13:18:44 -0800892 "#include $left$$dependency$.pb.h$right$$iwyu$\n",
Bo Yang5db21732015-05-21 14:28:59 -0700893 "dependency", StripProto(name),
Bo Yang1f0286a2015-12-04 13:18:44 -0800894 "iwyu", (public_import) ? " // IWYU pragma: export" : "",
Jisi Liu3b3c8ab2016-03-30 11:39:59 -0700895 "left", use_system_include ? "<" : "\"",
896 "right", use_system_include ? ">" : "\"");
Bo Yang5db21732015-05-21 14:28:59 -0700897 }
898}
899
900void FileGenerator::GenerateGlobalStateFunctionDeclarations(
901 io::Printer* printer) {
902 // Forward-declare the AddDescriptors, AssignDescriptors, and ShutdownFile
903 // functions, so that we can declare them to be friends of each class.
904 printer->Print(
905 "\n"
906 "// Internal implementation detail -- do not call these.\n"
907 "void $dllexport_decl$$adddescriptorsname$();\n",
908 "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
909 "dllexport_decl",
910 options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " ");
911
912 printer->Print(
913 // Note that we don't put dllexport_decl on these because they are only
914 // called by the .pb.cc file in which they are defined.
915 "void $assigndescriptorsname$();\n"
916 "void $shutdownfilename$();\n"
917 "\n",
918 "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()),
919 "shutdownfilename", GlobalShutdownFileName(file_->name()));
920}
921
922void FileGenerator::GenerateMessageForwardDeclarations(io::Printer* printer) {
Jisi Liu3b3c8ab2016-03-30 11:39:59 -0700923 map<string, const Descriptor*> classes;
Bo Yang5db21732015-05-21 14:28:59 -0700924 for (int i = 0; i < file_->message_type_count(); i++) {
Feng Xiaoeee38b02015-08-22 18:25:48 -0700925 message_generators_[i]->FillMessageForwardDeclarations(&classes);
926 }
Jisi Liu3b3c8ab2016-03-30 11:39:59 -0700927 for (map<string, const Descriptor *>::const_iterator it = classes.begin(),
928 end = classes.end();
Feng Xiaoeee38b02015-08-22 18:25:48 -0700929 it != end; ++it) {
Jisi Liu3b3c8ab2016-03-30 11:39:59 -0700930 printer->Print("class $classname$;\n", "classname", it->first);
931 printer->Annotate("classname", it->second);
Bo Yang5db21732015-05-21 14:28:59 -0700932 }
933}
934
935void FileGenerator::GenerateMessageDefinitions(io::Printer* printer) {
936 // Generate class definitions.
937 for (int i = 0; i < file_->message_type_count(); i++) {
938 if (i > 0) {
939 printer->Print("\n");
940 printer->Print(kThinSeparator);
941 printer->Print("\n");
942 }
943 message_generators_[i]->GenerateClassDefinition(printer);
944 }
945}
946
947void FileGenerator::GenerateEnumDefinitions(io::Printer* printer) {
948 // Generate enum definitions.
949 for (int i = 0; i < file_->message_type_count(); i++) {
950 message_generators_[i]->GenerateEnumDefinitions(printer);
951 }
952 for (int i = 0; i < file_->enum_type_count(); i++) {
953 enum_generators_[i]->GenerateDefinition(printer);
954 }
955}
956
957void FileGenerator::GenerateServiceDefinitions(io::Printer* printer) {
958 if (HasGenericServices(file_)) {
959 // Generate service definitions.
960 for (int i = 0; i < file_->service_count(); i++) {
961 if (i > 0) {
962 printer->Print("\n");
963 printer->Print(kThinSeparator);
964 printer->Print("\n");
965 }
966 service_generators_[i]->GenerateDeclarations(printer);
967 }
968
969 printer->Print("\n");
970 printer->Print(kThickSeparator);
971 printer->Print("\n");
972 }
973}
974
975void FileGenerator::GenerateExtensionIdentifiers(io::Printer* printer) {
976 // Declare extension identifiers.
977 for (int i = 0; i < file_->extension_count(); i++) {
978 extension_generators_[i]->GenerateDeclaration(printer);
979 }
980}
981
982void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* printer) {
983 // An aside about inline functions in .proto.h mode:
984 //
985 // The PROTOBUF_INLINE_NOT_IN_HEADERS symbol controls conditionally
986 // moving much of the inline functions to the .pb.cc file, which can be a
987 // significant performance benefit for compilation time, at the expense
988 // of non-inline function calls.
989 //
990 // However, in .proto.h mode, the definition of the internal dependent
991 // base class must remain in the header, and can never be out-lined. The
992 // dependent base class also needs access to has-bit manipuation
993 // functions, so the has-bit functions must be unconditionally inlined in
994 // proto_h mode.
995 //
996 // This gives us three flavors of functions:
997 //
998 // 1. Functions on the message not used by the internal dependent base
999 // class: in .proto.h mode, only some functions are defined on the
1000 // message class; others are defined on the dependent base class.
1001 // These are guarded and can be out-lined. These are generated by
1002 // GenerateInlineMethods, and include has_* bit functions in
1003 // non-proto_h mode.
1004 //
1005 // 2. Functions on the internal dependent base class: these functions
1006 // are dependent on a template parameter, so they always need to
1007 // remain in the header.
1008 //
1009 // 3. Functions on the message that are used by the dependent base: the
1010 // dependent base class down casts itself to the message
1011 // implementation class to access these functions (the has_* bit
1012 // manipulation functions). Unlike #1, these functions must
1013 // unconditionally remain in the header. These are emitted by
1014 // GenerateDependentInlineMethods, even though they are not actually
1015 // dependent.
1016
1017 printer->Print("#if !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
1018 // Generate class inline methods.
1019 for (int i = 0; i < file_->message_type_count(); i++) {
1020 if (i > 0) {
1021 printer->Print(kThinSeparator);
1022 printer->Print("\n");
1023 }
1024 message_generators_[i]->GenerateInlineMethods(printer,
1025 /* is_inline = */ true);
1026 }
1027 printer->Print("#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
1028
1029 for (int i = 0; i < file_->message_type_count(); i++) {
1030 if (i > 0) {
1031 printer->Print(kThinSeparator);
1032 printer->Print("\n");
1033 }
1034 // Methods of the dependent base class must always be inline in the header.
1035 message_generators_[i]->GenerateDependentInlineMethods(printer);
1036 }
Bo Yang5db21732015-05-21 14:28:59 -07001037}
1038
1039void FileGenerator::GenerateProto2NamespaceEnumSpecializations(
1040 io::Printer* printer) {
1041 // Emit GetEnumDescriptor specializations into google::protobuf namespace:
1042 if (HasEnumDefinitions(file_)) {
1043 // The SWIG conditional is to avoid a null-pointer dereference
1044 // (bug 1984964) in swig-1.3.21 resulting from the following syntax:
1045 // namespace X { void Y<Z::W>(); }
1046 // which appears in GetEnumDescriptor() specializations.
1047 printer->Print(
1048 "\n"
1049 "#ifndef SWIG\n"
1050 "namespace google {\nnamespace protobuf {\n"
1051 "\n");
1052 for (int i = 0; i < file_->message_type_count(); i++) {
1053 message_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
1054 }
1055 for (int i = 0; i < file_->enum_type_count(); i++) {
1056 enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
1057 }
1058 printer->Print(
1059 "\n"
1060 "} // namespace protobuf\n} // namespace google\n"
1061 "#endif // SWIG\n");
1062 }
1063}
1064
temporal40ee5512008-07-10 02:12:20 +00001065} // namespace cpp
1066} // namespace compiler
1067} // namespace protobuf
1068} // namespace google