rubocop 0.73.0 → 0.77.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 (216) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -2
  3. data/bin/console +1 -0
  4. data/config/default.yml +332 -295
  5. data/lib/rubocop.rb +46 -30
  6. data/lib/rubocop/ast/builder.rb +1 -0
  7. data/lib/rubocop/ast/node.rb +6 -8
  8. data/lib/rubocop/ast/node/block_node.rb +2 -0
  9. data/lib/rubocop/ast/node/mixin/method_dispatch_node.rb +1 -12
  10. data/lib/rubocop/ast/node/return_node.rb +24 -0
  11. data/lib/rubocop/cli.rb +11 -227
  12. data/lib/rubocop/cli/command.rb +21 -0
  13. data/lib/rubocop/cli/command/auto_genenerate_config.rb +105 -0
  14. data/lib/rubocop/cli/command/base.rb +33 -0
  15. data/lib/rubocop/cli/command/execute_runner.rb +76 -0
  16. data/lib/rubocop/cli/command/init_dotfile.rb +45 -0
  17. data/lib/rubocop/cli/command/show_cops.rb +73 -0
  18. data/lib/rubocop/cli/command/version.rb +17 -0
  19. data/lib/rubocop/cli/environment.rb +21 -0
  20. data/lib/rubocop/comment_config.rb +5 -4
  21. data/lib/rubocop/config.rb +28 -537
  22. data/lib/rubocop/config_loader.rb +21 -3
  23. data/lib/rubocop/config_loader_resolver.rb +4 -3
  24. data/lib/rubocop/config_obsoletion.rb +275 -0
  25. data/lib/rubocop/config_validator.rb +246 -0
  26. data/lib/rubocop/cop/autocorrect_logic.rb +2 -2
  27. data/lib/rubocop/cop/bundler/gem_comment.rb +4 -4
  28. data/lib/rubocop/cop/commissioner.rb +15 -7
  29. data/lib/rubocop/cop/cop.rb +33 -9
  30. data/lib/rubocop/cop/corrector.rb +8 -7
  31. data/lib/rubocop/cop/correctors/alignment_corrector.rb +43 -17
  32. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +2 -2
  33. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +1 -1
  34. data/lib/rubocop/cop/correctors/space_corrector.rb +1 -2
  35. data/lib/rubocop/cop/generator.rb +3 -3
  36. data/lib/rubocop/cop/generator/configuration_injector.rb +9 -4
  37. data/lib/rubocop/cop/generator/require_file_injector.rb +1 -1
  38. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  39. data/lib/rubocop/cop/internal_affairs/method_name_equal.rb +59 -0
  40. data/lib/rubocop/cop/layout/{align_arguments.rb → argument_alignment.rb} +1 -1
  41. data/lib/rubocop/cop/layout/{align_array.rb → array_alignment.rb} +1 -1
  42. data/lib/rubocop/cop/layout/{indent_assignment.rb → assignment_indentation.rb} +11 -2
  43. data/lib/rubocop/cop/layout/block_alignment.rb +2 -2
  44. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +1 -1
  45. data/lib/rubocop/cop/layout/comment_indentation.rb +10 -13
  46. data/lib/rubocop/cop/layout/empty_comment.rb +7 -16
  47. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +22 -7
  48. data/lib/rubocop/cop/layout/empty_line_after_magic_comment.rb +2 -2
  49. data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +2 -2
  50. data/lib/rubocop/cop/layout/end_of_line.rb +8 -3
  51. data/lib/rubocop/cop/layout/extra_spacing.rb +15 -60
  52. data/lib/rubocop/cop/layout/{indent_first_argument.rb → first_argument_indentation.rb} +12 -10
  53. data/lib/rubocop/cop/layout/{indent_first_array_element.rb → first_array_element_indentation.rb} +4 -4
  54. data/lib/rubocop/cop/layout/{indent_first_hash_element.rb → first_hash_element_indentation.rb} +4 -4
  55. data/lib/rubocop/cop/layout/{indent_first_parameter.rb → first_parameter_indentation.rb} +3 -3
  56. data/lib/rubocop/cop/layout/{align_hash.rb → hash_alignment.rb} +8 -4
  57. data/lib/rubocop/cop/layout/{indent_heredoc.rb → heredoc_indentation.rb} +2 -2
  58. data/lib/rubocop/cop/layout/indentation_width.rb +19 -5
  59. data/lib/rubocop/cop/layout/{leading_blank_lines.rb → leading_empty_lines.rb} +1 -1
  60. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -1
  61. data/lib/rubocop/cop/layout/multiline_block_layout.rb +24 -2
  62. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +1 -1
  63. data/lib/rubocop/cop/layout/{align_parameters.rb → parameter_alignment.rb} +1 -1
  64. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +2 -0
  65. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +5 -1
  66. data/lib/rubocop/cop/layout/space_around_keyword.rb +12 -0
  67. data/lib/rubocop/cop/layout/space_around_operators.rb +43 -24
  68. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +9 -7
  69. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +8 -5
  70. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +7 -0
  71. data/lib/rubocop/cop/layout/space_inside_parens.rb +6 -6
  72. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +24 -40
  73. data/lib/rubocop/cop/layout/{trailing_blank_lines.rb → trailing_empty_lines.rb} +1 -1
  74. data/lib/rubocop/cop/layout/trailing_whitespace.rb +18 -2
  75. data/lib/rubocop/cop/lint/assignment_in_condition.rb +17 -4
  76. data/lib/rubocop/cop/lint/debugger.rb +1 -3
  77. data/lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb +1 -1
  78. data/lib/rubocop/cop/lint/{duplicated_key.rb → duplicate_hash_key.rb} +1 -1
  79. data/lib/rubocop/cop/lint/empty_interpolation.rb +4 -4
  80. data/lib/rubocop/cop/lint/erb_new_arguments.rb +61 -4
  81. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +10 -36
  82. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -1
  83. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +7 -8
  84. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +2 -2
  85. data/lib/rubocop/cop/lint/{multiple_compare.rb → multiple_comparison.rb} +1 -1
  86. data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
  87. data/lib/rubocop/cop/lint/{unneeded_cop_disable_directive.rb → redundant_cop_disable_directive.rb} +24 -24
  88. data/lib/rubocop/cop/lint/{unneeded_cop_enable_directive.rb → redundant_cop_enable_directive.rb} +6 -8
  89. data/lib/rubocop/cop/lint/{unneeded_require_statement.rb → redundant_require_statement.rb} +1 -1
  90. data/lib/rubocop/cop/lint/{unneeded_splat_expansion.rb → redundant_splat_expansion.rb} +12 -7
  91. data/lib/rubocop/cop/lint/{string_conversion_in_interpolation.rb → redundant_string_coercion.rb} +7 -7
  92. data/lib/rubocop/cop/lint/redundant_with_index.rb +2 -2
  93. data/lib/rubocop/cop/lint/redundant_with_object.rb +2 -2
  94. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +5 -6
  95. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +91 -0
  96. data/lib/rubocop/cop/lint/{handle_exceptions.rb → suppressed_exception.rb} +1 -1
  97. data/lib/rubocop/cop/lint/unused_block_argument.rb +22 -6
  98. data/lib/rubocop/cop/lint/unused_method_argument.rb +23 -5
  99. data/lib/rubocop/cop/lint/useless_access_modifier.rb +57 -23
  100. data/lib/rubocop/cop/lint/useless_setter_call.rb +1 -1
  101. data/lib/rubocop/cop/lint/void.rb +7 -26
  102. data/lib/rubocop/cop/message_annotator.rb +16 -7
  103. data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
  104. data/lib/rubocop/cop/metrics/line_length.rb +48 -42
  105. data/lib/rubocop/cop/metrics/method_length.rb +1 -1
  106. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +23 -6
  107. data/lib/rubocop/cop/migration/department_name.rb +44 -0
  108. data/lib/rubocop/cop/mixin/alignment.rb +1 -1
  109. data/lib/rubocop/cop/mixin/documentation_comment.rb +0 -2
  110. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -1
  111. data/lib/rubocop/cop/mixin/{hash_alignment.rb → hash_alignment_styles.rb} +1 -1
  112. data/lib/rubocop/cop/mixin/interpolation.rb +27 -0
  113. data/lib/rubocop/cop/mixin/method_complexity.rb +2 -1
  114. data/lib/rubocop/cop/mixin/nil_methods.rb +4 -4
  115. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +87 -0
  116. data/lib/rubocop/cop/mixin/statement_modifier.rb +5 -2
  117. data/lib/rubocop/cop/mixin/surrounding_space.rb +7 -5
  118. data/lib/rubocop/cop/mixin/trailing_comma.rb +8 -6
  119. data/lib/rubocop/cop/naming/{uncommunicative_block_param_name.rb → block_parameter_name.rb} +3 -3
  120. data/lib/rubocop/cop/naming/file_name.rb +12 -5
  121. data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +5 -5
  122. data/lib/rubocop/cop/naming/method_name.rb +12 -1
  123. data/lib/rubocop/cop/naming/{uncommunicative_method_param_name.rb → method_parameter_name.rb} +3 -3
  124. data/lib/rubocop/cop/naming/predicate_name.rb +6 -6
  125. data/lib/rubocop/cop/naming/variable_name.rb +1 -0
  126. data/lib/rubocop/cop/offense.rb +18 -7
  127. data/lib/rubocop/cop/registry.rb +22 -1
  128. data/lib/rubocop/cop/style/access_modifier_declarations.rb +1 -0
  129. data/lib/rubocop/cop/style/alias.rb +1 -1
  130. data/lib/rubocop/cop/style/array_join.rb +1 -1
  131. data/lib/rubocop/cop/style/attr.rb +2 -2
  132. data/lib/rubocop/cop/style/block_delimiters.rb +2 -1
  133. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +35 -16
  134. data/lib/rubocop/cop/style/class_and_module_children.rb +1 -1
  135. data/lib/rubocop/cop/style/comment_annotation.rb +5 -5
  136. data/lib/rubocop/cop/style/commented_keyword.rb +16 -30
  137. data/lib/rubocop/cop/style/conditional_assignment.rb +5 -7
  138. data/lib/rubocop/cop/style/constant_visibility.rb +13 -2
  139. data/lib/rubocop/cop/style/copyright.rb +11 -7
  140. data/lib/rubocop/cop/style/documentation_method.rb +44 -0
  141. data/lib/rubocop/cop/style/double_cop_disable_directive.rb +10 -4
  142. data/lib/rubocop/cop/style/empty_case_condition.rb +2 -2
  143. data/lib/rubocop/cop/style/empty_literal.rb +2 -2
  144. data/lib/rubocop/cop/style/empty_method.rb +5 -5
  145. data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
  146. data/lib/rubocop/cop/style/even_odd.rb +1 -1
  147. data/lib/rubocop/cop/style/expand_path_arguments.rb +1 -1
  148. data/lib/rubocop/cop/style/format_string.rb +10 -7
  149. data/lib/rubocop/cop/style/format_string_token.rb +19 -68
  150. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +28 -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_unless_modifier.rb +58 -15
  154. data/lib/rubocop/cop/style/infinite_loop.rb +5 -4
  155. data/lib/rubocop/cop/style/inverse_methods.rb +19 -13
  156. data/lib/rubocop/cop/style/ip_addresses.rb +4 -4
  157. data/lib/rubocop/cop/style/lambda.rb +0 -2
  158. data/lib/rubocop/cop/style/line_end_concatenation.rb +14 -10
  159. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +25 -25
  160. data/lib/rubocop/cop/style/method_def_parentheses.rb +17 -9
  161. data/lib/rubocop/cop/style/mixin_grouping.rb +1 -1
  162. data/lib/rubocop/cop/style/mixin_usage.rb +11 -1
  163. data/lib/rubocop/cop/style/multiline_memoization.rb +1 -1
  164. data/lib/rubocop/cop/style/multiline_when_then.rb +1 -1
  165. data/lib/rubocop/cop/style/nested_modifier.rb +22 -4
  166. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +5 -5
  167. data/lib/rubocop/cop/style/next.rb +5 -5
  168. data/lib/rubocop/cop/style/non_nil_check.rb +21 -9
  169. data/lib/rubocop/cop/style/numeric_literals.rb +7 -3
  170. data/lib/rubocop/cop/style/option_hash.rb +3 -3
  171. data/lib/rubocop/cop/style/or_assignment.rb +6 -1
  172. data/lib/rubocop/cop/style/parentheses_around_condition.rb +14 -0
  173. data/lib/rubocop/cop/style/{unneeded_capital_w.rb → redundant_capital_w.rb} +1 -1
  174. data/lib/rubocop/cop/style/{unneeded_condition.rb → redundant_condition.rb} +3 -3
  175. data/lib/rubocop/cop/style/{unneeded_interpolation.rb → redundant_interpolation.rb} +1 -1
  176. data/lib/rubocop/cop/style/redundant_parentheses.rb +16 -7
  177. data/lib/rubocop/cop/style/{unneeded_percent_q.rb → redundant_percent_q.rb} +1 -1
  178. data/lib/rubocop/cop/style/redundant_return.rb +39 -29
  179. data/lib/rubocop/cop/style/redundant_self.rb +18 -1
  180. data/lib/rubocop/cop/style/{unneeded_sort.rb → redundant_sort.rb} +5 -5
  181. data/lib/rubocop/cop/style/rescue_modifier.rb +24 -0
  182. data/lib/rubocop/cop/style/safe_navigation.rb +23 -3
  183. data/lib/rubocop/cop/style/semicolon.rb +13 -2
  184. data/lib/rubocop/cop/style/single_line_methods.rb +8 -1
  185. data/lib/rubocop/cop/style/special_global_vars.rb +5 -7
  186. data/lib/rubocop/cop/style/ternary_parentheses.rb +19 -0
  187. data/lib/rubocop/cop/style/trailing_method_end_statement.rb +4 -6
  188. data/lib/rubocop/cop/style/trivial_accessors.rb +5 -5
  189. data/lib/rubocop/cop/style/variable_interpolation.rb +6 -16
  190. data/lib/rubocop/cop/team.rb +5 -0
  191. data/lib/rubocop/cop/util.rb +1 -1
  192. data/lib/rubocop/cop/utils/format_string.rb +120 -0
  193. data/lib/rubocop/cop/variable_force.rb +7 -5
  194. data/lib/rubocop/cop/variable_force/variable.rb +15 -2
  195. data/lib/rubocop/core_ext/string.rb +0 -24
  196. data/lib/rubocop/formatter/clang_style_formatter.rb +9 -6
  197. data/lib/rubocop/formatter/emacs_style_formatter.rb +22 -9
  198. data/lib/rubocop/formatter/file_list_formatter.rb +1 -1
  199. data/lib/rubocop/formatter/formatter_set.rb +16 -15
  200. data/lib/rubocop/formatter/pacman_formatter.rb +80 -0
  201. data/lib/rubocop/formatter/simple_text_formatter.rb +16 -4
  202. data/lib/rubocop/formatter/tap_formatter.rb +18 -7
  203. data/lib/rubocop/magic_comment.rb +4 -0
  204. data/lib/rubocop/node_pattern.rb +3 -1
  205. data/lib/rubocop/options.rb +17 -22
  206. data/lib/rubocop/path_util.rb +1 -1
  207. data/lib/rubocop/processed_source.rb +5 -1
  208. data/lib/rubocop/rake_task.rb +1 -0
  209. data/lib/rubocop/result_cache.rb +22 -8
  210. data/lib/rubocop/rspec/expect_offense.rb +4 -1
  211. data/lib/rubocop/runner.rb +55 -32
  212. data/lib/rubocop/target_finder.rb +12 -6
  213. data/lib/rubocop/version.rb +1 -1
  214. metadata +47 -32
  215. data/lib/rubocop/cop/mixin/ignored_method_patterns.rb +0 -19
  216. data/lib/rubocop/cop/mixin/safe_mode.rb +0 -22
