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

Handle ghost methods followed by undocumented methods #1261

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 42 additions & 49 deletions lib/rdoc/parser/ruby.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1804,65 +1804,58 @@ def parse_statements(container, single = NORMAL, current_method = nil,
non_comment_seen = true unless (:on_comment == tk[:kind] or :on_embdoc == tk[:kind])

case tk[:kind]
when :on_nl, :on_ignored_nl, :on_comment, :on_embdoc then
if :on_nl == tk[:kind] or :on_ignored_nl == tk[:kind]
skip_tkspace
tk = get_tk
else
past_tokens = @read.size > 1 ? @read[0..-2] : []
nl_position = 0
past_tokens.reverse.each_with_index do |read_tk, i|
if read_tk =~ /^\n$/ then
nl_position = (past_tokens.size - 1) - i
break
elsif read_tk =~ /^#.*\n$/ then
nl_position = ((past_tokens.size - 1) - i) + 1
break
end
end
comment_only_line = past_tokens[nl_position..-1].all?{ |c| c =~ /^\s+$/ }
unless comment_only_line then
tk = get_tk
when :on_nl, :on_ignored_nl then
skip_tkspace
non_comment_seen = parse_comment container, tk, comment unless
comment.empty?

keep_comment = true
container.current_line_visibility = nil

when :on_comment, :on_embdoc then
past_tokens = @read.size > 1 ? @read[0..-2] : []
nl_position = 0
past_tokens.reverse.each_with_index do |read_tk, i|
if read_tk =~ /^\n$/ then
nl_position = (past_tokens.size - 1) - i
break
elsif read_tk =~ /^#.*\n$/ then
nl_position = ((past_tokens.size - 1) - i) + 1
break
end
end
comment_only_line = past_tokens[nl_position..-1].all?{ |c| c =~ /^\s+$/ }
unless comment_only_line then
tk = get_tk
end

if tk and (:on_comment == tk[:kind] or :on_embdoc == tk[:kind]) then
if non_comment_seen then
# Look for RDoc in a comment about to be thrown away
non_comment_seen = parse_comment container, tk, comment unless
comment.empty?
if non_comment_seen then
comment = ''
comment = RDoc::Encoding.change_encoding comment, @encoding if @encoding
end

comment = ''
comment = RDoc::Encoding.change_encoding comment, @encoding if @encoding
end
line_no = nil
while tk and (:on_comment == tk[:kind] or :on_embdoc == tk[:kind]) do
comment_body = retrieve_comment_body(tk)
line_no = tk[:line_no] if comment.empty?
comment += comment_body
comment << "\n" unless comment_body =~ /\n\z/

line_no = nil
while tk and (:on_comment == tk[:kind] or :on_embdoc == tk[:kind]) do
comment_body = retrieve_comment_body(tk)
line_no = tk[:line_no] if comment.empty?
comment += comment_body
comment << "\n" unless comment_body =~ /\n\z/

if comment_body.size > 1 && comment_body =~ /\n\z/ then
skip_tkspace_without_nl # leading spaces
end
tk = get_tk
if comment_body.size > 1 && comment_body =~ /\n\z/ then
skip_tkspace_without_nl # leading spaces
end
tk = get_tk
end

comment = new_comment comment, line_no
comment = new_comment comment, line_no

unless comment.empty? then
look_for_directives_in container, comment
unless comment.empty? then
look_for_directives_in container, comment

if container.done_documenting then
throw :eof if RDoc::TopLevel === container
container.ongoing_visibility = save_visibility
end
if container.done_documenting then
throw :eof if RDoc::TopLevel === container
container.ongoing_visibility = save_visibility
end

keep_comment = true
else
non_comment_seen = true
end

unget_tk tk
Expand Down
74 changes: 74 additions & 0 deletions test/rdoc/test_rdoc_parser_ruby.rb
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,80 @@ class Foo
assert_equal 2, foo.method_list.length
end

def test_parse_comments_followed_by_linebreaks
util_parser <<-CLASS
class Foo
# Ignored comment

##
# :method: ghost
# This is a ghost method

# Comment followed by a method
def regular
end

##
# :method: another_ghost
# This is another ghost method

# Comment followed by a linebreak

def regular2
end
end
CLASS

tk = @parser.get_tk

@parser.parse_class @top_level, RDoc::Parser::Ruby::NORMAL, tk, @comment

foo = @top_level.classes.first
assert_equal 'Foo', foo.full_name

ghost = foo.method_list.first
assert_equal 'Foo#ghost', ghost.full_name
assert_equal 'This is a ghost method', ghost.comment.to_s

regular = foo.method_list[1]
assert_equal 'Foo#regular', regular.full_name
assert_equal 'Comment followed by a method', regular.comment.to_s

another_ghost = foo.method_list[2]
assert_equal 'Foo#another_ghost', another_ghost.full_name
assert_equal 'This is another ghost method', another_ghost.comment.to_s

regular2 = foo.method_list[3]
assert_equal 'Foo#regular2', regular2.full_name
assert_equal 'Comment followed by a linebreak', regular2.comment.to_s
end

def test_parse_ghost_method_followed_by_undocumented_method
util_parser <<-'CLASS'
class Foo
##
# :method: ghost
# This is a ghost method

def baz() end
end
CLASS

tk = @parser.get_tk

@parser.parse_class @top_level, RDoc::Parser::Ruby::NORMAL, tk, @comment

foo = @top_level.classes.first
assert_equal 'Foo', foo.full_name

ghost = foo.method_list.first
assert_equal 'Foo#ghost', ghost.full_name
assert_equal 'This is a ghost method', ghost.comment.to_s

baz = foo.method_list[1]
assert_equal 'Foo#baz', baz.full_name
end

def test_parse_class_nodoc
comment = RDoc::Comment.new "##\n# my class\n", @top_level

Expand Down
Loading