rubocop 1.19.0 → 1.23.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.
Files changed (236) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +129 -21
  4. data/lib/rubocop/config.rb +5 -0
  5. data/lib/rubocop/config_loader.rb +5 -3
  6. data/lib/rubocop/config_validator.rb +9 -1
  7. data/lib/rubocop/cop/base.rb +3 -3
  8. data/lib/rubocop/cop/bundler/gem_comment.rb +3 -3
  9. data/lib/rubocop/cop/bundler/gem_filename.rb +103 -0
  10. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +45 -21
  11. data/lib/rubocop/cop/bundler/ordered_gems.rb +3 -12
  12. data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +2 -2
  13. data/lib/rubocop/cop/correctors/line_break_corrector.rb +1 -1
  14. data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +11 -10
  15. data/lib/rubocop/cop/documentation.rb +1 -1
  16. data/lib/rubocop/cop/gemspec/date_assignment.rb +2 -10
  17. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +1 -10
  18. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +3 -12
  19. data/lib/rubocop/cop/gemspec/require_mfa.rb +146 -0
  20. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +31 -24
  21. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +3 -10
  22. data/lib/rubocop/cop/generator.rb +14 -8
  23. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +60 -0
  24. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
  25. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  26. data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
  27. data/lib/rubocop/cop/layout/assignment_indentation.rb +1 -1
  28. data/lib/rubocop/cop/layout/block_alignment.rb +3 -3
  29. data/lib/rubocop/cop/layout/class_structure.rb +2 -1
  30. data/lib/rubocop/cop/layout/dot_position.rb +34 -5
  31. data/lib/rubocop/cop/layout/empty_comment.rb +1 -1
  32. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +22 -1
  33. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +7 -4
  34. data/lib/rubocop/cop/layout/end_alignment.rb +2 -3
  35. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +1 -1
  36. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +1 -1
  37. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
  38. data/lib/rubocop/cop/layout/hash_alignment.rb +1 -1
  39. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +1 -1
  40. data/lib/rubocop/cop/layout/indentation_width.rb +1 -1
  41. data/lib/rubocop/cop/layout/leading_comment_space.rb +1 -1
  42. data/lib/rubocop/cop/layout/line_length.rb +9 -7
  43. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -1
  44. data/lib/rubocop/cop/layout/multiline_block_layout.rb +3 -3
  45. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +3 -0
  46. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +1 -1
  47. data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -0
  48. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +6 -5
  49. data/lib/rubocop/cop/layout/single_line_block_chain.rb +15 -4
  50. data/lib/rubocop/cop/layout/space_after_not.rb +1 -0
  51. data/lib/rubocop/cop/layout/space_around_equals_in_parameter_default.rb +2 -1
  52. data/lib/rubocop/cop/layout/space_around_keyword.rb +2 -2
  53. data/lib/rubocop/cop/layout/space_before_brackets.rb +1 -0
  54. data/lib/rubocop/cop/layout/space_before_comment.rb +1 -1
  55. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +11 -5
  56. data/lib/rubocop/cop/layout/space_inside_parens.rb +74 -28
  57. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +1 -1
  58. data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +111 -0
  59. data/lib/rubocop/cop/lint/ambiguous_range.rb +11 -11
  60. data/lib/rubocop/cop/lint/assignment_in_condition.rb +7 -5
  61. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +18 -5
  62. data/lib/rubocop/cop/lint/boolean_symbol.rb +5 -0
  63. data/lib/rubocop/cop/lint/debugger.rb +2 -4
  64. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +4 -4
  65. data/lib/rubocop/cop/lint/deprecated_constants.rb +3 -2
  66. data/lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb +24 -1
  67. data/lib/rubocop/cop/lint/else_layout.rb +10 -6
  68. data/lib/rubocop/cop/lint/empty_in_pattern.rb +1 -1
  69. data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -1
  70. data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -1
  71. data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +12 -3
  72. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +67 -0
  73. data/lib/rubocop/cop/lint/interpolation_check.rb +5 -0
  74. data/lib/rubocop/cop/lint/loop.rb +4 -3
  75. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +5 -1
  76. data/lib/rubocop/cop/lint/number_conversion.rb +16 -2
  77. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -1
  78. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +4 -2
  79. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +17 -0
  80. data/lib/rubocop/cop/lint/percent_string_array.rb +10 -0
  81. data/lib/rubocop/cop/lint/raise_exception.rb +4 -0
  82. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +5 -4
  83. data/lib/rubocop/cop/lint/require_relative_self_path.rb +50 -0
  84. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +1 -1
  85. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  86. data/lib/rubocop/cop/lint/triple_quotes.rb +1 -1
  87. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +8 -3
  88. data/lib/rubocop/cop/lint/unused_method_argument.rb +2 -3
  89. data/lib/rubocop/cop/lint/useless_method_definition.rb +3 -2
  90. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +117 -0
  91. data/lib/rubocop/cop/lint/useless_setter_call.rb +7 -4
  92. data/lib/rubocop/cop/lint/useless_times.rb +4 -3
  93. data/lib/rubocop/cop/metrics/abc_size.rb +6 -0
  94. data/lib/rubocop/cop/metrics/parameter_lists.rb +5 -2
  95. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  96. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -1
  97. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
  98. data/lib/rubocop/cop/mixin/annotation_comment.rb +57 -34
  99. data/lib/rubocop/cop/mixin/code_length.rb +1 -1
  100. data/lib/rubocop/cop/mixin/documentation_comment.rb +5 -2
  101. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -2
  102. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +23 -1
  103. data/lib/rubocop/cop/mixin/gemspec_help.rb +30 -0
  104. data/lib/rubocop/cop/mixin/hash_transform_method.rb +3 -3
  105. data/lib/rubocop/cop/mixin/heredoc.rb +1 -3
  106. data/lib/rubocop/cop/mixin/multiline_element_indentation.rb +1 -1
  107. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +2 -2
  108. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
  109. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +9 -1
  110. data/lib/rubocop/cop/mixin/percent_array.rb +11 -3
  111. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +9 -1
  112. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
  113. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  114. data/lib/rubocop/cop/mixin/statement_modifier.rb +1 -1
  115. data/lib/rubocop/cop/mixin/trailing_body.rb +1 -1
  116. data/lib/rubocop/cop/naming/ascii_identifiers.rb +0 -3
  117. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  118. data/lib/rubocop/cop/naming/constant_name.rb +1 -1
  119. data/lib/rubocop/cop/naming/file_name.rb +37 -4
  120. data/lib/rubocop/cop/naming/inclusive_language.rb +9 -9
  121. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +5 -4
  122. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +7 -0
  123. data/lib/rubocop/cop/security/io_methods.rb +49 -0
  124. data/lib/rubocop/cop/security/json_load.rb +8 -7
  125. data/lib/rubocop/cop/security/open.rb +4 -0
  126. data/lib/rubocop/cop/security/yaml_load.rb +4 -0
  127. data/lib/rubocop/cop/style/accessor_grouping.rb +2 -2
  128. data/lib/rubocop/cop/style/and_or.rb +5 -0
  129. data/lib/rubocop/cop/style/arguments_forwarding.rb +13 -2
  130. data/lib/rubocop/cop/style/array_coercion.rb +21 -3
  131. data/lib/rubocop/cop/style/ascii_comments.rb +0 -3
  132. data/lib/rubocop/cop/style/block_delimiters.rb +23 -6
  133. data/lib/rubocop/cop/style/case_equality.rb +6 -9
  134. data/lib/rubocop/cop/style/case_like_if.rb +5 -0
  135. data/lib/rubocop/cop/style/class_and_module_children.rb +9 -0
  136. data/lib/rubocop/cop/style/collection_compact.rb +7 -5
  137. data/lib/rubocop/cop/style/collection_methods.rb +8 -6
  138. data/lib/rubocop/cop/style/combinable_loops.rb +3 -2
  139. data/lib/rubocop/cop/style/comment_annotation.rb +25 -39
  140. data/lib/rubocop/cop/style/commented_keyword.rb +9 -4
  141. data/lib/rubocop/cop/style/date_time.rb +5 -0
  142. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +1 -1
  143. data/lib/rubocop/cop/style/documentation.rb +23 -8
  144. data/lib/rubocop/cop/style/double_negation.rb +27 -6
  145. data/lib/rubocop/cop/style/empty_method.rb +2 -2
  146. data/lib/rubocop/cop/style/encoding.rb +26 -15
  147. data/lib/rubocop/cop/style/explicit_block_argument.rb +21 -11
  148. data/lib/rubocop/cop/style/float_division.rb +10 -2
  149. data/lib/rubocop/cop/style/format_string_token.rb +2 -1
  150. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +7 -2
  151. data/lib/rubocop/cop/style/global_std_stream.rb +4 -0
  152. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +11 -0
  153. data/lib/rubocop/cop/style/hash_each_methods.rb +5 -0
  154. data/lib/rubocop/cop/style/hash_except.rb +4 -3
  155. data/lib/rubocop/cop/style/hash_transform_keys.rb +4 -6
  156. data/lib/rubocop/cop/style/hash_transform_values.rb +4 -6
  157. data/lib/rubocop/cop/style/identical_conditional_branches.rb +18 -16
  158. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +18 -4
  159. data/lib/rubocop/cop/style/infinite_loop.rb +4 -3
  160. data/lib/rubocop/cop/style/inverse_methods.rb +9 -2
  161. data/lib/rubocop/cop/style/lambda_call.rb +1 -1
  162. data/lib/rubocop/cop/style/line_end_concatenation.rb +14 -1
  163. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +6 -6
  164. data/lib/rubocop/cop/style/module_function.rb +8 -9
  165. data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +1 -1
  166. data/lib/rubocop/cop/style/multiline_when_then.rb +1 -1
  167. data/lib/rubocop/cop/style/mutable_constant.rb +73 -6
  168. data/lib/rubocop/cop/style/negated_if.rb +1 -1
  169. data/lib/rubocop/cop/style/negated_unless.rb +1 -1
  170. data/lib/rubocop/cop/style/non_nil_check.rb +2 -2
  171. data/lib/rubocop/cop/style/not.rb +2 -2
  172. data/lib/rubocop/cop/style/numbered_parameters.rb +46 -0
  173. data/lib/rubocop/cop/style/numbered_parameters_limit.rb +50 -0
  174. data/lib/rubocop/cop/style/numeric_literals.rb +7 -8
  175. data/lib/rubocop/cop/style/numeric_predicate.rb +5 -0
  176. data/lib/rubocop/cop/style/open_struct_use.rb +69 -0
  177. data/lib/rubocop/cop/style/optional_arguments.rb +4 -0
  178. data/lib/rubocop/cop/style/optional_boolean_parameter.rb +14 -4
  179. data/lib/rubocop/cop/style/parallel_assignment.rb +1 -1
  180. data/lib/rubocop/cop/style/parentheses_around_condition.rb +12 -2
  181. data/lib/rubocop/cop/style/percent_q_literals.rb +2 -2
  182. data/lib/rubocop/cop/style/preferred_hash_methods.rb +9 -4
  183. data/lib/rubocop/cop/style/quoted_symbols.rb +21 -7
  184. data/lib/rubocop/cop/style/raise_args.rb +1 -1
  185. data/lib/rubocop/cop/style/redundant_argument.rb +19 -9
  186. data/lib/rubocop/cop/style/redundant_begin.rb +25 -0
  187. data/lib/rubocop/cop/style/redundant_condition.rb +2 -3
  188. data/lib/rubocop/cop/style/redundant_fetch_block.rb +4 -0
  189. data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +12 -3
  190. data/lib/rubocop/cop/style/redundant_freeze.rb +4 -4
  191. data/lib/rubocop/cop/style/redundant_interpolation.rb +1 -1
  192. data/lib/rubocop/cop/style/redundant_percent_q.rb +2 -3
  193. data/lib/rubocop/cop/style/redundant_self.rb +10 -0
  194. data/lib/rubocop/cop/style/redundant_self_assignment.rb +4 -3
  195. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +23 -28
  196. data/lib/rubocop/cop/style/redundant_sort.rb +51 -18
  197. data/lib/rubocop/cop/style/regexp_literal.rb +3 -3
  198. data/lib/rubocop/cop/style/return_nil.rb +2 -1
  199. data/lib/rubocop/cop/style/safe_navigation.rb +13 -2
  200. data/lib/rubocop/cop/style/select_by_regexp.rb +139 -0
  201. data/lib/rubocop/cop/style/single_argument_dig.rb +5 -0
  202. data/lib/rubocop/cop/style/slicing_with_range.rb +13 -0
  203. data/lib/rubocop/cop/style/sole_nested_conditional.rb +4 -0
  204. data/lib/rubocop/cop/style/special_global_vars.rb +4 -0
  205. data/lib/rubocop/cop/style/static_class.rb +5 -5
  206. data/lib/rubocop/cop/style/string_chars.rb +4 -2
  207. data/lib/rubocop/cop/style/string_concatenation.rb +5 -1
  208. data/lib/rubocop/cop/style/string_hash_keys.rb +4 -0
  209. data/lib/rubocop/cop/style/struct_inheritance.rb +4 -0
  210. data/lib/rubocop/cop/style/swap_values.rb +4 -2
  211. data/lib/rubocop/cop/style/symbol_array.rb +3 -3
  212. data/lib/rubocop/cop/style/symbol_proc.rb +26 -0
  213. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +19 -0
  214. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  215. data/lib/rubocop/cop/style/word_array.rb +3 -3
  216. data/lib/rubocop/cop/style/yoda_condition.rb +24 -7
  217. data/lib/rubocop/cop/style/zero_length_predicate.rb +6 -0
  218. data/lib/rubocop/cop/util.rb +15 -4
  219. data/lib/rubocop/cops_documentation_generator.rb +17 -5
  220. data/lib/rubocop/formatter/html_formatter.rb +5 -2
  221. data/lib/rubocop/formatter/json_formatter.rb +4 -1
  222. data/lib/rubocop/magic_comment.rb +44 -15
  223. data/lib/rubocop/options.rb +126 -112
  224. data/lib/rubocop/rake_task.rb +1 -1
  225. data/lib/rubocop/remote_config.rb +1 -1
  226. data/lib/rubocop/result_cache.rb +3 -3
  227. data/lib/rubocop/rspec/cop_helper.rb +1 -1
  228. data/lib/rubocop/rspec/expect_offense.rb +6 -2
  229. data/lib/rubocop/rspec/parallel_formatter.rb +90 -0
  230. data/lib/rubocop/rspec/support.rb +1 -0
  231. data/lib/rubocop/runner.rb +2 -3
  232. data/lib/rubocop/target_finder.rb +1 -1
  233. data/lib/rubocop/version.rb +1 -1
  234. data/lib/rubocop/yaml_duplication_checker.rb +1 -1
  235. data/lib/rubocop.rb +14 -2
  236. metadata +20 -5
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ #
7
+ # This cop checks for `IO.select` that is incompatible with Fiber Scheduler since Ruby 3.0.
8
+ #
9
+ # @example
10
+ #
11
+ # # bad
12
+ # IO.select([io], [], [], timeout)
13
+ #
14
+ # # good
15
+ # io.wait_readable(timeout)
16
+ #
17
+ # # bad
18
+ # IO.select([], [io], [], timeout)
19
+ #
20
+ # # good
21
+ # io.wait_writable(timeout)
22
+ #
23
+ class IncompatibleIoSelectWithFiberScheduler < Base
24
+ extend AutoCorrector
25
+
26
+ MSG = 'Use `%<preferred>s` instead of `%<current>s`.'
27
+ RESTRICT_ON_SEND = %i[select].freeze
28
+
29
+ # @!method io_select(node)
30
+ def_node_matcher :io_select, <<~PATTERN
31
+ (send
32
+ (const {nil? cbase} :IO) :select $_ $_ {(array) nil} $...)
33
+ PATTERN
34
+
35
+ def on_send(node)
36
+ return unless (read, write, timeout = io_select(node))
37
+ return unless scheduler_compatible?(read, write) || scheduler_compatible?(write, read)
38
+
39
+ preferred = preferred_method(read, write, timeout)
40
+ message = format(MSG, preferred: preferred, current: node.source)
41
+
42
+ add_offense(node, message: message) do |corrector|
43
+ corrector.replace(node, preferred)
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def scheduler_compatible?(io1, io2)
50
+ return false unless io1.array_type? && io1.values.size == 1
51
+
52
+ io2.array_type? ? io2.values.empty? : io2.nil_type?
53
+ end
54
+
55
+ def preferred_method(read, write, timeout)
56
+ timeout_argument = timeout.empty? ? '' : "(#{timeout[0].source})"
57
+
58
+ if read.array_type? && read.values[0]
59
+ "#{read.values[0].source}.wait_readable#{timeout_argument}"
60
+ else
61
+ "#{write.values[0].source}.wait_writable#{timeout_argument}"
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -5,6 +5,11 @@ module RuboCop
5
5
  module Lint
