rubocop 1.64.0 → 1.65.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 -2
- data/config/default.yml +11 -1
- data/lib/rubocop/config_loader.rb +1 -1
- data/lib/rubocop/config_loader_resolver.rb +9 -3
- data/lib/rubocop/cop/cop.rb +20 -2
- data/lib/rubocop/cop/force.rb +12 -0
- data/lib/rubocop/cop/gemspec/add_runtime_dependency.rb +38 -0
- data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +2 -2
- data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +3 -3
- data/lib/rubocop/cop/layout/case_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_after_multiline_condition.rb +1 -1
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +1 -1
- data/lib/rubocop/cop/layout/line_length.rb +20 -20
- data/lib/rubocop/cop/layout/space_around_operators.rb +3 -0
- data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +3 -4
- data/lib/rubocop/cop/legacy/corrector.rb +12 -2
- data/lib/rubocop/cop/lint/duplicate_case_condition.rb +1 -1
- data/lib/rubocop/cop/lint/empty_when.rb +1 -1
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +21 -14
- data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +14 -7
- data/lib/rubocop/cop/lint/literal_as_condition.rb +1 -1
- data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -1
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +2 -9
- data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -0
- data/lib/rubocop/cop/lint/void.rb +5 -0
- data/lib/rubocop/cop/metrics/block_nesting.rb +19 -7
- data/lib/rubocop/cop/mixin/alignment.rb +5 -1
- data/lib/rubocop/cop/mixin/allowed_methods.rb +7 -1
- data/lib/rubocop/cop/mixin/allowed_pattern.rb +15 -3
- data/lib/rubocop/cop/mixin/configurable_max.rb +5 -1
- data/lib/rubocop/cop/mixin/rescue_node.rb +4 -0
- data/lib/rubocop/cop/style/arguments_forwarding.rb +1 -1
- data/lib/rubocop/cop/style/copyright.rb +5 -2
- data/lib/rubocop/cop/style/documentation.rb +24 -24
- data/lib/rubocop/cop/style/hash_except.rb +8 -5
- data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +77 -43
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +5 -0
- data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
- data/lib/rubocop/cop/style/redundant_begin.rb +1 -1
- data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +1 -1
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +2 -1
- data/lib/rubocop/cop/style/send_with_literal_method_name.rb +23 -2
- data/lib/rubocop/cop/style/super_arguments.rb +52 -15
- data/lib/rubocop/cop/style/symbol_proc.rb +8 -1
- data/lib/rubocop/cop/style/zero_length_predicate.rb +28 -24
- data/lib/rubocop/cop/team.rb +10 -0
- data/lib/rubocop/cop/util.rb +7 -1
- data/lib/rubocop/cops_documentation_generator.rb +1 -1
- data/lib/rubocop/ext/regexp_parser.rb +4 -21
- data/lib/rubocop/formatter/html_formatter.rb +3 -1
- data/lib/rubocop/lsp/routes.rb +1 -1
- data/lib/rubocop/rspec/shared_contexts.rb +20 -0
- data/lib/rubocop/rspec/support.rb +1 -0
- data/lib/rubocop/server/cache.rb +10 -0
- data/lib/rubocop/server/client_command/exec.rb +2 -2
- data/lib/rubocop/server/client_command/start.rb +1 -1
- data/lib/rubocop/server/core.rb +4 -0
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +1 -0
- metadata +7 -6
@@ -3,12 +3,12 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Metrics
|
6
|
-
# Checks for excessive nesting of conditional and looping
|
7
|
-
# constructs.
|
6
|
+
# Checks for excessive nesting of conditional and looping constructs.
|
8
7
|
#
|
9
|
-
# You can configure if blocks are considered using the `CountBlocks`
|
10
|
-
#
|
11
|
-
# towards the nesting level. Set to `true` to
|
8
|
+
# You can configure if blocks are considered using the `CountBlocks` and `CountModifierForms`
|
9
|
+
# options. When both are set to `false` (the default) blocks and modifier forms are not
|
10
|
+
# counted towards the nesting level. Set them to `true` to include these in the nesting level
|
11
|
+
# calculation as well.
|
12
12
|
#
|
13
13
|
# The maximum level of nesting allowed is configurable.
|
14
14
|
class BlockNesting < Base
|
@@ -27,7 +27,7 @@ module RuboCop
|
|
27
27
|
|
28
28
|
def check_nesting_level(node, max, current_level)
|
29
29
|
if consider_node?(node)
|
30
|
-
current_level += 1
|
30
|
+
current_level += 1 if count_if_block?(node)
|
31
31
|
if current_level > max
|
32
32
|
self.max = current_level
|
33
33
|
unless part_of_ignored_node?(node)
|
@@ -41,6 +41,14 @@ module RuboCop
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
+
def count_if_block?(node)
|
45
|
+
return true unless node.if_type?
|
46
|
+
return false if node.elsif?
|
47
|
+
return count_modifier_forms? if node.modifier_form?
|
48
|
+
|
49
|
+
true
|
50
|
+
end
|
51
|
+
|
44
52
|
def consider_node?(node)
|
45
53
|
return true if NESTING_BLOCKS.include?(node.type)
|
46
54
|
|
@@ -52,7 +60,11 @@ module RuboCop
|
|
52
60
|
end
|
53
61
|
|
54
62
|
def count_blocks?
|
55
|
-
cop_config
|
63
|
+
cop_config.fetch('CountBlocks', false)
|
64
|
+
end
|
65
|
+
|
66
|
+
def count_modifier_forms?
|
67
|
+
cop_config.fetch('CountModifierForms', false)
|
56
68
|
end
|
57
69
|
end
|
58
70
|
end
|
@@ -65,8 +65,12 @@ module RuboCop
|
|
65
65
|
inner.begin_pos >= outer.begin_pos && inner.end_pos <= outer.end_pos
|
66
66
|
end
|
67
67
|
|
68
|
-
# @deprecated Use processed_source.
|
68
|
+
# @deprecated Use processed_source.line_with_comment?(line)
|
69
69
|
def end_of_line_comment(line)
|
70
|
+
warn Rainbow(<<~WARNING).yellow, uplevel: 1
|
71
|
+
`end_of_line_comment` is deprecated. Use `processed_source.line_with_comment?` instead.
|
72
|
+
WARNING
|
73
|
+
|
70
74
|
processed_source.line_with_comment?(line)
|
71
75
|
end
|
72
76
|
|
@@ -15,7 +15,13 @@ module RuboCop
|
|
15
15
|
end
|
16
16
|
|
17
17
|
# @deprecated Use allowed_method? instead
|
18
|
-
|
18
|
+
def ignored_method?
|
19
|
+
warn Rainbow(<<~WARNING).yellow, uplevel: 1
|
20
|
+
`ignored_method?` is deprecated. Use `allowed_method?` instead.
|
21
|
+
WARNING
|
22
|
+
|
23
|
+
allowed_method?
|
24
|
+
end
|
19
25
|
|
20
26
|
# @api public
|
21
27
|
def allowed_methods
|
@@ -18,14 +18,26 @@ module RuboCop
|
|
18
18
|
end
|
19
19
|
|
20
20
|
# @deprecated Use allowed_line? instead
|
21
|
-
|
21
|
+
def ignored_line?
|
22
|
+
warn Rainbow(<<~WARNING).yellow, uplevel: 1
|
23
|
+
`ignored_line?` is deprecated. Use `allowed_line?` instead.
|
24
|
+
WARNING
|
25
|
+
|
26
|
+
allowed_line?
|
27
|
+
end
|
22
28
|
|
23
29
|
def matches_allowed_pattern?(line)
|
24
30
|
allowed_patterns.any? { |pattern| Regexp.new(pattern).match?(line) }
|
25
31
|
end
|
26
32
|
|
27
|
-
# @deprecated Use matches_allowed_pattern
|
28
|
-
|
33
|
+
# @deprecated Use matches_allowed_pattern? instead
|
34
|
+
def matches_ignored_pattern?
|
35
|
+
warn Rainbow(<<~WARNING).yellow, uplevel: 1
|
36
|
+
`matches_ignored_pattern?` is deprecated. Use `matches_allowed_pattern?` instead.
|
37
|
+
WARNING
|
38
|
+
|
39
|
+
matches_allowed_pattern?
|
40
|
+
end
|
29
41
|
|
30
42
|
def allowed_patterns
|
31
43
|
# Since there could be a pattern specified in the default config, merge the two
|
@@ -4,11 +4,15 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
# Handles `Max` configuration parameters, especially setting them to an
|
6
6
|
# appropriate value with --auto-gen-config.
|
7
|
-
# @deprecated Use `exclude_limit ParameterName
|
7
|
+
# @deprecated Use `exclude_limit <ParameterName>` instead.
|
8
8
|
module ConfigurableMax
|
9
9
|
private
|
10
10
|
|
11
11
|
def max=(value)
|
12
|
+
warn Rainbow(<<~WARNING).yellow, uplevel: 1
|
13
|
+
`max=` is deprecated. Use `exclude_limit <ParameterName>` instead.
|
14
|
+
WARNING
|
15
|
+
|
12
16
|
cfg = config_to_allow_offenses
|
13
17
|
cfg[:exclude_limit] ||= {}
|
14
18
|
current_max = cfg[:exclude_limit][max_parameter_name]
|
@@ -18,6 +18,10 @@ module RuboCop
|
|
18
18
|
|
19
19
|
# @deprecated Use ResbodyNode#exceptions instead
|
20
20
|
def rescued_exceptions(resbody)
|
21
|
+
warn Rainbow(<<~WARNING).yellow, uplevel: 1
|
22
|
+
`rescued_exceptions` is deprecated. Use `ResbodyNode#exceptions` instead.
|
23
|
+
WARNING
|
24
|
+
|
21
25
|
rescue_group, = *resbody
|
22
26
|
if rescue_group
|
23
27
|
rescue_group.values
|
@@ -148,7 +148,7 @@ module RuboCop
|
|
148
148
|
|
149
149
|
restarg, kwrestarg, blockarg = extract_forwardable_args(node.arguments)
|
150
150
|
forwardable_args = redundant_forwardable_named_args(restarg, kwrestarg, blockarg)
|
151
|
-
send_nodes = node.each_descendant(:send, :csend, :super).to_a
|
151
|
+
send_nodes = node.each_descendant(:send, :csend, :super, :yield).to_a
|
152
152
|
|
153
153
|
send_classifications = classify_send_nodes(
|
154
154
|
node, send_nodes, non_splat_or_block_pass_lvar_references(node.body), forwardable_args
|
@@ -58,12 +58,15 @@ module RuboCop
|
|
58
58
|
end
|
59
59
|
|
60
60
|
def verify_autocorrect_notice!
|
61
|
-
|
61
|
+
if autocorrect_notice.nil? || autocorrect_notice.empty?
|
62
|
+
raise Warning, "#{cop_name}: #{AUTOCORRECT_EMPTY_WARNING}"
|
63
|
+
end
|
62
64
|
|
63
65
|
regex = Regexp.new(notice)
|
64
66
|
return if autocorrect_notice.gsub(/^# */, '').match?(regex)
|
65
67
|
|
66
|
-
|
68
|
+
message = "AutocorrectNotice '#{autocorrect_notice}' must match Notice /#{notice}/"
|
69
|
+
raise Warning, "#{cop_name}: #{message}"
|
67
70
|
end
|
68
71
|
|
69
72
|
def insert_notice_before(processed_source)
|
@@ -29,36 +29,36 @@ module RuboCop
|
|
29
29
|
# end
|
30
30
|
#
|
31
31
|
# # allowed
|
32
|
-
#
|
32
|
+
# # Class without body
|
33
|
+
# class Person
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# # Namespace - A namespace can be a class or a module
|
37
|
+
# # Containing a class
|
38
|
+
# module Namespace
|
39
|
+
# # Description/Explanation of Person class
|
33
40
|
# class Person
|
41
|
+
# # ...
|
34
42
|
# end
|
43
|
+
# end
|
35
44
|
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
# # Description/Explanation of Person class
|
40
|
-
# class Person
|
41
|
-
# # ...
|
42
|
-
# end
|
45
|
+
# # Containing constant visibility declaration
|
46
|
+
# module Namespace
|
47
|
+
# class Private
|
43
48
|
# end
|
44
49
|
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
# class Private
|
48
|
-
# end
|
49
|
-
#
|
50
|
-
# private_constant :Private
|
51
|
-
# end
|
50
|
+
# private_constant :Private
|
51
|
+
# end
|
52
52
|
#
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
56
|
-
#
|
53
|
+
# # Containing constant definition
|
54
|
+
# module Namespace
|
55
|
+
# Public = Class.new
|
56
|
+
# end
|
57
57
|
#
|
58
|
-
#
|
59
|
-
#
|
60
|
-
#
|
61
|
-
#
|
58
|
+
# # Macro calls
|
59
|
+
# module Namespace
|
60
|
+
# extend Foo
|
61
|
+
# end
|
62
62
|
#
|
63
63
|
# @example AllowedConstants: ['ClassMethods']
|
64
64
|
#
|
@@ -67,7 +67,7 @@ module RuboCop
|
|
67
67
|
# module ClassMethods
|
68
68
|
# # ...
|
69
69
|
# end
|
70
|
-
#
|
70
|
+
# end
|
71
71
|
#
|
72
72
|
class Documentation < Base
|
73
73
|
include DocumentationComment
|
@@ -23,9 +23,9 @@ module RuboCop
|
|
23
23
|
# {foo: 1, bar: 2, baz: 3}.reject {|k, v| k == :bar }
|
24
24
|
# {foo: 1, bar: 2, baz: 3}.select {|k, v| k != :bar }
|
25
25
|
# {foo: 1, bar: 2, baz: 3}.filter {|k, v| k != :bar }
|
26
|
-
# {foo: 1, bar: 2, baz: 3}.reject {|k, v| %i[
|
27
|
-
# {foo: 1, bar: 2, baz: 3}.select {|k, v| !%i[
|
28
|
-
# {foo: 1, bar: 2, baz: 3}.filter {|k, v| !%i[
|
26
|
+
# {foo: 1, bar: 2, baz: 3}.reject {|k, v| %i[bar].include?(k) }
|
27
|
+
# {foo: 1, bar: 2, baz: 3}.select {|k, v| !%i[bar].include?(k) }
|
28
|
+
# {foo: 1, bar: 2, baz: 3}.filter {|k, v| !%i[bar].include?(k) }
|
29
29
|
#
|
30
30
|
# # good
|
31
31
|
# {foo: 1, bar: 2, baz: 3}.except(:bar)
|
@@ -73,8 +73,9 @@ module RuboCop
|
|
73
73
|
PATTERN
|
74
74
|
|
75
75
|
def on_send(node)
|
76
|
+
method_name = node.method_name
|
76
77
|
block = node.parent
|
77
|
-
return unless bad_method?(block) && semantically_except_method?(node, block)
|
78
|
+
return unless bad_method?(method_name, block) && semantically_except_method?(node, block)
|
78
79
|
|
79
80
|
except_key = except_key(block)
|
80
81
|
return if except_key.nil? || !safe_to_register_offense?(block, except_key)
|
@@ -91,7 +92,7 @@ module RuboCop
|
|
91
92
|
private
|
92
93
|
|
93
94
|
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
94
|
-
def bad_method?(block)
|
95
|
+
def bad_method?(method_name, block)
|
95
96
|
if active_support_extensions_enabled?
|
96
97
|
bad_method_with_active_support?(block) do |key_arg, send_node|
|
97
98
|
if send_node.method?(:in?) && send_node.receiver&.source != key_arg.source
|
@@ -103,6 +104,8 @@ module RuboCop
|
|
103
104
|
end
|
104
105
|
else
|
105
106
|
bad_method_with_poro?(block) do |key_arg, send_node|
|
107
|
+
return false if method_name == :reject && block.body.method?(:!)
|
108
|
+
|
106
109
|
!send_node.method?(:include?) || send_node.first_argument&.source == key_arg.source
|
107
110
|
end
|
108
111
|
end
|
@@ -4,6 +4,7 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
6
|
# Prefer `select` or `reject` over `map { ... }.compact`.
|
7
|
+
# This cop also handles `filter_map { ... }`, similar to `map { ... }.compact`.
|
7
8
|
#
|
8
9
|
# @example
|
9
10
|
#
|
@@ -11,6 +12,9 @@ module RuboCop
|
|
11
12
|
# array.map { |e| some_condition? ? e : next }.compact
|
12
13
|
#
|
13
14
|
# # bad
|
15
|
+
# array.filter_map { |e| some_condition? ? e : next }
|
16
|
+
#
|
17
|
+
# # bad
|
14
18
|
# array.map do |e|
|
15
19
|
# if some_condition?
|
16
20
|
# e
|
@@ -40,55 +44,73 @@ module RuboCop
|
|
40
44
|
class MapCompactWithConditionalBlock < Base
|
41
45
|
extend AutoCorrector
|
42
46
|
|
43
|
-
MSG = 'Replace `
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
47
|
+
MSG = 'Replace `%<current>s` with `%<method>s`.'
|
48
|
+
RESTRICT_ON_SEND = %i[compact filter_map].freeze
|
49
|
+
|
50
|
+
# @!method conditional_block(node)
|
51
|
+
def_node_matcher :conditional_block, <<~RUBY
|
52
|
+
(block
|
53
|
+
(call _ {:map :filter_map})
|
54
|
+
(args
|
55
|
+
$(arg _))
|
56
|
+
{
|
57
|
+
(if $_ $(lvar _) {next nil?})
|
58
|
+
(if $_ {next nil?} $(lvar _))
|
59
|
+
(if $_ (next $(lvar _)) {next nil nil?})
|
60
|
+
(if $_ {next nil nil?} (next $(lvar _)))
|
61
|
+
(begin
|
62
|
+
{
|
63
|
+
(if $_ next nil?)
|
64
|
+
(if $_ nil? next)
|
65
|
+
}
|
66
|
+
$(lvar _))
|
67
|
+
(begin
|
68
|
+
{
|
69
|
+
(if $_ (next $(lvar _)) nil?)
|
70
|
+
(if $_ nil? (next $(lvar _)))
|
71
|
+
}
|
72
|
+
(nil))
|
73
|
+
})
|
70
74
|
RUBY
|
71
75
|
|
72
76
|
def on_send(node)
|
73
|
-
|
74
|
-
|
75
|
-
return
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
)
|
85
|
-
end
|
77
|
+
map_candidate = node.children.first
|
78
|
+
if (block_argument, condition, return_value = conditional_block(map_candidate))
|
79
|
+
return unless node.method?(:compact) && node.arguments.empty?
|
80
|
+
|
81
|
+
range = map_with_compact_range(node)
|
82
|
+
elsif (block_argument, condition, return_value = conditional_block(node.parent))
|
83
|
+
return unless node.method?(:filter_map)
|
84
|
+
|
85
|
+
range = filter_map_range(node)
|
86
|
+
else
|
87
|
+
return
|
86
88
|
end
|
89
|
+
|
90
|
+
inspect(node, block_argument, condition, return_value, range)
|
87
91
|
end
|
88
92
|
alias on_csend on_send
|
89
93
|
|
90
94
|
private
|
91
95
|
|
96
|
+
def inspect(node, block_argument_node, condition_node, return_value_node, range)
|
97
|
+
return unless returns_block_argument?(block_argument_node, return_value_node)
|
98
|
+
return if condition_node.parent.elsif?
|
99
|
+
|
100
|
+
method = truthy_branch?(return_value_node) ? 'select' : 'reject'
|
101
|
+
current = current(node)
|
102
|
+
|
103
|
+
add_offense(range, message: format(MSG, current: current, method: method)) do |corrector|
|
104
|
+
return if part_of_ignored_node?(node) || ignored_node?(node)
|
105
|
+
|
106
|
+
corrector.replace(
|
107
|
+
range, "#{method} { |#{block_argument_node.source}| #{condition_node.source} }"
|
108
|
+
)
|
109
|
+
|
110
|
+
ignore_node(node)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
92
114
|
def returns_block_argument?(block_argument_node, return_value_node)
|
93
115
|
block_argument_node.name == return_value_node.children.first
|
94
116
|
end
|
@@ -123,10 +145,22 @@ module RuboCop
|
|
123
145
|
end
|
124
146
|
end
|
125
147
|
|
126
|
-
def
|
127
|
-
|
148
|
+
def current(node)
|
149
|
+
if node.method?(:compact)
|
150
|
+
map_or_filter_map_method = node.children.first
|
151
|
+
|
152
|
+
"#{map_or_filter_map_method.method_name} { ... }.compact"
|
153
|
+
else
|
154
|
+
'filter_map { ... }'
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def map_with_compact_range(node)
|
159
|
+
node.receiver.send_node.loc.selector.begin.join(node.source_range.end)
|
160
|
+
end
|
128
161
|
|
129
|
-
|
162
|
+
def filter_map_range(node)
|
163
|
+
node.loc.selector.join(node.parent.source_range.end)
|
130
164
|
end
|
131
165
|
end
|
132
166
|
end
|
@@ -18,6 +18,7 @@ module RuboCop
|
|
18
18
|
return if inside_endless_method_def?(node)
|
19
19
|
return if require_parentheses_for_hash_value_omission?(node)
|
20
20
|
return if syntax_like_method_call?(node)
|
21
|
+
return if method_call_before_constant_resolution?(node)
|
21
22
|
return if super_call_without_arguments?(node)
|
22
23
|
return if legitimate_call_with_parentheses?(node)
|
23
24
|
return if allowed_camel_case_method_call?(node)
|
@@ -63,6 +64,10 @@ module RuboCop
|
|
63
64
|
node.implicit_call? || node.operator_method?
|
64
65
|
end
|
65
66
|
|
67
|
+
def method_call_before_constant_resolution?(node)
|
68
|
+
node.parent&.const_type?
|
69
|
+
end
|
70
|
+
|
66
71
|
def super_call_without_arguments?(node)
|
67
72
|
node.super_type? && node.arguments.none?
|
68
73
|
end
|
@@ -9,7 +9,7 @@ module RuboCop
|
|
9
9
|
#
|
10
10
|
# String interpolation is always kept in double quotes.
|
11
11
|
#
|
12
|
-
#
|
12
|
+
# NOTE: `Lint/SymbolConversion` can be used in parallel to ensure that symbols
|
13
13
|
# are not quoted that don't need to be. This cop is for configuring the quoting
|
14
14
|
# style to use for symbols that require quotes.
|
15
15
|
#
|
@@ -6,7 +6,7 @@ module RuboCop
|
|
6
6
|
# Checks for the presence of superfluous `.rb` extension in
|
7
7
|
# the filename provided to `require` and `require_relative`.
|
8
8
|
#
|
9
|
-
#
|
9
|
+
# NOTE: If the extension is omitted, Ruby tries adding '.rb', '.so',
|
10
10
|
# and so on to the name until found. If the file named cannot be found,
|
11
11
|
# a `LoadError` will be raised.
|
12
12
|
# There is an edge case where `foo.so` file is loaded instead of a `LoadError`
|
@@ -74,6 +74,7 @@ module RuboCop
|
|
74
74
|
kFALSE kNIL kSELF kTRUE tCONSTANT tCVAR tFLOAT tGVAR tIDENTIFIER tINTEGER tIVAR
|
75
75
|
tLBRACK tLCURLY tLPAREN_ARG tSTRING tSTRING_BEG tSYMBOL tXSTRING_BEG
|
76
76
|
].freeze
|
77
|
+
ARGUMENT_TAKING_FLOW_TOKEN_TYPES = %i[tIDENTIFIER kRETURN kBREAK kNEXT kYIELD].freeze
|
77
78
|
|
78
79
|
def on_new_investigation
|
79
80
|
return unless processed_source.ast
|
@@ -137,7 +138,7 @@ module RuboCop
|
|
137
138
|
# do_something \
|
138
139
|
# argument
|
139
140
|
def method_with_argument?(current_token, next_token)
|
140
|
-
return false
|
141
|
+
return false unless ARGUMENT_TAKING_FLOW_TOKEN_TYPES.include?(current_token.type)
|
141
142
|
|
142
143
|
ARGUMENT_TYPES.include?(next_token.type)
|
143
144
|
end
|
@@ -7,6 +7,20 @@ module RuboCop
|
|
7
7
|
# Since the `send` method can be used to call private methods, by default,
|
8
8
|
# only the `public_send` method is detected.
|
9
9
|
#
|
10
|
+
# NOTE: Writer methods with names ending in `=` are always permitted because their
|
11
|
+
# behavior differs as follows:
|
12
|
+
#
|
13
|
+
# [source,ruby]
|
14
|
+
# ----
|
15
|
+
# def foo=(foo)
|
16
|
+
# @foo = foo
|
17
|
+
# 42
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# self.foo = 1 # => 1
|
21
|
+
# send(:foo=, 1) # => 42
|
22
|
+
# ----
|
23
|
+
#
|
10
24
|
# @safety
|
11
25
|
# This cop is not safe because it can incorrectly detect based on the receiver.
|
12
26
|
# Additionally, when `AllowSend` is set to `true`, it cannot determine whether
|
@@ -43,8 +57,14 @@ module RuboCop
|
|
43
57
|
MSG = 'Use `%<method_name>s` method call directly instead.'
|
44
58
|
RESTRICT_ON_SEND = %i[public_send send __send__].freeze
|
45
59
|
STATIC_METHOD_NAME_NODE_TYPES = %i[sym str].freeze
|
60
|
+
METHOD_NAME_PATTERN = /\A[a-zA-Z_][a-zA-Z0-9_]*[!?]?\z/.freeze
|
61
|
+
RESERVED_WORDS = %i[
|
62
|
+
BEGIN END alias and begin break case class def defined? do else elsif end ensure
|
63
|
+
false for if in module next nil not or redo rescue retry return self super then true
|
64
|
+
undef unless until when while yield
|
65
|
+
].freeze
|
46
66
|
|
47
|
-
# rubocop:disable Metrics/AbcSize
|
67
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
48
68
|
def on_send(node)
|
49
69
|
return if allow_send? && !node.method?(:public_send)
|
50
70
|
return unless (first_argument = node.first_argument)
|
@@ -52,6 +72,7 @@ module RuboCop
|
|
52
72
|
|
53
73
|
offense_range = offense_range(node)
|
54
74
|
method_name = first_argument.value
|
75
|
+
return if !METHOD_NAME_PATTERN.match?(method_name) || RESERVED_WORDS.include?(method_name)
|
55
76
|
|
56
77
|
add_offense(offense_range, message: format(MSG, method_name: method_name)) do |corrector|
|
57
78
|
if node.arguments.one?
|
@@ -62,7 +83,7 @@ module RuboCop
|
|
62
83
|
end
|
63
84
|
end
|
64
85
|
end
|
65
|
-
# rubocop:enable Metrics/AbcSize
|
86
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
66
87
|
|
67
88
|
private
|
68
89
|
|