rubocop 0.85.0 → 0.85.1
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 +10 -14
- data/lib/rubocop/cop/cop.rb +22 -15
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +1 -1
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +33 -2
- data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +8 -1
- data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
- data/lib/rubocop/cop/registry.rb +62 -7
- data/lib/rubocop/cop/style/redundant_conditional.rb +4 -3
- data/lib/rubocop/cop/team.rb +8 -0
- data/lib/rubocop/cop/utils/format_string.rb +18 -0
- data/lib/rubocop/rspec/expect_offense.rb +4 -1
- data/lib/rubocop/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 86b240fb0a653934db99c6ca12a1c53976c01f3d6de666842e9f7146f207f725
|
4
|
+
data.tar.gz: 606ea84dc8c148971ba8a2dc17ef2a03bbb48802e6053f5042d180e0f6c7c15f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4e6a817ec287b216c15e8820e29192fe1152fa77bb9b6fb9377f7a9b1bc22faef07e15c1f025691107914ae211f401549ef831c755fbf6b9c21bd04198388742
|
7
|
+
data.tar.gz: 2e3a6b4d35e5b24a9542ac5749247537ae2a47db242e86a189d3f719f7b1d35568eb22deaf491b2f5d1408de8415b2ee86fadfe8a56f229fbce89686744cc5e4
|
data/README.md
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
<p align="center">
|
2
|
+
<img src="https://raw.githubusercontent.com/rubocop-hq/rubocop/master/logo/rubo-logo-horizontal.png" alt="RuboCop Logo"/>
|
3
|
+
</p>
|
4
|
+
|
5
|
+
----------
|
1
6
|
[](https://badge.fury.io/rb/rubocop)
|
2
7
|
[](https://circleci.com/gh/rubocop-hq/rubocop/tree/master)
|
3
8
|
[](https://github.com/rubocop-hq/rubocop/actions?query=workflow%3ACI)
|
@@ -11,26 +16,17 @@
|
|
11
16
|
[](#open-collective-sponsors)
|
12
17
|
[](https://tidelift.com/subscription/pkg/rubygems-rubocop?utm_source=rubygems-rubocop&utm_medium=referral&utm_campaign=readme)
|
13
18
|
|
14
|
-
<p align="center">
|
15
|
-
<img src="https://raw.githubusercontent.com/rubocop-hq/rubocop/master/logo/rubo-logo-horizontal.png" alt="RuboCop Logo"/>
|
16
|
-
</p>
|
17
|
-
|
18
19
|
> Role models are important. <br/>
|
19
20
|
> -- Officer Alex J. Murphy / RoboCop
|
20
21
|
|
21
|
-
**RuboCop** is a Ruby static code analyzer and code formatter. Out of
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
**RuboCop** is a Ruby static code analyzer (a.k.a. `linter`) and code formatter. Out of the box it
|
23
|
+
will enforce many of the guidelines outlined in the community [Ruby Style
|
24
|
+
Guide](https://rubystyle.guide). Apart from reporting the problems discovered in your code,
|
25
|
+
RuboCop can also automatically fix many of them you.
|
25
26
|
|
26
27
|
RuboCop is extremely flexible and most aspects of its behavior can be tweaked via various
|
27
28
|
[configuration options](https://github.com/rubocop-hq/rubocop/blob/master/config/default.yml).
|
28
29
|
|
29
|
-
Apart from reporting problems in your code, RuboCop can also
|
30
|
-
automatically fix some of the problems for you.
|
31
|
-
|
32
|
-
[](https://gitter.im/bbatsov/rubocop?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
33
|
-
|
34
30
|
**Please consider [financially supporting its ongoing development](#funding).**
|
35
31
|
|
36
32
|
## Installation
|
@@ -53,7 +49,7 @@ haven't reached version 1.0 yet). To prevent an unwanted RuboCop update you
|
|
53
49
|
might want to use a conservative version lock in your `Gemfile`:
|
54
50
|
|
55
51
|
```rb
|
56
|
-
gem 'rubocop', '~> 0.85.
|
52
|
+
gem 'rubocop', '~> 0.85.1', require: false
|
57
53
|
```
|
58
54
|
|
59
55
|
## Quickstart
|
data/lib/rubocop/cop/cop.rb
CHANGED
@@ -23,7 +23,7 @@ module RuboCop
|
|
23
23
|
# # Do custom processing
|
24
24
|
# end
|
25
25
|
# end
|
26
|
-
class Cop
|
26
|
+
class Cop # rubocop:disable Metrics/ClassLength
|
27
27
|
extend RuboCop::AST::Sexp
|
28
28
|
extend NodePattern::Macros
|
29
29
|
include RuboCop::AST::Sexp
|
@@ -44,22 +44,12 @@ module RuboCop
|
|
44
44
|
attr_reader :config, :offenses, :corrections
|
45
45
|
attr_accessor :processed_source # TODO: Bad design.
|
46
46
|
|
47
|
-
|
48
|
-
|
49
|
-
class << self
|
50
|
-
attr_reader :registry
|
51
|
-
end
|
52
|
-
|
53
|
-
def self.all
|
54
|
-
registry.without_department(:Test).cops
|
55
|
-
end
|
56
|
-
|
57
|
-
def self.qualified_cop_name(name, origin)
|
58
|
-
registry.qualified_cop_name(name, origin)
|
47
|
+
def self.inherited(subclass)
|
48
|
+
Registry.global.enlist(subclass)
|
59
49
|
end
|
60
50
|
|
61
|
-
def self.
|
62
|
-
|
51
|
+
def self.exclude_from_registry
|
52
|
+
Registry.global.dismiss(self)
|
63
53
|
end
|
64
54
|
|
65
55
|
def self.badge
|
@@ -246,6 +236,23 @@ module RuboCop
|
|
246
236
|
nil
|
247
237
|
end
|
248
238
|
|
239
|
+
### Deprecated registry access
|
240
|
+
|
241
|
+
# @deprecated Use Registry.global
|
242
|
+
def self.registry
|
243
|
+
Registry.global
|
244
|
+
end
|
245
|
+
|
246
|
+
# @deprecated Use Registry.all
|
247
|
+
def self.all
|
248
|
+
Registry.all
|
249
|
+
end
|
250
|
+
|
251
|
+
# @deprecated Use Registry.qualified_cop_name
|
252
|
+
def self.qualified_cop_name(name, origin)
|
253
|
+
Registry.qualified_cop_name(name, origin)
|
254
|
+
end
|
255
|
+
|
249
256
|
private
|
250
257
|
|
251
258
|
def find_message(node, message)
|
@@ -147,7 +147,7 @@ module RuboCop
|
|
147
147
|
def indent_level(str)
|
148
148
|
indentations = str.lines
|
149
149
|
.map { |line| line[/^\s*/] }
|
150
|
-
.reject { |line| line
|
150
|
+
.reject { |line| line.end_with?("\n") }
|
151
151
|
indentations.empty? ? 0 : indentations.min_by(&:size).size
|
152
152
|
end
|
153
153
|
|
@@ -7,6 +7,10 @@ module RuboCop
|
|
7
7
|
# expected fields for format/sprintf/#% and what is actually
|
8
8
|
# passed as arguments.
|
9
9
|
#
|
10
|
+
# In addition it checks whether different formats are used in the same
|
11
|
+
# format string. Do not mix numbered, unnumbered, and named formats in
|
12
|
+
# the same format string.
|
13
|
+
#
|
10
14
|
# @example
|
11
15
|
#
|
12
16
|
# # bad
|
@@ -18,16 +22,37 @@ module RuboCop
|
|
18
22
|
# # good
|
19
23
|
#
|
20
24
|
# format('A value: %s and another: %i', a_value, another)
|
25
|
+
#
|
26
|
+
# @example
|
27
|
+
#
|
28
|
+
# # bad
|
29
|
+
#
|
30
|
+
# format('Unnumbered format: %s and numbered: %2$s', a_value, another)
|
31
|
+
#
|
32
|
+
# @example
|
33
|
+
#
|
34
|
+
# # good
|
35
|
+
#
|
36
|
+
# format('Numbered format: %1$s and numbered %2$s', a_value, another)
|
21
37
|
class FormatParameterMismatch < Cop
|
22
38
|
# http://rubular.com/r/CvpbxkcTzy
|
23
39
|
MSG = "Number of arguments (%<arg_num>i) to `%<method>s` doesn't " \
|
24
40
|
'match the number of fields (%<field_num>i).'
|
41
|
+
MSG_INVALID = 'Format string is invalid because formatting sequence types ' \
|
42
|
+
'(numbered, named or unnumbered) are mixed.'
|
25
43
|
|
26
44
|
KERNEL = 'Kernel'
|
27
45
|
SHOVEL = '<<'
|
28
46
|
STRING_TYPES = %i[str dstr].freeze
|
29
47
|
|
30
48
|
def on_send(node)
|
49
|
+
return unless format_string?(node)
|
50
|
+
|
51
|
+
if invalid_format_string?(node)
|
52
|
+
add_offense(node, location: :selector, message: MSG_INVALID)
|
53
|
+
return
|
54
|
+
end
|
55
|
+
|
31
56
|
return unless offending_node?(node)
|
32
57
|
|
33
58
|
add_offense(node, location: :selector)
|
@@ -35,9 +60,15 @@ module RuboCop
|
|
35
60
|
|
36
61
|
private
|
37
62
|
|
63
|
+
def format_string?(node)
|
64
|
+
called_on_string?(node) && method_with_format_args?(node)
|
65
|
+
end
|
66
|
+
|
67
|
+
def invalid_format_string?(node)
|
68
|
+
!RuboCop::Cop::Utils::FormatString.new(node.source).valid?
|
69
|
+
end
|
70
|
+
|
38
71
|
def offending_node?(node)
|
39
|
-
return false unless called_on_string?(node)
|
40
|
-
return false unless method_with_format_args?(node)
|
41
72
|
return false if splat_args?(node)
|
42
73
|
|
43
74
|
num_of_format_args, num_of_expected_fields = count_matches(node)
|
@@ -27,7 +27,14 @@ module RuboCop
|
|
27
27
|
def on_regexp(node)
|
28
28
|
return if contain_non_literal?(node)
|
29
29
|
|
30
|
-
|
30
|
+
begin
|
31
|
+
tree = Regexp::Parser.parse(node.content)
|
32
|
+
# Returns if a regular expression that cannot be processed by regexp_parser gem.
|
33
|
+
# https://github.com/rubocop-hq/rubocop/issues/8083
|
34
|
+
rescue Regexp::Scanner::ScannerError
|
35
|
+
return
|
36
|
+
end
|
37
|
+
|
31
38
|
return unless named_capture?(tree)
|
32
39
|
return unless numbered_capture?(tree)
|
33
40
|
|
data/lib/rubocop/cop/registry.rb
CHANGED
@@ -22,34 +22,42 @@ module RuboCop
|
|
22
22
|
|
23
23
|
# Registry that tracks all cops by their badge and department.
|
24
24
|
class Registry
|
25
|
+
include Enumerable
|
26
|
+
|
27
|
+
attr_reader :options
|
28
|
+
|
25
29
|
def initialize(cops = [], options = {})
|
26
30
|
@registry = {}
|
27
31
|
@departments = {}
|
28
32
|
@cops_by_cop_name = Hash.new { |hash, key| hash[key] = [] }
|
29
33
|
|
30
|
-
|
34
|
+
@enrollment_queue = cops
|
31
35
|
@options = options
|
32
36
|
end
|
33
37
|
|
34
38
|
def enlist(cop)
|
35
|
-
@
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
+
@enrollment_queue << cop
|
40
|
+
end
|
41
|
+
|
42
|
+
def dismiss(cop)
|
43
|
+
raise "Cop #{cop} could not be dismissed" unless @enrollment_queue.delete(cop)
|
39
44
|
end
|
40
45
|
|
41
46
|
# @return [Array<Symbol>] list of departments for current cops.
|
42
47
|
def departments
|
48
|
+
clear_enrollment_queue
|
43
49
|
@departments.keys
|
44
50
|
end
|
45
51
|
|
46
52
|
# @return [Registry] Cops for that specific department.
|
47
53
|
def with_department(department)
|
54
|
+
clear_enrollment_queue
|
48
55
|
with(@departments.fetch(department, []))
|
49
56
|
end
|
50
57
|
|
51
58
|
# @return [Registry] Cops not for a specific department.
|
52
59
|
def without_department(department)
|
60
|
+
clear_enrollment_queue
|
53
61
|
without_department = @departments.dup
|
54
62
|
without_department.delete(department)
|
55
63
|
|
@@ -119,6 +127,7 @@ module RuboCop
|
|
119
127
|
end
|
120
128
|
|
121
129
|
def unqualified_cop_names
|
130
|
+
clear_enrollment_queue
|
122
131
|
@unqualified_cop_names ||=
|
123
132
|
Set.new(@cops_by_cop_name.keys.map { |qn| File.basename(qn) }) <<
|
124
133
|
'RedundantCopDisableDirective'
|
@@ -126,18 +135,21 @@ module RuboCop
|
|
126
135
|
|
127
136
|
# @return [Hash{String => Array<Class>}]
|
128
137
|
def to_h
|
138
|
+
clear_enrollment_queue
|
129
139
|
@cops_by_cop_name
|
130
140
|
end
|
131
141
|
|
132
142
|
def cops
|
143
|
+
clear_enrollment_queue
|
133
144
|
@registry.values
|
134
145
|
end
|
135
146
|
|
136
147
|
def length
|
148
|
+
clear_enrollment_queue
|
137
149
|
@registry.size
|
138
150
|
end
|
139
151
|
|
140
|
-
def enabled(config, only, only_safe = false)
|
152
|
+
def enabled(config, only = [], only_safe = false)
|
141
153
|
select do |cop|
|
142
154
|
only.include?(cop.cop_name) || enabled?(cop, config, only_safe)
|
143
155
|
end
|
@@ -172,6 +184,7 @@ module RuboCop
|
|
172
184
|
end
|
173
185
|
|
174
186
|
def sort!
|
187
|
+
clear_enrollment_queue
|
175
188
|
@registry = Hash[@registry.sort_by { |badge, _| badge.cop_name }]
|
176
189
|
|
177
190
|
self
|
@@ -188,16 +201,57 @@ module RuboCop
|
|
188
201
|
# @param [String] cop_name
|
189
202
|
# @return [Class, nil]
|
190
203
|
def find_by_cop_name(cop_name)
|
191
|
-
|
204
|
+
to_h[cop_name].first
|
205
|
+
end
|
206
|
+
|
207
|
+
@global = new
|
208
|
+
|
209
|
+
class << self
|
210
|
+
attr_reader :global
|
211
|
+
end
|
212
|
+
|
213
|
+
def self.all
|
214
|
+
global.without_department(:Test).cops
|
215
|
+
end
|
216
|
+
|
217
|
+
def self.qualified_cop_name(name, origin)
|
218
|
+
global.qualified_cop_name(name, origin)
|
219
|
+
end
|
220
|
+
|
221
|
+
# Changes momentarily the global registry
|
222
|
+
# Intended for testing purposes
|
223
|
+
def self.with_temporary_global(temp_global = global.dup)
|
224
|
+
previous = @global
|
225
|
+
@global = temp_global
|
226
|
+
yield
|
227
|
+
ensure
|
228
|
+
@global = previous
|
192
229
|
end
|
193
230
|
|
194
231
|
private
|
195
232
|
|
233
|
+
def initialize_copy(reg)
|
234
|
+
initialize(reg.cops, reg.options)
|
235
|
+
end
|
236
|
+
|
237
|
+
def clear_enrollment_queue
|
238
|
+
return if @enrollment_queue.empty?
|
239
|
+
|
240
|
+
@enrollment_queue.each do |cop|
|
241
|
+
@registry[cop.badge] = cop
|
242
|
+
@departments[cop.department] ||= []
|
243
|
+
@departments[cop.department] << cop
|
244
|
+
@cops_by_cop_name[cop.cop_name] << cop
|
245
|
+
end
|
246
|
+
@enrollment_queue = []
|
247
|
+
end
|
248
|
+
|
196
249
|
def with(cops)
|
197
250
|
self.class.new(cops)
|
198
251
|
end
|
199
252
|
|
200
253
|
def qualify_badge(badge)
|
254
|
+
clear_enrollment_queue
|
201
255
|
@departments
|
202
256
|
.map { |department, _| badge.with_department(department) }
|
203
257
|
.select { |potential_badge| registered?(potential_badge) }
|
@@ -214,6 +268,7 @@ module RuboCop
|
|
214
268
|
end
|
215
269
|
|
216
270
|
def registered?(badge)
|
271
|
+
clear_enrollment_queue
|
217
272
|
@registry.key?(badge)
|
218
273
|
end
|
219
274
|
end
|
@@ -27,7 +27,8 @@ module RuboCop
|
|
27
27
|
class RedundantConditional < Cop
|
28
28
|
include Alignment
|
29
29
|
|
30
|
-
|
30
|
+
operators = RuboCop::AST::Node::COMPARISON_OPERATORS.to_a
|
31
|
+
COMPARISON_OPERATOR_MATCHER = "{:#{operators.join(' :')}}"
|
31
32
|
|
32
33
|
MSG = 'This conditional expression can just be replaced ' \
|
33
34
|
'by `%<msg>s`.'
|
@@ -54,11 +55,11 @@ module RuboCop
|
|
54
55
|
end
|
55
56
|
|
56
57
|
def_node_matcher :redundant_condition?, <<~RUBY
|
57
|
-
(if (send _ {
|
58
|
+
(if (send _ #{COMPARISON_OPERATOR_MATCHER} _) true false)
|
58
59
|
RUBY
|
59
60
|
|
60
61
|
def_node_matcher :redundant_condition_inverted?, <<~RUBY
|
61
|
-
(if (send _ {
|
62
|
+
(if (send _ #{COMPARISON_OPERATOR_MATCHER} _) false true)
|
62
63
|
RUBY
|
63
64
|
|
64
65
|
def offense?(node)
|
data/lib/rubocop/cop/team.rb
CHANGED
@@ -31,6 +31,14 @@ module RuboCop
|
|
31
31
|
validate_config
|
32
32
|
end
|
33
33
|
|
34
|
+
# @return [Team]
|
35
|
+
def self.new(cop_or_classes, config, options = {})
|
36
|
+
# Support v0 api:
|
37
|
+
return mobilize(cop_or_classes, config, options) if cop_or_classes.first.is_a?(Class)
|
38
|
+
|
39
|
+
super
|
40
|
+
end
|
41
|
+
|
34
42
|
# @return [Team] with cops assembled from the given `cop_classes`
|
35
43
|
def self.mobilize(cop_classes, config, options = nil)
|
36
44
|
options ||= DEFAULT_OPTIONS
|
@@ -97,6 +97,10 @@ module RuboCop
|
|
97
97
|
@format_sequences ||= parse
|
98
98
|
end
|
99
99
|
|
100
|
+
def valid?
|
101
|
+
!mixed_formats?
|
102
|
+
end
|
103
|
+
|
100
104
|
def named_interpolation?
|
101
105
|
format_sequences.any?(&:name)
|
102
106
|
end
|
@@ -114,6 +118,20 @@ module RuboCop
|
|
114
118
|
)
|
115
119
|
end
|
116
120
|
end
|
121
|
+
|
122
|
+
def mixed_formats?
|
123
|
+
formats = format_sequences.map do |seq|
|
124
|
+
if seq.name
|
125
|
+
:named
|
126
|
+
elsif seq.max_digit_dollar_num
|
127
|
+
:numbered
|
128
|
+
else
|
129
|
+
:unnumbered
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
formats.uniq.size > 1
|
134
|
+
end
|
117
135
|
end
|
118
136
|
end
|
119
137
|
end
|
@@ -115,7 +115,7 @@ module RuboCop
|
|
115
115
|
expect(actual_annotations.to_s).to eq(expected_annotations.to_s)
|
116
116
|
end
|
117
117
|
|
118
|
-
def expect_correction(correction, loop:
|
118
|
+
def expect_correction(correction, loop: true)
|
119
119
|
raise '`expect_correction` must follow `expect_offense`' unless @processed_source
|
120
120
|
|
121
121
|
iteration = 0
|
@@ -128,6 +128,7 @@ module RuboCop
|
|
128
128
|
|
129
129
|
break corrected_source unless loop
|
130
130
|
break corrected_source if cop.corrections.empty?
|
131
|
+
break corrected_source if corrected_source == @processed_source.buffer.source
|
131
132
|
|
132
133
|
if iteration > RuboCop::Runner::MAX_ITERATIONS
|
133
134
|
raise RuboCop::Runner::InfiniteCorrectionLoop.new(@processed_source.path, [])
|
@@ -135,6 +136,8 @@ module RuboCop
|
|
135
136
|
|
136
137
|
# Prepare for next loop
|
137
138
|
cop.instance_variable_set(:@corrections, [])
|
139
|
+
# Cache invalidation. This is bad!
|
140
|
+
cop.instance_variable_set(:@token_table, nil)
|
138
141
|
@processed_source = parse_source(corrected_source,
|
139
142
|
@processed_source.path)
|
140
143
|
_investigate(cop, @processed_source)
|
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: 0.85.
|
4
|
+
version: 0.85.1
|
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: 2020-06-
|
13
|
+
date: 2020-06-07 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: parallel
|
@@ -157,8 +157,8 @@ dependencies:
|
|
157
157
|
- !ruby/object:Gem::Version
|
158
158
|
version: '3.0'
|
159
159
|
description: |2
|
160
|
-
|
161
|
-
|
160
|
+
RuboCop is a Ruby code style checking and code formatting tool.
|
161
|
+
It aims to enforce the community-driven Ruby Style Guide.
|
162
162
|
email: rubocop@googlegroups.com
|
163
163
|
executables:
|
164
164
|
- rubocop
|