@@ -42,9 +42,13 @@ module RuboCop
42
42
  output.puts yellow("== #{smart_path(file)} ==")
43
43
 
44
44
  offenses.each do |o|
45
- output.printf("%s:%3d:%3d: %s\n",
46
- colored_severity_code(o),
47
- o.line, o.real_column, message(o))
45
+ output.printf(
46
+ "%<severity>s:%3<line>d:%3<column>d: %<message>s\n",
47
+ severity: colored_severity_code(o),
48
+ line: o.line,
49
+ column: o.real_column,
50
+ message: message(o)
51
+ )
48
52
  end
49
53
  end
50
54
 
@@ -75,7 +79,15 @@ module RuboCop
75
79
  end
76
80
 
77
81
  def message(offense)
78
- message = offense.corrected? ? green('[Corrected] ') : ''
82
+ message =
83
+ if offense.corrected_with_todo?
84
+ green('[Todo] ')
85
+ elsif offense.corrected?
86
+ green('[Corrected] ')
87
+ else
88
+ ''
89
+ end
90
+
79
91
  "#{message}#{annotate_message(offense.message)}"
80
92
  end
81
93
 
@@ -42,20 +42,23 @@ module RuboCop
42
42
  end
43
43
 
44
44
  def report_offense(file, offense)
