rubocop 1.45.1 → 1.48.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (173) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +28 -9
  4. data/lib/rubocop/cli/command/auto_generate_config.rb +7 -0
  5. data/lib/rubocop/comment_config.rb +19 -0
  6. data/lib/rubocop/config.rb +2 -2
  7. data/lib/rubocop/cop/autocorrect_logic.rb +1 -1
  8. data/lib/rubocop/cop/base.rb +1 -1
  9. data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
  10. data/lib/rubocop/cop/corrector.rb +1 -1
  11. data/lib/rubocop/cop/correctors/alignment_corrector.rb +2 -2
  12. data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +3 -3
  13. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +3 -3
  14. data/lib/rubocop/cop/correctors/line_break_corrector.rb +1 -1
  15. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +2 -2
  16. data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +1 -1
  17. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +1 -1
  18. data/lib/rubocop/cop/gemspec/dependency_version.rb +1 -1
  19. data/lib/rubocop/cop/internal_affairs/cop_description.rb +4 -4
  20. data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +1 -1
  21. data/lib/rubocop/cop/internal_affairs/location_expression.rb +37 -0
  22. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
  23. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +1 -1
  24. data/lib/rubocop/cop/internal_affairs/processed_source_buffer_name.rb +42 -0
  25. data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +1 -1
  26. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +1 -1
  27. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +39 -0
  28. data/lib/rubocop/cop/internal_affairs.rb +3 -0
  29. data/lib/rubocop/cop/layout/block_end_newline.rb +7 -21
  30. data/lib/rubocop/cop/layout/class_structure.rb +5 -3
  31. data/lib/rubocop/cop/layout/closing_heredoc_indentation.rb +1 -1
  32. data/lib/rubocop/cop/layout/empty_comment.rb +3 -3
  33. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +1 -1
  34. data/lib/rubocop/cop/layout/end_alignment.rb +4 -0
  35. data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -1
  36. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +8 -2
  37. data/lib/rubocop/cop/layout/heredoc_indentation.rb +2 -2
  38. data/lib/rubocop/cop/layout/leading_comment_space.rb +1 -1
  39. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +1 -3
  40. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +11 -7
  41. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +2 -2
  42. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +2 -2
  43. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +1 -1
  44. data/lib/rubocop/cop/layout/space_inside_percent_literal_delimiters.rb +1 -1
  45. data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
  46. data/lib/rubocop/cop/lint/constant_resolution.rb +1 -1
  47. data/lib/rubocop/cop/lint/debugger.rb +3 -0
  48. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
  49. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +1 -1
  50. data/lib/rubocop/cop/lint/duplicate_methods.rb +2 -2
  51. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -3
  52. data/lib/rubocop/cop/lint/else_layout.rb +1 -1
  53. data/lib/rubocop/cop/lint/empty_block.rb +1 -1
  54. data/lib/rubocop/cop/lint/empty_conditional_body.rb +4 -2
  55. data/lib/rubocop/cop/lint/empty_interpolation.rb +1 -1
  56. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -1
  57. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +46 -4
  58. data/lib/rubocop/cop/lint/missing_super.rb +31 -2
  59. data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -9
  60. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +2 -0
  61. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +6 -10
  62. data/lib/rubocop/cop/lint/percent_string_array.rb +1 -1
  63. data/lib/rubocop/cop/lint/percent_symbol_array.rb +1 -1
  64. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +10 -4
  65. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +5 -5
  66. data/lib/rubocop/cop/lint/redundant_require_statement.rb +1 -1
  67. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +1 -1
  68. data/lib/rubocop/cop/lint/redundant_with_index.rb +1 -1
  69. data/lib/rubocop/cop/lint/redundant_with_object.rb +1 -1
  70. data/lib/rubocop/cop/lint/refinement_import_methods.rb +2 -1
  71. data/lib/rubocop/cop/lint/rescue_type.rb +3 -3
  72. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +1 -1
  73. data/lib/rubocop/cop/lint/script_permission.rb +1 -1
  74. data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
  75. data/lib/rubocop/cop/lint/syntax.rb +4 -0
  76. data/lib/rubocop/cop/lint/to_enum_arguments.rb +6 -2
  77. data/lib/rubocop/cop/lint/useless_access_modifier.rb +10 -10
  78. data/lib/rubocop/cop/lint/useless_rescue.rb +6 -2
  79. data/lib/rubocop/cop/lint/useless_times.rb +1 -1
  80. data/lib/rubocop/cop/metrics/collection_literal_length.rb +76 -0
  81. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +2 -2
  82. data/lib/rubocop/cop/migration/department_name.rb +1 -1
  83. data/lib/rubocop/cop/mixin/annotation_comment.rb +1 -1
  84. data/lib/rubocop/cop/mixin/code_length.rb +1 -1
  85. data/lib/rubocop/cop/mixin/comments_help.rb +2 -2
  86. data/lib/rubocop/cop/mixin/documentation_comment.rb +1 -1
  87. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +1 -1
  88. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +10 -5
  89. data/lib/rubocop/cop/mixin/hash_transform_method.rb +3 -3
  90. data/lib/rubocop/cop/mixin/min_branches_count.rb +40 -0
  91. data/lib/rubocop/cop/mixin/multiline_element_line_breaks.rb +0 -3
  92. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
  93. data/lib/rubocop/cop/mixin/range_help.rb +1 -6
  94. data/lib/rubocop/cop/mixin/statement_modifier.rb +2 -2
  95. data/lib/rubocop/cop/mixin/trailing_comma.rb +1 -1
  96. data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +1 -1
  97. data/lib/rubocop/cop/naming/method_name.rb +3 -3
  98. data/lib/rubocop/cop/naming/predicate_name.rb +1 -1
  99. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +1 -1
  100. data/lib/rubocop/cop/registry.rb +3 -1
  101. data/lib/rubocop/cop/style/accessor_grouping.rb +39 -17
  102. data/lib/rubocop/cop/style/arguments_forwarding.rb +3 -3
  103. data/lib/rubocop/cop/style/array_intersect.rb +1 -1
  104. data/lib/rubocop/cop/style/ascii_comments.rb +1 -1
  105. data/lib/rubocop/cop/style/bisected_attr_accessor.rb +1 -1
  106. data/lib/rubocop/cop/style/block_comments.rb +1 -1
  107. data/lib/rubocop/cop/style/block_delimiters.rb +11 -2
  108. data/lib/rubocop/cop/style/case_like_if.rb +20 -3
  109. data/lib/rubocop/cop/style/collection_compact.rb +1 -1
  110. data/lib/rubocop/cop/style/comment_annotation.rb +1 -1
  111. data/lib/rubocop/cop/style/commented_keyword.rb +2 -2
  112. data/lib/rubocop/cop/style/concat_array_literals.rb +10 -2
  113. data/lib/rubocop/cop/style/conditional_assignment.rb +6 -6
  114. data/lib/rubocop/cop/style/dir_empty.rb +60 -0
  115. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +1 -1
  116. data/lib/rubocop/cop/style/documentation.rb +10 -4
  117. data/lib/rubocop/cop/style/documentation_method.rb +4 -4
  118. data/lib/rubocop/cop/style/each_with_object.rb +1 -1
  119. data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
  120. data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
  121. data/lib/rubocop/cop/style/eval_with_location.rb +4 -4
  122. data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
  123. data/lib/rubocop/cop/style/file_empty.rb +71 -0
  124. data/lib/rubocop/cop/style/file_read.rb +1 -1
  125. data/lib/rubocop/cop/style/file_write.rb +1 -1
  126. data/lib/rubocop/cop/style/guard_clause.rb +1 -1
  127. data/lib/rubocop/cop/style/hash_like_case.rb +3 -9
  128. data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
  129. data/lib/rubocop/cop/style/if_unless_modifier.rb +76 -9
  130. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +2 -0
  131. data/lib/rubocop/cop/style/inverse_methods.rb +5 -5
  132. data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +2 -2
  133. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +1 -1
  134. data/lib/rubocop/cop/style/min_max.rb +3 -3
  135. data/lib/rubocop/cop/style/mixin_grouping.rb +4 -4
  136. data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -1
  137. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +1 -1
  138. data/lib/rubocop/cop/style/negated_if_else_condition.rb +12 -7
  139. data/lib/rubocop/cop/style/nil_lambda.rb +2 -2
  140. data/lib/rubocop/cop/style/redundant_condition.rb +2 -2
  141. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +2 -2
  142. data/lib/rubocop/cop/style/redundant_interpolation.rb +2 -2
  143. data/lib/rubocop/cop/style/redundant_parentheses.rb +1 -1
  144. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +5 -6
  145. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +10 -3
  146. data/lib/rubocop/cop/style/redundant_sort.rb +3 -3
  147. data/lib/rubocop/cop/style/redundant_string_escape.rb +2 -2
  148. data/lib/rubocop/cop/style/require_order.rb +1 -3
  149. data/lib/rubocop/cop/style/rescue_standard_error.rb +2 -2
  150. data/lib/rubocop/cop/style/safe_navigation.rb +2 -2
  151. data/lib/rubocop/cop/style/slicing_with_range.rb +1 -1
  152. data/lib/rubocop/cop/style/sole_nested_conditional.rb +2 -2
  153. data/lib/rubocop/cop/style/stderr_puts.rb +1 -1
  154. data/lib/rubocop/cop/style/struct_inheritance.rb +1 -1
  155. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +1 -1
  156. data/lib/rubocop/cop/style/unpack_first.rb +3 -3
  157. data/lib/rubocop/cop/style/word_array.rb +17 -5
  158. data/lib/rubocop/cop/style/yoda_condition.rb +1 -1
  159. data/lib/rubocop/cop/style/zero_length_predicate.rb +9 -5
  160. data/lib/rubocop/cop/team.rb +11 -8
  161. data/lib/rubocop/cop/util.rb +13 -4
  162. data/lib/rubocop/cop/variable_force/variable.rb +5 -3
  163. data/lib/rubocop/directive_comment.rb +3 -3
  164. data/lib/rubocop/ext/comment.rb +18 -0
  165. data/lib/rubocop/formatter/junit_formatter.rb +4 -1
  166. data/lib/rubocop/rspec/cop_helper.rb +1 -1
  167. data/lib/rubocop/rspec/shared_contexts.rb +4 -0
  168. data/lib/rubocop/rspec/support.rb +1 -0
  169. data/lib/rubocop/server/core.rb +1 -1
  170. data/lib/rubocop/target_ruby.rb +1 -1
  171. data/lib/rubocop/version.rb +1 -1
  172. data/lib/rubocop.rb +5 -0
  173. metadata +17 -9