6
6
  # This cop checks for interpolation in a single quoted string.
7
7
  #
8
+ # @safety
9
+ # This cop is generally safe, but is marked as unsafe because
10
+ # it is possible to actually intentionally have text inside
11
+ # `#{...}` in a single quoted string.
12
+ #
8
13
  # @example
9
14
  #
10
15
  # # bad
@@ -5,9 +5,10 @@ module RuboCop
5
5
  module Lint
6
6
  # This cop checks for uses of `begin...end while/until something`.
7
7
  #
8
- # The cop is marked as unsafe because behaviour can change in some cases, including
9
- # if a local variable inside the loop body is accessed outside of it, or if the
10
- # loop body raises a `StopIteration` exception (which `Kernel#loop` rescues).
8
+ # @safety
9
+ # The cop is unsafe because behaviour can change in some cases, including
10
+ # if a local variable inside the loop body is accessed outside of it, or if the
11
+ # loop body raises a `StopIteration` exception (which `Kernel#loop` rescues).
11
12
  #
12
13
  # @example
13
14
  #
@@ -14,7 +14,11 @@ module RuboCop
14
14
  # `Dir.glob` and `Dir[]` sort globbed results by default in Ruby 3.0.
15
15
  # So all bad cases are acceptable when Ruby 3.0 or higher are used.
