rubocop 0.70.0 → 0.75.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 (274) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -10
  3. data/bin/console +1 -0
  4. data/config/default.yml +91 -494
  5. data/lib/rubocop.rb +16 -54
  6. data/lib/rubocop/ast/builder.rb +2 -0
  7. data/lib/rubocop/ast/node.rb +9 -15
  8. data/lib/rubocop/ast/node/float_node.rb +12 -0
  9. data/lib/rubocop/ast/node/int_node.rb +12 -0
  10. data/lib/rubocop/ast/node/mixin/method_dispatch_node.rb +4 -4
  11. data/lib/rubocop/ast/node/mixin/numeric_node.rb +21 -0
  12. data/lib/rubocop/ast/node/resbody_node.rb +1 -6
  13. data/lib/rubocop/ast/traversal.rb +3 -3
  14. data/lib/rubocop/cached_data.rb +1 -1
  15. data/lib/rubocop/comment_config.rb +3 -2
  16. data/lib/rubocop/config.rb +21 -508
  17. data/lib/rubocop/config_loader.rb +22 -4
  18. data/lib/rubocop/config_loader_resolver.rb +2 -8
  19. data/lib/rubocop/config_obsoletion.rb +213 -0
  20. data/lib/rubocop/config_validator.rb +239 -0
  21. data/lib/rubocop/cop/autocorrect_logic.rb +71 -1
  22. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +1 -1
  23. data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -1
  24. data/lib/rubocop/cop/commissioner.rb +3 -9
  25. data/lib/rubocop/cop/cop.rb +39 -12
  26. data/lib/rubocop/cop/corrector.rb +2 -3
  27. data/lib/rubocop/cop/correctors/alignment_corrector.rb +43 -17
  28. data/lib/rubocop/cop/correctors/empty_line_corrector.rb +2 -2
  29. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +2 -2
  30. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +2 -2
  31. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -1
  32. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +1 -1
  33. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +55 -0
  34. data/lib/rubocop/cop/generator.rb +4 -4
  35. data/lib/rubocop/cop/generator/configuration_injector.rb +9 -4
  36. data/lib/rubocop/cop/generator/require_file_injector.rb +1 -1
  37. data/lib/rubocop/cop/internal_affairs/node_destructuring.rb +2 -2
  38. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +1 -1
  39. data/lib/rubocop/cop/internal_affairs/offense_location_keyword.rb +2 -2
  40. data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +1 -1
  41. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +2 -2
  42. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +2 -2
  43. data/lib/rubocop/cop/layout/block_alignment.rb +3 -3
  44. data/lib/rubocop/cop/layout/class_structure.rb +2 -2
  45. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +1 -1
  46. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +3 -1
  47. data/lib/rubocop/cop/layout/extra_spacing.rb +14 -59
  48. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +4 -0
  49. data/lib/rubocop/cop/layout/indent_assignment.rb +9 -1
  50. data/lib/rubocop/cop/layout/indent_first_argument.rb +7 -3
  51. data/lib/rubocop/cop/layout/indent_first_parameter.rb +7 -3
  52. data/lib/rubocop/cop/layout/indent_heredoc.rb +4 -4
  53. data/lib/rubocop/cop/layout/indentation_consistency.rb +13 -12
  54. data/lib/rubocop/cop/layout/indentation_width.rb +28 -10
  55. data/lib/rubocop/cop/layout/leading_comment_space.rb +28 -0
  56. data/lib/rubocop/cop/layout/multiline_block_layout.rb +24 -2
  57. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +2 -0
  58. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +18 -4
  59. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +5 -1
  60. data/lib/rubocop/cop/layout/space_around_operators.rb +42 -23
  61. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +1 -1
  62. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +21 -2
  63. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +24 -40
  64. data/lib/rubocop/cop/layout/tab.rb +10 -22
  65. data/lib/rubocop/cop/lint/assignment_in_condition.rb +17 -4
  66. data/lib/rubocop/cop/lint/big_decimal_new.rb +1 -1
  67. data/lib/rubocop/cop/lint/debugger.rb +4 -6
  68. data/lib/rubocop/cop/lint/duplicate_methods.rb +3 -3
  69. data/lib/rubocop/cop/lint/each_with_object_argument.rb +1 -1
  70. data/lib/rubocop/cop/lint/empty_interpolation.rb +4 -4
  71. data/lib/rubocop/cop/lint/erb_new_arguments.rb +57 -1
  72. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +11 -37
  73. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -1
  74. data/lib/rubocop/cop/lint/inherit_exception.rb +1 -1
  75. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +7 -8
  76. data/lib/rubocop/cop/lint/multiple_compare.rb +1 -1
  77. data/lib/rubocop/cop/lint/nested_method_definition.rb +3 -3
  78. data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
  79. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +1 -1
  80. data/lib/rubocop/cop/lint/number_conversion.rb +4 -4
  81. data/lib/rubocop/cop/lint/rand_one.rb +1 -1
  82. data/lib/rubocop/cop/lint/redundant_with_index.rb +1 -1
  83. data/lib/rubocop/cop/lint/redundant_with_object.rb +1 -1
  84. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +5 -5
  85. data/lib/rubocop/cop/lint/safe_navigation_with_empty.rb +1 -1
  86. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +91 -0
  87. data/lib/rubocop/cop/lint/string_conversion_in_interpolation.rb +6 -6
  88. data/lib/rubocop/cop/lint/unified_integer.rb +1 -1
  89. data/lib/rubocop/cop/lint/unneeded_cop_disable_directive.rb +1 -1
  90. data/lib/rubocop/cop/lint/unneeded_require_statement.rb +1 -1
  91. data/lib/rubocop/cop/lint/unneeded_splat_expansion.rb +7 -2
  92. data/lib/rubocop/cop/lint/unreachable_code.rb +1 -1
  93. data/lib/rubocop/cop/lint/uri_escape_unescape.rb +1 -1
  94. data/lib/rubocop/cop/lint/uri_regexp.rb +2 -2
  95. data/lib/rubocop/cop/lint/useless_access_modifier.rb +6 -6
  96. data/lib/rubocop/cop/lint/useless_setter_call.rb +1 -1
  97. data/lib/rubocop/cop/message_annotator.rb +16 -7
  98. data/lib/rubocop/cop/metrics/class_length.rb +1 -1
  99. data/lib/rubocop/cop/metrics/line_length.rb +6 -0
  100. data/lib/rubocop/cop/metrics/module_length.rb +1 -1
  101. data/lib/rubocop/cop/metrics/parameter_lists.rb +1 -1
  102. data/lib/rubocop/cop/migration/department_name.rb +44 -0
  103. data/lib/rubocop/cop/mixin/alignment.rb +1 -1
  104. data/lib/rubocop/cop/mixin/def_node.rb +1 -1
  105. data/lib/rubocop/cop/mixin/documentation_comment.rb +0 -2
  106. data/lib/rubocop/cop/mixin/empty_parameter.rb +1 -1
  107. data/lib/rubocop/cop/mixin/enforce_superclass.rb +4 -4
  108. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -1
  109. data/lib/rubocop/cop/mixin/hash_alignment.rb +4 -0
  110. data/lib/rubocop/cop/mixin/interpolation.rb +27 -0
  111. data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
  112. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +3 -3
  113. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +87 -0
  114. data/lib/rubocop/cop/mixin/safe_mode.rb +2 -0
  115. data/lib/rubocop/cop/mixin/surrounding_space.rb +7 -5
  116. data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +1 -1
  117. data/lib/rubocop/cop/naming/constant_name.rb +2 -2
  118. data/lib/rubocop/cop/naming/method_name.rb +12 -1
  119. data/lib/rubocop/cop/naming/predicate_name.rb +1 -1
  120. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +20 -22
  121. data/lib/rubocop/cop/naming/variable_name.rb +1 -0
  122. data/lib/rubocop/cop/offense.rb +18 -7
  123. data/lib/rubocop/cop/registry.rb +22 -1
  124. data/lib/rubocop/cop/security/eval.rb +1 -1
  125. data/lib/rubocop/cop/security/json_load.rb +1 -1
  126. data/lib/rubocop/cop/security/marshal_load.rb +1 -1
  127. data/lib/rubocop/cop/security/open.rb +1 -1
  128. data/lib/rubocop/cop/security/yaml_load.rb +1 -1
  129. data/lib/rubocop/cop/style/access_modifier_declarations.rb +1 -0
  130. data/lib/rubocop/cop/style/alias.rb +1 -1
  131. data/lib/rubocop/cop/style/block_delimiters.rb +2 -1
  132. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +29 -10
  133. data/lib/rubocop/cop/style/class_and_module_children.rb +1 -1
  134. data/lib/rubocop/cop/style/colon_method_call.rb +1 -1
  135. data/lib/rubocop/cop/style/commented_keyword.rb +16 -30
  136. data/lib/rubocop/cop/style/conditional_assignment.rb +8 -9
  137. data/lib/rubocop/cop/style/constant_visibility.rb +14 -3
  138. data/lib/rubocop/cop/style/date_time.rb +3 -3
  139. data/lib/rubocop/cop/style/dir.rb +1 -1
  140. data/lib/rubocop/cop/style/documentation_method.rb +1 -1
  141. data/lib/rubocop/cop/style/double_cop_disable_directive.rb +55 -0
  142. data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
  143. data/lib/rubocop/cop/style/each_with_object.rb +1 -1
  144. data/lib/rubocop/cop/style/eval_with_location.rb +2 -2
  145. data/lib/rubocop/cop/style/even_odd.rb +1 -1
  146. data/lib/rubocop/cop/style/expand_path_arguments.rb +3 -3
  147. data/lib/rubocop/cop/style/float_division.rb +94 -0
  148. data/lib/rubocop/cop/style/format_string.rb +13 -9
  149. data/lib/rubocop/cop/style/format_string_token.rb +10 -40
  150. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +18 -33
  151. data/lib/rubocop/cop/style/guard_clause.rb +39 -10
  152. data/lib/rubocop/cop/style/hash_syntax.rb +2 -2
  153. data/lib/rubocop/cop/style/if_inside_else.rb +42 -0
  154. data/lib/rubocop/cop/style/if_unless_modifier.rb +51 -15
  155. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  156. data/lib/rubocop/cop/style/inverse_methods.rb +2 -2
  157. data/lib/rubocop/cop/style/lambda.rb +0 -2
  158. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +12 -6
  159. data/lib/rubocop/cop/style/min_max.rb +1 -1
  160. data/lib/rubocop/cop/style/mixin_usage.rb +12 -2
  161. data/lib/rubocop/cop/style/multiline_memoization.rb +1 -1
  162. data/lib/rubocop/cop/style/multiline_when_then.rb +55 -0
  163. data/lib/rubocop/cop/style/multiple_comparison.rb +1 -1
  164. data/lib/rubocop/cop/style/mutable_constant.rb +3 -3
  165. data/lib/rubocop/cop/style/nested_modifier.rb +18 -2
  166. data/lib/rubocop/cop/style/numeric_predicate.rb +3 -3
  167. data/lib/rubocop/cop/style/option_hash.rb +1 -1
  168. data/lib/rubocop/cop/style/or_assignment.rb +8 -3
  169. data/lib/rubocop/cop/style/parentheses_around_condition.rb +15 -1
  170. data/lib/rubocop/cop/style/random_with_offset.rb +6 -6
  171. data/lib/rubocop/cop/style/redundant_conditional.rb +2 -2
  172. data/lib/rubocop/cop/style/redundant_exception.rb +2 -2
  173. data/lib/rubocop/cop/style/redundant_freeze.rb +1 -1
  174. data/lib/rubocop/cop/style/redundant_parentheses.rb +15 -6
  175. data/lib/rubocop/cop/style/redundant_self.rb +18 -1
  176. data/lib/rubocop/cop/style/redundant_sort_by.rb +1 -1
  177. data/lib/rubocop/cop/style/rescue_modifier.rb +24 -0
  178. data/lib/rubocop/cop/style/rescue_standard_error.rb +2 -2
  179. data/lib/rubocop/cop/style/return_nil.rb +1 -1
  180. data/lib/rubocop/cop/style/safe_navigation.rb +11 -2
  181. data/lib/rubocop/cop/style/sample.rb +1 -1
  182. data/lib/rubocop/cop/style/single_line_methods.rb +8 -1
  183. data/lib/rubocop/cop/style/stderr_puts.rb +1 -1
  184. data/lib/rubocop/cop/style/string_hash_keys.rb +2 -2
  185. data/lib/rubocop/cop/style/strip.rb +1 -1
  186. data/lib/rubocop/cop/style/struct_inheritance.rb +3 -3
  187. data/lib/rubocop/cop/style/symbol_proc.rb +1 -1
  188. data/lib/rubocop/cop/style/ternary_parentheses.rb +32 -3
  189. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -0
  190. data/lib/rubocop/cop/style/trailing_method_end_statement.rb +4 -6
  191. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  192. data/lib/rubocop/cop/style/unneeded_sort.rb +1 -1
  193. data/lib/rubocop/cop/style/unpack_first.rb +1 -1
  194. data/lib/rubocop/cop/style/variable_interpolation.rb +6 -16
  195. data/lib/rubocop/cop/style/word_array.rb +2 -2
  196. data/lib/rubocop/cop/style/zero_length_predicate.rb +6 -6
  197. data/lib/rubocop/cop/team.rb +15 -14
  198. data/lib/rubocop/cop/utils/format_string.rb +128 -0
  199. data/lib/rubocop/cop/variable_force/variable.rb +15 -2
  200. data/lib/rubocop/core_ext/string.rb +0 -24
  201. data/lib/rubocop/error.rb +23 -0
  202. data/lib/rubocop/formatter/emacs_style_formatter.rb +8 -5
  203. data/lib/rubocop/formatter/formatter_set.rb +2 -1
  204. data/lib/rubocop/formatter/pacman_formatter.rb +80 -0
  205. data/lib/rubocop/formatter/simple_text_formatter.rb +9 -1
  206. data/lib/rubocop/formatter/tap_formatter.rb +9 -1
  207. data/lib/rubocop/magic_comment.rb +4 -0
  208. data/lib/rubocop/node_pattern.rb +86 -7
  209. data/lib/rubocop/options.rb +18 -2
  210. data/lib/rubocop/path_util.rb +1 -1
  211. data/lib/rubocop/processed_source.rb +9 -1
  212. data/lib/rubocop/rspec/cop_helper.rb +0 -1
  213. data/lib/rubocop/rspec/expect_offense.rb +4 -1
  214. data/lib/rubocop/rspec/shared_contexts.rb +12 -17
  215. data/lib/rubocop/rspec/support.rb +0 -1
  216. data/lib/rubocop/runner.rb +20 -15
  217. data/lib/rubocop/target_finder.rb +6 -4
  218. data/lib/rubocop/version.rb +1 -1
  219. data/lib/rubocop/yaml_duplication_checker.rb +8 -2
  220. metadata +16 -70
  221. data/lib/rubocop/cop/mixin/ignored_method_patterns.rb +0 -19
  222. data/lib/rubocop/cop/mixin/target_rails_version.rb +0 -16
  223. data/lib/rubocop/cop/rails/action_filter.rb +0 -117
  224. data/lib/rubocop/cop/rails/active_record_aliases.rb +0 -48
  225. data/lib/rubocop/cop/rails/active_record_override.rb +0 -82
  226. data/lib/rubocop/cop/rails/active_support_aliases.rb +0 -69
  227. data/lib/rubocop/cop/rails/application_job.rb +0 -40
  228. data/lib/rubocop/cop/rails/application_record.rb +0 -40
  229. data/lib/rubocop/cop/rails/assert_not.rb +0 -44
  230. data/lib/rubocop/cop/rails/belongs_to.rb +0 -102
  231. data/lib/rubocop/cop/rails/blank.rb +0 -164
  232. data/lib/rubocop/cop/rails/bulk_change_table.rb +0 -289
  233. data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +0 -91
  234. data/lib/rubocop/cop/rails/date.rb +0 -161
  235. data/lib/rubocop/cop/rails/delegate.rb +0 -132
  236. data/lib/rubocop/cop/rails/delegate_allow_blank.rb +0 -37
  237. data/lib/rubocop/cop/rails/dynamic_find_by.rb +0 -91
  238. data/lib/rubocop/cop/rails/enum_uniqueness.rb +0 -45
  239. data/lib/rubocop/cop/rails/environment_comparison.rb +0 -68
  240. data/lib/rubocop/cop/rails/exit.rb +0 -67
  241. data/lib/rubocop/cop/rails/file_path.rb +0 -108
  242. data/lib/rubocop/cop/rails/find_by.rb +0 -55
  243. data/lib/rubocop/cop/rails/find_each.rb +0 -51
  244. data/lib/rubocop/cop/rails/has_and_belongs_to_many.rb +0 -25
  245. data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +0 -106
  246. data/lib/rubocop/cop/rails/http_positional_arguments.rb +0 -117
  247. data/lib/rubocop/cop/rails/http_status.rb +0 -179
  248. data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +0 -94
  249. data/lib/rubocop/cop/rails/inverse_of.rb +0 -246
  250. data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +0 -175
  251. data/lib/rubocop/cop/rails/link_to_blank.rb +0 -98
  252. data/lib/rubocop/cop/rails/not_null_column.rb +0 -67
  253. data/lib/rubocop/cop/rails/output.rb +0 -49
  254. data/lib/rubocop/cop/rails/output_safety.rb +0 -99
  255. data/lib/rubocop/cop/rails/pluralization_grammar.rb +0 -107
  256. data/lib/rubocop/cop/rails/presence.rb +0 -124
  257. data/lib/rubocop/cop/rails/present.rb +0 -153
  258. data/lib/rubocop/cop/rails/read_write_attribute.rb +0 -74
  259. data/lib/rubocop/cop/rails/redundant_allow_nil.rb +0 -111
  260. data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +0 -136
  261. data/lib/rubocop/cop/rails/reflection_class_name.rb +0 -37
  262. data/lib/rubocop/cop/rails/refute_methods.rb +0 -76
  263. data/lib/rubocop/cop/rails/relative_date_constant.rb +0 -93
  264. data/lib/rubocop/cop/rails/request_referer.rb +0 -56
  265. data/lib/rubocop/cop/rails/reversible_migration.rb +0 -286
  266. data/lib/rubocop/cop/rails/safe_navigation.rb +0 -87
  267. data/lib/rubocop/cop/rails/save_bang.rb +0 -316
  268. data/lib/rubocop/cop/rails/scope_args.rb +0 -29
  269. data/lib/rubocop/cop/rails/skips_model_validations.rb +0 -87
  270. data/lib/rubocop/cop/rails/time_zone.rb +0 -238
  271. data/lib/rubocop/cop/rails/uniq_before_pluck.rb +0 -105
  272. data/lib/rubocop/cop/rails/unknown_env.rb +0 -63
  273. data/lib/rubocop/cop/rails/validation.rb +0 -109
  274. data/lib/rubocop/rspec/shared_examples.rb +0 -59
