rubocop 1.77.0 → 1.78.0
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/README.md +1 -1
- data/config/default.yml +4 -1
- data/lib/rubocop/cli.rb +12 -1
- data/lib/rubocop/config_loader.rb +1 -38
- data/lib/rubocop/cop/internal_affairs/example_description.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_methods.rb +25 -4
- data/lib/rubocop/cop/lint/literal_as_condition.rb +3 -1
- data/lib/rubocop/cop/lint/redundant_type_conversion.rb +4 -4
- data/lib/rubocop/cop/naming/method_name.rb +87 -12
- data/lib/rubocop/cop/naming/predicate_method.rb +23 -1
- data/lib/rubocop/cop/security/eval.rb +2 -1
- data/lib/rubocop/cop/security/open.rb +1 -0
- data/lib/rubocop/cop/style/hash_conversion.rb +8 -9
- data/lib/rubocop/cop/style/it_block_parameter.rb +1 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +16 -0
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -9
- data/lib/rubocop/cop/style/single_line_methods.rb +4 -1
- data/lib/rubocop/pending_cops_reporter.rb +56 -0
- data/lib/rubocop/server/cache.rb +4 -2
- data/lib/rubocop/server/client_command/base.rb +10 -0
- data/lib/rubocop/server/client_command/exec.rb +2 -1
- data/lib/rubocop/server/client_command/start.rb +11 -1
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +1 -0
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5b840814034fbb98e67e3bb60014f0f00f9387148ab85b8b66f3a7ca711efdd2
|
4
|
+
data.tar.gz: b223e62eeeef5effd425654bf869ea22935beb8955df6e6fb22f0ba2a623d0f3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 83f46c7462c956b9a37e61feb329b3dfdb96e631cab64ffa3d1485bdc2d36a3585dacc17fc0b546ca98a0ad1014e1818eabf328a367654ad0151eaea3eea7369
|
7
|
+
data.tar.gz: d7cd91419c2ff881ef14b5f4406c9b87e555d2948c2c20b98bf02e6007e44b3d20b0aa73f3b91a595c5613164e551ba5f728e0852d084d04fe37312a65fa2b96
|
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.
|
56
|
+
gem 'rubocop', '~> 1.78', 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
@@ -3072,7 +3072,7 @@ Naming/PredicateMethod:
|
|
3072
3072
|
Description: 'Checks that predicate methods end with `?` and non-predicate methods do not.'
|
3073
3073
|
Enabled: pending
|
3074
3074
|
VersionAdded: '1.76'
|
3075
|
-
VersionChanged: '1.
|
3075
|
+
VersionChanged: '1.78'
|
3076
3076
|
# In `aggressive` mode, the cop will register an offense for predicate methods that
|
3077
3077
|
# may return a non-boolean value.
|
3078
3078
|
# In `conservative` mode, the cop will *not* register an offense for predicate methods
|
@@ -3082,6 +3082,9 @@ Naming/PredicateMethod:
|
|
3082
3082
|
- call
|
3083
3083
|
AllowedPatterns: []
|
3084
3084
|
AllowBangMethods: false
|
3085
|
+
# Methods that are known to not return a boolean value, despite ending in `?`.
|
3086
|
+
WaywardPredicates:
|
3087
|
+
- nonzero?
|
3085
3088
|
|
3086
3089
|
Naming/PredicatePrefix:
|
3087
3090
|
Description: 'Predicate method names should not be prefixed and end with a `?`.'
|
data/lib/rubocop/cli.rb
CHANGED
@@ -12,7 +12,7 @@ module RuboCop
|
|
12
12
|
STATUS_INTERRUPTED = Signal.list['INT'] + 128
|
13
13
|
DEFAULT_PARALLEL_OPTIONS = %i[
|
14
14
|
color config debug display_style_guide display_time display_only_fail_level_offenses
|
15
|
-
display_only_failed editor_mode except extra_details fail_level fix_layout format
|
15
|
+
display_only_failed editor_mode except extra_details fail_level fix_layout format formatters
|
16
16
|
ignore_disable_comments lint only only_guide_cops require safe
|
17
17
|
autocorrect safe_autocorrect autocorrect_all
|
18
18
|
].freeze
|
@@ -48,6 +48,7 @@ module RuboCop
|
|
48
48
|
validate_options_vs_config
|
49
49
|
parallel_by_default!
|
50
50
|
apply_default_formatter
|
51
|
+
report_pending_cops
|
51
52
|
execute_runners
|
52
53
|
end
|
53
54
|
end
|
@@ -155,6 +156,7 @@ module RuboCop
|
|
155
156
|
|
156
157
|
def act_on_options
|
157
158
|
set_options_to_config_loader
|
159
|
+
set_options_to_pending_cops_reporter
|
158
160
|
handle_editor_mode
|
159
161
|
|
160
162
|
@config_store.options_config = @options[:config] if @options[:config]
|
@@ -179,6 +181,11 @@ module RuboCop
|
|
179
181
|
ConfigLoader.ignore_unrecognized_cops = @options[:ignore_unrecognized_cops]
|
180
182
|
end
|
181
183
|
|
184
|
+
def set_options_to_pending_cops_reporter
|
185
|
+
PendingCopsReporter.disable_pending_cops = @options[:disable_pending_cops]
|
186
|
+
PendingCopsReporter.enable_pending_cops = @options[:enable_pending_cops]
|
187
|
+
end
|
188
|
+
|
182
189
|
def handle_editor_mode
|
183
190
|
RuboCop::LSP.enable if @options[:editor_mode]
|
184
191
|
end
|
@@ -208,5 +215,9 @@ module RuboCop
|
|
208
215
|
[[formatter, @options[:output_path]]]
|
209
216
|
end
|
210
217
|
end
|
218
|
+
|
219
|
+
def report_pending_cops
|
220
|
+
PendingCopsReporter.warn_if_needed(@config_store.for_pwd)
|
221
|
+
end
|
211
222
|
end
|
212
223
|
end
|
@@ -22,14 +22,6 @@ module RuboCop
|
|
22
22
|
class << self
|
23
23
|
include FileFinder
|
24
24
|
|
25
|
-
PENDING_BANNER = <<~BANNER
|
26
|
-
The following cops were added to RuboCop, but are not configured. Please set Enabled to either `true` or `false` in your `.rubocop.yml` file.
|
27
|
-
|
28
|
-
Please also note that you can opt-in to new cops by default by adding this to your config:
|
29
|
-
AllCops:
|
30
|
-
NewCops: enable
|
31
|
-
BANNER
|
32
|
-
|
33
25
|
attr_accessor :debug, :ignore_parent_exclusion, :disable_pending_cops, :enable_pending_cops,
|
34
26
|
:ignore_unrecognized_cops
|
35
27
|
attr_writer :default_configuration
|
@@ -132,21 +124,7 @@ module RuboCop
|
|
132
124
|
add_excludes_from_files(config, config_file)
|
133
125
|
end
|
134
126
|
|
135
|
-
merge_with_default(config, config_file)
|
136
|
-
unless possible_new_cops?(merged_config)
|
137
|
-
pending_cops = pending_cops_only_qualified(merged_config.pending_cops)
|
138
|
-
warn_on_pending_cops(pending_cops) unless pending_cops.empty?
|
139
|
-
end
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
def pending_cops_only_qualified(pending_cops)
|
144
|
-
pending_cops.select { |cop| Cop::Registry.qualified_cop?(cop.name) }
|
145
|
-
end
|
146
|
-
|
147
|
-
def possible_new_cops?(config)
|
148
|
-
disable_pending_cops || enable_pending_cops ||
|
149
|
-
config.disabled_new_cops? || config.enabled_new_cops?
|
127
|
+
merge_with_default(config, config_file)
|
150
128
|
end
|
151
129
|
|
152
130
|
def add_excludes_from_files(config, config_file)
|
@@ -208,21 +186,6 @@ module RuboCop
|
|
208
186
|
ConfigFinder.project_root
|
209
187
|
end
|
210
188
|
|
211
|
-
def warn_on_pending_cops(pending_cops)
|
212
|
-
warn Rainbow(PENDING_BANNER).yellow
|
213
|
-
|
214
|
-
pending_cops.each { |cop| warn_pending_cop cop }
|
215
|
-
|
216
|
-
warn Rainbow('For more information: https://docs.rubocop.org/rubocop/versioning.html').yellow
|
217
|
-
end
|
218
|
-
|
219
|
-
def warn_pending_cop(cop)
|
220
|
-
version = cop.metadata['VersionAdded'] || 'N/A'
|
221
|
-
|
222
|
-
warn Rainbow("#{cop.name}: # new in #{version}").yellow
|
223
|
-
warn Rainbow(' Enabled: true').yellow
|
224
|
-
end
|
225
|
-
|
226
189
|
# Merges the given configuration with the default one.
|
227
190
|
def merge_with_default(config, config_file, unset_nil: true)
|
228
191
|
resolver.merge_with_default(config, config_file, unset_nil: unset_nil)
|
@@ -46,7 +46,7 @@ module RuboCop
|
|
46
46
|
/\A(does not|doesn't) (register|find|flag|report)/ => 'registers',
|
47
47
|
/\A(does not|doesn't) add (a|an|any )?offense/ => 'registers an offense',
|
48
48
|
/\Aregisters no offense/ => 'registers an offense',
|
49
|
-
/\A(accepts|register)\b/ => 'registers'
|
49
|
+
/\A(accepts|allows|register)\b/ => 'registers'
|
50
50
|
}.freeze
|
51
51
|
|
52
52
|
EXPECT_NO_CORRECTIONS_DESCRIPTION_MAPPING = {
|
@@ -6,6 +6,10 @@ module RuboCop
|
|
6
6
|
# Checks for duplicated instance (or singleton) method
|
7
7
|
# definitions.
|
8
8
|
#
|
9
|
+
# NOTE: Aliasing a method to itself is allowed, as it indicates that
|
10
|
+
# the developer intends to suppress Ruby's method redefinition warnings.
|
11
|
+
# See https://bugs.ruby-lang.org/issues/13574.
|
12
|
+
#
|
9
13
|
# @example
|
10
14
|
#
|
11
15
|
# # bad
|
@@ -40,6 +44,18 @@ module RuboCop
|
|
40
44
|
#
|
41
45
|
# alias bar foo
|
42
46
|
#
|
47
|
+
# # good
|
48
|
+
# alias foo foo
|
49
|
+
# def foo
|
50
|
+
# 1
|
51
|
+
# end
|
52
|
+
#
|
53
|
+
# # good
|
54
|
+
# alias_method :foo, :foo
|
55
|
+
# def foo
|
56
|
+
# 1
|
57
|
+
# end
|
58
|
+
#
|
43
59
|
# @example AllCops:ActiveSupportExtensionsEnabled: false (default)
|
44
60
|
#
|
45
61
|
# # good
|
@@ -113,11 +129,13 @@ module RuboCop
|
|
113
129
|
|
114
130
|
# @!method method_alias?(node)
|
115
131
|
def_node_matcher :method_alias?, <<~PATTERN
|
116
|
-
(alias (sym $_name) sym)
|
132
|
+
(alias (sym $_name) (sym $_original_name))
|
117
133
|
PATTERN
|
118
134
|
|
119
135
|
def on_alias(node)
|
120
|
-
|
136
|
+
name, original_name = method_alias?(node)
|
137
|
+
return unless name && original_name
|
138
|
+
return if name == original_name
|
121
139
|
return if node.ancestors.any?(&:if_type?)
|
122
140
|
|
123
141
|
found_instance_method(node, name)
|
@@ -125,7 +143,7 @@ module RuboCop
|
|
125
143
|
|
126
144
|
# @!method alias_method?(node)
|
127
145
|
def_node_matcher :alias_method?, <<~PATTERN
|
128
|
-
(send nil? :alias_method (sym $_name)
|
146
|
+
(send nil? :alias_method (sym $_name) (sym $_original_name))
|
129
147
|
PATTERN
|
130
148
|
|
131
149
|
# @!method delegate_method?(node)
|
@@ -140,7 +158,10 @@ module RuboCop
|
|
140
158
|
def_node_matcher :sym_name, '(sym $_name)'
|
141
159
|
|
142
160
|
def on_send(node) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
143
|
-
|
161
|
+
name, original_name = alias_method?(node)
|
162
|
+
|
163
|
+
if name && original_name
|
164
|
+
return if name == original_name
|
144
165
|
return if node.ancestors.any?(&:if_type?)
|
145
166
|
|
146
167
|
found_instance_method(node, name)
|
@@ -123,7 +123,9 @@ module RuboCop
|
|
123
123
|
# rubocop:enable Metrics/AbcSize
|
124
124
|
|
125
125
|
def on_case(case_node)
|
126
|
-
if case_node.condition
|
126
|
+
if (cond = case_node.condition)
|
127
|
+
return if !cond.falsey_literal? && !cond.truthy_literal?
|
128
|
+
|
127
129
|
check_case(case_node)
|
128
130
|
else
|
129
131
|
case_node.when_branches.each do |when_node|
|
@@ -185,9 +185,9 @@ module RuboCop
|
|
185
185
|
(hash (pair (sym :exception) false))
|
186
186
|
PATTERN
|
187
187
|
|
188
|
-
# rubocop:disable Metrics/AbcSize
|
188
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
189
189
|
def on_send(node)
|
190
|
-
return if hash_or_set_with_block?(node)
|
190
|
+
return if node.arguments.any? || hash_or_set_with_block?(node)
|
191
191
|
|
192
192
|
receiver = find_receiver(node)
|
193
193
|
return unless literal_receiver?(node, receiver) ||
|
@@ -198,10 +198,10 @@ module RuboCop
|
|
198
198
|
message = format(MSG, method: node.method_name)
|
199
199
|
|
200
200
|
add_offense(node.loc.selector, message: message) do |corrector|
|
201
|
-
corrector.remove(node.loc.dot.join(node.loc.selector))
|
201
|
+
corrector.remove(node.loc.dot.join(node.loc.end || node.loc.selector))
|
202
202
|
end
|
203
203
|
end
|
204
|
-
# rubocop:enable Metrics/AbcSize
|
204
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
205
205
|
alias on_csend on_send
|
206
206
|
|
207
207
|
private
|
@@ -39,6 +39,20 @@ module RuboCop
|
|
39
39
|
# # good
|
40
40
|
# def foo_bar; end
|
41
41
|
#
|
42
|
+
# # bad
|
43
|
+
# define_method :fooBar do
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# # good
|
47
|
+
# define_method :foo_bar do
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# # bad
|
51
|
+
# Struct.new(:fooBar)
|
52
|
+
#
|
53
|
+
# # good
|
54
|
+
# Struct.new(:foo_bar)
|
55
|
+
#
|
42
56
|
# @example EnforcedStyle: camelCase
|
43
57
|
# # bad
|
44
58
|
# def foo_bar; end
|
@@ -46,6 +60,20 @@ module RuboCop
|
|
46
60
|
# # good
|
47
61
|
# def fooBar; end
|
48
62
|
#
|
63
|
+
# # bad
|
64
|
+
# define_method :foo_bar do
|
65
|
+
# end
|
66
|
+
#
|
67
|
+
# # good
|
68
|
+
# define_method :fooBar do
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
# # bad
|
72
|
+
# Struct.new(:foo_bar)
|
73
|
+
#
|
74
|
+
# # good
|
75
|
+
# Struct.new(:fooBar)
|
76
|
+
#
|
49
77
|
# @example ForbiddenIdentifiers: ['def', 'super']
|
50
78
|
# # bad
|
51
79
|
# def def; end
|
@@ -72,7 +100,46 @@ module RuboCop
|
|
72
100
|
# @!method str_name(node)
|
73
101
|
def_node_matcher :str_name, '(str $_name)'
|
74
102
|
|
103
|
+
# @!method new_struct?(node)
|
104
|
+
def_node_matcher :new_struct?, '(send (const {nil? cbase} :Struct) :new ...)'
|
105
|
+
|
75
106
|
def on_send(node)
|
107
|
+
if node.method?(:define_method) || node.method?(:define_singleton_method)
|
108
|
+
handle_define_method(node)
|
109
|
+
elsif new_struct?(node)
|
110
|
+
handle_new_struct(node)
|
111
|
+
else
|
112
|
+
handle_attr_accessor(node)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def on_def(node)
|
117
|
+
return if node.operator_method? || matches_allowed_pattern?(node.method_name)
|
118
|
+
|
119
|
+
if forbidden_name?(node.method_name.to_s)
|
120
|
+
register_forbidden_name(node)
|
121
|
+
else
|
122
|
+
check_name(node, node.method_name, node.loc.name)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
alias on_defs on_def
|
126
|
+
|
127
|
+
private
|
128
|
+
|
129
|
+
def handle_define_method(node)
|
130
|
+
return unless node.first_argument&.type?(:str, :sym)
|
131
|
+
|
132
|
+
handle_method_name(node, node.first_argument.value)
|
133
|
+
end
|
134
|
+
|
135
|
+
def handle_new_struct(node)
|
136
|
+
arguments = node.first_argument&.str_type? ? node.arguments[1..] : node.arguments
|
137
|
+
arguments.select { |argument| argument.type?(:sym, :str) }.each do |name|
|
138
|
+
handle_method_name(name, name.value)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def handle_attr_accessor(node)
|
76
143
|
return unless (attrs = node.attribute_accessor?)
|
77
144
|
|
78
145
|
attrs.last.each do |name_item|
|
@@ -87,45 +154,53 @@ module RuboCop
|
|
87
154
|
end
|
88
155
|
end
|
89
156
|
|
90
|
-
def
|
91
|
-
return if
|
157
|
+
def handle_method_name(node, name)
|
158
|
+
return if !name || matches_allowed_pattern?(name)
|
92
159
|
|
93
|
-
if forbidden_name?(
|
160
|
+
if forbidden_name?(name.to_s)
|
94
161
|
register_forbidden_name(node)
|
95
162
|
else
|
96
|
-
check_name(node,
|
163
|
+
check_name(node, name, range_position(node))
|
97
164
|
end
|
98
165
|
end
|
99
|
-
alias on_defs on_def
|
100
|
-
|
101
|
-
private
|
102
166
|
|
103
167
|
def forbidden_name?(name)
|
104
168
|
forbidden_identifier?(name) || forbidden_pattern?(name)
|
105
169
|
end
|
106
170
|
|
171
|
+
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
107
172
|
def register_forbidden_name(node)
|
108
173
|
if node.any_def_type?
|
109
174
|
name_node = node.loc.name
|
110
175
|
method_name = node.method_name
|
111
|
-
|
112
|
-
|
176
|
+
elsif node.literal?
|
177
|
+
name_node = node
|
178
|
+
method_name = node.value
|
179
|
+
elsif (attrs = node.attribute_accessor?)
|
113
180
|
name_node = attrs.last.last
|
114
181
|
method_name = attr_name(name_node)
|
182
|
+
else
|
183
|
+
name_node = node.first_argument
|
184
|
+
method_name = node.first_argument.value
|
115
185
|
end
|
116
186
|
message = format(MSG_FORBIDDEN, identifier: method_name)
|
117
187
|
add_offense(name_node, message: message)
|
118
188
|
end
|
189
|
+
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize
|
119
190
|
|
120
191
|
def attr_name(name_item)
|
121
192
|
sym_name(name_item) || str_name(name_item)
|
122
193
|
end
|
123
194
|
|
124
195
|
def range_position(node)
|
125
|
-
|
126
|
-
|
196
|
+
if node.loc.respond_to?(:selector)
|
197
|
+
selector_end_pos = node.loc.selector.end_pos + 1
|
198
|
+
expr_end_pos = node.source_range.end_pos
|
127
199
|
|
128
|
-
|
200
|
+
range_between(selector_end_pos, expr_end_pos)
|
201
|
+
else
|
202
|
+
node.source_range
|
203
|
+
end
|
129
204
|
end
|
130
205
|
|
131
206
|
def message(style)
|
@@ -26,6 +26,11 @@ module RuboCop
|
|
26
26
|
# guidelines. By default, `call` is allowed. The cop also has `AllowedPatterns`
|
27
27
|
# configuration to allow method names by regular expression.
|
28
28
|
#
|
29
|
+
# Although returning a call to another predicate method is treated as a boolean value,
|
30
|
+
# certain method names can be known to not return a boolean, despite ending in a `?`
|
31
|
+
# (for example, `Numeric#nonzero?` returns `self` or `nil`). These methods can be
|
32
|
+
# configured using `NonBooleanPredicates`.
|
33
|
+
#
|
29
34
|
# The cop can furthermore be configured to allow all bang methods (method names
|
30
35
|
# ending with `!`), with `AllowBangMethods: true` (default false).
|
31
36
|
#
|
@@ -164,7 +169,7 @@ module RuboCop
|
|
164
169
|
def unknown_method_call?(value)
|
165
170
|
return false unless value.call_type?
|
166
171
|
|
167
|
-
!
|
172
|
+
!method_returning_boolean?(value)
|
168
173
|
end
|
169
174
|
|
170
175
|
def return_values(node)
|
@@ -190,7 +195,13 @@ module RuboCop
|
|
190
195
|
|
191
196
|
def boolean_return?(value)
|
192
197
|
return true if value.boolean_type?
|
198
|
+
|
199
|
+
method_returning_boolean?(value)
|
200
|
+
end
|
201
|
+
|
202
|
+
def method_returning_boolean?(value)
|
193
203
|
return false unless value.call_type?
|
204
|
+
return false if wayward_predicate?(value.method_name)
|
194
205
|
|
195
206
|
value.comparison_method? || value.predicate_method? || value.negation_method?
|
196
207
|
end
|
@@ -275,6 +286,17 @@ module RuboCop
|
|
275
286
|
def allow_bang_methods?
|
276
287
|
cop_config.fetch('AllowBangMethods', false)
|
277
288
|
end
|
289
|
+
|
290
|
+
# If a method ending in `?` is known to not return a boolean value,
|
291
|
+
# (for example, `Numeric#nonzero?`) it should be treated as a non-boolean
|
292
|
+
# value, despite the method naming.
|
293
|
+
def wayward_predicate?(name)
|
294
|
+
wayward_predicates.include?(name.to_s)
|
295
|
+
end
|
296
|
+
|
297
|
+
def wayward_predicates
|
298
|
+
Array(cop_config.fetch('WaywardPredicates', []))
|
299
|
+
end
|
278
300
|
end
|
279
301
|
end
|
280
302
|
end
|
@@ -11,13 +11,14 @@ module RuboCop
|
|
11
11
|
#
|
12
12
|
# eval(something)
|
13
13
|
# binding.eval(something)
|
14
|
+
# Kernel.eval(something)
|
14
15
|
class Eval < Base
|
15
16
|
MSG = 'The use of `eval` is a serious security risk.'
|
16
17
|
RESTRICT_ON_SEND = %i[eval].freeze
|
17
18
|
|
18
19
|
# @!method eval?(node)
|
19
20
|
def_node_matcher :eval?, <<~PATTERN
|
20
|
-
(send {nil? (send nil? :binding)} :eval $!str ...)
|
21
|
+
(send {nil? (send nil? :binding) (const {cbase nil?} :Kernel)} :eval $!str ...)
|
21
22
|
PATTERN
|
22
23
|
|
23
24
|
def on_send(node)
|
@@ -44,10 +44,10 @@ module RuboCop
|
|
44
44
|
class HashConversion < Base
|
45
45
|
extend AutoCorrector
|
46
46
|
|
47
|
-
MSG_TO_H = 'Prefer ary.to_h to Hash[ary]
|
48
|
-
MSG_LITERAL_MULTI_ARG = 'Prefer literal hash to Hash[arg1, arg2, ...]
|
49
|
-
MSG_LITERAL_HASH_ARG = 'Prefer literal hash to Hash[key: value, ...]
|
50
|
-
MSG_SPLAT = 'Prefer array_of_pairs.to_h to Hash[*array]
|
47
|
+
MSG_TO_H = 'Prefer `ary.to_h` to `Hash[ary]`.'
|
48
|
+
MSG_LITERAL_MULTI_ARG = 'Prefer literal hash to `Hash[arg1, arg2, ...]`.'
|
49
|
+
MSG_LITERAL_HASH_ARG = 'Prefer literal hash to `Hash[key: value, ...]`.'
|
50
|
+
MSG_SPLAT = 'Prefer `array_of_pairs.to_h` to `Hash[*array]`.'
|
51
51
|
RESTRICT_ON_SEND = %i[[]].freeze
|
52
52
|
|
53
53
|
# @!method hash_from_array?(node)
|
@@ -64,11 +64,11 @@ module RuboCop
|
|
64
64
|
# Hash[a1, a2, a3, a4] => {a1 => a2, a3 => a4}
|
65
65
|
# ...but don't suggest correction if there is odd number of them (it is a bug)
|
66
66
|
node.arguments.one? ? single_argument(node) : multi_argument(node)
|
67
|
+
ignore_node(node)
|
67
68
|
end
|
68
69
|
|
69
70
|
private
|
70
71
|
|
71
|
-
# rubocop:disable Metrics/MethodLength
|
72
72
|
def single_argument(node)
|
73
73
|
first_argument = node.first_argument
|
74
74
|
if first_argument.hash_type?
|
@@ -83,11 +83,8 @@ module RuboCop
|
|
83
83
|
replacement = "(#{replacement})" if requires_parens?(first_argument)
|
84
84
|
corrector.replace(node, "#{replacement}.to_h")
|
85
85
|
end
|
86
|
-
|
87
|
-
ignore_node(node)
|
88
86
|
end
|
89
87
|
end
|
90
|
-
# rubocop:enable Metrics/MethodLength
|
91
88
|
|
92
89
|
def use_zip_method_without_argument?(first_argument)
|
93
90
|
return false unless first_argument&.send_type?
|
@@ -131,7 +128,9 @@ module RuboCop
|
|
131
128
|
corrector.replace(node, args_to_hash(node.arguments))
|
132
129
|
|
133
130
|
parent = node.parent
|
134
|
-
|
131
|
+
if parent&.send_type? && !parent.method?(:to_h) && !parent.parenthesized?
|
132
|
+
add_parentheses(parent, corrector)
|
133
|
+
end
|
135
134
|
end
|
136
135
|
end
|
137
136
|
end
|
@@ -109,7 +109,7 @@ module RuboCop
|
|
109
109
|
private
|
110
110
|
|
111
111
|
def find_block_variables(node, block_argument_name)
|
112
|
-
node.each_descendant(:lvar).select do |descendant|
|
112
|
+
node.body.each_descendant(:lvar).select do |descendant|
|
113
113
|
descendant.source == block_argument_name
|
114
114
|
end
|
115
115
|
end
|
@@ -132,6 +132,22 @@ module RuboCop
|
|
132
132
|
# bar :baz
|
133
133
|
# end
|
134
134
|
#
|
135
|
+
# @example AllowedMethods: ["puts", "print"]
|
136
|
+
#
|
137
|
+
# # good
|
138
|
+
# puts "Hello world"
|
139
|
+
# print "Hello world"
|
140
|
+
# # still enforces parentheses on other methods
|
141
|
+
# array.delete(e)
|
142
|
+
#
|
143
|
+
# @example AllowedPatterns: ["^assert"]
|
144
|
+
#
|
145
|
+
# # good
|
146
|
+
# assert_equal 'test', x
|
147
|
+
# assert_match(/foo/, bar)
|
148
|
+
# # still enforces parentheses on other methods
|
149
|
+
# array.delete(e)
|
150
|
+
#
|
135
151
|
# @example AllowParenthesesInMultilineCall: false (default)
|
136
152
|
#
|
137
153
|
# # bad
|
@@ -49,7 +49,7 @@ module RuboCop
|
|
49
49
|
(block
|
50
50
|
$(call _ :fetch _)
|
51
51
|
(args)
|
52
|
-
${nil?
|
52
|
+
${nil? basic_literal? const_type?})
|
53
53
|
PATTERN
|
54
54
|
|
55
55
|
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
@@ -71,14 +71,6 @@ module RuboCop
|
|
71
71
|
|
72
72
|
private
|
73
73
|
|
74
|
-
def basic_literal?(node)
|
75
|
-
node&.basic_literal?
|
76
|
-
end
|
77
|
-
|
78
|
-
def const_type?(node)
|
79
|
-
node&.const_type?
|
80
|
-
end
|
81
|
-
|
82
74
|
def should_not_check?(send, body)
|
83
75
|
(body&.const_type? && !check_for_constant?) ||
|
84
76
|
(body&.str_type? && !check_for_string?) ||
|
@@ -130,7 +130,10 @@ module RuboCop
|
|
130
130
|
end
|
131
131
|
|
132
132
|
def require_parentheses?(method_body)
|
133
|
-
|
133
|
+
return false unless method_body.send_type?
|
134
|
+
return false if method_body.arithmetic_operation?
|
135
|
+
|
136
|
+
!method_body.arguments.empty? && !method_body.comparison_method?
|
134
137
|
end
|
135
138
|
|
136
139
|
def disallow_endless_method_style?
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
# Reports information about pending cops that are not explicitly configured.
|
5
|
+
#
|
6
|
+
# This class is responsible for displaying warnings when new cops have been added to RuboCop
|
7
|
+
# but have not yet been enabled or disabled in the user's configuration.
|
8
|
+
# It provides a centralized way to determine whether such warnings should be shown,
|
9
|
+
# based on global flags or configuration settings.
|
10
|
+
class PendingCopsReporter
|
11
|
+
class << self
|
12
|
+
PENDING_BANNER = <<~BANNER
|
13
|
+
The following cops were added to RuboCop, but are not configured. Please set Enabled to either `true` or `false` in your `.rubocop.yml` file.
|
14
|
+
|
15
|
+
Please also note that you can opt-in to new cops by default by adding this to your config:
|
16
|
+
AllCops:
|
17
|
+
NewCops: enable
|
18
|
+
BANNER
|
19
|
+
|
20
|
+
attr_accessor :disable_pending_cops, :enable_pending_cops
|
21
|
+
|
22
|
+
def warn_if_needed(config)
|
23
|
+
return if possible_new_cops?(config)
|
24
|
+
|
25
|
+
pending_cops = pending_cops_only_qualified(config.pending_cops)
|
26
|
+
warn_on_pending_cops(pending_cops) unless pending_cops.empty?
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def pending_cops_only_qualified(pending_cops)
|
32
|
+
pending_cops.select { |cop| Cop::Registry.qualified_cop?(cop.name) }
|
33
|
+
end
|
34
|
+
|
35
|
+
def possible_new_cops?(config)
|
36
|
+
disable_pending_cops || enable_pending_cops ||
|
37
|
+
config.disabled_new_cops? || config.enabled_new_cops?
|
38
|
+
end
|
39
|
+
|
40
|
+
def warn_on_pending_cops(pending_cops)
|
41
|
+
warn Rainbow(PENDING_BANNER).yellow
|
42
|
+
|
43
|
+
pending_cops.each { |cop| warn_pending_cop cop }
|
44
|
+
|
45
|
+
warn Rainbow('For more information: https://docs.rubocop.org/rubocop/versioning.html').yellow
|
46
|
+
end
|
47
|
+
|
48
|
+
def warn_pending_cop(cop)
|
49
|
+
version = cop.metadata['VersionAdded'] || 'N/A'
|
50
|
+
|
51
|
+
warn Rainbow("#{cop.name}: # new in #{version}").yellow
|
52
|
+
warn Rainbow(' Enabled: true').yellow
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/rubocop/server/cache.rb
CHANGED
@@ -46,12 +46,14 @@ module RuboCop
|
|
46
46
|
end
|
47
47
|
|
48
48
|
# rubocop:disable Metrics/AbcSize
|
49
|
-
def restart_key
|
49
|
+
def restart_key(args_config_file_path: nil)
|
50
50
|
lockfile_path = LOCKFILE_NAMES.map do |lockfile_name|
|
51
51
|
Pathname(project_dir).join(lockfile_name)
|
52
52
|
end.find(&:exist?)
|
53
53
|
version_data = lockfile_path&.read || RuboCop::Version::STRING
|
54
|
-
config_data = Pathname(
|
54
|
+
config_data = Pathname(
|
55
|
+
args_config_file_path || ConfigFinder.find_config_path(Dir.pwd)
|
56
|
+
).read
|
55
57
|
yaml = load_erb_templated_yaml(config_data)
|
56
58
|
|
57
59
|
inherit_from_data = inherit_from_data(yaml)
|
@@ -38,6 +38,16 @@ module RuboCop
|
|
38
38
|
warn 'RuboCop server is not running.' unless running
|
39
39
|
end
|
40
40
|
end
|
41
|
+
|
42
|
+
class << self
|
43
|
+
def args_config_file_path
|
44
|
+
first_args_config_key_index = ARGV.index { |value| ['-c', '--config'].include?(value) }
|
45
|
+
|
46
|
+
return if first_args_config_key_index.nil?
|
47
|
+
|
48
|
+
ARGV[first_args_config_key_index + 1]
|
49
|
+
end
|
50
|
+
end
|
41
51
|
end
|
42
52
|
end
|
43
53
|
end
|
@@ -34,7 +34,7 @@ module RuboCop
|
|
34
34
|
exit 0
|
35
35
|
end
|
36
36
|
|
37
|
-
|
37
|
+
write_version_file
|
38
38
|
|
39
39
|
host = ENV.fetch('RUBOCOP_SERVER_HOST', '127.0.0.1')
|
40
40
|
port = ENV.fetch('RUBOCOP_SERVER_PORT', 0)
|
@@ -42,6 +42,16 @@ module RuboCop
|
|
42
42
|
Server::Core.new.start(host, port, detach: @detach)
|
43
43
|
end
|
44
44
|
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def write_version_file
|
49
|
+
Cache.write_version_file(
|
50
|
+
Cache.restart_key(
|
51
|
+
args_config_file_path: self.class.args_config_file_path
|
52
|
+
)
|
53
|
+
)
|
54
|
+
end
|
45
55
|
end
|
46
56
|
end
|
47
57
|
end
|
data/lib/rubocop/version.rb
CHANGED
data/lib/rubocop.rb
CHANGED
@@ -812,6 +812,7 @@ require_relative 'rubocop/options'
|
|
812
812
|
require_relative 'rubocop/remote_config'
|
813
813
|
require_relative 'rubocop/target_ruby'
|
814
814
|
require_relative 'rubocop/yaml_duplication_checker'
|
815
|
+
require_relative 'rubocop/pending_cops_reporter'
|
815
816
|
|
816
817
|
# rubocop:enable Style/RequireOrder
|
817
818
|
|
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.
|
4
|
+
version: 1.78.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bozhidar Batsov
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
- Yuji Nakayama
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2025-
|
12
|
+
date: 2025-07-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: json
|
@@ -1040,6 +1040,7 @@ files:
|
|
1040
1040
|
- lib/rubocop/name_similarity.rb
|
1041
1041
|
- lib/rubocop/options.rb
|
1042
1042
|
- lib/rubocop/path_util.rb
|
1043
|
+
- lib/rubocop/pending_cops_reporter.rb
|
1043
1044
|
- lib/rubocop/platform.rb
|
1044
1045
|
- lib/rubocop/plugin.rb
|
1045
1046
|
- lib/rubocop/plugin/configuration_integrator.rb
|
@@ -1087,9 +1088,9 @@ licenses:
|
|
1087
1088
|
- MIT
|
1088
1089
|
metadata:
|
1089
1090
|
homepage_uri: https://rubocop.org/
|
1090
|
-
changelog_uri: https://github.com/rubocop/rubocop/releases/tag/v1.
|
1091
|
+
changelog_uri: https://github.com/rubocop/rubocop/releases/tag/v1.78.0
|
1091
1092
|
source_code_uri: https://github.com/rubocop/rubocop/
|
1092
|
-
documentation_uri: https://docs.rubocop.org/rubocop/1.
|
1093
|
+
documentation_uri: https://docs.rubocop.org/rubocop/1.78/
|
1093
1094
|
bug_tracker_uri: https://github.com/rubocop/rubocop/issues
|
1094
1095
|
rubygems_mfa_required: 'true'
|
1095
1096
|
rdoc_options: []
|