rubocop 1.22.1 → 1.24.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 (123) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +88 -8
  4. data/lib/rubocop/cli/command/auto_genenerate_config.rb +1 -1
  5. data/lib/rubocop/cli/command/init_dotfile.rb +1 -1
  6. data/lib/rubocop/cli/command/show_docs_url.rb +48 -0
  7. data/lib/rubocop/cli/command/suggest_extensions.rb +1 -1
  8. data/lib/rubocop/cli.rb +1 -0
  9. data/lib/rubocop/config_loader_resolver.rb +1 -1
  10. data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -1
  11. data/lib/rubocop/cop/bundler/gem_comment.rb +3 -3
  12. data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +1 -1
  13. data/lib/rubocop/cop/correctors/if_then_corrector.rb +55 -0
  14. data/lib/rubocop/cop/documentation.rb +19 -2
  15. data/lib/rubocop/cop/gemspec/date_assignment.rb +2 -10
  16. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +1 -10
  17. data/lib/rubocop/cop/gemspec/require_mfa.rb +146 -0
  18. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +30 -23
  19. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +3 -10
  20. data/lib/rubocop/cop/generator.rb +1 -1
  21. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +60 -0
  22. data/lib/rubocop/cop/internal_affairs/redundant_method_dispatch_node.rb +46 -0
  23. data/lib/rubocop/cop/internal_affairs/undefined_config.rb +3 -1
  24. data/lib/rubocop/cop/internal_affairs.rb +2 -0
  25. data/lib/rubocop/cop/layout/assignment_indentation.rb +1 -1
  26. data/lib/rubocop/cop/layout/block_alignment.rb +3 -3
  27. data/lib/rubocop/cop/layout/comment_indentation.rb +31 -2
  28. data/lib/rubocop/cop/layout/dot_position.rb +13 -7
  29. data/lib/rubocop/cop/layout/empty_comment.rb +1 -1
  30. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +22 -1
  31. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +7 -4
  32. data/lib/rubocop/cop/layout/end_alignment.rb +1 -2
  33. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +1 -1
  34. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +1 -1
  35. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
  36. data/lib/rubocop/cop/layout/hash_alignment.rb +2 -2
  37. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +1 -1
  38. data/lib/rubocop/cop/layout/indentation_width.rb +1 -1
  39. data/lib/rubocop/cop/layout/line_length.rb +1 -1
  40. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -1
  41. data/lib/rubocop/cop/layout/multiline_block_layout.rb +2 -2
  42. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +1 -1
  43. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +1 -1
  44. data/lib/rubocop/cop/layout/space_after_colon.rb +1 -1
  45. data/lib/rubocop/cop/layout/space_before_comment.rb +1 -1
  46. data/lib/rubocop/cop/layout/space_before_first_arg.rb +4 -0
  47. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +11 -5
  48. data/lib/rubocop/cop/layout/space_inside_parens.rb +0 -4
  49. data/lib/rubocop/cop/lint/ambiguous_range.rb +3 -3
  50. data/lib/rubocop/cop/lint/constant_definition_in_block.rb +1 -1
  51. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +16 -4
  52. data/lib/rubocop/cop/lint/deprecated_constants.rb +3 -2
  53. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +6 -0
  54. data/lib/rubocop/cop/lint/else_layout.rb +1 -1
  55. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +4 -0
  56. data/lib/rubocop/cop/lint/number_conversion.rb +5 -2
  57. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +117 -0
  58. data/lib/rubocop/cop/metrics/block_length.rb +1 -0
  59. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +0 -9
  60. data/lib/rubocop/cop/metrics/method_length.rb +1 -0
  61. data/lib/rubocop/cop/metrics/module_length.rb +1 -1
  62. data/lib/rubocop/cop/metrics/parameter_lists.rb +5 -2
  63. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
  64. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -2
  65. data/lib/rubocop/cop/mixin/enforce_superclass.rb +5 -0
  66. data/lib/rubocop/cop/mixin/gemspec_help.rb +30 -0
  67. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +4 -3
  68. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +56 -0
  69. data/lib/rubocop/cop/mixin/hash_transform_method.rb +3 -3
  70. data/lib/rubocop/cop/mixin/multiline_element_indentation.rb +1 -1
  71. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
  72. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
  73. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  74. data/lib/rubocop/cop/mixin/statement_modifier.rb +1 -1
  75. data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -5
  76. data/lib/rubocop/cop/mixin/trailing_body.rb +1 -1
  77. data/lib/rubocop/cop/naming/block_forwarding.rb +102 -0
  78. data/lib/rubocop/cop/naming/file_name.rb +37 -4
  79. data/lib/rubocop/cop/security/json_load.rb +1 -1
  80. data/lib/rubocop/cop/security/open.rb +11 -1
  81. data/lib/rubocop/cop/style/character_literal.rb +8 -1
  82. data/lib/rubocop/cop/style/collection_compact.rb +31 -13
  83. data/lib/rubocop/cop/style/combinable_loops.rb +2 -2
  84. data/lib/rubocop/cop/style/commented_keyword.rb +5 -3
  85. data/lib/rubocop/cop/style/documentation.rb +1 -1
  86. data/lib/rubocop/cop/style/empty_case_condition.rb +10 -0
  87. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  88. data/lib/rubocop/cop/style/file_read.rb +112 -0
  89. data/lib/rubocop/cop/style/file_write.rb +98 -0
  90. data/lib/rubocop/cop/style/format_string_token.rb +2 -1
  91. data/lib/rubocop/cop/style/hash_conversion.rb +2 -1
  92. data/lib/rubocop/cop/style/hash_syntax.rb +22 -0
  93. data/lib/rubocop/cop/style/if_inside_else.rb +15 -0
  94. data/lib/rubocop/cop/style/line_end_concatenation.rb +1 -1
  95. data/lib/rubocop/cop/style/map_to_hash.rb +68 -0
  96. data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +1 -1
  97. data/lib/rubocop/cop/style/multiline_when_then.rb +1 -1
  98. data/lib/rubocop/cop/style/numeric_literals.rb +10 -1
  99. data/lib/rubocop/cop/style/one_line_conditional.rb +18 -39
  100. data/lib/rubocop/cop/style/open_struct_use.rb +69 -0
  101. data/lib/rubocop/cop/style/parentheses_around_condition.rb +12 -2
  102. data/lib/rubocop/cop/style/quoted_symbols.rb +11 -1
  103. data/lib/rubocop/cop/style/redundant_interpolation.rb +17 -3
  104. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +5 -1
  105. data/lib/rubocop/cop/style/redundant_self.rb +1 -1
  106. data/lib/rubocop/cop/style/safe_navigation.rb +1 -5
  107. data/lib/rubocop/cop/style/select_by_regexp.rb +9 -3
  108. data/lib/rubocop/cop/style/single_line_block_params.rb +2 -2
  109. data/lib/rubocop/cop/style/sole_nested_conditional.rb +3 -1
  110. data/lib/rubocop/cop/team.rb +1 -1
  111. data/lib/rubocop/cop/util.rb +11 -1
  112. data/lib/rubocop/formatter/html_formatter.rb +5 -2
  113. data/lib/rubocop/formatter/json_formatter.rb +4 -1
  114. data/lib/rubocop/options.rb +6 -1
  115. data/lib/rubocop/remote_config.rb +2 -4
  116. data/lib/rubocop/result_cache.rb +1 -1
  117. data/lib/rubocop/rspec/parallel_formatter.rb +90 -0
  118. data/lib/rubocop/rspec/support.rb +1 -0
  119. data/lib/rubocop/target_finder.rb +1 -1
  120. data/lib/rubocop/version.rb +1 -1
  121. data/lib/rubocop/yaml_duplication_checker.rb +1 -1
  122. data/lib/rubocop.rb +11 -0
  123. metadata +24 -9
