Skip to content

Commit

Permalink
Merge pull request #462 from corsonknowles/add_performance_use_zip_to…
Browse files Browse the repository at this point in the history
…_wrap_arrays

Add new `ZipWithoutBlock` cop
  • Loading branch information
koic authored Jan 29, 2025
2 parents 063b56d + c4308ae commit 2d36cac
Show file tree
Hide file tree
Showing 5 changed files with 453 additions and 0 deletions.
1 change: 1 addition & 0 deletions changelog/new_merge_pull_request_462_from.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* [#462](https://github.com/rubocop/rubocop-performance/pull/462): Add new `Performance/ZipWithoutBlock` cop that checks patterns like `.map { |id| [id] }` or `.map { [_1] }` and can replace them with `.zip`. ([@corsonknowles][])
6 changes: 6 additions & 0 deletions config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -381,3 +381,9 @@ Performance/UriDefaultParser:
Description: 'Use `URI::DEFAULT_PARSER` instead of `URI::Parser.new`.'
Enabled: true
VersionAdded: '0.50'

Performance/ZipWithoutBlock:
Description: 'Checks for `map { |id| [id] }` and suggests replacing it with `zip`.'
Enabled: pending
Safe: false
VersionAdded: <<next>>
56 changes: 56 additions & 0 deletions lib/rubocop/cop/performance/zip_without_block.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# frozen_string_literal: true

module RuboCop
module Cop
module Performance
# Checks for `map { |id| [id] }` and suggests replacing it with `zip`.
#
# @safety
# This cop is unsafe for novel definitions of `map` and `collect`
# on non-Enumerable objects that do not respond to `zip`.
# To make your object enumerable, define an `each` method
# as described in https://ruby-doc.org/core/Enumerable.html
#
# @example
# # bad
# [1, 2, 3].map { |id| [id] }
#
# # good
# [1, 2, 3].zip
class ZipWithoutBlock < Base
extend AutoCorrector

MSG = 'Use `zip` without a block argument instead.'
RESTRICT_ON_SEND = Set.new(%i[map collect]).freeze

# @!method map_with_array?(node)
def_node_matcher :map_with_array?, <<~PATTERN
{
(block (call !nil? RESTRICT_ON_SEND) (args (arg _)) (array (lvar _)))
(numblock (call !nil? RESTRICT_ON_SEND) 1 (array (lvar _)))
}
PATTERN

def on_send(node)
return unless map_with_array?(node.parent)

register_offense(node)
end
alias on_csend on_send

private

def register_offense(node)
offense_range = offense_range(node)
add_offense(offense_range) do |corrector|
corrector.replace(offense_range, 'zip')
end
end

def offense_range(node)
node.loc.selector.join(node.parent.loc.end)
end
end
end
end
end
1 change: 1 addition & 0 deletions lib/rubocop/cop/performance_cops.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,4 @@
require_relative 'performance/unfreeze_string'
require_relative 'performance/uri_default_parser'
require_relative 'performance/chain_array_allocation'
require_relative 'performance/zip_without_block'
Loading

0 comments on commit 2d36cac

Please sign in to comment.