class Protobuf::Generators::FileGenerator
Attributes
output_file[R]
Public Class Methods
new(*args)
click to toggle source
Calls superclass method
Protobuf::Generators::Base::new
# File lib/protobuf/generators/file_generator.rb, line 11 def initialize(*args) super @output_file = ::Google::Protobuf::Compiler::CodeGeneratorResponse::File.new(:name => file_name) @extension_fields = Hash.new { |h, k| h[k] = [] } @known_messages = {} @known_enums = {} @dangling_messages = {} end
Public Instance Methods
compile()
click to toggle source
# File lib/protobuf/generators/file_generator.rb, line 24 def compile run_once(:compile) do map_extensions(descriptor, [descriptor.package]) print_file_comment print_generic_requires print_import_requires print_package do inject_optionable group = GroupGenerator.new(current_indent) group.add_options(descriptor.options) if descriptor.options group.add_enums(descriptor.enum_type, :namespace => [descriptor.package]) group.add_message_declarations(descriptor.message_type) group.add_messages(descriptor.message_type, :extension_fields => @extension_fields, :namespace => [descriptor.package]) group.add_extended_messages(unknown_extensions) group.add_services(descriptor.service) group.add_header(:enum, 'Enum Classes') group.add_header(:message_declaration, 'Message Classes') group.add_header(:options, 'File Options') group.add_header(:message, 'Message Fields') group.add_header(:extended_message, 'Extended Message Fields') group.add_header(:service, 'Service Classes') print group.to_s end end end
eval_unknown_extensions!()
click to toggle source
# File lib/protobuf/generators/file_generator.rb, line 144 def eval_unknown_extensions! @@evaled_dependencies ||= Set.new # rubocop:disable Style/ClassVars @@all_messages ||= {} # rubocop:disable Style/ClassVars @@all_enums ||= {} # rubocop:disable Style/ClassVars map_extensions(descriptor, [descriptor.package]) @known_messages.each do |name, descriptor| @@all_messages[name] = descriptor end @known_enums.each do |name, descriptor| @@all_enums[name] = descriptor end # create package namespace print_package {} eval_code unknown_extensions.each do |extendee, fields| eval_dependencies(extendee) fields.each do |field| eval_dependencies(field.type_name) end end group = GroupGenerator.new(0) group.add_extended_messages(unknown_extensions, false) print group.to_s eval_code rescue => e warn "Error loading unknown extensions #{descriptor.name.inspect} error=#{e}" raise e end
file_name()
click to toggle source
# File lib/protobuf/generators/file_generator.rb, line 20 def file_name convert_filename(descriptor.name, false) end
generate_output_file()
click to toggle source
# File lib/protobuf/generators/file_generator.rb, line 68 def generate_output_file compile output_file.content = to_s output_file end
map_extensions(descriptor, namespaces)
click to toggle source
Recursively map out all extensions known in this file. The key is the type_name of the message being extended, and the value is an array of field descriptors.
# File lib/protobuf/generators/file_generator.rb, line 78 def map_extensions(descriptor, namespaces) if fully_qualified_token?(descriptor.name) fully_qualified_namespace = descriptor.name elsif !(namespace = namespaces.reject(&:empty?).join(".")).empty? fully_qualified_namespace = ".#{namespace}" end # Record all the message descriptor name's we encounter (should be the whole tree). if descriptor.is_a?(::Google::Protobuf::DescriptorProto) @known_messages[fully_qualified_namespace || descriptor.name] = descriptor elsif descriptor.is_a?(::Google::Protobuf::EnumDescriptorProto) @known_enums[fully_qualified_namespace || descriptor.name] = descriptor return end descriptor.extension.each do |field_descriptor| unless fully_qualified_token?(field_descriptor.name) && fully_qualified_namespace field_descriptor.name = "#{fully_qualified_namespace}.#{field_descriptor.name}" end @extension_fields[field_descriptor.extendee] << field_descriptor end [:message_type, :nested_type, :enum_type].each do |type| next unless descriptor.respond_to_has_and_present?(type) descriptor.public_send(type).each do |type_descriptor| map_extensions(type_descriptor, (namespaces + [type_descriptor.name])) end end end
print_file_comment()
click to toggle source
# File lib/protobuf/generators/file_generator.rb, line 108 def print_file_comment puts "# encoding: utf-8" puts puts "##" puts "# This file is auto-generated. DO NOT EDIT!" puts "#" end
print_generic_requires()
click to toggle source
# File lib/protobuf/generators/file_generator.rb, line 116 def print_generic_requires print_require("protobuf") print_require("protobuf/rpc/service") if descriptor.service.count > 0 puts end
print_import_requires()
click to toggle source
# File lib/protobuf/generators/file_generator.rb, line 122 def print_import_requires return if descriptor.dependency.empty? header "Imports" descriptor.dependency.each do |dependency| print_require(convert_filename(dependency)) end puts end
print_package(&block)
click to toggle source
# File lib/protobuf/generators/file_generator.rb, line 134 def print_package(&block) namespaces = descriptor.package.split('.') if namespaces.empty? && ENV.key?('PB_ALLOW_DEFAULT_PACKAGE_NAME') namespaces = [File.basename(descriptor.name).sub('.proto', '')] end namespaces.reverse.reduce(block) do |previous, namespace| -> { print_module(namespace, &previous) } end.call end
unknown_extensions()
click to toggle source
# File lib/protobuf/generators/file_generator.rb, line 54 def unknown_extensions @unknown_extensions ||= @extension_fields.map do |message_name, fields| message_klass = modulize(message_name).safe_constantize if message_klass unknown_fields = fields.reject do |field| @known_messages[message_name] && message_klass.get_field(field.name, true) end [message_name, unknown_fields] else [message_name, fields] end end end
Private Instance Methods
convert_filename(filename, for_require = true)
click to toggle source
# File lib/protobuf/generators/file_generator.rb, line 178 def convert_filename(filename, for_require = true) filename.sub(/\.proto/, (for_require ? '.pb' : '.pb.rb')) end
create_ruby_namespace_heiarchy(namespace)
click to toggle source
# File lib/protobuf/generators/file_generator.rb, line 248 def create_ruby_namespace_heiarchy(namespace) loop do namespace, _match, _tail = namespace.rpartition(".") break if namespace.empty? eval_dependencies(namespace) end end
eval_code(context = Object)
click to toggle source
# File lib/protobuf/generators/file_generator.rb, line 241 def eval_code(context = Object) warn "#{context.inspect}.module_eval #{print_contents.inspect}" if ENV['PB_DEBUG'] context.module_eval print_contents.to_s @io.truncate(0) @io.rewind end
eval_dependencies(name, namespace = nil)
click to toggle source
# File lib/protobuf/generators/file_generator.rb, line 186 def eval_dependencies(name, namespace = nil) name = "#{namespace}.#{name}" if namespace && !fully_qualified_token?(name) return if name.empty? || @@evaled_dependencies.include?(name) || modulize(name).safe_constantize # if name = .foo.bar.Baz look for classes / modules named ::Foo::Bar and ::Foo # module == pure namespace (e.g. the descriptor package name) # class == nested messages create_ruby_namespace_heiarchy(name) if (message = @@all_messages[name]) # Create the blank namespace in case there are nested types eval_message_code(name) message.nested_type.each do |nested_type| eval_dependencies(nested_type.name, name) unless nested_type.name.empty? end message.field.each do |field| eval_dependencies(field.type_name, name) unless field.type_name.empty? end message.enum_type.each do |enum_type| eval_dependencies(enum_type.name, name) end # Check @@evaled_dependencies again in case there was a dependency # loop that already loaded this message return if @@evaled_dependencies.include?(name) eval_message_code(name, message.field) @@evaled_dependencies << name elsif (enum = @@all_enums[name]) # Check @@evaled_dependencies again in case there was a dependency # loop that already loaded this enum return if @@evaled_dependencies.include?(name) namespace = name.split(".") eval_enum_code(enum, namespace[0..-2].join(".")) @@evaled_dependencies << name else fail "Error loading unknown dependencies, could not find message or enum #{name.inspect}" end end
eval_enum_code(enum, fully_qualified_namespace)
click to toggle source
# File lib/protobuf/generators/file_generator.rb, line 234 def eval_enum_code(enum, fully_qualified_namespace) group = GroupGenerator.new(0) group.add_enums([enum], :namespace => [fully_qualified_namespace]) print group.to_s eval_code(modulize(fully_qualified_namespace).safe_constantize || Object) end
eval_message_code(fully_qualified_namespace, fields = [])
click to toggle source
# File lib/protobuf/generators/file_generator.rb, line 227 def eval_message_code(fully_qualified_namespace, fields = []) group = GroupGenerator.new(0) group.add_extended_messages({ fully_qualified_namespace => fields }, false) print group.to_s eval_code end
fully_qualified_token?(token)
click to toggle source
# File lib/protobuf/generators/file_generator.rb, line 182 def fully_qualified_token?(token) token[0] == '.' end
inject_optionable()
click to toggle source
# File lib/protobuf/generators/file_generator.rb, line 256 def inject_optionable return if descriptor.package.empty? && !ENV.key?('PB_ALLOW_DEFAULT_PACKAGE_NAME') puts "::Protobuf::Optionable.inject(self) { ::Google::Protobuf::FileOptions }" end