rubocop 0.73.0 → 0.77.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ class CLI
5
+ # Home of subcommands in the CLI.
6
+ module Command
7
+ class << self
8
+ # Find the command with a given name and run it in an environment.
9
+ def run(env, name)
10
+ class_for(name).new(env).run
11
+ end
12
+
13
+ private
14
+
15
+ def class_for(name)
16
+ Base.by_command_name(name)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ class CLI
5
+ module Command
6
+ # Generate a configuration file acting as a TODO list.
7
+ class AutoGenerateConfig < Base
8
+ self.command_name = :auto_gen_config
9
+
10
+ PHASE_1 = 'Phase 1 of 2: run Metrics/LineLength cop'
11
+ PHASE_2 = 'Phase 2 of 2: run all cops'
12
+
13
+ PHASE_1_OVERRIDDEN =
14
+ '(skipped because the default Metrics/LineLength:Max is overridden)'
15
+ PHASE_1_DISABLED =
16
+ '(skipped because Metrics/LineLength is disabled)'
17
+
18
+ def run
19
+ add_formatter
20
+ reset_config_and_auto_gen_file
21
+ line_length_contents = maybe_run_line_length_cop
22
+ run_all_cops(line_length_contents)
23
+ end
24
+
25
+ private
26
+
27
+ def maybe_run_line_length_cop
28
+ if !line_length_enabled?(@config_store.for(Dir.pwd))
29
+ skip_line_length_cop(PHASE_1_DISABLED)
30
+ elsif !same_max_line_length?(
31
+ @config_store.for(Dir.pwd), ConfigLoader.default_configuration
32
+ )
33
+ skip_line_length_cop(PHASE_1_OVERRIDDEN)
34
+ else
35
+ run_line_length_cop
36
+ end
37
+ end
38
+
39
+ def skip_line_length_cop(reason)
40
+ puts Rainbow("#{PHASE_1} #{reason}").yellow
41
+ ''
42
+ end
43
+
44
+ def line_length_enabled?(config)
45
+ line_length_cop(config)['Enabled']
46
+ end
47
+
48
+ def same_max_line_length?(config1, config2)
49
+ max_line_length(config1) == max_line_length(config2)
50
+ end
51
+
52
+ def max_line_length(config)
53
+ line_length_cop(config)['Max']
54
+ end
55
+
56
+ def line_length_cop(config)
57
+ config.for_cop('Metrics/LineLength')
58
+ end
59
+
60
+ # Do an initial run with only Metrics/LineLength so that cops that
61
+ # depend on Metrics/LineLength:Max get the correct value for that
62
+ # parameter.
63
+ def run_line_length_cop
64
+ puts Rainbow(PHASE_1).yellow
65
+ @options[:only] = ['Metrics/LineLength']
66
+ execute_runner
67
+ @options.delete(:only)
68
+ @config_store = ConfigStore.new
69
+ # Save the todo configuration of the LineLength cop.
70
+ IO.read(ConfigLoader::AUTO_GENERATED_FILE)
71
+ .lines
72
+ .drop_while { |line| line.start_with?('#') }
73
+ .join
74
+ end
75
+
76
+ def run_all_cops(line_length_contents)
77
+ puts Rainbow(PHASE_2).yellow
78
+ result = execute_runner
79
+ # This run was made with the current maximum length allowed, so append
80
+ # the saved setting for LineLength.
81
+ File.open(ConfigLoader::AUTO_GENERATED_FILE, 'a') do |f|
82
+ f.write(line_length_contents)
83
+ end
84
+ result
85
+ end
86
+
87
+ def reset_config_and_auto_gen_file
88
+ @config_store = ConfigStore.new
89
+ @config_store.options_config = @options[:config] if @options[:config]
90
+ File.open(ConfigLoader::AUTO_GENERATED_FILE, 'w') {}
91
+ ConfigLoader.add_inheritance_from_auto_generated_file
92
+ end
93
+
94
+ def add_formatter
95
+ @options[:formatters] << [Formatter::DisabledConfigFormatter,
96
+ ConfigLoader::AUTO_GENERATED_FILE]
97
+ end
98
+
99
+ def execute_runner
100
+ Environment.new(@options, @config_store, @paths).run(:execute_runner)
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ class CLI
5
+ module Command
6
+ # A subcommand in the CLI.
7
+ class Base
8
+ attr_reader :env
9
+
10
+ @subclasses = []
11
+
12
+ class << self
13
+ attr_accessor :command_name
14
+
15
+ def inherited(subclass)
16
+ @subclasses << subclass
17
+ end
18
+
19
+ def by_command_name(name)
20
+ @subclasses.detect { |s| s.command_name == name }
21
+ end
22
+ end
23
+
24
+ def initialize(env)
25
+ @env = env
26
+ @options = env.options
27
+ @config_store = env.config_store
28
+ @paths = env.paths
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ class CLI
5
+ module Command
6
+ # Run all the selected cops and report the result.
7
+ class ExecuteRunner < Base
8
+ include Formatter::TextUtil
9
+
10
+ self.command_name = :execute_runner
11
+
12
+ def run
13
+ execute_runner(@paths)
14
+ end
15
+
16
+ private
17
+
18
+ def execute_runner(paths)
19
+ runner = Runner.new(@options, @config_store)
20
+
21
+ all_passed = runner.run(paths)
22
+ display_warning_summary(runner.warnings)
23
+ display_error_summary(runner.errors)
24
+ maybe_print_corrected_source
25
+
26
+ all_pass_or_excluded = all_passed || @options[:auto_gen_config]
27
+
28
+ if runner.aborting?
29
+ STATUS_INTERRUPTED
30
+ elsif all_pass_or_excluded && runner.errors.empty?
31
+ STATUS_SUCCESS
32
+ else
33
+ STATUS_OFFENSES
34
+ end
35
+ end
36
+
37
+ def display_warning_summary(warnings)
38
+ return if warnings.empty?
39
+
40
+ warn Rainbow("\n#{pluralize(warnings.size, 'warning')}:").yellow
41
+
42
+ warnings.each { |warning| warn warning }
43
+ end
44
+
45
+ def display_error_summary(errors)
46
+ return if errors.empty?
47
+
48
+ warn Rainbow("\n#{pluralize(errors.size, 'error')} occurred:").red
49
+
50
+ errors.each { |error| warn error }
51
+
52
+ warn <<~WARNING
53
+ Errors are usually caused by RuboCop bugs.
54
+ Please, report your problems to RuboCop's issue tracker.
55
+ #{Gem.loaded_specs['rubocop'].metadata['bug_tracker_uri']}
56
+
57
+ Mention the following information in the issue report:
58
+ #{RuboCop::Version.version(true)}
59
+ WARNING
60
+ end
61
+
62
+ def maybe_print_corrected_source
63
+ # If we are asked to autocorrect source code read from stdin, the only
64
+ # reasonable place to write it is to stdout
65
+ # Unfortunately, we also write other information to stdout
66
+ # So a delimiter is needed for tools to easily identify where the
67
+ # autocorrected source begins
68
+ return unless @options[:stdin] && @options[:auto_correct]
69
+
70
+ puts '=' * 20
71
+ print @options[:stdin]
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ class CLI
5
+ module Command
6
+ # Generate a .rubocop.yml file in the current directory.
7
+ class InitDotfile < Base
8
+ DOTFILE = ConfigLoader::DOTFILE
9
+
10
+ self.command_name = :init
11
+
12
+ def run
13
+ path = File.expand_path(DOTFILE)
14
+
15
+ if File.exist?(DOTFILE)
16
+ warn Rainbow("#{DOTFILE} already exists at #{path}").red
17
+
18
+ STATUS_ERROR
19
+ else
20
+ description = <<~DESC
21
+ # The behavior of RuboCop can be controlled via the .rubocop.yml
22
+ # configuration file. It makes it possible to enable/disable
23
+ # certain cops (checks) and to alter their behavior if they accept
24
+ # any parameters. The file can be placed either in your home
25
+ # directory or in some project directory.
26
+ #
27
+ # RuboCop will start looking for the configuration file in the directory
28
+ # where the inspected file is and continue its way up to the root directory.
29
+ #
30
+ # See https://github.com/rubocop-hq/rubocop/blob/master/manual/configuration.md
31
+ DESC
32
+
33
+ File.open(DOTFILE, 'w') do |f|
34
+ f.write(description)
35
+ end
36
+
37
+ puts "Writing new #{DOTFILE} to #{path}"
38
+
39
+ STATUS_SUCCESS
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ class CLI
5
+ module Command
6
+ # Shows the given cops, or all cops by default, and their configurations
7
+ # for the current directory.
8
+ class ShowCops < Base
9
+ self.command_name = :show_cops
10
+
11
+ def run
12
+ print_available_cops
13
+ end
14
+
15
+ private
16
+
17
+ def print_available_cops
18
+ # Load the configs so the require()s are done for custom cops
19
+ @config_store.for(Dir.pwd)
20
+ registry = Cop::Cop.registry
21
+ show_all = @options[:show_cops].empty?
22
+
23
+ if show_all
24
+ puts "# Available cops (#{registry.length}) " \
25
+ "+ config for #{Dir.pwd}: "
26
+ end
27
+
28
+ registry.departments.sort!.each do |department|
29
+ print_cops_of_department(registry, department, show_all)
30
+ end
31
+ end
32
+
33
+ def print_cops_of_department(registry, department, show_all)
34
+ selected_cops = if show_all
35
+ cops_of_department(registry, department)
36
+ else
37
+ selected_cops_of_department(registry, department)
38
+ end
39
+
40
+ if show_all
41
+ puts "# Department '#{department}' (#{selected_cops.length}):"
42
+ end
43
+
44
+ print_cop_details(selected_cops)
45
+ end
46
+
47
+ def print_cop_details(cops)
48
+ cops.each do |cop|
49
+ puts '# Supports --auto-correct' if cop.new.support_autocorrect?
50
+ puts "#{cop.cop_name}:"
51
+ puts config_lines(cop)
52
+ puts
53
+ end
54
+ end
55
+
56
+ def selected_cops_of_department(cops, department)
57
+ cops_of_department(cops, department).select do |cop|
58
+ @options[:show_cops].include?(cop.cop_name)
59
+ end
60
+ end
61
+
62
+ def cops_of_department(cops, department)
63
+ cops.with_department(department).sort!
64
+ end
65
+
66
+ def config_lines(cop)
67
+ cnf = @config_store.for(Dir.pwd).for_cop(cop)
68
+ cnf.to_yaml.lines.to_a.drop(1).map { |line| ' ' + line }
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ class CLI
5
+ module Command
6
+ # Display version.
7
+ class Version < Base
8
+ self.command_name = :version
9
+
10
+ def run
11
+ puts RuboCop::Version.version(false) if @options[:version]
12
+ puts RuboCop::Version.version(true) if @options[:verbose_version]
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ class CLI
5
+ # Execution environment for a CLI command.
6
+ class Environment
7
+ attr_reader :options, :config_store, :paths
8
+
9
+ def initialize(options, config_store, paths)
10
+ @options = options
11
+ @config_store = config_store
12
+ @paths = paths
13
+ end
14
+
15
+ # Run a command in this environment.
16
+ def run(name)
17
+ Command.run(self, name)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -4,14 +4,15 @@ module RuboCop
4
4
  # This class parses the special `rubocop:disable` comments in a source