@@ -3,10 +3,11 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Gemspec
6
- # Checks that `required_ruby_version` of gemspec is specified and
7
- # equal to `TargetRubyVersion` of .rubocop.yml.
8
- # Thereby, RuboCop to perform static analysis working on the version
9
- # required by gemspec.
6
+ # Checks that `required_ruby_version` in a gemspec file is set to a valid
7
+ # value (non-blank) and matches `TargetRubyVersion` as set in RuboCop's
8
+ # configuration for the gem.
9
+ #
10
+ # This ensures that RuboCop is using the same Ruby version as the gem.
10
11
  #
11
12
  # @example
12
13
  # # When `TargetRubyVersion` of .rubocop.yml is `2.5`.
@@ -26,6 +27,11 @@ module RuboCop
26
27
  # spec.required_ruby_version = '>= 2.6.0'
27
28
  # end
28
29
  #
30
+ # # bad
31
+ # Gem::Specification.new do |spec|
32
+ # spec.required_ruby_version = ''
33
+ # end
34
+ #
29
35
  # # good
30
36
  # Gem::Specification.new do |spec|
31
37
  # spec.required_ruby_version = '>= 2.5.0'
@@ -49,15 +55,15 @@ module RuboCop
49
55
  class RequiredRubyVersion < Base
