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
@@ -30,19 +30,23 @@ module RuboCop
30
30
  METHOD_PATTERN = /^find_by_(.+?)(!)?$/
31
31
 
32
32
  def on_send(node)
33
- _receiver, method, _args = *node
34
- method_name = method.to_s
33
+ method_name = node.method_name.to_s
34
+
35
35
  return if whitelist.include?(method_name)
36
+
36
37
  static_name = static_method_name(method_name)
38
+
37
39
  return unless static_name
38
40
 
39
- add_offense(node, :expression, format(MSG, static_name, method))
41
+ add_offense(node, :expression,
42
+ format(MSG, static_name, node.method_name))
40
43
  end
41
44
 
42
45
  def autocorrect(node)
43
46
  _receiver, method, *args = *node
44
47
  static_name = static_method_name(method.to_s)
45
48
  keywords = column_keywords(method)
49
+
46
50
  return if keywords.size != args.size
47
51
 
48
52
  lambda do |corrector|
@@ -20,8 +20,8 @@ module RuboCop
20
20
  include ConfigurableEnforcedStyle
21
21
 
22
22
  MSG = 'Do not use `exit` in Rails applications.'.freeze
23
- TARGET_METHODS = [:exit, :exit!].freeze
24
- EXPLICIT_RECEIVERS = [:Kernel, :Process].freeze
23
+ TARGET_METHODS = %i(exit exit!).freeze
24
+ EXPLICIT_RECEIVERS = %i(Kernel Process).freeze
25
25
 
26
26
  def on_send(node)
27
27
  add_offense(node, :selector) if offending_node?(node)
@@ -30,11 +30,9 @@ module RuboCop
30
30
  private
31
31
 
32
32
  def offending_node?(node)
33
- receiver_node, method_name, *arg_nodes = *node
34
-
35
- right_method_name?(method_name) &&
36
- right_argument_count?(arg_nodes) &&
37
- right_receiver?(receiver_node)
33
+ right_method_name?(node.method_name) &&
34
+ right_argument_count?(node.arguments) &&
35
+ right_receiver?(node.receiver)
38
36
  end
39
37
 
40
38
  def right_method_name?(method_name)
@@ -44,15 +42,17 @@ module RuboCop
44
42
  # More than 1 argument likely means it is a different
45
43
  # `exit` implementation than the one we are preventing.
46
44
  def right_argument_count?(arg_nodes)
47
- arg_nodes.length <= 1
45
+ arg_nodes.size <= 1
48
46
  end
49
47
 
50
48
  # Only register if exit is being called explicitly on
51
49
  # Kernel or Process or if receiver node is nil for plain
52
50
  # `exit` calls.
53
51
  def right_receiver?(receiver_node)
54
- return true if receiver_node.nil?
52
+ return true unless receiver_node
53
+
55
54
  _a, receiver_node_class, _c = *receiver_node
55
+
56
56
  EXPLICIT_RECEIVERS.include?(receiver_node_class)
57
57
  end
58
58
  end
@@ -17,11 +17,7 @@ module RuboCop
17
17
  class FilePath < Cop
18
18
  MSG = 'Please use `Rails.root.join(\'path\', \'to\')` instead.'.freeze
19
19
 
20
- def_node_search :file_join_nodes, <<-PATTERN
21
- (send (const nil :File) :join ...)
22
- PATTERN
23
-
24
- def_node_search :file_join_nodes?, <<-PATTERN
20
+ def_node_matcher :file_join_nodes?, <<-PATTERN
25
21
  (send (const nil :File) :join ...)
26
22
  PATTERN
27
23
 
@@ -29,7 +25,7 @@ module RuboCop
29
25
  (send (const nil :Rails) :root)
30
26
  PATTERN
31
27
 
32
- def_node_search :rails_root_join_nodes, <<-PATTERN
28
+ def_node_matcher :rails_root_join_nodes?, <<-PATTERN
33
29
  (send (send (const nil :Rails) :root) :join ...)
34
30
  PATTERN
35
31
 
