rubocop 0.93.1 → 1.6.1

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 (199) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +36 -16
  3. data/config/default.yml +276 -82
  4. data/config/obsoletion.yml +196 -0
  5. data/exe/rubocop +1 -1
  6. data/lib/rubocop.rb +31 -2
  7. data/lib/rubocop/cli.rb +5 -1
  8. data/lib/rubocop/cli/command/auto_genenerate_config.rb +1 -1
  9. data/lib/rubocop/cli/command/execute_runner.rb +26 -11
  10. data/lib/rubocop/cli/command/suggest_extensions.rb +80 -0
  11. data/lib/rubocop/cli/command/version.rb +1 -1
  12. data/lib/rubocop/comment_config.rb +1 -1
  13. data/lib/rubocop/config.rb +4 -0
  14. data/lib/rubocop/config_loader.rb +34 -8
  15. data/lib/rubocop/config_loader_resolver.rb +12 -6
  16. data/lib/rubocop/config_obsoletion.rb +65 -247
  17. data/lib/rubocop/config_obsoletion/changed_enforced_styles.rb +33 -0
  18. data/lib/rubocop/config_obsoletion/changed_parameter.rb +21 -0
  19. data/lib/rubocop/config_obsoletion/cop_rule.rb +34 -0
  20. data/lib/rubocop/config_obsoletion/extracted_cop.rb +44 -0
  21. data/lib/rubocop/config_obsoletion/parameter_rule.rb +44 -0
  22. data/lib/rubocop/config_obsoletion/removed_cop.rb +41 -0
  23. data/lib/rubocop/config_obsoletion/renamed_cop.rb +34 -0
  24. data/lib/rubocop/config_obsoletion/rule.rb +41 -0
  25. data/lib/rubocop/config_obsoletion/split_cop.rb +27 -0
  26. data/lib/rubocop/config_regeneration.rb +1 -1
  27. data/lib/rubocop/config_validator.rb +25 -10
  28. data/lib/rubocop/cop/autocorrect_logic.rb +21 -6
  29. data/lib/rubocop/cop/badge.rb +9 -24
  30. data/lib/rubocop/cop/base.rb +33 -16
  31. data/lib/rubocop/cop/bundler/duplicated_gem.rb +26 -6
  32. data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
  33. data/lib/rubocop/cop/commissioner.rb +37 -23
  34. data/lib/rubocop/cop/cop.rb +2 -2
  35. data/lib/rubocop/cop/corrector.rb +3 -1
  36. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +2 -2
  37. data/lib/rubocop/cop/correctors/string_literal_corrector.rb +6 -8
  38. data/lib/rubocop/cop/force.rb +1 -1
  39. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +3 -3
  40. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +4 -5
  41. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +1 -1
  42. data/lib/rubocop/cop/generator.rb +3 -10
  43. data/lib/rubocop/cop/generator/configuration_injector.rb +1 -1
  44. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +1 -1
  45. data/lib/rubocop/cop/layout/block_alignment.rb +3 -4
  46. data/lib/rubocop/cop/layout/class_structure.rb +22 -3
  47. data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
  48. data/lib/rubocop/cop/layout/else_alignment.rb +15 -2
  49. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +80 -10
  50. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +1 -0
  51. data/lib/rubocop/cop/layout/empty_lines_around_arguments.rb +6 -1
  52. data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -1
  53. data/lib/rubocop/cop/layout/end_alignment.rb +3 -3
  54. data/lib/rubocop/cop/layout/end_of_line.rb +5 -5
  55. data/lib/rubocop/cop/layout/extra_spacing.rb +1 -2
  56. data/lib/rubocop/cop/layout/first_argument_indentation.rb +7 -2
  57. data/lib/rubocop/cop/layout/hash_alignment.rb +4 -4
  58. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +12 -0
  59. data/lib/rubocop/cop/layout/line_length.rb +10 -13
  60. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +7 -3
  61. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +24 -18
  62. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
  63. data/lib/rubocop/cop/layout/space_around_operators.rb +4 -1
  64. data/lib/rubocop/cop/layout/space_inside_parens.rb +35 -13
  65. data/lib/rubocop/cop/layout/trailing_whitespace.rb +37 -13
  66. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +2 -1
  67. data/lib/rubocop/cop/lint/constant_definition_in_block.rb +26 -2
  68. data/lib/rubocop/cop/lint/debugger.rb +17 -28
  69. data/lib/rubocop/cop/lint/duplicate_branch.rb +93 -0
  70. data/lib/rubocop/cop/lint/duplicate_case_condition.rb +2 -12
  71. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +77 -0
  72. data/lib/rubocop/cop/lint/else_layout.rb +29 -3
  73. data/lib/rubocop/cop/lint/empty_block.rb +82 -0
  74. data/lib/rubocop/cop/lint/empty_class.rb +93 -0
  75. data/lib/rubocop/cop/lint/flip_flop.rb +8 -2
  76. data/lib/rubocop/cop/lint/interpolation_check.rb +7 -2
  77. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +39 -7
  78. data/lib/rubocop/cop/lint/loop.rb +4 -4
  79. data/lib/rubocop/cop/lint/missing_super.rb +7 -4
  80. data/lib/rubocop/cop/lint/nested_percent_literal.rb +14 -0
  81. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +58 -0
  82. data/lib/rubocop/cop/lint/number_conversion.rb +46 -13
  83. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +27 -8
  84. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +19 -16
  85. data/lib/rubocop/cop/lint/shadowed_exception.rb +4 -5
  86. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +13 -0
  87. data/lib/rubocop/cop/lint/to_enum_arguments.rb +86 -0
  88. data/lib/rubocop/cop/lint/to_json.rb +1 -1
  89. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +85 -0
  90. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +199 -0
  91. data/lib/rubocop/cop/lint/useless_access_modifier.rb +2 -2
  92. data/lib/rubocop/cop/lint/useless_method_definition.rb +2 -4
  93. data/lib/rubocop/cop/lint/useless_setter_call.rb +6 -1
  94. data/lib/rubocop/cop/metrics/abc_size.rb +25 -1
  95. data/lib/rubocop/cop/metrics/block_length.rb +13 -7
  96. data/lib/rubocop/cop/metrics/method_length.rb +7 -2
  97. data/lib/rubocop/cop/metrics/parameter_lists.rb +68 -2
  98. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +20 -10
  99. data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +146 -0
  100. data/lib/rubocop/cop/metrics/utils/repeated_csend_discount.rb +6 -1
  101. data/lib/rubocop/cop/migration/department_name.rb +1 -1
  102. data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
  103. data/lib/rubocop/cop/mixin/configurable_numbering.rb +4 -3
  104. data/lib/rubocop/cop/mixin/enforce_superclass.rb +9 -1
  105. data/lib/rubocop/cop/mixin/ignored_methods.rb +36 -3
  106. data/lib/rubocop/cop/mixin/line_length_help.rb +1 -1
  107. data/lib/rubocop/cop/mixin/method_complexity.rb +6 -0
  108. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
  109. data/lib/rubocop/cop/mixin/statement_modifier.rb +9 -4
  110. data/lib/rubocop/cop/mixin/string_help.rb +4 -1
  111. data/lib/rubocop/cop/mixin/visibility_help.rb +1 -3
  112. data/lib/rubocop/cop/naming/accessor_method_name.rb +15 -1
  113. data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +12 -2
  114. data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +11 -5
  115. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +67 -18
  116. data/lib/rubocop/cop/naming/predicate_name.rb +2 -1
  117. data/lib/rubocop/cop/naming/variable_number.rb +100 -8
  118. data/lib/rubocop/cop/offense.rb +3 -3
  119. data/lib/rubocop/cop/security/open.rb +12 -10
  120. data/lib/rubocop/cop/style/accessor_grouping.rb +1 -1
  121. data/lib/rubocop/cop/style/and_or.rb +11 -3
  122. data/lib/rubocop/cop/style/arguments_forwarding.rb +142 -0
  123. data/lib/rubocop/cop/style/bisected_attr_accessor.rb +0 -4
  124. data/lib/rubocop/cop/style/case_like_if.rb +0 -4
  125. data/lib/rubocop/cop/style/character_literal.rb +10 -11
  126. data/lib/rubocop/cop/style/class_and_module_children.rb +8 -3
  127. data/lib/rubocop/cop/style/collection_compact.rb +91 -0
  128. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +169 -0
  129. data/lib/rubocop/cop/style/documentation.rb +12 -1
  130. data/lib/rubocop/cop/style/double_negation.rb +6 -1
  131. data/lib/rubocop/cop/style/float_division.rb +44 -1
  132. data/lib/rubocop/cop/style/format_string.rb +8 -3
  133. data/lib/rubocop/cop/style/format_string_token.rb +47 -2
  134. data/lib/rubocop/cop/style/hash_syntax.rb +3 -3
  135. data/lib/rubocop/cop/style/identical_conditional_branches.rb +7 -2
  136. data/lib/rubocop/cop/style/if_inside_else.rb +37 -1
  137. data/lib/rubocop/cop/style/if_unless_modifier.rb +11 -3
  138. data/lib/rubocop/cop/style/if_with_semicolon.rb +39 -4
  139. data/lib/rubocop/cop/style/infinite_loop.rb +4 -0
  140. data/lib/rubocop/cop/style/ip_addresses.rb +1 -1
  141. data/lib/rubocop/cop/style/keyword_parameters_order.rb +12 -0
  142. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +10 -13
  143. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +8 -13
  144. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +7 -11
  145. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +11 -2
  146. data/lib/rubocop/cop/style/mixin_grouping.rb +0 -4
  147. data/lib/rubocop/cop/style/multiple_comparison.rb +55 -7
  148. data/lib/rubocop/cop/style/negated_if_else_condition.rb +106 -0
  149. data/lib/rubocop/cop/style/nil_lambda.rb +52 -0
  150. data/lib/rubocop/cop/style/numeric_literals.rb +14 -11
  151. data/lib/rubocop/cop/style/perl_backrefs.rb +86 -9
  152. data/lib/rubocop/cop/style/raise_args.rb +21 -6
  153. data/lib/rubocop/cop/style/redundant_argument.rb +88 -0
  154. data/lib/rubocop/cop/style/redundant_condition.rb +2 -1
  155. data/lib/rubocop/cop/style/redundant_parentheses.rb +4 -0
  156. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +7 -1
  157. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +24 -8
  158. data/lib/rubocop/cop/style/redundant_self.rb +3 -0
  159. data/lib/rubocop/cop/style/safe_navigation.rb +16 -4
  160. data/lib/rubocop/cop/style/semicolon.rb +3 -0
  161. data/lib/rubocop/cop/style/single_line_block_params.rb +30 -7
  162. data/lib/rubocop/cop/style/sole_nested_conditional.rb +65 -3
  163. data/lib/rubocop/cop/style/special_global_vars.rb +1 -13
  164. data/lib/rubocop/cop/style/static_class.rb +97 -0
  165. data/lib/rubocop/cop/style/string_concatenation.rb +39 -2
  166. data/lib/rubocop/cop/style/string_literals.rb +14 -8
  167. data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +4 -3
  168. data/lib/rubocop/cop/style/swap_values.rb +108 -0
  169. data/lib/rubocop/cop/style/symbol_proc.rb +5 -3
  170. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +3 -1
  171. data/lib/rubocop/cop/style/while_until_modifier.rb +9 -0
  172. data/lib/rubocop/cop/team.rb +6 -1
  173. data/lib/rubocop/cop/util.rb +6 -2
  174. data/lib/rubocop/cop/variable_force/branch.rb +1 -1
  175. data/lib/rubocop/cop/variable_force/scope.rb +1 -1
  176. data/lib/rubocop/core_ext/hash.rb +20 -0
  177. data/lib/rubocop/ext/regexp_node.rb +36 -11
  178. data/lib/rubocop/ext/regexp_parser.rb +95 -0
  179. data/lib/rubocop/formatter/disabled_config_formatter.rb +21 -6
  180. data/lib/rubocop/formatter/emacs_style_formatter.rb +2 -0
  181. data/lib/rubocop/formatter/formatter_set.rb +2 -1
  182. data/lib/rubocop/formatter/git_hub_actions_formatter.rb +47 -0
  183. data/lib/rubocop/formatter/offense_count_formatter.rb +1 -1
  184. data/lib/rubocop/formatter/simple_text_formatter.rb +2 -0
  185. data/lib/rubocop/formatter/tap_formatter.rb +2 -0
  186. data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -1
  187. data/lib/rubocop/lockfile.rb +40 -0
  188. data/lib/rubocop/magic_comment.rb +2 -2
  189. data/lib/rubocop/options.rb +11 -1
  190. data/lib/rubocop/rake_task.rb +2 -2
  191. data/lib/rubocop/rspec/shared_contexts.rb +4 -0
  192. data/lib/rubocop/runner.rb +1 -1
  193. data/lib/rubocop/target_finder.rb +1 -1
  194. data/lib/rubocop/target_ruby.rb +65 -1
  195. data/lib/rubocop/version.rb +56 -6
  196. metadata +50 -9
  197. data/bin/console +0 -10
  198. data/bin/rubocop-profile +0 -32
  199. data/bin/setup +0 -7
