rubocop 1.79.2 → 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 +35 -7
- data/config/obsoletion.yml +4 -0
- data/exe/rubocop +1 -8
- data/lib/rubocop/cli/command/auto_generate_config.rb +2 -2
- data/lib/rubocop/cli.rb +8 -3
- data/lib/rubocop/comment_config.rb +62 -17
- data/lib/rubocop/config_loader.rb +5 -2
- data/lib/rubocop/config_loader_resolver.rb +7 -6
- data/lib/rubocop/config_store.rb +5 -0
- data/lib/rubocop/cop/autocorrect_logic.rb +8 -4
- data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -2
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +8 -7
- data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +7 -2
- 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/internal_affairs/node_pattern_groups.rb +3 -1
- data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +1 -1
- data/lib/rubocop/cop/layout/class_structure.rb +1 -1
- data/lib/rubocop/cop/layout/dot_position.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +3 -0
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +30 -12
- data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +1 -1
- data/lib/rubocop/cop/layout/end_alignment.rb +4 -0
- data/lib/rubocop/cop/layout/hash_alignment.rb +2 -5
- 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 +17 -5
- 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/multiline_operation_indentation.rb +8 -4
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +13 -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/layout/trailing_whitespace.rb +1 -1
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +47 -3
- data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +3 -2
- data/lib/rubocop/cop/lint/cop_directive_syntax.rb +14 -8
- data/lib/rubocop/cop/lint/debugger.rb +0 -2
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +4 -1
- data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +4 -4
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +5 -42
- data/lib/rubocop/cop/lint/else_layout.rb +19 -0
- data/lib/rubocop/cop/lint/empty_interpolation.rb +11 -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/missing_cop_enable_directive.rb +17 -8
- 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/rescue_exception.rb +1 -4
- data/lib/rubocop/cop/lint/self_assignment.rb +15 -6
- data/lib/rubocop/cop/lint/shadowed_argument.rb +7 -7
- data/lib/rubocop/cop/lint/unreachable_code.rb +5 -3
- data/lib/rubocop/cop/lint/uri_escape_unescape.rb +2 -0
- 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/lint/void.rb +7 -0
- data/lib/rubocop/cop/message_annotator.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -3
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
- 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/end_keyword_alignment.rb +1 -7
- 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 +8 -5
- data/lib/rubocop/cop/naming/method_name.rb +5 -3
- data/lib/rubocop/cop/naming/predicate_method.rb +19 -6
- data/lib/rubocop/cop/security/json_load.rb +33 -11
- data/lib/rubocop/cop/style/array_intersect.rb +46 -12
- data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +47 -0
- data/lib/rubocop/cop/style/bare_percent_literals.rb +1 -2
- data/lib/rubocop/cop/style/bitwise_predicate.rb +8 -1
- 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 +8 -14
- data/lib/rubocop/cop/style/constant_visibility.rb +17 -12
- data/lib/rubocop/cop/style/double_negation.rb +1 -1
- data/lib/rubocop/cop/style/empty_method.rb +0 -6
- data/lib/rubocop/cop/style/endless_method.rb +15 -2
- data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
- data/lib/rubocop/cop/style/float_division.rb +15 -1
- data/lib/rubocop/cop/style/guard_clause.rb +0 -11
- data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
- data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -3
- data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
- 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/nil_comparison.rb +9 -7
- data/lib/rubocop/cop/style/one_line_conditional.rb +17 -9
- 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_begin.rb +34 -0
- data/lib/rubocop/cop/style/redundant_condition.rb +1 -1
- data/lib/rubocop/cop/style/redundant_exception.rb +1 -1
- data/lib/rubocop/cop/style/redundant_format.rb +26 -5
- data/lib/rubocop/cop/style/redundant_interpolation.rb +11 -2
- data/lib/rubocop/cop/style/redundant_parentheses.rb +14 -11
- data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -2
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +9 -0
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -0
- data/lib/rubocop/cop/style/redundant_sort.rb +7 -7
- data/lib/rubocop/cop/style/safe_navigation.rb +18 -1
- data/lib/rubocop/cop/style/semicolon.rb +23 -7
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +8 -1
- data/lib/rubocop/cop/style/string_concatenation.rb +17 -13
- data/lib/rubocop/cop/style/super_arguments.rb +2 -2
- data/lib/rubocop/cop/style/symbol_array.rb +1 -1
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +45 -0
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +11 -11
- data/lib/rubocop/cop/style/unless_else.rb +10 -9
- data/lib/rubocop/cop/util.rb +2 -3
- data/lib/rubocop/cop/utils/format_string.rb +10 -0
- data/lib/rubocop/cop/variable_force/variable.rb +1 -1
- data/lib/rubocop/cop/variable_force.rb +9 -7
- data/lib/rubocop/cops_documentation_generator.rb +4 -4
- data/lib/rubocop/directive_comment.rb +46 -3
- data/lib/rubocop/formatter/disabled_config_formatter.rb +19 -5
- data/lib/rubocop/lsp/diagnostic.rb +10 -14
- data/lib/rubocop/lsp/routes.rb +31 -2
- data/lib/rubocop/lsp/stdin_runner.rb +0 -16
- 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 +39 -28
- data/lib/rubocop/rspec/shared_contexts.rb +2 -2
- data/lib/rubocop/rspec/support.rb +1 -1
- data/lib/rubocop/runner.rb +10 -4
- data/lib/rubocop/target_finder.rb +9 -9
- data/lib/rubocop/target_ruby.rb +11 -2
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +2 -0
- data/lib/ruby_lsp/rubocop/addon.rb +23 -8
- data/lib/ruby_lsp/rubocop/runtime_adapter.rb +49 -15
- metadata +9 -7
|
@@ -13,34 +13,40 @@ module RuboCop
|
|
|
13
13
|
# @example
|
|
14
14
|
# # bad
|
|
15
15
|
# # rubocop:disable Layout/LineLength Style/Encoding
|
|
16
|
-
#
|
|
16
|
+
#
|
|
17
|
+
# # good
|
|
18
|
+
# # rubocop:disable Layout/LineLength, Style/Encoding
|
|
17
19
|
#
|
|
18
20
|
# # bad
|
|
19
21
|
# # rubocop:disable
|
|
20
22
|
#
|
|
23
|
+
# # good
|
|
24
|
+
# # rubocop:disable all
|
|
25
|
+
#
|
|
21
26
|
# # bad
|
|
22
27
|
# # rubocop:disable Layout/LineLength # rubocop:disable Style/Encoding
|
|
23
28
|
#
|
|
29
|
+
# # good
|
|
30
|
+
# # rubocop:disable Layout/LineLength
|
|
31
|
+
# # rubocop:disable Style/Encoding
|
|
32
|
+
#
|
|
24
33
|
# # bad
|
|
25
34
|
# # rubocop:wrongmode Layout/LineLength
|
|
26
35
|
#
|
|
27
36
|
# # good
|
|
28
37
|
# # rubocop:disable Layout/LineLength
|
|
29
38
|
#
|
|
30
|
-
# #
|
|
31
|
-
# # rubocop:disable Layout/LineLength
|
|
32
|
-
#
|
|
33
|
-
# # good
|
|
34
|
-
# # rubocop:disable all
|
|
39
|
+
# # bad
|
|
40
|
+
# # rubocop:disable Layout/LineLength comment
|
|
35
41
|
#
|
|
36
42
|
# # good
|
|
37
|
-
# # rubocop:disable Layout/LineLength --
|
|
43
|
+
# # rubocop:disable Layout/LineLength -- comment
|
|
38
44
|
#
|
|
39
45
|
class CopDirectiveSyntax < Base
|
|
40
46
|
COMMON_MSG = 'Malformed directive comment detected.'
|
|
41
47
|
|
|
42
48
|
MISSING_MODE_NAME_MSG = 'The mode name is missing.'
|
|
43
|
-
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
|
|
44
50
|
MISSING_COP_NAME_MSG = 'The cop name is missing.'
|
|
45
51
|
MALFORMED_COP_NAMES_MSG = 'Cop names must be separated by commas. ' \
|
|
46
52
|
'Comment in the directive must start with `--`.'
|
|
@@ -118,8 +118,11 @@ module RuboCop
|
|
|
118
118
|
|
|
119
119
|
def replacement_args(node)
|
|
120
120
|
algorithm_constant, = algorithm_const(node)
|
|
121
|
-
|
|
121
|
+
if algorithm_constant.source == 'OpenSSL::Cipher::Cipher'
|
|
122
|
+
return node.first_argument.source
|
|
123
|
+
end
|
|
122
124
|
|
|
125
|
+
algorithm_name = algorithm_name(algorithm_constant)
|
|
123
126
|
if openssl_class(algorithm_constant) == 'OpenSSL::Cipher'
|
|
124
127
|
build_cipher_arguments(node, algorithm_name, node.arguments.empty?)
|
|
125
128
|
else
|
|
@@ -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
|
#
|
|
@@ -24,8 +24,6 @@ module RuboCop
|
|
|
24
24
|
|
|
25
25
|
MSG_REPEATED_ELEMENT = 'Duplicate element inside regexp character class'
|
|
26
26
|
|
|
27
|
-
OCTAL_DIGITS_AFTER_ESCAPE = 2
|
|
28
|
-
|
|
29
27
|
def on_regexp(node)
|
|
30
28
|
each_repeated_character_class_element_loc(node) do |loc|
|
|
31
29
|
add_offense(loc, message: MSG_REPEATED_ELEMENT) do |corrector|
|
|
@@ -40,9 +38,9 @@ module RuboCop
|
|
|
40
38
|
|
|
41
39
|
seen = Set.new
|
|
42
40
|
group_expressions(node, expr.expressions) do |group|
|
|
43
|
-
group_source = group.
|
|
41
|
+
group_source = group.to_s
|
|
44
42
|
|
|
45
|
-
yield
|
|
43
|
+
yield group.expression if seen.include?(group_source)
|
|
46
44
|
|
|
47
45
|
seen << group_source
|
|
48
46
|
end
|
|
@@ -52,40 +50,13 @@ module RuboCop
|
|
|
52
50
|
private
|
|
53
51
|
|
|
54
52
|
def group_expressions(node, expressions)
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
until expressions.empty?
|
|
59
|
-
# With we may need to compose a group of multiple expressions.
|
|
60
|
-
group = [expressions.shift]
|
|
61
|
-
next if within_interpolation?(node, group.first)
|
|
62
|
-
|
|
63
|
-
# With regexp_parser < 2.7 escaped octal sequences may be up to 3
|
|
64
|
-
# separate expressions ("\\0", "0", "1").
|
|
65
|
-
pop_octal_digits(group, expressions) if escaped_octal?(group.first.to_s)
|
|
66
|
-
|
|
67
|
-
yield(group)
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def pop_octal_digits(current_child, expressions)
|
|
72
|
-
OCTAL_DIGITS_AFTER_ESCAPE.times do
|
|
73
|
-
next_child = expressions.first
|
|
74
|
-
break unless octal?(next_child.to_s)
|
|
53
|
+
expressions.each do |expression|
|
|
54
|
+
next if within_interpolation?(node, expression)
|
|
75
55
|
|
|
76
|
-
|
|
56
|
+
yield(expression)
|
|
77
57
|
end
|
|
78
58
|
end
|
|
79
59
|
|
|
80
|
-
def source_range(children)
|
|
81
|
-
return children.first.expression if children.size == 1
|
|
82
|
-
|
|
83
|
-
range_between(
|
|
84
|
-
children.first.expression.begin_pos,
|
|
85
|
-
children.last.expression.begin_pos + children.last.to_s.length
|
|
86
|
-
)
|
|
87
|
-
end
|
|
88
|
-
|
|
89
60
|
def skip_expression?(expr)
|
|
90
61
|
expr.type != :set || expr.token == :intersection
|
|
91
62
|
end
|
|
@@ -99,14 +70,6 @@ module RuboCop
|
|
|
99
70
|
interpolation_locs(node).any? { |il| il.overlaps?(parse_tree_child_loc) }
|
|
100
71
|
end
|
|
101
72
|
|
|
102
|
-
def escaped_octal?(string)
|
|
103
|
-
string.length == 2 && string[0] == '\\' && octal?(string[1])
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
def octal?(char)
|
|
107
|
-
('0'..'7').cover?(char)
|
|
108
|
-
end
|
|
109
|
-
|
|
110
73
|
def interpolation_locs(node)
|
|
111
74
|
@interpolation_locs ||= {}
|
|
112
75
|
|
|
@@ -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?
|
|
@@ -19,12 +19,23 @@ module RuboCop
|
|
|
19
19
|
MSG = 'Empty interpolation detected.'
|
|
20
20
|
|
|
21
21
|
def on_interpolation(begin_node)
|
|
22
|
+
return if in_percent_literal_array?(begin_node)
|
|
23
|
+
|
|
22
24
|
node_children = begin_node.children.dup
|
|
23
25
|
node_children.delete_if { |e| e.nil_type? || (e.basic_literal? && e.str_content&.empty?) }
|
|
24
26
|
return unless node_children.empty?
|
|
25
27
|
|
|
26
28
|
add_offense(begin_node) { |corrector| corrector.remove(begin_node) }
|
|
27
29
|
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def in_percent_literal_array?(begin_node)
|
|
34
|
+
array_node = begin_node.each_ancestor(:array).first
|
|
35
|
+
return false unless array_node
|
|
36
|
+
|
|
37
|
+
array_node.percent_literal?
|
|
38
|
+
end
|
|
28
39
|
end
|
|
29
40
|
end
|
|
30
41
|
end
|
|
@@ -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)
|
|
@@ -9,9 +9,21 @@ module RuboCop
|
|
|
9
9
|
# cop disables on wide ranges of code, that latter contributors to
|
|
10
10
|
# a file wouldn't be aware of.
|
|
11
11
|
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
12
|
+
# You can set `MaximumRangeSize` to define the maximum number of
|
|
13
|
+
# consecutive lines a cop can be disabled for.
|
|
14
|
+
#
|
|
15
|
+
# - `.inf` any size (default)
|
|
16
|
+
# - `0` allows only single-line disables
|
|
17
|
+
# - `1` means the maximum allowed is as follows:
|
|
18
|
+
#
|
|
19
|
+
# [source,ruby]
|
|
20
|
+
# ----
|
|
21
|
+
# # rubocop:disable SomeCop
|
|
22
|
+
# a = 1
|
|
23
|
+
# # rubocop:enable SomeCop
|
|
24
|
+
# ----
|
|
25
|
+
#
|
|
26
|
+
# @example MaximumRangeSize: .inf (default)
|
|
15
27
|
#
|
|
16
28
|
# # good
|
|
17
29
|
# # rubocop:disable Layout/SpaceAroundOperators
|
|
@@ -25,9 +37,7 @@ module RuboCop
|
|
|
25
37
|
# x= 0
|
|
26
38
|
# # EOF
|
|
27
39
|
#
|
|
28
|
-
# @example
|
|
29
|
-
# # Lint/MissingCopEnableDirective:
|
|
30
|
-
# # MaximumRangeSize: 2
|
|
40
|
+
# @example MaximumRangeSize: 2
|
|
31
41
|
#
|
|
32
42
|
# # good
|
|
33
43
|
# # rubocop:disable Layout/SpaceAroundOperators
|
|
@@ -52,10 +62,9 @@ module RuboCop
|
|
|
52
62
|
each_missing_enable do |cop, line_range|
|
|
53
63
|
next if acceptable_range?(cop, line_range)
|
|
54
64
|
|
|
55
|
-
range = source_range(processed_source.buffer, line_range.min, 0..0)
|
|
56
65
|
comment = processed_source.comment_at_line(line_range.begin)
|
|
57
66
|
|
|
58
|
-
add_offense(
|
|
67
|
+
add_offense(comment, message: message(cop, comment))
|
|
59
68
|
end
|
|
60
69
|
end
|
|
61
70
|
|
|
@@ -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
|
|
@@ -24,10 +24,7 @@ module RuboCop
|
|
|
24
24
|
MSG = 'Avoid rescuing the `Exception` class. Perhaps you meant to rescue `StandardError`?'
|
|
25
25
|
|
|
26
26
|
def on_resbody(node)
|
|
27
|
-
return unless node.
|
|
28
|
-
|
|
29
|
-
rescue_args = node.children.first.children
|
|
30
|
-
return unless rescue_args.any? { |a| targets_exception?(a) }
|
|
27
|
+
return unless node.exceptions.any? { |exception| targets_exception?(exception) }
|
|
31
28
|
|
|
32
29
|
add_offense(node)
|
|
33
30
|
end
|
|
@@ -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
|
|
@@ -45,7 +53,7 @@ module RuboCop
|
|
|
45
53
|
return if allow_rbs_inline_annotation? && rbs_inline_annotation?(node.receiver)
|
|
46
54
|
|
|
47
55
|
if node.method?(:[]=)
|
|
48
|
-
handle_key_assignment(node)
|
|
56
|
+
handle_key_assignment(node)
|
|
49
57
|
elsif node.assignment_method?
|
|
50
58
|
handle_attribute_assignment(node) if node.arguments.size == 1
|
|
51
59
|
end
|
|
@@ -105,12 +113,13 @@ module RuboCop
|
|
|
105
113
|
end
|
|
106
114
|
|
|
107
115
|
def handle_key_assignment(node)
|
|
108
|
-
value_node = node.
|
|
116
|
+
value_node = node.last_argument
|
|
117
|
+
node_arguments = node.arguments[0...-1]
|
|
109
118
|
|
|
110
|
-
if value_node.
|
|
119
|
+
if value_node.respond_to?(:method?) && value_node.method?(:[]) &&
|
|
111
120
|
node.receiver == value_node.receiver &&
|
|
112
|
-
|
|
113
|
-
|
|
121
|
+
node_arguments.none?(&:call_type?) &&
|
|
122
|
+
node_arguments == value_node.arguments
|
|
114
123
|
add_offense(node)
|
|
115
124
|
end
|
|
116
125
|
end
|
|
@@ -125,13 +125,13 @@ module RuboCop
|
|
|
125
125
|
next false if assignment_node.shorthand_asgn?
|
|
126
126
|
next false unless assignment_node.parent
|
|
127
127
|
|
|
128
|
-
|
|
129
|
-
|
|
128
|
+
conditional_assignment =
|
|
129
|
+
conditional_assignment?(assignment_node.parent, argument.scope.node)
|
|
130
130
|
|
|
131
131
|
unless uses_var?(assignment_node, argument.name)
|
|
132
132
|
# It's impossible to decide whether a branch or block is executed,
|
|
133
133
|
# so the precise reassignment location is undecidable.
|
|
134
|
-
next false if
|
|
134
|
+
next false if conditional_assignment
|
|
135
135
|
|
|
136
136
|
yield(assignment.node, location_known)
|
|
137
137
|
break
|
|
@@ -147,13 +147,13 @@ module RuboCop
|
|
|
147
147
|
node.source_range.begin_pos
|
|
148
148
|
end
|
|
149
149
|
|
|
150
|
-
# Check whether the given node is
|
|
150
|
+
# Check whether the given node is always executed or not
|
|
151
151
|
#
|
|
152
|
-
def
|
|
152
|
+
def conditional_assignment?(node, stop_search_node)
|
|
153
153
|
return false if node == stop_search_node
|
|
154
154
|
|
|
155
|
-
node.conditional? || node.
|
|
156
|
-
|
|
155
|
+
node.conditional? || node.type?(:block, :rescue) ||
|
|
156
|
+
conditional_assignment?(node.parent, stop_search_node)
|
|
157
157
|
end
|
|
158
158
|
|
|
159
159
|
# Get argument references without assignments' references
|
|
@@ -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)
|
|
@@ -17,6 +17,7 @@ module RuboCop
|
|
|
17
17
|
#
|
|
18
18
|
# # good
|
|
19
19
|
# CGI.escape('http://example.com')
|
|
20
|
+
# URI.encode_uri_component(uri) # Since Ruby 3.1
|
|
20
21
|
# URI.encode_www_form([['example', 'param'], ['lang', 'en']])
|
|
21
22
|
# URI.encode_www_form(page: 10, locale: 'en')
|
|
22
23
|
# URI.encode_www_form_component('http://example.com')
|
|
@@ -27,6 +28,7 @@ module RuboCop
|
|
|
27
28
|
#
|
|
28
29
|
# # good
|
|
29
30
|
# CGI.unescape(enc_uri)
|
|
31
|
+
# URI.decode_uri_component(uri) # Since Ruby 3.1
|
|
30
32
|
# URI.decode_www_form(enc_uri)
|
|
31
33
|
# URI.decode_www_form_component(enc_uri)
|
|
32
34
|
class UriEscapeUnescape < Base
|
|
@@ -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
|