45
- output.printf("# %s:%d:%d: %s: %s\n",
46
- cyan(smart_path(file)), offense.line, offense.real_column,
47
- colored_severity_code(offense), message(offense))
45
+ output.printf(
46
+ "# %<path>s:%<line>d:%<column>d: %<severity>s: %<message>s\n",
47
+ path: cyan(smart_path(file)),
48
+ line: offense.line,
49
+ column: offense.real_column,
50
+ severity: colored_severity_code(offense),
51
+ message: message(offense)
52
+ )
48
53
 
49
- # rubocop:disable Lint/HandleExceptions
50
54
  begin
51
55
  return unless valid_line?(offense)
52
56
 
53
57
  report_line(offense.location)
54
58
  report_highlighted_area(offense.highlighted_area)
55
- rescue IndexError
59
+ rescue IndexError # rubocop:disable Lint/SuppressedException
56
60
  # range is not on a valid line; perhaps the source file is empty
57
61
  end
58
- # rubocop:enable Lint/HandleExceptions
59
62
  end
60
63
 
61
64
  def annotate_message(msg)
@@ -63,7 +66,15 @@ module RuboCop
63
66
  end
64
67
 
65
68
  def message(offense)
66
- message = offense.corrected? ? '[Corrected] ' : ''
69
+ message =
70
+ if offense.corrected_with_todo?
71
+ '[Todo] '
72
+ elsif offense.corrected?
73
+ '[Corrected] '
74
+ else
75
+ ''
76
+ end
77
+
67
78
  "#{message}#{annotate_message(offense.message)}"
