rubocop 0.71.0 → 0.75.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 (280) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -8
  3. data/bin/console +1 -0
  4. data/config/default.yml +84 -488
  5. data/lib/rubocop.rb +16 -54
  6. data/lib/rubocop/ast/builder.rb +2 -0
  7. data/lib/rubocop/ast/node.rb +9 -15
  8. data/lib/rubocop/ast/node/float_node.rb +12 -0
  9. data/lib/rubocop/ast/node/int_node.rb +12 -0
  10. data/lib/rubocop/ast/node/mixin/method_dispatch_node.rb +4 -4
  11. data/lib/rubocop/ast/node/mixin/numeric_node.rb +21 -0
  12. data/lib/rubocop/ast/node/resbody_node.rb +1 -6
  13. data/lib/rubocop/ast/traversal.rb +3 -3
  14. data/lib/rubocop/cached_data.rb +1 -1
  15. data/lib/rubocop/comment_config.rb +3 -2
  16. data/lib/rubocop/config.rb +21 -508
  17. data/lib/rubocop/config_loader.rb +22 -8
  18. data/lib/rubocop/config_loader_resolver.rb +2 -16
  19. data/lib/rubocop/config_obsoletion.rb +213 -0
  20. data/lib/rubocop/config_validator.rb +239 -0
  21. data/lib/rubocop/cop/autocorrect_logic.rb +71 -1
  22. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +1 -1
  23. data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -1
  24. data/lib/rubocop/cop/commissioner.rb +3 -9
  25. data/lib/rubocop/cop/cop.rb +39 -12
  26. data/lib/rubocop/cop/corrector.rb +2 -3
  27. data/lib/rubocop/cop/correctors/alignment_corrector.rb +43 -17
  28. data/lib/rubocop/cop/correctors/empty_line_corrector.rb +2 -2
  29. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +2 -2
  30. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +1 -1
  31. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +2 -2
  32. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -1
  33. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +1 -1
  34. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +55 -0
  35. data/lib/rubocop/cop/generator.rb +4 -4
  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/node_destructuring.rb +2 -2
  39. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +1 -1
  40. data/lib/rubocop/cop/internal_affairs/offense_location_keyword.rb +2 -2
  41. data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +1 -1
  42. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +2 -2
  43. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +2 -2
  44. data/lib/rubocop/cop/layout/block_alignment.rb +3 -3
  45. data/lib/rubocop/cop/layout/class_structure.rb +2 -2
  46. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +1 -1
  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/extra_spacing.rb +14 -59
  51. data/lib/rubocop/cop/layout/indent_assignment.rb +10 -1
  52. data/lib/rubocop/cop/layout/indent_first_argument.rb +7 -3
  53. data/lib/rubocop/cop/layout/indent_first_parameter.rb +7 -3
  54. data/lib/rubocop/cop/layout/indent_heredoc.rb +4 -4
  55. data/lib/rubocop/cop/layout/indentation_consistency.rb +13 -12
  56. data/lib/rubocop/cop/layout/indentation_width.rb +28 -10
  57. data/lib/rubocop/cop/layout/leading_comment_space.rb +28 -0
  58. data/lib/rubocop/cop/layout/multiline_block_layout.rb +24 -2
  59. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +18 -4
  60. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +5 -1
  61. data/lib/rubocop/cop/layout/space_around_operators.rb +42 -23
  62. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +1 -1
  63. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +21 -2
  64. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +24 -40
  65. data/lib/rubocop/cop/layout/tab.rb +10 -22
  66. data/lib/rubocop/cop/lint/assignment_in_condition.rb +17 -4
  67. data/lib/rubocop/cop/lint/big_decimal_new.rb +1 -1
  68. data/lib/rubocop/cop/lint/debugger.rb +4 -6
  69. data/lib/rubocop/cop/lint/duplicate_methods.rb +3 -3
  70. data/lib/rubocop/cop/lint/each_with_object_argument.rb +1 -1
  71. data/lib/rubocop/cop/lint/empty_interpolation.rb +4 -4
  72. data/lib/rubocop/cop/lint/erb_new_arguments.rb +57 -1
  73. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +11 -37
  74. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -1
  75. data/lib/rubocop/cop/lint/inherit_exception.rb +1 -1
  76. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +7 -8
  77. data/lib/rubocop/cop/lint/multiple_compare.rb +1 -1
  78. data/lib/rubocop/cop/lint/nested_method_definition.rb +3 -3
  79. data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
  80. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +1 -1
  81. data/lib/rubocop/cop/lint/number_conversion.rb +4 -4
  82. data/lib/rubocop/cop/lint/rand_one.rb +1 -1
  83. data/lib/rubocop/cop/lint/redundant_with_index.rb +1 -1
  84. data/lib/rubocop/cop/lint/redundant_with_object.rb +1 -1
  85. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +5 -5
  86. data/lib/rubocop/cop/lint/safe_navigation_with_empty.rb +1 -1
  87. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +91 -0
  88. data/lib/rubocop/cop/lint/string_conversion_in_interpolation.rb +6 -6
  89. data/lib/rubocop/cop/lint/unified_integer.rb +1 -1
  90. data/lib/rubocop/cop/lint/unneeded_cop_disable_directive.rb +1 -1
  91. data/lib/rubocop/cop/lint/unneeded_require_statement.rb +1 -1
  92. data/lib/rubocop/cop/lint/unneeded_splat_expansion.rb +7 -2
  93. data/lib/rubocop/cop/lint/unreachable_code.rb +1 -1
  94. data/lib/rubocop/cop/lint/unused_block_argument.rb +22 -6
  95. data/lib/rubocop/cop/lint/unused_method_argument.rb +23 -5
  96. data/lib/rubocop/cop/lint/uri_escape_unescape.rb +1 -1
  97. data/lib/rubocop/cop/lint/uri_regexp.rb +2 -2
  98. data/lib/rubocop/cop/lint/useless_access_modifier.rb +6 -6
  99. data/lib/rubocop/cop/lint/useless_setter_call.rb +1 -1
  100. data/lib/rubocop/cop/lint/void.rb +3 -22
  101. data/lib/rubocop/cop/message_annotator.rb +16 -7
  102. data/lib/rubocop/cop/metrics/class_length.rb +1 -1
  103. data/lib/rubocop/cop/metrics/line_length.rb +6 -0
  104. data/lib/rubocop/cop/metrics/module_length.rb +1 -1
  105. data/lib/rubocop/cop/metrics/parameter_lists.rb +1 -1
  106. data/lib/rubocop/cop/migration/department_name.rb +44 -0
  107. data/lib/rubocop/cop/mixin/alignment.rb +1 -1
  108. data/lib/rubocop/cop/mixin/def_node.rb +1 -1
  109. data/lib/rubocop/cop/mixin/documentation_comment.rb +0 -2
  110. data/lib/rubocop/cop/mixin/empty_parameter.rb +1 -1
  111. data/lib/rubocop/cop/mixin/enforce_superclass.rb +4 -4
  112. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -1
  113. data/lib/rubocop/cop/mixin/interpolation.rb +27 -0
  114. data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
  115. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +3 -3
  116. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +87 -0
  117. data/lib/rubocop/cop/mixin/safe_mode.rb +2 -0
  118. data/lib/rubocop/cop/mixin/surrounding_space.rb +7 -5
  119. data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +1 -1
  120. data/lib/rubocop/cop/naming/constant_name.rb +2 -2
  121. data/lib/rubocop/cop/naming/method_name.rb +12 -1
  122. data/lib/rubocop/cop/naming/predicate_name.rb +1 -1
  123. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +21 -20
  124. data/lib/rubocop/cop/naming/variable_name.rb +1 -0
  125. data/lib/rubocop/cop/offense.rb +18 -7
  126. data/lib/rubocop/cop/registry.rb +22 -1
  127. data/lib/rubocop/cop/security/eval.rb +1 -1
  128. data/lib/rubocop/cop/security/json_load.rb +1 -1
  129. data/lib/rubocop/cop/security/marshal_load.rb +1 -1
  130. data/lib/rubocop/cop/security/open.rb +1 -1
  131. data/lib/rubocop/cop/security/yaml_load.rb +1 -1
  132. data/lib/rubocop/cop/style/access_modifier_declarations.rb +1 -0
  133. data/lib/rubocop/cop/style/alias.rb +1 -1
  134. data/lib/rubocop/cop/style/block_delimiters.rb +2 -1
  135. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +29 -10
  136. data/lib/rubocop/cop/style/class_and_module_children.rb +1 -1
  137. data/lib/rubocop/cop/style/colon_method_call.rb +1 -1
  138. data/lib/rubocop/cop/style/commented_keyword.rb +16 -30
  139. data/lib/rubocop/cop/style/conditional_assignment.rb +8 -9
  140. data/lib/rubocop/cop/style/constant_visibility.rb +14 -3
  141. data/lib/rubocop/cop/style/date_time.rb +3 -3
  142. data/lib/rubocop/cop/style/dir.rb +1 -1
  143. data/lib/rubocop/cop/style/documentation_method.rb +45 -1
  144. data/lib/rubocop/cop/style/double_cop_disable_directive.rb +55 -0
  145. data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
  146. data/lib/rubocop/cop/style/each_with_object.rb +1 -1
  147. data/lib/rubocop/cop/style/eval_with_location.rb +2 -2
  148. data/lib/rubocop/cop/style/even_odd.rb +1 -1
  149. data/lib/rubocop/cop/style/expand_path_arguments.rb +4 -4
  150. data/lib/rubocop/cop/style/float_division.rb +94 -0
  151. data/lib/rubocop/cop/style/format_string.rb +13 -9
  152. data/lib/rubocop/cop/style/format_string_token.rb +18 -69
  153. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +18 -33
  154. data/lib/rubocop/cop/style/guard_clause.rb +39 -10
  155. data/lib/rubocop/cop/style/hash_syntax.rb +2 -2
  156. data/lib/rubocop/cop/style/if_inside_else.rb +42 -0
  157. data/lib/rubocop/cop/style/if_unless_modifier.rb +51 -15
  158. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  159. data/lib/rubocop/cop/style/inverse_methods.rb +2 -2
  160. data/lib/rubocop/cop/style/lambda.rb +0 -2
  161. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +32 -26
  162. data/lib/rubocop/cop/style/min_max.rb +1 -1
  163. data/lib/rubocop/cop/style/mixin_usage.rb +12 -2
  164. data/lib/rubocop/cop/style/multiline_memoization.rb +1 -1
  165. data/lib/rubocop/cop/style/multiline_when_then.rb +55 -0
  166. data/lib/rubocop/cop/style/multiple_comparison.rb +1 -1
  167. data/lib/rubocop/cop/style/mutable_constant.rb +3 -3
  168. data/lib/rubocop/cop/style/nested_modifier.rb +18 -2
  169. data/lib/rubocop/cop/style/numeric_predicate.rb +3 -3
  170. data/lib/rubocop/cop/style/option_hash.rb +1 -1
  171. data/lib/rubocop/cop/style/or_assignment.rb +8 -3
  172. data/lib/rubocop/cop/style/parentheses_around_condition.rb +15 -1
  173. data/lib/rubocop/cop/style/random_with_offset.rb +6 -6
  174. data/lib/rubocop/cop/style/redundant_conditional.rb +2 -2
  175. data/lib/rubocop/cop/style/redundant_exception.rb +2 -2
  176. data/lib/rubocop/cop/style/redundant_freeze.rb +1 -1
  177. data/lib/rubocop/cop/style/redundant_parentheses.rb +15 -6
  178. data/lib/rubocop/cop/style/redundant_return.rb +12 -0
  179. data/lib/rubocop/cop/style/redundant_self.rb +18 -1
  180. data/lib/rubocop/cop/style/redundant_sort_by.rb +1 -1
  181. data/lib/rubocop/cop/style/rescue_modifier.rb +24 -0
  182. data/lib/rubocop/cop/style/rescue_standard_error.rb +2 -2
  183. data/lib/rubocop/cop/style/return_nil.rb +1 -1
  184. data/lib/rubocop/cop/style/safe_navigation.rb +19 -2
  185. data/lib/rubocop/cop/style/sample.rb +1 -1
  186. data/lib/rubocop/cop/style/semicolon.rb +11 -0
  187. data/lib/rubocop/cop/style/single_line_methods.rb +8 -1
  188. data/lib/rubocop/cop/style/stderr_puts.rb +1 -1
  189. data/lib/rubocop/cop/style/string_hash_keys.rb +2 -2
  190. data/lib/rubocop/cop/style/strip.rb +1 -1
  191. data/lib/rubocop/cop/style/struct_inheritance.rb +3 -3
  192. data/lib/rubocop/cop/style/symbol_proc.rb +1 -1
  193. data/lib/rubocop/cop/style/ternary_parentheses.rb +32 -3
  194. data/lib/rubocop/cop/style/trailing_method_end_statement.rb +4 -6
  195. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  196. data/lib/rubocop/cop/style/unneeded_sort.rb +1 -1
  197. data/lib/rubocop/cop/style/unpack_first.rb +1 -1
  198. data/lib/rubocop/cop/style/variable_interpolation.rb +6 -16
  199. data/lib/rubocop/cop/style/word_array.rb +2 -2
  200. data/lib/rubocop/cop/style/zero_length_predicate.rb +6 -6
  201. data/lib/rubocop/cop/team.rb +15 -14
  202. data/lib/rubocop/cop/utils/format_string.rb +128 -0
  203. data/lib/rubocop/cop/variable_force/variable.rb +15 -2
  204. data/lib/rubocop/core_ext/string.rb +0 -24
  205. data/lib/rubocop/error.rb +23 -0
  206. data/lib/rubocop/formatter/clang_style_formatter.rb +8 -3
  207. data/lib/rubocop/formatter/emacs_style_formatter.rb +22 -9
  208. data/lib/rubocop/formatter/file_list_formatter.rb +1 -1
  209. data/lib/rubocop/formatter/formatter_set.rb +16 -15
  210. data/lib/rubocop/formatter/pacman_formatter.rb +80 -0
  211. data/lib/rubocop/formatter/simple_text_formatter.rb +16 -4
  212. data/lib/rubocop/formatter/tap_formatter.rb +17 -4
  213. data/lib/rubocop/magic_comment.rb +4 -0
  214. data/lib/rubocop/node_pattern.rb +2 -2
  215. data/lib/rubocop/options.rb +21 -17
  216. data/lib/rubocop/path_util.rb +1 -1
  217. data/lib/rubocop/processed_source.rb +6 -1
  218. data/lib/rubocop/rspec/cop_helper.rb +0 -1
  219. data/lib/rubocop/rspec/expect_offense.rb +4 -1
  220. data/lib/rubocop/rspec/shared_contexts.rb +12 -17
  221. data/lib/rubocop/rspec/support.rb +0 -1
  222. data/lib/rubocop/runner.rb +14 -25
  223. data/lib/rubocop/target_finder.rb +6 -4
  224. data/lib/rubocop/version.rb +1 -1
  225. data/lib/rubocop/yaml_duplication_checker.rb +8 -2
  226. metadata +17 -92
  227. data/lib/rubocop/cop/mixin/ignored_method_patterns.rb +0 -19
  228. data/lib/rubocop/cop/mixin/target_rails_version.rb +0 -16
  229. data/lib/rubocop/cop/rails/action_filter.rb +0 -117
  230. data/lib/rubocop/cop/rails/active_record_aliases.rb +0 -48
  231. data/lib/rubocop/cop/rails/active_record_override.rb +0 -82
  232. data/lib/rubocop/cop/rails/active_support_aliases.rb +0 -69
  233. data/lib/rubocop/cop/rails/application_job.rb +0 -40
  234. data/lib/rubocop/cop/rails/application_record.rb +0 -40
  235. data/lib/rubocop/cop/rails/assert_not.rb +0 -44
  236. data/lib/rubocop/cop/rails/belongs_to.rb +0 -102
  237. data/lib/rubocop/cop/rails/blank.rb +0 -164
  238. data/lib/rubocop/cop/rails/bulk_change_table.rb +0 -289
  239. data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +0 -91
  240. data/lib/rubocop/cop/rails/date.rb +0 -161
  241. data/lib/rubocop/cop/rails/delegate.rb +0 -132
  242. data/lib/rubocop/cop/rails/delegate_allow_blank.rb +0 -37
  243. data/lib/rubocop/cop/rails/dynamic_find_by.rb +0 -91
  244. data/lib/rubocop/cop/rails/enum_uniqueness.rb +0 -45
  245. data/lib/rubocop/cop/rails/environment_comparison.rb +0 -68
  246. data/lib/rubocop/cop/rails/exit.rb +0 -67
  247. data/lib/rubocop/cop/rails/file_path.rb +0 -108
  248. data/lib/rubocop/cop/rails/find_by.rb +0 -55
  249. data/lib/rubocop/cop/rails/find_each.rb +0 -51
  250. data/lib/rubocop/cop/rails/has_and_belongs_to_many.rb +0 -25
  251. data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +0 -106
  252. data/lib/rubocop/cop/rails/http_positional_arguments.rb +0 -117
  253. data/lib/rubocop/cop/rails/http_status.rb +0 -179
  254. data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +0 -94
  255. data/lib/rubocop/cop/rails/inverse_of.rb +0 -246
  256. data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +0 -175
  257. data/lib/rubocop/cop/rails/link_to_blank.rb +0 -98
  258. data/lib/rubocop/cop/rails/not_null_column.rb +0 -67
  259. data/lib/rubocop/cop/rails/output.rb +0 -49
  260. data/lib/rubocop/cop/rails/output_safety.rb +0 -99
  261. data/lib/rubocop/cop/rails/pluralization_grammar.rb +0 -107
  262. data/lib/rubocop/cop/rails/presence.rb +0 -124
  263. data/lib/rubocop/cop/rails/present.rb +0 -153
  264. data/lib/rubocop/cop/rails/read_write_attribute.rb +0 -74
  265. data/lib/rubocop/cop/rails/redundant_allow_nil.rb +0 -111
  266. data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +0 -136
  267. data/lib/rubocop/cop/rails/reflection_class_name.rb +0 -37
  268. data/lib/rubocop/cop/rails/refute_methods.rb +0 -76
  269. data/lib/rubocop/cop/rails/relative_date_constant.rb +0 -93
  270. data/lib/rubocop/cop/rails/request_referer.rb +0 -56
  271. data/lib/rubocop/cop/rails/reversible_migration.rb +0 -286
  272. data/lib/rubocop/cop/rails/safe_navigation.rb +0 -87
  273. data/lib/rubocop/cop/rails/save_bang.rb +0 -316
  274. data/lib/rubocop/cop/rails/scope_args.rb +0 -29
  275. data/lib/rubocop/cop/rails/skips_model_validations.rb +0 -87
  276. data/lib/rubocop/cop/rails/time_zone.rb +0 -238
  277. data/lib/rubocop/cop/rails/uniq_before_pluck.rb +0 -105
  278. data/lib/rubocop/cop/rails/unknown_env.rb +0 -63
  279. data/lib/rubocop/cop/rails/validation.rb +0 -109
  280. data/lib/rubocop/rspec/shared_examples.rb +0 -59
