rubocop 1.53.1 → 1.54.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d7b38b9b2471ab2c5972c061427da41ddf9820f91b21e7fa5d89330b2647eaa5
4
- data.tar.gz: 1a48aaee106f9e6c0459c8c5ef0a98dc39455bf06a68174d6b52ac2ea74abb0d
3
+ metadata.gz: c223b2bb07266543894d986f949feb9b6b0470bb43e511e82c8cdf12e9d48872
4
+ data.tar.gz: a785917f1251d60ebe36a2c41680e62a4b789ff40977b1b81a07e09c562c233c
5
5
  SHA512:
6
- metadata.gz: 181bd1ac83ae045a457b3b5b73bf8e18e964f7413cabfa843d594a10cc7435403827e0b001ef4d5574c0065944e942adb908b0e4bfac8766486f2c58dd10e8e1
7
- data.tar.gz: b14fad843c6eb6ba3aa2e521133fe63da2abfed97fb79b1e45893c055c273180d1f0d0ed25cf53c53885d41859637c4469a2527617bb1c84125331a4eaf24fa3
6
+ metadata.gz: 56c5e545a2440c9994ea57547601d322f940f5dc3215d2e76fc6ef1b59b2bf0a9b73f49c370e9f6eebe1e449bcc71f0e018d8a3d6f70a40a6b585b9034d28aa0
7
+ data.tar.gz: 4c38b1ab3e73fc9cd1579f72331240f3eeebaad1f10ce126fe85f7f57bdba283476310104244b883d90d86c6b78fe1ad2b9ff17b6ff5eb8cc64cf0c3e341dc55
data/README.md CHANGED
@@ -53,7 +53,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
53
53
  in your `Gemfile`:
54
54
 
55
55
  ```rb
56
- gem 'rubocop', '~> 1.53', require: false
56
+ gem 'rubocop', '~> 1.54', require: false
57
57
  ```
58
58
 
59
59
  See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
data/config/default.yml CHANGED
@@ -30,6 +30,7 @@ AllCops:
30
30
  - '**/*.rbx'
31
31
  - '**/*.ru'
32
32
  - '**/*.ruby'
33
+ - '**/*.schema'
33
34
  - '**/*.spec'
34
35
  - '**/*.thor'
35
36
  - '**/*.watchr'
@@ -55,6 +56,7 @@ AllCops:
55
56
  - '**/Puppetfile'
56
57
  - '**/Rakefile'
57
58
  - '**/rakefile'
59
+ - '**/Schemafile'
58
60
  - '**/Snapfile'
59
61
  - '**/Steepfile'
60
62
  - '**/Thorfile'
@@ -577,6 +579,8 @@ Layout/EmptyLineBetweenDefs:
577
579
  EmptyLineBetweenMethodDefs: true
578
580
  EmptyLineBetweenClassDefs: true
579
581
  EmptyLineBetweenModuleDefs: true
582
+ # `DefLikeMacros` takes the name of any macro that you want to treat like a def.
583
+ DefLikeMacros: []
580
584
  # `AllowAdjacentOneLineDefs` means that single line method definitions don't
581
585
  # need an empty line between them. `true` by default.
582
586
  AllowAdjacentOneLineDefs: true
@@ -51,7 +51,9 @@ module RuboCop
51
51
 
52
52
  def extract_receiver(node)
53
53
  receiver = node.receiver
54
- receiver = receiver.receiver if receiver.method?(:loc) || receiver.method?(:source_range)
54
+ if receiver.send_type? && (receiver.method?(:loc) || receiver.method?(:source_range))
55
+ receiver = receiver.receiver
56
+ end
55
57
  receiver.source
56
58
  end
57
59
  end
@@ -135,7 +135,8 @@ module RuboCop
135
135
  return if nodes.all?(&:single_line?) && cop_config['AllowAdjacentOneLineDefs']
136
136
 