68
79
  end
69
80
  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]
@@ -429,12 +429,13 @@ module RuboCop
429
429
  [0..Float::INFINITY, 'true']
430
430
  end
431
431
 
432
+ # rubocop:disable Metrics/AbcSize
432
433
  # rubocop:disable Metrics/MethodLength
433
434
  def compile_any_order(capture_all = nil)
434
435
  rest = capture_rest = nil
435
436
  patterns = []
436
437
  with_temp_variables do |child, matched|
437
- tokens_until('>', 'any child').each do
438
+ tokens_until('>', 'any child') do
438
439
  fail_due_to 'ellipsis must be at the end of <>' if rest
439
440
  token = tokens.shift
440
441
  case token
@@ -448,6 +449,7 @@ module RuboCop
448
449
  end
449
450
  end
450
451
  # rubocop:enable Metrics/MethodLength
452
+ # rubocop:enable Metrics/AbcSize
451
453
 
452
454
  def insure_same_captures(enum, what)
453
455
  return to_enum __method__, enum, what unless block_given?
@@ -255,11 +255,17 @@ module RuboCop
255
255
  @options = options
256
256
  end
257
257
 
258
+ def validate_cop_options
259
+ %i[only except].each do |opt|
260
+ OptionsValidator.validate_cop_list(@options[opt])
261
+ end
262
+ end
263
+
258
264
  # rubocop:disable Metrics/AbcSize
