rubocop 1.67.0 → 1.79.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +23 -19
- data/config/default.yml +371 -71
- data/config/internal_affairs.yml +20 -0
- data/config/obsoletion.yml +8 -3
- data/lib/rubocop/cached_data.rb +12 -4
- data/lib/rubocop/cli/command/execute_runner.rb +4 -4
- 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/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 +51 -26
- data/lib/rubocop/cop/base.rb +7 -1
- 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/insecure_protocol_source.rb +0 -1
- data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -1
- 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 +5 -2
- data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +10 -0
- data/lib/rubocop/cop/gemspec/attribute_assignment.rb +91 -0
- data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +1 -2
- 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/gemspec/required_ruby_version.rb +0 -2
- 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 +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 +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/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_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/style_detected_api_use.rb +0 -2
- 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 +7 -16
- data/lib/rubocop/cop/layout/access_modifier_indentation.rb +1 -1
- 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/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 +3 -3
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +7 -11
- data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +99 -0
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +37 -7
- 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_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 +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 +8 -7
- data/lib/rubocop/cop/layout/leading_comment_space.rb +57 -2
- 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 +149 -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 +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_method_parameter_line_breaks.rb +1 -0
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +3 -4
- data/lib/rubocop/cop/layout/parameter_alignment.rb +3 -4
- data/lib/rubocop/cop/layout/redundant_line_break.rb +19 -46
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +6 -7
- 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 +8 -2
- data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_operators.rb +31 -21
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +1 -0
- data/lib/rubocop/cop/layout/space_before_brackets.rb +7 -40
- 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 +18 -3
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +5 -0
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +7 -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 +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 +10 -12
- data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -1
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +4 -1
- 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 +3 -2
- 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_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_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/empty_interpolation.rb +3 -1
- data/lib/rubocop/cop/lint/ensure_return.rb +1 -1
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +0 -6
- data/lib/rubocop/cop/lint/float_comparison.rb +51 -18
- 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/identity_comparison.rb +19 -15
- data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
- data/lib/rubocop/cop/lint/interpolation_check.rb +9 -0
- data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +3 -0
- data/lib/rubocop/cop/lint/literal_as_condition.rb +125 -10
- data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +1 -1
- 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 +5 -8
- data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -1
- data/lib/rubocop/cop/lint/nested_method_definition.rb +10 -6
- 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 +3 -3
- 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 +94 -0
- data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +2 -3
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +3 -2
- 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_cop_enable_directive.rb +1 -1
- 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 +113 -9
- 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 +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/regexp_as_condition.rb +0 -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 +4 -8
- data/lib/rubocop/cop/lint/return_in_void_context.rb +9 -11
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +17 -1
- data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +5 -1
- data/lib/rubocop/cop/lint/self_assignment.rb +33 -10
- data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
- 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 +88 -0
- 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/unused_method_argument.rb +18 -2
- 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_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 +3 -1
- data/lib/rubocop/cop/lint/useless_or.rb +98 -0
- data/lib/rubocop/cop/lint/useless_rescue.rb +2 -2
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +5 -5
- data/lib/rubocop/cop/lint/useless_setter_call.rb +14 -25
- data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +121 -0
- data/lib/rubocop/cop/lint/void.rb +16 -12
- 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 +5 -2
- 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/abc_size_calculator.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +3 -4
- 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_assignment.rb +4 -12
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +22 -12
- 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/def_node.rb +1 -1
- data/lib/rubocop/cop/mixin/dig_help.rb +27 -0
- data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +1 -1
- data/lib/rubocop/cop/mixin/endless_method_rewriter.rb +24 -0
- 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 +4 -3
- 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 +7 -9
- 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 -4
- 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 +17 -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 +20 -16
- data/lib/rubocop/cop/naming/constant_name.rb +6 -7
- data/lib/rubocop/cop/naming/file_name.rb +2 -4
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +12 -13
- 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 +6 -14
- data/lib/rubocop/cop/naming/variable_name.rb +50 -6
- data/lib/rubocop/cop/naming/variable_number.rb +2 -3
- data/lib/rubocop/cop/offense.rb +2 -3
- 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 +114 -34
- data/lib/rubocop/cop/style/accessor_grouping.rb +32 -6
- 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 +57 -44
- data/lib/rubocop/cop/style/array_first_last.rb +18 -2
- data/lib/rubocop/cop/style/array_intersect.rb +84 -42
- data/lib/rubocop/cop/style/bitwise_predicate.rb +100 -0
- data/lib/rubocop/cop/style/block_delimiters.rb +44 -26
- data/lib/rubocop/cop/style/case_like_if.rb +9 -12
- 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 +115 -0
- 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 +20 -3
- 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 +42 -28
- data/lib/rubocop/cop/style/constant_visibility.rb +3 -12
- 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 +89 -0
- 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 +150 -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 +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 +1 -1
- 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/global_vars.rb +1 -3
- data/lib/rubocop/cop/style/guard_clause.rb +17 -3
- data/lib/rubocop/cop/style/hash_conversion.rb +16 -9
- 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 -14
- 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 +3 -4
- data/lib/rubocop/cop/style/if_with_semicolon.rb +20 -9
- data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
- data/lib/rubocop/cop/style/inverse_methods.rb +16 -13
- 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_arguments_merging.rb +67 -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 -4
- data/lib/rubocop/cop/style/line_end_concatenation.rb +10 -4
- data/lib/rubocop/cop/style/map_into_array.rb +11 -3
- data/lib/rubocop/cop/style/map_to_hash.rb +12 -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 +28 -20
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +18 -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 +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/missing_respond_to_missing.rb +33 -3
- 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_memoization.rb +1 -1
- data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -9
- 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_parenthesized_calls.rb +1 -1
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +5 -4
- data/lib/rubocop/cop/style/next.rb +44 -0
- data/lib/rubocop/cop/style/not.rb +1 -1
- data/lib/rubocop/cop/style/object_then.rb +15 -15
- data/lib/rubocop/cop/style/one_line_conditional.rb +25 -4
- data/lib/rubocop/cop/style/open_struct_use.rb +5 -5
- data/lib/rubocop/cop/style/operator_method_call.rb +5 -6
- data/lib/rubocop/cop/style/or_assignment.rb +3 -6
- data/lib/rubocop/cop/style/parallel_assignment.rb +41 -38
- 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 +15 -13
- 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_assignment.rb +1 -1
- data/lib/rubocop/cop/style/redundant_begin.rb +2 -1
- data/lib/rubocop/cop/style/redundant_condition.rb +95 -23
- 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 +55 -19
- data/lib/rubocop/cop/style/redundant_parentheses.rb +86 -26
- 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 +15 -18
- 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_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 +5 -3
- data/lib/rubocop/cop/style/return_nil.rb +2 -2
- data/lib/rubocop/cop/style/safe_navigation.rb +56 -16
- data/lib/rubocop/cop/style/safe_navigation_chain_length.rb +52 -0
- data/lib/rubocop/cop/style/select_by_regexp.rb +5 -2
- data/lib/rubocop/cop/style/self_assignment.rb +11 -17
- 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/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 +15 -4
- 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 -102
- data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/string_concatenation.rb +15 -15
- 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/swap_values.rb +4 -15
- data/lib/rubocop/cop/style/symbol_proc.rb +3 -1
- data/lib/rubocop/cop/style/ternary_parentheses.rb +25 -4
- 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/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 +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 +24 -5
- data/lib/rubocop/cop/variable_force/branch.rb +1 -1
- data/lib/rubocop/cop/variable_force/scope.rb +1 -1
- data/lib/rubocop/cop/variable_force/variable.rb +14 -3
- data/lib/rubocop/cop/variable_force/variable_table.rb +5 -5
- data/lib/rubocop/cop/variable_force.rb +23 -18
- data/lib/rubocop/cops_documentation_generator.rb +51 -25
- 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 +3 -2
- 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 +13 -13
- 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 +26 -15
- 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 +17 -2
- data/lib/rubocop/version.rb +53 -12
- data/lib/rubocop.rb +43 -2
- data/lib/ruby_lsp/rubocop/addon.rb +75 -0
- data/lib/ruby_lsp/rubocop/runtime_adapter.rb +65 -0
- metadata +89 -17
- data/lib/rubocop/cop/utils/regexp_ranges.rb +0 -113
- data/lib/rubocop/rspec/host_environment_simulation_helper.rb +0 -28
@@ -155,6 +155,7 @@ module RuboCop
|
|
155
155
|
UNDERSCORE_REQUIRED = 'Memoized variable `%<var>s` does not start ' \
|
156
156
|
'with `_`. Use `@%<suggested_var>s` instead.'
|
157
157
|
DYNAMIC_DEFINE_METHODS = %i[define_method define_singleton_method].to_set.freeze
|
158
|
+
INITIALIZE_METHODS = %i[initialize initialize_clone initialize_copy initialize_dup].freeze
|
158
159
|
|
159
160
|
# @!method method_definition?(node)
|
160
161
|
def_node_matcher :method_definition?, <<~PATTERN
|
@@ -168,7 +169,7 @@ module RuboCop
|
|
168
169
|
# rubocop:disable Metrics/AbcSize
|
169
170
|
# rubocop:disable Metrics/MethodLength
|
170
171
|
def on_or_asgn(node)
|
171
|
-
lhs
|
172
|
+
lhs = node.lhs
|
172
173
|
return unless lhs.ivasgn_type?
|
173
174
|
|
174
175
|
method_node, method_name = find_definition(node)
|
@@ -181,8 +182,8 @@ module RuboCop
|
|
181
182
|
|
182
183
|
suggested_var = suggested_var(method_name)
|
183
184
|
msg = format(
|
184
|
-
message(lhs.
|
185
|
-
var: lhs.
|
185
|
+
message(lhs.name),
|
186
|
+
var: lhs.name,
|
186
187
|
suggested_var: suggested_var,
|
187
188
|
method: method_name
|
188
189
|
)
|
@@ -209,14 +210,13 @@ module RuboCop
|
|
209
210
|
method_node, method_name = find_definition(node)
|
210
211
|
return false unless method_node
|
211
212
|
|
212
|
-
|
213
|
-
defined_memoized?(method_node.body, var_name) do |defined_ivar, return_ivar, ivar_assign|
|
213
|
+
defined_memoized?(method_node.body, arg.name) do |defined_ivar, return_ivar, ivar_assign|
|
214
214
|
return false if matches?(method_name, ivar_assign)
|
215
215
|
|
216
216
|
suggested_var = suggested_var(method_name)
|
217
217
|
msg = format(
|
218
|
-
message(
|
219
|
-
var:
|
218
|
+
message(arg.name),
|
219
|
+
var: arg.name,
|
220
220
|
suggested_var: suggested_var,
|
221
221
|
method: method_name
|
222
222
|
)
|
@@ -242,7 +242,7 @@ module RuboCop
|
|
242
242
|
def find_definition(node)
|
243
243
|
# Methods can be defined in a `def` or `defs`,
|
244
244
|
# or dynamically via a `block` node.
|
245
|
-
node.each_ancestor(:
|
245
|
+
node.each_ancestor(:any_def, :block).each do |ancestor|
|
246
246
|
method_node, method_name = method_definition?(ancestor)
|
247
247
|
return [method_node, method_name] if method_node
|
248
248
|
end
|
@@ -251,11 +251,10 @@ module RuboCop
|
|
251
251
|
end
|
252
252
|
|
253
253
|
def matches?(method_name, ivar_assign)
|
254
|
-
return true if ivar_assign.nil? || method_name
|
254
|
+
return true if ivar_assign.nil? || INITIALIZE_METHODS.include?(method_name)
|
255
255
|
|
256
|
-
method_name = method_name.to_s.delete('
|
257
|
-
|
258
|
-
variable_name = variable.to_s.sub('@', '')
|
256
|
+
method_name = method_name.to_s.delete('!?=')
|
257
|
+
variable_name = ivar_assign.name.to_s.sub('@', '')
|
259
258
|
|
260
259
|
variable_name_candidates(method_name).include?(variable_name)
|
261
260
|
end
|
@@ -269,7 +268,7 @@ module RuboCop
|
|
269
268
|
end
|
270
269
|
|
271
270
|
def suggested_var(method_name)
|
272
|
-
suggestion = method_name.to_s.delete('
|
271
|
+
suggestion = method_name.to_s.delete('!?=')
|
273
272
|
|
274
273
|
style == :required ? "_#{suggestion}" : suggestion
|
275
274
|
end
|
@@ -6,14 +6,31 @@ module RuboCop
|
|
6
6
|
# Makes sure that all methods use the configured style,
|
7
7
|
# snake_case or camelCase, for their names.
|
8
8
|
#
|
9
|
-
#
|
9
|
+
# Method names matching patterns are always allowed.
|
10
10
|
#
|
11
|
-
#
|
12
|
-
# AllowedPatterns:
|
13
|
-
# - '\AonSelectionBulkChange\z'
|
14
|
-
# - '\AonSelectionCleared\z'
|
11
|
+
# The cop can be configured with `AllowedPatterns` to allow certain regexp patterns:
|
15
12
|
#
|
16
|
-
#
|
13
|
+
# [source,yaml]
|
14
|
+
# ----
|
15
|
+
# Naming/MethodName:
|
16
|
+
# AllowedPatterns:
|
17
|
+
# - '\AonSelectionBulkChange\z'
|
18
|
+
# - '\AonSelectionCleared\z'
|
19
|
+
# ----
|
20
|
+
#
|
21
|
+
# As well, you can also forbid specific method names or regexp patterns
|
22
|
+
# using `ForbiddenIdentifiers` or `ForbiddenPatterns`:
|
23
|
+
#
|
24
|
+
# [source,yaml]
|
25
|
+
# ----
|
26
|
+
# Naming/MethodName:
|
27
|
+
# ForbiddenIdentifiers:
|
28
|
+
# - 'def'
|
29
|
+
# - 'super'
|
30
|
+
# ForbiddenPatterns:
|
31
|
+
# - '_v1\z'
|
32
|
+
# - '_gen1\z'
|
33
|
+
# ----
|
17
34
|
#
|
18
35
|
# @example EnforcedStyle: snake_case (default)
|
19
36
|
# # bad
|
@@ -22,18 +39,75 @@ module RuboCop
|
|
22
39
|
# # good
|
23
40
|
# def foo_bar; end
|
24
41
|
#
|
42
|
+
# # bad
|
43
|
+
# define_method :fooBar do
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# # good
|
47
|
+
# define_method :foo_bar do
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# # bad
|
51
|
+
# Struct.new(:fooBar)
|
52
|
+
#
|
53
|
+
# # good
|
54
|
+
# Struct.new(:foo_bar)
|
55
|
+
#
|
56
|
+
# # bad
|
57
|
+
# alias_method :fooBar, :some_method
|
58
|
+
#
|
59
|
+
# # good
|
60
|
+
# alias_method :foo_bar, :some_method
|
61
|
+
#
|
25
62
|
# @example EnforcedStyle: camelCase
|
26
63
|
# # bad
|
27
64
|
# def foo_bar; end
|
28
65
|
#
|
29
66
|
# # good
|
30
67
|
# def fooBar; end
|
68
|
+
#
|
69
|
+
# # bad
|
70
|
+
# define_method :foo_bar do
|
71
|
+
# end
|
72
|
+
#
|
73
|
+
# # good
|
74
|
+
# define_method :fooBar do
|
75
|
+
# end
|
76
|
+
#
|
77
|
+
# # bad
|
78
|
+
# Struct.new(:foo_bar)
|
79
|
+
#
|
80
|
+
# # good
|
81
|
+
# Struct.new(:fooBar)
|
82
|
+
#
|
83
|
+
# # bad
|
84
|
+
# alias_method :foo_bar, :some_method
|
85
|
+
#
|
86
|
+
# # good
|
87
|
+
# alias_method :fooBar, :some_method
|
88
|
+
#
|
89
|
+
# @example ForbiddenIdentifiers: ['def', 'super']
|
90
|
+
# # bad
|
91
|
+
# def def; end
|
92
|
+
# def super; end
|
93
|
+
#
|
94
|
+
# @example ForbiddenPatterns: ['_v1\z', '_gen1\z']
|
95
|
+
# # bad
|
96
|
+
# def release_v1; end
|
97
|
+
# def api_gen1; end
|
98
|
+
#
|
31
99
|
class MethodName < Base
|
32
100
|
include ConfigurableNaming
|
33
101
|
include AllowedPattern
|
34
102
|
include RangeHelp
|
103
|
+
include ForbiddenIdentifiers
|
104
|
+
include ForbiddenPattern
|
35
105
|
|
36
106
|
MSG = 'Use %<style>s for method names.'
|
107
|
+
MSG_FORBIDDEN = '`%<identifier>s` is forbidden, use another method name instead.'
|
108
|
+
|
109
|
+
OPERATOR_METHODS = %i[| ^ & <=> == === =~ > >= < <= << >> + - * /
|
110
|
+
% ** ~ +@ -@ !@ ~@ [] []= ! != !~ `].to_set.freeze
|
37
111
|
|
38
112
|
# @!method sym_name(node)
|
39
113
|
def_node_matcher :sym_name, '(sym $_name)'
|
@@ -41,35 +115,131 @@ module RuboCop
|
|
41
115
|
# @!method str_name(node)
|
42
116
|
def_node_matcher :str_name, '(str $_name)'
|
43
117
|
|
118
|
+
# @!method new_struct?(node)
|
119
|
+
def_node_matcher :new_struct?, '(send (const {nil? cbase} :Struct) :new ...)'
|
120
|
+
|
121
|
+
# @!method define_data?(node)
|
122
|
+
def_node_matcher :define_data?, '(send (const {nil? cbase} :Data) :define ...)'
|
123
|
+
|
44
124
|
def on_send(node)
|
125
|
+
if node.method?(:define_method) || node.method?(:define_singleton_method)
|
126
|
+
handle_define_method(node)
|
127
|
+
elsif new_struct?(node)
|
128
|
+
handle_new_struct(node)
|
129
|
+
elsif define_data?(node)
|
130
|
+
handle_define_data(node)
|
131
|
+
elsif node.method?(:alias_method)
|
132
|
+
handle_alias_method(node)
|
133
|
+
else
|
134
|
+
handle_attr_accessor(node)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def on_def(node)
|
139
|
+
return if node.operator_method? || matches_allowed_pattern?(node.method_name)
|
140
|
+
|
141
|
+
if forbidden_name?(node.method_name.to_s)
|
142
|
+
register_forbidden_name(node)
|
143
|
+
else
|
144
|
+
check_name(node, node.method_name, node.loc.name)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
alias on_defs on_def
|
148
|
+
|
149
|
+
def on_alias(node)
|
150
|
+
handle_method_name(node.new_identifier, node.new_identifier.value)
|
151
|
+
end
|
152
|
+
|
153
|
+
private
|
154
|
+
|
155
|
+
def handle_define_method(node)
|
156
|
+
return unless node.first_argument&.type?(:str, :sym)
|
157
|
+
|
158
|
+
handle_method_name(node, node.first_argument.value)
|
159
|
+
end
|
160
|
+
|
161
|
+
def handle_new_struct(node)
|
162
|
+
arguments = node.first_argument&.str_type? ? node.arguments[1..] : node.arguments
|
163
|
+
arguments.select { |argument| argument.type?(:sym, :str) }.each do |name|
|
164
|
+
handle_method_name(name, name.value)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def handle_define_data(node)
|
169
|
+
node.arguments.select { |argument| argument.type?(:sym, :str) }.each do |name|
|
170
|
+
handle_method_name(name, name.value)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def handle_alias_method(node)
|
175
|
+
return unless node.arguments.size == 2
|
176
|
+
return unless node.first_argument.type?(:str, :sym)
|
177
|
+
|
178
|
+
handle_method_name(node.first_argument, node.first_argument.value)
|
179
|
+
end
|
180
|
+
|
181
|
+
def handle_attr_accessor(node)
|
45
182
|
return unless (attrs = node.attribute_accessor?)
|
46
183
|
|
47
184
|
attrs.last.each do |name_item|
|
48
185
|
name = attr_name(name_item)
|
49
186
|
next if !name || matches_allowed_pattern?(name)
|
50
187
|
|
51
|
-
|
188
|
+
if forbidden_name?(name.to_s)
|
189
|
+
register_forbidden_name(node)
|
190
|
+
else
|
191
|
+
check_name(node, name, range_position(node))
|
192
|
+
end
|
52
193
|
end
|
53
194
|
end
|
54
195
|
|
55
|
-
def
|
56
|
-
return if
|
196
|
+
def handle_method_name(node, name)
|
197
|
+
return if !name || matches_allowed_pattern?(name)
|
57
198
|
|
58
|
-
|
199
|
+
if forbidden_name?(name.to_s)
|
200
|
+
register_forbidden_name(node)
|
201
|
+
elsif !OPERATOR_METHODS.include?(name)
|
202
|
+
check_name(node, name, range_position(node))
|
203
|
+
end
|
59
204
|
end
|
60
|
-
alias on_defs on_def
|
61
205
|
|
62
|
-
|
206
|
+
def forbidden_name?(name)
|
207
|
+
forbidden_identifier?(name) || forbidden_pattern?(name)
|
208
|
+
end
|
209
|
+
|
210
|
+
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
211
|
+
def register_forbidden_name(node)
|
212
|
+
if node.any_def_type?
|
213
|
+
name_node = node.loc.name
|
214
|
+
method_name = node.method_name
|
215
|
+
elsif node.literal?
|
216
|
+
name_node = node
|
217
|
+
method_name = node.value
|
218
|
+
elsif (attrs = node.attribute_accessor?)
|
219
|
+
name_node = attrs.last.last
|
220
|
+
method_name = attr_name(name_node)
|
221
|
+
else
|
222
|
+
name_node = node.first_argument
|
223
|
+
method_name = node.first_argument.value
|
224
|
+
end
|
225
|
+
message = format(MSG_FORBIDDEN, identifier: method_name)
|
226
|
+
add_offense(name_node, message: message)
|
227
|
+
end
|
228
|
+
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize
|
63
229
|
|
64
230
|
def attr_name(name_item)
|
65
231
|
sym_name(name_item) || str_name(name_item)
|
66
232
|
end
|
67
233
|
|
68
234
|
def range_position(node)
|
69
|
-
|
70
|
-
|
235
|
+
if node.loc.respond_to?(:selector)
|
236
|
+
selector_end_pos = node.loc.selector.end_pos + 1
|
237
|
+
expr_end_pos = node.source_range.end_pos
|
71
238
|
|
72
|
-
|
239
|
+
range_between(selector_end_pos, expr_end_pos)
|
240
|
+
else
|
241
|
+
node.source_range
|
242
|
+
end
|
73
243
|
end
|
74
244
|
|
75
245
|
def message(style)
|
@@ -0,0 +1,306 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Naming
|
6
|
+
# Checks that predicate methods end with `?` and non-predicate methods do not.
|
7
|
+
#
|
8
|
+
# The names of predicate methods (methods that return a boolean value) should end
|
9
|
+
# in a question mark. Methods that don't return a boolean, shouldn't
|
10
|
+
# end in a question mark.
|
11
|
+
#
|
12
|
+
# The cop assesses a predicate method as one that returns boolean values. Likewise,
|
13
|
+
# a method that only returns literal values is assessed as non-predicate. Other predicate
|
14
|
+
# method calls are assumed to return boolean values. The cop does not make an assessment
|
15
|
+
# if the return type is unknown (non-predicate method calls, variables, etc.).
|
16
|
+
#
|
17
|
+
# NOTE: Operator methods (`def ==`, etc.) are ignored.
|
18
|
+
#
|
19
|
+
# By default, the cop runs in `conservative` mode, which allows a method to be named
|
20
|
+
# with a question mark as long as at least one return value is boolean. In `aggressive`
|
21
|
+
# mode, methods with a question mark will register an offense if any known non-boolean
|
22
|
+
# return values are detected.
|
23
|
+
#
|
24
|
+
# The cop also has `AllowedMethods` configuration in order to prevent the cop from
|
25
|
+
# registering an offense from a method name that does not confirm to the naming
|
26
|
+
# guidelines. By default, `call` is allowed. The cop also has `AllowedPatterns`
|
27
|
+
# configuration to allow method names by regular expression.
|
28
|
+
#
|
29
|
+
# Although returning a call to another predicate method is treated as a boolean value,
|
30
|
+
# certain method names can be known to not return a boolean, despite ending in a `?`
|
31
|
+
# (for example, `Numeric#nonzero?` returns `self` or `nil`). These methods can be
|
32
|
+
# configured using `NonBooleanPredicates`.
|
33
|
+
#
|
34
|
+
# The cop can furthermore be configured to allow all bang methods (method names
|
35
|
+
# ending with `!`), with `AllowBangMethods: true` (default false).
|
36
|
+
#
|
37
|
+
# @example Mode: conservative (default)
|
38
|
+
# # bad
|
39
|
+
# def foo
|
40
|
+
# bar == baz
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# # good
|
44
|
+
# def foo?
|
45
|
+
# bar == baz
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# # bad
|
49
|
+
# def foo?
|
50
|
+
# 5
|
51
|
+
# end
|
52
|
+
#
|
53
|
+
# # good
|
54
|
+
# def foo
|
55
|
+
# 5
|
56
|
+
# end
|
57
|
+
#
|
58
|
+
# # bad
|
59
|
+
# def foo
|
60
|
+
# x == y
|
61
|
+
# end
|
62
|
+
#
|
63
|
+
# # good
|
64
|
+
# def foo?
|
65
|
+
# x == y
|
66
|
+
# end
|
67
|
+
#
|
68
|
+
# # bad
|
69
|
+
# def foo
|
70
|
+
# !x
|
71
|
+
# end
|
72
|
+
#
|
73
|
+
# # good
|
74
|
+
# def foo?
|
75
|
+
# !x
|
76
|
+
# end
|
77
|
+
#
|
78
|
+
# # bad - returns the value of another predicate method
|
79
|
+
# def foo
|
80
|
+
# bar?
|
81
|
+
# end
|
82
|
+
#
|
83
|
+
# # good
|
84
|
+
# def foo?
|
85
|
+
# bar?
|
86
|
+
# end
|
87
|
+
#
|
88
|
+
# # good - operator method
|
89
|
+
# def ==(other)
|
90
|
+
# hash == other.hash
|
91
|
+
# end
|
92
|
+
#
|
93
|
+
# # good - at least one return value is boolean
|
94
|
+
# def foo?
|
95
|
+
# return unless bar?
|
96
|
+
# true
|
97
|
+
# end
|
98
|
+
#
|
99
|
+
# # ok - return type is not known
|
100
|
+
# def foo?
|
101
|
+
# bar
|
102
|
+
# end
|
103
|
+
#
|
104
|
+
# # ok - return type is not known
|
105
|
+
# def foo
|
106
|
+
# bar?
|
107
|
+
# end
|
108
|
+
#
|
109
|
+
# @example Mode: aggressive
|
110
|
+
# # bad - the method returns nil in some cases
|
111
|
+
# def foo?
|
112
|
+
# return unless bar?
|
113
|
+
# true
|
114
|
+
# end
|
115
|
+
#
|
116
|
+
# @example AllowBangMethods: false (default)
|
117
|
+
# # bad
|
118
|
+
# def save!
|
119
|
+
# true
|
120
|
+
# end
|
121
|
+
#
|
122
|
+
# @example AllowBangMethods: true
|
123
|
+
# # good
|
124
|
+
# def save!
|
125
|
+
# true
|
126
|
+
# end
|
127
|
+
#
|
128
|
+
class PredicateMethod < Base
|
129
|
+
include AllowedMethods
|
130
|
+
include AllowedPattern
|
131
|
+
|
132
|
+
MSG_PREDICATE = 'Predicate method names should end with `?`.'
|
133
|
+
MSG_NON_PREDICATE = 'Non-predicate method names should not end with `?`.'
|
134
|
+
|
135
|
+
def on_def(node)
|
136
|
+
return if allowed?(node)
|
137
|
+
|
138
|
+
return_values = return_values(node.body)
|
139
|
+
return if acceptable?(return_values)
|
140
|
+
|
141
|
+
if node.predicate_method? && potential_non_predicate?(return_values)
|
142
|
+
add_offense(node.loc.name, message: MSG_NON_PREDICATE)
|
143
|
+
elsif !node.predicate_method? && all_return_values_boolean?(return_values)
|
144
|
+
add_offense(node.loc.name, message: MSG_PREDICATE)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
alias on_defs on_def
|
148
|
+
|
149
|
+
private
|
150
|
+
|
151
|
+
def allowed?(node)
|
152
|
+
allowed_method?(node.method_name) ||
|
153
|
+
matches_allowed_pattern?(node.method_name) ||
|
154
|
+
allowed_bang_method?(node) ||
|
155
|
+
node.operator_method? ||
|
156
|
+
node.body.nil?
|
157
|
+
end
|
158
|
+
|
159
|
+
def acceptable?(return_values)
|
160
|
+
# In `conservative` mode, if the method returns `super`, `zsuper`, or a
|
161
|
+
# non-comparison method call, the method name is acceptable.
|
162
|
+
return false unless conservative?
|
163
|
+
|
164
|
+
return_values.any? do |value|
|
165
|
+
value.type?(:super, :zsuper) || unknown_method_call?(value)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def unknown_method_call?(value)
|
170
|
+
return false unless value.call_type?
|
171
|
+
|
172
|
+
!method_returning_boolean?(value)
|
173
|
+
end
|
174
|
+
|
175
|
+
def return_values(node)
|
176
|
+
# Collect all the (implicit and explicit) return values of a node
|
177
|
+
return_values = Set.new(node.begin_type? ? [] : [extract_return_value(node)])
|
178
|
+
|
179
|
+
node.each_descendant(:return) do |return_node|
|
180
|
+
return_values << extract_return_value(return_node)
|
181
|
+
end
|
182
|
+
|
183
|
+
last_value = last_value(node)
|
184
|
+
return_values << last_value if last_value
|
185
|
+
|
186
|
+
process_return_values(return_values)
|
187
|
+
end
|
188
|
+
|
189
|
+
def all_return_values_boolean?(return_values)
|
190
|
+
values = return_values.reject { |value| value.type?(:super, :zsuper) }
|
191
|
+
return false if values.empty?
|
192
|
+
|
193
|
+
values.all? { |value| boolean_return?(value) }
|
194
|
+
end
|
195
|
+
|
196
|
+
def boolean_return?(value)
|
197
|
+
return true if value.boolean_type?
|
198
|
+
|
199
|
+
method_returning_boolean?(value)
|
200
|
+
end
|
201
|
+
|
202
|
+
def method_returning_boolean?(value)
|
203
|
+
return false unless value.call_type?
|
204
|
+
return false if wayward_predicate?(value.method_name)
|
205
|
+
|
206
|
+
value.comparison_method? || value.predicate_method? || value.negation_method?
|
207
|
+
end
|
208
|
+
|
209
|
+
def potential_non_predicate?(return_values)
|
210
|
+
# Assumes a method to be non-predicate if all return values are non-boolean literals.
|
211
|
+
#
|
212
|
+
# In `Mode: conservative`, if any of the return values is a boolean,
|
213
|
+
# the method name is acceptable.
|
214
|
+
# In `Mode: aggressive`, all return values must be booleans for a predicate
|
215
|
+
# method, or else an offense will be registered.
|
216
|
+
return false if conservative? && return_values.any? { |value| boolean_return?(value) }
|
217
|
+
|
218
|
+
return_values.any? do |value|
|
219
|
+
value.literal? && !value.boolean_type?
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def extract_return_value(node)
|
224
|
+
return node unless node.return_type?
|
225
|
+
|
226
|
+
# `return` without a value is a `nil` return.
|
227
|
+
return s(:nil) if node.arguments.empty?
|
228
|
+
|
229
|
+
# When there's a multiple return, it cannot be a predicate
|
230
|
+
# so just return an `array` sexp for simplicity.
|
231
|
+
return s(:array) unless node.arguments.one?
|
232
|
+
|
233
|
+
node.first_argument
|
234
|
+
end
|
235
|
+
|
236
|
+
def last_value(node)
|
237
|
+
value = node.begin_type? ? node.children.last : node
|
238
|
+
value&.return_type? ? extract_return_value(value) : value
|
239
|
+
end
|
240
|
+
|
241
|
+
def process_return_values(return_values)
|
242
|
+
return_values.flat_map do |value|
|
243
|
+
if value.conditional?
|
244
|
+
process_return_values(extract_conditional_branches(value))
|
245
|
+
elsif and_or?(value)
|
246
|
+
process_return_values(extract_and_or_clauses(value))
|
247
|
+
else
|
248
|
+
value
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
def and_or?(node)
|
254
|
+
node.type?(:and, :or)
|
255
|
+
end
|
256
|
+
|
257
|
+
def extract_and_or_clauses(node)
|
258
|
+
# Recursively traverse an `and` or `or` node to collect all clauses within
|
259
|
+
return node unless and_or?(node)
|
260
|
+
|
261
|
+
[extract_and_or_clauses(node.lhs), extract_and_or_clauses(node.rhs)].flatten
|
262
|
+
end
|
263
|
+
|
264
|
+
def extract_conditional_branches(node)
|
265
|
+
return node unless node.conditional?
|
266
|
+
|
267
|
+
if node.type?(:while, :until)
|
268
|
+
# If there is no body, act as implicit `nil`.
|
269
|
+
node.body ? [last_value(node.body)] : [s(:nil)]
|
270
|
+
else
|
271
|
+
# Branches with no value act as an implicit `nil`.
|
272
|
+
branches = node.branches.map { |branch| branch ? last_value(branch) : s(:nil) }
|
273
|
+
# Missing else branches also act as an implicit `nil`.
|
274
|
+
branches.push(s(:nil)) unless node.else_branch
|
275
|
+
branches
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
def conservative?
|
280
|
+
cop_config.fetch('Mode', :conservative).to_sym == :conservative
|
281
|
+
end
|
282
|
+
|
283
|
+
def allowed_bang_method?(node)
|
284
|
+
return false unless allow_bang_methods?
|
285
|
+
|
286
|
+
node.bang_method?
|
287
|
+
end
|
288
|
+
|
289
|
+
def allow_bang_methods?
|
290
|
+
cop_config.fetch('AllowBangMethods', false)
|
291
|
+
end
|
292
|
+
|
293
|
+
# If a method ending in `?` is known to not return a boolean value,
|
294
|
+
# (for example, `Numeric#nonzero?`) it should be treated as a non-boolean
|
295
|
+
# value, despite the method naming.
|
296
|
+
def wayward_predicate?(name)
|
297
|
+
wayward_predicates.include?(name.to_s)
|
298
|
+
end
|
299
|
+
|
300
|
+
def wayward_predicates
|
301
|
+
Array(cop_config.fetch('WaywardPredicates', []))
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|