rubocop 0.74.0 → 0.78.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 (213) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -2
  3. data/config/default.yml +366 -318
  4. data/lib/rubocop.rb +48 -32
  5. data/lib/rubocop/ast/builder.rb +1 -0
  6. data/lib/rubocop/ast/node.rb +5 -1
  7. data/lib/rubocop/ast/node/block_node.rb +2 -0
  8. data/lib/rubocop/ast/node/mixin/method_dispatch_node.rb +1 -12
  9. data/lib/rubocop/ast/node/return_node.rb +24 -0
  10. data/lib/rubocop/cli.rb +11 -227
  11. data/lib/rubocop/cli/command.rb +21 -0
  12. data/lib/rubocop/cli/command/auto_genenerate_config.rb +105 -0
  13. data/lib/rubocop/cli/command/base.rb +33 -0
  14. data/lib/rubocop/cli/command/execute_runner.rb +76 -0
  15. data/lib/rubocop/cli/command/init_dotfile.rb +45 -0
  16. data/lib/rubocop/cli/command/show_cops.rb +73 -0
  17. data/lib/rubocop/cli/command/version.rb +17 -0
  18. data/lib/rubocop/cli/environment.rb +21 -0
  19. data/lib/rubocop/comment_config.rb +5 -4
  20. data/lib/rubocop/config.rb +12 -1
  21. data/lib/rubocop/config_loader.rb +21 -3
  22. data/lib/rubocop/config_loader_resolver.rb +4 -3
  23. data/lib/rubocop/config_obsoletion.rb +85 -11
  24. data/lib/rubocop/config_validator.rb +28 -19
  25. data/lib/rubocop/cop/autocorrect_logic.rb +3 -3
  26. data/lib/rubocop/cop/bundler/gem_comment.rb +4 -4
  27. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +2 -2
  28. data/lib/rubocop/cop/commissioner.rb +15 -7
  29. data/lib/rubocop/cop/cop.rb +35 -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 +1 -7
  52. data/lib/rubocop/cop/layout/{indent_first_argument.rb → first_argument_indentation.rb} +14 -12
  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} +6 -6
  58. data/lib/rubocop/cop/layout/{leading_blank_lines.rb → leading_empty_lines.rb} +1 -1
  59. data/lib/rubocop/cop/{metrics → layout}/line_length.rb +41 -114
  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 +32 -7
  68. data/lib/rubocop/cop/layout/space_before_block_braces.rb +17 -0
  69. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +9 -7
  70. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +8 -5
  71. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +7 -0
  72. data/lib/rubocop/cop/layout/space_inside_parens.rb +6 -6
  73. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +2 -0
  74. data/lib/rubocop/cop/layout/{trailing_blank_lines.rb → trailing_empty_lines.rb} +1 -1
  75. data/lib/rubocop/cop/layout/trailing_whitespace.rb +18 -2
  76. data/lib/rubocop/cop/lint/assignment_in_condition.rb +17 -4
  77. data/lib/rubocop/cop/lint/debugger.rb +1 -1
  78. data/lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb +1 -1
  79. data/lib/rubocop/cop/lint/{duplicated_key.rb → duplicate_hash_key.rb} +1 -1
  80. data/lib/rubocop/cop/lint/each_with_object_argument.rb +1 -1
  81. data/lib/rubocop/cop/lint/erb_new_arguments.rb +9 -8
  82. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +10 -36
  83. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -1
  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/non_deterministic_require_order.rb +89 -0
  87. data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
  88. data/lib/rubocop/cop/lint/{unneeded_cop_disable_directive.rb → redundant_cop_disable_directive.rb} +26 -26
  89. data/lib/rubocop/cop/lint/{unneeded_cop_enable_directive.rb → redundant_cop_enable_directive.rb} +10 -12
  90. data/lib/rubocop/cop/lint/{unneeded_require_statement.rb → redundant_require_statement.rb} +1 -1
  91. data/lib/rubocop/cop/lint/{unneeded_splat_expansion.rb → redundant_splat_expansion.rb} +6 -6
  92. data/lib/rubocop/cop/lint/{string_conversion_in_interpolation.rb → redundant_string_coercion.rb} +1 -1
  93. data/lib/rubocop/cop/lint/redundant_with_index.rb +2 -2
  94. data/lib/rubocop/cop/lint/redundant_with_object.rb +2 -2
  95. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +5 -6
  96. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +91 -0
  97. data/lib/rubocop/cop/lint/{handle_exceptions.rb → suppressed_exception.rb} +1 -1
  98. data/lib/rubocop/cop/lint/unused_block_argument.rb +22 -6
  99. data/lib/rubocop/cop/lint/unused_method_argument.rb +23 -5
  100. data/lib/rubocop/cop/lint/useless_access_modifier.rb +57 -23
  101. data/lib/rubocop/cop/lint/useless_setter_call.rb +1 -1
  102. data/lib/rubocop/cop/lint/void.rb +7 -26
  103. data/lib/rubocop/cop/message_annotator.rb +16 -7
  104. data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
  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 +2 -2
  109. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -1
  110. data/lib/rubocop/cop/mixin/{hash_alignment.rb → hash_alignment_styles.rb} +1 -1
  111. data/lib/rubocop/cop/mixin/line_length_help.rb +88 -0
  112. data/lib/rubocop/cop/mixin/method_complexity.rb +2 -1
  113. data/lib/rubocop/cop/mixin/nil_methods.rb +4 -4
  114. data/lib/rubocop/cop/mixin/rational_literal.rb +18 -0
  115. data/lib/rubocop/cop/mixin/statement_modifier.rb +7 -4
  116. data/lib/rubocop/cop/mixin/trailing_comma.rb +14 -9
  117. data/lib/rubocop/cop/naming/{uncommunicative_block_param_name.rb → block_parameter_name.rb} +3 -3
  118. data/lib/rubocop/cop/naming/file_name.rb +12 -5
  119. data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +5 -5
  120. data/lib/rubocop/cop/naming/method_name.rb +12 -1
  121. data/lib/rubocop/cop/naming/{uncommunicative_method_param_name.rb → method_parameter_name.rb} +3 -3
  122. data/lib/rubocop/cop/naming/predicate_name.rb +6 -6
  123. data/lib/rubocop/cop/naming/variable_name.rb +1 -0
  124. data/lib/rubocop/cop/offense.rb +29 -7
  125. data/lib/rubocop/cop/registry.rb +22 -1
  126. data/lib/rubocop/cop/style/access_modifier_declarations.rb +1 -0
  127. data/lib/rubocop/cop/style/alias.rb +1 -1
  128. data/lib/rubocop/cop/style/array_join.rb +1 -1
  129. data/lib/rubocop/cop/style/attr.rb +10 -2
  130. data/lib/rubocop/cop/style/block_delimiters.rb +2 -1
  131. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +35 -16
  132. data/lib/rubocop/cop/style/class_and_module_children.rb +1 -1
  133. data/lib/rubocop/cop/style/comment_annotation.rb +5 -5
  134. data/lib/rubocop/cop/style/commented_keyword.rb +8 -2
  135. data/lib/rubocop/cop/style/conditional_assignment.rb +6 -6
  136. data/lib/rubocop/cop/style/copyright.rb +11 -7
  137. data/lib/rubocop/cop/style/documentation_method.rb +44 -0
  138. data/lib/rubocop/cop/style/double_cop_disable_directive.rb +10 -4
  139. data/lib/rubocop/cop/style/empty_case_condition.rb +2 -2
  140. data/lib/rubocop/cop/style/empty_literal.rb +2 -2
  141. data/lib/rubocop/cop/style/empty_method.rb +5 -5
  142. data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
  143. data/lib/rubocop/cop/style/even_odd.rb +1 -1
  144. data/lib/rubocop/cop/style/expand_path_arguments.rb +1 -1
  145. data/lib/rubocop/cop/style/format_string.rb +10 -7
  146. data/lib/rubocop/cop/style/format_string_token.rb +19 -68
  147. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +28 -33
  148. data/lib/rubocop/cop/style/guard_clause.rb +3 -2
  149. data/lib/rubocop/cop/style/hash_syntax.rb +2 -2
  150. data/lib/rubocop/cop/style/if_unless_modifier.rb +93 -15
  151. data/lib/rubocop/cop/style/infinite_loop.rb +6 -5
  152. data/lib/rubocop/cop/style/inverse_methods.rb +19 -13
  153. data/lib/rubocop/cop/style/ip_addresses.rb +4 -4
  154. data/lib/rubocop/cop/style/line_end_concatenation.rb +14 -10
  155. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +25 -25
  156. data/lib/rubocop/cop/style/method_def_parentheses.rb +17 -9
  157. data/lib/rubocop/cop/style/mixin_grouping.rb +1 -1
  158. data/lib/rubocop/cop/style/mixin_usage.rb +11 -1
  159. data/lib/rubocop/cop/style/multiline_memoization.rb +1 -1
  160. data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -1
  161. data/lib/rubocop/cop/style/multiline_when_then.rb +1 -1
  162. data/lib/rubocop/cop/style/nested_modifier.rb +22 -4
  163. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +5 -5
  164. data/lib/rubocop/cop/style/next.rb +5 -5
  165. data/lib/rubocop/cop/style/non_nil_check.rb +21 -9
  166. data/lib/rubocop/cop/style/numeric_literals.rb +7 -3
  167. data/lib/rubocop/cop/style/option_hash.rb +3 -3
  168. data/lib/rubocop/cop/style/or_assignment.rb +6 -1
  169. data/lib/rubocop/cop/style/parentheses_around_condition.rb +14 -0
  170. data/lib/rubocop/cop/style/{unneeded_capital_w.rb → redundant_capital_w.rb} +1 -1
  171. data/lib/rubocop/cop/style/{unneeded_condition.rb → redundant_condition.rb} +3 -3
  172. data/lib/rubocop/cop/style/{unneeded_interpolation.rb → redundant_interpolation.rb} +1 -1
  173. data/lib/rubocop/cop/style/redundant_parentheses.rb +16 -7
  174. data/lib/rubocop/cop/style/{unneeded_percent_q.rb → redundant_percent_q.rb} +1 -1
  175. data/lib/rubocop/cop/style/redundant_return.rb +39 -29
  176. data/lib/rubocop/cop/style/redundant_self.rb +18 -1
  177. data/lib/rubocop/cop/style/{unneeded_sort.rb → redundant_sort.rb} +5 -5
  178. data/lib/rubocop/cop/style/rescue_modifier.rb +24 -0
  179. data/lib/rubocop/cop/style/safe_navigation.rb +23 -3
  180. data/lib/rubocop/cop/style/semicolon.rb +13 -2
  181. data/lib/rubocop/cop/style/single_line_methods.rb +8 -1
  182. data/lib/rubocop/cop/style/special_global_vars.rb +5 -7
  183. data/lib/rubocop/cop/style/ternary_parentheses.rb +19 -0
  184. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +7 -1
  185. data/lib/rubocop/cop/style/trivial_accessors.rb +5 -5
  186. data/lib/rubocop/cop/style/while_until_modifier.rb +1 -1
  187. data/lib/rubocop/cop/team.rb +5 -0
  188. data/lib/rubocop/cop/util.rb +1 -1
  189. data/lib/rubocop/cop/utils/format_string.rb +120 -0
  190. data/lib/rubocop/cop/variable_force.rb +7 -5
  191. data/lib/rubocop/cop/variable_force/variable.rb +15 -2
  192. data/lib/rubocop/core_ext/string.rb +0 -24
  193. data/lib/rubocop/formatter/base_formatter.rb +2 -2
  194. data/lib/rubocop/formatter/clang_style_formatter.rb +9 -6
  195. data/lib/rubocop/formatter/emacs_style_formatter.rb +22 -9
  196. data/lib/rubocop/formatter/file_list_formatter.rb +1 -1
  197. data/lib/rubocop/formatter/formatter_set.rb +16 -15
  198. data/lib/rubocop/formatter/json_formatter.rb +6 -5
  199. data/lib/rubocop/formatter/pacman_formatter.rb +80 -0
  200. data/lib/rubocop/formatter/simple_text_formatter.rb +16 -4
  201. data/lib/rubocop/formatter/tap_formatter.rb +18 -7
  202. data/lib/rubocop/magic_comment.rb +4 -0
  203. data/lib/rubocop/node_pattern.rb +4 -2
  204. data/lib/rubocop/options.rb +21 -26
  205. data/lib/rubocop/processed_source.rb +1 -1
  206. data/lib/rubocop/rake_task.rb +1 -0
  207. data/lib/rubocop/result_cache.rb +24 -8
  208. data/lib/rubocop/runner.rb +60 -33
  209. data/lib/rubocop/target_finder.rb +12 -6
  210. data/lib/rubocop/version.rb +1 -1
  211. metadata +48 -33
  212. data/lib/rubocop/cop/mixin/ignored_method_patterns.rb +0 -19
  213. 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]
