rubocop 1.56.0 → 1.56.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: 76532b5c0c7ccf0baff454ad37e17c405e4f827a0c8323ce1a5aab0ee9e78c19
4
- data.tar.gz: fe2f7d727d5addd930a762ebe7fb34a38845164fed801744a6802ab91e6ba779
3
+ metadata.gz: 33c4c853e4bf651034a9ac3faa2f221baa77104521504824e2b4e88b349f01e0
4
+ data.tar.gz: d49422193353fc79c86b1c8cdfc3465f4abebf56bc01cd95d2c0e150c3f9747a
5
5
  SHA512:
6
- metadata.gz: ff206ac0d02084dd7014818da655f5f8d718ac1bb4bfc2f781d3c007839096a142236ded54d30084fa7b3e1689205ff7a8bc7ad7eee3ffea2d809e4610d6a1ae
7
- data.tar.gz: aaa03f29b7669ffcf6fdcb16b7da4c38a6bc62187eb91d6347e3ada22f396370b6564177eb3a040fd5ddd3eeea9cf8b3ff51943e79c3d0ad410508a75bb3177b
6
+ metadata.gz: 3bd1f56046aba375e89f62b8c954802636023539111238848c25b37a70ed95a41835198b2dd17ded64223b1f50e98f7e20f0c82aafed0381cad30f0be526b4fc
7
+ data.tar.gz: e02897c89f4869054ffea56efac2d9983f65bdce40c9254d5806effbda70561bf9c7c4161fa9a7d3269dc229d6d09b3e7c990eef10835f7ec5f2b3c55b32f6cf
@@ -5,6 +5,24 @@ module RuboCop
5
5
  module Bundler
6
6
  # A Gem group, or a set of groups, should be listed only once in a Gemfile.
7
7
  #
8
+ # For example, if the values of `source`, `git`, `platforms`, or `path`
9
+ # surrounding `group` are different, no offense will be registered:
10
+ #
11
+ # [source,ruby]
12
+ # -----
13
+ # platforms :ruby do
14
+ # group :default do
15
+ # gem 'openssl'
16
+ # end
17
+ # end
18
+ #
19
+ # platforms :jruby do
20
+ # group :default do
21
+ # gem 'jruby-openssl'
22
+ # end
23
+ # end
24
+ # -----
25
+ #
8
26
  # @example
9
27
  # # bad
10
28
  # group :development do
@@ -42,27 +60,35 @@ module RuboCop
42
60
 
43
61
  MSG = 'Gem group `%<group_name>s` already defined on line ' \
44
62
  '%<line_of_first_occurrence>d of the Gemfile.'
63
+ SOURCE_BLOCK_NAMES = %i[source git platforms path].freeze
64
+
65
+ # @!method group_declarations(node)
66
+ def_node_search :group_declarations, '(send nil? :group ...)'
45
67
 
46
68
  def on_new_investigation
47
69
  return if processed_source.blank?
48
70
 
49
71
  duplicated_group_nodes.each do |nodes|
50
72
  nodes[1..].each do |node|
51
- register_offense(node, node.arguments.map(&:value).join(', '), nodes.first.first_line)
73
+ group_name = node.arguments.map(&:source).join(', ')
74
+
75
+ register_offense(node, group_name, nodes.first.first_line)
52
76
  end
53
77
  end
54
78
  end
55
79
 
56
80
  private
57
81
 
58
- # @!method group_declarations(node)
59
- def_node_search :group_declarations, '(send nil? :group ...)'
60
-
61
82
  def duplicated_group_nodes
62
- group_declarations(processed_source.ast)
63
- .group_by { |node| node.arguments.map(&:value).map(&:to_s).sort }
64
- .values
65
- .select { |nodes| nodes.size > 1 }
83
+ group_declarations = group_declarations(processed_source.ast)
84
+ group_keys = group_declarations.group_by do |node|
85
+ source_key = find_source_key(node)
86
+ group_attributes = group_attributes(node).sort.join
87
+
88
+ "#{source_key}#{group_attributes}"
89
+ end
90
+
91
+ group_keys.values.select { |nodes| nodes.size > 1 }
66
92
  end
67
93
 
68
94
  def register_offense(node, group_name, line_of_first_occurrence)
@@ -75,6 +101,26 @@ module RuboCop
75
101
  )
76
102
  add_offense(offense_location, message: message)
77
103
  end
