aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc')
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc286
1 files changed, 286 insertions, 0 deletions
diff --git a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc
new file mode 100644
index 00000000..358cfa4f
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc
@@ -0,0 +1,286 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <sstream>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+
+#include <google/protobuf/compiler/csharp/csharp_umbrella_class.h>
+#include <google/protobuf/compiler/csharp/csharp_enum.h>
+#include <google/protobuf/compiler/csharp/csharp_extension.h>
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_message.h>
+#include <google/protobuf/compiler/csharp/csharp_writer.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+UmbrellaClassGenerator::UmbrellaClassGenerator(const FileDescriptor* file)
+ : SourceGeneratorBase(file),
+ file_(file) {
+ namespace_ = GetFileNamespace(file);
+ umbrellaClassname_ = GetFileUmbrellaClassname(file);
+ umbrellaNamespace_ = GetFileUmbrellaNamespace(file);
+}
+
+UmbrellaClassGenerator::~UmbrellaClassGenerator() {
+}
+
+void UmbrellaClassGenerator::Generate(Writer* writer) {
+ WriteIntroduction(writer);
+ WriteExtensionRegistration(writer);
+
+ // write children: Extensions
+ if (file_->extension_count() > 0) {
+ writer->WriteLine("#region Extensions");
+ for (int i = 0; i < file_->extension_count(); i++) {
+ ExtensionGenerator extensionGenerator(file_->extension(i));
+ extensionGenerator.Generate(writer);
+ }
+ writer->WriteLine("#endregion");
+ writer->WriteLine();
+ }
+
+ writer->WriteLine("#region Static variables");
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ MessageGenerator messageGenerator(file_->message_type(i));
+ messageGenerator.GenerateStaticVariables(writer);
+ }
+ writer->WriteLine("#endregion");
+ if (!use_lite_runtime()) {
+ WriteDescriptor(writer);
+ } else {
+ WriteLiteExtensions(writer);
+ }
+ // Close the class declaration.
+ writer->Outdent();
+ writer->WriteLine("}");
+
+ // Close the namespace around the umbrella class if defined
+ if (!umbrellaNamespace_.empty()) {
+ writer->Outdent();
+ writer->WriteLine("}");
+ }
+
+ // write children: Enums
+ if (file_->enum_type_count() > 0) {
+ writer->WriteLine("#region Enums");
+ for (int i = 0; i < file_->enum_type_count(); i++) {
+ EnumGenerator enumGenerator(file_->enum_type(i));
+ enumGenerator.Generate(writer);
+ }
+ writer->WriteLine("#endregion");
+ writer->WriteLine();
+ }
+
+ // write children: Messages
+ if (file_->message_type_count() > 0) {
+ writer->WriteLine("#region Messages");
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ MessageGenerator messageGenerator(file_->message_type(i));
+ messageGenerator.Generate(writer);
+ }
+ writer->WriteLine("#endregion");
+ writer->WriteLine();
+ }
+
+ // TODO(jtattermusch): add insertion point for services.
+
+ if (!namespace_.empty()) {
+ writer->Outdent();
+ writer->WriteLine("}");
+ }
+ writer->WriteLine();
+ writer->WriteLine("#endregion Designer generated code");
+}
+
+void UmbrellaClassGenerator::WriteIntroduction(Writer* writer) {
+ writer->WriteLine(
+ "// Generated by the protocol buffer compiler. DO NOT EDIT!");
+ writer->WriteLine("// source: $0$", file_->name());
+ writer->WriteLine("#pragma warning disable 1591, 0612, 3021");
+ writer->WriteLine("#region Designer generated code");
+
+ writer->WriteLine();
+ writer->WriteLine("using pb = global::Google.ProtocolBuffers;");
+ writer->WriteLine("using pbc = global::Google.ProtocolBuffers.Collections;");
+ writer->WriteLine("using pbd = global::Google.ProtocolBuffers.Descriptors;");
+ writer->WriteLine("using scg = global::System.Collections.Generic;");
+
+ if (!namespace_.empty()) {
+ writer->WriteLine("namespace $0$ {", namespace_);
+ writer->Indent();
+ writer->WriteLine();
+ }
+
+ // Add the namespace around the umbrella class if defined
+ if (!umbrellaNamespace_.empty()) {
+ writer->WriteLine("namespace $0$ {", umbrellaNamespace_);
+ writer->Indent();
+ writer->WriteLine();
+ }
+
+ writer->WriteLine(
+ "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]");
+ WriteGeneratedCodeAttributes(writer);
+ writer->WriteLine("$0$ static partial class $1$ {", class_access_level(),
+ umbrellaClassname_);
+ writer->WriteLine();
+ writer->Indent();
+}
+
+void UmbrellaClassGenerator::WriteExtensionRegistration(Writer* writer) {
+ writer->WriteLine("#region Extension registration");
+ writer->WriteLine(
+ "public static void RegisterAllExtensions(pb::ExtensionRegistry registry) {");
+ writer->Indent();
+ for (int i = 0; i < file_->extension_count(); i++) {
+ ExtensionGenerator extensionGenerator(file_->extension(i));
+ extensionGenerator.GenerateExtensionRegistrationCode(writer);
+ }
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ MessageGenerator messageGenerator(file_->message_type(i));
+ messageGenerator.GenerateExtensionRegistrationCode(writer);
+ }
+ writer->Outdent();
+ writer->WriteLine("}");
+ writer->WriteLine("#endregion");
+}
+
+void UmbrellaClassGenerator::WriteDescriptor(Writer* writer) {
+ writer->WriteLine("#region Descriptor");
+
+ writer->WriteLine("public static pbd::FileDescriptor Descriptor {");
+ writer->WriteLine(" get { return descriptor; }");
+ writer->WriteLine("}");
+ writer->WriteLine("private static pbd::FileDescriptor descriptor;");
+ writer->WriteLine();
+ writer->WriteLine("static $0$() {", umbrellaClassname_);
+ writer->Indent();
+ writer->WriteLine(
+ "byte[] descriptorData = global::System.Convert.FromBase64String(");
+ writer->Indent();
+ writer->Indent();
+ writer->WriteLine("string.Concat(");
+ writer->Indent();
+
+ // TODO(jonskeet): Consider a C#-escaping format here instead of just Base64.
+ std::string base64 = FileDescriptorToBase64(file_);
+ while (base64.size() > 60) {
+ writer->WriteLine("\"$0$\", ", base64.substr(0, 60));
+ base64 = base64.substr(60);
+ }
+ writer->Outdent();
+ writer->WriteLine("\"$0$\"));", base64);
+ writer->Outdent();
+ writer->Outdent();
+ writer->WriteLine(
+ "pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {");
+ writer->Indent();
+ writer->WriteLine("descriptor = root;");
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ MessageGenerator messageGenerator(file_->message_type(i));
+ messageGenerator.GenerateStaticVariableInitializers(writer);
+ }
+ for (int i = 0; i < file_->extension_count(); i++) {
+ ExtensionGenerator extensionGenerator(file_->extension(i));
+ extensionGenerator.GenerateStaticVariableInitializers(writer);
+ }
+
+ if (uses_extensions()) {
+ // Must construct an ExtensionRegistry containing all possible extensions
+ // and return it.
+ writer->WriteLine(
+ "pb::ExtensionRegistry registry = pb::ExtensionRegistry.CreateInstance();");
+ writer->WriteLine("RegisterAllExtensions(registry);");
+ for (int i = 0; i < file_->dependency_count(); i++) {
+ writer->WriteLine("$0$.RegisterAllExtensions(registry);",
+ GetFullUmbrellaClassName(file_->dependency(i)));
+ }
+ writer->WriteLine("return registry;");
+ } else {
+ writer->WriteLine("return null;");
+ }
+ writer->Outdent();
+ writer->WriteLine("};");
+
+ // -----------------------------------------------------------------
+ // Invoke internalBuildGeneratedFileFrom() to build the file.
+ writer->WriteLine(
+ "pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,");
+ writer->WriteLine(" new pbd::FileDescriptor[] {");
+ for (int i = 0; i < file_->dependency_count(); i++) {
+ writer->WriteLine(" $0$.Descriptor, ",
+ GetFullUmbrellaClassName(file_->dependency(i)));
+ }
+ writer->WriteLine(" }, assigner);");
+ writer->Outdent();
+ writer->WriteLine("}");
+ writer->WriteLine("#endregion");
+ writer->WriteLine();
+}
+
+void UmbrellaClassGenerator::WriteLiteExtensions(Writer* writer) {
+ writer->WriteLine("#region Extensions");
+ writer->WriteLine("internal static readonly object Descriptor;");
+ writer->WriteLine("static $0$() {", umbrellaClassname_);
+ writer->Indent();
+ writer->WriteLine("Descriptor = null;");
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ MessageGenerator messageGenerator(file_->message_type(i));
+ messageGenerator.GenerateStaticVariableInitializers(writer);
+ }
+ for (int i = 0; i < file_->extension_count(); i++) {
+ ExtensionGenerator extensionGenerator(file_->extension(i));
+ extensionGenerator.GenerateStaticVariableInitializers(writer);
+ }
+ writer->Outdent();
+ writer->WriteLine("}");
+ writer->WriteLine("#endregion");
+ writer->WriteLine();
+}
+
+bool UmbrellaClassGenerator::uses_extensions() {
+ // TODO(jtattermusch): implement recursive descent that looks for extensions.
+ // For now, we conservatively assume that extensions are used.
+ return true;
+}
+
+} // namespace csharp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google