rubocop 1.66.1 → 1.72.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 +2 -2
- data/config/default.yml +162 -14
- data/config/internal_affairs.yml +11 -0
- data/lib/rubocop/cached_data.rb +12 -4
- data/lib/rubocop/cli/command/auto_generate_config.rb +6 -7
- data/lib/rubocop/cli/command/execute_runner.rb +4 -4
- data/lib/rubocop/cli/command/lsp.rb +2 -2
- data/lib/rubocop/cli/command/show_cops.rb +24 -2
- data/lib/rubocop/cli/command/suggest_extensions.rb +7 -1
- data/lib/rubocop/cli/command/version.rb +2 -2
- data/lib/rubocop/comment_config.rb +2 -2
- data/lib/rubocop/config.rb +17 -4
- data/lib/rubocop/config_loader.rb +48 -8
- data/lib/rubocop/config_loader_resolver.rb +36 -11
- data/lib/rubocop/config_validator.rb +20 -9
- data/lib/rubocop/cop/autocorrect_logic.rb +36 -19
- data/lib/rubocop/cop/base.rb +13 -3
- 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/gem_filename.rb +0 -1
- data/lib/rubocop/cop/bundler/gem_version.rb +1 -0
- data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +0 -1
- data/lib/rubocop/cop/cop.rb +8 -0
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +1 -12
- data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +10 -0
- data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +1 -2
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +0 -2
- data/lib/rubocop/cop/generator.rb +6 -0
- data/lib/rubocop/cop/internal_affairs/cop_description.rb +0 -4
- data/lib/rubocop/cop/internal_affairs/cop_enabled.rb +85 -0
- data/lib/rubocop/cop/internal_affairs/example_description.rb +4 -2
- 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 +3 -4
- data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +3 -2
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
- 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 +229 -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/numblock_handler.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +90 -0
- data/lib/rubocop/cop/internal_affairs/operator_keyword.rb +48 -0
- data/lib/rubocop/cop/internal_affairs/plugin.rb +33 -0
- data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +6 -21
- data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +11 -2
- data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +5 -4
- data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +0 -2
- data/lib/rubocop/cop/internal_affairs/undefined_config.rb +7 -1
- data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +0 -5
- data/lib/rubocop/cop/internal_affairs.rb +6 -0
- data/lib/rubocop/cop/layout/access_modifier_indentation.rb +6 -2
- data/lib/rubocop/cop/layout/argument_alignment.rb +2 -9
- data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/begin_end_alignment.rb +0 -1
- data/lib/rubocop/cop/layout/block_alignment.rb +3 -2
- data/lib/rubocop/cop/layout/class_structure.rb +9 -9
- 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 +3 -3
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +7 -11
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +3 -3
- data/lib/rubocop/cop/layout/empty_lines_around_begin_body.rb +5 -6
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +4 -5
- data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +23 -1
- 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 +3 -8
- 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_method_argument_line_break.rb +8 -0
- data/lib/rubocop/cop/layout/first_parameter_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/hash_alignment.rb +6 -4
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +11 -12
- data/lib/rubocop/cop/layout/leading_comment_space.rb +71 -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 +119 -4
- 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 +2 -1
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +4 -4
- data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +2 -3
- data/lib/rubocop/cop/layout/parameter_alignment.rb +3 -4
- data/lib/rubocop/cop/layout/redundant_line_break.rb +10 -41
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +4 -3
- 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 +1 -1
- data/lib/rubocop/cop/layout/space_around_keyword.rb +2 -1
- data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_operators.rb +19 -20
- data/lib/rubocop/cop/layout/space_before_brackets.rb +5 -5
- 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 +6 -0
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +4 -0
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +4 -0
- data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +0 -1
- 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 +4 -1
- data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +119 -0
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +1 -3
- data/lib/rubocop/cop/lint/big_decimal_new.rb +4 -7
- data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +10 -12
- data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -1
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +6 -0
- 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 +1 -1
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +2 -1
- data/lib/rubocop/cop/lint/duplicate_branch.rb +39 -4
- data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_set_element.rb +87 -0
- data/lib/rubocop/cop/lint/empty_ensure.rb +1 -1
- data/lib/rubocop/cop/lint/empty_expression.rb +0 -2
- data/lib/rubocop/cop/lint/empty_file.rb +0 -2
- data/lib/rubocop/cop/lint/ensure_return.rb +1 -4
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -1
- data/lib/rubocop/cop/lint/float_comparison.rb +20 -9
- data/lib/rubocop/cop/lint/float_out_of_range.rb +2 -4
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +2 -2
- data/lib/rubocop/cop/lint/hash_new_with_keyword_arguments_as_default.rb +55 -0
- data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +11 -5
- data/lib/rubocop/cop/lint/interpolation_check.rb +9 -0
- data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +8 -14
- data/lib/rubocop/cop/lint/literal_as_condition.rb +1 -0
- data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +1 -1
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +49 -8
- data/lib/rubocop/cop/lint/missing_super.rb +2 -2
- data/lib/rubocop/cop/lint/mixed_case_range.rb +3 -6
- 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/no_return_in_begin_end_blocks.rb +2 -2
- data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +12 -3
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -3
- data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +1 -1
- data/lib/rubocop/cop/lint/number_conversion.rb +0 -1
- data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -2
- data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +93 -0
- data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +1 -2
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +3 -2
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +6 -11
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +13 -8
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +8 -7
- data/lib/rubocop/cop/lint/redundant_string_coercion.rb +2 -2
- data/lib/rubocop/cop/lint/redundant_type_conversion.rb +231 -0
- data/lib/rubocop/cop/lint/refinement_import_methods.rb +1 -1
- data/lib/rubocop/cop/lint/regexp_as_condition.rb +0 -1
- data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
- data/lib/rubocop/cop/lint/rescue_type.rb +3 -7
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +17 -1
- data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +109 -41
- data/lib/rubocop/cop/lint/self_assignment.rb +8 -10
- data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
- data/lib/rubocop/cop/lint/shared_mutable_default.rb +65 -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 +2 -2
- data/lib/rubocop/cop/lint/syntax.rb +4 -1
- data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +88 -0
- data/lib/rubocop/cop/lint/unexpected_block_arity.rb +1 -1
- data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -1
- data/lib/rubocop/cop/lint/unreachable_code.rb +51 -2
- data/lib/rubocop/cop/lint/unreachable_loop.rb +1 -1
- data/lib/rubocop/cop/lint/unused_method_argument.rb +18 -2
- data/lib/rubocop/cop/lint/uri_regexp.rb +25 -7
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +4 -4
- data/lib/rubocop/cop/lint/useless_assignment.rb +1 -1
- data/lib/rubocop/cop/lint/useless_constant_scoping.rb +80 -0
- data/lib/rubocop/cop/lint/useless_defined.rb +55 -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 +2 -1
- data/lib/rubocop/cop/lint/useless_rescue.rb +1 -1
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +2 -2
- data/lib/rubocop/cop/lint/useless_setter_call.rb +14 -25
- data/lib/rubocop/cop/lint/void.rb +8 -11
- 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 +5 -2
- data/lib/rubocop/cop/metrics/method_length.rb +8 -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/abc_size_calculator.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +2 -3
- data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +7 -7
- data/lib/rubocop/cop/mixin/alignment.rb +2 -2
- data/lib/rubocop/cop/mixin/allowed_pattern.rb +4 -4
- data/lib/rubocop/cop/mixin/check_assignment.rb +4 -12
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +20 -10
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +49 -0
- data/lib/rubocop/cop/mixin/comments_help.rb +8 -3
- data/lib/rubocop/cop/mixin/dig_help.rb +27 -0
- data/lib/rubocop/cop/mixin/endless_method_rewriter.rb +24 -0
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +4 -2
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +22 -22
- data/lib/rubocop/cop/mixin/hash_subset.rb +188 -0
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +74 -74
- data/lib/rubocop/cop/mixin/line_length_help.rb +5 -4
- data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +5 -9
- data/lib/rubocop/cop/mixin/percent_array.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 +3 -4
- data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
- data/lib/rubocop/cop/mixin/statement_modifier.rb +11 -5
- 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 +17 -1
- data/lib/rubocop/cop/mixin/trailing_comma.rb +3 -3
- data/lib/rubocop/cop/naming/accessor_method_name.rb +6 -6
- data/lib/rubocop/cop/naming/block_forwarding.rb +20 -16
- data/lib/rubocop/cop/naming/constant_name.rb +6 -7
- data/lib/rubocop/cop/naming/file_name.rb +0 -2
- data/lib/rubocop/cop/naming/inclusive_language.rb +12 -3
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +11 -12
- data/lib/rubocop/cop/naming/predicate_name.rb +45 -1
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +6 -14
- data/lib/rubocop/cop/naming/variable_name.rb +3 -4
- data/lib/rubocop/cop/naming/variable_number.rb +2 -3
- data/lib/rubocop/cop/offense.rb +4 -5
- data/lib/rubocop/cop/security/compound_hash.rb +2 -0
- data/lib/rubocop/cop/security/yaml_load.rb +3 -2
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +96 -28
- data/lib/rubocop/cop/style/accessor_grouping.rb +10 -2
- data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +79 -0
- data/lib/rubocop/cop/style/and_or.rb +1 -1
- data/lib/rubocop/cop/style/arguments_forwarding.rb +78 -22
- data/lib/rubocop/cop/style/array_first_last.rb +18 -2
- data/lib/rubocop/cop/style/array_intersect.rb +5 -4
- data/lib/rubocop/cop/style/bitwise_predicate.rb +100 -0
- data/lib/rubocop/cop/style/block_delimiters.rb +49 -19
- data/lib/rubocop/cop/style/case_like_if.rb +8 -11
- data/lib/rubocop/cop/style/class_and_module_children.rb +6 -3
- data/lib/rubocop/cop/style/collection_compact.rb +10 -10
- data/lib/rubocop/cop/style/collection_methods.rb +1 -1
- data/lib/rubocop/cop/style/combinable_defined.rb +115 -0
- data/lib/rubocop/cop/style/combinable_loops.rb +9 -2
- data/lib/rubocop/cop/style/commented_keyword.rb +17 -1
- data/lib/rubocop/cop/style/concat_array_literals.rb +1 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +26 -26
- data/lib/rubocop/cop/style/constant_visibility.rb +3 -12
- data/lib/rubocop/cop/style/data_inheritance.rb +1 -1
- data/lib/rubocop/cop/style/dig_chain.rb +89 -0
- data/lib/rubocop/cop/style/documentation.rb +1 -1
- data/lib/rubocop/cop/style/double_negation.rb +3 -3
- 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 +1 -1
- data/lib/rubocop/cop/style/empty_method.rb +1 -1
- data/lib/rubocop/cop/style/endless_method.rb +1 -14
- data/lib/rubocop/cop/style/eval_with_location.rb +2 -2
- data/lib/rubocop/cop/style/exact_regexp_match.rb +2 -3
- data/lib/rubocop/cop/style/explicit_block_argument.rb +15 -2
- data/lib/rubocop/cop/style/exponential_notation.rb +1 -1
- data/lib/rubocop/cop/style/fetch_env_var.rb +2 -1
- data/lib/rubocop/cop/style/file_null.rb +89 -0
- data/lib/rubocop/cop/style/file_touch.rb +75 -0
- data/lib/rubocop/cop/style/float_division.rb +8 -4
- data/lib/rubocop/cop/style/for.rb +0 -1
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
- data/lib/rubocop/cop/style/global_vars.rb +1 -3
- data/lib/rubocop/cop/style/guard_clause.rb +16 -3
- data/lib/rubocop/cop/style/hash_conversion.rb +1 -2
- data/lib/rubocop/cop/style/hash_each_methods.rb +9 -6
- data/lib/rubocop/cop/style/hash_except.rb +35 -147
- data/lib/rubocop/cop/style/hash_slice.rb +80 -0
- data/lib/rubocop/cop/style/hash_syntax.rb +8 -5
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +22 -3
- data/lib/rubocop/cop/style/if_inside_else.rb +1 -2
- data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -3
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +2 -3
- data/lib/rubocop/cop/style/if_with_semicolon.rb +26 -11
- data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
- data/lib/rubocop/cop/style/inverse_methods.rb +6 -7
- data/lib/rubocop/cop/style/it_assignment.rb +36 -0
- data/lib/rubocop/cop/style/keyword_arguments_merging.rb +67 -0
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +1 -1
- data/lib/rubocop/cop/style/lambda.rb +1 -1
- data/lib/rubocop/cop/style/lambda_call.rb +3 -2
- data/lib/rubocop/cop/style/map_into_array.rb +60 -9
- data/lib/rubocop/cop/style/map_to_hash.rb +1 -1
- data/lib/rubocop/cop/style/map_to_set.rb +3 -2
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +32 -20
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -0
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +8 -11
- data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +2 -4
- data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/missing_else.rb +2 -0
- data/lib/rubocop/cop/style/missing_respond_to_missing.rb +33 -3
- data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -1
- data/lib/rubocop/cop/style/multiline_memoization.rb +2 -2
- data/lib/rubocop/cop/style/multiple_comparison.rb +52 -51
- data/lib/rubocop/cop/style/mutable_constant.rb +7 -8
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +7 -5
- data/lib/rubocop/cop/style/nested_modifier.rb +1 -1
- data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +2 -2
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +5 -4
- data/lib/rubocop/cop/style/not.rb +1 -1
- data/lib/rubocop/cop/style/object_then.rb +14 -15
- data/lib/rubocop/cop/style/one_line_conditional.rb +29 -4
- data/lib/rubocop/cop/style/open_struct_use.rb +5 -5
- data/lib/rubocop/cop/style/operator_method_call.rb +25 -7
- data/lib/rubocop/cop/style/or_assignment.rb +3 -6
- data/lib/rubocop/cop/style/parallel_assignment.rb +9 -18
- 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/proc.rb +1 -2
- data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
- data/lib/rubocop/cop/style/raise_args.rb +7 -5
- 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_assignment.rb +1 -1
- data/lib/rubocop/cop/style/redundant_begin.rb +5 -1
- data/lib/rubocop/cop/style/redundant_condition.rb +39 -24
- data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +2 -1
- 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_format.rb +238 -0
- data/lib/rubocop/cop/style/redundant_freeze.rb +2 -2
- data/lib/rubocop/cop/style/redundant_initialize.rb +12 -3
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +56 -17
- data/lib/rubocop/cop/style/redundant_parentheses.rb +37 -25
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +4 -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_return.rb +2 -2
- data/lib/rubocop/cop/style/redundant_self.rb +8 -15
- data/lib/rubocop/cop/style/redundant_self_assignment.rb +20 -32
- data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +4 -4
- data/lib/rubocop/cop/style/redundant_sort.rb +3 -3
- data/lib/rubocop/cop/style/redundant_string_escape.rb +2 -2
- data/lib/rubocop/cop/style/require_order.rb +1 -1
- data/lib/rubocop/cop/style/rescue_modifier.rb +15 -4
- data/lib/rubocop/cop/style/return_nil.rb +1 -1
- data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +54 -12
- data/lib/rubocop/cop/style/safe_navigation.rb +105 -51
- data/lib/rubocop/cop/style/safe_navigation_chain_length.rb +52 -0
- data/lib/rubocop/cop/style/select_by_regexp.rb +10 -7
- data/lib/rubocop/cop/style/self_assignment.rb +11 -17
- data/lib/rubocop/cop/style/semicolon.rb +2 -2
- data/lib/rubocop/cop/style/send_with_literal_method_name.rb +2 -1
- data/lib/rubocop/cop/style/signal_exception.rb +2 -3
- data/lib/rubocop/cop/style/single_argument_dig.rb +9 -5
- data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
- data/lib/rubocop/cop/style/single_line_do_end_block.rb +12 -3
- data/lib/rubocop/cop/style/single_line_methods.rb +3 -4
- data/lib/rubocop/cop/style/slicing_with_range.rb +40 -11
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +4 -5
- data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
- data/lib/rubocop/cop/style/string_concatenation.rb +14 -13
- 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 +1 -1
- data/lib/rubocop/cop/style/super_arguments.rb +65 -17
- data/lib/rubocop/cop/style/swap_values.rb +4 -15
- data/lib/rubocop/cop/style/ternary_parentheses.rb +26 -5
- data/lib/rubocop/cop/style/top_level_method_definition.rb +1 -1
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -1
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +4 -4
- data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
- data/lib/rubocop/cop/style/variable_interpolation.rb +1 -2
- 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 +8 -1
- data/lib/rubocop/cop/util.rb +12 -5
- data/lib/rubocop/cop/utils/format_string.rb +7 -5
- data/lib/rubocop/cop/variable_force/assignment.rb +18 -3
- data/lib/rubocop/cop/variable_force/branch.rb +1 -1
- data/lib/rubocop/cop/variable_force/variable.rb +18 -2
- data/lib/rubocop/cop/variable_force/variable_table.rb +5 -5
- data/lib/rubocop/cop/variable_force.rb +4 -10
- data/lib/rubocop/cops_documentation_generator.rb +100 -51
- data/lib/rubocop/directive_comment.rb +44 -10
- data/lib/rubocop/file_finder.rb +9 -4
- data/lib/rubocop/formatter/disabled_config_formatter.rb +1 -1
- data/lib/rubocop/formatter/formatter_set.rb +1 -1
- data/lib/rubocop/lsp/diagnostic.rb +189 -0
- data/lib/rubocop/lsp/logger.rb +2 -2
- data/lib/rubocop/lsp/routes.rb +7 -23
- data/lib/rubocop/lsp/runtime.rb +18 -48
- data/lib/rubocop/lsp/server.rb +0 -3
- data/lib/rubocop/lsp/stdin_runner.rb +83 -0
- data/lib/rubocop/magic_comment.rb +3 -3
- data/lib/rubocop/options.rb +28 -12
- data/lib/rubocop/path_util.rb +15 -8
- 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 +39 -0
- data/lib/rubocop/rake_task.rb +4 -1
- data/lib/rubocop/result_cache.rb +13 -13
- data/lib/rubocop/rspec/cop_helper.rb +9 -0
- data/lib/rubocop/rspec/expect_offense.rb +7 -2
- data/lib/rubocop/rspec/shared_contexts.rb +4 -1
- data/lib/rubocop/rspec/support.rb +1 -2
- data/lib/rubocop/runner.rb +22 -12
- data/lib/rubocop/server/cache.rb +39 -1
- data/lib/rubocop/server/cli.rb +2 -2
- data/lib/rubocop/server/core.rb +1 -0
- data/lib/rubocop/target_finder.rb +1 -0
- data/lib/rubocop/target_ruby.rb +28 -13
- data/lib/rubocop/version.rb +42 -6
- data/lib/rubocop/yaml_duplication_checker.rb +20 -27
- data/lib/rubocop.rb +29 -0
- data/lib/ruby_lsp/rubocop/addon.rb +75 -0
- data/lib/ruby_lsp/rubocop/runtime_adapter.rb +47 -0
- metadata +75 -19
- data/lib/rubocop/rspec/host_environment_simulation_helper.rb +0 -28
@@ -0,0 +1,238 @@
|
|
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 argument is redundant, as it can be
|
9
|
+
# replaced by the string 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('%s %s', 'foo', 'bar')
|
42
|
+
# sprintf('%s %s', 'foo', 'bar')
|
43
|
+
#
|
44
|
+
# # good
|
45
|
+
# 'foo bar'
|
46
|
+
#
|
47
|
+
class RedundantFormat < Base
|
48
|
+
extend AutoCorrector
|
49
|
+
|
50
|
+
MSG = 'Redundant `%<method_name>s` can be removed.'
|
51
|
+
|
52
|
+
RESTRICT_ON_SEND = %i[format sprintf].to_set.freeze
|
53
|
+
ACCEPTABLE_LITERAL_TYPES = %i[str dstr sym dsym numeric boolean nil].freeze
|
54
|
+
|
55
|
+
# @!method format_without_additional_args?(node)
|
56
|
+
def_node_matcher :format_without_additional_args?, <<~PATTERN
|
57
|
+
(send {(const {nil? cbase} :Kernel) nil?} %RESTRICT_ON_SEND ${str dstr})
|
58
|
+
PATTERN
|
59
|
+
|
60
|
+
# @!method rational_number?(node)
|
61
|
+
def_node_matcher :rational_number?, <<~PATTERN
|
62
|
+
{rational (send int :/ rational) (begin rational) (begin (send int :/ rational))}
|
63
|
+
PATTERN
|
64
|
+
|
65
|
+
# @!method complex_number?(node)
|
66
|
+
def_node_matcher :complex_number?, <<~PATTERN
|
67
|
+
{complex (send int :+ complex) (begin complex) (begin (send int :+ complex))}
|
68
|
+
PATTERN
|
69
|
+
|
70
|
+
# @!method find_hash_value_node(node, name)
|
71
|
+
def_node_search :find_hash_value_node, <<~PATTERN
|
72
|
+
(pair (sym %1) $_)
|
73
|
+
PATTERN
|
74
|
+
|
75
|
+
def on_send(node)
|
76
|
+
format_without_additional_args?(node) do |value|
|
77
|
+
add_offense(node, message: message(node)) do |corrector|
|
78
|
+
corrector.replace(node, value.source)
|
79
|
+
end
|
80
|
+
return
|
81
|
+
end
|
82
|
+
|
83
|
+
detect_unnecessary_fields(node)
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
def message(node)
|
89
|
+
format(MSG, method_name: node.method_name)
|
90
|
+
end
|
91
|
+
|
92
|
+
def detect_unnecessary_fields(node)
|
93
|
+
return unless node.first_argument&.str_type?
|
94
|
+
|
95
|
+
string = node.first_argument.value
|
96
|
+
arguments = node.arguments[1..]
|
97
|
+
|
98
|
+
return unless string && arguments.any?
|
99
|
+
return if arguments.any?(&:splat_type?)
|
100
|
+
|
101
|
+
register_all_fields_literal(node, string, arguments)
|
102
|
+
end
|
103
|
+
|
104
|
+
def register_all_fields_literal(node, string, arguments)
|
105
|
+
return unless all_fields_literal?(string, arguments.dup)
|
106
|
+
|
107
|
+
add_offense(node, message: message(node)) do |corrector|
|
108
|
+
replacement = format(string, *argument_values(arguments))
|
109
|
+
corrector.replace(node, quote(replacement, node))
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def all_fields_literal?(string, arguments)
|
114
|
+
count = 0
|
115
|
+
sequences = RuboCop::Cop::Utils::FormatString.new(string).format_sequences
|
116
|
+
return false unless sequences.any?
|
117
|
+
|
118
|
+
sequences.each do |sequence|
|
119
|
+
next if sequence.percent?
|
120
|
+
|
121
|
+
hash = arguments.detect(&:hash_type?)
|
122
|
+
argument = find_argument(sequence, arguments, hash)
|
123
|
+
next unless matching_argument?(sequence, argument)
|
124
|
+
|
125
|
+
count += 1
|
126
|
+
end
|
127
|
+
|
128
|
+
sequences.size == count
|
129
|
+
end
|
130
|
+
|
131
|
+
def find_argument(sequence, arguments, hash)
|
132
|
+
if hash && (sequence.annotated? || sequence.template?)
|
133
|
+
find_hash_value_node(hash, sequence.name.to_sym).first
|
134
|
+
elsif sequence.arg_number
|
135
|
+
arguments[sequence.arg_number.to_i - 1]
|
136
|
+
else
|
137
|
+
# If the specifier contains `*`, the following arguments will be used
|
138
|
+
# to specify the width and can be ignored.
|
139
|
+
(sequence.arity - 1).times { arguments.shift }
|
140
|
+
arguments.shift
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def matching_argument?(sequence, argument)
|
145
|
+
# Template specifiers don't give a type, any acceptable literal type is ok.
|
146
|
+
return argument.type?(*ACCEPTABLE_LITERAL_TYPES) if sequence.template?
|
147
|
+
|
148
|
+
# An argument matches a specifier if it can be easily converted
|
149
|
+
# to that type.
|
150
|
+
case sequence.type
|
151
|
+
when 's'
|
152
|
+
argument.type?(*ACCEPTABLE_LITERAL_TYPES)
|
153
|
+
when 'd', 'i', 'u'
|
154
|
+
integer?(argument)
|
155
|
+
when 'f'
|
156
|
+
float?(argument)
|
157
|
+
else
|
158
|
+
false
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def numeric?(argument)
|
163
|
+
argument&.type?(:numeric, :str) ||
|
164
|
+
rational_number?(argument) ||
|
165
|
+
complex_number?(argument)
|
166
|
+
end
|
167
|
+
|
168
|
+
def integer?(argument)
|
169
|
+
numeric?(argument) && Integer(argument_value(argument), exception: false)
|
170
|
+
end
|
171
|
+
|
172
|
+
def float?(argument)
|
173
|
+
numeric?(argument) && Float(argument_value(argument), exception: false)
|
174
|
+
end
|
175
|
+
|
176
|
+
# Add correct quotes to the formatted string, preferring retaining the existing
|
177
|
+
# quotes if possible.
|
178
|
+
def quote(string, node)
|
179
|
+
str_node = node.first_argument
|
180
|
+
start_delimiter = str_node.loc.begin.source
|
181
|
+
end_delimiter = str_node.loc.end.source
|
182
|
+
|
183
|
+
# If there is any interpolation, the delimiters need to be changed potentially
|
184
|
+
if node.each_descendant(:dstr, :dsym).any?
|
185
|
+
case start_delimiter
|
186
|
+
when "'"
|
187
|
+
start_delimiter = end_delimiter = '"'
|
188
|
+
when /\A%q(.)/
|
189
|
+
start_delimiter = "%Q#{Regexp.last_match[1]}"
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
"#{start_delimiter}#{string}#{end_delimiter}"
|
194
|
+
end
|
195
|
+
|
196
|
+
def argument_values(arguments)
|
197
|
+
arguments.map { |argument| argument_value(argument) }
|
198
|
+
end
|
199
|
+
|
200
|
+
def argument_value(argument)
|
201
|
+
argument = argument.children.first if argument.begin_type?
|
202
|
+
|
203
|
+
if argument.dsym_type?
|
204
|
+
dsym_value(argument)
|
205
|
+
elsif argument.hash_type?
|
206
|
+
hash_value(argument)
|
207
|
+
elsif rational_number?(argument)
|
208
|
+
rational_value(argument)
|
209
|
+
elsif complex_number?(argument)
|
210
|
+
complex_value(argument)
|
211
|
+
elsif argument.respond_to?(:value)
|
212
|
+
argument.value
|
213
|
+
else
|
214
|
+
argument.source
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
def dsym_value(dsym_node)
|
219
|
+
dsym_node.children.first.source
|
220
|
+
end
|
221
|
+
|
222
|
+
def hash_value(hash_node)
|
223
|
+
hash_node.each_pair.with_object({}) do |pair, hash|
|
224
|
+
hash[pair.key.value] = argument_value(pair.value)
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
def rational_value(rational_node)
|
229
|
+
rational_node.source.to_r
|
230
|
+
end
|
231
|
+
|
232
|
+
def complex_value(complex_node)
|
233
|
+
Complex(complex_node.source)
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
@@ -5,7 +5,7 @@ module RuboCop
|
|
5
5
|
module Style
|
6
6
|
# Check 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)
|
@@ -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
|
|
@@ -69,17 +69,24 @@ module RuboCop
|
|
69
69
|
extend AutoCorrector
|
70
70
|
|
71
71
|
MSG = 'Redundant line continuation.'
|
72
|
+
LINE_CONTINUATION = '\\'
|
73
|
+
LINE_CONTINUATION_PATTERN = /(\\\n)/.freeze
|
72
74
|
ALLOWED_STRING_TOKENS = %i[tSTRING tSTRING_CONTENT].freeze
|
73
75
|
ARGUMENT_TYPES = %i[
|
74
|
-
kFALSE kNIL kSELF kTRUE
|
75
|
-
|
76
|
+
kDEF kDEFINED kFALSE kNIL kSELF kTRUE tAMPER tBANG tCARET tCHARACTER tCOLON3 tCONSTANT
|
77
|
+
tCVAR tDOT2 tDOT3 tFLOAT tGVAR tIDENTIFIER tINTEGER tIVAR tLAMBDA tLBRACK tLCURLY
|
78
|
+
tLPAREN_ARG tPIPE tQSYMBOLS_BEG tQWORDS_BEG tREGEXP_BEG tSTAR tSTRING tSTRING_BEG tSYMBEG
|
79
|
+
tSYMBOL tSYMBOLS_BEG tTILDE tUMINUS tUNARY_NUM tUPLUS tWORDS_BEG tXSTRING_BEG
|
76
80
|
].freeze
|
77
|
-
ARGUMENT_TAKING_FLOW_TOKEN_TYPES = %i[
|
81
|
+
ARGUMENT_TAKING_FLOW_TOKEN_TYPES = %i[
|
82
|
+
tIDENTIFIER kBREAK kNEXT kRETURN kSUPER kYIELD
|
83
|
+
].freeze
|
84
|
+
ARITHMETIC_OPERATOR_TOKENS = %i[tDIVIDE tDSTAR tMINUS tPERCENT tPLUS tSTAR2].freeze
|
78
85
|
|
79
86
|
def on_new_investigation
|
80
87
|
return unless processed_source.ast
|
81
88
|
|
82
|
-
each_match_range(processed_source.ast.source_range,
|
89
|
+
each_match_range(processed_source.ast.source_range, LINE_CONTINUATION_PATTERN) do |range|
|
83
90
|
next if require_line_continuation?(range)
|
84
91
|
next unless redundant_line_continuation?(range)
|
85
92
|
|
@@ -87,20 +94,27 @@ module RuboCop
|
|
87
94
|
corrector.remove_leading(range, 1)
|
88
95
|
end
|
89
96
|
end
|
97
|
+
|
98
|
+
inspect_end_of_ruby_code_line_continuation
|
90
99
|
end
|
91
100
|
|
92
101
|
private
|
93
102
|
|
94
103
|
def require_line_continuation?(range)
|
95
|
-
!
|
104
|
+
!ends_with_uncommented_backslash?(range) ||
|
96
105
|
string_concatenation?(range.source_line) ||
|
97
|
-
start_with_arithmetic_operator?(
|
106
|
+
start_with_arithmetic_operator?(range) ||
|
98
107
|
inside_string_literal_or_method_with_argument?(range) ||
|
99
108
|
leading_dot_method_chain_with_blank_line?(range)
|
100
109
|
end
|
101
110
|
|
102
|
-
def
|
103
|
-
|
111
|
+
def ends_with_uncommented_backslash?(range)
|
112
|
+
# A line continuation always needs to be the last character on the line, which
|
113
|
+
# means that it is impossible to have a comment following a continuation.
|
114
|
+
# Therefore, if the line contains a comment, it cannot end with a continuation.
|
115
|
+
return false if processed_source.line_with_comment?(range.line)
|
116
|
+
|
117
|
+
range.source_line.end_with?(LINE_CONTINUATION)
|
104
118
|
end
|
105
119
|
|
106
120
|
def string_concatenation?(source_line)
|
@@ -108,10 +122,13 @@ module RuboCop
|
|
108
122
|
end
|
109
123
|
|
110
124
|
def inside_string_literal_or_method_with_argument?(range)
|
125
|
+
line_range = range_by_whole_lines(range)
|
126
|
+
|
111
127
|
processed_source.tokens.each_cons(2).any? do |token, next_token|
|
112
128
|
next if token.line == next_token.line
|
113
129
|
|
114
|
-
inside_string_literal?(range, token) ||
|
130
|
+
inside_string_literal?(range, token) ||
|
131
|
+
method_with_argument?(line_range, token, next_token)
|
115
132
|
end
|
116
133
|
end
|
117
134
|
|
@@ -122,11 +139,31 @@ module RuboCop
|
|
122
139
|
end
|
123
140
|
|
124
141
|
def redundant_line_continuation?(range)
|
125
|
-
return true unless (node = find_node_for_line(range.
|
142
|
+
return true unless (node = find_node_for_line(range.last_line))
|
126
143
|
return false if argument_newline?(node)
|
127
144
|
|
128
|
-
source
|
129
|
-
|
145
|
+
# Check if source is still valid without the continuation
|
146
|
+
source = processed_source.raw_source.dup
|
147
|
+
source[range.begin_pos, range.length] = "\n"
|
148
|
+
parse(source).valid_syntax?
|
149
|
+
end
|
150
|
+
|
151
|
+
def inspect_end_of_ruby_code_line_continuation
|
152
|
+
last_line = processed_source.lines[processed_source.ast.last_line - 1]
|
153
|
+
return unless code_ends_with_continuation?(last_line)
|
154
|
+
|
155
|
+
last_column = last_line.length
|
156
|
+
line_continuation_range = range_between(last_column - 1, last_column)
|
157
|
+
|
158
|
+
add_offense(line_continuation_range) do |corrector|
|
159
|
+
corrector.remove_trailing(line_continuation_range, 1)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def code_ends_with_continuation?(last_line)
|
164
|
+
return false if processed_source.line_with_comment?(processed_source.ast.last_line)
|
165
|
+
|
166
|
+
last_line.end_with?(LINE_CONTINUATION)
|
130
167
|
end
|
131
168
|
|
132
169
|
def inside_string_literal?(range, token)
|
@@ -137,8 +174,9 @@ module RuboCop
|
|
137
174
|
#
|
138
175
|
# do_something \
|
139
176
|
# argument
|
140
|
-
def method_with_argument?(current_token, next_token)
|
177
|
+
def method_with_argument?(line_range, current_token, next_token)
|
141
178
|
return false unless ARGUMENT_TAKING_FLOW_TOKEN_TYPES.include?(current_token.type)
|
179
|
+
return false unless current_token.pos.overlaps?(line_range)
|
142
180
|
|
143
181
|
ARGUMENT_TYPES.include?(next_token.type)
|
144
182
|
end
|
@@ -160,9 +198,9 @@ module RuboCop
|
|
160
198
|
end
|
161
199
|
# rubocop:enable Metrics/AbcSize
|
162
200
|
|
163
|
-
def find_node_for_line(
|
201
|
+
def find_node_for_line(last_line)
|
164
202
|
processed_source.ast.each_node do |node|
|
165
|
-
return node if same_line?(node,
|
203
|
+
return node if same_line?(node, last_line)
|
166
204
|
end
|
167
205
|
end
|
168
206
|
|
@@ -191,8 +229,9 @@ module RuboCop
|
|
191
229
|
node.call_type? && !node.arguments.empty?
|
192
230
|
end
|
193
231
|
|
194
|
-
def start_with_arithmetic_operator?(
|
195
|
-
|
232
|
+
def start_with_arithmetic_operator?(range)
|
233
|
+
line_range = processed_source.buffer.line_range(range.line + 1)
|
234
|
+
ARITHMETIC_OPERATOR_TOKENS.include?(processed_source.first_token_of(line_range).type)
|
196
235
|
end
|
197
236
|
end
|
198
237
|
end
|
@@ -13,14 +13,16 @@ module RuboCop
|
|
13
13
|
# # good
|
14
14
|
# x if y.z.nil?
|
15
15
|
#
|
16
|
-
class RedundantParentheses < Base
|
16
|
+
class RedundantParentheses < Base # rubocop:disable Metrics/ClassLength
|
17
17
|
include Parentheses
|
18
18
|
extend AutoCorrector
|
19
19
|
|
20
20
|
ALLOWED_NODE_TYPES = %i[and or send splat kwsplat].freeze
|
21
21
|
|
22
22
|
# @!method square_brackets?(node)
|
23
|
-
def_node_matcher :square_brackets?,
|
23
|
+
def_node_matcher :square_brackets?, <<~PATTERN
|
24
|
+
(send `{(send _recv _msg) str array hash const #variable?} :[] ...)
|
25
|
+
PATTERN
|
24
26
|
|
25
27
|
# @!method method_node_and_args(node)
|
26
28
|
def_node_matcher :method_node_and_args, '$(call _recv _msg $...)'
|
@@ -31,9 +33,6 @@ module RuboCop
|
|
31
33
|
# @!method allowed_pin_operator?(node)
|
32
34
|
def_node_matcher :allowed_pin_operator?, '^(pin (begin !{lvar ivar cvar gvar}))'
|
33
35
|
|
34
|
-
# @!method arg_in_call_with_block?(node)
|
35
|
-
def_node_matcher :arg_in_call_with_block?, '^^(block (send _ _ equal?(%0) ...) ...)'
|
36
|
-
|
37
36
|
def on_begin(node)
|
38
37
|
return if !parentheses?(node) || parens_allowed?(node) || ignore_syntax?(node)
|
39
38
|
|
@@ -42,6 +41,10 @@ module RuboCop
|
|
42
41
|
|
43
42
|
private
|
44
43
|
|
44
|
+
def variable?(node)
|
45
|
+
node.respond_to?(:variable?) && node.variable?
|
46
|
+
end
|
47
|
+
|
45
48
|
def parens_allowed?(node)
|
46
49
|
empty_parentheses?(node) ||
|
47
50
|
first_arg_begins_with_hash_literal?(node) ||
|
@@ -53,13 +56,12 @@ module RuboCop
|
|
53
56
|
def ignore_syntax?(node)
|
54
57
|
return false unless (parent = node.parent)
|
55
58
|
|
56
|
-
parent.
|
59
|
+
parent.type?(:while_post, :until_post, :match_with_lvasgn) ||
|
57
60
|
like_method_argument_parentheses?(parent) || multiline_control_flow_statements?(node)
|
58
61
|
end
|
59
62
|
|
60
63
|
def allowed_expression?(node)
|
61
64
|
allowed_ancestor?(node) ||
|
62
|
-
allowed_method_call?(node) ||
|
63
65
|
allowed_multiple_expression?(node) ||
|
64
66
|
allowed_ternary?(node) ||
|
65
67
|
node.parent&.range_type?
|
@@ -70,18 +72,13 @@ module RuboCop
|
|
70
72
|
keyword_ancestor?(node) && parens_required?(node)
|
71
73
|
end
|
72
74
|
|
73
|
-
def allowed_method_call?(node)
|
74
|
-
# Don't flag `method (arg) { }`
|
75
|
-
arg_in_call_with_block?(node) && !parentheses?(node.parent)
|
76
|
-
end
|
77
|
-
|
78
75
|
def allowed_multiple_expression?(node)
|
79
76
|
return false if node.children.one?
|
80
77
|
|
81
78
|
ancestor = node.ancestors.first
|
82
79
|
return false unless ancestor
|
83
80
|
|
84
|
-
!ancestor.
|
81
|
+
!ancestor.type?(:begin, :def, :any_block)
|
85
82
|
end
|
86
83
|
|
87
84
|
def allowed_ternary?(node)
|
@@ -98,7 +95,7 @@ module RuboCop
|
|
98
95
|
end
|
99
96
|
|
100
97
|
def like_method_argument_parentheses?(node)
|
101
|
-
return false
|
98
|
+
return false unless node.type?(:send, :super, :yield)
|
102
99
|
|
103
100
|
node.arguments.one? && !node.parenthesized? &&
|
104
101
|
!node.arithmetic_operation? && node.first_argument.begin_type?
|
@@ -108,7 +105,7 @@ module RuboCop
|
|
108
105
|
return false unless (parent = node.parent)
|
109
106
|
return false if parent.single_line?
|
110
107
|
|
111
|
-
parent.
|
108
|
+
parent.type?(:return, :next, :break)
|
112
109
|
end
|
113
110
|
|
114
111
|
def empty_parentheses?(node)
|
@@ -137,6 +134,8 @@ module RuboCop
|
|
137
134
|
node = begin_node.children.first
|
138
135
|
|
139
136
|
if (message = find_offense_message(begin_node, node))
|
137
|
+
begin_node = begin_node.parent if node.range_type?
|
138
|
+
|
140
139
|
return offense(begin_node, message)
|
141
140
|
end
|
142
141
|
|
@@ -146,9 +145,12 @@ module RuboCop
|
|
146
145
|
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
147
146
|
def find_offense_message(begin_node, node)
|
148
147
|
return 'a keyword' if keyword_with_redundant_parentheses?(node)
|
149
|
-
return 'a literal' if disallowed_literal?(begin_node, node)
|
148
|
+
return 'a literal' if node.literal? && disallowed_literal?(begin_node, node)
|
150
149
|
return 'a variable' if node.variable?
|
151
150
|
return 'a constant' if node.const_type?
|
151
|
+
if node.assignment? && (begin_node.parent.nil? || begin_node.parent.begin_type?)
|
152
|
+
return 'an assignment'
|
153
|
+
end
|
152
154
|
if node.lambda_or_proc? && (node.braces? || node.send_node.lambda_literal?)
|
153
155
|
return 'an expression'
|
154
156
|
end
|
@@ -156,11 +158,11 @@ module RuboCop
|
|
156
158
|
|
157
159
|
return if begin_node.chained?
|
158
160
|
|
159
|
-
if node.
|
161
|
+
if node.operator_keyword?
|
160
162
|
return if node.semantic_operator? && begin_node.parent
|
161
163
|
return if node.multiline? && allow_in_multiline_conditions?
|
162
164
|
return if ALLOWED_NODE_TYPES.include?(begin_node.parent&.type)
|
163
|
-
return if begin_node.parent&.if_type? && begin_node.parent
|
165
|
+
return if begin_node.parent&.if_type? && begin_node.parent.ternary?
|
164
166
|
|
165
167
|
'a logical expression'
|
166
168
|
elsif node.respond_to?(:comparison_method?) && node.comparison_method?
|
@@ -175,17 +177,15 @@ module RuboCop
|
|
175
177
|
def_node_matcher :interpolation?, '[^begin ^^dstr]'
|
176
178
|
|
177
179
|
def allow_in_multiline_conditions?
|
178
|
-
|
179
|
-
return false unless parentheses_around_condition_config['Enabled']
|
180
|
-
|
181
|
-
!!parentheses_around_condition_config['AllowInMultilineConditions']
|
180
|
+
!!config.for_enabled_cop('Style/ParenthesesAroundCondition')['AllowInMultilineConditions']
|
182
181
|
end
|
183
182
|
|
184
183
|
def check_send(begin_node, node)
|
185
184
|
return check_unary(begin_node, node) if node.unary_operation?
|
186
185
|
|
187
186
|
return unless method_call_with_redundant_parentheses?(node)
|
188
|
-
return if call_chain_starts_with_int?(begin_node, node)
|
187
|
+
return if call_chain_starts_with_int?(begin_node, node) ||
|
188
|
+
do_end_block_in_method_chain?(begin_node, node)
|
189
189
|
|
190
190
|
offense(begin_node, 'a method call')
|
191
191
|
end
|
@@ -215,7 +215,13 @@ module RuboCop
|
|
215
215
|
end
|
216
216
|
|
217
217
|
def disallowed_literal?(begin_node, node)
|
218
|
-
|
218
|
+
if node.range_type?
|
219
|
+
return false unless (parent = begin_node.parent)
|
220
|
+
|
221
|
+
parent.begin_type? && parent.children.one?
|
222
|
+
else
|
223
|
+
!raised_to_power_negative_numeric?(begin_node, node)
|
224
|
+
end
|
219
225
|
end
|
220
226
|
|
221
227
|
def raised_to_power_negative_numeric?(begin_node, node)
|
@@ -252,7 +258,7 @@ module RuboCop
|
|
252
258
|
end
|
253
259
|
|
254
260
|
def only_begin_arg?(args)
|
255
|
-
args.one? && args.first
|
261
|
+
args.one? && args.first&.begin_type?
|
256
262
|
end
|
257
263
|
|
258
264
|
def first_argument?(node)
|
@@ -285,6 +291,12 @@ module RuboCop
|
|
285
291
|
recv&.int_type? && (parent = begin_node.parent) &&
|
286
292
|
parent.send_type? && (parent.method?(:-@) || parent.method?(:+@))
|
287
293
|
end
|
294
|
+
|
295
|
+
def do_end_block_in_method_chain?(begin_node, node)
|
296
|
+
return false unless (block = node.each_descendant(:any_block).first)
|
297
|
+
|
298
|
+
block.keywords? && begin_node.each_ancestor(:call).any?
|
299
|
+
end
|
288
300
|
end
|
289
301
|
end
|
290
302
|
end
|
@@ -70,6 +70,10 @@ module RuboCop
|
|
70
70
|
new_argument = replacement(regexp_node)
|
71
71
|
|
72
72
|
if new_argument.include?('"')
|
73
|
+
new_argument.gsub!("'", "\\\\'")
|
74
|
+
new_argument.gsub!('\"', '"')
|
75
|
+
quote = "'"
|
76
|
+
elsif new_argument.include?('\'')
|
73
77
|
new_argument.gsub!("'", "\\\\'")
|
74
78
|
quote = "'"
|
75
79
|
elsif new_argument.include?('\\')
|
@@ -61,9 +61,9 @@ module RuboCop
|
|
61
61
|
RESTRICT_ON_SEND = %i[define_method define_singleton_method lambda].freeze
|
62
62
|
|
63
63
|
def on_send(node)
|
64
|
-
return unless
|
64
|
+
return unless node.block_literal?
|
65
65
|
|
66
|
-
check_branch(parent.body)
|
66
|
+
check_branch(node.parent.body)
|
67
67
|
end
|
68
68
|
|
69
69
|
def on_def(node)
|