@@ -144,10 +144,6 @@ module RuboCop
144
144
  puts "Added inheritance from `#{AUTO_GENERATED_FILE}` in `#{DOTFILE}`."
145
145
  end
146
146
 
147
- def required_features
148
- resolver.required_features
149
- end
150
-
151
147
  private
152
148
 
153
149
  def find_project_dotfile(target_dir)
@@ -177,8 +173,8 @@ module RuboCop
177
173
 
178
174
  def existing_configuration(config_file)
179
175
  IO.read(config_file, encoding: Encoding::UTF_8)
180
- .sub(%r{^inherit_from: *[.\/\w]+}, '')
181
- .sub(%r{^inherit_from: *(\n *- *[.\/\w]+)+}, '')
176
+ .sub(/^inherit_from: *[^\n]+/, '')
177
+ .sub(/^inherit_from: *(\n *- *[^\n]+)+/, '')
182
178
  end
183
179
 
184
180
  def write_config_file(file_name, file_string, rubocop_yml_contents)
@@ -203,6 +199,8 @@ module RuboCop
203
199
  raise(TypeError, "Malformed configuration in #{absolute_path}")
204
200
  end
205
201
 
202
+ check_cop_config_value(hash)
203
+
206
204
  hash
207
205
  end
208
206
 
