@@ -5,35 +5,42 @@ module Cop
55 module Performance
66 # Identifies places where `sort { |a, b| a.foo <=> b.foo }`
77 # can be replaced by `sort_by(&:foo)`.
8- # This cop also checks `max` and `min ` methods.
8+ # This cop also checks `sort!`, `min`, ` max` and `minmax ` methods.
99 #
1010 # @example
1111 # # bad
12- # array.sort { |a, b| a.foo <=> b.foo }
13- # array.max { |a, b| a.foo <=> b.foo }
14- # array.min { |a, b| a.foo <=> b.foo }
15- # array.sort { |a, b| a[:foo] <=> b[:foo] }
12+ # array.sort { |a, b| a.foo <=> b.foo }
13+ # array.sort! { |a, b| a.foo <=> b.foo }
14+ # array.max { |a, b| a.foo <=> b.foo }
15+ # array.min { |a, b| a.foo <=> b.foo }
16+ # array.minmax { |a, b| a.foo <=> b.foo }
17+ # array.sort { |a, b| a[:foo] <=> b[:foo] }
1618 #
1719 # # good
1820 # array.sort_by(&:foo)
21+ # array.sort_by!(&:foo)
1922 # array.sort_by { |v| v.foo }
2023 # array.sort_by do |var|
2124 # var.foo
2225 # end
2326 # array.max_by(&:foo)
2427 # array.min_by(&:foo)
28+ # array.minmax_by(&:foo)
2529 # array.sort_by { |a| a[:foo] }
2630 class CompareWithBlock < Base
2731 include RangeHelp
2832 extend AutoCorrector
2933
30- MSG = 'Use `%<compare_method>s_by %<instead>s` instead of ' \
34+ MSG = 'Use `%<replacement_method>s %<instead>s` instead of ' \
3135 '`%<compare_method>s { |%<var_a>s, %<var_b>s| %<str_a>s ' \
3236 '<=> %<str_b>s }`.'
3337
38+ REPLACEMENT = { sort : :sort_by , sort! : :sort_by! , min : :min_by , max : :max_by , minmax : :minmax_by } . freeze
39+ private_constant :REPLACEMENT
40+
3441 def_node_matcher :compare? , <<~PATTERN
3542 (block
36- $(send _ {:sort :min :max})
43+ $(send _ {:sort :sort! : min :max :minmax })
3744 (args (arg $_a) (arg $_b))
3845 $send)
3946 PATTERN
@@ -54,9 +61,9 @@ def on_block(node)
5461
5562 add_offense ( range , message : message ( send , method , var_a , var_b , args_a ) ) do |corrector |
5663 replacement = if method == :[]
57- "#{ send . method_name } _by { |a| a[#{ args_a . first . source } ] }"
64+ "#{ REPLACEMENT [ send . method_name ] } { |a| a[#{ args_a . first . source } ] }"
5865 else
59- "#{ send . method_name } _by (&:#{ method } )"
66+ "#{ REPLACEMENT [ send . method_name ] } (&:#{ method } )"
6067 end
6168 corrector . replace ( range , replacement )
6269 end
@@ -82,7 +89,8 @@ def slow_compare?(method, args_a, args_b)
8289
8390 # rubocop:disable Metrics/MethodLength
8491 def message ( send , method , var_a , var_b , args )
85- compare_method = send . method_name
92+ compare_method = send . method_name
93+ replacement_method = REPLACEMENT [ compare_method ]
8694 if method == :[]
8795 key = args . first
8896 instead = " { |a| a[#{ key . source } ] }"
@@ -94,6 +102,7 @@ def message(send, method, var_a, var_b, args)
94102 str_b = "#{ var_b } .#{ method } "
95103 end
96104 format ( MSG , compare_method : compare_method ,
105+ replacement_method : replacement_method ,
97106 instead : instead ,
98107 var_a : var_a ,
99108 var_b : var_b ,
0 commit comments