rubocop 1.56.3 → 1.57.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +12 -0
  4. data/lib/rubocop/cli.rb +1 -1
  5. data/lib/rubocop/cop/autocorrect_logic.rb +3 -1
  6. data/lib/rubocop/cop/internal_affairs/example_description.rb +42 -22
  7. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +2 -0
  8. data/lib/rubocop/cop/layout/dot_position.rb +1 -5
  9. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +8 -0
  10. data/lib/rubocop/cop/layout/indentation_width.rb +1 -1
  11. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +18 -3
  12. data/lib/rubocop/cop/layout/space_inside_parens.rb +1 -1
  13. data/lib/rubocop/cop/lint/debugger.rb +10 -1
  14. data/lib/rubocop/cop/lint/empty_block.rb +1 -1
  15. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
  16. data/lib/rubocop/cop/lint/mixed_case_range.rb +1 -1
  17. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +0 -1
  18. data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -0
  19. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +20 -4
  20. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +11 -4
  21. data/lib/rubocop/cop/metrics/block_length.rb +1 -1
  22. data/lib/rubocop/cop/metrics/class_length.rb +2 -2
  23. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +2 -2
  24. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +3 -2
  25. data/lib/rubocop/cop/style/class_equality_comparison.rb +5 -0
  26. data/lib/rubocop/cop/style/collection_methods.rb +2 -0
  27. data/lib/rubocop/cop/style/format_string.rb +24 -3
  28. data/lib/rubocop/cop/style/guard_clause.rb +26 -0
  29. data/lib/rubocop/cop/style/identical_conditional_branches.rb +17 -3
  30. data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -1
  31. data/lib/rubocop/cop/style/nested_ternary_operator.rb +3 -11
  32. data/lib/rubocop/cop/style/operator_method_call.rb +6 -0
  33. data/lib/rubocop/cop/style/redundant_begin.rb +9 -1
  34. data/lib/rubocop/cop/style/redundant_conditional.rb +1 -9
  35. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +86 -5
  36. data/lib/rubocop/cop/style/redundant_exception.rb +32 -12
  37. data/lib/rubocop/cop/style/redundant_filter_chain.rb +18 -2
  38. data/lib/rubocop/cop/style/redundant_parentheses.rb +21 -5
  39. data/lib/rubocop/cop/style/return_nil.rb +6 -2
  40. data/lib/rubocop/cop/style/single_line_do_end_block.rb +65 -0
  41. data/lib/rubocop/magic_comment.rb +12 -10
  42. data/lib/rubocop/server/cache.rb +1 -0
  43. data/lib/rubocop/version.rb +1 -1
  44. data/lib/rubocop.rb +1 -0
  45. metadata +10 -9
@@ -55,6 +55,25 @@ module RuboCop
55
55
  # foo || raise('exception') if something
56
56
  # ok
57
57
  #
58
+ # # bad
59
+ # define_method(:test) do
60
+ # if something
61
+ # work
62
+ # end
63
+ # end
64
+ #
65
+ # # good
66
+ # define_method(:test) do
67
+ # return unless something
68
+ #
69
+ # work
70
+ # end
71
+ #
72
+ # # also good
73
+ # define_method(:test) do
74
+ # work if something
75
+ # end
76
+ #
58
77
  # @example AllowConsecutiveConditionals: false (default)
59
78
  # # bad
60
79
  # def test
@@ -110,6 +129,13 @@ module RuboCop
110
129
  end
111
130
  alias on_defs on_def
112
131
 
132
+ def on_block(node)
133
+ return unless node.method?(:define_method) || node.method?(:define_singleton_method)
134
+
135
+ on_def(node)
136
+ end
137
+ alias on_numblock on_block
138
+
113
139
  def on_if(node)
114
140
  return if accepted_form?(node)
115
141
 
@@ -136,7 +136,7 @@ module RuboCop
136
136
 
137
137
  private
138
138
 
139
- # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
139
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
140
140
  def check_branches(node, branches)
141
141
  # return if any branch is empty. An empty branch can be an `if`
142
142
  # without an `else` or a branch that contains only comments.
@@ -149,9 +149,15 @@ module RuboCop
149
149
  branches.any? { |branch| single_child_branch?(branch) }
