rubocop 0.42.0 → 0.43.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rubocop might be problematic. Click here for more details.

Files changed (221) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/assets/output.html.erb +21 -10
  4. data/config/default.yml +32 -2
  5. data/config/disabled.yml +8 -1
  6. data/config/enabled.yml +40 -12
  7. data/lib/rubocop.rb +14 -2
  8. data/lib/rubocop/ast_node.rb +2 -0
  9. data/lib/rubocop/cached_data.rb +13 -11
  10. data/lib/rubocop/cli.rb +5 -5
  11. data/lib/rubocop/config.rb +68 -24
  12. data/lib/rubocop/config_loader.rb +13 -11
  13. data/lib/rubocop/config_loader_resolver.rb +4 -2
  14. data/lib/rubocop/cop/cop.rb +16 -5
  15. data/lib/rubocop/cop/lint/assignment_in_condition.rb +21 -20
  16. data/lib/rubocop/cop/lint/block_alignment.rb +3 -4
  17. data/lib/rubocop/cop/lint/def_end_alignment.rb +2 -3
  18. data/lib/rubocop/cop/lint/duplicate_methods.rb +16 -6
  19. data/lib/rubocop/cop/lint/else_layout.rb +1 -1
  20. data/lib/rubocop/cop/lint/empty_interpolation.rb +1 -1
  21. data/lib/rubocop/cop/lint/end_alignment.rb +4 -6
  22. data/lib/rubocop/cop/lint/eval.rb +1 -1
  23. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +1 -1
  24. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +8 -8
  25. data/lib/rubocop/cop/lint/inherit_exception.rb +22 -7
  26. data/lib/rubocop/cop/lint/literal_in_condition.rb +5 -5
  27. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +3 -5
  28. data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
  29. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +9 -8
  30. data/lib/rubocop/cop/lint/percent_string_array.rb +17 -6
  31. data/lib/rubocop/cop/lint/percent_symbol_array.rb +4 -4
  32. data/lib/rubocop/cop/lint/rand_one.rb +3 -3
  33. data/lib/rubocop/cop/lint/require_parentheses.rb +1 -3
  34. data/lib/rubocop/cop/lint/shadowed_exception.rb +39 -44
  35. data/lib/rubocop/cop/lint/string_conversion_in_interpolation.rb +2 -2
  36. data/lib/rubocop/cop/lint/underscore_prefixed_variable_name.rb +1 -2
  37. data/lib/rubocop/cop/lint/unified_integer.rb +38 -0
  38. data/lib/rubocop/cop/lint/unneeded_disable.rb +51 -38
  39. data/lib/rubocop/cop/lint/unneeded_splat_expansion.rb +114 -0
  40. data/lib/rubocop/cop/lint/useless_assignment.rb +25 -12
  41. data/lib/rubocop/cop/lint/useless_setter_call.rb +27 -28
  42. data/lib/rubocop/cop/lint/void.rb +2 -4
  43. data/lib/rubocop/cop/mixin/access_modifier_node.rb +5 -5
  44. data/lib/rubocop/cop/mixin/array_hash_indentation.rb +19 -17
  45. data/lib/rubocop/cop/mixin/autocorrect_alignment.rb +3 -5
  46. data/lib/rubocop/cop/mixin/configurable_naming.rb +4 -5
  47. data/lib/rubocop/cop/mixin/configurable_numbering.rb +52 -0
  48. data/lib/rubocop/cop/mixin/def_node.rb +28 -0
  49. data/lib/rubocop/cop/mixin/documentation_comment.rb +41 -0
  50. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +18 -13
  51. data/lib/rubocop/cop/mixin/if_node.rb +6 -0
  52. data/lib/rubocop/cop/mixin/match_range.rb +2 -5
  53. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +2 -2
  54. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +40 -28
  55. data/lib/rubocop/cop/mixin/negative_conditional.rb +6 -6
  56. data/lib/rubocop/cop/mixin/percent_literal.rb +1 -5
  57. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +14 -4
  58. data/lib/rubocop/cop/mixin/safe_mode.rb +23 -0
  59. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +2 -4
  60. data/lib/rubocop/cop/mixin/space_inside.rb +1 -3
  61. data/lib/rubocop/cop/mixin/statement_modifier.rb +30 -20
  62. data/lib/rubocop/cop/mixin/trailing_comma.rb +19 -17
  63. data/lib/rubocop/cop/performance/case_when_splat.rb +16 -41
  64. data/lib/rubocop/cop/performance/casecmp.rb +28 -16
  65. data/lib/rubocop/cop/performance/count.rb +58 -34
  66. data/lib/rubocop/cop/performance/detect.rb +3 -7
  67. data/lib/rubocop/cop/performance/double_start_end_with.rb +17 -13
  68. data/lib/rubocop/cop/performance/fixed_size.rb +19 -14
  69. data/lib/rubocop/cop/performance/flat_map.rb +16 -9
  70. data/lib/rubocop/cop/performance/hash_each.rb +2 -3
  71. data/lib/rubocop/cop/performance/lstrip_rstrip.rb +4 -6
  72. data/lib/rubocop/cop/performance/redundant_match.rb +4 -1
  73. data/lib/rubocop/cop/performance/redundant_merge.rb +63 -32
  74. data/lib/rubocop/cop/performance/redundant_sort_by.rb +8 -7
  75. data/lib/rubocop/cop/performance/reverse_each.rb +1 -4
  76. data/lib/rubocop/cop/performance/size.rb +21 -8
  77. data/lib/rubocop/cop/performance/sort_with_block.rb +54 -0
  78. data/lib/rubocop/cop/performance/string_replacement.rb +3 -7
  79. data/lib/rubocop/cop/rails/delegate.rb +2 -3
  80. data/lib/rubocop/cop/rails/find_by.rb +4 -8
  81. data/lib/rubocop/cop/rails/not_null_column.rb +45 -0
  82. data/lib/rubocop/cop/rails/request_referer.rb +3 -3
  83. data/lib/rubocop/cop/rails/safe_navigation.rb +89 -0
  84. data/lib/rubocop/cop/rails/save_bang.rb +78 -9
  85. data/lib/rubocop/cop/rails/scope_args.rb +3 -1
  86. data/lib/rubocop/cop/rails/uniq_before_pluck.rb +2 -3
  87. data/lib/rubocop/cop/rails/validation.rb +1 -1
  88. data/lib/rubocop/cop/security/json_load.rb +36 -0
  89. data/lib/rubocop/cop/style/alias.rb +1 -1
  90. data/lib/rubocop/cop/style/align_hash.rb +25 -14
  91. data/lib/rubocop/cop/style/and_or.rb +13 -3
  92. data/lib/rubocop/cop/style/array_join.rb +3 -3
  93. data/lib/rubocop/cop/style/ascii_comments.rb +1 -2
  94. data/lib/rubocop/cop/style/ascii_identifiers.rb +1 -2
  95. data/lib/rubocop/cop/style/attr.rb +1 -3
  96. data/lib/rubocop/cop/style/block_comments.rb +2 -6
  97. data/lib/rubocop/cop/style/block_delimiters.rb +35 -21
  98. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +4 -4
  99. data/lib/rubocop/cop/style/case_indentation.rb +1 -3
  100. data/lib/rubocop/cop/style/class_methods.rb +3 -4
  101. data/lib/rubocop/cop/style/collection_methods.rb +1 -1
  102. data/lib/rubocop/cop/style/command_literal.rb +15 -8
  103. data/lib/rubocop/cop/style/comment_annotation.rb +1 -2
  104. data/lib/rubocop/cop/style/conditional_assignment.rb +68 -36
  105. data/lib/rubocop/cop/style/copyright.rb +1 -5
  106. data/lib/rubocop/cop/style/def_with_parentheses.rb +3 -5
  107. data/lib/rubocop/cop/style/documentation.rb +28 -56
  108. data/lib/rubocop/cop/style/documentation_method.rb +80 -0
  109. data/lib/rubocop/cop/style/each_for_simple_loop.rb +6 -5
  110. data/lib/rubocop/cop/style/each_with_object.rb +2 -2
  111. data/lib/rubocop/cop/style/else_alignment.rb +10 -9
  112. data/lib/rubocop/cop/style/empty_case_condition.rb +2 -4
  113. data/lib/rubocop/cop/style/empty_else.rb +1 -4
  114. data/lib/rubocop/cop/style/empty_line_between_defs.rb +1 -3
  115. data/lib/rubocop/cop/style/empty_lines_around_access_modifier.rb +2 -5
  116. data/lib/rubocop/cop/style/encoding.rb +28 -14
  117. data/lib/rubocop/cop/style/even_odd.rb +28 -17
  118. data/lib/rubocop/cop/style/extra_spacing.rb +36 -25
  119. data/lib/rubocop/cop/style/file_name.rb +19 -10
  120. data/lib/rubocop/cop/style/first_parameter_indentation.rb +2 -3
  121. data/lib/rubocop/cop/style/for.rb +12 -8
  122. data/lib/rubocop/cop/style/format_string.rb +1 -1
  123. data/lib/rubocop/cop/style/guard_clause.rb +22 -56
  124. data/lib/rubocop/cop/style/hash_syntax.rb +72 -7
  125. data/lib/rubocop/cop/style/if_unless_modifier.rb +23 -19
  126. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +3 -3
  127. data/lib/rubocop/cop/style/indentation_width.rb +30 -16
  128. data/lib/rubocop/cop/style/infinite_loop.rb +16 -13
  129. data/lib/rubocop/cop/style/initial_indentation.rb +23 -18
  130. data/lib/rubocop/cop/style/inline_comment.rb +16 -3
  131. data/lib/rubocop/cop/style/lambda.rb +22 -10
  132. data/lib/rubocop/cop/style/leading_comment_space.rb +12 -1
  133. data/lib/rubocop/cop/style/line_end_concatenation.rb +24 -6
  134. data/lib/rubocop/cop/style/method_call_parentheses.rb +18 -9
  135. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +3 -4
  136. data/lib/rubocop/cop/style/method_def_parentheses.rb +3 -4
  137. data/lib/rubocop/cop/style/method_missing.rb +10 -2
  138. data/lib/rubocop/cop/style/module_function.rb +14 -6
  139. data/lib/rubocop/cop/style/multiline_assignment_layout.rb +2 -5
  140. data/lib/rubocop/cop/style/multiline_block_chain.rb +3 -5
  141. data/lib/rubocop/cop/style/multiline_block_layout.rb +22 -15
  142. data/lib/rubocop/cop/style/multiline_method_call_brace_layout.rb +9 -0
  143. data/lib/rubocop/cop/style/multiline_method_call_indentation.rb +41 -20
  144. data/lib/rubocop/cop/style/multiline_operation_indentation.rb +6 -6
  145. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +3 -5
  146. data/lib/rubocop/cop/style/mutable_constant.rb +21 -13
  147. data/lib/rubocop/cop/style/negated_if.rb +1 -1
  148. data/lib/rubocop/cop/style/negated_while.rb +3 -3
  149. data/lib/rubocop/cop/style/nested_modifier.rb +2 -4
  150. data/lib/rubocop/cop/style/next.rb +4 -4
  151. data/lib/rubocop/cop/style/non_nil_check.rb +18 -10
  152. data/lib/rubocop/cop/style/numeric_literal_prefix.rb +8 -0
  153. data/lib/rubocop/cop/style/numeric_predicate.rb +9 -9
  154. data/lib/rubocop/cop/style/one_line_conditional.rb +11 -1
  155. data/lib/rubocop/cop/style/op_method.rb +1 -1
  156. data/lib/rubocop/cop/style/option_hash.rb +8 -8
  157. data/lib/rubocop/cop/style/optional_arguments.rb +21 -8
  158. data/lib/rubocop/cop/style/parallel_assignment.rb +51 -35
  159. data/lib/rubocop/cop/style/parentheses_around_condition.rb +2 -2
  160. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  161. data/lib/rubocop/cop/style/raise_args.rb +2 -2
  162. data/lib/rubocop/cop/style/redundant_begin.rb +1 -1
  163. data/lib/rubocop/cop/style/redundant_parentheses.rb +26 -15
  164. data/lib/rubocop/cop/style/redundant_return.rb +5 -5
  165. data/lib/rubocop/cop/style/redundant_self.rb +20 -11
  166. data/lib/rubocop/cop/style/regexp_literal.rb +16 -10
  167. data/lib/rubocop/cop/style/rescue_ensure_alignment.rb +8 -6
  168. data/lib/rubocop/cop/style/safe_navigation.rb +125 -0
  169. data/lib/rubocop/cop/style/self_assignment.rb +2 -2
  170. data/lib/rubocop/cop/style/semicolon.rb +9 -10
  171. data/lib/rubocop/cop/style/signal_exception.rb +2 -4
  172. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  173. data/lib/rubocop/cop/style/single_line_methods.rb +18 -11
  174. data/lib/rubocop/cop/style/space_after_method_name.rb +2 -3
  175. data/lib/rubocop/cop/style/space_after_not.rb +4 -6
  176. data/lib/rubocop/cop/style/space_around_block_parameters.rb +1 -2
  177. data/lib/rubocop/cop/style/space_around_equals_in_parameter_default.rb +1 -3
  178. data/lib/rubocop/cop/style/space_around_operators.rb +21 -16
  179. data/lib/rubocop/cop/style/space_before_block_braces.rb +2 -12
  180. data/lib/rubocop/cop/style/space_before_first_arg.rb +1 -3
  181. data/lib/rubocop/cop/style/space_inside_array_percent_literal.rb +1 -1
  182. data/lib/rubocop/cop/style/space_inside_block_braces.rb +33 -40
  183. data/lib/rubocop/cop/style/space_inside_hash_literal_braces.rb +38 -23
  184. data/lib/rubocop/cop/style/space_inside_percent_literal_delimiters.rb +1 -1
  185. data/lib/rubocop/cop/style/space_inside_string_interpolation.rb +26 -12
  186. data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +2 -4
  187. data/lib/rubocop/cop/style/symbol_array.rb +10 -10
  188. data/lib/rubocop/cop/style/symbol_proc.rb +28 -13
  189. data/lib/rubocop/cop/style/ternary_parentheses.rb +35 -5
  190. data/lib/rubocop/cop/style/trailing_blank_lines.rb +2 -4
  191. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +29 -17
  192. data/lib/rubocop/cop/style/trivial_accessors.rb +6 -6
  193. data/lib/rubocop/cop/style/unless_else.rb +2 -6
  194. data/lib/rubocop/cop/style/unneeded_capital_w.rb +8 -4
  195. data/lib/rubocop/cop/style/unneeded_interpolation.rb +4 -5
  196. data/lib/rubocop/cop/style/unneeded_percent_q.rb +13 -7
  197. data/lib/rubocop/cop/style/variable_number.rb +79 -0
  198. data/lib/rubocop/cop/style/while_until_modifier.rb +1 -1
  199. data/lib/rubocop/cop/style/word_array.rb +25 -15
  200. data/lib/rubocop/cop/style/zero_length_predicate.rb +2 -0
  201. data/lib/rubocop/cop/util.rb +23 -4
  202. data/lib/rubocop/cop/variable_force.rb +59 -25
  203. data/lib/rubocop/cop/variable_force/locatable.rb +8 -6
  204. data/lib/rubocop/cop/variable_force/variable.rb +2 -2
  205. data/lib/rubocop/cop/variable_force/variable_table.rb +3 -3
  206. data/lib/rubocop/formatter/disabled_config_formatter.rb +16 -11
  207. data/lib/rubocop/formatter/formatter_set.rb +12 -10
  208. data/lib/rubocop/formatter/worst_offenders_formatter.rb +4 -4
  209. data/lib/rubocop/node_pattern.rb +79 -35
  210. data/lib/rubocop/options.rb +4 -4
  211. data/lib/rubocop/processed_source.rb +9 -5
  212. data/lib/rubocop/remote_config.rb +14 -10
  213. data/lib/rubocop/result_cache.rb +14 -6
  214. data/lib/rubocop/runner.rb +55 -34
  215. data/lib/rubocop/string_util.rb +9 -5
  216. data/lib/rubocop/target_finder.rb +1 -1
  217. data/lib/rubocop/token.rb +1 -1
  218. data/lib/rubocop/version.rb +1 -1
  219. metadata +15 -4
  220. data/lib/rubocop/cop/lint/useless_array_splat.rb +0 -56
  221. data/lib/rubocop/cop/performance/push_splat.rb +0 -47