@@ -10,7 +10,7 @@ module RuboCop
10
10
 
11
11
  def run
12
12
  puts RuboCop::Version.version(debug: false) if @options[:version]
13
- puts RuboCop::Version.version(debug: true) if @options[:verbose_version]
13
+ puts RuboCop::Version.version(debug: true, env: env) if @options[:verbose_version]
14
14
  end
15
15
  end
16
16
  end
@@ -8,7 +8,7 @@ module RuboCop
8
8
  REDUNDANT_DISABLE = 'Lint/RedundantCopDisableDirective'
9
9
 
10
10
  # @api private
11
- COP_NAME_PATTERN = '([A-Z]\w+/)?(?:[A-Z]\w+)'
11
+ COP_NAME_PATTERN = '([A-Z]\w+/)*(?:[A-Z]\w+)'
12
12
  # @api private
13
13
  COP_NAMES_PATTERN = "(?:#{COP_NAME_PATTERN} , )*#{COP_NAME_PATTERN}"
14
14
  # @api private
@@ -37,6 +37,10 @@ module RuboCop
37
37
  new(hash, path).check
38
38
  end
39
39
 
40
+ def loaded_features
41
+ @loaded_features ||= ConfigLoader.loaded_features
42
+ end
43
+
40
44
  def check
41
45
  deprecation_check do |deprecation_message|
