Skip to content

Commit 3231430

Browse files
committed
Ignore visibility method, attr definition, module_function within block
We need to ignore these within `Module.new do end` and any other block because it might be a metaprogramming block.
1 parent 96f9312 commit 3231430

File tree

2 files changed

+105
-9
lines changed

2 files changed

+105
-9
lines changed

lib/rdoc/parser/prism_ruby.rb

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class RDoc::Parser::PrismRuby < RDoc::Parser
1616
parse_files_matching(/\.rbw?$/) if ENV['RDOC_USE_PRISM_PARSER']
1717

1818
attr_accessor :visibility
19-
attr_reader :container, :singleton
19+
attr_reader :container, :singleton, :in_proc_block
2020

2121
def initialize(top_level, content, options, stats)
2222
super
@@ -480,7 +480,6 @@ def add_attributes(names, rw, line_no)
480480
# Adds includes/extends. Module name is resolved to full before adding.
481481

482482
def add_includes_extends(names, rdoc_class, line_no) # :nodoc:
483-
return if @in_proc_block
484483
comment, directives = consecutive_comment(line_no)
485484
handle_code_object_directives(@container, directives) if directives
486485
names.each do |name|
@@ -508,8 +507,6 @@ def add_extends(names, line_no) # :nodoc:
508507
# Adds a method defined by `def` syntax
509508

510509
def add_method(method_name, receiver_name:, receiver_fallback_type:, visibility:, singleton:, params:, calls_super:, block_params:, tokens:, start_line:, args_end_line:, end_line:)
511-
return if @in_proc_block
512-
513510
receiver = receiver_name ? find_or_create_module_path(receiver_name, receiver_fallback_type) : @container
514511
comment, directives = consecutive_comment(start_line)
515512
handle_code_object_directives(@container, directives) if directives
@@ -775,7 +772,8 @@ def visit_call_node(node)
775772

776773
def visit_block_node(node)
777774
@scanner.with_in_proc_block do
778-
# include, extend and method definition inside block are not documentable
775+
# include, extend and method definition inside block are not documentable.
776+
# visibility methods and attribute definition methods should be ignored inside block.
779777
super
780778
end
781779
end
@@ -859,6 +857,8 @@ def visit_def_node(node)
859857
end_line = node.location.end_line
860858
@scanner.process_comments_until(start_line - 1)
861859

860+
return if @scanner.in_proc_block
861+
862862
case node.receiver
863863
when Prism::NilNode, Prism::TrueNode, Prism::FalseNode
864864
visibility = :public
@@ -997,19 +997,20 @@ def _visit_call_require(call_node)
997997

998998
def _visit_call_module_function(call_node)
999999
yield
1000-
return if @scanner.singleton
1000+
return if @scanner.in_proc_block || @scanner.singleton
10011001
names = visibility_method_arguments(call_node, singleton: false)&.map(&:to_s)
10021002
@scanner.change_method_to_module_function(names) if names
10031003
end
10041004

10051005
def _visit_call_public_private_class_method(call_node, visibility)
10061006
yield
1007-
return if @scanner.singleton
1007+
return if @scanner.in_proc_block || @scanner.singleton
10081008
names = visibility_method_arguments(call_node, singleton: true)
10091009
@scanner.change_method_visibility(names, visibility, singleton: true) if names
10101010
end
10111011

10121012
def _visit_call_public_private_protected(call_node, visibility)
1013+
return if @scanner.in_proc_block
10131014
arguments_node = call_node.arguments
10141015
if arguments_node.nil? # `public` `private`
10151016
@scanner.visibility = visibility
@@ -1021,12 +1022,16 @@ def _visit_call_public_private_protected(call_node, visibility)
10211022
end
10221023

10231024
def _visit_call_alias_method(call_node)
1025+
return if @scanner.in_proc_block
1026+
10241027
new_name, old_name, *rest = symbol_arguments(call_node)
10251028
return unless old_name && new_name && rest.empty?
10261029
@scanner.add_alias_method(old_name.to_s, new_name.to_s, call_node.location.start_line)
10271030
end
10281031

10291032
def _visit_call_include(call_node)
1033+
return if @scanner.in_proc_block
1034+
10301035
names = constant_arguments_names(call_node)
10311036
line_no = call_node.location.start_line
10321037
return unless names
@@ -1039,26 +1044,30 @@ def _visit_call_include(call_node)
10391044
end
10401045