@@ -231,7 +231,7 @@ module RuboCop
231
231
  cop_names = cops.sort.map { |c| describe(c) }.join(', ')
232
232
 
233
233
  add_offense(location, message: message(cop_names)) do |corrector|
234
- range = comment_range_with_surrounding_space(location, comment.loc.expression)
234
+ range = comment_range_with_surrounding_space(location, comment.source_range)
235
235
 
236
236
  if leave_free_comment?(comment, range)
237
237
  corrector.replace(range, ' # ')
@@ -263,8 +263,8 @@ module RuboCop
263
263
 
264
264
  def cop_range(comment, cop)
265
265
  cop = remove_department_marker(cop)
266
- matching_range(comment.loc.expression, cop) ||
267
- matching_range(comment.loc.expression, Badge.parse(cop).cop_name) ||
266
+ matching_range(comment.source_range, cop) ||
267
+ matching_range(comment.source_range, Badge.parse(cop).cop_name) ||
268
268
  raise("Couldn't find #{cop} in comment: #{comment.text}")
269
269
  end
270
270
 
@@ -284,12 +284,18 @@ module RuboCop
284
284
  .all? { |intervening| /\A\s*,\s*\Z/.match?(intervening) }
285
285
  end
286
286
 
287
+ SIMILAR_COP_NAMES_CACHE = Hash.new do |hash, cop_name|
288
+ hash[:all_cop_names] = Registry.global.names unless hash.key?(:all_cop_names)
289
+ hash[cop_name] = NameSimilarity.find_similar_name(cop_name, hash[:all_cop_names])
290
+ end
291
+ private_constant :SIMILAR_COP_NAMES_CACHE
292
+
287
293
  def describe(cop)