@@ -24,6 +24,8 @@ module RuboCop
24
24
  # own meaning. Correcting ActiveRecord methods with this cop should be
25
25
  # considered unsafe.
26
26
  class Detect < Cop
27
+ include SafeMode
28
+
27
29
  MSG = 'Use `%s` instead of `%s.%s`.'.freeze
28
30
  REVERSE_MSG = 'Use `reverse.%s` instead of `%s.%s`.'.freeze
29
31
 
@@ -31,7 +33,7 @@ module RuboCop
31
33
  DANGEROUS_METHODS = [:first, :last].freeze
32
34
 
33
35
  def on_send(node)
34
- return unless should_run?
36
+ return if rails_safe_mode?
35
37
  receiver, second_method, *args = *node
36
38
  return if accept_second_call?(receiver, second_method, args)
37
39
 
@@ -62,12 +64,6 @@ module RuboCop
62
64
 
63
65
  private
64
66
 
65
- def should_run?
66
- !(cop_config['SafeMode'.freeze] ||
67
- config['Rails'.freeze] &&
68
- config['Rails'.freeze]['Enabled'.freeze])
69
- end
70
-
71
67
  def accept_second_call?(receiver, method, args)
72
68
  !receiver ||
73
69
  !DANGEROUS_METHODS.include?(method) ||
