rubocop 0.52.1 → 0.53.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (292) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +2 -2
  4. data/config/default.yml +118 -46
  5. data/config/disabled.yml +8 -8
  6. data/config/enabled.yml +84 -28
  7. data/lib/rubocop.rb +28 -8
  8. data/lib/rubocop/ast/builder.rb +35 -37
  9. data/lib/rubocop/ast/node.rb +16 -1
  10. data/lib/rubocop/ast/node/and_node.rb +0 -8
  11. data/lib/rubocop/ast/node/block_node.rb +1 -9
  12. data/lib/rubocop/ast/node/case_node.rb +0 -8
  13. data/lib/rubocop/ast/node/ensure_node.rb +0 -8
  14. data/lib/rubocop/ast/node/for_node.rb +0 -8
  15. data/lib/rubocop/ast/node/or_node.rb +0 -8
  16. data/lib/rubocop/ast/node/pair_node.rb +0 -8
  17. data/lib/rubocop/ast/node/resbody_node.rb +0 -8
  18. data/lib/rubocop/ast/node/send_node.rb +0 -8
  19. data/lib/rubocop/ast/node/symbol_node.rb +0 -8
  20. data/lib/rubocop/ast/node/until_node.rb +0 -8
  21. data/lib/rubocop/ast/node/when_node.rb +0 -8
  22. data/lib/rubocop/ast/node/while_node.rb +0 -8
  23. data/lib/rubocop/cli.rb +17 -7
  24. data/lib/rubocop/comment_config.rb +24 -3
  25. data/lib/rubocop/config.rb +75 -6
  26. data/lib/rubocop/config_loader.rb +18 -28
  27. data/lib/rubocop/config_loader_resolver.rb +61 -9
  28. data/lib/rubocop/cop/bundler/duplicated_gem.rb +3 -1
  29. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +4 -2
  30. data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -1
  31. data/lib/rubocop/cop/commissioner.rb +2 -2
  32. data/lib/rubocop/cop/cop.rb +4 -0
  33. data/lib/rubocop/cop/corrector.rb +11 -1
  34. data/lib/rubocop/cop/correctors/alignment_corrector.rb +3 -6
  35. data/lib/rubocop/cop/correctors/line_break_corrector.rb +59 -0
  36. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +1 -1
  37. data/lib/rubocop/cop/correctors/space_corrector.rb +13 -0
  38. data/lib/rubocop/cop/correctors/unused_arg_corrector.rb +1 -1
  39. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +3 -1
  40. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -1
  41. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +3 -5
  42. data/lib/rubocop/cop/generator.rb +29 -8
  43. data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +2 -0
  44. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +2 -0
  45. data/lib/rubocop/cop/layout/align_hash.rb +106 -37
  46. data/lib/rubocop/cop/{lint → layout}/block_alignment.rb +8 -5
  47. data/lib/rubocop/cop/layout/block_end_newline.rb +7 -17
  48. data/lib/rubocop/cop/layout/case_indentation.rb +1 -0
  49. data/lib/rubocop/cop/layout/class_structure.rb +6 -7
  50. data/lib/rubocop/cop/layout/comment_indentation.rb +1 -1
  51. data/lib/rubocop/cop/{lint → layout}/condition_position.rb +3 -3
  52. data/lib/rubocop/cop/{lint → layout}/def_end_alignment.rb +2 -1
  53. data/lib/rubocop/cop/layout/else_alignment.rb +1 -1
  54. data/lib/rubocop/cop/layout/empty_comment.rb +140 -0
  55. data/lib/rubocop/cop/layout/empty_line_after_magic_comment.rb +2 -0
  56. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +2 -0
  57. data/lib/rubocop/cop/layout/empty_lines.rb +3 -1
  58. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +7 -5
  59. data/lib/rubocop/cop/layout/empty_lines_around_arguments.rb +20 -10
  60. data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +20 -0
  61. data/lib/rubocop/cop/{lint → layout}/end_alignment.rb +37 -6
  62. data/lib/rubocop/cop/layout/end_of_line.rb +1 -0
  63. data/lib/rubocop/cop/layout/extra_spacing.rb +30 -37
  64. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -0
  65. data/lib/rubocop/cop/layout/indent_heredoc.rb +38 -2
  66. data/lib/rubocop/cop/layout/indentation_consistency.rb +105 -1
  67. data/lib/rubocop/cop/layout/indentation_width.rb +4 -3
  68. data/lib/rubocop/cop/layout/initial_indentation.rb +15 -1
  69. data/lib/rubocop/cop/layout/leading_comment_space.rb +4 -2
  70. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -0
  71. data/lib/rubocop/cop/layout/multiline_block_layout.rb +2 -0
  72. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +62 -29
  73. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +1 -1
  74. data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +74 -33
  75. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +16 -2
  76. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +3 -1
  77. data/lib/rubocop/cop/layout/space_after_method_name.rb +2 -0
  78. data/lib/rubocop/cop/layout/space_after_not.rb +2 -0
  79. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +1 -0
  80. data/lib/rubocop/cop/layout/space_around_equals_in_parameter_default.rb +15 -2
  81. data/lib/rubocop/cop/layout/space_around_operators.rb +15 -13
  82. data/lib/rubocop/cop/layout/space_before_block_braces.rb +13 -1
  83. data/lib/rubocop/cop/layout/space_before_comment.rb +6 -4
  84. data/lib/rubocop/cop/layout/space_before_first_arg.rb +1 -0
  85. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +1 -0
  86. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +30 -45
  87. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +3 -2
  88. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +48 -18
  89. data/lib/rubocop/cop/layout/space_inside_parens.rb +8 -7
  90. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +57 -11
  91. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +1 -0
  92. data/lib/rubocop/cop/layout/tab.rb +42 -16
  93. data/lib/rubocop/cop/layout/trailing_blank_lines.rb +46 -13
  94. data/lib/rubocop/cop/layout/trailing_whitespace.rb +12 -0
  95. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +5 -3
  96. data/lib/rubocop/cop/lint/big_decimal_new.rb +44 -0
  97. data/lib/rubocop/cop/lint/boolean_symbol.rb +2 -2
  98. data/lib/rubocop/cop/lint/circular_argument_reference.rb +2 -2
  99. data/lib/rubocop/cop/lint/debugger.rb +2 -2
  100. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +5 -4
  101. data/lib/rubocop/cop/lint/duplicate_methods.rb +20 -9
  102. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +4 -3
  103. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +16 -10
  104. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +5 -4
  105. data/lib/rubocop/cop/lint/inherit_exception.rb +2 -2
  106. data/lib/rubocop/cop/lint/interpolation_check.rb +4 -3
  107. data/lib/rubocop/cop/lint/literal_as_condition.rb +2 -2
  108. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +2 -0
  109. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +7 -5
  110. data/lib/rubocop/cop/lint/nested_percent_literal.rb +1 -1
  111. data/lib/rubocop/cop/lint/number_conversion.rb +59 -0
  112. data/lib/rubocop/cop/lint/ordered_magic_comments.rb +86 -0
  113. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +2 -0
  114. data/lib/rubocop/cop/lint/percent_string_array.rb +0 -2
  115. data/lib/rubocop/cop/lint/rand_one.rb +2 -2
  116. data/lib/rubocop/cop/lint/redundant_with_index.rb +2 -0
  117. data/lib/rubocop/cop/lint/redundant_with_object.rb +2 -0
  118. data/lib/rubocop/cop/lint/require_parentheses.rb +2 -0
  119. data/lib/rubocop/cop/lint/rescue_type.rb +6 -3
  120. data/lib/rubocop/cop/lint/return_in_void_context.rb +2 -2
  121. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +17 -21
  122. data/lib/rubocop/cop/lint/script_permission.rb +30 -10
  123. data/lib/rubocop/cop/lint/shadowed_argument.rb +3 -3
  124. data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -0
  125. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +2 -2
  126. data/lib/rubocop/cop/lint/unified_integer.rb +2 -2
  127. data/lib/rubocop/cop/lint/{unneeded_disable.rb → unneeded_cop_disable_directive.rb} +13 -7
  128. data/lib/rubocop/cop/lint/unneeded_cop_enable_directive.rb +97 -0
  129. data/lib/rubocop/cop/lint/unneeded_require_statement.rb +1 -0
  130. data/lib/rubocop/cop/lint/unreachable_code.rb +3 -3
  131. data/lib/rubocop/cop/lint/uri_escape_unescape.rb +11 -10
  132. data/lib/rubocop/cop/lint/useless_access_modifier.rb +7 -5
  133. data/lib/rubocop/cop/lint/useless_assignment.rb +2 -2
  134. data/lib/rubocop/cop/lint/useless_setter_call.rb +2 -2
  135. data/lib/rubocop/cop/lint/void.rb +49 -10
  136. data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
  137. data/lib/rubocop/cop/metrics/line_length.rb +5 -2
  138. data/lib/rubocop/cop/mixin/alignment.rb +4 -0
  139. data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +1 -1
  140. data/lib/rubocop/cop/mixin/def_node.rb +4 -0
  141. data/lib/rubocop/cop/mixin/documentation_comment.rb +11 -3
  142. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +12 -2
  143. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +20 -1
  144. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +4 -0
  145. data/lib/rubocop/cop/mixin/hash_alignment.rb +2 -2
  146. data/lib/rubocop/cop/mixin/match_range.rb +2 -0
  147. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +6 -0
  148. data/lib/rubocop/cop/mixin/nil_methods.rb +19 -0
  149. data/lib/rubocop/cop/mixin/percent_literal.rb +57 -9
  150. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +6 -5
  151. data/lib/rubocop/cop/mixin/range_help.rb +102 -0
  152. data/lib/rubocop/cop/mixin/rescue_node.rb +1 -1
  153. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +8 -7
  154. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +11 -9
  155. data/lib/rubocop/cop/mixin/statement_modifier.rb +3 -10
  156. data/lib/rubocop/cop/mixin/surrounding_space.rb +38 -8
  157. data/lib/rubocop/cop/mixin/trailing_body.rb +26 -0
  158. data/lib/rubocop/cop/mixin/trailing_comma.rb +15 -3
  159. data/lib/rubocop/cop/mixin/uncommunicative_name.rb +104 -0
  160. data/lib/rubocop/cop/naming/ascii_identifiers.rb +3 -1
  161. data/lib/rubocop/cop/naming/file_name.rb +5 -10
  162. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +76 -0
  163. data/lib/rubocop/cop/naming/uncommunicative_block_param_name.rb +48 -0
  164. data/lib/rubocop/cop/naming/uncommunicative_method_param_name.rb +57 -0
  165. data/lib/rubocop/cop/offense.rb +3 -2
  166. data/lib/rubocop/cop/performance/case_when_splat.rb +1 -0
  167. data/lib/rubocop/cop/performance/casecmp.rb +17 -8
  168. data/lib/rubocop/cop/performance/compare_with_block.rb +2 -0
  169. data/lib/rubocop/cop/performance/count.rb +1 -0
  170. data/lib/rubocop/cop/performance/fixed_size.rb +41 -0
  171. data/lib/rubocop/cop/performance/flat_map.rb +2 -0
  172. data/lib/rubocop/cop/performance/lstrip_rstrip.rb +2 -0
  173. data/lib/rubocop/cop/performance/redundant_merge.rb +1 -1
  174. data/lib/rubocop/cop/performance/redundant_sort_by.rb +2 -0
  175. data/lib/rubocop/cop/performance/regexp_match.rb +4 -0
  176. data/lib/rubocop/cop/performance/reverse_each.rb +2 -0
  177. data/lib/rubocop/cop/performance/string_replacement.rb +2 -0
  178. data/lib/rubocop/cop/rails/active_record_aliases.rb +46 -0
  179. data/lib/rubocop/cop/rails/blank.rb +3 -3
  180. data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +6 -0
  181. data/lib/rubocop/cop/rails/delegate.rb +6 -6
  182. data/lib/rubocop/cop/rails/file_path.rb +7 -1
  183. data/lib/rubocop/cop/rails/find_by.rb +2 -0
  184. data/lib/rubocop/cop/rails/http_positional_arguments.rb +17 -5
  185. data/lib/rubocop/cop/rails/inverse_of.rb +21 -2
  186. data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +45 -9
  187. data/lib/rubocop/cop/rails/presence.rb +8 -2
  188. data/lib/rubocop/cop/rails/present.rb +5 -5
  189. data/lib/rubocop/cop/rails/read_write_attribute.rb +4 -3
  190. data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +1 -0
  191. data/lib/rubocop/cop/rails/relative_date_constant.rb +4 -3
  192. data/lib/rubocop/cop/rails/request_referer.rb +3 -2
  193. data/lib/rubocop/cop/rails/reversible_migration.rb +9 -8
  194. data/lib/rubocop/cop/rails/safe_navigation.rb +3 -2
  195. data/lib/rubocop/cop/rails/save_bang.rb +11 -12
  196. data/lib/rubocop/cop/rails/skips_model_validations.rb +2 -2
  197. data/lib/rubocop/cop/rails/time_zone.rb +38 -16
  198. data/lib/rubocop/cop/rails/uniq_before_pluck.rb +26 -16
  199. data/lib/rubocop/cop/rails/validation.rb +30 -2
  200. data/lib/rubocop/cop/security/open.rb +48 -0
  201. data/lib/rubocop/cop/style/and_or.rb +1 -0
  202. data/lib/rubocop/cop/style/ascii_comments.rb +3 -1
  203. data/lib/rubocop/cop/style/attr.rb +2 -0
  204. data/lib/rubocop/cop/style/block_comments.rb +3 -1
  205. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +2 -5
  206. data/lib/rubocop/cop/style/class_and_module_children.rb +1 -0
  207. data/lib/rubocop/cop/style/class_vars.rb +23 -0
  208. data/lib/rubocop/cop/style/colon_method_call.rb +1 -2
  209. data/lib/rubocop/cop/style/comment_annotation.rb +6 -4
  210. data/lib/rubocop/cop/style/commented_keyword.rb +3 -1
  211. data/lib/rubocop/cop/style/conditional_assignment.rb +1 -1
  212. data/lib/rubocop/cop/style/copyright.rb +3 -1
  213. data/lib/rubocop/cop/style/each_with_object.rb +15 -1
  214. data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -0
  215. data/lib/rubocop/cop/style/empty_case_condition.rb +2 -0
  216. data/lib/rubocop/cop/style/empty_else.rb +9 -5
  217. data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -0
  218. data/lib/rubocop/cop/style/empty_line_after_guard_clause.rb +80 -0
  219. data/lib/rubocop/cop/style/empty_literal.rb +1 -0
  220. data/lib/rubocop/cop/style/encoding.rb +2 -0
  221. data/lib/rubocop/cop/style/expand_path_arguments.rb +194 -0
  222. data/lib/rubocop/cop/style/for.rb +33 -0
  223. data/lib/rubocop/cop/style/format_string.rb +1 -1
  224. data/lib/rubocop/cop/style/format_string_token.rb +4 -5
  225. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +2 -1
  226. data/lib/rubocop/cop/style/hash_syntax.rb +1 -0
  227. data/lib/rubocop/cop/style/if_unless_modifier.rb +1 -1
  228. data/lib/rubocop/cop/style/inline_comment.rb +1 -1
  229. data/lib/rubocop/cop/style/lambda.rb +1 -1
  230. data/lib/rubocop/cop/style/line_end_concatenation.rb +2 -0
  231. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +2 -0
  232. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -0
  233. data/lib/rubocop/cop/style/missing_else.rb +72 -7
  234. data/lib/rubocop/cop/style/mixin_usage.rb +3 -5
  235. data/lib/rubocop/cop/style/module_function.rb +10 -0
  236. data/lib/rubocop/cop/style/multiline_block_chain.rb +2 -0
  237. data/lib/rubocop/cop/style/multiline_if_then.rb +1 -0
  238. data/lib/rubocop/cop/style/nested_modifier.rb +2 -0
  239. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +2 -0
  240. data/lib/rubocop/cop/style/next.rb +1 -0
  241. data/lib/rubocop/cop/style/not.rb +2 -0
  242. data/lib/rubocop/cop/style/numeric_literals.rb +1 -1
  243. data/lib/rubocop/cop/style/one_line_conditional.rb +2 -2
  244. data/lib/rubocop/cop/style/redundant_exception.rb +8 -3
  245. data/lib/rubocop/cop/style/redundant_return.rb +37 -3
  246. data/lib/rubocop/cop/style/redundant_self.rb +1 -1
  247. data/lib/rubocop/cop/style/rescue_standard_error.rb +1 -0
  248. data/lib/rubocop/cop/style/safe_navigation.rb +74 -32
  249. data/lib/rubocop/cop/style/semicolon.rb +3 -1
  250. data/lib/rubocop/cop/style/single_line_methods.rb +14 -23
  251. data/lib/rubocop/cop/style/stderr_puts.rb +2 -0
  252. data/lib/rubocop/cop/style/string_hash_keys.rb +12 -0
  253. data/lib/rubocop/cop/style/string_literals.rb +1 -1
  254. data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +1 -1
  255. data/lib/rubocop/cop/style/symbol_array.rb +29 -0
  256. data/lib/rubocop/cop/style/symbol_proc.rb +2 -0
  257. data/lib/rubocop/cop/style/trailing_body_on_class.rb +43 -0
  258. data/lib/rubocop/cop/style/trailing_body_on_method_definition.rb +7 -54
  259. data/lib/rubocop/cop/style/trailing_body_on_module.rb +43 -0
  260. data/lib/rubocop/cop/style/{trailing_comma_in_literal.rb → trailing_comma_in_array_literal.rb} +2 -20
  261. data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +56 -0
  262. data/lib/rubocop/cop/style/trailing_method_end_statement.rb +17 -20
  263. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +1 -0
  264. data/lib/rubocop/cop/style/unless_else.rb +2 -0
  265. data/lib/rubocop/cop/style/word_array.rb +0 -1
  266. data/lib/rubocop/cop/style/yoda_condition.rb +1 -0
  267. data/lib/rubocop/cop/team.rb +5 -5
  268. data/lib/rubocop/cop/util.rb +23 -188
  269. data/lib/rubocop/cop/variable_force.rb +1 -1
  270. data/lib/rubocop/file_finder.rb +45 -0
  271. data/lib/rubocop/formatter/disabled_config_formatter.rb +23 -14
  272. data/lib/rubocop/formatter/fuubar_style_formatter.rb +1 -1
  273. data/lib/rubocop/formatter/html_formatter.rb +12 -5
  274. data/lib/rubocop/formatter/json_formatter.rb +1 -1
  275. data/lib/rubocop/node_pattern.rb +8 -5
  276. data/lib/rubocop/options.rb +40 -33
  277. data/lib/rubocop/path_util.rb +5 -8
  278. data/lib/rubocop/processed_source.rb +53 -0
  279. data/lib/rubocop/remote_config.rb +1 -1
  280. data/lib/rubocop/result_cache.rb +1 -1
  281. data/lib/rubocop/rspec/cop_helper.rb +0 -4
  282. data/lib/rubocop/rspec/host_environment_simulation_helper.rb +0 -4
  283. data/lib/rubocop/rspec/shared_contexts.rb +3 -1
  284. data/lib/rubocop/rspec/shared_examples.rb +23 -25
  285. data/lib/rubocop/rspec/support.rb +5 -0
  286. data/lib/rubocop/runner.rb +3 -2
  287. data/lib/rubocop/string_util.rb +10 -9
  288. data/lib/rubocop/target_finder.rb +4 -1
  289. data/lib/rubocop/token.rb +26 -16
  290. data/lib/rubocop/version.rb +6 -4
  291. metadata +31 -17
  292. data/lib/rubocop/cop/performance/hash_each_methods.rb +0 -129