137
137
  correction_node = nodes.last
138
- location = correction_node.loc.keyword.join(correction_node.loc.name)
138
+
139
+ location = def_location(correction_node)
139
140
  add_offense(location, message: message(correction_node, count: count)) do |corrector|
140
141
  autocorrect(corrector, *nodes, count)
141
142
  end
@@ -159,10 +160,28 @@ module RuboCop
159
160
 
160
161
  private
161
162
 
163
+ def def_location(correction_node)
164
+ if correction_node.block_type?
165
+ correction_node.source_range.join(correction_node.children.first.source_range)
166
+ else
167
+ correction_node.loc.keyword.join(correction_node.loc.name)
168
+ end
169
+ end
170
+
162
171
  def candidate?(node)
163
172
  return false unless node
164
173
 
165
- method_candidate?(node) || class_candidate?(node) || module_candidate?(node)
174
+ method_candidate?(node) || class_candidate?(node) || module_candidate?(node) ||
175
+ macro_candidate?(node)
176
+ end
177
+
178
+ def empty_line_between_macros
179
+ cop_config.fetch('DefLikeMacros', []).map(&:to_sym)
180
+ end
181
+
182
+ def macro_candidate?(node)
183
+ node.block_type? && node.children.first.macro? &&
184
+ empty_line_between_macros.include?(node.children.first.method_name)
166
185
  end
167
186
 
168
187
  def method_candidate?(node)
@@ -226,7 +245,11 @@ module RuboCop
226
245
  end
227
246
 
228
247
  def def_start(node)
229
- node.loc.keyword.line
248
+ if node.block_type? && node.children.first.send_type?
249
+ node.source_range.line
250
+ else
251
+ node.loc.keyword.line
252
+ end
230
253
  end
231
254
 
232
255
  def def_end(node)
@@ -84,6 +84,8 @@ module RuboCop
84
84
  return unless strings_concatenated_with_backslash?(node)
85
85
 
86
86
  children = node.children
87
+ return if children.empty?
88
+
87
89
  if style == :aligned && !always_indented?(node)
88
90
  check_aligned(children, 1)
89
91
  else
@@ -24,7 +24,15 @@ module RuboCop
24
24
  end
25
25
 
26
26
  def kind(token)
27
- 'comma' if token.comma?
27
+ 'comma' if token.comma? && !before_semicolon?(token)
28
+ end
29
+
30
+ private
31
+
32
+ def before_semicolon?(token)
33
+ tokens = processed_source.tokens
34
+
35
+ tokens[tokens.index(token) + 1].semicolon?
28
36
  end
29
37
  end
30
38
  end
@@ -153,7 +153,9 @@ module RuboCop
153
153
  private
154
154
 
155
155
  def regular_operator?(send_node)
156
- !send_node.unary_operation? && !send_node.dot? && operator_with_regular_syntax?(send_node)
156
+ return false if send_node.unary_operation? || send_node.dot? || send_node.double_colon?
157
+
158
+ operator_with_regular_syntax?(send_node)
157
159
  end
158
160
 
159
161
  def operator_with_regular_syntax?(send_node)
@@ -68,10 +68,7 @@ module RuboCop
68
68
  MSG = 'Remove debugger entry point `%<source>s`.'
69
69
 
70
70
  def on_send(node)
71
- return unless debugger_method?(node)
72
-
73
- # Basically, debugger methods are not used as a method argument without arguments.
74
- return if node.arguments.empty? && node.each_ancestor(:send, :csend).any?
71
+ return if !debugger_method?(node) || assumed_usage_context?(node)
75
72
 
76
73
  add_offense(node)
77
74
  end
@@ -95,6 +92,13 @@ module RuboCop
95
92
  debugger_methods.include?(chained_method_name(send_node))
96
93
  end
97
94
 
