rubocop 1.66.1 → 1.72.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +2 -2
- data/config/default.yml +162 -14
- data/config/internal_affairs.yml +11 -0
- data/lib/rubocop/cached_data.rb +12 -4
- data/lib/rubocop/cli/command/auto_generate_config.rb +6 -7
- data/lib/rubocop/cli/command/execute_runner.rb +4 -4
- data/lib/rubocop/cli/command/lsp.rb +2 -2
- data/lib/rubocop/cli/command/show_cops.rb +24 -2
- data/lib/rubocop/cli/command/suggest_extensions.rb +7 -1
- data/lib/rubocop/cli/command/version.rb +2 -2
- data/lib/rubocop/comment_config.rb +2 -2
- data/lib/rubocop/config.rb +17 -4
- data/lib/rubocop/config_loader.rb +48 -8
- data/lib/rubocop/config_loader_resolver.rb +36 -11
- data/lib/rubocop/config_validator.rb +20 -9
- data/lib/rubocop/cop/autocorrect_logic.rb +36 -19
- data/lib/rubocop/cop/base.rb +13 -3
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +2 -2
- data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
- data/lib/rubocop/cop/bundler/gem_filename.rb +0 -1
- data/lib/rubocop/cop/bundler/gem_version.rb +1 -0
- data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +0 -1
- data/lib/rubocop/cop/cop.rb +8 -0
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +1 -12
- data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +10 -0
- data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +1 -2
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +0 -2
- data/lib/rubocop/cop/generator.rb +6 -0
- data/lib/rubocop/cop/internal_affairs/cop_description.rb +0 -4
- data/lib/rubocop/cop/internal_affairs/cop_enabled.rb +85 -0
- data/lib/rubocop/cop/internal_affairs/example_description.rb +4 -2
- data/lib/rubocop/cop/internal_affairs/location_exists.rb +116 -0
- data/lib/rubocop/cop/internal_affairs/location_expression.rb +2 -1
- data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +3 -4
- data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +3 -2
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +63 -0
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +131 -0
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +229 -0
- data/lib/rubocop/cop/internal_affairs/node_type_multiple_predicates.rb +126 -0
- data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +4 -3
- data/lib/rubocop/cop/internal_affairs/numblock_handler.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +90 -0
- data/lib/rubocop/cop/internal_affairs/operator_keyword.rb +48 -0
- data/lib/rubocop/cop/internal_affairs/plugin.rb +33 -0
- data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +6 -21
- data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +11 -2
- data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +5 -4
- data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +0 -2
- data/lib/rubocop/cop/internal_affairs/undefined_config.rb +7 -1
- data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +0 -5
- data/lib/rubocop/cop/internal_affairs.rb +6 -0
- data/lib/rubocop/cop/layout/access_modifier_indentation.rb +6 -2
- data/lib/rubocop/cop/layout/argument_alignment.rb +2 -9
- data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/begin_end_alignment.rb +0 -1
- data/lib/rubocop/cop/layout/block_alignment.rb +3 -2
- data/lib/rubocop/cop/layout/class_structure.rb +9 -9
- data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/dot_position.rb +1 -1
- data/lib/rubocop/cop/layout/else_alignment.rb +2 -2
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +3 -3
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +7 -11
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +3 -3
- data/lib/rubocop/cop/layout/empty_lines_around_begin_body.rb +5 -6
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +4 -5
- data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +23 -1
- data/lib/rubocop/cop/layout/end_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/extra_spacing.rb +1 -1
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +3 -8
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -7
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +2 -7
- data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +1 -1
- data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +8 -0
- data/lib/rubocop/cop/layout/first_parameter_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/hash_alignment.rb +6 -4
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +11 -12
- data/lib/rubocop/cop/layout/leading_comment_space.rb +71 -1
- data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +11 -2
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +7 -1
- data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/line_length.rb +119 -4
- data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +25 -0
- data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +2 -1
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +4 -4
- data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +2 -3
- data/lib/rubocop/cop/layout/parameter_alignment.rb +3 -4
- data/lib/rubocop/cop/layout/redundant_line_break.rb +10 -41
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +4 -3
- data/lib/rubocop/cop/layout/single_line_block_chain.rb +1 -1
- data/lib/rubocop/cop/layout/space_after_colon.rb +2 -2
- data/lib/rubocop/cop/layout/space_after_comma.rb +1 -1
- data/lib/rubocop/cop/layout/space_after_method_name.rb +1 -1
- data/lib/rubocop/cop/layout/space_after_semicolon.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_keyword.rb +2 -1
- data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_operators.rb +19 -20
- data/lib/rubocop/cop/layout/space_before_brackets.rb +5 -5
- data/lib/rubocop/cop/layout/space_before_comma.rb +1 -1
- data/lib/rubocop/cop/layout/space_before_semicolon.rb +1 -1
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +6 -0
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +4 -0
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +4 -0
- data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +0 -1
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +5 -3
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_range.rb +4 -1
- data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +119 -0
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +1 -3
- data/lib/rubocop/cop/lint/big_decimal_new.rb +4 -7
- data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +10 -12
- data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -1
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +6 -0
- data/lib/rubocop/cop/lint/constant_definition_in_block.rb +3 -3
- data/lib/rubocop/cop/lint/constant_reassignment.rb +148 -0
- data/lib/rubocop/cop/lint/cop_directive_syntax.rb +84 -0
- data/lib/rubocop/cop/lint/debugger.rb +1 -1
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +2 -1
- data/lib/rubocop/cop/lint/duplicate_branch.rb +39 -4
- data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_set_element.rb +87 -0
- data/lib/rubocop/cop/lint/empty_ensure.rb +1 -1
- data/lib/rubocop/cop/lint/empty_expression.rb +0 -2
- data/lib/rubocop/cop/lint/empty_file.rb +0 -2
- data/lib/rubocop/cop/lint/ensure_return.rb +1 -4
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -1
- data/lib/rubocop/cop/lint/float_comparison.rb +20 -9
- data/lib/rubocop/cop/lint/float_out_of_range.rb +2 -4
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +2 -2
- data/lib/rubocop/cop/lint/hash_new_with_keyword_arguments_as_default.rb +55 -0
- data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +11 -5
- data/lib/rubocop/cop/lint/interpolation_check.rb +9 -0
- data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +8 -14
- data/lib/rubocop/cop/lint/literal_as_condition.rb +1 -0
- data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +1 -1
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +49 -8
- data/lib/rubocop/cop/lint/missing_super.rb +2 -2
- data/lib/rubocop/cop/lint/mixed_case_range.rb +3 -6
- data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -1
- data/lib/rubocop/cop/lint/nested_method_definition.rb +9 -5
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
- data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +2 -2
- data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +12 -3
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -3
- data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +1 -1
- data/lib/rubocop/cop/lint/number_conversion.rb +0 -1
- data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -2
- data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +93 -0
- data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +1 -2
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +3 -2
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +6 -11
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +13 -8
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +8 -7
- data/lib/rubocop/cop/lint/redundant_string_coercion.rb +2 -2
- data/lib/rubocop/cop/lint/redundant_type_conversion.rb +231 -0
- data/lib/rubocop/cop/lint/refinement_import_methods.rb +1 -1
- data/lib/rubocop/cop/lint/regexp_as_condition.rb +0 -1
- data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
- data/lib/rubocop/cop/lint/rescue_type.rb +3 -7
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +17 -1
- data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +109 -41
- data/lib/rubocop/cop/lint/self_assignment.rb +8 -10
- data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
- data/lib/rubocop/cop/lint/shared_mutable_default.rb +65 -0
- data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
- data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +111 -0
- data/lib/rubocop/cop/lint/symbol_conversion.rb +2 -2
- data/lib/rubocop/cop/lint/syntax.rb +4 -1
- data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +88 -0
- data/lib/rubocop/cop/lint/unexpected_block_arity.rb +1 -1
- data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -1
- data/lib/rubocop/cop/lint/unreachable_code.rb +51 -2
- data/lib/rubocop/cop/lint/unreachable_loop.rb +1 -1
- data/lib/rubocop/cop/lint/unused_method_argument.rb +18 -2
- data/lib/rubocop/cop/lint/uri_regexp.rb +25 -7
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +4 -4
- data/lib/rubocop/cop/lint/useless_assignment.rb +1 -1
- data/lib/rubocop/cop/lint/useless_constant_scoping.rb +80 -0
- data/lib/rubocop/cop/lint/useless_defined.rb +55 -0
- data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +4 -0
- data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
- data/lib/rubocop/cop/lint/useless_numeric_operation.rb +2 -1
- data/lib/rubocop/cop/lint/useless_rescue.rb +1 -1
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +2 -2
- data/lib/rubocop/cop/lint/useless_setter_call.rb +14 -25
- data/lib/rubocop/cop/lint/void.rb +8 -11
- data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
- data/lib/rubocop/cop/metrics/class_length.rb +9 -9
- data/lib/rubocop/cop/metrics/collection_literal_length.rb +7 -0
- data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +5 -2
- data/lib/rubocop/cop/metrics/method_length.rb +8 -1
- data/lib/rubocop/cop/metrics/module_length.rb +1 -1
- data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +2 -3
- data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +7 -7
- data/lib/rubocop/cop/mixin/alignment.rb +2 -2
- data/lib/rubocop/cop/mixin/allowed_pattern.rb +4 -4
- data/lib/rubocop/cop/mixin/check_assignment.rb +4 -12
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +20 -10
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +49 -0
- data/lib/rubocop/cop/mixin/comments_help.rb +8 -3
- data/lib/rubocop/cop/mixin/dig_help.rb +27 -0
- data/lib/rubocop/cop/mixin/endless_method_rewriter.rb +24 -0
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +4 -2
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +22 -22
- data/lib/rubocop/cop/mixin/hash_subset.rb +188 -0
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +74 -74
- data/lib/rubocop/cop/mixin/line_length_help.rb +5 -4
- data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +5 -9
- data/lib/rubocop/cop/mixin/percent_array.rb +1 -1
- data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +68 -30
- data/lib/rubocop/cop/mixin/range_help.rb +3 -4
- data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
- data/lib/rubocop/cop/mixin/statement_modifier.rb +11 -5
- data/lib/rubocop/cop/mixin/string_help.rb +2 -2
- data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -1
- data/lib/rubocop/cop/mixin/target_ruby_version.rb +17 -1
- data/lib/rubocop/cop/mixin/trailing_comma.rb +3 -3
- data/lib/rubocop/cop/naming/accessor_method_name.rb +6 -6
- data/lib/rubocop/cop/naming/block_forwarding.rb +20 -16
- data/lib/rubocop/cop/naming/constant_name.rb +6 -7
- data/lib/rubocop/cop/naming/file_name.rb +0 -2
- data/lib/rubocop/cop/naming/inclusive_language.rb +12 -3
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +11 -12
- data/lib/rubocop/cop/naming/predicate_name.rb +45 -1
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +6 -14
- data/lib/rubocop/cop/naming/variable_name.rb +3 -4
- data/lib/rubocop/cop/naming/variable_number.rb +2 -3
- data/lib/rubocop/cop/offense.rb +4 -5
- data/lib/rubocop/cop/security/compound_hash.rb +2 -0
- data/lib/rubocop/cop/security/yaml_load.rb +3 -2
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +96 -28
- data/lib/rubocop/cop/style/accessor_grouping.rb +10 -2
- data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +79 -0
- data/lib/rubocop/cop/style/and_or.rb +1 -1
- data/lib/rubocop/cop/style/arguments_forwarding.rb +78 -22
- data/lib/rubocop/cop/style/array_first_last.rb +18 -2
- data/lib/rubocop/cop/style/array_intersect.rb +5 -4
- data/lib/rubocop/cop/style/bitwise_predicate.rb +100 -0
- data/lib/rubocop/cop/style/block_delimiters.rb +49 -19
- data/lib/rubocop/cop/style/case_like_if.rb +8 -11
- data/lib/rubocop/cop/style/class_and_module_children.rb +6 -3
- data/lib/rubocop/cop/style/collection_compact.rb +10 -10
- data/lib/rubocop/cop/style/collection_methods.rb +1 -1
- data/lib/rubocop/cop/style/combinable_defined.rb +115 -0
- data/lib/rubocop/cop/style/combinable_loops.rb +9 -2
- data/lib/rubocop/cop/style/commented_keyword.rb +17 -1
- data/lib/rubocop/cop/style/concat_array_literals.rb +1 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +26 -26
- data/lib/rubocop/cop/style/constant_visibility.rb +3 -12
- data/lib/rubocop/cop/style/data_inheritance.rb +1 -1
- data/lib/rubocop/cop/style/dig_chain.rb +89 -0
- data/lib/rubocop/cop/style/documentation.rb +1 -1
- data/lib/rubocop/cop/style/double_negation.rb +3 -3
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +4 -7
- data/lib/rubocop/cop/style/each_with_object.rb +2 -3
- data/lib/rubocop/cop/style/empty_else.rb +4 -2
- data/lib/rubocop/cop/style/empty_literal.rb +1 -1
- data/lib/rubocop/cop/style/empty_method.rb +1 -1
- data/lib/rubocop/cop/style/endless_method.rb +1 -14
- data/lib/rubocop/cop/style/eval_with_location.rb +2 -2
- data/lib/rubocop/cop/style/exact_regexp_match.rb +2 -3
- data/lib/rubocop/cop/style/explicit_block_argument.rb +15 -2
- data/lib/rubocop/cop/style/exponential_notation.rb +1 -1
- data/lib/rubocop/cop/style/fetch_env_var.rb +2 -1
- data/lib/rubocop/cop/style/file_null.rb +89 -0
- data/lib/rubocop/cop/style/file_touch.rb +75 -0
- data/lib/rubocop/cop/style/float_division.rb +8 -4
- data/lib/rubocop/cop/style/for.rb +0 -1
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
- data/lib/rubocop/cop/style/global_vars.rb +1 -3
- data/lib/rubocop/cop/style/guard_clause.rb +16 -3
- data/lib/rubocop/cop/style/hash_conversion.rb +1 -2
- data/lib/rubocop/cop/style/hash_each_methods.rb +9 -6
- data/lib/rubocop/cop/style/hash_except.rb +35 -147
- data/lib/rubocop/cop/style/hash_slice.rb +80 -0
- data/lib/rubocop/cop/style/hash_syntax.rb +8 -5
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +22 -3
- data/lib/rubocop/cop/style/if_inside_else.rb +1 -2
- data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -3
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +2 -3
- data/lib/rubocop/cop/style/if_with_semicolon.rb +26 -11
- data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
- data/lib/rubocop/cop/style/inverse_methods.rb +6 -7
- data/lib/rubocop/cop/style/it_assignment.rb +36 -0
- data/lib/rubocop/cop/style/keyword_arguments_merging.rb +67 -0
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +1 -1
- data/lib/rubocop/cop/style/lambda.rb +1 -1
- data/lib/rubocop/cop/style/lambda_call.rb +3 -2
- data/lib/rubocop/cop/style/map_into_array.rb +60 -9
- data/lib/rubocop/cop/style/map_to_hash.rb +1 -1
- data/lib/rubocop/cop/style/map_to_set.rb +3 -2
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +32 -20
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -0
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +8 -11
- data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +2 -4
- data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/missing_else.rb +2 -0
- data/lib/rubocop/cop/style/missing_respond_to_missing.rb +33 -3
- data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -1
- data/lib/rubocop/cop/style/multiline_memoization.rb +2 -2
- data/lib/rubocop/cop/style/multiple_comparison.rb +52 -51
- data/lib/rubocop/cop/style/mutable_constant.rb +7 -8
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +7 -5
- data/lib/rubocop/cop/style/nested_modifier.rb +1 -1
- data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +2 -2
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +5 -4
- data/lib/rubocop/cop/style/not.rb +1 -1
- data/lib/rubocop/cop/style/object_then.rb +14 -15
- data/lib/rubocop/cop/style/one_line_conditional.rb +29 -4
- data/lib/rubocop/cop/style/open_struct_use.rb +5 -5
- data/lib/rubocop/cop/style/operator_method_call.rb +25 -7
- data/lib/rubocop/cop/style/or_assignment.rb +3 -6
- data/lib/rubocop/cop/style/parallel_assignment.rb +9 -18
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +2 -2
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
- data/lib/rubocop/cop/style/proc.rb +1 -2
- data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
- data/lib/rubocop/cop/style/raise_args.rb +7 -5
- data/lib/rubocop/cop/style/random_with_offset.rb +3 -3
- data/lib/rubocop/cop/style/redundant_argument.rb +3 -1
- data/lib/rubocop/cop/style/redundant_assignment.rb +1 -1
- data/lib/rubocop/cop/style/redundant_begin.rb +5 -1
- data/lib/rubocop/cop/style/redundant_condition.rb +39 -24
- data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +2 -1
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +6 -10
- data/lib/rubocop/cop/style/redundant_each.rb +1 -1
- data/lib/rubocop/cop/style/redundant_exception.rb +2 -2
- data/lib/rubocop/cop/style/redundant_format.rb +238 -0
- data/lib/rubocop/cop/style/redundant_freeze.rb +2 -2
- data/lib/rubocop/cop/style/redundant_initialize.rb +12 -3
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +56 -17
- data/lib/rubocop/cop/style/redundant_parentheses.rb +37 -25
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +4 -0
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +1 -1
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +1 -1
- data/lib/rubocop/cop/style/redundant_return.rb +2 -2
- data/lib/rubocop/cop/style/redundant_self.rb +8 -15
- data/lib/rubocop/cop/style/redundant_self_assignment.rb +20 -32
- data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +4 -4
- data/lib/rubocop/cop/style/redundant_sort.rb +3 -3
- data/lib/rubocop/cop/style/redundant_string_escape.rb +2 -2
- data/lib/rubocop/cop/style/require_order.rb +1 -1
- data/lib/rubocop/cop/style/rescue_modifier.rb +15 -4
- data/lib/rubocop/cop/style/return_nil.rb +1 -1
- data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +54 -12
- data/lib/rubocop/cop/style/safe_navigation.rb +105 -51
- data/lib/rubocop/cop/style/safe_navigation_chain_length.rb +52 -0
- data/lib/rubocop/cop/style/select_by_regexp.rb +10 -7
- data/lib/rubocop/cop/style/self_assignment.rb +11 -17
- data/lib/rubocop/cop/style/semicolon.rb +2 -2
- data/lib/rubocop/cop/style/send_with_literal_method_name.rb +2 -1
- data/lib/rubocop/cop/style/signal_exception.rb +2 -3
- data/lib/rubocop/cop/style/single_argument_dig.rb +9 -5
- data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
- data/lib/rubocop/cop/style/single_line_do_end_block.rb +12 -3
- data/lib/rubocop/cop/style/single_line_methods.rb +3 -4
- data/lib/rubocop/cop/style/slicing_with_range.rb +40 -11
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +4 -5
- data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
- data/lib/rubocop/cop/style/string_concatenation.rb +14 -13
- data/lib/rubocop/cop/style/string_literals.rb +1 -1
- data/lib/rubocop/cop/style/string_methods.rb +1 -1
- data/lib/rubocop/cop/style/struct_inheritance.rb +1 -1
- data/lib/rubocop/cop/style/super_arguments.rb +65 -17
- data/lib/rubocop/cop/style/swap_values.rb +4 -15
- data/lib/rubocop/cop/style/ternary_parentheses.rb +26 -5
- data/lib/rubocop/cop/style/top_level_method_definition.rb +1 -1
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -1
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +4 -4
- data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
- data/lib/rubocop/cop/style/variable_interpolation.rb +1 -2
- data/lib/rubocop/cop/style/while_until_modifier.rb +0 -1
- data/lib/rubocop/cop/style/yoda_condition.rb +8 -4
- data/lib/rubocop/cop/style/yoda_expression.rb +2 -1
- data/lib/rubocop/cop/team.rb +8 -1
- data/lib/rubocop/cop/util.rb +12 -5
- data/lib/rubocop/cop/utils/format_string.rb +7 -5
- data/lib/rubocop/cop/variable_force/assignment.rb +18 -3
- data/lib/rubocop/cop/variable_force/branch.rb +1 -1
- data/lib/rubocop/cop/variable_force/variable.rb +18 -2
- data/lib/rubocop/cop/variable_force/variable_table.rb +5 -5
- data/lib/rubocop/cop/variable_force.rb +4 -10
- data/lib/rubocop/cops_documentation_generator.rb +100 -51
- data/lib/rubocop/directive_comment.rb +44 -10
- data/lib/rubocop/file_finder.rb +9 -4
- data/lib/rubocop/formatter/disabled_config_formatter.rb +1 -1
- data/lib/rubocop/formatter/formatter_set.rb +1 -1
- data/lib/rubocop/lsp/diagnostic.rb +189 -0
- data/lib/rubocop/lsp/logger.rb +2 -2
- data/lib/rubocop/lsp/routes.rb +7 -23
- data/lib/rubocop/lsp/runtime.rb +18 -48
- data/lib/rubocop/lsp/server.rb +0 -3
- data/lib/rubocop/lsp/stdin_runner.rb +83 -0
- data/lib/rubocop/magic_comment.rb +3 -3
- data/lib/rubocop/options.rb +28 -12
- data/lib/rubocop/path_util.rb +15 -8
- data/lib/rubocop/plugin/configuration_integrator.rb +143 -0
- data/lib/rubocop/plugin/load_error.rb +26 -0
- data/lib/rubocop/plugin/loader.rb +100 -0
- data/lib/rubocop/plugin/not_supported_error.rb +29 -0
- data/lib/rubocop/plugin.rb +39 -0
- data/lib/rubocop/rake_task.rb +4 -1
- data/lib/rubocop/result_cache.rb +13 -13
- data/lib/rubocop/rspec/cop_helper.rb +9 -0
- data/lib/rubocop/rspec/expect_offense.rb +7 -2
- data/lib/rubocop/rspec/shared_contexts.rb +4 -1
- data/lib/rubocop/rspec/support.rb +1 -2
- data/lib/rubocop/runner.rb +22 -12
- data/lib/rubocop/server/cache.rb +39 -1
- data/lib/rubocop/server/cli.rb +2 -2
- data/lib/rubocop/server/core.rb +1 -0
- data/lib/rubocop/target_finder.rb +1 -0
- data/lib/rubocop/target_ruby.rb +28 -13
- data/lib/rubocop/version.rb +42 -6
- data/lib/rubocop/yaml_duplication_checker.rb +20 -27
- data/lib/rubocop.rb +29 -0
- data/lib/ruby_lsp/rubocop/addon.rb +75 -0
- data/lib/ruby_lsp/rubocop/runtime_adapter.rb +47 -0
- metadata +75 -19
- data/lib/rubocop/rspec/host_environment_simulation_helper.rb +0 -28
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module InternalAffairs
|
6
|
+
# Use `config.cop_enabled?('Department/CopName')` instead of
|
7
|
+
# traversing the config hash.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # `for_cop(...)['Enabled']
|
11
|
+
#
|
12
|
+
# # bad
|
13
|
+
# config.for_cop('Department/CopName')['Enabled']
|
14
|
+
#
|
15
|
+
# # good
|
16
|
+
# config.cop_enabled?('Department/CopName')
|
17
|
+
#
|
18
|
+
# @example
|
19
|
+
# # when keeping a cop's config in a local and then checking the `Enabled` key
|
20
|
+
#
|
21
|
+
# # bad
|
22
|
+
# cop_config = config.for_cop('Department/CopName')
|
23
|
+
# cop_config['Enabled'] && cop_config['Foo']
|
24
|
+
#
|
25
|
+
# # good
|
26
|
+
# config.for_enabled_cop('Department/CopName')['Foo']
|
27
|
+
#
|
28
|
+
class CopEnabled < Base
|
29
|
+
extend AutoCorrector
|
30
|
+
|
31
|
+
MSG = 'Use `%<replacement>s` instead of `%<source>s`.'
|
32
|
+
MSG_HASH = 'Consider replacing uses of `%<hash_name>s` with `config.for_enabled_cop`.'
|
33
|
+
|
34
|
+
RESTRICT_ON_SEND = [:[]].freeze
|
35
|
+
|
36
|
+
# @!method for_cop_enabled?(node)
|
37
|
+
def_node_matcher :for_cop_enabled?, <<~PATTERN
|
38
|
+
(send
|
39
|
+
(send
|
40
|
+
${(send nil? :config) (ivar :@config)} :for_cop
|
41
|
+
$(str _)) :[]
|
42
|
+
(str "Enabled"))
|
43
|
+
PATTERN
|
44
|
+
|
45
|
+
# @!method config_enabled_lookup?(node)
|
46
|
+
def_node_matcher :config_enabled_lookup?, <<~PATTERN
|
47
|
+
(send
|
48
|
+
{(lvar $_) (ivar $_) (send nil? $_)} :[]
|
49
|
+
(str "Enabled"))
|
50
|
+
PATTERN
|
51
|
+
|
52
|
+
def on_send(node)
|
53
|
+
if (config_var, cop_name = for_cop_enabled?(node))
|
54
|
+
handle_for_cop(node, config_var, cop_name)
|
55
|
+
elsif (config_var = config_enabled_lookup?(node))
|
56
|
+
return unless config_var.end_with?('_config')
|
57
|
+
|
58
|
+
handle_hash(node, config_var)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def handle_for_cop(node, config_var, cop_name)
|
65
|
+
source = node.source
|
66
|
+
quote = cop_name.loc.begin.source
|
67
|
+
cop_name = cop_name.value
|
68
|
+
|
69
|
+
replacement = "#{config_var.source}.cop_enabled?(#{quote}#{cop_name}#{quote})"
|
70
|
+
message = format(MSG, source: source, replacement: replacement)
|
71
|
+
|
72
|
+
add_offense(node, message: message) do |corrector|
|
73
|
+
corrector.replace(node, replacement)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def handle_hash(node, config_var)
|
78
|
+
message = format(MSG_HASH, hash_name: config_var)
|
79
|
+
|
80
|
+
add_offense(node, message: message)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -90,8 +90,10 @@ module RuboCop
|
|
90
90
|
description_text = string_contents(current_description)
|
91
91
|
return unless (new_description = correct_description(description_text, description_map))
|
92
92
|
|
93
|
+
quote = current_description.dstr_type? ? '"' : "'"
|
94
|
+
|
93
95
|
add_offense(current_description, message: message) do |corrector|
|
94
|
-
corrector.replace(current_description, "
|
96
|
+
corrector.replace(current_description, "#{quote}#{new_description}#{quote}")
|
95
97
|
end
|
96
98
|
end
|
97
99
|
|
@@ -106,7 +108,7 @@ module RuboCop
|
|
106
108
|
end
|
107
109
|
|
108
110
|
def string_contents(node)
|
109
|
-
node.
|
111
|
+
node.type?(:str, :dstr) ? node.value : node.source
|
110
112
|
end
|
111
113
|
end
|
112
114
|
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module InternalAffairs
|
6
|
+
# When a node location may not exist, `Node#loc?` or `Node#loc_is?`
|
7
|
+
# can be used instead of calling `Node#respond_to?` before using
|
8
|
+
# the value.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# # bad
|
12
|
+
# node.loc.respond_to?(:begin) && node.loc.begin
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# node.loc?(:begin)
|
16
|
+
#
|
17
|
+
# # bad
|
18
|
+
# node.loc.respond_to?(:begin) && node.loc.begin.is?('(')
|
19
|
+
#
|
20
|
+
# # good
|
21
|
+
# node.loc_is?(:begin, '(')
|
22
|
+
#
|
23
|
+
# # bad
|
24
|
+
# node.loc.respond_to?(:begin) && node.loc.begin.source == '('
|
25
|
+
#
|
26
|
+
# # good
|
27
|
+
# node.loc_is?(:begin, '(')
|
28
|
+
#
|
29
|
+
class LocationExists < Base
|
30
|
+
extend AutoCorrector
|
31
|
+
|
32
|
+
MSG = 'Use `%<replacement>s` instead of `%<source>s`.'
|
33
|
+
|
34
|
+
# @!method replaceable_with_loc_is(node)
|
35
|
+
def_node_matcher :replaceable_with_loc_is, <<~PATTERN
|
36
|
+
(and
|
37
|
+
(call
|
38
|
+
(call $_receiver :loc) :respond_to?
|
39
|
+
$(sym _location))
|
40
|
+
{
|
41
|
+
(call
|
42
|
+
(call
|
43
|
+
(call _receiver :loc) _location) :is?
|
44
|
+
$(str _))
|
45
|
+
(call
|
46
|
+
(call
|
47
|
+
(call
|
48
|
+
(call _receiver :loc) _location) :source) :==
|
49
|
+
$(str _))
|
50
|
+
})
|
51
|
+
PATTERN
|
52
|
+
|
53
|
+
# @!method replaceable_with_loc(node)
|
54
|
+
def_node_matcher :replaceable_with_loc, <<~PATTERN
|
55
|
+
(and
|
56
|
+
(call
|
57
|
+
(call $_receiver :loc) :respond_to?
|
58
|
+
$(sym _location))
|
59
|
+
(call
|
60
|
+
(call _receiver :loc) _location))
|
61
|
+
PATTERN
|
62
|
+
|
63
|
+
def on_and(node)
|
64
|
+
replace_with_loc(node) || replace_with_loc_is(node)
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def replace_with_loc(node)
|
70
|
+
replaceable_with_loc(node) do |receiver, location|
|
71
|
+
if node.parent&.assignment?
|
72
|
+
register_offense(node, replace_assignment(receiver, location))
|
73
|
+
else
|
74
|
+
register_offense(node, replacement(receiver, "loc?(#{location.source})"))
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def replace_with_loc_is(node)
|
80
|
+
replaceable_with_loc_is(node) do |receiver, location, value|
|
81
|
+
replacement = replacement(receiver, "loc_is?(#{location.source}, #{value.source})")
|
82
|
+
register_offense(node, replacement)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def register_offense(node, replacement)
|
87
|
+
message = format(MSG, replacement: replacement, source: node.source)
|
88
|
+
|
89
|
+
add_offense(node, message: message) do |corrector|
|
90
|
+
corrector.replace(node, replacement)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def replacement(receiver, rest)
|
95
|
+
"#{replace_receiver(receiver)}#{rest}"
|
96
|
+
end
|
97
|
+
|
98
|
+
def replace_assignment(receiver, location)
|
99
|
+
prefix = replace_receiver(receiver)
|
100
|
+
|
101
|
+
"#{prefix}loc#{dot(receiver)}#{location.value} if #{prefix}loc?(#{location.source})"
|
102
|
+
end
|
103
|
+
|
104
|
+
def replace_receiver(receiver)
|
105
|
+
return '' unless receiver
|
106
|
+
|
107
|
+
"#{receiver.source}#{dot(receiver)}"
|
108
|
+
end
|
109
|
+
|
110
|
+
def dot(node)
|
111
|
+
node.parent.loc.dot.source
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -22,7 +22,7 @@ module RuboCop
|
|
22
22
|
|
23
23
|
def on_send(node)
|
24
24
|
return unless (parent = node.parent)
|
25
|
-
return unless parent.
|
25
|
+
return unless parent.call_type? && parent.method?(:expression)
|
26
26
|
return unless parent.receiver.receiver
|
27
27
|
|
28
28
|
offense = node.loc.selector.join(parent.source_range.end)
|
@@ -31,6 +31,7 @@ module RuboCop
|
|
31
31
|
corrector.replace(offense, 'source_range')
|
32
32
|
end
|
33
33
|
end
|
34
|
+
alias on_csend on_send
|
34
35
|
end
|
35
36
|
end
|
36
37
|
end
|
@@ -19,6 +19,7 @@ module RuboCop
|
|
19
19
|
extend AutoCorrector
|
20
20
|
|
21
21
|
MSG = 'Use `%<preferred>s`.'
|
22
|
+
RESTRICT_ON_SEND = [:==].freeze
|
22
23
|
|
23
24
|
# @!method line_send(node)
|
24
25
|
def_node_matcher :line_send, <<~PATTERN
|
@@ -36,10 +37,8 @@ module RuboCop
|
|
36
37
|
def on_send(node)
|
37
38
|
return unless location_line_equality_comparison?(node)
|
38
39
|
|
39
|
-
|
40
|
-
|
41
|
-
lhs_receiver = extract_receiver(lhs)
|
42
|
-
rhs_receiver = extract_receiver(rhs)
|
40
|
+
lhs_receiver = extract_receiver(node.receiver)
|
41
|
+
rhs_receiver = extract_receiver(node.first_argument)
|
43
42
|
preferred = "same_line?(#{lhs_receiver}, #{rhs_receiver})"
|
44
43
|
|
45
44
|
add_offense(node, message: format(MSG, preferred: preferred)) do |corrector|
|
@@ -27,8 +27,8 @@ module RuboCop
|
|
27
27
|
# @!method arguments_first_or_last?(node)
|
28
28
|
def_node_matcher :arguments_first_or_last?, <<~PATTERN
|
29
29
|
{
|
30
|
-
(
|
31
|
-
(
|
30
|
+
(call (call !nil? :arguments) ${:first :last})
|
31
|
+
(call (call !nil? :arguments) :[] (int ${0 -1}))
|
32
32
|
}
|
33
33
|
PATTERN
|
34
34
|
|
@@ -47,6 +47,7 @@ module RuboCop
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
end
|
50
|
+
alias on_csend on_send
|
50
51
|
end
|
51
52
|
end
|
52
53
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module InternalAffairs
|
6
|
+
class NodePatternGroups
|
7
|
+
# AST Processor for NodePattern ASTs, for use with `InternalAffairs/NodePatternGroups`.
|
8
|
+
#
|
9
|
+
# Looks for sequences and subsequences where the first item is a `node_type` node,
|
10
|
+
# and converts them to `node_sequence` nodes (not a true `Rubocop::AST::NodePattern`
|
11
|
+
# node type).
|
12
|
+
#
|
13
|
+
# The resulting AST will be walked by `InternalAffairs::NodePatternGroups::ASTWalker`
|
14
|
+
# in order to find node types in a `union` node that can be rewritten as a node group.
|
15
|
+
#
|
16
|
+
# NOTE: The `on_*` methods in this class relate not to the normal node types but
|
17
|
+
# rather to the Node Pattern node types. Not every node type is handled.
|
18
|
+
#
|
19
|
+
class ASTProcessor
|
20
|
+
include ::AST::Processor::Mixin
|
21
|
+
|
22
|
+
def handler_missing(node)
|
23
|
+
node.updated(nil, process_children(node))
|
24
|
+
end
|
25
|
+
|
26
|
+
# Look for `sequence` and `subsequence` nodes that contain a `node_type` node as
|
27
|
+
# their first child. These are rewritten as `node_sequence` nodes so that it is
|
28
|
+
# possible to compare nodes while looking for replacement candidates for node groups.
|
29
|
+
# This is necessary so that extended patterns can be matched and replaced.
|
30
|
+
# ie. `{(send _ :foo ...) (csend _ :foo ...)}` can become `(call _ :foo ...)`
|
31
|
+
def on_sequence(node)
|
32
|
+
first_child = node.child
|
33
|
+
|
34
|
+
if first_child.type == :node_type
|
35
|
+
children = [first_child.child, *process_children(node, 1..)]
|
36
|
+
|
37
|
+
# The `node_sequence` node contains the `node_type` symbol as its first child,
|
38
|
+
# followed by all the other nodes contained in the `sequence` node.
|
39
|
+
# The location is copied from the sequence, so that the entire sequence can
|
40
|
+
# eventually be corrected in the cop.
|
41
|
+
n(:node_sequence, children, location: node.location)
|
42
|
+
else
|
43
|
+
node.updated(nil, process_children(node))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
alias on_subsequence on_sequence
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def n(type, children = [], properties = {})
|
51
|
+
NodePattern::Node.new(type, children, properties)
|
52
|
+
end
|
53
|
+
|
54
|
+
def process_children(node, range = 0..-1)
|
55
|
+
node.children[range].map do |child|
|
56
|
+
child.is_a?(::AST::Node) ? process(child) : child
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module InternalAffairs
|
6
|
+
# rubocop:disable InternalAffairs/RedundantSourceRange -- node here is a `NodePattern::Node`
|
7
|
+
class NodePatternGroups
|
8
|
+
# Walks an AST that has been processed by `InternalAffairs::NodePatternGroups::Processor`
|
9
|
+
# in order to find `node_type` and `node_sequence` nodes that can be replaced with a node
|
10
|
+
# group in `InternalAffairs/NodePatternGroups`.
|
11
|
+
#
|
12
|
+
# Calling `ASTWalker#walk` sets `node_groups` with an array of `NodeGroup` structs
|
13
|
+
# that contain metadata about nodes that can be replaced, including location data. That
|
14
|
+
# metadata is used by the cop to register offenses and perform corrections.
|
15
|
+
class ASTWalker
|
16
|
+
# Struct to contain data about parts of a node pattern that can be replaced
|
17
|
+
NodeGroup = Struct.new(
|
18
|
+
:name, # The name of the node group that will be inserted
|
19
|
+
:union, # The entire `union` node
|
20
|
+
:node_types, # An array of `node_type` nodes that will be removed
|
21
|
+
:sequence?, # The pattern matches a node type with given attributes
|
22
|
+
:start_index, # The index in the union of the first node type to remove
|
23
|
+
:offense_range, # The range to mark an offense on
|
24
|
+
:ranges, # Range of each element to remove, since they may not be adjacent
|
25
|
+
:pipe, # Is the union delimited by pipes?
|
26
|
+
:other_elements?, # Does the union have other elements other than those to remove?
|
27
|
+
keyword_init: true
|
28
|
+
)
|
29
|
+
|
30
|
+
def initialize
|
31
|
+
reset!
|
32
|
+
end
|
33
|
+
|
34
|
+
def reset!
|
35
|
+
@node_groups = []
|
36
|
+
end
|
37
|
+
|
38
|
+
attr_reader :node_groups
|
39
|
+
|
40
|
+
# Recursively walk the AST in a depth-first manner.
|
41
|
+
# Only `union` nodes are handled further.
|
42
|
+
def walk(node)
|
43
|
+
return if node.nil?
|
44
|
+
|
45
|
+
on_union(node) if node.type == :union
|
46
|
+
|
47
|
+
node.child_nodes.each do |child|
|
48
|
+
walk(child)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Search `union` nodes for `node_type` and `node_sequence` nodes that can be
|
53
|
+
# collapsed into a node group.
|
54
|
+
# * `node_type` nodes are nodes with no further configuration (ie. `send`)
|
55
|
+
# * `node_sequence` nodes are nodes with further configuration (ie. `(send ...)`)
|
56
|
+
#
|
57
|
+
# Each group of types that can be collapsed will have a `NodeGroup` record added
|
58
|
+
# to `node_groups`, which is then used by the cop.
|
59
|
+
def on_union(node)
|
60
|
+
all_node_types = each_child_node(node, :node_type, :node_sequence).to_a
|
61
|
+
|
62
|
+
each_node_group(all_node_types) do |group_name, node_types|
|
63
|
+
next unless sequences_match?(node_types)
|
64
|
+
|
65
|
+
node_groups << node_group_data(
|
66
|
+
group_name, node, node_types,
|
67
|
+
all_node_types.index(node_types.first),
|
68
|
+
(node.children - node_types).any?
|
69
|
+
)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def each_child_node(node, *types)
|
76
|
+
return to_enum(__method__, node, *types) unless block_given?
|
77
|
+
|
78
|
+
node.children.each do |child|
|
79
|
+
yield child if types.empty? || types.include?(child.type)
|
80
|
+
end
|
81
|
+
|
82
|
+
self
|
83
|
+
end
|
84
|
+
|
85
|
+
def each_node_group(types_to_check)
|
86
|
+
# Find all node groups where all of the members are present in the union
|
87
|
+
type_names = types_to_check.map(&:child)
|
88
|
+
|
89
|
+
NODE_GROUPS.select { |_, group| group & type_names == group }.each_key do |name|
|
90
|
+
nodes = get_relevant_nodes(types_to_check, name)
|
91
|
+
|
92
|
+
yield name, nodes
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def get_relevant_nodes(node_types, group_name)
|
97
|
+
node_types.each_with_object([]) do |node_type, arr|
|
98
|
+
next unless NODE_GROUPS[group_name].include?(node_type.child)
|
99
|
+
|
100
|
+
arr << node_type
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def node_group_data(name, union, node_types, start_index, other)
|
105
|
+
NodeGroup.new(
|
106
|
+
name: name,
|
107
|
+
union: union,
|
108
|
+
node_types: node_types,
|
109
|
+
sequence?: node_types.first.type == :node_sequence,
|
110
|
+
start_index: start_index,
|
111
|
+
pipe: union.source_range.source['|'],
|
112
|
+
other_elements?: other
|
113
|
+
)
|
114
|
+
end
|
115
|
+
|
116
|
+
def sequences_match?(types)
|
117
|
+
# Ensure all given types have the same type and the same sequence
|
118
|
+
# ie. `(send ...)` and `(csend ...) is a match
|
119
|
+
# `(send)` and `(csend ...)` is not a match
|
120
|
+
# `send` and `(csend ...)` is not a match
|
121
|
+
|
122
|
+
types.each_cons(2).all? do |left, right|
|
123
|
+
left.type == right.type && left.children[1..] == right.children[1..]
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
# rubocop:enable InternalAffairs/RedundantSourceRange
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|