@@ -7,14 +7,6 @@ module RuboCop
7
7
  # available to all `sym` nodes within RuboCop.
8
8
  class SymbolNode < Node
9
9
  include BasicLiteralNode
10
-
11
- # Custom destructuring method. This can be used to normalize
12
- # destructuring for different variations of the node.
13
- #
14
- # @return [Array] the different parts of the `sym` node
15
- def node_parts
16
- to_a
17
- end
18
10
  end
19
11
  end
20
12
  end
@@ -30,14 +30,6 @@ module RuboCop
30
30
  def do?
31
31
  loc.begin && loc.begin.is?('do')
32
32
  end
33
-
34
- # Custom destructuring method. This can be used to normalize
35
- # destructuring for different variations of the node.
36
- #
37
- # @return [Array<Node>] the different parts of the `until` statement
38
- def node_parts
39
- to_a
40
- end
41
33
  end
42
34
  end
43
35
  end
@@ -48,14 +48,6 @@ module RuboCop
48
48
  def body
49
49
  node_parts[-1]
50
50
  end
51
-
52
- # Custom destructuring method. This can be used to normalize
53
- # destructuring for different variations of the node.
54
- #
55
- # @return [Array<Node>] the different parts of the `until` statement
56
- def node_parts
57
- to_a
58
- end
59
51
  end
