rubocop 1.50.2 → 1.62.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 +7 -5
- data/assets/output.css.erb +159 -0
- data/assets/output.html.erb +1 -160
- data/config/default.yml +196 -28
- data/config/obsoletion.yml +5 -0
- data/lib/rubocop/cli/command/auto_generate_config.rb +22 -8
- data/lib/rubocop/cli/command/lsp.rb +19 -0
- data/lib/rubocop/cli.rb +10 -2
- data/lib/rubocop/config.rb +8 -2
- data/lib/rubocop/config_finder.rb +14 -4
- data/lib/rubocop/config_loader.rb +0 -1
- data/lib/rubocop/config_loader_resolver.rb +4 -3
- data/lib/rubocop/config_obsoletion/parameter_rule.rb +9 -1
- data/lib/rubocop/config_obsoletion.rb +13 -10
- data/lib/rubocop/config_validator.rb +14 -7
- data/lib/rubocop/cop/autocorrect_logic.rb +9 -2
- data/lib/rubocop/cop/base.rb +23 -4
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -0
- data/lib/rubocop/cop/bundler/duplicated_group.rb +127 -0
- data/lib/rubocop/cop/bundler/gem_comment.rb +3 -3
- data/lib/rubocop/cop/bundler/gem_version.rb +2 -2
- data/lib/rubocop/cop/bundler/ordered_gems.rb +9 -1
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +1 -1
- 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/correctors/lambda_literal_to_method_corrector.rb +7 -4
- data/lib/rubocop/cop/exclude_limit.rb +1 -1
- data/lib/rubocop/cop/gemspec/dependency_version.rb +2 -2
- data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +2 -2
- data/lib/rubocop/cop/gemspec/development_dependencies.rb +1 -1
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +9 -1
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +5 -1
- data/lib/rubocop/cop/generator/require_file_injector.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/cop_description.rb +32 -8
- data/lib/rubocop/cop/internal_affairs/example_description.rb +45 -24
- data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +3 -1
- data/lib/rubocop/cop/internal_affairs/method_name_end_with.rb +8 -6
- data/lib/rubocop/cop/internal_affairs/method_name_equal.rb +19 -20
- data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +53 -0
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +127 -33
- data/lib/rubocop/cop/internal_affairs/redundant_expect_offense_arguments.rb +34 -0
- data/lib/rubocop/cop/internal_affairs/redundant_method_dispatch_node.rb +11 -2
- data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +2 -0
- data/lib/rubocop/cop/internal_affairs.rb +2 -0
- data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/class_structure.rb +7 -0
- data/lib/rubocop/cop/layout/closing_heredoc_indentation.rb +1 -2
- data/lib/rubocop/cop/layout/dot_position.rb +1 -5
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +42 -9
- data/lib/rubocop/cop/layout/empty_line_after_magic_comment.rb +14 -7
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +27 -4
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +2 -0
- data/lib/rubocop/cop/layout/end_alignment.rb +15 -3
- data/lib/rubocop/cop/layout/extra_spacing.rb +4 -10
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +22 -7
- data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +4 -4
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +4 -1
- data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +3 -3
- data/lib/rubocop/cop/layout/leading_comment_space.rb +1 -1
- data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +17 -9
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
- data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +2 -0
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +18 -3
- data/lib/rubocop/cop/layout/redundant_line_break.rb +30 -7
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +4 -4
- data/lib/rubocop/cop/layout/single_line_block_chain.rb +5 -0
- data/lib/rubocop/cop/layout/space_after_comma.rb +9 -1
- data/lib/rubocop/cop/layout/space_after_not.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +2 -2
- data/lib/rubocop/cop/layout/space_around_operators.rb +53 -21
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +19 -10
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +2 -0
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +1 -1
- data/lib/rubocop/cop/layout/space_inside_parens.rb +1 -1
- data/lib/rubocop/cop/layout/space_inside_range_literal.rb +1 -1
- data/lib/rubocop/cop/layout/trailing_empty_lines.rb +5 -0
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +13 -1
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +4 -4
- data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +2 -2
- data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +1 -1
- data/lib/rubocop/cop/lint/debugger.rb +19 -5
- data/lib/rubocop/cop/lint/duplicate_hash_key.rb +2 -1
- data/lib/rubocop/cop/lint/duplicate_methods.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +46 -19
- data/lib/rubocop/cop/lint/empty_block.rb +1 -1
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +1 -1
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +6 -7
- data/lib/rubocop/cop/lint/float_comparison.rb +10 -0
- data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +2 -1
- data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +1 -1
- data/lib/rubocop/cop/lint/identity_comparison.rb +0 -1
- data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -3
- data/lib/rubocop/cop/lint/inherit_exception.rb +9 -0
- data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +56 -0
- data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
- data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +85 -0
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
- data/lib/rubocop/cop/lint/missing_super.rb +34 -5
- data/lib/rubocop/cop/lint/mixed_case_range.rb +111 -0
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +6 -21
- data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +10 -7
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -5
- data/lib/rubocop/cop/lint/number_conversion.rb +14 -4
- data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +2 -2
- data/lib/rubocop/cop/lint/ordered_magic_comments.rb +0 -1
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +2 -2
- data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +130 -0
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +12 -3
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +72 -8
- data/lib/rubocop/cop/lint/redundant_string_coercion.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_with_index.rb +3 -2
- data/lib/rubocop/cop/lint/redundant_with_object.rb +2 -2
- data/lib/rubocop/cop/lint/rescue_type.rb +1 -3
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +14 -8
- data/lib/rubocop/cop/lint/script_permission.rb +3 -3
- data/lib/rubocop/cop/lint/self_assignment.rb +38 -0
- data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +1 -2
- data/lib/rubocop/cop/lint/shadowed_argument.rb +1 -0
- data/lib/rubocop/cop/lint/shadowed_exception.rb +5 -11
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +7 -1
- data/lib/rubocop/cop/lint/struct_new_override.rb +12 -12
- data/lib/rubocop/cop/lint/suppressed_exception.rb +2 -2
- data/lib/rubocop/cop/lint/symbol_conversion.rb +8 -3
- data/lib/rubocop/cop/lint/syntax.rb +6 -3
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +12 -5
- data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +23 -9
- data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +1 -1
- data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +2 -2
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +2 -2
- data/lib/rubocop/cop/lint/useless_assignment.rb +94 -10
- data/lib/rubocop/cop/lint/useless_times.rb +2 -2
- data/lib/rubocop/cop/lint/void.rb +97 -11
- data/lib/rubocop/cop/metrics/abc_size.rb +3 -3
- data/lib/rubocop/cop/metrics/block_length.rb +1 -1
- data/lib/rubocop/cop/metrics/class_length.rb +8 -3
- data/lib/rubocop/cop/metrics/method_length.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -2
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +32 -4
- data/lib/rubocop/cop/migration/department_name.rb +2 -2
- data/lib/rubocop/cop/mixin/allowed_receivers.rb +34 -0
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
- data/lib/rubocop/cop/mixin/comments_help.rb +19 -11
- data/lib/rubocop/cop/mixin/configurable_formatting.rb +1 -0
- data/lib/rubocop/cop/mixin/def_node.rb +1 -1
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -1
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +14 -11
- data/lib/rubocop/cop/mixin/heredoc.rb +6 -2
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +4 -3
- data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +6 -8
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
- data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
- data/lib/rubocop/cop/mixin/string_help.rb +4 -2
- data/lib/rubocop/cop/mixin/trailing_comma.rb +1 -1
- data/lib/rubocop/cop/naming/block_forwarding.rb +13 -5
- data/lib/rubocop/cop/naming/constant_name.rb +2 -3
- data/lib/rubocop/cop/naming/file_name.rb +1 -1
- data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +3 -1
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +26 -11
- data/lib/rubocop/cop/naming/predicate_name.rb +2 -2
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +11 -3
- data/lib/rubocop/cop/naming/variable_name.rb +6 -1
- data/lib/rubocop/cop/registry.rb +1 -1
- data/lib/rubocop/cop/security/open.rb +2 -2
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +2 -2
- data/lib/rubocop/cop/style/accessor_grouping.rb +6 -2
- data/lib/rubocop/cop/style/alias.rb +9 -8
- data/lib/rubocop/cop/style/arguments_forwarding.rb +411 -63
- data/lib/rubocop/cop/style/array_first_last.rb +64 -0
- data/lib/rubocop/cop/style/array_intersect.rb +13 -5
- data/lib/rubocop/cop/style/attr.rb +11 -1
- data/lib/rubocop/cop/style/auto_resource_cleanup.rb +21 -14
- data/lib/rubocop/cop/style/begin_block.rb +1 -2
- data/lib/rubocop/cop/style/bisected_attr_accessor.rb +2 -2
- data/lib/rubocop/cop/style/block_comments.rb +1 -1
- data/lib/rubocop/cop/style/block_delimiters.rb +5 -4
- data/lib/rubocop/cop/style/case_like_if.rb +5 -5
- data/lib/rubocop/cop/style/class_and_module_children.rb +1 -1
- data/lib/rubocop/cop/style/class_check.rb +1 -0
- data/lib/rubocop/cop/style/class_equality_comparison.rb +24 -39
- data/lib/rubocop/cop/style/class_vars.rb +3 -3
- data/lib/rubocop/cop/style/collection_compact.rb +32 -12
- data/lib/rubocop/cop/style/collection_methods.rb +2 -0
- data/lib/rubocop/cop/style/colon_method_call.rb +2 -2
- data/lib/rubocop/cop/style/combinable_loops.rb +36 -8
- data/lib/rubocop/cop/style/commented_keyword.rb +5 -2
- data/lib/rubocop/cop/style/concat_array_literals.rb +2 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +11 -10
- data/lib/rubocop/cop/style/copyright.rb +5 -2
- data/lib/rubocop/cop/style/date_time.rb +5 -4
- data/lib/rubocop/cop/style/dir.rb +1 -1
- data/lib/rubocop/cop/style/dir_empty.rb +8 -14
- data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +1 -1
- data/lib/rubocop/cop/style/documentation.rb +1 -1
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +7 -7
- data/lib/rubocop/cop/style/each_with_object.rb +2 -2
- data/lib/rubocop/cop/style/empty_case_condition.rb +6 -1
- data/lib/rubocop/cop/style/empty_literal.rb +1 -1
- data/lib/rubocop/cop/style/eval_with_location.rb +8 -19
- data/lib/rubocop/cop/style/exact_regexp_match.rb +69 -0
- data/lib/rubocop/cop/style/explicit_block_argument.rb +2 -2
- data/lib/rubocop/cop/style/file_read.rb +2 -2
- data/lib/rubocop/cop/style/for.rb +3 -1
- data/lib/rubocop/cop/style/format_string.rb +24 -3
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +3 -1
- data/lib/rubocop/cop/style/guard_clause.rb +28 -0
- data/lib/rubocop/cop/style/hash_conversion.rb +10 -0
- data/lib/rubocop/cop/style/hash_each_methods.rb +106 -33
- data/lib/rubocop/cop/style/hash_except.rb +21 -9
- data/lib/rubocop/cop/style/hash_syntax.rb +6 -2
- data/lib/rubocop/cop/style/hash_transform_keys.rb +2 -2
- data/lib/rubocop/cop/style/hash_transform_values.rb +2 -2
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +34 -5
- data/lib/rubocop/cop/style/if_inside_else.rb +6 -0
- data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -0
- data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -2
- data/lib/rubocop/cop/style/inverse_methods.rb +14 -13
- data/lib/rubocop/cop/style/invertible_unless_condition.rb +54 -8
- data/lib/rubocop/cop/style/lambda.rb +3 -3
- data/lib/rubocop/cop/style/lambda_call.rb +5 -0
- data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +8 -10
- data/lib/rubocop/cop/style/map_to_hash.rb +17 -7
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +24 -9
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -4
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +20 -0
- data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/missing_respond_to_missing.rb +2 -2
- data/lib/rubocop/cop/style/mixin_grouping.rb +1 -1
- data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -1
- data/lib/rubocop/cop/style/multiline_method_signature.rb +10 -1
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +6 -4
- data/lib/rubocop/cop/style/multiple_comparison.rb +14 -0
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +3 -11
- data/lib/rubocop/cop/style/next.rb +1 -1
- 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_literals.rb +1 -1
- data/lib/rubocop/cop/style/object_then.rb +5 -3
- data/lib/rubocop/cop/style/open_struct_use.rb +1 -1
- data/lib/rubocop/cop/style/operator_method_call.rb +8 -2
- 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/percent_literal_delimiters.rb +1 -1
- data/lib/rubocop/cop/style/preferred_hash_methods.rb +1 -1
- data/lib/rubocop/cop/style/raise_args.rb +4 -1
- data/lib/rubocop/cop/style/redundant_argument.rb +10 -4
- data/lib/rubocop/cop/style/redundant_array_constructor.rb +77 -0
- data/lib/rubocop/cop/style/redundant_assignment.rb +10 -2
- data/lib/rubocop/cop/style/redundant_begin.rb +10 -2
- data/lib/rubocop/cop/style/redundant_conditional.rb +2 -10
- data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +39 -0
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +93 -5
- data/lib/rubocop/cop/style/redundant_each.rb +7 -4
- data/lib/rubocop/cop/style/redundant_exception.rb +32 -12
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +3 -3
- data/lib/rubocop/cop/style/redundant_filter_chain.rb +118 -0
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +32 -8
- data/lib/rubocop/cop/style/redundant_parentheses.rb +72 -23
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +100 -0
- data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +46 -0
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +2 -1
- data/lib/rubocop/cop/style/redundant_return.rb +14 -3
- data/lib/rubocop/cop/style/redundant_self.rb +17 -2
- data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +8 -1
- data/lib/rubocop/cop/style/redundant_sort.rb +10 -9
- data/lib/rubocop/cop/style/redundant_sort_by.rb +2 -2
- data/lib/rubocop/cop/style/redundant_string_escape.rb +3 -1
- data/lib/rubocop/cop/style/regexp_literal.rb +11 -2
- data/lib/rubocop/cop/style/require_order.rb +11 -5
- data/lib/rubocop/cop/style/rescue_modifier.rb +1 -3
- data/lib/rubocop/cop/style/return_nil.rb +6 -2
- data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +95 -0
- data/lib/rubocop/cop/style/sample.rb +3 -4
- data/lib/rubocop/cop/style/select_by_regexp.rb +22 -11
- data/lib/rubocop/cop/style/self_assignment.rb +1 -1
- data/lib/rubocop/cop/style/semicolon.rb +20 -4
- data/lib/rubocop/cop/style/signal_exception.rb +1 -1
- data/lib/rubocop/cop/style/single_argument_dig.rb +7 -3
- data/lib/rubocop/cop/style/single_line_do_end_block.rb +67 -0
- data/lib/rubocop/cop/style/single_line_methods.rb +1 -1
- data/lib/rubocop/cop/style/slicing_with_range.rb +76 -10
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +6 -2
- data/lib/rubocop/cop/style/special_global_vars.rb +3 -4
- data/lib/rubocop/cop/style/string_chars.rb +1 -0
- data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +30 -5
- data/lib/rubocop/cop/style/strip.rb +7 -4
- data/lib/rubocop/cop/style/super_with_args_parentheses.rb +35 -0
- data/lib/rubocop/cop/style/symbol_array.rb +35 -15
- data/lib/rubocop/cop/style/symbol_proc.rb +36 -0
- data/lib/rubocop/cop/style/unpack_first.rb +11 -14
- data/lib/rubocop/cop/style/yaml_file_read.rb +66 -0
- data/lib/rubocop/cop/style/yoda_condition.rb +4 -2
- data/lib/rubocop/cop/style/yoda_expression.rb +8 -7
- data/lib/rubocop/cop/team.rb +1 -1
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/cop/utils/regexp_ranges.rb +113 -0
- data/lib/rubocop/cop/variable_force/assignment.rb +45 -4
- data/lib/rubocop/cop/variable_force/variable_table.rb +2 -2
- data/lib/rubocop/cop/variable_force.rb +1 -0
- data/lib/rubocop/cops_documentation_generator.rb +16 -4
- data/lib/rubocop/directive_comment.rb +10 -8
- data/lib/rubocop/ext/regexp_node.rb +9 -4
- data/lib/rubocop/ext/regexp_parser.rb +4 -1
- data/lib/rubocop/file_finder.rb +4 -7
- data/lib/rubocop/formatter/disabled_config_formatter.rb +17 -6
- data/lib/rubocop/formatter/html_formatter.rb +35 -14
- data/lib/rubocop/formatter/json_formatter.rb +0 -1
- data/lib/rubocop/formatter/junit_formatter.rb +1 -1
- data/lib/rubocop/formatter/offense_count_formatter.rb +12 -2
- data/lib/rubocop/formatter.rb +1 -1
- data/lib/rubocop/lsp/logger.rb +22 -0
- data/lib/rubocop/lsp/routes.rb +246 -0
- data/lib/rubocop/lsp/runtime.rb +99 -0
- data/lib/rubocop/lsp/server.rb +71 -0
- data/lib/rubocop/lsp/severity.rb +27 -0
- data/lib/rubocop/lsp.rb +29 -0
- data/lib/rubocop/magic_comment.rb +13 -11
- data/lib/rubocop/options.rb +22 -9
- data/lib/rubocop/path_util.rb +6 -2
- data/lib/rubocop/result_cache.rb +5 -2
- data/lib/rubocop/rspec/cop_helper.rb +8 -2
- data/lib/rubocop/rspec/expect_offense.rb +8 -8
- data/lib/rubocop/rspec/shared_contexts.rb +42 -18
- data/lib/rubocop/rspec/support.rb +2 -0
- data/lib/rubocop/runner.rb +15 -6
- data/lib/rubocop/server/cache.rb +1 -1
- data/lib/rubocop/server/client_command/exec.rb +3 -3
- data/lib/rubocop/server/server_command/exec.rb +0 -1
- data/lib/rubocop/string_interpreter.rb +3 -3
- data/lib/rubocop/target_finder.rb +91 -81
- data/lib/rubocop/target_ruby.rb +85 -78
- data/lib/rubocop/version.rb +27 -8
- data/lib/rubocop.rb +19 -0
- metadata +56 -14
- /data/lib/rubocop/formatter/{git_hub_actions_formatter.rb → github_actions_formatter.rb} +0 -0
@@ -35,6 +35,8 @@ module RuboCop
|
|
35
35
|
# array.join('')
|
36
36
|
# [1, 2, 3].join("")
|
37
37
|
# array.sum(0)
|
38
|
+
# exit(true)
|
39
|
+
# exit!(false)
|
38
40
|
# string.split(" ")
|
39
41
|
# "first\nsecond".split(" ")
|
40
42
|
# string.chomp("\n")
|
@@ -45,6 +47,8 @@ module RuboCop
|
|
45
47
|
# array.join
|
46
48
|
# [1, 2, 3].join
|
47
49
|
# array.sum
|
50
|
+
# exit
|
51
|
+
# exit!
|
48
52
|
# string.split
|
49
53
|
# "first second".split
|
50
54
|
# string.chomp
|
@@ -55,19 +59,21 @@ module RuboCop
|
|
55
59
|
extend AutoCorrector
|
56
60
|
|
57
61
|
MSG = 'Argument %<arg>s is redundant because it is implied by default.'
|
62
|
+
NO_RECEIVER_METHODS = %i[exit exit!].freeze
|
58
63
|
|
59
64
|
def on_send(node)
|
60
|
-
return if node.receiver.nil?
|
65
|
+
return if !NO_RECEIVER_METHODS.include?(node.method_name) && node.receiver.nil?
|
61
66
|
return if node.arguments.count != 1
|
62
67
|
return unless redundant_argument?(node)
|
63
68
|
|
64
69
|
offense_range = argument_range(node)
|
65
|
-
message = format(MSG, arg: node.
|
70
|
+
message = format(MSG, arg: node.first_argument.source)
|
66
71
|
|
67
72
|
add_offense(offense_range, message: message) do |corrector|
|
68
73
|
corrector.remove(offense_range)
|
69
74
|
end
|
70
75
|
end
|
76
|
+
alias on_csend on_send
|
71
77
|
|
72
78
|
private
|
73
79
|
|
@@ -75,14 +81,14 @@ module RuboCop
|
|
75
81
|
redundant_argument = redundant_arg_for_method(node.method_name.to_s)
|
76
82
|
return false if redundant_argument.nil?
|
77
83
|
|
78
|
-
node.
|
84
|
+
node.first_argument.source.sub(/\A'/, '"').sub(/'\z/, '"') == redundant_argument
|
79
85
|
end
|
80
86
|
|
81
87
|
def redundant_arg_for_method(method_name)
|
82
88
|
arg = cop_config['Methods'].fetch(method_name) { return }
|
83
89
|
|
84
90
|
@mem ||= {}
|
85
|
-
@mem[method_name] ||=
|
91
|
+
@mem[method_name] ||= arg.inspect
|
86
92
|
end
|
87
93
|
|
88
94
|
def argument_range(node)
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Checks for the instantiation of array using redundant `Array` constructor.
|
7
|
+
# Autocorrect replaces to array literal which is the simplest and fastest.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
#
|
11
|
+
# # bad
|
12
|
+
# Array.new([])
|
13
|
+
# Array[]
|
14
|
+
# Array([])
|
15
|
+
# Array.new(['foo', 'foo', 'foo'])
|
16
|
+
# Array['foo', 'foo', 'foo']
|
17
|
+
# Array(['foo', 'foo', 'foo'])
|
18
|
+
#
|
19
|
+
# # good
|
20
|
+
# []
|
21
|
+
# ['foo', 'foo', 'foo']
|
22
|
+
# Array.new(3, 'foo')
|
23
|
+
# Array.new(3) { 'foo' }
|
24
|
+
#
|
25
|
+
class RedundantArrayConstructor < Base
|
26
|
+
extend AutoCorrector
|
27
|
+
|
28
|
+
MSG = 'Remove the redundant `Array` constructor.'
|
29
|
+
|
30
|
+
RESTRICT_ON_SEND = %i[new [] Array].freeze
|
31
|
+
|
32
|
+
# @!method redundant_array_constructor(node)
|
33
|
+
def_node_matcher :redundant_array_constructor, <<~PATTERN
|
34
|
+
{
|
35
|
+
(send
|
36
|
+
(const {nil? cbase} :Array) :new
|
37
|
+
$(array ...))
|
38
|
+
(send
|
39
|
+
(const {nil? cbase} :Array) :[]
|
40
|
+
$...)
|
41
|
+
(send
|
42
|
+
nil? :Array
|
43
|
+
$(array ...))
|
44
|
+
}
|
45
|
+
PATTERN
|
46
|
+
|
47
|
+
def on_send(node)
|
48
|
+
return unless (array_literal = redundant_array_constructor(node))
|
49
|
+
|
50
|
+
receiver = node.receiver
|
51
|
+
selector = node.loc.selector
|
52
|
+
|
53
|
+
if node.method?(:new)
|
54
|
+
range = receiver.source_range.join(selector)
|
55
|
+
replacement = array_literal
|
56
|
+
elsif node.method?(:Array)
|
57
|
+
range = selector
|
58
|
+
replacement = array_literal
|
59
|
+
else
|
60
|
+
range = receiver
|
61
|
+
replacement = selector.begin.join(node.source_range.end)
|
62
|
+
end
|
63
|
+
|
64
|
+
register_offense(range, node, replacement)
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def register_offense(range, node, replacement)
|
70
|
+
add_offense(range) do |corrector|
|
71
|
+
corrector.replace(node, replacement.source)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -54,12 +54,14 @@ module RuboCop
|
|
54
54
|
|
55
55
|
private
|
56
56
|
|
57
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
57
58
|
def check_branch(node)
|
58
59
|
return unless node
|
59
60
|
|
60
61
|
case node.type
|
61
|
-
when :case
|
62
|
-
when :
|
62
|
+
when :case then check_case_node(node)
|
63
|
+
when :case_match then check_case_match_node(node)
|
64
|
+
when :if then check_if_node(node)
|
63
65
|
when :rescue, :resbody
|
64
66
|
check_rescue_node(node)
|
65
67
|
when :ensure then check_ensure_node(node)
|
@@ -67,12 +69,18 @@ module RuboCop
|
|
67
69
|
check_begin_node(node)
|
68
70
|
end
|
69
71
|
end
|
72
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
70
73
|
|
71
74
|
def check_case_node(node)
|
72
75
|
node.when_branches.each { |when_node| check_branch(when_node.body) }
|
73
76
|
check_branch(node.else_branch)
|
74
77
|
end
|
75
78
|
|
79
|
+
def check_case_match_node(node)
|
80
|
+
node.in_pattern_branches.each { |in_pattern_node| check_branch(in_pattern_node.body) }
|
81
|
+
check_branch(node.else_branch)
|
82
|
+
end
|
83
|
+
|
76
84
|
def check_if_node(node)
|
77
85
|
return if node.modifier_form? || node.ternary?
|
78
86
|
|
@@ -114,7 +114,7 @@ module RuboCop
|
|
114
114
|
if node.parent&.assignment?
|
115
115
|
replace_begin_with_statement(corrector, offense_range, node)
|
116
116
|
else
|
117
|
-
corrector
|
117
|
+
remove_begin(corrector, offense_range, node)
|
118
118
|
end
|
119
119
|
|
120
120
|
if use_modifier_form_after_multiline_begin_block?(node)
|
@@ -136,6 +136,14 @@ module RuboCop
|
|
136
136
|
restore_removed_comments(corrector, offense_range, node, first_child)
|
137
137
|
end
|
138
138
|
|
139
|
+
def remove_begin(corrector, offense_range, node)
|
140
|
+
if node.parent.respond_to?(:endless?) && node.parent.endless?
|
141
|
+
offense_range = range_with_surrounding_space(offense_range, newlines: true)
|
142
|
+
end
|
143
|
+
|
144
|
+
corrector.remove(offense_range)
|
145
|
+
end
|
146
|
+
|
139
147
|
# Restore comments that occur between "begin" and "first_child".
|
140
148
|
# These comments will be moved to above the assignment line.
|
141
149
|
def restore_removed_comments(corrector, offense_range, node, first_child)
|
@@ -146,7 +154,7 @@ module RuboCop
|
|
146
154
|
end
|
147
155
|
|
148
156
|
def use_modifier_form_after_multiline_begin_block?(node)
|
149
|
-
return unless (parent = node.parent)
|
157
|
+
return false unless (parent = node.parent)
|
150
158
|
|
151
159
|
node.multiline? && parent.if_type? && parent.modifier_form?
|
152
160
|
end
|
@@ -63,26 +63,18 @@ module RuboCop
|
|
63
63
|
RUBY
|
64
64
|
|
65
65
|
def offense?(node)
|
66
|
-
return if node.modifier_form?
|
66
|
+
return false if node.modifier_form?
|
67
67
|
|
68
68
|
redundant_condition?(node) || redundant_condition_inverted?(node)
|
69
69
|
end
|
70
70
|
|
71
71
|
def replacement_condition(node)
|
72
72
|
condition = node.condition.source
|
73
|
-
expression =
|
73
|
+
expression = redundant_condition_inverted?(node) ? "!(#{condition})" : condition
|
74
74
|
|
75
75
|
node.elsif? ? indented_else_node(expression, node) : expression
|
76
76
|
end
|
77
77
|
|
78
|
-
def invert_expression?(node)
|
79
|
-
(
|
80
|
-
(node.if? || node.elsif? || node.ternary?) && redundant_condition_inverted?(node)
|
81
|
-
) || (
|
82
|
-
node.unless? && redundant_condition?(node)
|
83
|
-
)
|
84
|
-
end
|
85
|
-
|
86
78
|
def indented_else_node(expression, node)
|
87
79
|
"else\n#{indentation(node)}#{expression}"
|
88
80
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Checks for uses a redundant current directory in path.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
#
|
10
|
+
# # bad
|
11
|
+
# require_relative './path/to/feature'
|
12
|
+
#
|
13
|
+
# # good
|
14
|
+
# require_relative 'path/to/feature'
|
15
|
+
#
|
16
|
+
class RedundantCurrentDirectoryInPath < Base
|
17
|
+
include RangeHelp
|
18
|
+
extend AutoCorrector
|
19
|
+
|
20
|
+
MSG = 'Remove the redundant current directory path.'
|
21
|
+
CURRENT_DIRECTORY_PATH = './'
|
22
|
+
|
23
|
+
def on_send(node)
|
24
|
+
return unless node.method?(:require_relative)
|
25
|
+
return unless (first_argument = node.first_argument)
|
26
|
+
return unless first_argument.str_content&.start_with?(CURRENT_DIRECTORY_PATH)
|
27
|
+
return unless (index = first_argument.source.index(CURRENT_DIRECTORY_PATH))
|
28
|
+
|
29
|
+
begin_pos = first_argument.source_range.begin.begin_pos + index
|
30
|
+
range = range_between(begin_pos, begin_pos + 2)
|
31
|
+
|
32
|
+
add_offense(range) do |corrector|
|
33
|
+
corrector.remove(range)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -13,25 +13,71 @@ module RuboCop
|
|
13
13
|
# # good
|
14
14
|
# do_something(foo: bar, baz: qux)
|
15
15
|
#
|
16
|
+
# # bad
|
17
|
+
# do_something(**{foo: bar, baz: qux}.merge(options))
|
18
|
+
#
|
19
|
+
# # good
|
20
|
+
# do_something(foo: bar, baz: qux, **options)
|
21
|
+
#
|
16
22
|
class RedundantDoubleSplatHashBraces < Base
|
17
23
|
extend AutoCorrector
|
18
24
|
|
19
25
|
MSG = 'Remove the redundant double splat and braces, use keyword arguments directly.'
|
26
|
+
MERGE_METHODS = %i[merge merge!].freeze
|
20
27
|
|
28
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
21
29
|
def on_hash(node)
|
22
30
|
return if node.pairs.empty? || node.pairs.any?(&:hash_rocket?)
|
23
31
|
return unless (parent = node.parent)
|
24
|
-
return unless parent.kwsplat_type?
|
32
|
+
return unless parent.call_type? || parent.kwsplat_type?
|
33
|
+
return unless mergeable?(parent)
|
34
|
+
return unless (kwsplat = node.each_ancestor(:kwsplat).first)
|
35
|
+
return if !node.braces? || allowed_double_splat_receiver?(kwsplat)
|
25
36
|
|
26
|
-
add_offense(
|
27
|
-
corrector
|
28
|
-
corrector.remove(opening_brace(node))
|
29
|
-
corrector.remove(closing_brace(node))
|
37
|
+
add_offense(kwsplat) do |corrector|
|
38
|
+
autocorrect(corrector, node, kwsplat)
|
30
39
|
end
|
31
40
|
end
|
41
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
32
42
|
|
33
43
|
private
|
34
44
|
|
45
|
+
def allowed_double_splat_receiver?(kwsplat)
|
46
|
+
first_child = kwsplat.children.first
|
47
|
+
return true if first_child.block_type? || first_child.numblock_type?
|
48
|
+
return false unless first_child.call_type?
|
49
|
+
|
50
|
+
root_receiver = root_receiver(first_child)
|
51
|
+
|
52
|
+
!root_receiver&.hash_type?
|
53
|
+
end
|
54
|
+
|
55
|
+
def autocorrect(corrector, node, kwsplat)
|
56
|
+
corrector.remove(kwsplat.loc.operator)
|
57
|
+
corrector.remove(opening_brace(node))
|
58
|
+
corrector.remove(closing_brace(node))
|
59
|
+
|
60
|
+
merge_methods = select_merge_method_nodes(kwsplat)
|
61
|
+
return if merge_methods.empty?
|
62
|
+
|
63
|
+
autocorrect_merge_methods(corrector, merge_methods, kwsplat)
|
64
|
+
end
|
65
|
+
|
66
|
+
def root_receiver(node)
|
67
|
+
receiver = node.receiver
|
68
|
+
if receiver&.receiver
|
69
|
+
root_receiver(receiver)
|
70
|
+
else
|
71
|
+
receiver
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def select_merge_method_nodes(kwsplat)
|
76
|
+
extract_send_methods(kwsplat).select do |node|
|
77
|
+
mergeable?(node)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
35
81
|
def opening_brace(node)
|
36
82
|
node.loc.begin.join(node.children.first.source_range.begin)
|
37
83
|
end
|
@@ -39,6 +85,48 @@ module RuboCop
|
|
39
85
|
def closing_brace(node)
|
40
86
|
node.children.last.source_range.end.join(node.loc.end)
|
41
87
|
end
|
88
|
+
|
89
|
+
def autocorrect_merge_methods(corrector, merge_methods, kwsplat)
|
90
|
+
range = range_of_merge_methods(merge_methods)
|
91
|
+
|
92
|
+
new_kwsplat_arguments = extract_send_methods(kwsplat).map do |descendant|
|
93
|
+
convert_to_new_arguments(descendant)
|
94
|
+
end
|
95
|
+
new_source = new_kwsplat_arguments.compact.reverse.unshift('').join(', ')
|
96
|
+
|
97
|
+
corrector.replace(range, new_source)
|
98
|
+
end
|
99
|
+
|
100
|
+
def range_of_merge_methods(merge_methods)
|
101
|
+
begin_merge_method = merge_methods.last
|
102
|
+
end_merge_method = merge_methods.first
|
103
|
+
|
104
|
+
begin_merge_method.loc.dot.begin.join(end_merge_method.source_range.end)
|
105
|
+
end
|
106
|
+
|
107
|
+
def extract_send_methods(kwsplat)
|
108
|
+
kwsplat.each_descendant(:send, :csend)
|
109
|
+
end
|
110
|
+
|
111
|
+
def convert_to_new_arguments(node)
|
112
|
+
return unless mergeable?(node)
|
113
|
+
|
114
|
+
node.arguments.map do |arg|
|
115
|
+
if arg.hash_type?
|
116
|
+
arg.source
|
117
|
+
else
|
118
|
+
"**#{arg.source}"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def mergeable?(node)
|
124
|
+
return true unless node.call_type?
|
125
|
+
return false unless MERGE_METHODS.include?(node.method_name)
|
126
|
+
return true unless (parent = node.parent)
|
127
|
+
|
128
|
+
mergeable?(parent)
|
129
|
+
end
|
42
130
|
end
|
43
131
|
end
|
44
132
|
end
|
@@ -56,6 +56,7 @@ module RuboCop
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
end
|
59
|
+
alias on_csend on_send
|
59
60
|
|
60
61
|
private
|
61
62
|
|
@@ -64,7 +65,7 @@ module RuboCop
|
|
64
65
|
return if node.last_argument&.block_pass_type?
|
65
66
|
|
66
67
|
if node.method?(:each) && !node.parent&.block_type?
|
67
|
-
ancestor_node = node.each_ancestor(:send).detect do |ancestor|
|
68
|
+
ancestor_node = node.each_ancestor(:send, :csend).detect do |ancestor|
|
68
69
|
ancestor.receiver == node &&
|
69
70
|
(RESTRICT_ON_SEND.include?(ancestor.method_name) || ancestor.method?(:reverse_each))
|
70
71
|
end
|
@@ -83,10 +84,12 @@ module RuboCop
|
|
83
84
|
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
84
85
|
|
85
86
|
def range(node)
|
86
|
-
|
87
|
-
|
87
|
+
return node.selector unless node.method?(:each)
|
88
|
+
|
89
|
+
if node.parent.call_type?
|
90
|
+
node.selector.join(node.parent.loc.dot)
|
88
91
|
else
|
89
|
-
node.loc.selector
|
92
|
+
node.loc.dot.join(node.selector)
|
90
93
|
end
|
91
94
|
end
|
92
95
|
|
@@ -5,17 +5,21 @@ module RuboCop
|
|
5
5
|
module Style
|
6
6
|
# Checks for RuntimeError as the argument of raise/fail.
|
7
7
|
#
|
8
|
-
# It checks for code like this:
|
9
|
-
#
|
10
8
|
# @example
|
11
|
-
# #
|
9
|
+
# # bad
|
12
10
|
# raise RuntimeError, 'message'
|
13
|
-
#
|
14
|
-
# # Bad
|
15
11
|
# raise RuntimeError.new('message')
|
16
12
|
#
|
17
|
-
# #
|
13
|
+
# # good
|
18
14
|
# raise 'message'
|
15
|
+
#
|
16
|
+
# # bad - message is not a string
|
17
|
+
# raise RuntimeError, Object.new
|
18
|
+
# raise RuntimeError.new(Object.new)
|
19
|
+
#
|
20
|
+
# # good
|
21
|
+
# raise Object.new.to_s
|
22
|
+
#
|
19
23
|
class RedundantException < Base
|
20
24
|
extend AutoCorrector
|
21
25
|
|
@@ -30,26 +34,42 @@ module RuboCop
|
|
30
34
|
fix_exploded(node) || fix_compact(node)
|
31
35
|
end
|
32
36
|
|
37
|
+
private
|
38
|
+
|
33
39
|
def fix_exploded(node)
|
34
40
|
exploded?(node) do |command, message|
|
35
41
|
add_offense(node, message: MSG_1) do |corrector|
|
36
|
-
|
37
|
-
corrector.replace(node, "#{command}(#{message.source})")
|
38
|
-
else
|
39
|
-
corrector.replace(node, "#{command} #{message.source}")
|
40
|
-
end
|
42
|
+
corrector.replace(node, replaced_exploded(node, command, message))
|
41
43
|
end
|
42
44
|
end
|
43
45
|
end
|
44
46
|
|
47
|
+
def replaced_exploded(node, command, message)
|
48
|
+
arg = string_message?(message) ? message.source : "#{message.source}.to_s"
|
49
|
+
arg = node.parenthesized? ? "(#{arg})" : " #{arg}"
|
50
|
+
"#{command}#{arg}"
|
51
|
+
end
|
52
|
+
|
53
|
+
def string_message?(message)
|
54
|
+
message.str_type? || message.dstr_type? || message.xstr_type?
|
55
|
+
end
|
56
|
+
|
45
57
|
def fix_compact(node)
|
46
58
|
compact?(node) do |new_call, message|
|
47
59
|
add_offense(node, message: MSG_2) do |corrector|
|
48
|
-
corrector.replace(new_call, message
|
60
|
+
corrector.replace(new_call, replaced_compact(message))
|
49
61
|
end
|
50
62
|
end
|
51
63
|
end
|
52
64
|
|
65
|
+
def replaced_compact(message)
|
66
|
+
if string_message?(message)
|
67
|
+
message.source
|
68
|
+
else
|
69
|
+
"#{message.source}.to_s"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
53
73
|
# @!method exploded?(node)
|
54
74
|
def_node_matcher :exploded?, <<~PATTERN
|
55
75
|
(send nil? ${:raise :fail} (const {nil? cbase} :RuntimeError) $_)
|
@@ -47,7 +47,7 @@ module RuboCop
|
|
47
47
|
# @!method redundant_fetch_block_candidate?(node)
|
48
48
|
def_node_matcher :redundant_fetch_block_candidate?, <<~PATTERN
|
49
49
|
(block
|
50
|
-
$(
|
50
|
+
$(call _ :fetch _)
|
51
51
|
(args)
|
52
52
|
${nil? #basic_literal? #const_type?})
|
53
53
|
PATTERN
|
@@ -61,10 +61,10 @@ module RuboCop
|
|
61
61
|
bad = build_bad_method(send, body)
|
62
62
|
|
63
63
|
add_offense(range, message: format(MSG, good: good, bad: bad)) do |corrector|
|
64
|
-
|
64
|
+
_, _, key = send.children
|
65
65
|
default_value = body ? body.source : 'nil'
|
66
66
|
|
67
|
-
corrector.replace(
|
67
|
+
corrector.replace(range, "fetch(#{key.source}, #{default_value})")
|
68
68
|
end
|
69
69
|
end
|
70
70
|
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Identifies usages of `any?`, `empty?` or `none?` predicate methods
|
7
|
+
# chained to `select`/`filter`/`find_all` and change them to use predicate method instead.
|
8
|
+
#
|
9
|
+
# @safety
|
10
|
+
# This cop's autocorrection is unsafe because `array.select.any?` evaluates all elements
|
11
|
+
# through the `select` method, while `array.any?` uses short-circuit evaluation.
|
12
|
+
# In other words, `array.select.any?` guarantees the evaluation of every element,
|
13
|
+
# but `array.any?` does not necessarily evaluate all of them.
|
14
|
+
#
|
15
|
+
# @example
|
16
|
+
# # bad
|
17
|
+
# arr.select { |x| x > 1 }.any?
|
18
|
+
#
|
19
|
+
# # good
|
20
|
+
# arr.any? { |x| x > 1 }
|
21
|
+
#
|
22
|
+
# # bad
|
23
|
+
# arr.select { |x| x > 1 }.empty?
|
24
|
+
# arr.select { |x| x > 1 }.none?
|
25
|
+
#
|
26
|
+
# # good
|
27
|
+
# arr.none? { |x| x > 1 }
|
28
|
+
#
|
29
|
+
# # good
|
30
|
+
# relation.select(:name).any?
|
31
|
+
# arr.select { |x| x > 1 }.any?(&:odd?)
|
32
|
+
#
|
33
|
+
# @example AllCops:ActiveSupportExtensionsEnabled: false (default)
|
34
|
+
# # good
|
35
|
+
# arr.select { |x| x > 1 }.many?
|
36
|
+
#
|
37
|
+
# # good
|
38
|
+
# arr.select { |x| x > 1 }.present?
|
39
|
+
#
|
40
|
+
# @example AllCops:ActiveSupportExtensionsEnabled: true
|
41
|
+
# # bad
|
42
|
+
# arr.select { |x| x > 1 }.many?
|
43
|
+
#
|
44
|
+
# # good
|
45
|
+
# arr.many? { |x| x > 1 }
|
46
|
+
#
|
47
|
+
# # bad
|
48
|
+
# arr.select { |x| x > 1 }.present?
|
49
|
+
#
|
50
|
+
# # good
|
51
|
+
# arr.any? { |x| x > 1 }
|
52
|
+
#
|
53
|
+
class RedundantFilterChain < Base
|
54
|
+
extend AutoCorrector
|
55
|
+
|
56
|
+
MSG = 'Use `%<prefer>s` instead of `%<first_method>s.%<second_method>s`.'
|
57
|
+
|
58
|
+
RAILS_METHODS = %i[many? present?].freeze
|
59
|
+
RESTRICT_ON_SEND = (%i[any? empty? none? one?] + RAILS_METHODS).freeze
|
60
|
+
|
61
|
+
# @!method select_predicate?(node)
|
62
|
+
def_node_matcher :select_predicate?, <<~PATTERN
|
63
|
+
(call
|
64
|
+
{
|
65
|
+
(block $(call _ {:select :filter :find_all}) ...)
|
66
|
+
$(call _ {:select :filter :find_all} block_pass_type?)
|
67
|
+
}
|
68
|
+
${:#{RESTRICT_ON_SEND.join(' :')}})
|
69
|
+
PATTERN
|
70
|
+
|
71
|
+
REPLACEMENT_METHODS = {
|
72
|
+
any?: :any?,
|
73
|
+
empty?: :none?,
|
74
|
+
none?: :none?,
|
75
|
+
one?: :one?,
|
76
|
+
many?: :many?,
|
77
|
+
present?: :any?
|
78
|
+
}.freeze
|
79
|
+
private_constant :REPLACEMENT_METHODS
|
80
|
+
|
81
|
+
def on_send(node)
|
82
|
+
return if node.arguments? || node.block_node
|
83
|
+
|
84
|
+
select_predicate?(node) do |select_node, filter_method|
|
85
|
+
return if RAILS_METHODS.include?(filter_method) && !active_support_extensions_enabled?
|
86
|
+
|
87
|
+
register_offense(select_node, node)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
alias on_csend on_send
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def register_offense(select_node, predicate_node)
|
95
|
+
replacement = REPLACEMENT_METHODS[predicate_node.method_name]
|
96
|
+
message = format(MSG, prefer: replacement,
|
97
|
+
first_method: select_node.method_name,
|
98
|
+
second_method: predicate_node.method_name)
|
99
|
+
|
100
|
+
offense_range = offense_range(select_node, predicate_node)
|
101
|
+
|
102
|
+
add_offense(offense_range, message: message) do |corrector|
|
103
|
+
corrector.remove(predicate_range(predicate_node))
|
104
|
+
corrector.replace(select_node.loc.selector, replacement)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def offense_range(select_node, predicate_node)
|
109
|
+
select_node.loc.selector.join(predicate_node.loc.selector)
|
110
|
+
end
|
111
|
+
|
112
|
+
def predicate_range(predicate_node)
|
113
|
+
predicate_node.receiver.source_range.end.join(predicate_node.loc.selector)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|