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
@@ -45,11 +45,11 @@ module RuboCop
45
45
  def autocorrect(node)
46
46
  send_node = node.send_type? ? node : node.each_descendant(:send).first
47
47
 
48
- receiver, _method_name, *args = *send_node
49
- count, = *receiver
48
+ count, = *send_node.receiver
50
49
 
51
- replacement = "Array.new(#{count.source}" \
52
- "#{args.map { |arg| ", #{arg.source}" }.join})"
50
+ replacement =
51
+ "Array.new(#{count.source}" \
52
+ "#{send_node.arguments.map { |arg| ", #{arg.source}" }.join})"
53
53
 
54
54
  lambda do |corrector|
55
55
  corrector.replace(send_node.loc.expression, replacement)
@@ -7,42 +7,48 @@ module RuboCop
7
7
  #
8
8
  # The cop is configurable and can enforce the use of the older
9
9
  # something_filter methods or the newer something_action methods.
10
+ #
11
+ # If the TargetRailsVersion is set to less than 4.0, the cop will enforce
12
+ # the use of filter methods.
10
13
  class ActionFilter < Cop
14
+ extend TargetRailsVersion
11
15
  include ConfigurableEnforcedStyle
12
16
 
13
17
  MSG = 'Prefer `%s` over `%s`.'.freeze
14
18
 
15
- FILTER_METHODS = [
16
- :after_filter,
17
- :append_after_filter,
18
- :append_around_filter,
19
- :append_before_filter,
20
- :around_filter,
21
- :before_filter,
22
- :prepend_after_filter,
23
- :prepend_around_filter,
24
- :prepend_before_filter,
25
- :skip_after_filter,
26
- :skip_around_filter,
27
- :skip_before_filter,
28
- :skip_filter
29
- ].freeze
30
-
31
- ACTION_METHODS = [
32
- :after_action,
33
- :append_after_action,
34
- :append_around_action,
35
- :append_before_action,
36
- :around_action,
37
- :before_action,
38
- :prepend_after_action,
39
- :prepend_around_action,
40
- :prepend_before_action,
41
- :skip_after_action,
42
- :skip_around_action,
43
- :skip_before_action,
44
- :skip_action_callback
45
- ].freeze
19
+ FILTER_METHODS = %i(
20
+ after_filter
21
+ append_after_filter
22
+ append_around_filter
23
+ append_before_filter
24
+ around_filter
25
+ before_filter
26
+ prepend_after_filter
27
+ prepend_around_filter
28
+ prepend_before_filter
29
+ skip_after_filter
30
+ skip_around_filter
31
+ skip_before_filter
32
+ skip_filter
33
+ ).freeze
34
+
35
+ ACTION_METHODS = %i(
36
+ after_action
37
+ append_after_action
38
+ append_around_action
39
+ append_before_action
40
+ around_action
41
+ before_action
42
+ prepend_after_action
43
+ prepend_around_action
44
+ prepend_before_action
45
+ skip_after_action
46
+ skip_around_action
47
+ skip_before_action
48
+ skip_action_callback
49
+ ).freeze
50
+
51
+ minimum_target_rails_version 4.0
46
52
 
47
53
  def on_block(node)
48
54
  method, _args, _body = *node
@@ -51,9 +57,7 @@ module RuboCop
51
57
  end
52
58
 
53
59
  def on_send(node)
54
- receiver, _method_name, *_args = *node
55
-
56
- check_method_node(node) if receiver.nil?
60
+ check_method_node(node) unless node.receiver
57
61
  end
58
62
 
59
63
  def autocorrect(node)
@@ -66,17 +70,13 @@ module RuboCop
66
70
  private
67
71
 
68
72
  def check_method_node(node)
69
- _receiver, method_name, *_args = *node
70
- return unless offending_method?(method_name)
73
+ return unless bad_methods.include?(node.method_name)
71
74
 
