rubocop 0.47.1 → 0.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (242) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +28 -16
  3. data/config/default.yml +203 -115
  4. data/config/disabled.yml +0 -5
  5. data/config/enabled.yml +92 -8
  6. data/lib/rubocop.rb +24 -1
  7. data/lib/rubocop/ast/builder.rb +7 -2
  8. data/lib/rubocop/ast/node.rb +23 -20
  9. data/lib/rubocop/ast/node/and_node.rb +37 -0
  10. data/lib/rubocop/ast/node/array_node.rb +4 -1
  11. data/lib/rubocop/ast/node/case_node.rb +1 -0
  12. data/lib/rubocop/ast/node/ensure_node.rb +25 -0
  13. data/lib/rubocop/ast/node/hash_node.rb +10 -3
  14. data/lib/rubocop/ast/node/if_node.rb +2 -0
  15. data/lib/rubocop/ast/node/mixin/binary_operator_node.rb +23 -0
  16. data/lib/rubocop/ast/node/mixin/predicate_operator_node.rb +35 -0
  17. data/lib/rubocop/ast/node/or_node.rb +37 -0
  18. data/lib/rubocop/ast/node/resbody_node.rb +25 -0
  19. data/lib/rubocop/ast/node/send_node.rb +190 -0
  20. data/lib/rubocop/ast/node/when_node.rb +1 -1
  21. data/lib/rubocop/ast/traversal.rb +15 -15
  22. data/lib/rubocop/comment_config.rb +1 -1
  23. data/lib/rubocop/config.rb +39 -15
  24. data/lib/rubocop/config_loader.rb +34 -13
  25. data/lib/rubocop/cop/bundler/ordered_gems.rb +23 -4
  26. data/lib/rubocop/cop/commissioner.rb +4 -0
  27. data/lib/rubocop/cop/cop.rb +5 -0
  28. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +53 -0
  29. data/lib/rubocop/cop/lint/debugger.rb +8 -1
  30. data/lib/rubocop/cop/lint/def_end_alignment.rb +2 -1
  31. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +2 -4
  32. data/lib/rubocop/cop/lint/duplicate_case_condition.rb +1 -1
  33. data/lib/rubocop/cop/lint/each_with_object_argument.rb +3 -1
  34. data/lib/rubocop/cop/lint/empty_ensure.rb +6 -2
  35. data/lib/rubocop/cop/lint/ensure_return.rb +1 -1
  36. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +20 -18
  37. data/lib/rubocop/cop/lint/handle_exceptions.rb +1 -3
  38. data/lib/rubocop/cop/lint/literal_in_condition.rb +1 -1
  39. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
  40. data/lib/rubocop/cop/lint/multiple_compare.rb +5 -3
  41. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +26 -18
  42. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +7 -8
  43. data/lib/rubocop/cop/lint/require_parentheses.rb +7 -13
  44. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +7 -3
  45. data/lib/rubocop/cop/lint/shadowed_exception.rb +2 -6
  46. data/lib/rubocop/cop/lint/string_conversion_in_interpolation.rb +7 -8
  47. data/lib/rubocop/cop/lint/unneeded_disable.rb +35 -11
  48. data/lib/rubocop/cop/lint/unneeded_splat_expansion.rb +1 -1
  49. data/lib/rubocop/cop/lint/unreachable_code.rb +5 -2
  50. data/lib/rubocop/cop/lint/unused_block_argument.rb +6 -6
  51. data/lib/rubocop/cop/lint/useless_assignment.rb +2 -1
  52. data/lib/rubocop/cop/lint/useless_comparison.rb +5 -4
  53. data/lib/rubocop/cop/lint/useless_setter_call.rb +1 -1
  54. data/lib/rubocop/cop/message_annotator.rb +7 -3
  55. data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
  56. data/lib/rubocop/cop/metrics/block_nesting.rb +4 -4
  57. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +2 -2
  58. data/lib/rubocop/cop/metrics/line_length.rb +2 -9
  59. data/lib/rubocop/cop/metrics/parameter_lists.rb +4 -3
  60. data/lib/rubocop/cop/metrics/perceived_complexity.rb +2 -2
  61. data/lib/rubocop/cop/mixin/access_modifier_node.rb +1 -1
  62. data/lib/rubocop/cop/mixin/array_hash_indentation.rb +2 -2
  63. data/lib/rubocop/cop/mixin/check_assignment.rb +6 -6
  64. data/lib/rubocop/cop/mixin/duplication.rb +1 -1
  65. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -1
  66. data/lib/rubocop/cop/mixin/ignored_pattern.rb +27 -0
  67. data/lib/rubocop/cop/mixin/method_preference.rb +2 -0
  68. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +17 -29
  69. data/lib/rubocop/cop/mixin/on_method_def.rb +3 -3
  70. data/lib/rubocop/cop/mixin/percent_literal.rb +27 -0
  71. data/lib/rubocop/cop/mixin/rescue_node.rb +21 -0
  72. data/lib/rubocop/cop/mixin/safe_mode.rb +1 -1
  73. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
  74. data/lib/rubocop/cop/mixin/statement_modifier.rb +2 -1
  75. data/lib/rubocop/cop/mixin/target_rails_version.rb +16 -0
  76. data/lib/rubocop/cop/mixin/unused_argument.rb +1 -1
  77. data/lib/rubocop/cop/offense.rb +3 -3
  78. data/lib/rubocop/cop/performance/casecmp.rb +1 -1
  79. data/lib/rubocop/cop/performance/detect.rb +2 -1
  80. data/lib/rubocop/cop/performance/double_start_end_with.rb +35 -1
  81. data/lib/rubocop/cop/performance/end_with.rb +3 -1
  82. data/lib/rubocop/cop/performance/flat_map.rb +6 -6
  83. data/lib/rubocop/cop/performance/lstrip_rstrip.rb +2 -2
  84. data/lib/rubocop/cop/performance/range_include.rb +3 -1
  85. data/lib/rubocop/cop/performance/redundant_match.rb +6 -5
  86. data/lib/rubocop/cop/performance/regexp_match.rb +10 -3
  87. data/lib/rubocop/cop/performance/reverse_each.rb +2 -1
  88. data/lib/rubocop/cop/performance/size.rb +6 -11
  89. data/lib/rubocop/cop/performance/start_with.rb +3 -1
  90. data/lib/rubocop/cop/performance/string_replacement.rb +13 -18
  91. data/lib/rubocop/cop/performance/times_map.rb +4 -4
  92. data/lib/rubocop/cop/rails/action_filter.rb +42 -42
  93. data/lib/rubocop/cop/rails/active_support_aliases.rb +68 -0
  94. data/lib/rubocop/cop/rails/blank.rb +131 -0
  95. data/lib/rubocop/cop/rails/date.rb +25 -28
  96. data/lib/rubocop/cop/rails/delegate_allow_blank.rb +5 -7
  97. data/lib/rubocop/cop/rails/dynamic_find_by.rb +7 -3
  98. data/lib/rubocop/cop/rails/exit.rb +9 -9
  99. data/lib/rubocop/cop/rails/file_path.rb +5 -14
  100. data/lib/rubocop/cop/rails/find_by.rb +8 -10
  101. data/lib/rubocop/cop/rails/find_each.rb +6 -9
  102. data/lib/rubocop/cop/rails/has_and_belongs_to_many.rb +1 -0
  103. data/lib/rubocop/cop/rails/http_positional_arguments.rb +15 -7
  104. data/lib/rubocop/cop/rails/output.rb +3 -5
  105. data/lib/rubocop/cop/rails/output_safety.rb +4 -8
  106. data/lib/rubocop/cop/rails/pluralization_grammar.rb +25 -24
  107. data/lib/rubocop/cop/rails/present.rb +137 -0
  108. data/lib/rubocop/cop/rails/read_write_attribute.rb +9 -18
  109. data/lib/rubocop/cop/rails/relative_date_constant.rb +53 -0
  110. data/lib/rubocop/cop/rails/request_referer.rb +7 -4
  111. data/lib/rubocop/cop/rails/reversible_migration.rb +1 -2
  112. data/lib/rubocop/cop/rails/safe_navigation.rb +2 -1
  113. data/lib/rubocop/cop/rails/save_bang.rb +10 -10
  114. data/lib/rubocop/cop/rails/skips_model_validations.rb +23 -6
  115. data/lib/rubocop/cop/rails/time_zone.rb +20 -18
  116. data/lib/rubocop/cop/rails/uniq_before_pluck.rb +3 -2
  117. data/lib/rubocop/cop/rails/validation.rb +8 -11
  118. data/lib/rubocop/cop/registry.rb +3 -3
  119. data/lib/rubocop/cop/security/json_load.rb +1 -1
  120. data/lib/rubocop/cop/security/marshal_load.rb +5 -1
  121. data/lib/rubocop/cop/security/yaml_load.rb +3 -3
  122. data/lib/rubocop/cop/severity.rb +1 -1
  123. data/lib/rubocop/cop/style/alias.rb +5 -5
  124. data/lib/rubocop/cop/style/align_hash.rb +1 -1
  125. data/lib/rubocop/cop/style/align_parameters.rb +5 -5
  126. data/lib/rubocop/cop/style/and_or.rb +16 -31
  127. data/lib/rubocop/cop/style/attr.rb +14 -8
  128. data/lib/rubocop/cop/style/auto_resource_cleanup.rb +8 -11
  129. data/lib/rubocop/cop/style/block_delimiters.rb +11 -13
  130. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +19 -23
  131. data/lib/rubocop/cop/style/case_indentation.rb +2 -0
  132. data/lib/rubocop/cop/style/class_and_module_children.rb +1 -1
  133. data/lib/rubocop/cop/style/class_check.rb +5 -7
  134. data/lib/rubocop/cop/style/closing_parenthesis_indentation.rb +5 -4
  135. data/lib/rubocop/cop/style/collection_methods.rb +8 -8
  136. data/lib/rubocop/cop/style/colon_method_call.rb +2 -9
  137. data/lib/rubocop/cop/style/conditional_assignment.rb +38 -45
  138. data/lib/rubocop/cop/style/constant_name.rb +1 -1
  139. data/lib/rubocop/cop/style/documentation_method.rb +1 -0
  140. data/lib/rubocop/cop/style/dot_position.rb +3 -7
  141. data/lib/rubocop/cop/style/double_negation.rb +2 -1
  142. data/lib/rubocop/cop/style/each_with_object.rb +1 -1
  143. data/lib/rubocop/cop/style/empty_else.rb +2 -2
  144. data/lib/rubocop/cop/style/empty_line_after_magic_comment.rb +63 -0
  145. data/lib/rubocop/cop/style/empty_line_between_defs.rb +74 -4
  146. data/lib/rubocop/cop/style/empty_lines_around_begin_body.rb +42 -0
  147. data/lib/rubocop/cop/style/empty_lines_around_exception_handling_keywords.rb +127 -0
  148. data/lib/rubocop/cop/style/empty_literal.rb +17 -9
  149. data/lib/rubocop/cop/style/end_of_line.rb +25 -3
  150. data/lib/rubocop/cop/style/file_name.rb +1 -1
  151. data/lib/rubocop/cop/style/first_method_argument_line_break.rb +1 -1
  152. data/lib/rubocop/cop/style/first_parameter_indentation.rb +17 -19
  153. data/lib/rubocop/cop/style/for.rb +2 -4
  154. data/lib/rubocop/cop/style/format_string.rb +5 -4
  155. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
  156. data/lib/rubocop/cop/style/identical_conditional_branches.rb +27 -1
  157. data/lib/rubocop/cop/style/if_unless_modifier.rb +2 -2
  158. data/lib/rubocop/cop/style/indent_assignment.rb +2 -2
  159. data/lib/rubocop/cop/style/indent_hash.rb +2 -1
  160. data/lib/rubocop/cop/style/indent_heredoc.rb +173 -0
  161. data/lib/rubocop/cop/style/indentation_width.rb +61 -29
  162. data/lib/rubocop/cop/style/inverse_methods.rb +130 -0
  163. data/lib/rubocop/cop/style/lambda_call.rb +15 -11
  164. data/lib/rubocop/cop/style/line_end_concatenation.rb +4 -4
  165. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +26 -14
  166. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +6 -16
  167. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +4 -1
  168. data/lib/rubocop/cop/style/missing_else.rb +4 -3
  169. data/lib/rubocop/cop/style/mixin_grouping.rb +97 -0
  170. data/lib/rubocop/cop/style/multiline_memoization.rb +38 -5
  171. data/lib/rubocop/cop/style/multiline_method_call_brace_layout.rb +2 -3
  172. data/lib/rubocop/cop/style/multiline_method_call_indentation.rb +38 -19
  173. data/lib/rubocop/cop/style/mutable_constant.rb +5 -1
  174. data/lib/rubocop/cop/style/negated_if.rb +73 -1
  175. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +21 -19
  176. data/lib/rubocop/cop/style/next.rb +5 -5
  177. data/lib/rubocop/cop/style/non_nil_check.rb +7 -10
  178. data/lib/rubocop/cop/style/not.rb +3 -4
  179. data/lib/rubocop/cop/style/numeric_literals.rb +25 -3
  180. data/lib/rubocop/cop/style/numeric_predicate.rb +1 -1
  181. data/lib/rubocop/cop/style/one_line_conditional.rb +2 -2
  182. data/lib/rubocop/cop/style/op_method.rb +2 -2
  183. data/lib/rubocop/cop/style/parallel_assignment.rb +6 -3
  184. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +52 -6
  185. data/lib/rubocop/cop/style/perl_backrefs.rb +1 -1
  186. data/lib/rubocop/cop/style/preferred_hash_methods.rb +9 -9
  187. data/lib/rubocop/cop/style/raise_args.rb +28 -24
  188. data/lib/rubocop/cop/style/redundant_freeze.rb +5 -7
  189. data/lib/rubocop/cop/style/redundant_parentheses.rb +2 -3
  190. data/lib/rubocop/cop/style/redundant_self.rb +17 -35
  191. data/lib/rubocop/cop/style/rescue_modifier.rb +2 -14
  192. data/lib/rubocop/cop/style/self_assignment.rb +3 -3
  193. data/lib/rubocop/cop/style/send.rb +4 -5
  194. data/lib/rubocop/cop/style/space_after_not.rb +7 -8
  195. data/lib/rubocop/cop/style/space_around_keyword.rb +8 -9
  196. data/lib/rubocop/cop/style/space_around_operators.rb +19 -15
  197. data/lib/rubocop/cop/style/space_before_first_arg.rb +17 -14
  198. data/lib/rubocop/cop/style/space_inside_brackets.rb +1 -1
  199. data/lib/rubocop/cop/style/space_inside_hash_literal_braces.rb +3 -3
  200. data/lib/rubocop/cop/style/space_inside_parens.rb +1 -1
  201. data/lib/rubocop/cop/style/special_global_vars.rb +14 -14
  202. data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +2 -1
  203. data/lib/rubocop/cop/style/string_literals.rb +1 -1
  204. data/lib/rubocop/cop/style/string_methods.rb +10 -5
  205. data/lib/rubocop/cop/style/struct_inheritance.rb +4 -15
  206. data/lib/rubocop/cop/style/symbol_array.rb +31 -35
  207. data/lib/rubocop/cop/style/symbol_proc.rb +2 -2
  208. data/lib/rubocop/cop/style/ternary_parentheses.rb +41 -13
  209. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +6 -9
  210. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +4 -1
  211. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  212. data/lib/rubocop/cop/style/unneeded_capital_w.rb +1 -2
  213. data/lib/rubocop/cop/style/unneeded_percent_q.rb +1 -1
  214. data/lib/rubocop/cop/style/word_array.rb +12 -34
  215. data/lib/rubocop/cop/style/zero_length_predicate.rb +11 -4
  216. data/lib/rubocop/cop/team.rb +4 -1
  217. data/lib/rubocop/cop/util.rb +33 -26
  218. data/lib/rubocop/cop/variable_force.rb +13 -13
  219. data/lib/rubocop/cop/variable_force/assignment.rb +1 -8
  220. data/lib/rubocop/cop/variable_force/branch.rb +318 -0
  221. data/lib/rubocop/cop/variable_force/branchable.rb +21 -0
  222. data/lib/rubocop/cop/variable_force/reference.rb +1 -3
  223. data/lib/rubocop/cop/variable_force/scope.rb +36 -20
  224. data/lib/rubocop/cop/variable_force/variable.rb +9 -8
  225. data/lib/rubocop/formatter/colorizable.rb +10 -10
  226. data/lib/rubocop/formatter/formatter_set.rb +1 -1
  227. data/lib/rubocop/formatter/html_formatter.rb +2 -1
  228. data/lib/rubocop/formatter/simple_text_formatter.rb +4 -2
  229. data/lib/rubocop/magic_comment.rb +20 -6
  230. data/lib/rubocop/options.rb +1 -1
  231. data/lib/rubocop/platform.rb +11 -0
  232. data/lib/rubocop/processed_source.rb +1 -1
  233. data/lib/rubocop/remote_config.rb +18 -6
  234. data/lib/rubocop/result_cache.rb +8 -8
  235. data/lib/rubocop/rspec/cop_helper.rb +2 -0
  236. data/lib/rubocop/rspec/shared_contexts.rb +20 -0
  237. data/lib/rubocop/rspec/shared_examples.rb +1 -1
  238. data/lib/rubocop/runner.rb +2 -2
  239. data/lib/rubocop/target_finder.rb +64 -6
  240. data/lib/rubocop/version.rb +2 -4
  241. metadata +27 -4
  242. data/lib/rubocop/cop/variable_force/locatable.rb +0 -200
