rubocop-performance 1.8.0 → 1.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 00b98a3d2af1bcfd781dfab24e4a8deb118d29fdaedeca8b2d404ff03eab3529
4
- data.tar.gz: cc5508a731d9c932d2c141892aefbe15f635d18bdd95ae6ad5b4998c931fcaf2
3
+ metadata.gz: f1f4841e8542a1f77f21d30ffe7c26019b9f2fb7308a985780506f1920146045
4
+ data.tar.gz: ed95379cd20af662ce6ce9ce4e64721ca156a6d7b62e511774df9d6abe3c9bae
5
5
  SHA512:
6
- metadata.gz: 806f21556b5e791a6a00866714c4feec42726b20d4c82db7c4cd89ec576624eaac3007f4a68fca4fd633fbc3ed7a41801fdb0dfc64f767ee241582a4185bbb8b
7
- data.tar.gz: 1e922a3d51a62df60cdb26f99960fec91e1fa558ceea751bcce7ec529f7d4db6e1644d0dfd24848cb75e384e08fd6a3f2afaaa8f531a1118a09d35d6fa1b0e21
6
+ metadata.gz: 10a1e89448abd75234807bbdd9be67b10e4b9a837d2d2d711adeb0a0d105b921d722dfcac0c46e30f55f278afc2960f888407959543097d81df4f1aa3667fac6
7
+ data.tar.gz: 668784bfe08775a1e8917806ef9f34d7dcb3f7581a9080ea14a44a54b43cf7e6516db4f5c4e015718824c32a8b045f43b429c8e1d3864960f41ead8684fbb5f5
@@ -115,7 +115,7 @@ module RuboCop
115
115
 
116
116
  def node_within_enumerable_loop?(node, ancestor)
117
117
  enumerable_loop?(ancestor) do |receiver|
118
- receiver != node && !receiver.descendants.include?(node)
118
+ receiver != node && !receiver&.descendants&.include?(node)
119
119
  end
120
120
  end
121
121
 
@@ -3,8 +3,8 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Performance
6
- # This cop is used to identify usages of
7
- # `select.first`, `select.last`, `find_all.first`, `find_all.last`, `filter.first`, and `filter.last`
6
+ # This cop is used to identify usages of `first`, `last`, `[0]` or `[-1]`
7
+ # chained to `select`, `find_all`, or `find_all`
8
8
  # and change them to use `detect` instead.
9
9
  #
10
10
  # @example
@@ -15,6 +15,8 @@ module RuboCop
15
15
  # [].find_all { |item| true }.last
16
16
  # [].filter { |item| true }.first
17
17
  # [].filter { |item| true }.last
18
+ # [].filter { |item| true }[0]
19
+ # [].filter { |item| true }[-1]
18
20
  #
19
21
  # # good
20
22
  # [].detect { |item| true }
@@ -27,27 +29,40 @@ module RuboCop
27
29
  class Detect < Base
28
30
  extend AutoCorrector
29
31
 
32
+ CANDIDATE_METHODS = Set[:select, :find_all, :filter].freeze
33
+
30
34
  MSG = 'Use `%<prefer>s` instead of ' \
31
35
  '`%<first_method>s.%<second_method>s`.'
32
36
  REVERSE_MSG = 'Use `reverse.%<prefer>s` instead of ' \
33
37
  '`%<first_method>s.%<second_method>s`.'
38
+ INDEX_MSG = 'Use `%<prefer>s` instead of ' \
39
+ '`%<first_method>s[%<index>i]`.'
40
+ INDEX_REVERSE_MSG = 'Use `reverse.%<prefer>s` instead of ' \
41
+ '`%<first_method>s[%<index>i]`.'
34
42
 
35
43
  def_node_matcher :detect_candidate?, <<~PATTERN
36
44
  {
37
- (send $(block (send _ {:select :find_all :filter}) ...) ${:first :last} $...)
38
- (send $(send _ {:select :find_all :filter} ...) ${:first :last} $...)
45
+ (send $(block (send _ %CANDIDATE_METHODS) ...) ${:first :last} $...)
46
+ (send $(block (send _ %CANDIDATE_METHODS) ...) $:[] (int ${0 -1}))
47
+ (send $(send _ %CANDIDATE_METHODS ...) ${:first :last} $...)
48
+ (send $(send _ %CANDIDATE_METHODS ...) $:[] (int ${0 -1}))
39
49
  }
40
50
  PATTERN
41
51
 
42
52
  def on_send(node)
43
53
  detect_candidate?(node) do |receiver, second_method, args|
54
+ if second_method == :[]
55
+ index = args
56
+ args = {}
57
+ end
58
+
44
59
  return unless args.empty?
45
60
  return unless receiver
46
61
 
47
62
  receiver, _args, body = *receiver if receiver.block_type?
48
63
  return if accept_first_call?(receiver, body)
49
64
 
50
- register_offense(node, receiver, second_method)
65
+ register_offense(node, receiver, second_method, index)
51
66
  end
52
67
  end
53
68
 
@@ -62,28 +77,31 @@ module RuboCop
62
77
  lazy?(caller)
63
78
  end
64
79
 
65
- def register_offense(node, receiver, second_method)
80
+ def register_offense(node, receiver, second_method, index)
66
81
  _caller, first_method, _args = *receiver
67
82
  range = receiver.loc.selector.join(node.loc.selector)
68
83
 
