rubocop 1.69.2 → 1.74.0
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 +4 -4
- data/config/default.yml +122 -17
- data/config/internal_affairs.yml +20 -0
- data/lib/rubocop/cli/command/execute_runner.rb +3 -3
- data/lib/rubocop/cli/command/show_cops.rb +24 -2
- data/lib/rubocop/cli/command/suggest_extensions.rb +7 -1
- data/lib/rubocop/comment_config.rb +2 -2
- data/lib/rubocop/config.rb +17 -4
- data/lib/rubocop/config_loader.rb +48 -9
- data/lib/rubocop/config_loader_resolver.rb +36 -10
- data/lib/rubocop/config_obsoletion/extracted_cop.rb +4 -3
- data/lib/rubocop/config_obsoletion.rb +1 -1
- data/lib/rubocop/config_validator.rb +19 -9
- data/lib/rubocop/cop/autocorrect_logic.rb +1 -1
- data/lib/rubocop/cop/base.rb +6 -0
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -1
- data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/cop_enabled.rb +85 -0
- data/lib/rubocop/cop/internal_affairs/example_description.rb +7 -3
- 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/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_group.rb +91 -0
- data/lib/rubocop/cop/internal_affairs/node_type_multiple_predicates.rb +126 -0
- data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +4 -3
- data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +90 -0
- data/lib/rubocop/cop/internal_affairs/plugin.rb +33 -0
- data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +3 -1
- data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +5 -4
- data/lib/rubocop/cop/internal_affairs/undefined_config.rb +7 -1
- data/lib/rubocop/cop/internal_affairs.rb +6 -16
- data/lib/rubocop/cop/layout/access_modifier_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/argument_alignment.rb +2 -8
- data/lib/rubocop/cop/layout/block_alignment.rb +3 -1
- data/lib/rubocop/cop/layout/class_structure.rb +9 -9
- data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +4 -4
- 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 +1 -1
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +7 -11
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +27 -1
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +22 -2
- data/lib/rubocop/cop/layout/end_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/extra_spacing.rb +1 -1
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +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_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/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 +4 -3
- data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +25 -0
- data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -0
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +4 -4
- data/lib/rubocop/cop/layout/redundant_line_break.rb +7 -6
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +1 -1
- 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 +1 -0
- data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_operators.rb +3 -3
- 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/trailing_whitespace.rb +5 -3
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -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/binary_operator_with_identical_operands.rb +1 -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 +1 -1
- data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_methods.rb +0 -14
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_set_element.rb +20 -7
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +14 -64
- data/lib/rubocop/cop/lint/empty_expression.rb +0 -2
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +0 -6
- data/lib/rubocop/cop/lint/float_comparison.rb +6 -8
- data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -1
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +2 -2
- data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
- data/lib/rubocop/cop/lint/literal_as_condition.rb +103 -9
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +24 -6
- data/lib/rubocop/cop/lint/missing_super.rb +2 -2
- data/lib/rubocop/cop/lint/mixed_case_range.rb +3 -3
- data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -1
- data/lib/rubocop/cop/lint/nested_method_definition.rb +8 -4
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
- data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +4 -3
- data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +3 -3
- data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +18 -31
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +2 -1
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -5
- data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +0 -21
- data/lib/rubocop/cop/lint/redundant_string_coercion.rb +2 -2
- data/lib/rubocop/cop/lint/redundant_type_conversion.rb +258 -0
- data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
- data/lib/rubocop/cop/lint/return_in_void_context.rb +4 -11
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +8 -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/unescaped_bracket_in_regexp.rb +1 -4
- 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 +1 -1
- data/lib/rubocop/cop/lint/unreachable_loop.rb +1 -1
- 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 +71 -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_ruby2_keywords.rb +2 -2
- data/lib/rubocop/cop/lint/void.rb +11 -9
- data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
- data/lib/rubocop/cop/metrics/collection_literal_length.rb +7 -0
- data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +1 -1
- data/lib/rubocop/cop/metrics/method_length.rb +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/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_line_breakable.rb +11 -11
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +1 -1
- data/lib/rubocop/cop/mixin/comments_help.rb +4 -2
- data/lib/rubocop/cop/mixin/dig_help.rb +1 -1
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -1
- 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/method_complexity.rb +1 -1
- data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +48 -24
- data/lib/rubocop/cop/mixin/range_help.rb +15 -3
- data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
- data/lib/rubocop/cop/mixin/statement_modifier.rb +8 -3
- data/lib/rubocop/cop/mixin/string_help.rb +2 -2
- data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -1
- data/lib/rubocop/cop/mixin/target_ruby_version.rb +1 -1
- data/lib/rubocop/cop/mixin/trailing_comma.rb +15 -3
- data/lib/rubocop/cop/naming/block_forwarding.rb +19 -15
- data/lib/rubocop/cop/naming/predicate_name.rb +44 -0
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +3 -3
- data/lib/rubocop/cop/naming/variable_name.rb +64 -6
- data/lib/rubocop/cop/security/compound_hash.rb +1 -0
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +34 -5
- data/lib/rubocop/cop/style/accessor_grouping.rb +19 -5
- data/lib/rubocop/cop/style/and_or.rb +1 -1
- data/lib/rubocop/cop/style/arguments_forwarding.rb +39 -23
- data/lib/rubocop/cop/style/array_first_last.rb +18 -2
- data/lib/rubocop/cop/style/block_delimiters.rb +7 -20
- data/lib/rubocop/cop/style/class_and_module_children.rb +35 -10
- data/lib/rubocop/cop/style/collection_methods.rb +1 -1
- data/lib/rubocop/cop/style/combinable_defined.rb +1 -1
- data/lib/rubocop/cop/style/combinable_loops.rb +2 -2
- data/lib/rubocop/cop/style/commented_keyword.rb +10 -3
- data/lib/rubocop/cop/style/comparable_between.rb +75 -0
- data/lib/rubocop/cop/style/concat_array_literals.rb +1 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +6 -4
- 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 +1 -1
- data/lib/rubocop/cop/style/empty_method.rb +1 -1
- data/lib/rubocop/cop/style/endless_method.rb +163 -18
- data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
- data/lib/rubocop/cop/style/exact_regexp_match.rb +3 -10
- data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -7
- data/lib/rubocop/cop/style/explicit_block_argument.rb +15 -2
- data/lib/rubocop/cop/style/exponential_notation.rb +3 -3
- data/lib/rubocop/cop/style/fetch_env_var.rb +1 -1
- data/lib/rubocop/cop/style/float_division.rb +8 -4
- data/lib/rubocop/cop/style/format_string_token.rb +38 -11
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
- data/lib/rubocop/cop/style/hash_each_methods.rb +3 -6
- data/lib/rubocop/cop/style/hash_except.rb +24 -148
- data/lib/rubocop/cop/style/hash_slice.rb +80 -0
- data/lib/rubocop/cop/style/hash_syntax.rb +6 -3
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +22 -3
- data/lib/rubocop/cop/style/if_unless_modifier.rb +5 -5
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +1 -1
- data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -2
- data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
- data/lib/rubocop/cop/style/inverse_methods.rb +14 -11
- data/lib/rubocop/cop/style/it_assignment.rb +36 -0
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +14 -8
- data/lib/rubocop/cop/style/line_end_concatenation.rb +10 -4
- data/lib/rubocop/cop/style/map_into_array.rb +1 -1
- 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 +22 -15
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -0
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -1
- 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/multiline_block_chain.rb +2 -2
- data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -9
- data/lib/rubocop/cop/style/multiple_comparison.rb +26 -20
- data/lib/rubocop/cop/style/mutable_constant.rb +3 -3
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +1 -1
- data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
- data/lib/rubocop/cop/style/object_then.rb +13 -15
- data/lib/rubocop/cop/style/open_struct_use.rb +5 -5
- data/lib/rubocop/cop/style/parallel_assignment.rb +1 -5
- 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 +6 -4
- data/lib/rubocop/cop/style/random_with_offset.rb +3 -3
- data/lib/rubocop/cop/style/redundant_begin.rb +1 -1
- data/lib/rubocop/cop/style/redundant_condition.rb +47 -2
- data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +16 -5
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +6 -10
- data/lib/rubocop/cop/style/redundant_each.rb +1 -1
- data/lib/rubocop/cop/style/redundant_exception.rb +2 -2
- data/lib/rubocop/cop/style/redundant_format.rb +250 -0
- data/lib/rubocop/cop/style/redundant_freeze.rb +3 -3
- data/lib/rubocop/cop/style/redundant_initialize.rb +12 -3
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +34 -13
- data/lib/rubocop/cop/style/redundant_parentheses.rb +28 -14
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +3 -0
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +1 -1
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +1 -1
- data/lib/rubocop/cop/style/redundant_self_assignment.rb +14 -28
- data/lib/rubocop/cop/style/redundant_sort.rb +2 -2
- data/lib/rubocop/cop/style/redundant_string_escape.rb +2 -2
- data/lib/rubocop/cop/style/rescue_modifier.rb +3 -0
- data/lib/rubocop/cop/style/return_nil.rb +1 -1
- data/lib/rubocop/cop/style/safe_navigation.rb +2 -2
- data/lib/rubocop/cop/style/semicolon.rb +1 -1
- data/lib/rubocop/cop/style/send_with_literal_method_name.rb +2 -1
- data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
- data/lib/rubocop/cop/style/single_line_do_end_block.rb +1 -2
- data/lib/rubocop/cop/style/single_line_methods.rb +6 -7
- data/lib/rubocop/cop/style/slicing_with_range.rb +40 -11
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +2 -8
- data/lib/rubocop/cop/style/string_concatenation.rb +2 -2
- 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/super_arguments.rb +65 -17
- data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
- 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_comma_in_array_literal.rb +47 -6
- data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +48 -6
- data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
- data/lib/rubocop/cop/style/while_until_modifier.rb +0 -1
- data/lib/rubocop/cop/style/yoda_condition.rb +8 -4
- data/lib/rubocop/cop/style/yoda_expression.rb +2 -1
- data/lib/rubocop/cop/util.rb +12 -5
- data/lib/rubocop/cop/utils/format_string.rb +10 -5
- data/lib/rubocop/cop/variable_force/variable.rb +14 -2
- data/lib/rubocop/cop/variable_force/variable_table.rb +3 -3
- data/lib/rubocop/cops_documentation_generator.rb +25 -14
- data/lib/rubocop/directive_comment.rb +45 -11
- data/lib/rubocop/ext/regexp_node.rb +0 -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 +17 -49
- data/lib/rubocop/lsp/server.rb +0 -2
- data/lib/rubocop/lsp/stdin_runner.rb +83 -0
- 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 +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 +9 -0
- data/lib/rubocop/rspec/expect_offense.rb +6 -2
- data/lib/rubocop/rspec/shared_contexts.rb +19 -1
- data/lib/rubocop/rspec/support.rb +2 -2
- data/lib/rubocop/runner.rb +5 -6
- data/lib/rubocop/server/cache.rb +35 -2
- data/lib/rubocop/server/cli.rb +2 -2
- data/lib/rubocop/target_finder.rb +1 -0
- data/lib/rubocop/target_ruby.rb +15 -0
- data/lib/rubocop/version.rb +17 -2
- data/lib/rubocop.rb +12 -1
- data/lib/ruby_lsp/rubocop/addon.rb +75 -0
- data/lib/ruby_lsp/rubocop/runtime_adapter.rb +47 -0
- metadata +55 -16
- data/lib/rubocop/cop/utils/regexp_ranges.rb +0 -113
- data/lib/rubocop/rspec/host_environment_simulation_helper.rb +0 -28
@@ -2,16 +2,35 @@
|
|
2
2
|
|
3
3
|
require 'pathname'
|
4
4
|
require 'yaml'
|
5
|
+
require_relative 'plugin'
|
5
6
|
|
6
7
|
module RuboCop
|
7
8
|
# A help class for ConfigLoader that handles configuration resolution.
|
8
9
|
# @api private
|
9
10
|
class ConfigLoaderResolver # rubocop:disable Metrics/ClassLength
|
11
|
+
def resolve_plugins(rubocop_config, plugins)
|
12
|
+
plugins = Array(plugins) - ConfigLoader.loaded_plugins.map { |plugin| plugin.about.name }
|
13
|
+
return if plugins.empty?
|
14
|
+
|
15
|
+
Plugin.integrate_plugins(rubocop_config, plugins)
|
16
|
+
end
|
17
|
+
|
10
18
|
def resolve_requires(path, hash)
|
11
19
|
config_dir = File.dirname(path)
|
12
20
|
hash.delete('require').tap do |loaded_features|
|
13
21
|
Array(loaded_features).each do |feature|
|
14
|
-
|
22
|
+
if Plugin.plugin_capable?(feature)
|
23
|
+
# NOTE: Compatibility for before plugins style.
|
24
|
+
warn Rainbow(<<~MESSAGE).yellow
|
25
|
+
#{feature} extension supports plugin, specify `plugins: #{feature}` instead of `require: #{feature}` in #{path}.
|
26
|
+
For more information, see https://docs.rubocop.org/rubocop/plugin_migration_guide.html.
|
27
|
+
MESSAGE
|
28
|
+
rubocop_config = Config.create(hash, path, check: false)
|
29
|
+
|
30
|
+
resolve_plugins(rubocop_config, feature)
|
31
|
+
else
|
32
|
+
FeatureLoader.load(config_directory_path: config_dir, feature: feature)
|
33
|
+
end
|
15
34
|
end
|
16
35
|
end
|
17
36
|
end
|
@@ -105,7 +124,7 @@ module RuboCop
|
|
105
124
|
elsif merge_hashes?(base_hash, derived_hash, key)
|
106
125
|
result[key] = merge(base_hash[key], derived_hash[key], **opts)
|
107
126
|
elsif should_union?(derived_hash, base_hash, opts[:inherit_mode], key)
|
108
|
-
result[key] = base_hash[key] | derived_hash[key]
|
127
|
+
result[key] = Array(base_hash[key]) | Array(derived_hash[key])
|
109
128
|
elsif opts[:debug]
|
110
129
|
warn_on_duplicate_setting(base_hash, derived_hash, key, **opts)
|
111
130
|
end
|
@@ -157,20 +176,27 @@ module RuboCop
|
|
157
176
|
return false if inherited_file.nil? # Not inheritance resolving merge
|
158
177
|
return false if inherited_file.start_with?('..') # Legitimate override
|
159
178
|
return false if base_hash[key] == derived_hash[key] # Same value
|
160
|
-
return false if remote_file?(inherited_file) # Can't change
|
179
|
+
return false if PathUtil.remote_file?(inherited_file) # Can't change
|
161
180
|
|
162
181
|
Gem.path.none? { |dir| inherited_file.start_with?(dir) } # Can change?
|
163
182
|
end
|
164
183
|
|
165
184
|
def warn_on_duplicate_setting(base_hash, derived_hash, key, **opts)
|
185
|
+
# If the file being considered is remote, don't bother checking for duplicates
|
186
|
+
return if remote_config?(opts[:file])
|
187
|
+
|
166
188
|
return unless duplicate_setting?(base_hash, derived_hash, key, opts[:inherited_file])
|
167
189
|
|
168
190
|
inherit_mode = opts[:inherit_mode]['merge'] || opts[:inherit_mode]['override']
|
169
191
|
return if base_hash[key].is_a?(Array) && inherit_mode&.include?(key)
|
170
192
|
|
171
|
-
puts
|
172
|
-
|
173
|
-
|
193
|
+
puts duplicate_setting_warning(opts, key)
|
194
|
+
end
|
195
|
+
|
196
|
+
def duplicate_setting_warning(opts, key)
|
197
|
+
"#{PathUtil.smart_path(opts[:file])}: " \
|
198
|
+
"#{opts[:cop_name]}:#{key} overrides " \
|
199
|
+
"the same parameter in #{opts[:inherited_file]}"
|
174
200
|
end
|
175
201
|
|
176
202
|
def determine_inherit_mode(hash, key)
|
@@ -180,7 +206,7 @@ module RuboCop
|
|
180
206
|
end
|
181
207
|
|
182
208
|
def should_union?(derived_hash, base_hash, root_mode, key)
|
183
|
-
return false unless base_hash[key].is_a?(Array)
|
209
|
+
return false unless base_hash[key].is_a?(Array) || derived_hash[key].is_a?(Array)
|
184
210
|
|
185
211
|
derived_mode = derived_hash['inherit_mode']
|
186
212
|
return false if should_override?(derived_mode, key)
|
@@ -218,7 +244,7 @@ module RuboCop
|
|
218
244
|
end
|
219
245
|
|
220
246
|
def inherited_file(path, inherit_from, file)
|
221
|
-
if remote_file?(inherit_from)
|
247
|
+
if PathUtil.remote_file?(inherit_from)
|
222
248
|
# A remote configuration, e.g. `inherit_from: http://example.com/rubocop.yml`.
|
223
249
|
RemoteConfig.new(inherit_from, File.dirname(path))
|
224
250
|
elsif Pathname.new(inherit_from).absolute?
|
@@ -238,8 +264,8 @@ module RuboCop
|
|
238
264
|
end
|
239
265
|
end
|
240
266
|
|
241
|
-
def
|
242
|
-
|
267
|
+
def remote_config?(file)
|
268
|
+
file.is_a?(RemoteConfig)
|
243
269
|
end
|
244
270
|
|
245
271
|
def handle_disabled_by_default(config, new_default_configuration)
|
@@ -15,7 +15,7 @@ module RuboCop
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def violated?
|
18
|
-
return false if
|
18
|
+
return false if plugin_loaded?
|
19
19
|
|
20
20
|
affected_cops.any?
|
21
21
|
end
|
@@ -38,8 +38,9 @@ module RuboCop
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
-
def
|
42
|
-
|
41
|
+
def plugin_loaded?
|
42
|
+
# Plugins loaded via `require` are included in `loaded_features`.
|
43
|
+
config.loaded_plugins.include?(gem) || config.loaded_features.include?(gem)
|
43
44
|
end
|
44
45
|
end
|
45
46
|
end
|
@@ -50,7 +50,7 @@ module RuboCop
|
|
50
50
|
# Default rules for obsoletions are in config/obsoletion.yml
|
51
51
|
# Additional rules files can be added with `RuboCop::ConfigObsoletion.files << filename`
|
52
52
|
def load_rules # rubocop:disable Metrics/AbcSize
|
53
|
-
rules = LOAD_RULES_CACHE[self.class.files] ||=
|
53
|
+
rules = LOAD_RULES_CACHE[self.class.files.hash] ||=
|
54
54
|
self.class.files.each_with_object({}) do |filename, hash|
|
55
55
|
hash.merge!(YAML.safe_load(File.read(filename)) || {}) do |_key, first, second|
|
56
56
|
case first
|
@@ -3,12 +3,13 @@
|
|
3
3
|
module RuboCop
|
4
4
|
# Handles validation of configuration, for example cop names, parameter
|
5
5
|
# names, and Ruby versions.
|
6
|
+
# rubocop:disable Metrics/ClassLength
|
6
7
|
class ConfigValidator
|
7
8
|
extend SimpleForwardable
|
8
9
|
|
9
10
|
# @api private
|
10
11
|
COMMON_PARAMS = %w[Exclude Include Severity inherit_mode AutoCorrect StyleGuide Details
|
11
|
-
Enabled].freeze
|
12
|
+
Enabled Reference].freeze
|
12
13
|
# @api private
|
13
14
|
INTERNAL_PARAMS = %w[Description StyleGuide
|
14
15
|
VersionAdded VersionChanged VersionRemoved
|
@@ -41,8 +42,9 @@ module RuboCop
|
|
41
42
|
ConfigLoader.default_configuration.key?(key)
|
42
43
|
end
|
43
44
|
|
44
|
-
|
45
|
+
validate_parameter_shape(valid_cop_names)
|
45
46
|
|
47
|
+
check_obsoletions
|
46
48
|
alert_about_unrecognized_cops(invalid_cop_names)
|
47
49
|
validate_new_cops_parameter
|
48
50
|
validate_parameter_names(valid_cop_names)
|
@@ -64,12 +66,6 @@ module RuboCop
|
|
64
66
|
target_ruby.version
|
65
67
|
end
|
66
68
|
|
67
|
-
def validate_section_presence(name)
|
68
|
-
return unless @config.key?(name) && @config[name].nil?
|
69
|
-
|
70
|
-
raise ValidationError, "empty section #{name} found in #{smart_loaded_path}"
|
71
|
-
end
|
72
|
-
|
73
69
|
private
|
74
70
|
|
75
71
|
attr_reader :target_ruby
|
@@ -177,9 +173,22 @@ module RuboCop
|
|
177
173
|
raise ValidationError, message
|
178
174
|
end
|
179
175
|
|
176
|
+
def validate_parameter_shape(valid_cop_names)
|
177
|
+
valid_cop_names.each do |name|
|
178
|
+
if @config[name].nil?
|
179
|
+
raise ValidationError, "empty section #{name.inspect} found in #{smart_loaded_path}"
|
180
|
+
elsif !@config[name].is_a?(Hash)
|
181
|
+
raise ValidationError, <<~MESSAGE
|
182
|
+
The configuration for #{name.inspect} in #{smart_loaded_path} is not a Hash.
|
183
|
+
|
184
|
+
Found: #{@config[name].inspect}
|
185
|
+
MESSAGE
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
180
190
|
def validate_parameter_names(valid_cop_names)
|
181
191
|
valid_cop_names.each do |name|
|
182
|
-
validate_section_presence(name)
|
183
192
|
each_invalid_parameter(name) do |param, supported_params|
|
184
193
|
warn Rainbow(<<~MESSAGE).yellow
|
185
194
|
Warning: #{name} does not support #{param} parameter.
|
@@ -277,4 +286,5 @@ module RuboCop
|
|
277
286
|
"is supposed to be #{supposed_values} and #{Rainbow(value).yellow} is not."
|
278
287
|
end
|
279
288
|
end
|
289
|
+
# rubocop:enable Metrics/ClassLength
|
280
290
|
end
|
@@ -102,7 +102,7 @@ module RuboCop
|
|
102
102
|
end
|
103
103
|
|
104
104
|
def string_continuation?(node)
|
105
|
-
|
105
|
+
node.type?(:str, :dstr, :xstr) && node.source.match?(/\\\s*$/)
|
106
106
|
end
|
107
107
|
|
108
108
|
def multiline_string?(node)
|
data/lib/rubocop/cop/base.rb
CHANGED
@@ -261,6 +261,12 @@ module RuboCop
|
|
261
261
|
@config.target_ruby_version
|
262
262
|
end
|
263
263
|
|
264
|
+
# Returns a gems locked versions (i.e. from Gemfile.lock or gems.locked)
|
265
|
+
# @returns [Gem::Version | nil] The locked gem version, or nil if the gem is not present.
|
266
|
+
def target_gem_version(gem_name)
|
267
|
+
@config.gem_versions_in_target && @config.gem_versions_in_target[gem_name]
|
268
|
+
end
|
269
|
+
|
264
270
|
def parser_engine
|
265
271
|
@config.parser_engine
|
266
272
|
end
|
@@ -66,7 +66,7 @@ module RuboCop
|
|
66
66
|
|
67
67
|
def conditional_declaration?(nodes)
|
68
68
|
parent = nodes[0].each_ancestor.find { |ancestor| !ancestor.begin_type? }
|
69
|
-
return false unless parent&.
|
69
|
+
return false unless parent&.type?(:if, :when)
|
70
70
|
|
71
71
|
root_conditional_node = parent.if_type? ? parent : parent.parent
|
72
72
|
nodes.all? { |node| within_conditional?(node, root_conditional_node) }
|
@@ -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
|
@@ -50,10 +50,12 @@ module RuboCop
|
|
50
50
|
}.freeze
|
51
51
|
|
52
52
|
EXPECT_NO_CORRECTIONS_DESCRIPTION_MAPPING = {
|
53
|
-
/\A(auto[- ]?)?
|
53
|
+
/\A(auto[- ]?)?corrects?/ => 'does not correct',
|
54
|
+
/\band (auto[- ]?)?corrects/ => 'but does not correct'
|
54
55
|
}.freeze
|
55
56
|
|
56
57
|
EXPECT_CORRECTION_DESCRIPTION_MAPPING = {
|
58
|
+
/\bbut (does not|doesn't) (auto[- ]?)?correct/ => 'and autocorrects',
|
57
59
|
/\b(does not|doesn't) (auto[- ]?)?correct/ => 'autocorrects'
|
58
60
|
}.freeze
|
59
61
|
|
@@ -90,8 +92,10 @@ module RuboCop
|
|
90
92
|
description_text = string_contents(current_description)
|
91
93
|
return unless (new_description = correct_description(description_text, description_map))
|
92
94
|
|
95
|
+
quote = current_description.dstr_type? ? '"' : "'"
|
96
|
+
|
93
97
|
add_offense(current_description, message: message) do |corrector|
|
94
|
-
corrector.replace(current_description, "
|
98
|
+
corrector.replace(current_description, "#{quote}#{new_description}#{quote}")
|
95
99
|
end
|
96
100
|
end
|
97
101
|
|
@@ -106,7 +110,7 @@ module RuboCop
|
|
106
110
|
end
|
107
111
|
|
108
112
|
def string_contents(node)
|
109
|
-
node.
|
113
|
+
node.type?(:str, :dstr) ? node.value : node.source
|
110
114
|
end
|
111
115
|
end
|
112
116
|
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
|
@@ -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
|