150
150
 
151
151
  heads = branches.map { |branch| head(branch) }
152
- check_expressions(node, heads, :before_condition) if duplicated_expressions?(node, heads)
152
+
153
+ return unless duplicated_expressions?(node, heads)
154
+
155
+ condition_variable = assignable_condition_value(node)
156
+ return if heads.first.assignment? && condition_variable == heads.first.name.to_s
157
+
158
+ check_expressions(node, heads, :before_condition)
153
159
  end
154
- # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
160
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
155
161
 
156
162
  def duplicated_expressions?(node, expressions)
157
163
  unique_expressions = expressions.uniq
@@ -164,6 +170,14 @@ module RuboCop
164
170
  node.condition.child_nodes.none? { |n| n.source == lhs.source if n.variable? }
165
171
  end
166
172
 
173
+ def assignable_condition_value(node)
174
+ if node.condition.call_type?
175
+ (receiver = node.condition.receiver) ? receiver.source : node.condition.source
176
+ elsif node.condition.variable?
177
+ node.condition.source
178
+ end
179
+ end
180
+
167
181
  # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
168
182
  def check_expressions(node, expressions, insert_position)
169
183
  return if expressions.any?(&:nil?)
@@ -28,7 +28,7 @@ module RuboCop
28
28
  MSG = 'Avoid multi-line chains of blocks.'
29
29
 
30
30
  def on_block(node)
31
- node.send_node.each_node(:send) do |send_node|
31
+ node.send_node.each_node(:send, :csend) do |send_node|
32
32
  receiver = send_node.receiver
33
33
 
34
34
  next unless (receiver&.block_type? || receiver&.numblock_type?) && receiver&.multiline?
@@ -27,24 +27,16 @@ module RuboCop
27
27
 
28
28
  node.each_descendant(:if).select(&:ternary?).each do |nested_ternary|
29
29
  add_offense(nested_ternary) do |corrector|
30
- if_node = if_node(nested_ternary)
31
- next if part_of_ignored_node?(if_node)
30
+ next if part_of_ignored_node?(node)
32
31
 
33
- autocorrect(corrector, if_node)
34
- ignore_node(if_node)
32
+ autocorrect(corrector, node)
33
+ ignore_node(node)
35
34
  end
36
35
  end
37
36
  end
38
37
 
39
38
  private
40
39
 
41
- def if_node(node)
42
- node = node.parent
43
- return node if node.if_type?
44
-
45
- if_node(node)
46
- end
47
-
48
40
  def autocorrect(corrector, if_node)
49
41
  replace_loc_and_whitespace(corrector, if_node.loc.question, "\n")
50
42
  replace_loc_and_whitespace(corrector, if_node.loc.colon, "\nelse\n")
@@ -23,6 +23,7 @@ module RuboCop
23
23
  MSG = 'Redundant dot detected.'
24
24
  RESTRICT_ON_SEND = %i[| ^ & <=> == === =~ > >= < <= << >> + - * / % ** ~ ! != !~].freeze
25
25
 
26
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
26
27
  def on_send(node)
27
28
  return unless (dot = node.loc.dot)
28
29
  return if node.receiver.const_type? || !node.arguments.one?
@@ -33,8 +34,12 @@ module RuboCop
33
34
  add_offense(dot) do |corrector|
34
35
  wrap_in_parentheses_if_chained(corrector, node)
35
36
  corrector.replace(dot, ' ')
37
+
38
+ selector = node.loc.selector
39
+ corrector.insert_after(selector, ' ') if selector.end_pos == rhs.source_range.begin_pos
36
40
  end
37
41
  end
42
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
38
43
 
39
44
  private
40
45
 
@@ -54,6 +59,7 @@ module RuboCop
54
59
 
55
60
  def wrap_in_parentheses_if_chained(corrector, node)
56
61
  return unless node.parent&.call_type?
62
+ return if node.parent.first_argument == node
57
63
 
58
64
  operator = node.loc.selector
59
65
 
@@ -114,7 +114,7 @@ module RuboCop
114
114
  if node.parent&.assignment?
115
115
  replace_begin_with_statement(corrector, offense_range, node)
116
116
  else
117
- corrector.remove(offense_range)
117
+ remove_begin(corrector, offense_range, node)
118
118
  end
