Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error on case statement parsing #1536

Open
kddnewton opened this issue Feb 29, 2024 · 1 comment
Open

Error on case statement parsing #1536

kddnewton opened this issue Feb 29, 2024 · 1 comment

Comments

@kddnewton
Copy link

Steps to reproduce

if foo
end

case
when :def
  if foo
  end
end

Actual Output

[debug]: Parsing ["doc", "test.rb"] with `ruby` parser
[debug]: Parsing test.rb
.../gems/yard-0.9.35/lib/yard/parser/ruby/ast_node.rb:274:in `first': cannot get the first element of beginless range (RangeError)
	from .../gems/yard-0.9.35/lib/yard/parser/ruby/ast_node.rb:274:in `line'
	from .../gems/yard-0.9.35/lib/yard/parser/ruby/ruby_parser.rb:630:in `block in insert_comments'
	from .../gems/yard-0.9.35/lib/yard/parser/ruby/ast_node.rb:212:in `traverse'
	from .../gems/yard-0.9.35/lib/yard/parser/ruby/ruby_parser.rb:621:in `insert_comments'
	from .../gems/yard-0.9.35/lib/yard/parser/ruby/ruby_parser.rb:60:in `parse'
	from .../gems/yard-0.9.35/lib/yard/parser/ruby/ruby_parser.rb:17:in `parse'
	from .../gems/yard-0.9.35/lib/yard/parser/source_parser.rb:442:in `parse'
	from .../gems/yard-0.9.35/lib/yard/parser/source_parser.rb:46:in `block in parse'
	from .../gems/yard-0.9.35/lib/yard/logging.rb:82:in `capture'
	from .../gems/yard-0.9.35/lib/yard/parser/source_parser.rb:45:in `parse'
	from .../gems/yard-0.9.35/lib/yard/parser/source_parser.rb:371:in `parse_in_order'
	from .../gems/yard-0.9.35/lib/yard/parser/source_parser.rb:114:in `block in parse'
	from .../gems/yard-0.9.35/lib/yard/logging.rb:182:in `enter_level'
	from .../gems/yard-0.9.35/lib/yard/parser/source_parser.rb:113:in `parse'
	from .../gems/yard-0.9.35/lib/yard.rb:20:in `parse'
	from .../gems/yard-0.9.35/lib/yard/cli/yardoc.rb:259:in `block in run'
	from .../gems/yard-0.9.35/lib/yard/serializers/yardoc_serializer.rb:56:in `lock_for_writing'
	from .../gems/yard-0.9.35/lib/yard/registry_store.rb:202:in `lock_for_writing'
	from .../gems/yard-0.9.35/lib/yard/registry.rb:210:in `lock_for_writing'
	from .../gems/yard-0.9.35/lib/yard/cli/yardoc.rb:258:in `run'
	from .../gems/yard-0.9.35/lib/yard/cli/command.rb:14:in `run'
	from .../gems/yard-0.9.35/lib/yard/cli/command_parser.rb:72:in `run'
	from .../gems/yard-0.9.35/lib/yard/cli/command_parser.rb:54:in `run'
	from .../gems/yard-0.9.35/bin/yard:13:in `<top (required)>'
	from .../bin/yard:25:in `load'
	from .../bin/yard:25:in `<main>'

Expected Output

Parses successfully.

Environment details:

  • OS: macOS
  • Ruby version (ruby -v): ruby 3.4.0dev (2024-02-07T11:34:48Z master 9ebaf7a8ef) [arm64-darwin23]
  • YARD version (yard -v): yard 0.9.35
@MSP-Greg
Copy link
Contributor

I checked this with Ruby 3.3. & 3.2, and they also have the problem.

Refresher on ranges, 'endless' ranges were added in Ruby 2.6, 'beginless' ranges were added in Ruby 2.7. Range#first and Range#last will throw errors if the range is 'beginless' or 'endless', respectively. Both begin and end return nil instead of raising an error. I think the original purpose was to make it easier to slice arrays.

The following patch seems to fix the errors, but I haven't had time to check further, nor write any tests...

diff --git a/lib/yard/parser/ruby/ast_node.rb b/lib/yard/parser/ruby/ast_node.rb
index c9deb3ed..ccfa9b6c 100644
--- a/lib/yard/parser/ruby/ast_node.rb
+++ b/lib/yard/parser/ruby/ast_node.rb
@@ -271,7 +271,7 @@ module YARD
 
         # @return [Fixnum] the starting line number of the node
         def line
-          line_range && line_range.first
+          line_range && (line_range.begin || line_range.end)
         end
 
         # @return [String] the first line of source represented by the node.
@@ -345,8 +345,8 @@ module YARD
           elsif !children.empty?
             f = children.first
             l = children.last
-            self.line_range = Range.new(f.line_range.first, l.line_range.last)
-            self.source_range = Range.new(f.source_range.first, l.source_range.last)
+            self.line_range = Range.new(f.line_range.begin, l.line_range.end)
+            self.source_range = Range.new(f.source_range.begin, l.source_range.end)
           elsif @fallback_line || @fallback_source
             self.line_range = @fallback_line
             self.source_range = @fallback_source
diff --git a/lib/yard/parser/ruby/ruby_parser.rb b/lib/yard/parser/ruby/ruby_parser.rb
index a7ba5fab..b8eaa7c2 100644
--- a/lib/yard/parser/ruby/ruby_parser.rb
+++ b/lib/yard/parser/ruby/ruby_parser.rb
@@ -627,11 +627,13 @@ module YARD
             end
 
             # check upwards from line before node; check node's line at the end
-            ((node.line - 1).downto(node.line - 2).to_a + [node.line]).each do |line|
-              comment = @comments[line]
-              if comment && !comment.empty?
-                add_comment(line, node)
-                break
+            if (n_l = node.line)
+              ((n_l - 1).downto(n_l - 2).to_a + [n_l]).each do |line|
+                comment = @comments[line]
+                if comment && !comment.empty?
+                  add_comment(line, node)
+                  break
+                end
               end
             end
 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants