rubocop 1.62.1 → 1.63.5
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 +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?})'
|