class RuboCop::Cop::Lint::ShadowedArgument
Checks for shadowed arguments.
This cop has ‘IgnoreImplicitReferences` configuration option. It means argument shadowing is used in order to pass parameters to zero arity `super` when `IgnoreImplicitReferences` is `true`.
@example
# bad do_something do |foo| foo = 42 puts foo end def do_something(foo) foo = 42 puts foo end # good do_something do |foo| foo = foo + 42 puts foo end def do_something(foo) foo = foo + 42 puts foo end def do_something(foo) puts foo end
@example IgnoreImplicitReferences: false (default)
# bad def do_something(foo) foo = 42 super end def do_something(foo) foo = super bar end
@example IgnoreImplicitReferences: true
# good def do_something(foo) foo = 42 super end def do_something(foo) foo = super bar end
Constants
- MSG
Public Class Methods
joining_forces()
click to toggle source
# File lib/rubocop/cop/lint/shadowed_argument.rb, line 72 def self.joining_forces VariableForce end
Public Instance Methods
after_leaving_scope(scope, _variable_table)
click to toggle source
# File lib/rubocop/cop/lint/shadowed_argument.rb, line 76 def after_leaving_scope(scope, _variable_table) scope.variables.each_value { |variable| check_argument(variable) } end
Private Instance Methods
argument_references(argument)
click to toggle source
Get argument references without assignments’ references
# File lib/rubocop/cop/lint/shadowed_argument.rb, line 161 def argument_references(argument) assignment_references = argument.assignments.flat_map(&:references).map(&:source_range) argument.references.reject do |ref| next false unless ref.explicit? assignment_references.include?(ref.node.source_range) end end
assignment_without_argument_usage(argument) { |node, location_known| ... }
click to toggle source
Find the first argument assignment, which doesn’t reference the argument at the rhs. If the assignment occurs inside a branch or block, it is impossible to tell whether it’s executed, so precise shadowing location is not known.
# File lib/rubocop/cop/lint/shadowed_argument.rb, line 120 def assignment_without_argument_usage(argument) argument.assignments.reduce(true) do |location_known, assignment| assignment_node = assignment.meta_assignment_node || assignment.node # Shorthand assignments always use their arguments next false if assignment_node.shorthand_asgn? next false unless assignment_node.parent node_within_block_or_conditional = node_within_block_or_conditional?(assignment_node.parent, argument.scope.node) unless uses_var?(assignment_node, argument.name) # It's impossible to decide whether a branch or block is executed, # so the precise reassignment location is undecidable. next false if node_within_block_or_conditional yield(assignment.node, location_known) break end location_known end end
check_argument(argument)
click to toggle source
# File lib/rubocop/cop/lint/shadowed_argument.rb, line 82 def check_argument(argument) return unless argument.method_argument? || argument.block_argument? # Block local variables, i.e., variables declared after ; inside # |...| aren't really arguments. return if argument.explicit_block_local_variable? shadowing_assignment(argument) do |node| message = format(MSG, argument: argument.name) add_offense(node, message: message) end end
ignore_implicit_references?()
click to toggle source
# File lib/rubocop/cop/lint/shadowed_argument.rb, line 171 def ignore_implicit_references? cop_config['IgnoreImplicitReferences'] end
node_within_block_or_conditional?(node, stop_search_node)
click to toggle source
Check whether the given node is nested into block or conditional.
# File lib/rubocop/cop/lint/shadowed_argument.rb, line 152 def node_within_block_or_conditional?(node, stop_search_node) return false if node == stop_search_node node.conditional? || node.block_type? || node_within_block_or_conditional?(node.parent, stop_search_node) end
reference_pos(node)
click to toggle source
# File lib/rubocop/cop/lint/shadowed_argument.rb, line 144 def reference_pos(node) node = node.parent if node.parent.masgn_type? node.source_range.begin_pos end
shadowing_assignment(argument) { |location_known ? node : declaration_node| ... }
click to toggle source
# File lib/rubocop/cop/lint/shadowed_argument.rb, line 95 def shadowing_assignment(argument) return unless argument.referenced? assignment_without_argument_usage(argument) do |node, location_known| assignment_without_usage_pos = node.source_range.begin_pos references = argument_references(argument) # If argument was referenced before it was reassigned # then it's not shadowed next if references.any? do |reference| next true if !reference.explicit? && ignore_implicit_references? reference_pos(reference.node) <= assignment_without_usage_pos end yield location_known ? node : argument.declaration_node end end