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
@@ -8,7 +8,7 @@ module RuboCop
|
|
8
8
|
#
|
9
9
|
# * `scientific` which enforces a mantissa between 1 (inclusive) and 10 (exclusive).
|
10
10
|
# * `engineering` which enforces the exponent to be a multiple of 3 and the mantissa
|
11
|
-
# to be between 0.1 (inclusive) and
|
11
|
+
# to be between 0.1 (inclusive) and 1000 (exclusive).
|
12
12
|
# * `integral` which enforces the mantissa to always be a whole number without
|
13
13
|
# trailing zeroes.
|
14
14
|
#
|
@@ -59,9 +59,10 @@ module RuboCop
|
|
59
59
|
#
|
60
60
|
class ExponentialNotation < Base
|
61
61
|
include ConfigurableEnforcedStyle
|
62
|
+
|
62
63
|
MESSAGES = {
|
63
|
-
scientific: 'Use a mantissa
|
64
|
-
engineering: 'Use an exponent divisible by 3 and a mantissa
|
64
|
+
scientific: 'Use a mantissa >= 1 and < 10.',
|
65
|
+
engineering: 'Use an exponent divisible by 3 and a mantissa >= 0.1 and < 1000.',
|
65
66
|
integral: 'Use an integer as mantissa, without trailing zero.'
|
66
67
|
}.freeze
|
67
68
|
|
@@ -87,7 +88,7 @@ module RuboCop
|
|
87
88
|
true
|
88
89
|
end
|
89
90
|
|
90
|
-
def integral(node)
|
91
|
+
def integral?(node)
|
91
92
|
mantissa, = node.source.split('e')
|
92
93
|
/^-?[1-9](\d*[1-9])?$/.match?(mantissa)
|
93
94
|
end
|
@@ -101,7 +102,7 @@ module RuboCop
|
|
101
102
|
when :engineering
|
102
103
|
!engineering?(node)
|
103
104
|
when :integral
|
104
|
-
!integral(node)
|
105
|
+
!integral?(node)
|
105
106
|
else
|
106
107
|
false
|
107
108
|
end
|
@@ -6,10 +6,23 @@ module RuboCop
|
|
6
6
|
# Suggests `ENV.fetch` for the replacement of `ENV[]`.
|
7
7
|
# `ENV[]` silently fails and returns `nil` when the environment variable is unset,
|
8
8
|
# which may cause unexpected behaviors when the developer forgets to set it.
|
9
|
-
# On the other hand, `ENV.fetch` raises KeyError or returns the explicitly
|
9
|
+
# On the other hand, `ENV.fetch` raises `KeyError` or returns the explicitly
|
10
10
|
# specified default value.
|
11
11
|
#
|
12
|
-
# @example
|
12
|
+
# @example DefaultToNil: true (default)
|
13
|
+
# # bad
|
14
|
+
# ENV['X']
|
15
|
+
# x = ENV['X']
|
16
|
+
#
|
17
|
+
# # good
|
18
|
+
# ENV.fetch('X', nil)
|
19
|
+
# x = ENV.fetch('X', nil)
|
20
|
+
#
|
21
|
+
# # also good
|
22
|
+
# !ENV['X']
|
23
|
+
# ENV['X'].some_method # (e.g. `.nil?`)
|
24
|
+
#
|
25
|
+
# @example DefaultToNil: false
|
13
26
|
# # bad
|
14
27
|
# ENV['X']
|
15
28
|
# x = ENV['X']
|
@@ -25,7 +38,9 @@ module RuboCop
|
|
25
38
|
class FetchEnvVar < Base
|
26
39
|
extend AutoCorrector
|
27
40
|
|
28
|
-
|
41
|
+
MSG_WITH_NIL = 'Use `ENV.fetch(%<key>s, nil)` instead of `ENV[%<key>s]`.'
|
42
|
+
MSG_WITHOUT_NIL = 'Use `ENV.fetch(%<key>s)` instead of `ENV[%<key>s]`.'
|
43
|
+
RESTRICT_ON_SEND = [:[]].freeze
|
29
44
|
|
30
45
|
# @!method env_with_bracket?(node)
|
31
46
|
def_node_matcher :env_with_bracket?, <<~PATTERN
|
@@ -36,7 +51,7 @@ module RuboCop
|
|
36
51
|
env_with_bracket?(node) do |name_node|
|
37
52
|
break unless offensive?(node)
|
38
53
|
|
39
|
-
message = format(
|
54
|
+
message = format(offense_message, key: name_node.source)
|
40
55
|
add_offense(node, message: message) do |corrector|
|
41
56
|
corrector.replace(node, new_code(name_node))
|
42
57
|
end
|
@@ -45,6 +60,14 @@ module RuboCop
|
|
45
60
|
|
46
61
|
private
|
47
62
|
|
63
|
+
def default_to_nil?
|
64
|
+
cop_config.fetch('DefaultToNil', true)
|
65
|
+
end
|
66
|
+
|
67
|
+
def offense_message
|
68
|
+
default_to_nil? ? MSG_WITH_NIL : MSG_WITHOUT_NIL
|
69
|
+
end
|
70
|
+
|
48
71
|
def allowed_var?(node)
|
49
72
|
env_key_node = node.children.last
|
50
73
|
env_key_node.str_type? && cop_config['AllowedVars'].include?(env_key_node.value)
|
@@ -52,12 +75,12 @@ module RuboCop
|
|
52
75
|
|
53
76
|
def used_as_flag?(node)
|
54
77
|
return false if node.root?
|
55
|
-
return true if used_if_condition_in_body(node)
|
78
|
+
return true if used_if_condition_in_body?(node)
|
56
79
|
|
57
80
|
node.parent.send_type? && (node.parent.prefix_bang? || node.parent.comparison_method?)
|
58
81
|
end
|
59
82
|
|
60
|
-
def used_if_condition_in_body(node)
|
83
|
+
def used_if_condition_in_body?(node)
|
61
84
|
if_node = node.ancestors.find(&:if_type?)
|
62
85
|
|
63
86
|
return false unless (condition = if_node&.condition)
|
@@ -124,7 +147,11 @@ module RuboCop
|
|
124
147
|
end
|
125
148
|
|
126
149
|
def new_code(name_node)
|
127
|
-
|
150
|
+
if default_to_nil?
|
151
|
+
"ENV.fetch(#{name_node.source}, nil)"
|
152
|
+
else
|
153
|
+
"ENV.fetch(#{name_node.source})"
|
154
|
+
end
|
128
155
|
end
|
129
156
|
end
|
130
157
|
end
|
@@ -8,6 +8,12 @@ module RuboCop
|
|
8
8
|
# Only looks for full string matches, substrings within a longer string are not
|
9
9
|
# considered.
|
10
10
|
#
|
11
|
+
# However, only files that use the string `'/dev/null'` are targeted for detection.
|
12
|
+
# This is because the string `'NUL'` is not limited to the null device.
|
13
|
+
# This behavior results in false negatives when the `'/dev/null'` string is not used,
|
14
|
+
# but it is a trade-off to avoid false positives. `NULL:`
|
15
|
+
# Unlike `'NUL'`, `'NUL:'` is regarded as something like `C:` and is always detected.
|
16
|
+
#
|
11
17
|
# NOTE: Uses inside arrays and hashes are ignored.
|
12
18
|
#
|
13
19
|
# @safety
|
@@ -42,11 +48,21 @@ module RuboCop
|
|
42
48
|
REGEXP = %r{\A(/dev/null|NUL:?)\z}i.freeze
|
43
49
|
MSG = 'Use `File::NULL` instead of `%<source>s`.'
|
44
50
|
|
51
|
+
def on_new_investigation
|
52
|
+
return unless (ast = processed_source.ast)
|
53
|
+
|
54
|
+
@contain_dev_null_string_in_file = ast.each_descendant(:str).any? do |str|
|
55
|
+
content = str.str_content
|
56
|
+
|
57
|
+
valid_string?(content) && content.downcase == '/dev/null' # rubocop:disable Style/FileNull
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
45
61
|
def on_str(node)
|
46
62
|
value = node.value
|
47
|
-
|
48
|
-
return if invalid_string?(value)
|
63
|
+
return unless valid_string?(value)
|
49
64
|
return if acceptable?(node)
|
65
|
+
return if value.downcase == 'nul' && !@contain_dev_null_string_in_file # rubocop:disable Style/FileNull
|
50
66
|
return unless REGEXP.match?(value)
|
51
67
|
|
52
68
|
add_offense(node, message: format(MSG, source: value)) do |corrector|
|
@@ -56,8 +72,8 @@ module RuboCop
|
|
56
72
|
|
57
73
|
private
|
58
74
|
|
59
|
-
def
|
60
|
-
value.empty?
|
75
|
+
def valid_string?(value)
|
76
|
+
!value.empty? && value.valid_encoding?
|
61
77
|
end
|
62
78
|
|
63
79
|
def acceptable?(node)
|
@@ -65,19 +65,23 @@ module RuboCop
|
|
65
65
|
|
66
66
|
# @!method right_coerce?(node)
|
67
67
|
def_node_matcher :right_coerce?, <<~PATTERN
|
68
|
-
(send _ :/
|
68
|
+
(send _ :/ #to_f_method?)
|
69
69
|
PATTERN
|
70
70
|
# @!method left_coerce?(node)
|
71
71
|
def_node_matcher :left_coerce?, <<~PATTERN
|
72
|
-
(send
|
72
|
+
(send #to_f_method? :/ _)
|
73
73
|
PATTERN
|
74
74
|
# @!method both_coerce?(node)
|
75
75
|
def_node_matcher :both_coerce?, <<~PATTERN
|
76
|
-
(send
|
76
|
+
(send #to_f_method? :/ #to_f_method?)
|
77
77
|
PATTERN
|
78
78
|
# @!method any_coerce?(node)
|
79
79
|
def_node_matcher :any_coerce?, <<~PATTERN
|
80
|
-
{(send _ :/
|
80
|
+
{(send _ :/ #to_f_method?) (send #to_f_method? :/ _)}
|
81
|
+
PATTERN
|
82
|
+
# @!method to_f_method?(node)
|
83
|
+
def_node_matcher :to_f_method?, <<~PATTERN
|
84
|
+
(send !nil? :to_f)
|
81
85
|
PATTERN
|
82
86
|
|
83
87
|
def on_send(node)
|
@@ -3,16 +3,24 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
# Use a consistent style for
|
6
|
+
# Use a consistent style for tokens within a format string.
|
7
7
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
# The reason is that _unannotated_ format is very similar
|
12
|
-
# to encoded URLs or Date/Time formatting strings.
|
8
|
+
# By default, all strings are evaluated. In some cases, this may be undesirable,
|
9
|
+
# as they could be used as arguments to a method that does not consider
|
10
|
+
# them to be tokens, but rather other identifiers or just part of the string.
|
13
11
|
#
|
14
|
-
#
|
15
|
-
#
|
12
|
+
# `AllowedMethods` or `AllowedPatterns` can be configured with in order to mark specific
|
13
|
+
# methods as always allowed, thereby avoiding an offense from the cop. By default, there
|
14
|
+
# are no allowed methods.
|
15
|
+
#
|
16
|
+
# Additionally, the cop can be made conservative by configuring it with
|
17
|
+
# `Mode: conservative` (default `aggressive`). In this mode, tokens (regardless
|
18
|
+
# of `EnforcedStyle`) are only considered if used in the format string argument to the
|
19
|
+
# methods `printf`, `sprintf`, `format` and `%`.
|
20
|
+
#
|
21
|
+
# NOTE: Tokens in the `unannotated` style (eg. `%s`) are always treated as if
|
22
|
+
# configured with `Conservative: true`. This is done in order to prevent false positives,
|
23
|
+
# because this format is very similar to encoded URLs or Date/Time formatting strings.
|
16
24
|
#
|
17
25
|
# @example EnforcedStyle: annotated (default)
|
18
26
|
#
|
@@ -82,6 +90,20 @@ module RuboCop
|
|
82
90
|
# # good
|
83
91
|
# redirect('foo/%{bar_id}')
|
84
92
|
#
|
93
|
+
# @example Mode: conservative, EnforcedStyle: annotated
|
94
|
+
# # In `conservative` mode, offenses are only registered for strings
|
95
|
+
# # given to a known formatting method.
|
96
|
+
#
|
97
|
+
# # good
|
98
|
+
# "%{greeting}"
|
99
|
+
# foo("%{greeting}")
|
100
|
+
#
|
101
|
+
# # bad
|
102
|
+
# format("%{greeting}", greeting: 'Hello')
|
103
|
+
# printf("%{greeting}", greeting: 'Hello')
|
104
|
+
# sprintf("%{greeting}", greeting: 'Hello')
|
105
|
+
# "%{greeting}" % { greeting: 'Hello' }
|
106
|
+
#
|
85
107
|
class FormatStringToken < Base
|
86
108
|
include ConfigurableEnforcedStyle
|
87
109
|
include AllowedMethods
|
@@ -153,8 +175,9 @@ module RuboCop
|
|
153
175
|
corrector.replace(token_range, correction)
|
154
176
|
end
|
155
177
|
|
156
|
-
def
|
157
|
-
detected_style == :unannotated
|
178
|
+
def allowed_string?(node, detected_style)
|
179
|
+
(detected_style == :unannotated || conservative?) &&
|
180
|
+
!format_string_in_typical_context?(node)
|
158
181
|
end
|
159
182
|
|
160
183
|
def message(detected_style)
|
@@ -203,7 +226,7 @@ module RuboCop
|
|
203
226
|
def collect_detections(node)
|
204
227
|
detections = []
|
205
228
|
tokens(node) do |detected_sequence, token_range|
|
206
|
-
unless
|
229
|
+
unless allowed_string?(node, detected_sequence.style)
|
207
230
|
detections << [detected_sequence, token_range]
|
208
231
|
end
|
209
232
|
end
|
@@ -222,6 +245,10 @@ module RuboCop
|
|
222
245
|
def max_unannotated_placeholders_allowed
|
223
246
|
cop_config['MaxUnannotatedPlaceholdersAllowed']
|
224
247
|
end
|
248
|
+
|
249
|
+
def conservative?
|
250
|
+
cop_config.fetch('Mode', :aggressive).to_sym == :conservative
|
251
|
+
end
|
225
252
|
end
|
226
253
|
end
|
227
254
|
end
|
@@ -151,7 +151,7 @@ module RuboCop
|
|
151
151
|
|
152
152
|
def frozen_string_literal_comment(processed_source)
|
153
153
|
processed_source.tokens.find do |token|
|
154
|
-
token.text.
|
154
|
+
MagicComment.parse(token.text).frozen_string_literal_specified?
|
155
155
|
end
|
156
156
|
end
|
157
157
|
|
@@ -189,8 +189,9 @@ module RuboCop
|
|
189
189
|
|
190
190
|
def enable_comment(corrector)
|
191
191
|
comment = frozen_string_literal_comment(processed_source)
|
192
|
+
replacement = MagicComment.parse(comment.text).new_frozen_string_literal(true)
|
192
193
|
|
193
|
-
corrector.replace(line_range(comment.line),
|
194
|
+
corrector.replace(line_range(comment.line), replacement)
|
194
195
|
end
|
195
196
|
|
196
197
|
def insert_comment(corrector)
|
@@ -8,6 +8,9 @@ module RuboCop
|
|
8
8
|
# reassign (possibly to redirect some stream) constants in Ruby, you'll get
|
9
9
|
# an interpreter warning if you do so.
|
10
10
|
#
|
11
|
+
# Additionally, `$stdout/$stderr/$stdin` can safely be accessed in a Ractor because they
|
12
|
+
# are ractor-local, while `STDOUT/STDERR/STDIN` will raise `Ractor::IsolationError`.
|
13
|
+
#
|
11
14
|
# @safety
|
12
15
|
# Autocorrection is unsafe because `STDOUT` and `$stdout` may point to different
|
13
16
|
# objects, for example.
|
@@ -135,6 +135,7 @@ module RuboCop
|
|
135
135
|
on_def(node)
|
136
136
|
end
|
137
137
|
alias on_numblock on_block
|
138
|
+
alias on_itblock on_block
|
138
139
|
|
139
140
|
def on_if(node)
|
140
141
|
return if accepted_form?(node)
|
@@ -213,7 +214,7 @@ module RuboCop
|
|
213
214
|
if_branch = node.if_branch
|
214
215
|
else_branch = node.else_branch
|
215
216
|
|
216
|
-
corrector.replace(node.loc.begin, "\n") if node.
|
217
|
+
corrector.replace(node.loc.begin, "\n") if node.then?
|
217
218
|
|
218
219
|
if if_branch&.send_type? && heredoc?(if_branch.last_argument)
|
219
220
|
autocorrect_heredoc_argument(corrector, node, if_branch, else_branch, guard)
|
@@ -44,17 +44,17 @@ module RuboCop
|
|
44
44
|
class HashConversion < Base
|
45
45
|
extend AutoCorrector
|
46
46
|
|
47
|
-
MSG_TO_H = 'Prefer ary.to_h to Hash[ary]
|
48
|
-
MSG_LITERAL_MULTI_ARG = 'Prefer literal hash to Hash[arg1, arg2, ...]
|
49
|
-
MSG_LITERAL_HASH_ARG = 'Prefer literal hash to Hash[key: value, ...]
|
50
|
-
MSG_SPLAT = 'Prefer array_of_pairs.to_h to Hash[*array]
|
47
|
+
MSG_TO_H = 'Prefer `ary.to_h` to `Hash[ary]`.'
|
48
|
+
MSG_LITERAL_MULTI_ARG = 'Prefer literal hash to `Hash[arg1, arg2, ...]`.'
|
49
|
+
MSG_LITERAL_HASH_ARG = 'Prefer literal hash to `Hash[key: value, ...]`.'
|
50
|
+
MSG_SPLAT = 'Prefer `array_of_pairs.to_h` to `Hash[*array]`.'
|
51
51
|
RESTRICT_ON_SEND = %i[[]].freeze
|
52
52
|
|
53
53
|
# @!method hash_from_array?(node)
|
54
54
|
def_node_matcher :hash_from_array?, '(send (const {nil? cbase} :Hash) :[] ...)'
|
55
55
|
|
56
56
|
def on_send(node)
|
57
|
-
return
|
57
|
+
return if part_of_ignored_node?(node) || !hash_from_array?(node)
|
58
58
|
|
59
59
|
# There are several cases:
|
60
60
|
# If there is one argument:
|
@@ -63,7 +63,8 @@ module RuboCop
|
|
63
63
|
# If there is 0 or 2+ arguments:
|
64
64
|
# Hash[a1, a2, a3, a4] => {a1 => a2, a3 => a4}
|
65
65
|
# ...but don't suggest correction if there is odd number of them (it is a bug)
|
66
|
-
node.arguments.
|
66
|
+
node.arguments.one? ? single_argument(node) : multi_argument(node)
|
67
|
+
ignore_node(node)
|
67
68
|
end
|
68
69
|
|
69
70
|
private
|
@@ -111,7 +112,12 @@ module RuboCop
|
|
111
112
|
end
|
112
113
|
|
113
114
|
def requires_parens?(node)
|
114
|
-
|
115
|
+
if node.call_type?
|
116
|
+
return false if node.method?(:[])
|
117
|
+
return true if node.arguments.any? && !node.parenthesized?
|
118
|
+
end
|
119
|
+
|
120
|
+
node.operator_keyword?
|
115
121
|
end
|
116
122
|
|
117
123
|
def multi_argument(node)
|
@@ -122,7 +128,9 @@ module RuboCop
|
|
122
128
|
corrector.replace(node, args_to_hash(node.arguments))
|
123
129
|
|
124
130
|
parent = node.parent
|
125
|
-
|
131
|
+
if parent&.send_type? && !parent.method?(:to_h) && !parent.parenthesized?
|
132
|
+
add_parentheses(parent, corrector)
|
133
|
+
end
|
126
134
|
end
|
127
135
|
end
|
128
136
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
# Checks for uses of `each_key` and `each_value` Hash methods.
|
6
|
+
# Checks for uses of `each_key` and `each_value` `Hash` methods.
|
7
7
|
#
|
8
8
|
# NOTE: If you have an array of two-element arrays, you can put
|
9
9
|
# parentheses around the block arguments to indicate that you're not
|
@@ -44,7 +44,7 @@ module RuboCop
|
|
44
44
|
|
45
45
|
# @!method kv_each(node)
|
46
46
|
def_node_matcher :kv_each, <<~PATTERN
|
47
|
-
(
|
47
|
+
(any_block $(call (call _ ${:keys :values}) :each) ...)
|
48
48
|
PATTERN
|
49
49
|
|
50
50
|
# @!method each_arguments(node)
|
@@ -74,6 +74,7 @@ module RuboCop
|
|
74
74
|
check_unused_block_args(node, key, value)
|
75
75
|
end
|
76
76
|
alias on_numblock on_block
|
77
|
+
alias on_itblock on_block
|
77
78
|
|
78
79
|
# rubocop:disable Metrics/AbcSize
|
79
80
|
def check_unused_block_args(node, key, value)
|
@@ -128,8 +129,8 @@ module RuboCop
|
|
128
129
|
lvar_sources = node.body.each_descendant(:lvar).map(&:source)
|
129
130
|
|
130
131
|
if block_arg.mlhs_type?
|
131
|
-
block_arg.each_descendant(:arg, :restarg).all? do |
|
132
|
-
lvar_sources.none?(
|
132
|
+
block_arg.each_descendant(:arg, :restarg).all? do |descendant|
|
133
|
+
lvar_sources.none?(descendant.source.delete_prefix('*'))
|
133
134
|
end
|
134
135
|
else
|
135
136
|
lvar_sources.none?(block_arg.source.delete_prefix('*'))
|
@@ -162,10 +163,7 @@ module RuboCop
|
|
162
163
|
|
163
164
|
def use_array_converter_method_as_preceding?(node)
|
164
165
|
return false unless (preceding_method = node.children.first.children.first)
|
165
|
-
unless preceding_method.
|
166
|
-
preceding_method.block_type? || preceding_method.numblock_type?
|
167
|
-
return false
|
168
|
-
end
|
166
|
+
return false unless preceding_method.type?(:call, :any_block)
|
169
167
|
|
170
168
|
ARRAY_CONVERTER_METHODS.include?(preceding_method.method_name)
|
171
169
|
end
|
@@ -10,8 +10,10 @@ module RuboCop
|
|
10
10
|
# (`Hash#except` was added in Ruby 3.0.)
|
11
11
|
#
|
12
12
|
# For safe detection, it is limited to commonly used string and symbol comparisons
|
13
|
-
# when
|
14
|
-
#
|
13
|
+
# when using `==` or `!=`.
|
14
|
+
#
|
15
|
+
# This cop doesn't check for `Hash#delete_if` and `Hash#keep_if` because they
|
16
|
+
# modify the receiver.
|
15
17
|
#
|
16
18
|
# @safety
|
17
19
|
# This cop is unsafe because it cannot be guaranteed that the receiver
|
@@ -23,6 +25,9 @@ module RuboCop
|
|
23
25
|
# {foo: 1, bar: 2, baz: 3}.reject {|k, v| k == :bar }
|
24
26
|
# {foo: 1, bar: 2, baz: 3}.select {|k, v| k != :bar }
|
25
27
|
# {foo: 1, bar: 2, baz: 3}.filter {|k, v| k != :bar }
|
28
|
+
# {foo: 1, bar: 2, baz: 3}.reject {|k, v| k.eql?(:bar) }
|
29
|
+
#
|
30
|
+
# # bad
|
26
31
|
# {foo: 1, bar: 2, baz: 3}.reject {|k, v| %i[bar].include?(k) }
|
27
32
|
# {foo: 1, bar: 2, baz: 3}.select {|k, v| !%i[bar].include?(k) }
|
28
33
|
# {foo: 1, bar: 2, baz: 3}.filter {|k, v| !%i[bar].include?(k) }
|
@@ -30,161 +35,44 @@ module RuboCop
|
|
30
35
|
# # good
|
31
36
|
# {foo: 1, bar: 2, baz: 3}.except(:bar)
|
32
37
|
#
|
38
|
+
# @example AllCops:ActiveSupportExtensionsEnabled: false (default)
|
39
|
+
#
|
40
|
+
# # good
|
41
|
+
# {foo: 1, bar: 2, baz: 3}.reject {|k, v| !%i[bar].exclude?(k) }
|
42
|
+
# {foo: 1, bar: 2, baz: 3}.select {|k, v| %i[bar].exclude?(k) }
|
43
|
+
#
|
44
|
+
# # good
|
45
|
+
# {foo: 1, bar: 2, baz: 3}.reject {|k, v| k.in?(%i[bar]) }
|
46
|
+
# {foo: 1, bar: 2, baz: 3}.select {|k, v| !k.in?(%i[bar]) }
|
47
|
+
#
|
48
|
+
# @example AllCops:ActiveSupportExtensionsEnabled: true
|
49
|
+
#
|
50
|
+
# # bad
|
51
|
+
# {foo: 1, bar: 2, baz: 3}.reject {|k, v| !%i[bar].exclude?(k) }
|
52
|
+
# {foo: 1, bar: 2, baz: 3}.select {|k, v| %i[bar].exclude?(k) }
|
53
|
+
#
|
54
|
+
# # bad
|
55
|
+
# {foo: 1, bar: 2, baz: 3}.reject {|k, v| k.in?(%i[bar]) }
|
56
|
+
# {foo: 1, bar: 2, baz: 3}.select {|k, v| !k.in?(%i[bar]) }
|
57
|
+
#
|
58
|
+
# # good
|
59
|
+
# {foo: 1, bar: 2, baz: 3}.except(:bar)
|
60
|
+
#
|
33
61
|
class HashExcept < Base
|
34
|
-
include
|
62
|
+
include HashSubset
|
35
63
|
extend TargetRubyVersion
|
36
64
|
extend AutoCorrector
|
37
65
|
|
38
66
|
minimum_target_ruby_version 3.0
|
39
67
|
|
40
|
-
MSG = 'Use `%<prefer>s` instead.'
|
41
|
-
RESTRICT_ON_SEND = %i[reject select filter].freeze
|
42
|
-
|
43
|
-
# @!method bad_method_with_poro?(node)
|
44
|
-
def_node_matcher :bad_method_with_poro?, <<~PATTERN
|
45
|
-
(block
|
46
|
-
(call _ _)
|
47
|
-
(args
|
48
|
-
$(arg _)
|
49
|
-
(arg _))
|
50
|
-
{
|
51
|
-
$(send
|
52
|
-
_ {:== :!= :eql? :include?} _)
|
53
|
-
(send
|
54
|
-
$(send
|
55
|
-
_ {:== :!= :eql? :include?} _) :!)
|
56
|
-
})
|
57
|
-
PATTERN
|
58
|
-
|
59
|
-
# @!method bad_method_with_active_support?(node)
|
60
|
-
def_node_matcher :bad_method_with_active_support?, <<~PATTERN
|
61
|
-
(block
|
62
|
-
(send _ _)
|
63
|
-
(args
|
64
|
-
$(arg _)
|
65
|
-
(arg _))
|
66
|
-
{
|
67
|
-
$(send
|
68
|
-
_ {:== :!= :eql? :in? :include? :exclude?} _)
|
69
|
-
(send
|
70
|
-
$(send
|
71
|
-
_ {:== :!= :eql? :in? :include? :exclude?} _) :!)
|
72
|
-
})
|
73
|
-
PATTERN
|
74
|
-
|
75
|
-
def on_send(node)
|
76
|
-
method_name = node.method_name
|
77
|
-
block = node.parent
|
78
|
-
return unless bad_method?(method_name, block) && semantically_except_method?(node, block)
|
79
|
-
|
80
|
-
except_key = except_key(block)
|
81
|
-
return if except_key.nil? || !safe_to_register_offense?(block, except_key)
|
82
|
-
|
83
|
-
range = offense_range(node)
|
84
|
-
preferred_method = "except(#{except_key_source(except_key)})"
|
85
|
-
|
86
|
-
add_offense(range, message: format(MSG, prefer: preferred_method)) do |corrector|
|
87
|
-
corrector.replace(range, preferred_method)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
alias on_csend on_send
|
91
|
-
|
92
68
|
private
|
93
69
|
|
94
|
-
|
95
|
-
|
96
|
-
if active_support_extensions_enabled?
|
97
|
-
bad_method_with_active_support?(block) do |key_arg, send_node|
|
98
|
-
if send_node.method?(:in?) && send_node.receiver&.source != key_arg.source
|
99
|
-
return false
|
100
|
-
end
|
101
|
-
return true if !send_node.method?(:include?) && !send_node.method?(:exclude?)
|
102
|
-
|
103
|
-
send_node.first_argument&.source == key_arg.source
|
104
|
-
end
|
105
|
-
else
|
106
|
-
bad_method_with_poro?(block) do |key_arg, send_node|
|
107
|
-
return false if method_name == :reject && block.body.method?(:!)
|
108
|
-
|
109
|
-
!send_node.method?(:include?) || send_node.first_argument&.source == key_arg.source
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
|
-
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
114
|
-
|
115
|
-
def semantically_except_method?(send, block)
|
116
|
-
body = block.body
|
117
|
-
|
118
|
-
negated = body.method?('!')
|
119
|
-
body = body.receiver if negated
|
120
|
-
|
121
|
-
case send.method_name
|
122
|
-
when :reject
|
123
|
-
body.method?('==') || body.method?('eql?') || included?(negated, body)
|
124
|
-
when :select, :filter
|
125
|
-
body.method?('!=') || not_included?(negated, body)
|
126
|
-
else
|
127
|
-
false
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
def included?(negated, body)
|
132
|
-
body.method?('include?') || body.method?('in?') || (negated && body.method?('exclude?'))
|
133
|
-
end
|
134
|
-
|
135
|
-
def not_included?(negated, body)
|
136
|
-
body.method?('exclude?') || (negated && (body.method?('include?') || body.method?('in?')))
|
137
|
-
end
|
138
|
-
|
139
|
-
def safe_to_register_offense?(block, except_key)
|
140
|
-
extracted = extract_body_if_negated(block.body)
|
141
|
-
if extracted.method?('in?') || extracted.method?('include?') ||
|
142
|
-
extracted.method?('exclude?')
|
143
|
-
return true
|
144
|
-
end
|
145
|
-
return true if block.body.method?('eql?')
|
146
|
-
|
147
|
-
except_key.sym_type? || except_key.str_type?
|
148
|
-
end
|
149
|
-
|
150
|
-
def extract_body_if_negated(body)
|
151
|
-
return body unless body.method?('!')
|
152
|
-
|
153
|
-
body.receiver
|
154
|
-
end
|
155
|
-
|
156
|
-
def except_key_source(key)
|
157
|
-
if key.array_type?
|
158
|
-
key = if key.percent_literal?
|
159
|
-
key.each_value.map { |v| decorate_source(v) }
|
160
|
-
else
|
161
|
-
key.each_value.map(&:source)
|
162
|
-
end
|
163
|
-
return key.join(', ')
|
164
|
-
end
|
165
|
-
|
166
|
-
key.literal? ? key.source : "*#{key.source}"
|
167
|
-
end
|
168
|
-
|
169
|
-
def decorate_source(value)
|
170
|
-
return ":\"#{value.source}\"" if value.dsym_type?
|
171
|
-
return "\"#{value.source}\"" if value.dstr_type?
|
172
|
-
return ":#{value.source}" if value.sym_type?
|
173
|
-
|
174
|
-
"'#{value.source}'"
|
175
|
-
end
|
176
|
-
|
177
|
-
def except_key(node)
|
178
|
-
key_argument = node.argument_list.first.source
|
179
|
-
body = extract_body_if_negated(node.body)
|
180
|
-
lhs, _method_name, rhs = *body
|
181
|
-
return if [lhs, rhs].map(&:source).none?(key_argument)
|
182
|
-
|
183
|
-
[lhs, rhs].find { |operand| operand.source != key_argument }
|
70
|
+
def semantically_subset_method?(node)
|
71
|
+
semantically_except_method?(node)
|
184
72
|
end
|
185
73
|
|
186
|
-
def
|
187
|
-
|
74
|
+
def preferred_method_name
|
75
|
+
'except'
|
188
76
|
end
|
189
77
|
end
|
190
78
|
end
|