rubocop 0.90.0 → 0.93.1

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.
Files changed (201) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/config/default.yml +79 -3
  4. data/lib/rubocop.rb +20 -5
  5. data/lib/rubocop/cached_data.rb +2 -1
  6. data/lib/rubocop/cli/command/execute_runner.rb +8 -0
  7. data/lib/rubocop/comment_config.rb +9 -5
  8. data/lib/rubocop/config_loader.rb +3 -3
  9. data/lib/rubocop/config_regeneration.rb +33 -0
  10. data/lib/rubocop/config_store.rb +3 -3
  11. data/lib/rubocop/cop/bundler/duplicated_gem.rb +5 -1
  12. data/lib/rubocop/cop/bundler/gem_comment.rb +1 -0
  13. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +2 -0
  14. data/lib/rubocop/cop/correctors/line_break_corrector.rb +2 -2
  15. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +10 -10
  16. data/lib/rubocop/cop/generator.rb +1 -1
  17. data/lib/rubocop/cop/internal_affairs/method_name_equal.rb +1 -0
  18. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +1 -0
  19. data/lib/rubocop/cop/internal_affairs/offense_location_keyword.rb +1 -0
  20. data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +1 -0
  21. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +1 -0
  22. data/lib/rubocop/cop/layout/array_alignment.rb +1 -0
  23. data/lib/rubocop/cop/layout/begin_end_alignment.rb +77 -0
  24. data/lib/rubocop/cop/layout/case_indentation.rb +4 -7
  25. data/lib/rubocop/cop/layout/class_structure.rb +1 -1
  26. data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
  27. data/lib/rubocop/cop/layout/dot_position.rb +6 -9
  28. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +2 -2
  29. data/lib/rubocop/cop/layout/empty_line_after_multiline_condition.rb +4 -12
  30. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +13 -8
  31. data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +2 -2
  32. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +1 -2
  33. data/lib/rubocop/cop/layout/end_alignment.rb +5 -10
  34. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +26 -4
  35. data/lib/rubocop/cop/layout/space_around_equals_in_parameter_default.rb +4 -13
  36. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +7 -7
  37. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +0 -4
  38. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +6 -21
  39. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +3 -8
  40. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +2 -2
  41. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +2 -0
  42. data/lib/rubocop/cop/lint/ambiguous_operator.rb +2 -0
  43. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +18 -1
  44. data/lib/rubocop/cop/lint/big_decimal_new.rb +1 -2
  45. data/lib/rubocop/cop/lint/boolean_symbol.rb +3 -0
  46. data/lib/rubocop/cop/lint/constant_definition_in_block.rb +74 -0
  47. data/lib/rubocop/cop/lint/debugger.rb +2 -3
  48. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -3
  49. data/lib/rubocop/cop/lint/duplicate_methods.rb +2 -4
  50. data/lib/rubocop/cop/lint/duplicate_require.rb +7 -2
  51. data/lib/rubocop/cop/lint/duplicate_rescue_exception.rb +2 -4
  52. data/lib/rubocop/cop/lint/each_with_object_argument.rb +1 -0
  53. data/lib/rubocop/cop/lint/empty_file.rb +1 -4
  54. data/lib/rubocop/cop/lint/erb_new_arguments.rb +2 -0
  55. data/lib/rubocop/cop/lint/float_comparison.rb +2 -2
  56. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +2 -2
  57. data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +37 -0
  58. data/lib/rubocop/cop/lint/identity_comparison.rb +51 -0
  59. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +2 -5
  60. data/lib/rubocop/cop/lint/inherit_exception.rb +2 -2
  61. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -0
  62. data/lib/rubocop/cop/lint/multiple_comparison.rb +3 -1
  63. data/lib/rubocop/cop/lint/number_conversion.rb +1 -0
  64. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +1 -2
  65. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -1
  66. data/lib/rubocop/cop/lint/raise_exception.rb +1 -0
  67. data/lib/rubocop/cop/lint/rand_one.rb +2 -1
  68. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +22 -12
  69. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +14 -4
  70. data/lib/rubocop/cop/lint/redundant_require_statement.rb +1 -0
  71. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +78 -0
  72. data/lib/rubocop/cop/lint/rescue_type.rb +0 -1
  73. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +3 -1
  74. data/lib/rubocop/cop/lint/shadowed_exception.rb +6 -6
  75. data/lib/rubocop/cop/lint/struct_new_override.rb +1 -0
  76. data/lib/rubocop/cop/lint/to_json.rb +16 -5
  77. data/lib/rubocop/cop/lint/unreachable_loop.rb +3 -6
  78. data/lib/rubocop/cop/lint/uri_escape_unescape.rb +3 -1
  79. data/lib/rubocop/cop/lint/uri_regexp.rb +2 -1
  80. data/lib/rubocop/cop/lint/useless_access_modifier.rb +3 -9
  81. data/lib/rubocop/cop/lint/useless_method_definition.rb +20 -27
  82. data/lib/rubocop/cop/lint/useless_times.rb +106 -0
  83. data/lib/rubocop/cop/metrics/block_length.rb +3 -1
  84. data/lib/rubocop/cop/metrics/class_length.rb +14 -6
  85. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +25 -16
  86. data/lib/rubocop/cop/mixin/comments_help.rb +3 -9
  87. data/lib/rubocop/cop/mixin/configurable_naming.rb +2 -2
  88. data/lib/rubocop/cop/mixin/configurable_numbering.rb +3 -3
  89. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +9 -0
  90. data/lib/rubocop/cop/mixin/hash_transform_method.rb +10 -2
  91. data/lib/rubocop/cop/mixin/rescue_node.rb +1 -0
  92. data/lib/rubocop/cop/mixin/statement_modifier.rb +9 -3
  93. data/lib/rubocop/cop/mixin/visibility_help.rb +4 -16
  94. data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +1 -1
  95. data/lib/rubocop/cop/naming/file_name.rb +1 -1
  96. data/lib/rubocop/cop/offense.rb +15 -2
  97. data/lib/rubocop/cop/security/eval.rb +1 -0
  98. data/lib/rubocop/cop/security/json_load.rb +1 -0
  99. data/lib/rubocop/cop/security/marshal_load.rb +1 -0
  100. data/lib/rubocop/cop/security/open.rb +1 -0
  101. data/lib/rubocop/cop/security/yaml_load.rb +1 -0
  102. data/lib/rubocop/cop/style/access_modifier_declarations.rb +7 -11
  103. data/lib/rubocop/cop/style/accessor_grouping.rb +3 -0
  104. data/lib/rubocop/cop/style/alias.rb +2 -0
  105. data/lib/rubocop/cop/style/array_coercion.rb +4 -0
  106. data/lib/rubocop/cop/style/array_join.rb +1 -0
  107. data/lib/rubocop/cop/style/attr.rb +1 -0
  108. data/lib/rubocop/cop/style/auto_resource_cleanup.rb +2 -0
  109. data/lib/rubocop/cop/style/case_equality.rb +3 -0
  110. data/lib/rubocop/cop/style/case_like_if.rb +20 -4
  111. data/lib/rubocop/cop/style/class_and_module_children.rb +2 -0
  112. data/lib/rubocop/cop/style/class_check.rb +6 -9
  113. data/lib/rubocop/cop/style/class_equality_comparison.rb +64 -0
  114. data/lib/rubocop/cop/style/class_methods_definitions.rb +42 -16
  115. data/lib/rubocop/cop/style/class_vars.rb +1 -2
  116. data/lib/rubocop/cop/style/combinable_loops.rb +13 -11
  117. data/lib/rubocop/cop/style/comment_annotation.rb +6 -0
  118. data/lib/rubocop/cop/style/commented_keyword.rb +7 -8
  119. data/lib/rubocop/cop/style/conditional_assignment.rb +49 -60
  120. data/lib/rubocop/cop/style/date_time.rb +12 -1
  121. data/lib/rubocop/cop/style/dir.rb +1 -0
  122. data/lib/rubocop/cop/style/double_negation.rb +1 -0
  123. data/lib/rubocop/cop/style/empty_literal.rb +3 -1
  124. data/lib/rubocop/cop/style/eval_with_location.rb +1 -3
  125. data/lib/rubocop/cop/style/even_odd.rb +1 -0
  126. data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -2
  127. data/lib/rubocop/cop/style/explicit_block_argument.rb +7 -3
  128. data/lib/rubocop/cop/style/float_division.rb +2 -0
  129. data/lib/rubocop/cop/style/for.rb +0 -4
  130. data/lib/rubocop/cop/style/format_string.rb +1 -4
  131. data/lib/rubocop/cop/style/format_string_token.rb +1 -1
  132. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +24 -5
  133. data/lib/rubocop/cop/style/hash_transform_keys.rb +5 -11
  134. data/lib/rubocop/cop/style/hash_transform_values.rb +5 -11
  135. data/lib/rubocop/cop/style/if_unless_modifier.rb +0 -4
  136. data/lib/rubocop/cop/style/implicit_runtime_error.rb +1 -0
  137. data/lib/rubocop/cop/style/keyword_parameters_order.rb +1 -6
  138. data/lib/rubocop/cop/style/lambda_call.rb +3 -1
  139. data/lib/rubocop/cop/style/method_def_parentheses.rb +0 -4
  140. data/lib/rubocop/cop/style/mixin_usage.rb +8 -27
  141. data/lib/rubocop/cop/style/multiline_block_chain.rb +2 -2
  142. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +14 -1
  143. data/lib/rubocop/cop/style/multiline_when_then.rb +1 -0
  144. data/lib/rubocop/cop/style/nested_ternary_operator.rb +2 -0
  145. data/lib/rubocop/cop/style/nil_comparison.rb +2 -0
  146. data/lib/rubocop/cop/style/non_nil_check.rb +2 -0
  147. data/lib/rubocop/cop/style/not.rb +1 -0
  148. data/lib/rubocop/cop/style/numeric_predicate.rb +1 -3
  149. data/lib/rubocop/cop/style/one_line_conditional.rb +3 -1
  150. data/lib/rubocop/cop/style/optional_boolean_parameter.rb +12 -1
  151. data/lib/rubocop/cop/style/preferred_hash_methods.rb +2 -0
  152. data/lib/rubocop/cop/style/raise_args.rb +2 -3
  153. data/lib/rubocop/cop/style/random_with_offset.rb +4 -3
  154. data/lib/rubocop/cop/style/redundant_assignment.rb +1 -9
  155. data/lib/rubocop/cop/style/redundant_begin.rb +36 -8
  156. data/lib/rubocop/cop/style/redundant_condition.rb +5 -1
  157. data/lib/rubocop/cop/style/redundant_conditional.rb +4 -5
  158. data/lib/rubocop/cop/style/redundant_exception.rb +1 -3
  159. data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +1 -0
  160. data/lib/rubocop/cop/style/redundant_freeze.rb +2 -1
  161. data/lib/rubocop/cop/style/redundant_interpolation.rb +6 -1
  162. data/lib/rubocop/cop/style/redundant_parentheses.rb +14 -6
  163. data/lib/rubocop/cop/style/redundant_percent_q.rb +9 -11
  164. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +39 -24
  165. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -15
  166. data/lib/rubocop/cop/style/redundant_return.rb +17 -17
  167. data/lib/rubocop/cop/style/redundant_self.rb +7 -9
  168. data/lib/rubocop/cop/style/redundant_self_assignment.rb +2 -2
  169. data/lib/rubocop/cop/style/redundant_sort.rb +12 -29
  170. data/lib/rubocop/cop/style/redundant_sort_by.rb +5 -9
  171. data/lib/rubocop/cop/style/rescue_standard_error.rb +20 -16
  172. data/lib/rubocop/cop/style/safe_navigation.rb +5 -0
  173. data/lib/rubocop/cop/style/sample.rb +2 -1
  174. data/lib/rubocop/cop/style/send.rb +2 -3
  175. data/lib/rubocop/cop/style/signal_exception.rb +2 -0
  176. data/lib/rubocop/cop/style/single_argument_dig.rb +1 -0
  177. data/lib/rubocop/cop/style/slicing_with_range.rb +2 -1
  178. data/lib/rubocop/cop/style/stderr_puts.rb +1 -0
  179. data/lib/rubocop/cop/style/string_concatenation.rb +17 -3
  180. data/lib/rubocop/cop/style/strip.rb +1 -0
  181. data/lib/rubocop/cop/style/ternary_parentheses.rb +2 -3
  182. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +4 -3
  183. data/lib/rubocop/cop/style/unpack_first.rb +1 -0
  184. data/lib/rubocop/cop/style/zero_length_predicate.rb +1 -5
  185. data/lib/rubocop/cop/util.rb +0 -1
  186. data/lib/rubocop/cop/variable_force/branch.rb +0 -4
  187. data/lib/rubocop/core_ext/string.rb +1 -1
  188. data/lib/rubocop/directive_comment.rb +32 -0
  189. data/lib/rubocop/ext/regexp_node.rb +23 -7
  190. data/lib/rubocop/formatter/disabled_config_formatter.rb +12 -5
  191. data/lib/rubocop/options.rb +37 -17
  192. data/lib/rubocop/result_cache.rb +38 -15
  193. data/lib/rubocop/rspec/cop_helper.rb +1 -1
  194. data/lib/rubocop/rspec/expect_offense.rb +5 -5
  195. data/lib/rubocop/runner.rb +37 -18
  196. data/lib/rubocop/target_finder.rb +27 -26
  197. data/lib/rubocop/target_ruby.rb +1 -1
  198. data/lib/rubocop/version.rb +6 -1
  199. metadata +19 -18
  200. data/lib/rubocop/cop/mixin/regexp_literal_help.rb +0 -43
  201. data/lib/rubocop/cop/tokens_util.rb +0 -84