16
16
  #
17
- # This cop will be deprecated and removed when supporting only Ruby 3.0 and higher.
17
+ # NOTE: This cop will be deprecated and removed when supporting only Ruby 3.0 and higher.
18
+ #
19
+ # @safety
20
+ # This cop is unsafe in the case where sorting files changes existing
21
+ # expected behaviour.
18
22
  #
19
23
  # @example
20
24
  #
@@ -18,6 +18,11 @@ module RuboCop
18
18
  # cop by default). Similarly, Rails' duration methods do not work well
19
19
  # with `Integer()` and can be ignored with `IgnoredMethods`.
20
20
  #
21
+ # @safety
22
+ # Autocorrection is unsafe because it is not guaranteed that the
23
+ # replacement `Kernel` methods are able to properly handle the
24
+ # input if it is not a standard class.
25
+ #
21
26
  # @example
22
27
  #
23
28
  # # bad
@@ -25,6 +30,7 @@ module RuboCop
25
30
  # '10'.to_i
26
31
  # '10.2'.to_f
27
32
  # '10'.to_c
33
+ # '1/3'.to_r
28
34
  # ['1', '2', '3'].map(&:to_i)
29
35
  # foo.try(:to_f)
30
36
  # bar.send(:to_c)
@@ -34,6 +40,7 @@ module RuboCop
34
40
  # Integer('10', 10)
