Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 34 additions & 4 deletions lib/rbs/subtractor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,46 @@ def call(minuend = @minuend, context: nil)

context = _ = [context, decl.name]
children = call(decl.each_decl.to_a, context: context) +
decl.each_member.reject { |m| member_exist?(owner, m, context: context) }
decl.each_member.filter_map { |m| subtract_member(owner, m, context: context) }
children = filter_redundant_access_modifiers(children)
return nil if children.empty?

update_decl(decl, members: children)
end

private def subtract_member(owner, member, context:)
if member.is_a?(AST::Members::AttrAccessor)
reader_exists = method_exist?(owner, member.name, member.kind)
writer_exists = method_exist?(owner, :"#{member.name}=", member.kind)

case
when reader_exists && writer_exists
nil
when reader_exists
accessor_part(member, AST::Members::AttrWriter)
when writer_exists
accessor_part(member, AST::Members::AttrReader)
else
member
end
else
member unless member_exist?(owner, member, context: context)
end
end

private def accessor_part(member, member_class)
member_class.new(
name: member.name,
type: member.type,
ivar_name: member.ivar_name,
kind: member.kind,
annotations: member.annotations,
location: member.location,
comment: member.comment,
visibility: member.visibility
)
end

private def member_exist?(owner, member, context:)
case member
when AST::Members::MethodDefinition
Expand All @@ -67,9 +100,6 @@ def call(minuend = @minuend, context: nil)
method_exist?(owner, member.name, member.kind)
when AST::Members::AttrWriter
method_exist?(owner, :"#{member.name}=", member.kind)
when AST::Members::AttrAccessor
# TODO: It unexpectedly removes attr_accessor even if either reader or writer does not exist in the subtrahend.
method_exist?(owner, member.name, member.kind) || method_exist?(owner, :"#{member.name}=", member.kind)
when AST::Members::InstanceVariable
ivar_exist?(owner, member.name, :instance)
when AST::Members::ClassInstanceVariable
Expand Down
4 changes: 4 additions & 0 deletions sig/subtractor.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ module RBS

private def filter_members: (decl_with_members, context: Resolver::context) -> decl_with_members?

private def subtract_member: (TypeName owner, AST::Members::t member, context: Resolver::context) -> AST::Members::t?

private def accessor_part: (AST::Members::AttrAccessor member, singleton(AST::Members::AttrReader) | singleton(AST::Members::AttrWriter) member_class) -> (AST::Members::AttrReader | AST::Members::AttrWriter)

private def member_exist?: (TypeName owner, AST::Members::t, context: Resolver::context) -> boolish

private def method_exist?: (TypeName owner, Symbol method_name, AST::Members::MethodDefinition::kind) -> boolish
Expand Down
7 changes: 7 additions & 0 deletions test/rbs/subtractor_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,8 @@ class C
attr_writer b: untyped
attr_writer c: untyped
attr_accessor d: untyped
attr_accessor e: untyped
attr_accessor f: untyped
end
RBS

Expand All @@ -428,6 +430,9 @@ def a: () -> Integer
def b=: (String) -> String
def c: (String) -> String
def d: (String) -> String
def e=: (String) -> String
def f: () -> String
def f=: (String) -> String
end
RBS

Expand All @@ -436,6 +441,8 @@ def d: (String) -> String
assert_subtracted <<~RBS, subtracted
class C
attr_writer c: untyped
attr_writer d: untyped
attr_reader e: untyped
end
RBS
end
Expand Down
Loading