rubocop 1.59.0 → 1.65.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/LICENSE.txt +1 -1
- data/README.md +3 -4
- data/assets/output.css.erb +159 -0
- data/assets/output.html.erb +1 -160
- data/config/default.yml +93 -17
- data/lib/rubocop/cached_data.rb +11 -3
- data/lib/rubocop/cli/command/auto_generate_config.rb +12 -3
- data/lib/rubocop/cli/command/lsp.rb +2 -2
- data/lib/rubocop/cli/command/show_docs_url.rb +2 -2
- data/lib/rubocop/cli.rb +10 -1
- data/lib/rubocop/config.rb +36 -12
- data/lib/rubocop/config_finder.rb +12 -2
- data/lib/rubocop/config_loader.rb +1 -2
- data/lib/rubocop/config_loader_resolver.rb +9 -3
- data/lib/rubocop/config_obsoletion.rb +1 -1
- data/lib/rubocop/config_validator.rb +14 -7
- data/lib/rubocop/cop/autocorrect_logic.rb +6 -1
- data/lib/rubocop/cop/base.rb +63 -16
- data/lib/rubocop/cop/bundler/gem_version.rb +3 -5
- data/lib/rubocop/cop/cop.rb +22 -4
- data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +4 -8
- data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +5 -13
- data/lib/rubocop/cop/documentation.rb +16 -6
- data/lib/rubocop/cop/exclude_limit.rb +1 -1
- data/lib/rubocop/cop/force.rb +12 -0
- data/lib/rubocop/cop/gemspec/add_runtime_dependency.rb +38 -0
- data/lib/rubocop/cop/gemspec/dependency_version.rb +3 -5
- data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +2 -2
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +5 -1
- data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +3 -3
- data/lib/rubocop/cop/internal_affairs/example_description.rb +6 -5
- data/lib/rubocop/cop/internal_affairs/method_name_end_with.rb +8 -6
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +122 -28
- data/lib/rubocop/cop/internal_affairs/redundant_expect_offense_arguments.rb +34 -0
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/layout/assignment_indentation.rb +3 -2
- data/lib/rubocop/cop/layout/case_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/comment_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/condition_position.rb +0 -4
- data/lib/rubocop/cop/layout/empty_comment.rb +3 -1
- data/lib/rubocop/cop/layout/empty_line_after_magic_comment.rb +14 -7
- data/lib/rubocop/cop/layout/empty_line_after_multiline_condition.rb +1 -1
- data/lib/rubocop/cop/layout/end_alignment.rb +8 -2
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +18 -1
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +1 -1
- data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +1 -1
- data/lib/rubocop/cop/layout/line_length.rb +20 -20
- data/lib/rubocop/cop/layout/redundant_line_break.rb +14 -2
- data/lib/rubocop/cop/layout/space_around_operators.rb +3 -0
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +19 -10
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +1 -1
- data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +3 -4
- data/lib/rubocop/cop/legacy/corrector.rb +12 -2
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +0 -2
- data/lib/rubocop/cop/lint/ambiguous_operator.rb +0 -2
- data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +0 -2
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +2 -2
- data/lib/rubocop/cop/lint/boolean_symbol.rb +0 -2
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +0 -13
- data/lib/rubocop/cop/lint/debugger.rb +27 -6
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +0 -10
- data/lib/rubocop/cop/lint/duplicate_case_condition.rb +1 -5
- data/lib/rubocop/cop/lint/duplicate_hash_key.rb +0 -4
- data/lib/rubocop/cop/lint/duplicate_methods.rb +0 -10
- data/lib/rubocop/cop/lint/each_with_object_argument.rb +0 -4
- data/lib/rubocop/cop/lint/else_layout.rb +0 -2
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +2 -2
- data/lib/rubocop/cop/lint/empty_ensure.rb +1 -11
- data/lib/rubocop/cop/lint/empty_interpolation.rb +0 -4
- data/lib/rubocop/cop/lint/empty_when.rb +1 -3
- data/lib/rubocop/cop/lint/ensure_return.rb +1 -6
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +21 -14
- data/lib/rubocop/cop/lint/float_comparison.rb +3 -1
- data/lib/rubocop/cop/lint/float_out_of_range.rb +0 -4
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +0 -10
- data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +15 -12
- data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +0 -7
- data/lib/rubocop/cop/lint/interpolation_check.rb +0 -4
- data/lib/rubocop/cop/lint/literal_as_condition.rb +1 -1
- data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +13 -6
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +0 -4
- data/lib/rubocop/cop/lint/loop.rb +6 -12
- data/lib/rubocop/cop/lint/mixed_case_range.rb +9 -4
- data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -7
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +0 -4
- data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +0 -5
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +1 -1
- data/lib/rubocop/cop/lint/percent_string_array.rb +0 -4
- data/lib/rubocop/cop/lint/percent_symbol_array.rb +0 -4
- data/lib/rubocop/cop/lint/rand_one.rb +0 -4
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +3 -1
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +14 -9
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_string_coercion.rb +0 -4
- data/lib/rubocop/cop/lint/redundant_with_index.rb +4 -0
- data/lib/rubocop/cop/lint/require_parentheses.rb +0 -4
- data/lib/rubocop/cop/lint/rescue_exception.rb +0 -4
- data/lib/rubocop/cop/lint/rescue_type.rb +1 -3
- data/lib/rubocop/cop/lint/return_in_void_context.rb +0 -2
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +0 -4
- data/lib/rubocop/cop/lint/script_permission.rb +3 -3
- data/lib/rubocop/cop/lint/shadowed_argument.rb +1 -0
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +6 -10
- data/lib/rubocop/cop/lint/syntax.rb +6 -3
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +1 -3
- data/lib/rubocop/cop/lint/unified_integer.rb +0 -4
- data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -0
- data/lib/rubocop/cop/lint/unreachable_code.rb +4 -7
- data/lib/rubocop/cop/lint/unreachable_loop.rb +8 -2
- data/lib/rubocop/cop/lint/useless_assignment.rb +1 -5
- data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +0 -4
- data/lib/rubocop/cop/lint/useless_setter_call.rb +0 -4
- data/lib/rubocop/cop/lint/useless_times.rb +1 -1
- data/lib/rubocop/cop/lint/void.rb +11 -1
- data/lib/rubocop/cop/metrics/block_nesting.rb +19 -7
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +5 -5
- data/lib/rubocop/cop/mixin/alignment.rb +5 -1
- data/lib/rubocop/cop/mixin/allowed_methods.rb +7 -1
- data/lib/rubocop/cop/mixin/allowed_pattern.rb +15 -3
- data/lib/rubocop/cop/mixin/code_length.rb +12 -1
- data/lib/rubocop/cop/mixin/configurable_formatting.rb +1 -0
- data/lib/rubocop/cop/mixin/configurable_max.rb +5 -1
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +9 -2
- data/lib/rubocop/cop/mixin/method_complexity.rb +15 -6
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
- data/lib/rubocop/cop/mixin/rescue_node.rb +4 -0
- data/lib/rubocop/cop/mixin/safe_assignment.rb +1 -1
- data/lib/rubocop/cop/naming/block_forwarding.rb +32 -5
- data/lib/rubocop/cop/naming/file_name.rb +2 -2
- data/lib/rubocop/cop/naming/inclusive_language.rb +1 -2
- data/lib/rubocop/cop/naming/predicate_name.rb +54 -28
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +10 -1
- data/lib/rubocop/cop/registry.rb +1 -1
- data/lib/rubocop/cop/security/compound_hash.rb +2 -2
- data/lib/rubocop/cop/security/open.rb +2 -2
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +50 -0
- data/lib/rubocop/cop/style/alias.rb +1 -0
- data/lib/rubocop/cop/style/arguments_forwarding.rb +89 -17
- data/lib/rubocop/cop/style/case_like_if.rb +1 -1
- data/lib/rubocop/cop/style/class_vars.rb +3 -3
- data/lib/rubocop/cop/style/collection_compact.rb +14 -5
- data/lib/rubocop/cop/style/commented_keyword.rb +5 -2
- data/lib/rubocop/cop/style/conditional_assignment.rb +6 -7
- data/lib/rubocop/cop/style/copyright.rb +31 -21
- data/lib/rubocop/cop/style/def_with_parentheses.rb +0 -2
- data/lib/rubocop/cop/style/documentation.rb +24 -24
- data/lib/rubocop/cop/style/documentation_method.rb +20 -0
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +7 -8
- data/lib/rubocop/cop/style/eval_with_location.rb +15 -23
- data/lib/rubocop/cop/style/exact_regexp_match.rb +2 -1
- data/lib/rubocop/cop/style/file_read.rb +2 -5
- data/lib/rubocop/cop/style/file_write.rb +2 -5
- data/lib/rubocop/cop/style/for.rb +2 -0
- data/lib/rubocop/cop/style/format_string.rb +9 -9
- data/lib/rubocop/cop/style/global_std_stream.rb +7 -1
- data/lib/rubocop/cop/style/hash_each_methods.rb +29 -8
- data/lib/rubocop/cop/style/hash_except.rb +8 -5
- data/lib/rubocop/cop/style/hash_syntax.rb +24 -2
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +4 -1
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +5 -4
- data/lib/rubocop/cop/style/inverse_methods.rb +8 -8
- data/lib/rubocop/cop/style/invertible_unless_condition.rb +46 -4
- data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +81 -50
- data/lib/rubocop/cop/style/map_into_array.rb +175 -0
- data/lib/rubocop/cop/style/map_to_hash.rb +10 -6
- data/lib/rubocop/cop/style/map_to_set.rb +1 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +18 -5
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -4
- data/lib/rubocop/cop/style/missing_else.rb +0 -4
- data/lib/rubocop/cop/style/multiline_method_signature.rb +10 -1
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +5 -3
- data/lib/rubocop/cop/style/multiline_when_then.rb +0 -4
- data/lib/rubocop/cop/style/nil_comparison.rb +2 -0
- data/lib/rubocop/cop/style/numeric_literal_prefix.rb +1 -1
- data/lib/rubocop/cop/style/numeric_predicate.rb +10 -2
- data/lib/rubocop/cop/style/object_then.rb +5 -3
- data/lib/rubocop/cop/style/one_line_conditional.rb +1 -1
- data/lib/rubocop/cop/style/parallel_assignment.rb +3 -5
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +8 -0
- data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
- data/lib/rubocop/cop/style/raise_args.rb +4 -1
- data/lib/rubocop/cop/style/redundant_argument.rb +25 -2
- data/lib/rubocop/cop/style/redundant_assignment.rb +10 -2
- data/lib/rubocop/cop/style/redundant_begin.rb +1 -1
- data/lib/rubocop/cop/style/redundant_condition.rb +0 -1
- data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +5 -4
- data/lib/rubocop/cop/style/redundant_each.rb +7 -4
- data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +1 -1
- data/lib/rubocop/cop/style/redundant_filter_chain.rb +1 -1
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +17 -2
- data/lib/rubocop/cop/style/redundant_parentheses.rb +18 -2
- data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -1
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -24
- data/lib/rubocop/cop/style/redundant_return.rb +6 -0
- data/lib/rubocop/cop/style/require_order.rb +1 -1
- data/lib/rubocop/cop/style/sample.rb +1 -3
- data/lib/rubocop/cop/style/send.rb +4 -4
- data/lib/rubocop/cop/style/send_with_literal_method_name.rb +104 -0
- data/lib/rubocop/cop/style/slicing_with_range.rb +76 -10
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +21 -2
- data/lib/rubocop/cop/style/special_global_vars.rb +1 -2
- data/lib/rubocop/cop/style/super_arguments.rb +174 -0
- data/lib/rubocop/cop/style/symbol_proc.rb +75 -5
- data/lib/rubocop/cop/style/top_level_method_definition.rb +1 -1
- data/lib/rubocop/cop/style/while_until_do.rb +0 -2
- data/lib/rubocop/cop/style/while_until_modifier.rb +0 -1
- data/lib/rubocop/cop/style/zero_length_predicate.rb +32 -24
- data/lib/rubocop/cop/team.rb +13 -0
- data/lib/rubocop/cop/util.rb +7 -1
- data/lib/rubocop/cop/utils/regexp_ranges.rb +1 -1
- data/lib/rubocop/cop/variable_force.rb +13 -1
- data/lib/rubocop/cops_documentation_generator.rb +16 -4
- data/lib/rubocop/core_ext/string.rb +2 -6
- data/lib/rubocop/directive_comment.rb +10 -8
- data/lib/rubocop/ext/regexp_node.rb +18 -35
- data/lib/rubocop/ext/regexp_parser.rb +4 -21
- data/lib/rubocop/formatter/clang_style_formatter.rb +3 -7
- data/lib/rubocop/formatter/disabled_config_formatter.rb +23 -8
- data/lib/rubocop/formatter/formatter_set.rb +7 -1
- data/lib/rubocop/formatter/html_formatter.rb +32 -10
- data/lib/rubocop/formatter/json_formatter.rb +0 -1
- data/lib/rubocop/formatter/offense_count_formatter.rb +12 -2
- data/lib/rubocop/formatter/tap_formatter.rb +3 -7
- data/lib/rubocop/formatter.rb +1 -1
- data/lib/rubocop/lockfile.rb +56 -7
- data/lib/rubocop/lsp/logger.rb +1 -1
- data/lib/rubocop/lsp/routes.rb +12 -15
- data/lib/rubocop/lsp/runtime.rb +1 -1
- data/lib/rubocop/lsp/server.rb +7 -2
- data/lib/rubocop/lsp/severity.rb +1 -1
- data/lib/rubocop/lsp.rb +36 -0
- data/lib/rubocop/magic_comment.rb +1 -1
- data/lib/rubocop/options.rb +17 -12
- data/lib/rubocop/path_util.rb +6 -2
- data/lib/rubocop/rake_task.rb +1 -1
- data/lib/rubocop/rspec/cop_helper.rb +8 -2
- data/lib/rubocop/rspec/expect_offense.rb +16 -8
- data/lib/rubocop/rspec/shared_contexts.rb +73 -16
- data/lib/rubocop/rspec/support.rb +3 -0
- data/lib/rubocop/runner.rb +14 -3
- data/lib/rubocop/server/cache.rb +11 -2
- data/lib/rubocop/server/client_command/exec.rb +2 -3
- data/lib/rubocop/server/client_command/start.rb +1 -1
- data/lib/rubocop/server/core.rb +4 -0
- data/lib/rubocop/server/server_command/exec.rb +0 -1
- data/lib/rubocop/target_finder.rb +84 -78
- data/lib/rubocop/target_ruby.rb +82 -80
- data/lib/rubocop/version.rb +19 -4
- data/lib/rubocop.rb +9 -0
- metadata +18 -11
- /data/lib/rubocop/formatter/{git_hub_actions_formatter.rb → github_actions_formatter.rb} +0 -0
@@ -3,8 +3,9 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
# Checks that arrays are sliced with
|
7
|
-
# `ary[start..-1]` on Ruby 2.6
|
6
|
+
# Checks that arrays are not sliced with the redundant `ary[0..-1]`, replacing it with `ary`,
|
7
|
+
# and ensures arrays are sliced with endless ranges instead of `ary[start..-1]` on Ruby 2.6+,
|
8
|
+
# and with beginless ranges instead of `ary[nil..end]` on Ruby 2.7+.
|
8
9
|
#
|
9
10
|
# @safety
|
10
11
|
# This cop is unsafe because `x..-1` and `x..` are only guaranteed to
|
@@ -21,29 +22,94 @@ module RuboCop
|
|
21
22
|
#
|
22
23
|
# @example
|
23
24
|
# # bad
|
24
|
-
# items[
|
25
|
+
# items[0..-1]
|
26
|
+
# items[0..nil]
|
27
|
+
# items[0...nil]
|
25
28
|
#
|
26
29
|
# # good
|
27
|
-
# items
|
30
|
+
# items
|
31
|
+
#
|
32
|
+
# # bad
|
33
|
+
# items[1..-1] # Ruby 2.6+
|
34
|
+
# items[1..nil] # Ruby 2.6+
|
35
|
+
#
|
36
|
+
# # good
|
37
|
+
# items[1..] # Ruby 2.6+
|
38
|
+
#
|
39
|
+
# # bad
|
40
|
+
# items[nil..42] # Ruby 2.7+
|
41
|
+
#
|
42
|
+
# # good
|
43
|
+
# items[..42] # Ruby 2.7+
|
44
|
+
# items[0..42] # Ruby 2.7+
|
45
|
+
#
|
28
46
|
class SlicingWithRange < Base
|
29
47
|
extend AutoCorrector
|
30
48
|
extend TargetRubyVersion
|
31
49
|
|
32
50
|
minimum_target_ruby_version 2.6
|
33
51
|
|
34
|
-
MSG = 'Prefer
|
52
|
+
MSG = 'Prefer `%<prefer>s` over `%<current>s`.'
|
53
|
+
MSG_USELESS_RANGE = 'Remove the useless `%<prefer>s`.'
|
35
54
|
RESTRICT_ON_SEND = %i[[]].freeze
|
36
55
|
|
56
|
+
# @!method range_from_zero_till_minus_one?(node)
|
57
|
+
def_node_matcher :range_from_zero_till_minus_one?, <<~PATTERN
|
58
|
+
{
|
59
|
+
(irange (int 0) {(int -1) nil})
|
60
|
+
(erange (int 0) nil)
|
61
|
+
}
|
62
|
+
PATTERN
|
63
|
+
|
37
64
|
# @!method range_till_minus_one?(node)
|
38
|
-
def_node_matcher :range_till_minus_one?,
|
65
|
+
def_node_matcher :range_till_minus_one?, <<~PATTERN
|
66
|
+
{
|
67
|
+
(irange !nil? {(int -1) nil})
|
68
|
+
(erange !nil? nil)
|
69
|
+
}
|
70
|
+
PATTERN
|
71
|
+
|
72
|
+
# @!method range_from_zero?(node)
|
73
|
+
def_node_matcher :range_from_zero?, <<~PATTERN
|
74
|
+
(irange nil !nil?)
|
75
|
+
PATTERN
|
39
76
|
|
40
77
|
def on_send(node)
|
41
|
-
return unless node.arguments.
|
42
|
-
return unless range_till_minus_one?(node.first_argument)
|
78
|
+
return unless node.arguments.one?
|
43
79
|
|
44
|
-
|
45
|
-
|
80
|
+
range_node = node.first_argument
|
81
|
+
selector = node.loc.selector
|
82
|
+
unless (message, removal_range = offense_message_with_removal_range(range_node, selector))
|
83
|
+
return
|
46
84
|
end
|
85
|
+
|
86
|
+
add_offense(selector, message: message) do |corrector|
|
87
|
+
corrector.remove(removal_range)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def offense_message_with_removal_range(range_node, selector)
|
94
|
+
if range_from_zero_till_minus_one?(range_node)
|
95
|
+
[format(MSG_USELESS_RANGE, prefer: selector.source), selector]
|
96
|
+
elsif range_till_minus_one?(range_node)
|
97
|
+
[
|
98
|
+
format(MSG, prefer: endless(range_node), current: selector.source), range_node.end
|
99
|
+
]
|
100
|
+
elsif range_from_zero?(range_node) && target_ruby_version >= 2.7
|
101
|
+
[
|
102
|
+
format(MSG, prefer: beginless(range_node), current: selector.source), range_node.begin
|
103
|
+
]
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def endless(range_node)
|
108
|
+
"[#{range_node.begin.source}#{range_node.loc.operator.source}]"
|
109
|
+
end
|
110
|
+
|
111
|
+
def beginless(range_node)
|
112
|
+
"[#{range_node.loc.operator.source}#{range_node.end.source}]"
|
47
113
|
end
|
48
114
|
end
|
49
115
|
end
|
@@ -159,7 +159,13 @@ module RuboCop
|
|
159
159
|
node_to_check = condition&.block_type? ? condition.send_node : condition
|
160
160
|
return unless wrap_condition?(node_to_check)
|
161
161
|
|
162
|
-
|
162
|
+
if condition.call_type?
|
163
|
+
source = parenthesized_method_arguments(condition)
|
164
|
+
|
165
|
+
corrector.replace(condition, source)
|
166
|
+
else
|
167
|
+
corrector.wrap(condition, '(', ')')
|
168
|
+
end
|
163
169
|
end
|
164
170
|
|
165
171
|
def correct_for_outer_condition_modify_form_style(corrector, node, if_branch)
|
@@ -236,7 +242,20 @@ module RuboCop
|
|
236
242
|
end
|
237
243
|
|
238
244
|
def replace_condition(condition)
|
239
|
-
|
245
|
+
return condition.source unless wrap_condition?(condition)
|
246
|
+
|
247
|
+
if condition.call_type?
|
248
|
+
parenthesized_method_arguments(condition)
|
249
|
+
else
|
250
|
+
"(#{condition.source})"
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
def parenthesized_method_arguments(node)
|
255
|
+
method_call = node.source_range.begin.join(node.loc.selector.end).source
|
256
|
+
arguments = node.first_argument.source_range.begin.join(node.source_range.end).source
|
257
|
+
|
258
|
+
"#{method_call}(#{arguments})"
|
240
259
|
end
|
241
260
|
|
242
261
|
def allow_modifier?
|
@@ -58,9 +58,8 @@ module RuboCop
|
|
58
58
|
#
|
59
59
|
# @example EnforcedStyle: use_builtin_english_names
|
60
60
|
#
|
61
|
-
# Like `use_perl_names` but allows builtin global vars.
|
62
|
-
#
|
63
61
|
# # good
|
62
|
+
# # Like `use_perl_names` but allows builtin global vars.
|
64
63
|
# puts $LOAD_PATH
|
65
64
|
# puts $LOADED_FEATURES
|
66
65
|
# puts $PROGRAM_NAME
|
@@ -0,0 +1,174 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Checks for redundant argument forwarding when calling super with arguments identical to
|
7
|
+
# the method definition.
|
8
|
+
#
|
9
|
+
# Using zero arity `super` within a `define_method` block results in `RuntimeError`:
|
10
|
+
#
|
11
|
+
# [source,ruby]
|
12
|
+
# ----
|
13
|
+
# def m
|
14
|
+
# define_method(:foo) { super() } # => OK
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# def m
|
18
|
+
# define_method(:foo) { super } # => RuntimeError
|
19
|
+
# end
|
20
|
+
# ----
|
21
|
+
#
|
22
|
+
# Furthermore, any arguments accompanied by a block may potentially be delegating to
|
23
|
+
# `define_method`, therefore, `super` used within these blocks will be allowed.
|
24
|
+
# This approach might result in false negatives, yet ensuring safe detection takes precedence.
|
25
|
+
#
|
26
|
+
# @example
|
27
|
+
# # bad
|
28
|
+
# def method(*args, **kwargs)
|
29
|
+
# super(*args, **kwargs)
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# # good - implicitly passing all arguments
|
33
|
+
# def method(*args, **kwargs)
|
34
|
+
# super
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# # good - forwarding a subset of the arguments
|
38
|
+
# def method(*args, **kwargs)
|
39
|
+
# super(*args)
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# # good - forwarding no arguments
|
43
|
+
# def method(*args, **kwargs)
|
44
|
+
# super()
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# # good - assigning to the block variable before calling super
|
48
|
+
# def method(&block)
|
49
|
+
# # Assigning to the block variable would pass the old value to super,
|
50
|
+
# # under this circumstance the block must be referenced explicitly.
|
51
|
+
# block ||= proc { 'fallback behavior' }
|
52
|
+
# super(&block)
|
53
|
+
# end
|
54
|
+
class SuperArguments < Base
|
55
|
+
extend AutoCorrector
|
56
|
+
|
57
|
+
DEF_TYPES = %i[def defs].freeze
|
58
|
+
ASSIGN_TYPES = %i[or_asgn lvasgn].freeze
|
59
|
+
|
60
|
+
MSG = 'Call `super` without arguments and parentheses when the signature is identical.'
|
61
|
+
|
62
|
+
def on_super(super_node)
|
63
|
+
def_node = super_node.ancestors.find do |node|
|
64
|
+
# When defining dynamic methods, implicitly calling `super` is not possible.
|
65
|
+
# Since there is a possibility of delegation to `define_method`,
|
66
|
+
# `super` used within the block is always allowed.
|
67
|
+
break if node.block_type?
|
68
|
+
|
69
|
+
break node if DEF_TYPES.include?(node.type)
|
70
|
+
end
|
71
|
+
return unless def_node
|
72
|
+
return unless arguments_identical?(def_node, def_node.arguments.argument_list,
|
73
|
+
super_node.arguments)
|
74
|
+
|
75
|
+
add_offense(super_node) { |corrector| corrector.replace(super_node, 'super') }
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
81
|
+
def arguments_identical?(def_node, def_args, super_args)
|
82
|
+
super_args = preprocess_super_args(super_args)
|
83
|
+
return false if def_args.size != super_args.size
|
84
|
+
|
85
|
+
def_args.zip(super_args).each do |def_arg, super_arg|
|
86
|
+
next if positional_arg_same?(def_arg, super_arg)
|
87
|
+
next if positional_rest_arg_same(def_arg, super_arg)
|
88
|
+
next if keyword_arg_same?(def_arg, super_arg)
|
89
|
+
next if keyword_rest_arg_same?(def_arg, super_arg)
|
90
|
+
next if block_arg_same?(def_node, def_arg, super_arg)
|
91
|
+
next if forward_arg_same?(def_arg, super_arg)
|
92
|
+
|
93
|
+
return false
|
94
|
+
end
|
95
|
+
true
|
96
|
+
end
|
97
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
98
|
+
|
99
|
+
def positional_arg_same?(def_arg, super_arg)
|
100
|
+
return false unless def_arg.arg_type? || def_arg.optarg_type?
|
101
|
+
return false unless super_arg.lvar_type?
|
102
|
+
|
103
|
+
def_arg.name == super_arg.children.first
|
104
|
+
end
|
105
|
+
|
106
|
+
def positional_rest_arg_same(def_arg, super_arg)
|
107
|
+
return false unless def_arg.restarg_type?
|
108
|
+
# anonymous forwarding
|
109
|
+
return true if def_arg.name.nil? && super_arg.forwarded_restarg_type?
|
110
|
+
return false unless super_arg.splat_type?
|
111
|
+
return false unless (lvar_node = super_arg.children.first).lvar_type?
|
112
|
+
|
113
|
+
def_arg.name == lvar_node.children.first
|
114
|
+
end
|
115
|
+
|
116
|
+
def keyword_arg_same?(def_arg, super_arg)
|
117
|
+
return false unless def_arg.kwarg_type? || def_arg.kwoptarg_type?
|
118
|
+
return false unless (pair_node = super_arg).pair_type?
|
119
|
+
return false unless (sym_node = pair_node.key).sym_type?
|
120
|
+
return false unless (lvar_node = pair_node.value).lvar_type?
|
121
|
+
return false unless sym_node.source == lvar_node.source
|
122
|
+
|
123
|
+
def_arg.name == sym_node.value
|
124
|
+
end
|
125
|
+
|
126
|
+
def keyword_rest_arg_same?(def_arg, super_arg)
|
127
|
+
return false unless def_arg.kwrestarg_type?
|
128
|
+
# anonymous forwarding
|
129
|
+
return true if def_arg.name.nil? && super_arg.forwarded_kwrestarg_type?
|
130
|
+
return false unless super_arg.kwsplat_type?
|
131
|
+
return false unless (lvar_node = super_arg.children.first).lvar_type?
|
132
|
+
|
133
|
+
def_arg.name == lvar_node.children.first
|
134
|
+
end
|
135
|
+
|
136
|
+
def block_arg_same?(def_node, def_arg, super_arg)
|
137
|
+
return false unless def_arg.blockarg_type? && super_arg.block_pass_type?
|
138
|
+
# anonymous forwarding
|
139
|
+
return true if (block_pass_child = super_arg.children.first).nil? && def_arg.name.nil?
|
140
|
+
|
141
|
+
block_arg_name = block_pass_child.children.first
|
142
|
+
def_arg.name == block_arg_name && !block_reassigned?(def_node, block_arg_name)
|
143
|
+
end
|
144
|
+
|
145
|
+
# Reassigning the block argument will still pass along the original block to super
|
146
|
+
# https://bugs.ruby-lang.org/issues/20505
|
147
|
+
def block_reassigned?(def_node, block_arg_name)
|
148
|
+
def_node.each_node(*ASSIGN_TYPES).any? do |assign_node|
|
149
|
+
# TODO: Since `Symbol#name` is supported from Ruby 3.0, the inheritance check for
|
150
|
+
# `AST::Node` can be removed when requiring Ruby 3.0+.
|
151
|
+
lhs = assign_node.node_parts[0]
|
152
|
+
next if lhs.is_a?(AST::Node) && !lhs.respond_to?(:name)
|
153
|
+
|
154
|
+
assign_node.name == block_arg_name
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def forward_arg_same?(def_arg, super_arg)
|
159
|
+
def_arg.forward_arg_type? && super_arg.forwarded_args_type?
|
160
|
+
end
|
161
|
+
|
162
|
+
def preprocess_super_args(super_args)
|
163
|
+
super_args.flat_map do |node|
|
164
|
+
if node.hash_type? && !node.braces?
|
165
|
+
node.children
|
166
|
+
else
|
167
|
+
node
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
@@ -37,6 +37,42 @@ module RuboCop
|
|
37
37
|
# # ArgumentError: wrong number of arguments (given 1, expected 0)
|
38
38
|
# ----
|
39
39
|
#
|
40
|
+
# It is also unsafe because `Symbol#to_proc` does not work with
|
41
|
+
# `protected` methods which would otherwise be accessible.
|
42
|
+
#
|
43
|
+
# For example:
|
44
|
+
#
|
45
|
+
# [source,ruby]
|
46
|
+
# ----
|
47
|
+
# class Box
|
48
|
+
# def initialize
|
49
|
+
# @secret = rand
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
# def normal_matches?(*others)
|
53
|
+
# others.map { |other| other.secret }.any?(secret)
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
# def symbol_to_proc_matches?(*others)
|
57
|
+
# others.map(&:secret).any?(secret)
|
58
|
+
# end
|
59
|
+
#
|
60
|
+
# protected
|
61
|
+
#
|
62
|
+
# attr_reader :secret
|
63
|
+
# end
|
64
|
+
#
|
65
|
+
# boxes = [Box.new, Box.new]
|
66
|
+
# Box.new.normal_matches?(*boxes)
|
67
|
+
# # => false
|
68
|
+
# boxes.first.normal_matches?(*boxes)
|
69
|
+
# # => true
|
70
|
+
# Box.new.symbol_to_proc_matches?(*boxes)
|
71
|
+
# # => NoMethodError: protected method `secret' called for #<Box...>
|
72
|
+
# boxes.first.symbol_to_proc_matches?(*boxes)
|
73
|
+
# # => NoMethodError: protected method `secret' called for #<Box...>
|
74
|
+
# ----
|
75
|
+
#
|
40
76
|
# @example
|
41
77
|
# # bad
|
42
78
|
# something.map { |s| s.upcase }
|
@@ -84,6 +120,23 @@ module RuboCop
|
|
84
120
|
# # good
|
85
121
|
# something.map { |s| s.upcase }
|
86
122
|
#
|
123
|
+
# @example AllCops:ActiveSupportExtensionsEnabled: false (default)
|
124
|
+
# # bad
|
125
|
+
# ->(x) { x.foo }
|
126
|
+
# proc { |x| x.foo }
|
127
|
+
# Proc.new { |x| x.foo }
|
128
|
+
#
|
129
|
+
# # good
|
130
|
+
# lambda(&:foo)
|
131
|
+
# proc(&:foo)
|
132
|
+
# Proc.new(&:foo)
|
133
|
+
#
|
134
|
+
# @example AllCops:ActiveSupportExtensionsEnabled: true
|
135
|
+
# # good
|
136
|
+
# ->(x) { x.foo }
|
137
|
+
# proc { |x| x.foo }
|
138
|
+
# Proc.new { |x| x.foo }
|
139
|
+
#
|
87
140
|
class SymbolProc < Base
|
88
141
|
include CommentsHelp
|
89
142
|
include RangeHelp
|
@@ -93,6 +146,7 @@ module RuboCop
|
|
93
146
|
|
94
147
|
MSG = 'Pass `&:%<method>s` as an argument to `%<block_method>s` instead of a block.'
|
95
148
|
SUPER_TYPES = %i[super zsuper].freeze
|
149
|
+
LAMBDA_OR_PROC = %i[lambda proc].freeze
|
96
150
|
|
97
151
|
# @!method proc_node?(node)
|
98
152
|
def_node_matcher :proc_node?, '(send (const {nil? cbase} :Proc) :new)'
|
@@ -115,13 +169,12 @@ module RuboCop
|
|
115
169
|
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
116
170
|
def on_block(node)
|
117
171
|
symbol_proc?(node) do |dispatch_node, arguments_node, method_name|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
172
|
+
if active_support_extensions_enabled?
|
173
|
+
return if proc_node?(dispatch_node)
|
174
|
+
return if LAMBDA_OR_PROC.include?(dispatch_node.method_name)
|
175
|
+
end
|
122
176
|
return if unsafe_hash_usage?(dispatch_node)
|
123
177
|
return if unsafe_array_usage?(dispatch_node)
|
124
|
-
return if %i[lambda proc].include?(dispatch_node.method_name)
|
125
178
|
return if allowed_method_name?(dispatch_node.method_name)
|
126
179
|
return if allow_if_method_has_argument?(node.send_node)
|
127
180
|
return if node.block_type? && destructuring_block_argument?(arguments_node)
|
@@ -170,6 +223,15 @@ module RuboCop
|
|
170
223
|
end
|
171
224
|
|
172
225
|
def autocorrect_without_args(corrector, node)
|
226
|
+
if node.send_node.lambda_literal?
|
227
|
+
if node.send_node.loc.selector.source == '->'
|
228
|
+
corrector.replace(node, "lambda(&:#{node.body.method_name})")
|
229
|
+
return
|
230
|
+
else
|
231
|
+
autocorrect_lambda_block(corrector, node)
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
173
235
|
corrector.replace(block_range_with_space(node), "(&:#{node.body.method_name})")
|
174
236
|
end
|
175
237
|
|
@@ -182,6 +244,14 @@ module RuboCop
|
|
182
244
|
corrector.remove(block_range_with_space(node))
|
183
245
|
end
|
184
246
|
|
247
|
+
def autocorrect_lambda_block(corrector, node)
|
248
|
+
send_node_loc = node.send_node.loc
|
249
|
+
corrector.replace(send_node_loc.selector, 'lambda')
|
250
|
+
|
251
|
+
range = range_between(send_node_loc.selector.end_pos, node.loc.begin.end_pos - 2)
|
252
|
+
corrector.remove(range)
|
253
|
+
end
|
254
|
+
|
185
255
|
def block_range_with_space(node)
|
186
256
|
block_range = range_between(begin_pos_for_replacement(node), node.loc.end.end_pos)
|
187
257
|
range_with_surrounding_space(block_range, side: :left)
|
@@ -48,14 +48,19 @@ module RuboCop
|
|
48
48
|
check_nonzero_length_comparison(node)
|
49
49
|
end
|
50
50
|
|
51
|
+
def on_csend(node)
|
52
|
+
check_zero_length_predicate(node)
|
53
|
+
check_zero_length_comparison(node)
|
54
|
+
end
|
55
|
+
|
51
56
|
private
|
52
57
|
|
53
58
|
def check_zero_length_predicate(node)
|
54
|
-
return unless
|
59
|
+
return unless zero_length_predicate?(node.parent)
|
55
60
|
return if non_polymorphic_collection?(node.parent)
|
56
61
|
|
57
62
|
offense = node.loc.selector.join(node.parent.source_range.end)
|
58
|
-
message = format(ZERO_MSG, current:
|
63
|
+
message = format(ZERO_MSG, current: offense.source)
|
59
64
|
|
60
65
|
add_offense(offense, message: message) do |corrector|
|
61
66
|
corrector.replace(offense, 'empty?')
|
@@ -92,44 +97,47 @@ module RuboCop
|
|
92
97
|
end
|
93
98
|
end
|
94
99
|
|
95
|
-
# @!method zero_length_predicate(node)
|
96
|
-
def_node_matcher :zero_length_predicate
|
97
|
-
(
|
100
|
+
# @!method zero_length_predicate?(node)
|
101
|
+
def_node_matcher :zero_length_predicate?, <<~PATTERN
|
102
|
+
(call (call (...) {:length :size}) :zero?)
|
98
103
|
PATTERN
|
99
104
|
|
100
105
|
# @!method zero_length_comparison(node)
|
101
106
|
def_node_matcher :zero_length_comparison, <<~PATTERN
|
102
|
-
{(
|
103
|
-
(
|
104
|
-
(
|
105
|
-
(
|
107
|
+
{(call (call (...) ${:length :size}) $:== (int $0))
|
108
|
+
(call (int $0) $:== (call (...) ${:length :size}))
|
109
|
+
(call (call (...) ${:length :size}) $:< (int $1))
|
110
|
+
(call (int $1) $:> (call (...) ${:length :size}))}
|
106
111
|
PATTERN
|
107
112
|
|
108
113
|
# @!method nonzero_length_comparison(node)
|
109
114
|
def_node_matcher :nonzero_length_comparison, <<~PATTERN
|
110
|
-
{(
|
111
|
-
(
|
115
|
+
{(call (call (...) ${:length :size}) ${:> :!=} (int $0))
|
116
|
+
(call (int $0) ${:< :!=} (call (...) ${:length :size}))}
|
112
117
|
PATTERN
|
113
118
|
|
114
119
|
def replacement(node)
|
115
|
-
|
116
|
-
|
120
|
+
length_node = zero_length_node(node)
|
121
|
+
if length_node&.receiver
|
122
|
+
return "#{length_node.receiver.source}#{length_node.loc.dot.source}empty?"
|
123
|
+
end
|
117
124
|
|
118
|
-
|
125
|
+
other_length_node = other_length_node(node)
|
126
|
+
"!#{other_length_node.receiver.source}#{other_length_node.loc.dot.source}empty?"
|
119
127
|
end
|
120
128
|
|
121
|
-
# @!method
|
122
|
-
def_node_matcher :
|
123
|
-
{(send (
|
124
|
-
(send (int 0) :== (
|
125
|
-
(send (
|
126
|
-
(send (int 1) :> (
|
129
|
+
# @!method zero_length_node(node)
|
130
|
+
def_node_matcher :zero_length_node, <<~PATTERN
|
131
|
+
{(send $(call _ _) :== (int 0))
|
132
|
+
(send (int 0) :== $(call _ _))
|
133
|
+
(send $(call _ _) :< (int 1))
|
134
|
+
(send (int 1) :> $(call _ _))}
|
127
135
|
PATTERN
|
128
136
|
|
129
|
-
# @!method
|
130
|
-
def_node_matcher :
|
131
|
-
{(
|
132
|
-
(
|
137
|
+
# @!method other_length_node(node)
|
138
|
+
def_node_matcher :other_length_node, <<~PATTERN
|
139
|
+
{(call $(call _ _) _ _)
|
140
|
+
(call _ _ $(call _ _))}
|
133
141
|
PATTERN
|
134
142
|
|
135
143
|
# Some collection like objects in the Ruby standard library
|
data/lib/rubocop/cop/team.rb
CHANGED
@@ -74,6 +74,10 @@ module RuboCop
|
|
74
74
|
# @deprecated. Use investigate
|
75
75
|
# @return Array<offenses>
|
76
76
|
def inspect_file(processed_source)
|
77
|
+
warn Rainbow(<<~WARNING).yellow, uplevel: 1
|
78
|
+
`inspect_file` is deprecated. Use `investigate` instead.
|
79
|
+
WARNING
|
80
|
+
|
77
81
|
investigate(processed_source).offenses
|
78
82
|
end
|
79
83
|
|
@@ -108,6 +112,10 @@ module RuboCop
|
|
108
112
|
|
109
113
|
# @deprecated
|
110
114
|
def forces
|
115
|
+
warn Rainbow(<<~WARNING).yellow, uplevel: 1
|
116
|
+
`forces` is deprecated.
|
117
|
+
WARNING
|
118
|
+
|
111
119
|
@forces ||= self.class.forces_for(cops)
|
112
120
|
end
|
113
121
|
|
@@ -174,6 +182,9 @@ module RuboCop
|
|
174
182
|
end
|
175
183
|
|
176
184
|
def support_target_rails_version?(cop)
|
185
|
+
# In this case, the rails version was already checked by `#excluded_file?`
|
186
|
+
return true if defined?(RuboCop::Rails::TargetRailsVersion::USES_REQUIRES_GEM_API)
|
187
|
+
|
177
188
|
return true unless cop.class.respond_to?(:support_target_rails_version?)
|
178
189
|
|
179
190
|
cop.class.support_target_rails_version?(cop.target_rails_version)
|
@@ -237,6 +248,8 @@ module RuboCop
|
|
237
248
|
|
238
249
|
if cause.is_a?(Warning)
|
239
250
|
handle_warning(cause, location)
|
251
|
+
elsif cause.is_a?(Force::HookError)
|
252
|
+
handle_error(cause.cause, location, cause.joining_cop)
|
240
253
|
else
|
241
254
|
handle_error(cause, location, error.cop)
|
242
255
|
end
|
data/lib/rubocop/cop/util.rb
CHANGED
@@ -20,6 +20,10 @@ module RuboCop
|
|
20
20
|
|
21
21
|
# @deprecated Use `ProcessedSource#line_with_comment?`, `contains_comment?` or similar
|
22
22
|
def comment_lines?(node)
|
23
|
+
warn Rainbow(<<~WARNING).yellow, uplevel: 1
|
24
|
+
`comment_lines?` is deprecated. Use `ProcessedSource#line_with_comment?`, `contains_comment?` or similar instead.
|
25
|
+
WARNING
|
26
|
+
|
23
27
|
processed_source[line_range(node)].any? { |line| comment_line?(line) }
|
24
28
|
end
|
25
29
|
|
@@ -173,7 +177,9 @@ module RuboCop
|
|
173
177
|
def same_line?(node1, node2)
|
174
178
|
line1 = line(node1)
|
175
179
|
line2 = line(node2)
|
176
|
-
|
180
|
+
return false unless line1 && line2
|
181
|
+
|
182
|
+
line1 == line2
|
177
183
|
end
|
178
184
|
|
179
185
|
def indent(node, offset: 0)
|