123456789_123456789_123456789_123456789_123456789_

Class: RuboCop::Cop::Style::SingleLineBlockParams

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/single_line_block_params.rb

Overview

Checks whether the block parameters of a single-line method accepting a block match the names specified via configuration.

For instance one can configure reduce(inject) to use |a, e| as parameters.

Configuration option: Methods Should be set to use this cop. Array of hashes, where each key is the method name and value - array of argument names.

Examples:

Methods: [%w[a b]]

# bad
foo.reduce { |c, d| c + d }
foo.reduce { |_, _d| 1 }

# good
foo.reduce { |a, b| a + b }
foo.reduce { |a, _b| a }
foo.reduce { |a, (id, _)| a + id }
foo.reduce { true }

# good
foo.reduce do |c, d|
  c + d
end

Constant Summary

::RuboCop::Cop::Base - Inherited

EMPTY_OFFENSES, RESTRICT_ON_SEND

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 on_new_investigation and on_investigation_end, the result of processed_source will remain constant.

.builtin?

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

Cops (other than builtin) are encouraged to implement this.

.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

Instance Method Summary

::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 add_offense or add_global_offense Cops are discouraged to override this; instead pass your message directly.

#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, #use_corrector

::RuboCop::Cop::AutocorrectLogic - Included

::RuboCop::Cop::IgnoredNode - Included

Constructor Details

This class inherits a constructor from RuboCop::Cop::Base

Instance Method Details

#args_match?(method_name, args) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/single_line_block_params.rb', line 105

def args_match?(method_name, args)
  actual_args = args.to_a.flat_map(&:to_a)

  # Prepending an underscore to mark an unused parameter is allowed, so
  # we remove any leading underscores before comparing.
  actual_args_no_underscores = actual_args.map { |arg| arg.to_s.sub(/^_+/, '') }

  # Allow the arguments if the names match but not all are given
  expected_args = target_args(method_name).first(actual_args_no_underscores.size)
  actual_args_no_underscores == expected_args
end

#autocorrect(corrector, node, preferred_block_arguments, joined_block_arguments) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/single_line_block_params.rb', line 69

def autocorrect(corrector, node, preferred_block_arguments, joined_block_arguments)
  corrector.replace(node.arguments, "|#{joined_block_arguments}|")

  node.each_descendant(:lvar) do |lvar|
    if (preferred_lvar = preferred_block_arguments[lvar.source])
      corrector.replace(lvar, preferred_lvar)
    end
  end
end

#build_preferred_arguments_map(node, preferred_arguments) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/single_line_block_params.rb', line 57

def build_preferred_arguments_map(node, preferred_arguments)
  preferred_arguments_map = {}
  node.arguments.each_with_index do |current_lvar, index|
    preferred_argument = preferred_arguments[index]
    current_argument = current_lvar.source
    preferred_argument = "_#{preferred_argument}" if current_argument.start_with?('_')
    preferred_arguments_map[current_argument] = preferred_argument
  end

  preferred_arguments_map
end

#eligible_arguments?(node) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/single_line_block_params.rb', line 79

def eligible_arguments?(node)
  node.arguments? && node.arguments.to_a.all?(&:arg_type?)
end

#eligible_method?(node) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/single_line_block_params.rb', line 83

def eligible_method?(node)
  node.receiver && method_names.include?(node.method_name)
end

#method_name(method) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/single_line_block_params.rb', line 95

def method_name(method)
  method.keys.first
end

#method_names (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/single_line_block_params.rb', line 91

def method_names
  methods.map { |method| method_name(method).to_sym }
end

#methods (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/single_line_block_params.rb', line 87

def methods
  cop_config['Methods']
end

#on_block(node)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/single_line_block_params.rb', line 36

def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
  return unless node.single_line?

  return unless eligible_method?(node)
  return unless eligible_arguments?(node)

  method_name = node.method_name
  return if args_match?(method_name, node.arguments)

  preferred_block_arguments = build_preferred_arguments_map(node, target_args(method_name))
  joined_block_arguments = preferred_block_arguments.values.join(', ')

  message = format(MSG, method: method_name, params: joined_block_arguments)

  add_offense(node.arguments, message: message) do |corrector|
    autocorrect(corrector, node, preferred_block_arguments, joined_block_arguments)
  end
end

#target_args(method_name) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/style/single_line_block_params.rb', line 99

def target_args(method_name)
  method_name = method_name.to_s
  method_hash = methods.find { |m| method_name(m) == method_name }
  method_hash[method_name]
end