259
265
  def validate_compatibility # rubocop:disable Metrics/MethodLength
260
- if only_includes_unneeded_disable?
261
- raise OptionArgumentError, 'Lint/UnneededCopDisableDirective can not ' \
262
- 'be used with --only.'
266
+ if only_includes_redundant_disable?
267
+ raise OptionArgumentError, 'Lint/RedundantCopDisableDirective can ' \
268
+ 'not be used with --only.'
263
269
  end
264
270
  if except_syntax?
265
271
  raise OptionArgumentError, 'Syntax checking can not be turned off.'
@@ -332,10 +338,10 @@ module RuboCop
332
338
  end
333
339
  end
334
340
 
335
- def only_includes_unneeded_disable?
341
+ def only_includes_redundant_disable?
336
342
  @options.key?(:only) &&
337
- (@options[:only] & %w[Lint/UnneededCopDisableDirective
338
- UnneededCopDisableDirective]).any?
343
+ (@options[:only] & %w[Lint/RedundantCopDisableDirective
344
+ RedundantCopDisableDirective]).any?
339
345
  end
340
346
 
341
347
  def display_only_fail_level_offenses_with_autocorrect?
@@ -367,8 +373,9 @@ module RuboCop
367
373
  # This module contains help texts for command line options.
368
374
  module OptionsHelp
369
375
  MAX_EXCL = RuboCop::Options::DEFAULT_MAXIMUM_EXCLUSION_ITEMS.to_s
370
-
371
376
  # rubocop:disable Metrics/LineLength