288
294
  return 'all cops' if cop == 'all'
289
295
  return "`#{remove_department_marker(cop)}` department" if department_marker?(cop)
290
296
  return "`#{cop}`" if all_cop_names.include?(cop)
291
297
 
292
- similar = NameSimilarity.find_similar_name(cop, all_cop_names)
298
+ similar = SIMILAR_COP_NAMES_CACHE[cop]
293
299
  similar ? "`#{cop}` (did you mean `#{similar}`?)" : "`#{cop}` (unknown cop)"
294
300
  end
295
301
 
@@ -74,7 +74,7 @@ module RuboCop
74
74
  end
75
75
 
76
76
  def comment_start(comment)
77
- comment.loc.expression.begin_pos
77
+ comment.source_range.begin_pos
78
78
  end
79
79
 
80
80
  def cop_name_indention(comment, name)
@@ -82,7 +82,7 @@ module RuboCop
82
82
  end
83
83
 
84
84
  def range_with_comma(comment, name)
85
- source = comment.loc.expression.source
85
+ source = comment.source
86
86
 
87
87
  begin_pos = cop_name_indention(comment, name)
88
88
  end_pos = begin_pos + name.size
@@ -94,14 +94,14 @@ module RuboCop
94
94
 
95
95
  def range_to_remove(begin_pos, end_pos, comment)
96
96
  start = comment_start(comment)
