class RuboCop::Cop::Style::SlicingWithRange
# Ruby 2.7+<br>items # Ruby 2.7+
# good<br><br>items # Ruby 2.7+
# bad<br><br>items # Ruby 2.6+
# good<br><br>items # Ruby 2.6+<br>items # Ruby 2.6+
# bad
items
# good
items[0…nil]
items[0..nil]
items[0..-1]
# bad<br>@example<br><br>—-<br>sum # Hangs forever<br>sum # => -6
sum = proc { |ary| ary.sum }
For example:
the receiver is.
be equivalent for ‘Array#[]`, `String#[]`, and the cop cannot determine what class
This cop is unsafe because `x..-1` and `x..` are only guaranteed to
@safety
and with beginless ranges instead of `ary` on Ruby 2.7+.
and ensures arrays are sliced with endless ranges instead of `ary` on Ruby 2.6+,
Checks that arrays are not sliced with the redundant `ary`, replacing it with `ary`,
def arguments_source(node)
def arguments_source(node) node.first_argument.source_range.join(node.last_argument.source_range.end).source end
def beginless(range_node)
def beginless(range_node) "#{range_node.loc.operator.source}#{range_node.end.source}" end
def endless(range_node)
def endless(range_node) "#{range_node.begin.source}#{range_node.loc.operator.source}" end
def find_offense_range(node)
def find_offense_range(node) if node.loc.dot node.loc.dot.join(node.source_range.end) else node.loc.selector end end
def offense_message_for_partial_range(node, prefer, offense_range)
def offense_message_for_partial_range(node, prefer, offense_range) current = node.loc.dot ? arguments_source(node) : offense_range.source prefer = "[#{prefer}]" unless node.loc.dot format(MSG, prefer: prefer, current: current) end
def offense_message_with_removal_range(node, range_node, offense_range)
def offense_message_with_removal_range(node, range_node, offense_range) if range_from_zero_till_minus_one?(range_node) [format(MSG_USELESS_RANGE, prefer: offense_range.source), offense_range] elsif range_till_minus_one?(range_node) [ offense_message_for_partial_range(node, endless(range_node), offense_range), range_node.end ] elsif range_from_zero?(range_node) && target_ruby_version >= 2.7 [ offense_message_for_partial_range(node, beginless(range_node), offense_range), range_node.begin ] end end
def on_send(node)
def on_send(node) return unless node.arguments.one? range_node = node.first_argument offense_range = find_offense_range(node) return unless (message, removal_range = offense_message_with_removal_range(node, range_node, offense_range)) # Changing the range to beginningless or endless when unparenthesized # changes the semantics of the code, and thus will not be considered # an offense. return if removal_range != offense_range && unparenthesized_call?(node) add_offense(offense_range, message: message) do |corrector| corrector.remove(removal_range) end end
def unparenthesized_call?(node)
def unparenthesized_call?(node) node.loc.dot && !node.parenthesized? end