119
119
 
120
120
  if use_modifier_form_after_multiline_begin_block?(node)
@@ -136,6 +136,14 @@ module RuboCop
136
136
  restore_removed_comments(corrector, offense_range, node, first_child)
137
137
  end
138
138
 
139
+ def remove_begin(corrector, offense_range, node)
140
+ if node.parent.respond_to?(:endless?) && node.parent.endless?
141
+ offense_range = range_with_surrounding_space(offense_range, newlines: true)
142
+ end
143
+
144
+ corrector.remove(offense_range)
145
+ end
146
+
139
147
  # Restore comments that occur between "begin" and "first_child".
140
148
  # These comments will be moved to above the assignment line.
141
149
  def restore_removed_comments(corrector, offense_range, node, first_child)
@@ -70,19 +70,11 @@ module RuboCop
70
70
 
71
71
  def replacement_condition(node)
72
72
  condition = node.condition.source
73
- expression = invert_expression?(node) ? "!(#{condition})" : condition
73
+ expression = redundant_condition_inverted?(node) ? "!(#{condition})" : condition
74
74
 
75
75
  node.elsif? ? indented_else_node(expression, node) : expression
76
76
  end
77
77
 
78
- def invert_expression?(node)
79
- (
80
- (node.if? || node.elsif? || node.ternary?) && redundant_condition_inverted?(node)
81
- ) || (
82
- node.unless? && redundant_condition?(node)
83
- )
84
- end
85
-
86
78
  def indented_else_node(expression, node)
87
79
  "else\n#{indentation(node)}#{expression}"
88
80
  end
@@ -13,25 +13,68 @@ module RuboCop
13
13
  # # good
14
14
  # do_something(foo: bar, baz: qux)
15
15
  #
16
+ # # bad
17
+ # do_something(**{foo: bar, baz: qux}.merge(options))
18
+ #
19
+ # # good
20
+ # do_something(foo: bar, baz: qux, **options)
21
+ #
16
22
  class RedundantDoubleSplatHashBraces < Base
17
23
  extend AutoCorrector
18
24
 
19
25
  MSG = 'Remove the redundant double splat and braces, use keyword arguments directly.'
26
+ MERGE_METHODS = %i[merge merge!].freeze
20
27
 
28
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
21
29
  def on_hash(node)
22
30
  return if node.pairs.empty? || node.pairs.any?(&:hash_rocket?)
23
31
  return unless (parent = node.parent)
24
- return unless parent.kwsplat_type?
32
+ return if parent.call_type? && !merge_method?(parent)
33
+ return unless (kwsplat = node.each_ancestor(:kwsplat).first)
34
+ return if allowed_double_splat_receiver?(kwsplat)
25
35
 
26
- add_offense(parent) do |corrector|
27
- corrector.remove(parent.loc.operator)
28
- corrector.remove(opening_brace(node))
29
- corrector.remove(closing_brace(node))
36
+ add_offense(kwsplat) do |corrector|
37
+ autocorrect(corrector, node, kwsplat)
30
38
  end
31
39
  end
40
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
32
41
 
33
42
  private
34
43
 
44
+ def allowed_double_splat_receiver?(kwsplat)
45
+ return false unless kwsplat.children.first.call_type?
46
+
47
+ root_receiver = root_receiver(kwsplat.children.first)
48
+
49
+ !root_receiver&.hash_type?
50
+ end
51
+
52
+ def autocorrect(corrector, node, kwsplat)
53
+ corrector.remove(kwsplat.loc.operator)
54
+ corrector.remove(opening_brace(node))
55
+ corrector.remove(closing_brace(node))
56
+
57
+ merge_methods = select_merge_method_nodes(kwsplat)
58
+ return if merge_methods.empty?
59
+
60
+ autocorrect_merge_methods(corrector, merge_methods, kwsplat)
61
+ end
62
+
63
+ def root_receiver(node)
64
+ receiver = node.receiver
65
+ if receiver&.receiver
66
+ root_receiver(receiver)
67
+ else
68
+ receiver
69
+ end
70
+ end
71
+
72
+ def select_merge_method_nodes(kwsplat)
73
+ extract_send_methods(kwsplat).select do |node|
74
+ merge_method?(node)
75
+ end
76
+ end
77
+
35
78
  def opening_brace(node)