97
- source = comment.loc.expression.source
97
+ source = comment.source
98
98
 
99
99
  if source[begin_pos - 1] == ','
100
100
  range_with_comma_before(start, begin_pos, end_pos)
101
101
  elsif source[end_pos] == ','
102
102
  range_with_comma_after(comment, start, begin_pos, end_pos)
103
103
  else
104
- range_between(start, comment.loc.expression.end_pos)
104
+ range_between(start, comment.source_range.end_pos)
105
105
  end
106
106
  end
107
107
 
@@ -112,7 +112,7 @@ module RuboCop
112
112
  # If the list of cops is comma-separated, but without a empty space after the comma,
113
113
  # we should **not** remove the prepending empty space, thus begin_pos += 1
114
114
  def range_with_comma_after(comment, start, begin_pos, end_pos)
115
- begin_pos += 1 if comment.loc.expression.source[end_pos + 1] != ' '
115
+ begin_pos += 1 if comment.source[end_pos + 1] != ' '
116
116
 
117
117
  range_between(start + begin_pos, start + end_pos + 1)
118
118
  end
@@ -56,7 +56,7 @@ module RuboCop
56
56
  if node.parent.respond_to?(:modifier_form?) && node.parent.modifier_form?
57
57
  corrector.insert_after(node.parent, "\nend")
58
58
 
59
- range = range_with_surrounding_space(node.loc.expression, side: :right)
59
+ range = range_with_surrounding_space(node.source_range, side: :right)
60
60
  else
61
61
  range = range_by_whole_lines(node.source_range, include_final_newline: true)
62
62
  end
@@ -141,7 +141,7 @@ module RuboCop
141
141
  expression = loc.expression
142
142
 
143
143
  if array_new?(variable)
144
- expression = node.parent.loc.expression if node.parent.array_type?
144
+ expression = node.parent.source_range if node.parent.array_type?
145
145
  [expression, variable.source]
146
146
  elsif !variable.array_type?
147
147
  [expression, "[#{variable.source}]"]
@@ -72,7 +72,7 @@ module RuboCop
72
72
  end
73
73
 
74
74
  def with_index_range(send)
75
- range_between(send.loc.selector.begin_pos, send.loc.expression.end_pos)
75
+ range_between(send.loc.selector.begin_pos, send.source_range.end_pos)
76
76
  end
77
77
  end
78
78
  end
@@ -71,7 +71,7 @@ module RuboCop
71
71
  end
72
72
 
73
73
  def with_object_range(send)
74
- range_between(send.loc.selector.begin_pos, send.loc.expression.end_pos)
74
+ range_between(send.loc.selector.begin_pos, send.source_range.end_pos)
75
75
  end
76
76
  end
77
77
  end
@@ -41,7 +41,8 @@ module RuboCop
41
41
 
42
42
  def on_send(node)
43
43
  return if node.receiver
44
- return unless node.parent.block_type? && node.parent.method?(:refine)
44
+ return unless (parent = node.parent)
45
+ return unless parent.block_type? && parent.method?(:refine)
45
46
 
46
47
  add_offense(node.loc.selector, message: format(MSG, current: node.method_name))
47
48
  end
@@ -50,7 +50,7 @@ module RuboCop
50
50
  return if invalid_exceptions.empty?
51
51
 
52
52
  add_offense(
53
- node.loc.keyword.join(rescued.loc.expression),
53
+ node.loc.keyword.join(rescued.source_range),
54
54
  message: format(MSG, invalid_exceptions: invalid_exceptions.map(&:source).join(', '))
55
55
  ) do |corrector|
56
56
  autocorrect(corrector, node)
@@ -59,9 +59,9 @@ module RuboCop
59
59
 
60
60
  def autocorrect(corrector, node)
61
61
  rescued, _, _body = *node
62
- range = Parser::Source::Range.new(node.loc.expression.source_buffer,
62
+ range = Parser::Source::Range.new(node.source_range.source_buffer,
63
63
  node.loc.keyword.end_pos,
64
- rescued.loc.expression.end_pos)
64
+ rescued.source_range.end_pos)
65
65
 
66
66
  corrector.replace(range, correction(*rescued))
67
67
  end
@@ -65,7 +65,7 @@ module RuboCop
65
65
  end
66
66
 
67
67
  def location(node, unsafe_method_call)
68
- node.loc.expression.join(unsafe_method_call.loc.expression)
68
+ node.source_range.join(unsafe_method_call.source_range)
69
69
  end
70
70
 
71
71
  def top_conditional_ancestor(node)
@@ -53,7 +53,7 @@ module RuboCop
53
53
  private
54
54
 
55
55
  def autocorrect(comment)
