rubocop 1.69.0 → 1.79.2
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 +23 -19
- data/config/default.yml +290 -65
- data/config/internal_affairs.yml +20 -0
- data/config/obsoletion.yml +8 -3
- data/lib/rubocop/cli/command/execute_runner.rb +3 -3
- data/lib/rubocop/cli/command/show_cops.rb +24 -2
- data/lib/rubocop/cli/command/suggest_extensions.rb +7 -1
- data/lib/rubocop/cli.rb +13 -2
- data/lib/rubocop/comment_config.rb +2 -2
- data/lib/rubocop/config.rb +52 -10
- data/lib/rubocop/config_loader.rb +53 -47
- data/lib/rubocop/config_loader_resolver.rb +36 -10
- 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_validator.rb +25 -14
- data/lib/rubocop/cop/autocorrect_logic.rb +44 -39
- data/lib/rubocop/cop/base.rb +6 -0
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +2 -2
- data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
- data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -1
- 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/generator.rb +6 -0
- data/lib/rubocop/cop/internal_affairs/cop_enabled.rb +85 -0
- data/lib/rubocop/cop/internal_affairs/example_description.rb +9 -5
- data/lib/rubocop/cop/internal_affairs/location_exists.rb +116 -0
- data/lib/rubocop/cop/internal_affairs/location_expression.rb +2 -1
- data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +1 -0
- data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +3 -2
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +5 -5
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +63 -0
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +131 -0
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +231 -0
- data/lib/rubocop/cop/internal_affairs/node_type_group.rb +92 -0
- data/lib/rubocop/cop/internal_affairs/node_type_multiple_predicates.rb +126 -0
- data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +4 -3
- data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +90 -0
- data/lib/rubocop/cop/internal_affairs/operator_keyword.rb +4 -2
- data/lib/rubocop/cop/internal_affairs/plugin.rb +33 -0
- data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +6 -5
- data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +3 -1
- data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +5 -4
- data/lib/rubocop/cop/internal_affairs/undefined_config.rb +13 -2
- data/lib/rubocop/cop/internal_affairs/useless_restrict_on_send.rb +1 -1
- data/lib/rubocop/cop/internal_affairs.rb +6 -16
- data/lib/rubocop/cop/layout/access_modifier_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/argument_alignment.rb +2 -8
- data/lib/rubocop/cop/layout/block_alignment.rb +3 -1
- data/lib/rubocop/cop/layout/block_end_newline.rb +1 -0
- data/lib/rubocop/cop/layout/class_structure.rb +44 -9
- 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 +2 -2
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +2 -2
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +7 -11
- data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +101 -0
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +35 -4
- data/lib/rubocop/cop/layout/empty_lines_around_arguments.rb +8 -29
- data/lib/rubocop/cop/layout/empty_lines_around_begin_body.rb +5 -6
- 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/empty_lines_around_exception_handling_keywords.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +22 -2
- data/lib/rubocop/cop/layout/end_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/extra_spacing.rb +1 -1
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +4 -9
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -7
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +2 -7
- data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +1 -1
- data/lib/rubocop/cop/layout/first_parameter_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/hash_alignment.rb +8 -6
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -1
- 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_continuation_leading_space.rb +11 -2
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +7 -1
- data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/line_length.rb +35 -9
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -0
- data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +25 -0
- data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -0
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +4 -4
- data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +1 -0
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/redundant_line_break.rb +16 -11
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +3 -5
- data/lib/rubocop/cop/layout/single_line_block_chain.rb +1 -1
- data/lib/rubocop/cop/layout/space_after_colon.rb +2 -2
- data/lib/rubocop/cop/layout/space_after_comma.rb +1 -1
- data/lib/rubocop/cop/layout/space_after_method_name.rb +1 -1
- data/lib/rubocop/cop/layout/space_after_semicolon.rb +11 -1
- data/lib/rubocop/cop/layout/space_around_keyword.rb +7 -1
- data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_operators.rb +15 -4
- 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_before_comma.rb +1 -1
- data/lib/rubocop/cop/layout/space_before_semicolon.rb +1 -1
- 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 +5 -3
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_range.rb +5 -0
- data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +118 -0
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +1 -3
- data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +2 -3
- data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -1
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +4 -3
- data/lib/rubocop/cop/lint/constant_definition_in_block.rb +3 -3
- data/lib/rubocop/cop/lint/constant_reassignment.rb +148 -0
- data/lib/rubocop/cop/lint/cop_directive_syntax.rb +84 -0
- data/lib/rubocop/cop/lint/debugger.rb +3 -3
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +2 -1
- data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_methods.rb +111 -23
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_set_element.rb +20 -7
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +14 -64
- data/lib/rubocop/cop/lint/empty_expression.rb +0 -2
- data/lib/rubocop/cop/lint/empty_interpolation.rb +3 -1
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +0 -6
- data/lib/rubocop/cop/lint/float_comparison.rb +37 -12
- data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -1
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +2 -2
- data/lib/rubocop/cop/lint/identity_comparison.rb +19 -15
- data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
- data/lib/rubocop/cop/lint/literal_as_condition.rb +125 -10
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +24 -6
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +1 -1
- data/lib/rubocop/cop/lint/missing_super.rb +2 -2
- data/lib/rubocop/cop/lint/mixed_case_range.rb +3 -3
- data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -1
- data/lib/rubocop/cop/lint/nested_method_definition.rb +9 -5
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
- data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +4 -2
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -3
- data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +3 -3
- data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +19 -31
- data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +1 -1
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +2 -1
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -5
- data/lib/rubocop/cop/lint/raise_exception.rb +29 -10
- data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +2 -2
- 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_string_coercion.rb +2 -2
- data/lib/rubocop/cop/lint/redundant_type_conversion.rb +261 -0
- 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/refinement_import_methods.rb +1 -1
- data/lib/rubocop/cop/lint/require_range_parentheses.rb +1 -1
- data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
- 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 +8 -1
- data/lib/rubocop/cop/lint/self_assignment.rb +25 -0
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +13 -1
- data/lib/rubocop/cop/lint/shared_mutable_default.rb +76 -0
- data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
- data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +111 -0
- data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/syntax.rb +4 -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/unescaped_bracket_in_regexp.rb +1 -1
- data/lib/rubocop/cop/lint/unexpected_block_arity.rb +3 -1
- data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -1
- data/lib/rubocop/cop/lint/unreachable_code.rb +52 -2
- data/lib/rubocop/cop/lint/unreachable_loop.rb +6 -6
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +34 -8
- data/lib/rubocop/cop/lint/useless_assignment.rb +3 -1
- data/lib/rubocop/cop/lint/useless_constant_scoping.rb +71 -0
- data/lib/rubocop/cop/lint/useless_default_value_argument.rb +90 -0
- data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +4 -0
- data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
- data/lib/rubocop/cop/lint/useless_numeric_operation.rb +3 -1
- 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 +5 -5
- data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +121 -0
- data/lib/rubocop/cop/lint/void.rb +14 -11
- 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/block_nesting.rb +1 -1
- data/lib/rubocop/cop/metrics/class_length.rb +9 -9
- data/lib/rubocop/cop/metrics/collection_literal_length.rb +7 -0
- data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +1 -1
- data/lib/rubocop/cop/metrics/method_length.rb +9 -1
- data/lib/rubocop/cop/metrics/module_length.rb +1 -1
- data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +2 -2
- data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +7 -7
- data/lib/rubocop/cop/mixin/alignment.rb +3 -3
- data/lib/rubocop/cop/mixin/allowed_pattern.rb +4 -4
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +13 -13
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +2 -2
- data/lib/rubocop/cop/mixin/comments_help.rb +8 -3
- data/lib/rubocop/cop/mixin/def_node.rb +1 -1
- data/lib/rubocop/cop/mixin/dig_help.rb +1 -1
- data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +1 -1
- 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_shorthand_syntax.rb +22 -22
- data/lib/rubocop/cop/mixin/hash_subset.rb +203 -0
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +74 -74
- data/lib/rubocop/cop/mixin/line_length_help.rb +27 -10
- data/lib/rubocop/cop/mixin/method_complexity.rb +2 -1
- 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/percent_literal.rb +1 -1
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +68 -30
- data/lib/rubocop/cop/mixin/range_help.rb +15 -3
- data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
- data/lib/rubocop/cop/mixin/statement_modifier.rb +8 -3
- data/lib/rubocop/cop/mixin/string_help.rb +2 -2
- data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -1
- data/lib/rubocop/cop/mixin/target_ruby_version.rb +1 -1
- data/lib/rubocop/cop/mixin/trailing_comma.rb +21 -5
- data/lib/rubocop/cop/naming/accessor_method_name.rb +6 -6
- data/lib/rubocop/cop/naming/block_forwarding.rb +19 -15
- 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 +185 -15
- data/lib/rubocop/cop/naming/predicate_method.rb +306 -0
- data/lib/rubocop/cop/naming/{predicate_name.rb → predicate_prefix.rb} +48 -4
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.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/compound_hash.rb +2 -0
- data/lib/rubocop/cop/security/eval.rb +2 -1
- data/lib/rubocop/cop/security/open.rb +1 -0
- data/lib/rubocop/cop/security/yaml_load.rb +3 -2
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +66 -15
- data/lib/rubocop/cop/style/accessor_grouping.rb +32 -6
- data/lib/rubocop/cop/style/and_or.rb +1 -1
- data/lib/rubocop/cop/style/arguments_forwarding.rb +57 -44
- data/lib/rubocop/cop/style/array_first_last.rb +18 -2
- data/lib/rubocop/cop/style/array_intersect.rb +81 -40
- data/lib/rubocop/cop/style/block_delimiters.rb +27 -24
- data/lib/rubocop/cop/style/case_like_if.rb +1 -1
- data/lib/rubocop/cop/style/class_and_module_children.rb +52 -11
- data/lib/rubocop/cop/style/class_equality_comparison.rb +1 -1
- data/lib/rubocop/cop/style/collection_methods.rb +2 -1
- data/lib/rubocop/cop/style/collection_querying.rb +167 -0
- data/lib/rubocop/cop/style/combinable_defined.rb +1 -1
- data/lib/rubocop/cop/style/combinable_loops.rb +3 -2
- 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/concat_array_literals.rb +1 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +23 -7
- 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 +6 -7
- data/lib/rubocop/cop/style/documentation.rb +1 -1
- data/lib/rubocop/cop/style/double_negation.rb +4 -4
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +4 -7
- data/lib/rubocop/cop/style/each_with_object.rb +2 -3
- data/lib/rubocop/cop/style/empty_else.rb +4 -2
- data/lib/rubocop/cop/style/empty_literal.rb +5 -1
- data/lib/rubocop/cop/style/empty_method.rb +1 -1
- data/lib/rubocop/cop/style/empty_string_inside_interpolation.rb +100 -0
- data/lib/rubocop/cop/style/endless_method.rb +163 -18
- data/lib/rubocop/cop/style/eval_with_location.rb +4 -4
- data/lib/rubocop/cop/style/exact_regexp_match.rb +2 -3
- data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -7
- data/lib/rubocop/cop/style/explicit_block_argument.rb +16 -3
- data/lib/rubocop/cop/style/exponential_notation.rb +6 -5
- data/lib/rubocop/cop/style/fetch_env_var.rb +34 -7
- data/lib/rubocop/cop/style/file_null.rb +20 -4
- data/lib/rubocop/cop/style/float_division.rb +8 -4
- 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 +6 -8
- data/lib/rubocop/cop/style/hash_except.rb +35 -147
- data/lib/rubocop/cop/style/hash_fetch_chain.rb +104 -0
- data/lib/rubocop/cop/style/hash_slice.rb +80 -0
- data/lib/rubocop/cop/style/hash_syntax.rb +9 -3
- 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 +25 -6
- data/lib/rubocop/cop/style/if_inside_else.rb +10 -13
- data/lib/rubocop/cop/style/if_unless_modifier.rb +36 -9
- 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 +2 -2
- data/lib/rubocop/cop/style/if_with_semicolon.rb +7 -5
- data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
- data/lib/rubocop/cop/style/inverse_methods.rb +16 -12
- 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 +93 -0
- data/lib/rubocop/cop/style/it_block_parameter.rb +121 -0
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +14 -8
- data/lib/rubocop/cop/style/lambda.rb +1 -0
- data/lib/rubocop/cop/style/lambda_call.rb +10 -3
- data/lib/rubocop/cop/style/line_end_concatenation.rb +10 -4
- data/lib/rubocop/cop/style/map_into_array.rb +5 -2
- data/lib/rubocop/cop/style/map_to_hash.rb +13 -4
- data/lib/rubocop/cop/style/map_to_set.rb +4 -5
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +27 -19
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +18 -0
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +3 -2
- data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +3 -4
- data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/min_max_comparison.rb +13 -5
- data/lib/rubocop/cop/style/missing_else.rb +2 -0
- data/lib/rubocop/cop/style/multiline_block_chain.rb +3 -2
- 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/multiple_comparison.rb +34 -22
- data/lib/rubocop/cop/style/mutable_constant.rb +3 -3
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +1 -1
- data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
- data/lib/rubocop/cop/style/next.rb +44 -0
- data/lib/rubocop/cop/style/object_then.rb +15 -15
- data/lib/rubocop/cop/style/open_struct_use.rb +5 -5
- data/lib/rubocop/cop/style/parallel_assignment.rb +33 -25
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +2 -2
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
- data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
- data/lib/rubocop/cop/style/proc.rb +2 -2
- data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
- data/lib/rubocop/cop/style/raise_args.rb +14 -12
- data/lib/rubocop/cop/style/random_with_offset.rb +3 -3
- data/lib/rubocop/cop/style/redundant_argument.rb +3 -1
- data/lib/rubocop/cop/style/redundant_array_flatten.rb +50 -0
- data/lib/rubocop/cop/style/redundant_begin.rb +2 -1
- data/lib/rubocop/cop/style/redundant_condition.rb +59 -2
- data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +16 -5
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +6 -10
- data/lib/rubocop/cop/style/redundant_each.rb +1 -1
- data/lib/rubocop/cop/style/redundant_exception.rb +2 -2
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -9
- data/lib/rubocop/cop/style/redundant_format.rb +262 -0
- data/lib/rubocop/cop/style/redundant_freeze.rb +4 -4
- data/lib/rubocop/cop/style/redundant_initialize.rb +12 -3
- data/lib/rubocop/cop/style/redundant_interpolation.rb +1 -1
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +39 -22
- data/lib/rubocop/cop/style/redundant_parentheses.rb +85 -17
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +3 -0
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +1 -1
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +1 -1
- data/lib/rubocop/cop/style/redundant_self.rb +10 -6
- data/lib/rubocop/cop/style/redundant_self_assignment.rb +14 -28
- data/lib/rubocop/cop/style/redundant_sort.rb +2 -2
- data/lib/rubocop/cop/style/redundant_sort_by.rb +17 -1
- data/lib/rubocop/cop/style/redundant_string_escape.rb +2 -2
- 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 +46 -16
- data/lib/rubocop/cop/style/select_by_regexp.rb +4 -1
- data/lib/rubocop/cop/style/semicolon.rb +1 -1
- data/lib/rubocop/cop/style/send_with_literal_method_name.rb +2 -1
- data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
- data/lib/rubocop/cop/style/single_line_do_end_block.rb +4 -3
- data/lib/rubocop/cop/style/single_line_methods.rb +13 -11
- data/lib/rubocop/cop/style/slicing_with_range.rb +40 -11
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +68 -101
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/string_concatenation.rb +15 -14
- data/lib/rubocop/cop/style/string_literals.rb +1 -1
- data/lib/rubocop/cop/style/string_methods.rb +1 -1
- data/lib/rubocop/cop/style/struct_inheritance.rb +8 -1
- data/lib/rubocop/cop/style/super_arguments.rb +66 -19
- data/lib/rubocop/cop/style/symbol_proc.rb +3 -1
- data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/top_level_method_definition.rb +2 -1
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +11 -2
- 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/while_until_modifier.rb +0 -1
- data/lib/rubocop/cop/style/yoda_condition.rb +8 -4
- data/lib/rubocop/cop/style/yoda_expression.rb +2 -1
- data/lib/rubocop/cop/team.rb +1 -1
- data/lib/rubocop/cop/util.rb +12 -5
- data/lib/rubocop/cop/utils/format_string.rb +10 -5
- 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 +10 -3
- data/lib/rubocop/cop/variable_force/variable_table.rb +3 -3
- data/lib/rubocop/cop/variable_force.rb +23 -8
- data/lib/rubocop/cops_documentation_generator.rb +32 -16
- data/lib/rubocop/directive_comment.rb +45 -11
- data/lib/rubocop/ext/regexp_node.rb +0 -1
- data/lib/rubocop/formatter/disabled_config_formatter.rb +2 -1
- data/lib/rubocop/formatter/formatter_set.rb +1 -1
- 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 +189 -0
- data/lib/rubocop/lsp/logger.rb +2 -2
- data/lib/rubocop/lsp/routes.rb +10 -26
- data/lib/rubocop/lsp/runtime.rb +18 -50
- data/lib/rubocop/lsp/server.rb +0 -2
- data/lib/rubocop/lsp/stdin_runner.rb +85 -0
- data/lib/rubocop/magic_comment.rb +11 -3
- data/lib/rubocop/options.rb +28 -12
- data/lib/rubocop/path_util.rb +15 -8
- data/lib/rubocop/pending_cops_reporter.rb +56 -0
- data/lib/rubocop/plugin/configuration_integrator.rb +143 -0
- data/lib/rubocop/plugin/load_error.rb +26 -0
- data/lib/rubocop/plugin/loader.rb +100 -0
- data/lib/rubocop/plugin/not_supported_error.rb +29 -0
- data/lib/rubocop/plugin.rb +46 -0
- data/lib/rubocop/rake_task.rb +4 -1
- data/lib/rubocop/result_cache.rb +26 -24
- data/lib/rubocop/rspec/cop_helper.rb +13 -1
- data/lib/rubocop/rspec/expect_offense.rb +15 -5
- data/lib/rubocop/rspec/shared_contexts.rb +38 -1
- data/lib/rubocop/rspec/support.rb +4 -2
- data/lib/rubocop/runner.rb +10 -7
- data/lib/rubocop/server/cache.rb +51 -13
- data/lib/rubocop/server/cli.rb +2 -2
- 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 +7 -2
- data/lib/rubocop/target_ruby.rb +16 -1
- data/lib/rubocop/version.rb +30 -8
- data/lib/rubocop.rb +27 -2
- data/lib/ruby_lsp/rubocop/addon.rb +75 -0
- data/lib/ruby_lsp/rubocop/runtime_adapter.rb +65 -0
- metadata +72 -19
- data/lib/rubocop/cop/utils/regexp_ranges.rb +0 -113
- data/lib/rubocop/rspec/host_environment_simulation_helper.rb +0 -28
@@ -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
|
@@ -95,6 +95,7 @@ module RuboCop
|
|
95
95
|
end
|
96
96
|
|
97
97
|
alias on_numblock on_block
|
98
|
+
alias on_itblock on_block
|
98
99
|
|
99
100
|
def on_kwbegin(node)
|
100
101
|
return unless (target_node = offensive_kwbegins(node).to_a.last)
|
@@ -185,7 +186,7 @@ module RuboCop
|
|
185
186
|
def contain_rescue_or_ensure?(node)
|
186
187
|
first_child = node.children.first
|
187
188
|
|
188
|
-
first_child.
|
189
|
+
first_child.type?(:rescue, :ensure)
|
189
190
|
end
|
190
191
|
|
191
192
|
def valid_context_using_only_begin?(node)
|
@@ -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
|
|
@@ -157,7 +200,7 @@ module RuboCop
|
|
157
200
|
end
|
158
201
|
|
159
202
|
def asgn_type?(node)
|
160
|
-
node.
|
203
|
+
node.type?(:lvasgn, :ivasgn, :cvasgn, :gvasgn)
|
161
204
|
end
|
162
205
|
|
163
206
|
def branches_have_method?(node)
|
@@ -184,9 +227,17 @@ module RuboCop
|
|
184
227
|
return false unless argument.hash_type?
|
185
228
|
return false unless (node = argument.children.first)
|
186
229
|
|
187
|
-
node.
|
230
|
+
node.type?(:kwsplat, :forwarded_kwrestarg)
|
231
|
+
end
|
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})"
|
188
238
|
end
|
189
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?
|
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
|
@@ -3,7 +3,8 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
# Checks for
|
6
|
+
# Checks for paths given to `require_relative` that start with
|
7
|
+
# the current directory (`./`), which can be omitted.
|
7
8
|
#
|
8
9
|
# @example
|
9
10
|
#
|
@@ -19,20 +20,30 @@ module RuboCop
|
|
19
20
|
|
20
21
|
MSG = 'Remove the redundant current directory path.'
|
21
22
|
RESTRICT_ON_SEND = %i[require_relative].freeze
|
22
|
-
|
23
|
+
CURRENT_DIRECTORY_PREFIX = %r{\./+}.freeze
|
24
|
+
REDUNDANT_CURRENT_DIRECTORY_PREFIX = /\A#{CURRENT_DIRECTORY_PREFIX}/.freeze
|
23
25
|
|
24
26
|
def on_send(node)
|
25
27
|
return unless (first_argument = node.first_argument)
|
26
|
-
return unless first_argument.
|
27
|
-
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))
|
28
30
|
|
29
31
|
begin_pos = first_argument.source_range.begin.begin_pos + index
|
30
|
-
|
32
|
+
end_pos = begin_pos + redundant_length
|
33
|
+
range = range_between(begin_pos, end_pos)
|
31
34
|
|
32
35
|
add_offense(range) do |corrector|
|
33
36
|
corrector.remove(range)
|
34
37
|
end
|
35
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
|
36
47
|
end
|
37
48
|
end
|
38
49
|
end
|
@@ -25,11 +25,11 @@ module RuboCop
|
|
25
25
|
MSG = 'Remove the redundant double splat and braces, use keyword arguments directly.'
|
26
26
|
MERGE_METHODS = %i[merge merge!].freeze
|
27
27
|
|
28
|
-
# rubocop:disable Metrics/
|
28
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
29
29
|
def on_hash(node)
|
30
30
|
return if node.pairs.empty? || node.pairs.any?(&:hash_rocket?)
|
31
31
|
return unless (parent = node.parent)
|
32
|
-
return unless parent.
|
32
|
+
return unless parent.type?(:call, :kwsplat)
|
33
33
|
return unless mergeable?(parent)
|
34
34
|
return unless (kwsplat = node.each_ancestor(:kwsplat).first)
|
35
35
|
return if !node.braces? || allowed_double_splat_receiver?(kwsplat)
|
@@ -38,13 +38,13 @@ module RuboCop
|
|
38
38
|
autocorrect(corrector, node, kwsplat)
|
39
39
|
end
|
40
40
|
end
|
41
|
-
# rubocop:enable Metrics/
|
41
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
42
42
|
|
43
43
|
private
|
44
44
|
|
45
45
|
def allowed_double_splat_receiver?(kwsplat)
|
46
46
|
first_child = kwsplat.children.first
|
47
|
-
return true if first_child.
|
47
|
+
return true if first_child.any_block_type?
|
48
48
|
return false unless first_child.call_type?
|
49
49
|
|
50
50
|
root_receiver = root_receiver(first_child)
|
@@ -73,7 +73,7 @@ module RuboCop
|
|
73
73
|
end
|
74
74
|
|
75
75
|
def select_merge_method_nodes(kwsplat)
|
76
|
-
|
76
|
+
kwsplat.each_descendant(:call).select do |node|
|
77
77
|
mergeable?(node)
|
78
78
|
end
|
79
79
|
end
|
@@ -89,7 +89,7 @@ module RuboCop
|
|
89
89
|
def autocorrect_merge_methods(corrector, merge_methods, kwsplat)
|
90
90
|
range = range_of_merge_methods(merge_methods)
|
91
91
|
|
92
|
-
new_kwsplat_arguments =
|
92
|
+
new_kwsplat_arguments = kwsplat.each_descendant(:call).map do |descendant|
|
93
93
|
convert_to_new_arguments(descendant)
|
94
94
|
end
|
95
95
|
new_source = new_kwsplat_arguments.compact.reverse.unshift('').join(', ')
|
@@ -104,10 +104,6 @@ module RuboCop
|
|
104
104
|
begin_merge_method.loc.dot.begin.join(end_merge_method.source_range.end)
|
105
105
|
end
|
106
106
|
|
107
|
-
def extract_send_methods(kwsplat)
|
108
|
-
kwsplat.each_descendant(:send, :csend)
|
109
|
-
end
|
110
|
-
|
111
107
|
def convert_to_new_arguments(node)
|
112
108
|
return unless mergeable?(node)
|
113
109
|
|
@@ -65,7 +65,7 @@ module RuboCop
|
|
65
65
|
return if node.last_argument&.block_pass_type?
|
66
66
|
|
67
67
|
if node.method?(:each) && !node.parent&.block_type?
|
68
|
-
ancestor_node = node.each_ancestor(:
|
68
|
+
ancestor_node = node.each_ancestor(:call).detect do |ancestor|
|
69
69
|
ancestor.receiver == node &&
|
70
70
|
(RESTRICT_ON_SEND.include?(ancestor.method_name) || ancestor.method?(:reverse_each))
|
71
71
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
# Checks for RuntimeError as the argument of raise
|
6
|
+
# Checks for `RuntimeError` as the argument of `raise`/`fail`.
|
7
7
|
#
|
8
8
|
# @example
|
9
9
|
# # bad
|
@@ -51,7 +51,7 @@ module RuboCop
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def string_message?(message)
|
54
|
-
message.
|
54
|
+
message.type?(:str, :dstr, :xstr)
|
55
55
|
end
|
56
56
|
|
57
57
|
def fix_compact(node)
|
@@ -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?) ||
|
@@ -0,0 +1,262 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Checks for calls to `Kernel#format` or `Kernel#sprintf` that are redundant.
|
7
|
+
#
|
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
|
+
#
|
11
|
+
# Also looks for `format` calls where the arguments are literals that can be
|
12
|
+
# inlined into a string easily. This applies to the `%s`, `%d`, `%i`, `%u`, and
|
13
|
+
# `%f` format specifiers.
|
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
|
+
#
|
31
|
+
# @example
|
32
|
+
#
|
33
|
+
# # bad
|
34
|
+
# format('the quick brown fox jumps over the lazy dog.')
|
35
|
+
# sprintf('the quick brown fox jumps over the lazy dog.')
|
36
|
+
#
|
37
|
+
# # good
|
38
|
+
# 'the quick brown fox jumps over the lazy dog.'
|
39
|
+
#
|
40
|
+
# # bad
|
41
|
+
# format(MESSAGE)
|
42
|
+
# sprintf(MESSAGE)
|
43
|
+
#
|
44
|
+
# # good
|
45
|
+
# MESSAGE
|
46
|
+
#
|
47
|
+
# # bad
|
48
|
+
# format('%s %s', 'foo', 'bar')
|
49
|
+
# sprintf('%s %s', 'foo', 'bar')
|
50
|
+
#
|
51
|
+
# # good
|
52
|
+
# 'foo bar'
|
53
|
+
#
|
54
|
+
class RedundantFormat < Base
|
55
|
+
extend AutoCorrector
|
56
|
+
|
57
|
+
MSG = 'Use `%<prefer>s` directly instead of `%<method_name>s`.'
|
58
|
+
|
59
|
+
RESTRICT_ON_SEND = %i[format sprintf].to_set.freeze
|
60
|
+
ACCEPTABLE_LITERAL_TYPES = %i[str dstr sym dsym numeric boolean nil].freeze
|
61
|
+
|
62
|
+
# @!method format_without_additional_args?(node)
|
63
|
+
def_node_matcher :format_without_additional_args?, <<~PATTERN
|
64
|
+
(send {(const {nil? cbase} :Kernel) nil?} %RESTRICT_ON_SEND ${str dstr const})
|
65
|
+
PATTERN
|
66
|
+
|
67
|
+
# @!method rational_number?(node)
|
68
|
+
def_node_matcher :rational_number?, <<~PATTERN
|
69
|
+
{rational (send int :/ rational) (begin rational) (begin (send int :/ rational))}
|
70
|
+
PATTERN
|
71
|
+
|
72
|
+
# @!method complex_number?(node)
|
73
|
+
def_node_matcher :complex_number?, <<~PATTERN
|
74
|
+
{complex (send int :+ complex) (begin complex) (begin (send int :+ complex))}
|
75
|
+
PATTERN
|
76
|
+
|
77
|
+
# @!method find_hash_value_node(node, name)
|
78
|
+
def_node_search :find_hash_value_node, <<~PATTERN
|
79
|
+
(pair (sym %1) $_)
|
80
|
+
PATTERN
|
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
|
+
|
90
|
+
def on_send(node)
|
91
|
+
format_without_additional_args?(node) do |value|
|
92
|
+
replacement = value.source
|
93
|
+
|
94
|
+
add_offense(node, message: message(node, replacement)) do |corrector|
|
95
|
+
corrector.replace(node, replacement)
|
96
|
+
end
|
97
|
+
return
|
98
|
+
end
|
99
|
+
|
100
|
+
detect_unnecessary_fields(node)
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
def message(node, prefer)
|
106
|
+
format(MSG, prefer: prefer, method_name: node.method_name)
|
107
|
+
end
|
108
|
+
|
109
|
+
def detect_unnecessary_fields(node)
|
110
|
+
return unless node.first_argument&.str_type?
|
111
|
+
|
112
|
+
string = node.first_argument.value
|
113
|
+
arguments = node.arguments[1..]
|
114
|
+
|
115
|
+
return unless string && arguments.any?
|
116
|
+
return if splatted_arguments?(node)
|
117
|
+
|
118
|
+
register_all_fields_literal(node, string, arguments)
|
119
|
+
end
|
120
|
+
|
121
|
+
def register_all_fields_literal(node, string, arguments)
|
122
|
+
return unless all_fields_literal?(string, arguments.dup)
|
123
|
+
|
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)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def all_fields_literal?(string, arguments)
|
138
|
+
count = 0
|
139
|
+
sequences = RuboCop::Cop::Utils::FormatString.new(string).format_sequences
|
140
|
+
return false unless sequences.any?
|
141
|
+
|
142
|
+
sequences.each do |sequence|
|
143
|
+
next if sequence.percent?
|
144
|
+
|
145
|
+
hash = arguments.detect(&:hash_type?)
|
146
|
+
next unless (argument = find_argument(sequence, arguments, hash))
|
147
|
+
next unless matching_argument?(sequence, argument)
|
148
|
+
|
149
|
+
count += 1
|
150
|
+
end
|
151
|
+
|
152
|
+
sequences.size == count
|
153
|
+
end
|
154
|
+
|
155
|
+
def find_argument(sequence, arguments, hash)
|
156
|
+
if hash && (sequence.annotated? || sequence.template?)
|
157
|
+
find_hash_value_node(hash, sequence.name.to_sym).first
|
158
|
+
elsif sequence.arg_number
|
159
|
+
arguments[sequence.arg_number.to_i - 1]
|
160
|
+
else
|
161
|
+
# If the specifier contains `*`, the following arguments will be used
|
162
|
+
# to specify the width and can be ignored.
|
163
|
+
(sequence.arity - 1).times { arguments.shift }
|
164
|
+
arguments.shift
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def matching_argument?(sequence, argument)
|
169
|
+
# Template specifiers don't give a type, any acceptable literal type is ok.
|
170
|
+
return argument.type?(*ACCEPTABLE_LITERAL_TYPES) if sequence.template?
|
171
|
+
|
172
|
+
# An argument matches a specifier if it can be easily converted
|
173
|
+
# to that type.
|
174
|
+
case sequence.type
|
175
|
+
when 's'
|
176
|
+
argument.type?(*ACCEPTABLE_LITERAL_TYPES)
|
177
|
+
when 'd', 'i', 'u'
|
178
|
+
integer?(argument)
|
179
|
+
when 'f'
|
180
|
+
float?(argument)
|
181
|
+
else
|
182
|
+
false
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def numeric?(argument)
|
187
|
+
argument.type?(:numeric, :str) ||
|
188
|
+
rational_number?(argument) ||
|
189
|
+
complex_number?(argument)
|
190
|
+
end
|
191
|
+
|
192
|
+
def integer?(argument)
|
193
|
+
numeric?(argument) && Integer(argument_value(argument), exception: false)
|
194
|
+
end
|
195
|
+
|
196
|
+
def float?(argument)
|
197
|
+
numeric?(argument) && Float(argument_value(argument), exception: false)
|
198
|
+
end
|
199
|
+
|
200
|
+
# Add correct quotes to the formatted string, preferring retaining the existing
|
201
|
+
# quotes if possible.
|
202
|
+
def quote(string, node)
|
203
|
+
str_node = node.first_argument
|
204
|
+
start_delimiter = str_node.loc.begin.source
|
205
|
+
end_delimiter = str_node.loc.end.source
|
206
|
+
|
207
|
+
# If there is any interpolation, the delimiters need to be changed potentially
|
208
|
+
if node.each_descendant(:dstr, :dsym).any?
|
209
|
+
case start_delimiter
|
210
|
+
when "'"
|
211
|
+
start_delimiter = end_delimiter = '"'
|
212
|
+
when /\A%q(.)/
|
213
|
+
start_delimiter = "%Q#{Regexp.last_match[1]}"
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
"#{start_delimiter}#{string}#{end_delimiter}"
|
218
|
+
end
|
219
|
+
|
220
|
+
def argument_values(arguments)
|
221
|
+
arguments.map { |argument| argument_value(argument) }
|
222
|
+
end
|
223
|
+
|
224
|
+
def argument_value(argument)
|
225
|
+
argument = argument.children.first if argument.begin_type?
|
226
|
+
|
227
|
+
if argument.dsym_type?
|
228
|
+
dsym_value(argument)
|
229
|
+
elsif argument.hash_type?
|
230
|
+
hash_value(argument)
|
231
|
+
elsif rational_number?(argument)
|
232
|
+
rational_value(argument)
|
233
|
+
elsif complex_number?(argument)
|
234
|
+
complex_value(argument)
|
235
|
+
elsif argument.respond_to?(:value)
|
236
|
+
argument.value
|
237
|
+
else
|
238
|
+
argument.source
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
def dsym_value(dsym_node)
|
243
|
+
dsym_node.children.first.source
|
244
|
+
end
|
245
|
+
|
246
|
+
def hash_value(hash_node)
|
247
|
+
hash_node.each_pair.with_object({}) do |pair, hash|
|
248
|
+
hash[pair.key.value] = argument_value(pair.value)
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
def rational_value(rational_node)
|
253
|
+
rational_node.source.to_r
|
254
|
+
end
|
255
|
+
|
256
|
+
def complex_value(complex_node)
|
257
|
+
Complex(complex_node.source)
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
@@ -3,9 +3,9 @@
|
|
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
|
-
# NOTE: Regexp and Range literals are frozen objects since Ruby 3.0.
|
8
|
+
# NOTE: `Regexp` and `Range` literals are frozen objects since Ruby 3.0.
|
9
9
|
#
|
10
10
|
# NOTE: From Ruby 3.0, this cop allows explicit freezing of interpolated
|
11
11
|
# string literals when `# frozen-string-literal: true` is used.
|
@@ -42,7 +42,7 @@ module RuboCop
|
|
42
42
|
return true if node.immutable_literal?
|
43
43
|
return true if frozen_string_literal?(node)
|
44
44
|
|
45
|
-
target_ruby_version >= 3.0 &&
|
45
|
+
target_ruby_version >= 3.0 && node.type?(:regexp, :range)
|
46
46
|
end
|
47
47
|
|
48
48
|
def strip_parenthesis(node)
|
@@ -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
|
@@ -11,6 +11,9 @@ module RuboCop
|
|
11
11
|
# will not register an offense, because it allows the initializer to take a different
|
12
12
|
# number of arguments as its superclass potentially does.
|
13
13
|
#
|
14
|
+
# NOTE: If an initializer takes any arguments and has an empty body, RuboCop
|
15
|
+
# assumes it to *not* be redundant. This is to prevent potential `ArgumentError`.
|
16
|
+
#
|
14
17
|
# NOTE: If an initializer argument has a default value, RuboCop assumes it
|
15
18
|
# to *not* be redundant.
|
16
19
|
#
|
@@ -19,8 +22,10 @@ module RuboCop
|
|
19
22
|
# initializer.
|
20
23
|
#
|
21
24
|
# @safety
|
22
|
-
# This cop is unsafe because
|
23
|
-
#
|
25
|
+
# This cop is unsafe because removing an empty initializer may alter
|
26
|
+
# the behavior of the code, particularly if the superclass initializer
|
27
|
+
# raises an exception. In such cases, the empty initializer may act as
|
28
|
+
# a safeguard to prevent unintended errors from propagating.
|
24
29
|
#
|
25
30
|
# @example
|
26
31
|
# # bad
|
@@ -69,6 +74,10 @@ module RuboCop
|
|
69
74
|
# end
|
70
75
|
#
|
71
76
|
# # good (changes the parameter requirements)
|
77
|
+
# def initialize(_)
|
78
|
+
# end
|
79
|
+
#
|
80
|
+
# # good (changes the parameter requirements)
|
72
81
|
# def initialize(*)
|
73
82
|
# end
|
74
83
|
#
|
@@ -111,7 +120,7 @@ module RuboCop
|
|
111
120
|
return if acceptable?(node)
|
112
121
|
|
113
122
|
if node.body.nil?
|
114
|
-
register_offense(node, MSG_EMPTY)
|
123
|
+
register_offense(node, MSG_EMPTY) if node.arguments.empty?
|
115
124
|
else
|
116
125
|
return if node.body.begin_type?
|
117
126
|
|