72
- add_offense(node, :selector,
73
- format(MSG,
74
- preferred_method(method_name),
75
- method_name))
75
+ add_offense(node, :selector)
76
76
  end
77
77
 
78
- def offending_method?(method_name)
79
- bad_methods.include?(method_name)
78
+ def message(node)
79
+ format(MSG, preferred_method(node.method_name), node.method_name)
80
80
  end
81
81
 
82
82
  def bad_methods
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # This cop checks that ActiveSupport aliases to core ruby methods
7
+ # are not used.
8
+ #
9
+ # @example
10
+ # # good
11
+ # 'some_string'.start_with?('prefix')
12
+ # 'some_string'.end_with?('suffix')
13
+ # [1, 2, 'a'] << 'b'
14
+ # [1, 2, 'a'].unshift('b')
15
+ #
16
+ # # bad
17
+ # 'some_string'.starts_with?('prefix')
18
+ # 'some_string'.ends_with?('suffix')
19
+ # [1, 2, 'a'].append('b')
20
+ # [1, 2, 'a'].prepend('b')
21
+ #
22
+ class ActiveSupportAliases < Cop
23
+ MSG = 'Use `%s` instead of `%s`.'.freeze
24
+
25
+ ALIASES = {
26
+ starts_with?: {
27
+ original: :start_with?, matcher: '(send str :starts_with? _)'
28
+ },
29
+ ends_with?: {
30
+ original: :end_with?, matcher: '(send str :ends_with? _)'
31
+ },
32
+ append: { original: :<<, matcher: '(send array :append _)' },
33
+ prepend: { original: :unshift, matcher: '(send array :prepend _)' }
34
+ }.freeze
35
+
36
+ ALIASES.each do |aliased_method, options|
37
+ def_node_matcher aliased_method, options[:matcher]
38
+ end
39
+
40
+ def on_send(node)
41
+ ALIASES.keys.each do |aliased_method|
42
+ register_offense(node, aliased_method) if
43
+ public_send(aliased_method, node)
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def autocorrect(node)
50
+ return false if append(node)
51
+ lambda do |corrector|
52
+ method_name = node.loc.selector.source
53
+ replacement = ALIASES[method_name.to_sym][:original]
54
+ corrector.replace(node.loc.selector, replacement.to_s)
55
+ end
56
+ end
57
+
58
+ def register_offense(node, method_name)
59
+ add_offense(
60
+ node,
61
+ :expression,
62
+ format(MSG, ALIASES[method_name][:original], method_name)
63
+ )
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,131 @@
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
+ # NilOrEmpty: Convert checks for `nil` or `empty?` to `blank?`
9
+ # NotPresent: Convert usages of not `present?` to `blank?`
10
+ # UnlessPresent: Convert usages of `unless` `present?` to `blank?`
11
+ #
12
+ # @example
13
+ # # NilOrEmpty: true
14
+ # # bad
15
+ # foo.nil? || foo.empty?
16
+ # foo == nil || foo.empty?
17
+ #
18
+ # # good
19
+ # foo.blank?
20
+ #
21
+ # # NotPresent: true
22
+ # # bad
23
+ # !foo.present?
24
+ #
25
+ # # good
26
+ # foo.blank?
27
+ #
28
+ # # UnlessPresent: true
29
+ # # bad
30
+ # something unless foo.present?
31
+ # unless foo.present?
32
+ # something
33
+ # end
34
+ #
35
+ # # good
36
+ # something if foo.blank?
37
+ # if foo.blank?
38
+ # something
39
+ # end
40
+ class Blank < Cop
41
+ MSG_NIL_OR_EMPTY = 'Use `%s.blank?` instead of `%s`.'.freeze
42
+ MSG_NOT_PRESENT = 'Use `%s.blank?` instead of `%s`.'.freeze
43
+ MSG_UNLESS_PRESENT = 'Use `if %s.blank?` instead of `%s`.'.freeze
44
+
45
+ def_node_matcher :nil_or_empty?, <<-PATTERN
46
+ (or
47
+ {
48
+ (send $_ :!)
49
+ (send $_ :nil?)
50
+ (send $_ :== (:nil))
51
+ (send (:nil) :== $_)
52
+ }
53
+ {
54
+ (send $_ :empty?)
55
+ (send (send (send $_ :empty?) :!) :!)
56
+ }
57
+ )
58
+ PATTERN
59
+
60
+ def_node_matcher :not_present?, '(send (send $_ :present?) :!)'
61
+
62
+ def_node_matcher :unless_present?, <<-PATTERN
63
+ (:if $(send $_ :present?) {nil (...)} ...)
64
+ PATTERN
65
+
66
+ def on_send(node)
67
+ return unless cop_config['NotPresent']
68
+
69
+ not_present?(node) do |receiver|
70
+ add_offense(node,
71
+ :expression,
72
+ format(MSG_NOT_PRESENT, receiver.source, node.source))
73
+ end
74
+ end
75
+
76
+ def on_or(node)
77
+ return unless cop_config['NilOrEmpty']
78
+
79
+ nil_or_empty?(node) do |variable1, variable2|
80
+ return unless variable1 == variable2
81
+
82
+ add_offense(node,
83
+ :expression,
84
+ format(MSG_NIL_OR_EMPTY, variable1.source, node.source))
85
+ end
86
+ end
87
+
88
+ def on_if(node)
89
+ return unless cop_config['UnlessPresent']
90
+ return unless node.unless?
91
+
92
+ unless_present?(node) do |method_call, receiver|
93
+ range = unless_condition(node, method_call)
94
+
95
+ add_offense(node,
96
+ range,
97
+ format(MSG_UNLESS_PRESENT,
98
+ receiver.source,
99
+ range.source))
100
+ end
101
+ end
102
+
103
+ def autocorrect(node)
104
+ lambda do |corrector|
105
+ method_call, variable1 = unless_present?(node)
106
+
107
+ if method_call && variable1
108
+ corrector.replace(node.loc.keyword, 'if')
109
+ range = method_call.loc.expression
110
+ else
111
+ variable1, _variable2 = nil_or_empty?(node) || not_present?(node)
112
+ range = node.loc.expression
113
+ end
114
+
115
+ corrector.replace(range, "#{variable1.source}.blank?")
116
+ end
117
+ end
118
+
119
+ private
120
+
121
+ def unless_condition(node, method_call)
122
+ if node.modifier_form?
123
+ node.loc.keyword.join(node.loc.expression.end)
124
+ else
125
+ node.loc.expression.begin.join(method_call.loc.expression)
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
@@ -25,7 +25,7 @@ module RuboCop
25
25
  # Time.zone.today