69
- message = second_method == :last ? REVERSE_MSG : MSG
84
+ message = message_for_method(second_method, index)
70
85
  formatted_message = format(message, prefer: preferred_method,
71
86
  first_method: first_method,
72
- second_method: second_method)
87
+ second_method: second_method,
88
+ index: index)
73
89
 
74
90
  add_offense(range, message: formatted_message) do |corrector|
75
- autocorrect(corrector, node)
91
+ autocorrect(corrector, node, replacement(second_method, index))
76
92
  end
77
93
  end
78
94
 
79
- def autocorrect(corrector, node)
80
- receiver, first_method = *node
95
+ def replacement(method, index)
96
+ if method == :last || method == :[] && index == -1
97
+ "reverse.#{preferred_method}"
98
+ else
99
+ preferred_method
100
+ end
101
+ end
81
102
 
82
- replacement = if first_method == :last
83
- "reverse.#{preferred_method}"
84
- else
85
- preferred_method
86
- end
103
+ def autocorrect(corrector, node, replacement)
104
+ receiver, _first_method = *node
87
105
 
88
106
  first_range = receiver.source_range.end.join(node.loc.selector)
89
107
 
@@ -93,6 +111,17 @@ module RuboCop
93
111
  corrector.replace(receiver.loc.selector, replacement)
94
112
  end
95
113
 
114
+ def message_for_method(method, index)
115
+ case method
116
+ when :[]
117
+ index == -1 ? INDEX_REVERSE_MSG : INDEX_MSG
118
+ when :last
119
+ REVERSE_MSG
120
+ else
121
+ MSG
122
+ end
123
+ end
124
+
96
125
  def preferred_method
97
126
  config.for_cop('Style/CollectionMethods')['PreferredMethods']['detect'] || 'detect'
98
127
  end
@@ -10,6 +10,7 @@ module RuboCop
10
10
  # # bad
11
11
  # [1, 2, 3].inject(:+)
12
12
  # [1, 2, 3].reduce(10, :+)
13
+ # [1, 2, 3].inject(&:+)
13
14
  # [1, 2, 3].reduce { |acc, elem| acc + elem }
14
15
  #
15
16
  # # good
@@ -24,7 +25,7 @@ module RuboCop
24
25
  MSG = 'Use `%<good_method>s` instead of `%<bad_method>s`.'
25
26
 
26
27
  def_node_matcher :sum_candidate?, <<~PATTERN
27
- (send _ ${:inject :reduce} $_init ? (sym :+))
28
+ (send _ ${:inject :reduce} $_init ? ${(sym :+) (block_pass (sym :+))})
28
29
  PATTERN
29
30
 
30
31
  def_node_matcher :sum_with_block_candidate?, <<~PATTERN
@@ -40,9 +41,9 @@ module RuboCop
40
41
  alias elem_plus_acc? acc_plus_elem?
41
42
 
42
43
  def on_send(node)
43
- sum_candidate?(node) do |method, init|
44
+ sum_candidate?(node) do |method, init, operation|
44
45
  range = sum_method_range(node)
45
- message = build_method_message(method, init)
46
+ message = build_method_message(method, init, operation)
46
47
 
47
48
  add_offense(range, message: message) do |corrector|
48
49
  autocorrect(corrector, init, range)
@@ -81,9 +82,9 @@ module RuboCop
81
82
  range_between(send.loc.selector.begin_pos, node.loc.end.end_pos)
82
83
  end
83
84
 
84
- def build_method_message(method, init)
85
+ def build_method_message(method, init, operation)
85
86
  good_method = build_good_method(init)
86
- bad_method = build_method_bad_method(init, method)
87
+ bad_method = build_method_bad_method(init, method, operation)
87
88
  format(MSG, good_method: good_method, bad_method: bad_method)
88
89
  end
89
90
 
@@ -98,18 +99,22 @@ module RuboCop
98
99
 
99
100
  unless init.empty?
100
101
  init = init.first
101
- good_method += "(#{init.source})" if init.source.to_i != 0
102
+ good_method += "(#{init.source})" unless init.int_type? && init.value.zero?
102
103
  end
103
104
  good_method
104
105
  end
105
106
 
106
- def build_method_bad_method(init, method)
107
+ def build_method_bad_method(init, method, operation)
107
108
  bad_method = "#{method}("
108
109
  unless init.empty?
109
110
  init = init.first
110
111
  bad_method += "#{init.source}, "
111
112
  end
112
- bad_method += ':+)'
113
+ bad_method += if operation.block_pass_type?
114
+ '&:+)'
115
+ else
116
+ ':+)'
117
+ end
113
118
  bad_method
114
119
  end
115
120
 
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Performance
5
5
  module Version
6
- STRING = '1.8.0'
6
+ STRING = '1.8.1'
7
7
  end
8
8
  end
9
9
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-performance
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.0
4
+ version: 1.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Batsov
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2020-09-04 00:00:00.000000000 Z
13
+ date: 2020-09-18 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rubocop
@@ -26,6 +26,20 @@ dependencies:
26
26
  - - ">="
27
27
  - !ruby/object:Gem::Version
28
28
  version: 0.87.0
29
+ - !ruby/object:Gem::Dependency
30
+ name: rubocop-ast
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: 0.4.0
36
+ type: :runtime
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 0.4.0
29
43
  - !ruby/object:Gem::Dependency
30
44
  name: simplecov
31
45
  requirement: !ruby/object:Gem::Requirement