lib/rubocop/cop/mixin/visibility_help.rb
# frozen_string_literal: true
require 'set'
module RuboCop
module Cop
# Help methods for determining node visibility.
module VisibilityHelp
extend NodePattern::Macros
VISIBILITY_SCOPES = ::Set[:private, :protected, :public].freeze
private
def node_visibility(node)
node_visibility_from_visibility_inline(node) ||
node_visibility_from_visibility_block(node) ||
:public
end
def node_visibility_from_visibility_inline(node)
return unless node.def_type?
node_visibility_from_visibility_inline_on_def(node) ||
node_visibility_from_visibility_inline_on_method_name(node)
end
def node_visibility_from_visibility_inline_on_def(node)
parent = node.parent
parent.method_name if visibility_inline_on_def?(parent)
end
def node_visibility_from_visibility_inline_on_method_name(node)
node.right_siblings.reverse.find do |sibling|
visibility_inline_on_method_name?(sibling, method_name: node.method_name)
end&.method_name
end
def node_visibility_from_visibility_block(node)
find_visibility_start(node)&.method_name
end
def find_visibility_start(node)
node.left_siblings.reverse.find { |sibling| visibility_block?(sibling) }
end
# Navigate to find the last protected method
def find_visibility_end(node)
possible_visibilities = VISIBILITY_SCOPES - ::Set[node_visibility(node)]
right = node.right_siblings
right.find do |child_node|
possible_visibilities.include?(node_visibility(child_node))
end || right.last
end
# @!method visibility_block?(node)
def_node_matcher :visibility_block?, <<~PATTERN
(send nil? VISIBILITY_SCOPES)
PATTERN
# @!method visibility_inline_on_def?(node)
def_node_matcher :visibility_inline_on_def?, <<~PATTERN
(send nil? VISIBILITY_SCOPES def)
PATTERN
# @!method visibility_inline_on_method_name?(node, method_name:)
def_node_matcher :visibility_inline_on_method_name?, <<~PATTERN
(send nil? VISIBILITY_SCOPES (sym %method_name))
PATTERN
end
end
end