95
+ def assumed_usage_context?(node)
96
+ # Basically, debugger methods are not used as a method argument without arguments.
97
+ return false unless node.arguments.empty? && node.each_ancestor(:send, :csend).any?
98
+
99
+ node.each_ancestor.none?(&:lambda_or_proc?)
100
+ end
101
+
98
102
  def chained_method_name(send_node)
99
103
  chained_method_name = send_node.method_name.to_s
100
104
  receiver = send_node.receiver
@@ -84,6 +84,8 @@ module RuboCop
84
84
  end
85
85
 
86
86
  def unsafe_range?(range_start, range_end)
87
+ return false if range_start.length != 1 || range_end.length != 1
88
+
87
89
  range_for(range_start) != range_for(range_end)
88
90
  end
89
91
 
@@ -5,6 +5,14 @@ module RuboCop
5
5
  module Lint
6
6
  # Checks for redundant quantifiers inside Regexp literals.
7
7
  #
8
+ # It is always allowed when interpolation is used in a regexp literal,
9
+ # because it's unknown what kind of string will be expanded as a result:
10
+ #
11
+ # [source,ruby]
12
+ # ----
13
+ # /(?:a*#{interpolation})?/x
14
+ # ----
15
+ #
8
16
  # @example
9
17
  # # bad
10
18
  # /(?:x+)+/
@@ -32,6 +40,8 @@ module RuboCop
32
40
  'with a single `%<replacement>s`.'
33
41
 
34
42
  def on_regexp(node)
43
+ return if node.interpolation?
44
+
35
45
  each_redundantly_quantified_pair(node) do |group, child|
36
46
  replacement = merged_quantifier(group, child)
