rubocop 1.57.1 → 1.57.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d38c0bf9376bd86de4bdf5561b74b11e895bc90ac263a8c29520afec2fb7d0b0
4
- data.tar.gz: 5e624dd813953b2058306d07986c19d55fa170fa8f3960844c4d62f2f87b3277
3
+ metadata.gz: adf1db90b03283f492e0e10f234d54d6efc215a8b182965087313e3954d533dd
4
+ data.tar.gz: fa84dfd9d61e4834df9287e0ba0619622f4b7eb9e229e8de1172bc1742c04df5
5
5
  SHA512:
6
- metadata.gz: dee188b376a118be4c08956361312fc91bf4e55cdadfa8129611f8a3b19fef80fb8241658778a5f6fb042336ba4137c6c64d2a65189ad00567730934e3dcde74
7
- data.tar.gz: 4dbf33a643a4f945d3564426b49338d463a55e734812d8c3113df04aa430577c2142b7685990bdd12915e537a1add4b181dd96488632dd89a544a33c5f712944
6
+ metadata.gz: 44a683eed5e4b9d26caf4d0c775a6f4ba00960b6aaeee29c3f610320d1471326d650e8fc41ee2725af07b4e6a50bf17d442232134522709ebb2a46ec5b80bf40
7
+ data.tar.gz: d4f5dda0dbf7689c55b39de3922c2bd1a0c40aa62ac1046f06c98a19e7f2719cfea11babd480ba4e9b9ff2203d20422a51f096165d5919bf564e009c3a91c087
@@ -10,6 +10,7 @@ module RuboCop
10
10
 
11
11
  AUTO_GENERATED_FILE = '.rubocop_todo.yml'