5
5
  # and provides a way to check if each cop is enabled at arbitrary line.
6
6
  class CommentConfig
7
- UNNEEDED_DISABLE = 'Lint/UnneededCopDisableDirective'
7
+ REDUNDANT_DISABLE = 'Lint/RedundantCopDisableDirective'
8
8
 
9
9
  COP_NAME_PATTERN = '([A-Z]\w+/)?(?:[A-Z]\w+)'
10
10
  COP_NAMES_PATTERN = "(?:#{COP_NAME_PATTERN} , )*#{COP_NAME_PATTERN}"
11
11
  COPS_PATTERN = "(all|#{COP_NAMES_PATTERN})"
12
12
 
13
13
  COMMENT_DIRECTIVE_REGEXP = Regexp.new(
14
- ('# rubocop : ((?:dis|en)able)\b ' + COPS_PATTERN).gsub(' ', '\s*')
14
+ ('# rubocop : ((?:disable|enable|todo))\b ' + COPS_PATTERN)
15
+ .gsub(' ', '\s*')
15
16
  )
16
17
 
17
18
  CopAnalysis = Struct.new(:line_ranges, :start_line_number)
@@ -141,7 +142,7 @@ module RuboCop
141
142
  cop_names =
142
143
  cops_string == 'all' ? all_cop_names : cops_string.split(/,\s*/)