377
+ FORMATTER_OPTION_LIST = RuboCop::Formatter::FormatterSet::BUILTIN_FORMATTERS_FOR_KEYS.keys
378
+
372
379
  TEXT = {
373
380
  only: 'Run only the given cop(s).',
374
381
  only_guide_cops: ['Run only cops for rules that link to a',
@@ -394,7 +401,7 @@ module RuboCop
394
401
  "properties to generate. Default is #{MAX_EXCL}."],
395
402
  disable_uncorrectable: ['Used with --auto-correct to annotate any',
396
403
  'offenses that do not support autocorrect',
397
- 'with `rubocop:disable` comments.'],
404
+ 'with `rubocop:todo` comments.'],
398
405
  force_exclusion: ['Force excluding files specified in the',
399
406
  'configuration `Exclude` even if they are',
400
407
  'explicitly passed as arguments.'],
@@ -407,20 +414,8 @@ module RuboCop
407
414
  format: ['Choose an output formatter. This option',
408
415
  'can be specified multiple times to enable',
409
416
  'multiple formatters at the same time.',
410
- ' [p]rogress (default)',
411
- ' [s]imple',
412
- ' [c]lang',
413
- ' [d]isabled cops via inline comments',
414
- ' [fu]ubar',
415
- ' [e]macs',
416
- ' [j]son',
417
- ' [h]tml',
418
- ' [fi]les',
419
- ' [o]ffenses',
420
- ' [w]orst',
421
- ' [t]ap',
422
- ' [q]uiet',
423
- ' [a]utogenconf',
417
+ '[p]rogress is used by default',
418
+ *FORMATTER_OPTION_LIST.map { |item| " #{item}" },
424
419
  ' custom formatter class name'],