@@ -42,6 +42,8 @@ module RuboCop
42
42
  # # good
43
43
  # something.to_time
44
44
  class DateTime < Base
45
+ extend AutoCorrector
46
+
45
47
  CLASS_MSG = 'Prefer Time over DateTime.'
46
48
  COERCION_MSG = 'Do not use #to_datetime.'
47
49
 
@@ -63,7 +65,10 @@ module RuboCop
63
65
  return if historic_date?(node)
64
66
 
65
67
  message = to_datetime?(node) ? COERCION_MSG : CLASS_MSG
66
- add_offense(node, message: message)
68
+
69
+ add_offense(node, message: message) do |corrector|
70
+ autocorrect(corrector, node)
71
+ end
67
72
  end
68
73
 
69
74
  private
@@ -71,6 +76,12 @@ module RuboCop
71
76
  def disallow_coercion?
72
77
  !cop_config['AllowCoercion']
73
78
  end
79
+
80
+ def autocorrect(corrector, node)
81
+ return if to_datetime?(node)
82
+
83
+ corrector.replace(node.receiver.loc.name, 'Time')
84
+ end
74
85
  end
75
86
  end
76
87
  end
@@ -20,6 +20,7 @@ module RuboCop
20
20
  extend AutoCorrector
21
21
 