56
- FileUtils.chmod('+x', comment.loc.expression.source_buffer.name)
56
+ FileUtils.chmod('+x', comment.source_range.source_buffer.name)
57
57
  end
58
58
 
59
59
  def executable?(processed_source)
@@ -83,7 +83,7 @@ module RuboCop
83
83
 
84
84
  def offense_range(rescues)
85
85
  shadowing_rescue = find_shadowing_rescue(rescues)
86
- expression = shadowing_rescue.loc.expression
86
+ expression = shadowing_rescue.source_range
87
87
  range_between(expression.begin_pos, expression.end_pos)
88
88
  end
89
89
 
@@ -33,6 +33,10 @@ module RuboCop
33
33
  message << '.' unless message.end_with?('.')
34
34
  message
35
35
  end
36
+
37
+ def find_severity(_range, _severity)
38
+ :fatal
39
+ end
36
40
  end
37
41
  end
38
42
  end
@@ -43,8 +43,12 @@ module RuboCop
43
43
  return unless def_node
44
44
 
45
45
  enum_conversion_call?(node) do |method_node, arguments|
46
- add_offense(node) unless method_name?(method_node, def_node.method_name) &&
47
- arguments_match?(arguments, def_node)
46
+ next if method_node.call_type? &&
47
+ !method_node.method?(:__method__) && !method_node.method?(:__callee__)
48
+ next if method_name?(method_node, def_node.method_name) &&
49
+ arguments_match?(arguments, def_node)
50
+
51
+ add_offense(node)
48
52
  end
49
53
  end
50
54
 
@@ -137,7 +137,7 @@ module RuboCop
137
137
  alias on_sclass on_class
138
138
 
139
139
  def on_block(node)
140
- return unless eval_call?(node)
140
+ return unless eval_call?(node) || included_block?(node)
141
141
 
142
142
  check_node(node.body)
143
143
  end
@@ -167,14 +167,6 @@ module RuboCop
167
167
  ({block numblock} (send _ {:class_eval :instance_eval}) ...)
168
168
  PATTERN
169
169
 
170
- # @!method class_constructor?(node)
171
- def_node_matcher :class_constructor?, <<~PATTERN
172
- ({block numblock} {
173
- (send (const {nil? cbase} {:Class :Module :Struct}) :new ...)
174
- (send (const {nil? cbase} :Data) :define ...)
175
- } ...)
176
- PATTERN
177
-
178
170
  def check_node(node)
179
171
  return if node.nil?
180
172
 
@@ -200,10 +192,13 @@ module RuboCop
200
192
  end
201
193
  end
202
194
 
195
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
203
196
  def check_child_nodes(node, unused, cur_vis)
204
197
  node.child_nodes.each do |child|
205
198
  if child.send_type? && access_modifier?(child)
206
199
  cur_vis, unused = check_send_node(child, cur_vis, unused)
200
+ elsif child.block_type? && included_block?(child)
201
+ next
207
202
  elsif method_definition?(child)
208
203
  unused = nil
209
204
  elsif start_of_new_scope?(child)
@@ -215,6 +210,7 @@ module RuboCop
215
210
 
216
211
  [cur_vis, unused]
217
212
  end
213
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
218
214
 
219
215
  def check_send_node(node, cur_vis, unused)
220
216
  if node.bare_access_modifier?
@@ -248,6 +244,10 @@ module RuboCop
248
244
  [new_vis, unused]
249
245
  end
250
246
 
247
+ def included_block?(block_node)
248
+ active_support_extensions_enabled? && block_node.method?(:included)
249
+ end
250
+
251
251
  def method_definition?(child)
252
252
  static_method_definition?(child) ||
253
253
  dynamic_method_definition?(child) ||
@@ -273,7 +273,7 @@ module RuboCop
273
273
 
274
274
  def eval_call?(child)
275
275
  class_or_instance_eval?(child) ||
276
- class_constructor?(child) ||
276
+ child.class_constructor? ||
277
277
  any_context_creating_methods?(child)
278
278
  end
279
279
 
@@ -56,11 +56,13 @@ module RuboCop
56
56
 
57
57
  private
58
58
 
59
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
59
60
  def only_reraising?(resbody_node)
60
61
  return false if use_exception_variable_in_ensure?(resbody_node)
61
62
 
62
63
  body = resbody_node.body
63
- return false if body.nil? || !body.send_type? || !body.method?(:raise)
64
+
65
+ return false if body.nil? || !body.send_type? || !body.method?(:raise) || body.receiver
64
66
  return true unless body.arguments?
65
67
  return false if body.arguments.size > 1
66
68
 