36
79
  node.loc.begin.join(node.children.first.source_range.begin)
37
80
  end
@@ -39,6 +82,44 @@ module RuboCop
39
82
  def closing_brace(node)
40
83
  node.children.last.source_range.end.join(node.loc.end)
41
84
  end
85
+
86
+ def autocorrect_merge_methods(corrector, merge_methods, kwsplat)
87
+ range = range_of_merge_methods(merge_methods)
88
+
89
+ new_kwsplat_arguments = extract_send_methods(kwsplat).map do |descendant|
90
+ convert_to_new_arguments(descendant)
91
+ end
92
+ new_source = new_kwsplat_arguments.compact.reverse.unshift('').join(', ')
93
+
94
+ corrector.replace(range, new_source)
95
+ end
96
+
97
+ def range_of_merge_methods(merge_methods)
98
+ begin_merge_method = merge_methods.last
99
+ end_merge_method = merge_methods.first
100
+
101
+ begin_merge_method.loc.dot.begin.join(end_merge_method.source_range.end)
102
+ end
103
+
104
+ def extract_send_methods(kwsplat)
105
+ kwsplat.each_descendant(:send, :csend)
106
+ end
107
+
108
+ def convert_to_new_arguments(node)
109
+ return unless merge_method?(node)
110
+
111
+ node.arguments.map do |arg|
112
+ if arg.hash_type?
113
+ arg.source
114
+ else
115
+ "**#{arg.source}"
116
+ end
117
+ end
118
+ end
119
+
120
+ def merge_method?(node)
121
+ MERGE_METHODS.include?(node.method_name)
122
+ end
42
123
  end
43
124
  end
44
125
  end
@@ -5,17 +5,21 @@ module RuboCop
5
5
  module Style
6
6
  # Checks for RuntimeError as the argument of raise/fail.
7
7
  #
8
- # It checks for code like this:
9
- #
10
8
  # @example
11
- # # Bad
9
+ # # bad
12
10
  # raise RuntimeError, 'message'
13
- #
14
- # # Bad
15
11
  # raise RuntimeError.new('message')
16
12
  #
17
- # # Good
13
+ # # good
18
14
  # raise 'message'
15
+ #
16
+ # # bad - message is not a string
17
+ # raise RuntimeError, Object.new
18
+ # raise RuntimeError.new(Object.new)
19
+ #
20
+ # # good
21
+ # raise Object.new.to_s
22
+ #
19
23
  class RedundantException < Base
20
24
  extend AutoCorrector
21
25
 
@@ -30,26 +34,42 @@ module RuboCop
30
34
  fix_exploded(node) || fix_compact(node)
31
35
  end
32
36
 
37
+ private
38
+
33
39
  def fix_exploded(node)
34
40
  exploded?(node) do |command, message|
35
41
  add_offense(node, message: MSG_1) do |corrector|
36
- if node.parenthesized?
37
- corrector.replace(node, "#{command}(#{message.source})")
38
- else
39
- corrector.replace(node, "#{command} #{message.source}")
40
- end
42
+ corrector.replace(node, replaced_exploded(node, command, message))
41
43
  end
42
44
  end
43
45
  end
44
46
 
47
+ def replaced_exploded(node, command, message)
48
+ arg = string_message?(message) ? message.source : "#{message.source}.to_s"
49
+ arg = node.parenthesized? ? "(#{arg})" : " #{arg}"
50
+ "#{command}#{arg}"
51
+ end
52
+
53
+ def string_message?(message)
54
+ message.str_type? || message.dstr_type? || message.xstr_type?
55
+ end
56
+
45
57
  def fix_compact(node)
46
58
  compact?(node) do |new_call, message|
47
59
  add_offense(node, message: MSG_2) do |corrector|
48
- corrector.replace(new_call, message.source)
60
+ corrector.replace(new_call, replaced_compact(message))
49
61
  end
50
62
  end
51
63
  end
52
64
 
65
+ def replaced_compact(message)
66
+ if string_message?(message)
67
+ message.source
68
+ else
69
+ "#{message.source}.to_s"
70
+ end
71
+ end
72
+
53
73
  # @!method exploded?(node)