@@ -224,6 +222,22 @@ module RuboCop
224
222
  end
225
223
  end
226
224
 
225
+ def check_cop_config_value(hash, parent = nil)
226
+ hash.each do |key, value|
227
+ check_cop_config_value(value, key) if value.is_a?(Hash)
228
+
229
+ next unless %w[Enabled
230
+ Safe
231
+ SafeAutoCorrect
232
+ AutoCorrect].include?(key) && value.is_a?(String)
233
+
234
+ abort(
235
+ "Property #{Rainbow(key).yellow} of cop #{Rainbow(parent).yellow}" \
236
+ " is supposed to be a boolean and #{Rainbow(value).yellow} is not."
237
+ )
238
+ end
239
+ end
240
+
227
241
  # Read the specified file, or exit with a friendly, concise message on
228
242
  # stderr. Care is taken to use the standard OS exit code for a "file not
229
243
  # found" error.
@@ -244,11 +258,11 @@ module RuboCop
244
258
  yaml_code,
245
259
  permitted_classes: [Regexp, Symbol],
246
260
  permitted_symbols: [],
247
- aliases: false,
261
+ aliases: true,
248
262
  filename: filename
249
263
  )
250
264
  else
251
- YAML.safe_load(yaml_code, [Regexp, Symbol], [], false, filename)
265
+ YAML.safe_load(yaml_code, [Regexp, Symbol], [], true, filename)
252
266
  end