@@ -47,20 +43,15 @@ module RuboCop
47
43
 
48
44
  def check_for_file_join_with_rails_root(node)
49
45
  return unless file_join_nodes?(node)
50
- return unless file_join_nodes(node).map(&:method_args)
51
- .flatten
52
- .any? { |e| rails_root_nodes?(e) }
46
+ return unless node.method_args.any? { |e| rails_root_nodes?(e) }
53
47
 
54
48
  register_offense(node)
55
49
  end
56
50
 
57
51
  def check_for_rails_root_join_with_slash_separated_path(node)
58
52
  return unless rails_root_nodes?(node)
59
- return unless rails_root_join_nodes(node).map(&:method_args)
60
- .flatten
61
- .any? do |arg|
62
- arg.source =~ %r{/}
63
- end
53
+ return unless rails_root_join_nodes?(node)
54
+ return unless node.method_args.any? { |arg| arg.source =~ %r{/} }
64
55
 
65
56
  register_offense(node)
66
57
  end
@@ -15,30 +15,28 @@ module RuboCop
15
15
  # User.find_by(name: 'Bruce')
16
16
  class FindBy < Cop
17
17
  MSG = 'Use `find_by` instead of `where.%s`.'.freeze
18
- TARGET_SELECTORS = [:first, :take].freeze
18
+ TARGET_SELECTORS = %i(first take).freeze
19
19
 
20
- def_node_matcher :where_first, <<-PATTERN
21
- (send $(send _ :where ...) ${:first :take})
20
+ def_node_matcher :where_first?, <<-PATTERN
21
+ (send (send _ :where ...) {:first :take})
22
22
  PATTERN
23
23
 
24
24
  def on_send(node)
25
- return unless (recv_and_method = where_first(node))
26
- receiver, second_method = *recv_and_method
25
+ return unless where_first?(node)
27
26
 
