diff --git a/lib/typeprof/core/ast/meta.rb b/lib/typeprof/core/ast/meta.rb index 8452d986..914476db 100644 --- a/lib/typeprof/core/ast/meta.rb +++ b/lib/typeprof/core/ast/meta.rb @@ -240,6 +240,22 @@ def initialize(raw_node, members, kind, lenv) def subnodes = { block_body: } def attrs = { static_cpath:, members:, kind: } + # A method written in the block body (e.g. a custom initialize) + # overrides the auto-generated one, which should then be hidden + # from the RBS output. + def block_defines_method?(singleton, mid) + return false unless @block_body + found = false + @block_body.traverse do |event, node| + if event == :enter && node.is_a?(DefNode) && + node.singleton == singleton && node.mid == mid && + node.lenv.cref.cpath == @static_cpath + found = true + end + end + found + end + # Interface expected by MethodDefBox def req_positionals = @kind == :struct ? @members : [] def opt_positionals = [] diff --git a/lib/typeprof/core/service.rb b/lib/typeprof/core/service.rb index ce5ffd60..52d112e3 100644 --- a/lib/typeprof/core/service.rb +++ b/lib/typeprof/core/service.rb @@ -499,6 +499,7 @@ def dump_declarations(path) end # Output method definitions from meta nodes (StructNewNode etc.) node.boxes(:mdef) do |mdef| + next if node.is_a?(AST::StructNewNode) && node.block_defines_method?(mdef.singleton, mdef.mid) out << " " * stack.size + "def #{ mdef.singleton ? "self." : "" }#{ mdef.mid }: " + mdef.show(@options[:output_parameter_names]) end else diff --git a/scenario/misc/struct_new.rb b/scenario/misc/struct_new.rb index 9357266b..bef9f469 100644 --- a/scenario/misc/struct_new.rb +++ b/scenario/misc/struct_new.rb @@ -69,3 +69,25 @@ def self.[]: (Integer) -> Baz def set_label: -> String def ivar: -> String end + +## update +# https://github.com/ruby/typeprof/issues/458 +# A user-defined initialize in the block overrides the auto-generated one, +# so the RBS output must contain only the user-defined signature. +Pt = Struct.new(:x, :y) do + def initialize(x = 0, y = 0) + super + end +end +Pt.new +Pt.new(3, 4) + +## assert +class Pt + def x: -> Integer + def x=: (untyped) -> untyped + def y: -> Integer + def y=: (untyped) -> untyped + def self.[]: (Integer, Integer) -> Pt + def initialize: (?Integer, ?Integer) -> void +end