@@ -68,12 +70,14 @@ module RuboCop
68
70
 
69
71
  exception_objects(resbody_node).include?(exception_name)
70
72
  end
73
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
71
74
 
72
75
  def use_exception_variable_in_ensure?(resbody_node)
73
76
  return false unless (exception_variable = resbody_node.exception_variable)
74
77
  return false unless (ensure_node = resbody_node.each_ancestor(:ensure).first)
78
+ return false unless (ensure_body = ensure_node.body)
75
79
 
76
- ensure_node.body.each_descendant(:lvar).map(&:source).include?(exception_variable.source)
80
+ ensure_body.each_descendant(:lvar).map(&:source).include?(exception_variable.source)
77
81
  end
78
82
 
79
83
  def exception_objects(resbody_node)
@@ -74,7 +74,7 @@ module RuboCop
74
74
  end
75
75
 
76
76
  def remove_node(corrector, node)
77
- corrector.remove(range_by_whole_lines(node.loc.expression, include_final_newline: true))
77
+ corrector.remove(range_by_whole_lines(node.source_range, include_final_newline: true))
78
78
  end
79
79
 
80
80
  def autocorrect_block_pass(corrector, node, proc_name)
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Metrics
6
+ # Checks for literals with extremely many entries. This is indicative of
7
+ # configuration or data that may be better extracted somewhere else, like
8
+ # a database, fetched from an API, or read from a non-code file (CSV,
9
+ # JSON, YAML, etc.).
10
+ #
11
+ # @example
12
+ # # bad
13
+ # # Huge Array literal
14
+ # [1, 2, '...', 999_999_999]
15
+ #
16
+ # # bad
17
+ # # Huge Hash literal
18
+ # { 1 => 1, 2 => 2, '...' => '...', 999_999_999 => 999_999_999}
19
+ #
20
+ # # bad
21
+ # # Huge Set "literal"
22
+ # Set[1, 2, '...', 999_999_999]
23
+ #
24
+ # # good
25
+ # # Reasonably sized Array literal
26
+ # [1, 2, '...', 10]
27
+ #
28
+ # # good
29
+ # # Reading huge Array from external data source
30
+ # # File.readlines('numbers.txt', chomp: true).map!(&:to_i)
31
+ #
32
+ # # good
33
+ # # Reasonably sized Hash literal
34
+ # { 1 => 1, 2 => 2, '...' => '...', 10 => 10}
35
+ #
36
+ # # good
37
+ # # Reading huge Hash from external data source
38
+ # CSV.foreach('numbers.csv', headers: true).each_with_object({}) do |row, hash|
39
+ # hash[row["key"].to_i] = row["value"].to_i
40
+ # end
41
+ #
42
+ # # good
43
+ # # Reasonably sized Set "literal"
44
+ # Set[1, 2, '...', 10]
45
+ #
46
+ # # good
47
+ # # Reading huge Set from external data source
48
+ # SomeFramework.config_for(:something)[:numbers].to_set
49
+ #
50
+ class CollectionLiteralLength < Base
51
+ MSG = 'Avoid hard coding large quantities of data in code. ' \
52
+ 'Prefer reading the data from an external source.'
53
+ RESTRICT_ON_SEND = [:[]].freeze
54
+
55
+ def on_array(node)
56
+ add_offense(node) if node.children.length >= collection_threshold
57
+ end
58
+ alias on_hash on_array
59
+
60
+ def on_index(node)
61
+ add_offense(node) if node.arguments.length >= collection_threshold
62
+ end
63
+
64
+ def on_send(node)
65
+ on_index(node) if node.method?(:[])
66
+ end
67
+
68
+ private
69
+
70
+ def collection_threshold
71
+ cop_config.fetch('LengthThreshold', Float::INFINITY)
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -163,8 +163,8 @@ module RuboCop
163
163
  return 0 unless parenthesized?(parent)
164
164
 
165
165
  [
166
- parent.loc.begin.end_pos != descendant.loc.expression.begin_pos,
167
- parent.loc.end.begin_pos != descendant.loc.expression.end_pos
166
+ parent.loc.begin.end_pos != descendant.source_range.begin_pos,
167
+ parent.loc.end.begin_pos != descendant.source_range.end_pos
168
168
  ].count(true)
169
169
  end
170
170
 
@@ -45,7 +45,7 @@ module RuboCop
45
45
  end
46
46
 
47
47
  def check_cop_name(name, comment, offset)
48
- start = comment.location.expression.begin_pos + offset
48
+ start = comment.source_range.begin_pos + offset
49
49
  range = range_between(start, start + name.length)
50
50
 
51
51
  add_offense(range) do |corrector|
