rubocop 1.18.1 → 1.22.3

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 (249) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +116 -23
  4. data/lib/rubocop/cli.rb +18 -0
  5. data/lib/rubocop/config.rb +5 -0
  6. data/lib/rubocop/config_loader.rb +5 -3
  7. data/lib/rubocop/config_loader_resolver.rb +22 -7
  8. data/lib/rubocop/config_validator.rb +27 -6
  9. data/lib/rubocop/cop/base.rb +3 -3
  10. data/lib/rubocop/cop/bundler/gem_comment.rb +3 -3
  11. data/lib/rubocop/cop/bundler/gem_filename.rb +103 -0
  12. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +45 -21
  13. data/lib/rubocop/cop/bundler/ordered_gems.rb +3 -12
  14. data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +2 -2
  15. data/lib/rubocop/cop/correctors/line_break_corrector.rb +1 -1
  16. data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +11 -10
  17. data/lib/rubocop/cop/correctors/require_library_corrector.rb +23 -0
  18. data/lib/rubocop/cop/documentation.rb +1 -1
  19. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +3 -12
  20. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +31 -24
  21. data/lib/rubocop/cop/generator.rb +14 -8
  22. data/lib/rubocop/cop/internal_affairs/inherit_deprecated_cop_class.rb +34 -0
  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/undefined_config.rb +71 -0
  26. data/lib/rubocop/cop/internal_affairs.rb +3 -0
  27. data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
  28. data/lib/rubocop/cop/layout/assignment_indentation.rb +1 -1
  29. data/lib/rubocop/cop/layout/block_alignment.rb +3 -3
  30. data/lib/rubocop/cop/layout/class_structure.rb +7 -2
  31. data/lib/rubocop/cop/layout/dot_position.rb +34 -5
  32. data/lib/rubocop/cop/layout/empty_comment.rb +1 -1
  33. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +9 -0
  34. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +7 -4
  35. data/lib/rubocop/cop/layout/end_alignment.rb +9 -2
  36. data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -1
  37. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +1 -1
  38. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +1 -1
  39. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
  40. data/lib/rubocop/cop/layout/hash_alignment.rb +22 -18
  41. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +1 -1
  42. data/lib/rubocop/cop/layout/heredoc_indentation.rb +0 -7
  43. data/lib/rubocop/cop/layout/indentation_style.rb +2 -2
  44. data/lib/rubocop/cop/layout/indentation_width.rb +1 -1
  45. data/lib/rubocop/cop/layout/leading_comment_space.rb +2 -2
  46. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +36 -17
  47. data/lib/rubocop/cop/layout/line_length.rb +9 -7
  48. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -1
  49. data/lib/rubocop/cop/layout/multiline_block_layout.rb +3 -3
  50. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +3 -0
  51. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +1 -1
  52. data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -0
  53. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +23 -10
  54. data/lib/rubocop/cop/layout/single_line_block_chain.rb +15 -4
  55. data/lib/rubocop/cop/layout/space_after_not.rb +1 -0
  56. data/lib/rubocop/cop/layout/space_around_equals_in_parameter_default.rb +2 -1
  57. data/lib/rubocop/cop/layout/space_around_keyword.rb +2 -2
  58. data/lib/rubocop/cop/layout/space_around_operators.rb +12 -1
  59. data/lib/rubocop/cop/layout/space_before_brackets.rb +1 -0
  60. data/lib/rubocop/cop/layout/space_before_comment.rb +2 -2
  61. data/lib/rubocop/cop/layout/space_inside_parens.rb +78 -32
  62. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +1 -1
  63. data/lib/rubocop/cop/layout/trailing_whitespace.rb +24 -1
  64. data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +111 -0
  65. data/lib/rubocop/cop/lint/ambiguous_range.rb +105 -0
  66. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +5 -2
  67. data/lib/rubocop/cop/lint/assignment_in_condition.rb +7 -5
  68. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +18 -5
  69. data/lib/rubocop/cop/lint/boolean_symbol.rb +5 -0
  70. data/lib/rubocop/cop/lint/debugger.rb +2 -4
  71. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +4 -4
  72. data/lib/rubocop/cop/lint/deprecated_constants.rb +3 -2
  73. data/lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb +24 -1
  74. data/lib/rubocop/cop/lint/duplicate_branch.rb +2 -1
  75. data/lib/rubocop/cop/lint/duplicate_methods.rb +8 -5
  76. data/lib/rubocop/cop/lint/else_layout.rb +10 -6
  77. data/lib/rubocop/cop/lint/empty_in_pattern.rb +1 -1
  78. data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -1
  79. data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -1
  80. data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +12 -3
  81. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +67 -0
  82. data/lib/rubocop/cop/lint/interpolation_check.rb +5 -0
  83. data/lib/rubocop/cop/lint/loop.rb +4 -3
  84. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +5 -1
  85. data/lib/rubocop/cop/lint/number_conversion.rb +12 -1
  86. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -1
  87. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +4 -2
  88. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +17 -0
  89. data/lib/rubocop/cop/lint/percent_string_array.rb +10 -0
  90. data/lib/rubocop/cop/lint/raise_exception.rb +4 -0
  91. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +5 -4
  92. data/lib/rubocop/cop/lint/require_relative_self_path.rb +50 -0
  93. data/lib/rubocop/cop/lint/shadowed_argument.rb +1 -1
  94. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +1 -1
  95. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  96. data/lib/rubocop/cop/lint/triple_quotes.rb +1 -1
  97. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +8 -3
  98. data/lib/rubocop/cop/lint/unused_method_argument.rb +2 -3
  99. data/lib/rubocop/cop/lint/useless_method_definition.rb +3 -2
  100. data/lib/rubocop/cop/lint/useless_setter_call.rb +7 -4
  101. data/lib/rubocop/cop/lint/useless_times.rb +5 -4
  102. data/lib/rubocop/cop/metrics/abc_size.rb +6 -0
  103. data/lib/rubocop/cop/metrics/parameter_lists.rb +5 -2
  104. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  105. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -1
  106. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
  107. data/lib/rubocop/cop/mixin/annotation_comment.rb +57 -34
  108. data/lib/rubocop/cop/mixin/check_line_breakable.rb +2 -2
  109. data/lib/rubocop/cop/mixin/code_length.rb +1 -1
  110. data/lib/rubocop/cop/mixin/documentation_comment.rb +5 -2
  111. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -2
  112. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +23 -1
  113. data/lib/rubocop/cop/mixin/hash_transform_method.rb +9 -4
  114. data/lib/rubocop/cop/mixin/heredoc.rb +5 -0
  115. data/lib/rubocop/cop/mixin/multiline_element_indentation.rb +1 -1
  116. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +2 -2
  117. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
  118. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +9 -1
  119. data/lib/rubocop/cop/mixin/percent_array.rb +18 -7
  120. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +9 -1
  121. data/lib/rubocop/cop/mixin/require_library.rb +59 -0
  122. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
  123. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +2 -2
  124. data/lib/rubocop/cop/mixin/statement_modifier.rb +1 -1
  125. data/lib/rubocop/cop/mixin/string_literals_help.rb +5 -1
  126. data/lib/rubocop/cop/mixin/trailing_body.rb +1 -1
  127. data/lib/rubocop/cop/naming/ascii_identifiers.rb +0 -3
  128. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  129. data/lib/rubocop/cop/naming/constant_name.rb +1 -1
  130. data/lib/rubocop/cop/naming/inclusive_language.rb +27 -10
  131. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +5 -4
  132. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +7 -0
  133. data/lib/rubocop/cop/security/io_methods.rb +49 -0
  134. data/lib/rubocop/cop/security/json_load.rb +8 -7
  135. data/lib/rubocop/cop/security/open.rb +4 -0
  136. data/lib/rubocop/cop/security/yaml_load.rb +4 -0
  137. data/lib/rubocop/cop/style/accessor_grouping.rb +2 -2
  138. data/lib/rubocop/cop/style/and_or.rb +5 -0
  139. data/lib/rubocop/cop/style/arguments_forwarding.rb +13 -2
  140. data/lib/rubocop/cop/style/array_coercion.rb +21 -3
  141. data/lib/rubocop/cop/style/ascii_comments.rb +0 -3
  142. data/lib/rubocop/cop/style/block_delimiters.rb +50 -2
  143. data/lib/rubocop/cop/style/case_equality.rb +6 -9
  144. data/lib/rubocop/cop/style/case_like_if.rb +5 -0
  145. data/lib/rubocop/cop/style/class_and_module_children.rb +9 -0
  146. data/lib/rubocop/cop/style/collection_compact.rb +7 -5
  147. data/lib/rubocop/cop/style/collection_methods.rb +8 -6
  148. data/lib/rubocop/cop/style/combinable_loops.rb +3 -2
  149. data/lib/rubocop/cop/style/comment_annotation.rb +55 -25
  150. data/lib/rubocop/cop/style/commented_keyword.rb +9 -3
  151. data/lib/rubocop/cop/style/conditional_assignment.rb +19 -5
  152. data/lib/rubocop/cop/style/date_time.rb +5 -0
  153. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +1 -1
  154. data/lib/rubocop/cop/style/documentation.rb +23 -8
  155. data/lib/rubocop/cop/style/double_cop_disable_directive.rb +1 -7
  156. data/lib/rubocop/cop/style/double_negation.rb +27 -6
  157. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  158. data/lib/rubocop/cop/style/encoding.rb +26 -15
  159. data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
  160. data/lib/rubocop/cop/style/explicit_block_argument.rb +46 -11
  161. data/lib/rubocop/cop/style/float_division.rb +10 -2
  162. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +14 -3
  163. data/lib/rubocop/cop/style/global_std_stream.rb +4 -0
  164. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +11 -0
  165. data/lib/rubocop/cop/style/hash_each_methods.rb +5 -0
  166. data/lib/rubocop/cop/style/hash_except.rb +4 -3
  167. data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
  168. data/lib/rubocop/cop/style/hash_transform_keys.rb +4 -9
  169. data/lib/rubocop/cop/style/hash_transform_values.rb +4 -6
  170. data/lib/rubocop/cop/style/identical_conditional_branches.rb +32 -5
  171. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +18 -4
  172. data/lib/rubocop/cop/style/infinite_loop.rb +4 -3
  173. data/lib/rubocop/cop/style/inverse_methods.rb +9 -2
  174. data/lib/rubocop/cop/style/lambda_call.rb +1 -1
  175. data/lib/rubocop/cop/style/line_end_concatenation.rb +14 -1
  176. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +6 -6
  177. data/lib/rubocop/cop/style/method_def_parentheses.rb +10 -1
  178. data/lib/rubocop/cop/style/missing_else.rb +7 -0
  179. data/lib/rubocop/cop/style/module_function.rb +8 -9
  180. data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +1 -1
  181. data/lib/rubocop/cop/style/multiline_when_then.rb +1 -1
  182. data/lib/rubocop/cop/style/mutable_constant.rb +79 -14
  183. data/lib/rubocop/cop/style/negated_if.rb +1 -1
  184. data/lib/rubocop/cop/style/negated_unless.rb +1 -1
  185. data/lib/rubocop/cop/style/non_nil_check.rb +2 -2
  186. data/lib/rubocop/cop/style/not.rb +2 -2
  187. data/lib/rubocop/cop/style/numbered_parameters.rb +46 -0
  188. data/lib/rubocop/cop/style/numbered_parameters_limit.rb +50 -0
  189. data/lib/rubocop/cop/style/numeric_literals.rb +7 -8
  190. data/lib/rubocop/cop/style/numeric_predicate.rb +5 -0
  191. data/lib/rubocop/cop/style/optional_arguments.rb +4 -0
  192. data/lib/rubocop/cop/style/optional_boolean_parameter.rb +14 -4
  193. data/lib/rubocop/cop/style/parallel_assignment.rb +1 -1
  194. data/lib/rubocop/cop/style/percent_q_literals.rb +2 -2
  195. data/lib/rubocop/cop/style/preferred_hash_methods.rb +9 -4
  196. data/lib/rubocop/cop/style/quoted_symbols.rb +10 -6
  197. data/lib/rubocop/cop/style/raise_args.rb +1 -1
  198. data/lib/rubocop/cop/style/redundant_argument.rb +19 -9
  199. data/lib/rubocop/cop/style/redundant_begin.rb +25 -0
  200. data/lib/rubocop/cop/style/redundant_condition.rb +2 -3
  201. data/lib/rubocop/cop/style/redundant_fetch_block.rb +4 -0
  202. data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +12 -3
  203. data/lib/rubocop/cop/style/redundant_freeze.rb +4 -4
  204. data/lib/rubocop/cop/style/redundant_interpolation.rb +1 -1
  205. data/lib/rubocop/cop/style/redundant_percent_q.rb +2 -3
  206. data/lib/rubocop/cop/style/redundant_self.rb +10 -0
  207. data/lib/rubocop/cop/style/redundant_self_assignment.rb +4 -3
  208. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +83 -0
  209. data/lib/rubocop/cop/style/redundant_sort.rb +53 -20
  210. data/lib/rubocop/cop/style/regexp_literal.rb +3 -3
  211. data/lib/rubocop/cop/style/return_nil.rb +2 -1
  212. data/lib/rubocop/cop/style/safe_navigation.rb +13 -2
  213. data/lib/rubocop/cop/style/select_by_regexp.rb +139 -0
  214. data/lib/rubocop/cop/style/semicolon.rb +32 -24
  215. data/lib/rubocop/cop/style/single_argument_dig.rb +5 -0
  216. data/lib/rubocop/cop/style/single_line_block_params.rb +3 -1
  217. data/lib/rubocop/cop/style/single_line_methods.rb +25 -15
  218. data/lib/rubocop/cop/style/slicing_with_range.rb +13 -0
  219. data/lib/rubocop/cop/style/sole_nested_conditional.rb +4 -0
  220. data/lib/rubocop/cop/style/special_global_vars.rb +25 -0
  221. data/lib/rubocop/cop/style/static_class.rb +5 -5
  222. data/lib/rubocop/cop/style/string_chars.rb +4 -2
  223. data/lib/rubocop/cop/style/string_concatenation.rb +5 -1
  224. data/lib/rubocop/cop/style/string_hash_keys.rb +4 -0
  225. data/lib/rubocop/cop/style/struct_inheritance.rb +4 -0
  226. data/lib/rubocop/cop/style/swap_values.rb +4 -2
  227. data/lib/rubocop/cop/style/symbol_array.rb +3 -3
  228. data/lib/rubocop/cop/style/symbol_proc.rb +26 -0
  229. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +19 -0
  230. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  231. data/lib/rubocop/cop/style/word_array.rb +23 -5
  232. data/lib/rubocop/cop/style/yoda_condition.rb +24 -7
  233. data/lib/rubocop/cop/style/zero_length_predicate.rb +6 -0
  234. data/lib/rubocop/cop/util.rb +22 -6
  235. data/lib/rubocop/cops_documentation_generator.rb +17 -5
  236. data/lib/rubocop/formatter/git_hub_actions_formatter.rb +1 -1
  237. data/lib/rubocop/magic_comment.rb +44 -15
  238. data/lib/rubocop/options.rb +127 -113
  239. data/lib/rubocop/rake_task.rb +1 -1
  240. data/lib/rubocop/result_cache.rb +3 -3
  241. data/lib/rubocop/rspec/cop_helper.rb +1 -1
  242. data/lib/rubocop/rspec/expect_offense.rb +6 -2
  243. data/lib/rubocop/rspec/parallel_formatter.rb +90 -0
  244. data/lib/rubocop/rspec/support.rb +1 -0
  245. data/lib/rubocop/runner.rb +2 -3
  246. data/lib/rubocop/target_finder.rb +1 -1
  247. data/lib/rubocop/version.rb +1 -1
  248. data/lib/rubocop.rb +14 -2
  249. metadata +21 -5