@@ -46,9 +46,13 @@ module RuboCop
46
46
  MSG = 'Empty `ensure` block detected.'.freeze
47
47
 
48
48
  def on_ensure(node)
49
- _body, ensure_body = *node
49
+ add_offense(node, :keyword) unless node.body
50
+ end
50
51
 
51
- add_offense(node, :keyword) unless ensure_body
52
+ def autocorrect(node)
53
+ lambda do |corrector|
54
+ corrector.remove(node.loc.keyword)
55
+ end
52
56
  end
53
57
  end
54
58
  end
@@ -29,7 +29,7 @@ module RuboCop
29
29
  MSG = 'Do not return from an `ensure` block.'.freeze
30
30
 
31
31
  def on_ensure(node)
32
- _body, ensure_body = *node
32
+ ensure_body = node.body
33
33
 
34
34
  return unless ensure_body
35
35
 
@@ -29,11 +29,13 @@ module RuboCop
29
29
  SHOVEL = '<<'.freeze
30
30
  PERCENT = '%'.freeze
31
31
  PERCENT_PERCENT = '%%'.freeze
32
- STRING_TYPES = [:str, :dstr].freeze
32
+ STRING_TYPES = %i(str dstr).freeze
33
33
  NAMED_INTERPOLATION = /%(?:<\w+>|\{\w+\})/