@@ -380,7 +380,7 @@ module RuboCop
380
380
  def compile_seq_head
381
381
  return unless seq_head?
382
382
 
383
- fail_due_to 'sequences can not start with <' \
383
+ fail_due_to 'sequences cannot start with <' \
384
384
  if @terms[0].respond_to? :call
385
385
 
386
386
  with_seq_head_context(@terms[0])
@@ -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,21 +255,27 @@ 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 ' \
266
+ if only_includes_redundant_disable?
267
+ raise OptionArgumentError, 'Lint/RedundantCopDisableDirective cannot ' \
262
268
  'be used with --only.'
263
269
  end
264
270
  if except_syntax?
265
- raise OptionArgumentError, 'Syntax checking can not be turned off.'
271
+ raise OptionArgumentError, 'Syntax checking cannot be turned off.'
266
272
  end
267
273
  unless boolean_or_empty_cache?
268
274
  raise OptionArgumentError, '-C/--cache argument must be true or false'
269
275
  end
270
276
 
271
277
  if display_only_fail_level_offenses_with_autocorrect?
272
- raise OptionArgumentError, '--autocorrect can not be used with ' \
278
+ raise OptionArgumentError, '--autocorrect cannot be used with ' \
273
279
  '--display-only-fail-level-offenses'