@@ -67,17 +67,27 @@ module RuboCop
67
67
  # so this can cause crashes in haml_lint
68
68
  return unless def_node
69
69
 
70
+ block_name = extract_block_name(def_node)
71
+
70
72
  add_offense(block_node) do |corrector|
71
73
  corrector.remove(block_body_range(block_node, send_node))
72
74
 
73
- add_block_argument(send_node, corrector)
74
- add_block_argument(def_node, corrector) if @def_nodes.add?(def_node)
75
+ add_block_argument(send_node, corrector, block_name)
76
+ add_block_argument(def_node, corrector, block_name) if @def_nodes.add?(def_node)
75
77
  end
76
78
  end
77
79
  end
78
80
 
79
81
  private
80
82
 
83
+ def extract_block_name(def_node)
84
+ if def_node.block_argument?
85
+ def_node.arguments.last.name
86
+ else
87
+ 'block'
88
+ end
89
+ end
90
+
81
91
  def yielding_arguments?(block_args, yield_args)
82
92
  yield_args = yield_args.dup.fill(
83
93
  nil,
@@ -91,20 +101,45 @@ module RuboCop
91
101
  end
92
102
  end
93
103
 
94
- def add_block_argument(node, corrector)
104
+ def add_block_argument(node, corrector, block_name)
95
105
  if node.arguments?
96
- last_arg = node.arguments.last
97
- arg_range = range_with_surrounding_comma(last_arg.source_range, :right)
98
- replacement = ' &block'
99
- replacement = ",#{replacement}" unless arg_range.source.end_with?(',')
100
- corrector.insert_after(arg_range, replacement) unless last_arg.blockarg_type?
101
- elsif node.call_type? || node.zsuper_type?
102
- corrector.insert_after(node, '(&block)')
106
+ insert_argument(node, corrector, block_name)
107
+ elsif empty_arguments?(node)
108
+ corrector.replace(node.arguments, "(&#{block_name})")
109
+ elsif call_like?(node)
110
+ correct_call_node(node, corrector, block_name)
103
111
  else
104
- corrector.insert_after(node.loc.name, '(&block)')
112
+ corrector.insert_after(node.loc.name, "(&#{block_name})")
105
113
  end
106
114
  end
107
115
 
116
+ def empty_arguments?(node)
117
+ # Is there an arguments node with only parentheses?
118
+ node.arguments.is_a?(RuboCop::AST::Node) && node.arguments.loc.begin
119
+ end
120
+
121
+ def call_like?(node)
122
+ node.call_type? || node.zsuper_type? || node.super_type?
123
+ end
124
+
125
+ def insert_argument(node, corrector, block_name)
126
+ last_arg = node.arguments.last
127
+ arg_range = range_with_surrounding_comma(last_arg.source_range, :right)
128
+ replacement = " &#{block_name}"
129
+ replacement = ",#{replacement}" unless arg_range.source.end_with?(',')
130
+ corrector.insert_after(arg_range, replacement) unless last_arg.blockarg_type?
131
+ end
132
+
133
+ def correct_call_node(node, corrector, block_name)
134
+ corrector.insert_after(node, "(&#{block_name})")
135
+ return unless node.parenthesized?
136
+
137
+ args_begin = Util.args_begin(node)
138
+ args_end = Util.args_end(node)
139
+ range = range_between(args_begin.begin_pos, args_end.end_pos)
140
+ corrector.remove(range)
141
+ end
142
+
108
143
  def block_body_range(block_node, send_node)
109
144
  range_between(send_node.loc.expression.end_pos, block_node.loc.end.end_pos)
110
145
  end
@@ -7,8 +7,16 @@ module RuboCop
7
7
  # It is recommended to either always use `fdiv` or coerce one side only.
8
8
  # This cop also provides other options for code consistency.
9
9
  #
10
- # This cop is marked as unsafe, because if operand variable is a string object
11
- # then `.to_f` will be removed and an error will occur.
10
+ # @safety
11
+ # This cop is unsafe, because if the operand variable is a string object
12
+ # then `.to_f` will be removed and an error will occur.
13
+ #
14
+ # [source,ruby]
15
+ # ----
16
+ # a = '1.2'
17
+ # b = '3.4'
18
+ # a.to_f / b.to_f # Both `to_f` calls are required here
19
+ # ----
12
20
  #
13
21
  # @example EnforcedStyle: single_coerce (default)
14
22
  # # bad
@@ -5,11 +5,22 @@ module RuboCop
5
5
  module Style
6
6
  # This cop is designed to help you transition from mutable string literals
7
7
  # to frozen string literals.
8
- # It will add the comment `# frozen_string_literal: true` to the top of
9
- # files to enable frozen string literals. Frozen string literals may be
8
+ # It will add the `# frozen_string_literal: true` magic comment to the top
9
+ # of files to enable frozen string literals. Frozen string literals may be
10
10
  # default in future Ruby. The comment will be added below a shebang and
11
11
  # encoding comment.
12
12
  #
13
+ # Note that the cop will accept files where the comment exists but is set
14
+ # to `false` instead of `true`.
15
+ #
16
+ # To require a blank line after this comment, please see
17
+ # `Layout/EmptyLineAfterMagicComment` cop.
18
+ #
19
+ # @safety
20
+ # This cop's autocorrection is unsafe since any strings mutations will
21
+ # change from being accepted to raising `FrozenError`, as all strings
22
+ # will become frozen by default, and will need to be manually refactored.
23
+ #
13
24
  # @example EnforcedStyle: always (default)
14
25
  # # The `always` style will always add the frozen string literal comment
15
26
  # # to a file, regardless of the Ruby version or if `freeze` or `<<` are
@@ -135,7 +146,7 @@ module RuboCop
135
146
 
136
147
  def frozen_string_literal_comment(processed_source)
137
148
  processed_source.find_token do |token|
138
- token.text.start_with?(FrozenStringLiteral::FROZEN_STRING_LITERAL)
149
+ token.text.start_with?(FROZEN_STRING_LITERAL)
139
150
  end
140
151
  end
141
152
 
@@ -8,6 +8,10 @@ module RuboCop
8
8
  # reassign (possibly to redirect some stream) constants in Ruby, you'll get
9
9
  # an interpreter warning if you do so.
10
10
  #
11
+ # @safety
12
+ # Autocorrection is unsafe because `STDOUT` and `$stdout` may point to different
13
+ # objects, for example.
14
+ #
11
15
  # @example
12
16
  # # bad
13
17
  # STDOUT.puts('hello')
@@ -29,6 +29,7 @@ module RuboCop
29
29
  # # good
30
30
  # [{ one: 1 }, { two: 2 }]
31
31
  class HashAsLastArrayItem < Base
32
+ include RangeHelp
32
33
  include ConfigurableEnforcedStyle
33
34
  extend AutoCorrector
34
35
 
@@ -74,6 +75,7 @@ module RuboCop
74
75
  return if node.children.empty? # Empty hash cannot be "unbraced"
75
76
 
76
77
  add_offense(node, message: 'Omit the braces around the hash.') do |corrector|
78
+ remove_last_element_trailing_comma(corrector, node.parent)
77
79
  corrector.remove(node.loc.begin)
78
80
  corrector.remove(node.loc.end)
79
81
  end
@@ -82,6 +84,15 @@ module RuboCop
82
84
  def braces_style?
83
85
  style == :braces
84
86
  end
87
+
88
+ def remove_last_element_trailing_comma(corrector, node)
89
+ range = range_with_surrounding_space(
90
+ range: node.children.last.source_range,
91
+ side: :right
92
+ ).end.resize(1)
93
+
94
+ corrector.remove(range) if range.source == ','
95
+ end
85
96
  end
86
97
  end
87
98
  end
@@ -9,6 +9,11 @@ module RuboCop
9
9
  # parentheses around the block arguments to indicate that you're not
10
10
  # working with a hash, and suppress RuboCop offenses.
11
11
  #
12
+ # @safety
13
+ # This cop is unsafe because it cannot be guaranteed that the receiver
14
+ # is a `Hash`. The `AllowedReceivers` configuration can mitigate,
15
+ # but not fully resolve, this safety issue.
16
+ #
12
17
  # @example
13
18
  # # bad
14
19
  # hash.keys.each { |k| p k }
@@ -49,7 +49,7 @@ module RuboCop
49
49
  return unless bad_method?(block) && semantically_except_method?(node, block)
50
50
 
51
51
  except_key = except_key(block)
52
- return unless safe_to_register_offense?(block, except_key)
52
+ return if except_key.nil? || !safe_to_register_offense?(block, except_key)
53
53
 
54
54
  range = offense_range(node)
55
55
  preferred_method = "except(#{except_key.source})"
@@ -81,10 +81,11 @@ module RuboCop
81
81
  end
82
82
 
83
83
  def except_key(node)
84
- key_argument = node.argument_list.first
84
+ key_argument = node.argument_list.first.source
85
85
  lhs, _method_name, rhs = *node.body
86
+ return if [lhs, rhs].map(&:source).none?(key_argument)
86
87
 
87
- [lhs, rhs].find { |operand| operand.source != key_argument.source }
88
+ [lhs, rhs].find { |operand| operand.source != key_argument }
88
89
  end
89
90
 
90
91
  def offense_range(node)
@@ -74,7 +74,7 @@ module RuboCop
74
74
  ruby19_no_mixed_keys_check(pairs)
75
75
  elsif style == :no_mixed_keys
76
76
  no_mixed_keys_check(pairs)
77
- elsif node.source.include?('=>')
77
+ else
78
78
  ruby19_check(pairs)
79
79
  end
80
80
  end
@@ -8,12 +8,10 @@ module RuboCop
8
8
  # transforming the keys of a hash, and tries to use a simpler & faster
9
9
  # call to `transform_keys` instead.
10
10
  #
11
- # This can produce false positives if we are transforming an enumerable
12
- # of key-value-like pairs that isn't actually a hash, e.g.:
13
- # `[[k1, v1], [k2, v2], ...]`
14
- #
15
- # This cop should only be enabled on Ruby version 2.5 or newer
16
- # (`transform_keys` was added in Ruby 2.5.)
11
+ # @safety
12
+ # This cop is unsafe, as it can produce false positives if we are
13
+ # transforming an enumerable of key-value-like pairs that isn't actually
14
+ # a hash, e.g.: `[[k1, v1], [k2, v2], ...]`
17
15
  #
18
16
  # @example
19
17
  # # bad
@@ -27,11 +25,8 @@ module RuboCop
27
25
  # {a: 1, b: 2}.transform_keys { |k| k.to_s }
28
26
  class HashTransformKeys < Base
29
27
  include HashTransformMethod
30
- extend TargetRubyVersion
31
28
  extend AutoCorrector
32
29
 
33
- minimum_target_ruby_version 2.5
34
-
35
30
  # @!method on_bad_each_with_object(node)
36
31
  def_node_matcher :on_bad_each_with_object, <<~PATTERN
37
32
  (block
@@ -8,12 +8,10 @@ module RuboCop
8
8
  # transforming the values of a hash, and tries to use a simpler & faster
9
9
  # call to `transform_values` instead.
10
10
  #
11
- # This can produce false positives if we are transforming an enumerable
12
- # of key-value-like pairs that isn't actually a hash, e.g.:
13
- # `[[k1, v1], [k2, v2], ...]`
14
- #
15
- # This cop should only be enabled on Ruby version 2.4 or newer
16
- # (`transform_values` was added in Ruby 2.4.)
11
+ # @safety
12
+ # This cop is unsafe, as it can produce false positives if we are
13
+ # transforming an enumerable of key-value-like pairs that isn't actually
14
+ # a hash, e.g.: `[[k1, v1], [k2, v2], ...]`
17
15
  #
18
16
  # @example
19
17
  # # bad
@@ -11,6 +11,24 @@ module RuboCop
11
11
  # checks for duplicated conditional branches. The name will probably be changed
12
12
  # in a future major RuboCop release.
13
13
  #
14
+ # @safety
15
+ # Auto-correction is unsafe because changing the order of method invocations
16
+ # may change the behaviour of the code. For example:
17
+ #
18
+ # [source,ruby]
19
+ # ----
20
+ # if method_that_modifies_global_state # 1
21
+ # method_that_relies_on_global_state # 2
22
+ # foo # 3
23
+ # else
24
+ # method_that_relies_on_global_state # 2
25
+ # bar # 3
26
+ # end
27
+ # ----
28
+ #
29
+ # In this example, `method_that_relies_on_global_state` will be moved before
30
+ # `method_that_modifies_global_state`, which changes the behaviour of the program.
31
+ #
14
32
  # @example
15
33
  # # bad
16
34
  # if condition
@@ -124,21 +142,30 @@ module RuboCop
124
142
  return if branches.any?(&:nil?)
125
143
 
126
144
  tails = branches.map { |branch| tail(branch) }
127
- check_expressions(node, tails, :after_condition) if duplicated_expressions?(tails)
145
+ check_expressions(node, tails, :after_condition) if duplicated_expressions?(node, tails)
128
146
 
129
147
  heads = branches.map { |branch| head(branch) }
130
- check_expressions(node, heads, :before_condition) if duplicated_expressions?(heads)
148
+ check_expressions(node, heads, :before_condition) if duplicated_expressions?(node, heads)
131
149
  end
132
150
 
133
- def duplicated_expressions?(expressions)
134
- expressions.size > 1 && expressions.uniq.one?
151
+ def duplicated_expressions?(node, expressions)
152
+ unique_expressions = expressions.uniq
153
+ return false unless expressions.size >= 1 && unique_expressions.one?
154
+
155
+ unique_expression = unique_expressions.first
156
+ return true unless unique_expression.assignment?
157
+
158
+ lhs = unique_expression.child_nodes.first
159
+ node.condition.child_nodes.none? { |n| n.source == lhs.source if n.variable? }
135
160
  end
136
161
 
137
- def check_expressions(node, expressions, insert_position)
162
+ def check_expressions(node, expressions, insert_position) # rubocop:disable Metrics/MethodLength
138
163
  inserted_expression = false
139
164
 
140
165
  expressions.each do |expression|
141
166
  add_offense(expression) do |corrector|
167
+ next if node.if_type? && node.ternary?
168
+
142
169
  range = range_by_whole_lines(expression.source_range, include_final_newline: true)
143
170
  corrector.remove(range)
144
171
  next if inserted_expression
@@ -6,8 +6,10 @@ module RuboCop
6
6
  # This cop checks for redundant `if` with boolean literal branches.
7
7
  # It checks only conditions to return boolean value (`true` or `false`) for safe detection.
8
8
  # The conditions to be checked are comparison methods, predicate methods, and double negative.
9
- # However, auto-correction is unsafe because there is no guarantee that all predicate methods
10
- # will return boolean value. Those methods can be allowed with `AllowedMethods` config.
9
+ #
10
+ # @safety
11
+ # Auto-correction is unsafe because there is no guarantee that all predicate methods
12
+ # will return a boolean value. Those methods can be allowed with `AllowedMethods` config.
11
13
  #
12
14
  # @example
13
15
  # # bad
@@ -23,6 +25,17 @@ module RuboCop
23
25
  # # good
24
26
  # foo == bar
25
27
  #
28
+ # @example
29
+ # # bad
30
+ # if foo.do_something?
31
+ # true
32
+ # else
33
+ # false
34
+ # end
35
+ #
36
+ # # good (but potentially an unsafe correction)
37
+ # foo.do_something?
38
+ #
26
39
  # @example AllowedMethods: ['nonzero?']
27
40
  # # good
28
41
  # num.nonzero? ? true : false
@@ -109,12 +122,13 @@ module RuboCop
109
122
  end
110
123
 
111
124
  def opposite_condition?(node)
112
- !node.unless? && node.if_branch.false_type? || node.unless? && node.if_branch.true_type?
125
+ (!node.unless? && node.if_branch.false_type?) ||
126
+ (node.unless? && node.if_branch.true_type?)
113
127
  end
114
128
 
115
129
  def require_parentheses?(condition)
116
130
  condition.and_type? || condition.or_type? ||
117
- condition.send_type? && condition.comparison_method?
131
+ (condition.send_type? && condition.comparison_method?)
118
132
  end
119
133
  end
120
134
  end
@@ -5,9 +5,10 @@ module RuboCop
5
5
  module Style
6
6
  # Use `Kernel#loop` for infinite loops.
7
7
  #
8
- # This cop is marked as unsafe as the rule does not necessarily
9
- # apply if the body might raise a `StopIteration` exception; contrary to
10
- # other infinite loops, `Kernel#loop` silently rescues that and returns `nil`.
8
+ # @safety
9
+ # This cop is unsafe as the rule should not necessarily apply if the loop
10
+ # body might raise a `StopIteration` exception; contrary to other infinite
11
+ # loops, `Kernel#loop` silently rescues that and returns `nil`.
11
12
  #
12
13
  # @example
13
14
  # # bad
@@ -5,11 +5,18 @@ module RuboCop
5
5
  module Style
6
6
  # This cop check for usages of not (`not` or `!`) called on a method
7
7
  # when an inverse of that method can be used instead.
8
+ #
8
9
  # Methods that can be inverted by a not (`not` or `!`) should be defined
9
- # in `InverseMethods`
10
+ # in `InverseMethods`.
11
+ #
10
12
  # Methods that are inverted by inverting the return
11
13
  # of the block that is passed to the method should be defined in
12
- # `InverseBlocks`
14
+ # `InverseBlocks`.
15
+ #
16
+ # @safety
17
+ # This cop is unsafe because it cannot be guaranteed that the method
18
+ # and its inverse method are both defined on receiver, and also are
19
+ # actually inverse of each other.
13
20
  #
14
21
  # @example
15
22
  # # bad
@@ -52,7 +52,7 @@ module RuboCop
52
52
  private
53
53
 
54
54
  def offense?(node)
55
- explicit_style? && node.implicit_call? || implicit_style? && !node.implicit_call?
55
+ (explicit_style? && node.implicit_call?) || (implicit_style? && !node.implicit_call?)
56
56
  end
57
57
 
58
58
  def message(_node)
@@ -6,6 +6,19 @@ module RuboCop
6
6
  # This cop checks for string literal concatenation at
7
7
  # the end of a line.
8
8
  #
9
+ # @safety
10
+ # This cop is unsafe because it cannot be guaranteed that the
11
+ # receiver is a string, in which case replacing `<<` with `\`
12
+ # would result in a syntax error.
13
+ #
14
+ # For example, this would be a false positive:
15
+ # [source,ruby]
16
+ # ----
17
+ # array << 'foo' <<
18
+ # 'bar' <<
19
+ # 'baz'
20
+ # ----
21
+ #
9
22
  # @example
10
23
  #
11
24
  # # bad
@@ -46,7 +59,7 @@ module RuboCop
46
59
 
47
60
  return unless eligible_token_set?(predecessor, operator, successor)
48
61
 
49
- return if operator.line == successor.line
62
+ return if same_line?(operator, successor)
50
63
 
51
64
  next_successor = token_after_last_string(successor, index)
52
65
 
@@ -93,8 +93,8 @@ module RuboCop
93
93
  parent = node.parent&.block_type? ? node.parent.parent : node.parent
94
94
  parent &&
95
95
  (logical_operator?(parent) ||
96
- parent.send_type? &&
97
- parent.arguments.any? { |argument| logical_operator?(argument) })
96
+ (parent.send_type? &&
97
+ parent.arguments.any? { |argument| logical_operator?(argument) }))
98
98
  end
99
99
 
100
100
  def call_in_optional_arguments?(node)
@@ -122,14 +122,14 @@ module RuboCop
122
122
 
123
123
  def call_as_argument_or_chain?(node)
124
124
  node.parent &&
125
- (node.parent.send_type? && !assigned_before?(node.parent, node) ||
125
+ ((node.parent.send_type? && !assigned_before?(node.parent, node)) ||
126
126
  node.parent.csend_type? || node.parent.super_type? || node.parent.yield_type?)
127
127
  end
128
128
 
129
129
  def hash_literal_in_arguments?(node)
130
130
  node.arguments.any? do |n|
131
131
  hash_literal?(n) ||
132
- n.send_type? && node.descendants.any? { |descendant| hash_literal?(descendant) }
132
+ (n.send_type? && node.descendants.any? { |descendant| hash_literal?(descendant) })
133
133
  end
134
134
  end
135
135
 
@@ -171,8 +171,8 @@ module RuboCop
171
171
  end
172
172
 
173
173
  def unary_literal?(node)
174
- node.numeric_type? && node.sign? ||
175
- node.parent&.send_type? && node.parent&.unary_operation?
174
+ (node.numeric_type? && node.sign?) ||
175
+ (node.parent&.send_type? && node.parent&.unary_operation?)
176
176
  end
177
177
 
178
178
  def assigned_before?(node, target)
@@ -96,7 +96,7 @@ module RuboCop
96
96
  MSG_MISSING = 'Use def with parentheses when there are parameters.'
97
97
 
98
98
  def on_def(node)
99
- return if node.endless?
99
+ return if forced_parentheses?(node)
100
100
 
101
101
  args = node.arguments
102
102
 
@@ -129,6 +129,15 @@ module RuboCop
129
129
  corrector.insert_after(arguments_range, ')')
130
130
  end
131
131
 
132
+ def forced_parentheses?(node)
133
+ # Regardless of style, parentheses are necessary for:
134
+ # 1. Endless methods
135
+ # 2. Argument lists containing a `forward-arg` (`...`)
136
+ # Removing the parens would be a syntax error here.
137
+
138
+ node.endless? || node.arguments.any?(&:forward_arg_type?)
139
+ end
140
+
132
141
  def require_parentheses?(args)
133
142
  style == :require_parentheses ||
134
143
  (style == :require_no_parentheses_except_multiline && args.multiline?)
@@ -5,6 +5,9 @@ module RuboCop
5
5
  module Style
6
6
  # Checks for `if` expressions that do not have an `else` branch.
7
7
  #
8
+ # NOTE: Pattern matching is allowed to have no `else` branch because unlike `if` and `case`,
9
+ # it raises `NoMatchingPatternError` if the pattern doesn't match and without having `else`.
10
+ #
8
11
  # Supported styles are: if, case, both.
9
12
  #
10
13
  # @example EnforcedStyle: if
@@ -114,6 +117,10 @@ module RuboCop
114
117
  check(node)
115
118
  end
116
119
 
120
+ def on_case_match(node)
121
+ # do nothing.
122
+ end
123
+
117
124
  private
118
125
 
119
126
  def check(node)
@@ -6,7 +6,14 @@ module RuboCop
6
6
  # This cop checks for use of `extend self` or `module_function` in a
7
7
  # module.
8
8
  #
9
- # Supported styles are: module_function, extend_self, forbidden.
9
+ # Supported styles are: module_function, extend_self, forbidden. `forbidden`
10
+ # style prohibits the usage of both styles.
11
+ #
12
+ # NOTE: the cop won't be activated when the module contains any private methods.
13
+ #
14
+ # @safety
15
+ # Autocorrection is unsafe (and is disabled by default) because `extend self`
16
+ # and `module_function` do not behave exactly the same.
10
17
  #
11
18
  # @example EnforcedStyle: module_function (default)
12
19
  # # bad
@@ -21,9 +28,6 @@ module RuboCop
21
28
  # # ...
22
29
  # end
23
30
  #
24
- # In case there are private methods, the cop won't be activated.
25
- # Otherwise, it forces to change the flow of the default code.
26
- #
27
31
  # @example EnforcedStyle: module_function (default)
28
32
  # # good
29
33
  # module Test
@@ -46,8 +50,6 @@ module RuboCop
46
50
  # # ...
47
51
  # end
48
52
  #
49
- # The option `forbidden` prohibits the usage of both styles.
50
- #
51
53
  # @example EnforcedStyle: forbidden
52
54
  # # bad
53
55
  # module Test
@@ -68,9 +70,6 @@ module RuboCop
68
70
  # private
69
71
  # # ...
70
72
  # end
71
- #
72
- # These offenses are not safe to auto-correct since there are different
73
- # implications to each approach.
74
73
  class ModuleFunction < Base
75
74
  include ConfigurableEnforcedStyle
76
75
  extend AutoCorrector
@@ -54,7 +54,7 @@ module RuboCop
54
54
  return true if in_pattern_node.pattern.first_line != in_pattern_node.pattern.last_line
55
55
  return false unless in_pattern_node.body
56
56
 
57
- in_pattern_node.loc.line == in_pattern_node.body.loc.line
57
+ same_line?(in_pattern_node, in_pattern_node.body)
58
58
  end
59
59
  end
60
60
  end
@@ -54,7 +54,7 @@ module RuboCop
54
54
  end
55
55
  return false unless when_node.body
56
56
 
57
- when_node.loc.line == when_node.body.loc.line
57
+ same_line?(when_node, when_node.body)
58
58
  end
59
59
 
60
60
  def accept_node_type?(node)