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
|
@@ -135,7 +135,7 @@ module RuboCop
|
|
|
135
135
|
end
|
|
136
136
|
end
|
|
137
137
|
|
|
138
|
-
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
|
138
|
+
# rubocop:disable-next Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
|
139
139
|
def argument_match?(send_arg, def_arg)
|
|
140
140
|
def_arg_name = def_arg.children[0]
|
|
141
141
|
|
|
@@ -157,7 +157,6 @@ module RuboCop
|
|
|
157
157
|
send_arg.forwarded_args_type?
|
|
158
158
|
end
|
|
159
159
|
end
|
|
160
|
-
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
|
161
160
|
|
|
162
161
|
def keyword_hash_argument?(send_arg)
|
|
163
162
|
send_arg.hash_type? && !send_arg.braces?
|
|
@@ -83,7 +83,7 @@ module RuboCop
|
|
|
83
83
|
}
|
|
84
84
|
PATTERN
|
|
85
85
|
|
|
86
|
-
# rubocop:disable Metrics/MethodLength
|
|
86
|
+
# rubocop:disable-next Metrics/MethodLength
|
|
87
87
|
def flow_expression?(node)
|
|
88
88
|
return report_on_flow_command?(node) if flow_command?(node)
|
|
89
89
|
|
|
@@ -102,7 +102,6 @@ module RuboCop
|
|
|
102
102
|
false
|
|
103
103
|
end
|
|
104
104
|
end
|
|
105
|
-
# rubocop:enable Metrics/MethodLength
|
|
106
105
|
|
|
107
106
|
def check_if(node)
|
|
108
107
|
if_branch = node.if_branch
|
|
@@ -14,10 +14,17 @@ module RuboCop
|
|
|
14
14
|
# in the indexed project (regardless of the receiver), when it is the source
|
|
15
15
|
# of an `alias`, or when its name appears in the same file as a symbol or
|
|
16
16
|
# inside a string literal (covering `send(:name)` and declarative DSLs like
|
|
17
|
-
# `before_action :name`).
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
17
|
+
# `before_action :name`). An interpolated symbol or string with a literal
|
|
18
|
+
# prefix (e.g. `send(:"format_#{type}")`) counts as a reference to every
|
|
19
|
+
# method whose name starts with that prefix; fully dynamic names cannot
|
|
20
|
+
# be detected. Methods defined in classes or modules with descendants are
|
|
21
|
+
# not checked, since they may be invoked through `super` or inherited
|
|
22
|
+
# dispatch.
|
|
23
|
+
#
|
|
24
|
+
# Methods whose names are composed by a framework (e.g. Rails
|
|
25
|
+
# `attribute_method_suffix` generating `attribute?` methods) can be
|
|
26
|
+
# excluded from the check with `AllowedNames` (exact names) or
|
|
27
|
+
# `AllowedPatterns` (regular expressions).
|
|
21
28
|
#
|
|
22
29
|
# The cop is disabled by default because symbol-based references from
|
|
23
30
|
# *other* files (e.g. a Rails callback declared in a concern) cannot be
|
|
@@ -49,28 +56,56 @@ module RuboCop
|
|
|
49
56
|
# end
|
|
50
57
|
# end
|
|
51
58
|
#
|
|
59
|
+
# @example AllowedNames: ['attribute?']
|
|
60
|
+
# # good - the name is explicitly allowed
|
|
61
|
+
# class Contact
|
|
62
|
+
# private
|
|
63
|
+
#
|
|
64
|
+
# def attribute?
|
|
65
|
+
# end
|
|
66
|
+
# end
|
|
67
|
+
#
|
|
68
|
+
# @example AllowedPatterns: ['_hook\z']
|
|
69
|
+
# # good - the name matches an allowed pattern
|
|
70
|
+
# class Service
|
|
71
|
+
# private
|
|
72
|
+
#
|
|
73
|
+
# def before_save_hook
|
|
74
|
+
# end
|
|
75
|
+
# end
|
|
76
|
+
#
|
|
52
77
|
class UnusedPrivateMethod < Base
|
|
78
|
+
include AllowedPattern
|
|
53
79
|
include ProjectIndexHelp
|
|
54
80
|
|
|
55
81
|
MSG = 'Private method `%<method>s` appears to be unused.'
|
|
56
82
|
|
|
57
83
|
IDENTIFIER_PATTERN = /[a-zA-Z_]\w*[?!=]?/.freeze
|
|
84
|
+
NAME_PREFIX_PATTERN = /[a-zA-Z_]\w*\z/.freeze
|
|
58
85
|
|
|
59
86
|
# Methods invoked implicitly by the Ruby runtime.
|
|
60
|
-
IMPLICITLY_INVOKED_METHODS = %i[
|
|
61
|
-
|
|
62
|
-
|
|
87
|
+
IMPLICITLY_INVOKED_METHODS = %i[
|
|
88
|
+
initialize initialize_copy initialize_clone initialize_dup
|
|
89
|
+
method_missing respond_to_missing? marshal_dump marshal_load
|
|
90
|
+
coerce instance_variables_to_inspect
|
|
91
|
+
inherited included extended prepended
|
|
92
|
+
append_features extend_object prepend_features
|
|
93
|
+
const_missing const_added
|
|
94
|
+
method_added method_removed method_undefined
|
|
95
|
+
singleton_method_added singleton_method_removed singleton_method_undefined
|
|
96
|
+
].to_set.freeze
|
|
63
97
|
|
|
64
98
|
class << self
|
|
65
|
-
# The reference-name set is
|
|
66
|
-
# per-file
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
99
|
+
# The reference-name set is a property of the index, not of the cop
|
|
100
|
+
# instance, so all per-file instances share one computation. A
|
|
101
|
+
# single-entry cache (instead of a hash keyed by index) avoids
|
|
102
|
+
# retaining stale graphs in long-lived processes.
|
|
103
|
+
attr_accessor :cached_reference_names
|
|
70
104
|
end
|
|
71
105
|
|
|
72
106
|
def on_new_investigation
|
|
73
107
|
@literal_names = nil
|
|
108
|
+
@literal_name_prefixes = nil
|
|
74
109
|
super
|
|
75
110
|
end
|
|
76
111
|
|
|
@@ -90,6 +125,7 @@ module RuboCop
|
|
|
90
125
|
|
|
91
126
|
def checkable_declaration(node)
|
|
92
127
|
return nil if IMPLICITLY_INVOKED_METHODS.include?(node.method_name)
|
|
128
|
+
return nil if allowed_name?(node.method_name)
|
|
93
129
|
return nil if node.each_ancestor(:any_def, :any_block, :sclass).any?
|
|
94
130
|
return nil unless (namespace_node = node.each_ancestor(:class, :module).first)
|
|
95
131
|
|
|
@@ -97,6 +133,12 @@ module RuboCop
|
|
|
97
133
|
declaration if declaration&.private?
|
|
98
134
|
end
|
|
99
135
|
|
|
136
|
+
def allowed_name?(method_name)
|
|
137
|
+
name = method_name.to_s
|
|
138
|
+
|
|
139
|
+
cop_config.fetch('AllowedNames', []).include?(name) || matches_allowed_pattern?(name)
|
|
140
|
+
end
|
|
141
|
+
|
|
100
142
|
def method_declaration(node, namespace_node)
|
|
101
143
|
namespace = resolve_constant_in_index(namespace_node.identifier)
|
|
102
144
|
return nil unless namespace.is_a?(Rubydex::Namespace)
|
|
@@ -107,13 +149,22 @@ module RuboCop
|
|
|
107
149
|
def referenced?(method_name)
|
|
108
150
|
name = method_name.to_s
|
|
109
151
|
|
|
110
|
-
referenced_names.include?(name) || literal_names.include?(name)
|
|
152
|
+
referenced_names.include?(name) || literal_names.include?(name) ||
|
|
153
|
+
literal_name_prefixes.any? { |prefix| name.start_with?(prefix) }
|
|
111
154
|
end
|
|
112
155
|
|
|
113
156
|
def referenced_names
|
|
114
|
-
self.class.
|
|
115
|
-
|
|
116
|
-
|
|
157
|
+
index, names = self.class.cached_reference_names
|
|
158
|
+
return names if index.equal?(project_index)
|
|
159
|
+
|
|
160
|
+
compute_referenced_names.tap do |computed|
|
|
161
|
+
self.class.cached_reference_names = [project_index, computed]
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def compute_referenced_names
|
|
166
|
+
project_index.method_references
|
|
167
|
+
.to_set { |reference| reference.name.delete_suffix('()') }
|
|
117
168
|
end
|
|
118
169
|
|
|
119
170
|
# Symbol literals and identifier-like tokens inside string literals in the
|
|
@@ -127,11 +178,37 @@ module RuboCop
|
|
|
127
178
|
if literal.sym_type?
|
|
128
179
|
names << literal.value.to_s
|
|
129
180
|
else
|
|
130
|
-
|
|
181
|
+
# `scan` raises on binary string literals with invalid byte sequences.
|
|
182
|
+
value = literal.value
|
|
183
|
+
value = value.scrub unless value.valid_encoding?
|
|
184
|
+
value.scan(IDENTIFIER_PATTERN) { |token| names << token }
|
|
131
185
|
end
|
|
132
186
|
end
|
|
133
187
|
end
|
|
134
188
|
|
|
189
|
+
# The leading literal fragment of an interpolated symbol or string acts
|
|
190
|
+
# as a method-name prefix: `send(:"format_#{type}")` may invoke any
|
|
191
|
+
# method whose name starts with `format_`. Only the leading fragment
|
|
192
|
+
# qualifies (a mid-string fragment is not a name prefix), and a fully
|
|
193
|
+
# dynamic name contributes nothing.
|
|
194
|
+
def literal_name_prefixes
|
|
195
|
+
@literal_name_prefixes ||=
|
|
196
|
+
processed_source.ast.each_descendant(:dsym, :dstr)
|
|
197
|
+
.with_object(Set.new) do |literal, prefixes|
|
|
198
|
+
prefix = interpolation_prefix(literal)
|
|
199
|
+
prefixes << prefix if prefix
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def interpolation_prefix(node)
|
|
204
|
+
return nil if node.children.all?(&:str_type?)
|
|
205
|
+
|
|
206
|
+
leading_fragment = node.children.first
|
|
207
|
+
return nil unless leading_fragment&.str_type?
|
|
208
|
+
|
|
209
|
+
leading_fragment.value[NAME_PREFIX_PATTERN]
|
|
210
|
+
end
|
|
211
|
+
|
|
135
212
|
# A method defined in a class or module with descendants may be invoked
|
|
136
213
|
# through `super` or inherited dispatch, which the index does not track.
|
|
137
214
|
def owner_with_descendants?(declaration)
|
|
@@ -210,7 +210,7 @@ module RuboCop
|
|
|
210
210
|
end
|
|
211
211
|
end
|
|
212
212
|
|
|
213
|
-
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
213
|
+
# rubocop:disable-next Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
214
214
|
def check_child_nodes(node, unused, cur_vis)
|
|
215
215
|
node.child_nodes.each do |child|
|
|
216
216
|
if child.send_type? && access_modifier?(child)
|
|
@@ -228,7 +228,6 @@ module RuboCop
|
|
|
228
228
|
|
|
229
229
|
[cur_vis, unused]
|
|
230
230
|
end
|
|
231
|
-
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
232
231
|
|
|
233
232
|
def check_send_node(node, cur_vis, unused)
|
|
234
233
|
if node.bare_access_modifier?
|
|
@@ -173,7 +173,7 @@ module RuboCop
|
|
|
173
173
|
node.receiver.nil? && !node.arguments?
|
|
174
174
|
end
|
|
175
175
|
|
|
176
|
-
# rubocop:disable Metrics/AbcSize
|
|
176
|
+
# rubocop:disable-next Metrics/AbcSize
|
|
177
177
|
def autocorrect(corrector, assignment)
|
|
178
178
|
if assignment.exception_assignment?
|
|
179
179
|
remove_exception_assignment_part(corrector, assignment.node)
|
|
@@ -189,7 +189,6 @@ module RuboCop
|
|
|
189
189
|
remove_local_variable_assignment_part(corrector, assignment.node)
|
|
190
190
|
end
|
|
191
191
|
end
|
|
192
|
-
# rubocop:enable Metrics/AbcSize
|
|
193
192
|
|
|
194
193
|
def remove_exception_assignment_part(corrector, node)
|
|
195
194
|
range = node.parent.children.first&.source_range || node.parent.location.keyword
|
|
@@ -10,6 +10,11 @@ module RuboCop
|
|
|
10
10
|
# It does not support autocorrection due to behavior change and multiple ways to fix it.
|
|
11
11
|
# Or a public constant may be intended.
|
|
12
12
|
#
|
|
13
|
+
# Constant assignments that define classes or modules via `Class.new`, `Module.new`,
|
|
14
|
+
# `Struct.new`, or `Data.define` are allowed. Those forms are class and module definitions
|
|
15
|
+
# written with assignment syntax, and match the common practice of placing nested
|
|
16
|
+
# `class` / `module` bodies after `private` without intending private constant visibility.
|
|
17
|
+
#
|
|
13
18
|
# @example
|
|
14
19
|
#
|
|
15
20
|
# # bad
|
|
@@ -29,6 +34,19 @@ module RuboCop
|
|
|
29
34
|
# PUBLIC_CONST = 42 # If private scope is not intended.
|
|
30
35
|
# end
|
|
31
36
|
#
|
|
37
|
+
# # good - class/module definitions via assignment, same as nested `class`/`module`
|
|
38
|
+
# class Foo
|
|
39
|
+
# private
|
|
40
|
+
#
|
|
41
|
+
# def some_private_method
|
|
42
|
+
# end
|
|
43
|
+
#
|
|
44
|
+
# MyClass = Class.new
|
|
45
|
+
# MyModule = Module.new
|
|
46
|
+
# MyStruct = Struct.new(:name)
|
|
47
|
+
# MyData = Data.define(:name)
|
|
48
|
+
# end
|
|
49
|
+
#
|
|
32
50
|
class UselessConstantScoping < Base
|
|
33
51
|
MSG = 'Useless `private` access modifier for constant scope.'
|
|
34
52
|
|
|
@@ -37,9 +55,27 @@ module RuboCop
|
|
|
37
55
|
(send nil? :private_constant $...)
|
|
38
56
|
PATTERN
|
|
39
57
|
|
|
58
|
+
# Matches class/module-like constant assignments. Nested `class` / `module`
|
|
59
|
+
# keyword definitions are not visited by this cop; these assignment forms are
|
|
60
|
+
# the equivalent syntax and should be treated the same way.
|
|
61
|
+
# @!method class_or_module_definition_assignment?(node)
|
|
62
|
+
def_node_matcher :class_or_module_definition_assignment?, <<~PATTERN
|
|
63
|
+
{
|
|
64
|
+
(send (const {nil? cbase} {:Class :Module :Struct}) :new ...)
|
|
65
|
+
(send (const {nil? cbase} :Data) :define ...)
|
|
66
|
+
(any_block
|
|
67
|
+
{
|
|
68
|
+
(send (const {nil? cbase} {:Class :Module :Struct}) :new ...)
|
|
69
|
+
(send (const {nil? cbase} :Data) :define ...)
|
|
70
|
+
}
|
|
71
|
+
...)
|
|
72
|
+
}
|
|
73
|
+
PATTERN
|
|
74
|
+
|
|
40
75
|
def on_casgn(node)
|
|
41
76
|
return unless after_private_modifier?(node.left_siblings)
|
|
42
77
|
return if private_constantize?(node.right_siblings, node.name)
|
|
78
|
+
return if class_or_module_definition_assignment?(node.expression)
|
|
43
79
|
|
|
44
80
|
add_offense(node)
|
|
45
81
|
end
|
|
@@ -59,7 +59,7 @@ module RuboCop
|
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
def use_rest_or_optional_args?(node)
|
|
62
|
-
node.arguments.any? { |arg| arg.type?(:restarg, :optarg, :kwoptarg) }
|
|
62
|
+
node.arguments.any? { |arg| arg.type?(:restarg, :optarg, :kwoptarg, :kwrestarg) }
|
|
63
63
|
end
|
|
64
64
|
|
|
65
65
|
def delegating?(node, def_node)
|
|
@@ -56,7 +56,7 @@ module RuboCop
|
|
|
56
56
|
|
|
57
57
|
private
|
|
58
58
|
|
|
59
|
-
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
|
59
|
+
# rubocop:disable-next Metrics/AbcSize, Metrics/CyclomaticComplexity
|
|
60
60
|
def only_reraising?(resbody_node)
|
|
61
61
|
return false if use_exception_variable_in_ensure?(resbody_node)
|
|
62
62
|
|
|
@@ -70,7 +70,6 @@ module RuboCop
|
|
|
70
70
|
|
|
71
71
|
exception_objects(resbody_node).include?(exception_name)
|
|
72
72
|
end
|
|
73
|
-
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
|
74
73
|
|
|
75
74
|
def use_exception_variable_in_ensure?(resbody_node)
|
|
76
75
|
return false unless (exception_variable = resbody_node.exception_variable)
|
|
@@ -12,6 +12,8 @@ module RuboCop
|
|
|
12
12
|
@receiver = receiver
|
|
13
13
|
@additional_nil_methods = additional_nil_methods
|
|
14
14
|
@checked_nodes = {}.compare_by_identity
|
|
15
|
+
@receiver_binding_name = binding_name(receiver)
|
|
16
|
+
@receiver_binding_scope = binding_scope(receiver) if @receiver_binding_name
|
|
15
17
|
end
|
|
16
18
|
|
|
17
19
|
def cant_be_nil?
|
|
@@ -20,7 +22,7 @@ module RuboCop
|
|
|
20
22
|
|
|
21
23
|
private
|
|
22
24
|
|
|
23
|
-
# rubocop:disable Metrics
|
|
25
|
+
# rubocop:disable-next Metrics
|
|
24
26
|
def _cant_be_nil?(node, receiver)
|
|
25
27
|
return false unless node
|
|
26
28
|
|
|
@@ -34,7 +36,9 @@ module RuboCop
|
|
|
34
36
|
when :def, :defs, :class, :module, :sclass
|
|
35
37
|
return false
|
|
36
38
|
when :send
|
|
37
|
-
|
|
39
|
+
if node.receiver == receiver && same_binding_as_receiver?(node.receiver)
|
|
40
|
+
return non_nil_method?(node.method_name)
|
|
41
|
+
end
|
|
38
42
|
|
|
39
43
|
node.arguments.each do |argument|
|
|
40
44
|
return true if _cant_be_nil?(argument, receiver)
|
|
@@ -74,13 +78,12 @@ module RuboCop
|
|
|
74
78
|
false
|
|
75
79
|
end
|
|
76
80
|
end
|
|
77
|
-
# rubocop:enable Metrics
|
|
78
81
|
|
|
79
82
|
def non_nil_method?(method_name)
|
|
80
83
|
!NIL_METHODS.include?(method_name) && !@additional_nil_methods.include?(method_name)
|
|
81
84
|
end
|
|
82
85
|
|
|
83
|
-
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
86
|
+
# rubocop:disable-next Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
84
87
|
def sole_condition_of_parent_if?(node)
|
|
85
88
|
child = node
|
|
86
89
|
parent = node.parent
|
|
@@ -104,12 +107,63 @@ module RuboCop
|
|
|
104
107
|
|
|
105
108
|
false
|
|
106
109
|
end
|
|
107
|
-
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
108
110
|
|
|
109
111
|
def non_nil_condition?(condition, node)
|
|
110
|
-
return true if condition == node
|
|
112
|
+
return true if condition == node && same_binding_as_receiver?(condition)
|
|
113
|
+
return false unless condition.csend_type?
|
|
114
|
+
|
|
115
|
+
root_receiver = csend_root_receiver(condition)
|
|
116
|
+
|
|
117
|
+
root_receiver == node && same_binding_as_receiver?(root_receiver)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Structurally equal occurrences can be different variables: `it` binds to
|
|
121
|
+
# its innermost block, and a block parameter can shadow an outer variable of
|
|
122
|
+
# the same name. Evidence about such a receiver only holds when both occurrences
|
|
123
|
+
# resolve to the same binding.
|
|
124
|
+
def same_binding_as_receiver?(occurrence)
|
|
125
|
+
return true unless @receiver_binding_name
|
|
126
|
+
|
|
127
|
+
binding_scope(occurrence).equal?(@receiver_binding_scope)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# The name whose binding can differ between structurally equal occurrences:
|
|
131
|
+
# a local variable (block parameters included), or a bare `it` call, which is
|
|
132
|
+
# how `it` parses when the target Ruby version is below 3.4 even though the code
|
|
133
|
+
# may run on 3.4+ where `it` is the implicit block parameter.
|
|
134
|
+
def binding_name(node)
|
|
135
|
+
if node.lvar_type?
|
|
136
|
+
node.children.first
|
|
137
|
+
elsif node.send_type? && !node.receiver && node.method?(:it) && node.arguments.empty?
|
|
138
|
+
:it
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def binding_scope(occurrence)
|
|
143
|
+
node = occurrence
|
|
144
|
+
|
|
145
|
+
while (parent = node.parent)
|
|
146
|
+
case parent.type
|
|
147
|
+
when :block, :numblock, :itblock
|
|
148
|
+
# Only the body is inside the block's scope; the send node and the arguments of
|
|
149
|
+
# the block node evaluate in the outer scope.
|
|
150
|
+
return parent if parent.body.equal?(node) && block_binds_name?(parent)
|
|
151
|
+
when :def, :defs, :class, :module, :sclass
|
|
152
|
+
return parent
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
node = parent
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
nil
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def block_binds_name?(block_node)
|
|
162
|
+
name = @receiver_binding_name
|
|
163
|
+
|
|
164
|
+
return true if block_node.argument_list.any? { |argument| argument.name == name }
|
|
111
165
|
|
|
112
|
-
|
|
166
|
+
name == :it && block_node.arguments.empty?
|
|
113
167
|
end
|
|
114
168
|
|
|
115
169
|
# Whether control reaches `node` by falling through its left siblings rather than by
|
|
@@ -153,7 +153,7 @@ module RuboCop
|
|
|
153
153
|
check_expression(case_node.else_branch) if case_node.else_branch
|
|
154
154
|
end
|
|
155
155
|
|
|
156
|
-
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
156
|
+
# rubocop:disable-next Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
157
157
|
def check_void_op(node, &block)
|
|
158
158
|
node = node.children.first while node&.begin_type?
|
|
159
159
|
return unless node&.call_type? && OPERATORS.include?(node.method_name)
|
|
@@ -168,7 +168,6 @@ module RuboCop
|
|
|
168
168
|
autocorrect_void_op(corrector, node)
|
|
169
169
|
end
|
|
170
170
|
end
|
|
171
|
-
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
172
171
|
|
|
173
172
|
def check_var(node)
|
|
174
173
|
return unless node.variable? || node.const_type?
|
data/lib/rubocop/cop/lint.rb
CHANGED
|
@@ -13,6 +13,7 @@ module RuboCop
|
|
|
13
13
|
register_cop :AmbiguousOperatorPrecedence, "#{__dir__}/lint/ambiguous_operator_precedence"
|
|
14
14
|
register_cop :AmbiguousRange, "#{__dir__}/lint/ambiguous_range"
|
|
15
15
|
register_cop :AmbiguousRegexpLiteral, "#{__dir__}/lint/ambiguous_regexp_literal"
|
|
16
|
+
register_cop :ArgumentMismatch, "#{__dir__}/lint/argument_mismatch"
|
|
16
17
|
register_cop :ArrayLiteralInRegexp, "#{__dir__}/lint/array_literal_in_regexp"
|
|
17
18
|
register_cop :AssignmentInCondition, "#{__dir__}/lint/assignment_in_condition"
|
|
18
19
|
register_cop :BigDecimalNew, "#{__dir__}/lint/big_decimal_new"
|
|
@@ -75,6 +76,7 @@ module RuboCop
|
|
|
75
76
|
register_cop :LiteralAssignmentInCondition, "#{__dir__}/lint/literal_assignment_in_condition"
|
|
76
77
|
register_cop :LiteralInInterpolation, "#{__dir__}/lint/literal_in_interpolation"
|
|
77
78
|
register_cop :Loop, "#{__dir__}/lint/loop"
|
|
79
|
+
register_cop :MisplacedMagicComment, "#{__dir__}/lint/misplaced_magic_comment"
|
|
78
80
|
register_cop :MissingCopEnableDirective, "#{__dir__}/lint/missing_cop_enable_directive"
|
|
79
81
|
register_cop :MissingSuper, "#{__dir__}/lint/missing_super"
|
|
80
82
|
register_cop :MixedCaseRange, "#{__dir__}/lint/mixed_case_range"
|
|
@@ -128,6 +130,7 @@ module RuboCop
|
|
|
128
130
|
register_cop :ShadowedException, "#{__dir__}/lint/shadowed_exception"
|
|
129
131
|
register_cop :ShadowingOuterLocalVariable, "#{__dir__}/lint/shadowing_outer_local_variable"
|
|
130
132
|
register_cop :StructNewOverride, "#{__dir__}/lint/struct_new_override"
|
|
133
|
+
register_cop :SuperArgumentMismatch, "#{__dir__}/lint/super_argument_mismatch"
|
|
131
134
|
register_cop :SuppressedException, "#{__dir__}/lint/suppressed_exception"
|
|
132
135
|
register_cop :SuppressedExceptionInNumberConversion, "#{__dir__}/lint/suppressed_exception_in_number_conversion"
|
|
133
136
|
register_cop :SymbolConversion, "#{__dir__}/lint/symbol_conversion"
|
|
@@ -49,7 +49,7 @@ module RuboCop
|
|
|
49
49
|
|
|
50
50
|
private
|
|
51
51
|
|
|
52
|
-
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
52
|
+
# rubocop:disable-next Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
53
53
|
def complexity_score_for(node)
|
|
54
54
|
case node.type
|
|
55
55
|
when :case
|
|
@@ -74,7 +74,6 @@ module RuboCop
|
|
|
74
74
|
super
|
|
75
75
|
end
|
|
76
76
|
end
|
|
77
|
-
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
78
77
|
|
|
79
78
|
def simple_in_pattern?(in_pattern_node)
|
|
80
79
|
# `in_pattern_node.children[1]` is the guard (`if`/`unless`), or `nil`.
|
|
@@ -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 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
|
|
@@ -85,4 +85,3 @@ module RuboCop
|
|
|
85
85
|
end
|
|
86
86
|
end
|
|
87
87
|
end
|
|
88
|
-
# rubocop:enable Lint/RedundantCopDisableDirective
|
|
@@ -66,7 +66,7 @@ module RuboCop
|
|
|
66
66
|
end
|
|
67
67
|
|
|
68
68
|
# @deprecated Use processed_source.line_with_comment?(line)
|
|
69
|
-
def end_of_line_comment(line) # rubocop:disable Naming/PredicateMethod
|
|
69
|
+
def end_of_line_comment(line) # rubocop:disable Naming/PredicateMethod -- a deprecated shim kept under its original name
|
|
70
70
|
warn Rainbow(<<~WARNING).yellow, uplevel: 1
|
|
71
71
|
`end_of_line_comment` is deprecated. Use `processed_source.line_with_comment?` instead.
|
|
72
72
|
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
|
|
@@ -64,7 +64,7 @@ module RuboCop
|
|
|
64
64
|
# Returns the end line of a node, which might be a comment and not part of the AST
|
|
65
65
|
# End line is considered either the line at which another node starts, or
|
|
66
66
|
# the line at which the parent node ends.
|
|
67
|
-
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
67
|
+
# rubocop:disable-next Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
68
68
|
def find_end_line(node)
|
|
69
69
|
if node.if_type?
|
|
70
70
|
if node.else?
|
|
@@ -89,7 +89,6 @@ module RuboCop
|
|
|
89
89
|
end
|
|
90
90
|
end || node.loc.end.line
|
|
91
91
|
end
|
|
92
|
-
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
93
92
|
end
|
|
94
93
|
end
|
|
95
94
|
end
|
|
@@ -25,7 +25,7 @@ module RuboCop
|
|
|
25
25
|
end
|
|
26
26
|
private_constant :SYMBOL_TO_STRING_CACHE
|
|
27
27
|
|
|
28
|
-
# rubocop:disable Metrics
|
|
28
|
+
# rubocop:disable-next Metrics
|
|
29
29
|
def style_detected(detected)
|
|
30
30
|
return if no_acceptable_style?
|
|
31
31
|
|
|
@@ -51,7 +51,6 @@ module RuboCop
|
|
|
51
51
|
config_to_allow_offenses[style_parameter_name] = updated_list.first
|
|
52
52
|
end
|
|
53
53
|
end
|
|
54
|
-
# rubocop:enable Metrics
|
|
55
54
|
|
|
56
55
|
def no_acceptable_style?
|
|
57
56
|
config_to_allow_offenses['Enabled'] == false
|
|
@@ -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
|
|
@@ -87,13 +87,17 @@ module RuboCop
|
|
|
87
87
|
def ignore_mixed_hash_shorthand_syntax?(hash_node)
|
|
88
88
|
target_ruby_version <= 3.0 ||
|
|
89
89
|
!%w[consistent either_consistent].include?(enforced_shorthand_syntax) ||
|
|
90
|
-
!hash_node.hash_type?
|
|
90
|
+
!hash_node.hash_type? || hash_rockets_enforced?(hash_node)
|
|
91
91
|
end
|
|
92
92
|
|
|
93
93
|
def ignore_hash_shorthand_syntax?(pair_node)
|
|
94
94
|
target_ruby_version <= 3.0 || enforced_shorthand_syntax == 'either' ||
|
|
95
95
|
%w[consistent either_consistent].include?(enforced_shorthand_syntax) ||
|
|
96
|
-
!pair_node.parent.hash_type?
|
|
96
|
+
!pair_node.parent.hash_type? || hash_rockets_enforced?(pair_node.parent)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def hash_rockets_enforced?(hash_node)
|
|
100
|
+
style == :hash_rockets || force_hash_rockets?(hash_node.pairs)
|
|
97
101
|
end
|
|
98
102
|
|
|
99
103
|
def enforced_shorthand_syntax
|
|
@@ -117,7 +121,7 @@ module RuboCop
|
|
|
117
121
|
use_modifier_form_without_parenthesized_method_call?(method_dispatch_node)
|
|
118
122
|
end
|
|
119
123
|
|
|
120
|
-
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
124
|
+
# rubocop:disable-next Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
121
125
|
def def_node_that_require_parentheses(node)
|
|
122
126
|
last_pair = node.parent.pairs.last
|
|
123
127
|
return unless last_pair.key.source == last_pair.value.source
|
|
@@ -131,7 +135,6 @@ module RuboCop
|
|
|
131
135
|
|
|
132
136
|
DefNode.new(def_node) unless def_node && def_node.arguments.empty?
|
|
133
137
|
end
|
|
134
|
-
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
135
138
|
|
|
136
139
|
def find_ancestor_method_dispatch_node(node)
|
|
137
140
|
return unless (ancestor = node.parent.parent)
|
|
@@ -5,7 +5,7 @@ module RuboCop
|
|
|
5
5
|
# Common functionality for Style/HashExcept and Style/HashSlice cops.
|
|
6
6
|
# It registers an offense on methods with blocks that are equivalent
|
|
7
7
|
# to Hash#except or Hash#slice.
|
|
8
|
-
# rubocop:disable Metrics/ModuleLength
|
|
8
|
+
# rubocop:disable-next Metrics/ModuleLength
|
|
9
9
|
module HashSubset
|
|
10
10
|
include RangeHelp
|
|
11
11
|
extend NodePattern::Macros
|
|
@@ -206,6 +206,5 @@ module RuboCop
|
|
|
206
206
|
range_between(node.loc.selector.begin_pos, node.parent.loc.end.end_pos)
|
|
207
207
|
end
|
|
208
208
|
end
|
|
209
|
-
# rubocop:enable Metrics/ModuleLength
|
|
210
209
|
end
|
|
211
210
|
end
|
|
@@ -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
|