143
144
 
144
- disabled = (switch == 'disable')
145
+ disabled = %w[disable todo].include?(switch)
145
146
 
146
147
  [cop_names, disabled]
147
148
  end
@@ -151,7 +152,7 @@ module RuboCop
151
152
  end
152
153
 
153
154
  def all_cop_names
154
- @all_cop_names ||= Cop::Cop.registry.names - [UNNEEDED_DISABLE]
155
+ @all_cop_names ||= Cop::Cop.registry.names - [REDUNDANT_DISABLE]
155
156
  end
156
157
 
157
158
  def comment_only_line?(line_number)
@@ -8,237 +8,12 @@ module RuboCop
8
8
  # file from which it was read. Several different Configs can be used
9
9
  # during a run of the rubocop program, if files in several
10
10
  # directories are inspected.
11
-
12
- # rubocop:disable Metrics/ClassLength
13
11
  class Config
14
12
  include PathUtil
15
13
  include FileFinder
14
+ extend Forwardable
16
15
 
17
- COMMON_PARAMS = %w[Exclude Include Severity inherit_mode
18
- AutoCorrect StyleGuide Details].freeze
19
- INTERNAL_PARAMS = %w[Description StyleGuide VersionAdded
20
- VersionChanged Reference Safe SafeAutoCorrect].freeze
21
-
22
- # 2.3 is the oldest officially supported Ruby version.
23
- DEFAULT_RUBY_VERSION = 2.3
24
- KNOWN_RUBIES = [2.3, 2.4, 2.5, 2.6, 2.7].freeze
25
- OBSOLETE_RUBIES = {
26
- 1.9 => '0.50', 2.0 => '0.50', 2.1 => '0.58', 2.2 => '0.69'
27
- }.freeze
28
- RUBY_VERSION_FILENAME = '.ruby-version'
29
16
  DEFAULT_RAILS_VERSION = 5.0
