rubocop 1.72.1 → 1.81.7
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 +22 -18
- data/config/default.yml +240 -65
- data/config/internal_affairs.yml +20 -0
- data/config/obsoletion.yml +8 -3
- data/exe/rubocop +1 -8
- data/lib/rubocop/cli/command/auto_generate_config.rb +2 -2
- data/lib/rubocop/cli.rb +19 -4
- data/lib/rubocop/config.rb +35 -6
- data/lib/rubocop/config_loader.rb +8 -40
- data/lib/rubocop/config_loader_resolver.rb +9 -7
- data/lib/rubocop/config_obsoletion/extracted_cop.rb +4 -3
- data/lib/rubocop/config_obsoletion/renamed_cop.rb +18 -3
- data/lib/rubocop/config_obsoletion.rb +46 -2
- data/lib/rubocop/config_store.rb +5 -0
- data/lib/rubocop/config_validator.rb +7 -6
- data/lib/rubocop/cop/autocorrect_logic.rb +22 -14
- data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -1
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +7 -4
- data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +7 -2
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +5 -2
- data/lib/rubocop/cop/gemspec/attribute_assignment.rb +91 -0
- data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +37 -15
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -1
- data/lib/rubocop/cop/gemspec/require_mfa.rb +15 -1
- data/lib/rubocop/cop/internal_affairs/example_description.rb +9 -5
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +4 -4
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +6 -2
- data/lib/rubocop/cop/internal_affairs/node_type_group.rb +92 -0
- data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +6 -5
- data/lib/rubocop/cop/internal_affairs/undefined_config.rb +6 -1
- data/lib/rubocop/cop/internal_affairs/useless_restrict_on_send.rb +1 -1
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/layout/block_alignment.rb +2 -2
- data/lib/rubocop/cop/layout/block_end_newline.rb +1 -0
- data/lib/rubocop/cop/layout/class_structure.rb +36 -1
- data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +5 -5
- data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/dot_position.rb +1 -1
- data/lib/rubocop/cop/layout/else_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +32 -14
- data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +101 -0
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +34 -4
- data/lib/rubocop/cop/layout/empty_lines_around_arguments.rb +8 -29
- data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +1 -0
- data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +1 -1
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/hash_alignment.rb +4 -7
- data/lib/rubocop/cop/layout/indentation_width.rb +1 -0
- data/lib/rubocop/cop/layout/leading_comment_space.rb +13 -1
- data/lib/rubocop/cop/layout/line_length.rb +43 -10
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -0
- data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +1 -0
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +9 -5
- data/lib/rubocop/cop/layout/redundant_line_break.rb +9 -5
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +11 -5
- data/lib/rubocop/cop/layout/space_after_semicolon.rb +10 -0
- data/lib/rubocop/cop/layout/space_around_keyword.rb +6 -1
- data/lib/rubocop/cop/layout/space_around_operators.rb +12 -1
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +1 -0
- data/lib/rubocop/cop/layout/space_before_brackets.rb +5 -38
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +12 -3
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +1 -0
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +3 -0
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_range.rb +5 -0
- data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +2 -3
- data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -1
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +2 -5
- data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +3 -2
- data/lib/rubocop/cop/lint/cop_directive_syntax.rb +13 -7
- data/lib/rubocop/cop/lint/debugger.rb +2 -4
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +5 -2
- data/lib/rubocop/cop/lint/duplicate_methods.rb +111 -23
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +5 -42
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +14 -64
- data/lib/rubocop/cop/lint/empty_interpolation.rb +14 -1
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +0 -6
- data/lib/rubocop/cop/lint/float_comparison.rb +32 -10
- data/lib/rubocop/cop/lint/identity_comparison.rb +19 -15
- data/lib/rubocop/cop/lint/literal_as_condition.rb +124 -10
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +17 -8
- data/lib/rubocop/cop/lint/mixed_case_range.rb +2 -2
- data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -1
- data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +3 -3
- data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +1 -0
- data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +1 -1
- data/lib/rubocop/cop/lint/raise_exception.rb +29 -10
- data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +0 -21
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +101 -2
- data/lib/rubocop/cop/lint/redundant_type_conversion.rb +43 -13
- data/lib/rubocop/cop/lint/redundant_with_index.rb +3 -0
- data/lib/rubocop/cop/lint/redundant_with_object.rb +3 -0
- data/lib/rubocop/cop/lint/require_range_parentheses.rb +1 -1
- data/lib/rubocop/cop/lint/rescue_exception.rb +1 -4
- data/lib/rubocop/cop/lint/rescue_type.rb +1 -1
- data/lib/rubocop/cop/lint/return_in_void_context.rb +9 -11
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +4 -4
- data/lib/rubocop/cop/lint/self_assignment.rb +31 -5
- data/lib/rubocop/cop/lint/shadowed_argument.rb +7 -7
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +13 -1
- data/lib/rubocop/cop/lint/shared_mutable_default.rb +12 -1
- data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +1 -1
- data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +1 -1
- data/lib/rubocop/cop/lint/unexpected_block_arity.rb +2 -0
- data/lib/rubocop/cop/lint/unreachable_code.rb +1 -0
- data/lib/rubocop/cop/lint/unreachable_loop.rb +5 -5
- data/lib/rubocop/cop/lint/uri_escape_unescape.rb +2 -0
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +30 -4
- data/lib/rubocop/cop/lint/useless_assignment.rb +2 -0
- data/lib/rubocop/cop/lint/useless_constant_scoping.rb +9 -12
- data/lib/rubocop/cop/lint/useless_default_value_argument.rb +90 -0
- data/lib/rubocop/cop/lint/useless_numeric_operation.rb +1 -0
- data/lib/rubocop/cop/lint/useless_or.rb +98 -0
- data/lib/rubocop/cop/lint/useless_rescue.rb +1 -1
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +3 -3
- data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +121 -0
- data/lib/rubocop/cop/lint/void.rb +16 -2
- data/lib/rubocop/cop/message_annotator.rb +7 -3
- data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
- data/lib/rubocop/cop/metrics/block_length.rb +1 -0
- data/lib/rubocop/cop/metrics/method_length.rb +1 -0
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
- data/lib/rubocop/cop/mixin/alignment.rb +1 -1
- data/lib/rubocop/cop/mixin/allowed_pattern.rb +4 -4
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +3 -3
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +2 -2
- data/lib/rubocop/cop/mixin/def_node.rb +1 -1
- data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +1 -1
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -7
- data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +20 -0
- data/lib/rubocop/cop/mixin/forbidden_pattern.rb +16 -0
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -2
- data/lib/rubocop/cop/mixin/gemspec_help.rb +22 -0
- data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +15 -14
- data/lib/rubocop/cop/mixin/hash_subset.rb +19 -4
- data/lib/rubocop/cop/mixin/line_length_help.rb +24 -8
- data/lib/rubocop/cop/mixin/method_complexity.rb +1 -0
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +2 -0
- data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
- data/lib/rubocop/cop/mixin/range_help.rb +12 -0
- data/lib/rubocop/cop/mixin/target_ruby_version.rb +1 -1
- data/lib/rubocop/cop/mixin/trailing_comma.rb +18 -2
- data/lib/rubocop/cop/naming/block_forwarding.rb +3 -3
- data/lib/rubocop/cop/naming/file_name.rb +2 -2
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -1
- data/lib/rubocop/cop/naming/method_name.rb +187 -15
- data/lib/rubocop/cop/naming/predicate_method.rb +319 -0
- data/lib/rubocop/cop/naming/{predicate_name.rb → predicate_prefix.rb} +4 -4
- data/lib/rubocop/cop/naming/variable_name.rb +51 -6
- data/lib/rubocop/cop/registry.rb +9 -6
- data/lib/rubocop/cop/security/eval.rb +2 -1
- data/lib/rubocop/cop/security/json_load.rb +33 -11
- data/lib/rubocop/cop/security/open.rb +1 -0
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +32 -10
- data/lib/rubocop/cop/style/accessor_grouping.rb +32 -6
- data/lib/rubocop/cop/style/arguments_forwarding.rb +21 -24
- data/lib/rubocop/cop/style/array_intersect.rb +113 -38
- data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +47 -0
- data/lib/rubocop/cop/style/bitwise_predicate.rb +8 -1
- data/lib/rubocop/cop/style/block_delimiters.rb +3 -2
- data/lib/rubocop/cop/style/case_like_if.rb +1 -1
- data/lib/rubocop/cop/style/class_and_module_children.rb +48 -10
- data/lib/rubocop/cop/style/class_equality_comparison.rb +1 -1
- data/lib/rubocop/cop/style/collection_methods.rb +1 -0
- data/lib/rubocop/cop/style/collection_querying.rb +167 -0
- data/lib/rubocop/cop/style/combinable_loops.rb +1 -0
- data/lib/rubocop/cop/style/command_literal.rb +1 -1
- data/lib/rubocop/cop/style/commented_keyword.rb +12 -5
- data/lib/rubocop/cop/style/comparable_between.rb +78 -0
- data/lib/rubocop/cop/style/conditional_assignment.rb +26 -8
- data/lib/rubocop/cop/style/constant_visibility.rb +14 -9
- data/lib/rubocop/cop/style/data_inheritance.rb +7 -0
- data/lib/rubocop/cop/style/def_with_parentheses.rb +18 -5
- data/lib/rubocop/cop/style/dig_chain.rb +1 -1
- data/lib/rubocop/cop/style/double_negation.rb +3 -3
- data/lib/rubocop/cop/style/empty_literal.rb +4 -0
- data/lib/rubocop/cop/style/empty_string_inside_interpolation.rb +100 -0
- data/lib/rubocop/cop/style/endless_method.rb +176 -18
- data/lib/rubocop/cop/style/eval_with_location.rb +3 -3
- data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -7
- data/lib/rubocop/cop/style/explicit_block_argument.rb +3 -3
- data/lib/rubocop/cop/style/exponential_notation.rb +5 -4
- data/lib/rubocop/cop/style/fetch_env_var.rb +32 -6
- data/lib/rubocop/cop/style/float_division.rb +15 -1
- data/lib/rubocop/cop/style/for.rb +1 -0
- data/lib/rubocop/cop/style/format_string_token.rb +38 -11
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +3 -2
- data/lib/rubocop/cop/style/global_std_stream.rb +3 -0
- data/lib/rubocop/cop/style/guard_clause.rb +2 -1
- data/lib/rubocop/cop/style/hash_conversion.rb +16 -8
- data/lib/rubocop/cop/style/hash_each_methods.rb +3 -2
- data/lib/rubocop/cop/style/hash_fetch_chain.rb +104 -0
- data/lib/rubocop/cop/style/hash_syntax.rb +4 -1
- 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 +3 -3
- data/lib/rubocop/cop/style/if_inside_else.rb +10 -13
- data/lib/rubocop/cop/style/if_unless_modifier.rb +35 -8
- data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +4 -7
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +1 -1
- data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
- data/lib/rubocop/cop/style/inverse_methods.rb +10 -6
- data/lib/rubocop/cop/style/invertible_unless_condition.rb +2 -2
- data/lib/rubocop/cop/style/ip_addresses.rb +2 -2
- data/lib/rubocop/cop/style/it_assignment.rb +69 -12
- data/lib/rubocop/cop/style/it_block_parameter.rb +121 -0
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +13 -7
- data/lib/rubocop/cop/style/lambda.rb +1 -0
- data/lib/rubocop/cop/style/lambda_call.rb +7 -2
- data/lib/rubocop/cop/style/line_end_concatenation.rb +10 -4
- data/lib/rubocop/cop/style/map_into_array.rb +4 -1
- data/lib/rubocop/cop/style/map_to_hash.rb +12 -3
- data/lib/rubocop/cop/style/map_to_set.rb +1 -3
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +9 -8
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +16 -0
- data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +2 -1
- data/lib/rubocop/cop/style/min_max_comparison.rb +13 -5
- data/lib/rubocop/cop/style/multiline_block_chain.rb +2 -1
- data/lib/rubocop/cop/style/multiline_if_modifier.rb +2 -0
- data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -9
- data/lib/rubocop/cop/style/next.rb +44 -0
- data/lib/rubocop/cop/style/nil_comparison.rb +9 -7
- data/lib/rubocop/cop/style/object_then.rb +1 -0
- data/lib/rubocop/cop/style/one_line_conditional.rb +17 -9
- data/lib/rubocop/cop/style/parallel_assignment.rb +32 -20
- data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
- data/lib/rubocop/cop/style/proc.rb +1 -0
- data/lib/rubocop/cop/style/raise_args.rb +8 -8
- data/lib/rubocop/cop/style/redundant_array_flatten.rb +50 -0
- data/lib/rubocop/cop/style/redundant_begin.rb +35 -0
- data/lib/rubocop/cop/style/redundant_condition.rb +57 -0
- data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +14 -4
- data/lib/rubocop/cop/style/redundant_exception.rb +1 -1
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -9
- data/lib/rubocop/cop/style/redundant_format.rb +79 -18
- data/lib/rubocop/cop/style/redundant_freeze.rb +2 -2
- data/lib/rubocop/cop/style/redundant_interpolation.rb +12 -3
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +1 -4
- data/lib/rubocop/cop/style/redundant_parentheses.rb +73 -18
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +4 -0
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -0
- data/lib/rubocop/cop/style/redundant_self.rb +9 -5
- data/lib/rubocop/cop/style/redundant_self_assignment.rb +1 -1
- data/lib/rubocop/cop/style/redundant_sort_by.rb +17 -1
- data/lib/rubocop/cop/style/regexp_literal.rb +1 -1
- data/lib/rubocop/cop/style/rescue_modifier.rb +3 -0
- data/lib/rubocop/cop/style/return_nil.rb +2 -2
- data/lib/rubocop/cop/style/safe_navigation.rb +61 -14
- data/lib/rubocop/cop/style/select_by_regexp.rb +4 -1
- data/lib/rubocop/cop/style/semicolon.rb +23 -7
- data/lib/rubocop/cop/style/single_line_do_end_block.rb +3 -1
- data/lib/rubocop/cop/style/single_line_methods.rb +10 -7
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +75 -101
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/string_concatenation.rb +18 -15
- data/lib/rubocop/cop/style/struct_inheritance.rb +8 -1
- data/lib/rubocop/cop/style/super_arguments.rb +1 -2
- data/lib/rubocop/cop/style/symbol_array.rb +1 -1
- data/lib/rubocop/cop/style/symbol_proc.rb +3 -1
- data/lib/rubocop/cop/style/top_level_method_definition.rb +1 -0
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +52 -1
- data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +47 -6
- data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
- data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +48 -6
- data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
- data/lib/rubocop/cop/style/unless_else.rb +10 -9
- data/lib/rubocop/cop/team.rb +1 -1
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/cop/utils/format_string.rb +15 -2
- data/lib/rubocop/cop/variable_force/assignment.rb +7 -3
- data/lib/rubocop/cop/variable_force/scope.rb +1 -1
- data/lib/rubocop/cop/variable_force/variable.rb +3 -8
- data/lib/rubocop/cop/variable_force.rb +26 -9
- data/lib/rubocop/cops_documentation_generator.rb +23 -7
- data/lib/rubocop/directive_comment.rb +1 -1
- data/lib/rubocop/ext/regexp_node.rb +0 -1
- data/lib/rubocop/formatter/disabled_config_formatter.rb +19 -5
- data/lib/rubocop/formatter/fuubar_style_formatter.rb +1 -1
- data/lib/rubocop/formatter/html_formatter.rb +1 -1
- data/lib/rubocop/formatter/markdown_formatter.rb +1 -0
- data/lib/rubocop/formatter/offense_count_formatter.rb +1 -1
- data/lib/rubocop/formatter/pacman_formatter.rb +2 -1
- data/lib/rubocop/lsp/diagnostic.rb +25 -24
- data/lib/rubocop/lsp/routes.rb +65 -9
- data/lib/rubocop/lsp/runtime.rb +5 -5
- data/lib/rubocop/lsp/server.rb +2 -2
- data/lib/rubocop/lsp/stdin_runner.rb +3 -17
- data/lib/rubocop/magic_comment.rb +8 -0
- data/lib/rubocop/pending_cops_reporter.rb +56 -0
- data/lib/rubocop/plugin/configuration_integrator.rb +2 -0
- data/lib/rubocop/plugin/load_error.rb +1 -1
- data/lib/rubocop/plugin.rb +9 -2
- data/lib/rubocop/result_cache.rb +14 -12
- data/lib/rubocop/rspec/cop_helper.rb +6 -1
- data/lib/rubocop/rspec/expect_offense.rb +9 -3
- data/lib/rubocop/rspec/shared_contexts.rb +34 -0
- data/lib/rubocop/rspec/support.rb +3 -0
- data/lib/rubocop/runner.rb +10 -4
- data/lib/rubocop/server/cache.rb +17 -12
- data/lib/rubocop/server/client_command/base.rb +10 -0
- data/lib/rubocop/server/client_command/exec.rb +2 -1
- data/lib/rubocop/server/client_command/start.rb +11 -1
- data/lib/rubocop/target_finder.rb +13 -9
- data/lib/rubocop/target_ruby.rb +11 -2
- data/lib/rubocop/version.rb +14 -7
- data/lib/rubocop.rb +17 -2
- data/lib/ruby_lsp/rubocop/addon.rb +25 -10
- data/lib/ruby_lsp/rubocop/runtime_adapter.rb +57 -5
- metadata +24 -8
- data/lib/rubocop/cop/utils/regexp_ranges.rb +0 -113
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'tsort'
|
|
4
|
-
|
|
5
3
|
module RuboCop
|
|
6
4
|
module Cop
|
|
7
5
|
module Style
|
|
@@ -29,6 +27,8 @@ module RuboCop
|
|
|
29
27
|
MSG = 'Do not use parallel assignment.'
|
|
30
28
|
|
|
31
29
|
def on_masgn(node) # rubocop:disable Metrics/AbcSize
|
|
30
|
+
return if part_of_ignored_node?(node)
|
|
31
|
+
|
|
32
32
|
rhs = node.rhs
|
|
33
33
|
rhs = rhs.body if rhs.rescue_type?
|
|
34
34
|
rhs_elements = Array(rhs).compact # edge case for one constant
|
|
@@ -41,6 +41,7 @@ module RuboCop
|
|
|
41
41
|
add_offense(range) do |corrector|
|
|
42
42
|
autocorrect(corrector, node, rhs)
|
|
43
43
|
end
|
|
44
|
+
ignore_node(node)
|
|
44
45
|
end
|
|
45
46
|
|
|
46
47
|
private
|
|
@@ -91,15 +92,9 @@ module RuboCop
|
|
|
91
92
|
def find_valid_order(left_elements, right_elements)
|
|
92
93
|
# arrange left_elements in an order such that no corresponding right
|
|
93
94
|
# element refers to a left element earlier in the sequence
|
|
94
|
-
# this can be done using an algorithm called a "topological sort"
|
|
95
|
-
# fortunately for us, Ruby's stdlib contains an implementation
|
|
96
95
|
assignments = left_elements.zip(right_elements)
|
|
97
96
|
|
|
98
|
-
|
|
99
|
-
AssignmentSorter.new(assignments).tsort
|
|
100
|
-
rescue TSort::Cyclic
|
|
101
|
-
nil
|
|
102
|
-
end
|
|
97
|
+
AssignmentSorter.new(assignments).tsort
|
|
103
98
|
end
|
|
104
99
|
|
|
105
100
|
# Converts (send nil :something) nodes to (send (:self) :something).
|
|
@@ -114,10 +109,9 @@ module RuboCop
|
|
|
114
109
|
# @!method implicit_self_getter?(node)
|
|
115
110
|
def_node_matcher :implicit_self_getter?, '(send nil? $_)'
|
|
116
111
|
|
|
117
|
-
#
|
|
118
|
-
#
|
|
112
|
+
# Topologically sorts the assignments with Kahn's algorithm.
|
|
113
|
+
# https://en.wikipedia.org/wiki/Topological_sorting#Kahn's_algorithm
|
|
119
114
|
class AssignmentSorter
|
|
120
|
-
include TSort
|
|
121
115
|
extend RuboCop::NodePattern::Macros
|
|
122
116
|
|
|
123
117
|
# @!method var_name(node)
|
|
@@ -133,21 +127,39 @@ module RuboCop
|
|
|
133
127
|
@assignments = assignments
|
|
134
128
|
end
|
|
135
129
|
|
|
136
|
-
def
|
|
137
|
-
@assignments.
|
|
130
|
+
def tsort
|
|
131
|
+
dependencies = @assignments.to_h do |assignment|
|
|
132
|
+
[assignment, dependencies_for_assignment(assignment)]
|
|
133
|
+
end
|
|
134
|
+
result = []
|
|
135
|
+
|
|
136
|
+
while (matched_node, = dependencies.find { |_node, edges| edges.empty? })
|
|
137
|
+
dependencies.delete(matched_node)
|
|
138
|
+
result.push(matched_node)
|
|
139
|
+
|
|
140
|
+
dependencies.each do |node, edges|
|
|
141
|
+
dependencies[node].delete(matched_node) if edges.include?(matched_node)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
# Cyclic dependency
|
|
145
|
+
return nil if dependencies.any?
|
|
146
|
+
|
|
147
|
+
result
|
|
138
148
|
end
|
|
139
149
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
150
|
+
# Returns all the assignments which must come after `assignment`
|
|
151
|
+
# (due to dependencies on the previous value of the assigned var)
|
|
152
|
+
def dependencies_for_assignment(assignment)
|
|
143
153
|
my_lhs, _my_rhs = *assignment
|
|
144
154
|
|
|
145
|
-
@assignments.
|
|
146
|
-
|
|
155
|
+
@assignments.filter_map do |other|
|
|
156
|
+
# Exclude self, there are no dependencies in cases such as `a, b = a, b`.
|
|
157
|
+
next if other == assignment
|
|
147
158
|
|
|
159
|
+
_other_lhs, other_rhs = *other
|
|
148
160
|
next unless dependency?(my_lhs, other_rhs)
|
|
149
161
|
|
|
150
|
-
|
|
162
|
+
other
|
|
151
163
|
end
|
|
152
164
|
end
|
|
153
165
|
|
|
@@ -45,7 +45,7 @@ module RuboCop
|
|
|
45
45
|
# Report offense only if changing case doesn't change semantics,
|
|
46
46
|
# i.e., if the string would become dynamic or has special characters.
|
|
47
47
|
ast = parse(corrected(node.source)).ast
|
|
48
|
-
return if node.children != ast
|
|
48
|
+
return if node.children != ast&.children
|
|
49
49
|
|
|
50
50
|
add_offense(node.loc.begin) do |corrector|
|
|
51
51
|
corrector.replace(node, corrected(node.source))
|
|
@@ -3,15 +3,15 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Style
|
|
6
|
-
# Checks the args passed to `fail` and `raise`.
|
|
7
|
-
# style (default), it recommends passing the exception class and message
|
|
8
|
-
# to `raise`, rather than construct an instance of the error. It will
|
|
9
|
-
# still allow passing just a message, or the construction of an error
|
|
10
|
-
# with more than one argument.
|
|
6
|
+
# Checks the args passed to `fail` and `raise`.
|
|
11
7
|
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
8
|
+
# Exploded style (default) enforces passing the exception class and message
|
|
9
|
+
# arguments separately, rather than constructing an instance of the error.
|
|
10
|
+
#
|
|
11
|
+
# Compact style enforces constructing an error instance.
|
|
12
|
+
#
|
|
13
|
+
# Both styles allow passing just a message, or an error instance when there is more
|
|
14
|
+
# than one argument.
|
|
15
15
|
#
|
|
16
16
|
# The exploded style has an `AllowedCompactTypes` configuration
|
|
17
17
|
# option that takes an `Array` of exception name Strings.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Style
|
|
6
|
+
# Checks for redundant calls of `Array#flatten`.
|
|
7
|
+
#
|
|
8
|
+
# `Array#join` joins nested arrays recursively, so flattening an array
|
|
9
|
+
# beforehand is redundant.
|
|
10
|
+
#
|
|
11
|
+
# @safety
|
|
12
|
+
# Cop is unsafe because the receiver of `flatten` method might not
|
|
13
|
+
# be an `Array`, so it's possible it won't respond to `join` method,
|
|
14
|
+
# or the end result would be different.
|
|
15
|
+
# Also, if the global variable `$,` is set to a value other than the default `nil`,
|
|
16
|
+
# false positives may occur.
|
|
17
|
+
#
|
|
18
|
+
# @example
|
|
19
|
+
# # bad
|
|
20
|
+
# x.flatten.join
|
|
21
|
+
# x.flatten(1).join
|
|
22
|
+
#
|
|
23
|
+
# # good
|
|
24
|
+
# x.join
|
|
25
|
+
#
|
|
26
|
+
class RedundantArrayFlatten < Base
|
|
27
|
+
extend AutoCorrector
|
|
28
|
+
|
|
29
|
+
MSG = 'Remove the redundant `flatten`.'
|
|
30
|
+
|
|
31
|
+
RESTRICT_ON_SEND = %i[flatten].freeze
|
|
32
|
+
|
|
33
|
+
# @!method flatten_join?(node)
|
|
34
|
+
def_node_matcher :flatten_join?, <<~PATTERN
|
|
35
|
+
(call (call !nil? :flatten _?) :join (nil)?)
|
|
36
|
+
PATTERN
|
|
37
|
+
|
|
38
|
+
def on_send(node)
|
|
39
|
+
return unless flatten_join?(node.parent)
|
|
40
|
+
|
|
41
|
+
range = node.loc.dot.begin.join(node.source_range.end)
|
|
42
|
+
add_offense(range) do |corrector|
|
|
43
|
+
corrector.remove(range)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
alias on_csend on_send
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -85,6 +85,29 @@ module RuboCop
|
|
|
85
85
|
end
|
|
86
86
|
alias on_defs on_def
|
|
87
87
|
|
|
88
|
+
def on_if(node)
|
|
89
|
+
return if node.modifier_form?
|
|
90
|
+
|
|
91
|
+
inspect_branches(node)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def on_case(node)
|
|
95
|
+
inspect_branches(node)
|
|
96
|
+
end
|
|
97
|
+
alias on_case_match on_case
|
|
98
|
+
|
|
99
|
+
def on_while(node)
|
|
100
|
+
return if node.modifier_form?
|
|
101
|
+
|
|
102
|
+
body = node.body
|
|
103
|
+
|
|
104
|
+
return unless body&.kwbegin_type?
|
|
105
|
+
return if body.rescue_node || body.ensure_node
|
|
106
|
+
|
|
107
|
+
register_offense(body)
|
|
108
|
+
end
|
|
109
|
+
alias on_until on_while
|
|
110
|
+
|
|
88
111
|
def on_block(node)
|
|
89
112
|
return if target_ruby_version < 2.5
|
|
90
113
|
return if node.send_node.lambda_literal?
|
|
@@ -95,6 +118,7 @@ module RuboCop
|
|
|
95
118
|
end
|
|
96
119
|
|
|
97
120
|
alias on_numblock on_block
|
|
121
|
+
alias on_itblock on_block
|
|
98
122
|
|
|
99
123
|
def on_kwbegin(node)
|
|
100
124
|
return unless (target_node = offensive_kwbegins(node).to_a.last)
|
|
@@ -179,6 +203,8 @@ module RuboCop
|
|
|
179
203
|
end
|
|
180
204
|
|
|
181
205
|
def begin_block_has_multiline_statements?(node)
|
|
206
|
+
return false unless node.parent
|
|
207
|
+
|
|
182
208
|
node.children.count >= 2
|
|
183
209
|
end
|
|
184
210
|
|
|
@@ -198,6 +224,15 @@ module RuboCop
|
|
|
198
224
|
def valid_begin_assignment?(node)
|
|
199
225
|
node.parent&.assignment? && !node.children.one?
|
|
200
226
|
end
|
|
227
|
+
|
|
228
|
+
def inspect_branches(node)
|
|
229
|
+
node.branches.each do |branch|
|
|
230
|
+
next unless branch&.kwbegin_type?
|
|
231
|
+
next if branch.rescue_node || branch.ensure_node
|
|
232
|
+
|
|
233
|
+
register_offense(branch)
|
|
234
|
+
end
|
|
235
|
+
end
|
|
201
236
|
end
|
|
202
237
|
end
|
|
203
238
|
end
|
|
@@ -42,7 +42,28 @@ module RuboCop
|
|
|
42
42
|
# c
|
|
43
43
|
# end
|
|
44
44
|
#
|
|
45
|
+
# # bad
|
|
46
|
+
# a.nil? ? true : a
|
|
47
|
+
#
|
|
48
|
+
# # good
|
|
49
|
+
# a.nil? || a
|
|
50
|
+
#
|
|
51
|
+
# # bad
|
|
52
|
+
# if a.nil?
|
|
53
|
+
# true
|
|
54
|
+
# else
|
|
55
|
+
# a
|
|
56
|
+
# end
|
|
57
|
+
#
|
|
58
|
+
# # good
|
|
59
|
+
# a.nil? || a
|
|
60
|
+
#
|
|
61
|
+
# @example AllowedMethods: ['nonzero?'] (default)
|
|
62
|
+
# # good
|
|
63
|
+
# num.nonzero? ? true : false
|
|
64
|
+
#
|
|
45
65
|
class RedundantCondition < Base
|
|
66
|
+
include AllowedMethods
|
|
46
67
|
include CommentsHelp
|
|
47
68
|
include RangeHelp
|
|
48
69
|
extend AutoCorrector
|
|
@@ -128,6 +149,16 @@ module RuboCop
|
|
|
128
149
|
# end
|
|
129
150
|
return true if condition == if_branch
|
|
130
151
|
|
|
152
|
+
# e.g.
|
|
153
|
+
# a.nil? ? true : a
|
|
154
|
+
# or
|
|
155
|
+
# if a.nil?
|
|
156
|
+
# true
|
|
157
|
+
# else
|
|
158
|
+
# a
|
|
159
|
+
# end
|
|
160
|
+
return true if if_branch_is_true_type_and_else_is_not?(node)
|
|
161
|
+
|
|
131
162
|
# e.g.
|
|
132
163
|
# if foo
|
|
133
164
|
# @value = foo
|
|
@@ -146,6 +177,18 @@ module RuboCop
|
|
|
146
177
|
!use_hash_key_access?(if_branch)
|
|
147
178
|
end
|
|
148
179
|
|
|
180
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
181
|
+
def if_branch_is_true_type_and_else_is_not?(node)
|
|
182
|
+
return false unless node.ternary? || node.if?
|
|
183
|
+
|
|
184
|
+
cond = node.condition
|
|
185
|
+
return false unless cond.call_type?
|
|
186
|
+
return false if !cond.predicate_method? || allowed_method?(cond.method_name)
|
|
187
|
+
|
|
188
|
+
node.if_branch&.true_type? && node.else_branch && !node.else_branch.true_type?
|
|
189
|
+
end
|
|
190
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
191
|
+
|
|
149
192
|
def branches_have_assignment?(node)
|
|
150
193
|
_condition, if_branch, else_branch = *node # rubocop:disable InternalAffairs/NodeDestructuring
|
|
151
194
|
|
|
@@ -187,6 +230,14 @@ module RuboCop
|
|
|
187
230
|
node.type?(:kwsplat, :forwarded_kwrestarg)
|
|
188
231
|
end
|
|
189
232
|
|
|
233
|
+
def wrap_arguments_with_parens(condition)
|
|
234
|
+
method = condition.source_range.begin.join(condition.loc.selector.end)
|
|
235
|
+
arguments = condition.first_argument.source_range.begin.join(condition.source_range.end)
|
|
236
|
+
|
|
237
|
+
"#{method.source}(#{arguments.source})"
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
# rubocop:disable Metrics/AbcSize
|
|
190
241
|
def if_source(if_branch, arithmetic_operation)
|
|
191
242
|
if branches_have_method?(if_branch.parent) && if_branch.parenthesized?
|
|
192
243
|
if_branch.source.delete_suffix(')')
|
|
@@ -194,10 +245,16 @@ module RuboCop
|
|
|
194
245
|
argument_source = if_branch.first_argument.source
|
|
195
246
|
|
|
196
247
|
"#{if_branch.receiver.source} #{if_branch.method_name} (#{argument_source}"
|
|
248
|
+
elsif if_branch.true_type?
|
|
249
|
+
condition = if_branch.parent.condition
|
|
250
|
+
return condition.source if condition.arguments.empty? || condition.parenthesized?
|
|
251
|
+
|
|
252
|
+
wrap_arguments_with_parens(condition)
|
|
197
253
|
else
|
|
198
254
|
if_branch.source
|
|
199
255
|
end
|
|
200
256
|
end
|
|
257
|
+
# rubocop:enable Metrics/AbcSize
|
|
201
258
|
|
|
202
259
|
def else_source(else_branch, arithmetic_operation) # rubocop:disable Metrics/AbcSize
|
|
203
260
|
if arithmetic_operation
|
|
@@ -20,20 +20,30 @@ module RuboCop
|
|
|
20
20
|
|
|
21
21
|
MSG = 'Remove the redundant current directory path.'
|
|
22
22
|
RESTRICT_ON_SEND = %i[require_relative].freeze
|
|
23
|
-
|
|
23
|
+
CURRENT_DIRECTORY_PREFIX = %r{\./+}.freeze
|
|
24
|
+
REDUNDANT_CURRENT_DIRECTORY_PREFIX = /\A#{CURRENT_DIRECTORY_PREFIX}/.freeze
|
|
24
25
|
|
|
25
26
|
def on_send(node)
|
|
26
27
|
return unless (first_argument = node.first_argument)
|
|
27
|
-
return unless first_argument.
|
|
28
|
-
return unless (
|
|
28
|
+
return unless (index = first_argument.source.index(CURRENT_DIRECTORY_PREFIX))
|
|
29
|
+
return unless (redundant_length = redundant_path_length(first_argument.str_content))
|
|
29
30
|
|
|
30
31
|
begin_pos = first_argument.source_range.begin.begin_pos + index
|
|
31
|
-
|
|
32
|
+
end_pos = begin_pos + redundant_length
|
|
33
|
+
range = range_between(begin_pos, end_pos)
|
|
32
34
|
|
|
33
35
|
add_offense(range) do |corrector|
|
|
34
36
|
corrector.remove(range)
|
|
35
37
|
end
|
|
36
38
|
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def redundant_path_length(path)
|
|
43
|
+
return unless (match = path&.match(REDUNDANT_CURRENT_DIRECTORY_PREFIX))
|
|
44
|
+
|
|
45
|
+
match[0].length
|
|
46
|
+
end
|
|
37
47
|
end
|
|
38
48
|
end
|
|
39
49
|
end
|
|
@@ -49,7 +49,7 @@ module RuboCop
|
|
|
49
49
|
(block
|
|
50
50
|
$(call _ :fetch _)
|
|
51
51
|
(args)
|
|
52
|
-
${nil?
|
|
52
|
+
${nil? basic_literal? const_type?})
|
|
53
53
|
PATTERN
|
|
54
54
|
|
|
55
55
|
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
|
@@ -71,14 +71,6 @@ module RuboCop
|
|
|
71
71
|
|
|
72
72
|
private
|
|
73
73
|
|
|
74
|
-
def basic_literal?(node)
|
|
75
|
-
node&.basic_literal?
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
def const_type?(node)
|
|
79
|
-
node&.const_type?
|
|
80
|
-
end
|
|
81
|
-
|
|
82
74
|
def should_not_check?(send, body)
|
|
83
75
|
(body&.const_type? && !check_for_constant?) ||
|
|
84
76
|
(body&.str_type? && !check_for_string?) ||
|
|
@@ -5,13 +5,29 @@ module RuboCop
|
|
|
5
5
|
module Style
|
|
6
6
|
# Checks for calls to `Kernel#format` or `Kernel#sprintf` that are redundant.
|
|
7
7
|
#
|
|
8
|
-
# Calling `format` with only a single string argument is redundant,
|
|
9
|
-
# replaced by the string itself.
|
|
8
|
+
# Calling `format` with only a single string or constant argument is redundant,
|
|
9
|
+
# as it can be replaced by the string or constant itself.
|
|
10
10
|
#
|
|
11
11
|
# Also looks for `format` calls where the arguments are literals that can be
|
|
12
12
|
# inlined into a string easily. This applies to the `%s`, `%d`, `%i`, `%u`, and
|
|
13
13
|
# `%f` format specifiers.
|
|
14
14
|
#
|
|
15
|
+
# @safety
|
|
16
|
+
# This cop's autocorrection is unsafe because string object returned by
|
|
17
|
+
# `format` and `sprintf` are never frozen. If `format('string')` is autocorrected to
|
|
18
|
+
# `'string'`, `FrozenError` may occur when calling a destructive method like `String#<<`.
|
|
19
|
+
# Consider using `'string'.dup` instead of `format('string')`.
|
|
20
|
+
# Additionally, since the necessity of `dup` cannot be determined automatically,
|
|
21
|
+
# this autocorrection is inherently unsafe.
|
|
22
|
+
#
|
|
23
|
+
# [source,ruby]
|
|
24
|
+
# ----
|
|
25
|
+
# # frozen_string_literal: true
|
|
26
|
+
#
|
|
27
|
+
# format('template').frozen? # => false
|
|
28
|
+
# 'template'.frozen? # => true
|
|
29
|
+
# ----
|
|
30
|
+
#
|
|
15
31
|
# @example
|
|
16
32
|
#
|
|
17
33
|
# # bad
|
|
@@ -22,6 +38,13 @@ module RuboCop
|
|
|
22
38
|
# 'the quick brown fox jumps over the lazy dog.'
|
|
23
39
|
#
|
|
24
40
|
# # bad
|
|
41
|
+
# format(MESSAGE)
|
|
42
|
+
# sprintf(MESSAGE)
|
|
43
|
+
#
|
|
44
|
+
# # good
|
|
45
|
+
# MESSAGE
|
|
46
|
+
#
|
|
47
|
+
# # bad
|
|
25
48
|
# format('%s %s', 'foo', 'bar')
|
|
26
49
|
# sprintf('%s %s', 'foo', 'bar')
|
|
27
50
|
#
|
|
@@ -31,14 +54,14 @@ module RuboCop
|
|
|
31
54
|
class RedundantFormat < Base
|
|
32
55
|
extend AutoCorrector
|
|
33
56
|
|
|
34
|
-
MSG = '
|
|
57
|
+
MSG = 'Use `%<prefer>s` directly instead of `%<method_name>s`.'
|
|
35
58
|
|
|
36
59
|
RESTRICT_ON_SEND = %i[format sprintf].to_set.freeze
|
|
37
60
|
ACCEPTABLE_LITERAL_TYPES = %i[str dstr sym dsym numeric boolean nil].freeze
|
|
38
61
|
|
|
39
62
|
# @!method format_without_additional_args?(node)
|
|
40
63
|
def_node_matcher :format_without_additional_args?, <<~PATTERN
|
|
41
|
-
(send {(const {nil? cbase} :Kernel) nil?} %RESTRICT_ON_SEND ${str dstr})
|
|
64
|
+
(send {(const {nil? cbase} :Kernel) nil?} %RESTRICT_ON_SEND ${str dstr const})
|
|
42
65
|
PATTERN
|
|
43
66
|
|
|
44
67
|
# @!method rational_number?(node)
|
|
@@ -56,10 +79,20 @@ module RuboCop
|
|
|
56
79
|
(pair (sym %1) $_)
|
|
57
80
|
PATTERN
|
|
58
81
|
|
|
82
|
+
# @!method splatted_arguments?(node)
|
|
83
|
+
def_node_matcher :splatted_arguments?, <<~PATTERN
|
|
84
|
+
(send _ %RESTRICT_ON_SEND <{
|
|
85
|
+
splat
|
|
86
|
+
(hash <kwsplat ...>)
|
|
87
|
+
} ...>)
|
|
88
|
+
PATTERN
|
|
89
|
+
|
|
59
90
|
def on_send(node)
|
|
60
91
|
format_without_additional_args?(node) do |value|
|
|
61
|
-
|
|
62
|
-
|
|
92
|
+
replacement = escape_control_chars(value.source)
|
|
93
|
+
|
|
94
|
+
add_offense(node, message: message(node, replacement)) do |corrector|
|
|
95
|
+
corrector.replace(node, replacement)
|
|
63
96
|
end
|
|
64
97
|
return
|
|
65
98
|
end
|
|
@@ -69,8 +102,8 @@ module RuboCop
|
|
|
69
102
|
|
|
70
103
|
private
|
|
71
104
|
|
|
72
|
-
def message(node)
|
|
73
|
-
format(MSG, method_name: node.method_name)
|
|
105
|
+
def message(node, prefer)
|
|
106
|
+
format(MSG, prefer: prefer, method_name: node.method_name)
|
|
74
107
|
end
|
|
75
108
|
|
|
76
109
|
def detect_unnecessary_fields(node)
|
|
@@ -80,7 +113,7 @@ module RuboCop
|
|
|
80
113
|
arguments = node.arguments[1..]
|
|
81
114
|
|
|
82
115
|
return unless string && arguments.any?
|
|
83
|
-
return if
|
|
116
|
+
return if splatted_arguments?(node)
|
|
84
117
|
|
|
85
118
|
register_all_fields_literal(node, string, arguments)
|
|
86
119
|
end
|
|
@@ -88,12 +121,20 @@ module RuboCop
|
|
|
88
121
|
def register_all_fields_literal(node, string, arguments)
|
|
89
122
|
return unless all_fields_literal?(string, arguments.dup)
|
|
90
123
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
124
|
+
format_arguments = argument_values(arguments)
|
|
125
|
+
begin
|
|
126
|
+
formatted_string = format(string, *format_arguments)
|
|
127
|
+
rescue ArgumentError
|
|
128
|
+
return
|
|
129
|
+
end
|
|
130
|
+
replacement = quote(formatted_string, node)
|
|
131
|
+
|
|
132
|
+
add_offense(node, message: message(node, replacement)) do |corrector|
|
|
133
|
+
corrector.replace(node, replacement)
|
|
94
134
|
end
|
|
95
135
|
end
|
|
96
136
|
|
|
137
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
97
138
|
def all_fields_literal?(string, arguments)
|
|
98
139
|
count = 0
|
|
99
140
|
sequences = RuboCop::Cop::Utils::FormatString.new(string).format_sequences
|
|
@@ -101,29 +142,44 @@ module RuboCop
|
|
|
101
142
|
|
|
102
143
|
sequences.each do |sequence|
|
|
103
144
|
next if sequence.percent?
|
|
145
|
+
next if unknown_variable_width?(sequence, arguments)
|
|
104
146
|
|
|
105
147
|
hash = arguments.detect(&:hash_type?)
|
|
106
|
-
argument = find_argument(sequence, arguments, hash)
|
|
148
|
+
next unless (argument = find_argument(sequence, arguments, hash))
|
|
107
149
|
next unless matching_argument?(sequence, argument)
|
|
150
|
+
next if (sequence.width || sequence.precision) && argument.dstr_type?
|
|
108
151
|
|
|
109
152
|
count += 1
|
|
110
153
|
end
|
|
111
154
|
|
|
112
155
|
sequences.size == count
|
|
113
156
|
end
|
|
157
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
114
158
|
|
|
159
|
+
# If the sequence has a variable (`*`) width, it cannot be autocorrected
|
|
160
|
+
# if the width is not given as a numeric literal argument
|
|
161
|
+
def unknown_variable_width?(sequence, arguments)
|
|
162
|
+
return false unless sequence.variable_width?
|
|
163
|
+
|
|
164
|
+
argument = arguments[sequence.variable_width_argument_number - 1]
|
|
165
|
+
!numeric?(argument)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# rubocop:disable Metrics/AbcSize
|
|
115
169
|
def find_argument(sequence, arguments, hash)
|
|
116
|
-
if sequence.annotated? || sequence.template?
|
|
170
|
+
if hash && (sequence.annotated? || sequence.template?)
|
|
117
171
|
find_hash_value_node(hash, sequence.name.to_sym).first
|
|
172
|
+
elsif sequence.variable_width?
|
|
173
|
+
# If the specifier contains `*`, the argument for the width can be ignored.
|
|
174
|
+
arguments.delete_at(sequence.variable_width_argument_number - 1)
|
|
175
|
+
arguments.shift
|
|
118
176
|
elsif sequence.arg_number
|
|
119
177
|
arguments[sequence.arg_number.to_i - 1]
|
|
120
178
|
else
|
|
121
|
-
# If the specifier contains `*`, the following arguments will be used
|
|
122
|
-
# to specify the width and can be ignored.
|
|
123
|
-
(sequence.arity - 1).times { arguments.shift }
|
|
124
179
|
arguments.shift
|
|
125
180
|
end
|
|
126
181
|
end
|
|
182
|
+
# rubocop:enable Metrics/AbcSize
|
|
127
183
|
|
|
128
184
|
def matching_argument?(sequence, argument)
|
|
129
185
|
# Template specifiers don't give a type, any acceptable literal type is ok.
|
|
@@ -174,7 +230,12 @@ module RuboCop
|
|
|
174
230
|
end
|
|
175
231
|
end
|
|
176
232
|
|
|
177
|
-
"#{start_delimiter}#{string}#{end_delimiter}"
|
|
233
|
+
"#{start_delimiter}#{escape_control_chars(string)}#{end_delimiter}"
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
# Escape any control characters in the string (eg. `\t` or `\n` become `\\t` or `\\n`)
|
|
237
|
+
def escape_control_chars(string)
|
|
238
|
+
string.gsub(/\p{Cc}/) { |s| s.dump[1..-2] }
|
|
178
239
|
end
|
|
179
240
|
|
|
180
241
|
def argument_values(arguments)
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Style
|
|
6
|
-
#
|
|
6
|
+
# Checks for uses of `Object#freeze` on immutable objects.
|
|
7
7
|
#
|
|
8
8
|
# NOTE: `Regexp` and `Range` literals are frozen objects since Ruby 3.0.
|
|
9
9
|
#
|
|
@@ -60,7 +60,7 @@ module RuboCop
|
|
|
60
60
|
(begin (send !{(str _) array} {:+ :- :* :** :/ :%} {float int}))
|
|
61
61
|
(begin (send _ {:== :=== :!= :<= :>= :< :>} _))
|
|
62
62
|
(send _ {:count :length :size} ...)
|
|
63
|
-
(
|
|
63
|
+
(any_block (send _ {:count :length :size} ...) ...)
|
|
64
64
|
}
|
|
65
65
|
PATTERN
|
|
66
66
|
end
|
|
@@ -49,9 +49,10 @@ module RuboCop
|
|
|
49
49
|
def on_dstr(node)
|
|
50
50
|
return unless single_interpolation?(node)
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
embedded_node = node.children.first
|
|
53
|
+
return if use_match_pattern?(embedded_node)
|
|
54
54
|
|
|
55
|
+
add_offense(node) do |corrector|
|
|
55
56
|
if variable_interpolation?(embedded_node)
|
|
56
57
|
autocorrect_variable_interpolation(corrector, embedded_node, node)
|
|
57
58
|
elsif single_variable_interpolation?(embedded_node)
|
|
@@ -71,6 +72,14 @@ module RuboCop
|
|
|
71
72
|
!embedded_in_percent_array?(node)
|
|
72
73
|
end
|
|
73
74
|
|
|
75
|
+
def use_match_pattern?(node)
|
|
76
|
+
return false if target_ruby_version <= 2.7
|
|
77
|
+
|
|
78
|
+
node.children.any? do |child|
|
|
79
|
+
child.respond_to?(:match_pattern_type?) && child.match_pattern_type?
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
74
83
|
def single_variable_interpolation?(node)
|
|
75
84
|
return false unless node.children.one?
|
|
76
85
|
|
|
@@ -130,7 +139,7 @@ module RuboCop
|
|
|
130
139
|
end
|
|
131
140
|
|
|
132
141
|
def require_parentheses?(node)
|
|
133
|
-
node.send_type? &&
|
|
142
|
+
node.send_type? && node.arguments.any? && !node.parenthesized_call?
|
|
134
143
|
end
|
|
135
144
|
end
|
|
136
145
|
end
|