rubocop 0.85.1 → 0.89.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 (357) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +16 -4
  3. data/bin/rubocop-profile +32 -0
  4. data/config/default.yml +227 -26
  5. data/lib/rubocop.rb +33 -5
  6. data/lib/rubocop/cli.rb +2 -4
  7. data/lib/rubocop/cli/command/auto_genenerate_config.rb +42 -7
  8. data/lib/rubocop/cli/command/base.rb +1 -0
  9. data/lib/rubocop/cli/command/execute_runner.rb +1 -1
  10. data/lib/rubocop/cli/command/init_dotfile.rb +1 -1
  11. data/lib/rubocop/cli/command/show_cops.rb +2 -2
  12. data/lib/rubocop/cli/command/version.rb +2 -2
  13. data/lib/rubocop/comment_config.rb +2 -2
  14. data/lib/rubocop/config.rb +20 -3
  15. data/lib/rubocop/config_loader.rb +40 -68
  16. data/lib/rubocop/config_loader_resolver.rb +4 -4
  17. data/lib/rubocop/config_obsoletion.rb +6 -2
  18. data/lib/rubocop/config_store.rb +4 -0
  19. data/lib/rubocop/config_validator.rb +1 -3
  20. data/lib/rubocop/cop/autocorrect_logic.rb +14 -24
  21. data/lib/rubocop/cop/badge.rb +1 -1
  22. data/lib/rubocop/cop/base.rb +407 -0
  23. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +10 -20
  24. data/lib/rubocop/cop/commissioner.rb +47 -50
  25. data/lib/rubocop/cop/cop.rb +85 -236
  26. data/lib/rubocop/cop/corrector.rb +38 -115
  27. data/lib/rubocop/cop/correctors/line_break_corrector.rb +3 -3
  28. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +26 -0
  29. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +1 -1
  30. data/lib/rubocop/cop/correctors/punctuation_corrector.rb +1 -1
  31. data/lib/rubocop/cop/correctors/unused_arg_corrector.rb +15 -18
  32. data/lib/rubocop/cop/force.rb +1 -0
  33. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +39 -13
  34. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +1 -1
  35. data/lib/rubocop/cop/generator.rb +1 -1
  36. data/lib/rubocop/cop/generator/configuration_injector.rb +3 -3
  37. data/lib/rubocop/cop/internal_affairs/method_name_equal.rb +4 -12
  38. data/lib/rubocop/cop/internal_affairs/node_destructuring.rb +1 -1
  39. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +11 -14
  40. data/lib/rubocop/cop/internal_affairs/offense_location_keyword.rb +8 -8
  41. data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +10 -7
  42. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +7 -8
  43. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +2 -2
  44. data/lib/rubocop/cop/layout/block_alignment.rb +1 -1
  45. data/lib/rubocop/cop/layout/case_indentation.rb +18 -19
  46. data/lib/rubocop/cop/layout/class_structure.rb +2 -37
  47. data/lib/rubocop/cop/layout/comment_indentation.rb +3 -3
  48. data/lib/rubocop/cop/layout/empty_comment.rb +1 -1
  49. data/lib/rubocop/cop/layout/empty_lines.rb +0 -2
  50. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +1 -0
  51. data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +3 -8
  52. data/lib/rubocop/cop/layout/end_alignment.rb +3 -2
  53. data/lib/rubocop/cop/layout/end_of_line.rb +1 -1
  54. data/lib/rubocop/cop/layout/extra_spacing.rb +9 -16
  55. data/lib/rubocop/cop/layout/first_argument_indentation.rb +5 -1
  56. data/lib/rubocop/cop/layout/first_array_element_line_break.rb +1 -1
  57. data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +1 -1
  58. data/lib/rubocop/cop/layout/hash_alignment.rb +2 -3
  59. data/lib/rubocop/cop/layout/heredoc_indentation.rb +2 -2
  60. data/lib/rubocop/cop/layout/indentation_style.rb +0 -2
  61. data/lib/rubocop/cop/layout/multiline_block_layout.rb +17 -7
  62. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +1 -1
  63. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +0 -2
  64. data/lib/rubocop/cop/layout/space_after_colon.rb +1 -1
  65. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +22 -27
  66. data/lib/rubocop/cop/layout/space_around_keyword.rb +2 -2
  67. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +33 -66
  68. data/lib/rubocop/cop/layout/space_around_operators.rb +1 -1
  69. data/lib/rubocop/cop/layout/space_before_block_braces.rb +14 -0
  70. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +4 -3
  71. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +1 -1
  72. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +2 -2
  73. data/lib/rubocop/cop/legacy/corrections_proxy.rb +49 -0
  74. data/lib/rubocop/cop/legacy/corrector.rb +29 -0
  75. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +7 -4
  76. data/lib/rubocop/cop/lint/ambiguous_operator.rb +15 -10
  77. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +11 -13
  78. data/lib/rubocop/cop/lint/assignment_in_condition.rb +2 -2
  79. data/lib/rubocop/cop/lint/big_decimal_new.rb +10 -10
  80. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +49 -0
  81. data/lib/rubocop/cop/lint/boolean_symbol.rb +16 -11
  82. data/lib/rubocop/cop/lint/circular_argument_reference.rb +1 -1
  83. data/lib/rubocop/cop/lint/constant_resolution.rb +89 -0
  84. data/lib/rubocop/cop/lint/debugger.rb +7 -1
  85. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +9 -10
  86. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +21 -17
  87. data/lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb +8 -2
  88. data/lib/rubocop/cop/lint/duplicate_case_condition.rb +1 -1
  89. data/lib/rubocop/cop/lint/duplicate_elsif_condition.rb +39 -0
  90. data/lib/rubocop/cop/lint/duplicate_hash_key.rb +1 -1
  91. data/lib/rubocop/cop/lint/duplicate_methods.rb +9 -6
  92. data/lib/rubocop/cop/lint/duplicate_rescue_exception.rb +60 -0
  93. data/lib/rubocop/cop/lint/each_with_object_argument.rb +1 -1
  94. data/lib/rubocop/cop/lint/else_layout.rb +1 -1
  95. data/lib/rubocop/cop/lint/empty_conditional_body.rb +67 -0
  96. data/lib/rubocop/cop/lint/empty_ensure.rb +5 -5
  97. data/lib/rubocop/cop/lint/empty_expression.rb +2 -2
  98. data/lib/rubocop/cop/lint/empty_interpolation.rb +5 -6
  99. data/lib/rubocop/cop/lint/empty_when.rb +2 -2
  100. data/lib/rubocop/cop/lint/ensure_return.rb +27 -29
  101. data/lib/rubocop/cop/lint/erb_new_arguments.rb +11 -10
  102. data/lib/rubocop/cop/lint/flip_flop.rb +1 -1
  103. data/lib/rubocop/cop/lint/float_comparison.rb +93 -0
  104. data/lib/rubocop/cop/lint/float_out_of_range.rb +2 -2
  105. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +11 -5
  106. data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +13 -14
  107. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +5 -4
  108. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +8 -8
  109. data/lib/rubocop/cop/lint/inherit_exception.rb +12 -7
  110. data/lib/rubocop/cop/lint/interpolation_check.rb +21 -5
  111. data/lib/rubocop/cop/lint/literal_as_condition.rb +14 -2
  112. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +7 -7
  113. data/lib/rubocop/cop/lint/loop.rb +23 -2
  114. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +6 -5
  115. data/lib/rubocop/cop/lint/missing_super.rb +99 -0
  116. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -1
  117. data/lib/rubocop/cop/lint/multiple_comparison.rb +6 -9
  118. data/lib/rubocop/cop/lint/nested_method_definition.rb +15 -21
  119. data/lib/rubocop/cop/lint/nested_percent_literal.rb +1 -1
  120. data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
  121. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +84 -13
  122. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +2 -2
  123. data/lib/rubocop/cop/lint/number_conversion.rb +6 -9
  124. data/lib/rubocop/cop/lint/ordered_magic_comments.rb +11 -13
  125. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +61 -0
  126. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +12 -13
  127. data/lib/rubocop/cop/lint/percent_string_array.rb +14 -13
  128. data/lib/rubocop/cop/lint/percent_symbol_array.rb +14 -13
  129. data/lib/rubocop/cop/lint/raise_exception.rb +15 -5
  130. data/lib/rubocop/cop/lint/rand_one.rb +3 -3
  131. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +31 -25
  132. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +7 -11
  133. data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -7
  134. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +15 -11
  135. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +6 -13
  136. data/lib/rubocop/cop/lint/redundant_with_index.rb +11 -14
  137. data/lib/rubocop/cop/lint/redundant_with_object.rb +11 -14
  138. data/lib/rubocop/cop/lint/regexp_as_condition.rb +6 -2
  139. data/lib/rubocop/cop/lint/require_parentheses.rb +2 -2
  140. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
  141. data/lib/rubocop/cop/lint/rescue_type.rb +8 -8
  142. data/lib/rubocop/cop/lint/return_in_void_context.rb +2 -4
  143. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +3 -6
  144. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +14 -10
  145. data/lib/rubocop/cop/lint/safe_navigation_with_empty.rb +10 -2
  146. data/lib/rubocop/cop/lint/script_permission.rb +10 -7
  147. data/lib/rubocop/cop/lint/self_assignment.rb +78 -0
  148. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +5 -11
  149. data/lib/rubocop/cop/lint/shadowed_argument.rb +3 -3
  150. data/lib/rubocop/cop/lint/shadowed_exception.rb +2 -2
  151. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +3 -3
  152. data/lib/rubocop/cop/lint/struct_new_override.rb +1 -1
  153. data/lib/rubocop/cop/lint/suppressed_exception.rb +4 -7
  154. data/lib/rubocop/cop/lint/syntax.rb +11 -26
  155. data/lib/rubocop/cop/lint/to_json.rb +4 -6
  156. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +34 -0
  157. data/lib/rubocop/cop/lint/underscore_prefixed_variable_name.rb +4 -4
  158. data/lib/rubocop/cop/lint/unified_integer.rb +4 -6
  159. data/lib/rubocop/cop/lint/unreachable_code.rb +1 -1
  160. data/lib/rubocop/cop/lint/unreachable_loop.rb +174 -0
  161. data/lib/rubocop/cop/lint/unused_block_argument.rb +8 -3
  162. data/lib/rubocop/cop/lint/unused_method_argument.rb +9 -4
  163. data/lib/rubocop/cop/lint/uri_escape_unescape.rb +1 -1
  164. data/lib/rubocop/cop/lint/uri_regexp.rb +11 -31
  165. data/lib/rubocop/cop/lint/useless_access_modifier.rb +26 -16
  166. data/lib/rubocop/cop/lint/useless_assignment.rb +4 -4
  167. data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +6 -15
  168. data/lib/rubocop/cop/lint/useless_setter_call.rb +4 -6
  169. data/lib/rubocop/cop/lint/void.rb +3 -7
  170. data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
  171. data/lib/rubocop/cop/metrics/block_length.rb +24 -2
  172. data/lib/rubocop/cop/metrics/block_nesting.rb +2 -2
  173. data/lib/rubocop/cop/metrics/class_length.rb +26 -3
  174. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +37 -4
  175. data/lib/rubocop/cop/metrics/method_length.rb +25 -2
  176. data/lib/rubocop/cop/metrics/module_length.rb +26 -3
  177. data/lib/rubocop/cop/metrics/parameter_lists.rb +2 -6
  178. data/lib/rubocop/cop/metrics/perceived_complexity.rb +7 -8
  179. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +47 -4
  180. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +157 -0
  181. data/lib/rubocop/cop/metrics/utils/iterating_block.rb +61 -0
  182. data/lib/rubocop/cop/metrics/utils/repeated_csend_discount.rb +37 -0
  183. data/lib/rubocop/cop/migration/department_name.rb +13 -15
  184. data/lib/rubocop/cop/mixin/allowed_methods.rb +19 -0
  185. data/lib/rubocop/cop/mixin/array_min_size.rb +1 -1
  186. data/lib/rubocop/cop/mixin/auto_corrector.rb +12 -0
  187. data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
  188. data/lib/rubocop/cop/mixin/code_length.rb +26 -5
  189. data/lib/rubocop/cop/mixin/configurable_formatting.rb +1 -1
  190. data/lib/rubocop/cop/mixin/configurable_naming.rb +1 -1
  191. data/lib/rubocop/cop/mixin/documentation_comment.rb +2 -2
  192. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -1
  193. data/lib/rubocop/cop/mixin/enforce_superclass.rb +5 -1
  194. data/lib/rubocop/cop/mixin/first_element_line_break.rb +1 -1
  195. data/lib/rubocop/cop/mixin/method_complexity.rb +10 -2
  196. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
  197. data/lib/rubocop/cop/mixin/nil_methods.rb +3 -5
  198. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +6 -1
  199. data/lib/rubocop/cop/mixin/parentheses.rb +1 -2
  200. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +1 -1
  201. data/lib/rubocop/cop/mixin/range_help.rb +1 -1
  202. data/lib/rubocop/cop/mixin/regexp_literal_help.rb +27 -0
  203. data/lib/rubocop/cop/mixin/statement_modifier.rb +38 -9
  204. data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -1
  205. data/lib/rubocop/cop/mixin/surrounding_space.rb +7 -27
  206. data/lib/rubocop/cop/mixin/trailing_comma.rb +1 -1
  207. data/lib/rubocop/cop/mixin/uncommunicative_name.rb +12 -17
  208. data/lib/rubocop/cop/mixin/unused_argument.rb +4 -6
  209. data/lib/rubocop/cop/mixin/visibility_help.rb +50 -0
  210. data/lib/rubocop/cop/naming/accessor_method_name.rb +4 -2
  211. data/lib/rubocop/cop/naming/ascii_identifiers.rb +29 -6
  212. data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +4 -4
  213. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  214. data/lib/rubocop/cop/naming/class_and_module_camel_case.rb +2 -2
  215. data/lib/rubocop/cop/naming/constant_name.rb +2 -2
  216. data/lib/rubocop/cop/naming/file_name.rb +4 -6
  217. data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +2 -2
  218. data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +3 -3
  219. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +2 -2
  220. data/lib/rubocop/cop/naming/method_name.rb +1 -1
  221. data/lib/rubocop/cop/naming/method_parameter_name.rb +2 -2
  222. data/lib/rubocop/cop/naming/predicate_name.rb +6 -10
  223. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +12 -11
  224. data/lib/rubocop/cop/naming/variable_name.rb +1 -1
  225. data/lib/rubocop/cop/naming/variable_number.rb +1 -1
  226. data/lib/rubocop/cop/offense.rb +16 -2
  227. data/lib/rubocop/cop/registry.rb +3 -3
  228. data/lib/rubocop/cop/security/eval.rb +2 -2
  229. data/lib/rubocop/cop/security/json_load.rb +6 -8
  230. data/lib/rubocop/cop/security/marshal_load.rb +2 -4
  231. data/lib/rubocop/cop/security/open.rb +2 -2
  232. data/lib/rubocop/cop/security/yaml_load.rb +6 -6
  233. data/lib/rubocop/cop/style/access_modifier_declarations.rb +11 -1
  234. data/lib/rubocop/cop/style/accessor_grouping.rb +149 -0
  235. data/lib/rubocop/cop/style/alias.rb +7 -3
  236. data/lib/rubocop/cop/style/array_coercion.rb +63 -0
  237. data/lib/rubocop/cop/style/auto_resource_cleanup.rb +3 -2
  238. data/lib/rubocop/cop/style/bare_percent_literals.rb +1 -1
  239. data/lib/rubocop/cop/style/bisected_attr_accessor.rb +144 -0
  240. data/lib/rubocop/cop/style/block_delimiters.rb +2 -4
  241. data/lib/rubocop/cop/style/case_equality.rb +22 -3
  242. data/lib/rubocop/cop/style/case_like_if.rb +217 -0
  243. data/lib/rubocop/cop/style/class_and_module_children.rb +1 -1
  244. data/lib/rubocop/cop/style/class_vars.rb +21 -0
  245. data/lib/rubocop/cop/style/colon_method_call.rb +3 -3
  246. data/lib/rubocop/cop/style/command_literal.rb +1 -1
  247. data/lib/rubocop/cop/style/commented_keyword.rb +5 -2
  248. data/lib/rubocop/cop/style/conditional_assignment.rb +11 -2
  249. data/lib/rubocop/cop/style/copyright.rb +3 -3
  250. data/lib/rubocop/cop/style/date_time.rb +1 -1
  251. data/lib/rubocop/cop/style/dir.rb +2 -2
  252. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +1 -1
  253. data/lib/rubocop/cop/style/documentation.rb +6 -6
  254. data/lib/rubocop/cop/style/each_with_object.rb +0 -2
  255. data/lib/rubocop/cop/style/empty_case_condition.rb +8 -6
  256. data/lib/rubocop/cop/style/empty_literal.rb +5 -5
  257. data/lib/rubocop/cop/style/empty_method.rb +5 -5
  258. data/lib/rubocop/cop/style/encoding.rb +1 -1
  259. data/lib/rubocop/cop/style/eval_with_location.rb +4 -0
  260. data/lib/rubocop/cop/style/expand_path_arguments.rb +6 -2
  261. data/lib/rubocop/cop/style/explicit_block_argument.rb +102 -0
  262. data/lib/rubocop/cop/style/exponential_notation.rb +8 -10
  263. data/lib/rubocop/cop/style/float_division.rb +7 -10
  264. data/lib/rubocop/cop/style/format_string.rb +4 -0
  265. data/lib/rubocop/cop/style/format_string_token.rb +6 -5
  266. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
  267. data/lib/rubocop/cop/style/global_std_stream.rb +65 -0
  268. data/lib/rubocop/cop/style/guard_clause.rb +2 -2
  269. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +69 -0
  270. data/lib/rubocop/cop/style/hash_like_case.rb +76 -0
  271. data/lib/rubocop/cop/style/hash_syntax.rb +6 -3
  272. data/lib/rubocop/cop/style/identical_conditional_branches.rb +1 -1
  273. data/lib/rubocop/cop/style/if_unless_modifier.rb +8 -28
  274. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +12 -0
  275. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  276. data/lib/rubocop/cop/style/inverse_methods.rb +3 -4
  277. data/lib/rubocop/cop/style/ip_addresses.rb +1 -1
  278. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +5 -0
  279. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +1 -1
  280. data/lib/rubocop/cop/style/missing_else.rb +1 -11
  281. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +9 -2
  282. data/lib/rubocop/cop/style/multiline_block_chain.rb +10 -1
  283. data/lib/rubocop/cop/style/multiline_if_then.rb +1 -1
  284. data/lib/rubocop/cop/style/multiline_memoization.rb +2 -2
  285. data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -1
  286. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +17 -6
  287. data/lib/rubocop/cop/style/mutable_constant.rb +4 -4
  288. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +2 -5
  289. data/lib/rubocop/cop/style/nested_ternary_operator.rb +27 -0
  290. data/lib/rubocop/cop/style/next.rb +2 -2
  291. data/lib/rubocop/cop/style/numeric_literal_prefix.rb +2 -2
  292. data/lib/rubocop/cop/style/numeric_predicate.rb +7 -4
  293. data/lib/rubocop/cop/style/optional_boolean_parameter.rb +42 -0
  294. data/lib/rubocop/cop/style/parallel_assignment.rb +5 -5
  295. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +2 -2
  296. data/lib/rubocop/cop/style/proc.rb +1 -1
  297. data/lib/rubocop/cop/style/random_with_offset.rb +5 -10
  298. data/lib/rubocop/cop/style/redundant_assignment.rb +117 -0
  299. data/lib/rubocop/cop/style/redundant_condition.rb +15 -3
  300. data/lib/rubocop/cop/style/redundant_exception.rb +18 -10
  301. data/lib/rubocop/cop/style/redundant_fetch_block.rb +122 -0
  302. data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +50 -0
  303. data/lib/rubocop/cop/style/redundant_freeze.rb +1 -1
  304. data/lib/rubocop/cop/style/redundant_parentheses.rb +8 -2
  305. data/lib/rubocop/cop/style/redundant_percent_q.rb +2 -2
  306. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +4 -3
  307. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +23 -32
  308. data/lib/rubocop/cop/style/redundant_self.rb +6 -9
  309. data/lib/rubocop/cop/style/redundant_sort.rb +28 -12
  310. data/lib/rubocop/cop/style/rescue_standard_error.rb +1 -1
  311. data/lib/rubocop/cop/style/sample.rb +1 -1
  312. data/lib/rubocop/cop/style/semicolon.rb +1 -1
  313. data/lib/rubocop/cop/style/signal_exception.rb +3 -1
  314. data/lib/rubocop/cop/style/single_argument_dig.rb +54 -0
  315. data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +3 -2
  316. data/lib/rubocop/cop/style/stderr_puts.rb +1 -1
  317. data/lib/rubocop/cop/style/string_concatenation.rb +92 -0
  318. data/lib/rubocop/cop/style/struct_inheritance.rb +23 -2
  319. data/lib/rubocop/cop/style/symbol_array.rb +6 -6
  320. data/lib/rubocop/cop/style/symbol_proc.rb +2 -2
  321. data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
  322. data/lib/rubocop/cop/style/trailing_method_end_statement.rb +9 -32
  323. data/lib/rubocop/cop/style/trivial_accessors.rb +8 -7
  324. data/lib/rubocop/cop/style/word_array.rb +1 -1
  325. data/lib/rubocop/cop/style/yoda_condition.rb +18 -1
  326. data/lib/rubocop/cop/style/zero_length_predicate.rb +12 -8
  327. data/lib/rubocop/cop/team.rb +98 -82
  328. data/lib/rubocop/cop/tokens_util.rb +84 -0
  329. data/lib/rubocop/cop/util.rb +3 -15
  330. data/lib/rubocop/cop/utils/format_string.rb +2 -3
  331. data/lib/rubocop/cop/variable_force.rb +0 -2
  332. data/lib/rubocop/cop/variable_force/branch.rb +1 -0
  333. data/lib/rubocop/cop/variable_force/variable.rb +7 -5
  334. data/lib/rubocop/cops_documentation_generator.rb +282 -0
  335. data/lib/rubocop/error.rb +1 -0
  336. data/lib/rubocop/file_finder.rb +12 -12
  337. data/lib/rubocop/formatter/disabled_config_formatter.rb +2 -2
  338. data/lib/rubocop/formatter/formatter_set.rb +2 -1
  339. data/lib/rubocop/name_similarity.rb +7 -3
  340. data/lib/rubocop/options.rb +15 -8
  341. data/lib/rubocop/path_util.rb +19 -19
  342. data/lib/rubocop/platform.rb +1 -1
  343. data/lib/rubocop/rake_task.rb +7 -9
  344. data/lib/rubocop/result_cache.rb +12 -8
  345. data/lib/rubocop/rspec/cop_helper.rb +4 -4
  346. data/lib/rubocop/rspec/expect_offense.rb +63 -22
  347. data/lib/rubocop/rspec/shared_contexts.rb +19 -16
  348. data/lib/rubocop/runner.rb +34 -33
  349. data/lib/rubocop/target_finder.rb +14 -11
  350. data/lib/rubocop/target_ruby.rb +2 -2
  351. data/lib/rubocop/version.rb +2 -2
  352. metadata +49 -11
  353. data/lib/rubocop/cop/lint/useless_comparison.rb +0 -28
  354. data/lib/rubocop/cop/mixin/classish_length.rb +0 -37
  355. data/lib/rubocop/cop/mixin/parser_diagnostic.rb +0 -37
  356. data/lib/rubocop/cop/mixin/too_many_lines.rb +0 -35
  357. data/lib/rubocop/cop/style/method_missing_super.rb +0 -34