60
52
  end
61
53
  end
@@ -30,14 +30,6 @@ module RuboCop
30
30
  def do?
31
31
  loc.begin && loc.begin.is?('do')
32
32
  end
33
-
34
- # Custom destructuring method. This can be used to normalize
35
- # destructuring for different variations of the node.
36
- #
37
- # @return [Array<Node>] the different parts of the `while` statement
38
- def node_parts
39
- to_a
40
- end
41
33
  end
42
34
  end
43
35
  end
@@ -10,6 +10,9 @@ module RuboCop
10
10
  SKIPPED_PHASE_1 = 'Phase 1 of 2: run Metrics/LineLength cop (skipped ' \
11
11
  'because the default Metrics/LineLength:Max is ' \
12
12
  'overridden)'.freeze
13
+ STATUS_SUCCESS = 0
14
+ STATUS_OFFENSES = 1
15
+ STATUS_ERROR = 2
13
16
 
14
17
  class Finished < RuntimeError; end
15
18
 
@@ -29,27 +32,30 @@ module RuboCop
29
32
  # @param args [Array<String>] command line arguments
30
33
  # @return [Integer] UNIX exit code
31
34
  #
32
- # rubocop:disable Metrics/MethodLength
35
+ # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
33
36
  def run(args = ARGV)
