rubocop 1.19.0 → 1.23.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 (236) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +129 -21
  4. data/lib/rubocop/config.rb +5 -0
  5. data/lib/rubocop/config_loader.rb +5 -3
  6. data/lib/rubocop/config_validator.rb +9 -1
  7. data/lib/rubocop/cop/base.rb +3 -3
  8. data/lib/rubocop/cop/bundler/gem_comment.rb +3 -3
  9. data/lib/rubocop/cop/bundler/gem_filename.rb +103 -0
  10. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +45 -21
  11. data/lib/rubocop/cop/bundler/ordered_gems.rb +3 -12
  12. data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +2 -2
  13. data/lib/rubocop/cop/correctors/line_break_corrector.rb +1 -1
  14. data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +11 -10
  15. data/lib/rubocop/cop/documentation.rb +1 -1
  16. data/lib/rubocop/cop/gemspec/date_assignment.rb +2 -10
  17. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +1 -10
  18. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +3 -12
  19. data/lib/rubocop/cop/gemspec/require_mfa.rb +146 -0
  20. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +31 -24
  21. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +3 -10
  22. data/lib/rubocop/cop/generator.rb +14 -8
  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.rb +1 -0
  26. data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
  27. data/lib/rubocop/cop/layout/assignment_indentation.rb +1 -1
  28. data/lib/rubocop/cop/layout/block_alignment.rb +3 -3
  29. data/lib/rubocop/cop/layout/class_structure.rb +2 -1
  30. data/lib/rubocop/cop/layout/dot_position.rb +34 -5
  31. data/lib/rubocop/cop/layout/empty_comment.rb +1 -1
  32. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +22 -1
  33. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +7 -4
  34. data/lib/rubocop/cop/layout/end_alignment.rb +2 -3
  35. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +1 -1
  36. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +1 -1
  37. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
  38. data/lib/rubocop/cop/layout/hash_alignment.rb +1 -1
  39. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +1 -1
  40. data/lib/rubocop/cop/layout/indentation_width.rb +1 -1
  41. data/lib/rubocop/cop/layout/leading_comment_space.rb +1 -1
  42. data/lib/rubocop/cop/layout/line_length.rb +9 -7
  43. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -1
  44. data/lib/rubocop/cop/layout/multiline_block_layout.rb +3 -3
  45. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +3 -0
  46. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +1 -1
  47. data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -0
  48. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +6 -5
  49. data/lib/rubocop/cop/layout/single_line_block_chain.rb +15 -4
  50. data/lib/rubocop/cop/layout/space_after_not.rb +1 -0
  51. data/lib/rubocop/cop/layout/space_around_equals_in_parameter_default.rb +2 -1
  52. data/lib/rubocop/cop/layout/space_around_keyword.rb +2 -2
  53. data/lib/rubocop/cop/layout/space_before_brackets.rb +1 -0
  54. data/lib/rubocop/cop/layout/space_before_comment.rb +1 -1
  55. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +11 -5
  56. data/lib/rubocop/cop/layout/space_inside_parens.rb +74 -28
  57. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +1 -1
  58. data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +111 -0
  59. data/lib/rubocop/cop/lint/ambiguous_range.rb +11 -11
  60. data/lib/rubocop/cop/lint/assignment_in_condition.rb +7 -5
  61. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +18 -5
  62. data/lib/rubocop/cop/lint/boolean_symbol.rb +5 -0
  63. data/lib/rubocop/cop/lint/debugger.rb +2 -4
  64. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +4 -4
  65. data/lib/rubocop/cop/lint/deprecated_constants.rb +3 -2
  66. data/lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb +24 -1
  67. data/lib/rubocop/cop/lint/else_layout.rb +10 -6
  68. data/lib/rubocop/cop/lint/empty_in_pattern.rb +1 -1
  69. data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -1
  70. data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -1
  71. data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +12 -3
  72. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +67 -0
  73. data/lib/rubocop/cop/lint/interpolation_check.rb +5 -0
  74. data/lib/rubocop/cop/lint/loop.rb +4 -3
  75. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +5 -1
  76. data/lib/rubocop/cop/lint/number_conversion.rb +16 -2
  77. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -1
  78. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +4 -2
  79. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +17 -0
  80. data/lib/rubocop/cop/lint/percent_string_array.rb +10 -0
  81. data/lib/rubocop/cop/lint/raise_exception.rb +4 -0
  82. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +5 -4
  83. data/lib/rubocop/cop/lint/require_relative_self_path.rb +50 -0
  84. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +1 -1
  85. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  86. data/lib/rubocop/cop/lint/triple_quotes.rb +1 -1
  87. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +8 -3
  88. data/lib/rubocop/cop/lint/unused_method_argument.rb +2 -3
  89. data/lib/rubocop/cop/lint/useless_method_definition.rb +3 -2
  90. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +117 -0
  91. data/lib/rubocop/cop/lint/useless_setter_call.rb +7 -4
  92. data/lib/rubocop/cop/lint/useless_times.rb +4 -3
  93. data/lib/rubocop/cop/metrics/abc_size.rb +6 -0
  94. data/lib/rubocop/cop/metrics/parameter_lists.rb +5 -2
  95. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  96. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -1
  97. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
  98. data/lib/rubocop/cop/mixin/annotation_comment.rb +57 -34
  99. data/lib/rubocop/cop/mixin/code_length.rb +1 -1
  100. data/lib/rubocop/cop/mixin/documentation_comment.rb +5 -2
  101. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -2
  102. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +23 -1
  103. data/lib/rubocop/cop/mixin/gemspec_help.rb +30 -0
  104. data/lib/rubocop/cop/mixin/hash_transform_method.rb +3 -3
  105. data/lib/rubocop/cop/mixin/heredoc.rb +1 -3
  106. data/lib/rubocop/cop/mixin/multiline_element_indentation.rb +1 -1
  107. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +2 -2
  108. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
  109. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +9 -1
  110. data/lib/rubocop/cop/mixin/percent_array.rb +11 -3
  111. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +9 -1
  112. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
  113. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  114. data/lib/rubocop/cop/mixin/statement_modifier.rb +1 -1
  115. data/lib/rubocop/cop/mixin/trailing_body.rb +1 -1
  116. data/lib/rubocop/cop/naming/ascii_identifiers.rb +0 -3
  117. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  118. data/lib/rubocop/cop/naming/constant_name.rb +1 -1
  119. data/lib/rubocop/cop/naming/file_name.rb +37 -4
  120. data/lib/rubocop/cop/naming/inclusive_language.rb +9 -9
  121. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +5 -4
  122. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +7 -0
  123. data/lib/rubocop/cop/security/io_methods.rb +49 -0
  124. data/lib/rubocop/cop/security/json_load.rb +8 -7
  125. data/lib/rubocop/cop/security/open.rb +4 -0
  126. data/lib/rubocop/cop/security/yaml_load.rb +4 -0
  127. data/lib/rubocop/cop/style/accessor_grouping.rb +2 -2
  128. data/lib/rubocop/cop/style/and_or.rb +5 -0
  129. data/lib/rubocop/cop/style/arguments_forwarding.rb +13 -2
  130. data/lib/rubocop/cop/style/array_coercion.rb +21 -3
  131. data/lib/rubocop/cop/style/ascii_comments.rb +0 -3
  132. data/lib/rubocop/cop/style/block_delimiters.rb +23 -6
  133. data/lib/rubocop/cop/style/case_equality.rb +6 -9
  134. data/lib/rubocop/cop/style/case_like_if.rb +5 -0
  135. data/lib/rubocop/cop/style/class_and_module_children.rb +9 -0
  136. data/lib/rubocop/cop/style/collection_compact.rb +7 -5
  137. data/lib/rubocop/cop/style/collection_methods.rb +8 -6
  138. data/lib/rubocop/cop/style/combinable_loops.rb +3 -2
  139. data/lib/rubocop/cop/style/comment_annotation.rb +25 -39
  140. data/lib/rubocop/cop/style/commented_keyword.rb +9 -4
  141. data/lib/rubocop/cop/style/date_time.rb +5 -0
  142. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +1 -1
  143. data/lib/rubocop/cop/style/documentation.rb +23 -8
  144. data/lib/rubocop/cop/style/double_negation.rb +27 -6
  145. data/lib/rubocop/cop/style/empty_method.rb +2 -2
  146. data/lib/rubocop/cop/style/encoding.rb +26 -15
  147. data/lib/rubocop/cop/style/explicit_block_argument.rb +21 -11
  148. data/lib/rubocop/cop/style/float_division.rb +10 -2
  149. data/lib/rubocop/cop/style/format_string_token.rb +2 -1
  150. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +7 -2
  151. data/lib/rubocop/cop/style/global_std_stream.rb +4 -0
  152. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +11 -0
  153. data/lib/rubocop/cop/style/hash_each_methods.rb +5 -0
  154. data/lib/rubocop/cop/style/hash_except.rb +4 -3
  155. data/lib/rubocop/cop/style/hash_transform_keys.rb +4 -6
  156. data/lib/rubocop/cop/style/hash_transform_values.rb +4 -6
  157. data/lib/rubocop/cop/style/identical_conditional_branches.rb +18 -16
  158. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +18 -4
  159. data/lib/rubocop/cop/style/infinite_loop.rb +4 -3
  160. data/lib/rubocop/cop/style/inverse_methods.rb +9 -2
  161. data/lib/rubocop/cop/style/lambda_call.rb +1 -1
  162. data/lib/rubocop/cop/style/line_end_concatenation.rb +14 -1
  163. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +6 -6
  164. data/lib/rubocop/cop/style/module_function.rb +8 -9
  165. data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +1 -1
  166. data/lib/rubocop/cop/style/multiline_when_then.rb +1 -1
  167. data/lib/rubocop/cop/style/mutable_constant.rb +73 -6
  168. data/lib/rubocop/cop/style/negated_if.rb +1 -1
  169. data/lib/rubocop/cop/style/negated_unless.rb +1 -1
  170. data/lib/rubocop/cop/style/non_nil_check.rb +2 -2
  171. data/lib/rubocop/cop/style/not.rb +2 -2
  172. data/lib/rubocop/cop/style/numbered_parameters.rb +46 -0
  173. data/lib/rubocop/cop/style/numbered_parameters_limit.rb +50 -0
  174. data/lib/rubocop/cop/style/numeric_literals.rb +7 -8
  175. data/lib/rubocop/cop/style/numeric_predicate.rb +5 -0
  176. data/lib/rubocop/cop/style/open_struct_use.rb +69 -0
  177. data/lib/rubocop/cop/style/optional_arguments.rb +4 -0
  178. data/lib/rubocop/cop/style/optional_boolean_parameter.rb +14 -4
  179. data/lib/rubocop/cop/style/parallel_assignment.rb +1 -1
  180. data/lib/rubocop/cop/style/parentheses_around_condition.rb +12 -2
  181. data/lib/rubocop/cop/style/percent_q_literals.rb +2 -2
  182. data/lib/rubocop/cop/style/preferred_hash_methods.rb +9 -4
  183. data/lib/rubocop/cop/style/quoted_symbols.rb +21 -7
  184. data/lib/rubocop/cop/style/raise_args.rb +1 -1
  185. data/lib/rubocop/cop/style/redundant_argument.rb +19 -9
  186. data/lib/rubocop/cop/style/redundant_begin.rb +25 -0
  187. data/lib/rubocop/cop/style/redundant_condition.rb +2 -3
  188. data/lib/rubocop/cop/style/redundant_fetch_block.rb +4 -0
  189. data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +12 -3
  190. data/lib/rubocop/cop/style/redundant_freeze.rb +4 -4
  191. data/lib/rubocop/cop/style/redundant_interpolation.rb +1 -1
  192. data/lib/rubocop/cop/style/redundant_percent_q.rb +2 -3
  193. data/lib/rubocop/cop/style/redundant_self.rb +10 -0
  194. data/lib/rubocop/cop/style/redundant_self_assignment.rb +4 -3
  195. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +23 -28
  196. data/lib/rubocop/cop/style/redundant_sort.rb +51 -18
  197. data/lib/rubocop/cop/style/regexp_literal.rb +3 -3
  198. data/lib/rubocop/cop/style/return_nil.rb +2 -1
  199. data/lib/rubocop/cop/style/safe_navigation.rb +13 -2
  200. data/lib/rubocop/cop/style/select_by_regexp.rb +139 -0
  201. data/lib/rubocop/cop/style/single_argument_dig.rb +5 -0
  202. data/lib/rubocop/cop/style/slicing_with_range.rb +13 -0
  203. data/lib/rubocop/cop/style/sole_nested_conditional.rb +4 -0
  204. data/lib/rubocop/cop/style/special_global_vars.rb +4 -0
  205. data/lib/rubocop/cop/style/static_class.rb +5 -5
  206. data/lib/rubocop/cop/style/string_chars.rb +4 -2
  207. data/lib/rubocop/cop/style/string_concatenation.rb +5 -1
  208. data/lib/rubocop/cop/style/string_hash_keys.rb +4 -0
  209. data/lib/rubocop/cop/style/struct_inheritance.rb +4 -0
  210. data/lib/rubocop/cop/style/swap_values.rb +4 -2
  211. data/lib/rubocop/cop/style/symbol_array.rb +3 -3
  212. data/lib/rubocop/cop/style/symbol_proc.rb +26 -0
  213. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +19 -0
  214. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  215. data/lib/rubocop/cop/style/word_array.rb +3 -3
  216. data/lib/rubocop/cop/style/yoda_condition.rb +24 -7
  217. data/lib/rubocop/cop/style/zero_length_predicate.rb +6 -0
  218. data/lib/rubocop/cop/util.rb +15 -4
  219. data/lib/rubocop/cops_documentation_generator.rb +17 -5
  220. data/lib/rubocop/formatter/html_formatter.rb +5 -2
  221. data/lib/rubocop/formatter/json_formatter.rb +4 -1
  222. data/lib/rubocop/magic_comment.rb +44 -15
  223. data/lib/rubocop/options.rb +126 -112
  224. data/lib/rubocop/rake_task.rb +1 -1
  225. data/lib/rubocop/remote_config.rb +1 -1
  226. data/lib/rubocop/result_cache.rb +3 -3
  227. data/lib/rubocop/rspec/cop_helper.rb +1 -1
  228. data/lib/rubocop/rspec/expect_offense.rb +6 -2
  229. data/lib/rubocop/rspec/parallel_formatter.rb +90 -0
  230. data/lib/rubocop/rspec/support.rb +1 -0
  231. data/lib/rubocop/runner.rb +2 -3
  232. data/lib/rubocop/target_finder.rb +1 -1
  233. data/lib/rubocop/version.rb +1 -1
  234. data/lib/rubocop/yaml_duplication_checker.rb +1 -1
  235. data/lib/rubocop.rb +14 -2
  236. metadata +20 -5
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module InternalAffairs
6
+ # This cop enforces the use of `same_line?` instead of location line comparison for equality.
7
+ #
8
+ # @example
9
+ # # bad
10
+ # node.loc.line == node.parent.loc.line
11
+ #
12
+ # # bad
13
+ # node.loc.first_line == node.parent.loc.first_line
14
+ #
15
+ # # good
16
+ # same_line?(node, node.parent)
17
+ #
18
+ class LocationLineEqualityComparison < Base
19
+ extend AutoCorrector
20
+
21
+ MSG = 'Use `%<preferred>s`.'
22
+
23
+ # @!method line_send(node)
24
+ def_node_matcher :line_send, <<~PATTERN
25
+ {
26
+ (send (send _ {:loc :source_range}) {:line :first_line})
27
+ (send _ :first_line)
28
+ }
29
+ PATTERN
30
+
31
+ # @!method location_line_equality_comparison?(node)
32
+ def_node_matcher :location_line_equality_comparison?, <<~PATTERN
33
+ (send #line_send :== #line_send)
34
+ PATTERN
35
+
36
+ def on_send(node)
37
+ return unless location_line_equality_comparison?(node)
38
+
39
+ lhs, _op, rhs = *node
40
+
41
+ lhs_receiver = extract_receiver(lhs)
42
+ rhs_receiver = extract_receiver(rhs)
43
+ preferred = "same_line?(#{lhs_receiver}, #{rhs_receiver})"
44
+
45
+ add_offense(node, message: format(MSG, preferred: preferred)) do |corrector|
46
+ corrector.replace(node, preferred)
47
+ end
48
+ end
49
+
50
+ private
51
+
52
+ def extract_receiver(node)
53
+ receiver = node.receiver
54
+ receiver = receiver.receiver if receiver.method?(:loc) || receiver.method?(:source_range)
55
+ receiver.source
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -23,7 +23,7 @@ module RuboCop
23
23
  extend AutoCorrector
24
24
  include RangeHelp
25
25
 
26
- MSG = 'Preceed `%<method>s` with a `@!method` YARD directive.'
26
+ MSG = 'Precede `%<method>s` with a `@!method` YARD directive.'
27
27
  MSG_WRONG_NAME = '`@!method` YARD directive has invalid method name, ' \
28
28
  'use `%<expected>s` instead of `%<actual>s`.'
29
29
  MSG_TOO_MANY = 'Multiple `@!method` YARD directives found for this matcher.'
@@ -3,6 +3,7 @@
3
3
  require_relative 'internal_affairs/empty_line_between_expect_offense_and_correction'
4
4
  require_relative 'internal_affairs/example_description'
5
5
  require_relative 'internal_affairs/inherit_deprecated_cop_class'
6
+ require_relative 'internal_affairs/location_line_equality_comparison'
6
7
  require_relative 'internal_affairs/method_name_equal'
7
8
  require_relative 'internal_affairs/node_destructuring'
8
9
  require_relative 'internal_affairs/node_matcher_directive'
@@ -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),
@@ -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)
@@ -77,13 +77,34 @@ module RuboCop
77
77
  # def b