54
74
  def_node_matcher :exploded?, <<~PATTERN
55
75
  (send nil? ${:raise :fail} (const {nil? cbase} :RuntimeError) $_)
@@ -6,6 +6,12 @@ module RuboCop
6
6
  # Identifies usages of `any?`, `empty?` or `none?` predicate methods
7
7
  # chained to `select`/`filter`/`find_all` and change them to use predicate method instead.
8
8
  #
9
+ # @safety
10
+ # This cop's autocorrection is unsafe because `array.select.any?` evaluates all elements
11
+ # through the `select` method, while `array.any?` uses short-circuit evaluation.
12
+ # In other words, `array.select.any?` guarantees the evaluation of every element,
13
+ # but `array.any?` does not necessarily evaluate all of them.
14
+ #
9
15
  # @example
10
16
  # # bad
11
17
  # arr.select { |x| x > 1 }.any?
@@ -28,6 +34,9 @@ module RuboCop
28
34
  # # good
29
35
  # arr.select { |x| x > 1 }.many?
30
36
  #
37
+ # # good
38
+ # arr.select { |x| x > 1 }.present?
39
+ #
31
40
  # @example AllCops:ActiveSupportExtensionsEnabled: true
32
41
  # # bad
33
42
  # arr.select { |x| x > 1 }.many?
@@ -35,12 +44,18 @@ module RuboCop
35
44
  # # good
36
45
  # arr.many? { |x| x > 1 }
37
46
  #
47
+ # # bad
48
+ # arr.select { |x| x > 1 }.present?
49
+ #
50
+ # # good
51
+ # arr.any? { |x| x > 1 }
52
+ #
38
53
  class RedundantFilterChain < Base
39
54
  extend AutoCorrector
40
55
 
41
56
  MSG = 'Use `%<prefer>s` instead of `%<first_method>s.%<second_method>s`.'
42
57
 
43
- RAILS_METHODS = %i[many?].freeze
58
+ RAILS_METHODS = %i[many? present?].freeze
44
59
  RESTRICT_ON_SEND = (%i[any? empty? none? one?] + RAILS_METHODS).freeze
45
60
 
46
61
  # @!method select_predicate?(node)
@@ -58,7 +73,8 @@ module RuboCop
58
73
  empty?: :none?,
59
74
  none?: :none?,
60
75
  one?: :one?,
61
- many?: :many?
76
+ many?: :many?,
77
+ present?: :any?
62
78
  }.freeze
63
79
  private_constant :REPLACEMENT_METHODS
64
80
 
@@ -126,16 +126,32 @@ module RuboCop
126
126
 
127
127
  def check(begin_node)
128
128
  node = begin_node.children.first
129
- return offense(begin_node, 'a keyword') if keyword_with_redundant_parentheses?(node)
130
- return offense(begin_node, 'a literal') if disallowed_literal?(begin_node, node)
131
- return offense(begin_node, 'a variable') if node.variable?
132
- return offense(begin_node, 'a constant') if node.const_type?
133
129
 
134
- return offense(begin_node, 'an interpolated expression') if interpolation?(begin_node)
130
+ if (message = find_offense_message(begin_node, node))
131
+ return offense(begin_node, message)
132
+ end
135
133
 
136
134
  check_send(begin_node, node) if node.call_type?
137
135
  end
138
136
 
137
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
138
+ def find_offense_message(begin_node, node)
139
+ return 'a keyword' if keyword_with_redundant_parentheses?(node)
140
+ return 'a literal' if disallowed_literal?(begin_node, node)
141
+ return 'a variable' if node.variable?
142
+ return 'a constant' if node.const_type?
143
+ return 'an interpolated expression' if interpolation?(begin_node)
144
+
145
+ return if begin_node.chained? || !begin_node.parent.nil?
146
+
147
+ if node.and_type? || node.or_type?
148
+ 'a logical expression'
149
+ elsif node.respond_to?(:comparison_method?) && node.comparison_method?
150
+ 'a comparison expression'
151
+ end
152
+ end
153
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
154
+
139
155
  # @!method interpolation?(node)
140
156
  def_node_matcher :interpolation?, '[^begin ^^dstr]'
141
157
 
