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
@@ -37,7 +37,7 @@ module RuboCop
37
37
  !@references.empty?
38
38
  end
39
39
 
40
- # rubocop:disable Metrics/AbcSize
40
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
41
41
  def reference!(node)
42
42
  reference = Reference.new(node, @scope)
43
43
  @references << reference
@@ -50,6 +50,13 @@ module RuboCop
50
50
  assignment.reference!(node)
51
51
  end
52
52
 
53
+ # Modifier if/unless conditions are special. Assignments made in
54
+ # them do not put the assigned variable in scope to the left of the
55
+ # if/unless keyword. A preceding assignment is needed to put the
56
+ # variable in scope. For this reason we skip to the next assignment
57
+ # here.
58
+ next if in_modifier_if?(assignment)
59
+
53
60
  break if !assignment.branch || assignment.branch == reference.branch
54
61
 
55
62
  unless assignment.branch.may_run_incompletely?
@@ -57,7 +64,13 @@ module RuboCop
57
64
  end
58
65
  end
59
66
  end
60
- # rubocop:enable Metrics/AbcSize
67
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
68
+
69
+ def in_modifier_if?(assignment)
70
+ parent = assignment.node.parent
71
+ parent = parent.parent if parent&.begin_type?
72
+ parent&.if_type? && parent&.modifier_form?
73
+ end
61
74
 
62
75
  def capture_with_block!
63
76
  @captured_by_block = true
@@ -20,28 +20,4 @@ class String
20
20
  empty? || strip.empty?
21
21
  end
22
22
  end