22
22
  MSG = "Use `__dir__` to get an absolute path to the current file's directory."
23
+ RESTRICT_ON_SEND = %i[expand_path dirname].freeze
23
24
 
24
25
  def_node_matcher :dir_replacement?, <<~PATTERN
25
26
  {(send (const {nil? cbase} :File) :expand_path (send (const {nil? cbase} :File) :dirname #file_keyword?))
@@ -36,6 +36,7 @@ module RuboCop
36
36
  include ConfigurableEnforcedStyle
37
37
 
38
38
  MSG = 'Avoid the use of double negation (`!!`).'
39
+ RESTRICT_ON_SEND = %i[!].freeze
39
40
 
40
41
  def_node_matcher :double_negative?, '(send (send _ :!) :!)'
41
42
 
@@ -25,6 +25,8 @@ module RuboCop
25
25
  HASH_MSG = 'Use hash literal `{}` instead of `Hash.new`.'
26
26
  STR_MSG = 'Use string literal `%<prefer>s` instead of `String.new`.'
27
27
 
28
+ RESTRICT_ON_SEND = %i[new].freeze
29
+
28
30
  def_node_matcher :array_node, '(send (const {nil? cbase} :Array) :new)'
29
31
  def_node_matcher :hash_node, '(send (const {nil? cbase} :Hash) :new)'
30
32
  def_node_matcher :str_node, '(send (const {nil? cbase} :String) :new)'
@@ -69,7 +71,7 @@ module RuboCop
69
71
  parent = node.parent
70
72
  return false unless parent && %i[send super zsuper].include?(parent.type)
71
73
 
72
- node.object_id == parent.arguments.first.object_id &&
74
+ node.equal?(parent.arguments.first) &&
73
75
  !parentheses?(node.parent)
74
76
  end
75
77
 
@@ -37,7 +37,7 @@ module RuboCop
37
37
  MSG_INCORRECT_LINE = 'Use `%<expected>s` instead of `%<actual>s`, ' \
38
38
  'as they are used by backtraces.'
39
39
 
40
- EVAL_METHODS = %i[eval class_eval module_eval instance_eval].to_set.freeze
40
+ RESTRICT_ON_SEND = %i[eval class_eval module_eval instance_eval].freeze
41
41
 
42
42
  def_node_matcher :eval_without_location?, <<~PATTERN
43
43
  {
@@ -63,8 +63,6 @@ module RuboCop
63
63
  PATTERN
64
64
 
65
65
  def on_send(node)
66
- return unless EVAL_METHODS.include?(node.method_name)
67
-
68
66
  eval_without_location?(node) do |code|
69
67
  if with_lineno?(node)
70
68
  on_with_lineno(node, code)
@@ -19,6 +19,7 @@ module RuboCop
19
19
  extend AutoCorrector
20
20
 
21
21
  MSG = 'Replace with `Integer#%<method>s?`.'
22
+ RESTRICT_ON_SEND = %i[== !=].freeze
22
23
 
23
24
  def_node_matcher :even_odd_candidate?, <<~PATTERN
24
25
  (send
@@ -52,6 +52,8 @@ module RuboCop
52
52
  'instead of ' \
53
53
  '`Pathname.new(__FILE__).parent.expand_path`.'
54
54
 
55
+ RESTRICT_ON_SEND = %i[expand_path].freeze
56
+
55
57
  def_node_matcher :file_expand_path, <<~PATTERN
56
58
  (send
57
59
  (const {nil? cbase} :File) :expand_path
@@ -75,8 +77,6 @@ module RuboCop
75
77
  PATTERN
76
78
 
77
79
  def on_send(node)
78
- return unless node.method?(:expand_path)
79
-
80
80
  if (current_path, default_dir = file_expand_path(node))
81
81
  inspect_offense_for_expand_path(node, current_path, default_dir)
82
82
  elsif (default_dir = pathname_parent_expand_path(node))
@@ -57,12 +57,16 @@ module RuboCop
57
57
  yielding_block?(block_node) do |send_node, block_args, yield_args|
58
58
  return unless yielding_arguments?(block_args, yield_args)
59
59
 
60
+ def_node = block_node.each_ancestor(:def, :defs).first
61
+ # if `yield` is being called outside of a method context, ignore
62
+ # this is not a valid ruby pattern, but can happen in haml or erb,
63
+ # so this can cause crashes in haml_lint
64
+ return unless def_node
65
+
60
66
  add_offense(block_node) do |corrector|
61
67
  corrector.remove(block_body_range(block_node, send_node))
62
68
 
63
69
  add_block_argument(send_node, corrector)
64
-
65
- def_node = block_node.each_ancestor(:def, :defs).first
66
70
  add_block_argument(def_node, corrector) if @def_nodes.add?(def_node)
67
71
  end
68
72
  end
@@ -83,7 +87,7 @@ module RuboCop
83
87
  replacement = ' &block'
84
88
  replacement = ",#{replacement}" unless arg_range.source.end_with?(',')
85
89
  corrector.insert_after(arg_range, replacement) unless last_arg.blockarg_type?
86
- elsif node.send_type?
90
+ elsif node.call_type?
87
91
  corrector.insert_after(node, '(&block)')
88
92
  else
89
93
  corrector.insert_after(node.loc.name, '(&block)')
@@ -48,6 +48,8 @@ module RuboCop
48
48
  fdiv: 'Prefer using `fdiv` for float divisions.'
49
49
  }.freeze
50
50
 
51
+ RESTRICT_ON_SEND = %i[/].freeze
52
+
51
53
  def_node_matcher :right_coerce?, <<~PATTERN
52
54
  (send _ :/ (send _ :to_f))
53
55
  PATTERN
@@ -49,8 +49,6 @@ module RuboCop
49
49
 
50
50
  def on_for(node)
51
51
  if style == :each
52
- return unless opposite_style_detected
53
-
54
52
  add_offense(node, message: PREFER_EACH) do |corrector|
55
53
  ForToEachCorrector.new(node).call(corrector)
56
54
  end
@@ -63,8 +61,6 @@ module RuboCop
63
61
  return unless suspect_enumerable?(node)
64
62
 
65
63
  if style == :for
66
- return unless opposite_style_detected
67
-
68
64
  add_offense(node, message: PREFER_FOR) do |corrector|
69
65
  EachToForCorrector.new(node).call(corrector)
70
66
  end
@@ -40,8 +40,7 @@ module RuboCop
40
40
  extend AutoCorrector
41
41
 
42
42
  MSG = 'Favor `%<prefer>s` over `%<current>s`.'
43
-
44
- FORMAT_METHODS = %i[format sprintf %].freeze
43
+ RESTRICT_ON_SEND = %i[format sprintf %].freeze
45
44
 
46
45
  def_node_matcher :formatter, <<~PATTERN
47
46
  {
@@ -56,8 +55,6 @@ module RuboCop
56
55
  PATTERN
57
56
 
58
57
  def on_send(node)
59
- return unless FORMAT_METHODS.include?(node.method_name)
60
-
61
58
  formatter(node) do |selector|
62
59
  detected_style = selector == :% ? :percent : selector
63
60
 
@@ -33,7 +33,7 @@ module RuboCop
33
33
  #
34
34
  # # bad
35
35
  # format('%<greeting>s', greeting: 'Hello')
36
- # format('%{greeting}', 'Hello')
36
+ # format('%{greeting}', greeting: 'Hello')
37
37
  #
38
38
  # # good
39
39
  # format('%s', 'Hello')
@@ -6,6 +6,9 @@ module RuboCop
6
6
  # Checks for presence or absence of braces around hash literal as a last
7
7
  # array item depending on configuration.
8
8
  #
9
+ # NOTE: This cop will ignore arrays where all items are hashes, regardless of
10
+ # EnforcedStyle.
11
+ #
9
12
  # @example EnforcedStyle: braces (default)
10
13
  # # bad
11
14
  # [1, 2, one: 1, two: 2]
@@ -13,6 +16,9 @@ module RuboCop
13
16
  # # good
14
17
  # [1, 2, { one: 1, two: 2 }]
15
18
  #
19
+ # # good
20
+ # [{ one: 1 }, { two: 2 }]
21
+ #
16
22
  # @example EnforcedStyle: no_braces
17
23
  # # bad
18
24
  # [1, 2, { one: 1, two: 2 }]
@@ -20,12 +26,15 @@ module RuboCop
20
26
  # # good
21
27
  # [1, 2, one: 1, two: 2]
22
28
  #
29
+ # # good
30
+ # [{ one: 1 }, { two: 2 }]
23
31
  class HashAsLastArrayItem < Base
24
32
  include ConfigurableEnforcedStyle
25
33
  extend AutoCorrector
26
34
 
27
35
  def on_hash(node)
28
- return unless last_array_item?(node)
36
+ return unless (array = containing_array(node))
37
+ return unless last_array_item?(array, node) && explicit_array?(array)
29
38
 
30
39
  if braces_style?
31
40
  check_braces(node)
@@ -36,11 +45,20 @@ module RuboCop
36
45
 
37
46
  private
38
47
 
39
- def last_array_item?(node)
40
- parent = node.parent
41
- return false unless parent
48
+ def containing_array(hash_node)
49
+ parent = hash_node.parent
50
+ parent if parent&.array_type?
51
+ end
52
+
53
+ def last_array_item?(array, node)
54
+ return false if array.child_nodes.all?(&:hash_type?)
55
+
56
+ array.children.last.equal?(node)
57
+ end
42
58
 
43
- parent.array_type? && parent.children.last.equal?(node)
59
+ def explicit_array?(array)
60
+ # an implicit array cannot have an "unbraced" hash
61
+ array.square_brackets?
44
62
  end
45
63
 
46
64
  def check_braces(node)
@@ -53,6 +71,7 @@ module RuboCop
53
71
 
54
72
  def check_no_braces(node)
55
73
  return unless node.braces?
74
+ return if node.children.empty? # Empty hash cannot be "unbraced"
56
75
 
57
76
  add_offense(node, message: 'Omit the braces around the hash.') do |corrector|
58
77
  corrector.remove(node.loc.begin)
@@ -34,15 +34,13 @@ module RuboCop
34
34
 
35
35
  def_node_matcher :on_bad_each_with_object, <<~PATTERN
36
36
  (block
37
- ({send csend}
38
- !{(send _ :each_with_index) (array ...)}
39
- :each_with_object (hash))
37
+ ({send csend} !#array_receiver? :each_with_object (hash))
40
38
  (args
41
39
  (mlhs
42
40
  (arg $_)
43
41
  (arg _val))
44
42
  (arg _memo))
45
- ({send csend} (lvar _memo) :[]= $_ $(lvar _val)))
43
+ ({send csend} (lvar _memo) :[]= $!`_memo $(lvar _val)))
46
44
  PATTERN
47
45
 
48
46
  def_node_matcher :on_bad_hash_brackets_map, <<~PATTERN
@@ -50,7 +48,7 @@ module RuboCop
50
48
  (const _ :Hash)
51
49
  :[]
52
50
  (block
53
- ({send csend} !(send _ :each_with_index) {:map :collect})
51
+ ({send csend} !#array_receiver? {:map :collect})
54
52
  (args
55
53
  (arg $_)
56
54
  (arg _val))
@@ -60,9 +58,7 @@ module RuboCop
60
58
  def_node_matcher :on_bad_map_to_h, <<~PATTERN
61
59
  ({send csend}
62
60
  (block
63
- ({send csend}
64
- !{(send _ :each_with_index) (array ...)}
65
- {:map :collect})
61
+ ({send csend} !#array_receiver? {:map :collect})
66
62
  (args
67
63
  (arg $_)
68
64
  (arg _val))
@@ -72,9 +68,7 @@ module RuboCop
72
68
 
73
69
  def_node_matcher :on_bad_to_h, <<~PATTERN
74
70
  (block
75
- ({send csend}
76
- !{(send _ :each_with_index) (array ...)}
77
- :to_h)
71
+ ({send csend} !#array_receiver? :to_h)
78
72
  (args
79
73
  (arg $_)
80
74
  (arg _val))
@@ -31,15 +31,13 @@ module RuboCop
31
31
 
32
32
  def_node_matcher :on_bad_each_with_object, <<~PATTERN
33
33
  (block
34
- ({send csend}
35
- !{(send _ :each_with_index) (array ...)}
36
- :each_with_object (hash))
34
+ ({send csend} !#array_receiver? :each_with_object (hash))
37
35
  (args
38
36
  (mlhs
39
37
  (arg _key)
40
38
  (arg $_))
41
39
  (arg _memo))
42
- ({send csend} (lvar _memo) :[]= $(lvar _key) $_))
40
+ ({send csend} (lvar _memo) :[]= $(lvar _key) $!`_memo))
43
41
  PATTERN
44
42
 
45
43
  def_node_matcher :on_bad_hash_brackets_map, <<~PATTERN
@@ -47,7 +45,7 @@ module RuboCop
47
45
  (const _ :Hash)
48
46
  :[]
49
47
  (block
50
- ({send csend} !(send _ :each_with_index) {:map :collect})
48
+ ({send csend} !#array_receiver? {:map :collect})
51
49
  (args
52
50
  (arg _key)
53
51
  (arg $_))
@@ -57,9 +55,7 @@ module RuboCop
57
55
  def_node_matcher :on_bad_map_to_h, <<~PATTERN
58
56
  ({send csend}
59
57
  (block
60
- ({send csend}
61
- !{(send _ :each_with_index) (array ...)}
62
- {:map :collect})
58
+ ({send csend} !#array_receiver? {:map :collect})
63
59
  (args
64
60
  (arg _key)
65
61
  (arg $_))
@@ -69,9 +65,7 @@ module RuboCop
69
65
 
70
66
  def_node_matcher :on_bad_to_h, <<~PATTERN
71
67
  (block
72
- ({send csend}
73
- !{(send _ :each_with_index) (array ...)}
74
- :to_h)
68
+ ({send csend} !#array_receiver? :to_h)
75
69
  (args
76
70
  (arg _key)
77
71
  (arg $_))
@@ -157,10 +157,6 @@ module RuboCop
157
157
  #{indentation}end
158
158
  RUBY
159
159
  end
160
-
161
- def first_line_comment(node)
162
- processed_source.comment_at_line(node.loc.line)&.text
163
- end
164
160
  end
165
161
  end
166
162
  end
@@ -17,6 +17,7 @@ module RuboCop
17
17
  class ImplicitRuntimeError < Base
18
18
  MSG = 'Use `%<method>s` with an explicit exception class and message,' \
19
19
  ' rather than just a message.'
20
+ RESTRICT_ON_SEND = %i[raise fail].freeze
20
21
 
21
22
  def_node_matcher :implicit_runtime_error_raise_or_fail,
22
23
  '(send nil? ${:raise :fail} {str dstr})'
@@ -28,7 +28,7 @@ module RuboCop
28
28
  MSG = 'Place optional keyword parameters at the end of the parameters list.'
29
29
 
30
30
  def on_kwoptarg(node)
31
- kwarg_nodes = right_siblings_of(node).select(&:kwarg_type?)
31
+ kwarg_nodes = node.right_siblings.select(&:kwarg_type?)
32
32
  return if kwarg_nodes.empty?
33
33
 
34
34
  add_offense(node) do |corrector|
@@ -41,11 +41,6 @@ module RuboCop
41
41
 
42
42
  private
43
43
 
44
- # TODO: Use API from `rubocop-ast` when released.
45
- def right_siblings_of(node)
46
- node.parent.children[node.sibling_index + 1..-1]
47
- end
48
-
49
44
  def remove_kwargs(kwarg_nodes, corrector)
50
45
  kwarg_nodes.each do |kwarg|
51
46
  with_space = range_with_surrounding_space(range: kwarg.source_range)
@@ -22,8 +22,10 @@ module RuboCop
22
22
  include ConfigurableEnforcedStyle
23
23
  extend AutoCorrector
24
24
 
25
+ RESTRICT_ON_SEND = %i[call].freeze
26
+
25
27
  def on_send(node)
26
- return unless node.receiver && node.method?(:call)
28
+ return unless node.receiver
27
29
 
28
30
  if offense?(node) && opposite_style_detected
29
31
  add_offense(node) do |corrector|
@@ -140,16 +140,12 @@ module RuboCop
140
140
  def missing_parentheses(node)
141
141
  location = node.arguments.source_range
142
142
 
143
- return unless unexpected_style_detected(:require_no_parentheses)
144
-
145
143
  add_offense(location, message: MSG_MISSING) do |corrector|
146
144
  correct_definition(node, corrector)
147
145
  end
148
146
  end
149
147
 
150
148
  def unwanted_parentheses(args)
151
- return unless unexpected_style_detected(:require_parentheses)
152
-
153
149
  add_offense(args, message: MSG_PRESENT) do |corrector|
154
150
  # offense is registered on args node when parentheses are unwanted
155
151
  correct_arguments(args, corrector)
@@ -43,47 +43,28 @@ module RuboCop
43
43
  class MixinUsage < Base
44
44
  MSG = '`%<statement>s` is used at the top level. Use inside `class` ' \
45
45
  'or `module`.'
46
+ RESTRICT_ON_SEND = %i[include extend prepend].freeze
46
47
 
47
48
  def_node_matcher :include_statement, <<~PATTERN
48
49
  (send nil? ${:include :extend :prepend}
49
50
  const)
50
51
  PATTERN
51
52
 
52
- def_node_matcher :wrapped_macro_scope?, <<~PATTERN
53
- {({sclass class module block} ... ({begin if} ...))}
53
+ def_node_matcher :in_top_level_scope?, <<~PATTERN
54
+ {
55
+ root? # either at the top level
56
+ ^[ {kwbegin begin if def} # or wrapped within one of these
57
+ #in_top_level_scope? ] # that is in top level scope
58
+ }
54
59
  PATTERN
55
60
 
56
61
  def on_send(node)
57
62
  include_statement(node) do |statement|
58
- return if node.argument? ||
59
- accepted_include?(node) ||
60
- belongs_to_class_or_module?(node)
63
+ return unless in_top_level_scope?(node)
61
64
 
62
65
  add_offense(node, message: format(MSG, statement: statement))
63
66
  end
64
67
  end
65
-
66
- private
67
-
68
- def accepted_include?(node)
69
- node.parent && (node.macro? || ascend_macro_scope?(node.parent))
70
- end
71
-
72
- def ascend_macro_scope?(ancestor)
73
- return true if wrapped_macro_scope?(ancestor)
74
-
75
- ancestor.parent && ascend_macro_scope?(ancestor.parent)
76
- end
77
-
78
- def belongs_to_class_or_module?(node)
79
- if !node.parent
80
- false
81
- else
82
- return true if node.parent.class_type? || node.parent.module_type?
83
-
84
- belongs_to_class_or_module?(node.parent)
85
- end
86
- end
87
68
  end
88
69
  end
89
70
  end