Class: RuboCop::Cop::Metrics::ParameterLists

Inherits:
Base
  • Object
show all
Defined in:
lib/rubocop/cop/metrics/parameter_lists.rb

Overview

Checks for methods with too many parameters.

The maximum number of parameters is configurable. Keyword arguments can optionally be excluded from the total count, as they add less complexity than positional or optional parameters.

Any number of arguments for ‘initialize` method inside a block of `Struct.new` and `Data.define` like this is always allowed:

source,ruby

Struct.new(:one, :two, :three, :four, :five, keyword_init: true) do

def initialize(one:, two:, three:, four:, five:)
end

end


This is because checking the number of arguments of the ‘initialize` method does not make sense.

NOTE: Explicit block argument ‘&block` is not counted to prevent erroneous change that is avoided by making block argument implicit.

This cop also checks for the maximum number of optional parameters. This can be configured using the ‘MaxOptionalParameters` config option.

Examples:

Max: 3

# good
def foo(a, b, c = 1)
end

Max: 2

# bad
def foo(a, b, c = 1)
end

CountKeywordArgs: true (default)

# counts keyword args towards the maximum

# bad (assuming Max is 3)
def foo(a, b, c, d: 1)
end

# good (assuming Max is 3)
def foo(a, b, c: 1)
end

CountKeywordArgs: false

# don't count keyword args towards the maximum

# good (assuming Max is 3)
def foo(a, b, c, d: 1)
end

MaxOptionalParameters: 3 (default)

# good
def foo(a = 1, b = 2, c = 3)
end

MaxOptionalParameters: 2

# bad
def foo(a = 1, b = 2, c = 3)
end

Constant Summary collapse

MSG =
'Avoid parameter lists longer than %<max>d parameters. [%<count>d/%<max>d]'
OPTIONAL_PARAMETERS_MSG =
'Method has too many optional parameters. [%<count>d/%<max>d]'

Constants inherited from Base

Base::RESTRICT_ON_SEND

Instance Attribute Summary

Attributes inherited from Base

#config, #processed_source

Instance Method Summary collapse

Methods inherited from Base

#active_support_extensions_enabled?, #add_global_offense, #add_offense, #always_autocorrect?, autocorrect_incompatible_with, badge, #begin_investigation, #callbacks_needed, callbacks_needed, #config_to_allow_offenses, #config_to_allow_offenses=, #contextual_autocorrect?, #cop_config, cop_name, #cop_name, department, documentation_url, exclude_from_registry, #excluded_file?, #external_dependency_checksum, inherited, #initialize, #inspect, joining_forces, lint?, match?, #message, #offenses, #on_investigation_end, #on_new_investigation, #on_other_file, #parse, #parser_engine, #ready, #relevant_file?, requires_gem, #string_literals_frozen_by_default?, support_autocorrect?, support_multiple_source?, #target_rails_version, #target_ruby_version

Methods included from ExcludeLimit

#exclude_limit

Methods included from AutocorrectLogic

#autocorrect?, #autocorrect_enabled?, #autocorrect_requested?, #autocorrect_with_disable_uncorrectable?, #correctable?, #disable_uncorrectable?, #safe_autocorrect?

Methods included from IgnoredNode

#ignore_node, #ignored_node?, #part_of_ignored_node?

Methods included from Util

silence_warnings

Constructor Details

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

Instance Method Details

#on_args(node) ⇒ Object



104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/rubocop/cop/metrics/parameter_lists.rb', line 104

def on_args(node)
  parent = node.parent
  return if parent.method?(:initialize) && struct_new_or_data_define_block?(parent.parent)

  count = args_count(node)
  return unless count > max_params

  return if argument_to_lambda_or_proc?(node)

  add_offense(node, message: format(MSG, max: max_params, count: args_count(node))) do
    self.max = count
  end
end

#on_def(node) ⇒ Object Also known as: on_defs



90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/rubocop/cop/metrics/parameter_lists.rb', line 90

def on_def(node)
  optargs = node.arguments.select(&:optarg_type?)
  return if optargs.count <= max_optional_parameters

  message = format(
    OPTIONAL_PARAMETERS_MSG,
    max: max_optional_parameters,
    count: optargs.count
  )

  add_offense(node, message: message) { self.max_optional_parameters = optargs.count }
end

#struct_new_or_data_define_block?(node) ⇒ Object



81
82
83
84
85
86
87
88
# File 'lib/rubocop/cop/metrics/parameter_lists.rb', line 81

def_node_matcher :struct_new_or_data_define_block?, <<~PATTERN
  (block
    {
      (send (const {nil? cbase} :Struct) :new ...)
      (send (const {nil? cbase} :Data) :define ...)
    }
    (args) ...)
PATTERN