104
+
105
+ def find_source_key(node)
106
+ source_block = node.each_ancestor(:block).find do |block_node|
107
+ SOURCE_BLOCK_NAMES.include?(block_node.method_name)
108
+ end
109
+
110
+ return unless source_block
111
+
112
+ "#{source_block.method_name}#{source_block.send_node.first_argument&.source}"
113
+ end
114
+
115
+ def group_attributes(node)
116
+ node.arguments.map do |argument|
117
+ if argument.hash_type?
118
+ argument.pairs.map(&:source).sort.join(', ')
119
+ else
120
+ argument.value.to_s
121
+ end
122
+ end
123
+ end
78
124
  end
79
125
  end
80
126
  end
@@ -14,12 +14,15 @@ module RuboCop
14
14
  # Check for unparenthesized args' preceding and trailing whitespaces.
15
15
  remove_unparenthesized_whitespace(corrector)
16
16
 
17
- # Avoid correcting to `lambdado` by inserting whitespace
18
- # if none exists before or after the lambda arguments.
19
- insert_separating_space(corrector)
17
+ if block_node.block_type?
18
+ # Avoid correcting to `lambdado` by inserting whitespace
19
+ # if none exists before or after the lambda arguments.
20
+ insert_separating_space(corrector)
21
+
22
+ remove_arguments(corrector)
23
+ end
20
24
 
21
25
  replace_selector(corrector)
22
- remove_arguments(corrector)
23
26
 
24
27
  replace_delimiters(corrector)
25
28
 
@@ -57,7 +57,7 @@ module RuboCop
57
57
 
58
58
  def on_new_investigation
59
59
  processed_source.comments.each do |comment|
60
- next unless /\A#+[^#\s=+-]/.match?(comment.text)
60
+ next unless /\A(?!#\+\+|#--)(#+[^#\s=])/.match?(comment.text)
61
61
  next if comment.loc.line == 1 && allowed_on_first_line?(comment)
62
62
  next if doxygen_comment_style?(comment)
63
63
  next if gemfile_ruby_comment?(comment)
@@ -109,7 +109,7 @@ module RuboCop
109
109
  # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
110
110
 
111
111
  def comment_ranges(comments)
112
- comments.map(&:loc).map(&:expression)
112
+ comments.map(&:source_range)
113
113
  end
114
114
 
115
115
  def last_line(processed_source)
@@ -118,7 +118,9 @@ module RuboCop
118
118
  end
119
119
 
120
120
  def comment_within?(node)
121
- processed_source.comments.map(&:loc).map(&:line).any? do |comment_line_number|
121
+ comment_line_numbers = processed_source.comments.map { |comment| comment.loc.line }
122
+
123
+ comment_line_numbers.any? do |comment_line_number|
122
124
  comment_line_number >= node.first_line && comment_line_number <= node.last_line
123
125
  end
124
126
  end
@@ -57,12 +57,12 @@ module RuboCop
57
57
  REMOVE_FORCE_METHODS).freeze
58
58
 
59
59
  # @!method send_exist_node(node)
60
- def_node_search :send_exist_node, <<-PATTERN
60
+ def_node_search :send_exist_node, <<~PATTERN
61
61
  $(send (const nil? {:FileTest :File :Dir :Shell}) {:exist? :exists?} ...)
62
62
  PATTERN
63
63
 
64
64
  # @!method receiver_and_method_name(node)
65
- def_node_matcher :receiver_and_method_name, <<-PATTERN
65
+ def_node_matcher :receiver_and_method_name, <<~PATTERN
66
66
  (send (const nil? $_) $_ ...)
67
67
  PATTERN
68
68
 
@@ -96,8 +96,7 @@ module RuboCop
96
96
  return_value_node = return_value_node_of_scope(scope)
97
97
  return unless assignment.meta_assignment_node.equal?(return_value_node)
98
98
 
99
- " Use `#{assignment.operator.sub(/=$/, '')}` " \
100
- "instead of `#{assignment.operator}`."
99
+ " Use `#{assignment.operator.delete_suffix('=')}` instead of `#{assignment.operator}`."
101
100
  end
102
101
 
103
102
  def similar_name_message(variable)
@@ -136,7 +136,7 @@ module RuboCop
136
136
  end
137
137
 
138
138
  def filename_good?(basename)
139
- basename = basename.sub(/^\./, '')
139
+ basename = basename.delete_prefix('.')
140
140
  basename = basename.sub(/\.[^.]+$/, '')
141
141
  # special handling for Action Pack Variants file names like
142
142
  # some_file.xlsx+mobile.axlsx
@@ -80,6 +80,7 @@ module RuboCop
80
80
  minimum_target_ruby_version 2.7
81
81
 
82
82
  FORWARDING_LVAR_TYPES = %i[splat kwsplat block_pass].freeze
