rubocop 1.90.0 → 1.92.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/README.md +1 -1
- data/config/default.yml +241 -11
- data/config/obsoletion.yml +9 -0
- data/lib/rubocop/cached_data.rb +47 -7
- data/lib/rubocop/changed_files.rb +134 -0
- data/lib/rubocop/cli/command/cop_names.rb +57 -0
- data/lib/rubocop/cli/command/execute_runner.rb +23 -3
- data/lib/rubocop/cli/command/explain.rb +34 -0
- data/lib/rubocop/cli/command/show_cops.rb +6 -0
- data/lib/rubocop/cli/command/show_docs_url.rb +6 -4
- data/lib/rubocop/cli.rb +11 -4
- data/lib/rubocop/comment_config/directive_range.rb +3 -1
- data/lib/rubocop/comment_config/disable_next.rb +49 -3
- data/lib/rubocop/comment_config/push_pop.rb +55 -0
- data/lib/rubocop/comment_config.rb +32 -53
- data/lib/rubocop/config.rb +10 -0
- data/lib/rubocop/config_loader.rb +18 -7
- data/lib/rubocop/config_loader_resolver.rb +79 -12
- data/lib/rubocop/config_obsoletion/cop_rule.rb +2 -1
- data/lib/rubocop/config_obsoletion/removed_cop.rb +9 -1
- data/lib/rubocop/config_obsoletion.rb +1 -1
- data/lib/rubocop/config_validator.rb +29 -3
- data/lib/rubocop/cop/autocorrect_logic.rb +10 -5
- data/lib/rubocop/cop/badge.rb +1 -1
- data/lib/rubocop/cop/base.rb +57 -24
- data/lib/rubocop/cop/bundler/gem_comment.rb +0 -1
- data/lib/rubocop/cop/bundler/ordered_gems.rb +0 -8
- data/lib/rubocop/cop/cop_documentation.rb +81 -0
- data/lib/rubocop/cop/cop_explanation.rb +140 -0
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +13 -1
- data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +22 -7
- data/lib/rubocop/cop/correctors/empty_line_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +23 -2
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +45 -8
- data/lib/rubocop/cop/correctors.rb +2 -2
- data/lib/rubocop/cop/documentation.rb +1 -1
- data/lib/rubocop/cop/gemspec/dependency_version.rb +0 -6
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +0 -6
- data/lib/rubocop/cop/gemspec/require_mfa.rb +1 -1
- data/lib/rubocop/cop/generator.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +2 -5
- data/lib/rubocop/cop/internal_affairs/node_type_group.rb +0 -7
- data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/redundant_context_config_parameter.rb +1 -7
- data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +1 -7
- data/lib/rubocop/cop/layout/argument_alignment.rb +2 -0
- data/lib/rubocop/cop/layout/block_alignment.rb +27 -0
- data/lib/rubocop/cop/layout/case_indentation.rb +25 -9
- data/lib/rubocop/cop/layout/class_structure.rb +9 -1
- data/lib/rubocop/cop/layout/comment_indentation.rb +8 -5
- data/lib/rubocop/cop/layout/def_end_alignment.rb +4 -0
- data/lib/rubocop/cop/layout/else_alignment.rb +1 -0
- data/lib/rubocop/cop/layout/empty_line_after_multiline_condition.rb +14 -5
- data/lib/rubocop/cop/layout/empty_lines.rb +5 -2
- data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.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 +1 -1
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +23 -1
- data/lib/rubocop/cop/layout/end_alignment.rb +16 -10
- data/lib/rubocop/cop/layout/extra_spacing.rb +4 -0
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -0
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +17 -4
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +5 -3
- data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +6 -0
- data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +4 -0
- data/lib/rubocop/cop/layout/first_parameter_indentation.rb +11 -0
- data/lib/rubocop/cop/layout/hash_alignment.rb +15 -10
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -0
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +15 -0
- data/lib/rubocop/cop/layout/indentation_style.rb +4 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +4 -4
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +8 -1
- data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +25 -9
- data/lib/rubocop/cop/layout/line_length.rb +71 -19
- data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +12 -0
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +8 -1
- data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +7 -0
- data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +6 -0
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +14 -0
- data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +4 -0
- data/lib/rubocop/cop/layout/redundant_line_break.rb +22 -1
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +15 -2
- data/lib/rubocop/cop/layout/single_line_block_chain.rb +10 -2
- data/lib/rubocop/cop/layout/space_after_not.rb +5 -0
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +10 -4
- data/lib/rubocop/cop/layout/space_around_keyword.rb +10 -0
- data/lib/rubocop/cop/layout/space_around_operators.rb +5 -1
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +4 -1
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +15 -2
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +31 -8
- data/lib/rubocop/cop/lint/ambiguous_operator.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +2 -1
- data/lib/rubocop/cop/lint/argument_mismatch.rb +14 -4
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +2 -0
- data/lib/rubocop/cop/lint/cop_directive_syntax.rb +88 -14
- data/lib/rubocop/cop/lint/duplicate_methods.rb +1 -1
- data/lib/rubocop/cop/lint/empty_block.rb +1 -1
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +3 -1
- data/lib/rubocop/cop/lint/literal_as_condition.rb +23 -2
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +63 -19
- data/lib/rubocop/cop/lint/loop.rb +24 -2
- data/lib/rubocop/cop/lint/misplaced_magic_comment.rb +245 -0
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +19 -4
- data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -1
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +1 -1
- data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +17 -1
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +42 -17
- data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +13 -2
- data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +18 -1
- data/lib/rubocop/cop/lint/useless_assignment.rb +14 -7
- data/lib/rubocop/cop/lint/void.rb +8 -1
- data/lib/rubocop/cop/lint.rb +1 -0
- data/lib/rubocop/cop/metrics/class_length.rb +4 -2
- data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +0 -4
- data/lib/rubocop/cop/metrics/module_length.rb +4 -2
- data/lib/rubocop/cop/migration/department_name.rb +1 -1
- data/lib/rubocop/cop/mixin/alignment.rb +5 -1
- data/lib/rubocop/cop/mixin/annotation_comment.rb +1 -1
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +17 -14
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +5 -1
- data/lib/rubocop/cop/mixin/code_length.rb +10 -2
- data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +12 -1
- data/lib/rubocop/cop/mixin/endless_method_body_help.rb +69 -0
- data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +2 -2
- data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +26 -2
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +31 -3
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +1 -1
- data/lib/rubocop/cop/mixin/min_branches_count.rb +3 -1
- data/lib/rubocop/cop/mixin/multiline_element_line_breaks.rb +11 -1
- data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +9 -0
- data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
- data/lib/rubocop/cop/mixin/pattern_matching_help.rb +35 -0
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +29 -3
- data/lib/rubocop/cop/mixin/project_index_help.rb +15 -0
- data/lib/rubocop/cop/mixin/reparsed_equivalence.rb +13 -3
- data/lib/rubocop/cop/mixin/statement_modifier.rb +22 -2
- data/lib/rubocop/cop/mixin.rb +4 -2
- data/lib/rubocop/cop/naming/accessor_method_name.rb +0 -16
- data/lib/rubocop/cop/naming/block_forwarding.rb +4 -1
- data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
- data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +9 -2
- data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +5 -3
- data/lib/rubocop/cop/naming/predicate_prefix.rb +7 -22
- data/lib/rubocop/cop/offense.rb +59 -3
- data/lib/rubocop/cop/registry.rb +10 -2
- data/lib/rubocop/cop/security/json_load.rb +16 -4
- data/lib/rubocop/cop/severity.rb +12 -0
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +10 -2
- data/lib/rubocop/cop/style/alias.rb +18 -5
- data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +4 -3
- data/lib/rubocop/cop/style/and_or.rb +4 -0
- data/lib/rubocop/cop/style/arguments_forwarding.rb +6 -3
- data/lib/rubocop/cop/style/attr.rb +3 -4
- data/lib/rubocop/cop/style/bitwise_predicate.rb +6 -4
- data/lib/rubocop/cop/style/block_delimiters.rb +29 -3
- data/lib/rubocop/cop/style/case_like_if.rb +9 -6
- data/lib/rubocop/cop/style/class_and_module_children.rb +54 -16
- data/lib/rubocop/cop/style/class_methods_definitions.rb +8 -0
- data/lib/rubocop/cop/style/combinable_loops.rb +85 -11
- data/lib/rubocop/cop/style/concat_array_literals.rb +46 -7
- data/lib/rubocop/cop/style/conditional_assignment.rb +4 -0
- data/lib/rubocop/cop/style/constant_visibility.rb +6 -2
- data/lib/rubocop/cop/style/data_inheritance.rb +14 -0
- data/lib/rubocop/cop/style/directive_scope.rb +154 -21
- data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +118 -18
- data/lib/rubocop/cop/style/documentation_method.rb +1 -9
- data/lib/rubocop/cop/style/double_negation.rb +11 -0
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
- data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
- data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
- data/lib/rubocop/cop/style/empty_literal.rb +1 -1
- data/lib/rubocop/cop/style/empty_method.rb +15 -3
- data/lib/rubocop/cop/style/endless_method.rb +91 -11
- data/lib/rubocop/cop/style/exact_regexp_match.rb +45 -8
- data/lib/rubocop/cop/style/explicit_block_argument.rb +50 -10
- data/lib/rubocop/cop/style/file_null.rb +2 -2
- data/lib/rubocop/cop/style/float_division.rb +28 -14
- data/lib/rubocop/cop/style/for.rb +44 -1
- data/lib/rubocop/cop/style/format_string.rb +28 -6
- data/lib/rubocop/cop/style/format_string_token.rb +1 -1
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +2 -1
- data/lib/rubocop/cop/style/guard_clause.rb +13 -1
- data/lib/rubocop/cop/style/hash_conversion.rb +28 -8
- data/lib/rubocop/cop/style/hash_lookup_method.rb +35 -9
- data/lib/rubocop/cop/style/hash_syntax.rb +16 -3
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +22 -3
- data/lib/rubocop/cop/style/if_inside_else.rb +21 -1
- data/lib/rubocop/cop/style/if_unless_modifier.rb +19 -20
- data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +4 -0
- data/lib/rubocop/cop/style/if_with_semicolon.rb +47 -4
- data/lib/rubocop/cop/style/inverse_methods.rb +24 -2
- data/lib/rubocop/cop/style/it_block_parameter.rb +32 -3
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +3 -1
- data/lib/rubocop/cop/style/lambda.rb +18 -0
- data/lib/rubocop/cop/style/lambda_call.rb +7 -2
- data/lib/rubocop/cop/style/magic_comment_format.rb +1 -1
- data/lib/rubocop/cop/style/map_into_array.rb +1 -2
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +45 -10
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +25 -2
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +26 -3
- data/lib/rubocop/cop/style/method_def_parentheses.rb +29 -3
- data/lib/rubocop/cop/style/missing_else.rb +7 -1
- data/lib/rubocop/cop/style/multiline_if_modifier.rb +45 -5
- data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +7 -0
- data/lib/rubocop/cop/style/multiline_method_signature.rb +2 -5
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +7 -3
- data/lib/rubocop/cop/style/multiline_when_then.rb +7 -0
- data/lib/rubocop/cop/style/mutable_constant.rb +28 -1
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +2 -1
- data/lib/rubocop/cop/style/negative_array_index.rb +9 -1
- data/lib/rubocop/cop/style/nested_modifier.rb +36 -12
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +26 -8
- data/lib/rubocop/cop/style/next.rb +24 -10
- data/lib/rubocop/cop/style/nil_comparison.rb +48 -8
- data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
- data/lib/rubocop/cop/style/non_nil_check.rb +18 -2
- data/lib/rubocop/cop/style/not.rb +10 -3
- data/lib/rubocop/cop/style/numeric_literal_prefix.rb +11 -1
- data/lib/rubocop/cop/style/numeric_predicate.rb +21 -5
- data/lib/rubocop/cop/style/one_line_conditional.rb +14 -3
- data/lib/rubocop/cop/style/parallel_assignment.rb +1 -1
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +6 -1
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +14 -3
- data/lib/rubocop/cop/style/reduce_to_hash.rb +17 -1
- data/lib/rubocop/cop/style/redundant_begin.rb +20 -3
- data/lib/rubocop/cop/style/redundant_condition.rb +34 -17
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +16 -1
- data/lib/rubocop/cop/style/redundant_exception.rb +15 -3
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +10 -2
- data/lib/rubocop/cop/style/redundant_freeze.rb +10 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +23 -2
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +7 -0
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +6 -5
- data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +25 -5
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +4 -0
- data/lib/rubocop/cop/style/regexp_literal.rb +75 -26
- data/lib/rubocop/cop/style/require_order.rb +9 -0
- data/lib/rubocop/cop/style/rescue_modifier.rb +5 -9
- data/lib/rubocop/cop/style/return_nil.rb +17 -2
- data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +11 -1
- data/lib/rubocop/cop/style/sample.rb +9 -8
- data/lib/rubocop/cop/style/self_assignment.rb +12 -15
- data/lib/rubocop/cop/style/semicolon.rb +16 -5
- data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
- data/lib/rubocop/cop/style/single_line_methods.rb +16 -4
- data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +29 -5
- data/lib/rubocop/cop/style/string_concatenation.rb +9 -3
- data/lib/rubocop/cop/style/struct_inheritance.rb +14 -0
- data/lib/rubocop/cop/style/super_arguments.rb +3 -0
- data/lib/rubocop/cop/style/symbol_proc.rb +23 -5
- data/lib/rubocop/cop/style/ternary_parentheses.rb +23 -1
- data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +23 -19
- data/lib/rubocop/cop/style/while_until_modifier.rb +1 -1
- data/lib/rubocop/cop/style/yoda_condition.rb +24 -9
- data/lib/rubocop/cop/style/yoda_expression.rb +10 -1
- data/lib/rubocop/cop/style.rb +0 -1
- data/lib/rubocop/cop/team.rb +10 -5
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/cop/variable_force/assignment.rb +1 -1
- data/lib/rubocop/cop/variable_force/variable.rb +14 -1
- data/lib/rubocop/cops_documentation_generator.rb +23 -2
- data/lib/rubocop/directive_comment.rb +37 -8
- data/lib/rubocop/formatter/base_formatter.rb +22 -0
- data/lib/rubocop/formatter/disabled_config_formatter.rb +19 -1
- data/lib/rubocop/formatter/formatter_set.rb +6 -1
- data/lib/rubocop/formatter/github_actions_formatter.rb +6 -5
- data/lib/rubocop/formatter/html_formatter.rb +2 -2
- data/lib/rubocop/formatter/json_formatter.rb +71 -1
- data/lib/rubocop/formatter/junit_formatter.rb +1 -1
- data/lib/rubocop/formatter/offense_count_formatter.rb +3 -1
- data/lib/rubocop/formatter/pacman_formatter.rb +3 -1
- data/lib/rubocop/formatter/sarif_formatter.rb +186 -0
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +3 -1
- data/lib/rubocop/formatter.rb +1 -0
- data/lib/rubocop/lsp/runtime.rb +47 -11
- data/lib/rubocop/lsp/stdin_runner.rb +11 -5
- data/lib/rubocop/lsp.rb +5 -2
- data/lib/rubocop/magic_comment.rb +27 -0
- data/lib/rubocop/mcp/autocorrection_request.rb +52 -0
- data/lib/rubocop/mcp/explain_tool.rb +68 -0
- data/lib/rubocop/mcp/scope.rb +65 -0
- data/lib/rubocop/mcp/server.rb +184 -76
- data/lib/rubocop/mcp/source_files.rb +35 -0
- data/lib/rubocop/offense_limit.rb +30 -0
- data/lib/rubocop/options.rb +97 -4
- data/lib/rubocop/path_util.rb +1 -1
- data/lib/rubocop/plugin/configuration_integrator.rb +12 -5
- data/lib/rubocop/plugin/loader.rb +1 -1
- data/lib/rubocop/rake_task.rb +1 -1
- data/lib/rubocop/remote_config.rb +8 -5
- data/lib/rubocop/result_cache.rb +36 -18
- data/lib/rubocop/runner.rb +160 -49
- data/lib/rubocop/server/cache.rb +2 -2
- data/lib/rubocop/unified_diff.rb +257 -0
- data/lib/rubocop/util.rb +69 -0
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +9 -1
- metadata +21 -6
- data/lib/rubocop/cop/style/double_cop_disable_directive.rb +0 -46
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# Lint/RedundantCopDisableDirective needs to be disabled so as
|
|
4
4
|
# to be able to provide examples of rubocop:disable comments.
|
|
5
|
-
# rubocop:disable-next Lint/RedundantCopDisableDirective
|
|
5
|
+
# rubocop:disable-next Lint/RedundantCopDisableDirective -- the examples below read as real directives
|
|
6
6
|
module RuboCop
|
|
7
7
|
module Cop
|
|
8
8
|
module Migration
|
|
@@ -15,6 +15,10 @@ module RuboCop
|
|
|
15
15
|
cop_config['IndentationWidth'] || config.for_cop('Layout/IndentationWidth')['Width'] || 2
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
+
def using_tabs?
|
|
19
|
+
config.for_cop('Layout/IndentationStyle')['EnforcedStyle'] == 'tabs'
|
|
20
|
+
end
|
|
21
|
+
|
|
18
22
|
def indentation(node)
|
|
19
23
|
offset(node) + (SPACE * configured_indentation_width)
|
|
20
24
|
end
|
|
@@ -66,7 +70,7 @@ module RuboCop
|
|
|
66
70
|
end
|
|
67
71
|
|
|
68
72
|
# @deprecated Use processed_source.line_with_comment?(line)
|
|
69
|
-
def end_of_line_comment(line) # rubocop:disable Naming/PredicateMethod
|
|
73
|
+
def end_of_line_comment(line) # rubocop:disable Naming/PredicateMethod -- a deprecated shim kept under its original name
|
|
70
74
|
warn Rainbow(<<~WARNING).yellow, uplevel: 1
|
|
71
75
|
`end_of_line_comment` is deprecated. Use `processed_source.line_with_comment?` instead.
|
|
72
76
|
WARNING
|
|
@@ -45,7 +45,7 @@ module RuboCop
|
|
|
45
45
|
match.captures
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
-
KEYWORDS_REGEX_CACHE = {} # rubocop:disable Style/MutableConstant
|
|
48
|
+
KEYWORDS_REGEX_CACHE = {} # rubocop:disable Style/MutableConstant -- a cache, written to at runtime
|
|
49
49
|
private_constant :KEYWORDS_REGEX_CACHE
|
|
50
50
|
|
|
51
51
|
def regex
|
|
@@ -94,22 +94,29 @@ module RuboCop
|
|
|
94
94
|
|
|
95
95
|
# @api private
|
|
96
96
|
def first_argument_is_heredoc?(node)
|
|
97
|
-
first_argument
|
|
98
|
-
|
|
99
|
-
first_argument.respond_to?(:heredoc?) && first_argument.heredoc?
|
|
97
|
+
node.first_argument.respond_to?(:heredoc?) && node.first_argument.heredoc?
|
|
100
98
|
end
|
|
101
99
|
|
|
102
100
|
# @api private
|
|
103
101
|
# If a `send` or `csend` node contains a heredoc argument, splitting cannot happen
|
|
104
102
|
# after the heredoc or else it will cause a syntax error.
|
|
105
103
|
def shift_elements_for_heredoc_arg(node, elements, index)
|
|
106
|
-
return index unless node.type?(:call, :array)
|
|
104
|
+
return index unless node.type?(:call, :array, :hash)
|
|
105
|
+
return index unless (heredoc_pos = heredoc_begin_position(node))
|
|
106
|
+
|
|
107
|
+
last_safe = elements.rindex { |element| element.source_range.begin_pos <= heredoc_pos }
|
|
108
|
+
return nil if last_safe.nil? ||
|
|
109
|
+
(last_safe.zero? && elements.first.source_range.end_pos > heredoc_pos)
|
|
107
110
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
return nil if heredoc_index.zero?
|
|
111
|
+
[index, last_safe + 1].min
|
|
112
|
+
end
|
|
111
113
|
|
|
112
|
-
|
|
114
|
+
# @api private
|
|
115
|
+
def heredoc_begin_position(node)
|
|
116
|
+
children = node.call_type? ? node.arguments : node.children
|
|
117
|
+
children.flat_map { |child| [child, *child.each_descendant(:any_str)] }
|
|
118
|
+
.find { |descendant| descendant.type?(:any_str) && descendant.heredoc? }
|
|
119
|
+
&.source_range&.begin_pos
|
|
113
120
|
end
|
|
114
121
|
|
|
115
122
|
# @api private
|
|
@@ -128,9 +135,7 @@ module RuboCop
|
|
|
128
135
|
# or redundant edits, we only mark one offense at a time.
|
|
129
136
|
return true if contained_by_breakable_collection_on_same_line?(node)
|
|
130
137
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
false
|
|
138
|
+
contained_by_multiline_collection_that_could_be_broken_up?(node)
|
|
134
139
|
end
|
|
135
140
|
|
|
136
141
|
# @api private
|
|
@@ -145,9 +150,7 @@ module RuboCop
|
|
|
145
150
|
# break before the second argument and the rest of the
|
|
146
151
|
# argument will get auto-formatted onto separate lines
|
|
147
152
|
# by other cops.
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
starts_with_bracket && has_second_element
|
|
153
|
+
starts_with_bracket && elements.length >= 2
|
|
151
154
|
end
|
|
152
155
|
|
|
153
156
|
# @api private
|
|
@@ -14,9 +14,13 @@ module RuboCop
|
|
|
14
14
|
private
|
|
15
15
|
|
|
16
16
|
def too_long?(node)
|
|
17
|
+
too_long_as_single_line?(node.first_line..node.last_line)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def too_long_as_single_line?(line_range)
|
|
17
21
|
return false unless max_line_length
|
|
18
22
|
|
|
19
|
-
lines = processed_source.lines[(
|
|
23
|
+
lines = processed_source.lines[(line_range.begin - 1)...line_range.end]
|
|
20
24
|
to_single_line(lines.join("\n")).length > max_line_length
|
|
21
25
|
end
|
|
22
26
|
|
|
@@ -59,12 +59,20 @@ module RuboCop
|
|
|
59
59
|
return node.loc.name if node.casgn_type?
|
|
60
60
|
|
|
61
61
|
if LSP.enabled?
|
|
62
|
-
|
|
63
|
-
node.source_range.begin.join(end_range)
|
|
62
|
+
node.source_range.begin.join(header_end(node))
|
|
64
63
|
else
|
|
65
64
|
node.source_range
|
|
66
65
|
end
|
|
67
66
|
end
|
|
67
|
+
|
|
68
|
+
# Where the header of a definition ends: the name of a class, module or
|
|
69
|
+
# method, the `self` of `class << self`, or the opening of a block.
|
|
70
|
+
def header_end(node)
|
|
71
|
+
return node.loc.name if node.loc?(:name)
|
|
72
|
+
return node.identifier.source_range if node.sclass_type?
|
|
73
|
+
|
|
74
|
+
node.loc.begin
|
|
75
|
+
end
|
|
68
76
|
end
|
|
69
77
|
end
|
|
70
78
|
end
|
|
@@ -5,7 +5,7 @@ module RuboCop
|
|
|
5
5
|
module Layout
|
|
6
6
|
# Common functionality for checking if presence/absence of empty lines
|
|
7
7
|
# around some kind of body matches the configuration.
|
|
8
|
-
module EmptyLinesAroundBody
|
|
8
|
+
module EmptyLinesAroundBody # rubocop:disable Metrics/ModuleLength
|
|
9
9
|
extend NodePattern::Macros
|
|
10
10
|
include ConfigurableEnforcedStyle
|
|
11
11
|
include RangeHelp
|
|
@@ -14,6 +14,8 @@ module RuboCop
|
|
|
14
14
|
MSG_MISSING = 'Empty line missing at %<kind>s body %<location>s.'
|
|
15
15
|
MSG_DEFERRED = 'Empty line missing before first %<type>s definition'
|
|
16
16
|
|
|
17
|
+
LEADING_DOT_TYPES = %i[tDOT tANDDOT].to_set.freeze
|
|
18
|
+
|
|
17
19
|
private
|
|
18
20
|
|
|
19
21
|
# @!method constant_definition?(node)
|
|
@@ -29,6 +31,7 @@ module RuboCop
|
|
|
29
31
|
|
|
30
32
|
first_line = adjusted_first_line || node.source_range.first_line
|
|
31
33
|
last_line = node.source_range.last_line
|
|
34
|
+
return if first_line >= last_line
|
|
32
35
|
|
|
33
36
|
case style
|
|
34
37
|
when :empty_lines_except_namespace
|
|
@@ -99,12 +102,20 @@ module RuboCop
|
|
|
99
102
|
return unless yield(processed_source.lines[line])
|
|
100
103
|
|
|
101
104
|
offset = style == :empty_lines && msg.include?('end.') ? 2 : 1
|
|
105
|
+
return if style == :empty_lines && leading_dot_line?(line + offset)
|
|
106
|
+
|
|
102
107
|
range = source_range(processed_source.buffer, line + offset, 0)
|
|
103
108
|
add_offense(range, message: msg) do |corrector|
|
|
104
109
|
EmptyLineCorrector.correct(corrector, [style, range])
|
|
105
110
|
end
|
|
106
111
|
end
|
|
107
112
|
|
|
113
|
+
def leading_dot_line?(line)
|
|
114
|
+
first_token = processed_source.sorted_tokens.find { |token| token.line == line }
|
|
115
|
+
|
|
116
|
+
LEADING_DOT_TYPES.include?(first_token&.type)
|
|
117
|
+
end
|
|
118
|
+
|
|
108
119
|
def check_deferred_empty_line(body)
|
|
109
120
|
node = first_empty_line_required_child(body)
|
|
110
121
|
return unless node
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
# Common functionality for checking whether a method body can become the
|
|
6
|
+
# body of an endless method definition without changing its meaning.
|
|
7
|
+
module EndlessMethodBodyHelp
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
def endless_method_body?(body)
|
|
11
|
+
return false if body.type?(:begin, :kwbegin, :rescue, :ensure, :masgn)
|
|
12
|
+
return false if low_precedence_body?(body)
|
|
13
|
+
return false if ends_with_omitted_hash_value?(body) || ends_with_anonymous_argument?(body)
|
|
14
|
+
return false if body.assignment? && multiple_values?(assigned_value(body))
|
|
15
|
+
|
|
16
|
+
!command_disallowed_in_endless_body?(body)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# `def foo = bar and baz` parses as `(def foo = bar) and baz`.
|
|
20
|
+
def low_precedence_body?(body)
|
|
21
|
+
body.type?(:any_match_pattern, :while_post, :until_post) ||
|
|
22
|
+
(body.type?(:and, :or) && body.semantic_operator?) ||
|
|
23
|
+
(body.type?(:if, :while, :until) && body.modifier_form?)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# `foo = 1, 2` and `foo = *bar` assign an array without brackets.
|
|
27
|
+
def multiple_values?(node)
|
|
28
|
+
node.array_type? && !node.bracketed?
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def ends_with_omitted_hash_value?(body)
|
|
32
|
+
body.each_descendant(:pair).any? do |pair|
|
|
33
|
+
pair.value_omission? && pair.source_range.end_pos == body.source_range.end_pos
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def ends_with_anonymous_argument?(body)
|
|
38
|
+
forwarding = %i[forwarded_restarg forwarded_kwrestarg block_pass]
|
|
39
|
+
|
|
40
|
+
body.each_descendant(*forwarding).any? do |argument|
|
|
41
|
+
argument.source_range.end_pos == body.source_range.end_pos &&
|
|
42
|
+
(!argument.block_pass_type? || argument.children.first.nil?)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def command_disallowed_in_endless_body?(body)
|
|
47
|
+
return true if body.assignment? && command_call?(assigned_value(body))
|
|
48
|
+
|
|
49
|
+
body.each_node(:any_block).any? do |block|
|
|
50
|
+
block.keywords? && command_call?(block.send_node)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def assigned_value(node)
|
|
55
|
+
while node.assignment? || node.rescue_type?
|
|
56
|
+
node = node.rescue_type? ? node.body : node.children.last
|
|
57
|
+
end
|
|
58
|
+
node
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def command_call?(node)
|
|
62
|
+
node = node.send_node if node.any_block_type?
|
|
63
|
+
return false unless node.type?(:call, :super, :yield)
|
|
64
|
+
|
|
65
|
+
node.arguments? && !node.parenthesized? && !node.operator_method? && !node.setter_method?
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -7,9 +7,9 @@ module RuboCop
|
|
|
7
7
|
SIGILS = '@$' # if a variable starts with a sigil it will be removed
|
|
8
8
|
|
|
9
9
|
def forbidden_identifier?(name)
|
|
10
|
-
|
|
10
|
+
return false if forbidden_identifiers.empty?
|
|
11
11
|
|
|
12
|
-
forbidden_identifiers.
|
|
12
|
+
forbidden_identifiers.include?(name.to_s.delete(SIGILS))
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def forbidden_identifiers
|
|
@@ -55,7 +55,7 @@ module RuboCop
|
|
|
55
55
|
# Common functionality for checking alignment of hash values.
|
|
56
56
|
module ValueAlignment
|
|
57
57
|
def checkable_layout?(node)
|
|
58
|
-
!node.pairs_on_same_line? && !node.mixed_delimiters?
|
|
58
|
+
!node.pairs_on_same_line? && !node.mixed_delimiters? && alignable_values?(node)
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
def deltas(first_pair, current_pair)
|
|
@@ -68,6 +68,16 @@ module RuboCop
|
|
|
68
68
|
|
|
69
69
|
private
|
|
70
70
|
|
|
71
|
+
def alignable_values?(node)
|
|
72
|
+
return false if node.pairs.first.value_omission?
|
|
73
|
+
|
|
74
|
+
node.pairs.none? { |pair| value_on_later_line?(pair) }
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def value_on_later_line?(pair)
|
|
78
|
+
pair.value && pair.key.last_line != pair.value.first_line
|
|
79
|
+
end
|
|
80
|
+
|
|
71
81
|
def separator_delta(first_pair, current_pair, key_delta)
|
|
72
82
|
if current_pair.hash_rocket?
|
|
73
83
|
hash_rocket_delta(first_pair, current_pair) - key_delta
|
|
@@ -142,6 +152,17 @@ module RuboCop
|
|
|
142
152
|
{}
|
|
143
153
|
end
|
|
144
154
|
|
|
155
|
+
# Keys are right-aligned by the column their last line ends on.
|
|
156
|
+
# A key spanning several lines ends on a line other than the one it starts on,
|
|
157
|
+
# so moving its first line would never change that column and the correction
|
|
158
|
+
# would be repeated on every pass. Such pairs are left alone, and so is every pair
|
|
159
|
+
# when the first key spans several lines, since there is then no column to right-align to.
|
|
160
|
+
def deltas(first_pair, current_pair)
|
|
161
|
+
return {} if first_pair.key.multiline? || current_pair.key.multiline?
|
|
162
|
+
|
|
163
|
+
super
|
|
164
|
+
end
|
|
165
|
+
|
|
145
166
|
private
|
|
146
167
|
|
|
147
168
|
def key_delta(first_pair, current_pair)
|
|
@@ -153,7 +174,10 @@ module RuboCop
|
|
|
153
174
|
end
|
|
154
175
|
|
|
155
176
|
def value_delta(first_pair, current_pair)
|
|
156
|
-
|
|
177
|
+
return 0 if first_pair.equal?(current_pair) || current_pair.value_omission?
|
|
178
|
+
|
|
179
|
+
expected_value_column = first_pair.loc.operator.end.column + 1
|
|
180
|
+
expected_value_column - current_pair.value.loc.column
|
|
157
181
|
end
|
|
158
182
|
end
|
|
159
183
|
|
|
@@ -11,6 +11,15 @@ module RuboCop
|
|
|
11
11
|
DO_NOT_MIX_OMIT_VALUE_MSG = "#{DO_NOT_MIX_MSG_PREFIX} #{OMIT_HASH_VALUE_MSG}"
|
|
12
12
|
DO_NOT_MIX_EXPLICIT_VALUE_MSG = "#{DO_NOT_MIX_MSG_PREFIX} #{EXPLICIT_HASH_VALUE_MSG}"
|
|
13
13
|
|
|
14
|
+
# A keyword parameter can be named after a keyword, as in `def foo(if:)`,
|
|
15
|
+
# but the parameter can only be referenced by an omitted hash value,
|
|
16
|
+
# so `{ if: }` has no explicit form: `{ if: if }` is invalid Ruby.
|
|
17
|
+
KEYWORDS = %i[
|
|
18
|
+
__ENCODING__ __FILE__ __LINE__ BEGIN END alias and begin break case class def do
|
|
19
|
+
else elsif end ensure false for if in module next nil not or redo rescue retry
|
|
20
|
+
return self super then true undef unless until when while yield
|
|
21
|
+
].to_set.freeze
|
|
22
|
+
|
|
14
23
|
DefNode = Struct.new(:node) do
|
|
15
24
|
def selector
|
|
16
25
|
if node.loc?(:selector)
|
|
@@ -53,7 +62,7 @@ module RuboCop
|
|
|
53
62
|
replacement = "#{hash_key_source}:"
|
|
54
63
|
self.config_to_allow_offenses = { 'Enabled' => false }
|
|
55
64
|
else
|
|
56
|
-
return
|
|
65
|
+
return if !node.value_omission? || keyword_value?(node)
|
|
57
66
|
|
|
58
67
|
message = EXPLICIT_HASH_VALUE_MSG
|
|
59
68
|
replacement = "#{hash_key_source}: #{hash_key_source}"
|
|
@@ -87,13 +96,26 @@ module RuboCop
|
|
|
87
96
|
def ignore_mixed_hash_shorthand_syntax?(hash_node)
|
|
88
97
|
target_ruby_version <= 3.0 ||
|
|
89
98
|
!%w[consistent either_consistent].include?(enforced_shorthand_syntax) ||
|
|
90
|
-
!hash_node.hash_type?
|
|
99
|
+
!hash_node.hash_type? || hash_rockets_enforced?(hash_node)
|
|
91
100
|
end
|
|
92
101
|
|
|
93
102
|
def ignore_hash_shorthand_syntax?(pair_node)
|
|
94
103
|
target_ruby_version <= 3.0 || enforced_shorthand_syntax == 'either' ||
|
|
95
104
|
%w[consistent either_consistent].include?(enforced_shorthand_syntax) ||
|
|
96
|
-
!pair_node.parent.hash_type?
|
|
105
|
+
!pair_node.parent.hash_type? || hash_rockets_enforced?(pair_node.parent)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def hash_rockets_enforced?(hash_node)
|
|
109
|
+
style == :hash_rockets || force_hash_rockets?(hash_node.pairs) ||
|
|
110
|
+
no_mixed_keys_enforces_hash_rockets?(hash_node.pairs)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def no_mixed_keys_enforces_hash_rockets?(pairs)
|
|
114
|
+
case style
|
|
115
|
+
when :no_mixed_keys then !sym_indices?(pairs) || pairs.first.delimiter == '=>'
|
|
116
|
+
when :ruby19_no_mixed_keys then !sym_indices?(pairs)
|
|
117
|
+
else false
|
|
118
|
+
end
|
|
97
119
|
end
|
|
98
120
|
|
|
99
121
|
def enforced_shorthand_syntax
|
|
@@ -206,6 +228,8 @@ module RuboCop
|
|
|
206
228
|
def mixed_shorthand_syntax_check(hash_value_type_breakdown)
|
|
207
229
|
if hash_with_values_that_cant_be_omitted?(hash_value_type_breakdown)
|
|
208
230
|
each_omitted_value_pair(hash_value_type_breakdown) do |pair_node|
|
|
231
|
+
next if keyword_value?(pair_node)
|
|
232
|
+
|
|
209
233
|
hash_key_source = pair_node.key.source
|
|
210
234
|
replacement = "#{hash_key_source}: #{hash_key_source}"
|
|
211
235
|
register_offense(pair_node, DO_NOT_MIX_EXPLICIT_VALUE_MSG, replacement)
|
|
@@ -229,6 +253,10 @@ module RuboCop
|
|
|
229
253
|
register_offense(pair_node, OMIT_HASH_VALUE_MSG, replacement)
|
|
230
254
|
end
|
|
231
255
|
end
|
|
256
|
+
|
|
257
|
+
def keyword_value?(pair_node)
|
|
258
|
+
KEYWORDS.include?(pair_node.key.value)
|
|
259
|
+
end
|
|
232
260
|
end
|
|
233
261
|
end
|
|
234
262
|
# rubocop:enable Metrics/ModuleLength
|
|
@@ -38,7 +38,7 @@ module RuboCop
|
|
|
38
38
|
(block (send _ :each_with_object (hash)) ...)}
|
|
39
39
|
PATTERN
|
|
40
40
|
|
|
41
|
-
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler, InternalAffairs/ItblockHandler
|
|
41
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler, InternalAffairs/ItblockHandler -- the patterns matched here all name their block parameters
|
|
42
42
|
on_bad_each_with_object(node) do |*match|
|
|
43
43
|
handle_possible_offense(node, match, 'each_with_object')
|
|
44
44
|
end
|
|
@@ -32,7 +32,9 @@ module RuboCop
|
|
|
32
32
|
branches << node.if_branch
|
|
33
33
|
|
|
34
34
|
else_branch = node.else_branch
|
|
35
|
-
|
|
35
|
+
if else_branch&.if_type? && else_branch.elsif?
|
|
36
|
+
if_conditional_branches(else_branch, branches)
|
|
37
|
+
end
|
|
36
38
|
branches
|
|
37
39
|
end
|
|
38
40
|
end
|
|
@@ -11,8 +11,10 @@ module RuboCop
|
|
|
11
11
|
return if all_on_same_line?(children, ignore_last: ignore_last)
|
|
12
12
|
|
|
13
13
|
last_seen_line = -1
|
|
14
|
-
children.
|
|
14
|
+
children.each_with_index do |child, index|
|
|
15
15
|
if last_seen_line >= child.first_line
|
|
16
|
+
next if heredoc_opened_before?(children.first(index), child)
|
|
17
|
+
|
|
16
18
|
add_offense(child) { |corrector| EmptyLineCorrector.insert_before(corrector, child) }
|
|
17
19
|
else
|
|
18
20
|
last_seen_line = child.last_line
|
|
@@ -27,6 +29,14 @@ module RuboCop
|
|
|
27
29
|
|
|
28
30
|
nodes.first.first_line == nodes.last.last_line
|
|
29
31
|
end
|
|
32
|
+
|
|
33
|
+
def heredoc_opened_before?(previous_children, child)
|
|
34
|
+
previous_children.any? do |previous|
|
|
35
|
+
previous.each_node(:any_str).any? do |str|
|
|
36
|
+
str.heredoc? && same_line?(str, child)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
30
40
|
end
|
|
31
41
|
end
|
|
32
42
|
end
|
|
@@ -15,6 +15,7 @@ module RuboCop
|
|
|
15
15
|
# If the last node is or contains a conflicting HEREDOC, we don't want
|
|
16
16
|
# to adjust the brace layout because this will result in invalid code.
|
|
17
17
|
return if last_line_heredoc?(node.children.last)
|
|
18
|
+
return if heredoc_opened_on_closing_brace_line?(node)
|
|
18
19
|
|
|
19
20
|
check(node)
|
|
20
21
|
end
|
|
@@ -136,6 +137,14 @@ module RuboCop
|
|
|
136
137
|
|
|
137
138
|
node.children.any? { |child| last_line_heredoc?(child, parent) }
|
|
138
139
|
end
|
|
140
|
+
|
|
141
|
+
def heredoc_opened_on_closing_brace_line?(node)
|
|
142
|
+
closing_brace_line = node.loc.end.line
|
|
143
|
+
|
|
144
|
+
node.each_descendant(:any_str).any? do |str|
|
|
145
|
+
str.heredoc? && str.first_line == closing_brace_line
|
|
146
|
+
end
|
|
147
|
+
end
|
|
139
148
|
end
|
|
140
149
|
end
|
|
141
150
|
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
# Common functionality for checking whether a node is used in a pattern of
|
|
6
|
+
# pattern matching, where only some expressions are allowed.
|
|
7
|
+
module PatternMatchingHelp
|
|
8
|
+
PATTERN_TYPES = %i[
|
|
9
|
+
array_pattern array_pattern_with_tail begin const_pattern find_pattern hash_pattern
|
|
10
|
+
match_alt match_as pair
|
|
11
|
+
].freeze
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def in_pattern?(node)
|
|
16
|
+
child = node
|
|
17
|
+
|
|
18
|
+
node.each_ancestor do |ancestor|
|
|
19
|
+
case ancestor.type
|
|
20
|
+
when :in_pattern
|
|
21
|
+
return ancestor.pattern.equal?(child)
|
|
22
|
+
when :match_pattern, :match_pattern_p
|
|
23
|
+
return ancestor.children[1].equal?(child)
|
|
24
|
+
when *PATTERN_TYPES
|
|
25
|
+
child = ancestor
|
|
26
|
+
else
|
|
27
|
+
return false
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
false
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -174,15 +174,31 @@ module RuboCop
|
|
|
174
174
|
# ^
|
|
175
175
|
tokens = remove_equals_in_def(tokens, processed_source)
|
|
176
176
|
|
|
177
|
-
# Only attempt to align the first = on each line
|
|
178
|
-
|
|
177
|
+
# Only attempt to align the first = on each line. An `=` that comes after a comparison
|
|
178
|
+
# on its line is left out as well: whether a line is aligned is judged by its first
|
|
179
|
+
# assignment or comparison operator, so such an `=` could never be found aligned
|
|
180
|
+
# and `Layout/SpaceAroundOperators` would keep undoing the padding added for it.
|
|
181
|
+
Set.new(tokens.uniq(&:line).select do |token|
|
|
182
|
+
first_operator_on_line(token.line).equal?(token)
|
|
183
|
+
end)
|
|
179
184
|
end
|
|
180
185
|
end
|
|
181
186
|
|
|
182
187
|
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
|
183
188
|
# rubocop:disable Metrics/PerceivedComplexity, Metrics/MethodLength
|
|
184
189
|
def relevant_assignment_lines(line_range)
|
|
185
|
-
relevant_lines(line_range)
|
|
190
|
+
relevant_lines(line_range, interrupting_operator_lines) do |line_number|
|
|
191
|
+
assignment_lines.include?(line_number)
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def interrupting_operator_lines
|
|
196
|
+
@interrupting_operator_lines ||=
|
|
197
|
+
processed_source.tokens.each_with_object(Set.new) do |token, lines|
|
|
198
|
+
next unless ASSIGNMENT_OR_COMPARISON_TOKENS.include?(token.type)
|
|
199
|
+
|
|
200
|
+
lines << token.line unless assignment_lines.include?(token.line)
|
|
201
|
+
end
|
|
186
202
|
end
|
|
187
203
|
|
|
188
204
|
def alignment_lines(line_number)
|
|
@@ -259,6 +275,16 @@ module RuboCop
|
|
|
259
275
|
|
|
260
276
|
asgn_tokens.reject { |t| eqls_to_ignore.include?(t.begin_pos) }
|
|
261
277
|
end
|
|
278
|
+
|
|
279
|
+
def first_operator_on_line(line)
|
|
280
|
+
@first_operator_by_line ||= processed_source.tokens.each_with_object({}) do |token, by_line|
|
|
281
|
+
next unless ASSIGNMENT_OR_COMPARISON_TOKENS.include?(token.type)
|
|
282
|
+
|
|
283
|
+
by_line[token.line] ||= token
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
@first_operator_by_line[line]
|
|
287
|
+
end
|
|
262
288
|
end
|
|
263
289
|
end
|
|
264
290
|
end
|
|
@@ -119,6 +119,21 @@ module RuboCop
|
|
|
119
119
|
end
|
|
120
120
|
end
|
|
121
121
|
|
|
122
|
+
# Whether the `def`/`defs` node overrides a method defined by an ancestor
|
|
123
|
+
# of its enclosing class or module elsewhere in the project.
|
|
124
|
+
def overrides_inherited_method?(def_node)
|
|
125
|
+
return false unless project_index
|
|
126
|
+
return false unless (namespace_node = def_node.each_ancestor(:class, :module).first)
|
|
127
|
+
|
|
128
|
+
declaration = resolve_constant_in_index(namespace_node.identifier)
|
|
129
|
+
return false unless declaration.is_a?(Rubydex::Namespace)
|
|
130
|
+
|
|
131
|
+
scope = def_node.defs_type? ? indexed_singleton_of(declaration) : declaration
|
|
132
|
+
!scope.nil? && inherited_index_member?(scope, "#{def_node.method_name}()")
|
|
133
|
+
rescue StandardError
|
|
134
|
+
false
|
|
135
|
+
end
|
|
136
|
+
|
|
122
137
|
# Whether every link of the declaration's ancestry is resolved in the
|
|
123
138
|
# index: no definition of any ancestor has an unresolved superclass or
|
|
124
139
|
# mixin reference. Unresolved links silently vanish from `ancestors`,
|
|
@@ -51,15 +51,25 @@ module RuboCop
|
|
|
51
51
|
# regardless of size (for cops where verification is the offense logic).
|
|
52
52
|
def verified_by_reparse(items, oversized: :report)
|
|
53
53
|
scope_groups(items).flat_map do |scope, group|
|
|
54
|
-
if
|
|
55
|
-
(group.size > 1 && corrections_verify?(scope, group))
|
|
54
|
+
if oversized == :report && verification_too_large?(scope)
|
|
56
55
|
group
|
|
57
56
|
else
|
|
58
|
-
|
|
57
|
+
verified_subset(scope, group)
|
|
59
58
|
end
|
|
60
59
|
end
|
|
61
60
|
end
|
|
62
61
|
|
|
62
|
+
# Verifies a group with a single reparse and bisects it when that fails,
|
|
63
|
+
# so a few significant items among many cost a logarithmic number of
|
|
64
|
+
# reparses rather than one each.
|
|
65
|
+
def verified_subset(scope, group)
|
|
66
|
+
return group if corrections_verify?(scope, group)
|
|
67
|
+
return [] if group.one?
|
|
68
|
+
|
|
69
|
+
half = group.size / 2
|
|
70
|
+
verified_subset(scope, group.take(half)) + verified_subset(scope, group.drop(half))
|
|
71
|
+
end
|
|
72
|
+
|
|
63
73
|
# Whether the exact correction for `item` produces source that still
|
|
64
74
|
# parses, without requiring an equivalent AST. For corrections that
|
|
65
75
|
# intentionally change the tree.
|
|
@@ -96,9 +96,15 @@ module RuboCop
|
|
|
96
96
|
[parenthesized, first_line_comment(node)].compact.join(' ')
|
|
97
97
|
end
|
|
98
98
|
|
|
99
|
+
# rubocop:disable-next Metrics/AbcSize
|
|
99
100
|
def if_body_source(if_body)
|
|
100
101
|
if if_body.call_type? && !if_body.method?(:[]=) && omitted_value_in_last_hash_arg?(if_body)
|
|
101
102
|
"#{method_source(if_body)}(#{if_body.arguments.map(&:source).join(', ')})"
|
|
103
|
+
elsif (value = wrapped_value(if_body))
|
|
104
|
+
prefix = if_body.source_range.begin.join(value.source_range.begin).source
|
|
105
|
+
suffix = value.source_range.end.join(if_body.source_range.end).source
|
|
106
|
+
|
|
107
|
+
"#{prefix}#{if_body_source(value)}#{suffix}"
|
|
102
108
|
else
|
|
103
109
|
if_body.source
|
|
104
110
|
end
|
|
@@ -116,6 +122,14 @@ module RuboCop
|
|
|
116
122
|
if_body.source_range.begin.join(end_range).source
|
|
117
123
|
end
|
|
118
124
|
|
|
125
|
+
def wrapped_value(if_body)
|
|
126
|
+
if if_body.type?(:return, :next, :break)
|
|
127
|
+
if_body.first_argument if if_body.arguments.one?
|
|
128
|
+
elsif if_body.type?(:lvasgn, :ivasgn, :cvasgn, :gvasgn, :casgn)
|
|
129
|
+
if_body.expression
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
119
133
|
def first_line_comment(node)
|
|
120
134
|
comment = processed_source.comment_at_line(node.first_line)
|
|
121
135
|
return unless comment
|
|
@@ -137,9 +151,15 @@ module RuboCop
|
|
|
137
151
|
parent = node.parent
|
|
138
152
|
return false if parent.nil?
|
|
139
153
|
return true if parent.assignment? || parent.operator_keyword?
|
|
140
|
-
return true if
|
|
154
|
+
return true if parent.type?(:array, :pair, :call, :yield, :super)
|
|
155
|
+
|
|
156
|
+
ternary_branch_or_endless_method_body?(parent)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def ternary_branch_or_endless_method_body?(parent)
|
|
160
|
+
return parent.ternary? if parent.if_type?
|
|
141
161
|
|
|
142
|
-
|
|
162
|
+
parent.any_def_type? && parent.endless?
|
|
143
163
|
end
|
|
144
164
|
|
|
145
165
|
def comment_disables_cop?(comment)
|