rubocop 1.18.1 → 1.22.3

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 (249) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +116 -23
  4. data/lib/rubocop/cli.rb +18 -0
  5. data/lib/rubocop/config.rb +5 -0
  6. data/lib/rubocop/config_loader.rb +5 -3
  7. data/lib/rubocop/config_loader_resolver.rb +22 -7
  8. data/lib/rubocop/config_validator.rb +27 -6
  9. data/lib/rubocop/cop/base.rb +3 -3
  10. data/lib/rubocop/cop/bundler/gem_comment.rb +3 -3
  11. data/lib/rubocop/cop/bundler/gem_filename.rb +103 -0
  12. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +45 -21
  13. data/lib/rubocop/cop/bundler/ordered_gems.rb +3 -12
  14. data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +2 -2
  15. data/lib/rubocop/cop/correctors/line_break_corrector.rb +1 -1
  16. data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +11 -10
  17. data/lib/rubocop/cop/correctors/require_library_corrector.rb +23 -0
  18. data/lib/rubocop/cop/documentation.rb +1 -1
  19. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +3 -12
  20. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +31 -24
  21. data/lib/rubocop/cop/generator.rb +14 -8
  22. data/lib/rubocop/cop/internal_affairs/inherit_deprecated_cop_class.rb +34 -0
  23. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +60 -0
  24. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
  25. data/lib/rubocop/cop/internal_affairs/undefined_config.rb +71 -0
  26. data/lib/rubocop/cop/internal_affairs.rb +3 -0
  27. data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
  28. data/lib/rubocop/cop/layout/assignment_indentation.rb +1 -1
  29. data/lib/rubocop/cop/layout/block_alignment.rb +3 -3
  30. data/lib/rubocop/cop/layout/class_structure.rb +7 -2
  31. data/lib/rubocop/cop/layout/dot_position.rb +34 -5
  32. data/lib/rubocop/cop/layout/empty_comment.rb +1 -1
  33. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +9 -0
  34. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +7 -4
  35. data/lib/rubocop/cop/layout/end_alignment.rb +9 -2
  36. data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -1
  37. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +1 -1
  38. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +1 -1
  39. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
  40. data/lib/rubocop/cop/layout/hash_alignment.rb +22 -18
  41. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +1 -1
  42. data/lib/rubocop/cop/layout/heredoc_indentation.rb +0 -7
  43. data/lib/rubocop/cop/layout/indentation_style.rb +2 -2
  44. data/lib/rubocop/cop/layout/indentation_width.rb +1 -1
  45. data/lib/rubocop/cop/layout/leading_comment_space.rb +2 -2
  46. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +36 -17
  47. data/lib/rubocop/cop/layout/line_length.rb +9 -7
  48. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -1
  49. data/lib/rubocop/cop/layout/multiline_block_layout.rb +3 -3
  50. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +3 -0
  51. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +1 -1
  52. data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -0
  53. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +23 -10
  54. data/lib/rubocop/cop/layout/single_line_block_chain.rb +15 -4
  55. data/lib/rubocop/cop/layout/space_after_not.rb +1 -0
  56. data/lib/rubocop/cop/layout/space_around_equals_in_parameter_default.rb +2 -1
  57. data/lib/rubocop/cop/layout/space_around_keyword.rb +2 -2
  58. data/lib/rubocop/cop/layout/space_around_operators.rb +12 -1
  59. data/lib/rubocop/cop/layout/space_before_brackets.rb +1 -0
  60. data/lib/rubocop/cop/layout/space_before_comment.rb +2 -2
  61. data/lib/rubocop/cop/layout/space_inside_parens.rb +78 -32
  62. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +1 -1
  63. data/lib/rubocop/cop/layout/trailing_whitespace.rb +24 -1
  64. data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +111 -0
  65. data/lib/rubocop/cop/lint/ambiguous_range.rb +105 -0
  66. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +5 -2
  67. data/lib/rubocop/cop/lint/assignment_in_condition.rb +7 -5
  68. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +18 -5
  69. data/lib/rubocop/cop/lint/boolean_symbol.rb +5 -0
  70. data/lib/rubocop/cop/lint/debugger.rb +2 -4
  71. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +4 -4
  72. data/lib/rubocop/cop/lint/deprecated_constants.rb +3 -2
  73. data/lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb +24 -1
  74. data/lib/rubocop/cop/lint/duplicate_branch.rb +2 -1
  75. data/lib/rubocop/cop/lint/duplicate_methods.rb +8 -5
  76. data/lib/rubocop/cop/lint/else_layout.rb +10 -6
  77. data/lib/rubocop/cop/lint/empty_in_pattern.rb +1 -1
  78. data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -1
  79. data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -1
  80. data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +12 -3
  81. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +67 -0
  82. data/lib/rubocop/cop/lint/interpolation_check.rb +5 -0
  83. data/lib/rubocop/cop/lint/loop.rb +4 -3
  84. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +5 -1
  85. data/lib/rubocop/cop/lint/number_conversion.rb +12 -1
  86. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -1
  87. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +4 -2
  88. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +17 -0
  89. data/lib/rubocop/cop/lint/percent_string_array.rb +10 -0
  90. data/lib/rubocop/cop/lint/raise_exception.rb +4 -0
  91. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +5 -4
  92. data/lib/rubocop/cop/lint/require_relative_self_path.rb +50 -0
  93. data/lib/rubocop/cop/lint/shadowed_argument.rb +1 -1
  94. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +1 -1
  95. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  96. data/lib/rubocop/cop/lint/triple_quotes.rb +1 -1
  97. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +8 -3
  98. data/lib/rubocop/cop/lint/unused_method_argument.rb +2 -3
  99. data/lib/rubocop/cop/lint/useless_method_definition.rb +3 -2
  100. data/lib/rubocop/cop/lint/useless_setter_call.rb +7 -4
  101. data/lib/rubocop/cop/lint/useless_times.rb +5 -4
  102. data/lib/rubocop/cop/metrics/abc_size.rb +6 -0
  103. data/lib/rubocop/cop/metrics/parameter_lists.rb +5 -2
  104. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  105. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -1
  106. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
  107. data/lib/rubocop/cop/mixin/annotation_comment.rb +57 -34
  108. data/lib/rubocop/cop/mixin/check_line_breakable.rb +2 -2
  109. data/lib/rubocop/cop/mixin/code_length.rb +1 -1
  110. data/lib/rubocop/cop/mixin/documentation_comment.rb +5 -2
  111. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -2
  112. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +23 -1
  113. data/lib/rubocop/cop/mixin/hash_transform_method.rb +9 -4
  114. data/lib/rubocop/cop/mixin/heredoc.rb +5 -0
  115. data/lib/rubocop/cop/mixin/multiline_element_indentation.rb +1 -1
  116. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +2 -2
  117. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
  118. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +9 -1
  119. data/lib/rubocop/cop/mixin/percent_array.rb +18 -7
  120. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +9 -1
  121. data/lib/rubocop/cop/mixin/require_library.rb +59 -0
  122. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
  123. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +2 -2
  124. data/lib/rubocop/cop/mixin/statement_modifier.rb +1 -1
  125. data/lib/rubocop/cop/mixin/string_literals_help.rb +5 -1
  126. data/lib/rubocop/cop/mixin/trailing_body.rb +1 -1
  127. data/lib/rubocop/cop/naming/ascii_identifiers.rb +0 -3
  128. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  129. data/lib/rubocop/cop/naming/constant_name.rb +1 -1
  130. data/lib/rubocop/cop/naming/inclusive_language.rb +27 -10
  131. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +5 -4
  132. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +7 -0
  133. data/lib/rubocop/cop/security/io_methods.rb +49 -0
  134. data/lib/rubocop/cop/security/json_load.rb +8 -7
  135. data/lib/rubocop/cop/security/open.rb +4 -0
  136. data/lib/rubocop/cop/security/yaml_load.rb +4 -0
  137. data/lib/rubocop/cop/style/accessor_grouping.rb +2 -2
  138. data/lib/rubocop/cop/style/and_or.rb +5 -0
  139. data/lib/rubocop/cop/style/arguments_forwarding.rb +13 -2
  140. data/lib/rubocop/cop/style/array_coercion.rb +21 -3
  141. data/lib/rubocop/cop/style/ascii_comments.rb +0 -3
  142. data/lib/rubocop/cop/style/block_delimiters.rb +50 -2
  143. data/lib/rubocop/cop/style/case_equality.rb +6 -9
  144. data/lib/rubocop/cop/style/case_like_if.rb +5 -0
  145. data/lib/rubocop/cop/style/class_and_module_children.rb +9 -0
  146. data/lib/rubocop/cop/style/collection_compact.rb +7 -5
  147. data/lib/rubocop/cop/style/collection_methods.rb +8 -6
  148. data/lib/rubocop/cop/style/combinable_loops.rb +3 -2
  149. data/lib/rubocop/cop/style/comment_annotation.rb +55 -25
  150. data/lib/rubocop/cop/style/commented_keyword.rb +9 -3
  151. data/lib/rubocop/cop/style/conditional_assignment.rb +19 -5
  152. data/lib/rubocop/cop/style/date_time.rb +5 -0
  153. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +1 -1
  154. data/lib/rubocop/cop/style/documentation.rb +23 -8
  155. data/lib/rubocop/cop/style/double_cop_disable_directive.rb +1 -7
  156. data/lib/rubocop/cop/style/double_negation.rb +27 -6
  157. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  158. data/lib/rubocop/cop/style/encoding.rb +26 -15
  159. data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
  160. data/lib/rubocop/cop/style/explicit_block_argument.rb +46 -11
  161. data/lib/rubocop/cop/style/float_division.rb +10 -2
  162. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +14 -3
  163. data/lib/rubocop/cop/style/global_std_stream.rb +4 -0
  164. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +11 -0
  165. data/lib/rubocop/cop/style/hash_each_methods.rb +5 -0
  166. data/lib/rubocop/cop/style/hash_except.rb +4 -3
  167. data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
  168. data/lib/rubocop/cop/style/hash_transform_keys.rb +4 -9
  169. data/lib/rubocop/cop/style/hash_transform_values.rb +4 -6
  170. data/lib/rubocop/cop/style/identical_conditional_branches.rb +32 -5
  171. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +18 -4
  172. data/lib/rubocop/cop/style/infinite_loop.rb +4 -3
  173. data/lib/rubocop/cop/style/inverse_methods.rb +9 -2
  174. data/lib/rubocop/cop/style/lambda_call.rb +1 -1
  175. data/lib/rubocop/cop/style/line_end_concatenation.rb +14 -1
  176. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +6 -6
  177. data/lib/rubocop/cop/style/method_def_parentheses.rb +10 -1
  178. data/lib/rubocop/cop/style/missing_else.rb +7 -0
  179. data/lib/rubocop/cop/style/module_function.rb +8 -9
  180. data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +1 -1
  181. data/lib/rubocop/cop/style/multiline_when_then.rb +1 -1
  182. data/lib/rubocop/cop/style/mutable_constant.rb +79 -14
  183. data/lib/rubocop/cop/style/negated_if.rb +1 -1
  184. data/lib/rubocop/cop/style/negated_unless.rb +1 -1
  185. data/lib/rubocop/cop/style/non_nil_check.rb +2 -2
  186. data/lib/rubocop/cop/style/not.rb +2 -2
  187. data/lib/rubocop/cop/style/numbered_parameters.rb +46 -0
  188. data/lib/rubocop/cop/style/numbered_parameters_limit.rb +50 -0
  189. data/lib/rubocop/cop/style/numeric_literals.rb +7 -8
  190. data/lib/rubocop/cop/style/numeric_predicate.rb +5 -0
  191. data/lib/rubocop/cop/style/optional_arguments.rb +4 -0
  192. data/lib/rubocop/cop/style/optional_boolean_parameter.rb +14 -4
  193. data/lib/rubocop/cop/style/parallel_assignment.rb +1 -1
  194. data/lib/rubocop/cop/style/percent_q_literals.rb +2 -2
  195. data/lib/rubocop/cop/style/preferred_hash_methods.rb +9 -4
  196. data/lib/rubocop/cop/style/quoted_symbols.rb +10 -6
  197. data/lib/rubocop/cop/style/raise_args.rb +1 -1
  198. data/lib/rubocop/cop/style/redundant_argument.rb +19 -9
  199. data/lib/rubocop/cop/style/redundant_begin.rb +25 -0
  200. data/lib/rubocop/cop/style/redundant_condition.rb +2 -3
  201. data/lib/rubocop/cop/style/redundant_fetch_block.rb +4 -0
  202. data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +12 -3
  203. data/lib/rubocop/cop/style/redundant_freeze.rb +4 -4
  204. data/lib/rubocop/cop/style/redundant_interpolation.rb +1 -1
  205. data/lib/rubocop/cop/style/redundant_percent_q.rb +2 -3
  206. data/lib/rubocop/cop/style/redundant_self.rb +10 -0
  207. data/lib/rubocop/cop/style/redundant_self_assignment.rb +4 -3
  208. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +83 -0
  209. data/lib/rubocop/cop/style/redundant_sort.rb +53 -20
  210. data/lib/rubocop/cop/style/regexp_literal.rb +3 -3
  211. data/lib/rubocop/cop/style/return_nil.rb +2 -1
  212. data/lib/rubocop/cop/style/safe_navigation.rb +13 -2
  213. data/lib/rubocop/cop/style/select_by_regexp.rb +139 -0
  214. data/lib/rubocop/cop/style/semicolon.rb +32 -24
  215. data/lib/rubocop/cop/style/single_argument_dig.rb +5 -0
  216. data/lib/rubocop/cop/style/single_line_block_params.rb +3 -1
  217. data/lib/rubocop/cop/style/single_line_methods.rb +25 -15
  218. data/lib/rubocop/cop/style/slicing_with_range.rb +13 -0
  219. data/lib/rubocop/cop/style/sole_nested_conditional.rb +4 -0
  220. data/lib/rubocop/cop/style/special_global_vars.rb +25 -0
  221. data/lib/rubocop/cop/style/static_class.rb +5 -5
  222. data/lib/rubocop/cop/style/string_chars.rb +4 -2
  223. data/lib/rubocop/cop/style/string_concatenation.rb +5 -1
  224. data/lib/rubocop/cop/style/string_hash_keys.rb +4 -0
  225. data/lib/rubocop/cop/style/struct_inheritance.rb +4 -0
  226. data/lib/rubocop/cop/style/swap_values.rb +4 -2
  227. data/lib/rubocop/cop/style/symbol_array.rb +3 -3
  228. data/lib/rubocop/cop/style/symbol_proc.rb +26 -0
  229. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +19 -0
  230. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  231. data/lib/rubocop/cop/style/word_array.rb +23 -5
  232. data/lib/rubocop/cop/style/yoda_condition.rb +24 -7
  233. data/lib/rubocop/cop/style/zero_length_predicate.rb +6 -0
  234. data/lib/rubocop/cop/util.rb +22 -6
  235. data/lib/rubocop/cops_documentation_generator.rb +17 -5
  236. data/lib/rubocop/formatter/git_hub_actions_formatter.rb +1 -1
  237. data/lib/rubocop/magic_comment.rb +44 -15
  238. data/lib/rubocop/options.rb +127 -113
  239. data/lib/rubocop/rake_task.rb +1 -1
  240. data/lib/rubocop/result_cache.rb +3 -3
  241. data/lib/rubocop/rspec/cop_helper.rb +1 -1
  242. data/lib/rubocop/rspec/expect_offense.rb +6 -2
  243. data/lib/rubocop/rspec/parallel_formatter.rb +90 -0
  244. data/lib/rubocop/rspec/support.rb +1 -0
  245. data/lib/rubocop/runner.rb +2 -3
  246. data/lib/rubocop/target_finder.rb +1 -1
  247. data/lib/rubocop/version.rb +1 -1
  248. data/lib/rubocop.rb +14 -2
  249. metadata +21 -5
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module InternalAffairs
6
+ # Looks for references to a cop configuration key that isn't defined in config/default.yml.
7
+ class UndefinedConfig < Base
8
+ ALLOWED_CONFIGURATIONS = %w[
9
+ Safe SafeAutoCorrect AutoCorrect Severity StyleGuide Details Reference Include Exclude
10
+ ].freeze
11
+ RESTRICT_ON_SEND = %i[[] fetch].freeze
12
+ MSG = '`%<name>s` is not defined in the configuration for `%<cop>s` ' \
13
+ 'in `config/default.yml`.'
14
+
15
+ # @!method cop_class_def(node)
16
+ def_node_search :cop_class_def, <<~PATTERN
17
+ (class _ (const _ {:Base :Cop}) ...)
18
+ PATTERN
19
+
20
+ # @!method cop_config_accessor?(node)
21
+ def_node_matcher :cop_config_accessor?, <<~PATTERN
22
+ (send (send nil? :cop_config) {:[] :fetch} ${str sym}...)
23
+ PATTERN
24
+
25
+ def on_new_investigation
26
+ super
27
+ return unless processed_source.ast
28
+
29
+ cop_class = cop_class_def(processed_source.ast).first
30
+ return unless (@cop_class_name = extract_cop_name(cop_class))
31
+
32
+ @config_for_cop = RuboCop::ConfigLoader.default_configuration.for_cop(@cop_class_name)
33
+ end
34
+
35
+ def on_send(node)
36
+ return unless cop_class_name
37
+ return unless (config_name_node = cop_config_accessor?(node))
38
+ return if always_allowed?(config_name_node)
39
+ return if configuration_key_defined?(config_name_node)
40
+
41
+ message = format(MSG, name: config_name_node.value, cop: cop_class_name)
42
+ add_offense(config_name_node, message: message)
43
+ end
44
+
45
+ private
46
+
47
+ attr_reader :config_for_cop, :cop_class_name
48
+
49
+ def extract_cop_name(class_node)
50
+ return unless class_node
51
+
52
+ segments = [class_node].concat(
53
+ class_node.each_ancestor(:class, :module).take_while do |n|
54
+ n.identifier.short_name != :Cop
55
+ end
56
+ )
57
+
58
+ segments.reverse_each.map { |s| s.identifier.short_name }.join('/')
59
+ end
60
+
61
+ def always_allowed?(node)
62
+ ALLOWED_CONFIGURATIONS.include?(node.value)
63
+ end
64
+
65
+ def configuration_key_defined?(node)
66
+ config_for_cop.key?(node.value)
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -2,6 +2,8 @@
2
2
 