@@ -74,7 +74,7 @@ module RuboCop
74
74
  end
75
75
 
76
76
  def timestamp
77
- @options[:no_auto_gen_timestamp] ? '' : "on #{Time.now} "
77
+ @options[:no_auto_gen_timestamp] ? '' : "on #{Time.now.utc} "
78
78
  end
79
79
 
80
80
  def output_offenses
@@ -115,7 +115,7 @@ module RuboCop
115
115
  output_buffer.puts "# Offense count: #{offense_count}" if @show_offense_counts
116
116
 
117
117
  cop_class = Cop::Cop.registry.find_by_cop_name(cop_name)
118
- output_buffer.puts '# Cop supports --auto-correct.' if cop_class&.new&.support_autocorrect?
118
+ output_buffer.puts '# Cop supports --auto-correct.' if cop_class&.support_autocorrect?
119
119
 
120
120
  default_cfg = default_config(cop_name)
121
121
  return unless default_cfg
@@ -35,6 +35,7 @@ module RuboCop
35
35
  end
36
36
 
37
37
  def initialize(options = {})
38
+ super()
38
39
  @options = options # CLI options
39
40
  end
40
41
 
@@ -82,7 +83,7 @@ module RuboCop
82
83
 
83
84
  def builtin_formatter_class(specified_key)
