forked from rubocop/rubocop-performance
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsize.rb
75 lines (68 loc) · 1.87 KB
/
size.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# frozen_string_literal: true
module RuboCop
module Cop
module Performance
# Identifies usages of `count` on an `Array` and `Hash` and change them to `size`.
#
# @example
# # bad
# [1, 2, 3].count
# (1..3).to_a.count
# Array[*1..3].count
# Array(1..3).count
#
# # bad
# {a: 1, b: 2, c: 3}.count
# [[:foo, :bar], [1, 2]].to_h.count
# Hash[*('a'..'z')].count
# Hash(key: :value).count
#
# # good
# [1, 2, 3].size
# (1..3).to_a.size
# Array[*1..3].size
# Array(1..3).size
#
# # good
# {a: 1, b: 2, c: 3}.size
# [[:foo, :bar], [1, 2]].to_h.size
# Hash[*('a'..'z')].size
# Hash(key: :value).size
#
# # good
# [1, 2, 3].count { |e| e > 2 }
# TODO: Add advanced detection of variables that could
# have been assigned to an array or a hash.
class Size < Base
extend AutoCorrector
MSG = 'Use `size` instead of `count`.'
RESTRICT_ON_SEND = %i[count].freeze
def_node_matcher :array?, <<~PATTERN
{
[!nil? array_type?]
(send _ :to_a)
(send (const nil? :Array) :[] _)
(send nil? :Array _)
}
PATTERN
def_node_matcher :hash?, <<~PATTERN
{
[!nil? hash_type?]
(send _ :to_h)
(send (const nil? :Hash) :[] _)
(send nil? :Hash _)
}
PATTERN
def_node_matcher :count?, <<~PATTERN
(send {#array? #hash?} :count)
PATTERN
def on_send(node)
return if node.parent&.block_type? || !count?(node)
add_offense(node.loc.selector) do |corrector|
corrector.replace(node.loc.selector, 'size')
end
end
end
end
end
end