@@ -3,9 +3,13 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Enforces consistency between 'return nil' and 'return'.
6
+ # Enforces consistency between `return nil` and `return`.
7
7
  #
8
- # Supported styles are: return, return_nil.
8
+ # This cop is disabled by default. Because there seems to be a perceived semantic difference
9
+ # between `return` and `return nil`. The former can be seen as just halting evaluation,
10
+ # while the latter might be used when the return value is of specific concern.
11
+ #
12
+ # Supported styles are `return` and `return_nil`.
9
13
  #
10
14
  # @example EnforcedStyle: return (default)
11
15
  # # bad
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Checks for single-line `do`...`end` block.
7
+ #
8
+ # In practice a single line `do`...`end` is autocorrected when `EnforcedStyle: semantic`
9
+ # in `Style/BlockDelimiters`. The autocorrection maintains the `do` ... `end` syntax to
10
+ # preserve semantics and does not change it to `{`...`}` block.
11
+ #
12
+ # @example
13
+ #
14
+ # # bad
15
+ # foo do |arg| bar(arg) end
16
+ #
17
+ # # good
18
+ # foo do |arg|
19
+ # bar(arg)
20
+ # end
21
+ #
22
+ # # bad
23
+ # ->(arg) do bar(arg) end
24
+ #
25
+ # # good
26
+ # ->(arg) { bar(arg) }
27
+ #
28
+ class SingleLineDoEndBlock < Base
29
+ extend AutoCorrector
30
+
31
+ MSG = 'Prefer multiline `do`...`end` block.'
32
+
33
+ def on_block(node)
34
+ return if !node.single_line? || node.braces?
35
+
36
+ add_offense(node) do |corrector|
37
+ corrector.insert_after(do_line(node), "\n")
38
+
39
+ node_body = node.body
40
+
41
+ if node_body.respond_to?(:heredoc?) && node_body.heredoc?
42
+ corrector.remove(node.loc.end)
43
+ corrector.insert_after(node_body.loc.heredoc_end, "\nend")
44
+ else
45
+ corrector.insert_after(node_body, "\n")
46
+ end
47
+ end
48
+ end
49
+ alias on_numblock on_block
50
+
51
+ private
52
+
53
+ def do_line(node)
54
+ if node.numblock_type? || node.arguments.children.empty? || node.send_node.lambda_literal?
55
+ node.loc.begin
56
+ else
57
+ node.arguments
58
+ end
59
+ end
60
+
61
+ def x(corrector, node); end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -7,7 +7,7 @@ module RuboCop
7
7
  class MagicComment
8
8
  # IRB's pattern for matching magic comment tokens.
9
9
  # @see https://github.com/ruby/ruby/blob/b4a55c1/lib/irb/magic-file.rb#L5