83
+ ADDITIONAL_ARG_TYPES = %i[lvar arg].freeze
83
84
 
84
85
  FORWARDING_MSG = 'Use shorthand syntax `...` for arguments forwarding.'
85
86
  ARGS_MSG = 'Use anonymous positional arguments forwarding (`*`).'
@@ -212,7 +213,7 @@ module RuboCop
212
213
  end
213
214
 
214
215
  def arguments_range(node, first_node)
215
- arguments = node.arguments
216
+ arguments = node.arguments.reject { |arg| ADDITIONAL_ARG_TYPES.include?(arg.type) }
216
217
 
217
218
  start_node = first_node || arguments.first
218
219
 
@@ -279,7 +280,7 @@ module RuboCop
279
280
 
280
281
  if can_forward_all?
281
282
  :all
282
- elsif target_ruby_version >= 3.2
283
+ else
283
284
  :rest_or_kwrest
284
285
  end
285
286
  end
@@ -332,9 +333,9 @@ module RuboCop
332
333
  end
333
334
 
334
335
  def no_post_splat_args?
335
- splat_index = arguments.index(forwarded_rest_arg)
336
- arg_after_splat = arguments[splat_index + 1]
336
+ return true unless (splat_index = arguments.index(forwarded_rest_arg))
337
337
 
338
+ arg_after_splat = arguments[splat_index + 1]
338
339
  [nil, :hash, :block_pass].include?(arg_after_splat&.type)
339
340
  end
340
341
 
@@ -74,7 +74,7 @@ module RuboCop
74
74
  new_arguments =
75
75
  node.arguments.map do |arg|
76
76
  if arg.percent_literal?
77
- arg.children.map(&:value).map(&:inspect)
77
+ arg.children.map { |child| child.value.inspect }
78
78
  else
79
79
  arg.children.map(&:source)
80
80
  end
@@ -146,7 +146,9 @@ module RuboCop
146
146
  end
147
147
 
148
148
  def call_in_match_pattern?(node)
149
- node.parent&.match_pattern_type?
149
+ return false unless (parent = node.parent)
150
+
151
+ parent.match_pattern_type? || parent.match_pattern_p_type?
150
152
  end
151
153
 
152
154
  def hash_literal_in_arguments?(node)
@@ -45,7 +45,7 @@ module RuboCop
45
45
  MSG = 'Avoid using `OpenStruct`; use `Struct`, `Hash`, a class or test doubles instead.'
46
46
 
47
47
  # @!method uses_open_struct?(node)
48
- def_node_matcher :uses_open_struct?, <<-PATTERN
48
+ def_node_matcher :uses_open_struct?, <<~PATTERN
49
49
  (const {nil? (cbase)} :OpenStruct)
50
50
  PATTERN
51
51
 
@@ -98,7 +98,9 @@ module RuboCop
98
98
  end
99
99
 
100
100
  def like_method_argument_parentheses?(node)
101
- node.send_type? && node.arguments.one? && !node.parenthesized? &&
101
+ return false if !node.send_type? && !node.super_type? && !node.yield_type?
102
+
103
+ node.arguments.one? && !node.parenthesized? &&
102
104
  !node.arithmetic_operation? && node.first_argument.begin_type?
103
105
  end
104
106
 
@@ -75,6 +75,11 @@ module RuboCop
75
75
  add_offense(offense_branch) do |corrector|
76
76
  assignment_value = opposite_branch ? opposite_branch.source : 'nil'
77
77
  replacement = "#{assignment_value} #{keyword} #{if_node.condition.source}"
78
+ if opposite_branch.respond_to?(:heredoc?) && opposite_branch.heredoc?
79
+ replacement += opposite_branch.loc.heredoc_end.with(
80
+ begin_pos: opposite_branch.source_range.end_pos
81
+ ).source
82
+ end
78
83
 
79
84
  corrector.replace(if_node, replacement)
80
85
  end
@@ -69,6 +69,8 @@ module RuboCop
69
69
 
70
70
  def complex_content?(node)
71
71
  node.children.any? do |sym|
72
+ return false if DELIMITERS.include?(sym.source)
73
+
72
74
  content = *sym
73
75
  content = content.map { |c| c.is_a?(AST::Node) ? c.source : c }.join
74
76
  content_without_delimiter_pairs = content.gsub(/(\[[^\s\[\]]*\])|(\([^\s\(\)]*\))/, '')
@@ -6,27 +6,40 @@ module RuboCop
6
6
  # Helper to abstract complexity of building range pairs
7
7
  # with octal escape reconstruction (needed for regexp_parser < 2.7).
8
8
  class RegexpRanges
