rubocop 1.62.1 → 1.63.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/config/default.yml +22 -3
- data/lib/rubocop/cached_data.rb +11 -3
- data/lib/rubocop/cli.rb +4 -0
- data/lib/rubocop/config.rb +33 -10
- data/lib/rubocop/config_obsoletion.rb +1 -1
- data/lib/rubocop/cop/base.rb +40 -1
- data/lib/rubocop/cop/internal_affairs/example_description.rb +2 -1
- data/lib/rubocop/cop/layout/comment_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -0
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +2 -2
- data/lib/rubocop/cop/lint/debugger.rb +27 -2
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +1 -1
- data/lib/rubocop/cop/lint/mixed_case_range.rb +9 -4
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_with_index.rb +3 -0
- data/lib/rubocop/cop/lint/unreachable_code.rb +4 -2
- data/lib/rubocop/cop/lint/unreachable_loop.rb +8 -2
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +2 -2
- data/lib/rubocop/cop/mixin/code_length.rb +12 -1
- data/lib/rubocop/cop/mixin/method_complexity.rb +15 -6
- data/lib/rubocop/cop/mixin/safe_assignment.rb +1 -1
- data/lib/rubocop/cop/naming/block_forwarding.rb +31 -12
- data/lib/rubocop/cop/naming/file_name.rb +2 -2
- data/lib/rubocop/cop/naming/inclusive_language.rb +1 -2
- data/lib/rubocop/cop/security/compound_hash.rb +2 -2
- data/lib/rubocop/cop/style/alias.rb +1 -0
- data/lib/rubocop/cop/style/arguments_forwarding.rb +2 -1
- data/lib/rubocop/cop/style/collection_compact.rb +3 -3
- data/lib/rubocop/cop/style/conditional_assignment.rb +1 -1
- data/lib/rubocop/cop/style/copyright.rb +16 -11
- data/lib/rubocop/cop/style/eval_with_location.rb +3 -1
- data/lib/rubocop/cop/style/exact_regexp_match.rb +2 -1
- data/lib/rubocop/cop/style/format_string.rb +9 -9
- data/lib/rubocop/cop/style/map_into_array.rb +175 -0
- data/lib/rubocop/cop/style/map_to_hash.rb +1 -1
- data/lib/rubocop/cop/style/map_to_set.rb +1 -1
- data/lib/rubocop/cop/style/numeric_predicate.rb +10 -2
- data/lib/rubocop/cop/style/redundant_argument.rb +24 -1
- data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +1 -1
- data/lib/rubocop/cop/style/redundant_each.rb +1 -1
- data/lib/rubocop/cop/style/redundant_filter_chain.rb +1 -1
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +11 -15
- data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -1
- data/lib/rubocop/cop/style/require_order.rb +1 -1
- data/lib/rubocop/cop/style/send.rb +4 -4
- data/lib/rubocop/cop/style/special_global_vars.rb +1 -2
- data/lib/rubocop/cop/style/top_level_method_definition.rb +1 -1
- data/lib/rubocop/cop/team.rb +3 -0
- data/lib/rubocop/formatter/clang_style_formatter.rb +3 -7
- data/lib/rubocop/formatter/tap_formatter.rb +3 -7
- data/lib/rubocop/lockfile.rb +56 -7
- data/lib/rubocop/lsp/routes.rb +3 -4
- data/lib/rubocop/lsp/server.rb +2 -0
- data/lib/rubocop/options.rb +3 -3
- data/lib/rubocop/rake_task.rb +1 -1
- data/lib/rubocop/rspec/expect_offense.rb +8 -0
- data/lib/rubocop/rspec/shared_contexts.rb +13 -1
- data/lib/rubocop/runner.rb +5 -1
- data/lib/rubocop/version.rb +5 -5
- 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: 1911c884de81dd524490fea5075e7605d3ccf82fad85ebc9d09adbe5d29637ca
|
4
|
+
data.tar.gz: 8206c237dd18bbcd9769d55b1206d160ce766a21caa5c8f8ea956ae845371ea2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 429dfdfda489516f4856fa00ad50c062a172588ca4bb1006baa25213c2fb949b0781af446d689200f0a87017f47708ad49324a6644cce104f79dd42b129dd680
|
7
|
+
data.tar.gz: ce8363fa68a56f9c5f36c40d1596932b1233854823c54bfb9dc36a669256dca64459186037fe10e9723a550cec0a6f11df2e1d802e4471d8c9d1e98db8c528f3
|
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.63', 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
@@ -156,13 +156,14 @@ AllCops:
|
|
156
156
|
# included.
|
157
157
|
SuggestExtensions:
|
158
158
|
rubocop-rails: [rails]
|
159
|
-
rubocop-rspec: [rspec
|
159
|
+
rubocop-rspec: [rspec]
|
160
160
|
rubocop-minitest: [minitest]
|
161
161
|
rubocop-sequel: [sequel]
|
162
162
|
rubocop-rake: [rake]
|
163
163
|
rubocop-graphql: [graphql]
|
164
164
|
rubocop-capybara: [capybara]
|
165
165
|
rubocop-factory_bot: [factory_bot, factory_bot_rails]
|
166
|
+
rubocop-rspec_rails: [rspec-rails]
|
166
167
|
# Enable/Disable checking the methods extended by Active Support.
|
167
168
|
ActiveSupportExtensionsEnabled: false
|
168
169
|
|
@@ -1657,7 +1658,7 @@ Lint/Debugger:
|
|
1657
1658
|
Description: 'Check for debugger calls.'
|
1658
1659
|
Enabled: true
|
1659
1660
|
VersionAdded: '0.14'
|
1660
|
-
VersionChanged: '1.
|
1661
|
+
VersionChanged: '1.63'
|
1661
1662
|
DebuggerMethods:
|
1662
1663
|
# Groups are available so that a specific group can be disabled in
|
1663
1664
|
# a user's configuration, but are otherwise not significant.
|
@@ -1670,8 +1671,14 @@ Lint/Debugger:
|
|
1670
1671
|
- Kernel.byebug
|
1671
1672
|
- Kernel.remote_byebug
|
1672
1673
|
Capybara:
|
1674
|
+
- page.save_and_open_page
|
1675
|
+
- page.save_and_open_screenshot
|
1676
|
+
- page.save_page
|
1677
|
+
- page.save_screenshot
|
1673
1678
|
- save_and_open_page
|
1674
1679
|
- save_and_open_screenshot
|
1680
|
+
- save_page
|
1681
|
+
- save_screenshot
|
1675
1682
|
debug.rb:
|
1676
1683
|
- binding.b
|
1677
1684
|
- binding.break
|
@@ -1693,6 +1700,10 @@ Lint/Debugger:
|
|
1693
1700
|
- jard
|
1694
1701
|
WebConsole:
|
1695
1702
|
- binding.console
|
1703
|
+
DebuggerRequires:
|
1704
|
+
debug.rb:
|
1705
|
+
- debug/open
|
1706
|
+
- debug/start
|
1696
1707
|
|
1697
1708
|
Lint/DeprecatedClassMethods:
|
1698
1709
|
Description: 'Check for deprecated class method calls.'
|
@@ -2762,7 +2773,8 @@ Naming/FileName:
|
|
2762
2773
|
VersionChanged: '1.23'
|
2763
2774
|
# Camel case file names listed in `AllCops:Include` and all file names listed
|
2764
2775
|
# in `AllCops:Exclude` are excluded by default. Add extra excludes here.
|
2765
|
-
Exclude:
|
2776
|
+
Exclude:
|
2777
|
+
- Rakefile.rb
|
2766
2778
|
# When `true`, requires that each source file should define a class or module
|
2767
2779
|
# with a name which matches the file name (converted to ... case).
|
2768
2780
|
# It further expects it to be nested inside modules which match the names
|
@@ -4276,6 +4288,13 @@ Style/MapCompactWithConditionalBlock:
|
|
4276
4288
|
Enabled: pending
|
4277
4289
|
VersionAdded: '1.30'
|
4278
4290
|
|
4291
|
+
Style/MapIntoArray:
|
4292
|
+
Description: 'Checks for usages of `each` with `<<`, `push`, or `append` which can be replaced by `map`.'
|
4293
|
+
StyleGuide: '#functional-code'
|
4294
|
+
Enabled: pending
|
4295
|
+
VersionAdded: '1.63'
|
4296
|
+
Safe: false
|
4297
|
+
|
4279
4298
|
Style/MapToHash:
|
4280
4299
|
Description: 'Prefer `to_h` with a block over `map.to_h`.'
|
4281
4300
|
Enabled: pending
|
data/lib/rubocop/cached_data.rb
CHANGED
@@ -48,11 +48,19 @@ module RuboCop
|
|
48
48
|
source_buffer = Parser::Source::Buffer.new(@filename)
|
49
49
|
source_buffer.source = File.read(@filename, encoding: Encoding::UTF_8)
|
50
50
|
offenses.map! do |o|
|
51
|
-
location =
|
52
|
-
o['location']['begin_pos'],
|
53
|
-
o['location']['end_pos'])
|
51
|
+
location = location_from_source_buffer(o, source_buffer)
|
54
52
|
Cop::Offense.new(o['severity'], location, o['message'], o['cop_name'], o['status'].to_sym)
|
55
53
|
end
|
56
54
|
end
|
55
|
+
|
56
|
+
def location_from_source_buffer(offense, source_buffer)
|
57
|
+
begin_pos = offense['location']['begin_pos']
|
58
|
+
end_pos = offense['location']['end_pos']
|
59
|
+
if begin_pos.zero? && end_pos.zero?
|
60
|
+
Cop::Offense::NO_LOCATION
|
61
|
+
else
|
62
|
+
Parser::Source::Range.new(source_buffer, begin_pos, end_pos)
|
63
|
+
end
|
64
|
+
end
|
57
65
|
end
|
58
66
|
end
|
data/lib/rubocop/cli.rb
CHANGED
@@ -57,6 +57,10 @@ module RuboCop
|
|
57
57
|
rescue RuboCop::Error => e
|
58
58
|
warn Rainbow("Error: #{e.message}").red
|
59
59
|
STATUS_ERROR
|
60
|
+
rescue Interrupt
|
61
|
+
warn ''
|
62
|
+
warn 'Exiting...'
|
63
|
+
STATUS_INTERRUPTED
|
60
64
|
rescue Finished
|
61
65
|
STATUS_SUCCESS
|
62
66
|
rescue OptionParser::InvalidOption => e
|
data/lib/rubocop/config.rb
CHANGED
@@ -263,6 +263,7 @@ module RuboCop
|
|
263
263
|
PathUtil.smart_path(@loaded_path)
|
264
264
|
end
|
265
265
|
|
266
|
+
# @return [String, nil]
|
266
267
|
def bundler_lock_file_path
|
267
268
|
return nil unless loaded_path
|
268
269
|
|
@@ -286,27 +287,49 @@ module RuboCop
|
|
286
287
|
end
|
287
288
|
end
|
288
289
|
|
290
|
+
# Returns target's locked gem versions (i.e. from Gemfile.lock or gems.locked)
|
291
|
+
# @returns [Hash{String => Gem::Version}] The locked gem versions, keyed by the gems' names.
|
292
|
+
def gem_versions_in_target
|
293
|
+
@gem_versions_in_target ||= read_gem_versions_from_target_lockfile
|
294
|
+
end
|
295
|
+
|
289
296
|
def inspect # :nodoc:
|
290
297
|
"#<#{self.class.name}:#{object_id} @loaded_path=#{loaded_path}>"
|
291
298
|
end
|
292
299
|
|
293
300
|
private
|
294
301
|
|
302
|
+
# @return [Float, nil] The Rails version as a `major.minor` Float.
|
295
303
|
def target_rails_version_from_bundler_lock_file
|
296
304
|
@target_rails_version_from_bundler_lock_file ||= read_rails_version_from_bundler_lock_file
|
297
305
|
end
|
298
306
|
|
307
|
+
# @return [Float, nil] The Rails version as a `major.minor` Float.
|
299
308
|
def read_rails_version_from_bundler_lock_file
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
309
|
+
return nil unless gem_versions_in_target
|
310
|
+
|
311
|
+
# Look for `railties` instead of `rails`, to support apps that only use a subset of `rails`
|
312
|
+
# See https://github.com/rubocop/rubocop/pull/11289
|
313
|
+
rails_version_in_target = gem_versions_in_target['railties']
|
314
|
+
return nil unless rails_version_in_target
|
315
|
+
|
316
|
+
gem_version_to_major_minor_float(rails_version_in_target)
|
317
|
+
end
|
318
|
+
|
319
|
+
# @param [Gem::Version] gem_version an object like `Gem::Version.new("7.1.2.3")`
|
320
|
+
# @return [Float] The major and minor version, like `7.1`
|
321
|
+
def gem_version_to_major_minor_float(gem_version)
|
322
|
+
segments = gem_version.canonical_segments
|
323
|
+
# segments.fetch(0).to_f + (segments.fetch(1, 0.0).to_f / 10)
|
324
|
+
Float("#{segments.fetch(0)}.#{segments.fetch(1, 0)}")
|
325
|
+
end
|
326
|
+
|
327
|
+
# @returns [Hash{String => Gem::Version}] The locked gem versions, keyed by the gems' names.
|
328
|
+
def read_gem_versions_from_target_lockfile
|
329
|
+
lockfile_path = bundler_lock_file_path
|
330
|
+
return nil unless lockfile_path
|
331
|
+
|
332
|
+
Lockfile.new(lockfile_path).gem_versions
|
310
333
|
end
|
311
334
|
|
312
335
|
def enable_cop?(qualified_cop_name, cop_options)
|
@@ -52,7 +52,7 @@ module RuboCop
|
|
52
52
|
def load_rules # rubocop:disable Metrics/AbcSize
|
53
53
|
rules = LOAD_RULES_CACHE[self.class.files] ||=
|
54
54
|
self.class.files.each_with_object({}) do |filename, hash|
|
55
|
-
hash.merge!(YAML.safe_load(File.read(filename))) do |_key, first, second|
|
55
|
+
hash.merge!(YAML.safe_load(File.read(filename)) || {}) do |_key, first, second|
|
56
56
|
case first
|
57
57
|
when Hash
|
58
58
|
first.merge(second)
|
data/lib/rubocop/cop/base.rb
CHANGED
@@ -70,6 +70,7 @@ module RuboCop
|
|
70
70
|
|
71
71
|
def self.inherited(subclass)
|
72
72
|
super
|
73
|
+
subclass.instance_variable_set(:@gem_requirements, gem_requirements.dup)
|
73
74
|
Registry.global.enlist(subclass)
|
74
75
|
end
|
75
76
|
|
@@ -126,6 +127,29 @@ module RuboCop
|
|
126
127
|
false
|
127
128
|
end
|
128
129
|
|
130
|
+
## Gem requirements
|
131
|
+
|
132
|
+
@gem_requirements = {}
|
133
|
+
|
134
|
+
class << self
|
135
|
+
attr_reader :gem_requirements
|
136
|
+
|
137
|
+
# Register a version requirement for the given gem name.
|
138
|
+
# This cop will be skipped unless the target satisfies *all* requirements.
|
139
|
+
# @param [String] gem_name
|
140
|
+
# @param [Array<String>] version_requirements The version requirements,
|
141
|
+
# using the same syntax as a Gemfile, e.g. ">= 1.2.3"
|
142
|
+
#
|
143
|
+
# If omitted, any version of the gem will be accepted.
|
144
|
+
#
|
145
|
+
# https://guides.rubygems.org/patterns/#declaring-dependencies
|
146
|
+
#
|
147
|
+
# @api public
|
148
|
+
def requires_gem(gem_name, *version_requirements)
|
149
|
+
@gem_requirements[gem_name] = Gem::Requirement.new(version_requirements)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
129
153
|
def initialize(config = nil, options = nil)
|
130
154
|
@config = config || Config.new
|
131
155
|
@options = options || { debug: false }
|
@@ -162,7 +186,9 @@ module RuboCop
|
|
162
186
|
def add_global_offense(message = nil, severity: nil)
|
163
187
|
severity = find_severity(nil, severity)
|
164
188
|
message = find_message(nil, message)
|
165
|
-
|
189
|
+
range = Offense::NO_LOCATION
|
190
|
+
status = enabled_line?(range.line) ? :unsupported : :disabled
|
191
|
+
current_offenses << Offense.new(severity, range, message, name, status)
|
166
192
|
end
|
167
193
|
|
168
194
|
# Adds an offense on the specified range (or node with an expression)
|
@@ -245,6 +271,7 @@ module RuboCop
|
|
245
271
|
end
|
246
272
|
|
247
273
|
def relevant_file?(file)
|
274
|
+
return false unless target_satisfies_all_gem_version_requirements?
|
248
275
|
return true unless @config.clusivity_config_for_badge?(self.class.badge)
|
249
276
|
|
250
277
|
file == RuboCop::AST::ProcessedSource::STRING_SOURCE_NAME ||
|
@@ -496,6 +523,18 @@ module RuboCop
|
|
496
523
|
range.end_pos + @current_offset
|
497
524
|
)
|
498
525
|
end
|
526
|
+
|
527
|
+
def target_satisfies_all_gem_version_requirements?
|
528
|
+
self.class.gem_requirements.all? do |gem_name, version_req|
|
529
|
+
all_gem_versions_in_target = @config.gem_versions_in_target
|
530
|
+
next false unless all_gem_versions_in_target
|
531
|
+
|
532
|
+
gem_version_in_target = all_gem_versions_in_target[gem_name]
|
533
|
+
next false unless gem_version_in_target
|
534
|
+
|
535
|
+
version_req.satisfied_by?(gem_version_in_target)
|
536
|
+
end
|
537
|
+
end
|
499
538
|
end
|
500
539
|
end
|
501
540
|
end
|
@@ -45,7 +45,8 @@ module RuboCop
|
|
45
45
|
EXPECT_OFFENSE_DESCRIPTION_MAPPING = {
|
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
50
|
}.freeze
|
50
51
|
|
51
52
|
EXPECT_NO_CORRECTIONS_DESCRIPTION_MAPPING = {
|
@@ -50,7 +50,7 @@ module RuboCop
|
|
50
50
|
MSG_WITHOUT_SAFE_ASSIGNMENT_ALLOWED =
|
51
51
|
'Use `==` if you meant to do a comparison or move the assignment ' \
|
52
52
|
'up out of the condition.'
|
53
|
-
ASGN_TYPES = [:begin, *AST::Node::EQUALS_ASSIGNMENTS, :send].freeze
|
53
|
+
ASGN_TYPES = [:begin, *AST::Node::EQUALS_ASSIGNMENTS, :send, :csend].freeze
|
54
54
|
|
55
55
|
def on_if(node)
|
56
56
|
return if node.condition.block_type?
|
@@ -88,7 +88,7 @@ module RuboCop
|
|
88
88
|
end
|
89
89
|
|
90
90
|
def skip_children?(asgn_node)
|
91
|
-
(asgn_node.
|
91
|
+
(asgn_node.call_type? && !asgn_node.assignment_method?) ||
|
92
92
|
empty_condition?(asgn_node) ||
|
93
93
|
(safe_assignment_allowed? && safe_assignment?(asgn_node))
|
94
94
|
end
|
@@ -29,6 +29,11 @@ module RuboCop
|
|
29
29
|
# MyDebugger.debug_this
|
30
30
|
# ----
|
31
31
|
#
|
32
|
+
# Some gems also ship files that will start a debugging session when required,
|
33
|
+
# for example `require 'debug/start'` from `ruby/debug`. These requires can
|
34
|
+
# be configured through `DebuggerRequires`. It has the same structure as
|
35
|
+
# `DebuggerMethods`, which you can read about above.
|
36
|
+
#
|
32
37
|
# @example
|
33
38
|
#
|
34
39
|
# # bad (ok during development)
|
@@ -64,14 +69,20 @@ module RuboCop
|
|
64
69
|
# def some_method
|
65
70
|
# my_debugger
|
66
71
|
# end
|
72
|
+
#
|
73
|
+
# @example DebuggerRequires: [my_debugger/start]
|
74
|
+
#
|
75
|
+
# # bad (ok during development)
|
76
|
+
#
|
77
|
+
# require 'my_debugger/start'
|
67
78
|
class Debugger < Base
|
68
79
|
MSG = 'Remove debugger entry point `%<source>s`.'
|
69
80
|
BLOCK_TYPES = %i[block numblock kwbegin].freeze
|
70
81
|
|
71
82
|
def on_send(node)
|
72
|
-
return if
|
83
|
+
return if assumed_usage_context?(node)
|
73
84
|
|
74
|
-
add_offense(node)
|
85
|
+
add_offense(node) if debugger_method?(node) || debugger_require?(node)
|
75
86
|
end
|
76
87
|
|
77
88
|
private
|
@@ -87,12 +98,26 @@ module RuboCop
|
|
87
98
|
end
|
88
99
|
end
|
89
100
|
|
101
|
+
def debugger_requires
|
102
|
+
@debugger_requires ||= begin
|
103
|
+
config = cop_config.fetch('DebuggerRequires', [])
|
104
|
+
config.is_a?(Array) ? config : config.values.flatten
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
90
108
|
def debugger_method?(send_node)
|
91
109
|
return false if send_node.parent&.send_type? && send_node.parent.receiver == send_node
|
92
110
|
|
93
111
|
debugger_methods.include?(chained_method_name(send_node))
|
94
112
|
end
|
95
113
|
|
114
|
+
def debugger_require?(send_node)
|
115
|
+
return false unless send_node.method?(:require) && send_node.arguments.one?
|
116
|
+
return false unless (argument = send_node.first_argument).str_type?
|
117
|
+
|
118
|
+
debugger_requires.include?(argument.value)
|
119
|
+
end
|
120
|
+
|
96
121
|
def assumed_usage_context?(node)
|
97
122
|
# Basically, debugger methods are not used as a method argument without arguments.
|
98
123
|
return false unless node.arguments.empty? && node.each_ancestor(:send, :csend).any?
|
@@ -52,7 +52,7 @@ module RuboCop
|
|
52
52
|
# @!method deprecated_class_method?(node)
|
53
53
|
def_node_matcher :deprecated_class_method?, <<~PATTERN
|
54
54
|
{
|
55
|
-
(send (const {cbase nil?}
|
55
|
+
(send (const {cbase nil?} :ENV) {:clone :dup :freeze})
|
56
56
|
(send (const {cbase nil?} {:File :Dir}) :exists? _)
|
57
57
|
(send (const {cbase nil?} :Socket) {:gethostbyaddr :gethostbyname} ...)
|
58
58
|
(send nil? :attr _ boolean)
|
@@ -146,7 +146,7 @@ module RuboCop
|
|
146
146
|
node.source_range.with(end_pos: node.condition.source_range.end_pos)
|
147
147
|
elsif all_branches_body_missing?(node)
|
148
148
|
if_node = node.ancestors.detect(&:if?)
|
149
|
-
node.source_range.
|
149
|
+
node.source_range.join(if_node.loc.end.end)
|
150
150
|
else
|
151
151
|
node.source_range
|
152
152
|
end
|
@@ -47,8 +47,10 @@ module RuboCop
|
|
47
47
|
|
48
48
|
def on_regexp(node)
|
49
49
|
each_unsafe_regexp_range(node) do |loc|
|
50
|
+
next unless (replacement = regexp_range(loc.source))
|
51
|
+
|
50
52
|
add_offense(loc) do |corrector|
|
51
|
-
corrector.replace(loc,
|
53
|
+
corrector.replace(loc, replacement)
|
52
54
|
end
|
53
55
|
end
|
54
56
|
end
|
@@ -99,10 +101,13 @@ module RuboCop
|
|
99
101
|
end
|
100
102
|
end
|
101
103
|
|
102
|
-
def
|
104
|
+
def regexp_range(source)
|
103
105
|
open, close = source.split('-')
|
104
|
-
|
105
|
-
|
106
|
+
return unless (open_range = range_for(open))
|
107
|
+
return unless (close_range = range_for(close))
|
108
|
+
|
109
|
+
first = [open, open_range.end]
|
110
|
+
second = [close_range.begin, close]
|
106
111
|
"#{first.uniq.join('-')}#{second.uniq.join('-')}"
|
107
112
|
end
|
108
113
|
end
|
@@ -130,7 +130,7 @@ module RuboCop
|
|
130
130
|
# @return [Parser::Source::Range]
|
131
131
|
#
|
132
132
|
def last_arg_range(node)
|
133
|
-
node.last_argument.source_range.
|
133
|
+
node.last_argument.source_range.join(node.arguments[-2].source_range.end)
|
134
134
|
end
|
135
135
|
|
136
136
|
def unsorted_dir_loop?(node)
|
@@ -33,8 +33,10 @@ module RuboCop
|
|
33
33
|
MSG_EACH_WITH_INDEX = 'Use `each` instead of `each_with_index`.'
|
34
34
|
MSG_WITH_INDEX = 'Remove redundant `with_index`.'
|
35
35
|
|
36
|
+
# rubocop:disable Metrics/AbcSize
|
36
37
|
def on_block(node)
|
37
38
|
return unless node.receiver
|
39
|
+
return if node.method?(:with_index) && !node.receiver.receiver
|
38
40
|
return unless (send = redundant_with_index?(node))
|
39
41
|
|
40
42
|
range = with_index_range(send)
|
@@ -48,6 +50,7 @@ module RuboCop
|
|
48
50
|
end
|
49
51
|
end
|
50
52
|
end
|
53
|
+
# rubocop:enable Metrics/AbcSize
|
51
54
|
|
52
55
|
alias on_numblock on_block
|
53
56
|
|
@@ -71,7 +71,7 @@ module RuboCop
|
|
71
71
|
expressions.any? { |expr| flow_expression?(expr) }
|
72
72
|
when :if
|
73
73
|
check_if(node)
|
74
|
-
when :case
|
74
|
+
when :case, :case_match
|
75
75
|
check_case(node)
|
76
76
|
else
|
77
77
|
false
|
@@ -89,7 +89,9 @@ module RuboCop
|
|
89
89
|
return false unless else_branch
|
90
90
|
return false unless flow_expression?(else_branch)
|
91
91
|
|
92
|
-
node.
|
92
|
+
branches = node.case_type? ? node.when_branches : node.in_pattern_branches
|
93
|
+
|
94
|
+
branches.all? { |branch| branch.body && flow_expression?(branch.body) }
|
93
95
|
end
|
94
96
|
end
|
95
97
|
end
|
@@ -160,7 +160,7 @@ module RuboCop
|
|
160
160
|
break_statement && !preceded_by_continue_statement?(break_statement)
|
161
161
|
when :if
|
162
162
|
check_if(node)
|
163
|
-
when :case
|
163
|
+
when :case, :case_match
|
164
164
|
check_case(node)
|
165
165
|
else
|
166
166
|
false
|
@@ -178,7 +178,13 @@ module RuboCop
|
|
178
178
|
return false unless else_branch
|
179
179
|
return false unless break_statement?(else_branch)
|
180
180
|
|
181
|
-
|
181
|
+
branches = if node.case_type?
|
182
|
+
node.when_branches
|
183
|
+
else
|
184
|
+
node.in_pattern_branches
|
185
|
+
end
|
186
|
+
|
187
|
+
branches.all? { |branch| branch.body && break_statement?(branch.body) }
|
182
188
|
end
|
183
189
|
|
184
190
|
def preceded_by_continue_statement?(break_statement)
|
@@ -51,8 +51,8 @@ module RuboCop
|
|
51
51
|
when :method_call
|
52
52
|
->(node) { node.call_type? }
|
53
53
|
else
|
54
|
-
raise
|
55
|
-
|
54
|
+
raise Warning, "Unknown foldable type: #{type.inspect}. " \
|
55
|
+
"Valid foldable types are: #{FOLDABLE_TYPES.join(', ')}."
|
56
56
|
end
|
57
57
|
end
|
58
58
|
end
|
@@ -36,7 +36,7 @@ module RuboCop
|
|
36
36
|
length = calculator.calculate
|
37
37
|
return if length <= max_length
|
38
38
|
|
39
|
-
location = node
|
39
|
+
location = location(node)
|
40
40
|
|
41
41
|
add_offense(location, message: message(length, max_length)) { self.max = length }
|
42
42
|
end
|
@@ -54,6 +54,17 @@ module RuboCop
|
|
54
54
|
foldable_types: count_as_one
|
55
55
|
)
|
56
56
|
end
|
57
|
+
|
58
|
+
def location(node)
|
59
|
+
return node.loc.name if node.casgn_type?
|
60
|
+
|
61
|
+
if LSP.enabled?
|
62
|
+
end_range = node.loc.respond_to?(:name) ? node.loc.name : node.loc.begin
|
63
|
+
node.source_range.begin.join(end_range)
|
64
|
+
else
|
65
|
+
node.source_range
|
66
|
+
end
|
67
|
+
end
|
57
68
|
end
|
58
69
|
end
|
59
70
|
end
|
@@ -49,13 +49,13 @@ module RuboCop
|
|
49
49
|
|
50
50
|
return unless complexity > max
|
51
51
|
|
52
|
-
msg = format(
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
52
|
+
msg = format(
|
53
|
+
self.class::MSG,
|
54
|
+
method: method_name, complexity: complexity, abc_vector: abc_vector, max: max
|
55
|
+
)
|
56
|
+
location = location(node)
|
57
57
|
|
58
|
-
add_offense(
|
58
|
+
add_offense(location, message: msg) { self.max = complexity.ceil }
|
59
59
|
end
|
60
60
|
|
61
61
|
def complexity(body)
|
@@ -69,6 +69,15 @@ module RuboCop
|
|
69
69
|
end
|
70
70
|
score
|
71
71
|
end
|
72
|
+
|
73
|
+
def location(node)
|
74
|
+
if LSP.enabled?
|
75
|
+
end_range = node.loc.respond_to?(:name) ? node.loc.name : node.loc.begin
|
76
|
+
node.source_range.begin.join(end_range)
|
77
|
+
else
|
78
|
+
node.source_range
|
79
|
+
end
|
80
|
+
end
|
72
81
|
end
|
73
82
|
end
|
74
83
|
end
|
@@ -14,7 +14,7 @@ module RuboCop
|
|
14
14
|
def_node_matcher :empty_condition?, '(begin)'
|
15
15
|
|
16
16
|
# @!method setter_method?(node)
|
17
|
-
def_node_matcher :setter_method?, '[(
|
17
|
+
def_node_matcher :setter_method?, '[(call ...) setter_method?]'
|
18
18
|
|
19
19
|
# @!method safe_assignment?(node)
|
20
20
|
def_node_matcher :safe_assignment?, '(begin {equals_asgn? #setter_method?})'
|