rubocop 1.57.1 → 1.58.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 +2 -2
- data/config/default.yml +37 -2
- data/lib/rubocop/cli/command/auto_generate_config.rb +10 -5
- data/lib/rubocop/config_obsoletion.rb +11 -8
- data/lib/rubocop/cop/bundler/gem_comment.rb +2 -2
- data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +2 -2
- data/lib/rubocop/cop/internal_affairs/method_name_equal.rb +19 -20
- data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +53 -0
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +2 -2
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/end_alignment.rb +7 -1
- data/lib/rubocop/cop/layout/extra_spacing.rb +4 -10
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +6 -6
- data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +4 -4
- data/lib/rubocop/cop/layout/single_line_block_chain.rb +4 -0
- data/lib/rubocop/cop/layout/space_around_operators.rb +50 -20
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +4 -4
- data/lib/rubocop/cop/lint/debugger.rb +2 -1
- data/lib/rubocop/cop/lint/duplicate_methods.rb +1 -1
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +3 -3
- data/lib/rubocop/cop/lint/float_comparison.rb +10 -0
- data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +64 -0
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -5
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +43 -0
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +3 -4
- data/lib/rubocop/cop/lint/self_assignment.rb +37 -0
- data/lib/rubocop/cop/lint/symbol_conversion.rb +7 -2
- data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +1 -1
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +2 -2
- data/lib/rubocop/cop/lint/void.rb +43 -12
- data/lib/rubocop/cop/metrics/class_length.rb +6 -1
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
- data/lib/rubocop/cop/mixin/comments_help.rb +16 -12
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +14 -11
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +1 -1
- data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
- data/lib/rubocop/cop/naming/block_forwarding.rb +2 -2
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -1
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +2 -2
- data/lib/rubocop/cop/style/accessor_grouping.rb +1 -1
- data/lib/rubocop/cop/style/arguments_forwarding.rb +68 -6
- data/lib/rubocop/cop/style/array_first_last.rb +64 -0
- data/lib/rubocop/cop/style/auto_resource_cleanup.rb +21 -14
- data/lib/rubocop/cop/style/bisected_attr_accessor.rb +2 -2
- data/lib/rubocop/cop/style/case_like_if.rb +4 -4
- data/lib/rubocop/cop/style/combinable_loops.rb +2 -7
- data/lib/rubocop/cop/style/conditional_assignment.rb +1 -1
- data/lib/rubocop/cop/style/empty_literal.rb +1 -1
- data/lib/rubocop/cop/style/eval_with_location.rb +3 -3
- data/lib/rubocop/cop/style/explicit_block_argument.rb +2 -2
- data/lib/rubocop/cop/style/hash_each_methods.rb +58 -10
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +9 -1
- data/lib/rubocop/cop/style/inverse_methods.rb +6 -5
- data/lib/rubocop/cop/style/map_to_hash.rb +9 -4
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/missing_respond_to_missing.rb +2 -2
- data/lib/rubocop/cop/style/redundant_argument.rb +2 -2
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +17 -10
- data/lib/rubocop/cop/style/redundant_filter_chain.rb +4 -3
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +2 -0
- data/lib/rubocop/cop/style/redundant_parentheses.rb +28 -12
- data/lib/rubocop/cop/style/redundant_return.rb +1 -1
- data/lib/rubocop/cop/style/redundant_sort.rb +1 -1
- data/lib/rubocop/cop/style/redundant_string_escape.rb +1 -1
- data/lib/rubocop/cop/style/select_by_regexp.rb +1 -1
- data/lib/rubocop/cop/style/self_assignment.rb +1 -1
- data/lib/rubocop/cop/style/semicolon.rb +8 -0
- data/lib/rubocop/cop/style/single_argument_dig.rb +2 -1
- data/lib/rubocop/cop/style/single_line_do_end_block.rb +3 -1
- data/lib/rubocop/cop/style/slicing_with_range.rb +1 -1
- data/lib/rubocop/cop/style/super_with_args_parentheses.rb +35 -0
- data/lib/rubocop/formatter/html_formatter.rb +5 -4
- data/lib/rubocop/result_cache.rb +0 -1
- data/lib/rubocop/runner.rb +1 -1
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +3 -0
- metadata +13 -23
@@ -17,10 +17,16 @@ module RuboCop
|
|
17
17
|
# @example
|
18
18
|
# # bad
|
19
19
|
# hash.keys.each { |k| p k }
|
20
|
-
# hash.
|
20
|
+
# hash.each { |k, unused_value| p k }
|
21
21
|
#
|
22
22
|
# # good
|
23
23
|
# hash.each_key { |k| p k }
|
24
|
+
#
|
25
|
+
# # bad
|
26
|
+
# hash.values.each { |v| p v }
|
27
|
+
# hash.each { |unused_key, v| p v }
|
28
|
+
#
|
29
|
+
# # good
|
24
30
|
# hash.each_value { |v| p v }
|
25
31
|
#
|
26
32
|
# @example AllowedReceivers: ['execute']
|
@@ -33,22 +39,44 @@ module RuboCop
|
|
33
39
|
extend AutoCorrector
|
34
40
|
|
35
41
|
MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
|
42
|
+
UNUSED_BLOCK_ARG_MSG = "#{MSG.chop} and remove the unused `%<unused_code>s` block argument."
|
36
43
|
|
37
44
|
# @!method kv_each(node)
|
38
45
|
def_node_matcher :kv_each, <<~PATTERN
|
39
|
-
({block numblock} $(
|
46
|
+
({block numblock} $(call (call _ ${:keys :values}) :each) ...)
|
47
|
+
PATTERN
|
48
|
+
|
49
|
+
# @!method each_arguments(node)
|
50
|
+
def_node_matcher :each_arguments, <<~PATTERN
|
51
|
+
(block (call _ :each)(args $_key $_value) ...)
|
40
52
|
PATTERN
|
41
53
|
|
42
54
|
# @!method kv_each_with_block_pass(node)
|
43
55
|
def_node_matcher :kv_each_with_block_pass, <<~PATTERN
|
44
|
-
(
|
56
|
+
(call $(call _ ${:keys :values}) :each (block_pass (sym _)))
|
45
57
|
PATTERN
|
46
58
|
|
59
|
+
# rubocop:disable Metrics/AbcSize
|
47
60
|
def on_block(node)
|
48
61
|
kv_each(node) do |target, method|
|
49
|
-
register_kv_offense(target, method)
|
62
|
+
register_kv_offense(target, method) and return
|
63
|
+
end
|
64
|
+
|
65
|
+
return unless (key, value = each_arguments(node))
|
66
|
+
|
67
|
+
if unused_block_arg_exist?(node, value.source)
|
68
|
+
message = message('each_key', node.method_name, value.source)
|
69
|
+
unused_range = key.source_range.end.join(value.source_range.end)
|
70
|
+
|
71
|
+
register_each_args_offense(node, message, 'each_key', unused_range)
|
72
|
+
elsif unused_block_arg_exist?(node, key.source)
|
73
|
+
message = message('each_value', node.method_name, key.source)
|
74
|
+
unused_range = key.source_range.begin.join(value.source_range.begin)
|
75
|
+
|
76
|
+
register_each_args_offense(node, message, 'each_value', unused_range)
|
50
77
|
end
|
51
78
|
end
|
79
|
+
# rubocop:enable Metrics/AbcSize
|
52
80
|
|
53
81
|
alias on_numblock on_block
|
54
82
|
|
@@ -64,23 +92,43 @@ module RuboCop
|
|
64
92
|
return unless (parent_receiver = target.receiver.receiver)
|
65
93
|
return if allowed_receiver?(parent_receiver)
|
66
94
|
|
67
|
-
|
95
|
+
current = target.receiver.loc.selector.join(target.source_range.end).source
|
96
|
+
|
97
|
+
add_offense(kv_range(target), message: format_message(method, current)) do |corrector|
|
68
98
|
correct_key_value_each(target, corrector)
|
69
99
|
end
|
70
100
|
end
|
71
101
|
|
102
|
+
def unused_block_arg_exist?(node, block_arg_source)
|
103
|
+
node.body.each_descendant(:lvar).map(&:source).none?(block_arg_source)
|
104
|
+
end
|
105
|
+
|
106
|
+
def message(prefer, method_name, unused_code)
|
107
|
+
format(
|
108
|
+
UNUSED_BLOCK_ARG_MSG, prefer: prefer, current: method_name, unused_code: unused_code
|
109
|
+
)
|
110
|
+
end
|
111
|
+
|
112
|
+
def register_each_args_offense(node, message, prefer, unused_range)
|
113
|
+
add_offense(node, message: message) do |corrector|
|
114
|
+
corrector.replace(node.send_node.loc.selector, prefer)
|
115
|
+
corrector.remove(unused_range)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
72
119
|
def register_kv_with_block_pass_offense(node, target, method)
|
73
120
|
return unless (parent_receiver = node.parent.receiver.receiver)
|
74
121
|
return if allowed_receiver?(parent_receiver)
|
75
122
|
|
76
|
-
range = target.loc.selector.
|
77
|
-
|
123
|
+
range = target.loc.selector.join(node.parent.loc.selector.end)
|
124
|
+
|
125
|
+
add_offense(range, message: format_message(method, range.source)) do |corrector|
|
78
126
|
corrector.replace(range, "each_#{method[0..-2]}")
|
79
127
|
end
|
80
128
|
end
|
81
129
|
|
82
|
-
def format_message(method_name)
|
83
|
-
format(MSG, prefer: "each_#{method_name[0..-2]}", current:
|
130
|
+
def format_message(method_name, current)
|
131
|
+
format(MSG, prefer: "each_#{method_name[0..-2]}", current: current)
|
84
132
|
end
|
85
133
|
|
86
134
|
def check_argument(variable)
|
@@ -103,7 +151,7 @@ module RuboCop
|
|
103
151
|
name = "each_#{node.receiver.method_name.to_s.chop}"
|
104
152
|
return correct_implicit(node, corrector, name) unless receiver
|
105
153
|
|
106
|
-
new_source = receiver.source + "
|
154
|
+
new_source = receiver.source + "#{node.loc.dot.source}#{name}"
|
107
155
|
corrector.replace(node, new_source)
|
108
156
|
end
|
109
157
|
|
@@ -153,7 +153,15 @@ module RuboCop
|
|
153
153
|
return unless duplicated_expressions?(node, heads)
|
154
154
|
|
155
155
|
condition_variable = assignable_condition_value(node)
|
156
|
-
|
156
|
+
|
157
|
+
head = heads.first
|
158
|
+
if head.assignment?
|
159
|
+
# The `send` node is used instead of the `indexasgn` node, so `name` cannot be used.
|
160
|
+
# https://github.com/rubocop/rubocop-ast/blob/v1.29.0/lib/rubocop/ast/node/indexasgn_node.rb
|
161
|
+
assigned_value = head.send_type? ? head.receiver.source : head.name.to_s
|
162
|
+
|
163
|
+
return if condition_variable == assigned_value
|
164
|
+
end
|
157
165
|
|
158
166
|
check_expressions(node, heads, :before_condition)
|
159
167
|
end
|
@@ -60,17 +60,17 @@ module RuboCop
|
|
60
60
|
# @!method inverse_candidate?(node)
|
61
61
|
def_node_matcher :inverse_candidate?, <<~PATTERN
|
62
62
|
{
|
63
|
-
(send $(
|
64
|
-
(send ({block numblock} $(
|
65
|
-
(send (begin $(
|
63
|
+
(send $(call $(...) $_ $...) :!)
|
64
|
+
(send ({block numblock} $(call $(...) $_) $...) :!)
|
65
|
+
(send (begin $(call $(...) $_ $...)) :!)
|
66
66
|
}
|
67
67
|
PATTERN
|
68
68
|
|
69
69
|
# @!method inverse_block?(node)
|
70
70
|
def_node_matcher :inverse_block?, <<~PATTERN
|
71
|
-
({block numblock} $(
|
71
|
+
({block numblock} $(call (...) $_) ... { $(call ... :!)
|
72
72
|
$(send (...) {:!= :!~} ...)
|
73
|
-
(begin ... $(
|
73
|
+
(begin ... $(call ... :!))
|
74
74
|
(begin ... $(send (...) {:!= :!~} ...))
|
75
75
|
})
|
76
76
|
PATTERN
|
@@ -87,6 +87,7 @@ module RuboCop
|
|
87
87
|
end
|
88
88
|
end
|
89
89
|
end
|
90
|
+
alias on_csend on_send
|
90
91
|
|
91
92
|
def on_block(node)
|
92
93
|
inverse_block?(node) do |_method_call, method, block|
|
@@ -34,21 +34,25 @@ module RuboCop
|
|
34
34
|
|
35
35
|
minimum_target_ruby_version 2.6
|
36
36
|
|
37
|
-
MSG = 'Pass a block to `to_h` instead of calling `%<method>s
|
37
|
+
MSG = 'Pass a block to `to_h` instead of calling `%<method>s%<dot>sto_h`.'
|
38
38
|
RESTRICT_ON_SEND = %i[to_h].freeze
|
39
39
|
|
40
40
|
# @!method map_to_h?(node)
|
41
41
|
def_node_matcher :map_to_h?, <<~PATTERN
|
42
42
|
{
|
43
|
-
$(
|
44
|
-
$(
|
43
|
+
$(call ({block numblock} $(call _ {:map :collect}) ...) :to_h)
|
44
|
+
$(call $(call _ {:map :collect} (block_pass sym)) :to_h)
|
45
45
|
}
|
46
46
|
PATTERN
|
47
47
|
|
48
|
+
def self.autocorrect_incompatible_with
|
49
|
+
[Layout::SingleLineBlockChain]
|
50
|
+
end
|
51
|
+
|
48
52
|
def on_send(node)
|
49
53
|
return unless (to_h_node, map_node = map_to_h?(node))
|
50
54
|
|
51
|
-
message = format(MSG, method: map_node.loc.selector.source)
|
55
|
+
message = format(MSG, method: map_node.loc.selector.source, dot: map_node.loc.dot.source)
|
52
56
|
add_offense(map_node.loc.selector, message: message) do |corrector|
|
53
57
|
# If the `to_h` call already has a block, do not autocorrect.
|
54
58
|
next if to_h_node.block_node
|
@@ -56,6 +60,7 @@ module RuboCop
|
|
56
60
|
autocorrect(corrector, to_h_node, map_node)
|
57
61
|
end
|
58
62
|
end
|
63
|
+
alias on_csend on_send
|
59
64
|
|
60
65
|
private
|
61
66
|
|
@@ -170,7 +170,7 @@ module RuboCop
|
|
170
170
|
return true if node.arguments.any? do |arg|
|
171
171
|
arg.forward_arg_type? || arg.restarg_type? || arg.kwrestarg_type?
|
172
172
|
end
|
173
|
-
return false unless (last_argument = node.
|
173
|
+
return false unless (last_argument = node.last_argument)
|
174
174
|
|
175
175
|
last_argument.blockarg_type? && last_argument.name.nil?
|
176
176
|
end
|
@@ -67,7 +67,7 @@ module RuboCop
|
|
67
67
|
return unless redundant_argument?(node)
|
68
68
|
|
69
69
|
offense_range = argument_range(node)
|
70
|
-
message = format(MSG, arg: node.
|
70
|
+
message = format(MSG, arg: node.first_argument.source)
|
71
71
|
|
72
72
|
add_offense(offense_range, message: message) do |corrector|
|
73
73
|
corrector.remove(offense_range)
|
@@ -80,7 +80,7 @@ module RuboCop
|
|
80
80
|
redundant_argument = redundant_arg_for_method(node.method_name.to_s)
|
81
81
|
return false if redundant_argument.nil?
|
82
82
|
|
83
|
-
node.
|
83
|
+
node.first_argument == redundant_argument
|
84
84
|
end
|
85
85
|
|
86
86
|
def redundant_arg_for_method(method_name)
|
@@ -25,26 +25,29 @@ module RuboCop
|
|
25
25
|
MSG = 'Remove the redundant double splat and braces, use keyword arguments directly.'
|
26
26
|
MERGE_METHODS = %i[merge merge!].freeze
|
27
27
|
|
28
|
-
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
28
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
29
29
|
def on_hash(node)
|
30
30
|
return if node.pairs.empty? || node.pairs.any?(&:hash_rocket?)
|
31
31
|
return unless (parent = node.parent)
|
32
|
-
return
|
32
|
+
return unless parent.call_type? || parent.kwsplat_type?
|
33
|
+
return unless mergeable?(parent)
|
33
34
|
return unless (kwsplat = node.each_ancestor(:kwsplat).first)
|
34
|
-
return if allowed_double_splat_receiver?(kwsplat)
|
35
|
+
return if !node.braces? || allowed_double_splat_receiver?(kwsplat)
|
35
36
|
|
36
37
|
add_offense(kwsplat) do |corrector|
|
37
38
|
autocorrect(corrector, node, kwsplat)
|
38
39
|
end
|
39
40
|
end
|
40
|
-
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
41
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
41
42
|
|
42
43
|
private
|
43
44
|
|
44
45
|
def allowed_double_splat_receiver?(kwsplat)
|
45
|
-
|
46
|
+
first_child = kwsplat.children.first
|
47
|
+
return true if first_child.block_type? || first_child.numblock_type?
|
48
|
+
return false unless first_child.call_type?
|
46
49
|
|
47
|
-
root_receiver = root_receiver(
|
50
|
+
root_receiver = root_receiver(first_child)
|
48
51
|
|
49
52
|
!root_receiver&.hash_type?
|
50
53
|
end
|
@@ -71,7 +74,7 @@ module RuboCop
|
|
71
74
|
|
72
75
|
def select_merge_method_nodes(kwsplat)
|
73
76
|
extract_send_methods(kwsplat).select do |node|
|
74
|
-
|
77
|
+
mergeable?(node)
|
75
78
|
end
|
76
79
|
end
|
77
80
|
|
@@ -106,7 +109,7 @@ module RuboCop
|
|
106
109
|
end
|
107
110
|
|
108
111
|
def convert_to_new_arguments(node)
|
109
|
-
return unless
|
112
|
+
return unless mergeable?(node)
|
110
113
|
|
111
114
|
node.arguments.map do |arg|
|
112
115
|
if arg.hash_type?
|
@@ -117,8 +120,12 @@ module RuboCop
|
|
117
120
|
end
|
118
121
|
end
|
119
122
|
|
120
|
-
def
|
121
|
-
|
123
|
+
def mergeable?(node)
|
124
|
+
return true unless node.call_type?
|
125
|
+
return false unless MERGE_METHODS.include?(node.method_name)
|
126
|
+
return true unless (parent = node.parent)
|
127
|
+
|
128
|
+
mergeable?(parent)
|
122
129
|
end
|
123
130
|
end
|
124
131
|
end
|
@@ -60,10 +60,10 @@ module RuboCop
|
|
60
60
|
|
61
61
|
# @!method select_predicate?(node)
|
62
62
|
def_node_matcher :select_predicate?, <<~PATTERN
|
63
|
-
(
|
63
|
+
(call
|
64
64
|
{
|
65
|
-
(block $(
|
66
|
-
$(
|
65
|
+
(block $(call _ {:select :filter :find_all}) ...)
|
66
|
+
$(call _ {:select :filter :find_all} block_pass_type?)
|
67
67
|
}
|
68
68
|
${:#{RESTRICT_ON_SEND.join(' :')}})
|
69
69
|
PATTERN
|
@@ -87,6 +87,7 @@ module RuboCop
|
|
87
87
|
register_offense(select_node, node)
|
88
88
|
end
|
89
89
|
end
|
90
|
+
alias on_csend on_send
|
90
91
|
|
91
92
|
private
|
92
93
|
|
@@ -107,6 +107,8 @@ module RuboCop
|
|
107
107
|
|
108
108
|
def inside_string_literal_or_method_with_argument?(range)
|
109
109
|
processed_source.tokens.each_cons(2).any? do |token, next_token|
|
110
|
+
next if token.line == next_token.line
|
111
|
+
|
110
112
|
inside_string_literal?(range, token) || method_with_argument?(token, next_token)
|
111
113
|
end
|
112
114
|
end
|
@@ -17,6 +17,8 @@ module RuboCop
|
|
17
17
|
include Parentheses
|
18
18
|
extend AutoCorrector
|
19
19
|
|
20
|
+
ALLOWED_NODE_TYPES = %i[and or send splat kwsplat].freeze
|
21
|
+
|
20
22
|
# @!method square_brackets?(node)
|
21
23
|
def_node_matcher :square_brackets?, '(send {(send _recv _msg) str array hash} :[] ...)'
|
22
24
|
|
@@ -111,17 +113,19 @@ module RuboCop
|
|
111
113
|
|
112
114
|
def first_arg_begins_with_hash_literal?(node)
|
113
115
|
# Don't flag `method ({key: value})` or `method ({key: value}.method)`
|
114
|
-
method_chain_begins_with_hash_literal
|
115
|
-
|
116
|
-
|
116
|
+
hash_literal = method_chain_begins_with_hash_literal(node.children.first)
|
117
|
+
if (root_method = node.each_ancestor(:send).to_a.last)
|
118
|
+
parenthesized = root_method.parenthesized_call?
|
119
|
+
end
|
120
|
+
hash_literal && first_argument?(node) && !parentheses?(hash_literal) && !parenthesized
|
117
121
|
end
|
118
122
|
|
119
|
-
def method_chain_begins_with_hash_literal
|
120
|
-
return
|
121
|
-
return
|
122
|
-
return
|
123
|
+
def method_chain_begins_with_hash_literal(node)
|
124
|
+
return if node.nil?
|
125
|
+
return node if node.hash_type?
|
126
|
+
return unless node.send_type?
|
123
127
|
|
124
|
-
method_chain_begins_with_hash_literal
|
128
|
+
method_chain_begins_with_hash_literal(node.children.first)
|
125
129
|
end
|
126
130
|
|
127
131
|
def check(begin_node)
|
@@ -134,23 +138,29 @@ module RuboCop
|
|
134
138
|
check_send(begin_node, node) if node.call_type?
|
135
139
|
end
|
136
140
|
|
137
|
-
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
141
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
138
142
|
def find_offense_message(begin_node, node)
|
139
143
|
return 'a keyword' if keyword_with_redundant_parentheses?(node)
|
140
144
|
return 'a literal' if disallowed_literal?(begin_node, node)
|
141
145
|
return 'a variable' if node.variable?
|
142
146
|
return 'a constant' if node.const_type?
|
147
|
+
return 'an expression' if node.lambda_or_proc?
|
143
148
|
return 'an interpolated expression' if interpolation?(begin_node)
|
144
149
|
|
145
|
-
return if begin_node.chained?
|
150
|
+
return if begin_node.chained?
|
146
151
|
|
147
152
|
if node.and_type? || node.or_type?
|
153
|
+
return if ALLOWED_NODE_TYPES.include?(begin_node.parent&.type)
|
154
|
+
return if begin_node.parent&.if_type? && begin_node.parent&.ternary?
|
155
|
+
|
148
156
|
'a logical expression'
|
149
157
|
elsif node.respond_to?(:comparison_method?) && node.comparison_method?
|
158
|
+
return unless begin_node.parent.nil?
|
159
|
+
|
150
160
|
'a comparison expression'
|
151
161
|
end
|
152
162
|
end
|
153
|
-
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
163
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
154
164
|
|
155
165
|
# @!method interpolation?(node)
|
156
166
|
def_node_matcher :interpolation?, '[^begin ^^dstr]'
|
@@ -231,7 +241,13 @@ module RuboCop
|
|
231
241
|
end
|
232
242
|
|
233
243
|
def first_argument?(node)
|
234
|
-
first_send_argument?(node) ||
|
244
|
+
if first_send_argument?(node) ||
|
245
|
+
first_super_argument?(node) ||
|
246
|
+
first_yield_argument?(node)
|
247
|
+
return true
|
248
|
+
end
|
249
|
+
|
250
|
+
node.each_ancestor.any? { |ancestor| first_argument?(ancestor) }
|
235
251
|
end
|
236
252
|
|
237
253
|
# @!method first_send_argument?(node)
|
@@ -58,7 +58,7 @@ module RuboCop
|
|
58
58
|
|
59
59
|
MSG = 'Redundant `return` detected.'
|
60
60
|
MULTI_RETURN_MSG = 'To return multiple values, use an array.'
|
61
|
-
RESTRICT_ON_SEND = %i[define_method define_singleton_method].freeze
|
61
|
+
RESTRICT_ON_SEND = %i[define_method define_singleton_method lambda].freeze
|
62
62
|
|
63
63
|
def on_send(node)
|
64
64
|
return unless (parent = node.parent) && parent.block_type?
|
@@ -133,7 +133,7 @@ module RuboCop
|
|
133
133
|
end
|
134
134
|
|
135
135
|
def percent_array_literal?(node)
|
136
|
-
|
136
|
+
percent_w_literal?(node) || percent_w_upper_literal?(node)
|
137
137
|
end
|
138
138
|
|
139
139
|
def heredoc_with_disabled_interpolation?(node)
|
@@ -146,7 +146,7 @@ module RuboCop
|
|
146
146
|
return node.child_nodes.first if node.match_with_lvasgn_type?
|
147
147
|
|
148
148
|
if node.receiver.lvar_type? &&
|
149
|
-
(block.numblock_type? || node.receiver.source == block.
|
149
|
+
(block.numblock_type? || node.receiver.source == block.first_argument.source)
|
150
150
|
node.first_argument
|
151
151
|
elsif node.first_argument.lvar_type?
|
152
152
|
node.receiver
|
@@ -80,6 +80,7 @@ module RuboCop
|
|
80
80
|
processed_source.tokens.group_by(&:line)
|
81
81
|
end
|
82
82
|
|
83
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
83
84
|
def semicolon_position(tokens)
|
84
85
|
if tokens.last.semicolon?
|
85
86
|
-1
|
@@ -90,10 +91,13 @@ module RuboCop
|
|
90
91
|
elsif exist_semicolon_after_left_curly_brace?(tokens) ||
|
91
92
|
exist_semicolon_after_left_string_interpolation_brace?(tokens)
|
92
93
|
2
|
94
|
+
elsif exist_semicolon_after_left_lambda_curly_brace?(tokens)
|
95
|
+
3
|
93
96
|
elsif exist_semicolon_before_right_string_interpolation_brace?(tokens)
|
94
97
|
-4
|
95
98
|
end
|
96
99
|
end
|
100
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
97
101
|
|
98
102
|
def exist_semicolon_before_right_curly_brace?(tokens)
|
99
103
|
tokens[-2]&.right_curly_brace? && tokens[-3]&.semicolon?
|
@@ -103,6 +107,10 @@ module RuboCop
|
|
103
107
|
tokens[1]&.left_curly_brace? && tokens[2]&.semicolon?
|
104
108
|
end
|
105
109
|
|
110
|
+
def exist_semicolon_after_left_lambda_curly_brace?(tokens)
|
111
|
+
tokens[2]&.type == :tLAMBEG && tokens[3]&.semicolon?
|
112
|
+
end
|
113
|
+
|
106
114
|
def exist_semicolon_before_right_string_interpolation_brace?(tokens)
|
107
115
|
tokens[-3]&.type == :tSTRING_DEND && tokens[-4]&.semicolon?
|
108
116
|
end
|
@@ -33,6 +33,7 @@ module RuboCop
|
|
33
33
|
|
34
34
|
MSG = 'Use `%<receiver>s[%<argument>s]` instead of `%<original>s`.'
|
35
35
|
RESTRICT_ON_SEND = %i[dig].freeze
|
36
|
+
IGNORED_ARGUMENT_TYPES = %i[block_pass forwarded_restarg forwarded_args hash].freeze
|
36
37
|
|
37
38
|
# @!method single_argument_dig?(node)
|
38
39
|
def_node_matcher :single_argument_dig?, <<~PATTERN
|
@@ -44,7 +45,7 @@ module RuboCop
|
|
44
45
|
|
45
46
|
expression = single_argument_dig?(node)
|
46
47
|
return unless expression
|
47
|
-
return if expression.
|
48
|
+
return if IGNORED_ARGUMENT_TYPES.include?(expression.type)
|
48
49
|
|
49
50
|
receiver = node.receiver.source
|
50
51
|
argument = expression.source
|
@@ -30,6 +30,7 @@ module RuboCop
|
|
30
30
|
|
31
31
|
MSG = 'Prefer multiline `do`...`end` block.'
|
32
32
|
|
33
|
+
# rubocop:disable Metrics/AbcSize
|
33
34
|
def on_block(node)
|
34
35
|
return if !node.single_line? || node.braces?
|
35
36
|
|
@@ -42,10 +43,11 @@ module RuboCop
|
|
42
43
|
corrector.remove(node.loc.end)
|
43
44
|
corrector.insert_after(node_body.loc.heredoc_end, "\nend")
|
44
45
|
else
|
45
|
-
corrector.
|
46
|
+
corrector.insert_before(node.loc.end, "\n")
|
46
47
|
end
|
47
48
|
end
|
48
49
|
end
|
50
|
+
# rubocop:enable Metrics/AbcSize
|
49
51
|
alias on_numblock on_block
|
50
52
|
|
51
53
|
private
|
@@ -39,7 +39,7 @@ module RuboCop
|
|
39
39
|
|
40
40
|
def on_send(node)
|
41
41
|
return unless node.arguments.count == 1
|
42
|
-
return unless range_till_minus_one?(node.
|
42
|
+
return unless range_till_minus_one?(node.first_argument)
|
43
43
|
|
44
44
|
add_offense(node.first_argument) do |corrector|
|
45
45
|
corrector.remove(node.first_argument.end)
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Enforces the presence of parentheses in `super` containing arguments.
|
7
|
+
#
|
8
|
+
# `super` is a keyword and is provided as a distinct cop from those designed for method call.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
#
|
12
|
+
# # bad
|
13
|
+
# super name, age
|
14
|
+
#
|
15
|
+
# # good
|
16
|
+
# super(name, age)
|
17
|
+
#
|
18
|
+
class SuperWithArgsParentheses < Base
|
19
|
+
extend AutoCorrector
|
20
|
+
|
21
|
+
MSG = 'Use parentheses for `super` with arguments.'
|
22
|
+
|
23
|
+
def on_super(node)
|
24
|
+
return if node.parenthesized?
|
25
|
+
|
26
|
+
add_offense(node) do |corrector|
|
27
|
+
range = node.loc.keyword.end.join(node.first_argument.source_range.begin)
|
28
|
+
corrector.replace(range, '(')
|
29
|
+
corrector.insert_after(node.last_argument, ')')
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -1,9 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'base64'
|
4
3
|
require 'cgi'
|
5
4
|
require 'erb'
|
6
|
-
require 'ostruct'
|
7
5
|
|
8
6
|
module RuboCop
|
9
7
|
module Formatter
|
@@ -88,7 +86,7 @@ module RuboCop
|
|
88
86
|
# rubocop:enable Lint/UselessMethodDefinition
|
89
87
|
|
90
88
|
def decorated_message(offense)
|
91
|
-
offense.message.gsub(/`(.+?)`/) { "<code>#{Regexp.last_match(1)}</code>" }
|
89
|
+
offense.message.gsub(/`(.+?)`/) { "<code>#{escape(Regexp.last_match(1))}</code>" }
|
92
90
|
end
|
93
91
|
|
94
92
|
def highlighted_source_line(offense)
|
@@ -124,7 +122,10 @@ module RuboCop
|
|
124
122
|
|
125
123
|
def base64_encoded_logo_image
|
126
124
|
image = File.read(LOGO_IMAGE_PATH, binmode: true)
|
127
|
-
|
125
|
+
|
126
|
+
# `Base64.encode64` compatible:
|
127
|
+
# https://github.com/ruby/base64/blob/v0.1.1/lib/base64.rb#L27-L40
|
128
|
+
[image].pack('m')
|
128
129
|
end
|
129
130
|
end
|
130
131
|
end
|