Class: RBS::DefinitionBuilder::AncestorBuilder
Relationships & Source Files | |
Namespace Children | |
Classes:
| |
Inherits: | Object |
Defined in: | lib/rbs/definition_builder/ancestor_builder.rb |
Class Method Summary
- .new(env:) ⇒ AncestorBuilder constructor
Instance Attribute Summary
- #env readonly
- #instance_ancestors_cache readonly
- #interface_ancestors_cache readonly
- #one_instance_ancestors_cache readonly
- #one_interface_ancestors_cache readonly
- #one_singleton_ancestors_cache readonly
- #singleton_ancestors_cache readonly
Instance Method Summary
- #fill_ancestor_source(ancestor, name:, source:, &block)
- #instance_ancestors(type_name, building_ancestors: [])
- #interface_ancestors(type_name, building_ancestors: [])
- #mixin_ancestors(entry, type_name, included_modules:, included_interfaces:, extended_modules:, prepended_modules:, extended_interfaces:)
- #mixin_ancestors0(decl, type_name, align_params:, included_modules:, included_interfaces:, extended_modules:, prepended_modules:, extended_interfaces:)
- #one_instance_ancestors(type_name)
- #one_interface_ancestors(type_name)
- #one_singleton_ancestors(type_name)
- #singleton_ancestors(type_name, building_ancestors: [])
- #validate_super_class!(type_name, entry)
Constructor Details
.new(env:) ⇒ AncestorBuilder
# File 'lib/rbs/definition_builder/ancestor_builder.rb', line 162
def initialize(env:) @env = env @one_instance_ancestors_cache = {} @instance_ancestors_cache = {} @one_singleton_ancestors_cache = {} @singleton_ancestors_cache = {} @one_interface_ancestors_cache = {} @interface_ancestors_cache = {} end
Instance Attribute Details
#env (readonly)
[ GitHub ]# File 'lib/rbs/definition_builder/ancestor_builder.rb', line 151
attr_reader :env
#instance_ancestors_cache (readonly)
[ GitHub ]# File 'lib/rbs/definition_builder/ancestor_builder.rb', line 154
attr_reader :instance_ancestors_cache
#interface_ancestors_cache (readonly)
[ GitHub ]# File 'lib/rbs/definition_builder/ancestor_builder.rb', line 160
attr_reader :interface_ancestors_cache
#one_instance_ancestors_cache (readonly)
[ GitHub ]# File 'lib/rbs/definition_builder/ancestor_builder.rb', line 153
attr_reader :one_instance_ancestors_cache
#one_interface_ancestors_cache (readonly)
[ GitHub ]# File 'lib/rbs/definition_builder/ancestor_builder.rb', line 159
attr_reader :one_interface_ancestors_cache
#one_singleton_ancestors_cache (readonly)
[ GitHub ]# File 'lib/rbs/definition_builder/ancestor_builder.rb', line 156
attr_reader :one_singleton_ancestors_cache
#singleton_ancestors_cache (readonly)
[ GitHub ]# File 'lib/rbs/definition_builder/ancestor_builder.rb', line 157
attr_reader :singleton_ancestors_cache
Instance Method Details
#fill_ancestor_source(ancestor, name:, source:, &block)
[ GitHub ]# File 'lib/rbs/definition_builder/ancestor_builder.rb', line 606
def fill_ancestor_source(ancestor, name:, source:, &block) case ancestor when Definition::Ancestor::Instance if ancestor.name == name && !ancestor.source Definition::Ancestor::Instance.new(name: ancestor.name, args: ancestor.args, source: source) else ancestor end else ancestor end end
#instance_ancestors(type_name, building_ancestors: [])
[ GitHub ]# File 'lib/rbs/definition_builder/ancestor_builder.rb', line 434
def instance_ancestors(type_name, building_ancestors: []) as = instance_ancestors_cache[type_name] and return as entry = env.class_decls[type_name] or raise "Unknown name for instance_ancestors: #{type_name}" params = entry.type_params.each.map(&:name) args = entry.type_params.map do |type_param| Types::Variable.new(name: type_param.name, location: type_param.location) end self_ancestor = Definition::Ancestor::Instance.new(name: type_name, args: args, source: nil) RecursiveAncestorError.check!(self_ancestor, ancestors: building_ancestors, location: entry.primary.decl.location) building_ancestors.push self_ancestor one_ancestors = one_instance_ancestors(type_name) # @type var ancestors: Array[::RBS::Definition::Ancestor::t] ancestors = [] case entry when Environment::ClassEntry if super_class = one_ancestors.super_class # @type var super_class: Definition::Ancestor::Instance super_name = super_class.name super_args = super_class.args super_ancestors = instance_ancestors(super_name, building_ancestors: building_ancestors) .apply(super_args, env: env, location: entry.primary.decl.super_class&.location) super_ancestors.map! {|ancestor| fill_ancestor_source(ancestor, name: super_name, source: :super) } ancestors.unshift(*super_ancestors) end end if self_types = one_ancestors.self_types self_types.each do |mod| if mod.name.class? # Ensure there is no loop in ancestors chain instance_ancestors(mod.name, building_ancestors: building_ancestors) end end end if included_modules = one_ancestors.included_modules included_modules.each do |mod| name = mod.name arg_types = mod.args mod.source.is_a?(AST::Members::Include) or raise mod_ancestors = instance_ancestors(name, building_ancestors: building_ancestors) .apply(arg_types, env: env, location: mod.source.location) mod_ancestors.map! {|ancestor| fill_ancestor_source(ancestor, name: name, source: mod.source) } ancestors.unshift(*mod_ancestors) end end ancestors.unshift(self_ancestor) if prepended_modules = one_ancestors.prepended_modules prepended_modules.each do |mod| name = mod.name arg_types = mod.args mod.source.is_a?(AST::Members::Prepend) or raise mod_ancestors = instance_ancestors(name, building_ancestors: building_ancestors) .apply(arg_types, env: env, location: mod.source.location) mod_ancestors.map! {|ancestor| fill_ancestor_source(ancestor, name: name, source: mod.source) } ancestors.unshift(*mod_ancestors) end end building_ancestors.pop instance_ancestors_cache[type_name] = Definition::InstanceAncestors.new( type_name: type_name, params: params, ancestors: ancestors ) end
#interface_ancestors(type_name, building_ancestors: [])
[ GitHub ]# File 'lib/rbs/definition_builder/ancestor_builder.rb', line 570
def interface_ancestors(type_name, building_ancestors: []) as = interface_ancestors_cache[type_name] and return as entry = env.interface_decls[type_name] or raise "Unknown name for interface_ancestors: #{type_name}" params = entry.decl.type_params.each.map(&:name) args = Types::Variable.build(params) self_ancestor = Definition::Ancestor::Instance.new(name: type_name, args: args, source: nil) RecursiveAncestorError.check!(self_ancestor, ancestors: building_ancestors, location: entry.decl.location) building_ancestors.push self_ancestor one_ancestors = one_interface_ancestors(type_name) ancestors = [] included_interfaces = one_ancestors.included_interfaces or raise included_interfaces.each do |a| a.source.is_a?(AST::Members::Include) or raise included_ancestors = interface_ancestors(a.name, building_ancestors: building_ancestors) .apply(a.args, env: env, location: a.source.location) included_ancestors.map! {|ancestor| fill_ancestor_source(ancestor, name: a.name, source: a.source) } ancestors.unshift(*included_ancestors) end ancestors.unshift(self_ancestor) building_ancestors.pop interface_ancestors_cache[type_name] = Definition::InstanceAncestors.new( type_name: type_name, params: params, ancestors: ancestors ) end
#mixin_ancestors(entry, type_name, included_modules:, included_interfaces:, extended_modules:, prepended_modules:, extended_interfaces:)
[ GitHub ]# File 'lib/rbs/definition_builder/ancestor_builder.rb', line 414
def mixin_ancestors(entry, type_name, included_modules:, included_interfaces:, extended_modules:, prepended_modules:, extended_interfaces:) entry.decls.each do |d| decl = d.decl align_params = Substitution.build( decl.type_params.each.map(&:name), entry.type_params.map {|param| Types::Variable.new(name: param.name, location: param.location) } ) mixin_ancestors0(decl, type_name, align_params: align_params, included_modules: included_modules, included_interfaces: included_interfaces, extended_modules: extended_modules, prepended_modules: prepended_modules, extended_interfaces: extended_interfaces) end end
#mixin_ancestors0(decl, type_name, align_params:, included_modules:, included_interfaces:, extended_modules:, prepended_modules:, extended_interfaces:)
[ GitHub ]# File 'lib/rbs/definition_builder/ancestor_builder.rb', line 348
def mixin_ancestors0(decl, type_name, align_params:, included_modules:, included_interfaces:, extended_modules:, prepended_modules:, extended_interfaces:) decl.each_mixin do |member| case member when AST::Members::Include module_name = member.name module_args = member.args.map {|type| align_params ? type.sub(align_params) : type } case when member.name.class? && included_modules MixinClassError.check!(type_name: type_name, env: env, member: member) NoMixinFoundError.check!(member.name, env: env, member: member) module_decl = env.normalized_module_entry(module_name) or raise module_args = AST::TypeParam.normalize_args(module_decl.type_params, module_args) module_name = env.normalize_module_name(module_name) included_modules << Definition::Ancestor::Instance.new(name: module_name, args: module_args, source: member) when member.name.interface? && included_interfaces NoMixinFoundError.check!(member.name, env: env, member: member) interface_decl = env.interface_decls.fetch(module_name) module_args = AST::TypeParam.normalize_args(interface_decl.decl.type_params, module_args) included_interfaces << Definition::Ancestor::Instance.new(name: module_name, args: module_args, source: member) end when AST::Members::Prepend if prepended_modules MixinClassError.check!(type_name: type_name, env: env, member: member) NoMixinFoundError.check!(member.name, env: env, member: member) module_decl = env.normalized_module_entry(member.name) or raise module_name = module_decl.name module_args = member.args.map {|type| align_params ? type.sub(align_params) : type } module_args = AST::TypeParam.normalize_args(module_decl.type_params, module_args) prepended_modules << Definition::Ancestor::Instance.new(name: module_name, args: module_args, source: member) end when AST::Members::Extend module_name = member.name module_args = member.args case when member.name.class? && extended_modules MixinClassError.check!(type_name: type_name, env: env, member: member) NoMixinFoundError.check!(member.name, env: env, member: member) module_decl = env.normalized_module_entry(module_name) or raise module_args = AST::TypeParam.normalize_args(module_decl.type_params, module_args) module_name = env.normalize_module_name(module_name) extended_modules << Definition::Ancestor::Instance.new(name: module_name, args: module_args, source: member) when member.name.interface? && extended_interfaces NoMixinFoundError.check!(member.name, env: env, member: member) interface_decl = env.interface_decls.fetch(module_name) module_args = AST::TypeParam.normalize_args(interface_decl.decl.type_params, module_args) extended_interfaces << Definition::Ancestor::Instance.new(name: module_name, args: module_args, source: member) end end end end
#one_instance_ancestors(type_name)
[ GitHub ]# File 'lib/rbs/definition_builder/ancestor_builder.rb', line 192
def one_instance_ancestors(type_name) type_name = env.normalize_module_name(type_name) as = one_instance_ancestors_cache[type_name] and return as entry = env.class_decls[type_name] or raise "Unknown name for one_instance_ancestors: #{type_name}" params = entry.type_params.each.map(&:name) case entry when Environment::ClassEntry validate_super_class!(type_name, entry) primary = entry.primary super_class = primary.decl.super_class if type_name != BuiltinNames::BasicObject.name if super_class super_name = super_class.name super_args = super_class.args else super_name = BuiltinNames::Object.name super_args = [] end super_name = env.normalize_module_name(super_name) NoSuperclassFoundError.check!(super_name, env: env, location: primary.decl.location) if super_class InheritModuleError.check!(super_class, env: env) end super_entry = env.normalized_class_entry(super_name) or raise super_args = AST::TypeParam.normalize_args(super_entry.type_params, super_args) ancestors = OneAncestors.class_instance( type_name: type_name, params: params, super_class: Definition::Ancestor::Instance.new(name: super_name, args: super_args, source: :super) ) else ancestors = OneAncestors.class_instance( type_name: type_name, params: params, super_class: nil ) end when Environment::ModuleEntry ancestors = OneAncestors.module_instance(type_name: type_name, params: params) self_types = ancestors.self_types or raise if entry.self_types.empty? self_types.push Definition::Ancestor::Instance.new(name: BuiltinNames::Object.name, args: [], source: nil) else entry.self_types.each do |module_self| NoSelfTypeFoundError.check!(module_self, env: env) module_name = module_self.name if module_name.class? module_entry = env.normalized_module_class_entry(module_name) or raise module_name = module_entry.name self_args = AST::TypeParam.normalize_args(module_entry.type_params, module_self.args) end if module_name.interface? interface_entry = env.interface_decls.fetch(module_name) self_args = AST::TypeParam.normalize_args(interface_entry.decl.type_params, module_self.args) end self_args or raise self_types.push Definition::Ancestor::Instance.new(name: module_name, args: self_args, source: module_self) end end end mixin_ancestors(entry, type_name, included_modules: ancestors.included_modules, included_interfaces: ancestors.included_interfaces, prepended_modules: ancestors.prepended_modules, extended_modules: nil, extended_interfaces: nil) one_instance_ancestors_cache[type_name] = ancestors end
#one_interface_ancestors(type_name)
[ GitHub ]# File 'lib/rbs/definition_builder/ancestor_builder.rb', line 329
def one_interface_ancestors(type_name) one_interface_ancestors_cache[type_name] ||= begin entry = env.interface_decls[type_name] or raise "Unknown name for one_interface_ancestors: #{type_name}" params = entry.decl.type_params.each.map(&:name) OneAncestors.interface(type_name: type_name, params: params).tap do |ancestors| mixin_ancestors0(entry.decl, type_name, align_params: nil, included_modules: nil, included_interfaces: ancestors.included_interfaces, prepended_modules: nil, extended_modules: nil, extended_interfaces: nil) end end end
#one_singleton_ancestors(type_name)
[ GitHub ]# File 'lib/rbs/definition_builder/ancestor_builder.rb', line 275
def one_singleton_ancestors(type_name) type_name = env.normalize_module_name(type_name) as = one_singleton_ancestors_cache[type_name] and return as entry = env.class_decls[type_name] or raise "Unknown name for one_singleton_ancestors: #{type_name}" case entry when Environment::ClassEntry validate_super_class!(type_name, entry) primary = entry.primary super_class = primary.decl.super_class if type_name != BuiltinNames::BasicObject.name if super_class super_name = super_class.name else super_name = BuiltinNames::Object.name end super_name = env.normalize_module_name(super_name) NoSuperclassFoundError.check!(super_name, env: env, location: primary.decl.location) if super_class InheritModuleError.check!(super_class, env: env) end ancestors = OneAncestors.singleton( type_name: type_name, super_class: Definition::Ancestor::Singleton.new(name: super_name) ) else ancestors = OneAncestors.singleton( type_name: type_name, super_class: Definition::Ancestor::Instance.new(name: BuiltinNames::Class.name, args: [], source: :super) ) end when Environment::ModuleEntry ancestors = OneAncestors.singleton( type_name: type_name, super_class: Definition::Ancestor::Instance.new(name: BuiltinNames::Module.name, args: [], source: :super) ) end mixin_ancestors(entry, type_name, included_modules: nil, included_interfaces: nil, prepended_modules: nil, extended_modules: ancestors.extended_modules, extended_interfaces: ancestors.extended_interfaces) one_singleton_ancestors_cache[type_name] = ancestors end
#singleton_ancestors(type_name, building_ancestors: [])
[ GitHub ]# File 'lib/rbs/definition_builder/ancestor_builder.rb', line 515
def singleton_ancestors(type_name, building_ancestors: []) as = singleton_ancestors_cache[type_name] and return as entry = env.class_decls[type_name] or raise "Unknown name for singleton_ancestors: #{type_name}" self_ancestor = Definition::Ancestor::Singleton.new(name: type_name) RecursiveAncestorError.check!(self_ancestor, ancestors: building_ancestors, location: entry.primary.decl.location) building_ancestors.push self_ancestor one_ancestors = one_singleton_ancestors(type_name) ancestors = [] case super_class = one_ancestors.super_class when Definition::Ancestor::Instance super_name = super_class.name super_args = super_class.args super_ancestors = instance_ancestors(super_name, building_ancestors: building_ancestors) .apply(super_args, env: env, location: nil) super_ancestors.map! {|ancestor| fill_ancestor_source(ancestor, name: super_name, source: :super) } ancestors.unshift(*super_ancestors) when Definition::Ancestor::Singleton super_name = super_class.name super_ancestors = singleton_ancestors(super_name, building_ancestors: []) ancestors.unshift(*super_ancestors.ancestors) end extended_modules = one_ancestors.extended_modules or raise extended_modules.each do |mod| name = mod.name args = mod.args mod.source.is_a?(AST::Members::Extend) or raise mod_ancestors = instance_ancestors(name, building_ancestors: building_ancestors) .apply(args, env: env, location: mod.source.location) mod_ancestors.map! {|ancestor| fill_ancestor_source(ancestor, name: name, source: mod.source) } ancestors.unshift(*mod_ancestors) end ancestors.unshift(self_ancestor) building_ancestors.pop singleton_ancestors_cache[type_name] = Definition::SingletonAncestors.new( type_name: type_name, ancestors: ancestors ) end
#validate_super_class!(type_name, entry)
# File 'lib/rbs/definition_builder/ancestor_builder.rb', line 175
def validate_super_class!(type_name, entry) with_super_classes = entry.decls.select {|d| d.decl.super_class } return if with_super_classes.size <= 1 super_types = with_super_classes.map do |d| super_class = d.decl.super_class or raise Types::ClassInstance.new(name: super_class.name, args: super_class.args, location: nil) end super_types.uniq! return if super_types.size == 1 raise SuperclassMismatchError.new(name: type_name, entry: entry) end