23
-
24
- unless method_defined? :strip_indent
25
- # The method strips the whitespace preceding the base indentation.
26
- # Useful for HEREDOCs and other multi-line strings.
27
- #
28
- # @example
29
- #
30
- # code = <<~END
31
- # def test
32
- # some_method
33
- # other_method
34
- # end
35
- # END
36
- #
37
- # #=> "def\n some_method\n \nother_method\nend"
38
- #
39
- # @todo Replace call sites with squiggly heredocs when required Ruby
40
- # version is >= 2.3.0
41
- def strip_indent
42
- leading_space = scan(/^[ \t]*(?=\S)/).min
43
- indent = leading_space ? leading_space.size : 0
44
- gsub(/^[ \t]{#{indent}}/, '')
45
- end
46
- end
47
23
  end
@@ -8,4 +8,27 @@ module RuboCop
8
8
  class Error < StandardError; end
9
9
 
10
10
  class ValidationError < Error; end
11
+
12
+ # A wrapper to display errored location of analyzed file.
13
+ class ErrorWithAnalyzedFileLocation < Error
14
+ def initialize(cause:, node:, cop:)
15
+ @cause = cause
16
+ @cop = cop
17
+ @location = node.is_a?(RuboCop::AST::Node) ? node.loc : node
18
+ end
19
+
20
+ attr_reader :cause, :cop
21
+
22
+ def line
23
+ @location&.line
24
+ end
25
+
26
+ def column
27
+ @location&.column
28
+ end
29
+
30
+ def message
31
+ "cause: #{cause.inspect}"
32
+ end
33
+ end
11
34
  end
@@ -8,11 +8,14 @@ module RuboCop
8
8
  class EmacsStyleFormatter < BaseFormatter
9
9
  def file_finished(file, offenses)
10
10
  offenses.each do |o|
11
- message = if o.corrected?
12
- "[Corrected] #{o.message}"
13
- else
14
- o.message
15
- end
11
+ message =
12
+ if o.corrected_with_todo?
13
+ "[Todo] #{o.message}"
14
+ elsif o.corrected?
15
+ "[Corrected] #{o.message}"
16
+ else
17
+ o.message
18
+ end
16
19
 
17
20
  output.printf("%s:%d:%d: %s: %s\n",
18
21
  file, o.line, o.real_column, o.severity.code,
@@ -22,7 +22,8 @@ module RuboCop
22
22
  'worst' => WorstOffendersFormatter,
23
23
  'tap' => TapFormatter,
24
24
  'quiet' => QuietFormatter,
25
- 'autogenconf' => AutoGenConfigFormatter
25
+ 'autogenconf' => AutoGenConfigFormatter,
26
+ 'pacman' => PacmanFormatter
26
27
  }.freeze
27
28
 
28
29
  FORMATTER_APIS = %i[started finished].freeze
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Formatter
5
+ # This formatter prints a PACDOT per every file to be analized.
6
+ # Pacman will "eat" one PACDOT per file when no offense is detected.
7
+ # Otherwise it will print a Ghost.
8
+ # This is inspired by the Pacman formatter for RSpec by Carlos Rojas.
9
+ # https://github.com/go-labs/rspec_pacman_formatter
10
+ class PacmanFormatter < ClangStyleFormatter
11
+ include TextUtil
12
+ attr_accessor :progress_line
13
+
14
+ FALLBACK_TERMINAL_WIDTH = 80
15
+ GHOST = 'ᗣ'
16
+ PACMAN = Rainbow('ᗧ').yellow.bright
17
+ PACDOT = Rainbow('•').yellow.bright
18
+
19
+ def initialize(output, options = {})
20
+ super
21
+ @progress_line = ''
22
+ @total_files = 0
23
+ @repetitions = 0
24
+ end
25
+
26
+ def started(target_files)
27
+ super
28
+ @total_files = target_files.size
29
+ output.puts "Eating #{pluralize(target_files.size, 'file')}"
30
+ update_progress_line
31
+ end
32
+
33
+ def file_started(_file, _options)
34
+ step(PACMAN)
35
+ end
36
+
37
+ def file_finished(file, offenses)
38
+ count_stats(offenses) unless offenses.empty?
39
+ next_step(offenses)
40
+ report_file(file, offenses)
41
+ end
42
+
43
+ def next_step(offenses)
44
+ return step('.') if offenses.empty?
45
+
46
+ ghost_color = COLOR_FOR_SEVERITY[offenses.last.severity.name]
47
+ step(colorize(GHOST, ghost_color))
48
+ end
49
+
50
+ def cols
51
+ @cols ||= begin
52
+ width = `tput cols`.chomp.to_i
53
+ width.nil? || width.zero? ? FALLBACK_TERMINAL_WIDTH : width
54
+ end
55
+ end
56
+
57
+ def update_progress_line
58
+ return pacdots(@total_files) unless @total_files > cols
59
+ return pacdots(cols) unless (@total_files / cols).eql?(@repetitions)
60
+
61
+ pacdots((@total_files - (cols * @repetitions)))
62
+ end
63
+
64
+ def pacdots(number)
65
+ @progress_line = PACDOT * number
66
+ end
67
+
68
+ def step(character)
69
+ regex = /#{Regexp.quote(PACMAN)}|#{Regexp.quote(PACDOT)}/
70
+ @progress_line = @progress_line.sub(regex, character)
71
+ output.printf("%s\r", @progress_line)
72
+ return unless @progress_line[-1] =~ /ᗣ|\./
73
+
74
+ @repetitions += 1
75
+ output.puts
76
+ update_progress_line
77
+ end
78
+ end
79
+ end
80
+ end
@@ -75,7 +75,15 @@ module RuboCop
75
75
  end
76
76
 
77
77
  def message(offense)
78
- message = offense.corrected? ? green('[Corrected] ') : ''
78
+ message =
79
+ if offense.corrected_with_todo?
80
+ green('[Todo] ')
81
+ elsif offense.corrected?
82
+ green('[Corrected] ')
83
+ else
84
+ ''
85
+ end
86
+
79
87
  "#{message}#{annotate_message(offense.message)}"
80
88
  end
81
89
 
@@ -63,7 +63,15 @@ module RuboCop
63
63
  end
64
64
 
65
65
  def message(offense)
66
- message = offense.corrected? ? '[Corrected] ' : ''
66
+ message =
67
+ if offense.corrected_with_todo?
68
+ '[Todo] '
69
+ elsif offense.corrected?
70
+ '[Corrected] '
71
+ else
72
+ ''
73
+ end
74
+
67
75
  "#{message}#{annotate_message(offense.message)}"
68
76
  end
69
77
  end
@@ -42,6 +42,10 @@ module RuboCop
42
42
  frozen_string_literal == true
43
43
  end
44
44
 
45
+ def valid_literal_value?
46
+ [true, false].include?(frozen_string_literal)
47
+ end
48
+
45
49
  # Was a magic comment for the frozen string literal found?
46
50
  #
47
51
  # @return [Boolean]
@@ -47,6 +47,11 @@ module RuboCop
47
47
  # # a `sym` node, but can have more.
48
48
  # '(array <$str $_>)' # captures are in the order of the pattern,
49
49
  # # irrespective of the actual order of the children
50
+ # '(array int*)' # will match an array of 0 or more integers
51
+ # '(array int ?)' # will match 0 or 1 integer.
52
+ # # Note: Space needed to distinguish from int?
53
+ # '(array int+)' # will match an array of 1 or more integers
54
+ # '(array (int $_)+)' # as above and will capture the numbers in an array
50
55
  # '(send $...)' # capture all the children as an array
51
56
  # '(send $... int)' # capture all children but the last as an array
52
57
  # '(send _x :+ _x)' # unification is performed on named wildcards
@@ -106,7 +111,9 @@ module RuboCop
106
111
  class Compiler
107
112
  SYMBOL = %r{:(?:[\w+@*/?!<>=~|%^-]+|\[\]=?)}.freeze
108
113
  IDENTIFIER = /[a-zA-Z_][a-zA-Z0-9_-]*/.freeze
109
- META = Regexp.union(%w"( ) { } [ ] $< < > $... $ ! ^ ...").freeze
114
+ META = Regexp.union(
115
+ %w"( ) { } [ ] $< < > $... $ ! ^ ... + * ?"
116
+ ).freeze
110
117
  NUMBER = /-?\d+(?:\.\d+)?/.freeze
111
118
  STRING = /".+?"/.freeze
112
119
  METHOD_NAME = /\#?#{IDENTIFIER}[\!\?]?\(?/.freeze
@@ -160,6 +167,21 @@ module RuboCop
160
167
  RUBY
161
168
  ANY_ORDER_TEMPLATE.location = [__FILE__, line + 1]
162
169
 
170
+ line = __LINE__
171
+ REPEATED_TEMPLATE = ERB.new <<~RUBY.gsub("-%>\n", '%>')
172
+ <% if captured %>(<%= accumulate %> = Array.new) && <% end %>
173
+ <%= CUR_NODE %>.children[<%= range %>].all? do |<%= child %>|
174
+ <%= with_context(expr, child, use_temp_node: false) %><% if captured %>&&
175
+ <%= accumulate %>.push(<%= captured %>)<% end %>
176
+ end <% if captured %>&&
177
+ (<%= captured %> = if <%= accumulate %>.empty?
178
+ <%= captured %>.map{[]} # Transpose hack won't work for empty case
179
+ else
180
+ <%= accumulate %>.transpose
181
+ end) <% end -%>
182
+ RUBY
183
+ REPEATED_TEMPLATE.location = [__FILE__, line + 1]
184
+
163
185
  def initialize(str, node_var = 'node0')
164
186
  @string = str
165
187
  @root = node_var
@@ -238,10 +260,48 @@ module RuboCop
238
260
  when REST then compile_ellipsis
239
261
  when '$<' then compile_any_order(next_capture)
240
262
  when '<' then compile_any_order
241
- else [1, compile_expr(token)]
263
+ else compile_repeated_expr(token)
264
+ end
265
+ end
266
+
267
+ def compile_repeated_expr(token)
268
+ before = @captures
269
+ expr = compile_expr(token)
270
+ min, max = parse_repetition_token
271
+ return [1, expr] if min.nil?
272
+
273
+ if @captures != before
274
+ captured = "captures[#{before}...#{@captures}]"
275
+ accumulate = next_temp_variable(:accumulate)
276
+ end
277
+ arity = min..max || Float::INFINITY
278
+
279
+ [arity, repeated_generator(expr, captured, accumulate)]
280
+ end
281
+
282
+ def repeated_generator(expr, captured, accumulate)
283
+ with_temp_variables do |child|
284
+ lambda do |range|
285
+ if range.begin == SEQ_HEAD_INDEX
286
+ fail_due_to 'repeated pattern at beginning of sequence'
287
+ end
288
+ REPEATED_TEMPLATE.result(binding)
289
+ end
242
290
  end
243
291
  end
244
292
 
293
+ def parse_repetition_token
294
+ case tokens.first
295
+ when '*' then min = 0
296
+ when '+' then min = 1
297
+ when '?' then min = 0
298
+ max = 1
299
+ else return
300
+ end
301
+ tokens.shift
302
+ [min, max]
303
+ end
304
+
245
305
  # @private
246
306
  # Builds Ruby code for a sequence
247
307
  # (head *first_terms variadic_term *last_terms)
@@ -276,6 +336,10 @@ module RuboCop
276
336
  last_terms_range { |r| @arities[r].inject(0, :+) } || 0
277
337
  end
278
338
 
339
+ def variadic_term_min_arity
340
+ @variadic_index ? @arities[@variadic_index].begin : 0
341
+ end
342
+
279
343
  def first_terms_range
280
344
  yield 1..(@variadic_index || @terms.size) - 1 if seq_head?
281
345
  end
@@ -289,8 +353,19 @@ module RuboCop
289
353
  end
290
354
 
291
355
  def compile_child_nb_guard
292
- min = first_terms_arity + last_terms_arity
293
- "#{CUR_NODE}.children.size #{@variadic_index ? '>' : '='}= #{min}"
356
+ fixed = first_terms_arity + last_terms_arity
357
+ min = fixed + variadic_term_min_arity
358
+ op = if @variadic_index
359
+ max_variadic = @arities[@variadic_index].end
360
+ if max_variadic != Float::INFINITY
361
+ range = min..fixed + max_variadic
362
+ return "(#{range}).cover?(#{CUR_NODE}.children.size)"
363
+ end
364
+ '>='
365
+ else
366
+ '=='
367
+ end
368
+ "#{CUR_NODE}.children.size #{op} #{min}"
294
369
  end
295
370
 
296
371
  def term(index, range)
@@ -537,7 +612,7 @@ module RuboCop
537
612
  end
538
613
 
539
614
  def emit_method_code
540
- <<-RUBY
615
+ <<~RUBY
541
616
  return unless #{@match_code}
542
617
  block_given? ? #{emit_yield_capture} : (return #{emit_retval})
543
618
  RUBY
@@ -555,10 +630,14 @@ module RuboCop
555
630
  end
556
631
 
557
632
  def with_temp_variables(&block)
558
- names = block.parameters.map { |_, name| "#{name}#{next_temp_value}" }
633
+ names = block.parameters.map { |_, name| next_temp_variable(name) }
559
634
  yield(*names)
560
635
  end
561
636
 
637
+ def next_temp_variable(name)
638
+ "#{name}#{next_temp_value}"
639
+ end
640
+
562
641
  def next_temp_value
563
642
  @temps += 1
564
643
  end
@@ -667,7 +746,7 @@ module RuboCop
667
746
 
668
747
  def node_search_body(method_name, trailing_params, prelude, match_code,
669
748
  on_match)
670
- <<-RUBY
749
+ <<~RUBY
671
750
  def #{method_name}(node0#{trailing_params})
672
751
  #{prelude}
673
752
  node0.each_node do |node|
@@ -109,6 +109,8 @@ module RuboCop
109
109
  @validator.validate_exclude_limit_option
110
110
  end
111
111
 
112
+ option(opts, '--disable-uncorrectable')
113
+
112
114
  option(opts, '--no-offense-counts') do
113
115
  @options[:no_offense_counts] = true
114
116
  end
@@ -159,7 +161,6 @@ module RuboCop
159
161
  option(opts, '-D', '--[no-]display-cop-names')
160
162
  option(opts, '-E', '--extra-details')
161
163
  option(opts, '-S', '--display-style-guide')
162
- option(opts, '-R', '--rails')
163
164
  option(opts, '-a', '--auto-correct')
164
165
  option(opts, '--ignore-disable-comments')
165
166
 
@@ -254,6 +255,7 @@ module RuboCop
254
255
  @options = options
255
256
  end
256
257
 
258
+ # rubocop:disable Metrics/AbcSize
257
259
  def validate_compatibility # rubocop:disable Metrics/MethodLength
258
260
  if only_includes_unneeded_disable?
259
261
  raise OptionArgumentError, 'Lint/UnneededCopDisableDirective can not ' \
@@ -271,6 +273,7 @@ module RuboCop
271
273
  '--display-only-fail-level-offenses'
272
274
  end
273
275
  validate_auto_gen_config
276
+ validate_auto_correct
274
277
  validate_parallel
275
278
 
276
279
  return if incompatible_options.size <= 1
@@ -278,6 +281,7 @@ module RuboCop
278
281
  raise OptionArgumentError, 'Incompatible cli options: ' \
279
282
  "#{incompatible_options.inspect}"
280
283
  end
284
+ # rubocop:enable Metrics/AbcSize
281
285
 
282
286
  def validate_auto_gen_config
283
287
  return if @options.key?(:auto_gen_config)
@@ -293,6 +297,15 @@ module RuboCop
293
297
  end
294
298
  end
295
299
 
300
+ def validate_auto_correct
301
+ return if @options.key?(:auto_correct)
302
+ return unless @options.key?(:disable_uncorrectable)
303
+
304
+ raise OptionArgumentError,
305
+ format('--%<flag>s can only be used together with --auto-correct.',
306
+ flag: '--disable-uncorrectable')
307
+ end
308
+
296
309
  def validate_parallel
297
310
  return unless @options.key?(:parallel)
298
311
 
@@ -379,6 +392,9 @@ module RuboCop
379
392
  exclude_limit: ['Used together with --auto-gen-config to',
380
393
  'set the limit for how many Exclude',
381
394
  "properties to generate. Default is #{MAX_EXCL}."],
395
+ disable_uncorrectable: ['Used with --auto-correct to annotate any',
396
+ 'offenses that do not support autocorrect',
397
+ 'with `rubocop:todo` comments.'],
382
398
  force_exclusion: ['Force excluding files specified in the',
383
399
  'configuration `Exclude` even if they are',
384
400
  'explicitly passed as arguments.'],
@@ -396,6 +412,7 @@ module RuboCop
396
412
  ' [c]lang',
397
413
  ' [d]isabled cops via inline comments',
398
414
  ' [fu]ubar',
415
+ ' [pa]cman',
399
416
  ' [e]macs',
400
417
  ' [j]son',
401
418
  ' [h]tml',
@@ -429,7 +446,6 @@ module RuboCop
429
446
  'Default is true.'],
430
447
  display_style_guide: 'Display style guide URLs in offense messages.',
431
448
  extra_details: 'Display extra details in offense messages.',
432
- rails: 'Run extra Rails cops.',
433
449
  lint: 'Run only lint cops.',
434
450
  safe: 'Run only safe cops.',
435
451
  list_target_files: 'List all files RuboCop will inspect.',