42
46
  warn("#{loaded_path} - #{deprecation_message}")
@@ -35,12 +35,13 @@ module RuboCop
35
35
  end
36
36
 
37
37
  def load_file(file)
38
- path = File.absolute_path(file.is_a?(RemoteConfig) ? file.file : file)
38
+ path = file_path(file)
39
39
 
40
40
  hash = load_yaml_configuration(path)
41
41
 
42
42
  # Resolve requires first in case they define additional cops
43
- resolver.resolve_requires(path, hash)
43
+ loaded_features = resolver.resolve_requires(path, hash)
44
+ add_loaded_features(loaded_features)
44
45
 
45
46
  add_missing_namespaces(path, hash)
46
47
 
@@ -108,7 +109,7 @@ module RuboCop
108
109
  end
109
110
 
110
111
  merge_with_default(config, config_file).tap do |merged_config|
111
- warn_on_pending_cops(merged_config.pending_cops) unless possible_new_cops?(config)
112
+ warn_on_pending_cops(merged_config.pending_cops) unless possible_new_cops?(merged_config)
112
113
  end
113
114
  end
114
115
 
@@ -172,8 +173,24 @@ module RuboCop
172
173
  resolver.merge_with_default(config, config_file, unset_nil: unset_nil)
173
174
  end
