Skip to content

Commit 2d36cac

Browse files
authored
Merge pull request #462 from corsonknowles/add_performance_use_zip_to_wrap_arrays
Add new `ZipWithoutBlock` cop
2 parents 063b56d + c4308ae commit 2d36cac

File tree

5 files changed

+453
-0
lines changed

5 files changed

+453
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
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][])

config/default.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,3 +381,9 @@ Performance/UriDefaultParser:
381381
Description: 'Use `URI::DEFAULT_PARSER` instead of `URI::Parser.new`.'
382382
Enabled: true
383383
VersionAdded: '0.50'
384+
385+
Performance/ZipWithoutBlock:
386+
Description: 'Checks for `map { |id| [id] }` and suggests replacing it with `zip`.'
387+
Enabled: pending
388+
Safe: false
389+
VersionAdded: <<next>>
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# frozen_string_literal: true
2+
3+
module RuboCop
4+
module Cop
5+
module Performance
6+
# Checks for `map { |id| [id] }` and suggests replacing it with `zip`.
7+
#
8+
# @safety
9+
# This cop is unsafe for novel definitions of `map` and `collect`
10+
# on non-Enumerable objects that do not respond to `zip`.
11+
# To make your object enumerable, define an `each` method
12+
# as described in https://ruby-doc.org/core/Enumerable.html
13+
#
14+
# @example
15+
# # bad
16+
# [1, 2, 3].map { |id| [id] }
17+
#
18+
# # good
19+
# [1, 2, 3].zip
20+
class ZipWithoutBlock < Base
21+
extend AutoCorrector
22+
23+
MSG = 'Use `zip` without a block argument instead.'
24+
RESTRICT_ON_SEND = Set.new(%i[map collect]).freeze
25+
26+
# @!method map_with_array?(node)
27+
def_node_matcher :map_with_array?, <<~PATTERN
28+
{
29+
(block (call !nil? RESTRICT_ON_SEND) (args (arg _)) (array (lvar _)))
30+
(numblock (call !nil? RESTRICT_ON_SEND) 1 (array (lvar _)))
31+
}
32+
PATTERN
33+
34+
def on_send(node)
35+
return unless map_with_array?(node.parent)
36+
37+
register_offense(node)
38+
end
39+
alias on_csend on_send
40+
41+
private
42+
43+
def register_offense(node)
44+
offense_range = offense_range(node)
45+
add_offense(offense_range) do |corrector|
46+
corrector.replace(offense_range, 'zip')
47+
end
48+
end
49+
50+
def offense_range(node)
51+
node.loc.selector.join(node.parent.loc.end)
52+
end
53+
end
54+
end
55+
end
56+
end

lib/rubocop/cop/performance_cops.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,4 @@
5454
require_relative 'performance/unfreeze_string'
5555
require_relative 'performance/uri_default_parser'
5656
require_relative 'performance/chain_array_allocation'
57+
require_relative 'performance/zip_without_block'

0 commit comments

Comments
 (0)