3
3
  require_relative 'internal_affairs/empty_line_between_expect_offense_and_correction'
4
4
  require_relative 'internal_affairs/example_description'
5
+ require_relative 'internal_affairs/inherit_deprecated_cop_class'
6
+ require_relative 'internal_affairs/location_line_equality_comparison'
5
7
  require_relative 'internal_affairs/method_name_equal'
6
8
  require_relative 'internal_affairs/node_destructuring'
7
9
  require_relative 'internal_affairs/node_matcher_directive'
@@ -12,4 +14,5 @@ require_relative 'internal_affairs/redundant_let_rubocop_config_new'
12
14
  require_relative 'internal_affairs/redundant_location_argument'
13
15
  require_relative 'internal_affairs/redundant_message_argument'
14
16
  require_relative 'internal_affairs/style_detected_api_use'
17
+ require_relative 'internal_affairs/undefined_config'
15
18
  require_relative 'internal_affairs/useless_message_assertion'
@@ -54,7 +54,7 @@ module RuboCop
54
54
 
55
55
  def on_send(node)
56
56
  first_arg = node.first_argument
57
- return if !multiple_arguments?(node, first_arg) || node.send_type? && node.method?(:[]=)
57
+ return if !multiple_arguments?(node, first_arg) || (node.send_type? && node.method?(:[]=))
58
58
 
