class RBSProtobuf::Translator::ProtobufGem
Public Class Methods
new(input, upcase_enum:, nested_namespace:)
click to toggle source
Calls superclass method
RBSProtobuf::Translator::Base::new
# File lib/rbs_protobuf/translator/protobuf_gem.rb, line 4 def initialize(input, upcase_enum:, nested_namespace:) super(input) @upcase_enum = upcase_enum @nested_namespace = nested_namespace end
Public Instance Methods
enum_base_class()
click to toggle source
# File lib/rbs_protobuf/translator/protobuf_gem.rb, line 362 def enum_base_class RBS::AST::Declarations::Class::Super.new( name: factory.type_name("::Protobuf::Enum"), args: [], location: nil ) end
enum_name(name)
click to toggle source
# File lib/rbs_protobuf/translator/protobuf_gem.rb, line 370 def enum_name(name) if upcase_enum? name.upcase.to_sym else name.to_sym end end
enum_type_to_decl(enum_type, prefix:, source_code_info:, path:)
click to toggle source
# File lib/rbs_protobuf/translator/protobuf_gem.rb, line 378 def enum_type_to_decl(enum_type, prefix:, source_code_info:, path:) enum_name = ActiveSupport::Inflector.upcase_first(enum_type.name) RBS::AST::Declarations::Class.new( name: RBS::TypeName.new(name: enum_name.to_sym, namespace: prefix), super_class: enum_base_class(), type_params: factory.module_type_params(), members: [], comment: comment_for_path(source_code_info, path), location: nil, annotations: [] ).tap do |enum_decl| names = enum_type.value.map do |v| factory.literal_type(enum_name(v.name)) end strings = enum_type.value.map do |v| factory.literal_type(enum_name(v.name).to_s) end tags = enum_type.value.map do |v| factory.literal_type(v.number) end.uniq enum_decl.members << RBS::AST::Declarations::Alias.new( name: factory.type_name("names"), type: factory.union_type(*names), location: nil, comment: nil, annotations: [] ) enum_decl.members << RBS::AST::Declarations::Alias.new( name: factory.type_name("strings"), type: factory.union_type(*strings), location: nil, comment: nil, annotations: [] ) enum_decl.members << RBS::AST::Declarations::Alias.new( name: factory.type_name("tags"), type: factory.union_type(*tags), location: nil, comment: nil, annotations: [] ) enum_decl.members << RBS::AST::Declarations::Alias.new( name: factory.type_name("values"), type: factory.union_type( factory.alias_type("names"), factory.alias_type("strings"), factory.alias_type("tags") ), location: nil, comment: nil, annotations: [] ) enum_decl.members << RBS::AST::Members::AttrReader.new( name: :name, type: factory.alias_type("names"), ivar_name: false, annotations: [], comment: nil, location: nil, kind: :instance ) enum_decl.members << RBS::AST::Members::AttrReader.new( name: :tag, type: factory.alias_type("tags"), ivar_name: false, annotations: [], comment: nil, location: nil, kind: :instance ) enum_type.value.each.with_index do |v, index| comment = comment_for_path(source_code_info, path + [2, index]) enum_decl.members << RBS::AST::Declarations::Constant.new( name: factory.type_name(enum_name(v.name).to_s), type: RBS::TypeName.new(name: enum_name.to_sym, namespace: prefix), comment: comment, location: nil ) end end end
extension_to_decl(extendee_name, extensions, prefix:, source_code_info:, path:)
click to toggle source
# File lib/rbs_protobuf/translator/protobuf_gem.rb, line 471 def extension_to_decl(extendee_name, extensions, prefix:, source_code_info:, path:) class_name = message_type(extendee_name).name extensions.map do |field| field_name = field.name.to_sym RBS::AST::Declarations::Class.new( name: class_name, super_class: nil, type_params: RBS::AST::Declarations::ModuleTypeParams.empty, location: nil, comment: nil, members: [], annotations: [] ).tap do |class_decl| read_type, write_type = field_type(field, {}) if read_type == write_type class_decl.members << RBS::AST::Members::AttrAccessor.new( name: field_name, type: read_type, comment: nil, location: nil, annotations: [], ivar_name: false, kind: :instance ) else class_decl.members << RBS::AST::Members::AttrReader.new( name: field_name, type: read_type, comment: nil, location: nil, annotations: [], ivar_name: false, kind: :instance ) class_decl.members << RBS::AST::Members::AttrWriter.new( name: field_name, type: write_type, comment: nil, location: nil, annotations: [], ivar_name: false, kind: :instance ) end class_decl.members << RBS::AST::Members::MethodDefinition.new( name: :[], types: [ factory.method_type( type: factory.function(read_type).update( required_positionals: [ factory.param(factory.literal_type(field_name)) ] ) ) ], annotations: [], comment: nil, location: nil, overload: true, kind: :instance ) class_decl.members << RBS::AST::Members::MethodDefinition.new( name: :[]=, types: [ factory.method_type( type: factory.function(write_type).update( required_positionals: [ factory.param(factory.literal_type(field_name)), factory.param(write_type) ] ) ) ], annotations: [], comment: nil, location: nil, overload: true, kind: :instance ) end end end
field_type(field, maps)
click to toggle source
# File lib/rbs_protobuf/translator/protobuf_gem.rb, line 294 def field_type(field, maps) case when field.type == FieldDescriptorProto::Type::TYPE_MESSAGE if maps.key?(field.type_name) key_field, value_field = maps[field.type_name] key_type_r, _ = field_type(key_field, maps) value_type_r, value_type_w = field_type(value_field, maps) hash_type = factory.instance_type( factory.type_name("::Protobuf::Field::FieldHash"), key_type_r, factory.unwrap_optional(value_type_r), factory.unwrap_optional(value_type_w) ) [ hash_type, hash_type ] else type = message_type(field.type_name) case field.label when FieldDescriptorProto::Label::LABEL_OPTIONAL type = factory.optional_type(type) [type, type] when FieldDescriptorProto::Label::LABEL_REPEATED type = repeated_field_type(type) [type, type] else [type, factory.optional_type(type)] end end when field.type == FieldDescriptorProto::Type::TYPE_ENUM type = message_type(field.type_name) enum_namespace = type.name.to_namespace wtype = factory.union_type( type, factory.alias_type(RBS::TypeName.new(name: :values, namespace: enum_namespace)) ) if field.label == FieldDescriptorProto::Label::LABEL_REPEATED type = repeated_field_type(type, wtype) [ type, type ] else [ type, factory.optional_type(wtype) ] end else type = base_type(field.type) if field.label == FieldDescriptorProto::Label::LABEL_REPEATED type = repeated_field_type(type) [type, type] else [type, factory.optional_type(type)] end end end
message_base_class()
click to toggle source
# File lib/rbs_protobuf/translator/protobuf_gem.rb, line 90 def message_base_class RBS::AST::Declarations::Class::Super.new( name: RBS::TypeName.new( name: :Message, namespace: RBS::Namespace.parse("::Protobuf") ), args: [], location: nil ) end
message_to_decl(message, prefix:, message_path:, source_code_info:, path:)
click to toggle source
# File lib/rbs_protobuf/translator/protobuf_gem.rb, line 109 def message_to_decl(message, prefix:, message_path:, source_code_info:, path:) class_name = ActiveSupport::Inflector.upcase_first(message.name) decl_namespace = prefix.append(class_name.to_sym) RBS::AST::Declarations::Class.new( name: RBS::TypeName.new(name: class_name.to_sym, namespace: prefix), super_class: message_base_class, type_params: RBS::AST::Declarations::ModuleTypeParams.empty, location: nil, comment: comment_for_path(source_code_info, path), members: [], annotations: [] ).tap do |class_decl| maps = {} message.nested_type.each_with_index do |nested_type, index| if nested_type.options&.map_entry key_field, value_field = nested_type.field.to_a map_type_name = ".#{(message_path + [nested_type.name]).join(".")}" maps[map_type_name] = [key_field, value_field] else class_decl.members << message_to_decl( nested_type, prefix: RBS::Namespace.empty, message_path: message_path + [nested_type.name.to_sym], source_code_info: source_code_info, path: path + [3, index] ) end end message.enum_type.each_with_index do |enum, index| class_decl.members << enum_type_to_decl( enum, prefix: RBS::Namespace.empty, source_code_info: source_code_info, path: path + [4, index] ) end field_read_types = {} field_write_types = {} message.field.each_with_index do |field, index| field_name = field.name.to_sym comment = comment_for_path(source_code_info, path + [2, index]) read_type, write_type = field_type(field, maps) field_read_types[field_name] = read_type field_write_types[field_name] = write_type if read_type == write_type class_decl.members << RBS::AST::Members::AttrAccessor.new( name: field_name, type: read_type, comment: comment, location: nil, annotations: [], ivar_name: false, kind: :instance ) else class_decl.members << RBS::AST::Members::AttrReader.new( name: field_name, type: read_type, comment: comment, location: nil, annotations: [], ivar_name: false, kind: :instance ) class_decl.members << RBS::AST::Members::AttrWriter.new( name: field_name, type: write_type, comment: comment, location: nil, annotations: [], ivar_name: false, kind: :instance ) end end class_decl.members << RBS::AST::Members::MethodDefinition.new( name: :initialize, types: [ factory.method_type( type: factory.function().update( optional_keywords: field_write_types.transform_values {|ty| factory.param(ty) } ) ) ], annotations: [], comment: nil, location: nil, overload: false, kind: :instance ) unless field_read_types.empty? class_decl.members << RBS::AST::Members::MethodDefinition.new( name: :[], types: field_read_types.keys.map do |key| factory.method_type( type: factory.function(field_read_types[key]).update( required_positionals: [ factory.param(factory.literal_type(key)) ] ) ) end + [ factory.method_type( type: factory.function(factory.untyped).update( required_positionals: [ factory.param(RBS::BuiltinNames::Symbol.instance_type) ] ) ) ], annotations: [], comment: nil, location: nil, overload: false, kind: :instance ) end unless field_write_types.empty? class_decl.members << RBS::AST::Members::MethodDefinition.new( name: :[]=, types: field_write_types.keys.map do |key| factory.method_type( type: factory.function(field_write_types[key]).update( required_positionals: [ factory.literal_type(key), field_write_types[key] ].map {|t| factory.param(t) } ) ) end + [ factory.method_type( type: factory.function(factory.untyped).update( required_positionals: [ RBS::BuiltinNames::Symbol.instance_type, factory.untyped ].map {|t| factory.param(t) } ) ) ], annotations: [], comment: nil, location: nil, overload: false, kind: :instance ) end message.field.each do |field| if field.type == FieldDescriptorProto::Type::TYPE_BOOL class_decl.members << RBS::AST::Members::MethodDefinition.new( name: :"#{field.name}?", types: [ factory.method_type( type: factory.function(factory.bool_type) ) ], annotations: [], comment: nil, location: nil, overload: false, kind: :instance ) end end end end
nested_namespace?()
click to toggle source
# File lib/rbs_protobuf/translator/protobuf_gem.rb, line 14 def nested_namespace? @nested_namespace end
rbs_content(file)
click to toggle source
# File lib/rbs_protobuf/translator/protobuf_gem.rb, line 18 def rbs_content(file) decls = [] source_code_info = file.source_code_info if file.package && !file.package.empty? package_namespace = message_type(file.package).name.to_namespace else package_namespace = RBS::Namespace.empty end prefix = if nested_namespace? RBS::Namespace.empty else package_namespace end file.enum_type.each_with_index do |enum, index| decls << enum_type_to_decl(enum, prefix: prefix, source_code_info: source_code_info, path: [5, index]) end file.message_type.each_with_index do |message, index| decls << message_to_decl(message, prefix: prefix, message_path: if package_namespace.empty? [message.name.to_sym] else [file.package.to_sym, message.name.to_sym] end, source_code_info: source_code_info, path: [4, index]) end file.service.each_with_index do |service, index| decls << service_to_decl(service, prefix: prefix, source_code_info: source_code_info, path: [6, index]) end if nested_namespace? package_namespace.path.reverse_each do |name| decls = [ RBS::AST::Declarations::Module.new( name: factory.type_name(name.to_s), self_types: [], type_params: factory.module_type_params, location: nil, comment: nil, annotations: [], members: decls ) ] end end file.extension.group_by(&:extendee).each.with_index do |(name, extensions), index| decls.push(*extension_to_decl(name, extensions, prefix: RBS::Namespace.root, source_code_info: source_code_info, path: [7, index])) end StringIO.new.tap do |io| RBS::Writer.new(out: io).write(decls) end.string end
repeated_field_type(type, wtype = type)
click to toggle source
# File lib/rbs_protobuf/translator/protobuf_gem.rb, line 101 def repeated_field_type(type, wtype = type) factory.instance_type( factory.type_name("::Protobuf::Field::FieldArray"), type, wtype ) end
service_base_class()
click to toggle source
# File lib/rbs_protobuf/translator/protobuf_gem.rb, line 560 def service_base_class RBS::AST::Declarations::Class::Super.new( name: factory.type_name("::Protobuf::Rpc::Service"), args: [], location: nil ) end
service_to_decl(service, prefix:, source_code_info:, path:)
click to toggle source
# File lib/rbs_protobuf/translator/protobuf_gem.rb, line 568 def service_to_decl(service, prefix:, source_code_info:, path:) service_name = ActiveSupport::Inflector.camelize(service.name) RBS::AST::Declarations::Class.new( name: RBS::TypeName.new(name: service_name.to_sym, namespace: prefix), super_class: service_base_class, type_params: factory.module_type_params(), members: [], comment: comment_for_path(source_code_info, path), location: nil, annotations: [] ) end
upcase_enum?()
click to toggle source
# File lib/rbs_protobuf/translator/protobuf_gem.rb, line 10 def upcase_enum? @upcase_enum end