rubocop 1.7.0 → 1.10.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/LICENSE.txt +1 -1
- data/README.md +4 -3
- data/config/default.yml +137 -31
- data/config/obsoletion.yml +4 -0
- data/lib/rubocop.rb +14 -1
- data/lib/rubocop/cli/command/auto_genenerate_config.rb +5 -4
- data/lib/rubocop/comment_config.rb +6 -6
- data/lib/rubocop/config.rb +5 -2
- data/lib/rubocop/config_loader.rb +7 -14
- data/lib/rubocop/config_store.rb +12 -1
- data/lib/rubocop/cop/base.rb +2 -1
- data/lib/rubocop/cop/exclude_limit.rb +26 -0
- data/lib/rubocop/cop/gemspec/date_assignment.rb +56 -0
- data/lib/rubocop/cop/generator.rb +1 -3
- data/lib/rubocop/cop/internal_affairs.rb +5 -1
- data/lib/rubocop/cop/internal_affairs/empty_line_between_expect_offense_and_correction.rb +68 -0
- data/lib/rubocop/cop/internal_affairs/example_description.rb +89 -0
- data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +61 -0
- data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +64 -0
- data/lib/rubocop/cop/layout/class_structure.rb +7 -2
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +38 -18
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +16 -2
- data/lib/rubocop/cop/layout/line_length.rb +2 -1
- data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +26 -0
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/space_before_brackets.rb +19 -16
- data/lib/rubocop/cop/lint/debugger.rb +58 -14
- data/lib/rubocop/cop/lint/deprecated_constants.rb +80 -0
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +13 -4
- data/lib/rubocop/cop/lint/duplicate_require.rb +2 -2
- data/lib/rubocop/cop/lint/else_layout.rb +1 -1
- data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +44 -0
- data/lib/rubocop/cop/lint/multiple_comparison.rb +4 -4
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +10 -6
- data/lib/rubocop/cop/lint/number_conversion.rb +41 -6
- data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +47 -0
- data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +39 -0
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +2 -1
- data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +50 -0
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +5 -3
- data/lib/rubocop/cop/lint/symbol_conversion.rb +103 -0
- data/lib/rubocop/cop/lint/triple_quotes.rb +71 -0
- data/lib/rubocop/cop/message_annotator.rb +4 -1
- data/lib/rubocop/cop/metrics/block_nesting.rb +2 -2
- data/lib/rubocop/cop/metrics/parameter_lists.rb +5 -2
- data/lib/rubocop/cop/mixin/allowed_identifiers.rb +18 -0
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +5 -0
- data/lib/rubocop/cop/mixin/code_length.rb +3 -1
- data/lib/rubocop/cop/mixin/comments_help.rb +1 -11
- data/lib/rubocop/cop/mixin/configurable_max.rb +1 -0
- data/lib/rubocop/cop/mixin/first_element_line_break.rb +1 -1
- data/lib/rubocop/cop/mixin/method_complexity.rb +3 -1
- data/lib/rubocop/cop/mixin/preferred_delimiters.rb +2 -2
- data/lib/rubocop/cop/mixin/uncommunicative_name.rb +5 -1
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +38 -5
- data/lib/rubocop/cop/naming/variable_name.rb +2 -0
- data/lib/rubocop/cop/naming/variable_number.rb +2 -9
- data/lib/rubocop/cop/registry.rb +1 -1
- data/lib/rubocop/cop/severity.rb +3 -3
- data/lib/rubocop/cop/style/ascii_comments.rb +1 -1
- data/lib/rubocop/cop/style/constant_visibility.rb +27 -0
- data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +49 -9
- data/lib/rubocop/cop/style/double_negation.rb +2 -2
- data/lib/rubocop/cop/style/empty_literal.rb +6 -2
- data/lib/rubocop/cop/style/endless_method.rb +102 -0
- data/lib/rubocop/cop/style/eval_with_location.rb +138 -49
- data/lib/rubocop/cop/style/explicit_block_argument.rb +11 -1
- data/lib/rubocop/cop/style/exponential_notation.rb +6 -7
- data/lib/rubocop/cop/style/float_division.rb +3 -0
- data/lib/rubocop/cop/style/format_string_token.rb +18 -2
- data/lib/rubocop/cop/style/hash_conversion.rb +81 -0
- data/lib/rubocop/cop/style/hash_like_case.rb +2 -1
- data/lib/rubocop/cop/style/if_inside_else.rb +22 -10
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +120 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +4 -0
- data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +4 -0
- data/lib/rubocop/cop/style/nil_comparison.rb +3 -0
- data/lib/rubocop/cop/style/non_nil_check.rb +23 -13
- data/lib/rubocop/cop/style/numeric_literals.rb +6 -9
- data/lib/rubocop/cop/style/numeric_predicate.rb +1 -1
- data/lib/rubocop/cop/style/raise_args.rb +3 -2
- data/lib/rubocop/cop/style/redundant_return.rb +1 -1
- data/lib/rubocop/cop/style/single_line_methods.rb +32 -2
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +29 -5
- data/lib/rubocop/cop/style/special_global_vars.rb +3 -3
- data/lib/rubocop/cop/style/string_concatenation.rb +1 -1
- data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/while_until_modifier.rb +2 -4
- data/lib/rubocop/formatter/git_hub_actions_formatter.rb +1 -0
- data/lib/rubocop/formatter/offense_count_formatter.rb +1 -1
- data/lib/rubocop/formatter/simple_text_formatter.rb +2 -1
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -1
- data/lib/rubocop/magic_comment.rb +30 -1
- data/lib/rubocop/options.rb +1 -1
- data/lib/rubocop/rspec/expect_offense.rb +5 -2
- data/lib/rubocop/runner.rb +1 -0
- data/lib/rubocop/target_ruby.rb +47 -11
- data/lib/rubocop/version.rb +2 -2
- metadata +24 -7
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module InternalAffairs
|
6
|
+
# This cop checks for redundant `subject(:cop) { described_class.new }`.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# RSpec.describe RuboCop::Cop::Department::Foo do
|
11
|
+
# subject(:cop) { described_class.new(config) }
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# RSpec.describe RuboCop::Cop::Department::Foo, :config do
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
class RedundantDescribedClassAsSubject < Base
|
19
|
+
include RangeHelp
|
20
|
+
extend AutoCorrector
|
21
|
+
|
22
|
+
MSG = 'Remove the redundant `subject`%<additional_message>s.'
|
23
|
+
|
24
|
+
def_node_matcher :described_class_subject?, <<~PATTERN
|
25
|
+
(block
|
26
|
+
(send nil? :subject
|
27
|
+
(sym :cop))
|
28
|
+
(args)
|
29
|
+
(send
|
30
|
+
(send nil? :described_class) :new
|
31
|
+
$...))
|
32
|
+
PATTERN
|
33
|
+
|
34
|
+
def on_block(node)
|
35
|
+
return unless (described_class_arguments = described_class_subject?(node))
|
36
|
+
return if described_class_arguments.count >= 2
|
37
|
+
|
38
|
+
describe = find_describe_method_node(node)
|
39
|
+
|
40
|
+
unless (exist_config = describe.last_argument.source == ':config')
|
41
|
+
additional_message = ' and specify `:config` in `describe`'
|
42
|
+
end
|
43
|
+
|
44
|
+
message = format(MSG, additional_message: additional_message)
|
45
|
+
|
46
|
+
add_offense(node, message: message) do |corrector|
|
47
|
+
corrector.remove(range_by_whole_lines(node.source_range, include_final_newline: true))
|
48
|
+
|
49
|
+
corrector.insert_after(describe.last_argument, ', :config') unless exist_config
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def find_describe_method_node(block_node)
|
56
|
+
block_node.ancestors.find { |node| node.block_type? && node.method?(:describe) }.send_node
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module InternalAffairs
|
6
|
+
# This cop checks that `let` is `RuboCop::Config.new` with no arguments.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# RSpec.describe RuboCop::Cop::Department::Foo, :config do
|
11
|
+
# let(:config) { RuboCop::Config.new }
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# RSpec.describe RuboCop::Cop::Department::Foo, :config do
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# RSpec.describe RuboCop::Cop::Department::Foo, :config do
|
19
|
+
# let(:config) { RuboCop::Config.new(argument) }
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
class RedundantLetRuboCopConfigNew < Base
|
23
|
+
include RangeHelp
|
24
|
+
extend AutoCorrector
|
25
|
+
|
26
|
+
MSG = 'Remove `let` that is `RuboCop::Config.new` with no arguments%<additional_message>s.'
|
27
|
+
|
28
|
+
def_node_matcher :let_rubocop_config_new?, <<~PATTERN
|
29
|
+
(block
|
30
|
+
(send nil? :let
|
31
|
+
(sym :config))
|
32
|
+
(args)
|
33
|
+
(send
|
34
|
+
(const
|
35
|
+
(const nil? :RuboCop) :Config) :new))
|
36
|
+
PATTERN
|
37
|
+
|
38
|
+
def on_block(node)
|
39
|
+
return unless let_rubocop_config_new?(node)
|
40
|
+
|
41
|
+
describe = find_describe_method_node(node)
|
42
|
+
|
43
|
+
unless (exist_config = describe.last_argument.source == ':config')
|
44
|
+
additional_message = ' and specify `:config` in `describe`'
|
45
|
+
end
|
46
|
+
|
47
|
+
message = format(MSG, additional_message: additional_message)
|
48
|
+
|
49
|
+
add_offense(node, message: message) do |corrector|
|
50
|
+
corrector.remove(range_by_whole_lines(node.source_range, include_final_newline: true))
|
51
|
+
|
52
|
+
corrector.insert_after(describe.last_argument, ', :config') unless exist_config
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def find_describe_method_node(block_node)
|
59
|
+
block_node.ancestors.find { |node| node.block_type? && node.method?(:describe) }.send_node
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -213,7 +213,12 @@ module RuboCop
|
|
213
213
|
name = node.method_name.to_s
|
214
214
|
category, = categories.find { |_, names| names.include?(name) }
|
215
215
|
key = category || name
|
216
|
-
visibility_key =
|
216
|
+
visibility_key =
|
217
|
+
if node.def_modifier?
|
218
|
+
"#{name}_methods"
|
219
|
+
else
|
220
|
+
"#{node_visibility(node)}_#{key}"
|
221
|
+
end
|
217
222
|
expected_order.include?(visibility_key) ? visibility_key : key
|
218
223
|
end
|
219
224
|
|
@@ -264,7 +269,7 @@ module RuboCop
|
|
264
269
|
|
265
270
|
def source_range_with_comment(node)
|
266
271
|
begin_pos, end_pos =
|
267
|
-
if node.def_type?
|
272
|
+
if node.def_type? && !node.method?(:initialize) || node.send_type? && node.def_modifier?
|
268
273
|
start_node = find_visibility_start(node) || node
|
269
274
|
end_node = find_visibility_end(node) || node
|
270
275
|
[begin_pos_with_comment(start_node),
|
@@ -88,7 +88,7 @@ module RuboCop
|
|
88
88
|
include RangeHelp
|
89
89
|
extend AutoCorrector
|
90
90
|
|
91
|
-
MSG = '
|
91
|
+
MSG = 'Expected %<expected>s between %<type>s definitions; found %<actual>d.'
|
92
92
|
|
93
93
|
def self.autocorrect_incompatible_with
|
94
94
|
[Layout::EmptyLines]
|
@@ -107,19 +107,21 @@ module RuboCop
|
|
107
107
|
end
|
108
108
|
|
109
109
|
def check_defs(nodes)
|
110
|
-
|
110
|
+
count = blank_lines_count_between(*nodes)
|
111
|
+
|
112
|
+
return if line_count_allowed?(count)
|
111
113
|
return if multiple_blank_lines_groups?(*nodes)
|
112
114
|
return if nodes.all?(&:single_line?) &&
|
113
115
|
cop_config['AllowAdjacentOneLineDefs']
|
114
116
|
|
115
117
|
correction_node = nodes.last
|
116
118
|
location = correction_node.loc.keyword.join(correction_node.loc.name)
|
117
|
-
add_offense(location, message: message(correction_node)) do |corrector|
|
118
|
-
autocorrect(corrector, *nodes)
|
119
|
+
add_offense(location, message: message(correction_node, count: count)) do |corrector|
|
120
|
+
autocorrect(corrector, *nodes, count)
|
119
121
|
end
|
120
122
|
end
|
121
123
|
|
122
|
-
def autocorrect(corrector, prev_def, node)
|
124
|
+
def autocorrect(corrector, prev_def, node, count)
|
123
125
|
# finds position of first newline
|
124
126
|
end_pos = end_loc(prev_def).end_pos
|
125
127
|
source_buffer = end_loc(prev_def).source_buffer
|
@@ -128,8 +130,6 @@ module RuboCop
|
|
128
130
|
# Handle the case when multiple one-liners are on the same line.
|
129
131
|
newline_pos = end_pos + 1 if newline_pos > node.source_range.begin_pos
|
130
132
|
|
131
|
-
count = blank_lines_count_between(prev_def, node)
|
132
|
-
|
133
133
|
if count > maximum_empty_lines
|
134
134
|
autocorrect_remove_lines(corrector, newline_pos, count)
|
135
135
|
else
|
@@ -157,14 +157,22 @@ module RuboCop
|
|
157
157
|
cop_config['EmptyLineBetweenModuleDefs'] && node.module_type?
|
158
158
|
end
|
159
159
|
|
160
|
-
def message(node)
|
161
|
-
type =
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
160
|
+
def message(node, count: nil)
|
161
|
+
type = node_type(node)
|
162
|
+
|
163
|
+
format(MSG,
|
164
|
+
type: type,
|
165
|
+
expected: expected_lines,
|
166
|
+
actual: count)
|
167
|
+
end
|
168
|
+
|
169
|
+
def expected_lines
|
170
|
+
if allowance_range?
|
171
|
+
"#{minimum_empty_lines..maximum_empty_lines} empty lines"
|
172
|
+
else
|
173
|
+
lines = maximum_empty_lines == 1 ? 'line' : 'lines'
|
174
|
+
"#{maximum_empty_lines} empty #{lines}"
|
175
|
+
end
|
168
176
|
end
|
169
177
|
|
170
178
|
def multiple_blank_lines_groups?(first_def_node, second_def_node)
|
@@ -176,8 +184,7 @@ module RuboCop
|
|
176
184
|
blank_start > non_blank_end
|
177
185
|
end
|
178
186
|
|
179
|
-
def
|
180
|
-
count = blank_lines_count_between(first_def_node, second_def_node)
|
187
|
+
def line_count_allowed?(count)
|
181
188
|
(minimum_empty_lines..maximum_empty_lines).cover?(count)
|
182
189
|
end
|
183
190
|
|
@@ -210,7 +217,7 @@ module RuboCop
|
|
210
217
|
end
|
211
218
|
|
212
219
|
def end_loc(node)
|
213
|
-
if node.def_type? && node.endless?
|
220
|
+
if (node.def_type? || node.defs_type?) && node.endless?
|
214
221
|
node.loc.expression.end
|
215
222
|
else
|
216
223
|
node.loc.end
|
@@ -230,6 +237,19 @@ module RuboCop
|
|
230
237
|
|
231
238
|
corrector.insert_after(where_to_insert, "\n" * difference)
|
232
239
|
end
|
240
|
+
|
241
|
+
def node_type(node)
|
242
|
+
case node.type
|
243
|
+
when :def, :defs
|
244
|
+
:method
|
245
|
+
else
|
246
|
+
node.type
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
def allowance_range?
|
251
|
+
minimum_empty_lines != maximum_empty_lines
|
252
|
+
end
|
233
253
|
end
|
234
254
|
end
|
235
255
|
end
|
@@ -4,11 +4,14 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module Layout
|
6
6
|
# This cop checks the indentation of the first argument in a method call.
|
7
|
-
# Arguments after the first one are checked by Layout/ArgumentAlignment
|
7
|
+
# Arguments after the first one are checked by `Layout/ArgumentAlignment`,
|
8
8
|
# not by this cop.
|
9
9
|
#
|
10
10
|
# For indenting the first parameter of method _definitions_, check out
|
11
|
-
# Layout/FirstParameterIndentation
|
11
|
+
# `Layout/FirstParameterIndentation`.
|
12
|
+
#
|
13
|
+
# This cop will respect `Layout/ArgumentAlignment` and will not work when
|
14
|
+
# `EnforcedStyle: with_fixed_indentation` is specified for `Layout/ArgumentAlignment`.
|
12
15
|
#
|
13
16
|
# @example
|
14
17
|
#
|
@@ -149,6 +152,7 @@ module RuboCop
|
|
149
152
|
MSG = 'Indent the first argument one step more than %<base>s.'
|
150
153
|
|
151
154
|
def on_send(node)
|
155
|
+
return if style != :consistent && enforce_first_argument_with_fixed_indentation?
|
152
156
|
return if !node.arguments? || node.operator_method?
|
153
157
|
|
154
158
|
indent = base_indentation(node) + configured_indentation_width
|
@@ -250,6 +254,16 @@ module RuboCop
|
|
250
254
|
def on_new_investigation
|
251
255
|
@comment_lines = nil
|
252
256
|
end
|
257
|
+
|
258
|
+
def enforce_first_argument_with_fixed_indentation?
|
259
|
+
return false unless argument_alignment_config['Enabled']
|
260
|
+
|
261
|
+
argument_alignment_config['EnforcedStyle'] == 'with_fixed_indentation'
|
262
|
+
end
|
263
|
+
|
264
|
+
def argument_alignment_config
|
265
|
+
config.for_cop('Layout/ArgumentAlignment')
|
266
|
+
end
|
253
267
|
end
|
254
268
|
end
|
255
269
|
end
|
@@ -60,12 +60,13 @@ module RuboCop
|
|
60
60
|
# }
|
61
61
|
class LineLength < Base
|
62
62
|
include CheckLineBreakable
|
63
|
-
include ConfigurableMax
|
64
63
|
include IgnoredPattern
|
65
64
|
include RangeHelp
|
66
65
|
include LineLengthHelp
|
67
66
|
extend AutoCorrector
|
68
67
|
|
68
|
+
exclude_limit 'Max'
|
69
|
+
|
69
70
|
MSG = 'Line is too long. [%<length>d/%<max>d]'
|
70
71
|
|
71
72
|
def on_block(node)
|
@@ -31,6 +31,32 @@ module RuboCop
|
|
31
31
|
# foo = if expression
|
32
32
|
# 'bar'
|
33
33
|
# end
|
34
|
+
#
|
35
|
+
# @example SupportedTypes: ['block', 'case', 'class', 'if', 'kwbegin', 'module'] (default)
|
36
|
+
# # good
|
37
|
+
# foo =
|
38
|
+
# if expression
|
39
|
+
# 'bar'
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# # good
|
43
|
+
# foo =
|
44
|
+
# [1].map do |i|
|
45
|
+
# i + 1
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# @example SupportedTypes: ['block']
|
49
|
+
# # good
|
50
|
+
# foo = if expression
|
51
|
+
# 'bar'
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
# # good
|
55
|
+
# foo =
|
56
|
+
# [1].map do |i|
|
57
|
+
# 'bar' * i
|
58
|
+
# end
|
59
|
+
#
|
34
60
|
class MultilineAssignmentLayout < Base
|
35
61
|
include CheckAssignment
|
36
62
|
include ConfigurableEnforcedStyle
|
@@ -16,14 +16,14 @@ module RuboCop
|
|
16
16
|
# if a +
|
17
17
|
# b
|
18
18
|
# something &&
|
19
|
-
#
|
19
|
+
# something_else
|
20
20
|
# end
|
21
21
|
#
|
22
22
|
# # good
|
23
23
|
# if a +
|
24
24
|
# b
|
25
25
|
# something &&
|
26
|
-
#
|
26
|
+
# something_else
|
27
27
|
# end
|
28
28
|
#
|
29
29
|
# @example EnforcedStyle: indented
|
@@ -6,10 +6,6 @@ module RuboCop
|
|
6
6
|
# Checks for space between the name of a receiver and a left
|
7
7
|
# brackets.
|
8
8
|
#
|
9
|
-
# This cop is marked as unsafe because it can occur false positives
|
10
|
-
# for `do_something [this_is_an_array_literal_argument]` that take
|
11
|
-
# an array without parentheses as an argument.
|
12
|
-
#
|
13
9
|
# @example
|
14
10
|
#
|
15
11
|
# # bad
|
@@ -25,28 +21,35 @@ module RuboCop
|
|
25
21
|
MSG = 'Remove the space before the opening brackets.'
|
26
22
|
|
27
23
|
def on_send(node)
|
28
|
-
return if node.parenthesized? || node.parent&.send_type?
|
29
24
|
return unless (first_argument = node.first_argument)
|
30
25
|
|
31
26
|
begin_pos = first_argument.source_range.begin_pos
|
32
|
-
|
33
|
-
return unless (range = offense_range(node, first_argument, begin_pos))
|
27
|
+
return unless (range = offense_range(node, begin_pos))
|
34
28
|
|
35
29
|
register_offense(range)
|
36
30
|
end
|
37
31
|
|
38
32
|
private
|
39
33
|
|
40
|
-
def offense_range(node,
|
41
|
-
if
|
42
|
-
|
34
|
+
def offense_range(node, begin_pos)
|
35
|
+
if reference_variable_with_brackets?(node)
|
36
|
+
receiver_end_pos = node.receiver.source_range.end_pos
|
37
|
+
selector_begin_pos = node.loc.selector.begin_pos
|
38
|
+
return if receiver_end_pos >= selector_begin_pos
|
39
|
+
|
40
|
+
range_between(receiver_end_pos, selector_begin_pos)
|
43
41
|
elsif node.method?(:[]=)
|
44
|
-
|
42
|
+
offense_range_for_assignment(node, begin_pos)
|
43
|
+
end
|
44
|
+
end
|
45
45
|
|
46
|
-
|
46
|
+
def offense_range_for_assignment(node, begin_pos)
|
47
|
+
end_pos = node.receiver.source_range.end_pos
|
47
48
|
|
48
|
-
|
49
|
-
|
49
|
+
return if begin_pos - end_pos == 1 ||
|
50
|
+
(range = range_between(end_pos, begin_pos - 1)).source.start_with?('[')
|
51
|
+
|
52
|
+
range
|
50
53
|
end
|
51
54
|
|
52
55
|
def register_offense(range)
|
@@ -55,8 +58,8 @@ module RuboCop
|
|
55
58
|
end
|
56
59
|
end
|
57
60
|
|
58
|
-
def
|
59
|
-
node.receiver
|
61
|
+
def reference_variable_with_brackets?(node)
|
62
|
+
node.receiver&.variable? && node.method?(:[]) && node.arguments.size == 1
|
60
63
|
end
|
61
64
|
end
|
62
65
|
end
|
@@ -3,8 +3,21 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Lint
|
6
|
-
# This cop checks for calls
|
7
|
-
#
|
6
|
+
# This cop checks for debug calls (such as `debugger` or `binding.pry`) that should
|
7
|
+
# not be kept for production code.
|
8
|
+
#
|
9
|
+
# The cop can be configured using `DebuggerMethods`. By default, a number of gems
|
10
|
+
# debug entrypoints are configured (`Kernel`, `Byebug`, `Capybara`, `Pry`, `Rails`,
|
11
|
+
# and `WebConsole`). Additional methods can be added.
|
12
|
+
#
|
13
|
+
# Specific default groups can be disabled if necessary:
|
14
|
+
#
|
15
|
+
# [source,yaml]
|
16
|
+
# ----
|
17
|
+
# Lint/Debugger:
|
18
|
+
# WebConsole: ~
|
19
|
+
# ---
|
20
|
+
#
|
8
21
|
#
|
9
22
|
# @example
|
10
23
|
#
|
@@ -33,14 +46,32 @@ module RuboCop
|
|
33
46
|
# def some_method
|
34
47
|
# do_something
|
35
48
|
# end
|
49
|
+
#
|
50
|
+
# @example DebuggerMethods: [my_debugger]
|
51
|
+
#
|
52
|
+
# # bad (ok during development)
|
53
|
+
#
|
54
|
+
# def some_method
|
55
|
+
# my_debugger
|
56
|
+
# end
|
36
57
|
class Debugger < Base
|
37
58
|
MSG = 'Remove debugger entry point `%<source>s`.'
|
38
59
|
|
39
60
|
RESTRICT_ON_SEND = [].freeze
|
40
61
|
|
62
|
+
def_node_matcher :kernel?, <<~PATTERN
|
63
|
+
(const {nil? cbase} :Kernel)
|
64
|
+
PATTERN
|
65
|
+
|
66
|
+
def_node_matcher :valid_receiver?, <<~PATTERN
|
67
|
+
{
|
68
|
+
(const {nil? cbase} %1)
|
69
|
+
(send {nil? #kernel?} %1)
|
70
|
+
}
|
71
|
+
PATTERN
|
72
|
+
|
41
73
|
def on_send(node)
|
42
|
-
return unless debugger_method?(node
|
43
|
-
return if !node.receiver.nil? && !debugger_receiver?(node)
|
74
|
+
return unless debugger_method?(node)
|
44
75
|
|
45
76
|
add_offense(node)
|
46
77
|
end
|
@@ -51,19 +82,32 @@ module RuboCop
|
|
51
82
|
format(MSG, source: node.source)
|
52
83
|
end
|
53
84
|
|
54
|
-
def
|
55
|
-
|
85
|
+
def debugger_methods
|
86
|
+
@debugger_methods ||= begin
|
87
|
+
config = cop_config.fetch('DebuggerMethods', [])
|
88
|
+
values = config.is_a?(Array) ? config : config.values.flatten
|
89
|
+
values.map do |v|
|
90
|
+
next unless v
|
91
|
+
|
92
|
+
*receiver, method_name = v.split('.')
|
93
|
+
{
|
94
|
+
receiver: receiver.empty? ? nil : receiver.join.to_sym,
|
95
|
+
method_name: method_name.to_sym
|
96
|
+
}
|
97
|
+
end.compact
|
98
|
+
end
|
56
99
|
end
|
57
100
|
|
58
|
-
def
|
59
|
-
|
60
|
-
|
61
|
-
node.receiver.method_name
|
62
|
-
when RuboCop::AST::ConstNode
|
63
|
-
node.receiver.const_name
|
64
|
-
end
|
101
|
+
def debugger_method?(send_node)
|
102
|
+
debugger_methods.any? do |method|
|
103
|
+
next unless method[:method_name] == send_node.method_name
|
65
104
|
|
66
|
-
|
105
|
+
if method[:receiver].nil?
|
106
|
+
send_node.receiver.nil?
|
107
|
+
else
|
108
|
+
valid_receiver?(send_node.receiver, method[:receiver])
|
109
|
+
end
|
110
|
+
end
|
67
111
|
end
|
68
112
|
end
|
69
113
|
end
|