34
37
  @options, paths = Options.new.parse(args)
35
38
  validate_options_vs_config
36
39
  act_on_options
37
40
  apply_default_formatter
38
41
  execute_runners(paths)
42
+ rescue RuboCop::ConfigNotFoundError => e
43
+ warn e.message
44
+ e.status
39
45
  rescue RuboCop::Error => e
40
46
  warn Rainbow("Error: #{e.message}").red
41
- return 2
47
+ STATUS_ERROR
42
48
  rescue Finished
43
- return 0
49
+ STATUS_SUCCESS
44
50
  rescue IncorrectCopNameError => e
45
51
  warn e.message
46
- return 2
52
+ STATUS_ERROR
47
53
  rescue StandardError, SyntaxError, LoadError => e
48
54
  warn e.message
49
55
  warn e.backtrace
50
- return 2
56
+ STATUS_ERROR
51
57
  end
52
- # rubocop:enable Metrics/MethodLength
58
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
53
59
 
54
60
  def trap_interrupt(runner)
55
61
  Signal.trap('INT') do
@@ -152,7 +158,11 @@ module RuboCop
152
158
  display_error_summary(runner.errors)
153
159
  maybe_print_corrected_source
154
160
 
155
- all_passed && !runner.aborting? && runner.errors.empty? ? 0 : 1
161
+ if all_passed && !runner.aborting? && runner.errors.empty?
162
+ STATUS_SUCCESS
163
+ else
164
+ STATUS_OFFENSES
165
+ end
156
166
  end
