rubocop-performance 1.8.0 → 1.8.1

Sign up to get free protection for your applications and to get access to all the features.
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