253
267
  end
254
268
  end
@@ -6,17 +6,9 @@ require 'pathname'
6
6
  module RuboCop
7
7
  # A help class for ConfigLoader that handles configuration resolution.
8
8
  class ConfigLoaderResolver
9
- attr_reader :required_features
10
-
11
- def initialize
12
- @required_features = []
13
- end
14
-
15
9
  def resolve_requires(path, hash)
16
10
  config_dir = File.dirname(path)
17
11
  Array(hash.delete('require')).each do |r|
18
- @required_features << r
19
-
20
12
  if r.start_with?('.')
21
13
  require(File.join(config_dir, r))
22
14
  else
@@ -81,7 +73,7 @@ module RuboCop
81
73
 
82
74
  opts = { inherit_mode: config['inherit_mode'] || {},
83
75
  unset_nil: unset_nil }
84
- Config.new(merge(default_configuration, config, opts), config_file)
76
+ Config.new(merge(default_configuration, config, **opts), config_file)
85
77
  end
86
78
 
87
79
  # Return a recursive merge of two hashes. That is, a normal hash merge,
@@ -100,7 +92,7 @@ module RuboCop
100
92
  elsif should_union?(base_hash, key, opts[:inherit_mode])
101
93
  result[key] = base_hash[key] | derived_hash[key]