30
- OBSOLETE_COPS = {
31
- 'Style/FlipFlop' =>
32
- 'The `Style/FlipFlop` cop has been moved to `Lint/FlipFlop`.',
33
- 'Style/TrailingComma' =>
34
- 'The `Style/TrailingComma` cop no longer exists. Please use ' \
35
- '`Style/TrailingCommaInArguments`, ' \
36
- '`Style/TrailingCommaInArrayLiteral`, and/or ' \
37
- '`Style/TrailingCommaInHashLiteral` instead.',
38
- 'Style/TrailingCommaInLiteral' =>
39
- 'The `Style/TrailingCommaInLiteral` cop no longer exists. Please use ' \
40
- '`Style/TrailingCommaInArrayLiteral` and/or ' \
41
- '`Style/TrailingCommaInHashLiteral` instead.',
42
- 'Rails/DefaultScope' =>
43
- 'The `Rails/DefaultScope` cop no longer exists.',
44
- 'Lint/InvalidCharacterLiteral' =>
45
- 'The `Lint/InvalidCharacterLiteral` cop has been removed since it ' \
46
- 'was never being actually triggered.',
47
- 'Style/SingleSpaceBeforeFirstArg' =>
48
- 'The `Style/SingleSpaceBeforeFirstArg` cop has been renamed to ' \
49
- '`Layout/SpaceBeforeFirstArg`.',
50
- 'Lint/RescueWithoutErrorClass' =>
51
- 'The `Lint/RescueWithoutErrorClass` cop has been replaced by ' \
52
- '`Style/RescueStandardError`.',
53
- 'Lint/SpaceBeforeFirstArg' =>
54
- 'The `Lint/SpaceBeforeFirstArg` cop has been removed, since it was a ' \
55
- 'duplicate of `Layout/SpaceBeforeFirstArg`. Please use ' \
56
- '`Layout/SpaceBeforeFirstArg` instead.',
57
- 'Layout/FirstParameterIndentation' =>
58
- 'The `Layout/FirstParameterIndentation` cop has been renamed to ' \
59
- '`Layout/IndentFirstArgument`.',
60
- 'Layout/IndentArray' =>
61
- 'The `Layout/IndentArray` cop has been renamed to ' \
62
- '`Layout/IndentFirstArrayElement`.',
63
- 'Layout/IndentHash' =>
64
- 'The `Layout/IndentHash` cop has been renamed to ' \
65
- '`Layout/IndentFirstHashElement`.',
66
- 'Layout/SpaceAfterControlKeyword' =>
67
- 'The `Layout/SpaceAfterControlKeyword` cop has been removed. Please ' \
68
- 'use `Layout/SpaceAroundKeyword` instead.',
69
- 'Layout/SpaceBeforeModifierKeyword' =>
70
- 'The `Layout/SpaceBeforeModifierKeyword` cop has been removed. ' \
71
- 'Please use `Layout/SpaceAroundKeyword` instead.',
72
- 'Style/SpaceAfterControlKeyword' =>
73
- 'The `Style/SpaceAfterControlKeyword` cop has been removed. Please ' \
74
- 'use `Layout/SpaceAroundKeyword` instead.',
75
- 'Style/SpaceBeforeModifierKeyword' =>
76
- 'The `Style/SpaceBeforeModifierKeyword` cop has been removed. Please ' \
77
- 'use `Layout/SpaceAroundKeyword` instead.',
78
- 'Style/MethodCallParentheses' =>
79
- 'The `Style/MethodCallParentheses` cop has been renamed to ' \
80
- '`Style/MethodCallWithoutArgsParentheses`.',
81
- 'Lint/Eval' =>
82
- 'The `Lint/Eval` cop has been renamed to `Security/Eval`.',
83
- 'Style/DeprecatedHashMethods' =>
84
- 'The `Style/DeprecatedHashMethods` cop has been renamed to ' \
85
- '`Style/PreferredHashMethods`.',
86
- 'Style/AccessorMethodName' =>
87
- 'The `Style/AccessorMethodName` cop has been moved to ' \
88
- '`Naming/AccessorMethodName`.',
89
- 'Style/AsciiIdentifiers' =>
90
- 'The `Style/AsciiIdentifiers` cop has been moved to ' \
91
- '`Naming/AccessorMethodName`.',
92
- 'Style/OpMethod' =>
93
- 'The `Style/OpMethod` cop has been renamed and moved to ' \
94
- '`Naming/BinaryOperatorParameterName`.',
95
- 'Style/ClassAndModuleCamelCase' =>
96
- 'The `Style/ClassAndModuleCamelCase` cop has been renamed to ' \
97
- '`Naming/ClassAndModuleCamelCase`.',
98
- 'Style/ConstantName' =>
99
- 'The `Style/ConstantName` cop has been renamed to ' \
100
- '`Naming/ConstantName`.',
101
- 'Style/FileName' =>
102
- 'The `Style/FileName` cop has been renamed to `Naming/FileName`.',
103
- 'Style/MethodName' =>
104
- 'The `Style/MethodName` cop has been renamed to ' \
105
- '`Naming/MethodName`.',
106
- 'Style/PredicateName' =>
107
- 'The `Style/PredicateName` cop has been renamed to ' \
108
- '`Naming/PredicateName`.',
109
- 'Style/VariableName' =>
110
- 'The `Style/VariableName` cop has been renamed to ' \
111
- '`Naming/VariableName`.',
112
- 'Style/VariableNumber' =>
113
- 'The `Style/VariableNumber` cop has been renamed to ' \
114
- '`Naming/VariableNumber`.',
115
- 'Lint/BlockAlignment' =>
116
- 'The `Lint/BlockAlignment` cop has been renamed to ' \
117
- '`Layout/BlockAlignment`.',
118
- 'Lint/EndAlignment' =>
119
- 'The `Lint/EndAlignment` cop has been renamed to ' \
120
- '`Layout/EndAlignment`.',
121
- 'Lint/DefEndAlignment' =>
122
- 'The `Lint/DefEndAlignment` cop has been renamed to ' \
123
- '`Layout/DefEndAlignment`.',
124
- 'Style/MethodMissing' =>
125
- 'The `Style/MethodMissing` cop has been split into ' \
126
- '`Style/MethodMissingSuper` and `Style/MissingRespondToMissing`.'
127
- }.freeze
128
-
129
- OBSOLETE_PARAMETERS = [
130
- {
131
- cop: 'Layout/SpaceAroundOperators',
132
- parameter: 'MultiSpaceAllowedForOperators',
133
- alternative: 'If your intention was to allow extra spaces ' \
134
- 'for alignment, please use AllowForAlignment: ' \
135
- 'true instead.'
136
- },
137
- {
138
- cop: 'Style/Encoding',
139
- parameter: 'EnforcedStyle',
140
- alternative: 'Style/Encoding no longer supports styles. ' \
141
- 'The "never" behavior is always assumed.'
142
- },
143
- {
144
- cop: 'Style/Encoding',
145
- parameter: 'SupportedStyles',
146
- alternative: 'Style/Encoding no longer supports styles. ' \
147
- 'The "never" behavior is always assumed.'
148
- },
149
- {
150
- cop: 'Style/Encoding',
151
- parameter: 'AutoCorrectEncodingComment',
152
- alternative: 'Style/Encoding no longer supports styles. ' \
153
- 'The "never" behavior is always assumed.'
154
- },
155
- {
156
- cop: 'Style/IfUnlessModifier',
157
- parameter: 'MaxLineLength',
158
- alternative:
159
- '`Style/IfUnlessModifier: MaxLineLength` has been removed. Use ' \
160
- '`Metrics/LineLength: Max` instead'
161
- },
162
- {
163
- cop: 'Style/SpaceAroundOperators',
164
- parameter: 'MultiSpaceAllowedForOperators',
165
- alternative: 'If your intention was to allow extra spaces ' \
166
- 'for alignment, please use AllowForAlignment: ' \
167
- 'true instead.'
168
- },
169
- {
170
- cop: 'Style/WhileUntilModifier',
171
- parameter: 'MaxLineLength',
172
- alternative:
173
- '`Style/WhileUntilModifier: MaxLineLength` has been removed. Use ' \
174
- '`Metrics/LineLength: Max` instead'
175
- },
176
- {
177
- cop: 'AllCops',
178
- parameter: 'RunRailsCops',
179
- alternative: "Use the following configuration instead:\n" \
180
- "Rails:\n Enabled: true"
181
- },
182
- {
183
- cop: 'Layout/CaseIndentation',
184
- parameter: 'IndentWhenRelativeTo',
185
- alternative: '`IndentWhenRelativeTo` has been renamed to ' \
186
- '`EnforcedStyle`'
187
- },
188
- {
189
- cop: 'Lint/BlockAlignment',
190
- parameter: 'AlignWith',
191
- alternative: '`AlignWith` has been renamed to ' \
192
- '`EnforcedStyleAlignWith`'
193
- },
194
- {
195
- cop: 'Layout/BlockAlignment',
196
- parameter: 'AlignWith',
197
- alternative: '`AlignWith` has been renamed to ' \
198
- '`EnforcedStyleAlignWith`'
199
- },
200
- {
201
- cop: 'Lint/EndAlignment',
202
- parameter: 'AlignWith',
203
- alternative: '`AlignWith` has been renamed to ' \
204
- '`EnforcedStyleAlignWith`'
205
- },
206
- {
207
- cop: 'Layout/EndAlignment',
208
- parameter: 'AlignWith',
209
- alternative: '`AlignWith` has been renamed to ' \
210
- '`EnforcedStyleAlignWith`'
211
- },
212
- {
213
- cop: 'Lint/DefEndAlignment',
214
- parameter: 'AlignWith',
215
- alternative: '`AlignWith` has been renamed to ' \
216
- '`EnforcedStyleAlignWith`'
217
- },
218
- {
219
- cop: 'Layout/DefEndAlignment',
220
- parameter: 'AlignWith',
221
- alternative: '`AlignWith` has been renamed to ' \
222
- '`EnforcedStyleAlignWith`'
223
- },
224
- {
225
- cop: 'Rails/UniqBeforePluck',
226
- parameter: 'EnforcedMode',
227
- alternative: '`EnforcedMode` has been renamed to ' \
228
- '`EnforcedStyle`'
229
- }
230
- ].freeze
231
-
232
- OBSOLETE_ENFORCED_STYLES = [
233
- {
234
- cop: 'Layout/IndentationConsistency',
235
- parameter: 'EnforcedStyle',
236
- enforced_style: 'rails',
237
- alternative: '`EnforcedStyle: rails` has been renamed to ' \
238
- '`EnforcedStyle: indented_internal_methods`'
239
- }
240
- ].freeze
241
-
242
17
  attr_reader :loaded_path