35
41
  # Float('10.2')
36
42
  # Complex('10')
43
+ # Rational('1/3')
37
44
  # ['1', '2', '3'].map { |i| Integer(i, 10) }
38
45
  # foo.try { |i| Float(i) }
39
46
  # bar.send { |i| Complex(i) }
@@ -54,12 +61,14 @@ module RuboCop
54
61
  CONVERSION_METHOD_CLASS_MAPPING = {
55
62
  to_i: "#{Integer.name}(%<number_object>s, 10)",
56
63
  to_f: "#{Float.name}(%<number_object>s)",
57
- to_c: "#{Complex.name}(%<number_object>s)"
64
+ to_c: "#{Complex.name}(%<number_object>s)",
65
+ to_r: "#{Rational.name}(%<number_object>s)"
58
66
  }.freeze
59
67
  MSG = 'Replace unsafe number conversion with number '\
60
68
  'class parsing, instead of using '\
61
69
  '`%<current>s`, use stricter '\
62
70
  '`%<corrected_method>s`.'
71
+ CONVERSION_METHODS = %i[Integer Float Complex Rational to_i to_f to_c to_r].freeze
63
72
  METHODS = CONVERSION_METHOD_CLASS_MAPPING.keys.map(&:inspect).join(' ')
64
73
 