174
175
 
176
+ def loaded_features
177
+ @loaded_features.flatten.compact
178
+ end
179
+
175
180
  private
176
181
 
182
+ def file_path(file)
183
+ File.absolute_path(file.is_a?(RemoteConfig) ? file.file : file)
184
+ end
185
+
186
+ def add_loaded_features(loaded_features)
187
+ if instance_variable_defined?(:@loaded_features)
188
+ instance_variable_get(:@loaded_features) << loaded_features
189
+ else
190
+ instance_variable_set(:@loaded_features, [loaded_features])
191
+ end
192
+ end
193
+
177
194
  def find_project_dotfile(target_dir)
178
195
  find_file_upwards(DOTFILE, target_dir, project_root)
179
196
  end
@@ -239,16 +256,25 @@ module RuboCop
239
256
  end
240
257
 
241
258
  def yaml_safe_load(yaml_code, filename)
242
- if defined?(SafeYAML) && SafeYAML.respond_to?(:load)
243
- SafeYAML.load(yaml_code, filename, whitelisted_tags: %w[!ruby/regexp])
244
- # Ruby 2.6+
245
- elsif Gem::Version.new(Psych::VERSION) >= Gem::Version.new('3.1.0')
259
+ yaml_safe_load!(yaml_code, filename)
260
+ rescue ::StandardError
261
+ if defined?(::SafeYAML)
262
+ raise 'SafeYAML is unmaintained, no longer needed and should be removed'
263
+ end
264
+
265
+ raise
266
+ end
267
+
268
+ if Gem::Version.new(Psych::VERSION) >= Gem::Version.new('3.1.0')
269
+ def yaml_safe_load!(yaml_code, filename)
246
270
  YAML.safe_load(yaml_code,
247
271
  permitted_classes: [Regexp, Symbol],
248
272
  permitted_symbols: [],
249
273
  aliases: true,
250
274
  filename: filename)
251
- else
275
+ end
276
+ else # Ruby < 2.6
277
+ def yaml_safe_load!(yaml_code, filename)
252
278
  YAML.safe_load(yaml_code, [Regexp, Symbol], [], true, filename)
253
279
  end
254
280
  end
@@ -9,11 +9,13 @@ module RuboCop
9
9
  class ConfigLoaderResolver
10
10
  def resolve_requires(path, hash)
11
11
  config_dir = File.dirname(path)
12
- Array(hash.delete('require')).each do |r|
13
- if r.start_with?('.')
14
- require(File.join(config_dir, r))
15
- else
16
- require(r)
12
+ hash.delete('require').tap do |loaded_features|
13
+ Array(loaded_features).each do |feature|
14
+ if feature.start_with?('.')
15
+ require(File.join(config_dir, feature))
16
+ else
17
+ require(feature)
18
+ end
17
19
  end
