diff --git a/lib/rbs/definition_builder.rb b/lib/rbs/definition_builder.rb index a4eece16b..255a9077c 100644 --- a/lib/rbs/definition_builder.rb +++ b/lib/rbs/definition_builder.rb @@ -31,9 +31,10 @@ def ensure_namespace!(namespace, location:) end def define_interface(definition, type_name, subst) - included_interfaces = ancestor_builder.one_interface_ancestors(type_name).included_interfaces or raise - interface_methods = interface_methods(included_interfaces) + included_interfaces = ancestor_builder.interface_ancestors(type_name).ancestors #: Array[Definition::Ancestor::Instance] + included_interfaces = included_interfaces.reject {|ancestor| ancestor.source == nil } + interface_methods = interface_methods(included_interfaces) methods = method_builder.build_interface(type_name) import_methods(definition, type_name, methods, interface_methods, subst) @@ -55,7 +56,6 @@ def build_interface(type_name) Definition.new(type_name: type_name, entry: entry, self_type: self_type, ancestors: ancestors).tap do |definition| methods = method_builder.build_interface(type_name) one_ancestors = ancestor_builder.one_interface_ancestors(type_name) - validate_type_params(definition, methods: methods, ancestors: one_ancestors) define_interface(definition, type_name, subst) @@ -94,7 +94,12 @@ def define_instance(definition, type_name, subst) define_instance(definition, mod.name, subst + tapp_subst(mod.name, mod.args)) end - interface_methods = interface_methods(one_ancestors.each_included_interface.to_a) + all_interfaces = one_ancestors.each_included_interface.flat_map do |interface| + other_interfaces = ancestor_builder.interface_ancestors(interface.name).ancestors #: Array[Definition::Ancestor::Instance] + other_interfaces = other_interfaces.select {|ancestor| ancestor.source } + [interface, *other_interfaces] + end + interface_methods = interface_methods(all_interfaces) import_methods(definition, type_name, methods, interface_methods, subst) one_ancestors.each_prepended_module do |mod| @@ -219,6 +224,7 @@ def build_singleton0(type_name) Definition.new(type_name: type_name, entry: entry, self_type: self_type, ancestors: ancestors).tap do |definition| one_ancestors = ancestor_builder.one_singleton_ancestors(type_name) + methods = method_builder.build_singleton(type_name) if super_class = one_ancestors.super_class case super_class @@ -233,8 +239,13 @@ def build_singleton0(type_name) definition.class_variables.merge!(defn.class_variables) end - one_ancestors = ancestor_builder.one_singleton_ancestors(type_name) - methods = method_builder.build_singleton(type_name) + all_interfaces = one_ancestors.each_extended_interface.flat_map do |interface| + other_interfaces = ancestor_builder.interface_ancestors(interface.name).ancestors #: Array[Definition::Ancestor::Instance] + other_interfaces = other_interfaces.select {|ancestor| ancestor.source } + [interface, *other_interfaces] + end + interface_methods = interface_methods(all_interfaces) + import_methods(definition, type_name, methods, interface_methods, Substitution.new) one_ancestors.each_extended_module do |mod| mod.args.each do |arg| @@ -279,7 +290,7 @@ def build_singleton0(type_name) def build_singleton(type_name) type_name = env.normalize_module_name(type_name) - + try_cache type_name, cache: singleton_cache do entry = env.class_decls[type_name] or raise "Unknown name for build_singleton: #{type_name}" ensure_namespace!(type_name.namespace, location: entry.decls[0].decl.location) @@ -683,8 +694,8 @@ def define_method(methods, definition, method, subst, defined_in:, implemented_i Definition::Method::TypeDef.new( type: method_type, member: original, - defined_in: definition.type_name, - implemented_in: definition.type_name + defined_in: defined_in, + implemented_in: implemented_in ) ], accessibility: method.accessibility, @@ -713,7 +724,7 @@ def define_method(methods, definition, method, subst, defined_in:, implemented_i method_definition = Definition::Method.new( super_method: super_method, defs: existing_method.defs.map do |defn| - defn.update(implemented_in: definition.type_name) + defn.update(implemented_in: implemented_in) end, accessibility: existing_method.accessibility, alias_of: existing_method.alias_of @@ -725,8 +736,8 @@ def define_method(methods, definition, method, subst, defined_in:, implemented_i type_def = Definition::Method::TypeDef.new( type: subst.empty? ? overload.method_type : overload.method_type.sub(subst), member: overloading_def, - defined_in: definition.type_name, - implemented_in: definition.type_name + defined_in: defined_in, + implemented_in: implemented_in ) method_definition.defs.unshift(type_def) diff --git a/lib/rbs/definition_builder/ancestor_builder.rb b/lib/rbs/definition_builder/ancestor_builder.rb index e452abd63..5293b8d85 100644 --- a/lib/rbs/definition_builder/ancestor_builder.rb +++ b/lib/rbs/definition_builder/ancestor_builder.rb @@ -432,8 +432,9 @@ def instance_ancestors(type_name, building_ancestors: []) super_name = super_class.name super_args = 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)) + super_ancestors = instance_ancestors(super_name, building_ancestors: building_ancestors).apply(super_args, location: entry.primary.decl.location) + super_ancestors.map! {|ancestor| fill_ancestor_source(ancestor, name: super_name, source: :super) } + ancestors.unshift(*super_ancestors) end end @@ -450,8 +451,9 @@ def instance_ancestors(type_name, building_ancestors: []) included_modules.each do |mod| name = mod.name arg_types = mod.args - mod_ancestors = instance_ancestors(name, building_ancestors: building_ancestors) - ancestors.unshift(*mod_ancestors.apply(arg_types, location: entry.primary.decl.location)) + mod_ancestors = instance_ancestors(name, building_ancestors: building_ancestors).apply(arg_types, location: entry.primary.decl.location) + mod_ancestors.map! {|ancestor| fill_ancestor_source(ancestor, name: name, source: mod.source) } + ancestors.unshift(*mod_ancestors) end end @@ -461,8 +463,9 @@ def instance_ancestors(type_name, building_ancestors: []) prepended_modules.each do |mod| name = mod.name arg_types = mod.args - mod_ancestors = instance_ancestors(name, building_ancestors: building_ancestors) - ancestors.unshift(*mod_ancestors.apply(arg_types, location: entry.primary.decl.location)) + mod_ancestors = instance_ancestors(name, building_ancestors: building_ancestors).apply(arg_types, location: entry.primary.decl.location) + mod_ancestors.map! {|ancestor| fill_ancestor_source(ancestor, name: name, source: mod.source) } + ancestors.unshift(*mod_ancestors) end end @@ -495,8 +498,9 @@ def singleton_ancestors(type_name, building_ancestors: []) super_name = super_class.name super_args = 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)) + super_ancestors = instance_ancestors(super_name, building_ancestors: building_ancestors).apply(super_args, location: entry.primary.decl.location) + 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 @@ -509,8 +513,9 @@ def singleton_ancestors(type_name, building_ancestors: []) extended_modules.each do |mod| 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)) + mod_ancestors = instance_ancestors(name, building_ancestors: building_ancestors).apply(args, location: entry.primary.decl.location) + mod_ancestors.map! {|ancestor| fill_ancestor_source(ancestor, name: name, source: mod.source) } + ancestors.unshift(*mod_ancestors) end ancestors.unshift(self_ancestor) @@ -541,9 +546,9 @@ def interface_ancestors(type_name, building_ancestors: []) included_interfaces = one_ancestors.included_interfaces or raise included_interfaces.each do |a| - included_ancestors = interface_ancestors(a.name, building_ancestors: building_ancestors) - - ancestors.unshift(*included_ancestors.apply(a.args, location: entry.decl.location)) + included_ancestors = interface_ancestors(a.name, building_ancestors: building_ancestors).apply(a.args, location: entry.decl.location) + included_ancestors.map! {|ancestor| fill_ancestor_source(ancestor, name: a.name, source: a.source) } + ancestors.unshift(*included_ancestors) end ancestors.unshift(self_ancestor) @@ -555,6 +560,19 @@ def interface_ancestors(type_name, building_ancestors: []) ancestors: ancestors ) end + + 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 end end end diff --git a/sig/ancestor_builder.rbs b/sig/ancestor_builder.rbs index 23691c34a..5b1d78faa 100644 --- a/sig/ancestor_builder.rbs +++ b/sig/ancestor_builder.rbs @@ -154,6 +154,10 @@ module RBS prepended_modules: Array[Definition::Ancestor::Instance]?, extended_modules: Array[Definition::Ancestor::Instance]?, extended_interfaces: Array[Definition::Ancestor::Instance]?) -> void + + # Fill `#source` of instance ancestor if `ancestor.name == name` and its `source` is `nil` + # + def fill_ancestor_source: (Definition::Ancestor::t, name: TypeName, source: Definition::Ancestor::Instance::source) -> Definition::Ancestor::t end end end diff --git a/sig/definition.rbs b/sig/definition.rbs index 7079688d9..055afd8b5 100644 --- a/sig/definition.rbs +++ b/sig/definition.rbs @@ -83,8 +83,9 @@ module RBS type t = Instance | Singleton class Instance - type source = :super | nil - | AST::Members::Include | AST::Members::Extend | AST::Members::Prepend + type source = :super # Inheritance + | nil # Itself + | AST::Members::Include | AST::Members::Extend | AST::Members::Prepend # AST | AST::Declarations::Module::Self attr_reader name: TypeName diff --git a/sig/definition_builder.rbs b/sig/definition_builder.rbs index 73afba4ed..e2b6f3e53 100644 --- a/sig/definition_builder.rbs +++ b/sig/definition_builder.rbs @@ -142,6 +142,10 @@ module RBS # def define_instance: (Definition definition, TypeName type_name, Substitution subst) -> void + # Updates `definition` with methods defined in an interface `type_name` + # + # It processes includes recursively + # def define_interface: (Definition definition, TypeName type_name, Substitution subst) -> void # Returns a substitution that corresponds to type application diff --git a/test/rbs/ancestor_builder_test.rb b/test/rbs/ancestor_builder_test.rb index 50eb1228d..2bb50923a 100644 --- a/test/rbs/ancestor_builder_test.rb +++ b/test/rbs/ancestor_builder_test.rb @@ -274,38 +274,100 @@ module Bar[Y, Z] builder.instance_ancestors(type_name("::Object")).tap do |a| assert_equal type_name("::Object"), a.type_name assert_equal [], a.params - assert_equal [ - Ancestor::Instance.new(name: BuiltinNames::Object.name, args: [], source: nil), - Ancestor::Instance.new(name: BuiltinNames::Kernel.name, args: [], source: nil), - Ancestor::Instance.new(name: BuiltinNames::BasicObject.name, args: [], source: nil) - ], - a.ancestors + + assert_equal 3, a.ancestors.size + a.ancestors[0].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal BuiltinNames::Object.name, ancestor.name + assert_equal [], ancestor.args + assert_nil ancestor.source + end + a.ancestors[1].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal BuiltinNames::Kernel.name, ancestor.name + assert_equal [], ancestor.args + assert_instance_of AST::Members::Include, ancestor.source + end + a.ancestors[2].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal BuiltinNames::BasicObject.name, ancestor.name + assert_equal [], ancestor.args + assert_equal :super, ancestor.source + end end builder.instance_ancestors(type_name("::String")).tap do |a| assert_equal type_name("::String"), a.type_name assert_equal [], a.params - assert_equal [ - Ancestor::Instance.new(name: BuiltinNames::String.name, args: [], source: nil), - Ancestor::Instance.new(name: BuiltinNames::Comparable.name, args: [], source: nil), - Ancestor::Instance.new(name: BuiltinNames::Object.name, args: [], source: nil), - Ancestor::Instance.new(name: BuiltinNames::Kernel.name, args: [], source: nil), - Ancestor::Instance.new(name: BuiltinNames::BasicObject.name, args: [], source: nil) - ], - a.ancestors + + assert_equal 5, a.ancestors.size + a.ancestors[0].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal BuiltinNames::String.name, ancestor.name + assert_equal [], ancestor.args + assert_nil ancestor.source + end + a.ancestors[1].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal BuiltinNames::Comparable.name, ancestor.name + assert_equal [], ancestor.args + assert_instance_of AST::Members::Include, ancestor.source + end + a.ancestors[2].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal BuiltinNames::Object.name, ancestor.name + assert_equal [], ancestor.args + assert_equal :super, ancestor.source + end + a.ancestors[3].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal BuiltinNames::Kernel.name, ancestor.name + assert_equal [], ancestor.args + assert_instance_of AST::Members::Include, ancestor.source + end + a.ancestors[4].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal BuiltinNames::BasicObject.name, ancestor.name + assert_equal [], ancestor.args + assert_equal :super, ancestor.source + end end builder.instance_ancestors(type_name("::Foo")).tap do |a| assert_equal type_name("::Foo"), a.type_name assert_equal [:X], a.params - assert_equal [ - Ancestor::Instance.new(name: type_name("::Foo"), args: [Types::Variable.build(:X)], source: nil), - Ancestor::Instance.new(name: type_name("::Bar"), args: [Types::Variable.build(:X), parse_type("::String")], source: nil), - Ancestor::Instance.new(name: BuiltinNames::Object.name, args: [], source: nil), - Ancestor::Instance.new(name: BuiltinNames::Kernel.name, args: [], source: nil), - Ancestor::Instance.new(name: BuiltinNames::BasicObject.name, args: [], source: nil) - ], - a.ancestors + + assert_equal 5, a.ancestors.size + a.ancestors[0].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal TypeName("::Foo"), ancestor.name + assert_equal [Types::Variable.build(:X)], ancestor.args + assert_nil ancestor.source + end + a.ancestors[1].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal TypeName("::Bar"), ancestor.name + assert_equal [Types::Variable.build(:X), parse_type("::String")], ancestor.args + assert_instance_of AST::Members::Include, ancestor.source + end + a.ancestors[2].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal BuiltinNames::Object.name, ancestor.name + assert_equal [], ancestor.args + assert_equal :super, ancestor.source + end + a.ancestors[3].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal BuiltinNames::Kernel.name, ancestor.name + assert_equal [], ancestor.args + assert_instance_of AST::Members::Include, ancestor.source + end + a.ancestors[4].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal BuiltinNames::BasicObject.name, ancestor.name + assert_equal [], ancestor.args + assert_equal :super, ancestor.source + end end end end @@ -364,53 +426,153 @@ module Bar[Y, Z] builder.singleton_ancestors(type_name("::BasicObject")).tap do |a| assert_equal type_name("::BasicObject"), a.type_name - assert_equal [ - Ancestor::Singleton.new(name: BuiltinNames::BasicObject.name), - Ancestor::Instance.new(name: BuiltinNames::Class.name, args: [], source: nil), - Ancestor::Instance.new(name: BuiltinNames::Module.name, args: [], source: nil), - Ancestor::Instance.new(name: BuiltinNames::Object.name, args: [], source: nil), - Ancestor::Instance.new(name: BuiltinNames::Kernel.name, args: [], source: nil), - Ancestor::Instance.new(name: BuiltinNames::BasicObject.name, args: [], source: nil), - ], a.ancestors + + assert_equal 6, a.ancestors.size + assert_equal Ancestor::Singleton.new(name: BuiltinNames::BasicObject.name), a.ancestors[0] + a.ancestors[1].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal BuiltinNames::Class.name, ancestor.name + assert_equal [], ancestor.args + assert_equal :super, ancestor.source + end + a.ancestors[2].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal BuiltinNames::Module.name, ancestor.name + assert_equal [], ancestor.args + assert_equal :super, ancestor.source + end + a.ancestors[3].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal BuiltinNames::Object.name, ancestor.name + assert_equal [], ancestor.args + assert_equal :super, ancestor.source + end + a.ancestors[4].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal BuiltinNames::Kernel.name, ancestor.name + assert_equal [], ancestor.args + assert_instance_of AST::Members::Include, ancestor.source + end + a.ancestors[5].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal BuiltinNames::BasicObject.name, ancestor.name + assert_equal [], ancestor.args + assert_equal :super, ancestor.source + end end builder.singleton_ancestors(type_name("::Object")).tap do |a| assert_equal type_name("::Object"), a.type_name - assert_equal [ - Ancestor::Singleton.new(name: BuiltinNames::Object.name), - Ancestor::Singleton.new(name: BuiltinNames::BasicObject.name), - Ancestor::Instance.new(name: BuiltinNames::Class.name, args: [], source: nil), - Ancestor::Instance.new(name: BuiltinNames::Module.name, args: [], source: nil), - Ancestor::Instance.new(name: BuiltinNames::Object.name, args: [], source: nil), - Ancestor::Instance.new(name: BuiltinNames::Kernel.name, args: [], source: nil), - Ancestor::Instance.new(name: BuiltinNames::BasicObject.name, args: [], source: nil), - ], a.ancestors + + assert_equal 7, a.ancestors.size + assert_equal Ancestor::Singleton.new(name: BuiltinNames::Object.name), a.ancestors[0] + assert_equal Ancestor::Singleton.new(name: BuiltinNames::BasicObject.name), a.ancestors[1] + a.ancestors[2].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal BuiltinNames::Class.name, ancestor.name + assert_equal [], ancestor.args + assert_equal :super, ancestor.source + end + a.ancestors[3].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal BuiltinNames::Module.name, ancestor.name + assert_equal [], ancestor.args + assert_equal :super, ancestor.source + end + a.ancestors[4].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal BuiltinNames::Object.name, ancestor.name + assert_equal [], ancestor.args + assert_equal :super, ancestor.source + end + a.ancestors[5].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal BuiltinNames::Kernel.name, ancestor.name + assert_equal [], ancestor.args + assert_instance_of AST::Members::Include, ancestor.source + end + a.ancestors[6].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal BuiltinNames::BasicObject.name, ancestor.name + assert_equal [], ancestor.args + assert_equal :super, ancestor.source + end end builder.singleton_ancestors(type_name("::Kernel")).tap do |a| assert_equal type_name("::Kernel"), a.type_name - assert_equal [ - Ancestor::Singleton.new(name: BuiltinNames::Kernel.name), - Ancestor::Instance.new(name: BuiltinNames::Module.name, args: [], source: nil), - Ancestor::Instance.new(name: BuiltinNames::Object.name, args: [], source: nil), - Ancestor::Instance.new(name: BuiltinNames::Kernel.name, args: [], source: nil), - Ancestor::Instance.new(name: BuiltinNames::BasicObject.name, args: [], source: nil), - ], a.ancestors + + assert_equal 5, a.ancestors.size + assert_equal Ancestor::Singleton.new(name: BuiltinNames::Kernel.name), a.ancestors[0] + a.ancestors[1].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal BuiltinNames::Module.name, ancestor.name + assert_equal [], ancestor.args + assert_equal :super, ancestor.source + end + a.ancestors[2].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal BuiltinNames::Object.name, ancestor.name + assert_equal [], ancestor.args + assert_equal :super, ancestor.source + end + a.ancestors[3].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal BuiltinNames::Kernel.name, ancestor.name + assert_equal [], ancestor.args + assert_instance_of AST::Members::Include, ancestor.source + end + a.ancestors[4].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal BuiltinNames::BasicObject.name, ancestor.name + assert_equal [], ancestor.args + assert_equal :super, ancestor.source + end end builder.singleton_ancestors(type_name("::Foo")).tap do |a| assert_equal type_name("::Foo"), a.type_name - assert_equal [ - Ancestor::Singleton.new(name: type_name("::Foo")), - Ancestor::Instance.new(name: type_name("::Bar"), args: [parse_type("::String"), parse_type("::Symbol")], source: nil), - Ancestor::Singleton.new(name: BuiltinNames::Object.name), - Ancestor::Singleton.new(name: BuiltinNames::BasicObject.name), - Ancestor::Instance.new(name: BuiltinNames::Class.name, args: [], source: nil), - Ancestor::Instance.new(name: BuiltinNames::Module.name, args: [], source: nil), - Ancestor::Instance.new(name: BuiltinNames::Object.name, args: [], source: nil), - Ancestor::Instance.new(name: BuiltinNames::Kernel.name, args: [], source: nil), - Ancestor::Instance.new(name: BuiltinNames::BasicObject.name, args: [], source: nil), - ], a.ancestors + + assert_equal 9, a.ancestors.size + assert_equal Ancestor::Singleton.new(name: type_name("::Foo")), a.ancestors[0] + a.ancestors[1].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal type_name("::Bar"), ancestor.name + assert_equal [parse_type("::String"), parse_type("::Symbol")], ancestor.args + assert_instance_of AST::Members::Extend, ancestor.source + end + assert_equal Ancestor::Singleton.new(name: BuiltinNames::Object.name), a.ancestors[2] + assert_equal Ancestor::Singleton.new(name: BuiltinNames::BasicObject.name), a.ancestors[3] + a.ancestors[4].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal BuiltinNames::Class.name, ancestor.name + assert_equal [], ancestor.args + assert_equal :super, ancestor.source + end + a.ancestors[5].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal BuiltinNames::Module.name, ancestor.name + assert_equal [], ancestor.args + assert_equal :super, ancestor.source + end + a.ancestors[6].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal BuiltinNames::Object.name, ancestor.name + assert_equal [], ancestor.args + assert_equal :super, ancestor.source + end + a.ancestors[7].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal BuiltinNames::Kernel.name, ancestor.name + assert_equal [], ancestor.args + assert_instance_of AST::Members::Include, ancestor.source + end + a.ancestors[8].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal BuiltinNames::BasicObject.name, ancestor.name + assert_equal [], ancestor.args + assert_equal :super, ancestor.source + end end end end @@ -437,12 +599,26 @@ def test_interface_ancestors assert_instance_of Definition::InstanceAncestors, a assert_equal type_name("::_I3"), a.type_name assert_equal [:X], a.params - assert_equal [ - Ancestor::Instance.new(name: type_name("::_I3"), args: [parse_type("X", variables: [:X])], source: nil), - Ancestor::Instance.new(name: type_name("::_I2"), args: [parse_type("::Integer"), parse_type("X", variables: [:X])], source: nil), - Ancestor::Instance.new(name: type_name("::_I1"), args: [parse_type("::Hash[::Integer, X]", variables: [:X])], source: nil) - ], - a.ancestors + + assert_equal 3, a.ancestors.size + a.ancestors[0].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal type_name("::_I3"), ancestor.name + assert_equal [parse_type("X", variables: [:X])], ancestor.args + assert_nil ancestor.source + end + a.ancestors[1].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal type_name("::_I2"), ancestor.name + assert_equal [parse_type("::Integer"), parse_type("X", variables: [:X])], ancestor.args + assert_instance_of AST::Members::Include, ancestor.source + end + a.ancestors[2].tap do |ancestor| + assert_instance_of Ancestor::Instance, ancestor + assert_equal type_name("::_I1"), ancestor.name + assert_equal [parse_type("::Hash[::Integer, X]", variables: [:X])], ancestor.args + assert_instance_of AST::Members::Include, ancestor.source + end end end end diff --git a/test/rbs/definition_builder_test.rb b/test/rbs/definition_builder_test.rb index 09ecca7a8..76212732c 100644 --- a/test/rbs/definition_builder_test.rb +++ b/test/rbs/definition_builder_test.rb @@ -2395,4 +2395,110 @@ module K = Kernel end end end + + def test_build_instance_interface_mixin_transitive + SignatureManager.new do |manager| + manager.files[Pathname("foo.rbs")] = <<~EOF + interface _X + def x: () -> void + + include _Y + end + + interface _Y + def y: () -> void + + include _Z + end + + interface _Z + def z: () -> void + end + + class A + include _X + extend _X + end + EOF + + manager.build do |env| + builder = DefinitionBuilder.new(env: env) + + builder.build_instance(type_name("::A")).tap do |definition| + assert_instance_of Definition, definition + + assert_operator Set[:x, :y, :z], :<=, Set.new(definition.methods.keys) + end + end + + manager.build do |env| + builder = DefinitionBuilder.new(env: env) + + builder.build_singleton(type_name("::A")).tap do |definition| + assert_instance_of Definition, definition + + assert_operator Set[:x, :y, :z], :<=, Set.new(definition.methods.keys) + end + end + + manager.build do |env| + builder = DefinitionBuilder.new(env: env) + + builder.build_interface(type_name("::_X")).tap do |definition| + assert_instance_of Definition, definition + + assert_operator Set[:x, :y, :z], :<=, Set.new(definition.methods.keys) + end + end + end + end + + def test_mixin_method_owners + SignatureManager.new do |manager| + manager.files[Pathname("foo.rbs")] = <<~EOF + class A + include B + end + + module B + def b: () -> void + + attr_reader c: String + + alias d b + + def __id__: () -> void + | ... + end + EOF + + manager.build do |env| + builder = DefinitionBuilder.new(env: env) + + builder.build_instance(type_name("::A")).tap do |definition| + assert_instance_of Definition, definition + + definition.methods[:b].tap do |method| + assert_equal [TypeName("::B")], method.defs.map(&:defined_in) + assert_equal [TypeName("::B")], method.defs.map(&:implemented_in) + end + + definition.methods[:c].tap do |method| + assert_equal [TypeName("::B")], method.defs.map(&:defined_in) + assert_equal [TypeName("::B")], method.defs.map(&:implemented_in) + end + + definition.methods[:d].tap do |method| + assert_equal [TypeName("::B")], method.defs.map(&:defined_in) + assert_equal [TypeName("::B")], method.defs.map(&:implemented_in) + end + + definition.methods[:__id__].tap do |method| + assert_equal [TypeName("::B"), TypeName("::Object")], method.defs.map(&:defined_in) + assert_equal [TypeName("::B"), TypeName("::B")], method.defs.map(&:implemented_in) + end + end + end + end + end end