65
74
  # @!method to_method(node)
@@ -127,7 +136,8 @@ module RuboCop
127
136
  end
128
137
 
129
138
  def ignore_receiver?(receiver)
130
- if receiver.send_type? && ignored_method?(receiver.method_name)
139
+ if receiver.numeric_type? || (receiver.send_type? &&
140
+ (conversion_method?(receiver.method_name) || ignored_method?(receiver.method_name)))
131
141
  true
132
142
  elsif (receiver = top_receiver(receiver))
133
143
  receiver.const_type? && ignored_class?(receiver.const_name)
@@ -142,6 +152,10 @@ module RuboCop
142
152
  receiver
143
153
  end
144
154
 
155
+ def conversion_method?(method_name)
156
+ CONVERSION_METHODS.include?(method_name)
157
+ end
158
+
145
159
  def ignored_classes
146
160
  cop_config.fetch('IgnoredClasses', [])
147
161
  end
@@ -10,7 +10,7 @@ module RuboCop
10
10
  # ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-darwin19]
11
11
  # -e:1: warning: `_1' is reserved for numbered parameter; consider another name
12
12
  #
13
- # Assiging to numbered parameter (from `_1` to `_9`) cause an error in Ruby 3.0.
13
+ # Assigning to a numbered parameter (from `_1` to `_9`) causes an error in Ruby 3.0.
14
14
  #
15
15
  # % ruby -ve '_1 = :value'
16
16
  # ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin19]
@@ -9,8 +9,10 @@ module RuboCop
9
9
  # should always be the same. If constants are assigned in multiple
10
10
  # locations, the result may vary depending on the order of `require`.
11
11
  #
12
- # Also, if you already have such an implementation, auto-correction may
13
- # change the result.
12
+ # @safety
13
+ # This cop is unsafe because code that is already conditionally
14
+ # assigning a constant may have its behaviour changed by
15
+ # auto-correction.
14
16
  #
15
17
  # @example
16
18
  #
@@ -6,6 +6,23 @@ module RuboCop
6
6
  # This cops looks for references of Regexp captures that are out of range
7
7
  # and thus always returns nil.
8
8
  #
9
+ # @safety
10
+ # This cop is unsafe because it is naive in how it determines what
11
+ # references are available based on the last encountered regexp, but
12
+ # it cannot handle some cases, such as conditional regexp matches, which
13
+ # leads to false positives, such as:
14
+ #
15
+ # [source,ruby]
16
+ # ----
17
+ # foo ? /(c)(b)/ =~ str : /(b)/ =~ str
18
+ # do_something if $2
19
+ # # $2 is defined for the first condition but not the second, however
20
+ # # the cop will mark this as an offense.
21
+ # ----
22
+ #
23
+ # This might be a good indication of code that should be refactored,
24
+ # however.
25
+ #
9
26
  # @example
10
27
  #
11
28
  # /(foo)bar/ =~ 'foobar'
@@ -9,6 +9,16 @@ module RuboCop
9
9
  # example, mistranslating an array of literals to percent string notation)
10
10
  # rather than meant to be part of the resulting strings.
11
11
  #