@@ -45,15 +45,15 @@ module RuboCop
45
45
  CLASS_MSG = 'Prefer Time over DateTime.'
46
46
  COERCION_MSG = 'Do not use #to_datetime.'
47
47
 
48
- def_node_matcher :date_time?, <<-PATTERN
48
+ def_node_matcher :date_time?, <<~PATTERN
49
49
  (send (const {nil? (cbase)} :DateTime) ...)
50
50
  PATTERN
51
51
 
52
- def_node_matcher :historic_date?, <<-PATTERN
52
+ def_node_matcher :historic_date?, <<~PATTERN
53
53
  (send _ _ _ (const (const nil? :Date) _))
54
54
  PATTERN
55
55
 
56
- def_node_matcher :to_datetime?, <<-PATTERN
56
+ def_node_matcher :to_datetime?, <<~PATTERN
57
57
  (send _ :to_datetime)
58
58
  PATTERN
59
59
 
@@ -20,7 +20,7 @@ module RuboCop
20
20
  MSG = 'Use `__dir__` to get an absolute path to the current ' \
21
21
  "file's directory."
22
22
 
23
- def_node_matcher :dir_replacement?, <<-PATTERN
23
+ def_node_matcher :dir_replacement?, <<~PATTERN
24
24
  {(send (const nil? :File) :expand_path (send (const nil? :File) :dirname #file_keyword?))
25
25
  (send (const nil? :File) :dirname (send (const nil? :File) :realpath #file_keyword?))}
26
26
  PATTERN
@@ -53,7 +53,7 @@ module RuboCop
53
53
 
54
54
  MSG = 'Missing method documentation comment.'
55
55
 
56
- def_node_matcher :module_function_node?, <<-PATTERN
56
+ def_node_matcher :module_function_node?, <<~PATTERN
57
57
  (send nil? :module_function ...)
58
58
  PATTERN
59
59
 
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rubocop:disable Lint/UnneededCopDisableDirective
4
+ # rubocop:disable Style/DoubleCopDisableDirective
5
+
6
+ module RuboCop
7
+ module Cop
8
+ module Style
9
+ # Detects double disable comments on one line. This is mostly to catch
10
+ # automatically generated comments that need to be regenerated.
11
+ #
12
+ # @example
13
+ # # bad
14
+ # def f # rubocop:disable Style/For # rubocop:disable Metrics/AbcSize
15
+ # end
16
+ #
17
+ # # good
18
+ # # rubocop:disable Metrics/AbcSize
19
+ # def f # rubocop:disable Style/For
20
+ # end
21
+ # # rubocop:enable Metrics/AbcSize
22
+ #
23
+ # # if both fit on one line
24
+ # def f # rubocop:disable Style/For, Metrics/AbcSize
25
+ # end
26
+ #
27
+ class DoubleCopDisableDirective < Cop
28
+ # rubocop:enable Style/For, Style/DoubleCopDisableDirective
29
+ # rubocop:enable Lint/UnneededCopDisableDirective, Metrics/AbcSize
30
+ MSG = 'More than one disable comment on one line.'
31
+
32
+ def investigate(processed_source)
33
+ processed_source.comments.each do |comment|
34
+ next unless comment.text.scan(/# rubocop:(?:disable|todo)/).size > 1
35
+
36
+ add_offense(comment)
37
+ end
38
+ end
39
+
40
+ def autocorrect(comment)
41
+ prefix = if comment.text.start_with?('# rubocop:disable')
42
+ '# rubocop:disable'
43
+ else
44
+ '# rubocop:todo'
45
+ end
46
+
47
+ lambda do |corrector|
48
+ corrector.replace(comment.loc.expression,
49
+ comment.text[/#{prefix} \S+/])
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -49,7 +49,7 @@ module RuboCop
49
49
 
50
50
  private
51
51
 
52
- def_node_matcher :offending_each_range, <<-PATTERN
52
+ def_node_matcher :offending_each_range, <<~PATTERN
53
53
  (block (send (begin (${irange erange} (int $_) (int $_))) :each) (args) ...)
54
54
  PATTERN
55
55
  end
@@ -22,7 +22,7 @@ module RuboCop
22
22
  MSG = 'Use `each_with_object` instead of `%<method>s`.'
23
23
  METHODS = %i[inject reduce].freeze
24
24
 
25
- def_node_matcher :each_with_object_candidate?, <<-PATTERN
25
+ def_node_matcher :each_with_object_candidate?, <<~PATTERN
26
26
  (block $(send _ {:inject :reduce} _) $_ $_)
27
27
  PATTERN
28
28
 
@@ -37,7 +37,7 @@ module RuboCop
37
37
  MSG_INCORRECT_LINE = 'Use `%<expected>s` instead of `%<actual>s`, ' \
38
38
  'as they are used by backtraces.'
39
39
 
40
- def_node_matcher :eval_without_location?, <<-PATTERN
40
+ def_node_matcher :eval_without_location?, <<~PATTERN
41
41
  {
42
42
  (send nil? :eval ${str dstr})
43
43
  (send nil? :eval ${str dstr} _)
@@ -53,7 +53,7 @@ module RuboCop
53
53
  }
54
54
  PATTERN
55
55
 
56
- def_node_matcher :line_with_offset?, <<-PATTERN
56
+ def_node_matcher :line_with_offset?, <<~PATTERN
57
57
  {
58
58
  (send #special_line_keyword? %1 (int %2))
59
59
  (send (int %2) %1 #special_line_keyword?)
@@ -18,7 +18,7 @@ module RuboCop
18
18
  class EvenOdd < Cop
19
19
  MSG = 'Replace with `Integer#%<method>s?`.'
20
20
 
21
- def_node_matcher :even_odd_candidate?, <<-PATTERN
21
+ def_node_matcher :even_odd_candidate?, <<~PATTERN
22
22
  (send
23
23
  {(send $_ :% (int 2))
24
24
  (begin (send $_ :% (int 2)))}
@@ -51,21 +51,21 @@ module RuboCop
51
51
  'instead of ' \
52
52
  '`Pathname.new(__FILE__).parent.expand_path`.'
53
53
 
54
- def_node_matcher :file_expand_path, <<-PATTERN
54
+ def_node_matcher :file_expand_path, <<~PATTERN
55
55
  (send
56
56
  (const nil? :File) :expand_path
57
57
  $_
58
58
  $_)
59
59
  PATTERN
60
60
 
61
- def_node_matcher :pathname_parent_expand_path, <<-PATTERN
61
+ def_node_matcher :pathname_parent_expand_path, <<~PATTERN
62
62
  (send
63
63
  (send
64
64
  (send nil? :Pathname
65
65
  $_) :parent) :expand_path)
66
66
  PATTERN
67
67
 
68
- def_node_matcher :pathname_new_parent_expand_path, <<-PATTERN
68
+ def_node_matcher :pathname_new_parent_expand_path, <<~PATTERN
69
69
  (send
70
70
  (send
71
71
  (send
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # This cop checks for division with integers coerced to floats.
7
+ # It is recommended to either always use `fdiv` or coerce one side only.
8
+ # This cop also provides other options for code consistency.
9
+ #
10
+ # @example EnforcedStyle: single_coerce (default)
11
+ # # bad
12
+ # a.to_f / b.to_f
13
+ #
14
+ # # good
15
+ # a.to_f / b
16
+ # a / b.to_f
17
+ #
18
+ # @example EnforcedStyle: left_coerce
19
+ # # bad
20
+ # a / b.to_f
21
+ # a.to_f / b.to_f
22
+ #
23
+ # # good
24
+ # a.to_f / b
25
+ #
26
+ # @example EnforcedStyle: right_coerce
27
+ # # bad
28
+ # a.to_f / b
29
+ # a.to_f / b.to_f
30
+ #
31
+ # # good
32
+ # a / b.to_f
33
+ #
34
+ # @example EnforcedStyle: fdiv
35
+ # # bad
36
+ # a / b.to_f
37
+ # a.to_f / b
38
+ # a.to_f / b.to_f
39
+ #
40
+ # # good
41
+ # a.fdiv(b)
42
+ class FloatDivision < Cop
43
+ include ConfigurableEnforcedStyle
44
+
45
+ def_node_matcher :right_coerce?, <<~PATTERN
46
+ (send _ :/ (send _ :to_f))
47
+ PATTERN
48
+ def_node_matcher :left_coerce?, <<~PATTERN
49
+ (send (send _ :to_f) :/ _)
50
+ PATTERN
51
+ def_node_matcher :both_coerce?, <<~PATTERN
52
+ (send (send _ :to_f) :/ (send _ :to_f))
53
+ PATTERN
54
+ def_node_matcher :any_coerce?, <<~PATTERN
55
+ {(send _ :/ (send _ :to_f)) (send (send _ :to_f) :/ _)}
56
+ PATTERN
57
+
58
+ def on_send(node)
59
+ add_offense(node) if offense_condition?(node)
60
+ end
61
+
62
+ private
63
+
64
+ def offense_condition?(node)
65
+ case style
66
+ when :left_coerce
67
+ right_coerce?(node)
68
+ when :right_coerce
69
+ left_coerce?(node)
70
+ when :single_coerce
71
+ both_coerce?(node)
72
+ when :fdiv
73
+ any_coerce?(node)
74
+ else
75
+ false
76
+ end
77
+ end
78
+
79
+ def message(_node)
80
+ case style
81
+ when :left_coerce
82
+ 'Prefer using `.to_f` on the left side.'
83
+ when :right_coerce
84
+ 'Prefer using `.to_f` on the right side.'
85
+ when :single_coerce
86
+ 'Prefer using `.to_f` on one side only.'
87
+ when :fdiv
88
+ 'Prefer using `fdiv` for float divisions.'
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
@@ -40,12 +40,16 @@ module RuboCop
40
40
 
41
41
  MSG = 'Favor `%<prefer>s` over `%<current>s`.'
42
42
 
43
- def_node_matcher :formatter, <<-PATTERN
44
- {
45
- (send nil? ${:sprintf :format} _ _ ...)
46
- (send {str dstr} $:% ... )
47
- (send !nil? $:% {array hash})
48
- }
43
+ def_node_matcher :formatter, <<~PATTERN
44
+ {
45
+ (send nil? ${:sprintf :format} _ _ ...)
46
+ (send {str dstr} $:% ... )
47
+ (send !nil? $:% {array hash})
48
+ }
49
+ PATTERN
50
+
51
+ def_node_matcher :variable_argument?, <<~PATTERN
52
+ (send {str dstr} :% {send_type? lvar_type?})
49
53
  PATTERN
50
54
 
51
55
  def on_send(node)
@@ -70,10 +74,10 @@ module RuboCop
70
74
  end
71
75
 
72
76
  def autocorrect(node)
73
- lambda do |corrector|
74
- detected_method = node.method_name
77
+ return if variable_argument?(node)
75
78
 
76
- case detected_method
79
+ lambda do |corrector|
80
+ case node.method_name
77
81
  when :%
78
82
  autocorrect_from_percent(corrector, node)
79
83
  when :format, :sprintf
@@ -41,15 +41,8 @@ module RuboCop
41
41
  class FormatStringToken < Cop
42
42
  include ConfigurableEnforcedStyle
43
43
 
44
- FIELD_CHARACTERS = Regexp.union(%w[A B E G X a b c d e f g i o p s u x])
45
44
  FORMAT_STRING_METHODS = %i[sprintf format %].freeze
46
45
 
47
- STYLE_PATTERNS = {
48
- annotated: /(?<token>%<[^>]+>#{FIELD_CHARACTERS})/,
49
- template: /(?<token>%\{[^\}]+\})/,
50
- unannotated: /(?<token>%#{FIELD_CHARACTERS})/
51
- }.freeze
52
-
53
46
  def on_str(node)
54
47
  return if placeholder_argument?(node)
55
48
  return if node.each_ancestor(:xstr, :regexp).any?
@@ -113,41 +106,18 @@ module RuboCop
113
106
  end
114
107
 
115
108
  def token_ranges(contents)
116
- while (offending_match = match_token(contents))
117
- detected_style, *range = *offending_match
118
- token, contents = split_token(contents, *range)
119
- yield(detected_style, token)
120
- end
121
- end
122
-
123
- def match_token(source_range)
124
- supported_styles.each do |style_name|
125
- pattern = STYLE_PATTERNS.fetch(style_name)
126
- match = source_range.source.match(pattern)
127
- next unless match
128
-
129
- return [style_name, match.begin(:token), match.end(:token)]
130
- end
131
-
132
- nil
133
- end
134
-
135
- def split_token(source_range, match_begin, match_end)
136
- token =
137
- slice_source(
138
- source_range,
139
- source_range.begin_pos + match_begin,
140
- source_range.begin_pos + match_end
141
- )
142
-
143
- remainder =
144
- slice_source(
145
- source_range,
146
- source_range.begin_pos + match_end,
147
- source_range.end_pos
109
+ format_string = RuboCop::Cop::Utils::FormatString.new(contents.source)
110
+
111
+ format_string.format_sequences.each do |seq|
112
+ detected_style = seq.style
113
+ token = slice_source(
114
+ contents,
115
+ contents.begin_pos + seq.begin_pos,
116
+ contents.begin_pos + seq.end_pos
148
117
  )
149
118
 
150
- [token, remainder]
119
+ yield(detected_style, token)
120
+ end
151
121
  end
152
122
 
153
123
  def slice_source(source_range, new_begin, new_end)
@@ -3,11 +3,13 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # This cop is designed to help upgrade to after Ruby 3.0. It will add the
7
- # comment `# frozen_string_literal: true` to the top of files to
8
- # enable frozen string literals. Frozen string literals may be default
9
- # after Ruby 3.0. The comment will be added below a shebang and encoding
10
- # comment. The frozen string literal comment is only valid in Ruby 2.3+.
6
+ # This cop is designed to help you transition from mutable string literals
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
10
+ # default in future Ruby. The comment will be added below a shebang and
11
+ # encoding comment. The frozen string literal comment is only valid in
12
+ # Ruby 2.3+.
11
13
  #
12
14
  # @example EnforcedStyle: always (default)
13
15
  # # The `always` style will always add the frozen string literal comment
@@ -121,42 +123,25 @@ module RuboCop
121
123
  end
122
124
 
123
125
  def insert_comment(corrector)
124
- last_special_comment = last_special_comment(processed_source)
125
- if last_special_comment.nil?
126
- corrector.insert_before(correction_range, preceding_comment)
127
- else
128
- corrector.insert_after(correction_range, proceeding_comment)
129
- end
130
- end
126
+ comment = last_special_comment(processed_source)
131
127
 
132
- def preceding_comment
133
- if processed_source.tokens[0].space_before?
134
- "#{FROZEN_STRING_LITERAL_ENABLED}\n"
128
+ if comment
129
+ corrector.insert_after(line_range(comment.line), following_comment)
135
130
  else
136
- "#{FROZEN_STRING_LITERAL_ENABLED}\n\n"
131
+ corrector.insert_before(line_range(1), preceding_comment)
137
132
  end
138
133
  end
139
134
 
140
- def proceeding_comment
141
- last_special_comment = last_special_comment(processed_source)
142
- following_line = processed_source.following_line(last_special_comment)
143
-
144
- if following_line&.empty?
145
- "\n#{FROZEN_STRING_LITERAL_ENABLED}"
146
- else
147
- "\n#{FROZEN_STRING_LITERAL_ENABLED}\n"
148
- end
135
+ def line_range(line)
136
+ processed_source.buffer.line_range(line)
149
137
  end
150
138
 
151
- def correction_range
152
- last_special_comment = last_special_comment(processed_source)
139
+ def preceding_comment
140
+ "#{FROZEN_STRING_LITERAL_ENABLED}\n"
141
+ end
153
142
 
154
- if last_special_comment.nil?
155
- range_with_surrounding_space(range: processed_source.tokens[0],
156
- side: :left)
157
- else
158
- last_special_comment.pos
159
- end
143
+ def following_comment
144
+ "\n#{FROZEN_STRING_LITERAL_ENABLED}"
160
145
  end
161
146
  end
162
147
  end
@@ -37,9 +37,10 @@ module RuboCop
37
37
  # ok
38
38
  class GuardClause < Cop
39
39
  include MinBodyLength
40
+ include StatementModifier
40
41
 
41
- MSG = 'Use a guard clause instead of wrapping the code inside a ' \
42
- 'conditional expression.'
42
+ MSG = 'Use a guard clause (`%<example>s`) instead of wrapping the ' \
43
+ 'code inside a conditional expression.'
43
44
 
44
45
  def on_def(node)
45
46
  body = node.body
@@ -55,9 +56,19 @@ module RuboCop
55
56
  alias on_defs on_def
56
57
 
57
58
  def on_if(node)
58
- return if accepted_form?(node) || !contains_guard_clause?(node)
59
+ return if accepted_form?(node)
59
60
 
60
- add_offense(node, location: :keyword)
61
+ guard_clause_in_if = node.if_branch&.guard_clause?
62
+ guard_clause_in_else = node.else_branch&.guard_clause?
63
+ guard_clause = guard_clause_in_if || guard_clause_in_else
64
+ return unless guard_clause
65
+
66
+ kw = if guard_clause_in_if
67
+ node.loc.keyword.source
68
+ else
69
+ opposite_keyword(node)
70
+ end
71
+ register_offense(node, guard_clause.source, kw)
61
72
  end
62
73
 
63
74
  private
@@ -65,7 +76,30 @@ module RuboCop
65
76
  def check_ending_if(node)
66
77
  return if accepted_form?(node, true) || !min_body_length?(node)
67
78
 
68
- add_offense(node, location: :keyword)
79
+ register_offense(node, 'return', opposite_keyword(node))
80
+ end
81
+
82
+ def opposite_keyword(node)
83
+ node.if? ? 'unless' : 'if'
84
+ end
85
+
86
+ def register_offense(node, scope_exiting_keyword, conditional_keyword)
87
+ condition, = node.node_parts
88
+ example = [scope_exiting_keyword,
89
+ conditional_keyword,
90
+ condition.source].join(' ')
91
+ if too_long_for_single_line?(node, example)
92
+ example = "#{conditional_keyword} #{condition.source}; " \
93
+ "#{scope_exiting_keyword}; end"
94
+ end
95
+ add_offense(node,
96
+ location: :keyword,
97
+ message: format(MSG, example: example))
98
+ end
99
+
100
+ def too_long_for_single_line?(node, example)
101
+ max = max_line_length
102
+ max && node.source_range.column + example.length > max
69
103
  end
70
104
 
71
105
  def accepted_form?(node, ending = false)
@@ -81,11 +115,6 @@ module RuboCop
81
115
  !node.else? || node.elsif?
82
116
  end
83
117
  end
84
-
85
- def contains_guard_clause?(node)
86
- node.if_branch&.guard_clause? ||
87
- node.else_branch&.guard_clause?
88
- end
89
118
  end
90
119
  end
91
120
  end