78
78
  # end
79
79
  #
80
- # @example AllowAdjacentOneLineDefs: true
80
+ # @example AllowAdjacentOneLineDefs: true (default)
81
81
  #
82
82
  # # good
83
83
  # class ErrorA < BaseError; end
84
84
  # class ErrorB < BaseError; end
85
85
  # class ErrorC < BaseError; end
86
86
  #
87
+ # # good
88
+ # class ErrorA < BaseError; end
89
+ #
90
+ # class ErrorB < BaseError; end
91
+ #
92
+ # class ErrorC < BaseError; end
93
+ #
94
+ # @example AllowAdjacentOneLineDefs: false
95
+ #
96
+ # # bad
97
+ # class ErrorA < BaseError; end
98
+ # class ErrorB < BaseError; end
99
+ # class ErrorC < BaseError; end
100
+ #
101
+ # # good
102
+ # class ErrorA < BaseError; end
103
+ #
104
+ # class ErrorB < BaseError; end
105
+ #
106
+ # class ErrorC < BaseError; end
107
+ #
87
108
  class EmptyLineBetweenDefs < Base
88
109
  include RangeHelp
89
110
  extend AutoCorrector
@@ -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,8 +165,7 @@ 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? &&
169
- node.loc.line == node.parent.loc.line
168
+ return node.parent if node.case_type? && node.argument? && same_line?(node, node.parent)
170
169
 