50
56
  include RangeHelp
51
57
 
52
- NOT_EQUAL_MSG = '`required_ruby_version` (%<required_ruby_version>s, ' \
53
- 'declared in %<gemspec_filename>s) and `TargetRubyVersion` ' \
58
+ RESTRICT_ON_SEND = %i[required_ruby_version=].freeze
59
+ NOT_EQUAL_MSG = '`required_ruby_version` and `TargetRubyVersion` ' \
54
60
  '(%<target_ruby_version>s, which may be specified in ' \
55
61
  '.rubocop.yml) should be equal.'
56
62
  MISSING_MSG = '`required_ruby_version` should be specified.'
57
63
 
58
- # @!method required_ruby_version(node)
59
- def_node_search :required_ruby_version, <<~PATTERN
60
- (send _ :required_ruby_version= $_)
64
+ # @!method required_ruby_version?(node)
65
+ def_node_search :required_ruby_version?, <<~PATTERN
66
+ (send _ :required_ruby_version= _)
61
67
  PATTERN
62
68
 
63
69
  # @!method defined_ruby_version(node)
@@ -66,27 +72,28 @@ module RuboCop
66
72
  (send (const (const nil? :Gem) :Requirement) :new $(str _))}
67
73
  PATTERN
68
74
 
69
- # rubocop:disable Metrics/AbcSize
70
75
  def on_new_investigation
71
- version_def = required_ruby_version(processed_source.ast).first
76
+ add_global_offense(MISSING_MSG) unless required_ruby_version?(processed_source.ast)
77
+ end
72
78
 
73
- if version_def
74
- ruby_version = extract_ruby_version(defined_ruby_version(version_def))
75
- return if !ruby_version || ruby_version == target_ruby_version.to_s
79
+ def on_send(node)
80
+ version_def = node.first_argument
81
+ return if dynamic_version?(version_def)
76
82
 
77
- add_offense(
78
- version_def.loc.expression,
79
- message: not_equal_message(ruby_version, target_ruby_version)
80
- )
81
- else
82
- range = source_range(processed_source.buffer, 1, 0)
83
- add_offense(range, message: MISSING_MSG)
84
- end
83
+ ruby_version = extract_ruby_version(defined_ruby_version(version_def))
84
+ return if ruby_version == target_ruby_version.to_s
85
+
86
+ add_offense(version_def, message: not_equal_message(ruby_version, target_ruby_version))
85
87
  end
86
- # rubocop:enable Metrics/AbcSize
87
88
 
88
89
  private
89
90
 
91
+ def dynamic_version?(node)
92
+ (node.send_type? && !node.receiver) ||
93
+ node.variable? ||
94
+ node.each_descendant(:send, *RuboCop::AST::Node::VARIABLES).any?
95
+ end
96
+
90
97
  def extract_ruby_version(required_ruby_version)
91
98
  return unless required_ruby_version
92
99
 
@@ -26,20 +26,13 @@ module RuboCop
26
26
  # end
27
27
  #
28
28
  class RubyVersionGlobalsUsage < Base
29
+ include GemspecHelp
30
+
29
31
  MSG = 'Do not use `RUBY_VERSION` in gemspec file.'
30
32
 
31
33
  # @!method ruby_version?(node)
32
34
  def_node_matcher :ruby_version?, '(const {cbase nil?} :RUBY_VERSION)'
33
35
 
34
- # @!method gem_specification?(node)
35
- def_node_search :gem_specification?, <<~PATTERN
36
- (block
37
- (send
38
- (const
39
- (const {cbase nil?} :Gem) :Specification) :new)
40
- ...)
41
- PATTERN
42
-
43
36
  def on_const(node)
44
37
  return unless gem_spec_with_ruby_version?(node)
45
38
 
@@ -49,7 +42,7 @@ module RuboCop
49
42
  private
50
43
 
51
44
  def gem_spec_with_ruby_version?(node)