243
18
 
244
19
  def initialize(hash = {}, loaded_path = nil)
@@ -250,6 +25,7 @@ module RuboCop
250
25
  h[cop] = cop_options
251
26
  end
252
27
  @hash = hash
28
+ @validator = ConfigValidator.new(self)
253
29
  end
254
30
 
255
31
  def self.create(hash, path)
@@ -260,54 +36,14 @@ module RuboCop
260
36
  deprecation_check do |deprecation_message|
261
37
  warn("#{loaded_path} - #{deprecation_message}")
262
38
  end
263
- validate
39
+ @validator.validate
264
40
  make_excludes_absolute
265
41
  self
266
42
  end
267
43
 
268
- def [](key)
269
- @hash[key]
270
- end
271
-
272
- def []=(key, value)
273
- @hash[key] = value
274
- end
275
-
276
- def delete(key)
277
- @hash.delete(key)
278
- end
279
-
280
- def each(&block)
281
- @hash.each(&block)
282
- end
283
-
284
- def key?(key)
285
- @hash.key?(key)
286
- end
287
-
288
- def keys
289
- @hash.keys
290
- end
291
-
292
- def each_key(&block)
293
- @hash.each_key(&block)
294
- end
295
-
296
- def map(&block)
297
- @hash.map(&block)
298
- end
299
-
300
- def merge(other_hash)
301
- @hash.merge(other_hash)
302
- end
303
-
304
- def to_h
305
- @hash
306
- end
307
-
308
- def to_hash
309
- @hash
310
- end
44
+ def_delegators :@hash, :[], :[]=, :delete, :each, :key?, :keys, :each_key,
45
+ :map, :merge, :to_h, :to_hash
46
+ def_delegators :@validator, :validate, :target_ruby_version
311
47
 
