diff --git a/Library/Homebrew/Gemfile b/Library/Homebrew/Gemfile index 975ad63837..bf6f42025a 100644 --- a/Library/Homebrew/Gemfile +++ b/Library/Homebrew/Gemfile @@ -20,5 +20,6 @@ gem "backports" gem "concurrent-ruby" gem "mechanize" gem "plist" +gem "rubocop-performance" gem "rubocop-rspec" gem "ruby-macho" diff --git a/Library/Homebrew/Gemfile.lock b/Library/Homebrew/Gemfile.lock index 5573978be7..fc6c5d725d 100644 --- a/Library/Homebrew/Gemfile.lock +++ b/Library/Homebrew/Gemfile.lock @@ -87,6 +87,8 @@ GEM rainbow (>= 2.2.2, < 4.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 1.6) + rubocop-performance (1.1.0) + rubocop (>= 0.67.0) rubocop-rspec (1.32.0) rubocop (>= 0.60.0) ruby-macho (2.2.0) @@ -128,6 +130,7 @@ DEPENDENCIES rspec-retry rspec-wait rubocop + rubocop-performance rubocop-rspec ruby-macho simplecov diff --git a/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop-performance.rb b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop-performance.rb new file mode 100644 index 0000000000..d7865b5453 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop-performance.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require 'rubocop' + +require_relative 'rubocop/performance' +require_relative 'rubocop/performance/version' +require_relative 'rubocop/performance/inject' + +RuboCop::Performance::Inject.defaults! + +require_relative 'rubocop/cop/performance_cops' diff --git a/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/caller.rb b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/caller.rb new file mode 100644 index 0000000000..92a70e76a2 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/caller.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Performance + # This cop identifies places where `caller[n]` + # can be replaced by `caller(n..n).first`. + # + # @example + # # bad + # caller[1] + # caller.first + # caller_locations[1] + # caller_locations.first + # + # # good + # caller(2..2).first + # caller(1..1).first + # caller_locations(2..2).first + # caller_locations(1..1).first + class Caller < Cop + MSG_BRACE = 'Use `%s(%d..%d).first`' \ + ' instead of `%s[%d]`.'.freeze + MSG_FIRST = 'Use `%s(%d..%d).first`' \ + ' instead of `%s.first`.'.freeze + + def_node_matcher :slow_caller?, <<-PATTERN + { + (send nil? {:caller :caller_locations}) + (send nil? {:caller :caller_locations} int) + } + PATTERN + + def_node_matcher :caller_with_scope_method?, <<-PATTERN + { + (send #slow_caller? :first) + (send #slow_caller? :[] int) + } + PATTERN + + def on_send(node) + return unless caller_with_scope_method?(node) + + add_offense(node) + end + + private + + def message(node) + method_name = node.receiver.method_name + caller_arg = node.receiver.first_argument + n = caller_arg ? int_value(caller_arg) : 1 + + if node.method_name == :[] + m = int_value(node.first_argument) + n += m + format(MSG_BRACE, n: n, m: m, method: method_name) + else + format(MSG_FIRST, n: n, method: method_name) + end + end + + def int_value(node) + node.children[0] + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/case_when_splat.rb b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/case_when_splat.rb new file mode 100644 index 0000000000..a536425ad8 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/case_when_splat.rb @@ -0,0 +1,177 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Performance + # Reordering `when` conditions with a splat to the end + # of the `when` branches can improve performance. + # + # Ruby has to allocate memory for the splat expansion every time + # that the `case` `when` statement is run. Since Ruby does not support + # fall through inside of `case` `when`, like some other languages do, + # the order of the `when` branches should not matter. By placing any + # splat expansions at the end of the list of `when` branches we will + # reduce the number of times that memory has to be allocated for + # the expansion. The exception to this is if multiple of your `when` + # conditions can be true for any given condition. A likely scenario for + # this defining a higher level when condition to override a condition + # that is inside of the splat expansion. + # + # This is not a guaranteed performance improvement. If the data being + # processed by the `case` condition is normalized in a manner that favors + # hitting a condition in the splat expansion, it is possible that + # moving the splat condition to the end will use more memory, + # and run slightly slower. + # + # @example + # # bad + # case foo + # when *condition + # bar + # when baz + # foobar + # end + # + # case foo + # when *[1, 2, 3, 4] + # bar + # when 5 + # baz + # end + # + # # good + # case foo + # when baz + # foobar + # when *condition + # bar + # end + # + # case foo + # when 1, 2, 3, 4 + # bar + # when 5 + # baz + # end + class CaseWhenSplat < Cop + include Alignment + include RangeHelp + + MSG = 'Reordering `when` conditions with a splat to the end ' \ + 'of the `when` branches can improve performance.'.freeze + ARRAY_MSG = 'Pass the contents of array literals ' \ + 'directly to `when` conditions.'.freeze + + def on_case(case_node) + when_conditions = case_node.when_branches.flat_map(&:conditions) + + splat_offenses(when_conditions).reverse_each do |condition| + range = condition.parent.loc.keyword.join(condition.source_range) + variable, = *condition + message = variable.array_type? ? ARRAY_MSG : MSG + add_offense(condition.parent, location: range, message: message) + end + end + + def autocorrect(when_node) + lambda do |corrector| + if needs_reorder?(when_node) + reorder_condition(corrector, when_node) + else + inline_fix_branch(corrector, when_node) + end + end + end + + private + + def replacement(conditions) + reordered = conditions.partition(&:splat_type?).reverse + reordered.flatten.map(&:source).join(', ') + end + + def inline_fix_branch(corrector, when_node) + conditions = when_node.conditions + range = range_between(conditions[0].loc.expression.begin_pos, + conditions[-1].loc.expression.end_pos) + + corrector.replace(range, replacement(conditions)) + end + + def reorder_condition(corrector, when_node) + when_branches = when_node.parent.when_branches + + return if when_branches.one? + + corrector.remove(when_branch_range(when_node)) + corrector.insert_after(when_branches.last.source_range, + reordering_correction(when_node)) + end + + def reordering_correction(when_node) + new_condition = replacement(when_node.conditions) + + if same_line?(when_node, when_node.body) + new_condition_with_then(when_node, new_condition) + else + new_branch_without_then(when_node, new_condition) + end + end + + def when_branch_range(when_node) + next_branch = + when_node.parent.when_branches[when_node.branch_index + 1] + + range_between(when_node.source_range.begin_pos, + next_branch.source_range.begin_pos) + end + + def new_condition_with_then(node, new_condition) + "\n#{indent_for(node)}when " \ + "#{new_condition} then #{node.body.source}" + end + + def new_branch_without_then(node, new_condition) + "\n#{indent_for(node)}when #{new_condition}" \ + "\n#{indent_for(node.body)}#{node.body.source}" + end + + def indent_for(node) + ' ' * node.loc.column + end + + def splat_offenses(when_conditions) + found_non_splat = false + + offenses = when_conditions.reverse.map do |condition| + found_non_splat ||= non_splat?(condition) + + next if non_splat?(condition) + + condition if found_non_splat + end + + offenses.compact + end + + def non_splat?(condition) + variable, = *condition + + (condition.splat_type? && variable.array_type?) || + !condition.splat_type? + end + + def needs_reorder?(when_node) + following_branches = + when_node.parent.when_branches[(when_node.branch_index + 1)..-1] + + following_branches.any? do |when_branch| + when_branch.conditions.any? do |condition| + non_splat?(condition) + end + end + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/casecmp.rb b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/casecmp.rb new file mode 100644 index 0000000000..ad9424bf39 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/casecmp.rb @@ -0,0 +1,108 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Performance + # This cop identifies places where a case-insensitive string comparison + # can better be implemented using `casecmp`. + # + # @example + # # bad + # str.downcase == 'abc' + # str.upcase.eql? 'ABC' + # 'abc' == str.downcase + # 'ABC'.eql? str.upcase + # str.downcase == str.downcase + # + # # good + # str.casecmp('ABC').zero? + # 'abc'.casecmp(str).zero? + class Casecmp < Cop + MSG = 'Use `%s` instead of `%s`.'.freeze + CASE_METHODS = %i[downcase upcase].freeze + + def_node_matcher :downcase_eq, <<-PATTERN + (send + $(send _ ${:downcase :upcase}) + ${:== :eql? :!=} + ${str (send _ {:downcase :upcase} ...) (begin str)}) + PATTERN + + def_node_matcher :eq_downcase, <<-PATTERN + (send + {str (send _ {:downcase :upcase} ...) (begin str)} + ${:== :eql? :!=} + $(send _ ${:downcase :upcase})) + PATTERN + + def_node_matcher :downcase_downcase, <<-PATTERN + (send + $(send _ ${:downcase :upcase}) + ${:== :eql? :!=} + $(send _ ${:downcase :upcase})) + PATTERN + + def on_send(node) + return unless downcase_eq(node) || eq_downcase(node) + return unless (parts = take_method_apart(node)) + + _, _, arg, variable = parts + good_method = build_good_method(arg, variable) + + add_offense( + node, + message: format(MSG, good: good_method, bad: node.source) + ) + end + + def autocorrect(node) + return unless (parts = take_method_apart(node)) + + receiver, method, arg, variable = parts + + correction(node, receiver, method, arg, variable) + end + + private + + def take_method_apart(node) + if downcase_downcase(node) + receiver, method, rhs = *node + arg, = *rhs + elsif downcase_eq(node) + receiver, method, arg = *node + elsif eq_downcase(node) + arg, method, receiver = *node + else + return + end + + variable, = *receiver + + [receiver, method, arg, variable] + end + + def correction(node, _receiver, method, arg, variable) + lambda do |corrector| + corrector.insert_before(node.loc.expression, '!') if method == :!= + + replacement = build_good_method(arg, variable) + + corrector.replace(node.loc.expression, replacement) + end + end + + def build_good_method(arg, variable) + # We want resulting call to be parenthesized + # if arg already includes one or more sets of parens, don't add more + # or if method call already used parens, again, don't add more + if arg.send_type? || !parentheses?(arg) + "#{variable.source}.casecmp(#{arg.source}).zero?" + else + "#{variable.source}.casecmp#{arg.source}.zero?" + end + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/chain_array_allocation.rb b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/chain_array_allocation.rb new file mode 100644 index 0000000000..dcad63ef8a --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/chain_array_allocation.rb @@ -0,0 +1,78 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Performance + # This cop is used to identify usages of + # @example + # # bad + # array = ["a", "b", "c"] + # array.compact.flatten.map { |x| x.downcase } + # + # Each of these methods (`compact`, `flatten`, `map`) will generate a + # new intermediate array that is promptly thrown away. Instead it is + # faster to mutate when we know it's safe. + # + # @example + # # good. + # array = ["a", "b", "c"] + # array.compact! + # array.flatten! + # array.map! { |x| x.downcase } + # array + class ChainArrayAllocation < Cop + include RangeHelp + + # These methods return a new array but only sometimes. They must be + # called with an argument. For example: + # + # [1,2].first # => 1 + # [1,2].first(1) # => [1] + # + RETURN_NEW_ARRAY_WHEN_ARGS = ':first :last :pop :sample :shift '.freeze + + # These methods return a new array only when called without a block. + RETURNS_NEW_ARRAY_WHEN_NO_BLOCK = ':zip :product '.freeze + + # These methods ALWAYS return a new array + # after they're called it's safe to mutate the the resulting array + ALWAYS_RETURNS_NEW_ARRAY = ':* :+ :- :collect :compact :drop '\ + ':drop_while :flatten :map :reject ' \ + ':reverse :rotate :select :shuffle :sort ' \ + ':take :take_while :transpose :uniq ' \ + ':values_at :| '.freeze + + # These methods have a mutation alternative. For example :collect + # can be called as :collect! + HAS_MUTATION_ALTERNATIVE = ':collect :compact :flatten :map :reject '\ + ':reverse :rotate :select :shuffle :sort '\ + ':uniq '.freeze + MSG = 'Use unchained `%s!` and `%s!` '\ + '(followed by `return array` if required) instead of chaining '\ + '`%s...%s`.'.freeze + + def_node_matcher :flat_map_candidate?, <<-PATTERN + { + (send (send _ ${#{RETURN_NEW_ARRAY_WHEN_ARGS}} {int lvar ivar cvar gvar}) ${#{HAS_MUTATION_ALTERNATIVE}} $...) + (send (block (send _ ${#{ALWAYS_RETURNS_NEW_ARRAY} }) ...) ${#{HAS_MUTATION_ALTERNATIVE}} $...) + (send (send _ ${#{ALWAYS_RETURNS_NEW_ARRAY + RETURNS_NEW_ARRAY_WHEN_NO_BLOCK}} ...) ${#{HAS_MUTATION_ALTERNATIVE}} $...) + } + PATTERN + + def on_send(node) + flat_map_candidate?(node) do |fm, sm, _| + range = range_between( + node.loc.dot.begin_pos, + node.source_range.end_pos + ) + add_offense( + node, + location: range, + message: format(MSG, method: fm, second_method: sm) + ) + end + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/compare_with_block.rb b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/compare_with_block.rb new file mode 100644 index 0000000000..a9b80a75a1 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/compare_with_block.rb @@ -0,0 +1,122 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Performance + # This cop identifies places where `sort { |a, b| a.foo <=> b.foo }` + # can be replaced by `sort_by(&:foo)`. + # This cop also checks `max` and `min` methods. + # + # @example + # # bad + # array.sort { |a, b| a.foo <=> b.foo } + # array.max { |a, b| a.foo <=> b.foo } + # array.min { |a, b| a.foo <=> b.foo } + # array.sort { |a, b| a[:foo] <=> b[:foo] } + # + # # good + # array.sort_by(&:foo) + # array.sort_by { |v| v.foo } + # array.sort_by do |var| + # var.foo + # end + # array.max_by(&:foo) + # array.min_by(&:foo) + # array.sort_by { |a| a[:foo] } + class CompareWithBlock < Cop + include RangeHelp + + MSG = 'Use `%s_by%s` instead of ' \ + '`%s { |%s, %s| %s ' \ + '<=> %s }`.'.freeze + + def_node_matcher :compare?, <<-PATTERN + (block + $(send _ {:sort :min :max}) + (args (arg $_a) (arg $_b)) + $send) + PATTERN + + def_node_matcher :replaceable_body?, <<-PATTERN + (send + (send (lvar %1) $_method $...) + :<=> + (send (lvar %2) _method $...)) + PATTERN + + def on_block(node) + compare?(node) do |send, var_a, var_b, body| + replaceable_body?(body, var_a, var_b) do |method, args_a, args_b| + return unless slow_compare?(method, args_a, args_b) + + range = compare_range(send, node) + + add_offense( + node, + location: range, + message: message(send, method, var_a, var_b, args_a) + ) + end + end + end + + def autocorrect(node) + lambda do |corrector| + send, var_a, var_b, body = compare?(node) + method, arg, = replaceable_body?(body, var_a, var_b) + replacement = + if method == :[] + "#{send.method_name}_by { |a| a[#{arg.first.source}] }" + else + "#{send.method_name}_by(&:#{method})" + end + corrector.replace(compare_range(send, node), + replacement) + end + end + + private + + def slow_compare?(method, args_a, args_b) + return false unless args_a == args_b + + if method == :[] + return false unless args_a.size == 1 + + key = args_a.first + return false unless %i[sym str int].include?(key.type) + else + return false unless args_a.empty? + end + true + end + + # rubocop:disable Metrics/MethodLength + def message(send, method, var_a, var_b, args) + compare_method = send.method_name + if method == :[] + key = args.first + instead = " { |a| a[#{key.source}] }" + str_a = "#{var_a}[#{key.source}]" + str_b = "#{var_b}[#{key.source}]" + else + instead = "(&:#{method})" + str_a = "#{var_a}.#{method}" + str_b = "#{var_b}.#{method}" + end + format(MSG, compare_method: compare_method, + instead: instead, + var_a: var_a, + var_b: var_b, + str_a: str_a, + str_b: str_b) + end + # rubocop:enable Metrics/MethodLength + + def compare_range(send, node) + range_between(send.loc.selector.begin_pos, node.loc.end.end_pos) + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/count.rb b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/count.rb new file mode 100644 index 0000000000..cdbee4166d --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/count.rb @@ -0,0 +1,102 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Performance + # This cop is used to identify usages of `count` on an `Enumerable` that + # follow calls to `select` or `reject`. Querying logic can instead be + # passed to the `count` call. + # + # @example + # # bad + # [1, 2, 3].select { |e| e > 2 }.size + # [1, 2, 3].reject { |e| e > 2 }.size + # [1, 2, 3].select { |e| e > 2 }.length + # [1, 2, 3].reject { |e| e > 2 }.length + # [1, 2, 3].select { |e| e > 2 }.count { |e| e.odd? } + # [1, 2, 3].reject { |e| e > 2 }.count { |e| e.even? } + # array.select(&:value).count + # + # # good + # [1, 2, 3].count { |e| e > 2 } + # [1, 2, 3].count { |e| e < 2 } + # [1, 2, 3].count { |e| e > 2 && e.odd? } + # [1, 2, 3].count { |e| e < 2 && e.even? } + # Model.select('field AS field_one').count + # Model.select(:value).count + # + # `ActiveRecord` compatibility: + # `ActiveRecord` will ignore the block that is passed to `count`. + # Other methods, such as `select`, will convert the association to an + # array and then run the block on the array. A simple work around to + # make `count` work with a block is to call `to_a.count {...}`. + # + # Example: + # Model.where(id: [1, 2, 3].select { |m| m.method == true }.size + # + # becomes: + # + # Model.where(id: [1, 2, 3]).to_a.count { |m| m.method == true } + class Count < Cop + include SafeMode + include RangeHelp + + MSG = 'Use `count` instead of `%s...%s`.'.freeze + + def_node_matcher :count_candidate?, <<-PATTERN + { + (send (block $(send _ ${:select :reject}) ...) ${:count :length :size}) + (send $(send _ ${:select :reject} (:block_pass _)) ${:count :length :size}) + } + PATTERN + + def on_send(node) + return if rails_safe_mode? + + count_candidate?(node) do |selector_node, selector, counter| + return unless eligible_node?(node) + + range = source_starting_at(node) do + selector_node.loc.selector.begin_pos + end + + add_offense(node, + location: range, + message: format(MSG, selector: selector, + counter: counter)) + end + end + + def autocorrect(node) + selector_node, selector, _counter = count_candidate?(node) + selector_loc = selector_node.loc.selector + + return if selector == :reject + + range = source_starting_at(node) { |n| n.loc.dot.begin_pos } + + lambda do |corrector| + corrector.remove(range) + corrector.replace(selector_loc, 'count') + end + end + + private + + def eligible_node?(node) + !(node.parent && node.parent.block_type?) + end + + def source_starting_at(node) + begin_pos = if block_given? + yield node + else + node.source_range.begin_pos + end + + range_between(begin_pos, node.source_range.end_pos) + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/detect.rb b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/detect.rb new file mode 100644 index 0000000000..417e2b6ca2 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/detect.rb @@ -0,0 +1,110 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Performance + # This cop is used to identify usages of + # `select.first`, `select.last`, `find_all.first`, and `find_all.last` + # and change them to use `detect` instead. + # + # @example + # # bad + # [].select { |item| true }.first + # [].select { |item| true }.last + # [].find_all { |item| true }.first + # [].find_all { |item| true }.last + # + # # good + # [].detect { |item| true } + # [].reverse.detect { |item| true } + # + # `ActiveRecord` compatibility: + # `ActiveRecord` does not implement a `detect` method and `find` has its + # own meaning. Correcting ActiveRecord methods with this cop should be + # considered unsafe. + class Detect < Cop + include SafeMode + + MSG = 'Use `%s` instead of ' \ + '`%s.%s`.'.freeze + REVERSE_MSG = 'Use `reverse.%s` instead of ' \ + '`%s.%s`.'.freeze + + def_node_matcher :detect_candidate?, <<-PATTERN + { + (send $(block (send _ {:select :find_all}) ...) ${:first :last} $...) + (send $(send _ {:select :find_all} ...) ${:first :last} $...) + } + PATTERN + + def on_send(node) + return if rails_safe_mode? + + detect_candidate?(node) do |receiver, second_method, args| + return unless args.empty? + return unless receiver + + receiver, _args, body = *receiver if receiver.block_type? + return if accept_first_call?(receiver, body) + + register_offense(node, receiver, second_method) + end + end + + def autocorrect(node) + receiver, first_method = *node + + replacement = if first_method == :last + "reverse.#{preferred_method}" + else + preferred_method + end + + first_range = receiver.source_range.end.join(node.loc.selector) + + receiver, _args, _body = *receiver if receiver.block_type? + + lambda do |corrector| + corrector.remove(first_range) + corrector.replace(receiver.loc.selector, replacement) + end + end + + private + + def accept_first_call?(receiver, body) + caller, _first_method, args = *receiver + + # check that we have usual block or block pass + return true if body.nil? && (args.nil? || !args.block_pass_type?) + + lazy?(caller) + end + + def register_offense(node, receiver, second_method) + _caller, first_method, _args = *receiver + range = receiver.loc.selector.join(node.loc.selector) + + message = second_method == :last ? REVERSE_MSG : MSG + formatted_message = format(message, prefer: preferred_method, + first_method: first_method, + second_method: second_method) + + add_offense(node, location: range, message: formatted_message) + end + + def preferred_method + config.for_cop('Style/CollectionMethods') \ + ['PreferredMethods']['detect'] || 'detect' + end + + def lazy?(node) + return false unless node + + receiver, method, _args = *node + method == :lazy && !receiver.nil? + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/double_start_end_with.rb b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/double_start_end_with.rb new file mode 100644 index 0000000000..b53d78b46f --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/double_start_end_with.rb @@ -0,0 +1,94 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Performance + # This cop checks for double `#start_with?` or `#end_with?` calls + # separated by `||`. In some cases such calls can be replaced + # with an single `#start_with?`/`#end_with?` call. + # + # @example + # # bad + # str.start_with?("a") || str.start_with?(Some::CONST) + # str.start_with?("a", "b") || str.start_with?("c") + # str.end_with?(var1) || str.end_with?(var2) + # + # # good + # str.start_with?("a", Some::CONST) + # str.start_with?("a", "b", "c") + # str.end_with?(var1, var2) + class DoubleStartEndWith < Cop + MSG = 'Use `%s.%s(%s)` ' \ + 'instead of `%s`.'.freeze + + def on_or(node) + receiver, + method, + first_call_args, + second_call_args = process_source(node) + + return unless receiver && second_call_args.all?(&:pure?) + + combined_args = combine_args(first_call_args, second_call_args) + + add_offense_for_double_call(node, receiver, method, combined_args) + end + + def autocorrect(node) + _receiver, _method, + first_call_args, second_call_args = process_source(node) + + combined_args = combine_args(first_call_args, second_call_args) + first_argument = first_call_args.first.loc.expression + last_argument = second_call_args.last.loc.expression + range = first_argument.join(last_argument) + + lambda do |corrector| + corrector.replace(range, combined_args) + end + end + + private + + def process_source(node) + if check_for_active_support_aliases? + check_with_active_support_aliases(node) + else + two_start_end_with_calls(node) + end + end + + def combine_args(first_call_args, second_call_args) + (first_call_args + second_call_args).map(&:source).join(', ') + end + + def add_offense_for_double_call(node, receiver, method, combined_args) + msg = format(MSG, receiver: receiver.source, + method: method, + combined_args: combined_args, + original_code: node.source) + + add_offense(node, message: msg) + end + + def check_for_active_support_aliases? + cop_config['IncludeActiveSupportAliases'] + end + + def_node_matcher :two_start_end_with_calls, <<-PATTERN + (or + (send $_recv [{:start_with? :end_with?} $_method] $...) + (send _recv _method $...)) + PATTERN + + def_node_matcher :check_with_active_support_aliases, <<-PATTERN + (or + (send $_recv + [{:start_with? :starts_with? :end_with? :ends_with?} $_method] + $...) + (send _recv _method $...)) + PATTERN + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/end_with.rb b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/end_with.rb new file mode 100644 index 0000000000..2f7c365177 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/end_with.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Performance + # This cop identifies unnecessary use of a regex where `String#end_with?` + # would suffice. + # + # @example + # # bad + # 'abc'.match?(/bc\Z/) + # 'abc' =~ /bc\Z/ + # 'abc'.match(/bc\Z/) + # + # # good + # 'abc'.end_with?('bc') + class EndWith < Cop + MSG = 'Use `String#end_with?` instead of a regex match anchored to ' \ + 'the end of the string.'.freeze + SINGLE_QUOTE = "'".freeze + + def_node_matcher :redundant_regex?, <<-PATTERN + {(send $!nil? {:match :=~ :match?} (regexp (str $#literal_at_end?) (regopt))) + (send (regexp (str $#literal_at_end?) (regopt)) {:match :=~} $_)} + PATTERN + + def literal_at_end?(regex_str) + # is this regexp 'literal' in the sense of only matching literal + # chars, rather than using metachars like . and * and so on? + # also, is it anchored at the end of the string? + regex_str =~ /\A(?:#{LITERAL_REGEX})+\\z\z/ + end + + def on_send(node) + return unless redundant_regex?(node) + + add_offense(node) + end + + def autocorrect(node) + redundant_regex?(node) do |receiver, regex_str| + receiver, regex_str = regex_str, receiver if receiver.is_a?(String) + regex_str = regex_str[0..-3] # drop \Z anchor + regex_str = interpret_string_escapes(regex_str) + + lambda do |corrector| + new_source = receiver.source + '.end_with?(' + + to_string_literal(regex_str) + ')' + corrector.replace(node.source_range, new_source) + end + end + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/fixed_size.rb b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/fixed_size.rb new file mode 100644 index 0000000000..77ea32f5d9 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/fixed_size.rb @@ -0,0 +1,97 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Performance + # Do not compute the size of statically sized objects. + # + # @example + # # String methods + # # bad + # 'foo'.size + # %q[bar].count + # %(qux).length + # + # # Symbol methods + # # bad + # :fred.size + # :'baz'.length + # + # # Array methods + # # bad + # [1, 2, thud].count + # %W(1, 2, bar).size + # + # # Hash methods + # # bad + # { a: corge, b: grault }.length + # + # # good + # foo.size + # bar.count + # qux.length + # + # # good + # :"#{fred}".size + # CONST = :baz.length + # + # # good + # [1, 2, *thud].count + # garply = [1, 2, 3] + # garly.size + # + # # good + # { a: corge, **grault }.length + # waldo = { a: corge, b: grault } + # waldo.size + # + class FixedSize < Cop + MSG = 'Do not compute the size of statically sized objects.'.freeze + + def_node_matcher :counter, <<-MATCHER + (send ${array hash str sym} {:count :length :size} $...) + MATCHER + + def on_send(node) + return if allowed_parent?(node.parent) + + counter(node) do |var, arg| + return if allowed_variable?(var) || allowed_argument?(arg) + + add_offense(node) + end + end + + private + + def allowed_variable?(var) + contains_splat?(var) || contains_double_splat?(var) + end + + def allowed_argument?(arg) + arg && non_string_argument?(arg.first) + end + + def allowed_parent?(node) + node && (node.casgn_type? || node.block_type?) + end + + def contains_splat?(node) + return unless node.array_type? + + node.each_child_node(:splat).any? + end + + def contains_double_splat?(node) + return unless node.hash_type? + + node.each_child_node(:kwsplat).any? + end + + def non_string_argument?(node) + node && !node.str_type? + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/flat_map.rb b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/flat_map.rb new file mode 100644 index 0000000000..71f9b7b562 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/flat_map.rb @@ -0,0 +1,78 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Performance + # This cop is used to identify usages of + # + # @example + # # bad + # [1, 2, 3, 4].map { |e| [e, e] }.flatten(1) + # [1, 2, 3, 4].collect { |e| [e, e] }.flatten(1) + # + # # good + # [1, 2, 3, 4].flat_map { |e| [e, e] } + # [1, 2, 3, 4].map { |e| [e, e] }.flatten + # [1, 2, 3, 4].collect { |e| [e, e] }.flatten + class FlatMap < Cop + include RangeHelp + + MSG = 'Use `flat_map` instead of `%s...%s`.'.freeze + FLATTEN_MULTIPLE_LEVELS = ' Beware, `flat_map` only flattens 1 level ' \ + 'and `flatten` can be used to flatten ' \ + 'multiple levels.'.freeze + + def_node_matcher :flat_map_candidate?, <<-PATTERN + (send (block $(send _ ${:collect :map}) ...) ${:flatten :flatten!} $...) + PATTERN + + def on_send(node) + flat_map_candidate?(node) do |map_node, first_method, flatten, params| + flatten_level, = *params.first + if cop_config['EnabledForFlattenWithoutParams'] && !flatten_level + offense_for_levels(node, map_node, first_method, flatten) + elsif flatten_level == 1 + offense_for_method(node, map_node, first_method, flatten) + end + end + end + + def autocorrect(node) + map_node, _first_method, _flatten, params = flat_map_candidate?(node) + flatten_level, = *params.first + + return unless flatten_level + + range = range_between(node.loc.dot.begin_pos, + node.source_range.end_pos) + + lambda do |corrector| + corrector.remove(range) + corrector.replace(map_node.loc.selector, 'flat_map') + end + end + + private + + def offense_for_levels(node, map_node, first_method, flatten) + message = MSG + FLATTEN_MULTIPLE_LEVELS + register_offense(node, map_node, first_method, flatten, message) + end + + def offense_for_method(node, map_node, first_method, flatten) + register_offense(node, map_node, first_method, flatten, MSG) + end + + def register_offense(node, map_node, first_method, flatten, message) + range = range_between(map_node.loc.selector.begin_pos, + node.loc.expression.end_pos) + + add_offense(node, + location: range, + message: format(message, method: first_method, + flatten: flatten)) + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/inefficient_hash_search.rb b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/inefficient_hash_search.rb new file mode 100644 index 0000000000..0a4a1cc0b2 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/inefficient_hash_search.rb @@ -0,0 +1,99 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Performance + # This cop checks for inefficient searching of keys and values within + # hashes. + # + # `Hash#keys.include?` is less efficient than `Hash#key?` because + # the former allocates a new array and then performs an O(n) search + # through that array, while `Hash#key?` does not allocate any array and + # performs a faster O(1) search for the key. + # + # `Hash#values.include?` is less efficient than `Hash#value?`. While they + # both perform an O(n) search through all of the values, calling `values` + # allocates a new array while using `value?` does not. + # + # @example + # # bad + # { a: 1, b: 2 }.keys.include?(:a) + # { a: 1, b: 2 }.keys.include?(:z) + # h = { a: 1, b: 2 }; h.keys.include?(100) + # + # # good + # { a: 1, b: 2 }.key?(:a) + # { a: 1, b: 2 }.has_key?(:z) + # h = { a: 1, b: 2 }; h.key?(100) + # + # # bad + # { a: 1, b: 2 }.values.include?(2) + # { a: 1, b: 2 }.values.include?('garbage') + # h = { a: 1, b: 2 }; h.values.include?(nil) + # + # # good + # { a: 1, b: 2 }.value?(2) + # { a: 1, b: 2 }.has_value?('garbage') + # h = { a: 1, b: 2 }; h.value?(nil) + # + class InefficientHashSearch < Cop + def_node_matcher :inefficient_include?, <<-PATTERN + (send (send $_ {:keys :values}) :include? _) + PATTERN + + def on_send(node) + inefficient_include?(node) do |receiver| + return if receiver.nil? + + add_offense(node) + end + end + + def autocorrect(node) + lambda do |corrector| + # Replace `keys.include?` or `values.include?` with the appropriate + # `key?`/`value?` method. + corrector.replace( + node.loc.expression, + "#{autocorrect_hash_expression(node)}."\ + "#{autocorrect_method(node)}(#{autocorrect_argument(node)})" + ) + end + end + + private + + def message(node) + "Use `##{autocorrect_method(node)}` instead of "\ + "`##{current_method(node)}.include?`." + end + + def autocorrect_method(node) + case current_method(node) + when :keys then use_long_method ? 'has_key?' : 'key?' + when :values then use_long_method ? 'has_value?' : 'value?' + end + end + + def current_method(node) + node.receiver.method_name + end + + def use_long_method + preferred_config = config.for_all_cops['Style/PreferredHashMethods'] + preferred_config && + preferred_config['EnforcedStyle'] == 'long' && + preferred_config['Enabled'] + end + + def autocorrect_argument(node) + node.arguments.first.source + end + + def autocorrect_hash_expression(node) + node.receiver.receiver.source + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/open_struct.rb b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/open_struct.rb new file mode 100644 index 0000000000..a263ab540b --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/open_struct.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Performance + # This cop checks for `OpenStruct.new` calls. + # Instantiation of an `OpenStruct` invalidates + # Ruby global method cache as it causes dynamic method + # definition during program runtime. + # This could have an effect on performance, + # especially in case of single-threaded + # applications with multiple `OpenStruct` instantiations. + # + # @example + # # bad + # class MyClass + # def my_method + # OpenStruct.new(my_key1: 'my_value1', my_key2: 'my_value2') + # end + # end + # + # # good + # class MyClass + # MyStruct = Struct.new(:my_key1, :my_key2) + # def my_method + # MyStruct.new('my_value1', 'my_value2') + # end + # end + # + class OpenStruct < Cop + MSG = 'Consider using `Struct` over `OpenStruct` ' \ + 'to optimize the performance.'.freeze + + def_node_matcher :open_struct, <<-PATTERN + (send (const {nil? cbase} :OpenStruct) :new ...) + PATTERN + + def on_send(node) + open_struct(node) do |method| + add_offense(node, location: :selector, message: format(MSG, method)) + end + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/range_include.rb b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/range_include.rb new file mode 100644 index 0000000000..be31278050 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/range_include.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Performance + # This cop identifies uses of `Range#include?`, which iterates over each + # item in a `Range` to see if a specified item is there. In contrast, + # `Range#cover?` simply compares the target item with the beginning and + # end points of the `Range`. In a great majority of cases, this is what + # is wanted. + # + # This cop is `Safe: false` by default because `Range#include?` and + # `Range#cover?` are not equivalent behaviour. + # + # @example + # # bad + # ('a'..'z').include?('b') # => true + # + # # good + # ('a'..'z').cover?('b') # => true + # + # # Example of a case where `Range#cover?` may not provide + # # the desired result: + # + # ('a'..'z').cover?('yellow') # => true + class RangeInclude < Cop + MSG = 'Use `Range#cover?` instead of `Range#include?`.'.freeze + + # TODO: If we traced out assignments of variables to their uses, we + # might pick up on a few more instances of this issue + # Right now, we only detect direct calls on a Range literal + # (We don't even catch it if the Range is in double parens) + + def_node_matcher :range_include, <<-PATTERN + (send {irange erange (begin {irange erange})} :include? ...) + PATTERN + + def on_send(node) + return unless range_include(node) + + add_offense(node, location: :selector) + end + + def autocorrect(node) + ->(corrector) { corrector.replace(node.loc.selector, 'cover?') } + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/redundant_block_call.rb b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/redundant_block_call.rb new file mode 100644 index 0000000000..0adaa4a8a8 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/redundant_block_call.rb @@ -0,0 +1,93 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Performance + # This cop identifies the use of a `&block` parameter and `block.call` + # where `yield` would do just as well. + # + # @example + # # bad + # def method(&block) + # block.call + # end + # def another(&func) + # func.call 1, 2, 3 + # end + # + # # good + # def method + # yield + # end + # def another + # yield 1, 2, 3 + # end + class RedundantBlockCall < Cop + MSG = 'Use `yield` instead of `%s.call`.'.freeze + YIELD = 'yield'.freeze + OPEN_PAREN = '('.freeze + CLOSE_PAREN = ')'.freeze + SPACE = ' '.freeze + + def_node_matcher :blockarg_def, <<-PATTERN + {(def _ (args ... (blockarg $_)) $_) + (defs _ _ (args ... (blockarg $_)) $_)} + PATTERN + + def_node_search :blockarg_calls, <<-PATTERN + (send (lvar %1) :call ...) + PATTERN + + def_node_search :blockarg_assigned?, <<-PATTERN + (lvasgn %1 ...) + PATTERN + + def on_def(node) + blockarg_def(node) do |argname, body| + next unless body + + calls_to_report(argname, body).each do |blockcall| + add_offense(blockcall, message: format(MSG, argname: argname)) + end + end + end + + # offenses are registered on the `block.call` nodes + def autocorrect(node) + _receiver, _method, *args = *node + new_source = String.new(YIELD) + unless args.empty? + new_source += if parentheses?(node) + OPEN_PAREN + else + SPACE + end + + new_source << args.map(&:source).join(', ') + end + + new_source << CLOSE_PAREN if parentheses?(node) && !args.empty? + ->(corrector) { corrector.replace(node.source_range, new_source) } + end + + private + + def calls_to_report(argname, body) + return [] if blockarg_assigned?(body, argname) + + calls = to_enum(:blockarg_calls, body, argname) + + return [] if calls.any? { |call| args_include_block_pass?(call) } + + calls + end + + def args_include_block_pass?(blockcall) + _receiver, _call, *args = *blockcall + + args.any?(&:block_pass_type?) + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/redundant_match.rb b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/redundant_match.rb new file mode 100644 index 0000000000..166fb3f71f --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/redundant_match.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Performance + # This cop identifies the use of `Regexp#match` or `String#match`, which + # returns `#`/`nil`. The return value of `=~` is an integral + # index/`nil` and is more performant. + # + # @example + # # bad + # do_something if str.match(/regex/) + # while regex.match('str') + # do_something + # end + # + # # good + # method(str =~ /regex/) + # return value unless regex =~ 'str' + class RedundantMatch < Cop + MSG = 'Use `=~` in places where the `MatchData` returned by ' \ + '`#match` will not be used.'.freeze + + # 'match' is a fairly generic name, so we don't flag it unless we see + # a string or regexp literal on one side or the other + def_node_matcher :match_call?, <<-PATTERN + {(send {str regexp} :match _) + (send !nil? :match {str regexp})} + PATTERN + + def_node_matcher :only_truthiness_matters?, <<-PATTERN + ^({if while until case while_post until_post} equal?(%0) ...) + PATTERN + + def on_send(node) + return unless match_call?(node) && + (!node.value_used? || only_truthiness_matters?(node)) && + !(node.parent && node.parent.block_type?) + + add_offense(node) + end + + def autocorrect(node) + # Regexp#match can take a second argument, but this cop doesn't + # register an offense in that case + return unless node.first_argument.regexp_type? + + new_source = + node.receiver.source + ' =~ ' + node.first_argument.source + + ->(corrector) { corrector.replace(node.source_range, new_source) } + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/redundant_merge.rb b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/redundant_merge.rb new file mode 100644 index 0000000000..0d655ed6e9 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/redundant_merge.rb @@ -0,0 +1,183 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Performance + # This cop identifies places where `Hash#merge!` can be replaced by + # `Hash#[]=`. + # + # @example + # hash.merge!(a: 1) + # hash.merge!({'key' => 'value'}) + # hash.merge!(a: 1, b: 2) + class RedundantMerge < Cop + AREF_ASGN = '%s[%s] = %s'.freeze + MSG = 'Use `%s` instead of `%s`.'.freeze + + WITH_MODIFIER_CORRECTION = <<-RUBY.strip_indent + %s %s + %s%s%s + %send + RUBY + + def_node_matcher :redundant_merge_candidate, <<-PATTERN + (send $!nil? :merge! [(hash $...) !kwsplat_type?]) + PATTERN + + def_node_matcher :modifier_flow_control?, <<-PATTERN + [{if while until} modifier_form?] + PATTERN + + def on_send(node) + each_redundant_merge(node) do |redundant_merge_node| + add_offense(redundant_merge_node) + end + end + + def autocorrect(node) + redundant_merge_candidate(node) do |receiver, pairs| + new_source = to_assignments(receiver, pairs).join("\n") + + if node.parent && pairs.size > 1 + correct_multiple_elements(node, node.parent, new_source) + else + correct_single_element(node, new_source) + end + end + end + + private + + def message(node) + redundant_merge_candidate(node) do |receiver, pairs| + assignments = to_assignments(receiver, pairs).join('; ') + + format(MSG, prefer: assignments, current: node.source) + end + end + + def each_redundant_merge(node) + redundant_merge_candidate(node) do |receiver, pairs| + next if non_redundant_merge?(node, receiver, pairs) + + yield node + end + end + + def non_redundant_merge?(node, receiver, pairs) + non_redundant_pairs?(receiver, pairs) || + kwsplat_used?(pairs) || + non_redundant_value_used?(receiver, node) + end + + def non_redundant_pairs?(receiver, pairs) + pairs.size > 1 && !receiver.pure? || pairs.size > max_key_value_pairs + end + + def kwsplat_used?(pairs) + pairs.any?(&:kwsplat_type?) + end + + def non_redundant_value_used?(receiver, node) + node.value_used? && + !EachWithObjectInspector.new(node, receiver).value_used? + end + + def correct_multiple_elements(node, parent, new_source) + if modifier_flow_control?(parent) + new_source = rewrite_with_modifier(node, parent, new_source) + node = parent + else + padding = "\n#{leading_spaces(node)}" + new_source.gsub!(/\n/, padding) + end + + ->(corrector) { corrector.replace(node.source_range, new_source) } + end + + def correct_single_element(node, new_source) + ->(corrector) { corrector.replace(node.source_range, new_source) } + end + + def to_assignments(receiver, pairs) + pairs.map do |pair| + key, value = *pair + + key = key.sym_type? && pair.colon? ? ":#{key.source}" : key.source + + format(AREF_ASGN, receiver: receiver.source, + key: key, + value: value.source) + end + end + + def rewrite_with_modifier(node, parent, new_source) + indent = ' ' * indent_width + padding = "\n#{indent + leading_spaces(node)}" + new_source.gsub!(/\n/, padding) + + format(WITH_MODIFIER_CORRECTION, keyword: parent.loc.keyword.source, + condition: parent.condition.source, + leading_space: leading_spaces(node), + indent: indent, + body: new_source).chomp + end + + def leading_spaces(node) + node.source_range.source_line[/\A\s*/] + end + + def indent_width + @config.for_cop('IndentationWidth')['Width'] || 2 + end + + def max_key_value_pairs + Integer(cop_config['MaxKeyValuePairs']) + end + + # A utility class for checking the use of values within an + # `each_with_object` call. + class EachWithObjectInspector + extend NodePattern::Macros + + def initialize(node, receiver) + @node = node + @receiver = unwind(receiver) + end + + def value_used? + return false unless eligible_receiver? && second_argument + + receiver.loc.name.source == second_argument.loc.name.source + end + + private + + attr_reader :node, :receiver + + def eligible_receiver? + receiver.respond_to?(:lvar_type?) && receiver.lvar_type? + end + + def second_argument + parent = node.parent + parent = parent.parent if parent.begin_type? + + @second_argument ||= each_with_object_node(parent) + end + + def unwind(receiver) + while receiver.respond_to?(:send_type?) && receiver.send_type? + receiver, = *receiver + end + receiver + end + + def_node_matcher :each_with_object_node, <<-PATTERN + (block (send _ :each_with_object _) (args _ $_) ...) + PATTERN + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/regexp_match.rb b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/regexp_match.rb new file mode 100644 index 0000000000..c98d9a715a --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/regexp_match.rb @@ -0,0 +1,265 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Performance + # In Ruby 2.4, `String#match?`, `Regexp#match?`, and `Symbol#match?` + # have been added. The methods are faster than `match`. + # Because the methods avoid creating a `MatchData` object or saving + # backref. + # So, when `MatchData` is not used, use `match?` instead of `match`. + # + # @example + # # bad + # def foo + # if x =~ /re/ + # do_something + # end + # end + # + # # bad + # def foo + # if x !~ /re/ + # do_something + # end + # end + # + # # bad + # def foo + # if x.match(/re/) + # do_something + # end + # end + # + # # bad + # def foo + # if /re/ === x + # do_something + # end + # end + # + # # good + # def foo + # if x.match?(/re/) + # do_something + # end + # end + # + # # good + # def foo + # if !x.match?(/re/) + # do_something + # end + # end + # + # # good + # def foo + # if x =~ /re/ + # do_something(Regexp.last_match) + # end + # end + # + # # good + # def foo + # if x.match(/re/) + # do_something($~) + # end + # end + # + # # good + # def foo + # if /re/ === x + # do_something($~) + # end + # end + class RegexpMatch < Cop + extend TargetRubyVersion + + minimum_target_ruby_version 2.4 + + # Constants are included in this list because it is unlikely that + # someone will store `nil` as a constant and then use it for comparison + TYPES_IMPLEMENTING_MATCH = %i[const regexp str sym].freeze + MSG = + 'Use `match?` instead of `%s` when `MatchData` ' \ + 'is not used.'.freeze + + def_node_matcher :match_method?, <<-PATTERN + { + (send _recv :match _) + (send _recv :match _ (int ...)) + } + PATTERN + + def_node_matcher :match_operator?, <<-PATTERN + (send !nil? {:=~ :!~} !nil?) + PATTERN + + def_node_matcher :match_threequals?, <<-PATTERN + (send (regexp (str _) {(regopt) (regopt _)}) :=== !nil?) + PATTERN + + def match_with_lvasgn?(node) + return false unless node.match_with_lvasgn_type? + + regexp, _rhs = *node + regexp.to_regexp.named_captures.empty? + end + + MATCH_NODE_PATTERN = <<-PATTERN.freeze + { + #match_method? + #match_operator? + #match_threequals? + #match_with_lvasgn? + } + PATTERN + + def_node_matcher :match_node?, MATCH_NODE_PATTERN + def_node_search :search_match_nodes, MATCH_NODE_PATTERN + + def_node_search :last_matches, <<-PATTERN + { + (send (const nil? :Regexp) :last_match) + (send (const nil? :Regexp) :last_match _) + ({back_ref nth_ref} _) + (gvar #match_gvar?) + } + PATTERN + + def on_if(node) + check_condition(node.condition) + end + + def on_case(node) + return if node.condition + + node.each_when do |when_node| + when_node.each_condition do |condition| + check_condition(condition) + end + end + end + + def autocorrect(node) + lambda do |corrector| + if match_method?(node) + corrector.replace(node.loc.selector, 'match?') + elsif match_operator?(node) || match_threequals?(node) + recv, oper, arg = *node + correct_operator(corrector, recv, arg, oper) + elsif match_with_lvasgn?(node) + recv, arg = *node + correct_operator(corrector, recv, arg) + end + end + end + + private + + def check_condition(cond) + match_node?(cond) do + return if last_match_used?(cond) + + add_offense(cond) + end + end + + def message(node) + format(MSG, current: node.loc.selector.source) + end + + def last_match_used?(match_node) + scope_root = scope_root(match_node) + body = scope_root ? scope_body(scope_root) : match_node.ancestors.last + + return true if match_node.parent.if_type? && + match_node.parent.modifier_form? + + match_node_pos = match_node.loc.expression.begin_pos + + next_match_pos = next_match_pos(body, match_node_pos, scope_root) + range = match_node_pos..next_match_pos + + find_last_match(body, range, scope_root) + end + + def next_match_pos(body, match_node_pos, scope_root) + node = search_match_nodes(body).find do |match| + match.loc.expression.begin_pos > match_node_pos && + scope_root(match) == scope_root + end + node ? node.loc.expression.begin_pos : Float::INFINITY + end + + def find_last_match(body, range, scope_root) + last_matches(body).find do |ref| + ref_pos = ref.loc.expression.begin_pos + range.cover?(ref_pos) && + scope_root(ref) == scope_root + end + end + + def scope_body(node) + children = node.children + case node.type + when :module + children[1] + when :defs + children[3] + else + children[2] + end + end + + def scope_root(node) + node.each_ancestor.find do |ancestor| + ancestor.def_type? || + ancestor.defs_type? || + ancestor.class_type? || + ancestor.module_type? + end + end + + def match_gvar?(sym) + %i[ + $~ + $MATCH + $PREMATCH + $POSTMATCH + $LAST_PAREN_MATCH + $LAST_MATCH_INFO + ].include?(sym) + end + + def correct_operator(corrector, recv, arg, oper = nil) + op_range = correction_range(recv, arg) + + if TYPES_IMPLEMENTING_MATCH.include?(recv.type) + corrector.replace(op_range, '.match?(') + elsif TYPES_IMPLEMENTING_MATCH.include?(arg.type) + corrector.replace(op_range, '.match?(') + swap_receiver_and_arg(corrector, recv, arg) + else + corrector.replace(op_range, '&.match?(') + end + + corrector.insert_after(arg.loc.expression, ')') + corrector.insert_before(recv.loc.expression, '!') if oper == :!~ + end + + def swap_receiver_and_arg(corrector, recv, arg) + corrector.replace(recv.loc.expression, arg.source) + corrector.replace(arg.loc.expression, recv.source) + end + + def correction_range(recv, arg) + buffer = processed_source.buffer + op_begin_pos = recv.loc.expression.end_pos + op_end_pos = arg.loc.expression.begin_pos + Parser::Source::Range.new(buffer, op_begin_pos, op_end_pos) + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/reverse_each.rb b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/reverse_each.rb new file mode 100644 index 0000000000..dbd4d9316c --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/reverse_each.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Performance + # This cop is used to identify usages of `reverse.each` and + # change them to use `reverse_each` instead. + # + # @example + # # bad + # [].reverse.each + # + # # good + # [].reverse_each + class ReverseEach < Cop + include RangeHelp + + MSG = 'Use `reverse_each` instead of `reverse.each`.'.freeze + UNDERSCORE = '_'.freeze + + def_node_matcher :reverse_each?, <<-MATCHER + (send $(send _ :reverse) :each) + MATCHER + + def on_send(node) + reverse_each?(node) do |receiver| + location_of_reverse = receiver.loc.selector.begin_pos + end_location = node.loc.selector.end_pos + + range = range_between(location_of_reverse, end_location) + + add_offense(node, location: range) + end + end + + def autocorrect(node) + ->(corrector) { corrector.replace(node.loc.dot, UNDERSCORE) } + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/size.rb b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/size.rb new file mode 100644 index 0000000000..64728c367c --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/size.rb @@ -0,0 +1,77 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Performance + # This cop is used to identify usages of `count` on an + # `Array` and `Hash` and change them to `size`. + # + # @example + # # bad + # [1, 2, 3].count + # + # # bad + # {a: 1, b: 2, c: 3}.count + # + # # good + # [1, 2, 3].size + # + # # good + # {a: 1, b: 2, c: 3}.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 < Cop + MSG = 'Use `size` instead of `count`.'.freeze + + def on_send(node) + return unless eligible_node?(node) + + add_offense(node, location: :selector) + end + + def autocorrect(node) + ->(corrector) { corrector.replace(node.loc.selector, 'size') } + end + + private + + def eligible_node?(node) + return false unless node.method?(:count) && !node.arguments? + + eligible_receiver?(node.receiver) && !allowed_parent?(node.parent) + end + + def eligible_receiver?(node) + return false unless node + + array?(node) || hash?(node) + end + + def allowed_parent?(node) + node && node.block_type? + end + + def array?(node) + return true if node.array_type? + return false unless node.send_type? + + _, constant = *node.receiver + + constant == :Array || node.method_name == :to_a + end + + def hash?(node) + return true if node.hash_type? + return false unless node.send_type? + + _, constant = *node.receiver + + constant == :Hash || node.method_name == :to_h + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/start_with.rb b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/start_with.rb new file mode 100644 index 0000000000..062957c5e0 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/start_with.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Performance + # This cop identifies unnecessary use of a regex where + # `String#start_with?` would suffice. + # + # @example + # # bad + # 'abc'.match?(/\Aab/) + # 'abc' =~ /\Aab/ + # 'abc'.match(/\Aab/) + # + # # good + # 'abc'.start_with?('ab') + class StartWith < Cop + MSG = 'Use `String#start_with?` instead of a regex match anchored to ' \ + 'the beginning of the string.'.freeze + SINGLE_QUOTE = "'".freeze + + def_node_matcher :redundant_regex?, <<-PATTERN + {(send $!nil? {:match :=~ :match?} (regexp (str $#literal_at_start?) (regopt))) + (send (regexp (str $#literal_at_start?) (regopt)) {:match :=~} $_)} + PATTERN + + def literal_at_start?(regex_str) + # is this regexp 'literal' in the sense of only matching literal + # chars, rather than using metachars like `.` and `*` and so on? + # also, is it anchored at the start of the string? + # (tricky: \s, \d, and so on are metacharacters, but other characters + # escaped with a slash are just literals. LITERAL_REGEX takes all + # that into account.) + regex_str =~ /\A\\A(?:#{LITERAL_REGEX})+\z/ + end + + def on_send(node) + return unless redundant_regex?(node) + + add_offense(node) + end + + def autocorrect(node) + redundant_regex?(node) do |receiver, regex_str| + receiver, regex_str = regex_str, receiver if receiver.is_a?(String) + regex_str = regex_str[2..-1] # drop \A anchor + regex_str = interpret_string_escapes(regex_str) + + lambda do |corrector| + new_source = receiver.source + '.start_with?(' + + to_string_literal(regex_str) + ')' + corrector.replace(node.source_range, new_source) + end + end + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/string_replacement.rb b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/string_replacement.rb new file mode 100644 index 0000000000..410ae07d99 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/string_replacement.rb @@ -0,0 +1,173 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Performance + # This cop identifies places where `gsub` can be replaced by + # `tr` or `delete`. + # + # @example + # # bad + # 'abc'.gsub('b', 'd') + # 'abc'.gsub('a', '') + # 'abc'.gsub(/a/, 'd') + # 'abc'.gsub!('a', 'd') + # + # # good + # 'abc'.gsub(/.*/, 'a') + # 'abc'.gsub(/a+/, 'd') + # 'abc'.tr('b', 'd') + # 'a b c'.delete(' ') + class StringReplacement < Cop + include RangeHelp + + MSG = 'Use `%s` instead of `%s`.'.freeze + DETERMINISTIC_REGEX = /\A(?:#{LITERAL_REGEX})+\Z/.freeze + DELETE = 'delete'.freeze + TR = 'tr'.freeze + BANG = '!'.freeze + SINGLE_QUOTE = "'".freeze + + def_node_matcher :string_replacement?, <<-PATTERN + (send _ {:gsub :gsub!} + ${regexp str (send (const nil? :Regexp) {:new :compile} _)} + $str) + PATTERN + + def on_send(node) + string_replacement?(node) do |first_param, second_param| + return if accept_second_param?(second_param) + return if accept_first_param?(first_param) + + offense(node, first_param, second_param) + end + end + + def autocorrect(node) + _string, _method, first_param, second_param = *node + first_source, = first_source(first_param) + second_source, = *second_param + + unless first_param.str_type? + first_source = interpret_string_escapes(first_source) + end + + replacement_method = + replacement_method(node, first_source, second_source) + + replace_method(node, first_source, second_source, first_param, + replacement_method) + end + + def replace_method(node, first, second, first_param, replacement) + lambda do |corrector| + corrector.replace(node.loc.selector, replacement) + unless first_param.str_type? + corrector.replace(first_param.source_range, + to_string_literal(first)) + end + + if second.empty? && first.length == 1 + remove_second_param(corrector, node, first_param) + end + end + end + + private + + def accept_second_param?(second_param) + second_source, = *second_param + second_source.length > 1 + end + + def accept_first_param?(first_param) + first_source, options = first_source(first_param) + return true if first_source.nil? + + unless first_param.str_type? + return true if options + return true unless first_source =~ DETERMINISTIC_REGEX + + # This must be done after checking DETERMINISTIC_REGEX + # Otherwise things like \s will trip us up + first_source = interpret_string_escapes(first_source) + end + + first_source.length != 1 + end + + def offense(node, first_param, second_param) + first_source, = first_source(first_param) + unless first_param.str_type? + first_source = interpret_string_escapes(first_source) + end + second_source, = *second_param + message = message(node, first_source, second_source) + + add_offense(node, location: range(node), message: message) + end + + def first_source(first_param) + case first_param.type + when :regexp + source_from_regex_literal(first_param) + when :send + source_from_regex_constructor(first_param) + when :str + first_param.children.first + end + end + + def source_from_regex_literal(node) + regex, options = *node + source, = *regex + options, = *options + [source, options] + end + + def source_from_regex_constructor(node) + _const, _init, regex = *node + case regex.type + when :regexp + source_from_regex_literal(regex) + when :str + source, = *regex + source + end + end + + def range(node) + range_between(node.loc.selector.begin_pos, node.source_range.end_pos) + end + + def replacement_method(node, first_source, second_source) + replacement = if second_source.empty? && first_source.length == 1 + DELETE + else + TR + end + + "#{replacement}#{BANG if node.bang_method?}" + end + + def message(node, first_source, second_source) + replacement_method = + replacement_method(node, first_source, second_source) + + format(MSG, prefer: replacement_method, current: node.method_name) + end + + def method_suffix(node) + node.loc.end ? node.loc.end.source : '' + end + + def remove_second_param(corrector, node, first_param) + end_range = range_between(first_param.source_range.end_pos, + node.source_range.end_pos) + + corrector.replace(end_range, method_suffix(node)) + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/times_map.rb b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/times_map.rb new file mode 100644 index 0000000000..1f2c801ff9 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/times_map.rb @@ -0,0 +1,71 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Performance + # This cop checks for .times.map calls. + # In most cases such calls can be replaced + # with an explicit array creation. + # + # @example + # # bad + # 9.times.map do |i| + # i.to_s + # end + # + # # good + # Array.new(9) do |i| + # i.to_s + # end + class TimesMap < Cop + MESSAGE = 'Use `Array.new(%s)` with a block ' \ + 'instead of `.times.%s`'.freeze + MESSAGE_ONLY_IF = 'only if `%s` is always 0 or more'.freeze + + def on_send(node) + check(node) + end + + def on_block(node) + check(node) + end + + def autocorrect(node) + map_or_collect, count = times_map_call(node) + + replacement = + "Array.new(#{count.source}" \ + "#{map_or_collect.arguments.map { |arg| ", #{arg.source}" }.join})" + + lambda do |corrector| + corrector.replace(map_or_collect.loc.expression, replacement) + end + end + + private + + def check(node) + times_map_call(node) do |map_or_collect, count| + add_offense(node, message: message(map_or_collect, count)) + end + end + + def message(map_or_collect, count) + template = if count.literal? + MESSAGE + '.' + else + "#{MESSAGE} #{MESSAGE_ONLY_IF}." + end + format(template, + count: count.source, + map_or_collect: map_or_collect.method_name) + end + + def_node_matcher :times_map_call, <<-PATTERN + {(block $(send (send $!nil? :times) {:map :collect}) ...) + $(send (send $!nil? :times) {:map :collect} (block_pass ...))} + PATTERN + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/unfreeze_string.rb b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/unfreeze_string.rb new file mode 100644 index 0000000000..057e17bfb3 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/unfreeze_string.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Performance + # In Ruby 2.3 or later, use unary plus operator to unfreeze a string + # literal instead of `String#dup` and `String.new`. + # Unary plus operator is faster than `String#dup`. + # + # Note: `String.new` (without operator) is not exactly the same as `+''`. + # These differ in encoding. `String.new.encoding` is always `ASCII-8BIT`. + # However, `(+'').encoding` is the same as script encoding(e.g. `UTF-8`). + # So, if you expect `ASCII-8BIT` encoding, disable this cop. + # + # @example + # # bad + # ''.dup + # "something".dup + # String.new + # String.new('') + # String.new('something') + # + # # good + # +'something' + # +'' + class UnfreezeString < Cop + extend TargetRubyVersion + + minimum_target_ruby_version 2.3 + + MSG = 'Use unary plus to get an unfrozen string literal.'.freeze + + def_node_matcher :dup_string?, <<-PATTERN + (send {str dstr} :dup) + PATTERN + + def_node_matcher :string_new?, <<-PATTERN + { + (send (const nil? :String) :new {str dstr}) + (send (const nil? :String) :new) + } + PATTERN + + def on_send(node) + add_offense(node) if dup_string?(node) || string_new?(node) + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/uri_default_parser.rb b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/uri_default_parser.rb new file mode 100644 index 0000000000..173c178b4c --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance/uri_default_parser.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Performance + # This cop identifies places where `URI::Parser.new` + # can be replaced by `URI::DEFAULT_PARSER`. + # + # @example + # # bad + # URI::Parser.new + # + # # good + # URI::DEFAULT_PARSER + # + class UriDefaultParser < Cop + MSG = 'Use `%sURI::DEFAULT_PARSER` instead of ' \ + '`%sURI::Parser.new`.'.freeze + + def_node_matcher :uri_parser_new?, <<-PATTERN + (send + (const + (const ${nil? cbase} :URI) :Parser) :new) + PATTERN + + def on_send(node) + return unless uri_parser_new?(node) do |captured_value| + double_colon = captured_value ? '::' : '' + message = format(MSG, double_colon: double_colon) + + add_offense(node, message: message) + end + end + + def autocorrect(node) + lambda do |corrector| + double_colon = uri_parser_new?(node) ? '::' : '' + + corrector.replace( + node.loc.expression, "#{double_colon}URI::DEFAULT_PARSER" + ) + end + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance_cops.rb b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance_cops.rb new file mode 100644 index 0000000000..e966c56834 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/cop/performance_cops.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +module RuboCop + # RuboCop included the performance cops directly before version 1.0.0. + # We can remove them to avoid warnings about redefining constants. + module Cop + remove_const('Performance') if const_defined?('Performance') + end +end + +require_relative 'performance/caller' +require_relative 'performance/case_when_splat' +require_relative 'performance/casecmp' +require_relative 'performance/compare_with_block' +require_relative 'performance/count' +require_relative 'performance/detect' +require_relative 'performance/double_start_end_with' +require_relative 'performance/end_with' +require_relative 'performance/fixed_size' +require_relative 'performance/flat_map' +require_relative 'performance/inefficient_hash_search' +require_relative 'performance/open_struct' +require_relative 'performance/range_include' +require_relative 'performance/redundant_block_call' +require_relative 'performance/redundant_match' +require_relative 'performance/redundant_merge' +require_relative 'performance/regexp_match' +require_relative 'performance/reverse_each' +require_relative 'performance/size' +require_relative 'performance/start_with' +require_relative 'performance/string_replacement' +require_relative 'performance/times_map' +require_relative 'performance/unfreeze_string' +require_relative 'performance/uri_default_parser' +require_relative 'performance/chain_array_allocation' diff --git a/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/performance.rb b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/performance.rb new file mode 100644 index 0000000000..2035903521 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/performance.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +module RuboCop + # RuboCop Performance project namespace + module Performance + PROJECT_ROOT = Pathname.new(__dir__).parent.parent.expand_path.freeze + CONFIG_DEFAULT = PROJECT_ROOT.join('config', 'default.yml').freeze + CONFIG = YAML.safe_load(CONFIG_DEFAULT.read).freeze + + private_constant(:CONFIG_DEFAULT, :PROJECT_ROOT) + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/performance/inject.rb b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/performance/inject.rb new file mode 100644 index 0000000000..f82404dad3 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/performance/inject.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +module RuboCop + module Performance + # Because RuboCop doesn't yet support plugins, we have to monkey patch in a + # bit of our configuration. + module Inject + def self.defaults! + path = CONFIG_DEFAULT.to_s + hash = ConfigLoader.send(:load_yaml_configuration, path) + config = Config.new(hash, path) + puts "configuration from #{path}" if ConfigLoader.debug? + config = ConfigLoader.merge_with_default(config, path) + ConfigLoader.instance_variable_set(:@default_configuration, config) + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/performance/version.rb b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/performance/version.rb new file mode 100644 index 0000000000..07759861c2 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.3.0/gems/rubocop-performance-1.1.0/lib/rubocop/performance/version.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module RuboCop + module Performance + module Version + STRING = '1.1.0'.freeze + end + end +end