rubocop 1.81.7 → 1.82.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/config/default.yml +21 -5
- data/config/obsoletion.yml +4 -0
- data/lib/rubocop/cli.rb +2 -1
- data/lib/rubocop/comment_config.rb +62 -17
- data/lib/rubocop/config_loader.rb +2 -1
- data/lib/rubocop/config_loader_resolver.rb +2 -2
- data/lib/rubocop/cop/autocorrect_logic.rb +4 -0
- data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -2
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +1 -3
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -2
- data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +10 -5
- data/lib/rubocop/cop/internal_affairs/location_exists.rb +28 -2
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +3 -0
- data/lib/rubocop/cop/layout/end_alignment.rb +4 -0
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +1 -4
- data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +12 -1
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
- data/lib/rubocop/cop/layout/line_length.rb +8 -4
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +2 -0
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +5 -1
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +5 -3
- data/lib/rubocop/cop/layout/space_after_comma.rb +2 -10
- data/lib/rubocop/cop/layout/space_after_semicolon.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +47 -3
- data/lib/rubocop/cop/lint/cop_directive_syntax.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +4 -4
- data/lib/rubocop/cop/lint/else_layout.rb +19 -0
- data/lib/rubocop/cop/lint/literal_as_condition.rb +4 -0
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
- data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +4 -0
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +23 -9
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -2
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +7 -1
- data/lib/rubocop/cop/lint/self_assignment.rb +9 -1
- data/lib/rubocop/cop/lint/unreachable_code.rb +5 -3
- data/lib/rubocop/cop/lint/useless_assignment.rb +44 -16
- data/lib/rubocop/cop/lint/useless_or.rb +15 -2
- data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -3
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +2 -4
- data/lib/rubocop/cop/mixin/code_length.rb +1 -1
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +1 -1
- data/lib/rubocop/cop/mixin/line_length_help.rb +21 -2
- data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
- data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +5 -4
- data/lib/rubocop/cop/mixin/statement_modifier.rb +0 -6
- data/lib/rubocop/cop/mixin/trailing_comma.rb +7 -4
- data/lib/rubocop/cop/naming/method_name.rb +1 -1
- data/lib/rubocop/cop/style/bare_percent_literals.rb +1 -2
- data/lib/rubocop/cop/style/case_equality.rb +11 -13
- data/lib/rubocop/cop/style/class_and_module_children.rb +1 -0
- data/lib/rubocop/cop/style/conditional_assignment.rb +1 -11
- data/lib/rubocop/cop/style/constant_visibility.rb +3 -3
- data/lib/rubocop/cop/style/empty_method.rb +0 -6
- data/lib/rubocop/cop/style/endless_method.rb +2 -2
- data/lib/rubocop/cop/style/guard_clause.rb +0 -11
- data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -3
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +12 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +17 -4
- data/lib/rubocop/cop/style/module_member_existence_check.rb +74 -0
- data/lib/rubocop/cop/style/multiline_method_signature.rb +2 -4
- data/lib/rubocop/cop/style/operator_method_call.rb +11 -2
- data/lib/rubocop/cop/style/parallel_assignment.rb +2 -2
- data/lib/rubocop/cop/style/redundant_argument.rb +2 -0
- data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -2
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +5 -0
- data/lib/rubocop/cop/style/redundant_sort.rb +7 -7
- data/lib/rubocop/cop/style/super_arguments.rb +2 -2
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +11 -11
- data/lib/rubocop/cop/util.rb +2 -3
- data/lib/rubocop/directive_comment.rb +46 -3
- data/lib/rubocop/formatter/disabled_config_formatter.rb +1 -0
- data/lib/rubocop/lsp/diagnostic.rb +12 -17
- data/lib/rubocop/lsp/routes.rb +9 -36
- data/lib/rubocop/lsp/runtime.rb +2 -2
- data/lib/rubocop/lsp/server.rb +2 -2
- data/lib/rubocop/magic_comment.rb +20 -0
- data/lib/rubocop/rake_task.rb +1 -1
- data/lib/rubocop/remote_config.rb +7 -8
- data/lib/rubocop/result_cache.rb +38 -27
- data/lib/rubocop/rspec/shared_contexts.rb +2 -2
- data/lib/rubocop/rspec/support.rb +1 -1
- data/lib/rubocop/runner.rb +4 -0
- data/lib/rubocop/target_ruby.rb +1 -1
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +1 -0
- metadata +8 -7
|
@@ -29,7 +29,7 @@ module RuboCop
|
|
|
29
29
|
MSG = '`%<kw_loc>s` at %<kw_loc_line>d, %<kw_loc_column>d is not ' \
|
|
30
30
|
'aligned with `%<beginning>s` at ' \
|
|
31
31
|
'%<begin_loc_line>d, %<begin_loc_column>d.'
|
|
32
|
-
ANCESTOR_TYPES = %i[kwbegin any_def class module any_block].freeze
|
|
32
|
+
ANCESTOR_TYPES = %i[kwbegin any_def class module sclass any_block].freeze
|
|
33
33
|
ALTERNATIVE_ACCESS_MODIFIERS = %i[public_class_method private_class_method].freeze
|
|
34
34
|
|
|
35
35
|
def on_resbody(node)
|
|
@@ -91,7 +91,7 @@ module RuboCop
|
|
|
91
91
|
)
|
|
92
92
|
end
|
|
93
93
|
|
|
94
|
-
# rubocop:disable Metrics/AbcSize
|
|
94
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
95
95
|
def alignment_source(node, starting_loc)
|
|
96
96
|
ending_loc =
|
|
97
97
|
case node.type
|
|
@@ -100,6 +100,8 @@ module RuboCop
|
|
|
100
100
|
when :def, :defs, :class, :module,
|
|
101
101
|
:lvasgn, :ivasgn, :cvasgn, :gvasgn, :casgn
|
|
102
102
|
node.loc.name
|
|
103
|
+
when :sclass
|
|
104
|
+
node.identifier.source_range
|
|
103
105
|
when :masgn
|
|
104
106
|
node.lhs.source_range
|
|
105
107
|
else
|
|
@@ -109,7 +111,7 @@ module RuboCop
|
|
|
109
111
|
|
|
110
112
|
range_between(starting_loc.begin_pos, ending_loc.end_pos).source
|
|
111
113
|
end
|
|
112
|
-
# rubocop:enable Metrics/AbcSize
|
|
114
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
|
113
115
|
|
|
114
116
|
# We will use ancestor or wrapper with access modifier.
|
|
115
117
|
|
|
@@ -23,16 +23,8 @@ module RuboCop
|
|
|
23
23
|
cfg['EnforcedStyle'] || 'space'
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
def kind(token)
|
|
27
|
-
'comma' if token.comma? && !
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
private
|
|
31
|
-
|
|
32
|
-
def before_semicolon?(token)
|
|
33
|
-
tokens = processed_source.tokens
|
|
34
|
-
|
|
35
|
-
tokens[tokens.index(token) + 1].semicolon?
|
|
26
|
+
def kind(token, next_token)
|
|
27
|
+
'comma' if token.comma? && !next_token.semicolon?
|
|
36
28
|
end
|
|
37
29
|
end
|
|
38
30
|
end
|
|
@@ -35,6 +35,26 @@ module RuboCop
|
|
|
35
35
|
# def cook(dry_ingredients = self.dry_ingredients)
|
|
36
36
|
# dry_ingredients.combine
|
|
37
37
|
# end
|
|
38
|
+
#
|
|
39
|
+
# # bad
|
|
40
|
+
# def foo(pie = pie = pie)
|
|
41
|
+
# pie.heat_up
|
|
42
|
+
# end
|
|
43
|
+
#
|
|
44
|
+
# # good
|
|
45
|
+
# def foo(pie)
|
|
46
|
+
# pie.heat_up
|
|
47
|
+
# end
|
|
48
|
+
#
|
|
49
|
+
# # bad
|
|
50
|
+
# def foo(pie = cake = pie)
|
|
51
|
+
# [pie, cake].each(&:heat_up)
|
|
52
|
+
# end
|
|
53
|
+
#
|
|
54
|
+
# # good
|
|
55
|
+
# def foo(cake = pie)
|
|
56
|
+
# [pie, cake].each(&:heat_up)
|
|
57
|
+
# end
|
|
38
58
|
class CircularArgumentReference < Base
|
|
39
59
|
extend TargetRubyVersion
|
|
40
60
|
|
|
@@ -51,11 +71,35 @@ module RuboCop
|
|
|
51
71
|
private
|
|
52
72
|
|
|
53
73
|
def check_for_circular_argument_references(arg_name, arg_value)
|
|
54
|
-
|
|
55
|
-
|
|
74
|
+
if arg_value.lvar_type? && arg_value.to_a == [arg_name]
|
|
75
|
+
add_offense(arg_value, message: format(MSG, arg_name: arg_name))
|
|
76
|
+
|
|
77
|
+
return
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
check_assignment_chain(arg_name, arg_value)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# rubocop:disable Metrics/AbcSize
|
|
84
|
+
def check_assignment_chain(arg_name, node)
|
|
85
|
+
return unless node.lvasgn_type?
|
|
86
|
+
|
|
87
|
+
seen_variables = Set[]
|
|
88
|
+
current_node = node
|
|
89
|
+
|
|
90
|
+
while current_node.lvasgn_type?
|
|
91
|
+
seen_variables << current_node.children.first if current_node.lvasgn_type?
|
|
92
|
+
current_node = current_node.children.last
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
return unless current_node.lvar_type?
|
|
96
|
+
|
|
97
|
+
variable_node = current_node.children.first
|
|
98
|
+
return unless seen_variables.include?(variable_node) || variable_node == arg_name
|
|
56
99
|
|
|
57
|
-
add_offense(
|
|
100
|
+
add_offense(current_node, message: format(MSG, arg_name: arg_name))
|
|
58
101
|
end
|
|
102
|
+
# rubocop:enable Metrics/AbcSize
|
|
59
103
|
end
|
|
60
104
|
end
|
|
61
105
|
end
|
|
@@ -46,7 +46,7 @@ module RuboCop
|
|
|
46
46
|
COMMON_MSG = 'Malformed directive comment detected.'
|
|
47
47
|
|
|
48
48
|
MISSING_MODE_NAME_MSG = 'The mode name is missing.'
|
|
49
|
-
INVALID_MODE_NAME_MSG = 'The mode name must be one of `enable`, `disable`, or `
|
|
49
|
+
INVALID_MODE_NAME_MSG = 'The mode name must be one of `enable`, `disable`, `todo`, `push`, or `pop`.' # rubocop:disable Layout/LineLength
|
|
50
50
|
MISSING_COP_NAME_MSG = 'The cop name is missing.'
|
|
51
51
|
MALFORMED_COP_NAMES_MSG = 'Cop names must be separated by commas. ' \
|
|
52
52
|
'Comment in the directive must start with `--`.'
|
|
@@ -25,17 +25,17 @@ module RuboCop
|
|
|
25
25
|
#
|
|
26
26
|
# # bad - repeated alternate patterns with the same conditions don't depend on the order
|
|
27
27
|
# case x
|
|
28
|
-
# in
|
|
28
|
+
# in 0 | 1
|
|
29
29
|
# first_method
|
|
30
|
-
# in
|
|
30
|
+
# in 1 | 0
|
|
31
31
|
# second_method
|
|
32
32
|
# end
|
|
33
33
|
#
|
|
34
34
|
# # good
|
|
35
35
|
# case x
|
|
36
|
-
# in
|
|
36
|
+
# in 0 | 1
|
|
37
37
|
# first_method
|
|
38
|
-
# in
|
|
38
|
+
# in 2 | 3
|
|
39
39
|
# second_method
|
|
40
40
|
# end
|
|
41
41
|
#
|
|
@@ -38,6 +38,24 @@ module RuboCop
|
|
|
38
38
|
# elsif do_this
|
|
39
39
|
# do_that
|
|
40
40
|
# end
|
|
41
|
+
#
|
|
42
|
+
# # bad
|
|
43
|
+
#
|
|
44
|
+
# # For single-line conditionals using `then` the layout is disallowed
|
|
45
|
+
# # when the `else` body is multiline because it is treated as a lint offense.
|
|
46
|
+
# if something then on_the_same_line_as_then
|
|
47
|
+
# else first_line
|
|
48
|
+
# second_line
|
|
49
|
+
# end
|
|
50
|
+
#
|
|
51
|
+
# # good
|
|
52
|
+
#
|
|
53
|
+
# # For single-line conditional using `then` the layout is allowed
|
|
54
|
+
# # when `else` body is a single-line because it is treated as intentional.
|
|
55
|
+
#
|
|
56
|
+
# if something then on_the_same_line_as_then
|
|
57
|
+
# else single_line
|
|
58
|
+
# end
|
|
41
59
|
class ElseLayout < Base
|
|
42
60
|
include Alignment
|
|
43
61
|
include RangeHelp
|
|
@@ -47,6 +65,7 @@ module RuboCop
|
|
|
47
65
|
|
|
48
66
|
def on_if(node)
|
|
49
67
|
return if node.ternary?
|
|
68
|
+
return if node.then? && !node.else_branch&.begin_type?
|
|
50
69
|
|
|
51
70
|
# If the if is on a single line, it'll be handled by `Style/OneLineConditional`
|
|
52
71
|
return if node.single_line?
|
|
@@ -269,7 +269,11 @@ module RuboCop
|
|
|
269
269
|
end
|
|
270
270
|
|
|
271
271
|
add_offense(cond) do |corrector|
|
|
272
|
+
next if part_of_ignored_node?(node)
|
|
273
|
+
|
|
272
274
|
corrector.replace(node, new_node)
|
|
275
|
+
|
|
276
|
+
ignore_node(node)
|
|
273
277
|
end
|
|
274
278
|
end
|
|
275
279
|
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
@@ -66,7 +66,7 @@ module RuboCop
|
|
|
66
66
|
|
|
67
67
|
def special_keyword?(node)
|
|
68
68
|
# handle strings like __FILE__
|
|
69
|
-
(node.str_type? && !node.loc
|
|
69
|
+
(node.str_type? && !node.loc?(:begin)) || node.source_range.is?('__LINE__')
|
|
70
70
|
end
|
|
71
71
|
|
|
72
72
|
def array_in_regexp?(node)
|
|
@@ -112,22 +112,36 @@ module RuboCop
|
|
|
112
112
|
|
|
113
113
|
def each_line_range(cop, line_ranges)
|
|
114
114
|
line_ranges.each_with_index do |line_range, line_range_index|
|
|
115
|
-
next if
|
|
116
|
-
next if expected_final_disable?(cop, line_range)
|
|
115
|
+
next if should_skip_line_range?(cop, line_range)
|
|
117
116
|
|
|
118
117
|
comment = processed_source.comment_at_line(line_range.begin)
|
|
119
|
-
|
|
120
|
-
find_redundant_all(line_range, line_ranges[line_range_index + 1])
|
|
121
|
-
elsif department_disabled?(cop, comment)
|
|
122
|
-
find_redundant_department(cop, line_range)
|
|
123
|
-
else
|
|
124
|
-
find_redundant_cop(cop, line_range)
|
|
125
|
-
end
|
|
118
|
+
next if skip_directive?(comment)
|
|
126
119
|
|
|
120
|
+
next_range = line_ranges[line_range_index + 1]
|
|
121
|
+
redundant = find_redundant_directive(cop, comment, line_range, next_range)
|
|
127
122
|
yield comment, redundant if redundant
|
|
128
123
|
end
|
|
129
124
|
end
|
|
130
125
|
|
|
126
|
+
def should_skip_line_range?(cop, line_range)
|
|
127
|
+
ignore_offense?(line_range) || expected_final_disable?(cop, line_range)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def skip_directive?(comment)
|
|
131
|
+
directive = DirectiveComment.new(comment)
|
|
132
|
+
directive.push? || directive.pop?
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def find_redundant_directive(cop, comment, line_range, next_range)
|
|
136
|
+
if all_disabled?(comment)
|
|
137
|
+
find_redundant_all(line_range, next_range)
|
|
138
|
+
elsif department_disabled?(cop, comment)
|
|
139
|
+
find_redundant_department(cop, line_range)
|
|
140
|
+
else
|
|
141
|
+
find_redundant_cop(cop, line_range)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
131
145
|
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
132
146
|
def each_already_disabled(cop, line_ranges)
|
|
133
147
|
line_ranges.each_cons(2) do |previous_range, range|
|
|
@@ -19,7 +19,8 @@ module RuboCop
|
|
|
19
19
|
# * 2.2+ ... Add `rational` and `complex` above
|
|
20
20
|
# * 2.7+ ... Add `ruby2_keywords` above
|
|
21
21
|
# * 3.1+ ... Add `fiber` above
|
|
22
|
-
# * 3.2+ ... `set`
|
|
22
|
+
# * 3.2+ ... Add `set` above
|
|
23
|
+
# * 4.0+ ... Add `pathname` above
|
|
23
24
|
#
|
|
24
25
|
# This cop target those features.
|
|
25
26
|
#
|
|
@@ -69,7 +70,8 @@ module RuboCop
|
|
|
69
70
|
(target_ruby_version >= 2.2 && RUBY_22_LOADED_FEATURES.include?(feature_name)) ||
|
|
70
71
|
(target_ruby_version >= 2.7 && feature_name == 'ruby2_keywords') ||
|
|
71
72
|
(target_ruby_version >= 3.1 && feature_name == 'fiber') ||
|
|
72
|
-
(target_ruby_version >= 3.2 && feature_name == 'set')
|
|
73
|
+
(target_ruby_version >= 3.2 && feature_name == 'set') ||
|
|
74
|
+
(target_ruby_version >= 4.0 && feature_name == 'pathname')
|
|
73
75
|
end
|
|
74
76
|
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
75
77
|
end
|
|
@@ -144,7 +144,9 @@ module RuboCop
|
|
|
144
144
|
expression = node.parent.source_range if node.parent.array_type?
|
|
145
145
|
[expression, variable.source]
|
|
146
146
|
elsif !variable.array_type?
|
|
147
|
-
|
|
147
|
+
replacement = variable.source
|
|
148
|
+
replacement = "[#{replacement}]" if wrap_in_brackets?(node)
|
|
149
|
+
[expression, replacement]
|
|
148
150
|
elsif redundant_brackets?(node)
|
|
149
151
|
[expression, remove_brackets(variable)]
|
|
150
152
|
else
|
|
@@ -176,6 +178,10 @@ module RuboCop
|
|
|
176
178
|
grandparent&.resbody_type?
|
|
177
179
|
end
|
|
178
180
|
|
|
181
|
+
def wrap_in_brackets?(node)
|
|
182
|
+
node.parent.array_type? && !node.parent.bracketed?
|
|
183
|
+
end
|
|
184
|
+
|
|
179
185
|
def remove_brackets(array)
|
|
180
186
|
array_start = array.loc.begin.source
|
|
181
187
|
elements = *array
|
|
@@ -23,7 +23,15 @@ module RuboCop
|
|
|
23
23
|
# # good (method calls possibly can return different results)
|
|
24
24
|
# hash[foo] = hash[foo]
|
|
25
25
|
#
|
|
26
|
-
# @example AllowRBSInlineAnnotation:
|
|
26
|
+
# @example AllowRBSInlineAnnotation: false (default)
|
|
27
|
+
# # bad
|
|
28
|
+
# foo = foo #: Integer
|
|
29
|
+
# foo, bar = foo, bar #: Integer
|
|
30
|
+
# Foo = Foo #: Integer
|
|
31
|
+
# hash['foo'] = hash['foo'] #: Integer
|
|
32
|
+
# obj.attr = obj.attr #: Integer
|
|
33
|
+
#
|
|
34
|
+
# @example AllowRBSInlineAnnotation: true
|
|
27
35
|
# # good
|
|
28
36
|
# foo = foo #: Integer
|
|
29
37
|
# foo, bar = foo, bar #: Integer
|
|
@@ -78,6 +78,7 @@ module RuboCop
|
|
|
78
78
|
}
|
|
79
79
|
PATTERN
|
|
80
80
|
|
|
81
|
+
# rubocop:disable Metrics/MethodLength
|
|
81
82
|
def flow_expression?(node)
|
|
82
83
|
return report_on_flow_command?(node) if flow_command?(node)
|
|
83
84
|
|
|
@@ -89,12 +90,14 @@ module RuboCop
|
|
|
89
90
|
check_if(node)
|
|
90
91
|
when :case, :case_match
|
|
91
92
|
check_case(node)
|
|
92
|
-
when :def
|
|
93
|
+
when :def, :defs
|
|
93
94
|
register_redefinition(node)
|
|
95
|
+
false
|
|
94
96
|
else
|
|
95
97
|
false
|
|
96
98
|
end
|
|
97
99
|
end
|
|
100
|
+
# rubocop:enable Metrics/MethodLength
|
|
98
101
|
|
|
99
102
|
def check_if(node)
|
|
100
103
|
if_branch = node.if_branch
|
|
@@ -113,8 +116,7 @@ module RuboCop
|
|
|
113
116
|
end
|
|
114
117
|
|
|
115
118
|
def register_redefinition(node)
|
|
116
|
-
@redefined << node.method_name if redefinable_flow_method?
|
|
117
|
-
false
|
|
119
|
+
@redefined << node.method_name if redefinable_flow_method?(node.method_name)
|
|
118
120
|
end
|
|
119
121
|
|
|
120
122
|
def instance_eval_block?(node)
|
|
@@ -52,32 +52,39 @@ module RuboCop
|
|
|
52
52
|
scope.variables.each_value { |variable| check_for_unused_assignments(variable) }
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
-
# rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
|
|
56
55
|
def check_for_unused_assignments(variable)
|
|
57
56
|
return if variable.should_be_unused?
|
|
58
57
|
|
|
59
58
|
variable.assignments.reverse_each do |assignment|
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
check_for_unused_assignment(variable, assignment)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
def check_for_unused_assignment(variable, assignment)
|
|
64
|
+
assignment_node = assignment.node
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
# In cases like `x = 1, y = 2`, where removing a variable would cause a syntax error,
|
|
68
|
-
# and where changing `x ||= 1` to `x = 1` would cause `NameError`,
|
|
69
|
-
# the autocorrect will be skipped, even if the variable is unused.
|
|
70
|
-
if sequential_assignment?(assignment_node) || assignment_node.parent&.or_asgn_type?
|
|
71
|
-
next
|
|
72
|
-
end
|
|
66
|
+
return if ignored_assignment?(variable, assignment_node, assignment)
|
|
73
67
|
|
|
74
|
-
|
|
75
|
-
|
|
68
|
+
message = message_for_useless_assignment(assignment)
|
|
69
|
+
range = offense_range(assignment)
|
|
76
70
|
|
|
77
|
-
|
|
71
|
+
add_offense(range, message: message) do |corrector|
|
|
72
|
+
# In cases like `x = 1, y = 2`, where removing a variable would cause a syntax error,
|
|
73
|
+
# and where changing `x ||= 1` to `x = 1` would cause `NameError`,
|
|
74
|
+
# the autocorrect will be skipped, even if the variable is unused.
|
|
75
|
+
next if sequential_assignment?(assignment_node) ||
|
|
76
|
+
assignment_node.parent&.or_asgn_type?
|
|
77
|
+
|
|
78
|
+
autocorrect(corrector, assignment)
|
|
78
79
|
end
|
|
80
|
+
|
|
81
|
+
ignore_node(assignment_node) if chained_assignment?(assignment_node)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def ignored_assignment?(variable, assignment_node, assignment)
|
|
85
|
+
assignment.used? || part_of_ignored_node?(assignment_node) ||
|
|
86
|
+
variable_in_loop_condition?(assignment_node, variable)
|
|
79
87
|
end
|
|
80
|
-
# rubocop:enable Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
|
|
81
88
|
|
|
82
89
|
def message_for_useless_assignment(assignment)
|
|
83
90
|
variable = assignment.variable
|
|
@@ -208,6 +215,27 @@ module RuboCop
|
|
|
208
215
|
def remove_local_variable_assignment_part(corrector, node)
|
|
209
216
|
corrector.replace(node, node.expression.source)
|
|
210
217
|
end
|
|
218
|
+
|
|
219
|
+
def variable_in_loop_condition?(assignment_node, variable)
|
|
220
|
+
return false if assignment_node.each_ancestor(:any_def).any?
|
|
221
|
+
|
|
222
|
+
loop_node = assignment_node.each_ancestor.find do |ancestor|
|
|
223
|
+
ancestor.type?(*VariableForce::LOOP_TYPES)
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
return false unless loop_node.respond_to?(:condition)
|
|
227
|
+
|
|
228
|
+
condition_node = loop_node.condition
|
|
229
|
+
variable_name = variable.name
|
|
230
|
+
|
|
231
|
+
return true if condition_node.lvar_type? && condition_node.children.first == variable_name
|
|
232
|
+
|
|
233
|
+
condition_node.each_descendant(:lvar) do |lvar_node|
|
|
234
|
+
return true if lvar_node.children.first == variable_name
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
false
|
|
238
|
+
end
|
|
211
239
|
end
|
|
212
240
|
end
|
|
213
241
|
end
|
|
@@ -9,6 +9,13 @@ module RuboCop
|
|
|
9
9
|
# on `nil` (e.g. `nil.to_i` evaluates to `0`). Therefore, OR expressions
|
|
10
10
|
# appended after these methods will never evaluate.
|
|
11
11
|
#
|
|
12
|
+
# @safety
|
|
13
|
+
# As shown in the examples below, there are generally two possible ways to correct the
|
|
14
|
+
# offense, but this cop’s autocorrection always chooses the option that preserves the
|
|
15
|
+
# current behavior. While this does not change how the code behaves, that option is not
|
|
16
|
+
# necessarily the appropriate fix in every situation. For this reason, the autocorrection
|
|
17
|
+
# provided by this cop is considered unsafe.
|
|
18
|
+
#
|
|
12
19
|
# @example
|
|
13
20
|
#
|
|
14
21
|
# # bad
|
|
@@ -64,6 +71,8 @@ module RuboCop
|
|
|
64
71
|
# x&.to_s or fallback
|
|
65
72
|
#
|
|
66
73
|
class UselessOr < Base
|
|
74
|
+
extend AutoCorrector
|
|
75
|
+
|
|
67
76
|
MSG = '`%<rhs>s` will never evaluate because `%<lhs>s` always returns a truthy value.'
|
|
68
77
|
|
|
69
78
|
TRUTHY_RETURN_VALUE_METHODS = Set[:to_a, :to_c, :to_d, :to_i, :to_f, :to_h, :to_r,
|
|
@@ -89,8 +98,12 @@ module RuboCop
|
|
|
89
98
|
private
|
|
90
99
|
|
|
91
100
|
def report_offense(or_node, truthy_node)
|
|
92
|
-
add_offense(
|
|
93
|
-
|
|
101
|
+
add_offense(
|
|
102
|
+
or_node.loc.operator.join(or_node.rhs.source_range),
|
|
103
|
+
message: format(MSG, lhs: truthy_node.source, rhs: or_node.rhs.source)
|
|
104
|
+
) do |corrector|
|
|
105
|
+
corrector.replace(or_node, or_node.lhs.source)
|
|
106
|
+
end
|
|
94
107
|
end
|
|
95
108
|
end
|
|
96
109
|
end
|
|
@@ -84,7 +84,10 @@ module RuboCop
|
|
|
84
84
|
end
|
|
85
85
|
|
|
86
86
|
def assignment?(node)
|
|
87
|
-
|
|
87
|
+
if node.masgn_type? || node.shorthand_asgn?
|
|
88
|
+
compound_assignment(node)
|
|
89
|
+
return false
|
|
90
|
+
end
|
|
88
91
|
|
|
89
92
|
node.for_type? ||
|
|
90
93
|
(node.respond_to?(:setter_method?) && node.setter_method?) ||
|
|
@@ -101,8 +104,6 @@ module RuboCop
|
|
|
101
104
|
child.respond_to?(:setter_method?) && !child.setter_method?
|
|
102
105
|
end
|
|
103
106
|
@assignment += will_be_miscounted
|
|
104
|
-
|
|
105
|
-
false
|
|
106
107
|
end
|
|
107
108
|
|
|
108
109
|
def simple_assignment?(node)
|
|
@@ -14,6 +14,8 @@ module RuboCop
|
|
|
14
14
|
private
|
|
15
15
|
|
|
16
16
|
def too_long?(node)
|
|
17
|
+
return false unless max_line_length
|
|
18
|
+
|
|
17
19
|
lines = processed_source.lines[(node.first_line - 1)...node.last_line]
|
|
18
20
|
to_single_line(lines.join("\n")).length > max_line_length
|
|
19
21
|
end
|
|
@@ -27,10 +29,6 @@ module RuboCop
|
|
|
27
29
|
.gsub(/\s*\\?\n\s*/, ' ') # Any other line break, with or without backslash
|
|
28
30
|
end
|
|
29
31
|
|
|
30
|
-
def max_line_length
|
|
31
|
-
config.for_cop('Layout/LineLength')['Max']
|
|
32
|
-
end
|
|
33
|
-
|
|
34
32
|
def comment_within?(node)
|
|
35
33
|
comment_line_numbers = processed_source.comments.map { |comment| comment.loc.line }
|
|
36
34
|
|
|
@@ -59,7 +59,7 @@ module RuboCop
|
|
|
59
59
|
return node.loc.name if node.casgn_type?
|
|
60
60
|
|
|
61
61
|
if LSP.enabled?
|
|
62
|
-
end_range = node.loc
|
|
62
|
+
end_range = node.loc?(:name) ? node.loc.name : node.loc.begin
|
|
63
63
|
node.source_range.begin.join(end_range)
|
|
64
64
|
else
|
|
65
65
|
node.source_range
|
|
@@ -8,8 +8,27 @@ module RuboCop
|
|
|
8
8
|
|
|
9
9
|
private
|
|
10
10
|
|
|
11
|
-
def
|
|
12
|
-
config.for_cop('Layout/LineLength')['
|
|
11
|
+
def allow_rbs_inline_annotation?
|
|
12
|
+
config.for_cop('Layout/LineLength')['AllowRBSInlineAnnotation']
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def rbs_inline_annotation_on_source_line?(line_index)
|
|
16
|
+
source_line_number = line_index + processed_source.buffer.first_line
|
|
17
|
+
comment = processed_source.comment_at_line(source_line_number)
|
|
18
|
+
|
|
19
|
+
return false unless comment
|
|
20
|
+
|
|
21
|
+
comment.text.start_with?(/#:|#\[.+\]|#\|/)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def allow_cop_directives?
|
|
25
|
+
# TODO: This logic for backward compatibility with deprecated `IgnoreCopDirectives` option.
|
|
26
|
+
# The following three lines will be removed in RuboCop 2.0.
|
|
27
|
+
ignore_cop_directives = config.for_cop('Layout/LineLength')['IgnoreCopDirectives']
|
|
28
|
+
return true if ignore_cop_directives
|
|
29
|
+
return false if ignore_cop_directives == false
|
|
30
|
+
|
|
31
|
+
config.for_cop('Layout/LineLength')['AllowCopDirectives']
|
|
13
32
|
end
|
|
14
33
|
|
|
15
34
|
def directive_on_source_line?(line_index)
|
|
@@ -73,7 +73,7 @@ module RuboCop
|
|
|
73
73
|
|
|
74
74
|
def location(node)
|
|
75
75
|
if LSP.enabled?
|
|
76
|
-
end_range = node.loc
|
|
76
|
+
end_range = node.loc?(:name) ? node.loc.name : node.loc.begin
|
|
77
77
|
node.source_range.begin.join(end_range)
|
|
78
78
|
else
|
|
79
79
|
node.source_range
|
|
@@ -200,7 +200,7 @@ module RuboCop
|
|
|
200
200
|
end
|
|
201
201
|
|
|
202
202
|
def grouped_expression?(node)
|
|
203
|
-
node.begin_type? && node.loc
|
|
203
|
+
node.begin_type? && node.loc?(:begin) && node.loc.begin
|
|
204
204
|
end
|
|
205
205
|
|
|
206
206
|
def inside_arg_list_parentheses?(node, ancestor)
|
|
@@ -8,8 +8,8 @@ module RuboCop
|
|
|
8
8
|
MSG = 'Space missing after %<token>s.'
|
|
9
9
|
|
|
10
10
|
def on_new_investigation
|
|
11
|
-
each_missing_space(processed_source.tokens) do |token|
|
|
12
|
-
add_offense(token.pos, message: format(MSG, token: kind
|
|
11
|
+
each_missing_space(processed_source.tokens) do |token, kind|
|
|
12
|
+
add_offense(token.pos, message: format(MSG, token: kind)) do |corrector|
|
|
13
13
|
PunctuationCorrector.add_space(corrector, token)
|
|
14
14
|
end
|
|
15
15
|
end
|
|
@@ -19,11 +19,12 @@ module RuboCop
|
|
|
19
19
|
|
|
20
20
|
def each_missing_space(tokens)
|
|
21
21
|
tokens.each_cons(2) do |token1, token2|
|
|
22
|
-
|
|
22
|
+
kind = kind(token1, token2)
|
|
23
|
+
next unless kind
|
|
23
24
|
next unless space_missing?(token1, token2)
|
|
24
25
|
next unless space_required_before?(token2)
|
|
25
26
|
|
|
26
|
-
yield token1
|
|
27
|
+
yield token1, kind
|
|
27
28
|
end
|
|
28
29
|
end
|
|
29
30
|
|