lib/rbs/definition_builder.rb in rbs-0.6.0 vs lib/rbs/definition_builder.rb in rbs-0.7.0

- old
+ new

@@ -11,10 +11,81 @@ attr_reader :one_singleton_cache attr_reader :instance_ancestors_cache attr_reader :singleton_ancestor_cache + attr_reader :one_instance_ancestors_cache + attr_reader :one_singleton_ancestors_cache + + class OneAncestors + attr_reader :type_name + attr_reader :params + attr_reader :super_class + attr_reader :self_types + attr_reader :included_modules + attr_reader :prepended_modules + attr_reader :extended_modules + + def initialize(type_name:, params:, super_class:, self_types:, included_modules:, prepended_modules:, extended_modules:) + @type_name = type_name + @params = params + @super_class = super_class + @self_types = self_types + @included_modules = included_modules + @prepended_modules = prepended_modules + @extended_modules = extended_modules + end + + def each_ancestor(&block) + if block_given? + yield super_class if super_class + self_types&.each(&block) + included_modules&.each(&block) + prepended_modules&.each(&block) + extended_modules&.each(&block) + else + enum_for :each_ancestor + end + end + + def self.class_instance(type_name:, params:, super_class:) + new( + type_name: type_name, + params: params, + super_class: super_class, + self_types: nil, + included_modules: [], + prepended_modules: [], + extended_modules: nil + ) + end + + def self.singleton(type_name:, super_class:) + new( + type_name: type_name, + params: nil, + super_class: super_class, + self_types: nil, + included_modules: nil, + prepended_modules: nil, + extended_modules: [] + ) + end + + def self.module_instance(type_name:, params:) + new( + type_name: type_name, + params: params, + self_types: [], + included_modules: [], + prepended_modules: [], + super_class: nil, + extended_modules: nil + ) + end + end + def initialize(env:) @env = env @type_name_resolver = TypeNameResolver.from_env(env) @instance_cache = {} @@ -24,10 +95,13 @@ @one_instance_cache = {} @one_singleton_cache = {} @instance_ancestors_cache = {} @singleton_ancestor_cache = {} + + @one_instance_ancestors_cache = {} + @one_singleton_ancestors_cache = {} end def validate_super_class!(type_name, entry) with_super_classes = entry.decls.select {|d| d.decl.super_class } @@ -43,133 +117,113 @@ return if super_types.size == 1 raise SuperclassMismatchError.new(name: type_name, super_classes: super_types, entry: entry) end - def instance_ancestors(type_name, building_ancestors: []) - as = instance_ancestors_cache[type_name] and return as + def one_instance_ancestors(type_name) + as = one_instance_ancestors_cache[type_name] and return as - entry = env.class_decls[type_name] or raise "Unknown name for instance_ancestors: #{type_name}" + entry = env.class_decls[type_name] or raise "Unknown name for one_instance_ancestors: #{type_name}" params = entry.type_params.each.map(&:name) - args = Types::Variable.build(params) - self_ancestor = Definition::Ancestor::Instance.new(name: type_name, args: args) - RecursiveAncestorError.check!(self_ancestor, - ancestors: building_ancestors, - location: entry.primary.decl.location) - building_ancestors.push self_ancestor - - ancestors = [] - case entry when Environment::ClassEntry validate_super_class!(type_name, entry) + primary = entry.primary + super_class = primary.decl.super_class - # Super class comes last - if self_ancestor.name != BuiltinNames::BasicObject.name - 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 NoSuperclassFoundError.check!(super_name, env: env, location: primary.decl.location) - super_ancestors = instance_ancestors(super_name, building_ancestors: building_ancestors) - ancestors.unshift(*super_ancestors.apply(super_args, location: primary.decl.location)) + ancestors = OneAncestors.class_instance( + type_name: type_name, + params: params, + super_class: Definition::Ancestor::Instance.new(name: super_name, args: super_args) + ) + else + ancestors = OneAncestors.class_instance( + type_name: type_name, + params: params, + super_class: nil + ) end - - build_ancestors_mixin_self(self_ancestor, entry, ancestors: ancestors, building_ancestors: building_ancestors) - when Environment::ModuleEntry - build_ancestors_mixin_self(self_ancestor, entry, ancestors: ancestors, building_ancestors: building_ancestors) + ancestors = OneAncestors.module_instance(type_name: type_name, params: params) + entry.self_types.each do |module_self| + NoSelfTypeFoundError.check!(module_self, env: env) + ancestors.self_types.push Definition::Ancestor::Instance.new(name: module_self.name, args: module_self.args) + end + else + raise "Unexpected entry for: #{type_name}" end - building_ancestors.pop + mixin_ancestors(entry, + included_modules: ancestors.included_modules, + prepended_modules: ancestors.prepended_modules, + extended_modules: nil) - instance_ancestors_cache[type_name] = Definition::InstanceAncestors.new( - type_name: type_name, - params: params, - ancestors: ancestors - ) + one_instance_ancestors_cache[type_name] = ancestors end - def singleton_ancestors(type_name, building_ancestors: []) - as = singleton_ancestor_cache[type_name] and return as + def one_singleton_ancestors(type_name) + as = one_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) + entry = env.class_decls[type_name] or raise "Unknown name for one_singleton_ancestors: #{type_name}" - RecursiveAncestorError.check!(self_ancestor, - ancestors: building_ancestors, - location: entry.primary.decl.location) - building_ancestors.push self_ancestor - - ancestors = [] - case entry when Environment::ClassEntry - # Super class comes last - if self_ancestor.name != BuiltinNames::BasicObject.name - primary = entry.primary - super_class = primary.decl.super_class + 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 NoSuperclassFoundError.check!(super_name, env: env, location: primary.decl.location) - super_ancestors = singleton_ancestors(super_name, building_ancestors: building_ancestors) - ancestors.unshift(*super_ancestors.ancestors) + ancestors = OneAncestors.singleton( + type_name: type_name, + super_class: Definition::Ancestor::Singleton.new(name: super_name) + ) else - as = instance_ancestors(BuiltinNames::Class.name, building_ancestors: building_ancestors) - ancestors.unshift(*as.apply([], location: entry.primary.decl.location)) + ancestors = OneAncestors.singleton( + type_name: type_name, + super_class: Definition::Ancestor::Instance.new(name: BuiltinNames::Class.name, args: []) + ) end - when Environment::ModuleEntry - as = instance_ancestors(BuiltinNames::Module.name, building_ancestors: building_ancestors) - ancestors.unshift(*as.apply([], location: entry.primary.decl.location)) - end + ancestors = OneAncestors.singleton( + type_name: type_name, + super_class: Definition::Ancestor::Instance.new(name: BuiltinNames::Module.name, args: []) + ) - # Extend comes next - entry.decls.each do |d| - decl = d.decl - - decl.each_mixin do |member| - case member - when AST::Members::Extend - if member.name.class? - NoMixinFoundError.check!(member.name, env: env, member: member) - - module_ancestors = instance_ancestors(member.name, building_ancestors: building_ancestors) - ancestors.unshift(*module_ancestors.apply(member.args, location: member.location)) - end - end - end + else + raise "Unexpected entry for: #{type_name}" end - ancestors.unshift self_ancestor + mixin_ancestors(entry, + included_modules: nil, + prepended_modules: nil, + extended_modules: ancestors.extended_modules) - building_ancestors.pop - - singleton_ancestor_cache[type_name] = Definition::SingletonAncestors.new( - type_name: type_name, - ancestors: ancestors - ) + one_singleton_ancestors_cache[type_name] = ancestors end - def build_ancestors_mixin_self(self_ancestor, entry, ancestors:, building_ancestors:) - # Include comes next + def mixin_ancestors(entry, included_modules:, extended_modules:, prepended_modules:) entry.decls.each do |d| decl = d.decl align_params = Substitution.build( decl.type_params.each.map(&:name), @@ -177,46 +231,147 @@ ) decl.each_mixin do |member| case member when AST::Members::Include - if member.name.class? + if included_modules NoMixinFoundError.check!(member.name, env: env, member: member) module_name = member.name module_args = member.args.map {|type| type.sub(align_params) } - module_ancestors = instance_ancestors(module_name, building_ancestors: building_ancestors) - ancestors.unshift(*module_ancestors.apply(module_args, location: member.location)) + included_modules << Definition::Ancestor::Instance.new(name: module_name, args: module_args) end + + when AST::Members::Prepend + if prepended_modules + NoMixinFoundError.check!(member.name, env: env, member: member) + + module_name = member.name + module_args = member.args.map {|type| type.sub(align_params) } + + prepended_modules << Definition::Ancestor::Instance.new(name: module_name, args: module_args) + end + + when AST::Members::Extend + if extended_modules + NoMixinFoundError.check!(member.name, env: env, member: member) + + module_name = member.name + module_args = member.args + + extended_modules << Definition::Ancestor::Instance.new(name: module_name, args: module_args) + end end end end + end - # Self + 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 = Types::Variable.build(params) + self_ancestor = Definition::Ancestor::Instance.new(name: type_name, args: args) + + RecursiveAncestorError.check!(self_ancestor, + ancestors: building_ancestors, + location: entry.primary.decl.location) + building_ancestors.push self_ancestor + + one_ancestors = one_instance_ancestors(type_name) + + ancestors = [] + + case entry + when Environment::ClassEntry + if one_ancestors.super_class + super_name = one_ancestors.super_class.name + super_args = one_ancestors.super_class.args + + super_ancestors = instance_ancestors(super_name, building_ancestors: building_ancestors) + ancestors.unshift(*super_ancestors.apply(super_args, location: entry.primary.decl.location)) + end + end + + one_ancestors.included_modules.each do |mod| + if mod.name.class? + name = mod.name + args = mod.args + mod_ancestors = instance_ancestors(name, building_ancestors: building_ancestors) + ancestors.unshift(*mod_ancestors.apply(args, location: entry.primary.decl.location)) + end + end + ancestors.unshift(self_ancestor) - # Prepends - entry.decls.each do |d| - decl = d.decl + one_ancestors.prepended_modules.each do |mod| + if mod.name.class? + name = mod.name + args = mod.args + mod_ancestors = instance_ancestors(name, building_ancestors: building_ancestors) + ancestors.unshift(*mod_ancestors.apply(args, location: entry.primary.decl.location)) + end + end - align_params = Substitution.build(decl.type_params.each.map(&:name), - Types::Variable.build(entry.type_params.each.map(&:name))) + building_ancestors.pop - decl.each_mixin do |member| - case member - when AST::Members::Prepend - NoMixinFoundError.check!(member.name, env: env, member: member) + instance_ancestors_cache[type_name] = Definition::InstanceAncestors.new( + type_name: type_name, + params: params, + ancestors: ancestors + ) + end - module_name = member.name - module_args = member.args.map {|type| type.sub(align_params) } + def singleton_ancestors(type_name, building_ancestors: []) + as = singleton_ancestor_cache[type_name] and return as - module_ancestors = instance_ancestors(module_name, building_ancestors: building_ancestors) - ancestors.unshift(*module_ancestors.apply(module_args)) - end + 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 one_ancestors.super_class + when Definition::Ancestor::Instance + super_name = one_ancestors.super_class.name + super_args = one_ancestors.super_class.args + + super_ancestors = instance_ancestors(super_name, building_ancestors: building_ancestors) + ancestors.unshift(*super_ancestors.apply(super_args, location: entry.primary.decl.location)) + + when Definition::Ancestor::Singleton + super_name = one_ancestors.super_class.name + + super_ancestors = singleton_ancestors(super_name, building_ancestors: []) + ancestors.unshift(*super_ancestors.ancestors) + end + + one_ancestors.extended_modules.each do |mod| + if mod.name.class? + name = mod.name + args = mod.args + mod_ancestors = instance_ancestors(name, building_ancestors: building_ancestors) + ancestors.unshift(*mod_ancestors.apply(args, location: entry.primary.decl.location)) end end + + ancestors.unshift(self_ancestor) + + building_ancestors.pop + + singleton_ancestor_cache[type_name] = Definition::SingletonAncestors.new( + type_name: type_name, + ancestors: ancestors + ) end def each_member_with_accessibility(members, accessibility: :public) members.each do |member| case member @@ -836,10 +991,10 @@ super_method = methods[name] methods[name] = Definition::Method.new( super_method: super_method, accessibility: method.accessibility, - defs: method.defs.map {|defn| defn.update(type: defn.type.sub(sub)) } + defs: sub.mapping.empty? ? method.defs : method.defs.map {|defn| defn.update(type: defn.type.sub(sub)) } ) end def try_cache(type_name, cache:) cached = cache[type_name]