34
34
 
35
35
  def on_send(node)
36
- add_offense(node, :selector) if offending_node?(node)
36
+ return unless offending_node?(node)
37
+
38
+ add_offense(node, :selector)
37
39
  end
38
40
 
39
41
  private
@@ -41,7 +43,7 @@ module RuboCop
41
43
  def offending_node?(node)
42
44
  return false unless called_on_string?(node)
43
45
  return false unless method_with_format_args?(node)
44
- return false if named_mode?(node) || node_with_splat_args?(node)
46
+ return false if named_mode?(node) || splat_args?(node)
45
47
 
46
48
  num_of_format_args, num_of_expected_fields = count_matches(node)
47
49
 
@@ -82,18 +84,14 @@ module RuboCop
82
84
  !relevant_node.source.scan(NAMED_FIELD_REGEX).empty?
83
85
  end
84
86
 
85
- def node_with_splat_args?(node)
87
+ def splat_args?(node)
86
88
  return false if percent?(node)
87
89
 
88
- _receiver_node, _method_name, *args = *node
89
-
90
- args.butfirst.any?(&:splat_type?)
90
+ node.arguments.butfirst.any?(&:splat_type?)
91
91
  end
92
92
 
93
93
  def heredoc?(node)
94
- _receiver, _name, args = *node
95
-
96
- args.source[0, 2] == SHOVEL
94
+ node.first_argument.source[0, 2] == SHOVEL
97
95
  end
