chanzuckerberg / sorbet-rails

A set of tools to make the Sorbet typechecker work with Ruby on Rails seamlessly.
MIT License
638 stars 84 forks source link

`rails_rbi:jobs` raise unknown prefix error #538

Open boiiiboi opened 1 year ago

boiiiboi commented 1 year ago

Describe the bug:

After running rails_rbi:jobs, following error occured.

-- Generate sigs for ActiveJob ActiveStorage::BaseJob --
rails aborted!
unknown prefix

Steps to reproduce:

  1. Run rails_rbi:jobs

Expected behavior:

Expect to generate sigs successfully.

Versions:

supersam654 commented 1 year ago

I'm running into this too while upgrading to Ruby 3.2.

After poking around a bit, it looks like the "unknown prefix" error is coming from Parlour:

https://github.com/AaronC81/parlour/blob/baddfc5d9dbfcde15aebe88b2bff89b200ecb137/lib/parlour/rbi_generator/parameter.rb#L75-L82

Parlour appears to be struggling with "forward everything arguments" (https://bugs.ruby-lang.org/issues/16253) which ActiveJob uses for perform_now and perform_later. Notably, this syntax was introduced in Ruby 2.7.

https://github.com/rails/rails/blob/23e0345fe900dfd7edd6e8e5a7a6bd54b2a7d2ed/activejob/lib/active_job/enqueuing.rb#L28

https://github.com/rails/rails/blob/23e0345fe900dfd7edd6e8e5a7a6bd54b2a7d2ed/activejob/lib/active_job/execution.rb#L17

The method Parlour is generating RBI for is re-constructed in sorbet-rails around:

https://github.com/chanzuckerberg/sorbet-rails/blob/447ecbe4a2586ce8aa9055290d571fe34a55e27f/lib/sorbet-rails/sorbet_utils.rb#L23-L69

That method is generating invalid Parlour Parameters:

# run with `rails runner repro.rb`

class Foo
  def m(...); end
end

method_def = Foo.instance_method(:m)
params = SorbetRails::SorbetUtils.parameters_from_method_def(method_def)
params.each { |param| pp param }

Prints:

Warning: unable to parse the source of m
#<Parlour::RbiGenerator::Parameter:0x00007fc43a24d758
 @default=nil,
 @kind=:double_splat,
 @name="**",
 @type="T.untyped">
#<Parlour::RbiGenerator::Parameter:0x00007fc43a24d1b8
 @default=nil,
 @kind=:double_splat,
 @name="****",
 @type="T.untyped">
#<Parlour::RbiGenerator::Parameter:0x00007fc43a24cf38
 @default=nil,
 @kind=:block,
 @name="&&",
 @type="T.untyped">

This fix (which I'm hoping to have a PR for today if I don't get terribly sidetracked) appears to be updating parameters_from_method_def so it generates Parlour Parameters with valid names.

simoleone commented 1 year ago

This also happens when alias and alias_method are used because recent versions of ruby seem to use forward everything on the alias.