Class: RuboCop::Cop::Style::AccessModifierDeclarations
Relationships & Source Files | |
Super Chains via Extension / Inclusion / Inheritance | |
Class Chain:
self,
::RuboCop::Cop::AutoCorrector ,
::RuboCop::Cop::Base ,
::RuboCop::ExcludeLimit ,
NodePattern::Macros,
RuboCop::AST::Sexp
|
|
Instance Chain:
|
|
Inherits: |
RuboCop::Cop::Base
|
Defined in: | lib/rubocop/cop/style/access_modifier_declarations.rb |
Overview
Access modifiers should be declared to apply to a group of methods
or inline before each method, depending on configuration.
EnforcedStyle config covers only method definitions.
Applications of visibility methods to symbols can be controlled
using AllowModifiersOnSymbols config.
Also, the visibility of attr*
methods can be controlled using
AllowModifiersOnAttrs config.
In Ruby 3.0, attr*
methods now return an array of defined method names
as symbols. So we can write the modifier and attr*
in inline style.
AllowModifiersOnAttrs config allows attr*
methods to be written in
inline style without modifying applications that have been maintained
for a long time in group style. Furthermore, developers who are not very
familiar with Ruby may know that the modifier applies to def
, but they
may not know that it also applies to attr*
methods. It would be easier
to understand if we could write attr*
methods in inline style.
Constant Summary
-
ALLOWED_NODE_TYPES =
# File 'lib/rubocop/cop/style/access_modifier_declarations.rb', line 133%i[pair block].freeze
-
GROUP_STYLE_MESSAGE =
# File 'lib/rubocop/cop/style/access_modifier_declarations.rb', line 121[ '`%<access_modifier>s` should not be', 'inlined in method definitions.' ].join(' ')
-
INLINE_STYLE_MESSAGE =
# File 'lib/rubocop/cop/style/access_modifier_declarations.rb', line 126[ '`%<access_modifier>s` should be', 'inlined in method definitions.' ].join(' ')
-
RESTRICT_ON_SEND =
# File 'lib/rubocop/cop/style/access_modifier_declarations.rb', line 131%i[private protected public module_function].freeze
::RuboCop::Cop::Base
- Inherited
EMPTY_OFFENSES, RESTRICT_ON_SEND
::RuboCop::Cop::ConfigurableEnforcedStyle
- Included
::RuboCop::Cop::RangeHelp
- Included
Class Attribute Summary
::RuboCop::Cop::AutoCorrector
- Extended
::RuboCop::Cop::Base
- Inherited
.gem_requirements, .lint?, | |
.support_autocorrect? | Returns if class supports autocorrect. |
.support_multiple_source? | Override if your cop should be called repeatedly for multiple investigations Between calls to |
Class Method Summary
::RuboCop::Cop::Base
- Inherited
.autocorrect_incompatible_with | List of cops that should not try to autocorrect at the same time as this cop. |
.badge | Naming. |
.callbacks_needed, .cop_name, .department, | |
.documentation_url | Returns a url to view this cops documentation online. |
.exclude_from_registry | Call for abstract Cop classes. |
.inherited, | |
.joining_forces | Override and return the Force class(es) you need to join. |
.match? | Returns true if the cop name or the cop namespace matches any of the given names. |
.new, | |
.requires_gem | Register a version requirement for the given gem name. |
.restrict_on_send |
::RuboCop::ExcludeLimit
- Extended
exclude_limit | Sets up a configuration option to have an exclude limit tracked. |
transform |
Instance Attribute Summary
- #group_style? ⇒ Boolean readonly private
- #inline_style? ⇒ Boolean readonly private
::RuboCop::Cop::ConfigurableEnforcedStyle
- Included
::RuboCop::Cop::Base
- Inherited
::RuboCop::Cop::AutocorrectLogic
- Included
Instance Method Summary
- #access_modifier_with_attr?(node)
- #access_modifier_with_symbol?(node)
- #on_send(node)
- #access_modifier_is_inlined?(node) ⇒ Boolean private
- #access_modifier_is_not_inlined?(node) ⇒ Boolean private
- #allow_modifiers_on_attrs?(node) ⇒ Boolean private
- #allow_modifiers_on_symbols?(node) ⇒ Boolean private
- #allowed?(node) ⇒ Boolean private
- #autocorrect(corrector, node) private
- #correctable_group_offense?(node) ⇒ Boolean private
- #def_source(node, def_nodes) private
- #find_argument_less_modifier_node(node) private
- #find_corresponding_def_nodes(node) private
- #insert_inline_modifier(corrector, node, modifier_name) private
- #message(range) private
- #offense?(node) ⇒ Boolean private
- #percent_symbol_array?(node) ⇒ Boolean private
- #remove_nodes(corrector, *nodes) private
- #replace_defs(corrector, node, def_nodes) private
- #right_siblings_same_inline_method?(node) ⇒ Boolean private
- #select_grouped_def_nodes(node) private
::RuboCop::Cop::RangeHelp
- Included
#add_range, #column_offset_between, | |
#contents_range | A range containing only the contents of a literal with delimiters (e.g. |
#directions, | |
#effective_column | Returns the column attribute of the range, except if the range is on the first line and there’s a byte order mark at the beginning of that line, in which case 1 is subtracted from the column value. |
#final_pos, #move_pos, #move_pos_str, #range_between, #range_by_whole_lines, #range_with_comments, #range_with_comments_and_lines, #range_with_surrounding_comma, #range_with_surrounding_space, #source_range |
::RuboCop::Cop::ConfigurableEnforcedStyle
- Included
::RuboCop::Cop::Base
- Inherited
#add_global_offense | Adds an offense that has no particular location. |
#add_offense | Adds an offense on the specified range (or node with an expression) Unless that offense is disabled for this range, a corrector will be yielded to provide the cop the opportunity to autocorrect the offense. |
#begin_investigation | Called before any investigation. |
#callbacks_needed, | |
#cop_config | Configuration Helpers. |
#cop_name, #excluded_file?, | |
#external_dependency_checksum | This method should be overridden when a cop’s behavior depends on state that lives outside of these locations: |
#inspect, | |
#message | Gets called if no message is specified when calling |
#name | Alias for Base#cop_name. |
#offenses, | |
#on_investigation_end | Called after all on_… |
#on_new_investigation | Called before all on_… |
#on_other_file | Called instead of all on_… |
#parse | There should be very limited reasons for a Cop to do it’s own parsing. |
#parser_engine, | |
#ready | Called between investigations. |
#relevant_file?, #target_rails_version, #target_ruby_version, #annotate, #apply_correction, #attempt_correction, | |
#callback_argument | Reserved for Cop::Cop. |
#complete_investigation | Called to complete an investigation. |
#correct, #current_corrector, | |
#current_offense_locations | Reserved for Commissioner: |
#current_offenses, #currently_disabled_lines, #custom_severity, #default_severity, #disable_uncorrectable, #enabled_line?, #file_name_matches_any?, #find_message, #find_severity, #range_for_original, #range_from_node_or_range, | |
#reset_investigation | Actually private methods. |
#use_corrector |
::RuboCop::Cop::AutocorrectLogic
- Included
#disable_offense, #disable_offense_at_end_of_line, #disable_offense_before_and_after, #disable_offense_with_eol_or_surround_comment, #max_line_length, | |
#range_by_lines | Expand the given range to include all of any lines it covers. |
#range_of_first_line, #range_overlaps_offense?, #string_continuation, #string_continuation?, #surrounding_heredoc, #surrounding_percent_array |
::RuboCop::Cop::IgnoredNode
- Included
Constructor Details
This class inherits a constructor from RuboCop::Cop::Base
Instance Attribute Details
#group_style? ⇒ Boolean
(readonly, private)
[ GitHub ]
# File 'lib/rubocop/cop/style/access_modifier_declarations.rb', line 210
def group_style? style == :group end
#inline_style? ⇒ Boolean
(readonly, private)
[ GitHub ]
# File 'lib/rubocop/cop/style/access_modifier_declarations.rb', line 214
def inline_style? style == :inline end
Instance Method Details
#access_modifier_is_inlined?(node) ⇒ Boolean
(private)
# File 'lib/rubocop/cop/style/access_modifier_declarations.rb', line 218
def access_modifier_is_inlined?(node) node.arguments.any? end
#access_modifier_is_not_inlined?(node) ⇒ Boolean
(private)
# File 'lib/rubocop/cop/style/access_modifier_declarations.rb', line 222
def access_modifier_is_not_inlined?(node) !access_modifier_is_inlined?(node) end
#access_modifier_with_attr?(node)
[ GitHub ]# File 'lib/rubocop/cop/style/access_modifier_declarations.rb', line 143
def_node_matcher :access_modifier_with_attr?, <<~PATTERN (send nil? {:private :protected :public :module_function} (send nil? {:attr :attr_reader :attr_writer :attr_accessor} _+)) PATTERN
#access_modifier_with_symbol?(node)
[ GitHub ]# File 'lib/rubocop/cop/style/access_modifier_declarations.rb', line 136
def_node_matcher :access_modifier_with_symbol?, <<~PATTERN (send nil? {:private :protected :public :module_function} {(sym _)+ (splat {#percent_symbol_array? const send})} ) PATTERN
#allow_modifiers_on_attrs?(node) ⇒ Boolean
(private)
# File 'lib/rubocop/cop/style/access_modifier_declarations.rb', line 193
def allow_modifiers_on_attrs?(node) cop_config['AllowModifiersOnAttrs'] && access_modifier_with_attr?(node) end
#allow_modifiers_on_symbols?(node) ⇒ Boolean
(private)
# File 'lib/rubocop/cop/style/access_modifier_declarations.rb', line 189
def allow_modifiers_on_symbols?(node) cop_config['AllowModifiersOnSymbols'] && access_modifier_with_symbol?(node) end
#allowed?(node) ⇒ Boolean
(private)
# File 'lib/rubocop/cop/style/access_modifier_declarations.rb', line 163
def allowed?(node) !node.access_modifier? || ALLOWED_NODE_TYPES.include?(node.parent&.type) || allow_modifiers_on_symbols?(node) || allow_modifiers_on_attrs?(node) end
#autocorrect(corrector, node) (private)
[ GitHub ]# File 'lib/rubocop/cop/style/access_modifier_declarations.rb', line 170
def autocorrect(corrector, node) case style when :group def_nodes = find_corresponding_def_nodes(node) return unless def_nodes.any? replace_defs(corrector, node, def_nodes) when :inline remove_nodes(corrector, node) select_grouped_def_nodes(node).each do |grouped_def_node| insert_inline_modifier(corrector, grouped_def_node, node.method_name) end end end
#correctable_group_offense?(node) ⇒ Boolean
(private)
# File 'lib/rubocop/cop/style/access_modifier_declarations.rb', line 203
def correctable_group_offense?(node) return false unless group_style? return false if allowed?(node) access_modifier_is_inlined?(node) && find_corresponding_def_nodes(node).any? end
#def_source(node, def_nodes) (private)
[ GitHub ]# File 'lib/rubocop/cop/style/access_modifier_declarations.rb', line 305
def def_source(node, def_nodes) [ *processed_source.ast_with_comments[node].map(&:text), *def_nodes.map(&:source) ].join("\n") end
#find_argument_less_modifier_node(node) (private)
[ GitHub ]# File 'lib/rubocop/cop/style/access_modifier_declarations.rb', line 265
def find_argument_less_modifier_node(node) return unless (parent = node.parent) parent.each_child_node(:send).find do |child| child.method?(node.method_name) && child.arguments.empty? end end
#find_corresponding_def_nodes(node) (private)
[ GitHub ]# File 'lib/rubocop/cop/style/access_modifier_declarations.rb', line 246
def find_corresponding_def_nodes(node) if access_modifier_with_symbol?(node) method_names = node.arguments.filter_map do |argument| next unless argument.sym_type? argument.respond_to?(:value) && argument.value end def_nodes = node.parent.each_child_node(:def).select do |child| method_names.include?(child.method_name) end # If there isn't a `def` node for each symbol, we will skip autocorrection. def_nodes.size == method_names.size ? def_nodes : [] else [node.first_argument] end end
#insert_inline_modifier(corrector, node, modifier_name) (private)
[ GitHub ]# File 'lib/rubocop/cop/style/access_modifier_declarations.rb', line 295
def insert_inline_modifier(corrector, node, modifier_name) corrector.insert_before(node, "#{modifier_name} ") end
#message(range) (private)
[ GitHub ]# File 'lib/rubocop/cop/style/access_modifier_declarations.rb', line 236
def (range) access_modifier = range.source if group_style? format(GROUP_STYLE_MESSAGE, access_modifier: access_modifier) elsif inline_style? format(INLINE_STYLE_MESSAGE, access_modifier: access_modifier) end end
#offense?(node) ⇒ Boolean
(private)
# File 'lib/rubocop/cop/style/access_modifier_declarations.rb', line 197
def offense?(node) (group_style? && access_modifier_is_inlined?(node) && !node.parent&.if_type? && !right_siblings_same_inline_method?(node)) || (inline_style? && access_modifier_is_not_inlined?(node)) end
#on_send(node)
[ GitHub ]# File 'lib/rubocop/cop/style/access_modifier_declarations.rb', line 148
def on_send(node) return if allowed?(node) if offense?(node) add_offense(node.loc.selector) do |corrector| autocorrect(corrector, node) end opposite_style_detected else correct_style_detected end end
#percent_symbol_array?(node) ⇒ Boolean
(private)
# File 'lib/rubocop/cop/style/access_modifier_declarations.rb', line 185
def percent_symbol_array?(node) node.array_type? && node.percent_literal?(:symbol) end
#remove_nodes(corrector, *nodes) (private)
[ GitHub ]# File 'lib/rubocop/cop/style/access_modifier_declarations.rb', line 299
def remove_nodes(corrector, *nodes) nodes.each do |node| corrector.remove(range_with_comments_and_lines(node)) end end
#replace_defs(corrector, node, def_nodes) (private)
[ GitHub ]# File 'lib/rubocop/cop/style/access_modifier_declarations.rb', line 279
def replace_defs(corrector, node, def_nodes) source = def_source(node, def_nodes) argument_less_modifier_node = find_argument_less_modifier_node(node) if argument_less_modifier_node corrector.insert_after(argument_less_modifier_node, "\n\n#{source}") elsif (ancestor = node.each_ancestor(:block, :class, :module).first) corrector.insert_before(ancestor.loc.end, "#{node.method_name}\n\n#{source}\n") else corrector.replace(node, "#{node.method_name}\n\n#{source}") return end remove_nodes(corrector, *def_nodes, node) end
#right_siblings_same_inline_method?(node) ⇒ Boolean
(private)
# File 'lib/rubocop/cop/style/access_modifier_declarations.rb', line 226
def right_siblings_same_inline_method?(node) node.right_siblings.any? do |sibling| sibling.send_type? && correctable_group_offense?(sibling) && sibling.method?(node.method_name) && !sibling.arguments.empty? && find_corresponding_def_nodes(sibling).any? end end
#select_grouped_def_nodes(node) (private)
[ GitHub ]# File 'lib/rubocop/cop/style/access_modifier_declarations.rb', line 273
def select_grouped_def_nodes(node) node.right_siblings.take_while do |sibling| !(sibling.send_type? && sibling. ) end.select(&:def_type?) end