98
96
 
99
97
  def count_matches(node)
@@ -131,7 +129,7 @@ module RuboCop
131
129
  node
132
130
  .source
133
131
  .scan(FIELD_REGEX)
134
- .select { |x| x.first != PERCENT_PERCENT }
132
+ .reject { |x| x.first == PERCENT_PERCENT }
135
133
  .reduce(0) { |acc, elem| acc + (elem[2] =~ /\*/ ? 2 : 1) }
136
134
  end
137
135
 
@@ -154,13 +152,13 @@ module RuboCop
154
152
  end
155
153
 
156
154
  def percent?(node)
157
- receiver_node, method_name, *arg_nodes = *node
155
+ receiver = node.receiver
158
156
 
159
- percent = method_name == :% &&
160
- (STRING_TYPES.include?(receiver_node.type) ||
161
- arg_nodes[0].array_type?)
157
+ percent = node.method_name == :% &&
158
+ (STRING_TYPES.include?(receiver.type) ||
159
+ node.first_argument.array_type?)
162
160
 
163
- if percent && STRING_TYPES.include?(receiver_node.type)
161
+ if percent && STRING_TYPES.include?(receiver.type)
164
162
  return false if heredoc?(node)
165
163
  end
166
164
 
@@ -168,10 +166,14 @@ module RuboCop
168
166
  end
