rubocop 0.90.0 → 0.93.1

Sign up to get free protection for your applications and to get access to all the features.
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