37
47
  add_offense(
@@ -113,9 +113,15 @@ module RuboCop
113
113
  def check_var(node)
114
114
  return unless node.variable? || node.const_type?
115
115
 
116
- add_offense(node.loc.name,
117
- message: format(VAR_MSG, var: node.loc.name.source)) do |corrector|
118
- autocorrect_void_var(corrector, node)
116
+ if node.const_type? && node.special_keyword?
117
+ add_offense(node, message: format(VAR_MSG, var: node.source)) do |corrector|
118
+ autocorrect_void_expression(corrector, node)
119
+ end
120
+ else
121
+ add_offense(node.loc.name,
122
+ message: format(VAR_MSG, var: node.loc.name.source)) do |corrector|
123
+ autocorrect_void_expression(corrector, node)
124
+ end
119
125
  end
120
126
  end
121
127
 
@@ -123,7 +129,7 @@ module RuboCop
123
129
  return if !node.literal? || node.xstr_type? || node.range_type?
124
130
 
125
131
  add_offense(node, message: format(LIT_MSG, lit: node.source)) do |corrector|
126
- autocorrect_void_literal(corrector, node)
132
+ autocorrect_void_expression(corrector, node)
127
133
  end
128
134
  end
129
135
 
@@ -131,7 +137,7 @@ module RuboCop
131
137
  return unless node.self_type?
132
138
 
133
139
  add_offense(node, message: SELF_MSG) do |corrector|
134
- autocorrect_void_self(corrector, node)
140
+ autocorrect_void_expression(corrector, node)
135
141
  end
136
142
  end
137
143
 
@@ -181,18 +187,6 @@ module RuboCop
181
187
  end
182
188
  end
183
189
 
184
- def autocorrect_void_var(corrector, node)
185
- corrector.remove(range_with_surrounding_space(range: node.loc.name, side: :left))
186
- end
187
-
188
- def autocorrect_void_literal(corrector, node)
189
- corrector.remove(range_with_surrounding_space(range: node.source_range, side: :left))
190
- end
191
-
192
- def autocorrect_void_self(corrector, node)
193
- corrector.remove(range_with_surrounding_space(range: node.source_range, side: :left))
194
- end
195
-
196
190
  def autocorrect_void_expression(corrector, node)
197
191
  corrector.remove(range_with_surrounding_space(range: node.source_range, side: :left))
198
192
  end
@@ -63,7 +63,7 @@ module RuboCop
63
63
  types
64
64
  end
65
65
 
66
- def code_length(node)
66
+ def code_length(node) # rubocop:disable Metrics/MethodLength
67
67
  if classlike_node?(node)
68
68
  classlike_code_length(node)
69
69
  elsif heredoc_node?(node)
@@ -72,7 +72,14 @@ module RuboCop
72
72
  body = extract_body(node)
73
73
  return 0 unless body
74
74
 
75
- body.source.each_line.count { |line| !irrelevant_line?(line) }
75
+ source =
76
+ if node_with_heredoc?(body)
77
+ source_from_node_with_heredoc(body)
78
+ else
79
+ body.source.lines
80
+ end
81
+
82
+ source.count { |line| !irrelevant_line?(line) }
76
83
  end
77
84
  end
78
85
 
@@ -175,6 +182,27 @@ module RuboCop
175
182
  def another_args?(node)
176
183
  node.call_type? && node.arguments.count > 1
177
184
  end
185
+
186
+ def node_with_heredoc?(node)
187
+ node.each_descendant(:str, :dstr).any? { |descendant| heredoc_node?(descendant) }
188
+ end
189
+
190
+ def source_from_node_with_heredoc(node)
191
+ last_line = -1
192
+ node.each_descendant do |descendant|
193
+ next unless descendant.source
194
+
195
+ descendant_last_line =
196
+ if heredoc_node?(descendant)
197
+ descendant.loc.heredoc_end.line
198
+ else
199
+ descendant.last_line
200
+ end
201
+
202
+ last_line = [last_line, descendant_last_line].max
203
+ end
204
+ @processed_source[(node.first_line - 1)..(last_line - 1)]
205
+ end
178
206
  end
179
207
  end
180
208
  end
@@ -26,11 +26,15 @@ module RuboCop
26
26
  end
27
27
 
28
28
  def delimiter_string(node)
29
- node.source.match(OPENING_DELIMITER).captures[1]
29
+ return '' unless (match = node.source.match(OPENING_DELIMITER))
30
+
31
+ match.captures[1]
30
32
  end
31
33
 
32
34
  def heredoc_type(node)
33
- node.source.match(OPENING_DELIMITER).captures[0]
35
+ return '' unless (match = node.source.match(OPENING_DELIMITER))
36
+
37
+ match.captures[0]
34
38
  end
35
39
  end
36
40
  end
@@ -47,7 +47,7 @@ module RuboCop
47
47
  def correct_elsif(node)
48
48
  <<~RUBY.chop
49
49
  if #{node.condition.source}
50
- #{node.if_branch.source}
50
+ #{node.if_branch&.source}
51
51
  #{build_else_branch(node.else_branch).chop}
52
52
  end
53
53
  RUBY
@@ -56,7 +56,7 @@ module RuboCop
56
56
  def build_else_branch(second_condition)
57
57
  result = <<~RUBY
58
58
  elsif #{second_condition.condition.source}
59
- #{second_condition.if_branch.source}
59
+ #{second_condition.if_branch&.source}
60
60
  RUBY
61
61
 
62
62
  if second_condition.else_branch
@@ -69,10 +69,10 @@ module RuboCop
69
69
  return unless offending_selector?(node, selector)
70
70
 
71
71
  add_offense(node.send_node.source_range, message: message(node, selector)) do |corrector|
72
- if node.send_node.source == 'lambda'
73
- autocorrect_method_to_literal(corrector, node)
74
- else
72
+ if node.send_node.lambda_literal?
75
73
  LambdaLiteralToMethodCorrector.new(node).call(corrector)
74
+ else
75
+ autocorrect_method_to_literal(corrector, node)
76
76
  end
77
77
  end
78
78
  end
@@ -40,7 +40,9 @@ module RuboCop
40
40
  byteindex byterindex gsub gsub! partition rpartition scan split start_with? sub sub!
41
41
  ].freeze
