Class: RuboCop::Cop::Style::ExplicitBlockArgument

Inherits:
Base
  • Object
show all
Extended by:
AutoCorrector
Includes:
RangeHelp
Defined in:
lib/rubocop/cop/style/explicit_block_argument.rb

Overview

Enforces the use of explicit block argument to avoid writing block literal that just passes its arguments to another block.

Note
This cop only registers an offense if the block args match the yield args exactly.

Examples:

# bad
def with_tmp_dir
  Dir.mktmpdir do |tmp_dir|
    Dir.chdir(tmp_dir) { |dir| yield dir } # block just passes arguments
  end
end

# bad
def nine_times
  9.times { yield }
end

# good
def with_tmp_dir(&block)
  Dir.mktmpdir do |tmp_dir|
    Dir.chdir(tmp_dir, &block)
  end
end

with_tmp_dir do |dir|
  puts "dir is accessible as a parameter and pwd is set: #{dir}"
end

# good
def nine_times(&block)
  9.times(&block)
end

Constant Summary collapse

MSG =
'Consider using explicit block argument in the ' \
"surrounding method's signature over `yield`."

Constants inherited from Base

Base::RESTRICT_ON_SEND

Instance Attribute Summary

Attributes inherited from Base

#config, #processed_source

Class Method Summary collapse

Instance Method Summary collapse

Methods included from AutoCorrector

support_autocorrect?

Methods inherited from Base

#active_support_extensions_enabled?, #add_global_offense, #add_offense, badge, #begin_investigation, #callbacks_needed, callbacks_needed, #config_to_allow_offenses, #config_to_allow_offenses=, #cop_config, cop_name, #cop_name, department, documentation_url, exclude_from_registry, #excluded_file?, #external_dependency_checksum, inherited, #inspect, joining_forces, lint?, match?, #message, #offenses, #on_investigation_end, #on_new_investigation, #on_other_file, #parse, #ready, #relevant_file?, 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

#initialize(config = nil, options = nil) ⇒ ExplicitBlockArgument

Returns a new instance of ExplicitBlockArgument.



57
58
59
60
# File 'lib/rubocop/cop/style/explicit_block_argument.rb', line 57

def initialize(config = nil, options = nil)
  super
  @def_nodes = Set.new
end

Class Method Details

.autocorrect_incompatible_withObject



53
54
55
# File 'lib/rubocop/cop/style/explicit_block_argument.rb', line 53

def self.autocorrect_incompatible_with
  [Lint::UnusedMethodArgument]
end

Instance Method Details

#on_yield(node) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/rubocop/cop/style/explicit_block_argument.rb', line 62

def on_yield(node)
  block_node = node.parent

  yielding_block?(block_node) do |send_node, block_args, yield_args|
    return unless yielding_arguments?(block_args, yield_args)

    def_node = block_node.each_ancestor(:def, :defs).first
    # if `yield` is being called outside of a method context, ignore
    # this is not a valid ruby pattern, but can happen in haml or erb,
    # so this can cause crashes in haml_lint
    return unless def_node

    block_name = extract_block_name(def_node)

    add_offense(block_node) do |corrector|
      corrector.remove(block_body_range(block_node, send_node))

      add_block_argument(send_node, corrector, block_name)
      add_block_argument(def_node, corrector, block_name) if @def_nodes.add?(def_node)
    end
  end
end

#yielding_block?(node) ⇒ Object



49
50
51
# File 'lib/rubocop/cop/style/explicit_block_argument.rb', line 49

def_node_matcher :yielding_block?, <<~PATTERN
  (block $_ (args $...) (yield $...))
PATTERN