102
94
  elsif opts[:debug]
103
- warn_on_duplicate_setting(base_hash, derived_hash, key, opts)
95
+ warn_on_duplicate_setting(base_hash, derived_hash, key, **opts)
104
96
  end
105
97
  end
106
98
  result
@@ -172,12 +164,6 @@ module RuboCop
172
164
  def handle_disabled_by_default(config, new_default_configuration)
173
165
  department_config = config.to_hash.reject { |cop| cop.include?('/') }
174
166
  department_config.each do |dept, dept_params|
175
- # Rails is always disabled by default and the department's Enabled flag
176
- # works like the --rails command line option, which is that when
177
- # AllCops:DisabledByDefault is true, each Rails cop must still be
178
- # explicitly mentioned in user configuration in order to be enabled.
179
- next if dept == 'Rails'
180
-
181
167
  next unless dept_params['Enabled']
182
168
 
183
169
  new_default_configuration.each do |cop, params|
@@ -0,0 +1,213 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ # This class handles obsolete configuration.
5
+ class ConfigObsoletion
6
+ RENAMED_COPS = {
7
+ 'Style/SingleSpaceBeforeFirstArg' => 'Layout/SpaceBeforeFirstArg',
8
+ 'Style/MethodCallParentheses' => 'Style/MethodCallWithoutArgsParentheses',
9
+ 'Style/DeprecatedHashMethods' => 'Style/PreferredHashMethods',
10
+ 'Style/OpMethod' => 'Naming/BinaryOperatorParameterName',
11
+ 'Layout/FirstParameterIndentation' => 'Layout/IndentFirstArgument',
12
+ 'Layout/IndentArray' => 'Layout/IndentFirstArrayElement',
13
+ 'Layout/IndentHash' => 'Layout/IndentFirstHashElement'
14
+ }.map do |old_name, new_name|
15
+ [old_name, "The `#{old_name}` cop has been renamed to `#{new_name}`."]
16
+ end
17
+
18
+ MOVED_COPS = {
19
+ 'Security' => 'Lint/Eval',
20
+ 'Naming' => %w[Style/ClassAndModuleCamelCase Style/ConstantName
21
+ Style/FileName Style/MethodName Style/PredicateName
22
+ Style/VariableName Style/VariableNumber
23
+ Style/AccessorMethodName Style/AsciiIdentifiers],
24
+ 'Layout' => %w[Lint/BlockAlignment Lint/EndAlignment
25
+ Lint/DefEndAlignment],
26
+ 'Lint' => 'Style/FlipFlop'
27
+ }.map do |new_department, old_names|
28
+ Array(old_names).map do |old_name|
29
+ [old_name, "The `#{old_name}` cop has been moved to " \
30
+ "`#{new_department}/#{old_name.split('/').last}`."]
31
+ end
32
+ end
33
+
34
+ REMOVED_COPS = {
35
+ 'Rails/DefaultScope' => nil,
36
+ 'Layout/SpaceAfterControlKeyword' => 'Layout/SpaceAroundKeyword',
37
+ 'Layout/SpaceBeforeModifierKeyword' => 'Layout/SpaceAroundKeyword',
38
+ 'Style/SpaceAfterControlKeyword' => 'Layout/SpaceAroundKeyword',
39
+ 'Style/SpaceBeforeModifierKeyword' => 'Layout/SpaceAroundKeyword',
40
+ 'Style/TrailingComma' => 'Style/TrailingCommaInArguments, ' \
41
+ 'Style/TrailingCommaInArrayLiteral, and/or ' \
42
+ 'Style/TrailingCommaInHashLiteral',
43
+ 'Style/TrailingCommaInLiteral' => 'Style/TrailingCommaInArrayLiteral ' \
44
+ 'and/or ' \
45
+ 'Style/TrailingCommaInHashLiteral',
46
+ 'Lint/RescueWithoutErrorClass' => 'Style/RescueStandardError'
47
+ }.map do |old_name, other_cops|
48
+ if other_cops
49
+ more = ". Please use #{other_cops} instead".gsub(%r{[A-Z]\w+/\w+},
50
+ '`\&`')
51
+ end
52
+ [old_name, "The `#{old_name}` cop has been removed#{more}."]
53
+ end
54
+
55
+ REMOVED_COPS_WITH_REASON = {
56
+ 'Lint/InvalidCharacterLiteral' => 'it was never being actually triggered',
57
+ 'Lint/SpaceBeforeFirstArg' =>
58
+ 'it was a duplicate of `Layout/SpaceBeforeFirstArg`. Please use ' \
59
+ '`Layout/SpaceBeforeFirstArg` instead'
60
+ }.map do |cop_name, reason|
61
+ [cop_name, "The `#{cop_name}` cop has been removed since #{reason}."]
62
+ end
63
+
64
+ SPLIT_COPS = {
65
+ 'Style/MethodMissing' =>
66
+ 'The `Style/MethodMissing` cop has been split into ' \
67
+ '`Style/MethodMissingSuper` and `Style/MissingRespondToMissing`.'
68
+ }.to_a
69
+
70
+ OBSOLETE_COPS = Hash[*(RENAMED_COPS + MOVED_COPS + REMOVED_COPS +
71
+ REMOVED_COPS_WITH_REASON + SPLIT_COPS).flatten]
72
+
73
+ OBSOLETE_PARAMETERS = [
74
+ {
75
+ cops: %w[Layout/SpaceAroundOperators Style/SpaceAroundOperators],
76
+ parameters: 'MultiSpaceAllowedForOperators',
77
+ alternative: 'If your intention was to allow extra spaces for ' \
78
+ 'alignment, please use AllowForAlignment: true instead.'
79
+ },
80
+ {
81
+ cops: 'Style/Encoding',
82
+ parameters: %w[EnforcedStyle SupportedStyles
83
+ AutoCorrectEncodingComment],
84
+ alternative: 'Style/Encoding no longer supports styles. ' \
85
+ 'The "never" behavior is always assumed.'
86
+ },
87
+ {
88
+ cops: 'Style/IfUnlessModifier',
89
+ parameters: 'MaxLineLength',
90
+ alternative: '`Style/IfUnlessModifier: MaxLineLength` has been ' \
91
+ 'removed. Use `Metrics/LineLength: Max` instead'
92
+ },
93
+ {
94
+ cops: 'Style/WhileUntilModifier',
95
+ parameters: 'MaxLineLength',
96
+ alternative: '`Style/WhileUntilModifier: MaxLineLength` has been ' \
97
+ 'removed. Use `Metrics/LineLength: Max` instead'
98
+ },
99
+ {
100
+ cops: 'AllCops',
101
+ parameters: 'RunRailsCops',
102
+ alternative: "Use the following configuration instead:\n" \
103
+ "Rails:\n Enabled: true"
104
+ },
105
+ {
106
+ cops: 'Layout/CaseIndentation',
107
+ parameters: 'IndentWhenRelativeTo',
108
+ alternative: '`IndentWhenRelativeTo` has been renamed to ' \
109
+ '`EnforcedStyle`'
110
+ },
111
+ {
112
+ cops: %w[Lint/BlockAlignment Layout/BlockAlignment Lint/EndAlignment
113
+ Layout/EndAlignment Lint/DefEndAlignment
114
+ Layout/DefEndAlignment],
115
+ parameters: 'AlignWith',
116
+ alternative: '`AlignWith` has been renamed to `EnforcedStyleAlignWith`'
117
+ },
118
+ {
119
+ cops: 'Rails/UniqBeforePluck',
120
+ parameters: 'EnforcedMode',
121
+ alternative: '`EnforcedMode` has been renamed to `EnforcedStyle`'
122
+ },
123
+ {
124
+ cops: 'Style/MethodCallWithArgsParentheses',
125
+ parameters: 'IgnoredMethodPatterns',
126
+ alternative: '`IgnoredMethodPatterns` has been renamed to ' \
127
+ '`IgnoredPatterns`'
128
+ },
129
+ {
130
+ cops: %w[Performance/Count Performance/Detect],
131
+ parameters: 'SafeMode',
132
+ alternative: '`SafeMode` has been removed. ' \
133
+ 'Use `SafeAutoCorrect` instead.'
134
+ }
135
+ ].freeze
136
+
137
+ OBSOLETE_ENFORCED_STYLES = [
138
+ {
139
+ cop: 'Layout/IndentationConsistency',
140
+ parameter: 'EnforcedStyle',
141
+ enforced_style: 'rails',
142
+ alternative: '`EnforcedStyle: rails` has been renamed to ' \
143
+ '`EnforcedStyle: indented_internal_methods`'
144
+ }
145
+ ].freeze
146
+
147
+ def initialize(config)
148
+ @config = config
149
+ end
150
+
151
+ def reject_obsolete_cops_and_parameters
152
+ messages = [obsolete_cops, obsolete_parameters,
153
+ obsolete_enforced_style].flatten.compact
154
+ return if messages.empty?
155
+
156
+ raise ValidationError, messages.join("\n")
157
+ end
158
+
159
+ private
160
+
161
+ def obsolete_cops
162
+ OBSOLETE_COPS.map do |cop_name, message|
163
+ next unless @config.key?(cop_name) ||
164
+ @config.key?(Cop::Badge.parse(cop_name).cop_name)
165
+
166
+ message + "\n(obsolete configuration found in " \
167
+ "#{smart_loaded_path}, please update it)"
168
+ end
169
+ end
170
+
171
+ def obsolete_enforced_style
172
+ OBSOLETE_ENFORCED_STYLES.map do |params|
173
+ obsolete_enforced_style_message(params[:cop], params[:parameter],
174
+ params[:enforced_style],
175
+ params[:alternative])
176
+ end
177
+ end
178
+
179
+ def obsolete_enforced_style_message(cop, param, enforced_style, alternative)
180
+ style = @config[cop]&.detect { |key, _| key.start_with?(param) }
181
+
182
+ return unless style && style[1] == enforced_style
183
+
184
+ "obsolete `#{param}: #{enforced_style}` (for #{cop}) found in " \
185
+ "#{smart_loaded_path}\n#{alternative}"
186
+ end
187
+
188
+ def obsolete_parameters
189
+ OBSOLETE_PARAMETERS.map do |params|
190
+ obsolete_parameter_message(params[:cops], params[:parameters],
191
+ params[:alternative])
192
+ end
193
+ end
194
+
195
+ def obsolete_parameter_message(cops, parameters, alternative)
196
+ Array(cops).map do |cop|
197
+ obsolete_parameters = Array(parameters).select do |param|
198
+ @config[cop]&.key?(param)
199
+ end
200
+ next if obsolete_parameters.empty?
201
+
202
+ obsolete_parameters.map do |parameter|
203
+ "obsolete parameter #{parameter} (for #{cop}) found in " \
204
+ "#{smart_loaded_path}\n#{alternative}"
205
+ end
206
+ end
207
+ end
208
+
209
+ def smart_loaded_path
210
+ PathUtil.smart_path(@config.loaded_path)
211
+ end
212
+ end
213
+ end
@@ -0,0 +1,239 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pathname'
4
+
5
+ module RuboCop
6
+ # Handles validation of configuration, for example cop names, parameter
7
+ # names, and Ruby versions.
8
+ class ConfigValidator
9
+ extend Forwardable
10
+
11
+ COMMON_PARAMS = %w[Exclude Include Severity inherit_mode
12
+ AutoCorrect StyleGuide Details].freeze
13
+ INTERNAL_PARAMS = %w[Description StyleGuide VersionAdded
14
+ VersionChanged Reference Safe SafeAutoCorrect].freeze
15
+
16
+ # 2.3 is the oldest officially supported Ruby version.
17
+ DEFAULT_RUBY_VERSION = 2.3
18
+ KNOWN_RUBIES = [2.3, 2.4, 2.5, 2.6, 2.7].freeze
19
+ OBSOLETE_RUBIES = {
20
+ 1.9 => '0.50', 2.0 => '0.50', 2.1 => '0.58', 2.2 => '0.69'
21
+ }.freeze
22
+ RUBY_VERSION_FILENAME = '.ruby-version'
23
+
24
+ def_delegators :@config,
25
+ :smart_loaded_path, :for_all_cops, :find_file_upwards,
26
+ :base_dir_for_path_parameters, :bundler_lock_file_path
27
+
28
+ def initialize(config)
29
+ @config = config
30
+ @config_obsoletion = ConfigObsoletion.new(config)
31
+ end
32
+
33
+ def validate
34
+ # Don't validate RuboCop's own files. Avoids infinite recursion.
35
+ base_config_path = File.expand_path(File.join(ConfigLoader::RUBOCOP_HOME,
36
+ 'config'))
37
+ return if File.expand_path(@config.loaded_path)
38
+ .start_with?(base_config_path)
39
+
40
+ valid_cop_names, invalid_cop_names = @config.keys.partition do |key|
41
+ ConfigLoader.default_configuration.key?(key)
42
+ end
43
+
44
+ @config_obsoletion.reject_obsolete_cops_and_parameters
45
+
46
+ warn_about_unrecognized_cops(invalid_cop_names)
47
+ check_target_ruby
48
+ validate_parameter_names(valid_cop_names)
49
+ validate_enforced_styles(valid_cop_names)
50
+ validate_syntax_cop
51
+ reject_mutually_exclusive_defaults
52
+ end
53
+
54
+ def target_ruby_version
55
+ @target_ruby_version ||= begin
56
+ if for_all_cops['TargetRubyVersion']
57
+ @target_ruby_version_source = :rubocop_yml
58
+
59
+ for_all_cops['TargetRubyVersion'].to_f
60
+ elsif target_ruby_version_from_version_file
61
+ @target_ruby_version_source = :ruby_version_file
62
+
63
+ target_ruby_version_from_version_file
64
+ elsif target_ruby_version_from_bundler_lock_file
65
+ @target_ruby_version_source = :bundler_lock_file
66
+
67
+ target_ruby_version_from_bundler_lock_file
68
+ else
69
+ DEFAULT_RUBY_VERSION
70
+ end
71
+ end
72
+ end
73
+
74
+ def validate_section_presence(name)
75
+ return unless @config.key?(name) && @config[name].nil?
76
+
77
+ raise ValidationError,
78
+ "empty section #{name} found in #{smart_loaded_path}"
79
+ end
80
+
81
+ private
82
+
83
+ def check_target_ruby
84
+ return if KNOWN_RUBIES.include?(target_ruby_version)
85
+
86
+ msg = if OBSOLETE_RUBIES.include?(target_ruby_version)
87
+ "RuboCop found unsupported Ruby version #{target_ruby_version} " \
88
+ "in #{target_ruby_source}. #{target_ruby_version}-compatible " \
89
+ 'analysis was dropped after version ' \
90
+ "#{OBSOLETE_RUBIES[target_ruby_version]}."
91
+ else
92
+ 'RuboCop found unknown Ruby version ' \
93
+ "#{target_ruby_version.inspect} in #{target_ruby_source}."
94
+ end
95
+
96
+ msg += "\nSupported versions: #{KNOWN_RUBIES.join(', ')}"
97
+
98
+ raise ValidationError, msg
99
+ end
100
+
101
+ def warn_about_unrecognized_cops(invalid_cop_names)
102
+ invalid_cop_names.each do |name|
103
+ # There could be a custom cop with this name. If so, don't warn
104
+ next if Cop::Cop.registry.contains_cop_matching?([name])
105
+
106
+ # Special case for inherit_mode, which is a directive that we keep in
107
+ # the configuration (even though it's not a cop), because it's easier
108
+ # to do so than to pass the value around to various methods.
109
+ next if name == 'inherit_mode'
110
+
111
+ warn Rainbow("Warning: unrecognized cop #{name} found in " \
112
+ "#{smart_loaded_path}").yellow
113
+ end
114
+ end
115
+
116
+ def validate_syntax_cop
117
+ syntax_config = @config['Lint/Syntax']
118
+ default_config = ConfigLoader.default_configuration['Lint/Syntax']
119
+
120
+ return unless syntax_config &&
121
+ default_config.merge(syntax_config) != default_config
122
+
123
+ raise ValidationError,
124
+ "configuration for Syntax cop found in #{smart_loaded_path}\n" \
125
+ 'It\'s not possible to disable this cop.'
126
+ end
127
+
128
+ def validate_parameter_names(valid_cop_names)
129
+ valid_cop_names.each do |name|
130
+ validate_section_presence(name)
131
+ default_config = ConfigLoader.default_configuration[name]
132
+
133
+ @config[name].each_key do |param|
134
+ next if COMMON_PARAMS.include?(param) || default_config.key?(param)
135
+
136
+ message =
137
+ "Warning: #{name} does not support #{param} parameter.\n\n" \
138
+ "Supported parameters are:\n\n" \
139
+ " - #{(default_config.keys - INTERNAL_PARAMS).join("\n - ")}\n"
140
+
141
+ warn Rainbow(message).yellow.to_s
142
+ end
143
+ end
144
+ end
145
+
146
+ def validate_enforced_styles(valid_cop_names)
147
+ valid_cop_names.each do |name|
148
+ styles = @config[name].select { |key, _| key.start_with?('Enforced') }
149
+
150
+ styles.each do |style_name, style|
151
+ supported_key = RuboCop::Cop::Util.to_supported_styles(style_name)
152
+ valid = ConfigLoader.default_configuration[name][supported_key]
153
+
154
+ next unless valid
155
+ next if valid.include?(style)
156
+ next if validate_support_and_has_list(name, style, valid)
157
+
158
+ msg = "invalid #{style_name} '#{style}' for #{name} found in " \
159
+ "#{smart_loaded_path}\n" \
160
+ "Valid choices are: #{valid.join(', ')}"
161
+ raise ValidationError, msg
162
+ end
163
+ end
164
+ end
165
+
166
+ def validate_support_and_has_list(name, formats, valid)
167
+ ConfigLoader.default_configuration[name]['AllowMultipleStyles'] &&
168
+ formats.is_a?(Array) &&
169
+ formats.all? { |format| valid.include?(format) }
170
+ end
171
+
172
+ def target_ruby_source
173
+ case @target_ruby_version_source
174
+ when :ruby_version_file
175
+ "`#{RUBY_VERSION_FILENAME}`"
176
+ when :bundler_lock_file
177
+ "`#{bundler_lock_file_path}`"
178
+ when :rubocop_yml
179
+ "`TargetRubyVersion` parameter (in #{smart_loaded_path})"
180
+ end
181
+ end
182
+
183
+ def ruby_version_file
184
+ @ruby_version_file ||=
185
+ find_file_upwards(RUBY_VERSION_FILENAME, base_dir_for_path_parameters)
186
+ end
187
+
188
+ def target_ruby_version_from_version_file
189
+ file = ruby_version_file
190
+ return unless file && File.file?(file)
191
+
192
+ @target_ruby_version_from_version_file ||=
193
+ File.read(file).match(/\A(ruby-)?(?<version>\d+\.\d+)/) do |md|
194
+ md[:version].to_f
195
+ end
196
+ end
197
+
198
+ def target_ruby_version_from_bundler_lock_file
199
+ @target_ruby_version_from_bundler_lock_file ||=
200
+ read_ruby_version_from_bundler_lock_file
201
+ end
202
+
203
+ def read_ruby_version_from_bundler_lock_file
204
+ lock_file_path = bundler_lock_file_path
205
+ return nil unless lock_file_path
206
+
207
+ in_ruby_section = false
208
+ File.foreach(lock_file_path) do |line|
209
+ # If ruby is in Gemfile.lock or gems.lock, there should be two lines
210
+ # towards the bottom of the file that look like:
211
+ # RUBY VERSION
212
+ # ruby W.X.YpZ
213
+ # We ultimately want to match the "ruby W.X.Y.pZ" line, but there's
214
+ # extra logic to make sure we only start looking once we've seen the
215
+ # "RUBY VERSION" line.
216
+ in_ruby_section ||= line.match(/^\s*RUBY\s*VERSION\s*$/)
217
+ next unless in_ruby_section
218
+
219
+ # We currently only allow this feature to work with MRI ruby. If jruby
220
+ # (or something else) is used by the project, it's lock file will have a
221
+ # line that looks like:
222
+ # RUBY VERSION
223
+ # ruby W.X.YpZ (jruby x.x.x.x)
224
+ # The regex won't match in this situation.
225
+ result = line.match(/^\s*ruby\s+(\d+\.\d+)[p.\d]*\s*$/)
226
+ return result.captures.first.to_f if result
227
+ end
228
+ end
229
+
230
+ def reject_mutually_exclusive_defaults
231
+ disabled_by_default = for_all_cops['DisabledByDefault']
232
+ enabled_by_default = for_all_cops['EnabledByDefault']
233
+ return unless disabled_by_default && enabled_by_default
234
+
235
+ msg = 'Cops cannot be both enabled by default and disabled by default'
236
+ raise ValidationError, msg
237
+ end
238
+ end
239
+ end