425
420
  out: ['Write output to a file instead of STDOUT.',
426
421
  'This option applies to the previously',
@@ -51,7 +51,7 @@ module RuboCop
51
51
 
52
52
  # Returns true for an absolute Unix or Windows path.
53
53
  def absolute?(path)
54
- path =~ %r{\A([A-Z]:)?/}
54
+ path =~ %r{\A([A-Z]:)?/}i
55
55
  end
56
56
 
57
57
  def self.pwd
@@ -123,6 +123,10 @@ module RuboCop
123
123
  lines[token.line - 2]
124
124
  end
125
125
 
126
+ def current_line(token)
127
+ lines[token.line - 1]
128
+ end
129
+
126
130
  def following_line(token)
127
131
  lines[token.line]
128
132
  end
@@ -159,7 +163,7 @@ module RuboCop
159
163
  ast, comments, tokens = parser.tokenize(@buffer)
160
164
 
161
165
  ast.respond_to?(:complete!) && ast.complete!
162
- rescue Parser::SyntaxError # rubocop:disable Lint/HandleExceptions
166
+ rescue Parser::SyntaxError # rubocop:disable Lint/SuppressedException
163
167
  # All errors are in diagnostics. No need to handle exception.
164
168
  end
165
169
 
@@ -70,6 +70,7 @@ module RuboCop
70
70
  RakeFileUtils.verbose(verbose) do
71
71
  yield(*[self, task_args].slice(0, task_block.arity)) if block_given?
72
72
  options = full_options.unshift('--auto-correct')
73
+ options.delete('--parallel')
73
74
  run_cli(verbose, options)
74
75
  end
75
76
  end
@@ -77,12 +77,13 @@ module RuboCop
77
77
  config_store.for('.').for_all_cops['AllowSymlinksInCacheRootDirectory']
78
78
  end
79
79
 
80
- def initialize(file, options, config_store, cache_root = nil)
80
+ def initialize(file, team, options, config_store, cache_root = nil)
81
81
  cache_root ||= ResultCache.cache_root(config_store)
82
82
  @allow_symlinks_in_cache_location =
83
83
  ResultCache.allow_symlinks_in_cache_location?(config_store)
84
- @path = File.join(cache_root, rubocop_checksum,
85
- relevant_options_digest(options),
84
+ @path = File.join(cache_root,
85
+ rubocop_checksum,
86
+ context_checksum(team, options),
86
87
  file_checksum(file, config_store))
87
88
  @cached_data = CachedData.new(file)
88
89
  end
@@ -100,7 +101,7 @@ module RuboCop
100
101
 
101
102
  begin
102
103
  FileUtils.mkdir_p(dir)
103
- rescue Errno::EACCES => e
104
+ rescue Errno::EACCES, Errno::EROFS => e
104
105
  warn "Couldn't create cache directory. Continuing without cache."\
105
106
  "\n #{e.message}"
106
107
  return
@@ -182,10 +183,23 @@ module RuboCop
182
183
  # don't affect caching.
183
184
  def relevant_options_digest(options)
184
185
  options = options.reject { |key, _| NON_CHANGING.include?(key) }
185
- options = options.to_s.gsub(/[^a-z]+/i, '_')
186
- # We must avoid making file names too long for some filesystems to handle
187
- # If they are short, we can leave them human-readable
188
- options.length <= 32 ? options : Digest::SHA1.hexdigest(options)
186
+ options.to_s.gsub(/[^a-z]+/i, '_')
187
+ end
188
+
189
+ def team_checksum(team)
190
+ @checksum_by_team ||= {}
191
+ @checksum_by_team[team.object_id] ||= team.external_dependency_checksum
192
+ end
193
+
194
+ # We combine team and options into a single "context" checksum to avoid
195
+ # making file names that are too long for some filesystems to handle.
196
+ # This context is for anything that's not (1) the RuboCop executable
197
+ # checksum or (2) the inspected file checksum.
198
+ def context_checksum(team, options)
199
+ Digest::SHA1.hexdigest([
200
+ team_checksum(team),
201
+ relevant_options_digest(options)
202
+ ].join)
189
203
  end
190
204
  end
191
205
  end
@@ -132,7 +132,10 @@ module RuboCop
132
132
  def expect_no_offenses(source, file = nil)
133
133
  inspect_source(source, file)
134
134
 
135
- expect(cop.offenses).to be_empty
135
+ expected_annotations = AnnotatedSource.parse(source)
136
+ actual_annotations =
137
+ expected_annotations.with_offense_annotations(cop.offenses)
138
+ expect(actual_annotations.to_s).to eq(source)
136
139
  end
137
140
 
138
141
  # Parsed representation of code annotated with the `^^^ Message` style
@@ -104,30 +104,31 @@ module RuboCop
104
104
  end
105
105
 
106
106
  def process_file(file)
107
- puts "Scanning #{file}" if @options[:debug]
108
107
  file_started(file)
109
-
110
108
  offenses = file_offenses(file)
111
- if @options[:display_only_fail_level_offenses]
112
- offenses = offenses.select { |o| considered_failure?(o) }
113
- end
114
- formatter_set.file_finished(file, offenses)
115
- offenses
116
109
  rescue InfiniteCorrectionLoop => e
117
- formatter_set.file_finished(file, e.offenses.compact.sort.freeze)
110
+ offenses = e.offenses.compact.sort.freeze
118
111
  raise
112
+ ensure
113
+ file_finished(file, offenses || [])
119
114
  end
120
115
 
121
116
  def file_offenses(file)
122
117
  file_offense_cache(file) do
123
118
  source = get_processed_source(file)
124
119
  source, offenses = do_inspection_loop(file, source)
125
- add_unneeded_disables(file, offenses.compact.sort, source)
120
+ add_redundant_disables(file, offenses.compact.sort, source)
126
121
  end
127
122
  end
128
123
 
124
+ def cached_result(file, team)
125
+ ResultCache.new(file, team, @options, @config_store)
126
+ end
127
+
129
128
  def file_offense_cache(file)
130
- cache = ResultCache.new(file, @options, @config_store) if cached_run?
129
+ config = @config_store.for(file)
130
+ cache = cached_result(file, standby_team(config)) if cached_run?
131
+
131
132
  if cache&.valid?
132
133
  offenses = cache.load
133
134
  # If we're running --auto-correct and the cache says there are
@@ -146,48 +147,66 @@ module RuboCop
146
147
  offenses
147
148
  end
148
149
 
149
- def add_unneeded_disables(file, offenses, source)
150
- if check_for_unneeded_disables?(source)
151
- config = @config_store.for(file)
152
- if config.for_cop(Cop::Lint::UnneededCopDisableDirective)
153
- .fetch('Enabled')
154
- cop = Cop::Lint::UnneededCopDisableDirective.new(config, @options)
155
- if cop.relevant_file?(file)
156
- cop.check(offenses, source.disabled_line_ranges, source.comments)
157
- offenses += cop.offenses
158
- autocorrect_unneeded_disables(source, cop)
159
- end
150
+ def add_redundant_disables(file, offenses, source)
151
+ if check_for_redundant_disables?(source)
152
+ redundant_cop_disable_directive(file) do |cop|
153
+ cop.check(offenses, source.disabled_line_ranges, source.comments)
154
+ offenses += cop.offenses
155
+ offenses += autocorrect_redundant_disables(file, source, cop,
156
+ offenses)
160
157
  end
161
- offenses
162
158
  end
163
159
 
164
160
  offenses.sort.reject(&:disabled?).freeze
165
161
  end
166
162
 
167
- def check_for_unneeded_disables?(source)
163
+ def check_for_redundant_disables?(source)
168
164
  !source.disabled_line_ranges.empty? && !filtered_run?
169
165
  end
170
166
 
167
+ def redundant_cop_disable_directive(file)
168
+ config = @config_store.for(file)
169
+ if config.for_cop(Cop::Lint::RedundantCopDisableDirective)
170
+ .fetch('Enabled')
171
+ cop = Cop::Lint::RedundantCopDisableDirective.new(config, @options)
172
+ yield cop if cop.relevant_file?(file)
173
+ end
174
+ end
175
+
171
176
  def filtered_run?
172
177
  @options[:except] || @options[:only]
173
178
  end
174
179
 
175
- def autocorrect_unneeded_disables(source, cop)
180
+ def autocorrect_redundant_disables(file, source, cop, offenses)
176
181
  cop.processed_source = source
177
182
 
178
- Cop::Team.new(
179
- RuboCop::Cop::Registry.new,
180
- nil,
181
- @options
182
- ).autocorrect(source.buffer, [cop])
183
+ team = Cop::Team.new(RuboCop::Cop::Registry.new, nil, @options)
184
+ team.autocorrect(source.buffer, [cop])
185
+
186
+ return [] unless team.updated_source_file?
187
+
188
+ # Do one extra inspection loop if any redundant disables were
189
+ # removed. This is done in order to find rubocop:enable directives that
190
+ # have now become useless.
191
+ _source, new_offenses = do_inspection_loop(file,
192
+ get_processed_source(file))
193
+ new_offenses - offenses
183
194
  end
184
195
 
185
196
  def file_started(file)
197
+ puts "Scanning #{file}" if @options[:debug]
186
198
  formatter_set.file_started(file,
187
199
  cli_options: @options,
188
200
  config_store: @config_store)
189
201
  end
190
202
 
203
+ def file_finished(file, offenses)
204
+ if @options[:display_only_fail_level_offenses]
205
+ offenses = offenses.select { |o| considered_failure?(o) }
206
+ end
207
+ formatter_set.file_finished(file, offenses)
208
+ end
209
+
191
210
  def cached_run?
192
211
  @cached_run ||=
193
212
  (@options[:cache] == 'true' ||
@@ -285,9 +304,7 @@ module RuboCop
285
304
  @mobilized_cop_classes[config.object_id] ||= begin
286
305
  cop_classes = Cop::Cop.all
287
306
 
288
- %i[only except].each do |opt|
289
- OptionsValidator.validate_cop_list(@options[opt])
290
- end
307
+ OptionsValidator.new(@options).validate_cop_options
291
308
 
292
309
  if @options[:only]
293
310
  cop_classes.select! { |c| c.match?(@options[:only]) }
@@ -348,5 +365,11 @@ module RuboCop
348
365
  ProcessedSource.from_file(file, ruby_version)
349
366
  end
350
367
  end
368
+
369
+ def standby_team(config)
370
+ @team_by_config ||= {}
371
+ @team_by_config[config.object_id] ||=
372
+ Cop::Team.new(mobilized_cop_classes(config), config, @options)
373
+ end
351
374
  end
352
375
  end
@@ -65,12 +65,7 @@ module RuboCop
65
65
  to_inspect?(file, hidden_files, base_dir_config)
66
66
  end
67
67
 
68
- if fail_fast?
69
- # Most recently modified file first.
70
- target_files.sort_by! { |path| -Integer(File.mtime(path)) }
71
- else
72
- target_files.sort!
73
- end
68
+ target_files.sort_by!(&order)
74
69
  end
75
70
 
76
71
  def to_inspect?(file, hidden_files, base_dir_config)
@@ -186,5 +181,16 @@ module RuboCop
186
181
  config.file_to_exclude?(file)
187
182
  end
188
183
  end
184
+
185
+ private
186
+
187
+ def order
188
+ if fail_fast?
189
+ # Most recently modified file first.
190
+ ->(path) { -Integer(File.mtime(path)) }
191
+ else
192
+ :itself
193
+ end
194
+ end
189
195
  end
190
196
  end