12
+ # @safety
13
+ # The cop is unsafe because the correction changes the values in the array
14
+ # and that might have been done purposely.
15
+ #
16
+ # [source,ruby]
17
+ # ----
18
+ # %w('foo', "bar") #=> ["'foo',", '"bar"']
19
+ # %w(foo bar) #=> ['foo', 'bar']
20
+ # ----
21
+ #
12
22
  # @example
13
23
  #
14
24
  # # bad
@@ -13,6 +13,10 @@ module RuboCop
13
13
  # `Exception`. Alternatively, make `Exception` a fully qualified class
14
14
  # name with an explicit namespace.
15
15
  #
16
+ # @safety
17
+ # This cop is unsafe because it will change the exception class being
18
+ # raised, which is a change in behaviour.
19
+ #
16
20
  # @example
17
21
  # # bad
18
22
  # raise Exception, 'Error message here'
@@ -7,13 +7,14 @@ module RuboCop
7
7
  # `instance_of?`, `kind_of?`, `is_a?`, `eql?`, `respond_to?`, and `equal?` methods
8
8
  # are checked by default. These are customizable with `AllowedMethods` option.
9
9
  #
10
- # This cop is marked as unsafe, because auto-correction can change the
11
- # return type of the expression. An offending expression that previously
12
- # could return `nil` will be auto-corrected to never return `nil`.
13
- #
14
10
  # In the example below, the safe navigation operator (`&.`) is unnecessary
15
11
  # because `NilClass` has methods like `respond_to?` and `is_a?`.
16
12
  #
13
+ # @safety
14
+ # This cop is unsafe, because auto-correction can change the return type of
15
+ # the expression. An offending expression that previously could return `nil`
16
+ # will be auto-corrected to never return `nil`.
17
+ #
17
18
  # @example
18
19
  # # bad
19
20
  # do_something if attrs&.respond_to?(:[])
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # Checks for uses a file requiring itself with `require_relative`.
7
+ #
8
+ # @example
9
+ #
10
+ # # bad
11
+ #
12
+ # # foo.rb
13
+ # require_relative 'foo'
14
+ # require_relative 'bar'
15
+ #
16
+ # # good
17
+ #
18
+ # # foo.rb
19
+ # require_relative 'bar'
20
+ #
21
+ class RequireRelativeSelfPath < Base
22
+ include RangeHelp
23
+ extend AutoCorrector
24
+
25
+ MSG = 'Remove the `require_relative` that requires itself.'
26
+ RESTRICT_ON_SEND = %i[require_relative].freeze
27
+
28
+ def on_send(node)
29
+ return unless (required_feature = node.first_argument)
30
+ return unless required_feature.respond_to?(:value)
31
+ return unless same_file?(processed_source.file_path, required_feature.value)
32
+
33
+ add_offense(node) do |corrector|
34
+ corrector.remove(range_by_whole_lines(node.source_range, include_final_newline: true))
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ def same_file?(file_path, required_feature)
41
+ file_path == required_feature || remove_ext(file_path) == required_feature
42
+ end
43
+
44
+ def remove_ext(file_path)
45
+ File.basename(file_path, File.extname(file_path))
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -10,7 +10,7 @@ module RuboCop
10
10
  #
11
11
  # NOTE: Shadowing of variables in block passed to `Ractor.new` is allowed
12
12
  # because `Ractor` should not access outer variables.
13
- # eg. following syle is encouraged:
13
+ # eg. following style is encouraged:
14
14
  #
15
15
  # worker_id, pipe = env
16
16
  # Ractor.new(worker_id, pipe) do |worker_id, pipe|
@@ -143,7 +143,7 @@ module RuboCop
143
143
  # Although some operators can be converted to symbols normally
144
144
  # (ie. `:==`), these are not accepted as hash keys and will
145
145
  # raise a syntax error (eg. `{ ==: ... }`). Therefore, if the
146
- # symbol does not start with an alpha-numeric or underscore, it
146
+ # symbol does not start with an alphanumeric or underscore, it
147
147
  # will be ignored.
148
148
  return unless node.value.to_s.match?(/\A[a-z0-9_]/i)
149
149
 
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # This cop checks for "triple quotes" (strings delimted by any odd number
6
+ # This cop checks for "triple quotes" (strings delimited by any odd number
7
7
  # of quotes greater than 1).
8
8
  #
9
9
  # Ruby allows multiple strings to be implicitly concatenated by just
@@ -13,14 +13,19 @@ module RuboCop
13
13
  # Keyword arguments (including `**kwargs`) do not get counted towards
14
14
  # this, as they are not used by the methods in question.
15
15
  #
16
- # NOTE: This cop matches for method names only and hence cannot tell apart
17
- # methods with same name in different classes.
18
- #
19
16
  # Method names and their expected arity can be configured like this:
20
17
  #
18
+ # [source,yaml]
19
+ # ----
21
20
  # Methods:
22
21
  # inject: 2
23
22
  # reduce: 2
23
+ # ----
24
+ #
25
+ # @safety
26
+ # This cop matches for method names only and hence cannot tell apart
27
+ # methods with same name in different classes, which may lead to a
28
+ # false positive.
24
29
  #
