lsegal / yard

YARD is a Ruby Documentation tool. The Y stands for "Yay!"
http://yardoc.org
MIT License
1.95k stars 398 forks source link

[0.9.27 regression] Parser gets confused by aref assignment #1420

Open dazuma opened 2 years ago

dazuma commented 2 years ago

Create the following file foo.rb:

module Foo
  a = {}

  # Earlier assignment
  a[:b] = 1

  # This constant fails to parse correctly
  X = a[:b]
end

Run yardoc with this file, using yard 0.9.27 on Ruby 3.0.3. It results in an exception similar to the following:

[error]: Exception occurred while generating 'Foo.html'
[error]: NoMethodError: undefined method `[]' for nil:NilClass
[error]: Stack trace:
    /Users/dazuma/opt/asdf/installs/ruby/3.0.3/lib/ruby/gems/3.0.0/gems/yard-0.9.27/lib/yard/templates/helpers/method_helper.rb:69:in `format_constant'
    /Users/dazuma/opt/asdf/installs/ruby/3.0.3/lib/ruby/gems/3.0.0/gems/yard-0.9.27/templates/default/module/html/constant_summary.erb:15:in `block (2 levels) in _erb_cache_18'
    /Users/dazuma/opt/asdf/installs/ruby/3.0.3/lib/ruby/gems/3.0.0/gems/yard-0.9.27/templates/default/module/html/constant_summary.erb:11:in `each'
    /Users/dazuma/opt/asdf/installs/ruby/3.0.3/lib/ruby/gems/3.0.0/gems/yard-0.9.27/templates/default/module/html/constant_summary.erb:11:in `block in _erb_cache_18'
    /Users/dazuma/opt/asdf/installs/ruby/3.0.3/lib/ruby/gems/3.0.0/gems/yard-0.9.27/templates/default/module/setup.rb:148:in `groups'
    /Users/dazuma/opt/asdf/installs/ruby/3.0.3/lib/ruby/gems/3.0.0/gems/yard-0.9.27/templates/default/module/html/constant_summary.erb:4:in `_erb_cache_18'

I've tracked this down as far as determining that the value for the constant node for X is empty due to the node having an invalid source_range where the ending position is less than the beginning. The ending position is actually coming from the previous aref from the line a[:b] = 1. The parser doesn't seem to consume that aref when it is on the LHS of an assignment operator, so when the X = a[:b] line gets parsed in RipperParser#on_aref, it's getting the ending position from the previous instance.

This appears to be a regression in 0.9.27. It does not happen in 0.9.26. Ruby 3.0.3. 2019 Macbook Pro running Monterey 12.1, although I doubt that matters.

notEthan commented 2 years ago

I am encountering this as well. without really grokking this code: https://github.com/lsegal/yard/blob/v0.9.27/lib/yard/parser/ruby/ruby_parser.rb#L373 I tried flipping the shift to a pop, since the correct entry of @map[:aref] was in the last position, which resolved my errors. but I see this change was made in https://github.com/lsegal/yard/pull/1389 and the test added there fails when it is a pop. some other fix is needed.

dduugg commented 2 years ago

đŸ‘‹ I'm the author of the PR that caused the regression, thanks for flagging it @notEthan.

Do one of you want to create a branch with a failing test? I'll take a look and see if I can land a fix things up.