169
167
 
170
168
  def message(node)
171
- _receiver, method_name, *_args = *node
172
169
  num_args_for_format, num_expected_fields = count_matches(node)
173
170
 
174
- method_name = 'String#%' if PERCENT == method_name.to_s
171
+ method_name = if node.method_name.to_s == PERCENT
172
+ 'String#%'
173
+ else
174
+ node.method_name
175
+ end
176
+
175
177
  format(MSG, num_args_for_format, method_name, num_expected_fields)
176
178
  end
177
179
  end
@@ -48,9 +48,7 @@ module RuboCop
48
48
  MSG = 'Do not suppress exceptions.'.freeze
49
49
 
50
50
  def on_resbody(node)
51
- _exc_list_node, _exc_var_node, body_node = *node
52
-
53
- add_offense(node, :expression) unless body_node
51
+ add_offense(node, :expression) unless node.body
54
52
  end
55
53
  end
56
54
  end
@@ -108,7 +108,7 @@ module RuboCop
108
108
  def handle_node(node)
109
109
  if node.literal?
110
110
  add_offense(node, :expression)
111
- elsif [:send, :and, :or, :begin].include?(node.type)
111
+ elsif %i(send and or begin).include?(node.type)
112
112
  check_node(node)
113
113
  end
114
114
  end
@@ -18,7 +18,7 @@ module RuboCop
18
18
  # "result is 10"