157
167
 
158
168
  def handle_exiting_options
@@ -4,7 +4,7 @@ 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/UnneededDisable'.freeze
7
+ UNNEEDED_DISABLE = 'Lint/UnneededCopDisableDirective'.freeze
8
8
 
9
9
  COP_NAME_PATTERN = '([A-Z]\w+/)?(?:[A-Z]\w+)'.freeze
10
10
  COP_NAMES_PATTERN = "(?:#{COP_NAME_PATTERN} , )*#{COP_NAME_PATTERN}".freeze
@@ -34,8 +34,29 @@ module RuboCop
34
34
  @cop_disabled_line_ranges ||= analyze
35
35
  end
36
36
 
37
+ def extra_enabled_comments
38
+ extra_enabled_comments_with_names([], {})
39
+ end
40
+
37
41
  private
38
42
 
43
+ def extra_enabled_comments_with_names(extras, names)
44
+ each_directive do |comment, cop_names, disabled|
45
+ next unless comment_only_line?(comment.loc.expression.line)
46
+ cop_names.each do |name|
47
+ names[name] ||= 0
48
+ if disabled
49
+ names[name] += 1
50
+ elsif names[name] > 0
51
+ names[name] -= 1
52
+ else
53
+ extras << [comment, name]
54
+ end
55
+ end
56
+ end
57
+ extras
58
+ end
59
+
39
60
  def analyze
40
61
  analyses = Hash.new { |hash, key| hash[key] = CopAnalysis.new([], nil) }
41
62
 
@@ -106,7 +127,7 @@ module RuboCop
106
127
  def each_directive
107
128
  return if processed_source.comments.nil?
108
129
 
109
- processed_source.comments.each do |comment|
130
+ processed_source.each_comment do |comment|
110
131
  directive = directive_parts(comment)
111
132
  next unless directive
112
133
 
@@ -129,7 +150,7 @@ module RuboCop
129
150
  end
130
151
 
131
152
  def qualified_cop_name(cop_name)
132
- Cop::Cop.qualified_cop_name(cop_name.strip, processed_source.buffer.name)
153
+ Cop::Cop.qualified_cop_name(cop_name.strip, processed_source.file_path)
133
154
  end
134
155
 
135
156
  def all_cop_names
@@ -12,6 +12,7 @@ module RuboCop
12
12
  # rubocop:disable Metrics/ClassLength
13
13
  class Config
14
14
  include PathUtil
15
+ include FileFinder
15
16
 
16
17
  COMMON_PARAMS = %w[Exclude Include Severity
17
18
  AutoCorrect StyleGuide Details].freeze