52
- gem_specification?(processed_source.ast) && ruby_version?(node)
45
+ gem_specification(processed_source.ast) && ruby_version?(node)
53
46
  end
54
47
  end
55
48
  end
@@ -150,7 +150,7 @@ module RuboCop
150
150
  1. Modify the description of #{badge} in config/default.yml
151
151
  2. Implement your new cop in the generated file!
152
152
  3. Commit your new cop with a message such as
153
- e.g. "Add new `#{badge}` cop."
153
+ e.g. "Add new `#{badge}` cop"
154
154
  4. Run `bundle exec rake changelog:new` to generate a changelog entry
155
155
  for your new cop.
156
156
  TODO
@@ -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
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module InternalAffairs
6
+ # Checks for redundant `send_node` method dispatch node.
7
+ #
8
+ # @example
9
+ #
10
+ # # bad
11
+ # node.send_node.method_name
12
+ #
13
+ # # good
14
+ # node.method_name
15
+ #
16
+ # # bad
17
+ # node.send_node.receiver
18
+ #
19
+ # # good
20
+ # node.receiver
21
+ #
22
+ class RedundantMethodDispatchNode < Base
23
+ include RangeHelp
24
+ extend AutoCorrector
25
+
26
+ MSG = 'Remove the redundant `send_node`.'
27
+ RESTRICT_ON_SEND = %i[method_name receiver].freeze
28
+
29
+ # @!method dispatch_method(node)
30
+ def_node_matcher :dispatch_method, <<~PATTERN
31
+ (send $(send _ :send_node) _)
32
+ PATTERN
33
+
34
+ def on_send(node)
35
+ return unless (dispatch_node = dispatch_method(node))
36
+
37
+ range = range_between(dispatch_node.loc.dot.begin_pos, dispatch_node.loc.selector.end_pos)
38
+
39
+ add_offense(range) do |corrector|
40
+ corrector.remove(range)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -14,7 +14,9 @@ module RuboCop
14
14
 
15
15
  # @!method cop_class_def(node)
16
16
  def_node_search :cop_class_def, <<~PATTERN
17
- (class _ (const _ {:Base :Cop}) ...)
17
+ (class _
18
+ (const {nil? (const nil? :Cop) (const (const {cbase nil?} :RuboCop) :Cop)}
19
+ {:Base :Cop}) ...)
18
20
  PATTERN
19
21
 
20
22
  # @!method cop_config_accessor?(node)
@@ -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'
@@ -12,6 +13,7 @@ require_relative 'internal_affairs/redundant_described_class_as_subject'
12
13
  require_relative 'internal_affairs/redundant_let_rubocop_config_new'
13
14
  require_relative 'internal_affairs/redundant_location_argument'
14
15
  require_relative 'internal_affairs/redundant_message_argument'
16
+ require_relative 'internal_affairs/redundant_method_dispatch_node'
15
17
  require_relative 'internal_affairs/style_detected_api_use'
16
18
  require_relative 'internal_affairs/undefined_config'
17
19
  require_relative 'internal_affairs/useless_message_assertion'
@@ -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)
@@ -32,6 +32,19 @@ module RuboCop
32
32
  # true
33
33
  # end
34
34
  #
35
+ # @example AllowForAlignment: false (default)
36
+ # # bad
37
+ # a = 1 # A really long comment
38
+ # # spanning two lines.
39
+ #
40
+ # # good
41
+ # # A really long comment spanning one line.
42
+ # a = 1
43
+ #
44
+ # @example AllowForAlignment: true
45
+ # # good
46
+ # a = 1 # A really long comment
47
+ # # spanning two lines.
35
48
  class CommentIndentation < Base
36
49
  include Alignment
37
50
  extend AutoCorrector
@@ -40,7 +53,7 @@ module RuboCop
40
53
  'instead of %<correct_comment_indentation>d).'
41
54
 
42
55
  def on_new_investigation
43
- processed_source.comments.each { |comment| check(comment) }
56
+ processed_source.comments.each_with_index { |comment, ix| check(comment, ix) }
44
57
  end
45
58
 
46
59
  private
@@ -76,7 +89,7 @@ module RuboCop
76
89
  AlignmentCorrector.correct(corrector, processed_source, comment, @column_delta)
77
90
  end
78
91
 
79
- def check(comment)
92
+ def check(comment, comment_index)
80
93
  return unless own_line_comment?(comment)