19
19
  class LiteralInInterpolation < Cop
20
20
  MSG = 'Literal interpolation detected.'.freeze
21
- COMPOSITE = [:array, :hash, :pair, :irange, :erange].freeze
21
+ COMPOSITE = %i(array hash pair irange erange).freeze
22
22
 
23
23
  def on_dstr(node)
24
24
  node.each_child_node(:begin) do |begin_node|
@@ -22,7 +22,7 @@ module RuboCop
22
22
  # x < y && y < z
23
23
  # 10 <= x && x <= 20
24
24
  class MultipleCompare < Cop
25
- MSG = 'Use `&&` operator to compare multiple value.'.freeze
25
+ MSG = 'Use the `&&` operator to compare multiple values.'.freeze
26
26
 
27
27
  def_node_matcher :multiple_compare?, <<-PATTERN
28
28
  (send (send _ {:< :> :<= :>=} $_) {:< :> :<= :>=} _)
@@ -30,13 +30,15 @@ module RuboCop
30
30
 
31
31
  def on_send(node)
32
32
  return unless multiple_compare?(node)
33
+
33
34
  add_offense(node, :expression)
34
35
  end
35
36
 
36
37
  def autocorrect(node)
38
+ center = multiple_compare?(node)
39
+ new_center = "#{center.source} && #{center.source}"
40
+
37
41
  lambda do |corrector|
38
- center = multiple_compare?(node)
39
- new_center = "#{center.source} && #{center.source}"
40
42
  corrector.replace(center.source_range, new_center)
41
43
  end
42
44
  end
@@ -3,11 +3,16 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # This cop checks for non-local exit from iterator, without return value.
7
- # It warns only when satisfies all of these: `return` doesn't have return
8
- # value, the block is preceded by a method chain, the block has arguments,
9
- # and the method which receives the block is not `define_method`
10
- # or `define_singleton_method`.
6
+ # This cop checks for non-local exits from iterators without a return
7
+ # value. It registers an offense under these conditions:
8
+ #
9
+ # - No value is returned,
10
+ # - the block is preceded by a method chain,
11
+ # - the block has arguments,
12
+ # - the method which receives the block is not `define_method`
13
+ # or `define_singleton_method`,
14
+ # - the return is not contained in an inner scope, e.g. a lambda or a
15
+ # method definition.
11
16
  #
12
17
  # @example
13
18
  #
@@ -40,17 +45,19 @@ module RuboCop
40
45
 
41
46
  def on_return(return_node)
42
47
  return if return_value?(return_node)
43
- return_node.each_ancestor(:block) do |block_node|
44
- send_node, args_node, _body_node = *block_node
45
48
 
46
- # `return` does not exit to outside of lambda block, this is safe.
47
- break if block_node.lambda?
49
+ return_node.each_ancestor(:block, :def, :defs) do |node|
50
+ break if scoped_node?(node)
51
+
52
+ send_node, args_node, _body_node = *node
53
+
48
54
  # if a proc is passed to `Module#define_method` or
49
55
  # `Object#define_singleton_method`, `return` will not cause a
50
56
  # non-local exit error
51
57
  break if define_method?(send_node)
52
58
 
53
59
  next if args_node.children.empty?
60
+
54
61
  if chained_send?(send_node)
55
62
  add_offense(return_node, :keyword)
56
63
  break
@@ -58,19 +65,20 @@ module RuboCop
58
65
  end
59
66
  end
60
67
 
61
- def return_value?(return_node)
62
- !return_node.children.empty?
63
- end
68
+ private
64
69
 
65
- def chained_send?(send_node)
66
- receiver_node, _selector_node = *send_node
67
- !receiver_node.nil?
70
+ def scoped_node?(node)
71
+ node.def_type? || node.defs_type? || node.lambda?
68
72
  end
69
73
 
70
- def define_method?(send_node)
71
- _receiver, selector = *send_node
72
- %i(define_method define_singleton_method).include? selector
74
+ def return_value?(return_node)
75
+ !return_node.children.empty?
73
76
  end
77
+
78
+ def_node_matcher :chained_send?, '(send !nil ...)'
79
+ def_node_matcher :define_method?, <<-PATTERN
80
+ (send _ {:define_method :define_singleton_method} _)
81
+ PATTERN
74
82
  end
75
83
  end
76
84
  end
@@ -21,23 +21,22 @@ module RuboCop
21
21
  MSG = '`(...)` interpreted as grouped expression.'.freeze
22
22
 
23
23
  def on_send(node)
24
- _receiver, method_name, *args = *node
25
- return unless args.one?
26
- return if operator?(method_name) || node.asgn_method_call?
24
+ return unless node.arguments.one?
25
+ return if node.operator_method? || node.setter_method?
27
26
 
