class RuboCop::Cop::Style::RedundantFetchBlock


ENV.fetch(:key, VALUE)
# good
ENV.fetch(:key) { VALUE }
# bad
@example SafeForConstants: true
ENV.fetch(:key, ‘value’)
array.fetch(5, :value)
hash.fetch(:key, nil)
hash.fetch(:key, true)
hash.fetch(:key, 5)
# good
ENV.fetch(:key) { ‘value’ }
array.fetch(5) { :value }
hash.fetch(:key) { nil }
hash.fetch(:key) { true }
hash.fetch(:key) { 5 }
# bad
@example SafeForConstants: false (default)
does not have a different implementation of ‘fetch`.
This cop is unsafe because it cannot be guaranteed that the receiver
@safety
but not when disabled.
when frozen string literal magic comment is enabled (i.e. `# frozen_string_literal: true`),
NOTE: The block string `’value’‘ in `hash.fetch(:key) { ’value’ }‘ is detected
In such cases `fetch(key, value)` method is faster than `fetch(key) { value }`.
Identifies places where `fetch(key) { value }` can be replaced by `fetch(key, value)`.

def basic_literal?(node)

def basic_literal?(node)
  node&.basic_literal?
end

def build_bad_method(send, body)

def build_bad_method(send, body)
  key = send.children[2].source
  block = body ? "{ #{body.source} }" : '{}'
  "fetch(#{key}) #{block}"
end

def build_good_method(send, body)

def build_good_method(send, body)
  key = send.children[2].source
  default_value = body ? body.source : 'nil'
  "fetch(#{key}, #{default_value})"
end

def check_for_constant?

def check_for_constant?
  cop_config['SafeForConstants']
end

def check_for_string?

def check_for_string?
  frozen_string_literals_enabled?
end

def const_type?(node)

def const_type?(node)
  node&.const_type?
end

def fetch_range(send, node)

def fetch_range(send, node)
  range_between(send.loc.selector.begin_pos, node.loc.end.end_pos)
end

def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler

rubocop:disable InternalAffairs/NumblockHandler
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
  redundant_fetch_block_candidate?(node) do |send, body|
    return if should_not_check?(send, body)
    range = fetch_range(send, node)
    good = build_good_method(send, body)
    bad = build_bad_method(send, body)
    add_offense(range, message: format(MSG, good: good, bad: bad)) do |corrector|
      receiver, _, key = send.children
      default_value = body ? body.source : 'nil'
      corrector.replace(node, "#{receiver.source}.fetch(#{key.source}, #{default_value})")
    end
  end
end

def should_not_check?(send, body)

def should_not_check?(send, body)
  (body&.const_type? && !check_for_constant?) ||
    (body&.str_type? && !check_for_string?) ||
    rails_cache?(send.receiver)
end