312
48
  def to_s
313
49
  @to_s ||= @hash.to_s
@@ -317,9 +53,16 @@ module RuboCop
317
53
  @signature ||= Digest::SHA1.hexdigest(to_s)
318
54
  end
319
55
 
56
+ # True if this is a config file that is shipped with RuboCop
57
+ def internal?
58
+ base_config_path = File.expand_path(File.join(ConfigLoader::RUBOCOP_HOME,
59
+ 'config'))
60
+ File.expand_path(loaded_path).start_with?(base_config_path)
61
+ end
62
+
320
63
  def make_excludes_absolute
321
64
  each_key do |key|
322
- validate_section_presence(key)
65
+ @validator.validate_section_presence(key)
323
66
  next unless self[key]['Exclude']
324
67
 
325
68
  self[key]['Exclude'].map! do |exclude_elem|
@@ -360,27 +103,12 @@ module RuboCop
360
103
  @for_cop[cop.respond_to?(:cop_name) ? cop.cop_name : cop]
361
104
  end
362
105
 
363
- def for_all_cops
364
- @for_all_cops ||= self['AllCops'] || {}
106
+ def for_department(department_name)
107
+ @for_cop[department_name]
365
108
  end
366
109
 
367
- def validate
368
- # Don't validate RuboCop's own files. Avoids infinite recursion.
369
- base_config_path = File.expand_path(File.join(ConfigLoader::RUBOCOP_HOME,
370
- 'config'))
371
- return if File.expand_path(loaded_path).start_with?(base_config_path)
372
-
373
- valid_cop_names, invalid_cop_names = keys.partition do |key|
374
- ConfigLoader.default_configuration.key?(key)
375
- end
376
-
377
- reject_obsolete_cops_and_parameters
378
- warn_about_unrecognized_cops(invalid_cop_names)
379
- check_target_ruby
380
- validate_parameter_names(valid_cop_names)
381
- validate_enforced_styles(valid_cop_names)
382
- validate_syntax_cop
383
- reject_mutually_exclusive_defaults
110
+ def for_all_cops
111
+ @for_all_cops ||= self['AllCops'] || {}
384
112
  end
385
113
 
386
114
  def file_to_include?(file)
@@ -461,26 +189,6 @@ module RuboCop
461
189
  end
462
190
  end
463
191
 
464
- def target_ruby_version
465
- @target_ruby_version ||= begin
466
- if for_all_cops['TargetRubyVersion']
467
- @target_ruby_version_source = :rubocop_yml
468
-
469
- for_all_cops['TargetRubyVersion'].to_f
470
- elsif target_ruby_version_from_version_file
471
- @target_ruby_version_source = :ruby_version_file
472
-
473
- target_ruby_version_from_version_file
474
- elsif target_ruby_version_from_bundler_lock_file
475
- @target_ruby_version_source = :bundler_lock_file
476
-
477
- target_ruby_version_from_bundler_lock_file
478
- else
479
- DEFAULT_RUBY_VERSION
480
- end
481
- end
482
- end
483
-
484
192
  def target_rails_version
485
193
  @target_rails_version ||=
486
194
  if for_all_cops['TargetRailsVersion']
@@ -492,214 +200,22 @@ module RuboCop
492
200
  end
493
201
  end