26
26
  # Time.zone.today - 1.day
27
27
  #
28
- # # acceptable
28
+ # # flexible
29
29
  # Date.current
30
30
  # Date.yesterday
31
31
  #
@@ -43,7 +43,7 @@ module RuboCop
43
43
  MSG_SEND = 'Do not use `%s` on Date objects, because they ' \
44
44
  'know nothing about the time zone in use.'.freeze
45
45
 
46
- BAD_DAYS = [:today, :current, :yesterday, :tomorrow].freeze
46
+ BAD_DAYS = %i(today current yesterday tomorrow).freeze
47
47
 
48
48
  def on_const(node)
49
49
  mod, klass = *node.children
@@ -54,23 +54,18 @@ module RuboCop
54
54
  end
55
55
 
56
56
  def on_send(node)
57
- receiver, method_name, *args = *node
58
- return unless receiver && bad_methods.include?(method_name)
57
+ return unless node.receiver && bad_methods.include?(node.method_name)
59
58
 
60
- chain = extract_method_chain(node)
61
- return if safe_chain?(chain)
62
-
63
- return if method_name == :to_time && args.length == 1
59
+ return if safe_chain?(node) || safe_to_time?(node)
64
60
 
65
- add_offense(node, :selector,
66
- format(MSG_SEND,
67
- method_name))
61
+ add_offense(node, :selector, format(MSG_SEND, node.method_name))
68
62
  end