@@ -29,7 +29,7 @@ module RuboCop
29
29
 
30
30
  # Returns the range bounds for just the annotation
31
31
  def bounds
32
- start = comment.loc.expression.begin_pos + margin.length
32
+ start = comment.source_range.begin_pos + margin.length
33
33
  length = [keyword, colon, space].reduce(0) { |len, elem| len + elem.to_s.length }
34
34
  [start, start + length]
35
35
  end
@@ -36,7 +36,7 @@ module RuboCop
36
36
  length = calculator.calculate
37
37
  return if length <= max_length
38
38
 
39
- location = node.casgn_type? ? node.loc.name : node.loc.expression
39
+ location = node.casgn_type? ? node.loc.name : node.source_range
40
40
 
41
41
  add_offense(location, message: message(length, max_length)) { self.max = length }
42
42
  end
@@ -37,7 +37,7 @@ module RuboCop
37
37
  private
38
38
 
39
39
  def end_position_for(node)
40
- end_line = buffer.line_for_position(node.loc.expression.end_pos)
40
+ end_line = buffer.line_for_position(node.source_range.end_pos)
41
41
  buffer.line_range(end_line).end_pos
42
42
  end
43
43
 
@@ -68,7 +68,7 @@ module RuboCop
68
68
  node.loc.else.line
69
69
  elsif node.if_type? && node.ternary?
70
70
  node.else_branch.loc.line
71
- elsif (next_sibling = node.right_sibling)
71
+ elsif (next_sibling = node.right_sibling) && next_sibling.is_a?(AST::Node)
72
72
  next_sibling.loc.line
73
73
  elsif (parent = node.parent)
74
74
  parent.loc.end ? parent.loc.end.line : parent.loc.line
@@ -23,7 +23,7 @@ module RuboCop
23
23
  # The args node1 & node2 may represent a RuboCop::AST::Node
24
24
  # or a Parser::Source::Comment. Both respond to #loc.
25
25
  def preceding_comment?(node1, node2)
26
- node1 && node2 && precede?(node2, node1) && comment_line?(node2.loc.expression.source)
26
+ node1 && node2 && precede?(node2, node1) && comment_line?(node2.source)
27
27
  end
28
28
 
29
29
  # The args node1 & node2 may represent a RuboCop::AST::Node
@@ -33,7 +33,7 @@ module RuboCop
33
33
 
34
34
  def separator_delta(pair)
35
35
  if pair.hash_rocket?
36
- correct_separator_column = pair.key.loc.expression.end.column + 1
36
+ correct_separator_column = pair.key.source_range.end.column + 1
37
37
  actual_separator_column = pair.loc.operator.column
38
38
 
39
39
  correct_separator_column - actual_separator_column
@@ -100,8 +100,10 @@ module RuboCop
100
100
  last_pair = node.parent.pairs.last
101
101
  return unless last_pair.key.source == last_pair.value.source
102
102
  return unless (dispatch_node = find_ancestor_method_dispatch_node(node))
103
- return if node.respond_to?(:parenthesized?) && !node.parenthesized?
104
- return unless last_expression?(dispatch_node) || method_dispatch_as_argument?(dispatch_node)
103
+ return if dispatch_node.assignment_method?
104
+ return if dispatch_node.parenthesized?
105
+ return if dispatch_node.parent && parentheses?(dispatch_node.parent)
106
+ return if last_expression?(dispatch_node) && !method_dispatch_as_argument?(dispatch_node)
105
107
 
106
108
  def_node = node.each_ancestor(:send, :csend, :super, :yield).first
107
109
 
@@ -132,9 +134,12 @@ module RuboCop
132
134
  ancestor.ancestors.any? { |node| node.respond_to?(:modifier_form?) && node.modifier_form? }
133
135
  end
134
136
 
135
- def last_expression?(ancestor)
136
- ancestor.right_sibling ||
137
- ancestor.each_ancestor.find { |node| node.assignment? || node.send_type? }&.right_sibling
137
+ def last_expression?(node)
138
+ return false if node.right_sibling
139
+ return true unless (assignment_node = node.each_ancestor.find(&:assignment?))
140
+ return last_expression?(assignment_node.parent) if assignment_node.parent&.assignment?
141
+
142
+ !assignment_node.right_sibling
138
143
  end
139
144
 
140
145
  def method_dispatch_as_argument?(method_dispatch_node)
@@ -159,7 +159,7 @@ module RuboCop
159
159
  end
160
160
 
161
161
  def strip_prefix_and_suffix(node, corrector)
162
- expression = node.loc.expression
162
+ expression = node.source_range
163
163
  corrector.remove_leading(expression, leading)