10411046
def _visit_call_extend(call_node)
1047+
return if @scanner.in_proc_block
1048+
10421049
names = constant_arguments_names(call_node)
10431050
@scanner.add_extends(names, call_node.location.start_line) if names && !@scanner.singleton
10441051
end
10451052

10461053
def _visit_call_public_constant(call_node)
1047-
return if @scanner.singleton
1054+
return if @scanner.in_proc_block || @scanner.singleton
10481055
names = symbol_arguments(call_node)
10491056
@scanner.container.set_constant_visibility_for(names.map(&:to_s), :public) if names
10501057
end
10511058

10521059
def _visit_call_private_constant(call_node)
1053-
return if @scanner.singleton
1060+
return if @scanner.in_proc_block || @scanner.singleton
10541061
names = symbol_arguments(call_node)
10551062
@scanner.container.set_constant_visibility_for(names.map(&:to_s), :private) if names
10561063
end
10571064

10581065
def _visit_call_attr_reader_writer_accessor(call_node, rw)
1066+
return if @scanner.in_proc_block
10591067
names = symbol_arguments(call_node)
10601068
@scanner.add_attributes(names.map(&:to_s), rw, call_node.location.start_line) if names
10611069
end
1070+
10621071
class MethodSignatureVisitor < Prism::Visitor # :nodoc:
10631072
class << self
10641073
def scan_signature(def_node)

test/rdoc/parser/prism_ruby_test.rb

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2032,6 +2032,93 @@ class B
20322032
assert_equal ['N'], b.extends.map(&:name)
20332033
end
20342034

2035+
def test_visibility_methods_suppressed_within_block
2036+
util_parser <<~RUBY
2037+
class A
2038+
def pub1; end
2039+
X = 1
2040+
Y = 1
2041+
def self.s_pub; end
2042+
private_class_method def self.s_pri; end
2043+
private_constant :Y
2044+
Module.new do
2045+
private_method :pub1
2046+
private_constant :X
2047+
public_constant :Y
2048+
private
2049+
private_class_method :s_pub
2050+
public_class_method :s_pri
2051+
end
2052+
def pub2; end
2053+
private
2054+
Module.new do
2055+
public
2056+
end
2057+
def pri; end
2058+
end
2059+
RUBY
2060+
klass = @store.find_class_named 'A'
2061+
2062+
assert_equal :public, klass.find_constant_named('X').visibility
2063+
assert_equal :private, klass.find_constant_named('Y').visibility
2064+
assert_equal :public, klass.find_method_named('pub1').visibility
2065+
assert_equal :private, klass.find_method_named('pri').visibility
2066+
assert_equal :public, klass.find_method_named('pub2').visibility
2067+
assert_equal :public, klass.find_class_method_named('s_pub').visibility
2068+
assert_equal :private, klass.find_class_method_named('s_pri').visibility unless accept_legacy_bug?
2069+
end
2070+
2071+
def test_alias_method_suppressed_within_block
2072+
omit if accept_legacy_bug?
2073+
2074+
util_parser <<~RUBY
2075+
class A
2076+
def foo; end
2077+
Module.new do
2078+
def bar; end
2079+
alias_method :bar2, :bar
2080+
end
2081+
alias_method :foo3, :foo
2082+
end
2083+
RUBY
2084+
klass = @store.find_class_named 'A'
2085+
assert_equal ['foo', 'foo3'], klass.method_list.map(&:name)
2086+
end
2087+
2088+
def test_attr_method_suppressed_within_block
2089+
util_parser <<~RUBY
2090+
class A
2091+
attr_reader :r
2092+
attr_writer :w
2093+
attr_accessor :rw
2094+
Module.new do
2095+
attr_reader :r2
2096+
attr_writer :w2
2097+
attr_accessor :rw2
2098+
end
2099+
alias_method :foo3, :foo
2100+
end
2101+
RUBY
2102+
klass = @store.find_class_named 'A'
2103+
assert_equal ['r', 'w', 'rw'], klass.attributes.map(&:name)
2104+
end
2105+
2106+
def test_module_function_suppressed_within_block
2107+
util_parser <<~RUBY
2108+
module M
2109+
def foo; end
2110+
Module.new do
2111+
def foo; end
2112+
module_function :foo
2113+
end
2114+
def bar; end
2115+
module_function :bar
2116+
end
2117+
RUBY
2118+
mod = @store.find_module_named 'M'
2119+
assert_equal ['bar'], mod.class_method_list.map(&:name)
2120+
end
2121+
20352122
def test_multibyte_method_name
20362123
content = <<~RUBY
20372124
class Foo

0 commit comments

Comments
 (0)