25
30
  # @example
26
31
  # # bad
@@ -87,9 +87,8 @@ module RuboCop
87
87
  end
88
88
 
89
89
  def ignored_method?(body)
90
- cop_config['IgnoreEmptyMethods'] && body.nil? ||
91
- cop_config['IgnoreNotImplementedMethods'] &&
92
- not_implemented?(body)
90
+ (cop_config['IgnoreEmptyMethods'] && body.nil?) ||
91
+ (cop_config['IgnoreNotImplementedMethods'] && not_implemented?(body))
93
92
  end
94
93
 
95
94
  def message(variable)
@@ -6,8 +6,9 @@ module RuboCop
6
6
  # This cop checks for useless method definitions, specifically: empty constructors
7
7
  # and methods just delegating to `super`.
8
8
  #
9
- # This cop is marked as unsafe as it can trigger false positives for cases when
10
- # an empty constructor just overrides the parent constructor, which is bad anyway.
9
+ # @safety
10
+ # This cop is unsafe as it can register false positives for cases when an empty
11
+ # constructor just overrides the parent constructor, which is bad anyway.
11
12
  #
12
13
  # @example
13
14
  # # bad
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # This cop looks for `ruby2_keywords` calls for methods that do not need it.
7
+ #
8
+ # `ruby2_keywords` should only be called on methods that accept an argument splat
9
+ # (`*args`) but do not explicit keyword arguments (`k:` or `k: true`) or
10
+ # a keyword splat (`**kwargs`).
11
+ #
12
+ # @example
13
+ # # good (splat argument without keyword arguments)
14
+ # ruby2_keywords def foo(*args); end
15
+ #
16
+ # # bad (no arguments)
17
+ # ruby2_keywords def foo; end
18
+ #
19
+ # # good
20
+ # def foo; end
21
+ #
22
+ # # bad (positional argument)
23
+ # ruby2_keywords def foo(arg); end
24
+ #
25
+ # # good
26
+ # def foo(arg); end
27
+ #
28
+ # # bad (double splatted argument)
29
+ # ruby2_keywords def foo(**args); end
30
+ #
31
+ # # good
32
+ # def foo(**args); end
33
+ #
34
+ # # bad (keyword arguments)
35
+ # ruby2_keywords def foo(i:, j:); end
36
+ #
37
+ # # good
38
+ # def foo(i:, j:); end
39
+ #
40
+ # # bad (splat argument with keyword arguments)
41
+ # ruby2_keywords def foo(*args, i:, j:); end
42
+ #
43
+ # # good
44
+ # def foo(*args, i:, j:); end
45
+ #
46
+ # # bad (splat argument with double splat)
47
+ # ruby2_keywords def foo(*args, **kwargs); end
48
+ #
49
+ # # good
50
+ # def foo(*args, **kwargs); end
51
+ #
52
+ # # bad (ruby2_keywords given a symbol)
53
+ # def foo; end
54
+ # ruby2_keywords :foo
55
+ #
56
+ # # good
57
+ # def foo; end
58
+ #
59
+ # # bad (ruby2_keywords with dynamic method)
60
+ # define_method(:foo) { |arg| }
61
+ # ruby2_keywords :foo
62
+ #
63
+ # # good
64
+ # define_method(:foo) { |arg| }
65
+ #
66
+ class UselessRuby2Keywords < Base
67
+ MSG = '`ruby2_keywords` is unnecessary for method `%<method_name>s`.'
68
+ RESTRICT_ON_SEND = %i[ruby2_keywords].freeze
69
+
70
+ # Looks for statically or dynamically defined methods with a given name
71
+ # @!method method_definition(node, method_name)
72
+ def_node_matcher :method_definition, <<~PATTERN
73
+ {
74
+ (def %1 ...)
75
+ ({block numblock} (send _ :define_method (sym %1)) ...)
76
+ }
77
+ PATTERN
78
+
79
+ def on_send(node)
80
+ if node.first_argument.def_type?
81
+ inspect_def(node, node.first_argument)
82
+ elsif node.first_argument.sym_type?
83
+ inspect_sym(node, node.first_argument)
84
+ end
85
+ end
86
+
87
+ private
88
+
89
+ def inspect_def(node, def_node)
90
+ return if allowed_arguments(def_node.arguments)
91
+
92
+ add_offense(node.loc.selector, message: format(MSG, method_name: def_node.method_name))
93
+ end
94
+
95
+ def inspect_sym(node, sym_node)
96
+ return unless node.parent
97
+
98
+ method_name = sym_node.value
99
+ definition = node.parent.each_child_node.detect { |n| method_definition(n, method_name) }
100
+
101
+ return unless definition
102
+ return if allowed_arguments(definition.arguments)
103
+
104
+ add_offense(node, message: format(MSG, method_name: method_name))
105
+ end
106
+
107
+ # `ruby2_keywords` is only allowed if there's a `restarg` and no keyword arguments
108
+ def allowed_arguments(arguments)
109
+ return false if arguments.empty?
110
+
111
+ arguments.each_child_node(:restarg).any? &&
112
+ arguments.each_child_node(:kwarg, :kwoptarg, :kwrestarg).none?
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
@@ -5,11 +5,14 @@ module RuboCop
5
5
  module Lint
