From df02b181dd7f11e9f0fe293d744d23e546b1c8b1 Mon Sep 17 00:00:00 2001 From: rhiroe Date: Fri, 10 Jan 2025 14:18:41 +0000 Subject: [PATCH] Set the generics of the struct based on the type of its attributes ```rb Account = Struct.new( :id, #: Integer :email, #: String ) ``` This Ruby code generates the following RBS code: ```rbs class Account < Struct[Integer | String] attr_accessor id(): Integer attr_accessor email(): String def self.new: (?Integer id, ?String email) -> instance | (?id: Integer, ?email: String) -> instance end ``` --- lib/rbs/inline/writer.rb | 7 ++++++- test/rbs/inline/writer_test.rb | 6 +++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/rbs/inline/writer.rb b/lib/rbs/inline/writer.rb index 381fc0e..83b0c34 100644 --- a/lib/rbs/inline/writer.rb +++ b/lib/rbs/inline/writer.rb @@ -428,7 +428,12 @@ def translate_struct_assign_decl(decl, rbs) #: void members: [*attributes, new], super_class: RBS::AST::Declarations::Class::Super.new( name: RBS::TypeName.new(name: :Struct, namespace: RBS::Namespace.empty), - args: [RBS::Types::Bases::Any.new(location: nil)], + args: [ + RBS::Types::Union.new( + types: decl.each_attribute.map { |_, attr| attr&.type || RBS::Types::Bases::Any.new(location: nil) }.uniq, + location: nil + ) + ], location: nil ), annotations: decl.class_annotations, diff --git a/test/rbs/inline/writer_test.rb b/test/rbs/inline/writer_test.rb index dae0053..5c79c5a 100644 --- a/test/rbs/inline/writer_test.rb +++ b/test/rbs/inline/writer_test.rb @@ -1011,7 +1011,7 @@ class Account assert_equal <<~RBS, output # Account record - class Account < Struct[untyped] + class Account < Struct[Integer | String] attr_accessor id(): Integer attr_accessor email(): String @@ -1029,7 +1029,7 @@ def self.new: (?name: untyped) -> instance end end - class Item < Struct[untyped] + class Item < Struct[String | Integer] attr_accessor sku(): String attr_accessor price(): Integer @@ -1041,7 +1041,7 @@ def self.new: (?String sku, ?Integer price) -> instance # @rbs %a{rbs-inline:readonly-attributes=true} %a{rbs-inline:new-args=required} %a{rbs-inline:readonly-attributes=true} - class User < Struct[untyped] + class User < Struct[String] attr_reader name(): String def self.new: (String name) -> instance