84
85
  matching_keys = BUILTIN_FORMATTERS_FOR_KEYS.keys.select do |key|
85
- key =~ /^\[#{specified_key}\]/ || specified_key == key.delete('[]')
86
+ /^\[#{specified_key}\]/.match?(key) || specified_key == key.delete('[]')
86
87
  end
87
88
 
88
89
  raise %(No formatter for "#{specified_key}") if matching_keys.empty?
@@ -12,13 +12,17 @@ module RuboCop
12
12
  end
13
13
 
14
14
  def find_similar_names(target_name, names)
15
+ # DidYouMean::SpellChecker is not available in all versions of Ruby, and
16
+ # even on versions where it *is* available (>= 2.3), it is not always
17
+ # required correctly. So we do a feature check first.
18
+ # See: https://github.com/rubocop-hq/rubocop/issues/7979
19
+ return [] unless defined?(DidYouMean::SpellChecker)
20
+
15
21
  names = names.dup
16
22
  names.delete(target_name)
17
23
 
18
24
  spell_checker = DidYouMean::SpellChecker.new(dictionary: names)
19
- similar_names = spell_checker.correct(target_name)
20
-
21
- similar_names
25
+ spell_checker.correct(target_name)
22
26
  end
23
27
  end
24
28
  end
@@ -163,7 +163,7 @@ module RuboCop
163
163
  end
164
164
  end
165
165
 
166
- # rubocop:disable Metrics/MethodLength
166
+ # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
167
167
  def add_boolean_flags(opts)
168
168
  option(opts, '-F', '--fail-fast')
169
169
  option(opts, '-C', '--cache FLAG')
@@ -171,7 +171,16 @@ module RuboCop
171
171
  option(opts, '-D', '--[no-]display-cop-names')
172
172
  option(opts, '-E', '--extra-details')
173
173
  option(opts, '-S', '--display-style-guide')
174
- option(opts, '-a', '--auto-correct')
174
+ option(opts, '-a', '--auto-correct') do
175
+ @options[:safe_auto_correct] = true
176
+ end
177
+ option(opts, '--safe-auto-correct') do
178
+ warn '--safe-auto-correct is deprecated; use --auto-correct'
179
+ @options[:safe_auto_correct] = @options[:auto_correct] = true
180
+ end
181
+ option(opts, '-A', '--auto-correct-all') do
182
+ @options[:auto_correct] = true
183
+ end
175
184
  option(opts, '--disable-pending-cops')
176
185
  option(opts, '--enable-pending-cops')
177
186
  option(opts, '--ignore-disable-comments')
@@ -184,7 +193,7 @@ module RuboCop
184
193
  option(opts, '-V', '--verbose-version')
185
194
  option(opts, '-P', '--parallel')
186
195
  end
187
- # rubocop:enable Metrics/MethodLength
196
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
188
197
 
189
198
  def add_aliases(opts)
190
199
  option(opts, '-l', '--lint') do
@@ -196,9 +205,6 @@ module RuboCop
196
205
  @options[:only] << 'Layout'
197
206
  @options[:auto_correct] = true
198
207
  end
199
- option(opts, '--safe-auto-correct') do
200
- @options[:auto_correct] = true
201
- end
202
208
  end
203
209
 
204
210
  def add_list_options(opts)
@@ -465,8 +471,9 @@ module RuboCop
465
471
  lint: 'Run only lint cops.',
466
472
  safe: 'Run only safe cops.',
467
473
  list_target_files: 'List all files RuboCop will inspect.',
468
- auto_correct: 'Auto-correct offenses.',
469
- safe_auto_correct: 'Run auto-correct only when it\'s safe.',
474
+ auto_correct: 'Auto-correct offenses (only when it\'s safe).',
475
+ safe_auto_correct: '(same, deprecated)',
476
+ auto_correct_all: 'Auto-correct offenses (safe and unsafe)',
470
477
  fix_layout: 'Run only layout cops, with auto-correct on.',
471
478
  color: 'Force color output on or off.',
472
479
  version: 'Display version.',
@@ -5,7 +5,7 @@ module RuboCop
5
5
  module PathUtil
6
6
  module_function
7
7
 
8
- def relative_path(path, base_dir = PathUtil.pwd)
8
+ def relative_path(path, base_dir = Dir.pwd)
9
9
  # Optimization for the common case where path begins with the base
10
10
  # dir. Just cut off the first part.
11
11
  if path.start_with?(base_dir)
@@ -24,7 +24,7 @@ module RuboCop
24
24
 
25
25
  def smart_path(path)
26
26
  # Ideally, we calculate this relative to the project root.
27
- base_dir = PathUtil.pwd
27
+ base_dir = Dir.pwd
28
28
 
29
29
  if path.start_with? base_dir
30
30
  relative_path(path, base_dir)
@@ -40,7 +40,7 @@ module RuboCop
40
40
  hidden_file_in_not_hidden_dir?(pattern, path)
41
41
  when Regexp
42
42
  begin
43
- path =~ pattern
43
+ pattern.match?(path)
44
44
  rescue ArgumentError => e
45
45
  return false if e.message.start_with?('invalid byte sequence')
46
46
 
@@ -51,29 +51,29 @@ module RuboCop
51
51
 
52
52
  # Returns true for an absolute Unix or Windows path.
53
53
  def absolute?(path)
54
- path =~ %r{\A([A-Z]:)?/}i
54
+ %r{\A([A-Z]:)?/}i.match?(path)
55
55
  end
56
56
 
57
- def self.pwd
58
- @pwd ||= Dir.pwd
57
+ def hidden_file_in_not_hidden_dir?(pattern, path)
58
+ hidden_file?(path) &&
59
+ File.fnmatch?(
60
+ pattern, path,
61
+ File::FNM_PATHNAME | File::FNM_EXTGLOB | File::FNM_DOTMATCH
62
+ ) &&
63
+ !hidden_dir?(path)
59
64
  end
60
65
 
61
- def self.reset_pwd
62
- @pwd = nil
66
+ def hidden_file?(path)
67
+ maybe_hidden_file?(path) && File.basename(path).start_with?('.')
63
68
  end
64
69
 
65
- def self.chdir(dir, &block)
66
- reset_pwd
67
- Dir.chdir(dir, &block)
68
- ensure
69
- reset_pwd
70
- end
70
+ # Loose check to reduce memory allocations
71
+ def maybe_hidden_file?(path)
72
+ separator_index = path.rindex(File::SEPARATOR)
73
+ return false unless separator_index
71
74
 
72
- def hidden_file_in_not_hidden_dir?(pattern, path)
73
- File.fnmatch?(
74
- pattern, path,
75
- File::FNM_PATHNAME | File::FNM_EXTGLOB | File::FNM_DOTMATCH
76
- ) && File.basename(path).start_with?('.') && !hidden_dir?(path)
75
+ dot_index = path.index('.', separator_index + 1)
76
+ dot_index == separator_index + 1
77
77
  end
78
78
 
79
79
  def hidden_dir?(path)
@@ -5,7 +5,7 @@ module RuboCop
5
5
  # on.
6
6
  module Platform
7
7
  def self.windows?
8
- RbConfig::CONFIG['host_os'] =~ /cygwin|mswin|mingw|bccwin|wince|emx/
8
+ /cygwin|mswin|mingw|bccwin|wince|emx/.match?(RbConfig::CONFIG['host_os'])
9
9
  end
10
10
  end
11
11
  end
@@ -8,16 +8,14 @@ module RuboCop
8
8
  #
9
9
  # require 'rubocop/rake_task'
10
10
  # RuboCop::RakeTask.new
11
- class RakeTask < Rake::TaskLib
12
- attr_accessor :name
13
- attr_accessor :verbose
14
- attr_accessor :fail_on_error
15
- attr_accessor :patterns
16
- attr_accessor :formatters
17
- attr_accessor :requires
18
- attr_accessor :options
11
+ #
12
+ # Use global Rake namespace here to avoid namespace issues with custom
13
+ # rubocop-rake tasks
14
+ class RakeTask < ::Rake::TaskLib
15
+ attr_accessor :name, :verbose, :fail_on_error, :patterns, :formatters, :requires, :options
19
16
 
20
17
  def initialize(name = :rubocop, *args, &task_block)
18
+ super()
21
19
  setup_ivars(name)
22
20
 
23
21
  desc 'Run RuboCop' unless ::Rake.application.last_description
@@ -69,7 +67,7 @@ module RuboCop
69
67
  task(:auto_correct, *args) do |_, task_args|
70
68
  RakeFileUtils.verbose(verbose) do
71
69
  yield(*[self, task_args].slice(0, task_block.arity)) if block_given?
72
- options = full_options.unshift('--auto-correct')
70
+ options = full_options.unshift('--auto-correct-all')
73
71
  options.delete('--parallel')
74
72
  run_cli(verbose, options)
75
73
  end
@@ -33,7 +33,7 @@ module RuboCop
33
33
 
34
34
  def requires_file_removal?(file_count, config_store)
35
35
  file_count > 1 &&
36
- file_count > config_store.for_dir('.').for_all_cops['MaxFilesInCache']
36
+ file_count > config_store.for_pwd.for_all_cops['MaxFilesInCache']
37
37
  end
38
38
 
39
39
  def remove_oldest_files(files, dirs, cache_root, verbose)
@@ -60,7 +60,7 @@ module RuboCop
60
60
  end
61
61
 
62
62
  def self.cache_root(config_store)
63
- root = config_store.for_dir('.').for_all_cops['CacheRootDirectory']
63
+ root = config_store.for_pwd.for_all_cops['CacheRootDirectory']
64
64
  root ||= if ENV.key?('XDG_CACHE_HOME')
65
65
  # Include user ID in the path to make sure the user has write
66
66
  # access.
@@ -72,7 +72,7 @@ module RuboCop
72
72
  end
73
73
 
74
74
  def self.allow_symlinks_in_cache_location?(config_store)
75
- config_store.for_dir('.').for_all_cops['AllowSymlinksInCacheRootDirectory']
75
+ config_store.for_pwd.for_all_cops['AllowSymlinksInCacheRootDirectory']
76
76
  end
77
77
 
78
78
  def initialize(file, team, options, config_store, cache_root = nil)
@@ -158,6 +158,7 @@ module RuboCop
158
158
  end
159
159
 
160
160
  # The checksum of the rubocop program running the inspection.
161
+ # rubocop:disable Metrics/AbcSize
161
162
  def rubocop_checksum
162
163
  ResultCache.source_checksum ||=
163
164
  begin
@@ -168,13 +169,16 @@ module RuboCop
168
169
  # exe directory. A change to any of them could affect the cop output
169
170
  # so we include them in the cache hash.
170
171
  source_files = $LOADED_FEATURES + Find.find(exe_root).to_a
171
- sources = source_files
172
- .select { |path| File.file?(path) }
173
- .sort
174
- .map { |path| IO.read(path, encoding: Encoding::UTF_8) }
175
- Digest::SHA1.hexdigest(sources.join)
172
+
173
+ digest = Digest::SHA1.new
174
+ source_files
175
+ .select { |path| File.file?(path) }
176
+ .sort!
177
+ .each { |path| digest << File.mtime(path).to_s }
178
+ digest.hexdigest
176
179
  end
177
180
  end
181
+ # rubocop:enable Metrics/AbcSize
178
182
 
179
183
  # Return a hash of the options given at invocation, minus the ones that have
180
184
  # no effect on which offenses and disabled line ranges are found, and thus
@@ -43,14 +43,14 @@ module CopHelper
43
43
  processed_source = parse_source(source, file)
44
44
  _investigate(cop, processed_source)
45
45
 
46
- corrector =
47
- RuboCop::Cop::Corrector.new(processed_source.buffer, cop.corrections)
48
- corrector.rewrite
46
+ @last_corrector.rewrite
49
47
  end
50
48
 
51
49
  def _investigate(cop, processed_source)
52
50
  team = RuboCop::Cop::Team.new([cop], nil, raise_error: true)
53
- team.inspect_file(processed_source)
51
+ report = team.investigate(processed_source)
52
+ @last_corrector = report.correctors.first || RuboCop::Cop::Corrector.new(processed_source)
53
+ report.offenses
54
54
  end
55
55
  end
56
56
 
@@ -72,25 +72,47 @@ module RuboCop
72
72
  #
73
73
  # expect_no_corrections
74
74
  #
75
- # If your code has variables of different lengths, you can use `%{foo}`
76
- # and `^{foo}` to format your template:
75
+ # If your code has variables of different lengths, you can use `%{foo}`,
76
+ # `^{foo}`, and `_{foo}` to format your template; you can also abbreviate
77
+ # offense messages with `[...]`:
77
78
  #
78
79
  # %w[raise fail].each do |keyword|
79
80
  # expect_offense(<<~RUBY, keyword: keyword)
80
81
  # %{keyword}(RuntimeError, msg)
81
- # ^{keyword}^^^^^^^^^^^^^^^^^^^ Redundant `RuntimeError` argument can be removed.
82
+ # ^{keyword}^^^^^^^^^^^^^^^^^^^ Redundant `RuntimeError` argument [...]
82
83
  # RUBY
84
+ #
85
+ # %w[has_one has_many].each do |type|
86
+ # expect_offense(<<~RUBY, type: type)
87
+ # class Book
88
+ # %{type} :chapter, foreign_key: 'book_id'
89
+ # _{type} ^^^^^^^^^^^^^^^^^^^^^^ Specifying the default [...]
90
+ # end
91
+ # RUBY
92
+ # end
93
+ #
94
+ # If you need to specify an offense on a blank line, use the empty `^{}` marker:
95
+ #
96
+ # @example `^{}` empty line offense
97
+ #
98
+ # expect_offense(<<~RUBY)
99
+ #
100
+ # ^{} Missing frozen string literal comment.
101
+ # puts 1
102
+ # RUBY
83
103
  module ExpectOffense
84
104
  def format_offense(source, **replacements)
85
105
  replacements.each do |keyword, value|
106
+ value = value.to_s
86
107
  source = source.gsub("%{#{keyword}}", value)
87
108
  .gsub("^{#{keyword}}", '^' * value.size)
109
+ .gsub("_{#{keyword}}", ' ' * value.size)
88
110
  end
89
111
  source
90
112
  end
91
113
 
92
114
  # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
93
- def expect_offense(source, file = nil, **replacements)
115
+ def expect_offense(source, file = nil, severity: nil, **replacements)
94
116
  source = format_offense(source, **replacements)
95
117
  RuboCop::Formatter::DisabledConfigFormatter
96
118
  .config_to_allow_offenses = {}
@@ -108,11 +130,12 @@ module RuboCop
108
130
 
109
131
  raise 'Error parsing example code' unless @processed_source.valid_syntax?
110
132
 
111
- _investigate(cop, @processed_source)
133
+ offenses = _investigate(cop, @processed_source)
112
134
  actual_annotations =
113
- expected_annotations.with_offense_annotations(cop.offenses)
135
+ expected_annotations.with_offense_annotations(offenses)
114
136
 
115
- expect(actual_annotations.to_s).to eq(expected_annotations.to_s)
137
+ expect(actual_annotations).to eq(expected_annotations), ''
138
+ expect(offenses.map(&:severity).uniq).to eq([severity]) if severity
116
139
  end
117
140
 
118
141
  def expect_correction(correction, loop: true)
@@ -122,12 +145,10 @@ module RuboCop
122
145
  new_source = loop do
123
146
  iteration += 1
124
147
 
125
- corrector =
126
- RuboCop::Cop::Corrector.new(@processed_source.buffer, cop.corrections)
127
- corrected_source = corrector.rewrite
148
+ corrected_source = @last_corrector.rewrite
128
149
 
129
150
  break corrected_source unless loop
130
- break corrected_source if cop.corrections.empty?
151
+ break corrected_source if @last_corrector.empty?
131
152
  break corrected_source if corrected_source == @processed_source.buffer.source
132
153
 
133
154
  if iteration > RuboCop::Runner::MAX_ITERATIONS
@@ -135,9 +156,6 @@ module RuboCop
135
156
  end
136
157
 
137
158
  # Prepare for next loop
138
- cop.instance_variable_set(:@corrections, [])
139
- # Cache invalidation. This is bad!
140
- cop.instance_variable_set(:@token_table, nil)
141
159
  @processed_source = parse_source(corrected_source,
142
160
  @processed_source.path)
143
161
  _investigate(cop, @processed_source)
@@ -150,30 +168,29 @@ module RuboCop
150
168
  def expect_no_corrections
151
169
  raise '`expect_no_corrections` must follow `expect_offense`' unless @processed_source
152
170
 
153
- return if cop.corrections.empty?
171
+ return if @last_corrector.empty?
154
172
 
155
173
  # In order to print a nice diff, e.g. what source got corrected to,
156
174
  # we need to run the actual corrections
157
175
 
158
- corrector =
159
- RuboCop::Cop::Corrector.new(@processed_source.buffer, cop.corrections)
160
- new_source = corrector.rewrite
176
+ new_source = @last_corrector.rewrite
161
177
 
162
178
  expect(new_source).to eq(@processed_source.buffer.source)
163
179
  end
164
180
 
165
181
  def expect_no_offenses(source, file = nil)
166
- inspect_source(source, file)
182
+ offenses = inspect_source(source, file)
167
183
 
168
184
  expected_annotations = AnnotatedSource.parse(source)
169
185
  actual_annotations =
170
- expected_annotations.with_offense_annotations(cop.offenses)
186
+ expected_annotations.with_offense_annotations(offenses)
171
187
  expect(actual_annotations.to_s).to eq(source)
172
188
  end
173
189
 
174
190
  # Parsed representation of code annotated with the `^^^ Message` style
175
191
  class AnnotatedSource
176
- ANNOTATION_PATTERN = /\A\s*\^+ /.freeze
192
+ ANNOTATION_PATTERN = /\A\s*(\^+|\^{}) /.freeze
193
+ ABBREV = "[...]\n"
177
194
 
178
195
  # @param annotated_source [String] string passed to the matchers
179
196
  #
@@ -192,6 +209,7 @@ module RuboCop
192
209
  source << source_line
193
210
  end
194
211
  end
212
+ annotations.each { |a| a[0] = 1 } if source.empty?
195
213
 
196
214
  new(source, annotations)
197
215
  end
@@ -207,6 +225,27 @@ module RuboCop
207
225
  @annotations = annotations.sort.freeze
208
226
  end
209
227
 
228
+ def ==(other)
229
+ other.is_a?(self.class) &&
230
+ other.lines == lines &&
231
+ match_annotations?(other)
232
+ end
233
+
234
+ # Dirty hack: expectations with [...] are rewritten when they match
235
+ # This way the diff is clean.
236
+ def match_annotations?(other)
237
+ annotations.zip(other.annotations) do |(_actual_line, actual_annotation),
238
+ (_expected_line, expected_annotation)|
239
+ if expected_annotation&.end_with?(ABBREV)
240
+ if actual_annotation.start_with?(expected_annotation[0...-ABBREV.length])
241
+ expected_annotation.replace(actual_annotation)
242
+ end
243
+ end
244
+ end
245
+
246
+ annotations == other.annotations
247
+ end
248
+
210
249
  # Construct annotated source string (like what we parse)
211
250
  #
212
251
  # Reconstruct a deterministic annotated source string. This is
@@ -239,6 +278,7 @@ module RuboCop
239
278
 
240
279
  reconstructed.join
241
280
  end
281
+ alias inspect to_s
242
282
 
243
283
  # Return the plain source code without annotations
244
284
  #
@@ -257,6 +297,7 @@ module RuboCop
257
297
  offenses.map do |offense|
258
298
  indent = ' ' * offense.column
259
299
  carets = '^' * offense.column_length
300
+ carets = '^{}' if offense.column_length.zero?
260
301
 
261
302
  [offense.line, "#{indent}#{carets} #{offense.message}\n"]
262
303
  end
@@ -264,7 +305,7 @@ module RuboCop
264
305
  self.class.new(lines, offense_annotations)
265
306
  end
266
307
 
267
- private
308
+ protected
268
309
 
269
310
  attr_reader :lines, :annotations
270
311
  end