171
170
  assignment = assignment_or_operator_method(node)
172
171
 
@@ -182,7 +181,7 @@ module RuboCop
182
181
 
183
182
  def assignment_or_operator_method(node)
184
183
  node.ancestors.find do |ancestor|
185
- ancestor.assignment_or_similar? || ancestor.send_type? && ancestor.operator_method?
184
+ ancestor.assignment_or_similar? || (ancestor.send_type? && ancestor.operator_method?)
186
185
  end
187
186
  end
188
187
  end
@@ -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
@@ -224,7 +224,7 @@ module RuboCop
224
224
 
225
225
  parent_loc = node.parent.loc
226
226
  selector = parent_loc.selector || parent_loc.expression
227
- selector.line == node.pairs.first.loc.line
227
+ same_line?(selector, node.pairs.first)
228
228
  end
229
229
 
230
230
  def reset!
@@ -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
 
@@ -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
 
@@ -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)
@@ -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
 
@@ -88,7 +88,7 @@ module RuboCop
88
88
  end
89
89
 
90
90
  def check_new_line_offense(node, rhs)
91
- return unless node.loc.operator.line == rhs.first_line
91
+ return unless same_line?(node.loc.operator, rhs)
92
92
 
93
93
  add_offense(node, message: NEW_LINE_OFFENSE) do |corrector|
