rubocop 1.84.2 → 1.88.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/config/default.yml +180 -86
- data/config/obsoletion.yml +26 -1
- data/lib/rubocop/cache_config.rb +1 -1
- data/lib/rubocop/cli/command/auto_generate_config.rb +34 -2
- data/lib/rubocop/cli/command/list_enabled_cops_for.rb +40 -0
- data/lib/rubocop/cli/command/mcp.rb +19 -0
- data/lib/rubocop/cli/command/show_cops.rb +2 -2
- data/lib/rubocop/cli/command/show_docs_url.rb +4 -8
- data/lib/rubocop/cli/command/suggest_extensions.rb +1 -1
- data/lib/rubocop/cli.rb +9 -7
- data/lib/rubocop/comment_config.rb +12 -15
- data/lib/rubocop/config.rb +14 -10
- data/lib/rubocop/config_finder.rb +1 -1
- data/lib/rubocop/config_loader.rb +17 -2
- data/lib/rubocop/config_loader_resolver.rb +13 -4
- data/lib/rubocop/config_obsoletion/extracted_cop.rb +4 -2
- data/lib/rubocop/config_store.rb +2 -2
- data/lib/rubocop/config_validator.rb +1 -1
- data/lib/rubocop/cop/autocorrect_logic.rb +2 -1
- data/lib/rubocop/cop/base.rb +25 -4
- data/lib/rubocop/cop/bundler/gem_comment.rb +2 -2
- data/lib/rubocop/cop/correctors/condition_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +1 -5
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +33 -2
- data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +2 -2
- data/lib/rubocop/cop/correctors.rb +28 -0
- data/lib/rubocop/cop/documentation.rb +2 -3
- data/lib/rubocop/cop/exclude_limit.rb +31 -5
- data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +2 -2
- data/lib/rubocop/cop/gemspec/require_mfa.rb +5 -5
- data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +3 -3
- data/lib/rubocop/cop/internal_affairs/itblock_handler.rb +69 -0
- data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +1 -0
- data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +5 -3
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/layout/argument_alignment.rb +2 -2
- data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/begin_end_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/block_alignment.rb +41 -4
- data/lib/rubocop/cop/layout/class_structure.rb +1 -1
- data/lib/rubocop/cop/layout/dot_position.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +23 -7
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -0
- data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +12 -2
- data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +16 -2
- data/lib/rubocop/cop/layout/empty_lines_around_module_body.rb +16 -2
- data/lib/rubocop/cop/layout/end_alignment.rb +8 -5
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +7 -1
- data/lib/rubocop/cop/layout/hash_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +12 -0
- data/lib/rubocop/cop/layout/line_length.rb +5 -3
- data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +9 -2
- data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +53 -3
- data/lib/rubocop/cop/layout/parameter_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/redundant_line_break.rb +3 -1
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_keyword.rb +3 -1
- data/lib/rubocop/cop/layout/space_before_brackets.rb +1 -1
- data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +1 -0
- data/lib/rubocop/cop/lint/ambiguous_assignment.rb +1 -11
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +1 -10
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +1 -3
- data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +1 -1
- data/lib/rubocop/cop/lint/constant_reassignment.rb +93 -11
- data/lib/rubocop/cop/lint/constant_resolution.rb +6 -6
- data/lib/rubocop/cop/lint/data_define_override.rb +63 -0
- data/lib/rubocop/cop/lint/debugger.rb +0 -1
- data/lib/rubocop/cop/lint/deprecated_constants.rb +2 -8
- data/lib/rubocop/cop/lint/duplicate_methods.rb +55 -8
- data/lib/rubocop/cop/lint/empty_block.rb +4 -4
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +6 -1
- data/lib/rubocop/cop/lint/empty_in_pattern.rb +8 -1
- data/lib/rubocop/cop/lint/empty_when.rb +8 -1
- data/lib/rubocop/cop/lint/ensure_return.rb +19 -1
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +4 -2
- data/lib/rubocop/cop/lint/float_comparison.rb +1 -0
- data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -1
- data/lib/rubocop/cop/lint/interpolation_check.rb +25 -5
- data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
- data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +11 -1
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +8 -11
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +5 -5
- data/lib/rubocop/cop/lint/multiple_comparison.rb +2 -2
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +2 -0
- data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +16 -0
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +4 -2
- data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +1 -1
- data/lib/rubocop/cop/lint/number_conversion.rb +19 -10
- data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -1
- data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +3 -0
- data/lib/rubocop/cop/lint/ordered_magic_comments.rb +7 -7
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +3 -13
- data/lib/rubocop/cop/lint/raise_exception.rb +1 -1
- data/lib/rubocop/cop/lint/rand_one.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +4 -1
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +6 -12
- data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +15 -4
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +36 -12
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +4 -0
- data/lib/rubocop/cop/lint/redundant_type_conversion.rb +10 -3
- data/lib/rubocop/cop/lint/redundant_with_index.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_with_object.rb +5 -0
- data/lib/rubocop/cop/lint/refinement_import_methods.rb +8 -1
- data/lib/rubocop/cop/lint/regexp_as_condition.rb +9 -1
- data/lib/rubocop/cop/lint/require_parentheses.rb +13 -4
- data/lib/rubocop/cop/lint/require_range_parentheses.rb +2 -1
- data/lib/rubocop/cop/lint/require_relative_self_path.rb +7 -5
- data/lib/rubocop/cop/lint/rescue_type.rb +1 -1
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +18 -0
- data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +7 -1
- data/lib/rubocop/cop/lint/safe_navigation_with_empty.rb +1 -1
- data/lib/rubocop/cop/lint/script_permission.rb +5 -1
- data/lib/rubocop/cop/lint/self_assignment.rb +24 -1
- data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +1 -1
- data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +14 -0
- data/lib/rubocop/cop/lint/shared_mutable_default.rb +3 -1
- data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +12 -0
- data/lib/rubocop/cop/lint/symbol_conversion.rb +21 -4
- data/lib/rubocop/cop/lint/syntax.rb +25 -1
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +28 -1
- data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +1 -1
- data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +5 -1
- data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +4 -2
- data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -0
- data/lib/rubocop/cop/lint/unreachable_code.rb +2 -2
- data/lib/rubocop/cop/lint/unreachable_pattern_branch.rb +113 -0
- data/lib/rubocop/cop/lint/unused_method_argument.rb +10 -0
- data/lib/rubocop/cop/lint/useless_assignment.rb +14 -14
- data/lib/rubocop/cop/lint/useless_constant_scoping.rb +4 -4
- data/lib/rubocop/cop/lint/useless_default_value_argument.rb +2 -0
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +8 -4
- data/lib/rubocop/cop/lint/useless_setter_call.rb +4 -1
- data/lib/rubocop/cop/lint/useless_times.rb +22 -1
- data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +35 -9
- data/lib/rubocop/cop/lint/void.rb +32 -12
- data/lib/rubocop/cop/metrics/block_length.rb +1 -1
- data/lib/rubocop/cop/metrics/block_nesting.rb +23 -0
- data/lib/rubocop/cop/metrics/collection_literal_length.rb +1 -1
- data/lib/rubocop/cop/metrics/method_length.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/iterating_block.rb +1 -1
- data/lib/rubocop/cop/migration/department_name.rb +12 -1
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +2 -2
- data/lib/rubocop/cop/mixin/configurable_max.rb +6 -5
- data/lib/rubocop/cop/mixin/hash_transform_method/autocorrection.rb +63 -0
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +10 -60
- data/lib/rubocop/cop/mixin/project_index_help.rb +48 -0
- data/lib/rubocop/cop/mixin.rb +86 -0
- data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +1 -1
- data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -1
- data/lib/rubocop/cop/naming/predicate_method.rb +2 -2
- data/lib/rubocop/cop/naming/predicate_prefix.rb +1 -1
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +1 -1
- data/lib/rubocop/cop/offense.rb +8 -0
- data/lib/rubocop/cop/registry.rb +62 -38
- data/lib/rubocop/cop/security/eval.rb +15 -2
- data/lib/rubocop/cop/security/io_methods.rb +1 -1
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +14 -2
- data/lib/rubocop/cop/style/accessor_grouping.rb +4 -2
- data/lib/rubocop/cop/style/alias.rb +15 -3
- data/lib/rubocop/cop/style/and_or.rb +2 -1
- data/lib/rubocop/cop/style/arguments_forwarding.rb +25 -7
- data/lib/rubocop/cop/style/array_first_last.rb +12 -1
- data/lib/rubocop/cop/style/array_intersect.rb +4 -0
- data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +3 -0
- data/lib/rubocop/cop/style/array_join.rb +4 -2
- data/lib/rubocop/cop/style/ascii_comments.rb +6 -3
- data/lib/rubocop/cop/style/attr.rb +5 -2
- data/lib/rubocop/cop/style/bare_percent_literals.rb +3 -1
- data/lib/rubocop/cop/style/begin_block.rb +3 -1
- data/lib/rubocop/cop/style/block_delimiters.rb +37 -31
- data/lib/rubocop/cop/style/case_equality.rb +18 -2
- data/lib/rubocop/cop/style/character_literal.rb +2 -2
- data/lib/rubocop/cop/style/class_and_module_children.rb +18 -2
- data/lib/rubocop/cop/style/class_equality_comparison.rb +21 -13
- data/lib/rubocop/cop/style/class_methods_definitions.rb +11 -5
- data/lib/rubocop/cop/style/collection_compact.rb +36 -16
- data/lib/rubocop/cop/style/colon_method_call.rb +16 -7
- data/lib/rubocop/cop/style/combinable_loops.rb +5 -0
- data/lib/rubocop/cop/style/comparable_clamp.rb +12 -1
- data/lib/rubocop/cop/style/concat_array_literals.rb +7 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +6 -5
- data/lib/rubocop/cop/style/constant_visibility.rb +4 -1
- data/lib/rubocop/cop/style/copyright.rb +22 -11
- data/lib/rubocop/cop/style/date_time.rb +4 -4
- data/lib/rubocop/cop/style/dig_chain.rb +5 -0
- data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +1 -1
- data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +6 -1
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
- data/lib/rubocop/cop/style/each_with_object.rb +2 -0
- data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
- data/lib/rubocop/cop/style/empty_class_definition.rb +43 -20
- data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
- data/lib/rubocop/cop/style/encoding.rb +7 -1
- data/lib/rubocop/cop/style/end_block.rb +3 -1
- data/lib/rubocop/cop/style/endless_method.rb +8 -3
- data/lib/rubocop/cop/style/fetch_env_var.rb +1 -1
- data/lib/rubocop/cop/style/file_open.rb +84 -0
- data/lib/rubocop/cop/style/file_write.rb +21 -16
- data/lib/rubocop/cop/style/for.rb +3 -0
- data/lib/rubocop/cop/style/format_string.rb +4 -3
- data/lib/rubocop/cop/style/format_string_token.rb +29 -2
- data/lib/rubocop/cop/style/global_vars.rb +5 -2
- data/lib/rubocop/cop/style/guard_clause.rb +9 -6
- data/lib/rubocop/cop/style/hash_as_last_array_item.rb +21 -5
- data/lib/rubocop/cop/style/hash_conversion.rb +1 -1
- data/lib/rubocop/cop/style/hash_lookup_method.rb +19 -7
- data/lib/rubocop/cop/style/hash_slice.rb +16 -0
- data/lib/rubocop/cop/style/hash_transform_keys.rb +17 -7
- data/lib/rubocop/cop/style/hash_transform_values.rb +17 -7
- data/lib/rubocop/cop/style/if_inside_else.rb +16 -7
- data/lib/rubocop/cop/style/if_unless_modifier.rb +15 -4
- data/lib/rubocop/cop/style/if_with_semicolon.rb +7 -5
- data/lib/rubocop/cop/style/inline_comment.rb +4 -1
- data/lib/rubocop/cop/style/ip_addresses.rb +1 -2
- data/lib/rubocop/cop/style/magic_comment_format.rb +3 -3
- data/lib/rubocop/cop/style/map_join.rb +123 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +5 -3
- data/lib/rubocop/cop/style/min_max_comparison.rb +1 -1
- data/lib/rubocop/cop/style/module_member_existence_check.rb +7 -14
- data/lib/rubocop/cop/style/multiline_if_then.rb +3 -1
- data/lib/rubocop/cop/style/mutable_constant.rb +106 -12
- data/lib/rubocop/cop/style/nil_comparison.rb +2 -3
- data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
- data/lib/rubocop/cop/style/non_nil_check.rb +5 -11
- data/lib/rubocop/cop/style/not.rb +2 -0
- data/lib/rubocop/cop/style/numeric_literals.rb +3 -2
- data/lib/rubocop/cop/style/one_class_per_file.rb +115 -0
- data/lib/rubocop/cop/style/one_line_conditional.rb +4 -3
- data/lib/rubocop/cop/style/parallel_assignment.rb +12 -1
- data/lib/rubocop/cop/style/partition_instead_of_double_select.rb +270 -0
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +2 -0
- data/lib/rubocop/cop/style/predicate_with_kind.rb +84 -0
- data/lib/rubocop/cop/style/proc.rb +3 -2
- data/lib/rubocop/cop/style/raise_args.rb +1 -1
- data/lib/rubocop/cop/style/reduce_to_hash.rb +200 -0
- data/lib/rubocop/cop/style/redundant_array_constructor.rb +2 -2
- data/lib/rubocop/cop/style/redundant_begin.rb +3 -3
- data/lib/rubocop/cop/style/redundant_constant_base.rb +5 -5
- data/lib/rubocop/cop/style/redundant_each.rb +3 -3
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -1
- data/lib/rubocop/cop/style/redundant_format.rb +1 -0
- data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +26 -10
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +16 -0
- data/lib/rubocop/cop/style/redundant_min_max_by.rb +93 -0
- data/lib/rubocop/cop/style/redundant_parentheses.rb +25 -22
- data/lib/rubocop/cop/style/redundant_percent_q.rb +4 -1
- data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +2 -2
- data/lib/rubocop/cop/style/redundant_return.rb +3 -1
- data/lib/rubocop/cop/style/redundant_self.rb +2 -2
- data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +0 -5
- data/lib/rubocop/cop/style/redundant_struct_keyword_init.rb +114 -0
- data/lib/rubocop/cop/style/regexp_literal.rb +31 -2
- data/lib/rubocop/cop/style/rescue_modifier.rb +3 -3
- data/lib/rubocop/cop/style/safe_navigation.rb +7 -7
- data/lib/rubocop/cop/style/select_by_kind.rb +158 -0
- data/lib/rubocop/cop/style/select_by_range.rb +197 -0
- data/lib/rubocop/cop/style/select_by_regexp.rb +51 -21
- data/lib/rubocop/cop/style/self_assignment.rb +1 -1
- data/lib/rubocop/cop/style/semicolon.rb +18 -1
- data/lib/rubocop/cop/style/single_line_block_params.rb +2 -2
- data/lib/rubocop/cop/style/single_line_do_end_block.rb +1 -1
- data/lib/rubocop/cop/style/single_line_methods.rb +3 -1
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +4 -2
- data/lib/rubocop/cop/style/special_global_vars.rb +6 -1
- data/lib/rubocop/cop/style/struct_inheritance.rb +13 -0
- data/lib/rubocop/cop/style/symbol_proc.rb +7 -6
- data/lib/rubocop/cop/style/tally_method.rb +181 -0
- data/lib/rubocop/cop/style/top_level_method_definition.rb +2 -2
- data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
- data/lib/rubocop/cop/style/trailing_method_end_statement.rb +1 -0
- data/lib/rubocop/cop/style/unless_logical_operators.rb +3 -3
- data/lib/rubocop/cop/style/while_until_do.rb +7 -0
- data/lib/rubocop/cop/style/while_until_modifier.rb +16 -0
- data/lib/rubocop/cop/style/word_array.rb +1 -0
- data/lib/rubocop/cop/style/yoda_condition.rb +1 -1
- data/lib/rubocop/cop/style/yoda_expression.rb +1 -1
- data/lib/rubocop/cop/style/zero_length_predicate.rb +6 -3
- data/lib/rubocop/cop/team.rb +86 -35
- data/lib/rubocop/cop/variable_force/branch.rb +2 -2
- data/lib/rubocop/directive_comment.rb +2 -1
- data/lib/rubocop/file_patterns.rb +9 -1
- data/lib/rubocop/formatter/disabled_config_formatter.rb +19 -9
- data/lib/rubocop/formatter/formatter_set.rb +1 -1
- data/lib/rubocop/formatter/junit_formatter.rb +1 -1
- data/lib/rubocop/formatter/simple_text_formatter.rb +0 -2
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -1
- data/lib/rubocop/formatter.rb +22 -21
- data/lib/rubocop/lsp/diagnostic.rb +1 -0
- data/lib/rubocop/lsp/routes.rb +10 -3
- data/lib/rubocop/lsp/runtime.rb +1 -2
- data/lib/rubocop/mcp/server.rb +200 -0
- data/lib/rubocop/options.rb +35 -4
- data/lib/rubocop/path_util.rb +14 -2
- data/lib/rubocop/plugin/loader.rb +1 -1
- data/lib/rubocop/project_index_loader.rb +66 -0
- data/lib/rubocop/result_cache.rb +22 -10
- data/lib/rubocop/rspec/cop_helper.rb +8 -0
- data/lib/rubocop/rspec/shared_contexts.rb +32 -2
- data/lib/rubocop/runner.rb +124 -53
- data/lib/rubocop/server/cache.rb +5 -7
- data/lib/rubocop/server/core.rb +8 -0
- data/lib/rubocop/target_finder.rb +14 -7
- data/lib/rubocop/target_ruby.rb +18 -12
- data/lib/rubocop/version.rb +21 -3
- data/lib/rubocop.rb +22 -96
- metadata +27 -5
|
@@ -46,7 +46,7 @@ module RuboCop
|
|
|
46
46
|
message = format_message_from(processed_source)
|
|
47
47
|
|
|
48
48
|
add_offense(comment, message: message) do
|
|
49
|
-
autocorrect if
|
|
49
|
+
autocorrect if autocorrect?
|
|
50
50
|
end
|
|
51
51
|
end
|
|
52
52
|
|
|
@@ -57,6 +57,10 @@ module RuboCop
|
|
|
57
57
|
end
|
|
58
58
|
|
|
59
59
|
def executable?(processed_source)
|
|
60
|
+
# Virtual sources (LSP buffers, programmatic `ProcessedSource`) have no file on
|
|
61
|
+
# disk to stat or `chmod`, so treat them as executable to skip the offense.
|
|
62
|
+
return true unless File.exist?(processed_source.file_path)
|
|
63
|
+
|
|
60
64
|
# Returns true if stat is executable or if the operating system
|
|
61
65
|
# doesn't distinguish executable files from nonexecutable files.
|
|
62
66
|
# See at: https://github.com/ruby/ruby/blob/ruby_2_4/file.c#L5362
|
|
@@ -90,12 +90,35 @@ module RuboCop
|
|
|
90
90
|
def on_or_asgn(node)
|
|
91
91
|
return if allow_rbs_inline_annotation? && rbs_inline_annotation?(node.lhs)
|
|
92
92
|
|
|
93
|
-
add_offense(node) if
|
|
93
|
+
add_offense(node) if or_and_asgn_self_assignment?(node.lhs, node.rhs)
|
|
94
94
|
end
|
|
95
95
|
alias on_and_asgn on_or_asgn
|
|
96
96
|
|
|
97
97
|
private
|
|
98
98
|
|
|
99
|
+
def or_and_asgn_self_assignment?(lhs, rhs)
|
|
100
|
+
case lhs.type
|
|
101
|
+
when :casgn
|
|
102
|
+
rhs.const_type? && lhs.namespace == rhs.namespace && lhs.short_name == rhs.short_name
|
|
103
|
+
when :send, :csend
|
|
104
|
+
reader_self_assignment?(lhs, rhs)
|
|
105
|
+
else
|
|
106
|
+
rhs_matches_lhs?(rhs, lhs)
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Compares two reader calls (attribute `foo.bar` or key `hash['foo']`).
|
|
111
|
+
def reader_self_assignment?(lhs, rhs)
|
|
112
|
+
return false unless rhs.type == lhs.type
|
|
113
|
+
return false unless lhs.method?(rhs.method_name)
|
|
114
|
+
return false unless lhs.receiver == rhs.receiver
|
|
115
|
+
return false unless lhs.arguments == rhs.arguments
|
|
116
|
+
|
|
117
|
+
# `hash[foo] ||= hash[foo]` is intentionally allowed because a method-call key may
|
|
118
|
+
# return different results on each call.
|
|
119
|
+
lhs.arguments.none?(&:call_type?)
|
|
120
|
+
end
|
|
121
|
+
|
|
99
122
|
def multiple_self_assignment?(node)
|
|
100
123
|
lhs = node.lhs
|
|
101
124
|
rhs = node.rhs
|
|
@@ -45,7 +45,7 @@ module RuboCop
|
|
|
45
45
|
# @!method send_with_mixin_argument?(node)
|
|
46
46
|
def_node_matcher :send_with_mixin_argument?, <<~PATTERN
|
|
47
47
|
(send
|
|
48
|
-
(const _ _) {:#{SEND_METHODS.join(' :')}}
|
|
48
|
+
{nil? self (const _ _)} {:#{SEND_METHODS.join(' :')}}
|
|
49
49
|
({sym str} $#mixin_method?)
|
|
50
50
|
$(const _ _)+)
|
|
51
51
|
PATTERN
|
|
@@ -75,6 +75,8 @@ module RuboCop
|
|
|
75
75
|
end
|
|
76
76
|
|
|
77
77
|
def same_conditions_node_different_branch?(variable, outer_local_variable)
|
|
78
|
+
return true if different_case_in_branch?(variable, outer_local_variable)
|
|
79
|
+
|
|
78
80
|
variable_node = variable_node(variable)
|
|
79
81
|
return false unless node_or_its_ascendant_conditional?(variable_node)
|
|
80
82
|
|
|
@@ -88,6 +90,18 @@ module RuboCop
|
|
|
88
90
|
variable_node == outer_local_variable_node.else_branch
|
|
89
91
|
end
|
|
90
92
|
|
|
93
|
+
# `case ... in` binds variables in the pattern itself, so a block argument in one
|
|
94
|
+
# `in` branch does not shadow a pattern variable from a different `in` branch of the
|
|
95
|
+
# same `case` (the branches are mutually exclusive).
|
|
96
|
+
def different_case_in_branch?(variable, outer_local_variable)
|
|
97
|
+
inner_branch = variable.scope.node.each_ancestor(:in_pattern).first
|
|
98
|
+
outer_branch = outer_local_variable.declaration_node.each_ancestor(:in_pattern).first
|
|
99
|
+
|
|
100
|
+
return false unless inner_branch && outer_branch
|
|
101
|
+
|
|
102
|
+
inner_branch != outer_branch && inner_branch.parent == outer_branch.parent
|
|
103
|
+
end
|
|
104
|
+
|
|
91
105
|
def variable_node(variable)
|
|
92
106
|
parent_node = variable.scope.node.parent
|
|
93
107
|
|
|
@@ -56,7 +56,9 @@ module RuboCop
|
|
|
56
56
|
{array hash (send (const {nil? cbase} {:Array :Hash}) :new)}
|
|
57
57
|
!#capacity_keyword_argument?
|
|
58
58
|
])
|
|
59
|
-
(send (const {nil? cbase} :Hash) :new
|
|
59
|
+
(send (const {nil? cbase} :Hash) :new
|
|
60
|
+
{array hash (send (const {nil? cbase} {:Array :Hash}) :new)}
|
|
61
|
+
#capacity_keyword_argument?)
|
|
60
62
|
}
|
|
61
63
|
PATTERN
|
|
62
64
|
|
|
@@ -88,6 +88,10 @@ module RuboCop
|
|
|
88
88
|
return unless (method = numeric_constructor_rescue_nil(node))
|
|
89
89
|
end
|
|
90
90
|
|
|
91
|
+
# `Integer(arg, exception: false)` already suppresses the conversion error, so there
|
|
92
|
+
# is nothing unintentionally swallowed; adding another `exception: false` is wrong.
|
|
93
|
+
return if exception_keyword_argument?(method)
|
|
94
|
+
|
|
91
95
|
arguments = method.arguments.map(&:source) << 'exception: false'
|
|
92
96
|
prefer = "#{method.method_name}(#{arguments.join(', ')})"
|
|
93
97
|
prefer = "#{method.receiver.source}#{method.loc.dot.source}#{prefer}" if method.receiver
|
|
@@ -100,6 +104,14 @@ module RuboCop
|
|
|
100
104
|
|
|
101
105
|
private
|
|
102
106
|
|
|
107
|
+
def exception_keyword_argument?(method)
|
|
108
|
+
method.arguments.any? do |argument|
|
|
109
|
+
argument.hash_type? && argument.pairs.any? do |pair|
|
|
110
|
+
pair.key.sym_type? && pair.key.value == :exception
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
103
115
|
def expected_exception_classes_only?(exception_classes)
|
|
104
116
|
return true unless (arguments = exception_classes.first)
|
|
105
117
|
|
|
@@ -77,11 +77,28 @@ module RuboCop
|
|
|
77
77
|
|
|
78
78
|
def on_send(node)
|
|
79
79
|
return unless node.receiver
|
|
80
|
+
return unless (correction = symbol_conversion_correction(node.receiver))
|
|
80
81
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
register_offense(node, correction: correction)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def symbol_conversion_correction(receiver)
|
|
86
|
+
if receiver.type?(:str, :sym)
|
|
87
|
+
receiver.value.to_sym.inspect
|
|
88
|
+
elsif receiver.dstr_type? && !receiver.heredoc?
|
|
89
|
+
dstr_correction(receiver)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Reuse the already-escaped inner source for a plain `"..."` string so embedded
|
|
94
|
+
# quotes stay escaped. Percent literals (`%{}`, `%Q{}`, ...) and adjacent string
|
|
95
|
+
# concatenation have multi-character or no delimiters, so slicing the source would
|
|
96
|
+
# corrupt them; fall back to the node's value there.
|
|
97
|
+
def dstr_correction(receiver)
|
|
98
|
+
if receiver.loc.begin&.source == '"'
|
|
99
|
+
":\"#{receiver.source[1..-2]}\""
|
|
100
|
+
else
|
|
101
|
+
":\"#{receiver.value.to_sym}\""
|
|
85
102
|
end
|
|
86
103
|
end
|
|
87
104
|
|
|
@@ -26,7 +26,31 @@ module RuboCop
|
|
|
26
26
|
"#{diagnostic.message}\n(Using Ruby #{ruby_version} parser; " \
|
|
27
27
|
'configure using `TargetRubyVersion` parameter, under `AllCops`)'
|
|
28
28
|
end
|
|
29
|
-
|
|
29
|
+
location = diagnostic_location(diagnostic.location)
|
|
30
|
+
add_offense(location, message: message, severity: diagnostic.level)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Expand zero-length diagnostic ranges so that editors and formatters
|
|
34
|
+
# can display them. This typically occurs when the parser reports
|
|
35
|
+
# `unexpected token $end` at EOF.
|
|
36
|
+
def diagnostic_location(location)
|
|
37
|
+
return location if location.size.positive?
|
|
38
|
+
|
|
39
|
+
source_buffer = location.source_buffer
|
|
40
|
+
if location.end_pos < source_buffer.source.size
|
|
41
|
+
location.resize(1)
|
|
42
|
+
elsif location.begin_pos.positive?
|
|
43
|
+
location.adjust(begin_pos: -1)
|
|
44
|
+
else
|
|
45
|
+
location
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Override to skip multiline_ranges check which requires AST.
|
|
50
|
+
# Syntax errors mean the AST is nil, so we go directly to
|
|
51
|
+
# the EOL comment insertion path.
|
|
52
|
+
def disable_offense(offense_range)
|
|
53
|
+
disable_offense_with_eol_or_surround_comment(offense_range)
|
|
30
54
|
end
|
|
31
55
|
|
|
32
56
|
def add_offense_from_error(error)
|
|
@@ -61,7 +61,7 @@ module RuboCop
|
|
|
61
61
|
def arguments_match?(arguments, def_node)
|
|
62
62
|
index = 0
|
|
63
63
|
|
|
64
|
-
def_node.arguments.reject(&:blockarg_type?).all? do |def_arg|
|
|
64
|
+
all_present = def_node.arguments.reject(&:blockarg_type?).all? do |def_arg|
|
|
65
65
|
send_arg = arguments[index]
|
|
66
66
|
case def_arg.type
|
|
67
67
|
when :arg, :restarg, :optarg
|
|
@@ -70,6 +70,33 @@ module RuboCop
|
|
|
70
70
|
|
|
71
71
|
send_arg && argument_match?(send_arg, def_arg)
|
|
72
72
|
end
|
|
73
|
+
|
|
74
|
+
all_present && !extra_positional_arguments?(arguments, def_node)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# The enumerator re-invokes the method with these arguments, so passing more
|
|
78
|
+
# positional arguments than the method accepts raises `ArgumentError` at runtime.
|
|
79
|
+
def extra_positional_arguments?(arguments, def_node)
|
|
80
|
+
return false if variadic_parameters?(def_node) || expandable_arguments?(arguments)
|
|
81
|
+
|
|
82
|
+
positional_arguments(arguments).size > positional_parameters(def_node).size
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def variadic_parameters?(def_node)
|
|
86
|
+
def_node.arguments.any? { |arg| arg.type?(:restarg, :forward_arg) }
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# A splat or argument forwarding on the call side can expand to any arity.
|
|
90
|
+
def expandable_arguments?(arguments)
|
|
91
|
+
arguments.any? { |arg| arg.type?(:splat, :forwarded_args, :forwarded_restarg) }
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def positional_arguments(arguments)
|
|
95
|
+
arguments.reject { |arg| arg.type?(:hash, :kwsplat, :block_pass, :forwarded_kwrestarg) }
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def positional_parameters(def_node)
|
|
99
|
+
def_node.arguments.select { |arg| arg.type?(:arg, :optarg) }
|
|
73
100
|
end
|
|
74
101
|
|
|
75
102
|
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
|
@@ -40,7 +40,7 @@ module RuboCop
|
|
|
40
40
|
# top-level return node's ancestors should not be of block, def, or
|
|
41
41
|
# defs type.
|
|
42
42
|
def top_level_return?(return_node)
|
|
43
|
-
return_node.each_ancestor(:
|
|
43
|
+
return_node.each_ancestor(:any_block, :any_def).none?
|
|
44
44
|
end
|
|
45
45
|
end
|
|
46
46
|
end
|
|
@@ -32,9 +32,13 @@ module RuboCop
|
|
|
32
32
|
include RangeHelp
|
|
33
33
|
|
|
34
34
|
MSG = 'Avoid leaving a trailing comma in attribute declarations.'
|
|
35
|
+
RESTRICT_ON_SEND = %i[attr_reader attr_writer attr_accessor attr].freeze
|
|
35
36
|
|
|
36
37
|
def on_send(node)
|
|
37
|
-
return unless node.attribute_accessor? && node.last_argument.
|
|
38
|
+
return unless node.attribute_accessor? && node.last_argument.any_def_type?
|
|
39
|
+
# A lone `def` argument (e.g. `attr_reader def foo; end`) has no preceding
|
|
40
|
+
# attribute, so there is no trailing comma to flag.
|
|
41
|
+
return unless node.arguments.size > 1
|
|
38
42
|
|
|
39
43
|
trailing_comma = trailing_comma_range(node)
|
|
40
44
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Lint
|
|
6
|
-
# Checks for
|
|
6
|
+
# Checks for Regexps (both literals and via `Regexp.new` / `Regexp.compile`)
|
|
7
7
|
# that contain unescaped `]` characters.
|
|
8
8
|
#
|
|
9
9
|
# It emulates the following Ruby warning:
|
|
@@ -68,7 +68,9 @@ module RuboCop
|
|
|
68
68
|
|
|
69
69
|
expr.text.scan(/(?<!\\)\]/) do
|
|
70
70
|
pos = Regexp.last_match.begin(0)
|
|
71
|
-
|
|
71
|
+
# If the unescaped bracket is the first character of the regexp, Ruby does not warn.
|
|
72
|
+
# `pos` is relative to the sub-expression, so add its start offset (`expr.ts`).
|
|
73
|
+
next if (expr.ts + pos).zero?
|
|
72
74
|
|
|
73
75
|
location = range_at_index(node, expr.ts, pos)
|
|
74
76
|
|
|
@@ -4,8 +4,8 @@ module RuboCop
|
|
|
4
4
|
module Cop
|
|
5
5
|
module Lint
|
|
6
6
|
# Checks for unreachable code.
|
|
7
|
-
# The check
|
|
8
|
-
#
|
|
7
|
+
# The check is based on the presence of flow-of-control
|
|
8
|
+
# statements in non-final position in `begin` (implicit) blocks.
|
|
9
9
|
#
|
|
10
10
|
# @example
|
|
11
11
|
#
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Lint
|
|
6
|
+
# Checks for unreachable `in` pattern branches in `case...in` statements.
|
|
7
|
+
#
|
|
8
|
+
# An `in` branch is unreachable when a previous branch uses an unguarded
|
|
9
|
+
# catch-all pattern that matches any value unconditionally. Any `in` branches
|
|
10
|
+
# (and `else`) that follow such a catch-all are dead code.
|
|
11
|
+
#
|
|
12
|
+
# A catch-all pattern is one of:
|
|
13
|
+
#
|
|
14
|
+
# * A bare variable capture (`in x`)
|
|
15
|
+
# * An underscore (`in _`)
|
|
16
|
+
# * A pattern alias where the left side is a catch-all (`in _ => y`)
|
|
17
|
+
# * An alternation pattern where at least one alternative is a catch-all
|
|
18
|
+
# (`in _ | Integer`)
|
|
19
|
+
#
|
|
20
|
+
# NOTE: A catch-all pattern with a guard clause (e.g., `in _ if condition`)
|
|
21
|
+
# does NOT make subsequent branches unreachable because the guard might
|
|
22
|
+
# not be satisfied.
|
|
23
|
+
#
|
|
24
|
+
# @example
|
|
25
|
+
#
|
|
26
|
+
# # bad
|
|
27
|
+
# case value
|
|
28
|
+
# in Integer
|
|
29
|
+
# handle_integer
|
|
30
|
+
# in x
|
|
31
|
+
# handle_other
|
|
32
|
+
# in String
|
|
33
|
+
# handle_string
|
|
34
|
+
# else
|
|
35
|
+
# handle_else
|
|
36
|
+
# end
|
|
37
|
+
#
|
|
38
|
+
# # good
|
|
39
|
+
# case value
|
|
40
|
+
# in Integer
|
|
41
|
+
# handle_integer
|
|
42
|
+
# in String
|
|
43
|
+
# handle_string
|
|
44
|
+
# in x
|
|
45
|
+
# handle_other
|
|
46
|
+
# end
|
|
47
|
+
#
|
|
48
|
+
# # bad - else is unreachable after catch-all
|
|
49
|
+
# case value
|
|
50
|
+
# in Integer
|
|
51
|
+
# handle_integer
|
|
52
|
+
# in _
|
|
53
|
+
# handle_other
|
|
54
|
+
# else
|
|
55
|
+
# handle_else
|
|
56
|
+
# end
|
|
57
|
+
#
|
|
58
|
+
# # good - guard clause means catch-all might not match
|
|
59
|
+
# case value
|
|
60
|
+
# in x if x.positive?
|
|
61
|
+
# handle_positive
|
|
62
|
+
# in Integer
|
|
63
|
+
# handle_integer
|
|
64
|
+
# else
|
|
65
|
+
# handle_other
|
|
66
|
+
# end
|
|
67
|
+
#
|
|
68
|
+
class UnreachablePatternBranch < Base
|
|
69
|
+
extend TargetRubyVersion
|
|
70
|
+
|
|
71
|
+
MSG = 'Unreachable `in` pattern branch detected.'
|
|
72
|
+
MSG_ELSE = 'Unreachable `else` branch detected.'
|
|
73
|
+
|
|
74
|
+
minimum_target_ruby_version 2.7
|
|
75
|
+
|
|
76
|
+
def on_case_match(case_node)
|
|
77
|
+
catch_all_found = false
|
|
78
|
+
|
|
79
|
+
case_node.in_pattern_branches.each do |in_pattern_node|
|
|
80
|
+
if catch_all_found
|
|
81
|
+
add_offense(in_pattern_node)
|
|
82
|
+
next
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
pattern = in_pattern_node.pattern
|
|
86
|
+
guard = in_pattern_node.children[1]
|
|
87
|
+
|
|
88
|
+
catch_all_found = true if catch_all_pattern?(pattern) && guard.nil?
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
return unless catch_all_found && case_node.else?
|
|
92
|
+
|
|
93
|
+
add_offense(case_node.loc.else, message: MSG_ELSE)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
private
|
|
97
|
+
|
|
98
|
+
def catch_all_pattern?(pattern)
|
|
99
|
+
case pattern.type
|
|
100
|
+
when :match_var
|
|
101
|
+
true
|
|
102
|
+
when :match_as, :begin
|
|
103
|
+
catch_all_pattern?(pattern.children[0])
|
|
104
|
+
when :match_alt
|
|
105
|
+
pattern.children.any? { |child| catch_all_pattern?(child) }
|
|
106
|
+
else
|
|
107
|
+
false
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
@@ -95,10 +95,20 @@ module RuboCop
|
|
|
95
95
|
return unless variable.method_argument?
|
|
96
96
|
return if variable.keyword_argument? && cop_config['AllowUnusedKeywordArguments']
|
|
97
97
|
return if ignored_method?(variable.scope.node.body)
|
|
98
|
+
return if block_argument_with_yield?(variable)
|
|
98
99
|
|
|
99
100
|
super
|
|
100
101
|
end
|
|
101
102
|
|
|
103
|
+
def block_argument_with_yield?(variable)
|
|
104
|
+
return false unless variable.declaration_node.blockarg_type?
|
|
105
|
+
|
|
106
|
+
method_body = variable.scope.node.body
|
|
107
|
+
return false unless method_body
|
|
108
|
+
|
|
109
|
+
method_body.yield_type? || method_body.each_descendant(:yield).any?
|
|
110
|
+
end
|
|
111
|
+
|
|
102
112
|
def ignored_method?(body)
|
|
103
113
|
(cop_config['IgnoreEmptyMethods'] && body.nil?) ||
|
|
104
114
|
(cop_config['IgnoreNotImplementedMethods'] && not_implemented?(body))
|
|
@@ -40,8 +40,6 @@ module RuboCop
|
|
|
40
40
|
class UselessAssignment < Base
|
|
41
41
|
extend AutoCorrector
|
|
42
42
|
|
|
43
|
-
include RangeHelp
|
|
44
|
-
|
|
45
43
|
MSG = 'Useless assignment to variable - `%<variable>s`.'
|
|
46
44
|
|
|
47
45
|
def self.joining_forces
|
|
@@ -69,11 +67,7 @@ module RuboCop
|
|
|
69
67
|
range = offense_range(assignment)
|
|
70
68
|
|
|
71
69
|
add_offense(range, message: message) do |corrector|
|
|
72
|
-
|
|
73
|
-
# and where changing `x ||= 1` to `x = 1` would cause `NameError`,
|
|
74
|
-
# the autocorrect will be skipped, even if the variable is unused.
|
|
75
|
-
next if sequential_assignment?(assignment_node) ||
|
|
76
|
-
assignment_node.parent&.or_asgn_type?
|
|
70
|
+
next if uncorrectable_assignment?(assignment_node)
|
|
77
71
|
|
|
78
72
|
autocorrect(corrector, assignment)
|
|
79
73
|
end
|
|
@@ -81,6 +75,15 @@ module RuboCop
|
|
|
81
75
|
ignore_node(assignment_node) if chained_assignment?(assignment_node)
|
|
82
76
|
end
|
|
83
77
|
|
|
78
|
+
# Autocorrect is skipped when removing a variable would cause a syntax error
|
|
79
|
+
# (`x = 1, y = 2`), or where rewriting `x ||= 1`/`x &&= 1` to `x = 1` would raise
|
|
80
|
+
# `NameError` because the variable is not declared before the operator assignment.
|
|
81
|
+
def uncorrectable_assignment?(assignment_node)
|
|
82
|
+
sequential_assignment?(assignment_node) ||
|
|
83
|
+
assignment_node.parent&.or_asgn_type? ||
|
|
84
|
+
assignment_node.parent&.and_asgn_type?
|
|
85
|
+
end
|
|
86
|
+
|
|
84
87
|
def ignored_assignment?(variable, assignment_node, assignment)
|
|
85
88
|
assignment.used? || part_of_ignored_node?(assignment_node) ||
|
|
86
89
|
variable_in_loop_condition?(assignment_node, variable)
|
|
@@ -189,12 +192,9 @@ module RuboCop
|
|
|
189
192
|
# rubocop:enable Metrics/AbcSize
|
|
190
193
|
|
|
191
194
|
def remove_exception_assignment_part(corrector, node)
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
node.source_range.end_pos
|
|
196
|
-
)
|
|
197
|
-
)
|
|
195
|
+
range = node.parent.children.first&.source_range || node.parent.location.keyword
|
|
196
|
+
|
|
197
|
+
corrector.remove(range.end.join(node.source_range.end))
|
|
198
198
|
end
|
|
199
199
|
|
|
200
200
|
def rename_variable_with_underscore(corrector, node)
|
|
@@ -213,7 +213,7 @@ module RuboCop
|
|
|
213
213
|
end
|
|
214
214
|
|
|
215
215
|
def remove_local_variable_assignment_part(corrector, node)
|
|
216
|
-
corrector.
|
|
216
|
+
corrector.remove(node.loc.name.begin.join(node.expression.source_range.begin))
|
|
217
217
|
end
|
|
218
218
|
|
|
219
219
|
def variable_in_loop_condition?(assignment_node, variable)
|
|
@@ -48,12 +48,12 @@ module RuboCop
|
|
|
48
48
|
|
|
49
49
|
def after_private_modifier?(left_siblings)
|
|
50
50
|
access_modifier_candidates = left_siblings.compact.select do |left_sibling|
|
|
51
|
-
left_sibling.respond_to?(:
|
|
51
|
+
left_sibling.respond_to?(:bare_access_modifier?) && left_sibling.bare_access_modifier?
|
|
52
52
|
end
|
|
53
53
|
|
|
54
|
-
access_modifier_candidates.
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
return false if access_modifier_candidates.empty?
|
|
55
|
+
|
|
56
|
+
access_modifier_candidates.last.command?(:private)
|
|
57
57
|
end
|
|
58
58
|
|
|
59
59
|
def private_constantize?(right_siblings, const_value)
|
|
@@ -6,7 +6,7 @@ module RuboCop
|
|
|
6
6
|
# Looks for `ruby2_keywords` calls for methods that do not need it.
|
|
7
7
|
#
|
|
8
8
|
# `ruby2_keywords` should only be called on methods that accept an argument splat
|
|
9
|
-
# (`\*args`) but do not explicit keyword arguments (`k:` or `k: true`) or
|
|
9
|
+
# (`\*args`) but do not have explicit keyword arguments (`k:` or `k: true`) or
|
|
10
10
|
# a keyword splat (`**kwargs`).
|
|
11
11
|
#
|
|
12
12
|
# @example
|
|
@@ -107,11 +107,15 @@ module RuboCop
|
|
|
107
107
|
end
|
|
108
108
|
|
|
109
109
|
def find_method_definition(node, method_name)
|
|
110
|
-
node.each_ancestor
|
|
111
|
-
ancestor.each_child_node(:def, :any_block).find do |child|
|
|
110
|
+
node.each_ancestor do |ancestor|
|
|
111
|
+
found = ancestor.each_child_node(:def, :any_block).find do |child|
|
|
112
112
|
method_definition(child, method_name)
|
|
113
113
|
end
|
|
114
|
-
|
|
114
|
+
return found if found
|
|
115
|
+
# A method defined in an outer lexical scope does not define this scope's method,
|
|
116
|
+
# so stop searching once a class/module boundary is crossed without a match.
|
|
117
|
+
return nil if ancestor.type?(:class, :module, :sclass)
|
|
118
|
+
end
|
|
115
119
|
end
|
|
116
120
|
|
|
117
121
|
# `ruby2_keywords` is only allowed if there's a `restarg` and no keyword arguments
|
|
@@ -107,7 +107,10 @@ module RuboCop
|
|
|
107
107
|
end
|
|
108
108
|
|
|
109
109
|
def process_multiple_assignment(masgn_node)
|
|
110
|
-
|
|
110
|
+
# Iterate the top-level destructuring slots so each maps to the right-hand side
|
|
111
|
+
# element at the same position. Using the flattened `assignments` would misalign
|
|
112
|
+
# the index when a slot is itself a nested destructuring (e.g. `(a, b), c = x, y`).
|
|
113
|
+
masgn_node.lhs.children.each_with_index do |lhs_node, index|
|
|
111
114
|
next unless ASSIGNMENT_TYPES.include?(lhs_node.type)
|
|
112
115
|
|
|
113
116
|
if masgn_node.rhs.array_type? && (rhs_node = masgn_node.rhs.children[index])
|
|
@@ -83,7 +83,7 @@ module RuboCop
|
|
|
83
83
|
|
|
84
84
|
def autocorrect_block(corrector, node)
|
|
85
85
|
block_arg = block_arg(node)
|
|
86
|
-
return
|
|
86
|
+
return unless reducible_to_body?(node, block_arg)
|
|
87
87
|
|
|
88
88
|
source = node.body.source
|
|
89
89
|
source.gsub!(/\b#{block_arg}\b/, '0') if block_arg
|
|
@@ -91,6 +91,27 @@ module RuboCop
|
|
|
91
91
|
corrector.replace(node, fix_indentation(source, node.loc.column...node.body.loc.column))
|
|
92
92
|
end
|
|
93
93
|
|
|
94
|
+
def reducible_to_body?(node, block_arg)
|
|
95
|
+
# A block with multiple arguments can't be reduced to its body (the extra arguments
|
|
96
|
+
# would become undefined references), and `next`/`break`/`redo` bound to the block
|
|
97
|
+
# become orphaned (a syntax error) once the block is removed.
|
|
98
|
+
return false if node.arguments.size > 1 || orphans_loop_control_keyword?(node)
|
|
99
|
+
|
|
100
|
+
# A lone non-simple argument (destructuring `|(a, b)|` or a splat `|*a|`) can't be
|
|
101
|
+
# substituted either, so reducing to the body would leave it referencing an
|
|
102
|
+
# undefined variable.
|
|
103
|
+
return false if node.arguments.one? && block_arg.nil?
|
|
104
|
+
|
|
105
|
+
!block_reassigns_arg?(node, block_arg)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def orphans_loop_control_keyword?(node)
|
|
109
|
+
node.body&.each_node(:next, :break, :redo)&.any? do |control|
|
|
110
|
+
inner = control.each_ancestor.take_while { |ancestor| !ancestor.equal?(node) }
|
|
111
|
+
inner.none? { |ancestor| ancestor.type?(:any_block, :while, :until, :for) }
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
94
115
|
def fix_indentation(source, range)
|
|
95
116
|
# Cleanup indentation in a multiline block
|
|
96
117
|
source_lines = source.split("\n")
|