59
59
  if first_arg.hash_type? && !first_arg.braces?
60
60
  pairs = first_arg.pairs
@@ -33,7 +33,7 @@ module RuboCop
33
33
  def check_assignment(node, rhs)
34
34
  return unless rhs
35
35
  return unless node.loc.operator
36
- return if node.loc.operator.line == rhs.first_line
36
+ return if same_line?(node.loc.operator, rhs)
37
37
 
38
38
  base = display_column(leftmost_multiple_assignment(node).source_range)
39
39
  check_alignment([rhs], base + configured_indentation_width)
@@ -101,11 +101,11 @@ module RuboCop
101
101
  def block_end_align_target(node)
102
102
  lineage = [node, *node.ancestors]
103
103
 
104
- target = lineage.each_cons(2) do |current, parent|
105
- break current if end_align_target?(current, parent)
104
+ lineage.each_cons(2) do |current, parent|
105
+ return current if end_align_target?(current, parent)
106
106
  end
107
107
 
108
- target || lineage.last
108
+ lineage.last
109
109
  end
110
110
 
111
111
  def end_align_target?(node, parent)
@@ -264,7 +264,8 @@ module RuboCop
264
264
 
265
265
  def source_range_with_comment(node)
266
266
  begin_pos, end_pos =
267
- if node.def_type? && !node.method?(:initialize) || node.send_type? && node.def_modifier?
267
+ if (node.def_type? && !node.method?(:initialize)) ||
268
+ (node.send_type? && node.def_modifier?)
268
269
  start_node = find_visibility_start(node) || node
