diff --git a/lib/rbs/ast/members.rb b/lib/rbs/ast/members.rb index 7888a1686..af90d7628 100644 --- a/lib/rbs/ast/members.rb +++ b/lib/rbs/ast/members.rb @@ -304,6 +304,21 @@ def update(name: self.name, type: self.type, ivar_name: self.ivar_name, kind: se visibility: visibility ) end + + def ivar + @ivar ||= begin + ivar_name = case self.ivar_name + when false + return nil # Skip the instance variable declaration entirely + when nil + :"@#{name}" # Infer the instance variable name from the attribute name + else + self.ivar_name # Use the custom instance variable name given by the user + end + + InstanceVariable.new(name: ivar_name, type: type, location: location, comment: comment) + end + end end class AttrReader < Base diff --git a/sig/members.rbs b/sig/members.rbs index 2951d3ba2..13b471158 100644 --- a/sig/members.rbs +++ b/sig/members.rbs @@ -185,6 +185,8 @@ module RBS include _HashEqual def update: (?name: Symbol, ?type: Types::t, ?ivar_name: Symbol | false | nil, ?kind: kind, ?annotations: Array[Annotation], ?location: loc?, ?comment: Comment?, ?visibility: visibility?) -> instance + + def ivar: () -> InstanceVariable? end class AttrReader < Base diff --git a/test/rbs/signature_parsing_test.rb b/test/rbs/signature_parsing_test.rb index 95e40805c..c9277c1dd 100644 --- a/test/rbs/signature_parsing_test.rb +++ b/test/rbs/signature_parsing_test.rb @@ -361,6 +361,13 @@ def self?.three: -> bool assert_equal :a, m.name assert_nil m.ivar_name assert_equal parse_type("Integer"), m.type + + ivar = m.ivar + assert_instance_of Members::InstanceVariable, ivar + assert_equal :@a, ivar.name # Inferred from the attribute name + assert_equal m.type, ivar.type + assert_equal m.location, ivar.location + assert_equal m.comment, ivar.comment end module_decl.members[11].yield_self do |m| @@ -369,6 +376,13 @@ def self?.three: -> bool assert_equal :a, m.name assert_equal :@A, m.ivar_name assert_equal parse_type("String"), m.type + + ivar = m.ivar + assert_instance_of Members::InstanceVariable, ivar + assert_equal :@A, ivar.name # Explicitly given ivar name + assert_equal m.type, ivar.type + assert_equal m.location, ivar.location + assert_equal m.comment, ivar.comment end module_decl.members[12].yield_self do |m| @@ -377,6 +391,8 @@ def self?.three: -> bool assert_equal :a, m.name assert_equal false, m.ivar_name assert_equal parse_type("bool"), m.type + + assert_nil m.ivar # The instance variable was explicitly skipped end module_decl.members[13].yield_self do |m| @@ -385,6 +401,13 @@ def self?.three: -> bool assert_equal :b, m.name assert_nil m.ivar_name assert_equal parse_type("Integer"), m.type + + ivar = m.ivar + assert_instance_of Members::InstanceVariable, ivar + assert_equal :@b, ivar.name # Inferred from the attribute name + assert_equal m.type, ivar.type + assert_equal m.location, ivar.location + assert_equal m.comment, ivar.comment end module_decl.members[14].yield_self do |m| @@ -393,6 +416,13 @@ def self?.three: -> bool assert_equal :b, m.name assert_equal :@B, m.ivar_name assert_equal parse_type("String"), m.type + + ivar = m.ivar + assert_instance_of Members::InstanceVariable, ivar + assert_equal :@B, ivar.name # Explicitly given ivar name + assert_equal m.type, ivar.type + assert_equal m.location, ivar.location + assert_equal m.comment, ivar.comment end module_decl.members[15].yield_self do |m| @@ -401,6 +431,8 @@ def self?.three: -> bool assert_equal :b, m.name assert_equal false, m.ivar_name assert_equal parse_type("bool"), m.type + + assert_nil m.ivar # The instance variable was explicitly skipped end module_decl.members[16].yield_self do |m| @@ -409,6 +441,13 @@ def self?.three: -> bool assert_equal :c, m.name assert_nil m.ivar_name assert_equal parse_type("Integer"), m.type + + ivar = m.ivar + assert_instance_of Members::InstanceVariable, ivar + assert_equal :@c, ivar.name # Inferred from the attribute name + assert_equal m.type, ivar.type + assert_equal m.location, ivar.location + assert_equal m.comment, ivar.comment end module_decl.members[17].yield_self do |m| @@ -417,6 +456,13 @@ def self?.three: -> bool assert_equal :c, m.name assert_equal :@C, m.ivar_name assert_equal parse_type("String"), m.type + + ivar = m.ivar + assert_instance_of Members::InstanceVariable, ivar + assert_equal :@C, ivar.name # Explicitly given ivar name + assert_equal m.type, ivar.type + assert_equal m.location, ivar.location + assert_equal m.comment, ivar.comment end module_decl.members[18].yield_self do |m| @@ -425,6 +471,8 @@ def self?.three: -> bool assert_equal :c, m.name assert_equal false, m.ivar_name assert_equal parse_type("bool"), m.type + + assert_nil m.ivar # The instance variable was explicitly skipped end end end