164
164
  corrector.remove_trailing(expression, trailing)
165
165
  end
@@ -175,11 +175,11 @@ module RuboCop
175
175
  end
176
176
 
177
177
  def set_new_arg_name(transformed_argname, corrector)
178
- corrector.replace(block_node.arguments.loc.expression, "|#{transformed_argname}|")
178
+ corrector.replace(block_node.arguments.source_range, "|#{transformed_argname}|")
179
179
  end
180
180
 
181
181
  def set_new_body_expression(transforming_body_expr, corrector)
182
- body_source = transforming_body_expr.loc.expression.source
182
+ body_source = transforming_body_expr.source
183
183
  if transforming_body_expr.hash_type? && !transforming_body_expr.braces?
184
184
  body_source = "{ #{body_source} }"
185
185
  end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ # Common functionality for checking minimum branches count.
6
+ module MinBranchesCount
7
+ private
8
+
9
+ def min_branches_count?(node)
10
+ branches =
11
+ if node.case_type?
12
+ node.when_branches
13
+ elsif node.if_type?
14
+ if_conditional_branches(node)
15
+ else
16
+ raise ArgumentError, "Unsupported #{node.type.inspect} node type"
17
+ end
18
+
19
+ branches.size >= min_branches_count
20
+ end
21
+
22
+ def min_branches_count
23
+ length = cop_config['MinBranchesCount'] || 3
24
+ return length if length.is_a?(Integer) && length.positive?
25
+
26
+ raise 'MinBranchesCount needs to be a positive integer!'
27
+ end
28
+
29
+ def if_conditional_branches(node, branches = [])
30
+ return [] if node.nil? || !node.if_type?
31
+
32
+ branches << node.if_branch
33
+
34
+ else_branch = node.else_branch
35
+ if_conditional_branches(else_branch, branches) if else_branch&.if_type?
36
+ branches
37
+ end
38
+ end
39
+ end
40
+ end
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # TEAM: backend_infra
4
- # WATCHERS: maxh
5
-
6
3
  module RuboCop
7
4
  module Cop
8
5
  # Common functionality for checking for a line break before each
@@ -10,7 +10,7 @@ module RuboCop
10
10
  def get_source_range(node, comments_as_separators)
11
11
  unless comments_as_separators
12
12
  first_comment = processed_source.ast_with_comments[node].first
13
- return first_comment.loc.expression unless first_comment.nil?
13
+ return first_comment.source_range unless first_comment.nil?
14
14
  end
15
15
  node.source_range
16
16
  end
@@ -132,12 +132,7 @@ module RuboCop
132
132
  end
133
133
 
134
134
  def range_with_comments(node)
135
- ranges = [
136
- node,
137
- *@processed_source.ast_with_comments[node]
138
- ].map do |element|
139
- element.location.expression
140
- end
135
+ ranges = [node, *@processed_source.ast_with_comments[node]].map(&:source_range)
141
136
  ranges.reduce do |result, range|
142
137
  add_range(result, range)
143
138
  end
@@ -65,14 +65,14 @@ module RuboCop
65
65
  end
66
66
 
67
67
  def method_source(if_body)
68
- range_between(if_body.loc.expression.begin_pos, if_body.loc.selector.end_pos).source
68
+ range_between(if_body.source_range.begin_pos, if_body.loc.selector.end_pos).source
69
69
  end
70
70
 
71
71
  def first_line_comment(node)
72
72
  comment = processed_source.find_comment { |c| same_line?(c, node) }
73
73
  return unless comment
74
74
 
75
- comment_source = comment.loc.expression.source
75
+ comment_source = comment.source
76
76
  comment_source unless comment_disables_cop?(comment_source)
77
77
  end
78
78
 
@@ -75,7 +75,7 @@ module RuboCop
75
75
 
76
76
  def inside_comment?(range, comma_offset)
77
77
  comment = processed_source.comment_at_line(range.line)
78
- comment && comment.loc.expression.begin_pos < range.begin_pos + comma_offset
78
+ comment && comment.source_range.begin_pos < range.begin_pos + comma_offset
79
79
  end
80
80
 
81
81
  # Returns true if the node has round/square/curly brackets.
@@ -38,7 +38,7 @@ module RuboCop
38
38
  return if correct_case_delimiters?(node)
39
39
 
40
40
  add_offense(node.loc.heredoc_end) do |corrector|
41
- expr = node.loc.expression
41
+ expr = node.source_range
42
42
 
43
43
  corrector.replace(expr, correct_delimiters(expr.source))
44
44
  corrector.replace(node.loc.heredoc_end, correct_delimiters(delimiter_string(expr)))