@@ -24,8 +25,13 @@ module RuboCop
24
25
  OBSOLETE_COPS = {
25
26
  'Style/TrailingComma' =>
26
27
  'The `Style/TrailingComma` cop no longer exists. Please use ' \
27
- '`Style/TrailingCommaInLiteral` and/or ' \
28
- '`Style/TrailingCommaInArguments` instead.',
28
+ '`Style/TrailingCommaInArguments`, ' \
29
+ '`Style/TrailingCommaInArrayLiteral`, and/or ' \
30
+ '`Style/TrailingCommaInHashLiteral` instead.',
31
+ 'Style/TrailingCommaInLiteral' =>
32
+ 'The `Style/TrailingCommaInLiteral` cop no longer exists. Please use ' \
33
+ '`Style/TrailingCommaInArrayLiteral` and/or ' \
34
+ '`Style/TrailingCommaInHashLiteral` instead.',
29
35
  'Rails/DefaultScope' =>
30
36
  'The `Rails/DefaultScope` cop no longer exists.',
31
37
  'Lint/InvalidCharacterLiteral' =>
@@ -89,7 +95,20 @@ module RuboCop
89
95
  '`Naming/VariableName`.',
90
96
  'Style/VariableNumber' =>
91
97
  'The `Style/VariableNumber` cop has been renamed to ' \
92
- '`Naming/VariableNumber`.'
98
+ '`Naming/VariableNumber`.',
99
+ 'Lint/BlockAlignment' =>
100
+ 'The `Lint/BlockAlignment` cop has been renamed to ' \
101
+ '`Layout/BlockAlignment`.',
102
+ 'Lint/EndAlignment' =>
103
+ 'The `Lint/EndAlignment` cop has been renamed to ' \
104
+ '`Layout/EndAlignment`.',
105
+ 'Lint/DefEndAlignment' =>
106
+ 'The `Lint/DefEndAlignment` cop has been renamed to ' \
107
+ '`Layout/DefEndAlignment`.',
108
+ 'Performance/HashEachMethods' =>
109
+ 'The `Performance/HashEachMethods` cop has been removed ' \
110
+ 'since it no longer provides performance benefits in ' \
111
+ 'modern rubies.'
93
112
  }.freeze
94
113
 
95
114
  OBSOLETE_PARAMETERS = [
@@ -157,18 +176,36 @@ module RuboCop
157
176
  alternative: '`AlignWith` has been renamed to ' \
158
177
  '`EnforcedStyleAlignWith`'
159
178
  },
179
+ {
180
+ cop: 'Layout/BlockAlignment',
181
+ parameter: 'AlignWith',
182
+ alternative: '`AlignWith` has been renamed to ' \
183
+ '`EnforcedStyleAlignWith`'
184
+ },
160
185
  {
161
186
  cop: 'Lint/EndAlignment',
162
187
  parameter: 'AlignWith',
163
188
  alternative: '`AlignWith` has been renamed to ' \
164
189
  '`EnforcedStyleAlignWith`'
165
190
  },
191
+ {
192
+ cop: 'Layout/EndAlignment',
193
+ parameter: 'AlignWith',
194
+ alternative: '`AlignWith` has been renamed to ' \
195
+ '`EnforcedStyleAlignWith`'
196
+ },
166
197
  {
167
198
  cop: 'Lint/DefEndAlignment',
168
199
  parameter: 'AlignWith',
169
200
  alternative: '`AlignWith` has been renamed to ' \
170
201
  '`EnforcedStyleAlignWith`'
171
202
  },