94
94
  corrector.insert_after(node.loc.operator, "\n")
@@ -63,7 +63,7 @@ module RuboCop
63
63
  add_offense_for_expression(node, node.arguments, ARG_MSG)
64
64
  end
65
65
 
66
- return unless node.body && node.loc.begin.line == node.body.first_line
66
+ return unless node.body && same_line?(node.loc.begin, node.body)
67
67
 
68
68
  add_offense_for_expression(node, node.body, MSG)
69
69
  end
@@ -89,7 +89,7 @@ module RuboCop
89
89
  if node.source.lines.first.end_with?("|\n")
90
90
  PIPE_SIZE
91
91
  else
92
- 1 + PIPE_SIZE * 2
92
+ 1 + (PIPE_SIZE * 2)
93
93
  end
94
94
  end
95
95
 
@@ -110,7 +110,7 @@ module RuboCop
110
110
 
111
111
  expr_before_body ||= node.loc.begin
112
112
 
113
- return unless expr_before_body.line == node.body.first_line
113
+ return unless same_line?(expr_before_body, node.body)
114
114
 
115
115
  autocorrect_body(corrector, node, node.body)
116
116
  end
@@ -6,6 +6,9 @@ module RuboCop
6
6
  # This cop ensures that each argument in a multi-line method call
