Class: RBS::Subtractor
Relationships & Source Files | |
Inherits: | Object |
Defined in: | lib/rbs/subtractor.rb |
Class Method Summary
- .new(minuend, subtrahend) ⇒ Subtractor constructor
Instance Method Summary
- #call(minuend = @minuend, context: nil)
- #absolute_typename(name, context:) private
- #access_modifier?(decl) ⇒ Boolean private
- #cvar_exist?(owner, name) ⇒ Boolean private
- #each_member(owner, &block) private
- #filter_members(decl, context:) private
- #filter_redundunt_access_modifiers(decls) private
- #ivar_exist?(owner, name, kind) ⇒ Boolean private
- #member_exist?(owner, member, context:) ⇒ Boolean private
- #method_exist?(owner, method_name, kind) ⇒ Boolean private
- #mixin_exist?(owner, mixin, context:) ⇒ Boolean private
- #typename_candidates(name, context:) private
- #update_decl(decl, members:) private
Constructor Details
.new(minuend, subtrahend) ⇒ Subtractor
# File 'lib/rbs/subtractor.rb', line 5
def initialize(minuend, subtrahend) @minuend = minuend @subtrahend = subtrahend end
Instance Method Details
#absolute_typename(name, context:) (private)
[ GitHub ]# File 'lib/rbs/subtractor.rb', line 177
private def absolute_typename(name, context:) while context ns = context[1] or raise name = name.with_prefix(ns.to_namespace) context = _ = context[0] end name.absolute! end
#access_modifier?(decl) ⇒ Boolean
(private)
#call(minuend = @minuend, context: nil)
[ GitHub ]# File 'lib/rbs/subtractor.rb', line 10
def call(minuend = @minuend, context: nil) minuend.map do |decl| case decl when AST::Declarations::Constant name = absolute_typename(decl.name, context: context) decl unless @subtrahend.constant_name?(name) when AST::Declarations::Interface name = absolute_typename(decl.name, context: context) decl unless @subtrahend.interface_name?(name) when AST::Declarations::Class, AST::Declarations::Module name = absolute_typename(decl.name, context: context) case when @subtrahend.class_decl?(name) && decl.is_a?(AST::Declarations::Class) filter_members(decl, context: context) when @subtrahend.module_decl?(name) && decl.is_a?(AST::Declarations::Module) filter_members(decl, context: context) when @subtrahend.constant_name?(name) nil else decl end when AST::Declarations::Global decl unless @subtrahend.global_decls[decl.name] when AST::Declarations::TypeAlias name = absolute_typename(decl.name, context: context) decl unless @subtrahend.type_alias_decls[name] when AST::Declarations::ClassAlias name = absolute_typename(decl.new_name, context: context) decl unless @subtrahend.class_alias?(name) || @subtrahend.class_decl?(name) when AST::Declarations::ModuleAlias name = absolute_typename(decl.new_name, context: context) decl unless @subtrahend.module_alias?(name) || @subtrahend.module_decl?(name) else raise "unknwon decl: #{(_ = decl).class}" end end.compact end
#cvar_exist?(owner, name) ⇒ Boolean
(private)
# File 'lib/rbs/subtractor.rb', line 118
private def cvar_exist?(owner, name) each_member(owner).any? do |m| case m when AST::Members::ClassVariable m.name == name end end end
#each_member(owner, &block) (private)
[ GitHub ]# File 'lib/rbs/subtractor.rb', line 127
private def each_member(owner, &block) return enum_for((__method__ or raise), owner) unless block entry = @subtrahend.class_decls[owner] return unless entry decls = entry.decls.map { |d| d.decl } decls.each { |d| d.members.each { |m| block.call(m) } } end
#filter_members(decl, context:) (private)
[ GitHub ]# File 'lib/rbs/subtractor.rb', line 48
private def filter_members(decl, context:) owner = absolute_typename(decl.name, context: context) context = _ = [context, decl.name] children = call(decl.each_decl.to_a, context: context) + decl.each_member.reject { |m| member_exist?(owner, m, context: context) } children = filter_redundunt_access_modifiers(children) return nil if children.empty? update_decl(decl, members: children) end
#filter_redundunt_access_modifiers(decls) (private)
[ GitHub ]# File 'lib/rbs/subtractor.rb', line 148
private def filter_redundunt_access_modifiers(decls) decls = decls.dup decls.pop while access_modifier?(decls.last) decls = decls.map.with_index do |decl, i| if access_modifier?(decl) && access_modifier?(decls[i + 1]) nil else decl end end.compact end
#ivar_exist?(owner, name, kind) ⇒ Boolean
(private)
# File 'lib/rbs/subtractor.rb', line 106
private def ivar_exist?(owner, name, kind) each_member(owner).any? do |m| case m when AST::Members::InstanceVariable m.name == name when AST::Members::Attribute ivar_name = m.ivar_name == false ? nil : m.ivar_name || :"@#{m.name}" ivar_name == name && m.kind == kind end end end
#member_exist?(owner, member, context:) ⇒ Boolean
(private)
# File 'lib/rbs/subtractor.rb', line 60
private def member_exist?(owner, member, context:) case member when AST::Members::MethodDefinition method_exist?(owner, member.name, member.kind) when AST::Members::Alias method_exist?(owner, member.new_name, member.kind) when AST::Members::AttrReader 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 ivar_exist?(owner, member.name, :singleton) when AST::Members::ClassVariable cvar_exist?(owner, member.name) when AST::Members::Include, AST::Members::Extend, AST::Members::Prepend mixin_exist?(owner, member, context: context) when AST::Members::Public, AST::Members::Private # They should not be removed even if the subtrahend has them. false else raise "unknown member: #{(_ = member).class}" end end
#method_exist?(owner, method_name, kind) ⇒ Boolean
(private)
# File 'lib/rbs/subtractor.rb', line 89
private def method_exist?(owner, method_name, kind) each_member(owner).any? do |m| case m when AST::Members::MethodDefinition m.name == method_name && m.kind == kind when AST::Members::Alias m.new_name == method_name && m.kind == kind when AST::Members::AttrReader m.name == method_name && m.kind == kind when AST::Members::AttrWriter :"#{m.name}=" == method_name && m.kind == kind when AST::Members::AttrAccessor (m.name == method_name || :"#{m.name}=" == method_name) && m.kind == kind end end end
#mixin_exist?(owner, mixin, context:) ⇒ Boolean
(private)
# File 'lib/rbs/subtractor.rb', line 137
private def mixin_exist?(owner, mixin, context:) candidates = typename_candidates(mixin.name, context: context) each_member(owner).any? do |m| case m when mixin.class # @type var m: AST::Members::Include | AST::Members::Extend | AST::Members::Prepend candidates.include?(m.name) end end end
#typename_candidates(name, context:) (private)
[ GitHub ]# File 'lib/rbs/subtractor.rb', line 186
private def typename_candidates(name, context:) ret = [name.absolute!, name.relative!] return ret if name.absolute? while context ns = context[1] or raise name = name.with_prefix(ns.to_namespace) ret.concat [name.absolute!, name.relative!] context = _ = context[0] end ret end
#update_decl(decl, members:) (private)
[ GitHub ]# File 'lib/rbs/subtractor.rb', line 164
private def update_decl(decl, members:) case decl when AST::Declarations::Class decl.class.new(name: decl.name, type_params: decl.type_params, super_class: decl.super_class, annotations: decl.annotations, location: decl.location, comment: decl.comment, members: members) when AST::Declarations::Module decl.class.new(name: decl.name, type_params: decl.type_params, self_types: decl.self_types, annotations: decl.annotations, location: decl.location, comment: decl.comment, members: members) end end