28
- first_arg = args.first
29
- return unless first_arg.source.start_with?('(')
27
+ return unless node.first_argument.source.start_with?('(')
30
28
 
31
29
  space_length = spaces_before_left_parenthesis(node)
32
30
  return unless space_length > 0
33
31
 
34
- add_offense(nil, space_range(first_arg.source_range, space_length))
32
+ add_offense(nil, space_range(node.first_argument.source_range,
33
+ space_length))
35
34
  end
36
35
 
37
36
  private
38
37
 
39
38
  def spaces_before_left_parenthesis(node)
40
- receiver, method_name, _args = *node
39
+ receiver = node.receiver
41
40
  receiver_length = if receiver
42
41
  receiver.source.length
43
42
  else
@@ -46,7 +45,7 @@ module RuboCop
46
45
  without_receiver = node.source[receiver_length..-1]
47
46
 
48
47
  # Escape question mark if any.
49
- method_regexp = Regexp.escape(method_name)
48
+ method_regexp = Regexp.escape(node.method_name)
50
49
 
51
50
  match = without_receiver.match(/^\s*\.?\s*#{method_regexp}(\s+)\(/)
52
51
  match ? match.captures[0].length : 0
@@ -30,21 +30,19 @@ module RuboCop
30
30
  'precedence.'.freeze
31
31
 
32
32
  def on_send(node)
33
- _receiver, method_name, *args = *node
33
+ return if !node.arguments? || node.parenthesized?
34
34
 
35
- return if parentheses?(node) || args.empty?
36
-
37
- if args.first.if_type? && args.first.ternary?
38
- check_ternary(args.first, node)
39
- elsif method_name.to_s.end_with?('?')
40
- check_predicate(args.last, node)
35
+ if node.first_argument.if_type? && node.first_argument.ternary?
36
+ check_ternary(node.first_argument, node)
37
+ elsif node.predicate_method?
38
+ check_predicate(node.last_argument, node)
41
39
  end
42
40
  end
43
41
 
44
42
  private
45
43
 
46
44
  def check_ternary(ternary, node)
47
- return unless offense?(ternary.condition)
45
+ return unless ternary.condition.operator_keyword?
48
46
 
49
47
  range = range_between(node.source_range.begin_pos,
50
48
  ternary.condition.source_range.end_pos)
@@ -53,14 +51,10 @@ module RuboCop
53
51
  end
54
52
 
55
53
  def check_predicate(predicate, node)
56
- return unless offense?(predicate)
54
+ return unless predicate.operator_keyword?
57
55
 
58
56
  add_offense(node, :expression)
59
57
  end
60
-
61
- def offense?(node)
62
- [:and, :or].include?(node.type)
63
- end
64
58
  end
65
59
  end
66
60
  end
@@ -29,8 +29,6 @@ module RuboCop
29
29
  MSG = 'Do not chain ordinary method call' \
30
30
  ' after safe navigation operator.'.freeze
31
31
 
32
- ADDITIONAL_NIL_METHODS = %i(present? blank? try).freeze
33
-
34
32
  def_node_matcher :bad_method?, <<-PATTERN
35
33
  (send (csend ...) $_ ...)
36
34
  PATTERN
@@ -42,12 +40,14 @@ module RuboCop
42
40
  return if nil_methods.include?(method)
43
41
 
44
42
  loc = node.loc.dot || :selector
43
+
45
44
  add_offense(node, loc)
46
45
  end
47
46
  end
48
47
 
49
48
  def autocorrect(node)
50
49
  dot = node.loc.dot
50
+
51
51
  return unless dot
52
52
 
53
53
  lambda do |corrector|
@@ -58,7 +58,11 @@ module RuboCop
58
58
  private
59
59
 
60
60
  def nil_methods
61
- nil.methods + ADDITIONAL_NIL_METHODS
61
+ nil.methods + whitelist
62
+ end
63
+
64
+ def whitelist
65
+ cop_config['Whitelist'].map(&:to_sym)
62
66
  end
63
67
  end
64
68
  end
@@ -31,6 +31,8 @@ module RuboCop
31
31
  # handle_exception
32
32
  # end
33
33
  class ShadowedException < Cop
34
+ include RescueNode
35
+
34
36
  MSG = 'Do not shadow rescued Exceptions.'.freeze
35
37
 
36
38
  def on_rescue(node)
@@ -68,12 +70,6 @@ module RuboCop
68
70
  range_between(first_rescue.loc.expression.begin_pos, end_pos)
69
71
  end
70
72
 
71
- def rescue_modifier?(node)
72
- node && node.rescue_type? &&
73
- (node.parent.nil? || !(node.parent.kwbegin_type? ||
74
- node.parent.ensure_type?))
75
- end
76
-
77
73
  def contains_multiple_levels_of_exceptions?(group)
78
74
  if group.size > 1 && group.include?(Exception)
79
75
  # Treat `Exception` as the highest level exception unless `nil` was
@@ -25,21 +25,20 @@ module RuboCop
25
25
  def on_dstr(node)
26
26
  node.each_child_node(:begin) do |begin_node|
27
27
  final_node = begin_node.children.last
28
- next unless final_node && final_node.send_type?
29
28
 
30
- receiver, method_name, *args = *final_node
31
- next unless method_name == :to_s && args.empty?
29
+ next unless final_node && final_node.send_type? &&
30
+ final_node.method?(:to_s) && !final_node.arguments?
32
31
 
33
- add_offense(
34
- final_node,
35
- :selector,
36
- receiver ? MSG_DEFAULT : MSG_SELF
37
- )
32
+ add_offense(final_node, :selector)
38
33
  end
39
34
  end
40
35
 
41
36
  private
42
37
 
38
+ def message(node)
39
+ node.receiver ? MSG_DEFAULT : MSG_SELF
40
+ end
41
+
43
42
  def autocorrect(node)
44
43
  lambda do |corrector|
45
44
  receiver, _method_name, *_args = *node
@@ -70,7 +70,8 @@ module RuboCop
70
70
  range_with_surrounding_space(range, :right, false)
71
71
  end
72
72
 
73
- def each_unneeded_disable(cop_disabled_line_ranges, offenses, comments)
73
+ def each_unneeded_disable(cop_disabled_line_ranges, offenses, comments,
74
+ &block)
74
75
  disabled_ranges = cop_disabled_line_ranges[COP_NAME] || [0..0]
75
76
 
76
77
  cop_disabled_line_ranges.each do |cop, line_ranges|
@@ -78,16 +79,23 @@ module RuboCop
78
79
  yield comment, cop
79
80
  end
80
81
 
81
- line_ranges.each do |line_range|
82
- comment = comments.find { |c| c.loc.line == line_range.begin }
82
+ each_line_range(line_ranges, disabled_ranges, offenses, comments,
83
+ cop, &block)
84
+ end
85
+ end
83
86
 
84
- unless all_disabled?(comment)
85
- next if ignore_offense?(disabled_ranges, line_range)
86
- end
87
+ def each_line_range(line_ranges, disabled_ranges, offenses, comments,
88
+ cop)
89
+ line_ranges.each_with_index do |line_range, ix|
90
+ comment = comments.find { |c| c.loc.line == line_range.begin }
87
91
 
88
- unneeded_cop = find_unneeded(comment, offenses, cop, line_range)
89
- yield comment, unneeded_cop if unneeded_cop
92
+ unless all_disabled?(comment)
93
+ next if ignore_offense?(disabled_ranges, line_range)
90
94
  end
95
+
96
+ unneeded_cop = find_unneeded(comment, offenses, cop, line_range,
97
+ line_ranges[ix + 1])
98
+ yield comment, unneeded_cop if unneeded_cop
91
99
  end
92
100
  end
93
101
 
@@ -99,13 +107,29 @@ module RuboCop
99
107
  # the end of the previous range, it means that the cop was
100
108
  # already disabled by an earlier comment. So it's unneeded
101
109
  # whether there are offenses or not.
102
- yield comments.find { |c| c.loc.line == range.begin }
110
+ unneeded_comment = comments.find do |c|
111
+ c.loc.line == range.begin &&
112
+ # Comments disabling all cops don't count since it's reasonable
113
+ # to disable a few select cops first and then all cops further
114
+ # down in the code.
115
+ !all_disabled?(c)
116
+ end
117
+ yield unneeded_comment if unneeded_comment
103
118
  end
104
119
  end
105
120
 
106
- def find_unneeded(comment, offenses, cop, line_range)
121
+ def find_unneeded(comment, offenses, cop, line_range, next_line_range)
107
122
  if all_disabled?(comment)
108
- 'all' if offenses.none? { |o| line_range.cover?(o.line) }
123
+ # If there's a disable all comment followed by a comment
124
+ # specifically disabling `cop`, we don't report the `all`
125
+ # comment. If the disable all comment is truly unneeded, we will
126
+ # detect that when examining the comments of another cop, and we
127
+ # get the full line range for the disable all.
128
+ if (next_line_range.nil? ||
129
+ line_range.last != next_line_range.first) &&
130
+ offenses.none? { |o| line_range.cover?(o.line) }
131
+ 'all'
132
+ end
109
133
  else
110
134
  cop_offenses = offenses.select { |o| o.cop_name == cop }
111
135
  cop if cop_offenses.none? { |o| line_range.cover?(o.line) }