7
7
  # starts on a separate line.
8
8
  #
9
+ # NOTE: this cop does not move the first argument, if you want that to
10
+ # be on a separate line, see `Layout/FirstMethodArgumentLineBreak`.
11
+ #
9
12
  # @example
10
13
  #
11
14
  # # bad
@@ -75,7 +75,7 @@ module RuboCop
75
75
  def right_hand_side(send_node)
76
76
  dot = send_node.loc.dot
77
77
  selector = send_node.loc.selector
78
- if send_node.dot? && selector && dot.line == selector.line
78
+ if send_node.dot? && selector && same_line?(dot, selector)
79
79
  dot.join(selector)
80
80
  elsif selector
81
81
  selector
@@ -127,6 +127,7 @@ module RuboCop
127
127
  .gsub(/" *\\\n\s*'/, %q(" + ')) # Double quote, backslash, and then single quote
128
128
  .gsub(/' *\\\n\s*"/, %q(' + ")) # Single quote, backslash, and then double quote
129
129
  .gsub(/(["']) *\\\n\s*\1/, '') # Double or single quote, backslash, then same quote
130
+ .gsub(/\n\s*(?=\.\w)/, '') # Extra space within method chaining
130
131
  .gsub(/\s*\\?\n\s*/, ' ') # Any other line break, with or without backslash
131
132
  end
132
133
 
@@ -61,7 +61,7 @@ module RuboCop
61
61
  alignment_loc = alignment_location(alignment_node)
62
62
  kw_loc = node.loc.keyword
63
63
 
64
- return if alignment_loc.column == kw_loc.column || alignment_loc.line == kw_loc.line
64
+ return if alignment_loc.column == kw_loc.column || same_line?(alignment_loc, kw_loc)
65
65
 
66
66
  add_offense(
67
67
  kw_loc, message: format_message(alignment_node, alignment_loc, kw_loc)
@@ -137,17 +137,18 @@ module RuboCop
137
137
  send_node_loc = ancestor_node.send_node.loc
138
138
  do_keyword_line = ancestor_node.loc.begin.line
139
139
  rescue_keyword_column = node.loc.keyword.column
140
- selector = send_node_loc.selector
140
+ selector = send_node_loc.respond_to?(:selector) ? send_node_loc.selector : send_node_loc
141
141
 
142
- if send_node_loc.respond_to?(:dot) && (dot = send_node_loc.dot) &&
143
- aligned_with_leading_dot?(do_keyword_line, dot, rescue_keyword_column)
142
+ if aligned_with_leading_dot?(do_keyword_line, send_node_loc, rescue_keyword_column)
144
143
  return true
145
144
  end
146
145
 
147
146
  do_keyword_line == selector.line && rescue_keyword_column == selector.column
148
147
  end
149
148
 
150
- def aligned_with_leading_dot?(do_keyword_line, dot, rescue_keyword_column)
149
+ def aligned_with_leading_dot?(do_keyword_line, send_node_loc, rescue_keyword_column)
150
+ return false unless send_node_loc.respond_to?(:dot) && (dot = send_node_loc.dot)
151
+
151
152
  do_keyword_line == dot.line && rescue_keyword_column == dot.column
152
153
  end
153
154
 
@@ -37,15 +37,26 @@ module RuboCop
37
37
  return unless receiver&.block_type?
38
38
 
39
39
  receiver_location = receiver.loc
40
- closing_block_delimiter_line_number = receiver_location.end.line
41
- return if receiver_location.begin.line < closing_block_delimiter_line_number
40
+ closing_block_delimiter_line_num = receiver_location.end.line
41
+ return if receiver_location.begin.line < closing_block_delimiter_line_num
42
42
 
43
43
  node_location = node.loc
44
44
  dot_range = node_location.dot
45
45
  return unless dot_range
46
- return if dot_range.line > closing_block_delimiter_line_number
46
+ return unless call_method_after_block?(node, dot_range, closing_block_delimiter_line_num)
47
47
 
48
- range_between(dot_range.begin_pos, node_location.selector.end_pos)
48
+ range_between(dot_range.begin_pos, selector_range(node).end_pos)
49
+ end
50
+
51
+ def call_method_after_block?(node, dot_range, closing_block_delimiter_line_num)
52
+ return false if dot_range.line > closing_block_delimiter_line_num
53
+
54
+ dot_range.column < selector_range(node).column
55
+ end
56
+
57
+ def selector_range(node)
58
+ # l.(1) has no selector, so we use the opening parenthesis instead
59
+ node.loc.selector || node.loc.begin
49
60
  end
50
61
  end
51
62
  end
@@ -16,6 +16,7 @@ module RuboCop
16
16
  extend AutoCorrector
17
17
 
18
18
  MSG = 'Do not leave space between `!` and its argument.'
19
+ RESTRICT_ON_SEND = %i[!].freeze
19
20
 
20
21
  def on_send(node)
21
22
  return unless node.prefix_bang? && whitespace_after_operator?(node)
@@ -47,7 +47,8 @@ module RuboCop
47
47
  space_on_both_sides = space_on_both_sides?(arg, equals)
48
48
  no_surrounding_space = no_surrounding_space?(arg, equals)
49
49
 
50
- if style == :space && space_on_both_sides || style == :no_space && no_surrounding_space
50
+ if (style == :space && space_on_both_sides) ||
51
+ (style == :no_space && no_surrounding_space)
51
52
  correct_style_detected
52
53
  else
53
54
  incorrect_style_detected(arg, value)
@@ -228,8 +228,8 @@ module RuboCop
228
228
  def accepted_opening_delimiter?(range, char)
229
229
  return true unless char
230
230
 
231
- accept_left_square_bracket?(range) && char == '[' ||
232
- accept_left_parenthesis?(range) && char == '('
231
+ (accept_left_square_bracket?(range) && char == '[') ||
232
+ (accept_left_parenthesis?(range) && char == '(')
233
233
  end
234
234
 
235
235
  def accept_left_parenthesis?(range)
@@ -19,6 +19,7 @@ module RuboCop
19
19
  extend AutoCorrector
20
20
 
21
21
  MSG = 'Remove the space before the opening brackets.'
22
+ RESTRICT_ON_SEND = %i[[] []=].freeze
22
23
 
23
24
  def on_send(node)
24
25
  return unless (first_argument = node.first_argument)
@@ -20,7 +20,7 @@ module RuboCop
20
20
  def on_new_investigation
21
21
  processed_source.sorted_tokens.each_cons(2) do |token1, token2|
22
22
  next unless token2.comment?
23
- next unless token1.line == token2.line
23
+ next unless same_line?(token1, token2)
24
24
  next unless token1.pos.end == token2.pos.begin
25
25
 
26
26
  range = token2.pos
@@ -30,15 +30,17 @@ module RuboCop
30
30
  def on_send(node)
31
31
  return unless arrow_lambda_with_args?(node)
32
32
 
33
- lambda_node = range_of_offense(node)
34
-
35
33
  if style == :require_space && !space_after_arrow?(node)
34
+ lambda_node = range_of_offense(node)
35
+
36
36
  add_offense(lambda_node, message: MSG_REQUIRE_SPACE) do |corrector|
37
- corrector.insert_before(node.parent.children[1], ' ')
37
+ corrector.insert_before(lambda_arguments(node), ' ')
38
38
  end
39
39
  elsif style == :require_no_space && space_after_arrow?(node)
40
- add_offense(lambda_node, message: MSG_REQUIRE_NO_SPACE) do |corrector|
41
- corrector.remove(space_after_arrow(node))
40
+ space = space_after_arrow(node)
41
+
42
+ add_offense(space, message: MSG_REQUIRE_NO_SPACE) do |corrector|
43
+ corrector.remove(space)
42
44
  end
43
45
  end
44
46
  end
@@ -66,6 +68,10 @@ module RuboCop
66
68
  node.parent.arguments.loc.expression.end_pos
67
69
  )
68
70
  end
71
+
72
+ def lambda_arguments(node)
73
+ node.parent.children[1]
74
+ end
69
75
  end
70
76
  end
71
77
  end