274
280
  end
275
281
  validate_auto_gen_config
@@ -323,8 +329,8 @@ module RuboCop
323
329
  auto_gen_config: '-P/--parallel uses caching to speed up execution, ' \
324
330
  'while --auto-gen-config needs a non-cached run, ' \
325
331
  'so they cannot be combined.',
326
- fail_fast: '-P/--parallel can not be combined with -F/--fail-fast.',
327
- auto_correct: '-P/--parallel can not be combined with --auto-correct.'
332
+ fail_fast: '-P/--parallel cannot be combined with -F/--fail-fast.',
333
+ auto_correct: '-P/--parallel cannot be combined with --auto-correct.'
328
334
  }
329
335
 
330
336
  combos.each do |key, msg|
@@ -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
376
+ # rubocop:disable Layout/LineLength
377
+ FORMATTER_OPTION_LIST = RuboCop::Formatter::FormatterSet::BUILTIN_FORMATTERS_FOR_KEYS.keys
370
378
 
371
- # rubocop:disable Metrics/LineLength
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',
@@ -460,6 +455,6 @@ module RuboCop
460
455
  'reports. This is useful for editor integration.'],
461
456
  init: 'Generate a .rubocop.yml file in the current directory.'
462
457
  }.freeze
463
- # rubocop:enable Metrics/LineLength
458
+ # rubocop:enable Layout/LineLength
464
459
  end