18
20
  end
19
21
  end
@@ -90,7 +92,7 @@ module RuboCop
90
92
  keys_appearing_in_both.each do |key|
91
93
  if opts[:unset_nil] && derived_hash[key].nil?
92
94
  result.delete(key)
93
- elsif base_hash[key].is_a?(Hash)
95
+ elsif merge_hashes?(base_hash, derived_hash, key)
94
96
  result[key] = merge(base_hash[key], derived_hash[key], **opts)
95
97
  elsif should_union?(base_hash, key, opts[:inherit_mode])
96
98
  result[key] = base_hash[key] | derived_hash[key]
@@ -162,6 +164,10 @@ module RuboCop
162
164
  inherit_mode['merge'].include?(key)
163
165
  end
164
166
 
167
+ def merge_hashes?(base_hash, derived_hash, key)
168
+ base_hash[key].is_a?(Hash) && derived_hash[key].is_a?(Hash)
169
+ end
170
+
165
171
  def base_configs(path, inherit_from, file)
166
172
  configs = Array(inherit_from).compact.map do |f|
167
173
  ConfigLoader.load_file(inherited_file(path, f, file))
@@ -4,223 +4,40 @@ module RuboCop
4
4
  # This class handles obsolete configuration.
5
5
  # @api private
6
6
  class ConfigObsoletion
7
- RENAMED_COPS = {
8
- 'Layout/AlignArguments' => 'Layout/ArgumentAlignment',
9
- 'Layout/AlignArray' => 'Layout/ArrayAlignment',
10
- 'Layout/AlignHash' => 'Layout/HashAlignment',
11
- 'Layout/AlignParameters' => 'Layout/ParameterAlignment',
12
- 'Layout/IndentArray' => 'Layout/FirstArrayElementIndentation',
13
- 'Layout/IndentAssignment' => 'Layout/AssignmentIndentation',
14
- 'Layout/IndentFirstArgument' => 'Layout/FirstArgumentIndentation',
15
- 'Layout/IndentFirstArrayElement' => 'Layout/FirstArrayElementIndentation',
16
- 'Layout/IndentFirstHashElement' => 'Layout/FirstHashElementIndentation',
17
- 'Layout/IndentFirstParameter' => 'Layout/FirstParameterIndentation',
18
- 'Layout/IndentHash' => 'Layout/FirstHashElementIndentation',
19
- 'Layout/IndentHeredoc' => 'Layout/HeredocIndentation',
20
- 'Layout/LeadingBlankLines' => 'Layout/LeadingEmptyLines',
21
- 'Layout/Tab' => 'Layout/IndentationStyle',
22
- 'Layout/TrailingBlankLines' => 'Layout/TrailingEmptyLines',
23
- 'Lint/DuplicatedKey' => 'Lint/DuplicateHashKey',
24
- 'Lint/EndInMethod' => 'Style/EndBlock',
25
- 'Lint/HandleExceptions' => 'Lint/SuppressedException',
26
- 'Lint/MultipleCompare' => 'Lint/MultipleComparison',
27
- 'Lint/StringConversionInInterpolation' => 'Lint/RedundantStringCoercion',
28
- 'Lint/UnneededCopDisableDirective' => 'Lint/RedundantCopDisableDirective',
29
- 'Lint/UnneededCopEnableDirective' => 'Lint/RedundantCopEnableDirective',
30
- 'Lint/UnneededRequireStatement' => 'Lint/RedundantRequireStatement',
31
- 'Lint/UnneededSplatExpansion' => 'Lint/RedundantSplatExpansion',
32
- 'Naming/UncommunicativeBlockParamName' => 'Naming/BlockParameterName',
33
- 'Naming/UncommunicativeMethodParamName' => 'Naming/MethodParameterName',
34
- 'Style/DeprecatedHashMethods' => 'Style/PreferredHashMethods',
35
- 'Style/MethodCallParentheses' => 'Style/MethodCallWithoutArgsParentheses',
36
- 'Style/OpMethod' => 'Naming/BinaryOperatorParameterName',
37
- 'Style/SingleSpaceBeforeFirstArg' => 'Layout/SpaceBeforeFirstArg',
38
- 'Style/UnneededCapitalW' => 'Style/RedundantCapitalW',
39
- 'Style/UnneededCondition' => 'Style/RedundantCondition',
40
- 'Style/UnneededInterpolation' => 'Style/RedundantInterpolation',
41
- 'Style/UnneededPercentQ' => 'Style/RedundantPercentQ',
42
- 'Style/UnneededSort' => 'Style/RedundantSort'
43
- }.map do |old_name, new_name|
44
- [old_name, "The `#{old_name}` cop has been renamed to `#{new_name}`."]
45
- end
46
-
47
- MOVED_COPS = {
48
- 'Security' => 'Lint/Eval',
49
- 'Naming' => %w[Style/ClassAndModuleCamelCase Style/ConstantName
50
- Style/FileName Style/MethodName Style/PredicateName
51
- Style/VariableName Style/VariableNumber
52
- Style/AccessorMethodName Style/AsciiIdentifiers],
53
- 'Layout' => %w[Lint/BlockAlignment Lint/EndAlignment
54
- Lint/DefEndAlignment Metrics/LineLength],
55
- 'Lint' => 'Style/FlipFlop'
56
- }.map do |new_department, old_names|
57
- Array(old_names).map do |old_name|
58
- [old_name, "The `#{old_name}` cop has been moved to " \
59
- "`#{new_department}/#{old_name.split('/').last}`."]
60
- end
61
- end
62
-
63
- REMOVED_COPS = {
64
- 'Layout/SpaceAfterControlKeyword' => 'Layout/SpaceAroundKeyword',
65
- 'Layout/SpaceBeforeModifierKeyword' => 'Layout/SpaceAroundKeyword',
66
- 'Lint/RescueWithoutErrorClass' => 'Style/RescueStandardError',
67
- 'Style/SpaceAfterControlKeyword' => 'Layout/SpaceAroundKeyword',
68
- 'Style/SpaceBeforeModifierKeyword' => 'Layout/SpaceAroundKeyword',
69
- 'Style/TrailingComma' => 'Style/TrailingCommaInArguments, ' \
70
- 'Style/TrailingCommaInArrayLiteral, and/or ' \
71
- 'Style/TrailingCommaInHashLiteral',
72
- 'Style/TrailingCommaInLiteral' => 'Style/TrailingCommaInArrayLiteral ' \
73
- 'and/or ' \
74
- 'Style/TrailingCommaInHashLiteral',
75
- 'Style/BracesAroundHashParameters' => nil
76
- }.map do |old_name, other_cops|
77
- if other_cops
78
- more = ". Please use #{other_cops} instead".gsub(%r{[A-Z]\w+/\w+},
79
- '`\&`')
7
+ DEFAULT_RULES_FILE = File.join(ConfigLoader::RUBOCOP_HOME, 'config', 'obsoletion.yml')
8
+ COP_RULE_CLASSES = {
9
+ 'renamed' => RenamedCop,
10
+ 'removed' => RemovedCop,
11
+ 'split' => SplitCop,
12
+ 'extracted' => ExtractedCop
13
+ }.freeze
14
+ PARAMETER_RULE_CLASSES = {
15
+ 'changed_parameters' => ChangedParameter,
16
+ 'changed_enforced_styles' => ChangedEnforcedStyles
17
+ }.freeze
18
+
19
+ attr_reader :rules, :warnings
20
+
21
+ class << self
22
+ attr_accessor :files
23
+
24
+ def legacy_cop_names
25
+ # Used by DepartmentName#qualified_legacy_cop_name
26
+ new(Config.new).rules.select(&:cop_rule?).map(&:old_name)
80
27
  end