9
- attr_reader :compound_token, :root
9
+ attr_reader :root
10
10
 
11
11
  def initialize(root)
12
12
  @root = root
13
13
  @compound_token = []
14
+ @pairs = []
15
+ @populated = false
16
+ end
17
+
18
+ def compound_token
19
+ populate_all unless @populated
20
+
21
+ @compound_token
14
22
  end
15
23
 
16
24
  def pairs
17
- unless @pairs
18
- @pairs = []
19
- populate(root)
20
- end
25
+ populate_all unless @populated
26
+
27
+ @pairs
28
+ end
29
+
30
+ private
31
+
32
+ def populate_all
33
+ populate(@root)
21
34
 
22
35
  # If either bound is a compound the first one is an escape
23
36
  # and that's all we need to work with.
24
37
  # If there are any cops that wanted to operate on the compound
25
38
  # expression we could wrap it with a facade class.
26
- @pairs.map { |pair| pair.map(&:first) }
27
- end
39
+ @pairs.map! { |pair| pair.map(&:first) }
28
40
 
29
- private
41
+ @populated = true
42
+ end
30
43
 
31
44
  def populate(expr)
32
45
  expressions = expr.expressions.to_a
@@ -35,15 +48,15 @@ module RuboCop
35
48
  current = expressions.shift
36
49
 
37
50
  if escaped_octal?(current)
38
- compound_token << current
39
- compound_token.concat(pop_octal_digits(expressions))
51
+ @compound_token << current
52
+ @compound_token.concat(pop_octal_digits(expressions))
40
53
  # If we have all the digits we can discard.
41
54
  end
42
55
 
43
56
  next unless current.type == :set
44
57
 
45
58
  process_set(expressions, current)
46
- compound_token.clear
59
+ @compound_token.clear
47
60
  end
48
61
  end
49
62
 
@@ -64,8 +77,8 @@ module RuboCop
64
77
 
65
78
  def compose_range(expressions, current)
66
79
  range_start, range_end = current.expressions
67
- range_start = if compound_token.size.between?(1, 2) && octal_digit?(range_start.text)
68
- compound_token.dup << range_start
80
+ range_start = if @compound_token.size.between?(1, 2) && octal_digit?(range_start.text)
81
+ @compound_token.dup << range_start
69
82
  else
70
83
  [range_start]
71
84
  end
@@ -155,9 +155,11 @@ module RuboCop
155
155
  (send _ :required_ruby_version= $_)
156
156
  PATTERN
157
157
 
158
- # @!method gem_requirement?(node)
159
- def_node_matcher :gem_requirement?, <<~PATTERN
160
- (send (const(const _ :Gem):Requirement) :new $str)
158
+ # @!method gem_requirement_versions(node)
159
+ def_node_matcher :gem_requirement_versions, <<~PATTERN
160
+ (send (const(const _ :Gem):Requirement) :new
161
+ {$str+ | (send $str :freeze)+ | (array $str+) | (array (send $str :freeze)+)}
162
+ )
161
163
  PATTERN
162
164
 
163
165
  def name
@@ -194,10 +196,12 @@ module RuboCop
194
196
  end
195
197
 
196
198
  def version_from_right_hand_side(right_hand_side)
199
+ gem_requirement_versions = gem_requirement_versions(right_hand_side)
200
+
197
201
  if right_hand_side.array_type?
198
202
  version_from_array(right_hand_side)
199
- elsif gem_requirement?(right_hand_side)
200
- right_hand_side.children.last.value
203
+ elsif gem_requirement_versions
204
+ gem_requirement_versions.map(&:value)
201
205
  else
202
206
  right_hand_side.value
203
207
  end
@@ -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.0'
6
+ STRING = '1.56.1'
7
7
 
8
8
  MSG = '%<version>s (using Parser %<parser_version>s, ' \
9
9
  'rubocop-ast %<rubocop_ast_version>s, ' \
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.56.0
4
+ version: 1.56.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Batsov
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2023-08-09 00:00:00.000000000 Z
13
+ date: 2023-08-21 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: base64
@@ -196,9 +196,9 @@ dependencies:
196
196
  - - "<"
197
197
  - !ruby/object:Gem::Version
198
198
  version: '3.0'
199
- description: |2
200
- RuboCop is a Ruby code style checking and code formatting tool.
201
- It aims to enforce the community-driven Ruby Style Guide.
199
+ description: |
200
+ RuboCop is a Ruby code style checking and code formatting tool.
201
+ It aims to enforce the community-driven Ruby Style Guide.
202
202
  email: rubocop@googlegroups.com
203
203
  executables:
204
204
  - rubocop