465
460
  end
@@ -163,7 +163,7 @@ module RuboCop
163
163
  ast, comments, tokens = parser.tokenize(@buffer)
164
164
 
165
165
  ast.respond_to?(:complete!) && ast.complete!
166
- rescue Parser::SyntaxError # rubocop:disable Lint/HandleExceptions
166
+ rescue Parser::SyntaxError # rubocop:disable Lint/SuppressedException
167
167
  # All errors are in diagnostics. No need to handle exception.
168
168
  end
169
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,25 @@ 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
+ # The external dependency checksums are cached per RuboCop team so that
190
+ # the checksums don't need to be recomputed for each file.
191
+ def team_checksum(team)
192
+ @checksum_by_team ||= {}
193
+ @checksum_by_team[team.object_id] ||= team.external_dependency_checksum
194
+ end
195
+
196
+ # We combine team and options into a single "context" checksum to avoid
197
+ # making file names that are too long for some filesystems to handle.
198
+ # This context is for anything that's not (1) the RuboCop executable
199
+ # checksum or (2) the inspected file checksum.
200
+ def context_checksum(team, options)
201
+ Digest::SHA1.hexdigest([
202
+ team_checksum(team),
203
+ relevant_options_digest(options)
204
+ ].join)
189
205
  end
190
206
  end
191
207
  end
@@ -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' ||
@@ -195,7 +214,7 @@ module RuboCop
195
214
  @config_store.for(Dir.pwd).for_all_cops['UseCache']) &&
196
215
  # When running --auto-gen-config, there's some processing done in the
197
216
  # cops related to calculating the Max parameters for Metrics cops. We
198
- # need to do that processing and can not use caching.
217
+ # need to do that processing and cannot use caching.
199
218
  !@options[:auto_gen_config] &&
200
219
  # We can't cache results from code which is piped in to stdin
201
220
  !@options[:stdin]
@@ -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,15 @@ module RuboCop
348
365
  ProcessedSource.from_file(file, ruby_version)
349
366
  end
350
367
  end
368
+
369
+ # A Cop::Team instance is stateful and may change when inspecting.
370
+ # The "standby" team for a given config is an initialized but
371
+ # otherwise dormant team that can be used for config- and option-
372
+ # level caching in ResultCache.
373
+ def standby_team(config)
374
+ @team_by_config ||= {}
375
+ @team_by_config[config.object_id] ||=
376
+ Cop::Team.new(mobilized_cop_classes(config), config, @options)
377
+ end
351
378
  end
352
379
  end