81
- [old_name, "The `#{old_name}` cop has been removed#{more}."]
82
- end
83
-
84
- REMOVED_COPS_WITH_REASON = {
85
- 'Lint/InvalidCharacterLiteral' => 'it was never being actually triggered',
86
- 'Lint/SpaceBeforeFirstArg' =>
87
- 'it was a duplicate of `Layout/SpaceBeforeFirstArg`. Please use ' \
88
- '`Layout/SpaceBeforeFirstArg` instead',
89
- 'Style/MethodMissingSuper' => 'it has been superseded by `Lint/MissingSuper`. Please use ' \
90
- '`Lint/MissingSuper` instead',
91
- 'Lint/UselessComparison' => 'it has been superseded by '\
92
- '`Lint/BinaryOperatorWithIdenticalOperands`. Please use '\
93
- '`Lint/BinaryOperatorWithIdenticalOperands` instead'
94
- }.map do |cop_name, reason|
95
- [cop_name, "The `#{cop_name}` cop has been removed since #{reason}."]
96
28
  end
97
29
 
98
- SPLIT_COPS = {
99
- 'Style/MethodMissing' =>
100
- 'The `Style/MethodMissing` cop has been split into ' \
101
- '`Style/MethodMissingSuper` and `Style/MissingRespondToMissing`.'
102
- }.to_a
103
-
104
- OBSOLETE_COPS = Hash[*(RENAMED_COPS + MOVED_COPS + REMOVED_COPS +
105
- REMOVED_COPS_WITH_REASON + SPLIT_COPS).flatten]
106
-
107
- OBSOLETE_PARAMETERS = [
108
- {
109
- cops: %w[Layout/SpaceAroundOperators Style/SpaceAroundOperators],
110
- parameters: 'MultiSpaceAllowedForOperators',
111
- alternative: 'If your intention was to allow extra spaces for ' \
112
- 'alignment, please use AllowForAlignment: true instead.'
113
- },
114
- {
115
- cops: 'Style/Encoding',
116
- parameters: %w[EnforcedStyle SupportedStyles
117
- AutoCorrectEncodingComment],
118
- alternative: 'Style/Encoding no longer supports styles. ' \
119
- 'The "never" behavior is always assumed.'
120
- },
121
- {
122
- cops: 'Style/IfUnlessModifier',
123
- parameters: 'MaxLineLength',
124
- alternative: '`Style/IfUnlessModifier: MaxLineLength` has been ' \
125
- 'removed. Use `Layout/LineLength: Max` instead'
126
- },
127
- {
128
- cops: 'Style/WhileUntilModifier',
129
- parameters: 'MaxLineLength',
130
- alternative: '`Style/WhileUntilModifier: MaxLineLength` has been ' \
131
- 'removed. Use `Layout/LineLength: Max` instead'
132
- },
133
- {
134
- cops: 'AllCops',
135
- parameters: 'RunRailsCops',
136
- alternative: "Use the following configuration instead:\n" \
137
- "Rails:\n Enabled: true"
138
- },
139
- {
140
- cops: 'Layout/CaseIndentation',
141
- parameters: 'IndentWhenRelativeTo',
142
- alternative: '`IndentWhenRelativeTo` has been renamed to ' \
143
- '`EnforcedStyle`'
144
- },
145
- {
146
- cops: %w[Lint/BlockAlignment Layout/BlockAlignment Lint/EndAlignment
147
- Layout/EndAlignment Lint/DefEndAlignment
148
- Layout/DefEndAlignment],
149
- parameters: 'AlignWith',
150
- alternative: '`AlignWith` has been renamed to `EnforcedStyleAlignWith`'
151
- },
152
- {
153
- cops: 'Rails/UniqBeforePluck',
154
- parameters: 'EnforcedMode',
155
- alternative: '`EnforcedMode` has been renamed to `EnforcedStyle`'
156
- },
157
- {
158
- cops: 'Style/MethodCallWithArgsParentheses',
159
- parameters: 'IgnoredMethodPatterns',
160
- alternative: '`IgnoredMethodPatterns` has been renamed to ' \
161
- '`IgnoredPatterns`'
162
- },
163
- {
164
- cops: %w[Performance/Count Performance/Detect],
165
- parameters: 'SafeMode',
166
- alternative: '`SafeMode` has been removed. ' \
167
- 'Use `SafeAutoCorrect` instead.'
168
- },
169
- {
170
- cops: 'Bundler/GemComment',
171
- parameters: 'Whitelist',
172
- alternative: '`Whitelist` has been renamed to `IgnoredGems`.'
173
- },
174
- {
175
- cops: %w[
176
- Lint/SafeNavigationChain Lint/SafeNavigationConsistency
177
- Style/NestedParenthesizedCalls Style/SafeNavigation
178
- Style/TrivialAccessors
179
- ],
180
- parameters: 'Whitelist',
181
- alternative: '`Whitelist` has been renamed to `AllowedMethods`.'
182
- },
183
- {
184
- cops: 'Style/IpAddresses',
185
- parameters: 'Whitelist',
186
- alternative: '`Whitelist` has been renamed to `AllowedAddresses`.'
187
- },
188
- {
189
- cops: 'Naming/HeredocDelimiterNaming',
190
- parameters: 'Blacklist',
191
- alternative: '`Blacklist` has been renamed to `ForbiddenDelimiters`.'
192
- },
193
- {
194
- cops: 'Naming/PredicateName',
195
- parameters: 'NamePrefixBlacklist',
196
- alternative: '`NamePrefixBlacklist` has been renamed to ' \
197
- '`ForbiddenPrefixes`.'
198
- },
199
- {
200
- cops: 'Naming/PredicateName',
201
- parameters: 'NameWhitelist',
202
- alternative: '`NameWhitelist` has been renamed to ' \
203
- '`AllowedMethods`.'
204
- }
205
- ].freeze
206
-
207
- OBSOLETE_ENFORCED_STYLES = [
208
- {
209
- cop: 'Layout/IndentationConsistency',
210
- parameter: 'EnforcedStyle',
211
- enforced_style: 'rails',
212
- alternative: '`EnforcedStyle: rails` has been renamed to ' \
213
- '`EnforcedStyle: indented_internal_methods`'
214
- }
215
- ].freeze
30
+ # Can be extended by extension libraries to add their own obsoletions
31
+ self.files = [DEFAULT_RULES_FILE]
216
32
 