@@ -33,19 +33,11 @@ module RuboCop
33
33
  first_call_args,
34
34
  second_call_args = two_start_end_with_calls(node)
35
35
 
36
- if receiver && second_call_args.all?(&:pure?)
37
- add_offense(
38
- node,
39
- :expression,
40
- format(
41
- MSG,
42
- receiver: receiver.source,
43
- method: method,
44
- combined_args: combine_args(first_call_args, second_call_args),
45
- original_code: node.source
46
- )
47
- )
48
- end
36
+ return unless receiver && second_call_args.all?(&:pure?)
37
+
38
+ combined_args = combine_args(first_call_args, second_call_args)
39
+
40
+ add_offense_for_double_call(node, receiver, method, combined_args)
49
41
  end
50
42
 
51
43
  private
@@ -54,6 +46,18 @@ module RuboCop
54
46
  (first_call_args + second_call_args).map(&:source).join(', ')
55
47
  end
56
48
 
49
+ def add_offense_for_double_call(node, receiver, method, combined_args)
50
+ add_offense(node,
51
+ :expression,
52
+ format(
53
+ MSG,
54
+ receiver: receiver.source,
55
+ method: method,
56
+ combined_args: combined_args,
57
+ original_code: node.source
58
+ ))
59
+ end
60
+
57
61
  def_node_matcher :two_start_end_with_calls, <<-END
