rubocop 1.57.1 → 1.57.2
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 +4 -4
- data/lib/rubocop/cli/command/auto_generate_config.rb +10 -5
- data/lib/rubocop/cop/layout/end_alignment.rb +7 -1
- data/lib/rubocop/cop/lint/void.rb +29 -11
- data/lib/rubocop/cop/metrics/class_length.rb +6 -1
- data/lib/rubocop/cop/mixin/comments_help.rb +16 -12
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +14 -11
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +9 -1
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +14 -7
- data/lib/rubocop/cop/style/redundant_filter_chain.rb +4 -3
- data/lib/rubocop/cop/style/redundant_parentheses.rb +17 -9
- data/lib/rubocop/cop/style/single_argument_dig.rb +2 -1
- data/lib/rubocop/cop/style/single_line_do_end_block.rb +3 -1
- data/lib/rubocop/formatter/html_formatter.rb +4 -2
- data/lib/rubocop/version.rb +1 -1
- metadata +6 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: adf1db90b03283f492e0e10f234d54d6efc215a8b182965087313e3954d533dd
|
4
|
+
data.tar.gz: fa84dfd9d61e4834df9287e0ba0619622f4b7eb9e229e8de1172bc1742c04df5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
135
|
-
|
136
|
-
|
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
|
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?
|
117
|
-
|
118
|
-
|
119
|
-
|
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
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
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
|
|
@@ -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
|
65
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
66
66
|
def find_end_line(node)
|
67
|
-
if node.if_type?
|
68
|
-
node.
|
69
|
-
|
70
|
-
node.
|
71
|
-
|
72
|
-
node.
|
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
|
79
|
-
|
80
|
-
|
81
|
-
|
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
|
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
|
-
|
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
|
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
|
-
|
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(
|
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
|
-
|
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
|
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
|
121
|
-
|
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
|
-
(
|
63
|
+
(call
|
64
64
|
{
|
65
|
-
(block $(
|
66
|
-
$(
|
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
|
115
|
-
|
116
|
-
|
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
|
120
|
-
return
|
121
|
-
return
|
122
|
-
return
|
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
|
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) ||
|
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.
|
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.
|
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
|
-
|
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
|
data/lib/rubocop/version.rb
CHANGED
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.
|
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
|
+
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.
|
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: []
|