217
33
  def initialize(config)
218
34
  @config = config
35
+ @rules = load_rules
36
+ @warnings = []
219
37
  end
220
38
 
221
- def reject_obsolete_cops_and_parameters
222
- messages = [obsolete_cops, obsolete_parameters,
223
- obsolete_enforced_style].flatten.compact
39
+ def reject_obsolete!
40
+ messages = obsoletions.flatten.compact
224
41
  return if messages.empty?
225
42
 
226
43
  raise ValidationError, messages.join("\n")
@@ -228,56 +45,57 @@ module RuboCop
228
45
 
229
46
  private
230
47
 
231
- def obsolete_cops
232
- OBSOLETE_COPS.map do |cop_name, message|
233
- next unless @config.key?(cop_name) ||
234
- @config.key?(Cop::Badge.parse(cop_name).cop_name)
235
-
236
- message + "\n(obsolete configuration found in " \
237
- "#{smart_loaded_path}, please update it)"
238
- end
239
- end
240
-
241
- def obsolete_enforced_style
242
- OBSOLETE_ENFORCED_STYLES.map do |params|
243
- obsolete_enforced_style_message(params[:cop], params[:parameter],
244
- params[:enforced_style],
245
- params[:alternative])
48
+ # Default rules for obsoletions are in config/obsoletion.yml
49
+ # Additional rules files can be added with `RuboCop::ConfigObsoletion.files << filename`
50
+ def load_rules
51
+ rules = self.class.files.each_with_object({}) do |filename, hash|
52
+ hash.merge!(YAML.safe_load(File.read(filename))) do |_key, first, second|
53
+ first.merge(second)
54
+ end
246
55
  end