42
42
  DETERMINISTIC_REGEX = /\A(?:#{LITERAL_REGEX})+\Z/.freeze
43
- STR_SPECIAL_CHARS = %w[\n \" \' \\\\ \t \b \f \r].freeze
43
+ STR_SPECIAL_CHARS = %w[
44
+ \a \c \C \e \f \M \n \" \' \\\\ \t \b \f \r \u \v \x \0 \1 \2 \3 \4 \5 \6 \7
45
+ ].freeze
44
46
 
45
47
  def on_send(node)
46
48
  return unless (regexp_node = node.first_argument)
@@ -55,6 +57,7 @@ module RuboCop
55
57
  corrector.replace(regexp_node, prefer)
56
58
  end
57
59
  end
60
+ alias on_csend on_send
58
61
 
59
62
  private
60
63
 
@@ -118,16 +118,18 @@ module RuboCop
118
118
  node.comparison_method? && !noncommutative_operator?(node)
119
119
  end
120
120
 
121
+ # rubocop:disable Metrics/CyclomaticComplexity
121
122
  def valid_yoda?(node)
122
- lhs = node.receiver
123
- rhs = node.first_argument
123
+ return true unless (rhs = node.first_argument)
124
124
 
125
+ lhs = node.receiver
125
126
  return true if (constant_portion?(lhs) && constant_portion?(rhs)) ||
126
127
  (!constant_portion?(lhs) && !constant_portion?(rhs)) ||
127
128
  interpolation?(lhs)
128
129
 
129
130
  enforce_yoda? ? constant_portion?(lhs) : constant_portion?(rhs)
130
131
  end
132
+ # rubocop:enable Metrics/CyclomaticComplexity
131
133
 
132
134
  def message(node)
133
135
  format(MSG, source: node.source)
@@ -102,10 +102,11 @@ module RuboCop
102
102
  end
103
103
 
104
104
  def multiple_assignment_node
105
- grandparent_node = node.parent&.parent
106
- return nil unless grandparent_node
105
+ return nil unless (grandparent_node = node.parent&.parent)
106
+ if (node = find_multiple_assignment_node(grandparent_node))
107
+ return node
108
+ end
107
109
  return nil unless grandparent_node.type == MULTIPLE_ASSIGNMENT_TYPE
108
- return nil unless node.parent.type == MULTIPLE_LEFT_HAND_SIDE_TYPE
109
110
 
110
111
  grandparent_node
111
112
  end
@@ -122,6 +123,16 @@ module RuboCop
122
123
 
123
124
  node.parent
124
125
  end
126
+
127
+ def find_multiple_assignment_node(grandparent_node)
128
+ return unless grandparent_node.type == MULTIPLE_LEFT_HAND_SIDE_TYPE
129
+ return if grandparent_node.children.any?(&:splat_type?)
130
+
131
+ parent = grandparent_node.parent
132
+ return parent if parent.type == MULTIPLE_ASSIGNMENT_TYPE
133
+
134
+ find_multiple_assignment_node(parent)
135
+ end
125
136
  end
126
137
  end
127
138
  end
@@ -36,6 +36,8 @@ module RuboCop
36
36
  end
37
37
 
38
38
  handle 'initialize' do |request|
39
+ @server.configure(safe_autocorrect: safe_autocorrect?(request))
40
+
39
41
  @server.write(
40
42
  id: request[:id],
41
43
  result: LanguageServer::Protocol::Interface::InitializeResult.new(
@@ -162,6 +164,12 @@ module RuboCop
162
164
 
163
165
  private
164
166
 
167
+ def safe_autocorrect?(request)
168
+ safe_autocorrect = request.dig(:params, :initializationOptions, :safeAutocorrect)
169
+
170
+ safe_autocorrect.nil? || safe_autocorrect == true
171
+ end
172
+
165
173
  def format_file(file_uri)
166
174
  unless (text = @text_cache[file_uri])
167
175
  Logger.log("Format request arrived before text synchronized; skipping: `#{file_uri}'")
@@ -14,9 +14,12 @@ module RuboCop
14
14
  # Runtime for Language Server Protocol of RuboCop.
15
15
  # @api private
16
16
  class Runtime
17
+ attr_writer :safe_autocorrect
18
+
17
19
  def initialize(config_store)
18
20
  @config_store = config_store
19
21
  @logged_paths = []
22
+ @safe_autocorrect = true
20
23
  end
21
24
 
22
25
  # This abuses the `--stdin` option of rubocop and reads the formatted text
@@ -32,7 +35,7 @@ module RuboCop
32
35
  # https://github.com/rubocop/rubocop/blob/v1.52.0/lib/rubocop/runner.rb#L72
33
36
  def format(path, text)
34
37
  formatting_options = {
35
- stdin: text, force_exclusion: true, autocorrect: true, safe_autocorrect: true
38
+ stdin: text, force_exclusion: true, autocorrect: true, safe_autocorrect: @safe_autocorrect
36
39
  }
37
40
 
38
41
  redirect_stdout { run_rubocop(formatting_options, path) }
@@ -36,8 +36,8 @@ module RuboCop
36
36
  @routes.handle_unsupported_method(request)
37
37
  end
38
38
  rescue StandardError => e
39
- log("Error #{e.class} #{e.message[0..100]}")
40
- log(e.backtrace.inspect)
39
+ Logger.log("Error #{e.class} #{e.message[0..100]}")
40
+ Logger.log(e.backtrace.inspect)
41
41
  end
42
42
  end
43
43
 
@@ -53,6 +53,10 @@ module RuboCop
53
53
  @runtime.offenses(path, text)
54
54
  end
55
55
 
56
+ def configure(safe_autocorrect: true)
57
+ @runtime.safe_autocorrect = safe_autocorrect
58
+ end
59
+
56
60
  def stop(&block)
57
61
  at_exit(&block) if block
58
62
  exit
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  # This module holds the RuboCop version information.
5
5
  module Version
6
- STRING = '1.53.1'
6
+ STRING = '1.54.1'
7
7
 
8
8
  MSG = '%<version>s (using Parser %<parser_version>s, ' \
9
9
  'rubocop-ast %<rubocop_ast_version>s, ' \
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.53.1
4
+ version: 1.54.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Batsov
8
8
  - Jonas Arvidsson
9
9
  - Yuji Nakayama
10
- autorequire:
10
+ autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2023-06-26 00:00:00.000000000 Z
13
+ date: 2023-07-04 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: json
@@ -1023,10 +1023,10 @@ metadata:
1023
1023
  homepage_uri: https://rubocop.org/
1024
1024
  changelog_uri: https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md
1025
1025
  source_code_uri: https://github.com/rubocop/rubocop/
1026
- documentation_uri: https://docs.rubocop.org/rubocop/1.53/
1026
+ documentation_uri: https://docs.rubocop.org/rubocop/1.54/
1027
1027
  bug_tracker_uri: https://github.com/rubocop/rubocop/issues
1028
1028
  rubygems_mfa_required: 'true'
1029
- post_install_message:
1029
+ post_install_message:
1030
1030
  rdoc_options: []
1031
1031
  require_paths:
1032
1032
  - lib
@@ -1041,8 +1041,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
1041
1041
  - !ruby/object:Gem::Version
1042
1042
  version: '0'
1043
1043
  requirements: []
1044
- rubygems_version: 3.3.7
1045
- signing_key:
1044
+ rubygems_version: 3.4.6
1045
+ signing_key:
1046
1046
  specification_version: 4
1047
1047
  summary: Automatic Ruby code style checking tool.
1048
1048
  test_files: []