AaronC81/sord

Asterisk parameters are lost

connorshea opened this issue · 5 comments

Describe the bug
Apparently Ruby accepts * as a parameter, for some reason. Sord doesn't currently handle this correctly.

To Reproduce
Run Sord on a file like so (these two methods are from optparse.rb https://github.com/ruby/ruby/blob/trunk/lib/optparse.rb):

# typed: true
# test
module Test
  def self.incompatible_argument_styles(*)
  end

  def convert(opt = nil, val = nil, *)
  end
end

Expected behavior

# typed: strong
module Test
  sig { params(_: T.untyped).returns(T.untyped) }
  def self.incompatible_argument_styles(*_); end

  sig { params(opt: T.untyped, val: T.untyped, _: T.untyped).returns(T.untyped) }
  def convert(opt = nil, val = nil, *_); end
end

Actual behavior

# typed: strong
module Test
  sig { returns(T.untyped) }
  def self.incompatible_argument_styles; end

  sig { params(opt: T.untyped, val: T.untyped).returns(T.untyped) }
  def convert(opt = nil, val = nil); end
end

The reason I say it should return *_ is because that's how it was resolved in sorbet. That's just a limitation of Sorbet since the params would strip the *, so it needs to be represented as *_.

As is obligatory, here's a spec

it 'correctly generates constants in nested classes' do
  YARD.parse_string(<<-RUBY)
    class A
      def foo(*); end
      
      def bar(baz, *); end
    end
    RUBY
    
    expect(subject.generate.strip).to eq fix_heredoc(<<-RUBY)
    # typed: strong
    class A
      # sord omit - no YARD type given for "_", using T.untyped
      # sord omit - no YARD return type given, using T.untyped
      sig { params(_: T.untyped).returns(T.untyped) }
      def foo(*_); end
      
      # sord omit - no YARD type given for "_", using T.untyped
      # sord omit - no YARD type given for "baz", using T.untyped
      # sord omit - no YARD return type given, using T.untyped
      sig { params(baz: T.untyped, _: T.untyped).returns(T.untyped) }
      def bar(baz, *_); end
    end
  RUBY
end

I guess this is a problem with YARD?

Screen Shot 2019-07-23 at 7 48 56 PM

irb(main):001:0> def meth(x, y, z); end
=> :meth
irb(main):002:0> method(:meth).parameters
=> [[:req, :x], [:req, :y], [:req, :z]]
irb(main):003:0> def meth2(x, y, z, *); end
=> :meth2
irb(main):004:0> method(:meth2).parameters
=> [[:req, :x], [:req, :y], [:req, :z], [:rest]]

Nice catch - this seems like a YARD problem. I can't find an existing issue about this so I'll open one.

I'm not sure if this is related, but it seems like ... is also stripped. I'm assuming it's a YARD problem too.