69
63
 
70
64
  private
71
65
 
72
66
  def check_date_node(node)
73
67
  chain = extract_method_chain(node)
68
+
74
69
  return if (chain & bad_days).empty?
75
70
 
76
71
  method_name = (chain & bad_days).join('.')
@@ -82,17 +77,7 @@ module RuboCop
82
77
  end
83
78
 
84
79
  def extract_method_chain(node)
85
- chain = []
86
- while !node.nil? && node.send_type?
87
- chain << extract_method(node)
88
- node = node.parent
89
- end
90
- chain
91
- end
92
-
93
- def extract_method(node)
94
- _receiver, method_name, *_args = *node
95
- method_name
80
+ [node, *node.each_ancestor(:send)].map(&:method_name)
96
81
  end
97
82
 
98
83
  # checks that parent node of send_type
@@ -100,17 +85,29 @@ module RuboCop
100
85
  def method_send?(node)
101
86
  return false unless node.parent && node.parent.send_type?
102
87
 
103
- receiver, _method_name, *_args = *node.parent
104
-
105
- receiver == node
88
+ node.parent.receiver == node
106
89
  end
107
90
 
108
- def safe_chain?(chain)
91
+ def safe_chain?(node)
92
+ chain = extract_method_chain(node)
93
+
109
94
  (chain & bad_methods).empty? || !(chain & good_methods).empty?
110
95
  end
111
96
 
97
+ def safe_to_time?(node)
98
+ return unless node.method?(:to_time)
99
+
100
+ if node.receiver.str_type?
101
+ zone_regexp = /[+-][\d:]+\z/
102
+
103
+ node.receiver.str_content.match(zone_regexp)
104
+ else
105
+ node.arguments.one?
106
+ end
107
+ end
108
+
112
109
  def good_days
113
- style == :strict ? [] : [:current, :yesterday, :tomorrow]
110
+ style == :strict ? [] : %i(current yesterday tomorrow)
114
111
  end
115
112
 
116
113
  def bad_days
@@ -118,7 +115,7 @@ module RuboCop
118
115
  end
119
116
 
120
117
  def bad_methods
121
- style == :strict ? [:to_time, :to_time_in_current_zone] : [:to_time]
118
+ style == :strict ? %i(to_time to_time_in_current_zone) : [:to_time]
122
119
  end
123
120
 
124
121
  def good_methods
@@ -16,7 +16,7 @@ module RuboCop
16
16
  class DelegateAllowBlank < Cop
17
17
  MSG = '`allow_blank` is not a valid option, use `allow_nil`.'.freeze
18
18
 
19
- def_node_matcher :delegate, <<-PATTERN
19
+ def_node_matcher :delegate_options, <<-PATTERN
20
20
  (send nil :delegate _ $hash)
21
21
  PATTERN
22
22
 
@@ -29,7 +29,7 @@ module RuboCop
29
29
 
30
30
  return unless offending_node
31
31
 
32
- add_offense(offending_node, :expression, MSG)
32
+ add_offense(offending_node, :expression)
33
33
  end
34
34
 
35
35
  private
@@ -41,11 +41,9 @@ module RuboCop
41
41
  end
42
42
 
43
43
  def allow_blank_option(node)
44
- options_hash = delegate(node)
45
-
46
- return unless options_hash
47
-
48
- options_hash.pairs.find { |opt| allow_blank_option?(opt) }
44
+ delegate_options(node) do |hash|
45
+ hash.pairs.find { |opt| allow_blank_option?(opt) }
46
+ end
49
47
  end
50
48
  end
51
49
  end