rubocop 1.13.0 → 1.14.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 +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: []
|