10
- TOKEN = /[[:alnum:]\-_]+/.freeze
10
+ TOKEN = '(?<token>[[:alnum:]\-_]+)'
11
11
  KEYWORDS = {
12
12
  encoding: '(?:en)?coding',
13
13
  frozen_string_literal: 'frozen[_-]string[_-]literal',
@@ -129,7 +129,7 @@ module RuboCop
129
129
  # @return [String] if pattern matched
130
130
  # @return [nil] otherwise
131
131
  def extract(pattern)
132
- @comment[pattern, 1]
132
+ @comment[pattern, :token]
133
133
  end
134
134
 
135
135
  # Parent to Vim and Emacs magic comment handling.
@@ -157,10 +157,10 @@ module RuboCop
157
157
  # @return [String] extracted value if it is found
158
158
  # @return [nil] otherwise
159
159
  def match(keyword)
160
- pattern = /\A#{keyword}\s*#{self.class::OPERATOR}\s*(#{TOKEN})\z/
160
+ pattern = /\A#{keyword}\s*#{self.class::OPERATOR}\s*#{TOKEN}\z/
161
161
 
162
162
  tokens.each do |token|
163
- next unless (value = token[pattern, 1])
163
+ next unless (value = token[pattern, :token])
164
164
 
165
165
  return value.downcase
166
166
  end
@@ -188,7 +188,7 @@ module RuboCop
188
188
  # @see https://www.gnu.org/software/emacs/manual/html_node/emacs/Specify-Coding.html
189
189
  # @see https://github.com/ruby/ruby/blob/3f306dc/parse.y#L6873-L6892 Emacs handling in parse.y
190
190
  class EmacsComment < EditorComment
191
- REGEXP = /-\*-(.+)-\*-/.freeze
191
+ REGEXP = /-\*-(?<token>.+)-\*-/.freeze
192
192
  FORMAT = '# -*- %s -*-'
193
193
  SEPARATOR = ';'
194
194
  OPERATOR = ':'
@@ -216,7 +216,7 @@ module RuboCop
216
216
  #
217
217
  # comment.encoding # => 'ascii-8bit'
218
218
  class VimComment < EditorComment
219
- REGEXP = /#\s*vim:\s*(.+)/.freeze
219
+ REGEXP = /#\s*vim:\s*(?<token>.+)/.freeze
220
220
  FORMAT = '# vim: %s'
221
221
  SEPARATOR = ', '
222
222
  OPERATOR = '='
@@ -259,9 +259,11 @@ module RuboCop
259
259
  # comment2.frozen_string_literal # => nil
260
260
  # comment2.encoding # => 'utf-8'
261
261
  class SimpleComment < MagicComment
262
+ FSTRING_LITERAL_COMMENT = 'frozen_string_literal:\s*(true|false)'
263
+
262
264
  # Match `encoding` or `coding`
263
265
  def encoding
264
- extract(/\A\s*\#.*\b#{KEYWORDS[:encoding]}: (#{TOKEN})/io)
266
+ extract(/\A\s*\#\s*(#{FSTRING_LITERAL_COMMENT})?\s*#{KEYWORDS[:encoding]}: (#{TOKEN})/io)
265
267
  end
266
268
 
267
269
  # Rewrite the comment without a given token type
@@ -283,15 +285,15 @@ module RuboCop
283
285
  # Case-insensitive and dashes/underscores are acceptable.
284
286
  # @see https://github.com/ruby/ruby/blob/78b95b4/parse.y#L7134-L7138
285
287
  def extract_frozen_string_literal
286
- extract(/\A\s*#\s*#{KEYWORDS[:frozen_string_literal]}:\s*(#{TOKEN})\s*\z/io)
288
+ extract(/\A\s*#\s*#{KEYWORDS[:frozen_string_literal]}:\s*#{TOKEN}\s*\z/io)
287
289
  end
288
290
 
289
291
  def extract_shareable_constant_value
290
- extract(/\A\s*#\s*#{KEYWORDS[:shareable_constant_value]}:\s*(#{TOKEN})\s*\z/io)
292
+ extract(/\A\s*#\s*#{KEYWORDS[:shareable_constant_value]}:\s*#{TOKEN}\s*\z/io)
291
293
  end
292
294
 
293
295
  def extract_typed
294
- extract(/\A\s*#\s*#{KEYWORDS[:typed]}:\s*(#{TOKEN})\s*\z/io)
296
+ extract(/\A\s*#\s*#{KEYWORDS[:typed]}:\s*#{TOKEN}\s*\z/io)
295
297
  end
296
298
  end
297
299
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'fileutils'
3
4
  require 'pathname'
4
5
  require_relative '../cache_config'
5
6
  require_relative '../config_finder'
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  # This module holds the RuboCop version information.
5
5
  module Version
6
- STRING = '1.56.3'
6
+ STRING = '1.57.1'
7
7
 
8
8
  MSG = '%<version>s (using Parser %<parser_version>s, ' \
9
9
  'rubocop-ast %<rubocop_ast_version>s, ' \
data/lib/rubocop.rb CHANGED
@@ -580,6 +580,7 @@ require_relative 'rubocop/cop/style/redundant_regexp_constructor'
580
580
  require_relative 'rubocop/cop/style/redundant_self_assignment'
581
581
  require_relative 'rubocop/cop/style/redundant_self_assignment_branch'
582
582
  require_relative 'rubocop/cop/style/require_order'
583
+ require_relative 'rubocop/cop/style/single_line_do_end_block'
583
584
  require_relative 'rubocop/cop/style/sole_nested_conditional'
584
585
  require_relative 'rubocop/cop/style/static_class'
585
586
  require_relative 'rubocop/cop/style/map_compact_with_conditional_block'