58
62
  (or
59
63
  (send $_recv [{:start_with? :end_with?} $_method] $...)
@@ -13,13 +13,10 @@ module RuboCop
13
13
  MATCHER
14
14
 
15
15
  def on_send(node)
16
- counter(node) do |variable, arg|
17
- return if contains_splat?(variable)
18
- return if contains_double_splat?(variable)
19
- return if !arg.nil? && string_argument?(arg.first)
20
- if node.parent
21
- return if node.parent.casgn_type? || node.parent.block_type?
22
- end
16
+ return if allowed_parent?(node.parent)
17
+
18
+ counter(node) do |var, arg|
19
+ return if allowed_variable?(var) || allowed_argument?(arg)
23
20
 
24
21
  add_offense(node, :expression)
25
22
  end
@@ -27,23 +24,31 @@ module RuboCop
27
24
 
28
25
  private
29
26
 
27
+ def allowed_variable?(var)
28
+ contains_splat?(var) || contains_double_splat?(var)
29
+ end
30
+
31
+ def allowed_argument?(arg)
32
+ arg && non_string_argument?(arg.first)
33
+ end
34
+
35
+ def allowed_parent?(node)
36
+ node && (node.casgn_type? || node.block_type?)
37
+ end
38
+
30
39
  def contains_splat?(node)
31
40
  return unless node.array_type?
32
41
 
33
- node.children.any? do |child|
34
- child.respond_to?(:splat_type?) && child.splat_type?
35
- end
42
+ node.each_child_node(:splat).any?
36
43
  end
37
44
 
38
45
  def contains_double_splat?(node)
39
46
  return unless node.hash_type?
40
47
 
41
- node.children.any? do |child|
42
- child.respond_to?(:kwsplat_type?) && child.kwsplat_type?
43
- end
48
+ node.each_child_node(:kwsplat).any?
44
49
  end
45
50
 
46
- def string_argument?(node)
51
+ def non_string_argument?(node)
47
52
  node && !node.str_type?
48
53
  end
49
54
  end
@@ -20,16 +20,17 @@ module RuboCop
20
20
  FLATTEN_MULTIPLE_LEVELS = ' Beware, `flat_map` only flattens 1 level ' \
21
21
  'and `flatten` can be used to flatten ' \
22
22
  'multiple levels.'.freeze
23
- FLATTEN = [:flatten, :flatten!].freeze
23
+ FLATTEN_METHODS = [:flatten, :flatten!].freeze
24
+ MAP_METHODS = [:map, :collect].freeze
24
25
 
25
26
  def on_send(node)
26
27
  left, second_method, flatten_param = *node
27
- return unless FLATTEN.include?(second_method)
28
+ return unless flatten_method?(second_method)
28
29
 
29
30
  flatten_level, = *flatten_param
30
31
  expression, = *left
31
32
  _array, first_method = *expression
32
- return unless first_method == :map || first_method == :collect
33
+ return unless map_method?(first_method)
33
34
 
34
35
  if cop_config['EnabledForFlattenWithoutParams'] && flatten_level.nil?
35
36
  offense_for_levels(node, expression, first_method, second_method)
@@ -46,9 +47,8 @@ module RuboCop
46
47
  array, = *receiver
47
48
 
48
49
  lambda do |corrector|
49
- range = Parser::Source::Range.new(node.source_range.source_buffer,
50
- node.loc.dot.begin_pos,
51
- node.source_range.end_pos)
50
+ range = range_between(node.loc.dot.begin_pos,
51
+ node.source_range.end_pos)
52
52
 
53
53
  corrector.remove(range)
54
54
  corrector.replace(array.loc.selector, 'flat_map')
@@ -57,6 +57,14 @@ module RuboCop
57
57
 
58
58
  private
59
59
 
60
+ def flatten_method?(method_name)
61
+ FLATTEN_METHODS.include?(method_name)
62
+ end
63
+
64
+ def map_method?(method_name)
65
+ MAP_METHODS.include?(method_name)
66
+ end
67
+
60
68
  def offense_for_levels(node, expression, first_method, second_method)
61
69
  message = MSG + FLATTEN_MULTIPLE_LEVELS
62
70
  offense(node, expression, first_method, second_method, message)
@@ -67,9 +75,8 @@ module RuboCop
67
75
  end
68
76
 
69
77
  def offense(node, expression, first_method, second_method, message)
70
- range = Parser::Source::Range.new(node.source_range.source_buffer,
71
- expression.loc.selector.begin_pos,
72
- node.loc.selector.end_pos)
78
+ range = range_between(expression.loc.selector.begin_pos,
79
+ node.loc.selector.end_pos)
73
80
 
74
81
  add_offense(node, range, format(message, first_method, second_method))
75
82
  end
@@ -70,9 +70,8 @@ module RuboCop
70
70
  def correct_args(node, corrector)
71
71
  args = node.parent.children[1]
72
72
  used_arg = "|#{@args.detect { |_k, v| v }.first}|"
73
- args_range = Parser::Source::Range.new(node.parent.source,
74
- args.loc.begin.begin_pos,
75
- args.loc.end.end_pos)
73
+ args_range = range_between(args.loc.begin.begin_pos,
74
+ args.loc.end.end_pos)
76
75
  corrector.replace(args_range, used_arg)
77
76
  end
78
77
 
@@ -24,18 +24,16 @@ module RuboCop
24
24
 
25
25
  def on_send(node)
26
26
  lstrip_rstrip(node) do |first_send, method_one, method_two|
27
- range = Parser::Source::Range.new(node.source_range.source_buffer,
28
- first_send.loc.selector.begin_pos,
29
- node.source_range.end_pos)
27
+ range = range_between(first_send.loc.selector.begin_pos,
28
+ node.source_range.end_pos)
30
29
  add_offense(node, range, format(MSG, method_one, method_two))
31
30
  end
32
31
  end
33
32
 
34
33
  def autocorrect(node)
35
34
  first_send, = *node
36
- range = Parser::Source::Range.new(node.source_range.source_buffer,
37
- first_send.loc.selector.begin_pos,
38
- node.source_range.end_pos)
35
+ range = range_between(first_send.loc.selector.begin_pos,
36
+ node.source_range.end_pos)
39
37
  ->(corrector) { corrector.replace(range, 'strip') }
40
38
  end
41
39
  end
@@ -40,9 +40,12 @@ module RuboCop
40
40
  end
41
41
 
42
42
  def autocorrect(node)
43
+ receiver, _method, arg = *node
44
+
43
45
  # Regexp#match can take a second argument, but this cop doesn't
44
46
  # register an offense in that case
45
- receiver, _method, arg = *node
47
+ return unless arg.regexp_type?
48
+
46
49
  new_source = receiver.source + ' =~ ' + arg.source
47
50
  ->(corrector) { corrector.replace(node.source_range, new_source) }
48
51
  end
@@ -16,12 +16,9 @@ module RuboCop
16
16
  MSG = 'Use `%s` instead of `%s`.'.freeze
17
17
 
18
18
  def_node_matcher :redundant_merge, '(send $_ :merge! (hash $...))'
19
- def_node_matcher :modifier_flow_control, <<-END
19
+ def_node_matcher :modifier_flow_control?, <<-END
20
20
  [{if while until} modifier_form?]
21
21
  END
22
- def_node_matcher :each_with_object_node, <<-END
23
- (block (send _ :each_with_object _) (args _ $_) ...)
24
- END
25
22
 
26
23
  def on_send(node)
27
24
  each_redundant_merge(node) do |receiver, pairs|
@@ -33,21 +30,13 @@ module RuboCop
33
30
 
34
31
  def autocorrect(node)
35
32
  redundant_merge(node) do |receiver, pairs|
36
- lambda do |corrector|
37
- new_source = to_assignments(receiver, pairs).join("\n")
38
-
39
- parent = node.parent
40
- if parent && pairs.size > 1
41
- if modifier_flow_control(parent)
42
- new_source = rewrite_with_modifier(node, parent, new_source)
43
- node = parent
44
- else
45
- padding = "\n#{leading_spaces(node)}"
46
- new_source.gsub!(/\n/, padding)
47
- end
48
- end
49
-
50
- corrector.replace(node.source_range, new_source)
33
+ new_source = to_assignments(receiver, pairs).join("\n")
34
+
35
+ parent = node.parent
36
+ if parent && pairs.size > 1
37
+ correct_multiple_elements(node, parent, new_source)
38
+ else
39
+ correct_single_element(node, new_source)
51
40
  end
52
41
  end
53
42
  end
@@ -57,7 +46,7 @@ module RuboCop
57
46
  def each_redundant_merge(node)
58
47
  redundant_merge(node) do |receiver, pairs|
59
48
  next if node.value_used? &&
60
- !value_used_inside_each_with_object?(node, receiver)
49
+ !EachWithObjectInspector.new(node, receiver).value_used?
61
50
  next if pairs.size > 1 && !receiver.pure?
62
51
  next if pairs.size > max_key_value_pairs
63
52
 
@@ -65,21 +54,20 @@ module RuboCop
65
54
  end
66
55
  end
67
56
 
68
- def value_used_inside_each_with_object?(node, receiver)
69
- while receiver.respond_to?(:send_type?) && receiver.send_type?
70
- receiver, = *receiver
71
- end
72
-
73
- unless receiver.respond_to?(:lvar_type?) && receiver.lvar_type?
74
- return false
57
+ def correct_multiple_elements(node, parent, new_source)
58
+ if modifier_flow_control?(parent)
59
+ new_source = rewrite_with_modifier(node, parent, new_source)
60
+ node = parent
61
+ else
62
+ padding = "\n#{leading_spaces(node)}"
63
+ new_source.gsub!(/\n/, padding)
75
64
  end
76
65
 
77
- parent = node.parent
78
- grandparent = parent.parent if parent.begin_type?
79
- second_arg = each_with_object_node(grandparent || parent)
80
- return false if second_arg.nil?
66
+ ->(corrector) { corrector.replace(node.source_range, new_source) }
67
+ end
81
68
 
82
- receiver.loc.name.source == second_arg.loc.name.source
69
+ def correct_single_element(node, new_source)
70
+ ->(corrector) { corrector.replace(node.source_range, new_source) }
83
71
  end
84
72
 
85
73
  def to_assignments(receiver, pairs)
@@ -115,6 +103,49 @@ module RuboCop
115
103
  def max_key_value_pairs
116
104
  cop_config['MaxKeyValuePairs'].to_i
117
105
  end
106
+
107
+ # A utility class for checking the use of values within an
108
+ # `each_with_object` call.
109
+ class EachWithObjectInspector
110
+ extend NodePattern::Macros
111
+
112
+ def initialize(node, receiver)
113
+ @node = node
114
+ @receiver = unwind(receiver)
115
+ end
116
+
117
+ def value_used?
118
+ return false unless eligible_receiver? && second_argument
119
+
120
+ receiver.loc.name.source == second_argument.loc.name.source
121
+ end
122
+
123
+ private
124
+
125
+ attr_reader :node, :receiver
126
+
127
+ def eligible_receiver?
128
+ receiver.respond_to?(:lvar_type?) && receiver.lvar_type?
129
+ end
130
+
131
+ def second_argument
132
+ parent = node.parent
133
+ parent = parent.parent if parent.begin_type?
134
+
135
+ @second_argument ||= each_with_object_node(parent)
136
+ end
137
+
138
+ def unwind(receiver)
139
+ while receiver.respond_to?(:send_type?) && receiver.send_type?
140
+ receiver, = *receiver
141
+ end
142
+ receiver
143
+ end
144
+
145
+ def_node_matcher :each_with_object_node, <<-END
146
+ (block (send _ :each_with_object _) (args _ $_) ...)
147
+ END
148
+ end
118
149
  end
119
150
  end
120
151
  end
@@ -25,19 +25,20 @@ module RuboCop
25
25
 
26
26
  def on_block(node)
27
27
  redundant_sort_by(node) do |send, var_name|
28
- range = Parser::Source::Range.new(node.source_range.source_buffer,
29
- send.loc.selector.begin_pos,
30
- node.loc.end.end_pos)
28
+ range = sort_by_range(send, node)
31
29
  add_offense(node, range, format(MSG, var_name, var_name))
32
30
  end
33
31
  end
34
32
 
35
33
  def autocorrect(node)
36
34
  send, = *node
37
- range = Parser::Source::Range.new(node.source_range.source_buffer,
38
- send.loc.selector.begin_pos,
39
- node.loc.end.end_pos)
40
- ->(corrector) { corrector.replace(range, 'sort') }
35
+ ->(corrector) { corrector.replace(sort_by_range(send, node), 'sort') }
36
+ end
37
+
38
+ private
39
+
40
+ def sort_by_range(send, node)
41
+ range_between(send.loc.selector.begin_pos, node.loc.end.end_pos)
41
42
  end
42
43
  end
43
44
  end
@@ -23,13 +23,10 @@ module RuboCop
23
23
 
24
24
  def on_send(node)
25
25
  reverse_each?(node) do |receiver|
26
- source_buffer = node.source_range.source_buffer
27
26
  location_of_reverse = receiver.loc.selector.begin_pos
28
27
  end_location = node.loc.selector.end_pos
29
28
 
30
- range = Parser::Source::Range.new(source_buffer,
31
- location_of_reverse,
32
- end_location)
29
+ range = range_between(location_of_reverse, end_location)
33
30
  add_offense(node, range, MSG)
34
31
  end
35
32
  end
@@ -28,22 +28,35 @@ module RuboCop
28
28
  MSG = 'Use `size` instead of `count`.'.freeze
29
29
 
30
30
  def on_send(node)
31
- receiver, method, args = *node
32
-
33
- return if receiver.nil?
34
- return unless method == :count
35
- return unless array?(receiver) || hash?(receiver)
36
- return if node.parent && node.parent.block_type?
37
- return if args
31
+ return unless eligible_node?(node)
38
32
 
39
33
  add_offense(node, node.loc.selector)
40
34
  end
41
35
 
36
+ private
37
+
42
38
  def autocorrect(node)
43
39
  ->(corrector) { corrector.replace(node.loc.selector, 'size') }
44
40
  end
45
41
 
46
- private
42
+ def eligible_node?(node)
43
+ receiver, method, args = *node
44
+
45
+ return false unless method == :count
46
+ return false if args
47
+
48
+ eligible_receiver?(receiver) && !allowed_parent?(node.parent)
49
+ end
50
+
51
+ def eligible_receiver?(node)
52
+ return false unless node
53
+
54
+ array?(node) || hash?(node)
55
+ end
56
+
57
+ def allowed_parent?(node)
58
+ node && node.block_type?
59
+ end
47
60
 
48
61
  def array?(node)
49
62
  receiver, method = *node