rubocop 1.9.0 → 1.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (275) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +14 -14
  3. data/assets/output.html.erb +1 -1
  4. data/config/default.yml +70 -17
  5. data/config/obsoletion.yml +4 -0
  6. data/lib/rubocop.rb +5 -0
  7. data/lib/rubocop/cli/command/execute_runner.rb +1 -1
  8. data/lib/rubocop/cli/command/suggest_extensions.rb +3 -2
  9. data/lib/rubocop/comment_config.rb +43 -94
  10. data/lib/rubocop/config.rb +4 -1
  11. data/lib/rubocop/cop/base.rb +1 -0
  12. data/lib/rubocop/cop/bundler/duplicated_gem.rb +2 -1
  13. data/lib/rubocop/cop/bundler/gem_comment.rb +1 -0
  14. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +1 -0
  15. data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -0
  16. data/lib/rubocop/cop/correctors/alignment_corrector.rb +3 -6
  17. data/lib/rubocop/cop/exclude_limit.rb +26 -0
  18. data/lib/rubocop/cop/gemspec/date_assignment.rb +57 -0
  19. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +2 -0
  20. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -0
  21. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +2 -0
  22. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +2 -0
  23. data/lib/rubocop/cop/generator.rb +2 -2
  24. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  25. data/lib/rubocop/cop/internal_affairs/example_description.rb +1 -0
  26. data/lib/rubocop/cop/internal_affairs/method_name_equal.rb +1 -0
  27. data/lib/rubocop/cop/internal_affairs/node_destructuring.rb +2 -0
  28. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +151 -0
  29. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +1 -0
  30. data/lib/rubocop/cop/internal_affairs/offense_location_keyword.rb +2 -0
  31. data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +1 -0
  32. data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +1 -0
  33. data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +1 -0
  34. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +3 -0
  35. data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +4 -0
  36. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +2 -0
  37. data/lib/rubocop/cop/layout/access_modifier_indentation.rb +11 -8
  38. data/lib/rubocop/cop/layout/argument_alignment.rb +6 -5
  39. data/lib/rubocop/cop/layout/array_alignment.rb +7 -6
  40. data/lib/rubocop/cop/layout/assignment_indentation.rb +6 -3
  41. data/lib/rubocop/cop/layout/block_alignment.rb +1 -0
  42. data/lib/rubocop/cop/layout/block_end_newline.rb +4 -8
  43. data/lib/rubocop/cop/layout/class_structure.rb +1 -0
  44. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +14 -15
  45. data/lib/rubocop/cop/layout/comment_indentation.rb +16 -16
  46. data/lib/rubocop/cop/layout/else_alignment.rb +9 -6
  47. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +20 -3
  48. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +37 -17
  49. data/lib/rubocop/cop/layout/extra_spacing.rb +2 -2
  50. data/lib/rubocop/cop/layout/first_argument_indentation.rb +27 -7
  51. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +9 -6
  52. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +22 -15
  53. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +6 -5
  54. data/lib/rubocop/cop/layout/indentation_consistency.rb +9 -6
  55. data/lib/rubocop/cop/layout/indentation_style.rb +27 -30
  56. data/lib/rubocop/cop/layout/indentation_width.rb +20 -9
  57. data/lib/rubocop/cop/layout/line_length.rb +2 -1
  58. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +26 -0
  59. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +18 -5
  60. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +10 -5
  61. data/lib/rubocop/cop/layout/parameter_alignment.rb +6 -5
  62. data/lib/rubocop/cop/layout/space_before_block_braces.rb +1 -1
  63. data/lib/rubocop/cop/layout/space_before_brackets.rb +9 -4
  64. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +1 -1
  65. data/lib/rubocop/cop/lint/big_decimal_new.rb +1 -0
  66. data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -0
  67. data/lib/rubocop/cop/lint/constant_definition_in_block.rb +2 -0
  68. data/lib/rubocop/cop/lint/constant_resolution.rb +1 -0
  69. data/lib/rubocop/cop/lint/debugger.rb +60 -14
  70. data/lib/rubocop/cop/lint/deprecated_constants.rb +5 -0
  71. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +14 -4
  72. data/lib/rubocop/cop/lint/duplicate_branch.rb +1 -1
  73. data/lib/rubocop/cop/lint/duplicate_methods.rb +3 -0
  74. data/lib/rubocop/cop/lint/duplicate_require.rb +3 -2
  75. data/lib/rubocop/cop/lint/each_with_object_argument.rb +1 -0
  76. data/lib/rubocop/cop/lint/else_layout.rb +1 -1
  77. data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -0
  78. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +1 -0
  79. data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +1 -0
  80. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -0
  81. data/lib/rubocop/cop/lint/inherit_exception.rb +1 -0
  82. data/lib/rubocop/cop/lint/multiple_comparison.rb +5 -4
  83. data/lib/rubocop/cop/lint/nested_method_definition.rb +3 -0
  84. data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -0
  85. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +7 -0
  86. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +3 -0
  87. data/lib/rubocop/cop/lint/number_conversion.rb +11 -2
  88. data/lib/rubocop/cop/lint/raise_exception.rb +2 -0
  89. data/lib/rubocop/cop/lint/rand_one.rb +1 -0
  90. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +1 -2
  91. data/lib/rubocop/cop/lint/redundant_require_statement.rb +1 -0
  92. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +1 -0
  93. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +7 -3
  94. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +1 -0
  95. data/lib/rubocop/cop/lint/redundant_with_index.rb +1 -0
  96. data/lib/rubocop/cop/lint/redundant_with_object.rb +1 -0
  97. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +1 -0
  98. data/lib/rubocop/cop/lint/safe_navigation_with_empty.rb +1 -0
  99. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +1 -0
  100. data/lib/rubocop/cop/lint/shadowed_argument.rb +1 -0
  101. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +1 -0
  102. data/lib/rubocop/cop/lint/struct_new_override.rb +1 -0
  103. data/lib/rubocop/cop/lint/suppressed_exception.rb +44 -1
  104. data/lib/rubocop/cop/lint/symbol_conversion.rb +91 -3
  105. data/lib/rubocop/cop/lint/to_enum_arguments.rb +3 -0
  106. data/lib/rubocop/cop/lint/unified_integer.rb +1 -0
  107. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +5 -0
  108. data/lib/rubocop/cop/lint/unreachable_code.rb +1 -0
  109. data/lib/rubocop/cop/lint/unreachable_loop.rb +1 -0
  110. data/lib/rubocop/cop/lint/unused_method_argument.rb +1 -0
  111. data/lib/rubocop/cop/lint/uri_escape_unescape.rb +1 -0
  112. data/lib/rubocop/cop/lint/useless_access_modifier.rb +4 -0
  113. data/lib/rubocop/cop/lint/useless_setter_call.rb +1 -0
  114. data/lib/rubocop/cop/lint/useless_times.rb +3 -0
  115. data/lib/rubocop/cop/message_annotator.rb +4 -1
  116. data/lib/rubocop/cop/metrics/block_nesting.rb +2 -2
  117. data/lib/rubocop/cop/metrics/module_length.rb +1 -0
  118. data/lib/rubocop/cop/metrics/parameter_lists.rb +6 -2
  119. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +6 -4
  120. data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +2 -0
  121. data/lib/rubocop/cop/mixin/alignment.rb +10 -3
  122. data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
  123. data/lib/rubocop/cop/mixin/code_length.rb +3 -1
  124. data/lib/rubocop/cop/mixin/comments_help.rb +5 -1
  125. data/lib/rubocop/cop/mixin/configurable_max.rb +1 -0
  126. data/lib/rubocop/cop/mixin/def_node.rb +1 -0
  127. data/lib/rubocop/cop/mixin/documentation_comment.rb +1 -1
  128. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +3 -0
  129. data/lib/rubocop/cop/mixin/empty_parameter.rb +1 -0
  130. data/lib/rubocop/cop/mixin/enforce_superclass.rb +2 -0
  131. data/lib/rubocop/cop/mixin/hash_transform_method.rb +1 -0
  132. data/lib/rubocop/cop/mixin/line_length_help.rb +11 -6
  133. data/lib/rubocop/cop/mixin/method_complexity.rb +4 -1
  134. data/lib/rubocop/cop/mixin/multiline_element_indentation.rb +3 -1
  135. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +4 -23
  136. data/lib/rubocop/cop/mixin/negative_conditional.rb +3 -0
  137. data/lib/rubocop/cop/mixin/preferred_delimiters.rb +3 -3
  138. data/lib/rubocop/cop/mixin/rational_literal.rb +1 -0
  139. data/lib/rubocop/cop/mixin/safe_assignment.rb +5 -0
  140. data/lib/rubocop/cop/mixin/uncommunicative_name.rb +4 -6
  141. data/lib/rubocop/cop/mixin/visibility_help.rb +1 -0
  142. data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +1 -0
  143. data/lib/rubocop/cop/naming/constant_name.rb +2 -0
  144. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +6 -0
  145. data/lib/rubocop/cop/naming/method_name.rb +3 -0
  146. data/lib/rubocop/cop/naming/predicate_name.rb +1 -0
  147. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +10 -0
  148. data/lib/rubocop/cop/registry.rb +10 -1
  149. data/lib/rubocop/cop/security/eval.rb +1 -0
  150. data/lib/rubocop/cop/security/json_load.rb +1 -0
  151. data/lib/rubocop/cop/security/marshal_load.rb +1 -0
  152. data/lib/rubocop/cop/security/open.rb +1 -0
  153. data/lib/rubocop/cop/security/yaml_load.rb +1 -0
  154. data/lib/rubocop/cop/style/access_modifier_declarations.rb +3 -2
  155. data/lib/rubocop/cop/style/alias.rb +1 -0
  156. data/lib/rubocop/cop/style/and_or.rb +3 -1
  157. data/lib/rubocop/cop/style/arguments_forwarding.rb +3 -0
  158. data/lib/rubocop/cop/style/array_coercion.rb +2 -0
  159. data/lib/rubocop/cop/style/array_join.rb +1 -0
  160. data/lib/rubocop/cop/style/attr.rb +1 -0
  161. data/lib/rubocop/cop/style/bisected_attr_accessor.rb +59 -71
  162. data/lib/rubocop/cop/style/bisected_attr_accessor/macro.rb +62 -0
  163. data/lib/rubocop/cop/style/case_equality.rb +2 -1
  164. data/lib/rubocop/cop/style/case_like_if.rb +15 -4
  165. data/lib/rubocop/cop/style/class_equality_comparison.rb +3 -0
  166. data/lib/rubocop/cop/style/collection_compact.rb +2 -0
  167. data/lib/rubocop/cop/style/colon_method_call.rb +1 -0
  168. data/lib/rubocop/cop/style/command_literal.rb +1 -1
  169. data/lib/rubocop/cop/style/commented_keyword.rb +10 -10
  170. data/lib/rubocop/cop/style/conditional_assignment.rb +2 -0
  171. data/lib/rubocop/cop/style/constant_visibility.rb +28 -0
  172. data/lib/rubocop/cop/style/date_time.rb +3 -0
  173. data/lib/rubocop/cop/style/dir.rb +1 -0
  174. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +2 -2
  175. data/lib/rubocop/cop/style/documentation.rb +30 -3
  176. data/lib/rubocop/cop/style/documentation_method.rb +1 -0
  177. data/lib/rubocop/cop/style/double_negation.rb +3 -2
  178. data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -0
  179. data/lib/rubocop/cop/style/each_with_object.rb +1 -0
  180. data/lib/rubocop/cop/style/empty_literal.rb +9 -0
  181. data/lib/rubocop/cop/style/endless_method.rb +1 -0
  182. data/lib/rubocop/cop/style/eval_with_location.rb +90 -28
  183. data/lib/rubocop/cop/style/even_odd.rb +1 -0
  184. data/lib/rubocop/cop/style/expand_path_arguments.rb +3 -0
  185. data/lib/rubocop/cop/style/explicit_block_argument.rb +2 -1
  186. data/lib/rubocop/cop/style/exponential_notation.rb +6 -7
  187. data/lib/rubocop/cop/style/float_division.rb +4 -0
  188. data/lib/rubocop/cop/style/format_string.rb +2 -0
  189. data/lib/rubocop/cop/style/format_string_token.rb +1 -0
  190. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +0 -3
  191. data/lib/rubocop/cop/style/global_std_stream.rb +1 -0
  192. data/lib/rubocop/cop/style/hash_conversion.rb +108 -0
  193. data/lib/rubocop/cop/style/hash_each_methods.rb +1 -0
  194. data/lib/rubocop/cop/style/hash_except.rb +1 -0
  195. data/lib/rubocop/cop/style/hash_like_case.rb +1 -0
  196. data/lib/rubocop/cop/style/hash_syntax.rb +16 -15
  197. data/lib/rubocop/cop/style/hash_transform_keys.rb +4 -0
  198. data/lib/rubocop/cop/style/hash_transform_values.rb +4 -0
  199. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +37 -11
  200. data/lib/rubocop/cop/style/implicit_runtime_error.rb +1 -0
  201. data/lib/rubocop/cop/style/inverse_methods.rb +2 -0
  202. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +46 -2
  203. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +19 -3
  204. data/lib/rubocop/cop/style/min_max.rb +1 -0
  205. data/lib/rubocop/cop/style/mixin_usage.rb +2 -0
  206. data/lib/rubocop/cop/style/module_function.rb +5 -0
  207. data/lib/rubocop/cop/style/multiline_method_signature.rb +10 -3
  208. data/lib/rubocop/cop/style/multiple_comparison.rb +21 -2
  209. data/lib/rubocop/cop/style/mutable_constant.rb +3 -0
  210. data/lib/rubocop/cop/style/negated_if_else_condition.rb +16 -2
  211. data/lib/rubocop/cop/style/nil_comparison.rb +6 -1
  212. data/lib/rubocop/cop/style/nil_lambda.rb +1 -0
  213. data/lib/rubocop/cop/style/non_nil_check.rb +7 -0
  214. data/lib/rubocop/cop/style/numeric_literals.rb +6 -9
  215. data/lib/rubocop/cop/style/numeric_predicate.rb +4 -1
  216. data/lib/rubocop/cop/style/option_hash.rb +1 -0
  217. data/lib/rubocop/cop/style/or_assignment.rb +2 -0
  218. data/lib/rubocop/cop/style/parallel_assignment.rb +6 -0
  219. data/lib/rubocop/cop/style/parentheses_around_condition.rb +1 -0
  220. data/lib/rubocop/cop/style/proc.rb +1 -0
  221. data/lib/rubocop/cop/style/random_with_offset.rb +5 -0
  222. data/lib/rubocop/cop/style/redundant_assignment.rb +1 -0
  223. data/lib/rubocop/cop/style/redundant_begin.rb +44 -4
  224. data/lib/rubocop/cop/style/redundant_conditional.rb +2 -0
  225. data/lib/rubocop/cop/style/redundant_exception.rb +2 -0
  226. data/lib/rubocop/cop/style/redundant_fetch_block.rb +2 -0
  227. data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +1 -0
  228. data/lib/rubocop/cop/style/redundant_freeze.rb +1 -0
  229. data/lib/rubocop/cop/style/redundant_parentheses.rb +13 -0
  230. data/lib/rubocop/cop/style/redundant_return.rb +4 -0
  231. data/lib/rubocop/cop/style/redundant_self.rb +7 -3
  232. data/lib/rubocop/cop/style/redundant_self_assignment.rb +2 -0
  233. data/lib/rubocop/cop/style/redundant_sort.rb +1 -0
  234. data/lib/rubocop/cop/style/redundant_sort_by.rb +1 -0
  235. data/lib/rubocop/cop/style/regexp_literal.rb +1 -1
  236. data/lib/rubocop/cop/style/rescue_modifier.rb +17 -14
  237. data/lib/rubocop/cop/style/rescue_standard_error.rb +2 -0
  238. data/lib/rubocop/cop/style/return_nil.rb +6 -0
  239. data/lib/rubocop/cop/style/safe_navigation.rb +2 -0
  240. data/lib/rubocop/cop/style/sample.rb +1 -0
  241. data/lib/rubocop/cop/style/signal_exception.rb +3 -0
  242. data/lib/rubocop/cop/style/single_argument_dig.rb +1 -0
  243. data/lib/rubocop/cop/style/single_line_methods.rb +4 -1
  244. data/lib/rubocop/cop/style/slicing_with_range.rb +1 -0
  245. data/lib/rubocop/cop/style/sole_nested_conditional.rb +20 -4
  246. data/lib/rubocop/cop/style/special_global_vars.rb +3 -3
  247. data/lib/rubocop/cop/style/stderr_puts.rb +1 -0
  248. data/lib/rubocop/cop/style/string_chars.rb +38 -0
  249. data/lib/rubocop/cop/style/string_concatenation.rb +1 -0
  250. data/lib/rubocop/cop/style/string_hash_keys.rb +2 -0
  251. data/lib/rubocop/cop/style/strip.rb +1 -0
  252. data/lib/rubocop/cop/style/struct_inheritance.rb +3 -0
  253. data/lib/rubocop/cop/style/symbol_proc.rb +25 -1
  254. data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -0
  255. data/lib/rubocop/cop/style/trailing_body_on_method_definition.rb +5 -0
  256. data/lib/rubocop/cop/style/trailing_method_end_statement.rb +1 -1
  257. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -0
  258. data/lib/rubocop/cop/style/unless_logical_operators.rb +105 -0
  259. data/lib/rubocop/cop/style/unpack_first.rb +1 -0
  260. data/lib/rubocop/cop/style/yoda_condition.rb +1 -0
  261. data/lib/rubocop/cop/style/zero_length_predicate.rb +5 -0
  262. data/lib/rubocop/cop/util.rb +4 -1
  263. data/lib/rubocop/directive_comment.rb +69 -9
  264. data/lib/rubocop/ext/regexp_parser.rb +3 -6
  265. data/lib/rubocop/formatter/clang_style_formatter.rb +4 -2
  266. data/lib/rubocop/formatter/offense_count_formatter.rb +1 -1
  267. data/lib/rubocop/formatter/simple_text_formatter.rb +2 -1
  268. data/lib/rubocop/formatter/tap_formatter.rb +4 -2
  269. data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -1
  270. data/lib/rubocop/magic_comment.rb +1 -1
  271. data/lib/rubocop/name_similarity.rb +1 -1
  272. data/lib/rubocop/target_finder.rb +1 -0
  273. data/lib/rubocop/target_ruby.rb +21 -13
  274. data/lib/rubocop/version.rb +1 -1
  275. metadata +14 -7
