rubocop 1.62.1 → 1.67.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +67 -68
- data/config/default.yml +82 -12
- data/config/internal_affairs.yml +11 -0
- data/exe/rubocop +4 -3
- data/lib/rubocop/cached_data.rb +11 -3
- data/lib/rubocop/cli/command/auto_generate_config.rb +6 -7
- 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 +4 -0
- data/lib/rubocop/comment_config.rb +1 -1
- data/lib/rubocop/config.rb +37 -11
- data/lib/rubocop/config_loader.rb +15 -9
- data/lib/rubocop/config_loader_resolver.rb +13 -8
- data/lib/rubocop/config_obsoletion.rb +1 -1
- data/lib/rubocop/config_validator.rb +3 -2
- data/lib/rubocop/cop/base.rb +56 -16
- data/lib/rubocop/cop/bundler/gem_version.rb +4 -5
- data/lib/rubocop/cop/cop.rb +30 -4
- data/lib/rubocop/cop/correctors/line_break_corrector.rb +2 -0
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +1 -1
- data/lib/rubocop/cop/documentation.rb +32 -5
- 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/ruby_version_globals_usage.rb +3 -3
- data/lib/rubocop/cop/internal_affairs/cop_description.rb +0 -4
- data/lib/rubocop/cop/internal_affairs/empty_line_between_expect_offense_and_correction.rb +2 -1
- data/lib/rubocop/cop/internal_affairs/example_description.rb +2 -1
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +6 -21
- data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +8 -1
- data/lib/rubocop/cop/internal_affairs/undefined_config.rb +11 -1
- data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +0 -5
- data/lib/rubocop/cop/internal_affairs.rb +16 -0
- data/lib/rubocop/cop/layout/access_modifier_indentation.rb +5 -1
- data/lib/rubocop/cop/layout/assignment_indentation.rb +3 -2
- data/lib/rubocop/cop/layout/block_alignment.rb +30 -12
- 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/def_end_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/empty_comment.rb +3 -1
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_after_multiline_condition.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +2 -1
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +8 -3
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -3
- data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +8 -0
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +5 -6
- data/lib/rubocop/cop/layout/leading_comment_space.rb +28 -1
- data/lib/rubocop/cop/layout/line_length.rb +20 -20
- data/lib/rubocop/cop/layout/space_around_operators.rb +3 -0
- 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_range.rb +4 -1
- 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/big_decimal_new.rb +4 -7
- data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -3
- 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/duplicate_set_element.rb +74 -0
- 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 +28 -7
- 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 -9
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +21 -14
- data/lib/rubocop/cop/lint/float_comparison.rb +1 -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 +23 -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/it_without_arguments_in_block.rb +5 -14
- data/lib/rubocop/cop/lint/literal_as_condition.rb +1 -1
- data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +1 -1
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +25 -6
- 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/parentheses_as_grouped_expression.rb +5 -6
- 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 +1 -1
- 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 +3 -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/return_in_void_context.rb +0 -2
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +0 -4
- data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +105 -41
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +6 -10
- data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +2 -9
- 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/uri_regexp.rb +25 -7
- data/lib/rubocop/cop/lint/useless_assignment.rb +19 -16
- data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +0 -4
- data/lib/rubocop/cop/lint/useless_numeric_operation.rb +77 -0
- data/lib/rubocop/cop/lint/useless_setter_call.rb +0 -4
- data/lib/rubocop/cop/lint/void.rb +35 -8
- data/lib/rubocop/cop/metrics/block_length.rb +6 -5
- data/lib/rubocop/cop/metrics/block_nesting.rb +19 -7
- data/lib/rubocop/cop/metrics/class_length.rb +6 -5
- data/lib/rubocop/cop/metrics/method_length.rb +6 -5
- data/lib/rubocop/cop/metrics/module_length.rb +6 -5
- 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/annotation_comment.rb +0 -2
- data/lib/rubocop/cop/mixin/code_length.rb +12 -1
- data/lib/rubocop/cop/mixin/configurable_max.rb +5 -1
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +19 -9
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +9 -2
- data/lib/rubocop/cop/mixin/line_length_help.rb +7 -2
- data/lib/rubocop/cop/mixin/method_complexity.rb +15 -6
- data/lib/rubocop/cop/mixin/percent_array.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/mixin/statement_modifier.rb +3 -2
- data/lib/rubocop/cop/mixin/string_literals_help.rb +12 -0
- data/lib/rubocop/cop/naming/accessor_method_name.rb +5 -0
- data/lib/rubocop/cop/naming/block_forwarding.rb +31 -12
- data/lib/rubocop/cop/naming/file_name.rb +2 -2
- data/lib/rubocop/cop/naming/inclusive_language.rb +13 -5
- data/lib/rubocop/cop/naming/predicate_name.rb +53 -27
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +10 -1
- data/lib/rubocop/cop/offense.rb +2 -2
- data/lib/rubocop/cop/security/compound_hash.rb +2 -2
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +62 -2
- data/lib/rubocop/cop/style/accessor_grouping.rb +10 -2
- data/lib/rubocop/cop/style/alias.rb +2 -1
- data/lib/rubocop/cop/style/arguments_forwarding.rb +59 -11
- data/lib/rubocop/cop/style/block_delimiters.rb +14 -1
- data/lib/rubocop/cop/style/collection_compact.rb +9 -9
- data/lib/rubocop/cop/style/combinable_loops.rb +7 -0
- data/lib/rubocop/cop/style/commented_keyword.rb +7 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +2 -2
- data/lib/rubocop/cop/style/copyright.rb +31 -21
- data/lib/rubocop/cop/style/data_inheritance.rb +1 -1
- 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 +0 -1
- data/lib/rubocop/cop/style/empty_else.rb +6 -5
- data/lib/rubocop/cop/style/empty_heredoc.rb +1 -14
- data/lib/rubocop/cop/style/empty_literal.rb +31 -22
- data/lib/rubocop/cop/style/eval_with_location.rb +16 -13
- 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/format_string.rb +9 -9
- data/lib/rubocop/cop/style/format_string_token.rb +2 -2
- data/lib/rubocop/cop/style/global_std_stream.rb +7 -1
- data/lib/rubocop/cop/style/guard_clause.rb +3 -1
- data/lib/rubocop/cop/style/hash_each_methods.rb +6 -0
- data/lib/rubocop/cop/style/hash_except.rb +8 -5
- data/lib/rubocop/cop/style/hash_syntax.rb +20 -2
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +1 -1
- data/lib/rubocop/cop/style/if_inside_else.rb +1 -1
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +5 -4
- data/lib/rubocop/cop/style/if_with_semicolon.rb +49 -6
- data/lib/rubocop/cop/style/in_pattern_then.rb +6 -2
- data/lib/rubocop/cop/style/invertible_unless_condition.rb +2 -2
- data/lib/rubocop/cop/style/lambda.rb +1 -1
- data/lib/rubocop/cop/style/magic_comment_format.rb +1 -1
- data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +77 -43
- data/lib/rubocop/cop/style/map_into_array.rb +228 -0
- data/lib/rubocop/cop/style/map_to_hash.rb +1 -1
- data/lib/rubocop/cop/style/map_to_set.rb +1 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +17 -7
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -2
- data/lib/rubocop/cop/style/missing_else.rb +0 -4
- data/lib/rubocop/cop/style/multiline_memoization.rb +1 -1
- data/lib/rubocop/cop/style/multiline_when_then.rb +0 -4
- data/lib/rubocop/cop/style/multiple_comparison.rb +3 -11
- data/lib/rubocop/cop/style/nested_modifier.rb +1 -1
- data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
- data/lib/rubocop/cop/style/numeric_predicate.rb +12 -4
- data/lib/rubocop/cop/style/one_line_conditional.rb +6 -2
- data/lib/rubocop/cop/style/operator_method_call.rb +25 -6
- data/lib/rubocop/cop/style/parallel_assignment.rb +5 -4
- data/lib/rubocop/cop/style/quoted_symbols.rb +1 -3
- data/lib/rubocop/cop/style/redundant_argument.rb +24 -1
- data/lib/rubocop/cop/style/redundant_begin.rb +5 -1
- data/lib/rubocop/cop/style/redundant_condition.rb +4 -4
- data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +1 -1
- data/lib/rubocop/cop/style/redundant_each.rb +1 -1
- 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_interpolation_unfreeze.rb +46 -0
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +15 -18
- data/lib/rubocop/cop/style/redundant_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -1
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +4 -1
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -24
- data/lib/rubocop/cop/style/require_order.rb +2 -2
- data/lib/rubocop/cop/style/rescue_modifier.rb +13 -1
- data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +54 -12
- data/lib/rubocop/cop/style/safe_navigation.rb +94 -52
- data/lib/rubocop/cop/style/select_by_regexp.rb +9 -6
- data/lib/rubocop/cop/style/semicolon.rb +1 -1
- 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/sole_nested_conditional.rb +21 -2
- data/lib/rubocop/cop/style/special_global_vars.rb +1 -2
- data/lib/rubocop/cop/style/struct_inheritance.rb +1 -1
- data/lib/rubocop/cop/style/super_arguments.rb +174 -0
- data/lib/rubocop/cop/style/symbol_proc.rb +39 -5
- data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/top_level_method_definition.rb +1 -1
- data/lib/rubocop/cop/style/trivial_accessors.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 +27 -3
- data/lib/rubocop/cop/util.rb +8 -2
- data/lib/rubocop/cop/variable_force.rb +13 -1
- data/lib/rubocop/cops_documentation_generator.rb +73 -34
- data/lib/rubocop/core_ext/string.rb +2 -6
- data/lib/rubocop/ext/regexp_node.rb +9 -31
- data/lib/rubocop/ext/regexp_parser.rb +4 -21
- data/lib/rubocop/file_finder.rb +9 -4
- data/lib/rubocop/formatter/clang_style_formatter.rb +3 -7
- data/lib/rubocop/formatter/disabled_config_formatter.rb +13 -9
- data/lib/rubocop/formatter/formatter_set.rb +7 -1
- data/lib/rubocop/formatter/html_formatter.rb +3 -1
- data/lib/rubocop/formatter/junit_formatter.rb +70 -23
- data/lib/rubocop/formatter/tap_formatter.rb +3 -7
- data/lib/rubocop/lockfile.rb +58 -7
- data/lib/rubocop/lsp/routes.rb +10 -13
- data/lib/rubocop/lsp/runtime.rb +2 -0
- data/lib/rubocop/lsp/server.rb +2 -1
- data/lib/rubocop/lsp.rb +9 -2
- data/lib/rubocop/options.rb +6 -4
- data/lib/rubocop/rake_task.rb +1 -1
- data/lib/rubocop/remote_config.rb +5 -1
- data/lib/rubocop/result_cache.rb +2 -8
- data/lib/rubocop/rspec/expect_offense.rb +9 -0
- data/lib/rubocop/rspec/shared_contexts.rb +35 -3
- data/lib/rubocop/rspec/support.rb +1 -0
- data/lib/rubocop/runner.rb +8 -1
- data/lib/rubocop/server/cache.rb +16 -1
- data/lib/rubocop/server/client_command/exec.rb +2 -2
- data/lib/rubocop/server/client_command/start.rb +1 -1
- data/lib/rubocop/server/core.rb +5 -0
- data/lib/rubocop/target_ruby.rb +19 -15
- data/lib/rubocop/version.rb +7 -5
- data/lib/rubocop/yaml_duplication_checker.rb +20 -26
- data/lib/rubocop.rb +13 -1
- metadata +20 -32
|
@@ -3,88 +3,152 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Lint
|
|
6
|
-
# Check to make sure that if safe navigation is used
|
|
7
|
-
#
|
|
8
|
-
# method calls on
|
|
6
|
+
# Check to make sure that if safe navigation is used in an `&&` or `||` condition,
|
|
7
|
+
# consistent and appropriate safe navigation, without excess or deficiency,
|
|
8
|
+
# is used for all method calls on the same object.
|
|
9
9
|
#
|
|
10
10
|
# @example
|
|
11
11
|
# # bad
|
|
12
|
-
# foo&.bar && foo
|
|
12
|
+
# foo&.bar && foo&.baz
|
|
13
13
|
#
|
|
14
|
-
# #
|
|
15
|
-
# foo
|
|
14
|
+
# # good
|
|
15
|
+
# foo&.bar && foo.baz
|
|
16
16
|
#
|
|
17
17
|
# # bad
|
|
18
|
-
# foo
|
|
18
|
+
# foo.bar && foo&.baz
|
|
19
19
|
#
|
|
20
20
|
# # good
|
|
21
21
|
# foo.bar && foo.baz
|
|
22
22
|
#
|
|
23
|
+
# # bad
|
|
24
|
+
# foo&.bar || foo.baz
|
|
25
|
+
#
|
|
23
26
|
# # good
|
|
24
27
|
# foo&.bar || foo&.baz
|
|
25
28
|
#
|
|
29
|
+
# # bad
|
|
30
|
+
# foo.bar || foo&.baz
|
|
31
|
+
#
|
|
26
32
|
# # good
|
|
33
|
+
# foo.bar || foo.baz
|
|
34
|
+
#
|
|
35
|
+
# # bad
|
|
27
36
|
# foo&.bar && (foobar.baz || foo&.baz)
|
|
28
37
|
#
|
|
38
|
+
# # good
|
|
39
|
+
# foo&.bar && (foobar.baz || foo.baz)
|
|
40
|
+
#
|
|
29
41
|
class SafeNavigationConsistency < Base
|
|
30
|
-
include IgnoredNode
|
|
31
42
|
include NilMethods
|
|
32
43
|
extend AutoCorrector
|
|
33
44
|
|
|
34
|
-
|
|
45
|
+
USE_DOT_MSG = 'Use `.` instead of unnecessary `&.`.'
|
|
46
|
+
USE_SAFE_NAVIGATION_MSG = 'Use `&.` for consistency with safe navigation.'
|
|
47
|
+
|
|
48
|
+
def on_and(node)
|
|
49
|
+
all_operands = collect_operands(node, [])
|
|
50
|
+
operand_groups = all_operands.group_by { |operand| receiver_name_as_key(operand, +'') }
|
|
51
|
+
|
|
52
|
+
operand_groups.each_value do |grouped_operands|
|
|
53
|
+
next unless (dot_op, begin_of_rest_operands = find_consistent_parts(grouped_operands))
|
|
35
54
|
|
|
36
|
-
|
|
37
|
-
|
|
55
|
+
rest_operands = grouped_operands[begin_of_rest_operands..]
|
|
56
|
+
rest_operands.each do |operand|
|
|
57
|
+
next if already_appropriate_call?(operand, dot_op)
|
|
38
58
|
|
|
39
|
-
|
|
59
|
+
register_offense(operand, dot_op)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
40
62
|
end
|
|
63
|
+
alias on_or on_and
|
|
41
64
|
|
|
42
|
-
|
|
43
|
-
ancestor = top_conditional_ancestor(node)
|
|
44
|
-
conditions = ancestor.conditions
|
|
45
|
-
safe_nav_receiver = node.receiver
|
|
65
|
+
private
|
|
46
66
|
|
|
47
|
-
|
|
48
|
-
|
|
67
|
+
def collect_operands(node, operand_nodes)
|
|
68
|
+
operand_nodes(node.lhs, operand_nodes)
|
|
69
|
+
operand_nodes(node.rhs, operand_nodes)
|
|
49
70
|
|
|
50
|
-
|
|
51
|
-
|
|
71
|
+
operand_nodes
|
|
72
|
+
end
|
|
52
73
|
|
|
53
|
-
|
|
74
|
+
def receiver_name_as_key(method, fully_receivers)
|
|
75
|
+
if method.parent.call_type?
|
|
76
|
+
receiver(method.parent, fully_receivers)
|
|
77
|
+
else
|
|
78
|
+
fully_receivers << method.receiver&.source.to_s
|
|
79
|
+
end
|
|
80
|
+
end
|
|
54
81
|
|
|
55
|
-
|
|
82
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
83
|
+
def find_consistent_parts(grouped_operands)
|
|
84
|
+
csend_in_and, csend_in_or, send_in_and, send_in_or = most_left_indices(grouped_operands)
|
|
85
|
+
|
|
86
|
+
if csend_in_and
|
|
87
|
+
['.', (send_in_and ? [send_in_and, csend_in_and].min : csend_in_and) + 1]
|
|
88
|
+
elsif send_in_or && csend_in_or
|
|
89
|
+
send_in_or < csend_in_or ? ['.', send_in_or + 1] : ['&.', csend_in_or + 1]
|
|
90
|
+
elsif send_in_and && csend_in_or && send_in_and < csend_in_or
|
|
91
|
+
['.', csend_in_or]
|
|
56
92
|
end
|
|
57
93
|
end
|
|
94
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
58
95
|
|
|
59
|
-
|
|
96
|
+
def already_appropriate_call?(operand, dot_op)
|
|
97
|
+
(operand.safe_navigation? && dot_op == '&.') || (operand.dot? && dot_op == '.')
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def register_offense(operand, dot_operator)
|
|
101
|
+
offense_range = operand.operator_method? ? operand : operand.loc.dot
|
|
102
|
+
message = dot_operator == '.' ? USE_DOT_MSG : USE_SAFE_NAVIGATION_MSG
|
|
60
103
|
|
|
61
|
-
|
|
62
|
-
|
|
104
|
+
add_offense(offense_range, message: message) do |corrector|
|
|
105
|
+
next if operand.operator_method?
|
|
63
106
|
|
|
64
|
-
|
|
107
|
+
corrector.replace(operand.loc.dot, dot_operator)
|
|
108
|
+
end
|
|
65
109
|
end
|
|
66
110
|
|
|
67
|
-
def
|
|
68
|
-
|
|
111
|
+
def operand_nodes(operand, operand_nodes)
|
|
112
|
+
if operand.operator_keyword?
|
|
113
|
+
collect_operands(operand, operand_nodes)
|
|
114
|
+
elsif operand.call_type?
|
|
115
|
+
operand_nodes << operand
|
|
116
|
+
end
|
|
69
117
|
end
|
|
70
118
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
119
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
120
|
+
def most_left_indices(grouped_operands)
|
|
121
|
+
indices = { csend_in_and: nil, csend_in_or: nil, send_in_and: nil, send_in_or: nil }
|
|
122
|
+
|
|
123
|
+
grouped_operands.each_with_index do |operand, index|
|
|
124
|
+
indices[:csend_in_and] ||= index if operand_in_and?(operand) && operand.csend_type?
|
|
125
|
+
indices[:csend_in_or] ||= index if operand_in_or?(operand) && operand.csend_type?
|
|
126
|
+
indices[:send_in_and] ||= index if operand_in_and?(operand) && !nilable?(operand)
|
|
127
|
+
indices[:send_in_or] ||= index if operand_in_or?(operand) && !nilable?(operand)
|
|
77
128
|
end
|
|
78
129
|
|
|
79
|
-
|
|
130
|
+
indices.values
|
|
80
131
|
end
|
|
132
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
81
133
|
|
|
82
|
-
def
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
134
|
+
def operand_in_and?(node)
|
|
135
|
+
return true if node.parent.and_type?
|
|
136
|
+
|
|
137
|
+
parent = node.parent.parent while node.parent.begin_type?
|
|
138
|
+
|
|
139
|
+
parent&.and_type?
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def operand_in_or?(node)
|
|
143
|
+
return true if node.parent.or_type?
|
|
144
|
+
|
|
145
|
+
parent = node.parent.parent while node.parent.begin_type?
|
|
146
|
+
|
|
147
|
+
parent&.or_type?
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def nilable?(node)
|
|
151
|
+
node.csend_type? || nil_methods.include?(node.method_name)
|
|
88
152
|
end
|
|
89
153
|
end
|
|
90
154
|
end
|
|
@@ -12,17 +12,16 @@ module RuboCop
|
|
|
12
12
|
# because `Ractor` should not access outer variables.
|
|
13
13
|
# eg. following style is encouraged:
|
|
14
14
|
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
15
|
+
# [source,ruby]
|
|
16
|
+
# ----
|
|
17
|
+
# worker_id, pipe = env
|
|
18
|
+
# Ractor.new(worker_id, pipe) do |worker_id, pipe|
|
|
19
|
+
# end
|
|
20
|
+
# ----
|
|
21
21
|
#
|
|
22
22
|
# @example
|
|
23
23
|
#
|
|
24
24
|
# # bad
|
|
25
|
-
#
|
|
26
25
|
# def some_method
|
|
27
26
|
# foo = 1
|
|
28
27
|
#
|
|
@@ -31,10 +30,7 @@ module RuboCop
|
|
|
31
30
|
# end
|
|
32
31
|
# end
|
|
33
32
|
#
|
|
34
|
-
# @example
|
|
35
|
-
#
|
|
36
33
|
# # good
|
|
37
|
-
#
|
|
38
34
|
# def some_method
|
|
39
35
|
# foo = 1
|
|
40
36
|
#
|
|
@@ -49,15 +49,8 @@ module RuboCop
|
|
|
49
49
|
return unless def_node
|
|
50
50
|
|
|
51
51
|
enum_conversion_call?(node) do |method_node, arguments|
|
|
52
|
-
next if method_node.
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
valid = if method_name?(method_node, def_node.method_name)
|
|
56
|
-
arguments_match?(arguments, def_node)
|
|
57
|
-
else
|
|
58
|
-
def_node.arguments.empty?
|
|
59
|
-
end
|
|
60
|
-
return if valid
|
|
52
|
+
next if !method_name?(method_node, def_node.method_name) ||
|
|
53
|
+
arguments_match?(arguments, def_node)
|
|
61
54
|
|
|
62
55
|
add_offense(node)
|
|
63
56
|
end
|
|
@@ -10,14 +10,12 @@ module RuboCop
|
|
|
10
10
|
# @example
|
|
11
11
|
#
|
|
12
12
|
# # bad
|
|
13
|
-
#
|
|
14
13
|
# def some_method
|
|
15
14
|
# return
|
|
16
15
|
# do_something
|
|
17
16
|
# end
|
|
18
17
|
#
|
|
19
18
|
# # bad
|
|
20
|
-
#
|
|
21
19
|
# def some_method
|
|
22
20
|
# if cond
|
|
23
21
|
# return
|
|
@@ -27,10 +25,7 @@ module RuboCop
|
|
|
27
25
|
# do_something
|
|
28
26
|
# end
|
|
29
27
|
#
|
|
30
|
-
# @example
|
|
31
|
-
#
|
|
32
28
|
# # good
|
|
33
|
-
#
|
|
34
29
|
# def some_method
|
|
35
30
|
# do_something
|
|
36
31
|
# end
|
|
@@ -71,7 +66,7 @@ module RuboCop
|
|
|
71
66
|
expressions.any? { |expr| flow_expression?(expr) }
|
|
72
67
|
when :if
|
|
73
68
|
check_if(node)
|
|
74
|
-
when :case
|
|
69
|
+
when :case, :case_match
|
|
75
70
|
check_case(node)
|
|
76
71
|
else
|
|
77
72
|
false
|
|
@@ -89,7 +84,9 @@ module RuboCop
|
|
|
89
84
|
return false unless else_branch
|
|
90
85
|
return false unless flow_expression?(else_branch)
|
|
91
86
|
|
|
92
|
-
node.
|
|
87
|
+
branches = node.case_type? ? node.when_branches : node.in_pattern_branches
|
|
88
|
+
|
|
89
|
+
branches.all? { |branch| branch.body && flow_expression?(branch.body) }
|
|
93
90
|
end
|
|
94
91
|
end
|
|
95
92
|
end
|
|
@@ -160,7 +160,7 @@ module RuboCop
|
|
|
160
160
|
break_statement && !preceded_by_continue_statement?(break_statement)
|
|
161
161
|
when :if
|
|
162
162
|
check_if(node)
|
|
163
|
-
when :case
|
|
163
|
+
when :case, :case_match
|
|
164
164
|
check_case(node)
|
|
165
165
|
else
|
|
166
166
|
false
|
|
@@ -178,7 +178,13 @@ module RuboCop
|
|
|
178
178
|
return false unless else_branch
|
|
179
179
|
return false unless break_statement?(else_branch)
|
|
180
180
|
|
|
181
|
-
|
|
181
|
+
branches = if node.case_type?
|
|
182
|
+
node.when_branches
|
|
183
|
+
else
|
|
184
|
+
node.in_pattern_branches
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
branches.all? { |branch| branch.body && break_statement?(branch.body) }
|
|
182
188
|
end
|
|
183
189
|
|
|
184
190
|
def preceded_by_continue_statement?(break_statement)
|
|
@@ -3,29 +3,47 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Lint
|
|
6
|
-
# Identifies places where `URI.regexp` is obsolete and should
|
|
7
|
-
#
|
|
6
|
+
# Identifies places where `URI.regexp` is obsolete and should not be used.
|
|
7
|
+
#
|
|
8
|
+
# For Ruby 3.3 or lower, use `URI::DEFAULT_PARSER.make_regexp`.
|
|
9
|
+
# For Ruby 3.4 or higher, use `URI::RFC2396_PARSER.make_regexp`.
|
|
10
|
+
#
|
|
11
|
+
# NOTE: If you need to support both Ruby 3.3 and lower as well as Ruby 3.4 and higher,
|
|
12
|
+
# consider manually changing the code as follows:
|
|
13
|
+
#
|
|
14
|
+
# [source,ruby]
|
|
15
|
+
# ----
|
|
16
|
+
# defined?(URI::RFC2396_PARSER) ? URI::RFC2396_PARSER : URI::DEFAULT_PARSER
|
|
17
|
+
# ----
|
|
8
18
|
#
|
|
9
19
|
# @example
|
|
10
20
|
# # bad
|
|
11
21
|
# URI.regexp('http://example.com')
|
|
12
22
|
#
|
|
13
|
-
# # good
|
|
23
|
+
# # good - Ruby 3.3 or lower
|
|
14
24
|
# URI::DEFAULT_PARSER.make_regexp('http://example.com')
|
|
15
25
|
#
|
|
26
|
+
# # good - Ruby 3.4 or higher
|
|
27
|
+
# URI::RFC2396_PARSER.make_regexp('http://example.com')
|
|
28
|
+
#
|
|
16
29
|
class UriRegexp < Base
|
|
17
30
|
extend AutoCorrector
|
|
18
31
|
|
|
19
32
|
MSG = '`%<current>s` is obsolete and should not be used. Instead, use `%<preferred>s`.'
|
|
20
|
-
URI_CONSTANTS = ['URI', '::URI'].freeze
|
|
21
33
|
RESTRICT_ON_SEND = %i[regexp].freeze
|
|
22
34
|
|
|
35
|
+
# @!method uri_constant?(node)
|
|
36
|
+
def_node_matcher :uri_constant?, <<~PATTERN
|
|
37
|
+
(const {cbase nil?} :URI)
|
|
38
|
+
PATTERN
|
|
39
|
+
|
|
23
40
|
def on_send(node)
|
|
24
|
-
return unless node.receiver
|
|
25
|
-
return unless URI_CONSTANTS.include?(node.receiver.source)
|
|
41
|
+
return unless uri_constant?(node.receiver)
|
|
26
42
|
|
|
43
|
+
parser = target_ruby_version >= 3.4 ? 'RFC2396_PARSER' : 'DEFAULT_PARSER'
|
|
27
44
|
argument = node.first_argument ? "(#{node.first_argument.source})" : ''
|
|
28
|
-
|
|
45
|
+
|
|
46
|
+
preferred_method = "#{node.receiver.source}::#{parser}.make_regexp#{argument}"
|
|
29
47
|
message = format(MSG, current: node.source, preferred: preferred_method)
|
|
30
48
|
|
|
31
49
|
add_offense(node.loc.selector, message: message) do |corrector|
|
|
@@ -16,28 +16,23 @@ module RuboCop
|
|
|
16
16
|
# reassignments and properly handles varied cases such as branch, loop,
|
|
17
17
|
# rescue, ensure, etc.
|
|
18
18
|
#
|
|
19
|
+
# This cop's autocorrection avoids cases like `a ||= 1` because removing assignment from
|
|
20
|
+
# operator assignment can cause NameError if this assignment has been used to declare
|
|
21
|
+
# a local variable. For example, replacing `a ||= 1` with `a || 1` may cause
|
|
22
|
+
# "undefined local variable or method `a' for main:Object (NameError)".
|
|
23
|
+
#
|
|
19
24
|
# NOTE: Given the assignment `foo = 1, bar = 2`, removing unused variables
|
|
20
25
|
# can lead to a syntax error, so this case is not autocorrected.
|
|
21
26
|
#
|
|
22
|
-
# @safety
|
|
23
|
-
# This cop's autocorrection is unsafe because removing assignment from
|
|
24
|
-
# operator assignment can cause NameError if this assignment has been used to declare
|
|
25
|
-
# local variable. For example, replacing `a ||= 1` to `a || 1` may cause
|
|
26
|
-
# "undefined local variable or method `a' for main:Object (NameError)".
|
|
27
|
-
#
|
|
28
27
|
# @example
|
|
29
28
|
#
|
|
30
29
|
# # bad
|
|
31
|
-
#
|
|
32
30
|
# def some_method
|
|
33
31
|
# some_var = 1
|
|
34
32
|
# do_something
|
|
35
33
|
# end
|
|
36
34
|
#
|
|
37
|
-
# @example
|
|
38
|
-
#
|
|
39
35
|
# # good
|
|
40
|
-
#
|
|
41
36
|
# def some_method
|
|
42
37
|
# some_var = 1
|
|
43
38
|
# do_something(some_var)
|
|
@@ -57,24 +52,32 @@ module RuboCop
|
|
|
57
52
|
scope.variables.each_value { |variable| check_for_unused_assignments(variable) }
|
|
58
53
|
end
|
|
59
54
|
|
|
60
|
-
# rubocop:disable Metrics/AbcSize
|
|
55
|
+
# rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
|
|
61
56
|
def check_for_unused_assignments(variable)
|
|
62
57
|
return if variable.should_be_unused?
|
|
63
58
|
|
|
64
|
-
variable.assignments.
|
|
65
|
-
|
|
59
|
+
variable.assignments.reverse_each do |assignment|
|
|
60
|
+
assignment_node = assignment.node
|
|
61
|
+
next if assignment.used? || part_of_ignored_node?(assignment_node)
|
|
66
62
|
|
|
67
63
|
message = message_for_useless_assignment(assignment)
|
|
68
64
|
range = offense_range(assignment)
|
|
69
65
|
|
|
70
66
|
add_offense(range, message: message) do |corrector|
|
|
71
|
-
|
|
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
|
|
73
|
+
|
|
74
|
+
autocorrect(corrector, assignment)
|
|
72
75
|
end
|
|
73
76
|
|
|
74
|
-
ignore_node(
|
|
77
|
+
ignore_node(assignment_node) if chained_assignment?(assignment_node)
|
|
75
78
|
end
|
|
76
79
|
end
|
|
77
|
-
# rubocop:enable Metrics/AbcSize
|
|
80
|
+
# rubocop:enable Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
|
|
78
81
|
|
|
79
82
|
def message_for_useless_assignment(assignment)
|
|
80
83
|
variable = assignment.variable
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Lint
|
|
6
|
+
# Certain numeric operations have no impact, being:
|
|
7
|
+
# Adding or subtracting 0, multiplying or dividing by 1 or raising to the power of 1.
|
|
8
|
+
# These are probably leftover from debugging, or are mistakes.
|
|
9
|
+
#
|
|
10
|
+
# @example
|
|
11
|
+
#
|
|
12
|
+
# # bad
|
|
13
|
+
# x + 0
|
|
14
|
+
# x - 0
|
|
15
|
+
# x * 1
|
|
16
|
+
# x / 1
|
|
17
|
+
# x ** 1
|
|
18
|
+
#
|
|
19
|
+
# # good
|
|
20
|
+
# x
|
|
21
|
+
#
|
|
22
|
+
# # bad
|
|
23
|
+
# x += 0
|
|
24
|
+
# x -= 0
|
|
25
|
+
# x *= 1
|
|
26
|
+
# x /= 1
|
|
27
|
+
# x **= 1
|
|
28
|
+
#
|
|
29
|
+
# # good
|
|
30
|
+
# x = x
|
|
31
|
+
#
|
|
32
|
+
class UselessNumericOperation < Base
|
|
33
|
+
extend AutoCorrector
|
|
34
|
+
MSG = 'Do not apply inconsequential numeric operations to variables.'
|
|
35
|
+
RESTRICT_ON_SEND = %i[+ - * / **].freeze
|
|
36
|
+
|
|
37
|
+
# @!method useless_operation?(node)
|
|
38
|
+
def_node_matcher :useless_operation?, '(send (send nil? $_) $_ (int $_))'
|
|
39
|
+
|
|
40
|
+
# @!method useless_abbreviated_assignment?(node)
|
|
41
|
+
def_node_matcher :useless_abbreviated_assignment?, '(op-asgn (lvasgn $_) $_ (int $_))'
|
|
42
|
+
|
|
43
|
+
def on_send(node)
|
|
44
|
+
return unless useless_operation?(node)
|
|
45
|
+
|
|
46
|
+
variable, operation, number = useless_operation?(node)
|
|
47
|
+
return unless useless?(operation, number)
|
|
48
|
+
|
|
49
|
+
add_offense(node) do |corrector|
|
|
50
|
+
corrector.replace(node, variable)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def on_op_asgn(node)
|
|
55
|
+
return unless useless_abbreviated_assignment?(node)
|
|
56
|
+
|
|
57
|
+
variable, operation, number = useless_abbreviated_assignment?(node)
|
|
58
|
+
return unless useless?(operation, number)
|
|
59
|
+
|
|
60
|
+
add_offense(node) do |corrector|
|
|
61
|
+
corrector.replace(node, "#{variable} = #{variable}")
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
private
|
|
66
|
+
|
|
67
|
+
def useless?(operation, number)
|
|
68
|
+
if number.zero?
|
|
69
|
+
true if %i[+ -].include?(operation)
|
|
70
|
+
elsif number == 1
|
|
71
|
+
true if %i[* / **].include?(operation)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|