203
+ {
204
+ cop: 'Layout/DefEndAlignment',
205
+ parameter: 'AlignWith',
206
+ alternative: '`AlignWith` has been renamed to ' \
207
+ '`EnforcedStyleAlignWith`'
208
+ },
172
209
  {
173
210
  cop: 'Rails/UniqBeforePluck',
174
211
  parameter: 'EnforcedMode',
@@ -395,7 +432,13 @@ module RuboCop
395
432
 
396
433
  def target_rails_version
397
434
  @target_rails_version ||=
398
- for_all_cops.fetch('TargetRailsVersion', DEFAULT_RAILS_VERSION)
435
+ if for_all_cops['TargetRailsVersion']
436
+ for_all_cops['TargetRailsVersion'].to_f
437
+ elsif target_rails_version_from_bundler_lock_file
438
+ target_rails_version_from_bundler_lock_file
439
+ else
440
+ DEFAULT_RAILS_VERSION
441
+ end
399
442
  end
400
443
 
401
444
  private
@@ -521,8 +564,7 @@ module RuboCop
521
564
 
522
565
  def ruby_version_file
523
566
  @ruby_version_file ||=
524
- PathUtil.find_file_upwards(RUBY_VERSION_FILENAME,
525
- base_dir_for_path_parameters)
567
+ find_file_upwards(RUBY_VERSION_FILENAME, base_dir_for_path_parameters)
526
568
  end
527
569
 
528
570
  def target_ruby_version_from_version_file
@@ -535,6 +577,33 @@ module RuboCop
535
577
  end
536
578
  end
537
579
 
580
+ def target_rails_version_from_bundler_lock_file
581
+ @target_rails_version_from_bundler_lock_file ||=
582
+ read_rails_version_from_bundler_lock_file
583
+ end
584
+
585
+ def read_rails_version_from_bundler_lock_file
586
+ lock_file_path = bundler_lock_file_path
587
+ return nil unless lock_file_path
588
+
589
+ File.foreach(lock_file_path) do |line|
590
+ # If rails is in the Gemfile, the lock file should have a line like:
591
+ # rails (X.X.X)
592
+ result = line.match(/^\s+rails\s+\((\d\.\d\.\d)/)
593
+ return result.captures.first.to_f if result
594
+ end
595
+ end
596
+
597
+ def bundler_lock_file_path
598
+ return nil unless loaded_path
599
+ base_path = base_dir_for_path_parameters
600
+ ['gems.locked', 'Gemfile.lock'].each do |file_name|
601
+ path = File.join(base_path, file_name)
602
+ return path if File.file?(path)
603
+ end
604
+ nil
605
+ end
606
+
538
607
  def reject_mutually_exclusive_defaults
539
608
  disabled_by_default = for_all_cops['DisabledByDefault']
540
609
  enabled_by_default = for_all_cops['EnabledByDefault']
@@ -4,6 +4,10 @@ require 'yaml'
4
4
  require 'pathname'
5
5
 
6
6
  module RuboCop
7
+ # Raised when a RuboCop configuration file is not found.
8
+ class ConfigNotFoundError < Error
9
+ end
10
+
7
11
  # This class represents the configuration of the RuboCop application
8
12
  # and all its cops. A Config is associated with a YAML configuration
9
13
  # file from which it was read. Several different Configs can be used
@@ -16,8 +20,9 @@ module RuboCop
16
20
  AUTO_GENERATED_FILE = '.rubocop_todo.yml'.freeze
17
21
 
18
22
  class << self
23
+ include FileFinder
24
+
19
25
  attr_accessor :debug, :auto_gen_config, :ignore_parent_exclusion
20
- attr_writer :root_level # The upwards search is stopped at this level.
21
26
  attr_writer :default_configuration
22
27
 
23
28
  alias debug? debug
@@ -25,7 +30,8 @@ module RuboCop
25
30
  alias ignore_parent_exclusion? ignore_parent_exclusion
26
31
 
27
32
  def clear_options
28
- @debug = @auto_gen_config = @root_level = nil
33
+ @debug = @auto_gen_config = nil
34
+ FileFinder.root_level = nil
29
35
  end
30
36
 
31
37
  def load_file(file)
@@ -44,11 +50,11 @@ module RuboCop
44
50
  resolver.resolve_inheritance(path, hash, file)
45
51
 
46
52
  hash.delete('inherit_from')
53
+ hash.delete('inherit_mode')
47
54
 
48
55
  Config.create(hash, path)
49
56
  end
50
57
 
51
- # rubocop:disable Performance/HashEachMethods
52
58
  def add_missing_namespaces(path, hash)
53
59
  hash.keys.each do |key|
54
60
  q = Cop::Cop.qualified_cop_name(key, path)
@@ -57,7 +63,6 @@ module RuboCop
57
63
  hash[q] = hash.delete(key)
58
64
  end
59
65
  end
60
- # rubocop:enable Performance/HashEachMethods
61
66
 
62
67
  # Return a recursive merge of two hashes. That is, a normal hash merge,
63
68
  # with the addition that any value that is a hash, and occurs in both
@@ -72,7 +77,7 @@ module RuboCop
72
77
  # user's home directory is checked. If there's no .rubocop.yml
73
78
  # there either, the path to the default file is returned.
74
79
  def configuration_file_for(target_dir)
75
- config_files_in_path(target_dir).first || DEFAULT_FILE
80
+ find_file_upwards(DOTFILE, target_dir, use_home: true) || DEFAULT_FILE
76
81
  end
77
82
 
78
83
  def configuration_from_file(config_file)
@@ -88,8 +93,10 @@ module RuboCop
88
93
  end
89
94
 
90
95
  def add_excludes_from_files(config, config_file)
91
- found_files = config_files_in_path(config_file)
92
- return unless found_files.any? && found_files.last != config_file
96
+ found_files = find_files_upwards(DOTFILE, config_file, use_home: true)
97
+ return if found_files.empty?
98
+ return if PathUtil.relative_path(found_files.last) ==
99
+ PathUtil.relative_path(config_file)
93
100
  print 'AllCops/Exclude ' if debug?
94
101
  config.add_excludes_from_higher_level(load_file(found_files.last))
95
102
  end
@@ -138,8 +145,8 @@ module RuboCop
138
145
 
139
146
  def write_dotfile(file_string, rubocop_yml_contents)
140
147
  File.open(DOTFILE, 'w') do |f|
141
- f.write "inherit_from:#{file_string}\n\n"
142
- f.write rubocop_yml_contents if rubocop_yml_contents
148
+ f.write "inherit_from:#{file_string}\n"
149
+ f.write "\n#{rubocop_yml_contents}" if rubocop_yml_contents
143
150
  end
144
151
  end
145
152
 
@@ -166,8 +173,8 @@ module RuboCop
166
173
  def read_file(absolute_path)
167
174
  IO.read(absolute_path, encoding: Encoding::UTF_8)
168
175
  rescue Errno::ENOENT
169
- warn(format('Configuration file not found: %s', absolute_path))
170
- exit(Errno::ENOENT::Errno)
176
+ raise ConfigNotFoundError,
177
+ "Configuration file not found: #{absolute_path}"
171
178
  end
172
179
 
173
180
  def yaml_safe_load(yaml_code, filename)
@@ -182,23 +189,6 @@ module RuboCop
182
189
  YAML.load(yaml_code, filename) # rubocop:disable Security/YAMLLoad
183
190
  end
184
191
  end
185
-
186
- def config_files_in_path(target)
187
- possible_config_files = dirs_to_search(target).map do |dir|
188
- File.join(dir, DOTFILE)
189
- end
190
- possible_config_files.select { |config_file| File.exist?(config_file) }
191
- end
192
-
193
- def dirs_to_search(target_dir)
194
- dirs_to_search = []
195
- Pathname.new(File.expand_path(target_dir)).ascend do |dir_pathname|
196
- break if dir_pathname.to_s == @root_level
197
- dirs_to_search << dir_pathname.to_s
198
- end
199
- dirs_to_search << Dir.home if ENV.key? 'HOME'
200
- dirs_to_search
201
- end
202
192
  end
203
193
 
204
194
  # Initializing class ivars
@@ -18,10 +18,18 @@ module RuboCop
18
18
  end
19
19
 
20
20
  def resolve_inheritance(path, hash, file)
21
- base_configs(path, hash['inherit_from'], file)
22
- .reverse_each do |base_config|
21
+ inherited_files = Array(hash['inherit_from'])
22
+ base_configs(path, inherited_files, file)
23
+ .reverse.each_with_index do |base_config, index|
23
24
  base_config.each do |k, v|
24
- hash[k] = hash.key?(k) ? merge(v, hash[k]) : v if v.is_a?(Hash)
25
+ next unless v.is_a?(Hash)
26
+ if hash.key?(k)
27
+ v = merge(v, hash[k],
28
+ cop_name: k, file: file,
29
+ inherited_file: inherited_files[index],
30
+ inherit_mode: determine_inherit_mode(hash, k))
31
+ end
32
+ hash[k] = v
25
33
  end
26
34
  end
27
35
  end
@@ -70,18 +78,58 @@ module RuboCop
70
78
  # Return a recursive merge of two hashes. That is, a normal hash merge,
71
79
  # with the addition that any value that is a hash, and occurs in both
72
80
  # arguments, will also be merged. And so on.
73
- def merge(base_hash, derived_hash)
81
+ def merge(base_hash, derived_hash, **opts)
74
82
  result = base_hash.merge(derived_hash)
75
83
  keys_appearing_in_both = base_hash.keys & derived_hash.keys
76
84
  keys_appearing_in_both.each do |key|
77
- next unless base_hash[key].is_a?(Hash)
78
- result[key] = merge(base_hash[key], derived_hash[key])
85
+ if base_hash[key].is_a?(Hash)
86
+ result[key] = merge(base_hash[key], derived_hash[key])
87
+ elsif should_union?(base_hash, key, opts[:inherit_mode])
88
+ result[key] = base_hash[key] | derived_hash[key]
89
+ else
90
+ warn_on_duplicate_setting(base_hash, derived_hash, key, opts)
91
+ end
79
92
  end
80
93
  result
81
94
  end
82
95
 
83
96
  private
84
97
 
98
+ def duplicate_setting?(base_hash, derived_hash, key, inherited_file)
99
+ return false if inherited_file.nil? # Not inheritance resolving merge
100
+ return false if inherited_file.start_with?('..') # Legitimate override
101
+ return false if base_hash[key] == derived_hash[key] # Same value
102
+ return false if remote_file?(inherited_file) # Can't change
103
+ Gem.path.none? { |dir| inherited_file.start_with?(dir) } # Can change?
104
+ end
105
+
106
+ def warn_on_duplicate_setting(base_hash, derived_hash, key, **opts)
107
+ return unless duplicate_setting?(base_hash, derived_hash,
108
+ key, opts[:inherited_file])
109
+
110
+ inherit_mode = opts[:inherit_mode]['merge'] ||
111
+ opts[:inherit_mode]['override']
112
+ return if base_hash[key].is_a?(Array) &&
113
+ inherit_mode && inherit_mode.include?(key)
114
+
115
+ warn("#{PathUtil.smart_path(opts[:file])}: " \
116
+ "#{opts[:cop_name]}:#{key} overrides " \
117
+ "the same parameter in #{opts[:inherited_file]}")
118
+ end
119
+
120
+ def determine_inherit_mode(hash, key)
121
+ cop_cfg = hash[key]
122
+ local_inherit = cop_cfg.delete('inherit_mode') if cop_cfg.is_a?(Hash)
123
+ local_inherit || hash['inherit_mode'] || {}
124
+ end
125
+
126
+ def should_union?(base_hash, key, inherit_mode)
127
+ base_hash[key].is_a?(Array) &&
128
+ inherit_mode &&
129
+ inherit_mode['merge'] &&
130
+ inherit_mode['merge'].include?(key)
131
+ end
132
+
85
133
  def base_configs(path, inherit_from, file)
86
134
  configs = Array(inherit_from).compact.map do |f|
87
135
  ConfigLoader.load_file(inherited_file(path, f, file))
@@ -91,8 +139,7 @@ module RuboCop
91
139
  end
92
140
 
93
141
  def inherited_file(path, inherit_from, file)
94
- regex = URI::DEFAULT_PARSER.make_regexp(%w[http https])
95
- if inherit_from =~ /\A#{regex}\z/
142
+ if remote_file?(inherit_from)
96
143
  RemoteConfig.new(inherit_from, File.dirname(path))
97
144
  elsif file.is_a?(RemoteConfig)
98
145
  file.inherit_from_remote(inherit_from, path)
@@ -102,6 +149,11 @@ module RuboCop
102
149
  end
103
150
  end
104
151
 
152
+ def remote_file?(uri)
153
+ regex = URI::DEFAULT_PARSER.make_regexp(%w[http https])
154
+ uri =~ /\A#{regex}\z/
155
+ end
156
+
105
157
  def handle_disabled_by_default(config, new_default_configuration)
106
158
  department_config = config.to_hash.reject { |cop| cop.include?('/') }
107
159
  department_config.each do |dept, dept_params|
@@ -132,7 +184,7 @@ module RuboCop
132
184
 
133
185
  def gem_config_path(gem_name, relative_config_path)
134
186
  spec = Gem::Specification.find_by_name(gem_name)
135
- return File.join(spec.gem_dir, relative_config_path)
187
+ File.join(spec.gem_dir, relative_config_path)
136
188
  rescue Gem::LoadError => e
137
189
  raise Gem::LoadError,
138
190
  "Unable to find gem #{gem_name}; is the gem installed? #{e}"