494
202
 
495
- private
496
-
497
- def warn_about_unrecognized_cops(invalid_cop_names)
498
- invalid_cop_names.each do |name|
499
- # There could be a custom cop with this name. If so, don't warn
500
- next if Cop::Cop.registry.contains_cop_matching?([name])
501
-
502
- # Special case for inherit_mode, which is a directive that we keep in
503
- # the configuration (even though it's not a cop), because it's easier
504
- # to do so than to pass the value around to various methods.
505
- next if name == 'inherit_mode'
506
-
507
- warn Rainbow("Warning: unrecognized cop #{name} found in " \
508
- "#{smart_loaded_path}").yellow
509
- end
510
- end
511
-
512
- def validate_syntax_cop
513
- syntax_config = self['Lint/Syntax']
514
- default_config = ConfigLoader.default_configuration['Lint/Syntax']
515
-
516
- return unless syntax_config &&
517
- default_config.merge(syntax_config) != default_config
518
-
519
- raise ValidationError,
520
- "configuration for Syntax cop found in #{smart_loaded_path}\n" \
521
- 'It\'s not possible to disable this cop.'
522
- end
523
-
524
- def validate_section_presence(name)
525
- return unless key?(name) && self[name].nil?
526
-
527
- raise ValidationError,
528
- "empty section #{name} found in #{smart_loaded_path}"
529
- end
530
-
531
- def validate_parameter_names(valid_cop_names)
532
- valid_cop_names.each do |name|
533
- validate_section_presence(name)
534
- default_config = ConfigLoader.default_configuration[name]
535
-
536
- self[name].each_key do |param|
537
- next if COMMON_PARAMS.include?(param) || default_config.key?(param)
538
-
539
- message =
540
- "Warning: #{name} does not support #{param} parameter.\n\n" \
541
- "Supported parameters are:\n\n" \
542
- " - #{(default_config.keys - INTERNAL_PARAMS).join("\n - ")}\n"
543
-
544
- warn Rainbow(message).yellow.to_s
545
- end
546
- end
547
- end
548
-
549
- def validate_enforced_styles(valid_cop_names)
550
- valid_cop_names.each do |name|
551
- styles = self[name].select { |key, _| key.start_with?('Enforced') }
552
-
553
- styles.each do |style_name, style|
554
- supported_key = RuboCop::Cop::Util.to_supported_styles(style_name)
555
- valid = ConfigLoader.default_configuration[name][supported_key]
556
-
557
- next unless valid
558
- next if valid.include?(style)
559
- next if validate_support_and_has_list(name, style, valid)
560
-
561
- msg = "invalid #{style_name} '#{style}' for #{name} found in " \
562
- "#{smart_loaded_path}\n" \
563
- "Valid choices are: #{valid.join(', ')}"
564
- raise ValidationError, msg
565
- end
566
- end
567
- end
568
-
569
- def validate_support_and_has_list(name, formats, valid)
570
- ConfigLoader.default_configuration[name]['AllowMultipleStyles'] &&
571
- formats.is_a?(Array) &&
572
- formats.all? { |format| valid.include?(format) }
573
- end
574
-
575
- def reject_obsolete_cops_and_parameters
576
- messages = [
577
- obsolete_cops,
578
- obsolete_parameters,
579
- obsolete_enforced_style
580
- ].flatten.compact
581
- return if messages.empty?
582
-
583
- raise ValidationError, messages.join("\n")
584
- end
585
-
586
- def obsolete_parameters
587
- OBSOLETE_PARAMETERS.map do |params|
588
- obsolete_parameter_message(params[:cop], params[:parameter],
589
- params[:alternative])
590
- end
591
- end
592
-
593
- def obsolete_parameter_message(cop, parameter, alternative)
594
- return unless self[cop]&.key?(parameter)
595
-
596
- "obsolete parameter #{parameter} (for #{cop}) " \
597
- "found in #{smart_loaded_path}" \
598
- "\n#{alternative}"
599
- end
600
-
601
- def obsolete_cops
602
- OBSOLETE_COPS.map do |cop_name, message|
603
- next unless key?(cop_name) || key?(Cop::Badge.parse(cop_name).cop_name)
604
-
605
- message + "\n(obsolete configuration found in #{smart_loaded_path}," \
606
- ' please update it)'
607
- end
608
- end
609
-
610
- def obsolete_enforced_style
611
- OBSOLETE_ENFORCED_STYLES.map do |params|
612
- obsolete_enforced_style_message(params[:cop], params[:parameter],
613
- params[:enforced_style],
614
- params[:alternative])
615
- end
616
- end
617
-
618
- def obsolete_enforced_style_message(cop, param, enforced_style, alternative)
619
- style = self[cop]&.detect { |key, _| key.start_with?(param) }
620
-
621
- return unless style && style[1] == enforced_style
622
-
623
- "obsolete `#{param}: #{enforced_style}` (for #{cop}) " \
624
- "found in #{smart_loaded_path}" \
625
- "\n#{alternative}"
203
+ def smart_loaded_path
204
+ PathUtil.smart_path(@loaded_path)
626
205
  end
627
206
 