6
6
  # This cop checks for setter call to local variable as the final
7
7
  # expression of a function definition.
8
- # Its auto-correction is marked as unsafe because return value will be changed.
9
8
  #
10
- # NOTE: There are edge cases in which the local variable references a
11
- # value that is also accessible outside the local scope. This is not
12
- # detected by the cop, and it can yield a false positive.
9
+ # @safety
10
+ # There are edge cases in which the local variable references a
11
+ # value that is also accessible outside the local scope. This is not
12
+ # detected by the cop, and it can yield a false positive.
13
+ #
14
+ # As well, auto-correction is unsafe because the method's
15
+ # return value will be changed.
13
16
  #
14
17
  # @example
15
18
  #
@@ -7,8 +7,9 @@ module RuboCop
7
7
  # (when the integer <= 0) or that will only ever yield once
8
8
  # (`1.times`).
9
9
  #
10
- # This cop is marked as unsafe as `times` returns its receiver, which
11
- # is *usually* OK, but might change behavior.
10
+ # @safety
11
+ # This cop is unsafe as `times` returns its receiver, which is
12
+ # *usually* OK, but might change behavior.
12
13
  #
13
14
  # @example
14
15
  # # bad
@@ -65,7 +66,7 @@ module RuboCop
65
66
  private
66
67
 
67
68
  def never_process?(count, node)
68
- count < 1 || node.block_type? && node.body.nil?
69
+ count < 1 || (node.block_type? && node.body.nil?)
69
70
  end
70
71
 
71
72
  def remove_node(corrector, node)
@@ -8,6 +8,12 @@ module RuboCop
8
8
  # (method calls), and conditions. See http://c2.com/cgi/wiki?AbcMetric
9
9
  # and https://en.wikipedia.org/wiki/ABC_Software_Metric.
10
10
  #
11
+ # Interpreting ABC size:
12
+ #
13
+ # * <= 17 satisfactory
14
+ # * 18..30 unsatisfactory
15
+ # * > 30 dangerous
16
+ #
11
17
  # You can have repeated "attributes" calls count as a single "branch".
12
18
  # For this purpose, attributes are any method with no argument; no attempt
13
19
  # is meant to distinguish actual `attr_reader` from other methods.
@@ -9,6 +9,9 @@ module RuboCop
9
9
  # Keyword arguments can optionally be excluded from the total count,
10
10
  # as they add less complexity than positional or optional parameters.
11
11
  #
12
+ # NOTE: Explicit block argument `&block` is not counted to prevent
13
+ # erroneous change that is avoided by making block argument implicit.
14
+ #
12
15
  # @example Max: 3
13
16
  # # good
14
17
  # def foo(a, b, c = 1)
@@ -94,9 +97,9 @@ module RuboCop
94
97
 
95
98
  def args_count(node)
96
99
  if count_keyword_args?
97
- node.children.size
100
+ node.children.count { |a| !a.blockarg_type? }
98
101
  else
99
- node.children.count { |a| !NAMED_KEYWORD_TYPES.include?(a.type) }
102
+ node.children.count { |a| !NAMED_KEYWORD_TYPES.include?(a.type) && !a.blockarg_type? }
100
103
  end
101
104
  end
102
105
 
@@ -45,7 +45,7 @@ module RuboCop
45
45
  else
46
46
  # Otherwise, the case node gets 0.8 complexity points and each
47
47
  # when gets 0.2.
48
- (0.8 + 0.2 * nb_branches).round
48
+ (0.8 + (0.2 * nb_branches)).round
49
49
  end
50
50
  when :if
51
51
  node.else? && !node.elsif? ? 2 : 1
@@ -46,7 +46,7 @@ module RuboCop
46
46
  visit_depth_last(@node) { |child| calculate_node(child) }
47
47
 
48
48
  [
49
- Math.sqrt(@assignment**2 + @branch**2 + @condition**2).round(2),
49
+ Math.sqrt((@assignment**2) + (@branch**2) + (@condition**2)).round(2),
50
50
  "<#{@assignment}, #{@branch}, #{@condition}>"
51
51
  ]
52
52
  end
@@ -147,7 +147,7 @@ module RuboCop
147
147
 
148
148
  # Returns true for lines that shall not be included in the count.
149
149
  def irrelevant_line?(source_line)
150
- source_line.blank? || !count_comments? && comment_line?(source_line)
150
+ source_line.blank? || (!count_comments? && comment_line?(source_line))
151
151
  end
152
152
 
153
153
  def count_comments?