269
270
  end_node = find_visibility_end(node) || node
270
271
  [begin_pos_with_comment(start_node),
@@ -289,12 +290,16 @@ module RuboCop
289
290
  (node.first_line - 1).downto(1) do |annotation_line|
290
291
  break unless (comment = processed_source.comment_at_line(annotation_line))
291
292
 
292
- first_comment = comment
293
+ first_comment = comment if whole_line_comment_at_line?(annotation_line)
293
294
  end
294
295
 
295
296
  start_line_position(first_comment || node)
296
297
  end
297
298
 
299
+ def whole_line_comment_at_line?(line)
300
+ /\A\s*#/.match?(processed_source.lines[line - 1])
301
+ end
302
+
298
303
  def start_line_position(node)
299
304
  buffer.line_range(node.loc.line).begin_pos - 1
300
305
  end
@@ -68,19 +68,22 @@ module RuboCop
68
68
  end
69
69
 
70
70
  def proper_dot_position?(node)
71
- receiver_line = node.receiver.source_range.end.line
72
- selector_line = selector_range(node).line
71
+ selector_range = selector_range(node)
73
72
 
74
- # receiver and selector are on the same line
75
- return true if selector_line == receiver_line
73
+ return true if same_line?(selector_range, end_range(node.receiver))
76
74
 
75
+ selector_line = selector_range.line
76
+ receiver_line = receiver_end_line(node.receiver)
77
77
  dot_line = node.loc.dot.line
78
78
 
79
79
  # don't register an offense if there is a line comment between the
80
80
  # dot and the selector otherwise, we might break the code while
81
81
  # "correcting" it (even if there is just an extra blank line, treat
82
82
  # it the same)
83
- return true if line_between?(selector_line, dot_line)
83
+ # Also, in the case of a heredoc, the receiver will end after the dot,
84
+ # because the heredoc body is on subsequent lines, so use the highest
85
+ # line to compare to.
86
+ return true if line_between?(selector_line, [receiver_line, dot_line].max)
84
87
 
85
88
  correct_dot_position_style?(dot_line, selector_line)
86
89
  end
@@ -96,7 +99,33 @@ module RuboCop
96
99
  end
97
100
  end
98
101
 
102
+ def receiver_end_line(node)
103
+ if (line = last_heredoc_line(node))
104
+ line
105
+ else
106
+ node.source_range.end.line
107
+ end
108
+ end
109
+
110
+ def last_heredoc_line(node)
111
+ if node.send_type?
112
+ node.arguments.select { |arg| heredoc?(arg) }.map { |arg| arg.loc.heredoc_end.line }.max
113
+ elsif heredoc?(node)
114
+ node.loc.heredoc_end.line
115
+ end
116
+ end
117
+
118
+ def heredoc?(node)
119
+ (node.str_type? || node.dstr_type?) && node.heredoc?
120
+ end
121
+
122
+ def end_range(node)
123
+ node.source_range.end
124
+ end
125
+
99
126
  def selector_range(node)
127
+ return node unless node.call_type?
128
+
100
129
  # l.(1) has no selector, so we use the opening parenthesis instead
101
130
  node.loc.selector || node.loc.begin
102
131
  end
@@ -96,7 +96,7 @@ module RuboCop
96
96
 
97
97
  def autocorrect(corrector, node)
98
98
  previous_token = previous_token(node)
99
- range = if previous_token && node.loc.line == previous_token.line
99
+ range = if previous_token && same_line?(node, previous_token)
100
100
  range_with_surrounding_space(range: node.loc.expression, newlines: false)
101
101
  else
102
102
  range_by_whole_lines(node.loc.expression, include_final_newline: true)
@@ -38,12 +38,14 @@ module RuboCop
38
38
  class EmptyLineAfterGuardClause < Base
39
39
  include RangeHelp
40
40
  extend AutoCorrector
41
+ extend Util
41
42
 
42
43
  MSG = 'Add empty line after guard clause.'
43
44
  END_OF_HEREDOC_LINE = 1
44
45
 
45
46
  def on_if(node)
46
47
  return if correct_style?(node)
48
+ return if multiple_statements_on_line?(node)
47
49
 
48
50
  if node.modifier_form? && (heredoc_node = last_heredoc_argument(node))
49
51
  return if next_line_empty_or_enable_directive_comment?(heredoc_line(node, heredoc_node))
@@ -166,6 +168,13 @@ module RuboCop
166
168
  node
167
169
  end
168
170
  end
171
+
172
+ def multiple_statements_on_line?(node)
173
+ parent = node.parent
174
+ return false unless parent
175
+
176
+ parent.begin_type? && parent.single_line?
177
+ end
169
178
  end
170
179
  end
171
180
  end
@@ -65,21 +65,24 @@ module RuboCop
65
65
  MSG = 'Extra empty line detected %<location>s the `%<keyword>s`.'
66
66
 
67
67
  def on_def(node)
68
- check_body(node.body)
68
+ check_body(node.body, node.loc.line)
69
69
  end
70
70
  alias on_defs on_def
71
71
 
72
72
  def on_kwbegin(node)
73
73
  body, = *node
74
- check_body(body)
74
+ check_body(body, node.loc.line)
75
75
  end
76
76
 
77
77
  private
78
78
 
79
- def check_body(node)
80
- locations = keyword_locations(node)
79
+ def check_body(body, line_of_def_or_kwbegin)
80
+ locations = keyword_locations(body)
81
+
81
82
  locations.each do |loc|
82
83
  line = loc.line
84
+ next if line == line_of_def_or_kwbegin
85
+
83
86
  keyword = loc.source
84
87
  # below the keyword
85
88
  check_line(style, line, message('after', keyword), &:empty?)
@@ -165,9 +165,10 @@ module RuboCop
165
165
  end
166
166
 
167
167
  def alignment_node_for_variable_style(node)
168
- return node.parent if node.case_type? && node.argument?
168
+ return node.parent if node.case_type? && node.argument? && same_line?(node, node.parent)
169
+
170
+ assignment = assignment_or_operator_method(node)
169
171
 
170
- assignment = node.ancestors.find(&:assignment_or_similar?)
171
172
  if assignment && !line_break_before_keyword?(assignment.source_range, node)
172
173
  assignment
173
174
  else
@@ -177,6 +178,12 @@ module RuboCop
177
178
  node
178
179
  end
179
180
  end
181
+
182
+ def assignment_or_operator_method(node)
183
+ node.ancestors.find do |ancestor|
184
+ ancestor.assignment_or_similar? || (ancestor.send_type? && ancestor.operator_method?)
185
+ end
186
+ end
180
187
  end
181
188
  end
182
189
  end
@@ -154,7 +154,7 @@ module RuboCop
154
154
 
155
155
  def on_send(node)
156
156
  return if style != :consistent && enforce_first_argument_with_fixed_indentation?
157
- return if !node.arguments? || bare_operator?(node)
157
+ return if !node.arguments? || bare_operator?(node) || node.setter_method?
158
158
 
159
159
  indent = base_indentation(node) + configured_indentation_width
160
160
 
@@ -115,7 +115,7 @@ module RuboCop
115
115
  left_bracket = array_node.loc.begin
116
116
  first_elem = array_node.values.first
117
117
  if first_elem
118
- return if first_elem.source_range.line == left_bracket.line
118
+ return if same_line?(first_elem, left_bracket)
119
119
 
120
120
  check_first(first_elem, left_bracket, left_parenthesis, 0)
121
121
  end
@@ -116,7 +116,7 @@ module RuboCop
116
116
  first_pair = hash_node.pairs.first
117
117
 
118
118
  if first_pair
119
- return if first_pair.first_line == left_brace.line
119
+ return if same_line?(first_pair, left_brace)
120
120
 
121
121
  if separator_style?(first_pair)
122
122
  check_based_on_longest_key(hash_node, left_brace, left_parenthesis)
@@ -74,7 +74,7 @@ module RuboCop
74
74
  left_parenthesis = def_node.arguments.loc.begin
75
75
  first_elem = def_node.arguments.first
76
76
  return unless first_elem
77
- return if first_elem.source_range.line == left_parenthesis.line
77
+ return if same_line?(first_elem, left_parenthesis)
78
78
 
79
79
  check_first(first_elem, left_parenthesis, nil, 0)
80
80
  end
@@ -213,18 +213,22 @@ module RuboCop
213
213
  check_pairs(node)
214
214
  end
215
215
 
216
- attr_accessor :offences_by, :column_deltas
216
+ attr_accessor :offenses_by, :column_deltas
217
217
 
218
218
  private
219
219
 
220
220
  def autocorrect_incompatible_with_other_cops?(node)
221
- enforce_first_argument_with_fixed_indentation? &&
222
- node.pairs.any? &&
223
- node.parent&.call_type? && node.parent.loc.selector.line == node.pairs.first.loc.line
221
+ return false unless enforce_first_argument_with_fixed_indentation? &&
222
+ node.pairs.any? &&
223
+ node.parent&.call_type?
224
+
225
+ parent_loc = node.parent.loc
226
+ selector = parent_loc.selector || parent_loc.expression
227
+ same_line?(selector, node.pairs.first)
224
228
  end
225
229
 
226
230
  def reset!
227
- self.offences_by = {}
231
+ self.offenses_by = {}
228
232
  self.column_deltas = Hash.new { |hash, key| hash[key] = {} }
229
233
  end
230
234
 
@@ -248,33 +252,33 @@ module RuboCop
248
252
  end
249
253
  end
250
254
 
251
- add_offences
255
+ add_offenses
252
256
  end
253
257
 
254
- def add_offences
255
- kwsplat_offences = offences_by.delete(KeywordSplatAlignment)
256
- register_offences_with_format(kwsplat_offences, KeywordSplatAlignment)
258
+ def add_offenses
259
+ kwsplat_offenses = offenses_by.delete(KeywordSplatAlignment)
260
+ register_offenses_with_format(kwsplat_offenses, KeywordSplatAlignment)
257
261
 
258
- format, offences = offences_by.min_by { |_, v| v.length }
259
- register_offences_with_format(offences, format)
262
+ format, offenses = offenses_by.min_by { |_, v| v.length }
263
+ register_offenses_with_format(offenses, format)
260
264
  end
261
265
 
262
- def register_offences_with_format(offences, format)
263
- (offences || []).each do |offence|
264
- add_offense(offence, message: MESSAGES[format]) do |corrector|
265
- delta = column_deltas[alignment_for(offence).first.class][offence]
266
+ def register_offenses_with_format(offenses, format)
267
+ (offenses || []).each do |offense|
268
+ add_offense(offense, message: MESSAGES[format]) do |corrector|
269
+ delta = column_deltas[alignment_for(offense).first.class][offense]
266
270
 
267
- correct_node(corrector, offence, delta) unless delta.nil?
271
+ correct_node(corrector, offense, delta) unless delta.nil?
268
272
  end
269
273
  end
270
274
  end
271
275
 
272
276
  def check_delta(delta, node:, alignment:)
273
- offences_by[alignment.class] ||= []
277
+ offenses_by[alignment.class] ||= []
274
278
  return if good_alignment? delta
275
279
 
276
280
  column_deltas[alignment.class][node] = delta
277
- offences_by[alignment.class].push(node)
281
+ offenses_by[alignment.class].push(node)
278
282
  end
279
283
 
280
284
  def ignore_hash_argument?(node)
@@ -167,7 +167,7 @@ module RuboCop
167
167
 
168
168
  end_of_outer_send = outermost_send.loc.end
169
169
 
170
- end_of_outer_send.line == end_of_last_arg_of_outer_send.line &&
170
+ same_line?(end_of_outer_send, end_of_last_arg_of_outer_send) &&
171
171
  end_of_outer_send.column == end_of_last_arg_of_outer_send.column + 1
172
172
  end
173
173
 
@@ -143,13 +143,6 @@ module RuboCop
143
143
  indent_level(base_line)
144
144
  end
145
145
 
146
- def indent_level(str)
147
- indentations = str.lines
148
- .map { |line| line[/^\s*/] }
149
- .reject { |line| line.end_with?("\n") }
150
- indentations.empty? ? 0 : indentations.min_by(&:size).size
151
- end
152
-
153
146
  # Returns '~', '-' or nil
154
147
  def heredoc_indent_type(node)
155
148
  node.source[/^<<([~-])/, 1]
@@ -43,7 +43,7 @@ module RuboCop
43
43
  str_ranges = string_literal_ranges(processed_source.ast)
44
44
 
45
45
  processed_source.lines.each.with_index(1) do |line, lineno|
46
- next unless (range = find_offence(line, lineno))
46
+ next unless (range = find_offense(line, lineno))
47
47
  next if in_string_literal?(str_ranges, range)
48
48
 
49
49
  add_offense(range) { |corrector| autocorrect(corrector, range) }
@@ -60,7 +60,7 @@ module RuboCop
60
60
  end
61
61
  end
62
62
 
63
- def find_offence(line, lineno)
63
+ def find_offense(line, lineno)
64
64
  match = if style == :spaces
65
65
  line.match(/\A\s*\t+/)
66
66
  else
@@ -341,7 +341,7 @@ module RuboCop
341
341
  return true unless body_node
342
342
 
343
343
  # Don't check if expression is on same line as "then" keyword, etc.
344
- return true if body_node.loc.line == base_loc.line
344
+ return true if same_line?(body_node, base_loc)
345
345
 
346
346
  return true if starts_with_access_modifier?(body_node)
347
347
 
@@ -57,7 +57,7 @@ module RuboCop
57
57
 
58
58
  def on_new_investigation
59
59
  processed_source.comments.each do |comment|
60
- next unless /\A#+[^#\s=:+-]/.match?(comment.text)
60
+ next unless /\A#+[^#\s=+-]/.match?(comment.text)
61
61
  next if comment.loc.line == 1 && allowed_on_first_line?(comment)
62
62
  next if doxygen_comment_style?(comment)
63
63
  next if gemfile_ruby_comment?(comment)
@@ -77,7 +77,7 @@ module RuboCop
77
77
  end
78
78
 
79
79
  def allowed_on_first_line?(comment)
80
- shebang?(comment) || rackup_config_file? && rackup_options?(comment)
80
+ shebang?(comment) || (rackup_config_file? && rackup_options?(comment))
81
81
  end
82
82
 
83
83
  def shebang?(comment)
@@ -11,8 +11,7 @@ module RuboCop
11
11
  # concatenated string parts shall be indented regardless of `EnforcedStyle` configuration.
12
12
  #
13
13
  # If `EnforcedStyle: indented` is set, it's the second line that shall be indented one step
14
- # more than the first line. Lines 3 and forward shall be aligned with line 2. Here too there
15
- # are exceptions. Values in a hash literal are always aligned.
14
+ # more than the first line. Lines 3 and forward shall be aligned with line 2.
16
15
  #
17
16
  # @example
18
17
  # # bad
@@ -34,29 +33,44 @@ module RuboCop
34
33
  # 'z'
35
34
  # end
36
35
  #
37
- # my_hash = {
38
- # first: 'a message' \
39
- # 'in two parts'
40
- # }
41
- #
42
36
  # @example EnforcedStyle: aligned (default)
43
37
  # # bad
44
38
  # puts 'x' \
45
39
  # 'y'
46
40
  #
41
+ # my_hash = {
42
+ # first: 'a message' \
43
+ # 'in two parts'
44
+ # }
45
+ #
47
46
  # # good
48
47
  # puts 'x' \
49
48
  # 'y'
50
49
  #
50
+ # my_hash = {
51
+ # first: 'a message' \
52
+ # 'in two parts'
53
+ # }
54
+ #
51
55
  # @example EnforcedStyle: indented
52
56
  # # bad
53
57
  # result = 'x' \
54
58
  # 'y'
55
59
  #
60
+ # my_hash = {
61
+ # first: 'a message' \
62
+ # 'in two parts'
63
+ # }
64
+ #
56
65
  # # good
57
66
  # result = 'x' \
58
67
  # 'y'
59
68
  #
69
+ # my_hash = {
70
+ # first: 'a message' \
71
+ # 'in two parts'
72
+ # }
73
+ #
60
74
  class LineEndStringConcatenationIndentation < Base
61
75
  include ConfigurableEnforcedStyle
62
76
  include Alignment
@@ -70,7 +84,7 @@ module RuboCop
70
84
  return unless strings_concatenated_with_backslash?(node)
71
85
 
72
86
  children = node.children
73
- if style == :aligned && !always_indented?(node) || always_aligned?(node)
87
+ if style == :aligned && !always_indented?(node)
74
88
  check_aligned(children, 1)
75
89
  else
76
90
  check_indented(children)
@@ -85,19 +99,15 @@ module RuboCop
85
99
  private
86
100
 
87
101
  def strings_concatenated_with_backslash?(dstr_node)
88
- !dstr_node.heredoc? &&
89
- dstr_node.children.length > 1 &&
90
- dstr_node.children.all? { |c| c.str_type? || c.dstr_type? }
102
+ dstr_node.multiline? &&
103
+ dstr_node.children.all? { |c| c.str_type? || c.dstr_type? } &&
104
+ dstr_node.children.none?(&:multiline?)
91
105
  end
92
106
 
93
107
  def always_indented?(dstr_node)
94
108
  PARENT_TYPES_FOR_INDENTED.include?(dstr_node.parent&.type)
95
109
  end
96
110
 
97
- def always_aligned?(dstr_node)
98
- dstr_node.parent&.pair_type?
99
- end
100
-
101
111
  def check_aligned(children, start_index)
102
112
  base_column = children[start_index - 1].loc.column
103
113
  children[start_index..-1].each do |child|
@@ -108,11 +118,20 @@ module RuboCop
108
118
  end
109
119
 
110
120
  def check_indented(children)
111
- base_column = children[0].source_range.source_line =~ /\S/
112
- @column_delta = base_column + configured_indentation_width - children[1].loc.column
121
+ @column_delta = base_column(children[0]) + configured_indentation_width -
122
+ children[1].loc.column
113
123
  add_offense_and_correction(children[1], MSG_INDENT) if @column_delta != 0
114
124
  end
115
125
 
126
+ def base_column(child)
127
+ grandparent = child.parent.parent
128
+ if grandparent&.type == :pair
129
+ grandparent.loc.column
130
+ else
131
+ child.source_range.source_line =~ /\S/
132
+ end
133
+ end
134
+
116
135
  def add_offense_and_correction(node, message)
117
136
  add_offense(node, message: message) { |corrector| autocorrect(corrector, node) }
118
137
  end
@@ -137,7 +137,7 @@ module RuboCop
137
137
  range = semicolon_token.pos
138
138
  end_pos = range.end_pos
139
139
  next_range = range_between(end_pos, end_pos + 1)
140
- return nil unless next_range.line == range.line
140
+ return nil unless same_line?(next_range, range)
141
141
 
142
142
  next_char = next_range.source
143
143
  return nil if /[\r\n]/.match?(next_char)
@@ -176,15 +176,15 @@ module RuboCop
176
176
  def ignored_line?(line, line_index)
177
177
  matches_ignored_pattern?(line) ||
178
178
  shebang?(line, line_index) ||
179
- heredocs && line_in_permitted_heredoc?(line_index.succ)
179
+ (heredocs && line_in_permitted_heredoc?(line_index.succ))
180
180
  end
181
181
 
182
182
  def shebang?(line, line_index)
183
183
  line_index.zero? && line.start_with?('#!')
184
184
  end
185
185
 
186
- def register_offense(loc, line, line_index)
187
- message = format(MSG, length: line_length(line), max: max)
186
+ def register_offense(loc, line, line_index, length: line_length(line))
187
+ message = format(MSG, length: length, max: max)
188
188
 
189
189
  self.breakable_range = breakable_range_by_line_index[line_index]
190
190
 
@@ -241,9 +241,10 @@ module RuboCop
241
241
  end
242
242
 
243
243
  def check_directive_line(line, line_index)
244
- return if line_length_without_directive(line) <= max
244
+ length_without_directive = line_length_without_directive(line)
245
+ return if length_without_directive <= max
245
246
 
246
- range = max..(line_length_without_directive(line) - 1)
247
+ range = max..(length_without_directive - 1)
247
248
  register_offense(
248
249
  source_range(
249
250
  processed_source.buffer,
@@ -251,7 +252,8 @@ module RuboCop
251
252
  range
252
253
  ),
253
254
  line,
254
- line_index
255
+ line_index,
256
+ length: length_without_directive
255
257
  )
256
258
  end
257
259