rubocop 1.13.0 → 1.14.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 +21 -2
- data/lib/rubocop.rb +3 -0
- data/lib/rubocop/cop/bundler/gem_comment.rb +1 -3
- data/lib/rubocop/cop/bundler/gem_version.rb +99 -0
- data/lib/rubocop/cop/layout/redundant_line_break.rb +13 -1
- data/lib/rubocop/cop/layout/single_line_block_chain.rb +53 -0
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +79 -39
- data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/unreachable_loop.rb +12 -2
- data/lib/rubocop/cop/lint/unused_block_argument.rb +7 -1
- data/lib/rubocop/cop/mixin/gem_declaration.rb +13 -0
- data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -1
- data/lib/rubocop/cop/style/class_and_module_children.rb +3 -3
- data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -4
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +17 -9
- data/lib/rubocop/cop/style/single_line_methods.rb +8 -3
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +14 -5
- data/lib/rubocop/cop/variable_force/branch.rb +15 -0
- data/lib/rubocop/rspec/shared_contexts.rb +4 -0
- data/lib/rubocop/target_finder.rb +9 -2
- data/lib/rubocop/target_ruby.rb +1 -1
- data/lib/rubocop/version.rb +1 -1
- metadata +8 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bf17e65fbe829bbc1328bfc1898fe4df1fc1a1e9773b946e1136b3dc16625fd5
|
4
|
+
data.tar.gz: a35649eeecce4e75f2fb623094b4cc5f93323c1b44393482c0b57e3b37358d86
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 696e932f19f9f47448de8858c7444be66fb1a58fa25588e26a8b3842a786677bcf3bd49f9f80b945cbbbed3f5826939fbdf8a8cf106e93843e9c659e20d47b10
|
7
|
+
data.tar.gz: 70729c8cc362bca0ee4397881f2acd0ba088430bfc1c6867e17a9a3da61eff8a0aa911d44a673e1e70d44978638675aedd3717dccfafe3f8cfc78c3f09baeabf
|
data/README.md
CHANGED
@@ -52,7 +52,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
|
|
52
52
|
in your `Gemfile`:
|
53
53
|
|
54
54
|
```rb
|
55
|
-
gem 'rubocop', '~> 1.
|
55
|
+
gem 'rubocop', '~> 1.14', require: false
|
56
56
|
```
|
57
57
|
|
58
58
|
See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
|
data/config/default.yml
CHANGED
@@ -130,7 +130,7 @@ AllCops:
|
|
130
130
|
# What MRI version of the Ruby interpreter is the inspected code intended to
|
131
131
|
# run on? (If there is more than one, set this to the lowest version.)
|
132
132
|
# If a value is specified for TargetRubyVersion then it is used. Acceptable
|
133
|
-
# values are specificed as a float (i.e.
|
133
|
+
# values are specificed as a float (i.e. 3.0); the teeny version of Ruby
|
134
134
|
# should not be included. If the project specifies a Ruby version in the
|
135
135
|
# .tool-versions or .ruby-version files, Gemfile or gems.rb file, RuboCop will
|
136
136
|
# try to determine the desired version of Ruby by inspecting the
|
@@ -138,7 +138,7 @@ AllCops:
|
|
138
138
|
# or gems.locked file. (Although the Ruby version is specified in the Gemfile
|
139
139
|
# or gems.rb file, RuboCop reads the final value from the lock file.) If the
|
140
140
|
# Ruby version is still unresolved, RuboCop will use the oldest officially
|
141
|
-
# supported Ruby version (currently Ruby 2.
|
141
|
+
# supported Ruby version (currently Ruby 2.5).
|
142
142
|
TargetRubyVersion: ~
|
143
143
|
# Determines if a notification for extension libraries should be shown when
|
144
144
|
# rubocop is run. Keys are the name of the extension, and values are an array
|
@@ -174,6 +174,20 @@ Bundler/GemComment:
|
|
174
174
|
IgnoredGems: []
|
175
175
|
OnlyFor: []
|
176
176
|
|
177
|
+
Bundler/GemVersion:
|
178
|
+
Description: 'Requires or forbids specifying gem versions.'
|
179
|
+
Enabled: false
|
180
|
+
VersionAdded: '1.14'
|
181
|
+
EnforcedStyle: 'required'
|
182
|
+
SupportedStyles:
|
183
|
+
- 'required'
|
184
|
+
- 'forbidden'
|
185
|
+
Include:
|
186
|
+
- '**/*.gemfile'
|
187
|
+
- '**/Gemfile'
|
188
|
+
- '**/gems.rb'
|
189
|
+
AllowedGems: []
|
190
|
+
|
177
191
|
Bundler/InsecureProtocolSource:
|
178
192
|
Description: >-
|
179
193
|
The source `:gemcutter`, `:rubygems` and `:rubyforge` are deprecated
|
@@ -1114,6 +1128,11 @@ Layout/RescueEnsureAlignment:
|
|
1114
1128
|
Enabled: true
|
1115
1129
|
VersionAdded: '0.49'
|
1116
1130
|
|
1131
|
+
Layout/SingleLineBlockChain:
|
1132
|
+
Description: 'Put method call on a separate line if chained to a single line block.'
|
1133
|
+
Enabled: false
|
1134
|
+
VersionAdded: '1.14'
|
1135
|
+
|
1117
1136
|
Layout/SpaceAfterColon:
|
1118
1137
|
Description: 'Use spaces after colons.'
|
1119
1138
|
StyleGuide: '#spaces-operators'
|
data/lib/rubocop.rb
CHANGED
@@ -82,6 +82,7 @@ require_relative 'rubocop/cop/mixin/end_keyword_alignment'
|
|
82
82
|
require_relative 'rubocop/cop/mixin/enforce_superclass'
|
83
83
|
require_relative 'rubocop/cop/mixin/first_element_line_break'
|
84
84
|
require_relative 'rubocop/cop/mixin/frozen_string_literal'
|
85
|
+
require_relative 'rubocop/cop/mixin/gem_declaration'
|
85
86
|
require_relative 'rubocop/cop/mixin/hash_alignment_styles'
|
86
87
|
require_relative 'rubocop/cop/mixin/hash_transform_method'
|
87
88
|
require_relative 'rubocop/cop/mixin/ignored_pattern'
|
@@ -148,6 +149,7 @@ require_relative 'rubocop/cop/correctors/unused_arg_corrector'
|
|
148
149
|
|
149
150
|
require_relative 'rubocop/cop/bundler/duplicated_gem'
|
150
151
|
require_relative 'rubocop/cop/bundler/gem_comment'
|
152
|
+
require_relative 'rubocop/cop/bundler/gem_version'
|
151
153
|
require_relative 'rubocop/cop/bundler/insecure_protocol_source'
|
152
154
|
require_relative 'rubocop/cop/bundler/ordered_gems'
|
153
155
|
|
@@ -223,6 +225,7 @@ require_relative 'rubocop/cop/layout/multiline_operation_indentation'
|
|
223
225
|
require_relative 'rubocop/cop/layout/parameter_alignment'
|
224
226
|
require_relative 'rubocop/cop/layout/redundant_line_break'
|
225
227
|
require_relative 'rubocop/cop/layout/rescue_ensure_alignment'
|
228
|
+
require_relative 'rubocop/cop/layout/single_line_block_chain'
|
226
229
|
require_relative 'rubocop/cop/layout/space_after_colon'
|
227
230
|
require_relative 'rubocop/cop/layout/space_after_comma'
|
228
231
|
require_relative 'rubocop/cop/layout/space_after_method_name'
|
@@ -82,6 +82,7 @@ module RuboCop
|
|
82
82
|
#
|
83
83
|
class GemComment < Base
|
84
84
|
include DefNode
|
85
|
+
include GemDeclaration
|
85
86
|
|
86
87
|
MSG = 'Missing gem description comment.'
|
87
88
|
CHECKED_OPTIONS_CONFIG = 'OnlyFor'
|
@@ -90,9 +91,6 @@ module RuboCop
|
|
90
91
|
RESTRICTIVE_VERSION_PATTERN = /<|~>/.freeze
|
91
92
|
RESTRICT_ON_SEND = %i[gem].freeze
|
92
93
|
|
93
|
-
# @!method gem_declaration?(node)
|
94
|
-
def_node_matcher :gem_declaration?, '(send nil? :gem str ...)'
|
95
|
-
|
96
94
|
def on_send(node)
|
97
95
|
return unless gem_declaration?(node)
|
98
96
|
return if ignored_gem?(node)
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Bundler
|
6
|
+
# Enforce that Gem version specifications are either required
|
7
|
+
# or forbidden.
|
8
|
+
#
|
9
|
+
# @example EnforcedStyle: required (default)
|
10
|
+
# # bad
|
11
|
+
# gem 'rubocop'
|
12
|
+
#
|
13
|
+
# # good
|
14
|
+
# gem 'rubocop', '~> 1.12'
|
15
|
+
#
|
16
|
+
# # good
|
17
|
+
# gem 'rubocop', '>= 1.10.0'
|
18
|
+
#
|
19
|
+
# # good
|
20
|
+
# gem 'rubocop', '>= 1.5.0', '< 1.10.0'
|
21
|
+
#
|
22
|
+
# @example EnforcedStyle: forbidden
|
23
|
+
# # good
|
24
|
+
# gem 'rubocop'
|
25
|
+
#
|
26
|
+
# # bad
|
27
|
+
# gem 'rubocop', '~> 1.12'
|
28
|
+
#
|
29
|
+
# # bad
|
30
|
+
# gem 'rubocop', '>= 1.10.0'
|
31
|
+
#
|
32
|
+
# # bad
|
33
|
+
# gem 'rubocop', '>= 1.5.0', '< 1.10.0'
|
34
|
+
#
|
35
|
+
class GemVersion < Base
|
36
|
+
include ConfigurableEnforcedStyle
|
37
|
+
include GemDeclaration
|
38
|
+
|
39
|
+
REQUIRED_MSG = 'Gem version specification is required.'
|
40
|
+
FORBIDDEN_MSG = 'Gem version specification is forbidden.'
|
41
|
+
VERSION_SPECIFICATION_REGEX = /^\s*[~<>=]*\s*[0-9.]+/.freeze
|
42
|
+
|
43
|
+
# @!method includes_version_specification?(node)
|
44
|
+
def_node_matcher :includes_version_specification?, <<~PATTERN
|
45
|
+
(send nil? :gem <(str #version_specification?) ...>)
|
46
|
+
PATTERN
|
47
|
+
|
48
|
+
def on_send(node)
|
49
|
+
return unless gem_declaration?(node)
|
50
|
+
return if allowed_gem?(node)
|
51
|
+
|
52
|
+
if offense?(node)
|
53
|
+
add_offense(node)
|
54
|
+
opposite_style_detected
|
55
|
+
else
|
56
|
+
correct_style_detected
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def allowed_gem?(node)
|
63
|
+
allowed_gems.include?(node.first_argument.value)
|
64
|
+
end
|
65
|
+
|
66
|
+
def allowed_gems
|
67
|
+
Array(cop_config['AllowedGems'])
|
68
|
+
end
|
69
|
+
|
70
|
+
def message(range)
|
71
|
+
gem_specification = range.source
|
72
|
+
|
73
|
+
if required_style?
|
74
|
+
format(REQUIRED_MSG, gem_specification: gem_specification)
|
75
|
+
elsif forbidden_style?
|
76
|
+
format(FORBIDDEN_MSG, gem_specification: gem_specification)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def offense?(node)
|
81
|
+
(required_style? && !includes_version_specification?(node)) ||
|
82
|
+
(forbidden_style? && includes_version_specification?(node))
|
83
|
+
end
|
84
|
+
|
85
|
+
def forbidden_style?
|
86
|
+
style == :forbidden
|
87
|
+
end
|
88
|
+
|
89
|
+
def required_style?
|
90
|
+
style == :required
|
91
|
+
end
|
92
|
+
|
93
|
+
def version_specification?(expression)
|
94
|
+
expression.match?(VERSION_SPECIFICATION_REGEX)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -79,8 +79,20 @@ module RuboCop
|
|
79
79
|
end
|
80
80
|
|
81
81
|
def configured_to_not_be_inspected?(node)
|
82
|
+
return true if other_cop_takes_precedence?(node)
|
83
|
+
|
82
84
|
!cop_config['InspectBlocks'] && (node.block_type? ||
|
83
|
-
node.
|
85
|
+
node.each_descendant(:block).any?(&:multiline?))
|
86
|
+
end
|
87
|
+
|
88
|
+
def other_cop_takes_precedence?(node)
|
89
|
+
single_line_block_chain_enabled? && node.each_descendant(:block).any? do |block_node|
|
90
|
+
block_node.parent.send_type? && block_node.parent.loc.dot && !block_node.multiline?
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def single_line_block_chain_enabled?
|
95
|
+
@config.for_cop('Layout/SingleLineBlockChain')['Enabled']
|
84
96
|
end
|
85
97
|
|
86
98
|
def suitable_as_single_line?(node)
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Layout
|
6
|
+
# This cop checks if method calls are chained onto single line blocks. It considers that a
|
7
|
+
# line break before the dot improves the readability of the code.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# example.select { |item| item.cond? }.join('-')
|
12
|
+
#
|
13
|
+
# # good
|
14
|
+
# example.select { |item| item.cond? }
|
15
|
+
# .join('-')
|
16
|
+
#
|
17
|
+
# # good (not a concern for this cop)
|
18
|
+
# example.select do |item|
|
19
|
+
# item.cond?
|
20
|
+
# end.join('-')
|
21
|
+
#
|
22
|
+
class SingleLineBlockChain < Base
|
23
|
+
include RangeHelp
|
24
|
+
extend AutoCorrector
|
25
|
+
|
26
|
+
MSG = 'Put method call on a separate line if chained to a single line block.'
|
27
|
+
|
28
|
+
def on_send(node)
|
29
|
+
range = offending_range(node)
|
30
|
+
add_offense(range) { |corrector| corrector.insert_before(range, "\n") } if range
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def offending_range(node)
|
36
|
+
receiver = node.receiver
|
37
|
+
return unless receiver&.block_type?
|
38
|
+
|
39
|
+
receiver_location = receiver.loc
|
40
|
+
closing_block_delimiter_line_number = receiver_location.end.line
|
41
|
+
return if receiver_location.begin.line < closing_block_delimiter_line_number
|
42
|
+
|
43
|
+
node_location = node.loc
|
44
|
+
dot_range = node_location.dot
|
45
|
+
return unless dot_range
|
46
|
+
return if dot_range.line > closing_block_delimiter_line_number
|
47
|
+
|
48
|
+
range_between(dot_range.begin_pos, node_location.selector.end_pos)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -24,17 +24,17 @@ module RuboCop
|
|
24
24
|
extend AutoCorrector
|
25
25
|
|
26
26
|
# Inner class to DeprecatedClassMethods.
|
27
|
-
# This class exists to add abstraction and clean naming
|
28
|
-
#
|
27
|
+
# This class exists to add abstraction and clean naming
|
28
|
+
# to the deprecated objects
|
29
29
|
class DeprecatedClassMethod
|
30
30
|
include RuboCop::AST::Sexp
|
31
31
|
|
32
|
-
attr_reader :
|
32
|
+
attr_reader :method, :class_constant
|
33
33
|
|
34
|
-
def initialize(
|
35
|
-
@
|
36
|
-
@replacement_method = replacement
|
34
|
+
def initialize(method, class_constant: nil, correctable: true)
|
35
|
+
@method = method
|
37
36
|
@class_constant = class_constant
|
37
|
+
@correctable = correctable
|
38
38
|
end
|
39
39
|
|
40
40
|
def class_nodes
|
@@ -48,28 +48,80 @@ module RuboCop
|
|
48
48
|
[nil]
|
49
49
|
end
|
50
50
|
end
|
51
|
+
|
52
|
+
def correctable?
|
53
|
+
@correctable
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_s
|
57
|
+
[class_constant, method].compact.join(delimeter)
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def delimeter
|
63
|
+
CLASS_METHOD_DELIMETER
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Inner class to DeprecatedClassMethods.
|
68
|
+
# This class exists to add abstraction and clean naming
|
69
|
+
# to the replacements for deprecated objects
|
70
|
+
class Replacement
|
71
|
+
attr_reader :method, :class_constant
|
72
|
+
|
73
|
+
def initialize(method, class_constant: nil, instance_method: false)
|
74
|
+
@method = method
|
75
|
+
@class_constant = class_constant
|
76
|
+
@instance_method = instance_method
|
77
|
+
end
|
78
|
+
|
79
|
+
def to_s
|
80
|
+
[class_constant, method].compact.join(delimeter)
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def delimeter
|
86
|
+
instance_method? ? INSTANCE_METHOD_DELIMETER : CLASS_METHOD_DELIMETER
|
87
|
+
end
|
88
|
+
|
89
|
+
def instance_method?
|
90
|
+
@instance_method
|
91
|
+
end
|
51
92
|
end
|
52
93
|
|
53
94
|
MSG = '`%<current>s` is deprecated in favor of `%<prefer>s`.'
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
95
|
+
|
96
|
+
DEPRECATED_METHODS_OBJECT = {
|
97
|
+
DeprecatedClassMethod.new(:exists?, class_constant: :File) =>
|
98
|
+
Replacement.new(:exist?, class_constant: :File),
|
99
|
+
|
100
|
+
DeprecatedClassMethod.new(:exists?, class_constant: :Dir) =>
|
101
|
+
Replacement.new(:exist?, class_constant: :Dir),
|
102
|
+
|
103
|
+
DeprecatedClassMethod.new(:iterator?) => Replacement.new(:block_given?),
|
104
|
+
|
105
|
+
DeprecatedClassMethod.new(:gethostbyaddr, class_constant: :Socket, correctable: false) =>
|
106
|
+
Replacement.new(:getnameinfo, class_constant: :Addrinfo, instance_method: true),
|
107
|
+
|
108
|
+
DeprecatedClassMethod.new(:gethostbyname, class_constant: :Socket, correctable: false) =>
|
109
|
+
Replacement.new(:getaddrinfo, class_constant: :Addrinfo, instance_method: true)
|
110
|
+
}.freeze
|
111
|
+
|
112
|
+
RESTRICT_ON_SEND = DEPRECATED_METHODS_OBJECT.keys.map(&:method).freeze
|
113
|
+
|
114
|
+
CLASS_METHOD_DELIMETER = '.'
|
115
|
+
INSTANCE_METHOD_DELIMETER = '#'
|
65
116
|
|
66
117
|
def on_send(node)
|
67
|
-
check(node) do |
|
68
|
-
message = format(MSG, current:
|
69
|
-
prefer: replacement_method(data))
|
118
|
+
check(node) do |deprecated|
|
119
|
+
message = format(MSG, current: deprecated, prefer: replacement(deprecated))
|
70
120
|
|
71
121
|
add_offense(node.loc.selector, message: message) do |corrector|
|
72
|
-
|
122
|
+
if deprecated.correctable?
|
123
|
+
corrector.replace(node.loc.selector, replacement(deprecated).method)
|
124
|
+
end
|
73
125
|
end
|
74
126
|
end
|
75
127
|
end
|
@@ -77,28 +129,16 @@ module RuboCop
|
|
77
129
|
private
|
78
130
|
|
79
131
|
def check(node)
|
80
|
-
DEPRECATED_METHODS_OBJECT.
|
81
|
-
next unless
|
82
|
-
next unless node.method?(
|
132
|
+
DEPRECATED_METHODS_OBJECT.each_key do |deprecated|
|
133
|
+
next unless deprecated.class_nodes.include?(node.receiver)
|
134
|
+
next unless node.method?(deprecated.method)
|
83
135
|
|
84
|
-
yield
|
136
|
+
yield deprecated
|
85
137
|
end
|
86
138
|
end
|
87
139
|
|
88
|
-
def
|
89
|
-
|
90
|
-
end
|
91
|
-
|
92
|
-
def replacement_method(data)
|
93
|
-
method_call(data.class_constant, data.replacement_method)
|
94
|
-
end
|
95
|
-
|
96
|
-
def method_call(class_constant, method)
|
97
|
-
if class_constant
|
98
|
-
format('%<constant>s.%<method>s', constant: class_constant, method: method)
|
99
|
-
else
|
100
|
-
format('%<method>s', method: method)
|
101
|
-
end
|
140
|
+
def replacement(deprecated)
|
141
|
+
DEPRECATED_METHODS_OBJECT[deprecated]
|
102
142
|
end
|
103
143
|
end
|
104
144
|
end
|
@@ -87,6 +87,7 @@ module RuboCop
|
|
87
87
|
include IgnoredPattern
|
88
88
|
|
89
89
|
MSG = 'This loop will have at most one iteration.'
|
90
|
+
CONTINUE_KEYWORDS = %i[next redo].freeze
|
90
91
|
|
91
92
|
def on_while(node)
|
92
93
|
check(node)
|
@@ -116,7 +117,10 @@ module RuboCop
|
|
116
117
|
break_statement = statements.find { |statement| break_statement?(statement) }
|
117
118
|
return unless break_statement
|
118
119
|
|
119
|
-
|
120
|
+
unless preceded_by_continue_statement?(break_statement) ||
|
121
|
+
conditional_continue_keyword?(break_statement)
|
122
|
+
add_offense(node)
|
123
|
+
end
|
120
124
|
end
|
121
125
|
|
122
126
|
def statements(node)
|
@@ -177,9 +181,15 @@ module RuboCop
|
|
177
181
|
break_statement.left_siblings.any? do |sibling|
|
178
182
|
next if sibling.loop_keyword? || loop_method?(sibling)
|
179
183
|
|
180
|
-
sibling.each_descendant(
|
184
|
+
sibling.each_descendant(*CONTINUE_KEYWORDS).any?
|
181
185
|
end
|
182
186
|
end
|
187
|
+
|
188
|
+
def conditional_continue_keyword?(break_statement)
|
189
|
+
or_node = break_statement.each_descendant(:or).to_a.last
|
190
|
+
|
191
|
+
or_node && CONTINUE_KEYWORDS.include?(or_node.rhs.type)
|
192
|
+
end
|
183
193
|
end
|
184
194
|
end
|
185
195
|
end
|
@@ -67,11 +67,17 @@ module RuboCop
|
|
67
67
|
end
|
68
68
|
|
69
69
|
def check_argument(variable)
|
70
|
-
return if allowed_block?(variable) ||
|
70
|
+
return if allowed_block?(variable) ||
|
71
|
+
allowed_keyword_argument?(variable) ||
|
72
|
+
used_block_local?(variable)
|
71
73
|
|
72
74
|
super
|
73
75
|
end
|
74
76
|
|
77
|
+
def used_block_local?(variable)
|
78
|
+
variable.explicit_block_local_variable? && !variable.assignments.empty?
|
79
|
+
end
|
80
|
+
|
75
81
|
def allowed_block?(variable)
|
76
82
|
!variable.block_argument? || (ignore_empty_blocks? && empty_block?(variable))
|
77
83
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
# Common functionality for checking gem declarations.
|
6
|
+
module GemDeclaration
|
7
|
+
extend NodePattern::Macros
|
8
|
+
|
9
|
+
# @!method gem_declaration?(node)
|
10
|
+
def_node_matcher :gem_declaration?, '(send nil? :gem str ...)'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -132,7 +132,7 @@ module RuboCop
|
|
132
132
|
end
|
133
133
|
|
134
134
|
def check_compact_style(node, body)
|
135
|
-
return unless
|
135
|
+
return unless needs_compacting?(body)
|
136
136
|
|
137
137
|
add_offense(node.loc.name, message: COMPACT_MSG) do |corrector|
|
138
138
|
autocorrect(corrector, node)
|
@@ -145,12 +145,12 @@ module RuboCop
|
|
145
145
|
nest_or_compact(corrector, node)
|
146
146
|
end
|
147
147
|
|
148
|
-
def
|
148
|
+
def needs_compacting?(body)
|
149
149
|
body && %i[module class].include?(body.type)
|
150
150
|
end
|
151
151
|
|
152
152
|
def compact_node_name?(node)
|
153
|
-
/::/.match?(node.
|
153
|
+
/::/.match?(node.identifier.source)
|
154
154
|
end
|
155
155
|
end
|
156
156
|
end
|
@@ -67,15 +67,14 @@ module RuboCop
|
|
67
67
|
|
68
68
|
def autocorrect(corrector, node)
|
69
69
|
replacement = if node.modifier_form?
|
70
|
-
|
71
|
-
last_argument = node.if_branch.last_argument
|
70
|
+
last_argument = node.if_branch.last_argument if node.if_branch.send_type?
|
72
71
|
|
73
72
|
if last_argument.respond_to?(:heredoc?) && last_argument.heredoc?
|
74
73
|
heredoc = extract_heredoc_from(last_argument)
|
75
74
|
remove_heredoc(corrector, heredoc)
|
76
|
-
to_normal_form_with_heredoc(node,
|
75
|
+
to_normal_form_with_heredoc(node, indent(node), heredoc)
|
77
76
|
else
|
78
|
-
to_normal_form(node,
|
77
|
+
to_normal_form(node, indent(node))
|
79
78
|
end
|
80
79
|
else
|
81
80
|
to_modifier_form(node)
|
@@ -29,7 +29,6 @@ module RuboCop
|
|
29
29
|
#
|
30
30
|
class NegatedIfElseCondition < Base
|
31
31
|
include RangeHelp
|
32
|
-
include CommentsHelp
|
33
32
|
extend AutoCorrector
|
34
33
|
|
35
34
|
MSG = 'Invert the negated condition and swap the %<type>s branches.'
|
@@ -98,21 +97,30 @@ module RuboCop
|
|
98
97
|
if node.if_branch.nil?
|
99
98
|
corrector.remove(range_by_whole_lines(node.loc.else, include_final_newline: true))
|
100
99
|
else
|
101
|
-
if_range =
|
102
|
-
else_range =
|
100
|
+
if_range = if_range(node)
|
101
|
+
else_range = else_range(node)
|
103
102
|
|
104
103
|
corrector.replace(if_range, else_range.source)
|
105
104
|
corrector.replace(else_range, if_range.source)
|
106
105
|
end
|
107
106
|
end
|
108
107
|
|
109
|
-
|
110
|
-
|
111
|
-
|
108
|
+
# Collect the entire if branch, including whitespace and comments
|
109
|
+
def if_range(node)
|
110
|
+
if node.ternary?
|
111
|
+
node.if_branch
|
112
|
+
else
|
113
|
+
range_between(node.condition.loc.expression.end_pos, node.loc.else.begin_pos)
|
114
|
+
end
|
115
|
+
end
|
112
116
|
|
113
|
-
|
114
|
-
|
115
|
-
|
117
|
+
# Collect the entire else branch, including whitespace and comments
|
118
|
+
def else_range(node)
|
119
|
+
if node.ternary?
|
120
|
+
node.else_branch
|
121
|
+
else
|
122
|
+
range_between(node.loc.else.end_pos, node.loc.end.begin_pos)
|
123
|
+
end
|
116
124
|
end
|
117
125
|
end
|
118
126
|
end
|
@@ -68,6 +68,7 @@ module RuboCop
|
|
68
68
|
return false unless endless_method_config['Enabled']
|
69
69
|
return false if endless_method_config['EnforcedStyle'] == 'disallow'
|
70
70
|
return false unless body_node
|
71
|
+
return false if body_node.parent.assignment_method?
|
71
72
|
|
72
73
|
!(body_node.begin_type? || body_node.kwbegin_type?)
|
73
74
|
end
|
@@ -115,15 +116,19 @@ module RuboCop
|
|
115
116
|
end
|
116
117
|
|
117
118
|
def method_body_source(method_body)
|
118
|
-
if
|
119
|
-
method_body.source
|
120
|
-
else
|
119
|
+
if require_parentheses?(method_body)
|
121
120
|
arguments_source = method_body.arguments.map(&:source).join(', ')
|
122
121
|
body_source = "#{method_body.method_name}(#{arguments_source})"
|
123
122
|
|
124
123
|
method_body.receiver ? "#{method_body.receiver.source}.#{body_source}" : body_source
|
124
|
+
else
|
125
|
+
method_body.source
|
125
126
|
end
|
126
127
|
end
|
128
|
+
|
129
|
+
def require_parentheses?(method_body)
|
130
|
+
method_body.send_type? && !method_body.arguments.empty? && !method_body.comparison_method?
|
131
|
+
end
|
127
132
|
end
|
128
133
|
end
|
129
134
|
end
|
@@ -80,10 +80,7 @@ module RuboCop
|
|
80
80
|
def autocorrect(corrector, node, if_branch)
|
81
81
|
corrector.wrap(node.condition, '(', ')') if node.condition.or_type?
|
82
82
|
|
83
|
-
if node.unless?
|
84
|
-
corrector.replace(node.loc.keyword, 'if')
|
85
|
-
corrector.insert_before(node.condition, '!')
|
86
|
-
end
|
83
|
+
correct_from_unless_to_if(corrector, node) if node.unless?
|
87
84
|
|
88
85
|
and_operator = if_branch.unless? ? ' && !' : ' && '
|
89
86
|
if if_branch.modifier_form?
|
@@ -94,6 +91,17 @@ module RuboCop
|
|
94
91
|
end
|
95
92
|
end
|
96
93
|
|
94
|
+
def correct_from_unless_to_if(corrector, node)
|
95
|
+
corrector.replace(node.loc.keyword, 'if')
|
96
|
+
|
97
|
+
condition = node.condition
|
98
|
+
if condition.send_type? && condition.comparison_method? && !condition.parenthesized?
|
99
|
+
corrector.wrap(node.condition, '!(', ')')
|
100
|
+
else
|
101
|
+
corrector.insert_before(node.condition, '!')
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
97
105
|
def correct_for_guard_condition_style(corrector, node, if_branch, and_operator)
|
98
106
|
outer_condition = node.condition
|
99
107
|
correct_outer_condition(corrector, outer_condition)
|
@@ -136,7 +144,8 @@ module RuboCop
|
|
136
144
|
end
|
137
145
|
|
138
146
|
def requrie_parentheses?(condition)
|
139
|
-
condition.send_type? && !condition.arguments.empty? && !condition.parenthesized?
|
147
|
+
condition.send_type? && !condition.arguments.empty? && !condition.parenthesized? &&
|
148
|
+
!condition.comparison_method?
|
140
149
|
end
|
141
150
|
|
142
151
|
def arguments_range(node)
|
@@ -226,6 +226,21 @@ module RuboCop
|
|
226
226
|
end
|
227
227
|
end
|
228
228
|
|
229
|
+
# case target
|
230
|
+
# in pattern # in_pattern
|
231
|
+
# else
|
232
|
+
# else_body
|
233
|
+
# end
|
234
|
+
class CaseMatch < Base
|
235
|
+
define_predicate :target?, child_index: 0
|
236
|
+
define_predicate :in_pattern?, child_index: 1..-2
|
237
|
+
define_predicate :else_body?, child_index: -1
|
238
|
+
|
239
|
+
def always_run?
|
240
|
+
target?
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
229
244
|
# for element in collection
|
230
245
|
# loop_body
|
231
246
|
# end
|
@@ -100,12 +100,19 @@ module RuboCop
|
|
100
100
|
next true if dir.end_with?('/./', '/../')
|
101
101
|
next true if File.fnmatch?(exclude_pattern, dir, flags)
|
102
102
|
|
103
|
-
|
104
|
-
"#{File.realpath(dir)}/", flags)
|
103
|
+
symlink_excluded_or_infinite_loop?(base_dir, dir, exclude_pattern, flags)
|
105
104
|
end
|
106
105
|
dirs.flat_map { |dir| wanted_dir_patterns(dir, exclude_pattern, flags) }.unshift(base_dir)
|
107
106
|
end
|
108
107
|
|
108
|
+
def symlink_excluded_or_infinite_loop?(base_dir, current_dir, exclude_pattern, flags)
|
109
|
+
dir_realpath = File.realpath(current_dir)
|
110
|
+
File.symlink?(current_dir.chomp('/')) && (
|
111
|
+
File.fnmatch?(exclude_pattern, "#{dir_realpath}/", flags) ||
|
112
|
+
File.realpath(base_dir).start_with?(dir_realpath)
|
113
|
+
)
|
114
|
+
end
|
115
|
+
|
109
116
|
def combined_exclude_glob_patterns(base_dir)
|
110
117
|
exclude = @config_store.for(base_dir).for_all_cops['Exclude']
|
111
118
|
patterns = exclude.select { |pattern| pattern.is_a?(String) && pattern.end_with?('/**/*') }
|
data/lib/rubocop/target_ruby.rb
CHANGED
@@ -4,7 +4,7 @@ module RuboCop
|
|
4
4
|
# The kind of Ruby that code inspected by RuboCop is written in.
|
5
5
|
# @api private
|
6
6
|
class TargetRuby
|
7
|
-
KNOWN_RUBIES = [2.5, 2.6, 2.7, 3.0].freeze
|
7
|
+
KNOWN_RUBIES = [2.5, 2.6, 2.7, 3.0, 3.1].freeze
|
8
8
|
DEFAULT_VERSION = KNOWN_RUBIES.first
|
9
9
|
|
10
10
|
OBSOLETE_RUBIES = {
|
data/lib/rubocop/version.rb
CHANGED
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.14.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: 2021-
|
13
|
+
date: 2021-05-05 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: parallel
|
@@ -100,7 +100,7 @@ dependencies:
|
|
100
100
|
requirements:
|
101
101
|
- - ">="
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: 1.
|
103
|
+
version: 1.5.0
|
104
104
|
- - "<"
|
105
105
|
- !ruby/object:Gem::Version
|
106
106
|
version: '2.0'
|
@@ -110,7 +110,7 @@ dependencies:
|
|
110
110
|
requirements:
|
111
111
|
- - ">="
|
112
112
|
- !ruby/object:Gem::Version
|
113
|
-
version: 1.
|
113
|
+
version: 1.5.0
|
114
114
|
- - "<"
|
115
115
|
- !ruby/object:Gem::Version
|
116
116
|
version: '2.0'
|
@@ -221,6 +221,7 @@ files:
|
|
221
221
|
- lib/rubocop/cop/base.rb
|
222
222
|
- lib/rubocop/cop/bundler/duplicated_gem.rb
|
223
223
|
- lib/rubocop/cop/bundler/gem_comment.rb
|
224
|
+
- lib/rubocop/cop/bundler/gem_version.rb
|
224
225
|
- lib/rubocop/cop/bundler/insecure_protocol_source.rb
|
225
226
|
- lib/rubocop/cop/bundler/ordered_gems.rb
|
226
227
|
- lib/rubocop/cop/commissioner.rb
|
@@ -333,6 +334,7 @@ files:
|
|
333
334
|
- lib/rubocop/cop/layout/parameter_alignment.rb
|
334
335
|
- lib/rubocop/cop/layout/redundant_line_break.rb
|
335
336
|
- lib/rubocop/cop/layout/rescue_ensure_alignment.rb
|
337
|
+
- lib/rubocop/cop/layout/single_line_block_chain.rb
|
336
338
|
- lib/rubocop/cop/layout/space_after_colon.rb
|
337
339
|
- lib/rubocop/cop/layout/space_after_comma.rb
|
338
340
|
- lib/rubocop/cop/layout/space_after_method_name.rb
|
@@ -524,6 +526,7 @@ files:
|
|
524
526
|
- lib/rubocop/cop/mixin/enforce_superclass.rb
|
525
527
|
- lib/rubocop/cop/mixin/first_element_line_break.rb
|
526
528
|
- lib/rubocop/cop/mixin/frozen_string_literal.rb
|
529
|
+
- lib/rubocop/cop/mixin/gem_declaration.rb
|
527
530
|
- lib/rubocop/cop/mixin/hash_alignment_styles.rb
|
528
531
|
- lib/rubocop/cop/mixin/hash_transform_method.rb
|
529
532
|
- lib/rubocop/cop/mixin/heredoc.rb
|
@@ -872,7 +875,7 @@ metadata:
|
|
872
875
|
homepage_uri: https://rubocop.org/
|
873
876
|
changelog_uri: https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md
|
874
877
|
source_code_uri: https://github.com/rubocop/rubocop/
|
875
|
-
documentation_uri: https://docs.rubocop.org/rubocop/1.
|
878
|
+
documentation_uri: https://docs.rubocop.org/rubocop/1.14/
|
876
879
|
bug_tracker_uri: https://github.com/rubocop/rubocop/issues
|
877
880
|
post_install_message:
|
878
881
|
rdoc_options: []
|