1b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Protocol Buffers - Google's data interchange format 2b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Copyright 2008 Google Inc. All rights reserved. 3b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// https://developers.google.com/protocol-buffers/ 4b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// 5b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Redistribution and use in source and binary forms, with or without 6b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// modification, are permitted provided that the following conditions are 7b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// met: 8b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// 9b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// * Redistributions of source code must retain the above copyright 10b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// notice, this list of conditions and the following disclaimer. 11b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// * Redistributions in binary form must reproduce the above 12b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// copyright notice, this list of conditions and the following disclaimer 13b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// in the documentation and/or other materials provided with the 14b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// distribution. 15b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// * Neither the name of Google Inc. nor the names of its 16b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// contributors may be used to endorse or promote products derived from 17b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// this software without specific prior written permission. 18b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// 19b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 31b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <sstream> 32b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 33b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <google/protobuf/compiler/code_generator.h> 34b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <google/protobuf/compiler/plugin.h> 35b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <google/protobuf/descriptor.h> 36b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <google/protobuf/descriptor.pb.h> 37b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <google/protobuf/io/printer.h> 38b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <google/protobuf/io/zero_copy_stream.h> 39b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <google/protobuf/stubs/strutil.h> 40b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 41b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 42b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <google/protobuf/compiler/csharp/csharp_enum.h> 43b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <google/protobuf/compiler/csharp/csharp_helpers.h> 44b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <google/protobuf/compiler/csharp/csharp_message.h> 45b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <google/protobuf/compiler/csharp/csharp_names.h> 46b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <google/protobuf/compiler/csharp/csharp_options.h> 47b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <google/protobuf/compiler/csharp/csharp_reflection_class.h> 48b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 49b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammernamespace google { 50b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammernamespace protobuf { 51b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammernamespace compiler { 52b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammernamespace csharp { 53b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 54b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerReflectionClassGenerator::ReflectionClassGenerator(const FileDescriptor* file, 55b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer const Options* options) 56b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer : SourceGeneratorBase(file, options), 57b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer file_(file) { 58b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer namespace_ = GetFileNamespace(file); 59b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer reflectionClassname_ = GetReflectionClassUnqualifiedName(file); 60b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} 61b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 62b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerReflectionClassGenerator::~ReflectionClassGenerator() { 63b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} 64b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 65b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid ReflectionClassGenerator::Generate(io::Printer* printer) { 66b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer WriteIntroduction(printer); 67b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 68b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer WriteDescriptor(printer); 69b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Close the class declaration. 70b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Outdent(); 71b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("}\n"); 72b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 73b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // write children: Enums 74b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (file_->enum_type_count() > 0) { 75b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("#region Enums\n"); 76b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer for (int i = 0; i < file_->enum_type_count(); i++) { 77b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer EnumGenerator enumGenerator(file_->enum_type(i), this->options()); 78b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer enumGenerator.Generate(printer); 79b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 80b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("#endregion\n"); 81b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("\n"); 82b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 83b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 84b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // write children: Messages 85b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (file_->message_type_count() > 0) { 86b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("#region Messages\n"); 87b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer for (int i = 0; i < file_->message_type_count(); i++) { 88b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer MessageGenerator messageGenerator(file_->message_type(i), this->options()); 89b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer messageGenerator.Generate(printer); 90b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 91b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("#endregion\n"); 92b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("\n"); 93b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 94b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 95b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // TODO(jtattermusch): add insertion point for services. 96b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 97b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (!namespace_.empty()) { 98b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Outdent(); 99b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("}\n"); 100b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 101b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("\n"); 102b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("#endregion Designer generated code\n"); 103b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} 104b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 105b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid ReflectionClassGenerator::WriteIntroduction(io::Printer* printer) { 106b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print( 107b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" 108b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "// source: $file_name$\n" 109b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "#pragma warning disable 1591, 0612, 3021\n" 110b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "#region Designer generated code\n" 111b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "\n" 112b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "using pb = global::Google.Protobuf;\n" 113b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "using pbc = global::Google.Protobuf.Collections;\n" 114b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "using pbr = global::Google.Protobuf.Reflection;\n" 115b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "using scg = global::System.Collections.Generic;\n", 116b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "file_name", file_->name()); 117b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 118b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (!namespace_.empty()) { 119b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("namespace $namespace$ {\n", "namespace", namespace_); 120b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Indent(); 121b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("\n"); 122b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 123b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 124b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print( 125b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "/// <summary>Holder for reflection information generated from $file_name$</summary>\n" 126b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n", 127b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "file_name", file_->name()); 128b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer WriteGeneratedCodeAttributes(printer); 129b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print( 130b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "$access_level$ static partial class $reflection_class_name$ {\n" 131b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "\n", 132b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "access_level", class_access_level(), 133b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "reflection_class_name", reflectionClassname_); 134b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Indent(); 135b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} 136b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 137b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid ReflectionClassGenerator::WriteDescriptor(io::Printer* printer) { 138b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print( 139b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "#region Descriptor\n" 140b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "/// <summary>File descriptor for $file_name$</summary>\n" 141b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "public static pbr::FileDescriptor Descriptor {\n" 142b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer " get { return descriptor; }\n" 143b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "}\n" 144b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "private static pbr::FileDescriptor descriptor;\n" 145b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "\n" 146b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "static $reflection_class_name$() {\n", 147b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "file_name", file_->name(), 148b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "reflection_class_name", reflectionClassname_); 149b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Indent(); 150b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print( 151b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "byte[] descriptorData = global::System.Convert.FromBase64String(\n"); 152b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Indent(); 153b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Indent(); 154b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("string.Concat(\n"); 155b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Indent(); 156b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 157b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // TODO(jonskeet): Consider a C#-escaping format here instead of just Base64. 158b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer std::string base64 = FileDescriptorToBase64(file_); 159b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer while (base64.size() > 60) { 160b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("\"$base64$\",\n", "base64", base64.substr(0, 60)); 161b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer base64 = base64.substr(60); 162b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 163b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("\"$base64$\"));\n", "base64", base64); 164b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Outdent(); 165b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Outdent(); 166b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Outdent(); 167b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 168b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // ----------------------------------------------------------------- 169b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Invoke InternalBuildGeneratedFileFrom() to build the file. 170b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print( 171b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,\n"); 172b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print(" new pbr::FileDescriptor[] { "); 173b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer for (int i = 0; i < file_->dependency_count(); i++) { 174b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // descriptor.proto is special: we don't allow access to the generated code, but there's 175b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // a separately-exposed property to get at the file descriptor, specifically to allow this 176b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // kind of dependency. 177b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (IsDescriptorProto(file_->dependency(i))) { 178b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("pbr::FileDescriptor.DescriptorProtoFileDescriptor, "); 179b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 180b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print( 181b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "$full_reflection_class_name$.Descriptor, ", 182b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "full_reflection_class_name", 183b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer GetReflectionClassName(file_->dependency(i))); 184b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 185b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 186b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("},\n" 187b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer " new pbr::GeneratedClrTypeInfo("); 188b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Specify all the generated code information, recursively. 189b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (file_->enum_type_count() > 0) { 190b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("new[] {"); 191b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer for (int i = 0; i < file_->enum_type_count(); i++) { 192b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("typeof($type_name$), ", "type_name", GetClassName(file_->enum_type(i))); 193b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 194b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("}, "); 195b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 196b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer else { 197b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("null, "); 198b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 199b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (file_->message_type_count() > 0) { 200b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("new pbr::GeneratedClrTypeInfo[] {\n"); 201b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Indent(); 202b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Indent(); 203b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Indent(); 204b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer for (int i = 0; i < file_->message_type_count(); i++) { 205b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer WriteGeneratedCodeInfo(file_->message_type(i), printer, i == file_->message_type_count() - 1); 206b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 207b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Outdent(); 208b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("\n}));\n"); 209b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Outdent(); 210b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Outdent(); 211b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 212b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer else { 213b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("null));\n"); 214b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 215b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 216b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Outdent(); 217b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("}\n"); 218b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("#endregion\n\n"); 219b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} 220b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 221b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Write out the generated code for a particular message. This consists of the CLR type, property names 222b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// corresponding to fields, names corresponding to oneofs, nested enums, and nested types. Each array part 223b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// can be specified as null if it would be empty, to make the generated code somewhat simpler to read. 224b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// We write a line break at the end of each generated code info, so that in the final file we'll see all 225b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// the types, pre-ordered depth first, one per line. The indentation will be slightly unusual, 226b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// in that it will look like a single array when it's actually constructing a tree, but it'll be easy to 227b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// read even with multiple levels of nesting. 228b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// The "last" parameter indicates whether this message descriptor is the last one being printed in this immediate 229b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// context. It governs whether or not a trailing comma and newline is written after the constructor, effectively 230b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// just controlling the formatting in the generated code. 231b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid ReflectionClassGenerator::WriteGeneratedCodeInfo(const Descriptor* descriptor, io::Printer* printer, bool last) { 232b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (IsMapEntryMessage(descriptor)) { 233b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("null, "); 234b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return; 235b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 236b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Generated message type 237b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("new pbr::GeneratedClrTypeInfo(typeof($type_name$), $type_name$.Parser, ", "type_name", GetClassName(descriptor)); 238b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 239b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Fields 240b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (descriptor->field_count() > 0) { 241b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer std::vector<std::string> fields; 242b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer for (int i = 0; i < descriptor->field_count(); i++) { 243b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer fields.push_back(GetPropertyName(descriptor->field(i))); 244b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 245b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("new[]{ \"$fields$\" }, ", "fields", JoinStrings(fields, "\", \"")); 246b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 247b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer else { 248b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("null, "); 249b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 250b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 251b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Oneofs 252b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (descriptor->oneof_decl_count() > 0) { 253b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer std::vector<std::string> oneofs; 254b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer for (int i = 0; i < descriptor->oneof_decl_count(); i++) { 255b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer oneofs.push_back(UnderscoresToCamelCase(descriptor->oneof_decl(i)->name(), true)); 256b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 257b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("new[]{ \"$oneofs$\" }, ", "oneofs", JoinStrings(oneofs, "\", \"")); 258b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 259b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer else { 260b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("null, "); 261b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 262b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 263b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Nested enums 264b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (descriptor->enum_type_count() > 0) { 265b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer std::vector<std::string> enums; 266b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer for (int i = 0; i < descriptor->enum_type_count(); i++) { 267b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer enums.push_back(GetClassName(descriptor->enum_type(i))); 268b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 269b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("new[]{ typeof($enums$) }, ", "enums", JoinStrings(enums, "), typeof(")); 270b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 271b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer else { 272b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("null, "); 273b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 274b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 275b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Nested types 276b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (descriptor->nested_type_count() > 0) { 277b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Need to specify array type explicitly here, as all elements may be null. 278b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("new pbr::GeneratedClrTypeInfo[] { "); 279b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer for (int i = 0; i < descriptor->nested_type_count(); i++) { 280b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer WriteGeneratedCodeInfo(descriptor->nested_type(i), printer, i == descriptor->nested_type_count() - 1); 281b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 282b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("}"); 283b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 284b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer else { 285b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("null"); 286b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 287b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print(last ? ")" : "),\n"); 288b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} 289b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 290b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} // namespace csharp 291b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} // namespace compiler 292b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} // namespace protobuf 293b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} // namespace google 294