Conversation
|
|
||
| def _visit_call_module_function(call_node) | ||
| if !call_node.arguments || call_node.arguments.arguments.empty? | ||
| @scanner.visibility = :private |
There was a problem hiding this comment.
This condition doesn't check @scanner.in_proc_block and it means in cases like
module M
Module.new do
module_function
end
def outer; end
endThe private visibility leaks outside of the anonymous module.
| assert_equal ['m1', 'm2'], singleton_methods.map(&:name) | ||
| assert_equal [:public, :public], singleton_methods.map(&:visibility) | ||
| end | ||
|
|
There was a problem hiding this comment.
Let's also add this test:
def test_module_function_no_arg_does_not_leak_from_block
util_parser <<~RUBY
module M
Module.new do
module_function
end
def outer; end
end
RUBY
mod = @store.find_module_named 'M'
methods = mod.method_list.map { |method| [method.name, method.singleton, method.visibility] }
assert_equal [['outer', false, :public]], methods
end| RBS_SIG_LINE = /\A#:\s/ # :nodoc: | ||
|
|
||
| attr_accessor :visibility | ||
| attr_accessor :visibility, :module_function_mode |
There was a problem hiding this comment.
Visibility and module_function_mode are exclusive.
We don't want to introduce instance values with complex dependencies. Simple internal representation is better.
How about changing attr_accessor :visibility to attr_accessor :visibility_mode
and define def visibility that computes actual visibility from exclusive state like this?
attr_accessor :visibility_mode # :public, :private, :protected, :module_function
def visibility
@visibility_mode == :module_function ? :private : @visibility_mode
end| return unless receiver_name | ||
| when nil | ||
| visibility = @scanner.visibility | ||
| mod_function = @scanner.module_function_mode && !singleton |
There was a problem hiding this comment.
singleton is always nil because the local variable is not assigned yet.
I think it's a mistake of @scanner.singleton, but module_function_mode is only set on non-singleton module scope. Simply removing && (singleton_check_expression) is enough.
There was a problem hiding this comment.
I think it's better to check singleton in _visit_call_module_function.
module A
class << A
module_function rescue p($!) # NameError, RDoc should just ignore it
def f; end # public method
end
end
This supports module_function without argument (#1823).
I had initially the intention to use a special value for
@visibibility, but I think it is better that it has actual visibility values, so I introduced@module_function_mode.