12
12
  YAML_OPTIONAL_DOC_START = /\A---(\s+#|\s*\z)/.freeze
13
+ PLACEHOLDER = '###rubocop:inherit_here'
13
14
 
14
15
  PHASE_1 = 'Phase 1 of 2: run Layout/LineLength cop'
15
16
  PHASE_2 = 'Phase 2 of 2: run all cops'
@@ -125,15 +126,19 @@ module RuboCop
125
126
 
126
127
  def existing_configuration(config_file)
127
128
  File.read(config_file, encoding: Encoding::UTF_8)
128
- .sub(/^inherit_from: *[^\n]+/, '')
129
- .sub(/^inherit_from: *(\n *- *[^\n]+)+/, '')
129
+ .sub(/^inherit_from: *[^\n]+/, PLACEHOLDER)
130
+ .sub(/^inherit_from: *(\n *- *[^\n]+)+/, PLACEHOLDER)
130
131
  end
131
132
 
132
133
  def write_config_file(file_name, file_string, rubocop_yml_contents)
133
134
  lines = /\S/.match?(rubocop_yml_contents) ? rubocop_yml_contents.split("\n", -1) : []
134
- doc_start_index = lines.index { |line| YAML_OPTIONAL_DOC_START.match?(line) } || -1
135
- lines.insert(doc_start_index + 1, "inherit_from:#{file_string}\n")
136
- File.write(file_name, lines.join("\n"))
135
+ unless rubocop_yml_contents&.include?(PLACEHOLDER)
136
+ doc_start_index = lines.index { |line| YAML_OPTIONAL_DOC_START.match?(line) } || -1
137
+ lines.insert(doc_start_index + 1, PLACEHOLDER)
138
+ end
139
+ File.write(file_name, lines.join("\n")
140
+ .sub(/#{PLACEHOLDER}\n*/o, "inherit_from:#{file_string}\n\n")
141
+ .sub(/\n\n+\Z/, "\n"))
137
142
  end
138
143
 
139
144
  def relative_path_to_todo_from_options_config
@@ -163,7 +163,13 @@ module RuboCop
163
163
  when :keyword
164
164
  node
165
165
  when :variable
166
- alignment_node_for_variable_style(node)
166
+ align_to = alignment_node_for_variable_style(node)
167
+
168
+ while (parent = align_to.parent) && parent.send_type? && same_line?(align_to, parent)
169
+ align_to = parent
170
+ end
171
+
172
+ align_to
167
173
  else
168
174
  start_line_range(node)
169
175
  end
@@ -6,6 +6,16 @@ module RuboCop
6
6
  # Checks for operators, variables, literals, lambda, proc and nonmutating
7
7
  # methods used in void context.
8
8
  #
9
+ # `each` blocks are allowed to prevent false positives.
10
+ # For example, the expression inside the `each` block below.
11
+ # It's not void, especially when the receiver is an `Enumerator`:
12
+ #
13
+ # [source,ruby]
14
+ # ----
15
+ # enumerator = [1, 2, 3].filter
16
+ # enumerator.each { |item| item >= 2 } #=> [2, 3]
17
+ # ----
18
+ #
9
19
  # @example CheckForMethodsWithNoSideEffects: false (default)
10
20
  # # bad
11
21
  # def some_method
@@ -47,6 +57,7 @@ module RuboCop
47
57
 
48
58
  OP_MSG = 'Operator `%<op>s` used in void context.'
49
59
  VAR_MSG = 'Variable `%<var>s` used in void context.'
60
+ CONST_MSG = 'Constant `%<var>s` used in void context.'
50
61
  LIT_MSG = 'Literal `%<lit>s` used in void context.'
51
62
  SELF_MSG = '`self` used in void context.'
52
63
  EXPRESSION_MSG = '`%<expression>s` used in void context.'
@@ -72,6 +83,7 @@ module RuboCop
72
83
  return unless node.body && !node.body.begin_type?
73
84
  return unless in_void_context?(node.body)
74
85
 
86
+ check_void_op(node.body) { node.method?(:each) }
75
87
  check_expression(node.body)
76
88
  end
77
89
 
@@ -87,11 +99,13 @@ module RuboCop
87
99
  def check_begin(node)
88
100
  expressions = *node
89
101
  expressions.pop unless in_void_context?(node)
90
- expressions.each { |expr| check_expression(expr) }
102
+ expressions.each do |expr|
103
+ check_void_op(expr)
104
+ check_expression(expr)
105
+ end
91
106
  end
92
107
 
93
108
  def check_expression(expr)
94
- check_void_op(expr)
95
109
  check_literal(expr)
96
110
  check_var(expr)
97
111
  check_self(expr)
@@ -101,8 +115,9 @@ module RuboCop
101
115
  check_nonmutating(expr)
102
116
  end
103
117
 
104
- def check_void_op(node)
118
+ def check_void_op(node, &block)
105
119
  return unless node.send_type? && OPERATORS.include?(node.method_name)
120
+ return if block && yield(node)
106
121
 
107
122
  add_offense(node.loc.selector,
108
123
  message: format(OP_MSG, op: node.method_name)) do |corrector|
@@ -113,15 +128,18 @@ module RuboCop
113
128
  def check_var(node)
114
129
  return unless node.variable? || node.const_type?
115
130
 
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
131
+ if node.const_type?
132
+ template = node.special_keyword? ? VAR_MSG : CONST_MSG
133
+
134
+ offense_range = node
135
+ message = format(template, var: node.source)
120
136
  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
137
+ offense_range = node.loc.name
138
+ message = format(VAR_MSG, var: node.loc.name.source)
139
+ end
140
+
141
+ add_offense(offense_range, message: message) do |corrector|
142
+ autocorrect_void_expression(corrector, node)
125
143
  end
126
144
  end
127
145
 
@@ -42,7 +42,12 @@ module RuboCop
42
42
  def on_class(node)
43
43
  check_code_length(node)
44
44
  end
45
- alias on_sclass on_class
45
+
46
+ def on_sclass(node)
47
+ return if node.each_ancestor(:class).any?
48
+
49
+ on_class(node)
50
+ end
46
51
 
47
52
  def on_casgn(node)
48
53
  parent = node.parent
@@ -62,25 +62,29 @@ module RuboCop
62
62
  # Returns the end line of a node, which might be a comment and not part of the AST
63
63
  # End line is considered either the line at which another node starts, or
64
64
  # the line at which the parent node ends.
65
- # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity, Lint/DuplicateBranch
65
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
66
66
  def find_end_line(node)
67
- if node.if_type? && node.else?
68
- node.loc.else.line
69
- elsif node.if_type? && node.ternary?
70
- node.else_branch.loc.line
71
- elsif node.if_type? && node.elsif?
72
- node.each_ancestor(:if).find(&:if?).loc.end.line
67
+ if node.if_type?
68
+ if node.else?
69
+ node.loc.else.line
70
+ elsif node.ternary?
71
+ node.else_branch.loc.line
72
+ elsif node.elsif?
73
+ node.each_ancestor(:if).find(&:if?).loc.end.line
74
+ end
73
75
  elsif node.block_type? || node.numblock_type?
74
76
  node.loc.end.line
75
77
  elsif (next_sibling = node.right_sibling) && next_sibling.is_a?(AST::Node)
76
78
  next_sibling.loc.line
77
79
  elsif (parent = node.parent)
78
- parent.loc.respond_to?(:end) && parent.loc.end ? parent.loc.end.line : parent.loc.line
79
- else
80
- node.loc.end.line
81
- end
80
+ if parent.loc.respond_to?(:end) && parent.loc.end
81
+ parent.loc.end.line
82
+ else
83
+ parent.loc.line
84
+ end
85
+ end || node.loc.end.line
82
86
  end
83
- # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity, Lint/DuplicateBranch
87
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
84
88
  end
85
89
  end
86
90
  end
@@ -48,18 +48,21 @@ module RuboCop
48
48
 
49
49
  def register_offense(node, message, replacement) # rubocop:disable Metrics/AbcSize
50
50
  add_offense(node.value, message: message) do |corrector|
51
- if (def_node = def_node_that_require_parentheses(node))
52
- last_argument = def_node.last_argument
53
- if last_argument.nil? || !last_argument.hash_type?
54
- next corrector.replace(node, replacement)
55
- end
56
-
57
- white_spaces = range_between(def_node.selector.end_pos,
58
- def_node.first_argument.source_range.begin_pos)
59
- corrector.replace(white_spaces, '(')
60
- corrector.insert_after(last_argument, ')') if node == last_argument.pairs.last
61
- end
62
51
  corrector.replace(node, replacement)
52
+
53
+ next unless (def_node = def_node_that_require_parentheses(node))
54
+
55
+ last_argument = def_node.last_argument
56
+ if last_argument.nil? || !last_argument.hash_type?
57
+ next corrector.replace(node, replacement)
58
+ end
59
+
60
+ white_spaces = range_between(def_node.selector.end_pos,
61
+ def_node.first_argument.source_range.begin_pos)
62
+ next if node.parent.braces?
63
+
64
+ corrector.replace(white_spaces, '(')
65
+ corrector.insert_after(last_argument, ')') if node == last_argument.pairs.last
63
66
  end
64
67
  end
65
68
 
@@ -153,7 +153,15 @@ module RuboCop
153
153
  return unless duplicated_expressions?(node, heads)
154
154
 
155
155
  condition_variable = assignable_condition_value(node)
156
- return if heads.first.assignment? && condition_variable == heads.first.name.to_s
156
+
157
+ head = heads.first
158
+ if head.assignment?
159
+ # The `send` node is used instead of the `indexasgn` node, so `name` cannot be used.
160
+ # https://github.com/rubocop/rubocop-ast/blob/v1.29.0/lib/rubocop/ast/node/indexasgn_node.rb
161
+ assigned_value = head.send_type? ? head.receiver.source : head.name.to_s
162
+
163
+ return if condition_variable == assigned_value
164
+ end
157
165
 
158
166
  check_expressions(node, heads, :before_condition)
159
167
  end
@@ -29,7 +29,8 @@ module RuboCop
29
29
  def on_hash(node)
30
30
  return if node.pairs.empty? || node.pairs.any?(&:hash_rocket?)
31
31
  return unless (parent = node.parent)
32
- return if parent.call_type? && !merge_method?(parent)
32
+ return unless parent.call_type? || parent.kwsplat_type?
33
+ return unless mergeable?(parent)
33
34
  return unless (kwsplat = node.each_ancestor(:kwsplat).first)
34
35
  return if allowed_double_splat_receiver?(kwsplat)
35
36
 
@@ -42,9 +43,11 @@ module RuboCop
42
43
  private
43
44
 
44
45
  def allowed_double_splat_receiver?(kwsplat)
45
- return false unless kwsplat.children.first.call_type?
46
+ first_child = kwsplat.children.first
47
+ return true if first_child.block_type? || first_child.numblock_type?
48
+ return false unless first_child.call_type?
46
49
 
47
- root_receiver = root_receiver(kwsplat.children.first)
50
+ root_receiver = root_receiver(first_child)
48
51
 
49
52
  !root_receiver&.hash_type?
50
53
  end
@@ -71,7 +74,7 @@ module RuboCop
71
74
 
72
75
  def select_merge_method_nodes(kwsplat)
73
76
  extract_send_methods(kwsplat).select do |node|
74
- merge_method?(node)
77
+ mergeable?(node)
75
78
  end
76
79
  end
77
80
 
@@ -106,7 +109,7 @@ module RuboCop
106
109
  end
107
110
 
108
111
  def convert_to_new_arguments(node)
109
- return unless merge_method?(node)
112
+ return unless mergeable?(node)
110
113
 
111
114
  node.arguments.map do |arg|
112
115
  if arg.hash_type?
@@ -117,8 +120,12 @@ module RuboCop
117
120
  end
118
121
  end
119
122
 
120
- def merge_method?(node)
121
- MERGE_METHODS.include?(node.method_name)
123
+ def mergeable?(node)
124
+ return true unless node.call_type?
125
+ return false unless MERGE_METHODS.include?(node.method_name)
126
+ return true unless (parent = node.parent)
127
+
128
+ mergeable?(parent)
122
129
  end
123
130
  end
124
131
  end
@@ -60,10 +60,10 @@ module RuboCop
60
60
 
61
61
  # @!method select_predicate?(node)
62
62
  def_node_matcher :select_predicate?, <<~PATTERN
63
- (send
63
+ (call
64
64
  {
65
- (block $(send _ {:select :filter :find_all}) ...)
66
- $(send _ {:select :filter :find_all} block_pass_type?)
65
+ (block $(call _ {:select :filter :find_all}) ...)
66
+ $(call _ {:select :filter :find_all} block_pass_type?)
67
67
  }
68
68
  ${:#{RESTRICT_ON_SEND.join(' :')}})
69
69
  PATTERN
@@ -87,6 +87,7 @@ module RuboCop
87
87
  register_offense(select_node, node)
88
88
  end
89
89
  end
90
+ alias on_csend on_send
90
91
 
91
92
  private
92
93
 
@@ -111,17 +111,19 @@ module RuboCop
111
111
 
112
112
  def first_arg_begins_with_hash_literal?(node)
113
113
  # Don't flag `method ({key: value})` or `method ({key: value}.method)`
114
- method_chain_begins_with_hash_literal?(node.children.first) &&
115
- first_argument?(node) &&
116
- !parentheses?(node.parent)
114
+ hash_literal = method_chain_begins_with_hash_literal(node.children.first)
115
+ if (root_method = node.each_ancestor(:send).to_a.last)
116
+ parenthesized = root_method.parenthesized_call?
117
+ end
118
+ hash_literal && first_argument?(node) && !parentheses?(hash_literal) && !parenthesized
117
119
  end
118
120
 
119
- def method_chain_begins_with_hash_literal?(node)
120
- return false if node.nil?
121
- return true if node.hash_type?
122
- return false unless node.send_type?
121
+ def method_chain_begins_with_hash_literal(node)
122
+ return if node.nil?
123
+ return node if node.hash_type?
124
+ return unless node.send_type?
123
125
 
124
- method_chain_begins_with_hash_literal?(node.children.first)
126
+ method_chain_begins_with_hash_literal(node.children.first)
125
127
  end
126
128
 
127
129
  def check(begin_node)
@@ -231,7 +233,13 @@ module RuboCop
231
233
  end
232
234
 
233
235
  def first_argument?(node)
234
- first_send_argument?(node) || first_super_argument?(node) || first_yield_argument?(node)
236
+ if first_send_argument?(node) ||
237
+ first_super_argument?(node) ||
238
+ first_yield_argument?(node)
239
+ return true
240
+ end
241
+
242
+ node.each_ancestor.any? { |ancestor| first_argument?(ancestor) }
235
243
  end
236
244
 
237
245
  # @!method first_send_argument?(node)
@@ -33,6 +33,7 @@ module RuboCop
33
33
 
34
34
  MSG = 'Use `%<receiver>s[%<argument>s]` instead of `%<original>s`.'
35
35
  RESTRICT_ON_SEND = %i[dig].freeze
36
+ IGNORED_ARGUMENT_TYPES = %i[block_pass forwarded_restarg forwarded_args hash].freeze
36
37
 
37
38
  # @!method single_argument_dig?(node)
38
39
  def_node_matcher :single_argument_dig?, <<~PATTERN
@@ -44,7 +45,7 @@ module RuboCop
44
45
 
45
46
  expression = single_argument_dig?(node)
46
47
  return unless expression
47
- return if expression.forwarded_args_type?
48
+ return if IGNORED_ARGUMENT_TYPES.include?(expression.type)
48
49
 
49
50
  receiver = node.receiver.source
50
51
  argument = expression.source
@@ -30,6 +30,7 @@ module RuboCop
30
30
 
31
31
  MSG = 'Prefer multiline `do`...`end` block.'
32
32
 
33
+ # rubocop:disable Metrics/AbcSize
33
34
  def on_block(node)
34
35
  return if !node.single_line? || node.braces?
35
36
 
@@ -42,10 +43,11 @@ module RuboCop
42
43
  corrector.remove(node.loc.end)
43
44
  corrector.insert_after(node_body.loc.heredoc_end, "\nend")
44
45
  else
45
- corrector.insert_after(node_body, "\n")
46
+ corrector.insert_before(node.loc.end, "\n")
46
47
  end
47
48
  end
48
49
  end
50
+ # rubocop:enable Metrics/AbcSize
49
51
  alias on_numblock on_block
50
52
 
51
53
  private
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'base64'
4
3
  require 'cgi'
5
4
  require 'erb'
6
5
  require 'ostruct'
@@ -124,7 +123,10 @@ module RuboCop
124
123
 
125
124
  def base64_encoded_logo_image
126
125
  image = File.read(LOGO_IMAGE_PATH, binmode: true)
127
- Base64.encode64(image)
126
+
127
+ # `Base64.encode64` compatible:
128
+ # https://github.com/ruby/base64/blob/v0.1.1/lib/base64.rb#L27-L40
129
+ [image].pack('m')
128
130
  end
129
131
  end
130
132
  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.57.1'
6
+ STRING = '1.57.2'
7
7
 
8
8
  MSG = '%<version>s (using Parser %<parser_version>s, ' \
9
9
  'rubocop-ast %<rubocop_ast_version>s, ' \
metadata CHANGED
@@ -1,31 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.57.1
4
+ version: 1.57.2
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-10-13 00:00:00.000000000 Z
13
+ date: 2023-10-26 00:00:00.000000000 Z
14
14
  dependencies:
15
- - !ruby/object:Gem::Dependency
16
- name: base64
17
- requirement: !ruby/object:Gem::Requirement
18
- requirements:
19
- - - "~>"
20
- - !ruby/object:Gem::Version
21
- version: 0.1.1
22
- type: :runtime
23
- prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
25
- requirements:
26
- - - "~>"
27
- - !ruby/object:Gem::Version
28
- version: 0.1.1
29
15
  - !ruby/object:Gem::Dependency
30
16
  name: json
31
17
  requirement: !ruby/object:Gem::Requirement
@@ -1042,7 +1028,7 @@ metadata:
1042
1028
  documentation_uri: https://docs.rubocop.org/rubocop/1.57/
1043
1029
  bug_tracker_uri: https://github.com/rubocop/rubocop/issues
1044
1030
  rubygems_mfa_required: 'true'
1045
- post_install_message:
1031
+ post_install_message:
1046
1032
  rdoc_options: []
1047
1033
  require_paths:
1048
1034
  - lib
@@ -1057,8 +1043,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
1057
1043
  - !ruby/object:Gem::Version
1058
1044
  version: '0'
1059
1045
  requirements: []
1060
- rubygems_version: 3.3.7
1061
- signing_key:
1046
+ rubygems_version: 3.4.6
1047
+ signing_key:
1062
1048
  specification_version: 4
1063
1049
  summary: Automatic Ruby code style checking tool.
1064
1050
  test_files: []