rubocop 1.33.0 → 1.34.0
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 +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.
|