@@ -21,6 +21,7 @@ module RuboCop
21
21
  MSG = 'Replace with `Integer#%<method>s?`.'
22
22
  RESTRICT_ON_SEND = %i[== !=].freeze
23
23
 
24
+ # @!method even_odd_candidate?(node)
24
25
  def_node_matcher :even_odd_candidate?, <<~PATTERN
25
26
  (send
26
27
  {(send $_ :% (int 2))
@@ -54,6 +54,7 @@ module RuboCop
54
54
 
55
55
  RESTRICT_ON_SEND = %i[expand_path].freeze
56
56
 
57
+ # @!method file_expand_path(node)
57
58
  def_node_matcher :file_expand_path, <<~PATTERN
58
59
  (send
59
60
  (const {nil? cbase} :File) :expand_path
@@ -61,6 +62,7 @@ module RuboCop
61
62
  $_)
62
63
  PATTERN
63
64
 
65
+ # @!method pathname_parent_expand_path(node)
64
66
  def_node_matcher :pathname_parent_expand_path, <<~PATTERN
65
67
  (send
66
68
  (send
@@ -68,6 +70,7 @@ module RuboCop
68
70
  $_) :parent) :expand_path)
69
71
  PATTERN
70
72
 
73
+ # @!method pathname_new_parent_expand_path(node)
71
74
  def_node_matcher :pathname_new_parent_expand_path, <<~PATTERN
72
75
  (send
73
76
  (send
@@ -45,6 +45,7 @@ module RuboCop
45
45
  MSG = 'Consider using explicit block argument in the '\
46
46
  "surrounding method's signature over `yield`."
47
47
 
48
+ # @!method yielding_block?(node)
48
49
  def_node_matcher :yielding_block?, <<~PATTERN
49
50
  (block $_ (args $...) (yield $...))
50
51
  PATTERN
@@ -97,7 +98,7 @@ module RuboCop
97
98
  replacement = ' &block'
98
99
  replacement = ",#{replacement}" unless arg_range.source.end_with?(',')
99
100
  corrector.insert_after(arg_range, replacement) unless last_arg.blockarg_type?
100
- elsif node.call_type?
101
+ elsif node.call_type? || node.zsuper_type?
101
102
  corrector.insert_after(node, '(&block)')
102
103
  else
103
104
  corrector.insert_after(node.loc.name, '(&block)')
@@ -5,13 +5,12 @@ module RuboCop
5
5
  module Style
6
6
  # This cop enforces consistency when using exponential notation
7
7
  # for numbers in the code (eg 1.2e4). Different styles are supported:
8
- # * `scientific` which enforces a mantissa between 1 (inclusive)
9
- # and 10 (exclusive).
10
- # * `engineering` which enforces the exponent to be a multiple of 3
11
- # and the mantissa to be between 0.1 (inclusive)
12
- # and 10 (exclusive).
13
- # * `integral` which enforces the mantissa to always be a whole number
14
- # without trailing zeroes.
8
+ #
9
+ # * `scientific` which enforces a mantissa between 1 (inclusive) and 10 (exclusive).
10
+ # * `engineering` which enforces the exponent to be a multiple of 3 and the mantissa
11
+ # to be between 0.1 (inclusive) and 10 (exclusive).
12
+ # * `integral` which enforces the mantissa to always be a whole number without
13
+ # trailing zeroes.
15
14
  #
16
15
  # @example EnforcedStyle: scientific (default)
17
16
  # # Enforces a mantissa between 1 (inclusive) and 10 (exclusive).
@@ -55,15 +55,19 @@ module RuboCop
55
55
 
56
56
  RESTRICT_ON_SEND = %i[/].freeze
57
57
 
58
+ # @!method right_coerce?(node)
58
59
  def_node_matcher :right_coerce?, <<~PATTERN
59
60
  (send _ :/ (send _ :to_f))
60
61
  PATTERN
62
+ # @!method left_coerce?(node)
61
63
  def_node_matcher :left_coerce?, <<~PATTERN
62
64
  (send (send _ :to_f) :/ _)
63
65
  PATTERN
66
+ # @!method both_coerce?(node)
64
67
  def_node_matcher :both_coerce?, <<~PATTERN
65
68
  (send (send _ :to_f) :/ (send _ :to_f))
66
69
  PATTERN
70
+ # @!method any_coerce?(node)
67
71
  def_node_matcher :any_coerce?, <<~PATTERN
68
72
  {(send _ :/ (send _ :to_f)) (send (send _ :to_f) :/ _)}
69
73
  PATTERN
@@ -42,6 +42,7 @@ module RuboCop
42
42
  MSG = 'Favor `%<prefer>s` over `%<current>s`.'
43
43
  RESTRICT_ON_SEND = %i[format sprintf %].freeze
44
44
 
45
+ # @!method formatter(node)
45
46
  def_node_matcher :formatter, <<~PATTERN
46
47
  {
47
48
  (send nil? ${:sprintf :format} _ _ ...)
@@ -50,6 +51,7 @@ module RuboCop
50
51
  }
51
52
  PATTERN
52
53
 
54
+ # @!method variable_argument?(node)
53
55
  def_node_matcher :variable_argument?, <<~PATTERN
54
56
  (send {str dstr} :% {send_type? lvar_type?})
55
57
  PATTERN
@@ -89,6 +89,7 @@ module RuboCop
89
89
 
90
90
  private
91
91
 
92
+ # @!method format_string_in_typical_context?(node)
92
93
  def_node_matcher :format_string_in_typical_context?, <<~PATTERN
93
94
  {
94
95
  ^(send _ {:format :sprintf :printf} %0 ...)
@@ -10,9 +10,6 @@ module RuboCop
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 ignore files where the comment exists but is set
14
- # to `false` instead of `true`.
15
- #
16
13
  # @example EnforcedStyle: always (default)
17
14
  # # The `always` style will always add the frozen string literal comment
18
15
  # # to a file, regardless of the Ruby version or if `freeze` or `<<` are
@@ -34,6 +34,7 @@ module RuboCop
34
34
 
35
35
  STD_STREAMS = %i[STDIN STDOUT STDERR].to_set.freeze
36
36
 
37
+ # @!method const_to_gvar_assignment?(node, name)
37
38
  def_node_matcher :const_to_gvar_assignment?, <<~PATTERN
38
39
  (gvasgn %1 (const nil? _))
39
40
  PATTERN
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # This cop checks the usage of pre-2.1 `Hash[args]` method of converting enumerables and
7
+ # sequences of values to hashes.
8
+ #
9
+ # Correction code from splat argument (`Hash[*ary]`) is not simply determined. For example,
10
+ # `Hash[*ary]` can be replaced with `ary.each_slice(2).to_h` but it will be complicated.
11
+ # So, `AllowSplatArgument` option is true by default to allow splat argument for simple code.
12
+ #
13
+ # @example
14
+ # # bad
15
+ # Hash[ary]
16
+ #
17
+ # # good
18
+ # ary.to_h
19
+ #
20
+ # # bad
21
+ # Hash[key1, value1, key2, value2]
22
+ #
23
+ # # good
24
+ # {key1 => value1, key2 => value2}
25
+ #
26
+ # @example AllowSplatArgument: true (default)
27
+ # # good
28
+ # Hash[*ary]
29
+ #
30
+ # @example AllowSplatArgument: false
31
+ # # bad
32
+ # Hash[*ary]
33
+ #
34
+ class HashConversion < Base
35
+ extend AutoCorrector
36
+
37
+ MSG_TO_H = 'Prefer ary.to_h to Hash[ary].'
38
+ MSG_LITERAL_MULTI_ARG = 'Prefer literal hash to Hash[arg1, arg2, ...].'
39
+ MSG_LITERAL_HASH_ARG = 'Prefer literal hash to Hash[key: value, ...].'
40
+ MSG_SPLAT = 'Prefer array_of_pairs.to_h to Hash[*array].'
41
+ RESTRICT_ON_SEND = %i[[]].freeze
42
+
43
+ # @!method hash_from_array?(node)
44
+ def_node_matcher :hash_from_array?, '(send (const {nil? cbase} :Hash) :[] ...)'
45
+
46
+ def on_send(node)
47
+ return unless hash_from_array?(node)
48
+
49
+ # There are several cases:
50
+ # If there is one argument:
51
+ # Hash[ary] => ary.to_h
52
+ # Hash[*ary] => don't suggest corrections
53
+ # If there is 0 or 2+ arguments:
54
+ # Hash[a1, a2, a3, a4] => {a1 => a2, a3 => a4}
55
+ # ...but don't suggest correction if there is odd number of them (it is a bug)
56
+ node.arguments.count == 1 ? single_argument(node) : multi_argument(node)
57
+ end
58
+
59
+ private
60
+
61
+ def single_argument(node)
62
+ first_argument = node.first_argument
63
+ if first_argument.hash_type?
64
+ add_offense(node, message: MSG_LITERAL_HASH_ARG) do |corrector|
65
+ corrector.replace(node, "{#{first_argument.source}}")
66
+ end
67
+ elsif first_argument.splat_type?
68
+ add_offense(node, message: MSG_SPLAT) unless allowed_splat_argument?
69
+ else
70
+ add_offense(node, message: MSG_TO_H) do |corrector|
71
+ replacement = first_argument.source
72
+ replacement = "(#{replacement})" if requires_parens?(first_argument)
73
+ corrector.replace(node, "#{replacement}.to_h")
74
+ end
75
+ end
76
+ end
77
+
78
+ def requires_parens?(node)
79
+ node.call_type? && node.arguments.any? && !node.parenthesized?
80
+ end
81
+
82
+ def multi_argument(node)
83
+ if node.arguments.count.odd?
84
+ add_offense(node, message: MSG_LITERAL_MULTI_ARG)
85
+ else
86
+ add_offense(node, message: MSG_LITERAL_MULTI_ARG) do |corrector|
87
+ corrector.replace(node, args_to_hash(node.arguments))
88
+
89
+ parent = node.parent
90
+ add_parentheses(parent, corrector) if parent&.send_type? && !parent.parenthesized?
91
+ end
92
+ end
93
+ end
94
+
95
+ def args_to_hash(args)
96
+ content = args.each_slice(2)
97
+ .map { |arg1, arg2| "#{arg1.source} => #{arg2.source}" }
98
+ .join(', ')
99
+ "{#{content}}"
100
+ end
101
+
102
+ def allowed_splat_argument?
103
+ cop_config.fetch('AllowSplatArgument', true)
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
@@ -23,6 +23,7 @@ module RuboCop
23
23
 
24
24
  MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
25
25
 
26
+ # @!method kv_each(node)
26
27
  def_node_matcher :kv_each, <<~PATTERN
27
28
  (block $(send (send _ ${:keys :values}) :each) ...)
28
29
  PATTERN
@@ -33,6 +33,7 @@ module RuboCop
33
33
  MSG = 'Use `%<prefer>s` instead.'
34
34
  RESTRICT_ON_SEND = %i[reject select filter].freeze
35
35
 
36
+ # @!method bad_method?(node)
36
37
  def_node_matcher :bad_method?, <<~PATTERN
37
38
  (block
38
39
  (send _ _)
@@ -39,6 +39,7 @@ module RuboCop
39
39
  class HashLikeCase < Base
40
40
  MSG = 'Consider replacing `case-when` with a hash lookup.'
41
41
 
42
+ # @!method hash_like_case?(node)
42
43
  def_node_matcher :hash_like_case?, <<~PATTERN
43
44
  (case
44
45
  _
@@ -54,9 +54,10 @@ module RuboCop
54
54
  # # good
55
55
  # {a: 1, b: 2}
56
56
  # {:c => 3, 'd' => 4}
57
- class HashSyntax < Cop
57
+ class HashSyntax < Base
58
58
  include ConfigurableEnforcedStyle
59
59
  include RangeHelp
60
+ extend AutoCorrector
60
61
 
61
62
  MSG_19 = 'Use the new Ruby 1.9 hash syntax.'
62
63
  MSG_NO_MIXED_KEYS = "Don't mix styles in the same hash."
@@ -104,18 +105,6 @@ module RuboCop
104
105
  end
105
106
  end
106
107
 
107
- def autocorrect(node)
108
- lambda do |corrector|
109
- if style == :hash_rockets || force_hash_rockets?(node.parent.pairs)
110
- autocorrect_hash_rockets(corrector, node)
111
- elsif style == :ruby19_no_mixed_keys || style == :no_mixed_keys
112
- autocorrect_no_mixed_keys(corrector, node)
113
- else
114
- autocorrect_ruby19(corrector, node)
115
- end
116
- end
117
- end
118
-
119
108
  def alternative_style
120
109
  case style
121
110
  when :hash_rockets
@@ -127,6 +116,16 @@ module RuboCop
127
116
 
128
117
  private
129
118
 
119
+ def autocorrect(corrector, node)
120
+ if style == :hash_rockets || force_hash_rockets?(node.parent.pairs)
121
+ autocorrect_hash_rockets(corrector, node)
122
+ elsif style == :ruby19_no_mixed_keys || style == :no_mixed_keys
123
+ autocorrect_no_mixed_keys(corrector, node)
124
+ else
125
+ autocorrect_ruby19(corrector, node)
126
+ end
127
+ end
128
+
130
129
  def sym_indices?(pairs)
131
130
  pairs.all? { |p| word_symbol_pair?(p) }
132
131
  end
@@ -152,14 +151,16 @@ module RuboCop
152
151
  return true if /\A[_a-z]\w*[?!]?\z/i.match?(sym_name)
153
152
 
154
153
  # For more complicated hash keys, let the parser validate the syntax.
155
- parse("{ #{sym_name}: :foo }").valid_syntax?
154
+ ProcessedSource.new("{ #{sym_name}: :foo }", target_ruby_version).valid_syntax?
156
155
  end
157
156
 
158
157
  def check(pairs, delim, msg)
159
158
  pairs.each do |pair|
160
159
  if pair.delimiter == delim
161
160
  location = pair.source_range.begin.join(pair.loc.operator)
162
- add_offense(pair, location: location, message: msg) do
161
+ add_offense(location, message: msg) do |corrector|
162
+ autocorrect(corrector, pair)
163
+
163
164
  opposite_style_detected
164
165
  end
165
166
  else
@@ -32,6 +32,7 @@ module RuboCop
32
32
 
33
33
  minimum_target_ruby_version 2.5
34
34
 
35
+ # @!method on_bad_each_with_object(node)
35
36
  def_node_matcher :on_bad_each_with_object, <<~PATTERN
36
37
  (block
37
38
  ({send csend} !#array_receiver? :each_with_object (hash))
@@ -43,6 +44,7 @@ module RuboCop
43
44
  ({send csend} (lvar _memo) :[]= $!`_memo $(lvar _val)))
44
45
  PATTERN
45
46
 
47
+ # @!method on_bad_hash_brackets_map(node)
46
48
  def_node_matcher :on_bad_hash_brackets_map, <<~PATTERN
47
49
  (send
48
50
  (const _ :Hash)
@@ -55,6 +57,7 @@ module RuboCop
55
57
  (array $_ $(lvar _val))))
56
58
  PATTERN
57
59
 
60
+ # @!method on_bad_map_to_h(node)
58
61
  def_node_matcher :on_bad_map_to_h, <<~PATTERN
59
62
  ({send csend}
60
63
  (block
@@ -66,6 +69,7 @@ module RuboCop
66
69
  :to_h)
67
70
  PATTERN
68
71
 
72
+ # @!method on_bad_to_h(node)
69
73
  def_node_matcher :on_bad_to_h, <<~PATTERN
70
74
  (block
71
75
  ({send csend} !#array_receiver? :to_h)
@@ -29,6 +29,7 @@ module RuboCop
29
29
  include HashTransformMethod
30
30
  extend AutoCorrector
31
31
 
32
+ # @!method on_bad_each_with_object(node)
32
33
  def_node_matcher :on_bad_each_with_object, <<~PATTERN
33
34
  (block
34
35
  ({send csend} !#array_receiver? :each_with_object (hash))
@@ -40,6 +41,7 @@ module RuboCop
40
41
  ({send csend} (lvar _memo) :[]= $(lvar _key) $!`_memo))
41
42
  PATTERN
42
43
 
44
+ # @!method on_bad_hash_brackets_map(node)
43
45
  def_node_matcher :on_bad_hash_brackets_map, <<~PATTERN
44
46
  (send
45
47
  (const _ :Hash)
@@ -52,6 +54,7 @@ module RuboCop
52
54
  (array $(lvar _key) $_)))
53
55
  PATTERN
54
56
 
57
+ # @!method on_bad_map_to_h(node)
55
58
  def_node_matcher :on_bad_map_to_h, <<~PATTERN
56
59
  ({send csend}
57
60
  (block
@@ -63,6 +66,7 @@ module RuboCop
63
66
  :to_h)
64
67
  PATTERN
65
68
 
69
+ # @!method on_bad_to_h(node)
66
70
  def_node_matcher :on_bad_to_h, <<~PATTERN
67
71
  (block
68
72
  ({send csend} !#array_receiver? :to_h)
@@ -6,6 +6,8 @@ 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
11
  #
10
12
  # @example
11
13
  # # bad
@@ -21,39 +23,62 @@ module RuboCop
21
23
  # # good
22
24
  # foo == bar
23
25
  #
26
+ # @example AllowedMethods: ['nonzero?']
27
+ # # good
28
+ # num.nonzero? ? true : false
29
+ #
24
30
  class IfWithBooleanLiteralBranches < Base
31
+ include AllowedMethods
25
32
  extend AutoCorrector
26
33
 
27
34
  MSG = 'Remove redundant %<keyword>s with boolean literal branches.'
35
+ MSG_FOR_ELSIF = 'Use `else` instead of redundant `elsif` with boolean literal branches.'
28
36
 
37
+ # @!method if_with_boolean_literal_branches?(node)
29
38
  def_node_matcher :if_with_boolean_literal_branches?, <<~PATTERN
30
39
  (if #return_boolean_value? {(true) (false) | (false) (true)})
31
40
  PATTERN
41
+ # @!method double_negative?(node)
32
42
  def_node_matcher :double_negative?, '(send (send _ :!) :!)'
33
43
 
34
44
  def on_if(node)
35
45
  return unless if_with_boolean_literal_branches?(node)
36
46
 
37
47
  condition = node.condition
38
- range, keyword = if node.ternary?
39
- range = condition.source_range.end.join(node.source_range.end)
40
-
41
- [range, 'ternary operator']
42
- else
43
- keyword = node.loc.keyword
44
-
45
- [keyword, "`#{keyword.source}`"]
46
- end
48
+ range, keyword = offense_range_with_keyword(node, condition)
47
49
 
48
- add_offense(range, message: format(MSG, keyword: keyword)) do |corrector|
50
+ add_offense(range, message: message(node, keyword)) do |corrector|
49
51
  replacement = replacement_condition(node, condition)
50
52
 
51
- corrector.replace(node, replacement)
53
+ if node.elsif?
54
+ corrector.insert_before(node, "else\n")
55
+ corrector.replace(node, "#{indent(node.if_branch)}#{replacement}")
56
+ else
57
+ corrector.replace(node, replacement)
58
+ end
52
59
  end
53
60
  end
54
61
 
55
62
  private
56
63
 
64
+ def offense_range_with_keyword(node, condition)
65
+ if node.ternary?
66
+ range = condition.source_range.end.join(node.source_range.end)
67
+
68
+ [range, 'ternary operator']
69
+ else
70
+ keyword = node.loc.keyword
71
+
72
+ [keyword, "`#{keyword.source}`"]
73
+ end
74
+ end
75
+
76
+ def message(node, keyword)
77
+ message_template = node.elsif? ? MSG_FOR_ELSIF : MSG
78
+
79
+ format(message_template, keyword: keyword)
80
+ end
81
+
57
82
  def return_boolean_value?(condition)
58
83
  if condition.begin_type?
59
84
  return_boolean_value?(condition.children.first)
@@ -68,6 +93,7 @@ module RuboCop
68
93
 
69
94
  def assume_boolean_value?(condition)
70
95
  return false unless condition.send_type?
96
+ return false if allowed_method?(condition.method_name)
71
97
 
72
98
  condition.comparison_method? || condition.predicate_method? || double_negative?(condition)
73
99
  end