628
- def check_target_ruby
629
- return if KNOWN_RUBIES.include?(target_ruby_version)
630
-
631
- msg = if OBSOLETE_RUBIES.include?(target_ruby_version)
632
- "RuboCop found unsupported Ruby version #{target_ruby_version} " \
633
- "in #{target_ruby_source}. #{target_ruby_version}-compatible " \
634
- 'analysis was dropped after version ' \
635
- "#{OBSOLETE_RUBIES[target_ruby_version]}."
636
- else
637
- 'RuboCop found unknown Ruby version ' \
638
- "#{target_ruby_version.inspect} in #{target_ruby_source}."
639
- end
640
-
641
- msg += "\nSupported versions: #{KNOWN_RUBIES.join(', ')}"
642
-
643
- raise ValidationError, msg
644
- end
207
+ def bundler_lock_file_path
208
+ return nil unless loaded_path
645
209
 
646
- def target_ruby_source
647
- case @target_ruby_version_source
648
- when :ruby_version_file
649
- "`#{RUBY_VERSION_FILENAME}`"
650
- when :bundler_lock_file
651
- "`#{bundler_lock_file_path}`"
652
- when :rubocop_yml
653
- "`TargetRubyVersion` parameter (in #{smart_loaded_path})"
210
+ base_path = base_dir_for_path_parameters
211
+ ['gems.locked', 'Gemfile.lock'].each do |file_name|
212
+ path = find_file_upwards(file_name, base_path)
213
+ return path if path
654
214
  end
215
+ nil
655
216
  end
656
217
 
657
- def ruby_version_file
658
- @ruby_version_file ||=
659
- find_file_upwards(RUBY_VERSION_FILENAME, base_dir_for_path_parameters)
660
- end
661
-
662
- def target_ruby_version_from_version_file
663
- file = ruby_version_file
664
- return unless file && File.file?(file)
665
-
666
- @target_ruby_version_from_version_file ||=
667
- File.read(file).match(/\A(ruby-)?(?<version>\d+\.\d+)/) do |md|
668
- md[:version].to_f
669
- end
670
- end
671
-
672
- def target_ruby_version_from_bundler_lock_file
673
- @target_ruby_version_from_bundler_lock_file ||=
674
- read_ruby_version_from_bundler_lock_file
675
- end
676
-
677
- def read_ruby_version_from_bundler_lock_file
678
- lock_file_path = bundler_lock_file_path
679
- return nil unless lock_file_path
680
-
681
- in_ruby_section = false
682
- File.foreach(lock_file_path) do |line|
683
- # If ruby is in Gemfile.lock or gems.lock, there should be two lines
684
- # towards the bottom of the file that look like:
685
- # RUBY VERSION
686
- # ruby W.X.YpZ
687
- # We ultimately want to match the "ruby W.X.Y.pZ" line, but there's
688
- # extra logic to make sure we only start looking once we've seen the
689
- # "RUBY VERSION" line.
690
- in_ruby_section ||= line.match(/^\s*RUBY\s*VERSION\s*$/)
691
- next unless in_ruby_section
692
-
693
- # We currently only allow this feature to work with MRI ruby. If jruby
694
- # (or something else) is used by the project, it's lock file will have a
695
- # line that looks like:
696
- # RUBY VERSION
697
- # ruby W.X.YpZ (jruby x.x.x.x)
698
- # The regex won't match in this situation.
699
- result = line.match(/^\s*ruby\s+(\d+\.\d+)[p.\d]*\s*$/)
700
- return result.captures.first.to_f if result
701
- end
702
- end
218
+ private
703
219
 
704
220
  def target_rails_version_from_bundler_lock_file
705
221
  @target_rails_version_from_bundler_lock_file ||=
@@ -718,26 +234,6 @@ module RuboCop
718
234
  end
719
235
  end
720
236
 
721
- def bundler_lock_file_path
722
- return nil unless loaded_path
723
-
724
- base_path = base_dir_for_path_parameters
725
- ['gems.locked', 'Gemfile.lock'].each do |file_name|
726
- path = find_file_upwards(file_name, base_path)
727
- return path if path
728
- end
729
- nil
730
- end
731
-
732
- def reject_mutually_exclusive_defaults
733
- disabled_by_default = for_all_cops['DisabledByDefault']
734
- enabled_by_default = for_all_cops['EnabledByDefault']
735
- return unless disabled_by_default && enabled_by_default
736
-
737
- msg = 'Cops cannot be both enabled by default and disabled by default'
738
- raise ValidationError, msg
739
- end
740
-
741
237
  def enable_cop?(qualified_cop_name, cop_options)
742
238
  cop_department, cop_name = qualified_cop_name.split('/')
743
239
  department = cop_name.nil?
@@ -751,10 +247,5 @@ module RuboCop
751
247
 
752
248
  cop_options.fetch('Enabled') { !for_all_cops['DisabledByDefault'] }
753
249
  end
754
-
755
- def smart_loaded_path
756
- PathUtil.smart_path(@loaded_path)
757
- end
758
250
  end
759
- # rubocop:enable Metrics/ClassLength
760
251
  end