28
- range = range_between(receiver.loc.selector.begin_pos,
27
+ range = range_between(node.receiver.loc.selector.begin_pos,
29
28
  node.loc.selector.end_pos)
30
29
 
31
- add_offense(node, range, format(MSG, second_method))
30
+ add_offense(node, range, format(MSG, node.method_name))
32
31
  end
33
32
 
34
33
  def autocorrect(node)
35
- receiver, second_method = where_first(node)
36
34
  # Don't autocorrect where(...).first, because it can return different
37
35
  # results from find_by. (They order records differently, so the
38
36
  # 'first' record can be different.)
39
- return if second_method == :first
37
+ return if node.method?(:first)
40
38
 
41
- where_loc = receiver.loc.selector
39
+ where_loc = node.receiver.loc.selector
42
40
  first_loc = range_between(node.loc.dot.begin_pos,
43
41
  node.loc.selector.end_pos)
44
42
 
@@ -15,23 +15,20 @@ module RuboCop
15
15
  class FindEach < Cop
16
16
  MSG = 'Use `find_each` instead of `each`.'.freeze
17
17
 
18
- SCOPE_METHODS = [:all, :where, :not].freeze
18
+ SCOPE_METHODS = %i(all where not).freeze
19
+ IGNORED_METHODS = %i(order limit select).freeze
19
20
 
20
21
  def on_send(node)
21
- receiver, method, _selector = *node
22
- return unless receiver && method == :each
22
+ return unless node.receiver && node.method?(:each)
23
23
 
24
- _model, preceding_method = *receiver
25
- return unless SCOPE_METHODS.include?(preceding_method)
24
+ return unless SCOPE_METHODS.include?(node.receiver.method_name)
26
25
  return if method_chain(node).any? { |m| ignored_by_find_each?(m) }
27
26
 
28
27
  add_offense(node, node.loc.selector, MSG)
29
28
  end
30
29
 
31
30
  def autocorrect(node)
32
- each_loc = node.loc.selector
33
-
34
- ->(corrector) { corrector.replace(each_loc, 'find_each') }
31
+ ->(corrector) { corrector.replace(node.loc.selector, 'find_each') }
35
32
  end
36
33
 
37
34
  private
@@ -42,7 +39,7 @@ module RuboCop
42
39
 
43
40
  def ignored_by_find_each?(relation_method)
44
41
  # Active Record's #find_each ignores various extra parameters
45
- [:order, :limit, :select].include?(relation_method)
42
+ IGNORED_METHODS.include?(relation_method)
46
43
  end
47
44
  end
48
45
  end
@@ -9,6 +9,7 @@ module RuboCop
9
9
 
10
10
  def on_send(node)
11
11
  return unless node.command?(:has_and_belongs_to_many)
12
+
12
13
  add_offense(node, :selector)
13
14
  end
14
15
  end
@@ -5,7 +5,10 @@ module RuboCop
5
5
  module Rails
6
6
  # This cop is used to identify usages of http methods like `get`, `post`,
7
7
  # `put`, `patch` without the usage of keyword arguments in your tests and
8
- # change them to use keyword arguments.
8
+ # change them to use keyword args. This cop only applies to Rails >= 5 .
9
+ # If you are not running Rails < 5 you should disable # the
10
+ # Rails/HttpPositionalArguments cop or set your TargetRailsVersion in your
11
+ # .rubocop.yml file to 4.0, etc.
9
12
  #
10
13
  # @example
11
14
  # # bad
@@ -14,12 +17,16 @@ module RuboCop
14
17
  # # good
15
18
  # get :new, params: { user_id: 1 }
16
19
  class HttpPositionalArguments < Cop
20
+ extend TargetRailsVersion
21
+
17
22
  MSG = 'Use keyword arguments instead of ' \
18
23
  'positional arguments for http call: `%s`.'.freeze
19
- KEYWORD_ARGS = [
20
- :headers, :env, :params, :body, :flash, :as, :xhr, :session, :method
21
- ].freeze
22
- HTTP_METHODS = [:get, :post, :put, :patch, :delete, :head].freeze
24
+ KEYWORD_ARGS = %i(
25
+ headers env params body flash as xhr session method
26
+ ).freeze
27
+ HTTP_METHODS = %i(get post put patch delete head).freeze
28
+
29
+ minimum_target_rails_version 5.0
23
30
 
24
31
  def_node_matcher :http_request?, <<-END
25
32
  (send nil {#{HTTP_METHODS.map(&:inspect).join(' ')}} !nil $_data ...)
@@ -80,7 +87,8 @@ module RuboCop
80
87
  # the data is the http parameters and environment sent in
81
88
  # the Rails 5 http call
82
89
  def autocorrect(node)
83
- _receiver, http_method, http_path, *data = *node
90
+ http_path, *data = *node.arguments
91
+
84
92
  controller_action = http_path.source
85
93
  params = convert_hash_data(data.first, 'params')
86
94
  headers = convert_hash_data(data.last, 'headers') if data.size > 1
@@ -88,7 +96,7 @@ module RuboCop
88
96
  code_to_replace = node.loc.expression
89
97
  # what to replace with
90
98
  format = parentheses?(node) ? '%s(%s%s%s)' : '%s %s%s%s'
91
- new_code = format(format, http_method, controller_action,
99
+ new_code = format(format, node.method_name, controller_action,
92
100
  params, headers)
93
101
  ->(corrector) { corrector.replace(code_to_replace, new_code) }
94
102
  end
@@ -9,15 +9,13 @@ module RuboCop
9
9
  "Use Rails's logger if you want to log.".freeze
10
10
 
11
11
  def_node_matcher :output?, <<-PATTERN
12
- (send nil {:ap :p :pp :pretty_print :print :puts} $...)
12
+ (send nil {:ap :p :pp :pretty_print :print :puts} ...)
13
13
  PATTERN
14
14
 
15
15
  def on_send(node)
16
- output?(node) do |args|
17
- return if args.empty?
16
+ return unless output?(node) && node.arguments?
18
17
 
19
- add_offense(node, :selector)
20
- end
18
+ add_offense(node, :selector)
21
19
  end
22
20
  end
23
21
  end
@@ -30,8 +30,8 @@ module RuboCop
30
30
  'prefer `safe_join` or other Rails tag helpers instead.'.freeze
31
31
 
32
32
  def on_send(node)
33
- _receiver, method_name, *_args = *node
34
- ignore_node(node) if method_name == :safe_join
33
+ ignore_node(node) if node.method?(:safe_join)
34
+
35
35
  return unless !part_of_ignored_node?(node) &&
36
36
  (looks_like_rails_html_safe?(node) ||
37
37
  looks_like_rails_raw?(node))
@@ -42,15 +42,11 @@ module RuboCop
42
42
  private
43
43
 
44
44
  def looks_like_rails_html_safe?(node)
45
- receiver, method_name, *args = *node
46
-
47
- receiver && method_name == :html_safe && args.empty?
45
+ node.receiver && node.method?(:html_safe) && !node.arguments?
48
46
  end
49
47
 
50
48
  def looks_like_rails_raw?(node)
51
- receiver, method_name, *args = *node
52
-
53
- receiver.nil? && method_name == :raw && args.one?
49
+ node.command?(:raw) && node.arguments.one?
54
50
  end
55
51
  end
56
52
  end
@@ -29,42 +29,43 @@ module RuboCop
29
29
  MSG = 'Prefer `%s.%s`.'.freeze
30
30
 
31
31
  def on_send(node)
32
- receiver, method_name, *_args = *node
33
- return unless duration_method?(method_name)
34
- return unless literal_number?(receiver)
35
-
36
- number, = *receiver
37
- if expect_singular_method?(number, method_name)
38
- add_offense(node,
39
- :expression,
40
- format(MSG, number, singularize(method_name)))
41
- elsif expect_plural_method?(number, method_name)
42
- add_offense(node,
43
- :expression,
44
- format(MSG, number, pluralize(method_name)))
45
- end
32
+ return unless duration_method?(node.method_name)
33
+ return unless literal_number?(node.receiver)
34
+
35
+ return unless offense?(node)
36
+
37
+ add_offense(node, :expression)
46
38
  end
47
39
 
48
40
  private
49
41
 
42
+ def message(node)
43
+ number, = *node.receiver
44
+
45
+ format(MSG, number, correct_method(node.method_name.to_s))
46
+ end
47
+
50
48
  def autocorrect(node)
51
49
  lambda do |corrector|
52
50
  method_name = node.loc.selector.source
53
- replacement = if plural_method?(method_name)
54
- singularize(method_name)
55
- else
56
- pluralize(method_name)
57
- end
58
- corrector.replace(node.loc.selector, replacement)
51
+
52
+ corrector.replace(node.loc.selector, correct_method(method_name))
59
53
  end
60
54
  end
61
55
 
62
- def expect_singular_method?(number, method_name)
63
- singular_receiver?(number) && plural_method?(method_name)
56
+ def correct_method(method_name)
57
+ if plural_method?(method_name)
58
+ singularize(method_name)
59
+ else
60
+ pluralize(method_name)
61
+ end
64
62
  end
65
63
 
66
- def expect_plural_method?(number, method_name)
67
- plural_receiver?(number) && singular_method?(method_name)
64
+ def offense?(node)
65
+ number, = *node.receiver
66
+
67
+ singular_receiver?(number) && plural_method?(node.method_name) ||
68
+ plural_receiver?(number) && singular_method?(node.method_name)
68
69
  end
69
70
 
70
71
  def plural_method?(method_name)
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # This cops checks for code that can be changed to `blank?`.
7
+ # Settings:
8
+ # NotNilAndNotEmpty: Convert checks for not `nil` and `not empty?`
9
+ # to `present?`
10
+ # NotBlank: Convert usages of not `blank?` to `present?`
11
+ # UnlessBlank: Convert usages of `unless` `blank?` to `if` `present?`
12
+ #
13
+ # @example
14
+ # # NotNilAndNotEmpty: true
15
+ # # bad
16
+ # !foo.nil? && !foo.empty?
17
+ # foo != nil && !foo.empty?
18
+ # !foo.blank?
19
+ #
20
+ # # good
21
+ # foo.present?
22
+ #
23
+ # # NotBlank: true
24
+ # # bad
25
+ # !foo.blank?
26
+ # not foo.blank?
27
+ #
28
+ # # good
29
+ # foo.present?
30
+ #
31
+ # # UnlessBlank: true
32
+ # # bad
33
+ # something unless foo.blank?
34
+ #
35
+ # # good
36
+ # something if foo.present?
37
+ class Present < Cop
38
+ MSG_NOT_BLANK = 'Use `%s.present?` instead of `%s`.'.freeze
39
+ MSG_EXISTS_AND_NOT_EMPTY = 'Use `%s.present?` instead of `%s`.'.freeze
40
+ MSG_UNLESS_BLANK = 'Use `if %s.present?` instead of `%s`.'.freeze
41
+
42
+ def_node_matcher :exists_and_not_empty?, <<-PATTERN
43
+ (and
44
+ {
45
+ (send (send $_ :nil?) :!)
46
+ (send (send $_ :!) :!)
47
+ (send $_ :!= (:nil))
48
+ $_
49
+ }
50
+ {
51
+ (send (send $_ :empty?) :!)
52
+ }
53
+ )
54
+ PATTERN
55
+
56
+ def_node_matcher :not_blank?, '(send (send $_ :blank?) :!)'
57
+
58
+ def_node_matcher :unless_blank?, <<-PATTERN
59
+ (:if $(send $_ :blank?) {nil (...)} ...)
60
+ PATTERN
61
+
62
+ def on_send(node)
63
+ return unless cop_config['NotBlank']
64
+
65
+ not_blank?(node) do |receiver|
66
+ add_offense(node,
67
+ :expression,
68
+ format(MSG_NOT_BLANK, receiver.source, node.source))
69
+ end
70
+ end
71
+
72
+ def on_and(node)
73
+ return unless cop_config['NotNilAndNotEmpty']
74
+
75
+ exists_and_not_empty?(node) do |variable1, variable2|
76
+ return unless variable1 == variable2
77
+
78
+ add_offense(node,
79
+ :expression,
80
+ format(MSG_EXISTS_AND_NOT_EMPTY,
81
+ variable1.source,
82
+ node.source))
83
+ end
84
+ end
85
+
86
+ def on_or(node)
87
+ return unless cop_config['NilOrEmpty']
88
+
89
+ exists_and_not_empty?(node) do |variable1, variable2|
90
+ return unless variable1 == variable2
91
+
92
+ add_offense(node, :expression, MSG_EXISTS_AND_NOT_EMPTY)
93
+ end
94
+ end
95
+
96
+ def on_if(node)
97
+ return unless cop_config['UnlessBlank']
98
+ return unless node.unless?
99
+
100
+ unless_blank?(node) do |method_call, receiver|
101
+ range = unless_condition(node, method_call)
102
+ add_offense(node,
103
+ range,
104
+ format(MSG_UNLESS_BLANK, receiver.source, range.source))
105
+ end
106
+ end
107
+
108
+ def autocorrect(node)
109
+ lambda do |corrector|
110
+ method_call, variable1 = unless_blank?(node)
111
+
112
+ if method_call && variable1
113
+ corrector.replace(node.loc.keyword, 'if')
114
+ range = method_call.loc.expression
115
+ else
116
+ variable1, _variable2 =
117
+ exists_and_not_empty?(node) || not_blank?(node)
118
+ range = node.loc.expression
119
+ end
120
+
121
+ corrector.replace(range, "#{variable1.source}.present?")
122
+ end
123
+ end
124
+
125
+ private
126
+
127
+ def unless_condition(node, method_call)
128
+ if node.modifier_form?
129
+ node.loc.keyword.join(node.loc.expression.end)
130
+ else
131
+ node.loc.expression.begin.join(method_call.loc.expression)
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end