commit
1d7788077b
@ -107,10 +107,11 @@ GEM
|
|||||||
rubocop-ast (>= 0.4.0, < 1.0)
|
rubocop-ast (>= 0.4.0, < 1.0)
|
||||||
ruby-progressbar (~> 1.7)
|
ruby-progressbar (~> 1.7)
|
||||||
unicode-display_width (>= 1.4.0, < 2.0)
|
unicode-display_width (>= 1.4.0, < 2.0)
|
||||||
rubocop-ast (0.4.1)
|
rubocop-ast (0.4.2)
|
||||||
parser (>= 2.7.1.4)
|
parser (>= 2.7.1.4)
|
||||||
rubocop-performance (1.8.0)
|
rubocop-performance (1.8.1)
|
||||||
rubocop (>= 0.87.0)
|
rubocop (>= 0.87.0)
|
||||||
|
rubocop-ast (>= 0.4.0)
|
||||||
rubocop-rspec (1.43.2)
|
rubocop-rspec (1.43.2)
|
||||||
rubocop (~> 0.87)
|
rubocop (~> 0.87)
|
||||||
ruby-macho (2.2.0)
|
ruby-macho (2.2.0)
|
||||||
@ -173,4 +174,4 @@ DEPENDENCIES
|
|||||||
tapioca
|
tapioca
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
1.17.2
|
1.17.3
|
||||||
|
|||||||
@ -8,7 +8,7 @@ require "English"
|
|||||||
|
|
||||||
module Homebrew
|
module Homebrew
|
||||||
# Keep in sync with the Gemfile.lock's BUNDLED WITH.
|
# Keep in sync with the Gemfile.lock's BUNDLED WITH.
|
||||||
HOMEBREW_BUNDLER_VERSION = "1.17.2"
|
HOMEBREW_BUNDLER_VERSION = "1.17.3"
|
||||||
|
|
||||||
module_function
|
module_function
|
||||||
|
|
||||||
|
|||||||
16
Library/Homebrew/vendor/bundle/bundler/setup.rb
vendored
16
Library/Homebrew/vendor/bundle/bundler/setup.rb
vendored
@ -48,10 +48,10 @@ $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/mechanize-2.7.6/lib"
|
|||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/method_source-1.0.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/method_source-1.0.0/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/mustache-1.1.1/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/mustache-1.1.1/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parallel-1.19.2/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parallel-1.19.2/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parallel_tests-3.2.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parallel_tests-3.3.0/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parser-2.7.1.4/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parser-2.7.1.4/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rainbow-3.0.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rainbow-3.0.0/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-runtime-0.5.5895/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-runtime-0.5.5913/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parlour-4.0.1/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parlour-4.0.1/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/patchelf-1.3.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/patchelf-1.3.0/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/plist-3.5.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/plist-3.5.0/lib"
|
||||||
@ -69,15 +69,15 @@ $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rspec-3.9.0/lib"
|
|||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rspec-its-1.3.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rspec-its-1.3.0/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rspec-retry-0.6.2/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rspec-retry-0.6.2/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rspec-wait-0.0.9/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rspec-wait-0.0.9/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-ast-0.3.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-ast-0.4.2/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ruby-progressbar-1.10.1/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ruby-progressbar-1.10.1/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/unicode-display_width-1.7.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/unicode-display_width-1.7.0/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-0.90.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-0.91.0/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-performance-1.8.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-performance-1.8.1/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-rspec-1.43.2/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-rspec-1.43.2/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ruby-macho-2.2.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ruby-macho-2.2.0/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-static-0.5.5898-universal-darwin-19/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-static-0.5.5913-universal-darwin-19/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-0.5.5898/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-0.5.5913/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/thor-1.0.1/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/thor-1.0.1/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/spoom-1.0.4/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/spoom-1.0.4/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/tapioca-0.4.4/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/tapioca-0.4.6/lib"
|
||||||
|
|||||||
@ -115,7 +115,7 @@ module RuboCop
|
|||||||
|
|
||||||
def node_within_enumerable_loop?(node, ancestor)
|
def node_within_enumerable_loop?(node, ancestor)
|
||||||
enumerable_loop?(ancestor) do |receiver|
|
enumerable_loop?(ancestor) do |receiver|
|
||||||
receiver != node && !receiver.descendants.include?(node)
|
receiver != node && !receiver&.descendants&.include?(node)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -3,8 +3,8 @@
|
|||||||
module RuboCop
|
module RuboCop
|
||||||
module Cop
|
module Cop
|
||||||
module Performance
|
module Performance
|
||||||
# This cop is used to identify usages of
|
# This cop is used to identify usages of `first`, `last`, `[0]` or `[-1]`
|
||||||
# `select.first`, `select.last`, `find_all.first`, `find_all.last`, `filter.first`, and `filter.last`
|
# chained to `select`, `find_all`, or `find_all`
|
||||||
# and change them to use `detect` instead.
|
# and change them to use `detect` instead.
|
||||||
#
|
#
|
||||||
# @example
|
# @example
|
||||||
@ -15,6 +15,8 @@ module RuboCop
|
|||||||
# [].find_all { |item| true }.last
|
# [].find_all { |item| true }.last
|
||||||
# [].filter { |item| true }.first
|
# [].filter { |item| true }.first
|
||||||
# [].filter { |item| true }.last
|
# [].filter { |item| true }.last
|
||||||
|
# [].filter { |item| true }[0]
|
||||||
|
# [].filter { |item| true }[-1]
|
||||||
#
|
#
|
||||||
# # good
|
# # good
|
||||||
# [].detect { |item| true }
|
# [].detect { |item| true }
|
||||||
@ -27,27 +29,40 @@ module RuboCop
|
|||||||
class Detect < Base
|
class Detect < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
|
CANDIDATE_METHODS = Set[:select, :find_all, :filter].freeze
|
||||||
|
|
||||||
MSG = 'Use `%<prefer>s` instead of ' \
|
MSG = 'Use `%<prefer>s` instead of ' \
|
||||||
'`%<first_method>s.%<second_method>s`.'
|
'`%<first_method>s.%<second_method>s`.'
|
||||||
REVERSE_MSG = 'Use `reverse.%<prefer>s` instead of ' \
|
REVERSE_MSG = 'Use `reverse.%<prefer>s` instead of ' \
|
||||||
'`%<first_method>s.%<second_method>s`.'
|
'`%<first_method>s.%<second_method>s`.'
|
||||||
|
INDEX_MSG = 'Use `%<prefer>s` instead of ' \
|
||||||
|
'`%<first_method>s[%<index>i]`.'
|
||||||
|
INDEX_REVERSE_MSG = 'Use `reverse.%<prefer>s` instead of ' \
|
||||||
|
'`%<first_method>s[%<index>i]`.'
|
||||||
|
|
||||||
def_node_matcher :detect_candidate?, <<~PATTERN
|
def_node_matcher :detect_candidate?, <<~PATTERN
|
||||||
{
|
{
|
||||||
(send $(block (send _ {:select :find_all :filter}) ...) ${:first :last} $...)
|
(send $(block (send _ %CANDIDATE_METHODS) ...) ${:first :last} $...)
|
||||||
(send $(send _ {:select :find_all :filter} ...) ${:first :last} $...)
|
(send $(block (send _ %CANDIDATE_METHODS) ...) $:[] (int ${0 -1}))
|
||||||
|
(send $(send _ %CANDIDATE_METHODS ...) ${:first :last} $...)
|
||||||
|
(send $(send _ %CANDIDATE_METHODS ...) $:[] (int ${0 -1}))
|
||||||
}
|
}
|
||||||
PATTERN
|
PATTERN
|
||||||
|
|
||||||
def on_send(node)
|
def on_send(node)
|
||||||
detect_candidate?(node) do |receiver, second_method, args|
|
detect_candidate?(node) do |receiver, second_method, args|
|
||||||
|
if second_method == :[]
|
||||||
|
index = args
|
||||||
|
args = {}
|
||||||
|
end
|
||||||
|
|
||||||
return unless args.empty?
|
return unless args.empty?
|
||||||
return unless receiver
|
return unless receiver
|
||||||
|
|
||||||
receiver, _args, body = *receiver if receiver.block_type?
|
receiver, _args, body = *receiver if receiver.block_type?
|
||||||
return if accept_first_call?(receiver, body)
|
return if accept_first_call?(receiver, body)
|
||||||
|
|
||||||
register_offense(node, receiver, second_method)
|
register_offense(node, receiver, second_method, index)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -62,28 +77,31 @@ module RuboCop
|
|||||||
lazy?(caller)
|
lazy?(caller)
|
||||||
end
|
end
|
||||||
|
|
||||||
def register_offense(node, receiver, second_method)
|
def register_offense(node, receiver, second_method, index)
|
||||||
_caller, first_method, _args = *receiver
|
_caller, first_method, _args = *receiver
|
||||||
range = receiver.loc.selector.join(node.loc.selector)
|
range = receiver.loc.selector.join(node.loc.selector)
|
||||||
|
|
||||||
message = second_method == :last ? REVERSE_MSG : MSG
|
message = message_for_method(second_method, index)
|
||||||
formatted_message = format(message, prefer: preferred_method,
|
formatted_message = format(message, prefer: preferred_method,
|
||||||
first_method: first_method,
|
first_method: first_method,
|
||||||
second_method: second_method)
|
second_method: second_method,
|
||||||
|
index: index)
|
||||||
|
|
||||||
add_offense(range, message: formatted_message) do |corrector|
|
add_offense(range, message: formatted_message) do |corrector|
|
||||||
autocorrect(corrector, node)
|
autocorrect(corrector, node, replacement(second_method, index))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def autocorrect(corrector, node)
|
def replacement(method, index)
|
||||||
receiver, first_method = *node
|
if method == :last || method == :[] && index == -1
|
||||||
|
"reverse.#{preferred_method}"
|
||||||
|
else
|
||||||
|
preferred_method
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
replacement = if first_method == :last
|
def autocorrect(corrector, node, replacement)
|
||||||
"reverse.#{preferred_method}"
|
receiver, _first_method = *node
|
||||||
else
|
|
||||||
preferred_method
|
|
||||||
end
|
|
||||||
|
|
||||||
first_range = receiver.source_range.end.join(node.loc.selector)
|
first_range = receiver.source_range.end.join(node.loc.selector)
|
||||||
|
|
||||||
@ -93,6 +111,17 @@ module RuboCop
|
|||||||
corrector.replace(receiver.loc.selector, replacement)
|
corrector.replace(receiver.loc.selector, replacement)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def message_for_method(method, index)
|
||||||
|
case method
|
||||||
|
when :[]
|
||||||
|
index == -1 ? INDEX_REVERSE_MSG : INDEX_MSG
|
||||||
|
when :last
|
||||||
|
REVERSE_MSG
|
||||||
|
else
|
||||||
|
MSG
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def preferred_method
|
def preferred_method
|
||||||
config.for_cop('Style/CollectionMethods')['PreferredMethods']['detect'] || 'detect'
|
config.for_cop('Style/CollectionMethods')['PreferredMethods']['detect'] || 'detect'
|
||||||
end
|
end
|
||||||
@ -10,6 +10,7 @@ module RuboCop
|
|||||||
# # bad
|
# # bad
|
||||||
# [1, 2, 3].inject(:+)
|
# [1, 2, 3].inject(:+)
|
||||||
# [1, 2, 3].reduce(10, :+)
|
# [1, 2, 3].reduce(10, :+)
|
||||||
|
# [1, 2, 3].inject(&:+)
|
||||||
# [1, 2, 3].reduce { |acc, elem| acc + elem }
|
# [1, 2, 3].reduce { |acc, elem| acc + elem }
|
||||||
#
|
#
|
||||||
# # good
|
# # good
|
||||||
@ -24,7 +25,7 @@ module RuboCop
|
|||||||
MSG = 'Use `%<good_method>s` instead of `%<bad_method>s`.'
|
MSG = 'Use `%<good_method>s` instead of `%<bad_method>s`.'
|
||||||
|
|
||||||
def_node_matcher :sum_candidate?, <<~PATTERN
|
def_node_matcher :sum_candidate?, <<~PATTERN
|
||||||
(send _ ${:inject :reduce} $_init ? (sym :+))
|
(send _ ${:inject :reduce} $_init ? ${(sym :+) (block_pass (sym :+))})
|
||||||
PATTERN
|
PATTERN
|
||||||
|
|
||||||
def_node_matcher :sum_with_block_candidate?, <<~PATTERN
|
def_node_matcher :sum_with_block_candidate?, <<~PATTERN
|
||||||
@ -40,9 +41,9 @@ module RuboCop
|
|||||||
alias elem_plus_acc? acc_plus_elem?
|
alias elem_plus_acc? acc_plus_elem?
|
||||||
|
|
||||||
def on_send(node)
|
def on_send(node)
|
||||||
sum_candidate?(node) do |method, init|
|
sum_candidate?(node) do |method, init, operation|
|
||||||
range = sum_method_range(node)
|
range = sum_method_range(node)
|
||||||
message = build_method_message(method, init)
|
message = build_method_message(method, init, operation)
|
||||||
|
|
||||||
add_offense(range, message: message) do |corrector|
|
add_offense(range, message: message) do |corrector|
|
||||||
autocorrect(corrector, init, range)
|
autocorrect(corrector, init, range)
|
||||||
@ -81,9 +82,9 @@ module RuboCop
|
|||||||
range_between(send.loc.selector.begin_pos, node.loc.end.end_pos)
|
range_between(send.loc.selector.begin_pos, node.loc.end.end_pos)
|
||||||
end
|
end
|
||||||
|
|
||||||
def build_method_message(method, init)
|
def build_method_message(method, init, operation)
|
||||||
good_method = build_good_method(init)
|
good_method = build_good_method(init)
|
||||||
bad_method = build_method_bad_method(init, method)
|
bad_method = build_method_bad_method(init, method, operation)
|
||||||
format(MSG, good_method: good_method, bad_method: bad_method)
|
format(MSG, good_method: good_method, bad_method: bad_method)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -98,18 +99,22 @@ module RuboCop
|
|||||||
|
|
||||||
unless init.empty?
|
unless init.empty?
|
||||||
init = init.first
|
init = init.first
|
||||||
good_method += "(#{init.source})" if init.source.to_i != 0
|
good_method += "(#{init.source})" unless init.int_type? && init.value.zero?
|
||||||
end
|
end
|
||||||
good_method
|
good_method
|
||||||
end
|
end
|
||||||
|
|
||||||
def build_method_bad_method(init, method)
|
def build_method_bad_method(init, method, operation)
|
||||||
bad_method = "#{method}("
|
bad_method = "#{method}("
|
||||||
unless init.empty?
|
unless init.empty?
|
||||||
init = init.first
|
init = init.first
|
||||||
bad_method += "#{init.source}, "
|
bad_method += "#{init.source}, "
|
||||||
end
|
end
|
||||||
bad_method += ':+)'
|
bad_method += if operation.block_pass_type?
|
||||||
|
'&:+)'
|
||||||
|
else
|
||||||
|
':+)'
|
||||||
|
end
|
||||||
bad_method
|
bad_method
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -3,7 +3,7 @@
|
|||||||
module RuboCop
|
module RuboCop
|
||||||
module Performance
|
module Performance
|
||||||
module Version
|
module Version
|
||||||
STRING = '1.8.0'
|
STRING = '1.8.1'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
Loading…
x
Reference in New Issue
Block a user