rubocop 1.33.0 → 1.34.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 +7 -1
- data/lib/rubocop/cli/command/suggest_extensions.rb +53 -15
- data/lib/rubocop/config_loader.rb +12 -0
- data/lib/rubocop/config_loader_resolver.rb +1 -5
- data/lib/rubocop/cop/cop.rb +1 -1
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +28 -0
- data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +61 -0
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/layout/block_end_newline.rb +2 -1
- data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -1
- data/lib/rubocop/cop/legacy/corrections_proxy.rb +1 -1
- data/lib/rubocop/cop/legacy/corrector.rb +1 -1
- data/lib/rubocop/cop/lint/debugger.rb +15 -15
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +5 -0
- data/lib/rubocop/cop/lint/shadowed_exception.rb +15 -0
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +9 -1
- data/lib/rubocop/cop/mixin/enforce_superclass.rb +2 -1
- data/lib/rubocop/cop/mixin/range_help.rb +2 -2
- data/lib/rubocop/cop/style/double_negation.rb +2 -0
- data/lib/rubocop/cop/style/if_unless_modifier.rb +1 -1
- data/lib/rubocop/cop/style/numeric_literals.rb +16 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +15 -22
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +14 -3
- data/lib/rubocop/cop/style/symbol_proc.rb +5 -0
- data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -13
- data/lib/rubocop/ext/range.rb +15 -0
- data/lib/rubocop/feature_loader.rb +88 -0
- data/lib/rubocop/formatter/clang_style_formatter.rb +1 -1
- data/lib/rubocop/formatter/disabled_config_formatter.rb +1 -1
- data/lib/rubocop/formatter/html_formatter.rb +1 -1
- data/lib/rubocop/formatter/markdown_formatter.rb +1 -1
- data/lib/rubocop/formatter/tap_formatter.rb +1 -1
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +2 -0
- metadata +11 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d1c7a1f010764e941e11b523804a06d0fa77002769d763a4b1de81b459808c98
|
4
|
+
data.tar.gz: 28014c651859698a9a8fbdc122ba93159095f8a3182ac8bed497fbd9c2362c8e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9cf155f34f4e1a5520a03668455234518417a154029bafa1f8ee43713fd83f3d1745267abff56fcb487ad8254653cf55bb3d902f93eef8cac5f31fc01430d2f9
|
7
|
+
data.tar.gz: 0f5349bb191f7a321136cfe349497b2e3edb847849039cc4d6a9b520332388cf2538e62ec65ab70fc8572dac8d354d276b8a77674562e7ddd54cefaa44a317d4
|
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.34', 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
@@ -1604,6 +1604,7 @@ Lint/Debugger:
|
|
1604
1604
|
# a user's configuration, but are otherwise not significant.
|
1605
1605
|
Kernel:
|
1606
1606
|
- binding.irb
|
1607
|
+
- Kernel.binding.irb
|
1607
1608
|
Byebug:
|
1608
1609
|
- byebug
|
1609
1610
|
- remote_byebug
|
@@ -1621,6 +1622,9 @@ Lint/Debugger:
|
|
1621
1622
|
- binding.pry
|
1622
1623
|
- binding.remote_pry
|
1623
1624
|
- binding.pry_remote
|
1625
|
+
- Kernel.binding.pry
|
1626
|
+
- Kernel.binding.remote_pry
|
1627
|
+
- Kernel.binding.pry_remote
|
1624
1628
|
- Pry.rescue
|
1625
1629
|
Rails:
|
1626
1630
|
- debugger
|
@@ -1753,9 +1757,10 @@ Lint/EmptyClass:
|
|
1753
1757
|
Lint/EmptyConditionalBody:
|
1754
1758
|
Description: 'Checks for the presence of `if`, `elsif` and `unless` branches without a body.'
|
1755
1759
|
Enabled: true
|
1760
|
+
SafeAutoCorrect: false
|
1756
1761
|
AllowComments: true
|
1757
1762
|
VersionAdded: '0.89'
|
1758
|
-
VersionChanged: '1.
|
1763
|
+
VersionChanged: '1.34'
|
1759
1764
|
|
1760
1765
|
Lint/EmptyEnsure:
|
1761
1766
|
Description: 'Checks for empty ensure block.'
|
@@ -4400,6 +4405,7 @@ Style/NumericLiterals:
|
|
4400
4405
|
Strict: false
|
4401
4406
|
# You can specify allowed numbers. (e.g. port number 3000, 8080, and etc)
|
4402
4407
|
AllowedNumbers: []
|
4408
|
+
AllowedPatterns: []
|
4403
4409
|
|
4404
4410
|
Style/NumericPredicate:
|
4405
4411
|
Description: >-
|
@@ -17,20 +17,10 @@ module RuboCop
|
|
17
17
|
def run
|
18
18
|
return if skip? || extensions.none?
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
'RuboCop extension libraries might be helpful:'
|
23
|
-
|
24
|
-
extensions.sort.each do |extension|
|
25
|
-
puts " * #{extension} (https://rubygems.org/gems/#{extension})"
|
26
|
-
end
|
20
|
+
print_install_suggestions if not_installed_extensions.any?
|
21
|
+
print_load_suggestions if installed_and_not_loaded_extensions.any?
|
27
22
|
|
28
|
-
|
29
|
-
puts 'You can opt out of this message by adding the following to your config ' \
|
30
|
-
'(see https://docs.rubocop.org/rubocop/extensions.html#extension-suggestions ' \
|
31
|
-
'for more options):'
|
32
|
-
puts ' AllCops:'
|
33
|
-
puts ' SuggestExtensions: false'
|
23
|
+
print_opt_out_instruction
|
34
24
|
|
35
25
|
puts if @options[:display_time]
|
36
26
|
end
|
@@ -48,15 +38,63 @@ module RuboCop
|
|
48
38
|
!INCLUDED_FORMATTERS.include?(current_formatter)
|
49
39
|
end
|
50
40
|
|
41
|
+
def print_install_suggestions
|
42
|
+
puts
|
43
|
+
puts 'Tip: Based on detected gems, the following ' \
|
44
|
+
'RuboCop extension libraries might be helpful:'
|
45
|
+
|
46
|
+
not_installed_extensions.sort.each do |extension|
|
47
|
+
puts " * #{extension} (https://rubygems.org/gems/#{extension})"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def print_load_suggestions
|
52
|
+
puts
|
53
|
+
puts 'The following RuboCop extension libraries are installed but not loaded in config:'
|
54
|
+
|
55
|
+
installed_and_not_loaded_extensions.sort.each do |extension|
|
56
|
+
puts " * #{extension}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def print_opt_out_instruction
|
61
|
+
puts
|
62
|
+
puts 'You can opt out of this message by adding the following to your config ' \
|
63
|
+
'(see https://docs.rubocop.org/rubocop/extensions.html#extension-suggestions ' \
|
64
|
+
'for more options):'
|
65
|
+
puts ' AllCops:'
|
66
|
+
puts ' SuggestExtensions: false'
|
67
|
+
end
|
68
|
+
|
51
69
|
def current_formatter
|
52
70
|
@options[:format] || @config_store.for_pwd.for_all_cops['DefaultFormatter'] || 'p'
|
53
71
|
end
|
54
72
|
|
55
|
-
def
|
73
|
+
def all_extensions
|
56
74
|
return [] unless lockfile.dependencies.any?
|
57
75
|
|
58
76
|
extensions = @config_store.for_pwd.for_all_cops['SuggestExtensions'] || {}
|
59
|
-
extensions.select { |_, v| (Array(v) & dependent_gems).any? }.keys
|
77
|
+
extensions.select { |_, v| (Array(v) & dependent_gems).any? }.keys
|
78
|
+
end
|
79
|
+
|
80
|
+
def extensions
|
81
|
+
not_installed_extensions + installed_and_not_loaded_extensions
|
82
|
+
end
|
83
|
+
|
84
|
+
def installed_extensions
|
85
|
+
all_extensions & installed_gems
|
86
|
+
end
|
87
|
+
|
88
|
+
def not_installed_extensions
|
89
|
+
all_extensions - installed_gems
|
90
|
+
end
|
91
|
+
|
92
|
+
def loaded_extensions
|
93
|
+
@config_store.for_pwd.loaded_features.to_a
|
94
|
+
end
|
95
|
+
|
96
|
+
def installed_and_not_loaded_extensions
|
97
|
+
installed_extensions - loaded_extensions
|
60
98
|
end
|
61
99
|
|
62
100
|
def lockfile
|
@@ -137,6 +137,18 @@ module RuboCop
|
|
137
137
|
end
|
138
138
|
end
|
139
139
|
|
140
|
+
# Returns the path RuboCop inferred as the root of the project. No file
|
141
|
+
# searches will go past this directory.
|
142
|
+
# @deprecated Use `RuboCop::ConfigFinder.project_root` instead.
|
143
|
+
def project_root
|
144
|
+
warn Rainbow(<<~WARNING).yellow
|
145
|
+
`RuboCop::ConfigLoader.project_root` is deprecated and will be removed in RuboCop 2.0. \
|
146
|
+
Use `RuboCop::ConfigFinder.project_root` instead.
|
147
|
+
WARNING
|
148
|
+
|
149
|
+
ConfigFinder.project_root
|
150
|
+
end
|
151
|
+
|
140
152
|
PENDING_BANNER = <<~BANNER
|
141
153
|
The following cops were added to RuboCop, but are not configured. Please set Enabled to either `true` or `false` in your `.rubocop.yml` file.
|
142
154
|
|
@@ -11,11 +11,7 @@ module RuboCop
|
|
11
11
|
config_dir = File.dirname(path)
|
12
12
|
hash.delete('require').tap do |loaded_features|
|
13
13
|
Array(loaded_features).each do |feature|
|
14
|
-
|
15
|
-
require(File.join(config_dir, feature))
|
16
|
-
else
|
17
|
-
require(feature)
|
18
|
-
end
|
14
|
+
FeatureLoader.load(config_directory_path: config_dir, feature: feature)
|
19
15
|
end
|
20
16
|
end
|
21
17
|
end
|
data/lib/rubocop/cop/cop.rb
CHANGED
@@ -7,7 +7,7 @@ module RuboCop
|
|
7
7
|
module Cop
|
8
8
|
# @deprecated Use Cop::Base instead
|
9
9
|
# Legacy scaffold for Cops.
|
10
|
-
# See https://docs.rubocop.org/rubocop/
|
10
|
+
# See https://docs.rubocop.org/rubocop/v1_upgrade_notes.html
|
11
11
|
class Cop < Base
|
12
12
|
attr_reader :offenses
|
13
13
|
|
@@ -5,9 +5,13 @@ module RuboCop
|
|
5
5
|
# This autocorrects parentheses
|
6
6
|
class ParenthesesCorrector
|
7
7
|
class << self
|
8
|
+
include RangeHelp
|
9
|
+
|
8
10
|
def correct(corrector, node)
|
9
11
|
corrector.remove(node.loc.begin)
|
10
12
|
corrector.remove(node.loc.end)
|
13
|
+
handle_orphaned_comma(corrector, node)
|
14
|
+
|
11
15
|
return unless ternary_condition?(node) && next_char_is_question_mark?(node)
|
12
16
|
|
13
17
|
corrector.insert_after(node.loc.end, ' ')
|
@@ -22,6 +26,30 @@ module RuboCop
|
|
22
26
|
def next_char_is_question_mark?(node)
|
23
27
|
node.loc.last_column == node.parent.loc.question.column
|
24
28
|
end
|
29
|
+
|
30
|
+
def only_closing_paren_before_comma?(node)
|
31
|
+
source_buffer = node.source_range.source_buffer
|
32
|
+
line_range = source_buffer.line_range(node.loc.end.line)
|
33
|
+
|
34
|
+
line_range.source.start_with?(/\s*\)\s*,/)
|
35
|
+
end
|
36
|
+
|
37
|
+
# If removing parentheses leaves a comma on its own line, remove all the whitespace
|
38
|
+
# preceding it to prevent a syntax error.
|
39
|
+
def handle_orphaned_comma(corrector, node)
|
40
|
+
return unless only_closing_paren_before_comma?(node)
|
41
|
+
|
42
|
+
range = range_with_surrounding_space(
|
43
|
+
range: node.loc.end,
|
44
|
+
buffer: node.source_range.source_buffer,
|
45
|
+
side: :left,
|
46
|
+
newlines: true,
|
47
|
+
whitespace: true,
|
48
|
+
continuations: true
|
49
|
+
)
|
50
|
+
|
51
|
+
corrector.remove(range)
|
52
|
+
end
|
25
53
|
end
|
26
54
|
end
|
27
55
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module InternalAffairs
|
6
|
+
# Enforces the use of `node.single_line?` instead of
|
7
|
+
# comparing `first_line` and `last_line` for equality.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# node.loc.first_line == node.loc.last_line
|
12
|
+
#
|
13
|
+
# # bad
|
14
|
+
# node.loc.last_line == node.loc.first_line
|
15
|
+
#
|
16
|
+
# # bad
|
17
|
+
# node.loc.line == node.loc.last_line
|
18
|
+
#
|
19
|
+
# # bad
|
20
|
+
# node.loc.last_line == node.loc.line
|
21
|
+
#
|
22
|
+
# # bad
|
23
|
+
# node.first_line == node.last_line
|
24
|
+
#
|
25
|
+
# # good
|
26
|
+
# node.single_line?
|
27
|
+
#
|
28
|
+
class SingleLineComparison < Base
|
29
|
+
extend AutoCorrector
|
30
|
+
|
31
|
+
MSG = 'Use `%<preferred>s`.'
|
32
|
+
RESTRICT_ON_SEND = %i[==].freeze
|
33
|
+
|
34
|
+
# @!method single_line_comparison(node)
|
35
|
+
def_node_matcher :single_line_comparison, <<~PATTERN
|
36
|
+
{
|
37
|
+
(send (send $_receiver {:line :first_line}) :== (send _receiver :last_line))
|
38
|
+
(send (send $_receiver :last_line) :== (send _receiver {:line :first_line}))
|
39
|
+
}
|
40
|
+
PATTERN
|
41
|
+
|
42
|
+
def on_send(node)
|
43
|
+
return unless (receiver = single_line_comparison(node))
|
44
|
+
|
45
|
+
preferred = "#{extract_receiver(receiver)}.single_line?"
|
46
|
+
|
47
|
+
add_offense(node, message: format(MSG, preferred: preferred)) do |corrector|
|
48
|
+
corrector.replace(node, preferred)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def extract_receiver(node)
|
55
|
+
node = node.receiver if node.send_type? && %i[loc source_range].include?(node.method_name)
|
56
|
+
node.source
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -17,6 +17,7 @@ require_relative 'internal_affairs/redundant_let_rubocop_config_new'
|
|
17
17
|
require_relative 'internal_affairs/redundant_location_argument'
|
18
18
|
require_relative 'internal_affairs/redundant_message_argument'
|
19
19
|
require_relative 'internal_affairs/redundant_method_dispatch_node'
|
20
|
+
require_relative 'internal_affairs/single_line_comparison'
|
20
21
|
require_relative 'internal_affairs/style_detected_api_use'
|
21
22
|
require_relative 'internal_affairs/undefined_config'
|
22
23
|
require_relative 'internal_affairs/useless_message_assertion'
|
@@ -60,9 +60,10 @@ module RuboCop
|
|
60
60
|
end
|
61
61
|
|
62
62
|
def last_heredoc_argument(node)
|
63
|
+
return unless node&.call_type?
|
63
64
|
return unless (arguments = node&.arguments)
|
64
65
|
|
65
|
-
heredoc = arguments.reverse.detect
|
66
|
+
heredoc = arguments.reverse.detect { |arg| arg.str_type? && arg.heredoc? }
|
66
67
|
return heredoc if heredoc
|
67
68
|
|
68
69
|
last_heredoc_argument(node.children.first)
|
@@ -73,7 +73,7 @@ module RuboCop
|
|
73
73
|
return if node.send_type? && node.loc.operator&.source != '='
|
74
74
|
return unless rhs
|
75
75
|
return unless supported_types.include?(rhs.type)
|
76
|
-
return if rhs.
|
76
|
+
return if rhs.single_line?
|
77
77
|
|
78
78
|
check_by_enforced_style(node, rhs)
|
79
79
|
end
|
@@ -4,7 +4,7 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module Legacy
|
6
6
|
# Legacy support for Corrector#corrections
|
7
|
-
# See https://docs.rubocop.org/rubocop/
|
7
|
+
# See https://docs.rubocop.org/rubocop/v1_upgrade_notes.html
|
8
8
|
class CorrectionsProxy
|
9
9
|
def initialize(corrector)
|
10
10
|
@corrector = corrector
|
@@ -4,7 +4,7 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module Legacy
|
6
6
|
# Legacy Corrector for v0 API support.
|
7
|
-
# See https://docs.rubocop.org/rubocop/
|
7
|
+
# See https://docs.rubocop.org/rubocop/v1_upgrade_notes.html
|
8
8
|
class Corrector < RuboCop::Cop::Corrector
|
9
9
|
# Support legacy second argument
|
10
10
|
def initialize(source, corr = [])
|
@@ -67,19 +67,6 @@ module RuboCop
|
|
67
67
|
class Debugger < Base
|
68
68
|
MSG = 'Remove debugger entry point `%<source>s`.'
|
69
69
|
|
70
|
-
# @!method kernel?(node)
|
71
|
-
def_node_matcher :kernel?, <<~PATTERN
|
72
|
-
(const {nil? cbase} :Kernel)
|
73
|
-
PATTERN
|
74
|
-
|
75
|
-
# @!method valid_receiver?(node, arg1)
|
76
|
-
def_node_matcher :valid_receiver?, <<~PATTERN
|
77
|
-
{
|
78
|
-
(const {nil? cbase} %1)
|
79
|
-
(send {nil? #kernel?} %1)
|
80
|
-
}
|
81
|
-
PATTERN
|
82
|
-
|
83
70
|
def on_send(node)
|
84
71
|
return unless debugger_method?(node)
|
85
72
|
|
@@ -101,7 +88,7 @@ module RuboCop
|
|
101
88
|
|
102
89
|
*receiver, method_name = v.split('.')
|
103
90
|
{
|
104
|
-
receiver: receiver.empty? ? nil : receiver.
|
91
|
+
receiver: receiver.empty? ? nil : receiver.map(&:to_sym),
|
105
92
|
method_name: method_name.to_sym
|
106
93
|
}
|
107
94
|
end.compact
|
@@ -115,10 +102,23 @@ module RuboCop
|
|
115
102
|
if method[:receiver].nil?
|
116
103
|
send_node.receiver.nil?
|
117
104
|
else
|
118
|
-
|
105
|
+
method[:receiver] == receiver_chain(send_node)
|
119
106
|
end
|
120
107
|
end
|
121
108
|
end
|
109
|
+
|
110
|
+
def receiver_chain(send_node)
|
111
|
+
receivers = []
|
112
|
+
receiver = send_node.receiver
|
113
|
+
|
114
|
+
while receiver
|
115
|
+
name = receiver.send_type? ? receiver.method_name : receiver.const_name&.to_sym
|
116
|
+
receivers.unshift(name)
|
117
|
+
receiver = receiver.receiver
|
118
|
+
end
|
119
|
+
|
120
|
+
receivers
|
121
|
+
end
|
122
122
|
end
|
123
123
|
end
|
124
124
|
end
|
@@ -7,6 +7,11 @@ module RuboCop
|
|
7
7
|
#
|
8
8
|
# NOTE: empty `else` branches are handled by `Style/EmptyElse`.
|
9
9
|
#
|
10
|
+
# @safety
|
11
|
+
# Autocorrection for this cop is not safe. The conditions for empty branches that
|
12
|
+
# the autocorrection removes may have side effects, or the logic in subsequent
|
13
|
+
# branches may change due to the removal of a previous condition.
|
14
|
+
#
|
10
15
|
# @example
|
11
16
|
# # bad
|
12
17
|
# if condition
|
@@ -7,6 +7,14 @@ module RuboCop
|
|
7
7
|
# less specific exception being rescued before a more specific
|
8
8
|
# exception is rescued.
|
9
9
|
#
|
10
|
+
# An exception is considered shadowed if it is rescued after its
|
11
|
+
# ancestor is, or if it and its ancestor are both rescued in the
|
12
|
+
# same `rescue` statement. In both cases, the more specific rescue is
|
13
|
+
# unnecessary because it is covered by rescuing the less specific
|
14
|
+
# exception. (ie. `rescue Exception, StandardError` has the same behavior
|
15
|
+
# whether `StandardError` is included or not, because all `StandardError`s
|
16
|
+
# are rescued by `rescue Exception`).
|
17
|
+
#
|
10
18
|
# @example
|
11
19
|
#
|
12
20
|
# # bad
|
@@ -19,6 +27,13 @@ module RuboCop
|
|
19
27
|
# handle_standard_error
|
20
28
|
# end
|
21
29
|
#
|
30
|
+
# # bad
|
31
|
+
# begin
|
32
|
+
# something
|
33
|
+
# rescue Exception, StandardError
|
34
|
+
# handle_error
|
35
|
+
# end
|
36
|
+
#
|
22
37
|
# # good
|
23
38
|
#
|
24
39
|
# begin
|
@@ -67,10 +67,18 @@ module RuboCop
|
|
67
67
|
variable_node = variable.scope.node.parent
|
68
68
|
return false unless variable_node.conditional?
|
69
69
|
|
70
|
-
outer_local_variable_node =
|
70
|
+
outer_local_variable_node =
|
71
|
+
find_conditional_node_from_ascendant(outer_local_variable.declaration_node)
|
71
72
|
|
72
73
|
outer_local_variable_node.conditional? && variable_node == outer_local_variable_node
|
73
74
|
end
|
75
|
+
|
76
|
+
def find_conditional_node_from_ascendant(node)
|
77
|
+
return unless (parent = node.parent)
|
78
|
+
return parent if parent.conditional?
|
79
|
+
|
80
|
+
find_conditional_node_from_ascendant(parent)
|
81
|
+
end
|
74
82
|
end
|
75
83
|
end
|
76
84
|
end
|
@@ -6,7 +6,8 @@ module RuboCop
|
|
6
6
|
#
|
7
7
|
# IMPORTANT: RuboCop core depended on this module when it supported Rails department.
|
8
8
|
# Rails department has been extracted to RuboCop Rails gem.
|
9
|
-
#
|
9
|
+
#
|
10
|
+
# @deprecated This module is deprecated and will be removed by RuboCop 2.0.
|
10
11
|
# It will not be updated to `RuboCop::Cop::Base` v1 API to maintain compatibility
|
11
12
|
# with existing RuboCop Rails 2.8 or lower.
|
12
13
|
#
|
@@ -54,11 +54,11 @@ module RuboCop
|
|
54
54
|
NOT_GIVEN = Module.new
|
55
55
|
def range_with_surrounding_space(range_positional = NOT_GIVEN, # rubocop:disable Metrics/ParameterLists
|
56
56
|
range: NOT_GIVEN, side: :both, newlines: true,
|
57
|
-
whitespace: false, continuations: false
|
57
|
+
whitespace: false, continuations: false,
|
58
|
+
buffer: @processed_source.buffer)
|
58
59
|
|
59
60
|
range = range_positional unless range_positional == NOT_GIVEN
|
60
61
|
|
61
|
-
buffer = @processed_source.buffer
|
62
62
|
src = buffer.source
|
63
63
|
|
64
64
|
go_left, go_right = directions(side)
|
@@ -93,6 +93,8 @@ module RuboCop
|
|
93
93
|
|
94
94
|
if conditional_node
|
95
95
|
double_negative_condition_return_value?(node, last_child, conditional_node)
|
96
|
+
elsif last_child.pair_type? || last_child.hash_type? || last_child.parent.array_type?
|
97
|
+
false
|
96
98
|
else
|
97
99
|
last_child.last_line <= node.last_line
|
98
100
|
end
|
@@ -96,7 +96,7 @@ module RuboCop
|
|
96
96
|
return false unless max_line_length
|
97
97
|
|
98
98
|
range = node.source_range
|
99
|
-
return false unless range.
|
99
|
+
return false unless range.single_line?
|
100
100
|
return false unless line_length_enabled_at_line?(range.first_line)
|
101
101
|
|
102
102
|
line = range.source_line
|
@@ -3,9 +3,17 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
# Checks for big numeric literals without _ between groups
|
6
|
+
# Checks for big numeric literals without `_` between groups
|
7
7
|
# of digits in them.
|
8
8
|
#
|
9
|
+
# Additional allowed patterns can be added by adding regexps to
|
10
|
+
# the `AllowedPatterns` configuration. All regexps are treated
|
11
|
+
# as anchored even if the patterns do not contain anchors (so
|
12
|
+
# `\d{4}_\d{4}` will allow `1234_5678` but not `1234_5678_9012`).
|
13
|
+
#
|
14
|
+
# NOTE: Even if `AllowedPatterns` are given, autocorrection will
|
15
|
+
# only correct to the standard pattern of an `_` every 3 digits.
|
16
|
+
#
|
9
17
|
# @example
|
10
18
|
#
|
11
19
|
# # bad
|
@@ -34,6 +42,7 @@ module RuboCop
|
|
34
42
|
#
|
35
43
|
class NumericLiterals < Base
|
36
44
|
include IntegerNode
|
45
|
+
include AllowedPattern
|
37
46
|
extend AutoCorrector
|
38
47
|
|
39
48
|
MSG = 'Use underscores(_) as thousands separator and separate every 3 digits with them.'
|
@@ -59,6 +68,7 @@ module RuboCop
|
|
59
68
|
# TODO: handle non-decimal literals as well
|
60
69
|
return if int.start_with?('0')
|
61
70
|
return if allowed_numbers.include?(int)
|
71
|
+
return if matches_allowed_pattern?(int)
|
62
72
|
return unless int.size >= min_digits
|
63
73
|
|
64
74
|
case int
|
@@ -108,6 +118,11 @@ module RuboCop
|
|
108
118
|
def allowed_numbers
|
109
119
|
cop_config.fetch('AllowedNumbers', []).map(&:to_s)
|
110
120
|
end
|
121
|
+
|
122
|
+
def allowed_patterns
|
123
|
+
# Convert the patterns to be anchored
|
124
|
+
super.map { |regexp| Regexp.new(/\A#{regexp}\z/) }
|
125
|
+
end
|
111
126
|
end
|
112
127
|
end
|
113
128
|
end
|
@@ -57,8 +57,8 @@ module RuboCop
|
|
57
57
|
def allowed_expression?(node)
|
58
58
|
allowed_ancestor?(node) ||
|
59
59
|
allowed_method_call?(node) ||
|
60
|
-
|
61
|
-
|
60
|
+
allowed_multiple_expression?(node) ||
|
61
|
+
allowed_ternary?(node)
|
62
62
|
end
|
63
63
|
|
64
64
|
def allowed_ancestor?(node)
|
@@ -80,6 +80,19 @@ module RuboCop
|
|
80
80
|
!ancestor.begin_type? && !ancestor.def_type? && !ancestor.block_type?
|
81
81
|
end
|
82
82
|
|
83
|
+
def allowed_ternary?(node)
|
84
|
+
return unless node&.parent&.if_type?
|
85
|
+
|
86
|
+
node.parent.ternary? && ternary_parentheses_required?
|
87
|
+
end
|
88
|
+
|
89
|
+
def ternary_parentheses_required?
|
90
|
+
config = @config.for_cop('Style/TernaryParentheses')
|
91
|
+
allowed_styles = %w[require_parentheses require_parentheses_when_complex]
|
92
|
+
|
93
|
+
config.fetch('Enabled') && allowed_styles.include?(config['EnforcedStyle'])
|
94
|
+
end
|
95
|
+
|
83
96
|
def like_method_argument_parentheses?(node)
|
84
97
|
node.send_type? && node.arguments.one? &&
|
85
98
|
!node.arithmetic_operation? && node.first_argument.begin_type?
|
@@ -153,26 +166,6 @@ module RuboCop
|
|
153
166
|
node.parent&.keyword?
|
154
167
|
end
|
155
168
|
|
156
|
-
def allowed_array_or_hash_element?(node)
|
157
|
-
# Don't flag
|
158
|
-
# ```
|
159
|
-
# { a: (1
|
160
|
-
# ), }
|
161
|
-
# ```
|
162
|
-
hash_or_array_element?(node) && only_closing_paren_before_comma?(node)
|
163
|
-
end
|
164
|
-
|
165
|
-
def hash_or_array_element?(node)
|
166
|
-
node.each_ancestor(:array, :hash).any?
|
167
|
-
end
|
168
|
-
|
169
|
-
def only_closing_paren_before_comma?(node)
|
170
|
-
source_buffer = node.source_range.source_buffer
|
171
|
-
line_range = source_buffer.line_range(node.loc.end.line)
|
172
|
-
|
173
|
-
/^\s*\)\s*,/.match?(line_range.source)
|
174
|
-
end
|
175
|
-
|
176
169
|
def disallowed_literal?(begin_node, node)
|
177
170
|
node.literal? && !node.range_type? && !raised_to_power_negative_numeric?(begin_node, node)
|
178
171
|
end
|
@@ -148,7 +148,18 @@ module RuboCop
|
|
148
148
|
)
|
149
149
|
corrector.replace(range, and_operator)
|
150
150
|
corrector.remove(range_by_whole_lines(node.loc.end, include_final_newline: true))
|
151
|
-
|
151
|
+
|
152
|
+
wrap_condition(corrector, if_branch.condition)
|
153
|
+
end
|
154
|
+
|
155
|
+
def wrap_condition(corrector, condition)
|
156
|
+
# Handle `send` and `block` nodes that need to be wrapped in parens
|
157
|
+
# FIXME: autocorrection prevents syntax errors by wrapping the entire node in parens,
|
158
|
+
# but wrapping the argument list would be a more ergonomic correction.
|
159
|
+
node_to_check = condition&.block_type? ? condition.send_node : condition
|
160
|
+
return unless wrap_condition?(node_to_check)
|
161
|
+
|
162
|
+
corrector.wrap(condition, '(', ')')
|
152
163
|
end
|
153
164
|
|
154
165
|
def correct_for_outer_condition_modify_form_style(corrector, node, if_branch)
|
@@ -207,7 +218,7 @@ module RuboCop
|
|
207
218
|
end
|
208
219
|
|
209
220
|
def require_parentheses?(condition)
|
210
|
-
condition.
|
221
|
+
condition.call_type? && !condition.arguments.empty? && !condition.parenthesized? &&
|
211
222
|
!condition.comparison_method?
|
212
223
|
end
|
213
224
|
|
@@ -219,7 +230,7 @@ module RuboCop
|
|
219
230
|
|
220
231
|
def wrap_condition?(node)
|
221
232
|
node.and_type? || node.or_type? ||
|
222
|
-
(node.
|
233
|
+
(node.call_type? && node.arguments.any? && !node.parenthesized?)
|
223
234
|
end
|
224
235
|
|
225
236
|
def replace_condition(condition)
|
@@ -121,6 +121,7 @@ module RuboCop
|
|
121
121
|
# we should allow lambdas & procs
|
122
122
|
return if proc_node?(dispatch_node)
|
123
123
|
return if unsafe_hash_usage?(dispatch_node)
|
124
|
+
return if unsafe_array_usage?(dispatch_node)
|
124
125
|
return if %i[lambda proc].include?(dispatch_node.method_name)
|
125
126
|
return if allowed_method_name?(dispatch_node.method_name)
|
126
127
|
return if allow_if_method_has_argument?(node.send_node)
|
@@ -144,6 +145,10 @@ module RuboCop
|
|
144
145
|
node.receiver&.hash_type? && %i[reject select].include?(node.method_name)
|
145
146
|
end
|
146
147
|
|
148
|
+
def unsafe_array_usage?(node)
|
149
|
+
node.receiver&.array_type? && %i[min max].include?(node.method_name)
|
150
|
+
end
|
151
|
+
|
147
152
|
def allowed_method_name?(name)
|
148
153
|
allowed_method?(name) || matches_allowed_pattern?(name)
|
149
154
|
end
|
@@ -71,7 +71,7 @@ module RuboCop
|
|
71
71
|
|
72
72
|
return if only_closing_parenthesis_is_last_line?(condition)
|
73
73
|
return if condition_as_parenthesized_one_line_pattern_matching?(condition)
|
74
|
-
return unless node.ternary? &&
|
74
|
+
return unless node.ternary? && offense?(node)
|
75
75
|
|
76
76
|
message = message(node)
|
77
77
|
|
@@ -166,22 +166,10 @@ module RuboCop
|
|
166
166
|
style == :require_parentheses_when_complex
|
167
167
|
end
|
168
168
|
|
169
|
-
def redundant_parentheses_enabled?
|
170
|
-
@config.for_cop('Style/RedundantParentheses').fetch('Enabled')
|
171
|
-
end
|
172
|
-
|
173
169
|
def parenthesized?(node)
|
174
170
|
node.begin_type?
|
175
171
|
end
|
176
172
|
|
177
|
-
# When this cop is configured to enforce parentheses and the
|
178
|
-
# `RedundantParentheses` cop is enabled, it will cause an infinite loop
|
179
|
-
# as they compete to add and remove the parentheses respectively.
|
180
|
-
def infinite_loop?
|
181
|
-
(require_parentheses? || require_parentheses_when_complex?) &&
|
182
|
-
redundant_parentheses_enabled?
|
183
|
-
end
|
184
|
-
|
185
173
|
def unsafe_autocorrect?(condition)
|
186
174
|
condition.children.any? do |child|
|
187
175
|
unparenthesized_method_call?(child) || below_ternary_precedence?(child)
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Ext
|
5
|
+
# Extensions to Parser::Source::Range
|
6
|
+
module Range
|
7
|
+
# Adds `Range#single_line?` to parallel `Node#single_line?`
|
8
|
+
def single_line?
|
9
|
+
first_line == last_line
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Parser::Source::Range.include RuboCop::Ext::Range
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
# This class handles loading files (a.k.a. features in Ruby) specified
|
5
|
+
# by `--require` command line option and `require` directive in the config.
|
6
|
+
#
|
7
|
+
# Normally, the given string is directly passed to `require`. If a string
|
8
|
+
# beginning with `.` is given, it is assumed to be relative to the given
|
9
|
+
# directory.
|
10
|
+
#
|
11
|
+
# If a string containing `-` is given, it will be used as is, but if we
|
12
|
+
# cannot find the file to load, we will replace `-` with `/` and try it
|
13
|
+
# again as when Bundler loads gems.
|
14
|
+
#
|
15
|
+
# @api private
|
16
|
+
class FeatureLoader
|
17
|
+
class << self
|
18
|
+
# @param [String] config_directory_path
|
19
|
+
# @param [String] feature
|
20
|
+
def load(config_directory_path:, feature:)
|
21
|
+
new(config_directory_path: config_directory_path, feature: feature).load
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param [String] config_directory_path
|
26
|
+
# @param [String] feature
|
27
|
+
def initialize(config_directory_path:, feature:)
|
28
|
+
@config_directory_path = config_directory_path
|
29
|
+
@feature = feature
|
30
|
+
end
|
31
|
+
|
32
|
+
def load
|
33
|
+
::Kernel.require(target)
|
34
|
+
rescue ::LoadError => e
|
35
|
+
raise if e.path != target
|
36
|
+
|
37
|
+
begin
|
38
|
+
::Kernel.require(namespaced_target)
|
39
|
+
rescue ::LoadError => error_for_namespaced_target
|
40
|
+
raise e if error_for_namespaced_target.path == namespaced_target
|
41
|
+
|
42
|
+
raise error_for_namespaced_target
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
# @return [String]
|
49
|
+
def namespaced_feature
|
50
|
+
@feature.tr('-', '/')
|
51
|
+
end
|
52
|
+
|
53
|
+
# @return [String]
|
54
|
+
def namespaced_target
|
55
|
+
if relative?
|
56
|
+
relative(namespaced_feature)
|
57
|
+
else
|
58
|
+
namespaced_feature
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# @param [String]
|
63
|
+
# @return [String]
|
64
|
+
def relative(feature)
|
65
|
+
::File.join(@config_directory_path, feature)
|
66
|
+
end
|
67
|
+
|
68
|
+
# @return [Boolean]
|
69
|
+
def relative?
|
70
|
+
@feature.start_with?('.')
|
71
|
+
end
|
72
|
+
|
73
|
+
# @param [LoadError] error
|
74
|
+
# @return [Boolean]
|
75
|
+
def seems_cannot_load_such_file_error?(error)
|
76
|
+
error.path == target
|
77
|
+
end
|
78
|
+
|
79
|
+
# @return [String]
|
80
|
+
def target
|
81
|
+
if relative?
|
82
|
+
relative(@feature)
|
83
|
+
else
|
84
|
+
@feature
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
data/lib/rubocop/version.rb
CHANGED
data/lib/rubocop.rb
CHANGED
@@ -16,6 +16,7 @@ require 'rubocop-ast'
|
|
16
16
|
require_relative 'rubocop/ast_aliases'
|
17
17
|
require_relative 'rubocop/ext/regexp_node'
|
18
18
|
require_relative 'rubocop/ext/regexp_parser'
|
19
|
+
require_relative 'rubocop/ext/range'
|
19
20
|
|
20
21
|
require_relative 'rubocop/core_ext/string'
|
21
22
|
require_relative 'rubocop/ext/processed_source'
|
@@ -689,6 +690,7 @@ require_relative 'rubocop/config_obsoletion/split_cop'
|
|
689
690
|
require_relative 'rubocop/config_obsoletion'
|
690
691
|
require_relative 'rubocop/config_store'
|
691
692
|
require_relative 'rubocop/config_validator'
|
693
|
+
require_relative 'rubocop/feature_loader'
|
692
694
|
require_relative 'rubocop/lockfile'
|
693
695
|
require_relative 'rubocop/target_finder'
|
694
696
|
require_relative 'rubocop/directive_comment'
|
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.34.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bozhidar Batsov
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: exe
|
12
12
|
cert_chain: []
|
13
|
-
date: 2022-08-
|
13
|
+
date: 2022-08-09 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: json
|
@@ -46,14 +46,14 @@ dependencies:
|
|
46
46
|
requirements:
|
47
47
|
- - ">="
|
48
48
|
- !ruby/object:Gem::Version
|
49
|
-
version: 3.1.
|
49
|
+
version: 3.1.2.1
|
50
50
|
type: :runtime
|
51
51
|
prerelease: false
|
52
52
|
version_requirements: !ruby/object:Gem::Requirement
|
53
53
|
requirements:
|
54
54
|
- - ">="
|
55
55
|
- !ruby/object:Gem::Version
|
56
|
-
version: 3.1.
|
56
|
+
version: 3.1.2.1
|
57
57
|
- !ruby/object:Gem::Dependency
|
58
58
|
name: rainbow
|
59
59
|
requirement: !ruby/object:Gem::Requirement
|
@@ -120,7 +120,7 @@ dependencies:
|
|
120
120
|
requirements:
|
121
121
|
- - ">="
|
122
122
|
- !ruby/object:Gem::Version
|
123
|
-
version: 1.
|
123
|
+
version: 1.20.0
|
124
124
|
- - "<"
|
125
125
|
- !ruby/object:Gem::Version
|
126
126
|
version: '2.0'
|
@@ -130,7 +130,7 @@ dependencies:
|
|
130
130
|
requirements:
|
131
131
|
- - ">="
|
132
132
|
- !ruby/object:Gem::Version
|
133
|
-
version: 1.
|
133
|
+
version: 1.20.0
|
134
134
|
- - "<"
|
135
135
|
- !ruby/object:Gem::Version
|
136
136
|
version: '2.0'
|
@@ -300,6 +300,7 @@ files:
|
|
300
300
|
- lib/rubocop/cop/internal_affairs/redundant_location_argument.rb
|
301
301
|
- lib/rubocop/cop/internal_affairs/redundant_message_argument.rb
|
302
302
|
- lib/rubocop/cop/internal_affairs/redundant_method_dispatch_node.rb
|
303
|
+
- lib/rubocop/cop/internal_affairs/single_line_comparison.rb
|
303
304
|
- lib/rubocop/cop/internal_affairs/style_detected_api_use.rb
|
304
305
|
- lib/rubocop/cop/internal_affairs/undefined_config.rb
|
305
306
|
- lib/rubocop/cop/internal_affairs/useless_message_assertion.rb
|
@@ -898,8 +899,10 @@ files:
|
|
898
899
|
- lib/rubocop/directive_comment.rb
|
899
900
|
- lib/rubocop/error.rb
|
900
901
|
- lib/rubocop/ext/processed_source.rb
|
902
|
+
- lib/rubocop/ext/range.rb
|
901
903
|
- lib/rubocop/ext/regexp_node.rb
|
902
904
|
- lib/rubocop/ext/regexp_parser.rb
|
905
|
+
- lib/rubocop/feature_loader.rb
|
903
906
|
- lib/rubocop/file_finder.rb
|
904
907
|
- lib/rubocop/formatter.rb
|
905
908
|
- lib/rubocop/formatter/auto_gen_config_formatter.rb
|
@@ -972,7 +975,7 @@ metadata:
|
|
972
975
|
homepage_uri: https://rubocop.org/
|
973
976
|
changelog_uri: https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md
|
974
977
|
source_code_uri: https://github.com/rubocop/rubocop/
|
975
|
-
documentation_uri: https://docs.rubocop.org/rubocop/1.
|
978
|
+
documentation_uri: https://docs.rubocop.org/rubocop/1.34/
|
976
979
|
bug_tracker_uri: https://github.com/rubocop/rubocop/issues
|
977
980
|
rubygems_mfa_required: 'true'
|
978
981
|
post_install_message:
|
@@ -990,7 +993,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
990
993
|
- !ruby/object:Gem::Version
|
991
994
|
version: '0'
|
992
995
|
requirements: []
|
993
|
-
rubygems_version: 3.
|
996
|
+
rubygems_version: 3.2.22
|
994
997
|
signing_key:
|
995
998
|
specification_version: 4
|
996
999
|
summary: Automatic Ruby code style checking tool.
|