rubocop 1.36.0 → 1.38.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 -1
- data/config/default.yml +27 -1
- data/lib/rubocop/arguments_env.rb +17 -0
- data/lib/rubocop/arguments_file.rb +17 -0
- data/lib/rubocop/cli/command/execute_runner.rb +7 -7
- data/lib/rubocop/cli/command/suggest_extensions.rb +8 -1
- data/lib/rubocop/comment_config.rb +36 -1
- data/lib/rubocop/cop/commissioner.rb +3 -1
- data/lib/rubocop/cop/generator.rb +1 -2
- data/lib/rubocop/cop/internal_affairs/create_empty_file.rb +37 -0
- data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +111 -0
- data/lib/rubocop/cop/internal_affairs.rb +2 -0
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -0
- data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +1 -1
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +13 -9
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +30 -3
- data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +6 -2
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_magic_comment.rb +73 -0
- data/lib/rubocop/cop/lint/duplicate_methods.rb +11 -1
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +25 -6
- data/lib/rubocop/cop/lint/empty_class.rb +3 -1
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +20 -8
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +18 -3
- data/lib/rubocop/cop/lint/nested_method_definition.rb +50 -1
- data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/ordered_magic_comments.rb +4 -5
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +23 -1
- data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +7 -0
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +38 -10
- data/lib/rubocop/cop/lint/require_parentheses.rb +1 -1
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +3 -2
- data/lib/rubocop/cop/lint/shadowed_exception.rb +0 -10
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +3 -0
- data/lib/rubocop/cop/lint/unreachable_loop.rb +1 -1
- data/lib/rubocop/cop/lint/unused_method_argument.rb +4 -0
- data/lib/rubocop/cop/mixin/comments_help.rb +12 -0
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +4 -0
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +6 -3
- data/lib/rubocop/cop/mixin/rescue_node.rb +3 -1
- data/lib/rubocop/cop/mixin/surrounding_space.rb +10 -8
- data/lib/rubocop/cop/naming/inclusive_language.rb +1 -1
- data/lib/rubocop/cop/registry.rb +10 -4
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +24 -2
- data/lib/rubocop/cop/style/accessor_grouping.rb +7 -3
- data/lib/rubocop/cop/style/block_delimiters.rb +2 -2
- data/lib/rubocop/cop/style/character_literal.rb +1 -1
- data/lib/rubocop/cop/style/class_equality_comparison.rb +1 -1
- data/lib/rubocop/cop/style/collection_compact.rb +11 -2
- data/lib/rubocop/cop/style/empty_method.rb +1 -1
- data/lib/rubocop/cop/style/endless_method.rb +1 -1
- data/lib/rubocop/cop/style/explicit_block_argument.rb +4 -0
- data/lib/rubocop/cop/style/format_string_token.rb +1 -1
- data/lib/rubocop/cop/style/guard_clause.rb +62 -21
- data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +25 -2
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +13 -2
- data/lib/rubocop/cop/style/module_function.rb +28 -6
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +7 -1
- data/lib/rubocop/cop/style/numeric_predicate.rb +1 -1
- data/lib/rubocop/cop/style/operator_method_call.rb +40 -0
- data/lib/rubocop/cop/style/redundant_begin.rb +1 -0
- data/lib/rubocop/cop/style/redundant_condition.rb +5 -2
- data/lib/rubocop/cop/style/redundant_each.rb +111 -0
- data/lib/rubocop/cop/style/redundant_initialize.rb +3 -1
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +8 -1
- data/lib/rubocop/cop/style/redundant_string_escape.rb +181 -0
- data/lib/rubocop/cop/style/rescue_modifier.rb +1 -1
- data/lib/rubocop/cop/style/static_class.rb +32 -1
- data/lib/rubocop/cop/style/symbol_array.rb +2 -0
- data/lib/rubocop/cop/style/symbol_proc.rb +1 -1
- data/lib/rubocop/cop/style/word_array.rb +2 -0
- data/lib/rubocop/cop/team.rb +3 -4
- data/lib/rubocop/cop/variable_force/variable_table.rb +1 -1
- data/lib/rubocop/cops_documentation_generator.rb +4 -2
- data/lib/rubocop/ext/processed_source.rb +2 -0
- data/lib/rubocop/formatter/disabled_config_formatter.rb +8 -2
- data/lib/rubocop/formatter/offense_count_formatter.rb +8 -5
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +6 -3
- data/lib/rubocop/options.rb +19 -15
- data/lib/rubocop/rspec/cop_helper.rb +21 -1
- data/lib/rubocop/rspec/shared_contexts.rb +14 -1
- data/lib/rubocop/runner.rb +15 -11
- data/lib/rubocop/server/cache.rb +5 -1
- data/lib/rubocop/server/cli.rb +9 -2
- data/lib/rubocop/server/client_command/exec.rb +5 -0
- data/lib/rubocop/server/core.rb +3 -1
- data/lib/rubocop/server/socket_reader.rb +5 -1
- data/lib/rubocop/server.rb +1 -1
- data/lib/rubocop/version.rb +8 -3
- data/lib/rubocop.rb +4 -0
- metadata +13 -5
@@ -96,11 +96,14 @@ module RuboCop
|
|
96
96
|
end
|
97
97
|
|
98
98
|
def without_parentheses_call_expr_follows?(ancestor)
|
99
|
+
return false unless ancestor.respond_to?(:parenthesized?) && !ancestor.parenthesized?
|
100
|
+
|
99
101
|
right_sibling = ancestor.right_sibling
|
100
|
-
right_sibling ||= ancestor.each_ancestor.find
|
101
|
-
|
102
|
+
right_sibling ||= ancestor.each_ancestor.find do |node|
|
103
|
+
node.assignment? || node.send_type?
|
104
|
+
end&.right_sibling
|
102
105
|
|
103
|
-
|
106
|
+
!!right_sibling
|
104
107
|
end
|
105
108
|
|
106
109
|
def breakdown_value_types_of_hash(hash_node)
|
@@ -11,7 +11,9 @@ module RuboCop
|
|
11
11
|
private
|
12
12
|
|
13
13
|
def rescue_modifier?(node)
|
14
|
-
|
14
|
+
return false unless node.respond_to?(:resbody_type?)
|
15
|
+
|
16
|
+
node.resbody_type? && @modifier_locations.include?(node.loc.keyword)
|
15
17
|
end
|
16
18
|
|
17
19
|
# @deprecated Use ResbodyNode#exceptions instead
|
@@ -13,7 +13,7 @@ module RuboCop
|
|
13
13
|
|
14
14
|
private
|
15
15
|
|
16
|
-
def side_space_range(range:, side:)
|
16
|
+
def side_space_range(range:, side:, include_newlines: false)
|
17
17
|
buffer = processed_source.buffer
|
18
18
|
src = buffer.source
|
19
19
|
|
@@ -21,11 +21,11 @@ module RuboCop
|
|
21
21
|
end_pos = range.end_pos
|
22
22
|
if side == :left
|
23
23
|
end_pos = begin_pos
|
24
|
-
begin_pos = reposition(src, begin_pos, -1)
|
24
|
+
begin_pos = reposition(src, begin_pos, -1, include_newlines: include_newlines)
|
25
25
|
end
|
26
26
|
if side == :right
|
27
27
|
begin_pos = end_pos
|
28
|
-
end_pos = reposition(src, end_pos, 1)
|
28
|
+
end_pos = reposition(src, end_pos, 1, include_newlines: include_newlines)
|
29
29
|
end
|
30
30
|
Parser::Source::Range.new(buffer, begin_pos, end_pos)
|
31
31
|
end
|
@@ -75,9 +75,10 @@ module RuboCop
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
-
def reposition(src, pos, step)
|
78
|
+
def reposition(src, pos, step, include_newlines: false)
|
79
79
|
offset = step == -1 ? -1 : 0
|
80
|
-
pos += step while SINGLE_SPACE_REGEXP.match?(src[pos + offset])
|
80
|
+
pos += step while SINGLE_SPACE_REGEXP.match?(src[pos + offset]) ||
|
81
|
+
(include_newlines && src[pos + offset] == "\n")
|
81
82
|
pos.negative? ? 0 : pos
|
82
83
|
end
|
83
84
|
|
@@ -117,14 +118,15 @@ module RuboCop
|
|
117
118
|
end
|
118
119
|
|
119
120
|
def offending_empty_no_space?(config, left_token, right_token)
|
120
|
-
config == 'no_space' && !
|
121
|
+
config == 'no_space' && !no_character_between?(left_token, right_token)
|
121
122
|
end
|
122
123
|
|
123
124
|
def space_between?(left_bracket_token, right_bracket_token)
|
124
|
-
left_bracket_token.end_pos + 1 == right_bracket_token.begin_pos
|
125
|
+
left_bracket_token.end_pos + 1 == right_bracket_token.begin_pos &&
|
126
|
+
processed_source.buffer.source[left_bracket_token.end_pos] == ' '
|
125
127
|
end
|
126
128
|
|
127
|
-
def
|
129
|
+
def no_character_between?(left_bracket_token, right_bracket_token)
|
128
130
|
left_bracket_token.end_pos == right_bracket_token.begin_pos
|
129
131
|
end
|
130
132
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Naming
|
6
|
-
#
|
6
|
+
# Recommends the use of inclusive language instead of problematic terms.
|
7
7
|
# The cop can check the following locations for offenses:
|
8
8
|
# - identifiers
|
9
9
|
# - constants
|
data/lib/rubocop/cop/registry.rb
CHANGED
@@ -149,16 +149,22 @@ module RuboCop
|
|
149
149
|
@registry.size
|
150
150
|
end
|
151
151
|
|
152
|
-
def enabled(config
|
153
|
-
select { |cop|
|
152
|
+
def enabled(config)
|
153
|
+
select { |cop| enabled?(cop, config) }
|
154
154
|
end
|
155
155
|
|
156
|
-
def
|
156
|
+
def disabled(config)
|
157
|
+
reject { |cop| enabled?(cop, config) }
|
158
|
+
end
|
159
|
+
|
160
|
+
def enabled?(cop, config)
|
161
|
+
return true if options.fetch(:only, []).include?(cop.cop_name)
|
162
|
+
|
157
163
|
cfg = config.for_cop(cop)
|
158
164
|
|
159
165
|
cop_enabled = cfg.fetch('Enabled') == true || enabled_pending_cop?(cfg, config)
|
160
166
|
|
161
|
-
if
|
167
|
+
if options.fetch(:safe, false)
|
162
168
|
cop_enabled && cfg.fetch('Safe', true)
|
163
169
|
else
|
164
170
|
cop_enabled
|
@@ -85,6 +85,8 @@ module RuboCop
|
|
85
85
|
|
86
86
|
RESTRICT_ON_SEND = %i[private protected public module_function].freeze
|
87
87
|
|
88
|
+
ALLOWED_NODE_TYPES = %i[pair block].freeze
|
89
|
+
|
88
90
|
# @!method access_modifier_with_symbol?(node)
|
89
91
|
def_node_matcher :access_modifier_with_symbol?, <<~PATTERN
|
90
92
|
(send nil? {:private :protected :public :module_function} (sym _))
|
@@ -92,7 +94,7 @@ module RuboCop
|
|
92
94
|
|
93
95
|
def on_send(node)
|
94
96
|
return unless node.access_modifier?
|
95
|
-
return if node.parent&.
|
97
|
+
return if ALLOWED_NODE_TYPES.include?(node.parent&.type)
|
96
98
|
return if allow_modifiers_on_symbols?(node)
|
97
99
|
|
98
100
|
if offense?(node)
|
@@ -183,6 +185,7 @@ module RuboCop
|
|
183
185
|
end
|
184
186
|
|
185
187
|
def insert_def(corrector, node, source)
|
188
|
+
source = [*processed_source.ast_with_comments[node].map(&:text), source].join("\n")
|
186
189
|
argument_less_modifier_node = find_argument_less_modifier_node(node)
|
187
190
|
if argument_less_modifier_node
|
188
191
|
corrector.insert_after(argument_less_modifier_node, "\n\n#{source}")
|
@@ -201,11 +204,30 @@ module RuboCop
|
|
201
204
|
def remove_node(corrector, node)
|
202
205
|
corrector.remove(
|
203
206
|
range_by_whole_lines(
|
204
|
-
node
|
207
|
+
range_with_comments(node),
|
205
208
|
include_final_newline: true
|
206
209
|
)
|
207
210
|
)
|
208
211
|
end
|
212
|
+
|
213
|
+
def range_with_comments(node)
|
214
|
+
ranges = [
|
215
|
+
node,
|
216
|
+
*processed_source.ast_with_comments[node]
|
217
|
+
].map do |element|
|
218
|
+
element.location.expression
|
219
|
+
end
|
220
|
+
ranges.reduce do |result, range|
|
221
|
+
add_range(result, range)
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def add_range(range1, range2)
|
226
|
+
range1.with(
|
227
|
+
begin_pos: [range1.begin_pos, range2.begin_pos].min,
|
228
|
+
end_pos: [range1.end_pos, range2.end_pos].max
|
229
|
+
)
|
230
|
+
end
|
209
231
|
end
|
210
232
|
end
|
211
233
|
end
|
@@ -135,12 +135,16 @@ module RuboCop
|
|
135
135
|
end
|
136
136
|
|
137
137
|
def separate_accessors(node)
|
138
|
-
node.arguments.
|
139
|
-
|
138
|
+
node.arguments.flat_map do |arg|
|
139
|
+
lines = [
|
140
|
+
*processed_source.ast_with_comments[arg].map(&:text),
|
140
141
|
"#{node.method_name} #{arg.source}"
|
142
|
+
]
|
143
|
+
if arg == node.arguments.first
|
144
|
+
lines
|
141
145
|
else
|
142
146
|
indent = ' ' * node.loc.column
|
143
|
-
"#{indent}#{
|
147
|
+
lines.map { |line| "#{indent}#{line}" }
|
144
148
|
end
|
145
149
|
end.join("\n")
|
146
150
|
end
|
@@ -157,7 +157,7 @@ module RuboCop
|
|
157
157
|
# process(something)
|
158
158
|
# }
|
159
159
|
#
|
160
|
-
# @example AllowedPatterns: [
|
160
|
+
# @example AllowedPatterns: ['map']
|
161
161
|
#
|
162
162
|
# # good
|
163
163
|
# things.map { |thing|
|
@@ -425,7 +425,7 @@ module RuboCop
|
|
425
425
|
if node.parent.begin_type?
|
426
426
|
return_value_used?(node.parent)
|
427
427
|
else
|
428
|
-
node.parent.assignment? || node.parent.
|
428
|
+
node.parent.assignment? || node.parent.call_type?
|
429
429
|
end
|
430
430
|
end
|
431
431
|
|
@@ -29,7 +29,7 @@ module RuboCop
|
|
29
29
|
|
30
30
|
def offense?(node)
|
31
31
|
# we don't register an offense for things like ?\C-\M-d
|
32
|
-
node.
|
32
|
+
node.character_literal? && node.source.size.between?(2, 3)
|
33
33
|
end
|
34
34
|
|
35
35
|
def autocorrect(corrector, node)
|
@@ -8,7 +8,9 @@ module RuboCop
|
|
8
8
|
#
|
9
9
|
# @safety
|
10
10
|
# It is unsafe by default because false positives may occur in the
|
11
|
-
# `nil` check of block arguments to the receiver object.
|
11
|
+
# `nil` check of block arguments to the receiver object. Additionally,
|
12
|
+
# we can't know the type of the receiver object for sure, which may
|
13
|
+
# result in false positives as well.
|
12
14
|
#
|
13
15
|
# For example, `[[1, 2], [3, nil]].reject { |first, second| second.nil? }`
|
14
16
|
# and `[[1, 2], [3, nil]].compact` are not compatible. This will work fine
|
@@ -36,8 +38,8 @@ module RuboCop
|
|
36
38
|
extend AutoCorrector
|
37
39
|
|
38
40
|
MSG = 'Use `%<good>s` instead of `%<bad>s`.'
|
39
|
-
|
40
41
|
RESTRICT_ON_SEND = %i[reject reject! select select!].freeze
|
42
|
+
TO_ENUM_METHODS = %i[to_enum lazy].freeze
|
41
43
|
|
42
44
|
# @!method reject_method_with_block_pass?(node)
|
43
45
|
def_node_matcher :reject_method_with_block_pass?, <<~PATTERN
|
@@ -69,6 +71,7 @@ module RuboCop
|
|
69
71
|
|
70
72
|
def on_send(node)
|
71
73
|
return unless (range = offense_range(node))
|
74
|
+
return if target_ruby_version <= 3.0 && to_enum_method?(node)
|
72
75
|
|
73
76
|
good = good_method_name(node)
|
74
77
|
message = format(MSG, good: good, bad: range.source)
|
@@ -94,6 +97,12 @@ module RuboCop
|
|
94
97
|
end
|
95
98
|
end
|
96
99
|
|
100
|
+
def to_enum_method?(node)
|
101
|
+
return false unless node.receiver.send_type?
|
102
|
+
|
103
|
+
TO_ENUM_METHODS.include?(node.receiver.method_name)
|
104
|
+
end
|
105
|
+
|
97
106
|
def good_method_name(node)
|
98
107
|
if node.bang_method?
|
99
108
|
'compact!'
|
@@ -52,7 +52,7 @@ module RuboCop
|
|
52
52
|
MSG_EXPANDED = 'Put the `end` of empty method definitions on the next line.'
|
53
53
|
|
54
54
|
def on_def(node)
|
55
|
-
return if node.body ||
|
55
|
+
return if node.body || processed_source.contains_comment?(node.source_range)
|
56
56
|
return if correct_style?(node)
|
57
57
|
|
58
58
|
add_offense(node) do |corrector|
|
@@ -10,6 +10,9 @@ module RuboCop
|
|
10
10
|
# one of `return`, `break`, `next`, `raise`, or `fail` is used
|
11
11
|
# in the body of the conditional expression.
|
12
12
|
#
|
13
|
+
# NOTE: Autocorrect works in most cases except with if-else statements
|
14
|
+
# that contain logical operators such as `foo || raise('exception')`
|
15
|
+
#
|
13
16
|
# @example
|
14
17
|
# # bad
|
15
18
|
# def test
|
@@ -90,6 +93,7 @@ module RuboCop
|
|
90
93
|
# end
|
91
94
|
#
|
92
95
|
class GuardClause < Base
|
96
|
+
extend AutoCorrector
|
93
97
|
include MinBodyLength
|
94
98
|
include StatementModifier
|
95
99
|
|
@@ -101,40 +105,49 @@ module RuboCop
|
|
101
105
|
|
102
106
|
return unless body
|
103
107
|
|
104
|
-
|
105
|
-
check_ending_if(body)
|
106
|
-
elsif body.begin_type?
|
107
|
-
final_expression = body.children.last
|
108
|
-
check_ending_if(final_expression) if final_expression&.if_type?
|
109
|
-
end
|
108
|
+
check_ending_body(body)
|
110
109
|
end
|
111
110
|
alias on_defs on_def
|
112
111
|
|
113
112
|
def on_if(node)
|
114
113
|
return if accepted_form?(node)
|
115
114
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
115
|
+
if (guard_clause = node.if_branch&.guard_clause?)
|
116
|
+
kw = node.loc.keyword.source
|
117
|
+
guard = :if
|
118
|
+
elsif (guard_clause = node.else_branch&.guard_clause?)
|
119
|
+
kw = node.inverse_keyword
|
120
|
+
guard = :else
|
121
|
+
else
|
122
|
+
return
|
123
|
+
end
|
120
124
|
|
121
|
-
|
122
|
-
node.loc.keyword.source
|
123
|
-
else
|
124
|
-
node.inverse_keyword
|
125
|
-
end
|
125
|
+
guard = nil if and_or_guard_clause?(guard_clause)
|
126
126
|
|
127
|
-
register_offense(node, guard_clause_source(guard_clause), kw)
|
127
|
+
register_offense(node, guard_clause_source(guard_clause), kw, guard)
|
128
128
|
end
|
129
129
|
|
130
130
|
private
|
131
131
|
|
132
|
+
def check_ending_body(body)
|
133
|
+
return if body.nil?
|
134
|
+
|
135
|
+
if body.if_type?
|
136
|
+
check_ending_if(body)
|
137
|
+
elsif body.begin_type?
|
138
|
+
final_expression = body.children.last
|
139
|
+
check_ending_if(final_expression) if final_expression&.if_type?
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
132
143
|
def check_ending_if(node)
|
133
144
|
return if accepted_form?(node, ending: true) || !min_body_length?(node)
|
134
145
|
return if allowed_consecutive_conditionals? &&
|
135
146
|
consecutive_conditionals?(node.parent, node)
|
136
147
|
|
137
148
|
register_offense(node, 'return', node.inverse_keyword)
|
149
|
+
|
150
|
+
check_ending_body(node.if_branch)
|
138
151
|
end
|
139
152
|
|
140
153
|
def consecutive_conditionals?(parent, node)
|
@@ -145,28 +158,56 @@ module RuboCop
|
|
145
158
|
end
|
146
159
|
end
|
147
160
|
|
148
|
-
def register_offense(node, scope_exiting_keyword, conditional_keyword)
|
161
|
+
def register_offense(node, scope_exiting_keyword, conditional_keyword, guard = nil)
|
149
162
|
condition, = node.node_parts
|
150
163
|
example = [scope_exiting_keyword, conditional_keyword, condition.source].join(' ')
|
151
164
|
if too_long_for_single_line?(node, example)
|
152
165
|
return if trivial?(node)
|
153
166
|
|
154
167
|
example = "#{conditional_keyword} #{condition.source}; #{scope_exiting_keyword}; end"
|
168
|
+
replacement = <<~RUBY.chomp
|
169
|
+
#{conditional_keyword} #{condition.source}
|
170
|
+
#{scope_exiting_keyword}
|
171
|
+
end
|
172
|
+
RUBY
|
155
173
|
end
|
156
174
|
|
157
|
-
add_offense(node.loc.keyword, message: format(MSG, example: example))
|
175
|
+
add_offense(node.loc.keyword, message: format(MSG, example: example)) do |corrector|
|
176
|
+
next if node.else? && guard.nil?
|
177
|
+
|
178
|
+
autocorrect(corrector, node, condition, replacement || example, guard)
|
179
|
+
end
|
158
180
|
end
|
159
181
|
|
160
|
-
def
|
161
|
-
|
182
|
+
def autocorrect(corrector, node, condition, replacement, guard)
|
183
|
+
corrector.replace(node.loc.keyword.join(condition.loc.expression), replacement)
|
184
|
+
corrector.remove(node.loc.end)
|
185
|
+
return unless node.else?
|
186
|
+
|
187
|
+
corrector.remove(node.loc.else)
|
188
|
+
corrector.remove(branch_to_remove(node, guard))
|
189
|
+
end
|
190
|
+
|
191
|
+
def branch_to_remove(node, guard)
|
192
|
+
case guard
|
193
|
+
when :if then node.if_branch
|
194
|
+
when :else then node.else_branch
|
195
|
+
end
|
196
|
+
end
|
162
197
|
|
163
|
-
|
198
|
+
def guard_clause_source(guard_clause)
|
199
|
+
if and_or_guard_clause?(guard_clause)
|
164
200
|
guard_clause.parent.source
|
165
201
|
else
|
166
202
|
guard_clause.source
|
167
203
|
end
|
168
204
|
end
|
169
205
|
|
206
|
+
def and_or_guard_clause?(guard_clause)
|
207
|
+
parent = guard_clause.parent
|
208
|
+
parent.and_type? || parent.or_type?
|
209
|
+
end
|
210
|
+
|
170
211
|
def too_long_for_single_line?(node, example)
|
171
212
|
max = max_line_length
|
172
213
|
max && node.source_range.column + example.length > max
|
@@ -28,7 +28,7 @@ module RuboCop
|
|
28
28
|
# * always - forces use of the 3.1 syntax (e.g. {foo:})
|
29
29
|
# * never - forces use of explicit hash literal value
|
30
30
|
# * either - accepts both shorthand and explicit use of hash literal value
|
31
|
-
# * consistent - like "
|
31
|
+
# * consistent - like "either", but will avoid mixing styles in a single hash
|
32
32
|
#
|
33
33
|
# @example EnforcedStyle: ruby19 (default)
|
34
34
|
# # bad
|
@@ -5,10 +5,27 @@ module RuboCop
|
|
5
5
|
module Style
|
6
6
|
# Checks for redundant `if` with boolean literal branches.
|
7
7
|
# It checks only conditions to return boolean value (`true` or `false`) for safe detection.
|
8
|
-
# The conditions to be checked are comparison methods, predicate methods, and
|
8
|
+
# The conditions to be checked are comparison methods, predicate methods, and
|
9
|
+
# double negation (!!).
|
9
10
|
# `nonzero?` method is allowed by default.
|
10
11
|
# These are customizable with `AllowedMethods` option.
|
11
12
|
#
|
13
|
+
# This cop targets only `if`s with a single `elsif` or `else` branch. The following
|
14
|
+
# code will be allowed, because it has two `elsif` branches:
|
15
|
+
#
|
16
|
+
# [source,ruby]
|
17
|
+
# ----
|
18
|
+
# if foo
|
19
|
+
# true
|
20
|
+
# elsif bar > baz
|
21
|
+
# true
|
22
|
+
# elsif qux > quux # Single `elsif` is warned, but two or more `elsif`s are not.
|
23
|
+
# true
|
24
|
+
# else
|
25
|
+
# false
|
26
|
+
# end
|
27
|
+
# ----
|
28
|
+
#
|
12
29
|
# @safety
|
13
30
|
# Autocorrection is unsafe because there is no guarantee that all predicate methods
|
14
31
|
# will return a boolean value. Those methods can be allowed with `AllowedMethods` config.
|
@@ -57,7 +74,7 @@ module RuboCop
|
|
57
74
|
def_node_matcher :double_negative?, '(send (send _ :!) :!)'
|
58
75
|
|
59
76
|
def on_if(node)
|
60
|
-
return
|
77
|
+
return if !if_with_boolean_literal_branches?(node) || multiple_elsif?(node)
|
61
78
|
|
62
79
|
condition = node.condition
|
63
80
|
range, keyword = offense_range_with_keyword(node, condition)
|
@@ -76,6 +93,12 @@ module RuboCop
|
|
76
93
|
|
77
94
|
private
|
78
95
|
|
96
|
+
def multiple_elsif?(node)
|
97
|
+
return false unless (parent = node.parent)
|
98
|
+
|
99
|
+
parent.if_type? && parent.elsif?
|
100
|
+
end
|
101
|
+
|
79
102
|
def offense_range_with_keyword(node, condition)
|
80
103
|
if node.ternary?
|
81
104
|
range = condition.source_range.end.join(node.source_range.end)
|
@@ -20,8 +20,8 @@ module RuboCop
|
|
20
20
|
return if require_parentheses_for_hash_value_omission?(node)
|
21
21
|
return if syntax_like_method_call?(node)
|
22
22
|
return if super_call_without_arguments?(node)
|
23
|
-
return if allowed_camel_case_method_call?(node)
|
24
23
|
return if legitimate_call_with_parentheses?(node)
|
24
|
+
return if allowed_camel_case_method_call?(node)
|
25
25
|
return if allowed_string_interpolation_method_call?(node)
|
26
26
|
|
27
27
|
add_offense(offense_range(node), message: OMIT_MSG) do |corrector|
|
@@ -97,7 +97,8 @@ module RuboCop
|
|
97
97
|
call_in_optional_arguments?(node) ||
|
98
98
|
call_in_single_line_inheritance?(node) ||
|
99
99
|
allowed_multiline_call_with_parentheses?(node) ||
|
100
|
-
allowed_chained_call_with_parentheses?(node)
|
100
|
+
allowed_chained_call_with_parentheses?(node) ||
|
101
|
+
assignment_in_condition?(node)
|
101
102
|
end
|
102
103
|
|
103
104
|
def call_in_literals?(node)
|
@@ -202,6 +203,16 @@ module RuboCop
|
|
202
203
|
def inside_string_interpolation?(node)
|
203
204
|
node.ancestors.drop_while { |a| !a.begin_type? }.any?(&:dstr_type?)
|
204
205
|
end
|
206
|
+
|
207
|
+
def assignment_in_condition?(node)
|
208
|
+
parent = node.parent
|
209
|
+
return false unless parent
|
210
|
+
|
211
|
+
grandparent = parent.parent
|
212
|
+
return false unless grandparent
|
213
|
+
|
214
|
+
parent.assignment? && (grandparent.conditional? || grandparent.when_type?)
|
215
|
+
end
|
205
216
|
end
|
206
217
|
# rubocop:enable Metrics/ModuleLength, Metrics/CyclomaticComplexity
|
207
218
|
end
|
@@ -3,13 +3,15 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
# Checks for use of `extend self` or `module_function` in a
|
7
|
-
# module.
|
6
|
+
# Checks for use of `extend self` or `module_function` in a module.
|
8
7
|
#
|
9
|
-
# Supported styles are: module_function, extend_self
|
10
|
-
# style prohibits the usage of both styles.
|
8
|
+
# Supported styles are: `module_function` (default), `extend_self` and `forbidden`.
|
11
9
|
#
|
12
|
-
#
|
10
|
+
# A couple of things to keep in mind:
|
11
|
+
#
|
12
|
+
# - `forbidden` style prohibits the usage of both styles
|
13
|
+
# - in default mode (`module_function`), the cop won't be activated when the module
|
14
|
+
# contains any private methods
|
13
15
|
#
|
14
16
|
# @safety
|
15
17
|
# Autocorrection is unsafe (and is disabled by default) because `extend self`
|
@@ -28,7 +30,6 @@ module RuboCop
|
|
28
30
|
# # ...
|
29
31
|
# end
|
30
32
|
#
|
31
|
-
# @example EnforcedStyle: module_function (default)
|
32
33
|
# # good
|
33
34
|
# module Test
|
34
35
|
# extend self
|
@@ -37,6 +38,13 @@ module RuboCop
|
|
37
38
|
# # ...
|
38
39
|
# end
|
39
40
|
#
|
41
|
+
# # good
|
42
|
+
# module Test
|
43
|
+
# class << self
|
44
|
+
# # ...
|
45
|
+
# end
|
46
|
+
# end
|
47
|
+
#
|
40
48
|
# @example EnforcedStyle: extend_self
|
41
49
|
# # bad
|
42
50
|
# module Test
|
@@ -50,6 +58,13 @@ module RuboCop
|
|
50
58
|
# # ...
|
51
59
|
# end
|
52
60
|
#
|
61
|
+
# # good
|
62
|
+
# module Test
|
63
|
+
# class << self
|
64
|
+
# # ...
|
65
|
+
# end
|
66
|
+
# end
|
67
|
+
#
|
53
68
|
# @example EnforcedStyle: forbidden
|
54
69
|
# # bad
|
55
70
|
# module Test
|
@@ -70,6 +85,13 @@ module RuboCop
|
|
70
85
|
# private
|
71
86
|
# # ...
|
72
87
|
# end
|
88
|
+
#
|
89
|
+
# # good
|
90
|
+
# module Test
|
91
|
+
# class << self
|
92
|
+
# # ...
|
93
|
+
# end
|
94
|
+
# end
|
73
95
|
class ModuleFunction < Base
|
74
96
|
include ConfigurableEnforcedStyle
|
75
97
|
extend AutoCorrector
|
@@ -49,7 +49,8 @@ module RuboCop
|
|
49
49
|
def on_if(node)
|
50
50
|
return unless if_else?(node)
|
51
51
|
|
52
|
-
condition = node.condition
|
52
|
+
condition = unwrap_begin_nodes(node.condition)
|
53
|
+
|
53
54
|
return if double_negation?(condition) || !negated_condition?(condition)
|
54
55
|
|
55
56
|
type = node.ternary? ? 'ternary' : 'if-else'
|
@@ -71,6 +72,11 @@ module RuboCop
|
|
71
72
|
!node.elsif? && else_branch && (!else_branch.if_type? || !else_branch.elsif?)
|
72
73
|
end
|
73
74
|
|
75
|
+
def unwrap_begin_nodes(node)
|
76
|
+
node = node.children.first while node.begin_type? || node.kwbegin_type?
|
77
|
+
node
|
78
|
+
end
|
79
|
+
|
74
80
|
def negated_condition?(node)
|
75
81
|
node.send_type? &&
|
76
82
|
(node.negation_method? || NEGATED_EQUALITY_METHODS.include?(node.method_name))
|