81
94
 
82
95
  next_line = line_after_comment(comment)
@@ -94,11 +107,27 @@ module RuboCop
94
107
  return if column == correct_comment_indentation
95
108
  end
96
109
 
110
+ return if correctly_aligned_with_preceding_comment?(comment_index, column)
111
+
97
112
  add_offense(comment, message: message(column, correct_comment_indentation)) do |corrector|
98
113
  autocorrect(corrector, comment)
99
114
  end
100
115
  end
101
116
 
117
+ # Returns true if:
118
+ # a) the cop is configured to allow extra indentation for alignment, and
119
+ # b) the currently inspected comment is aligned with the nearest preceding end-of-line
120
+ # comment.
121
+ def correctly_aligned_with_preceding_comment?(comment_index, column)
122
+ return false unless cop_config['AllowForAlignment']
123
+
124
+ processed_source.comments[0...comment_index].reverse_each do |other_comment|
125
+ return other_comment.loc.column == column unless own_line_comment?(other_comment)
126
+ end
127
+
128
+ false
129
+ end
130
+
102
131
  def message(column, correct_comment_indentation)
103
132
  format(MSG, column: column, correct_comment_indentation: correct_comment_indentation)
104
133
  end
@@ -27,6 +27,10 @@ module RuboCop
27
27
  include RangeHelp
28
28
  extend AutoCorrector
29
29
 
30
+ def self.autocorrect_incompatible_with
31
+ [Style::RedundantSelf]
32
+ end
33
+
30
34
  def on_send(node)
31
35
  return unless node.dot? || ampersand_dot?(node)
32
36
 
@@ -68,18 +72,14 @@ module RuboCop
68
72
  end
69
73
 
70
74
  def proper_dot_position?(node)
71
- selector_line = selector_range(node).line
75
+ selector_range = selector_range(node)
72
76
 
73
- # If the receiver is a HEREDOC and the selector is on the same line
74
- # then there is nothing to do
75
- return true if heredoc?(node.receiver) && node.receiver.loc.first_line == selector_line
77
+ return true if same_line?(selector_range, end_range(node.receiver))
76
78
 
79
+ selector_line = selector_range.line
77
80
  receiver_line = receiver_end_line(node.receiver)
78
81
  dot_line = node.loc.dot.line
79
82
 
80
- # receiver and selector are on the same line
81
- return true if selector_line == receiver_line
82
-
83
83
  # don't register an offense if there is a line comment between the
84
84
  # dot and the selector otherwise, we might break the code while
85
85
  # "correcting" it (even if there is just an extra blank line, treat
@@ -123,7 +123,13 @@ module RuboCop
123
123
  (node.str_type? || node.dstr_type?) && node.heredoc?
124
124
  end
125
125
 
126
+ def end_range(node)
127
+ node.source_range.end
128
+ end
129
+
126
130
  def selector_range(node)
131
+ return node unless node.call_type?
132
+
127
133
  # l.(1) has no selector, so we use the opening parenthesis instead
128
134
  node.loc.selector || node.loc.begin
129
135
  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
 
@@ -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!
@@ -313,7 +313,7 @@ module RuboCop
313
313
  # just give each lambda the same reference and they would all get the
314
314
  # last value of each. A local variable fixes the problem.
315
315
 
316
- if node.value
316
+ if node.value && node.respond_to?(:value_omission?) && !node.value_omission?
317
317
  correct_key_value(corrector, delta, node.key.source_range,
318
318
  node.value.source_range,
319
319
  node.loc.operator)
@@ -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
 
@@ -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)
@@ -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
@@ -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
@@ -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
@@ -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)
@@ -19,7 +19,7 @@ module RuboCop
19
19
  MSG = 'Space missing after colon.'
20
20
 
21
21
  def on_pair(node)
22
- return unless node.colon?
22
+ return if !node.colon? || node.value_omission?
23
23
 
24
24
  colon = node.loc.operator
25
25
 
@@ -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
@@ -28,6 +28,10 @@ module RuboCop
28
28
 
29
29
  MSG = 'Put one space between the method name and the first argument.'
30
30
 
31
+ def self.autocorrect_incompatible_with
32
+ [Style::MethodCallWithArgsParentheses]
33
+ end
34
+
31
35
  def on_send(node)
32
36
  return unless regular_method_call_with_arguments?(node)
33
37