rubocop 1.89.0 → 1.91.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 +309 -14
- data/config/obsoletion.yml +9 -0
- data/exe/rubocop +1 -1
- data/lib/rubocop/cached_data.rb +7 -2
- data/lib/rubocop/changed_files.rb +112 -0
- data/lib/rubocop/cli/command/execute_runner.rb +52 -1
- data/lib/rubocop/cli.rb +11 -7
- data/lib/rubocop/comment_config/directive_range.rb +34 -0
- data/lib/rubocop/comment_config/disable_next.rb +143 -0
- data/lib/rubocop/comment_config/push_pop.rb +55 -0
- data/lib/rubocop/comment_config.rb +50 -64
- data/lib/rubocop/config.rb +33 -5
- data/lib/rubocop/config_loader.rb +13 -6
- data/lib/rubocop/config_loader_resolver.rb +50 -9
- data/lib/rubocop/config_obsoletion/cop_rule.rb +2 -1
- data/lib/rubocop/config_obsoletion/removed_cop.rb +8 -0
- data/lib/rubocop/config_obsoletion.rb +1 -1
- data/lib/rubocop/config_validator.rb +19 -5
- data/lib/rubocop/cop/autocorrect_logic.rb +8 -0
- data/lib/rubocop/cop/badge.rb +1 -1
- data/lib/rubocop/cop/base.rb +49 -5
- data/lib/rubocop/cop/corrector.rb +3 -3
- data/lib/rubocop/cop/correctors.rb +2 -2
- 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 +1 -2
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +1 -2
- data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +1 -1
- data/lib/rubocop/cop/layout/argument_alignment.rb +2 -0
- data/lib/rubocop/cop/layout/block_alignment.rb +1 -2
- data/lib/rubocop/cop/layout/class_structure.rb +102 -26
- data/lib/rubocop/cop/layout/comment_indentation.rb +8 -5
- data/lib/rubocop/cop/layout/else_alignment.rb +1 -0
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +1 -2
- data/lib/rubocop/cop/layout/empty_line_after_magic_comment.rb +63 -5
- data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +1 -1
- data/lib/rubocop/cop/layout/end_alignment.rb +1 -2
- data/lib/rubocop/cop/layout/extra_spacing.rb +105 -3
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +21 -1
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +17 -4
- data/lib/rubocop/cop/layout/first_parameter_indentation.rb +11 -0
- data/lib/rubocop/cop/layout/hash_alignment.rb +6 -5
- data/lib/rubocop/cop/layout/indentation_width.rb +2 -2
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -2
- data/lib/rubocop/cop/layout/line_length.rb +20 -3
- data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -2
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +5 -5
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +1 -2
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +14 -3
- data/lib/rubocop/cop/layout/space_around_operators.rb +12 -1
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +2 -4
- data/lib/rubocop/cop/lint/ambiguous_range.rb +1 -2
- data/lib/rubocop/cop/lint/argument_mismatch.rb +99 -0
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +2 -0
- data/lib/rubocop/cop/lint/constant_reassignment.rb +17 -11
- data/lib/rubocop/cop/lint/cop_directive_syntax.rb +165 -15
- data/lib/rubocop/cop/lint/deprecated_reference.rb +11 -2
- data/lib/rubocop/cop/lint/duplicate_methods.rb +113 -15
- data/lib/rubocop/cop/lint/empty_block.rb +1 -1
- data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -2
- data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -2
- data/lib/rubocop/cop/lint/interpolation_check.rb +1 -2
- data/lib/rubocop/cop/lint/literal_as_condition.rb +11 -8
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +3 -6
- data/lib/rubocop/cop/lint/misplaced_magic_comment.rb +185 -0
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +25 -12
- data/lib/rubocop/cop/lint/name_typo.rb +53 -6
- 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/out_of_range_regexp_ref.rb +15 -0
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +17 -1
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +122 -29
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +47 -7
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +1 -2
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +1 -2
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +1 -2
- data/lib/rubocop/cop/lint/redundant_type_conversion.rb +1 -2
- data/lib/rubocop/cop/lint/redundant_with_index.rb +1 -2
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +1 -2
- data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +2 -4
- data/lib/rubocop/cop/lint/super_argument_mismatch.rb +179 -0
- data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +1 -2
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +1 -2
- data/lib/rubocop/cop/lint/unreachable_code.rb +1 -2
- data/lib/rubocop/cop/lint/unused_private_method.rb +94 -17
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +1 -2
- data/lib/rubocop/cop/lint/useless_assignment.rb +1 -2
- data/lib/rubocop/cop/lint/useless_constant_scoping.rb +36 -0
- data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
- data/lib/rubocop/cop/lint/useless_rescue.rb +1 -2
- data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +61 -7
- data/lib/rubocop/cop/lint/void.rb +1 -2
- data/lib/rubocop/cop/lint.rb +3 -0
- data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -2
- data/lib/rubocop/cop/migration/department_name.rb +1 -2
- data/lib/rubocop/cop/mixin/alignment.rb +1 -1
- data/lib/rubocop/cop/mixin/annotation_comment.rb +1 -1
- data/lib/rubocop/cop/mixin/comments_help.rb +1 -2
- data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +1 -2
- data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +11 -1
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +7 -4
- data/lib/rubocop/cop/mixin/hash_subset.rb +1 -2
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +1 -1
- data/lib/rubocop/cop/mixin/indexed_method_arity.rb +94 -0
- data/lib/rubocop/cop/mixin/line_length_help.rb +7 -1
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +62 -6
- data/lib/rubocop/cop/mixin/range_help.rb +1 -2
- data/lib/rubocop/cop/mixin/statement_modifier.rb +13 -7
- data/lib/rubocop/cop/mixin/trailing_comma.rb +2 -4
- data/lib/rubocop/cop/mixin.rb +6 -2
- data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +16 -0
- 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/memoized_instance_variable_name.rb +2 -4
- data/lib/rubocop/cop/naming/method_name.rb +5 -2
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +1 -2
- data/lib/rubocop/cop/offense.rb +27 -4
- data/lib/rubocop/cop/registry.rb +43 -11
- data/lib/rubocop/cop/severity.rb +12 -0
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +3 -2
- data/lib/rubocop/cop/style/accessor_grouping.rb +1 -2
- data/lib/rubocop/cop/style/arguments_forwarding.rb +5 -8
- data/lib/rubocop/cop/style/array_first_last.rb +1 -2
- data/lib/rubocop/cop/style/bitwise_predicate.rb +1 -2
- data/lib/rubocop/cop/style/block_delimiters.rb +3 -6
- data/lib/rubocop/cop/style/case_like_if.rb +5 -7
- data/lib/rubocop/cop/style/class_and_module_children.rb +1 -2
- data/lib/rubocop/cop/style/combinable_loops.rb +1 -2
- data/lib/rubocop/cop/style/concat_array_literals.rb +1 -2
- data/lib/rubocop/cop/style/conditional_assignment.rb +1 -2
- data/lib/rubocop/cop/style/constant_visibility.rb +6 -3
- data/lib/rubocop/cop/style/copyright.rb +1 -2
- data/lib/rubocop/cop/style/data_inheritance.rb +14 -0
- data/lib/rubocop/cop/style/directive_scope.rb +304 -0
- data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +83 -13
- data/lib/rubocop/cop/style/documentation_method.rb +1 -9
- 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_case_condition.rb +1 -2
- data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
- data/lib/rubocop/cop/style/empty_method.rb +12 -2
- data/lib/rubocop/cop/style/endless_method.rb +31 -12
- data/lib/rubocop/cop/style/file_null.rb +2 -2
- data/lib/rubocop/cop/style/float_division.rb +10 -16
- data/lib/rubocop/cop/style/for.rb +5 -0
- data/lib/rubocop/cop/style/format_string_token.rb +1 -2
- data/lib/rubocop/cop/style/guard_clause.rb +5 -2
- data/lib/rubocop/cop/style/hash_each_methods.rb +1 -2
- data/lib/rubocop/cop/style/hash_lookup_method.rb +3 -0
- data/lib/rubocop/cop/style/hash_syntax.rb +1 -2
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +2 -4
- data/lib/rubocop/cop/style/if_inside_else.rb +1 -2
- data/lib/rubocop/cop/style/if_unless_modifier.rb +1 -2
- data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +1 -2
- data/lib/rubocop/cop/style/magic_comment_format.rb +1 -1
- data/lib/rubocop/cop/style/map_to_hash.rb +1 -2
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +2 -4
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +1 -2
- data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -2
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +1 -2
- data/lib/rubocop/cop/style/negative_array_index.rb +2 -4
- data/lib/rubocop/cop/style/nested_modifier.rb +9 -4
- data/lib/rubocop/cop/style/nil_comparison.rb +36 -9
- 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 +3 -1
- data/lib/rubocop/cop/style/numeric_literal_prefix.rb +11 -1
- data/lib/rubocop/cop/style/one_line_conditional.rb +1 -1
- data/lib/rubocop/cop/style/operator_method_call.rb +1 -2
- data/lib/rubocop/cop/style/parallel_assignment.rb +1 -2
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +6 -1
- data/lib/rubocop/cop/style/redundant_assignment.rb +1 -2
- data/lib/rubocop/cop/style/redundant_condition.rb +6 -8
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +11 -3
- data/lib/rubocop/cop/style/redundant_each.rb +1 -2
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -1
- data/lib/rubocop/cop/style/redundant_format.rb +2 -4
- data/lib/rubocop/cop/style/redundant_parentheses.rb +13 -5
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +1 -2
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +6 -5
- data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +6 -6
- data/lib/rubocop/cop/style/redundant_return.rb +1 -2
- data/lib/rubocop/cop/style/redundant_self_assignment.rb +1 -2
- data/lib/rubocop/cop/style/redundant_string_escape.rb +1 -2
- data/lib/rubocop/cop/style/rescue_modifier.rb +1 -2
- data/lib/rubocop/cop/style/safe_navigation.rb +1 -2
- data/lib/rubocop/cop/style/sample.rb +11 -6
- data/lib/rubocop/cop/style/select_by_regexp.rb +1 -2
- data/lib/rubocop/cop/style/semicolon.rb +2 -4
- 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/sole_nested_conditional.rb +1 -2
- data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +2 -0
- data/lib/rubocop/cop/style/string_concatenation.rb +18 -5
- data/lib/rubocop/cop/style/struct_inheritance.rb +14 -0
- data/lib/rubocop/cop/style/super_arguments.rb +1 -2
- data/lib/rubocop/cop/style/symbol_proc.rb +1 -2
- data/lib/rubocop/cop/style/time_now.rb +41 -0
- data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
- data/lib/rubocop/cop/style/yoda_condition.rb +1 -2
- data/lib/rubocop/cop/style.rb +2 -1
- data/lib/rubocop/cop/team.rb +11 -3
- data/lib/rubocop/cop/util.rb +3 -5
- data/lib/rubocop/cop/variable_force/variable.rb +1 -2
- data/lib/rubocop/cops_documentation_generator.rb +26 -8
- data/lib/rubocop/directive_comment.rb +73 -10
- data/lib/rubocop/formatter/disabled_config_formatter.rb +19 -1
- data/lib/rubocop/formatter/emacs_style_formatter.rb +3 -1
- data/lib/rubocop/formatter/formatter_set.rb +2 -1
- data/lib/rubocop/formatter/github_actions_formatter.rb +6 -5
- data/lib/rubocop/formatter/html_formatter.rb +2 -4
- data/lib/rubocop/formatter/json_formatter.rb +11 -6
- data/lib/rubocop/formatter/junit_formatter.rb +26 -9
- data/lib/rubocop/formatter/offense_count_formatter.rb +1 -2
- data/lib/rubocop/formatter/sarif_formatter.rb +181 -0
- data/lib/rubocop/formatter/simple_text_formatter.rb +4 -3
- data/lib/rubocop/formatter/tap_formatter.rb +3 -1
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -2
- data/lib/rubocop/formatter.rb +1 -0
- data/lib/rubocop/lockfile.rb +18 -0
- data/lib/rubocop/lsp/diagnostic.rb +4 -8
- data/lib/rubocop/lsp/routes.rb +48 -19
- data/lib/rubocop/magic_comment.rb +27 -0
- data/lib/rubocop/mcp/server.rb +1 -2
- data/lib/rubocop/options.rb +69 -7
- data/lib/rubocop/path_util.rb +2 -3
- data/lib/rubocop/plugin/configuration_integrator.rb +6 -3
- data/lib/rubocop/plugin/loader.rb +1 -1
- data/lib/rubocop/rake_task.rb +1 -2
- data/lib/rubocop/remote_config.rb +4 -4
- data/lib/rubocop/result_cache.rb +16 -5
- data/lib/rubocop/rspec/expect_offense.rb +2 -4
- data/lib/rubocop/rspec/shared_contexts.rb +4 -2
- data/lib/rubocop/runner.rb +90 -44
- data/lib/rubocop/server/cache.rb +1 -2
- data/lib/rubocop/server/cli.rb +2 -4
- data/lib/rubocop/server.rb +14 -0
- data/lib/rubocop/target_finder.rb +4 -1
- data/lib/rubocop/todo_audit.rb +111 -0
- data/lib/rubocop/unified_diff.rb +257 -0
- data/lib/rubocop/version.rb +3 -5
- data/lib/rubocop.rb +7 -1
- data/lib/ruby_lsp/rubocop/addon.rb +1 -2
- metadata +18 -6
- data/lib/rubocop/cop/style/double_cop_disable_directive.rb +0 -46
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Style
|
|
6
|
+
# Checks for directive scopes that can be expressed with the tighter
|
|
7
|
+
# next-statement forms: a `disable`/`enable` pair, an
|
|
8
|
+
# `enable`/`disable` pair, or a `push`/`pop` with signed arguments
|
|
9
|
+
# wrapping exactly one statement. A statement-scoped directive cannot
|
|
10
|
+
# drift as the surrounding code changes and needs no closing boundary.
|
|
11
|
+
#
|
|
12
|
+
# @safety
|
|
13
|
+
# The autocorrection is unsafe because the suppression scope shrinks
|
|
14
|
+
# from the whole region to the statement: offenses of the suppressed
|
|
15
|
+
# cops located on the directive lines themselves resurface.
|
|
16
|
+
#
|
|
17
|
+
# @example
|
|
18
|
+
# # bad
|
|
19
|
+
# # rubocop:disable Metrics/AbcSize
|
|
20
|
+
# def foo
|
|
21
|
+
# end
|
|
22
|
+
# # rubocop:enable Metrics/AbcSize
|
|
23
|
+
#
|
|
24
|
+
# # good
|
|
25
|
+
# # rubocop:disable-next Metrics/AbcSize
|
|
26
|
+
# def foo
|
|
27
|
+
# end
|
|
28
|
+
#
|
|
29
|
+
# # bad
|
|
30
|
+
# # rubocop:push -Metrics/AbcSize
|
|
31
|
+
# def foo
|
|
32
|
+
# end
|
|
33
|
+
# # rubocop:pop
|
|
34
|
+
#
|
|
35
|
+
# # good
|
|
36
|
+
# # rubocop:disable-next Metrics/AbcSize
|
|
37
|
+
# def foo
|
|
38
|
+
# end
|
|
39
|
+
#
|
|
40
|
+
# # bad
|
|
41
|
+
# # rubocop:disable Metrics/AbcSize
|
|
42
|
+
# # rubocop:push +Metrics/AbcSize
|
|
43
|
+
# def foo
|
|
44
|
+
# end
|
|
45
|
+
# # rubocop:pop
|
|
46
|
+
# # rubocop:enable Metrics/AbcSize
|
|
47
|
+
#
|
|
48
|
+
# # good
|
|
49
|
+
# # rubocop:disable Metrics/AbcSize
|
|
50
|
+
# # rubocop:enable-next Metrics/AbcSize
|
|
51
|
+
# def foo
|
|
52
|
+
# end
|
|
53
|
+
# # rubocop:enable Metrics/AbcSize
|
|
54
|
+
#
|
|
55
|
+
# # good - the region spans more than one statement
|
|
56
|
+
# # rubocop:disable Metrics/AbcSize
|
|
57
|
+
# def foo
|
|
58
|
+
# end
|
|
59
|
+
#
|
|
60
|
+
# def bar
|
|
61
|
+
# end
|
|
62
|
+
# # rubocop:enable Metrics/AbcSize
|
|
63
|
+
#
|
|
64
|
+
class DirectiveScope < Base
|
|
65
|
+
include RangeHelp
|
|
66
|
+
extend AutoCorrector
|
|
67
|
+
|
|
68
|
+
MSG_PAIR = 'Use `%<mode>s-next` instead of a `%<mode>s`/`enable` pair ' \
|
|
69
|
+
'around a single statement.'
|
|
70
|
+
MSG_ENABLE_PAIR = 'Use `enable-next` instead of an `enable`/`disable` pair ' \
|
|
71
|
+
'around a single statement.'
|
|
72
|
+
MSG_PUSH_POP = 'Use `%<replacement>s` instead of `push`/`pop` around a single statement.'
|
|
73
|
+
|
|
74
|
+
def on_new_investigation
|
|
75
|
+
processed_source.comments.each do |comment|
|
|
76
|
+
directive = DirectiveComment.new(comment)
|
|
77
|
+
next unless comment_config.comment_only_line?(directive.line_number)
|
|
78
|
+
|
|
79
|
+
if plain_disable?(directive)
|
|
80
|
+
check_pair(directive)
|
|
81
|
+
elsif signed_push?(directive)
|
|
82
|
+
check_push_pop(directive)
|
|
83
|
+
elsif plain_enable?(directive)
|
|
84
|
+
check_enable_pair(directive)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
private
|
|
90
|
+
|
|
91
|
+
def comment_config
|
|
92
|
+
processed_source.comment_config
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def plain_disable?(directive)
|
|
96
|
+
directive.disabled? && !directive.disable_next?
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def plain_enable?(directive)
|
|
100
|
+
directive.enabled? && !directive.enable_next? && !directive.all_cops?
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def signed_push?(directive)
|
|
104
|
+
directive.push? && !directive.signed_args.empty?
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def check_pair(directive)
|
|
108
|
+
enable = single_statement_closing_directive(directive)
|
|
109
|
+
return unless enable&.enabled?
|
|
110
|
+
return unless enable.raw_cop_names.sort == directive.raw_cop_names.sort
|
|
111
|
+
|
|
112
|
+
message = format(MSG_PAIR, mode: directive.mode)
|
|
113
|
+
add_offense(directive.comment, message: message) do |corrector|
|
|
114
|
+
convert_pair(corrector, directive, enable)
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def convert_pair(corrector, directive, enable)
|
|
119
|
+
replacement = directive.comment.text.sub(/\b#{directive.mode}\b/,
|
|
120
|
+
"#{directive.mode}-next")
|
|
121
|
+
corrector.replace(directive.comment, replacement)
|
|
122
|
+
remove_line(corrector, enable.comment)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def check_push_pop(directive)
|
|
126
|
+
pop_line = balancing_pop_line(directive)
|
|
127
|
+
return unless pop_line && comment_config.comment_only_line?(pop_line)
|
|
128
|
+
return unless wraps_single_statement?(directive, pop_line)
|
|
129
|
+
|
|
130
|
+
pop_comment = processed_source.comment_at_line(pop_line)
|
|
131
|
+
replacement = push_replacement(directive)
|
|
132
|
+
message = format(MSG_PUSH_POP, replacement: replacement_mode(directive))
|
|
133
|
+
add_offense(directive.comment, message: message) do |corrector|
|
|
134
|
+
corrector.replace(directive.comment, replacement)
|
|
135
|
+
remove_line(corrector, pop_comment)
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# The line of the `pop` balancing this `push`, taking nesting into
|
|
140
|
+
# account, or `nil` when the push is never popped.
|
|
141
|
+
def balancing_pop_line(push_directive)
|
|
142
|
+
depth = 0
|
|
143
|
+
each_directive_after(push_directive) do |directive|
|
|
144
|
+
if directive.push?
|
|
145
|
+
depth += 1
|
|
146
|
+
elsif directive.pop?
|
|
147
|
+
return directive.line_number if depth.zero?
|
|
148
|
+
|
|
149
|
+
depth -= 1
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
nil
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def each_directive_after(reference)
|
|
156
|
+
processed_source.comments.each do |comment|
|
|
157
|
+
directive = DirectiveComment.new(comment)
|
|
158
|
+
next unless directive.cop_names || directive.push? || directive.pop?
|
|
159
|
+
|
|
160
|
+
yield directive if directive.line_number > reference.line_number
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def replacement_mode(directive)
|
|
165
|
+
ops = directive.signed_args.keys.sort
|
|
166
|
+
if ops == ['-']
|
|
167
|
+
'disable-next'
|
|
168
|
+
elsif ops == ['+']
|
|
169
|
+
'enable-next'
|
|
170
|
+
else
|
|
171
|
+
'next'
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def push_replacement(directive)
|
|
176
|
+
text = case replacement_mode(directive)
|
|
177
|
+
when 'disable-next'
|
|
178
|
+
"# rubocop:disable-next #{directive.signed_args['-'].join(', ')}"
|
|
179
|
+
when 'enable-next'
|
|
180
|
+
"# rubocop:enable-next #{directive.signed_args['+'].join(', ')}"
|
|
181
|
+
else
|
|
182
|
+
"# rubocop:next #{directive.cops}"
|
|
183
|
+
end
|
|
184
|
+
reason = directive.reason
|
|
185
|
+
reason ? "#{text} -- #{reason}" : text
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# An `enable`/`disable` pair around one statement inside a disabled
|
|
189
|
+
# region re-enables the cops for just that statement - `enable-next`
|
|
190
|
+
# says the same without the closing boundary. The pair only counts
|
|
191
|
+
# when the `enable` really closed open disables (otherwise the
|
|
192
|
+
# trailing `disable` opens a new region and the conversion would
|
|
193
|
+
# change what is covered).
|
|
194
|
+
def check_enable_pair(directive)
|
|
195
|
+
closing = enable_pair_closing(directive)
|
|
196
|
+
return unless closing
|
|
197
|
+
|
|
198
|
+
add_offense(directive.comment, message: MSG_ENABLE_PAIR) do |corrector|
|
|
199
|
+
corrector.replace(directive.comment,
|
|
200
|
+
directive.comment.text.sub(/\benable\b/, 'enable-next'))
|
|
201
|
+
remove_line(corrector, closing.comment)
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def enable_pair_closing(directive)
|
|
206
|
+
scope = comment_config.statement_scope_after(directive.line_number)
|
|
207
|
+
return nil unless scope && scope.begin == directive.line_number + 1
|
|
208
|
+
|
|
209
|
+
closing = re_disable_below(directive, scope.end + 1)
|
|
210
|
+
closing if closing && closed_open_disables?(directive, closing)
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def re_disable_below(directive, line)
|
|
214
|
+
return nil unless comment_config.comment_only_line?(line)
|
|
215
|
+
|
|
216
|
+
comment = processed_source.comment_at_line(line)
|
|
217
|
+
return nil unless comment
|
|
218
|
+
|
|
219
|
+
closing = DirectiveComment.new(comment)
|
|
220
|
+
return nil unless closing.disabled? && !closing.disable_next?
|
|
221
|
+
return nil unless closing.raw_cop_names.sort == directive.raw_cop_names.sort
|
|
222
|
+
|
|
223
|
+
closing
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
# Every cop of the pair must have a range the `enable` closed and a
|
|
227
|
+
# range the trailing `disable` reopened - otherwise the `enable` was
|
|
228
|
+
# not inside a disabled region and the conversion would change what
|
|
229
|
+
# is covered.
|
|
230
|
+
def closed_open_disables?(directive, closing)
|
|
231
|
+
directive.cop_names.all? do |cop|
|
|
232
|
+
ranges = comment_config.cop_disabled_line_ranges[qualified_name(cop)]
|
|
233
|
+
ranges && closed_at?(ranges, directive.line_number) && reopened_by?(ranges, closing)
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def closed_at?(ranges, line)
|
|
238
|
+
ranges.any? { |range| range.end == line }
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def reopened_by?(ranges, closing)
|
|
242
|
+
ranges.any? do |range|
|
|
243
|
+
range.respond_to?(:directive) && range.directive.comment.equal?(closing.comment)
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def qualified_name(cop_name)
|
|
248
|
+
Registry.qualified_cop_name(cop_name.strip, processed_source.file_path,
|
|
249
|
+
correct_namespace: false)
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
# The directive closing this one's scope, when that scope wraps
|
|
253
|
+
# exactly one statement - `nil` otherwise.
|
|
254
|
+
def single_statement_closing_directive(directive)
|
|
255
|
+
closing_line = single_closing_line(directive)
|
|
256
|
+
return nil unless closing_line
|
|
257
|
+
|
|
258
|
+
closing_comment = processed_source.comment_at_line(closing_line)
|
|
259
|
+
return nil unless closing_comment
|
|
260
|
+
return nil unless wraps_single_statement?(directive, closing_line)
|
|
261
|
+
|
|
262
|
+
DirectiveComment.new(closing_comment)
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
# The single line on which every disabled range opened by this
|
|
266
|
+
# directive ends, or `nil` when the ranges disagree or never close.
|
|
267
|
+
# For a `disable` that is the `enable` line; for a `push` it is the
|
|
268
|
+
# line before the `pop`.
|
|
269
|
+
def single_closing_line(directive)
|
|
270
|
+
ranges = ranges_opened_by(directive)
|
|
271
|
+
return nil if ranges.empty?
|
|
272
|
+
|
|
273
|
+
ends = ranges.map(&:end).uniq
|
|
274
|
+
return nil unless ends.size == 1 && ends.first.to_f.finite?
|
|
275
|
+
|
|
276
|
+
ends.first
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
def ranges_opened_by(directive)
|
|
280
|
+
comment_config.cop_disabled_line_ranges.each_value.flat_map do |ranges|
|
|
281
|
+
ranges.select do |range|
|
|
282
|
+
range.respond_to?(:directive) && range.directive.comment.equal?(directive.comment)
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
# The region wraps a single statement only when the directive sits
|
|
288
|
+
# immediately above it and the closing directive immediately below -
|
|
289
|
+
# any other line inside the region (a comment, a blank line) may
|
|
290
|
+
# carry offenses of the suppressed cops that the tighter scope
|
|
291
|
+
# would no longer cover.
|
|
292
|
+
def wraps_single_statement?(directive, closing_line)
|
|
293
|
+
scope = comment_config.statement_scope_after(directive.line_number)
|
|
294
|
+
|
|
295
|
+
!scope.nil? && scope.begin == directive.line_number + 1 && scope.end + 1 == closing_line
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
def remove_line(corrector, comment)
|
|
299
|
+
corrector.remove(range_by_whole_lines(comment.source_range, include_final_newline: true))
|
|
300
|
+
end
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# rubocop:disable Lint/RedundantCopDisableDirective
|
|
3
|
+
# rubocop:disable Lint/RedundantCopDisableDirective -- the examples below read as real directives
|
|
4
4
|
|
|
5
5
|
module RuboCop
|
|
6
6
|
module Cop
|
|
@@ -12,6 +12,10 @@ module RuboCop
|
|
|
12
12
|
# Specific cops can be allowed with the `AllowedCops` configuration. Note that
|
|
13
13
|
# if this configuration is set, `rubocop:disable all` is still disallowed.
|
|
14
14
|
#
|
|
15
|
+
# `AllowedCops` and `DisallowedCops` accept cop names and department names
|
|
16
|
+
# alike. Listing a cop does not cover its whole department: a directive
|
|
17
|
+
# disabling `Metrics` is broader than one disabling `Metrics/AbcSize`.
|
|
18
|
+
#
|
|
15
19
|
# Alternatively, specific cops can be disallowed with the `DisallowedCops`
|
|
16
20
|
# configuration. When `DisallowedCops` is set, only directives for the listed
|
|
17
21
|
# cops (and `all`) will be flagged. This is useful when you want
|
|
@@ -19,6 +23,18 @@ module RuboCop
|
|
|
19
23
|
# allowlisting all other cops. `AllowedCops` and `DisallowedCops` should not
|
|
20
24
|
# both be set at the same time; if `DisallowedCops` is set, it takes precedence.
|
|
21
25
|
#
|
|
26
|
+
# `AllowedDirectives` names directive forms - `disable`, `todo`,
|
|
27
|
+
# `disable-next`, `todo-next`, `push`, `next` - and exempts them from the
|
|
28
|
+
# cop entirely. `rubocop:todo` is the usual candidate, since
|
|
29
|
+
# `--disable-uncorrectable` generates those and they record debt rather
|
|
30
|
+
# than a decision someone should be asked to justify.
|
|
31
|
+
#
|
|
32
|
+
# With `AllowWithReason` set to `true`, a disable directive carrying
|
|
33
|
+
# a `--` trailing justification comment is allowed, so a team can require
|
|
34
|
+
# every disable to be documented instead of banning them outright. Enable
|
|
35
|
+
# directives are not checked in this mode, since they end a suppression
|
|
36
|
+
# rather than start one.
|
|
37
|
+
#
|
|
22
38
|
# This cop cannot be disabled via directive comments when it is explicitly
|
|
23
39
|
# enabled with `Enabled: true`. This prevents users from bypassing the cop
|
|
24
40
|
# with `# rubocop:disable Style/DisableCopsWithinSourceCodeDirective`.
|
|
@@ -52,16 +68,42 @@ module RuboCop
|
|
|
52
68
|
# foo
|
|
53
69
|
# # rubocop:enable Metrics/AbcSize
|
|
54
70
|
#
|
|
71
|
+
# @example AllowedDirectives: [todo]
|
|
72
|
+
# # good - the cop does not look at `todo` directives at all
|
|
73
|
+
# x = 0 # rubocop:todo Layout/SpaceAroundOperators
|
|
74
|
+
#
|
|
75
|
+
# # bad
|
|
76
|
+
# x = 0 # rubocop:disable Layout/SpaceAroundOperators
|
|
77
|
+
#
|
|
78
|
+
# @example AllowedCops: [Metrics]
|
|
79
|
+
# # good - every cop the directive disables is in an exempt department
|
|
80
|
+
# # rubocop:disable Metrics/AbcSize
|
|
81
|
+
# def foo
|
|
82
|
+
# end
|
|
83
|
+
# # rubocop:enable Metrics/AbcSize
|
|
84
|
+
#
|
|
85
|
+
# @example AllowWithReason: true
|
|
86
|
+
# # bad
|
|
87
|
+
# x = 0 # rubocop:disable Layout/SpaceAroundOperators
|
|
88
|
+
#
|
|
89
|
+
# # good
|
|
90
|
+
# x = 0 # rubocop:disable Layout/SpaceAroundOperators -- would misalign the table
|
|
91
|
+
#
|
|
55
92
|
class DisableCopsWithinSourceCodeDirective < Base
|
|
56
93
|
extend AutoCorrector
|
|
57
94
|
|
|
58
95
|
# rubocop:enable Lint/RedundantCopDisableDirective
|
|
59
96
|
MSG = 'RuboCop disable/enable directives are not permitted.'
|
|
60
97
|
MSG_FOR_COPS = 'RuboCop disable/enable directives for %<cops>s are not permitted.'
|
|
98
|
+
MSG_MISSING_REASON = 'RuboCop disable directives without a `--` justification ' \
|
|
99
|
+
'comment are not permitted.'
|
|
61
100
|
|
|
62
101
|
def on_new_investigation
|
|
63
102
|
processed_source.comments.each do |comment|
|
|
64
|
-
|
|
103
|
+
directive = DirectiveComment.new(comment)
|
|
104
|
+
next if ignored?(directive)
|
|
105
|
+
|
|
106
|
+
directive_cops = directive_cops(directive)
|
|
65
107
|
disallowed_cops = compute_disallowed_cops(directive_cops)
|
|
66
108
|
|
|
67
109
|
next unless disallowed_cops.any?
|
|
@@ -77,21 +119,15 @@ module RuboCop
|
|
|
77
119
|
if directive_cops.include?('all')
|
|
78
120
|
directive_cops
|
|
79
121
|
else
|
|
80
|
-
directive_cops.uniq.select { |cop|
|
|
122
|
+
directive_cops.uniq.select { |cop| listed?(disallowed_cops_config, cop) }
|
|
81
123
|
end
|
|
82
124
|
else
|
|
83
|
-
directive_cops.reject { |cop|
|
|
125
|
+
directive_cops.reject { |cop| cop != 'all' && listed?(allowed_cops, cop) }
|
|
84
126
|
end
|
|
85
127
|
end
|
|
86
128
|
|
|
87
129
|
def register_offense(comment, directive_cops, disallowed_cops)
|
|
88
|
-
message
|
|
89
|
-
format(MSG_FOR_COPS, cops: "`#{disallowed_cops.join('`, `')}`")
|
|
90
|
-
else
|
|
91
|
-
MSG
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
add_offense(comment, message: message) do |corrector|
|
|
130
|
+
add_offense(comment, message: offense_message(disallowed_cops)) do |corrector|
|
|
95
131
|
replacement = ''
|
|
96
132
|
|
|
97
133
|
if directive_cops.length != disallowed_cops.length
|
|
@@ -103,15 +139,49 @@ module RuboCop
|
|
|
103
139
|
end
|
|
104
140
|
end
|
|
105
141
|
|
|
106
|
-
def
|
|
107
|
-
|
|
142
|
+
def offense_message(disallowed_cops)
|
|
143
|
+
if allow_with_reason?
|
|
144
|
+
MSG_MISSING_REASON
|
|
145
|
+
elsif any_cops_allowed? || disallowed_cops_config.any?
|
|
146
|
+
format(MSG_FOR_COPS, cops: "`#{disallowed_cops.join('`, `')}`")
|
|
147
|
+
else
|
|
148
|
+
MSG
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def directive_cops(directive)
|
|
153
|
+
match_captures = directive.match_captures
|
|
108
154
|
match_captures && match_captures[1] ? match_captures[1].split(',').map(&:strip) : []
|
|
109
155
|
end
|
|
110
156
|
|
|
157
|
+
def ignored?(directive)
|
|
158
|
+
return true if exempt_mode?(directive)
|
|
159
|
+
|
|
160
|
+
allow_with_reason? && (directive.reason || directive.enabled?)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def exempt_mode?(directive)
|
|
164
|
+
allowed_directives.include?(directive.mode)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def allowed_directives
|
|
168
|
+
@allowed_directives ||= Array(cop_config['AllowedDirectives'])
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def allow_with_reason?
|
|
172
|
+
cop_config['AllowWithReason']
|
|
173
|
+
end
|
|
174
|
+
|
|
111
175
|
def allowed_cops
|
|
112
176
|
@allowed_cops ||= Array(cop_config['AllowedCops']).to_set
|
|
113
177
|
end
|
|
114
178
|
|
|
179
|
+
# A name matches either outright or through its department, so
|
|
180
|
+
# `Metrics` covers `Metrics/AbcSize` but not the other way round.
|
|
181
|
+
def listed?(names, cop)
|
|
182
|
+
names.include?(cop) || names.include?(cop.split('/').first)
|
|
183
|
+
end
|
|
184
|
+
|
|
115
185
|
def any_cops_allowed?
|
|
116
186
|
allowed_cops.any?
|
|
117
187
|
end
|
|
@@ -119,6 +119,7 @@ module RuboCop
|
|
|
119
119
|
|
|
120
120
|
def on_def(node)
|
|
121
121
|
return if node.method?(:initialize)
|
|
122
|
+
return if allowed_methods.include?(node.method_name)
|
|
122
123
|
|
|
123
124
|
parent = node.parent
|
|
124
125
|
modifier_node?(parent) ? check(parent) : check(node)
|
|
@@ -130,7 +131,6 @@ module RuboCop
|
|
|
130
131
|
def check(node)
|
|
131
132
|
return if non_public?(node) && !require_for_non_public_methods?
|
|
132
133
|
return if documentation_comment?(node)
|
|
133
|
-
return if method_allowed?(node)
|
|
134
134
|
|
|
135
135
|
add_offense(node)
|
|
136
136
|
end
|
|
@@ -139,14 +139,6 @@ module RuboCop
|
|
|
139
139
|
cop_config['RequireForNonPublicMethods']
|
|
140
140
|
end
|
|
141
141
|
|
|
142
|
-
def method_allowed?(node)
|
|
143
|
-
# For a modifier form like `module_function def foo; end`, `node` is the
|
|
144
|
-
# `module_function`/`ruby2_keywords` send; the real method name is on its
|
|
145
|
-
# `def`/`defs` argument, not the modifier itself.
|
|
146
|
-
method_name = node.send_type? ? node.first_argument.method_name : node.method_name
|
|
147
|
-
allowed_methods.include?(method_name)
|
|
148
|
-
end
|
|
149
|
-
|
|
150
142
|
def allowed_methods
|
|
151
143
|
@allowed_methods ||= cop_config.fetch('AllowedMethods', []).map(&:to_sym)
|
|
152
144
|
end
|
|
@@ -26,7 +26,7 @@ module RuboCop
|
|
|
26
26
|
|
|
27
27
|
MSG = 'Use `Integer#times` for a simple loop which iterates a fixed number of times.'
|
|
28
28
|
|
|
29
|
-
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler, InternalAffairs/ItblockHandler
|
|
29
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler, InternalAffairs/ItblockHandler -- only matches blocks that take no parameters
|
|
30
30
|
return unless offending?(node)
|
|
31
31
|
|
|
32
32
|
send_node = node.send_node
|
|
@@ -28,7 +28,7 @@ module RuboCop
|
|
|
28
28
|
|
|
29
29
|
MSG = 'Omit pipes for the empty block parameters.'
|
|
30
30
|
|
|
31
|
-
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler, InternalAffairs/ItblockHandler
|
|
31
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler, InternalAffairs/ItblockHandler -- the offense is an empty `||`
|
|
32
32
|
send_node = node.send_node
|
|
33
33
|
check(node) unless send_node.send_type? && send_node.lambda_literal?
|
|
34
34
|
end
|
|
@@ -42,7 +42,7 @@ module RuboCop
|
|
|
42
42
|
MSG = 'Do not use empty `case` condition, instead use an `if` expression.'
|
|
43
43
|
NOT_SUPPORTED_PARENT_TYPES = %i[return break next send csend yield super].freeze
|
|
44
44
|
|
|
45
|
-
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
45
|
+
# rubocop:disable-next Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
46
46
|
def on_case(case_node)
|
|
47
47
|
if case_node.condition || NOT_SUPPORTED_PARENT_TYPES.include?(case_node.parent&.type)
|
|
48
48
|
return
|
|
@@ -56,7 +56,6 @@ module RuboCop
|
|
|
56
56
|
|
|
57
57
|
add_offense(case_node.loc.keyword) { |corrector| autocorrect(corrector, case_node) }
|
|
58
58
|
end
|
|
59
|
-
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
60
59
|
|
|
61
60
|
private
|
|
62
61
|
|
|
@@ -23,7 +23,7 @@ module RuboCop
|
|
|
23
23
|
|
|
24
24
|
MSG = 'Omit parentheses for the empty lambda parameters.'
|
|
25
25
|
|
|
26
|
-
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler, InternalAffairs/ItblockHandler
|
|
26
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler, InternalAffairs/ItblockHandler -- the offense is an empty `()`
|
|
27
27
|
send_node = node.send_node
|
|
28
28
|
return unless send_node.send_type?
|
|
29
29
|
|
|
@@ -53,11 +53,11 @@ module RuboCop
|
|
|
53
53
|
|
|
54
54
|
def on_def(node)
|
|
55
55
|
return if node.body || processed_source.contains_comment?(node.source_range)
|
|
56
|
-
return if correct_style?(node)
|
|
56
|
+
return if correct_style?(node) || compact_style_disallowed?
|
|
57
57
|
|
|
58
58
|
add_offense(node) do |corrector|
|
|
59
59
|
correction = corrected(node)
|
|
60
|
-
next if
|
|
60
|
+
next if correction_exceeds_line_length?(correction)
|
|
61
61
|
|
|
62
62
|
corrector.replace(node, correction)
|
|
63
63
|
end
|
|
@@ -74,6 +74,12 @@ module RuboCop
|
|
|
74
74
|
(compact_style? && compact?(node)) || (expanded_style? && expanded?(node))
|
|
75
75
|
end
|
|
76
76
|
|
|
77
|
+
def compact_style_disallowed?
|
|
78
|
+
return false unless compact_style?
|
|
79
|
+
|
|
80
|
+
config.for_enabled_cop('Style/SingleLineMethods')['AllowIfMethodIsEmpty'] == false
|
|
81
|
+
end
|
|
82
|
+
|
|
77
83
|
def corrected(node)
|
|
78
84
|
scope = node.receiver ? "#{node.receiver.source}." : ''
|
|
79
85
|
arguments = if node.arguments?
|
|
@@ -86,6 +92,10 @@ module RuboCop
|
|
|
86
92
|
["def #{signature}", 'end'].join(joint(node))
|
|
87
93
|
end
|
|
88
94
|
|
|
95
|
+
def correction_exceeds_line_length?(correction)
|
|
96
|
+
compact_style? && max_line_length && correction.size > max_line_length
|
|
97
|
+
end
|
|
98
|
+
|
|
89
99
|
def joint(node)
|
|
90
100
|
indent = ' ' * node.loc.column
|
|
91
101
|
|
|
@@ -166,6 +166,8 @@ module RuboCop
|
|
|
166
166
|
return if node.single_line? || style == :allow_always
|
|
167
167
|
|
|
168
168
|
add_offense(node, message: MSG_MULTI_LINE) do |corrector|
|
|
169
|
+
next if endless_parent?(node)
|
|
170
|
+
|
|
169
171
|
correct_to_multiline(corrector, node)
|
|
170
172
|
end
|
|
171
173
|
end
|
|
@@ -175,11 +177,11 @@ module RuboCop
|
|
|
175
177
|
add_offense(node, message: MSG_MULTI_LINE) do |corrector|
|
|
176
178
|
correct_to_multiline(corrector, node)
|
|
177
179
|
end
|
|
178
|
-
elsif !node.endless? && can_be_made_endless?(node) && node
|
|
180
|
+
elsif !node.endless? && can_be_made_endless?(node) && single_line_when_made_endless?(node)
|
|
179
181
|
return if too_long_when_made_endless?(node)
|
|
180
182
|
|
|
181
183
|
add_offense(node, message: MSG_REQUIRE_SINGLE) do |corrector|
|
|
182
|
-
corrector
|
|
184
|
+
correct_to_endless(corrector, node)
|
|
183
185
|
end
|
|
184
186
|
end
|
|
185
187
|
end
|
|
@@ -189,14 +191,22 @@ module RuboCop
|
|
|
189
191
|
return if too_long_when_made_endless?(node)
|
|
190
192
|
|
|
191
193
|
add_offense(node, message: MSG_REQUIRE_ALWAYS) do |corrector|
|
|
192
|
-
corrector
|
|
194
|
+
correct_to_endless(corrector, node)
|
|
193
195
|
end
|
|
194
196
|
end
|
|
195
197
|
|
|
196
198
|
def handle_disallow_style(node)
|
|
197
199
|
return unless node.endless?
|
|
198
200
|
|
|
199
|
-
add_offense(node)
|
|
201
|
+
add_offense(node) do |corrector|
|
|
202
|
+
next if endless_parent?(node)
|
|
203
|
+
|
|
204
|
+
correct_to_multiline(corrector, node)
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def endless_parent?(node)
|
|
209
|
+
node.parent&.any_def_type? && node.parent.endless?
|
|
200
210
|
end
|
|
201
211
|
|
|
202
212
|
def use_heredoc?(node)
|
|
@@ -206,6 +216,17 @@ module RuboCop
|
|
|
206
216
|
body.each_descendant(:str).any?(&:heredoc?)
|
|
207
217
|
end
|
|
208
218
|
|
|
219
|
+
def correct_to_endless(corrector, node)
|
|
220
|
+
corrector.replace(signature_to_body_range(node), ' = ')
|
|
221
|
+
corrector.remove(node.body.source_range.end.join(node.loc.end.end))
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def signature_to_body_range(node)
|
|
225
|
+
signature_end = node.arguments.any? ? node.arguments.source_range.end : node.loc.name.end
|
|
226
|
+
|
|
227
|
+
signature_end.join(node.body.source_range.begin)
|
|
228
|
+
end
|
|
229
|
+
|
|
209
230
|
def endless_replacement(node)
|
|
210
231
|
<<~RUBY.strip
|
|
211
232
|
def #{receiver(node)}#{node.method_name}#{arguments(node)} = #{node.body.source}
|
|
@@ -221,19 +242,17 @@ module RuboCop
|
|
|
221
242
|
end
|
|
222
243
|
|
|
223
244
|
def can_be_made_endless?(node)
|
|
224
|
-
node.body && !node.body.
|
|
245
|
+
node.body && !node.body.type?(:begin, :kwbegin, :rescue, :ensure)
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def single_line_when_made_endless?(node)
|
|
249
|
+
!endless_replacement(node).include?("\n")
|
|
225
250
|
end
|
|
226
251
|
|
|
227
252
|
def too_long_when_made_endless?(node)
|
|
228
253
|
return false unless config.cop_enabled?('Layout/LineLength')
|
|
229
254
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
endless_replacement(node).length + offset > max_line_length
|
|
233
|
-
end
|
|
234
|
-
|
|
235
|
-
def modifier_offset(node)
|
|
236
|
-
same_line?(node.parent, node) ? node.loc.column - node.parent.loc.column : 0
|
|
255
|
+
endless_replacement(node).length + node.loc.column > max_line_length
|
|
237
256
|
end
|
|
238
257
|
end
|
|
239
258
|
end
|
|
@@ -54,7 +54,7 @@ module RuboCop
|
|
|
54
54
|
@contain_dev_null_string_in_file = ast.each_descendant(:str).any? do |str|
|
|
55
55
|
content = str.str_content
|
|
56
56
|
|
|
57
|
-
valid_string?(content) && content.downcase == '/dev/null' # rubocop:disable Style/FileNull
|
|
57
|
+
valid_string?(content) && content.downcase == '/dev/null' # rubocop:disable Style/FileNull -- the cop needs the literal it is matching
|
|
58
58
|
end
|
|
59
59
|
end
|
|
60
60
|
|
|
@@ -62,7 +62,7 @@ module RuboCop
|
|
|
62
62
|
value = node.value
|
|
63
63
|
return unless valid_string?(value)
|
|
64
64
|
return if acceptable?(node)
|
|
65
|
-
return if value.downcase == 'nul' && !@contain_dev_null_string_in_file # rubocop:disable Style/FileNull
|
|
65
|
+
return if value.downcase == 'nul' && !@contain_dev_null_string_in_file # rubocop:disable Style/FileNull -- the cop needs the literal it is matching
|
|
66
66
|
return unless REGEXP.match?(value)
|
|
67
67
|
|
|
68
68
|
add_offense(node, message: format(MSG, source: value)) do |corrector|
|