247
- end
248
-
249
- def obsolete_enforced_style_message(cop, param, enforced_style, alternative)
250
- style = @config[cop]&.detect { |key, _| key.start_with?(param) }
251
56
 
252
- return unless style && style[1] == enforced_style
57
+ cop_rules = rules.slice(*COP_RULE_CLASSES.keys)
58
+ parameter_rules = rules.slice(*PARAMETER_RULE_CLASSES.keys)
253
59
 
254
- "obsolete `#{param}: #{enforced_style}` (for #{cop}) found in " \
255
- "#{smart_loaded_path}\n#{alternative}"
60
+ load_cop_rules(cop_rules).concat(load_parameter_rules(parameter_rules))
256
61
  end
257
62
 
258
- def obsolete_parameters
259
- OBSOLETE_PARAMETERS.map do |params|
260
- obsolete_parameter_message(params[:cops], params[:parameters],
261
- params[:alternative])
63
+ # Cop rules are keyed by the name of the original cop
64
+ def load_cop_rules(rules)
65
+ rules.flat_map do |rule_type, data|
66
+ data.map do |configuration|
67
+ COP_RULE_CLASSES[rule_type].new(@config, *configuration)
68
+ end
262
69
  end
263
70
  end
264
71
 
265
- def obsolete_parameter_message(cops, parameters, alternative)
266
- Array(cops).map do |cop|
267
- obsolete_parameters = Array(parameters).select do |param|
268
- @config[cop]&.key?(param)
269
- end
270
- next if obsolete_parameters.empty?
271
-
272
- obsolete_parameters.map do |parameter|
273
- "obsolete parameter #{parameter} (for #{cop}) found in " \
274
- "#{smart_loaded_path}\n#{alternative}"
72
+ # Parameter rules may apply to multiple cops and multiple parameters
73
+ # and are given as an array. Each combination is turned into a separate
74
+ # rule object.
75
+ def load_parameter_rules(rules)
76
+ rules.flat_map do |rule_type, data|
77
+ data.flat_map do |configuration|
78
+ cops = Array(configuration['cops'])
79
+ parameters = Array(configuration['parameters'])
80
+
81
+ cops.product(parameters).map do |cop, parameter|
82
+ PARAMETER_RULE_CLASSES[rule_type].new(@config, cop, parameter, configuration)
83
+ end
275
84
  end
276
85
  end
277
86
  end
278
87
 
279
- def smart_loaded_path
280
- PathUtil.smart_path(@config.loaded_path)
88
+ def obsoletions
89
+ rules.map do |rule|
90
+ next unless rule.violated?
91
+
92
+ if rule.warning?
93
+ @warnings.push(rule.message)
94
+ next
95
+ end
96
+
97
+ rule.message
98
+ end
281
99
  end
282
100
  end
283
101
  end