rubocop 1.45.1 → 1.50.1
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 +46 -15
- data/lib/rubocop/cli/command/auto_generate_config.rb +7 -0
- data/lib/rubocop/cli/command/execute_runner.rb +7 -2
- data/lib/rubocop/cli.rb +6 -6
- data/lib/rubocop/comment_config.rb +19 -0
- data/lib/rubocop/config.rb +3 -3
- data/lib/rubocop/config_loader.rb +8 -8
- data/lib/rubocop/cop/autocorrect_logic.rb +29 -13
- data/lib/rubocop/cop/base.rb +1 -1
- data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
- data/lib/rubocop/cop/cop.rb +2 -2
- data/lib/rubocop/cop/corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +2 -2
- data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +3 -3
- data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +3 -3
- data/lib/rubocop/cop/correctors/line_break_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +2 -2
- data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +2 -2
- data/lib/rubocop/cop/gemspec/dependency_version.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/cop_description.rb +5 -5
- data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +3 -3
- data/lib/rubocop/cop/internal_affairs/inherit_deprecated_cop_class.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/location_expression.rb +37 -0
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/processed_source_buffer_name.rb +42 -0
- data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +66 -0
- data/lib/rubocop/cop/internal_affairs.rb +3 -0
- data/lib/rubocop/cop/layout/block_end_newline.rb +7 -21
- data/lib/rubocop/cop/layout/class_structure.rb +6 -3
- data/lib/rubocop/cop/layout/closing_heredoc_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/empty_comment.rb +3 -3
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +2 -0
- data/lib/rubocop/cop/layout/end_alignment.rb +9 -1
- data/lib/rubocop/cop/layout/extra_spacing.rb +6 -1
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +7 -2
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +8 -2
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/initial_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/leading_comment_space.rb +1 -1
- data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +1 -3
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +11 -7
- data/lib/rubocop/cop/layout/redundant_line_break.rb +6 -7
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +2 -2
- data/lib/rubocop/cop/layout/space_before_first_arg.rb +1 -1
- data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +2 -2
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +1 -1
- data/lib/rubocop/cop/layout/space_inside_parens.rb +2 -2
- data/lib/rubocop/cop/layout/space_inside_percent_literal_delimiters.rb +1 -1
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
- data/lib/rubocop/cop/lint/constant_resolution.rb +1 -1
- data/lib/rubocop/cop/lint/debugger.rb +3 -0
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +4 -4
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +122 -0
- data/lib/rubocop/cop/lint/duplicate_methods.rb +2 -2
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -3
- data/lib/rubocop/cop/lint/else_layout.rb +1 -1
- data/lib/rubocop/cop/lint/empty_block.rb +1 -1
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +4 -2
- data/lib/rubocop/cop/lint/empty_interpolation.rb +1 -1
- data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -1
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +46 -4
- data/lib/rubocop/cop/lint/missing_super.rb +31 -2
- data/lib/rubocop/cop/lint/nested_method_definition.rb +3 -11
- data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +2 -0
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +6 -10
- data/lib/rubocop/cop/lint/percent_string_array.rb +1 -1
- data/lib/rubocop/cop/lint/percent_symbol_array.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +11 -5
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +5 -5
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_string_coercion.rb +35 -15
- data/lib/rubocop/cop/lint/redundant_with_index.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_with_object.rb +1 -1
- data/lib/rubocop/cop/lint/refinement_import_methods.rb +2 -1
- data/lib/rubocop/cop/lint/rescue_type.rb +3 -3
- data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +1 -1
- data/lib/rubocop/cop/lint/script_permission.rb +1 -1
- data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
- data/lib/rubocop/cop/lint/syntax.rb +4 -0
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +13 -3
- data/lib/rubocop/cop/lint/unreachable_loop.rb +3 -3
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +10 -10
- data/lib/rubocop/cop/lint/useless_method_definition.rb +10 -2
- data/lib/rubocop/cop/lint/useless_rescue.rb +6 -2
- data/lib/rubocop/cop/lint/useless_times.rb +1 -1
- data/lib/rubocop/cop/lint/void.rb +7 -3
- data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
- data/lib/rubocop/cop/metrics/class_length.rb +1 -0
- data/lib/rubocop/cop/metrics/collection_literal_length.rb +76 -0
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +3 -3
- data/lib/rubocop/cop/migration/department_name.rb +1 -1
- data/lib/rubocop/cop/mixin/annotation_comment.rb +1 -1
- data/lib/rubocop/cop/mixin/code_length.rb +1 -1
- data/lib/rubocop/cop/mixin/comments_help.rb +3 -3
- data/lib/rubocop/cop/mixin/documentation_comment.rb +1 -1
- data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +1 -1
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +10 -5
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +3 -3
- data/lib/rubocop/cop/mixin/min_branches_count.rb +40 -0
- data/lib/rubocop/cop/mixin/multiline_element_line_breaks.rb +0 -3
- data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
- data/lib/rubocop/cop/mixin/range_help.rb +1 -6
- data/lib/rubocop/cop/mixin/statement_modifier.rb +3 -3
- data/lib/rubocop/cop/mixin/trailing_comma.rb +1 -1
- data/lib/rubocop/cop/naming/ascii_identifiers.rb +1 -1
- data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +1 -1
- data/lib/rubocop/cop/naming/inclusive_language.rb +23 -4
- data/lib/rubocop/cop/naming/method_name.rb +3 -3
- data/lib/rubocop/cop/naming/predicate_name.rb +1 -1
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +1 -1
- data/lib/rubocop/cop/registry.rb +3 -1
- data/lib/rubocop/cop/style/accessor_grouping.rb +39 -17
- data/lib/rubocop/cop/style/arguments_forwarding.rb +3 -3
- data/lib/rubocop/cop/style/array_intersect.rb +1 -1
- data/lib/rubocop/cop/style/ascii_comments.rb +1 -1
- data/lib/rubocop/cop/style/bisected_attr_accessor.rb +1 -1
- data/lib/rubocop/cop/style/block_comments.rb +1 -1
- data/lib/rubocop/cop/style/block_delimiters.rb +11 -2
- data/lib/rubocop/cop/style/case_like_if.rb +20 -3
- data/lib/rubocop/cop/style/class_and_module_children.rb +1 -1
- data/lib/rubocop/cop/style/class_equality_comparison.rb +42 -9
- data/lib/rubocop/cop/style/collection_compact.rb +1 -1
- data/lib/rubocop/cop/style/comment_annotation.rb +1 -1
- data/lib/rubocop/cop/style/commented_keyword.rb +2 -2
- data/lib/rubocop/cop/style/concat_array_literals.rb +10 -2
- data/lib/rubocop/cop/style/conditional_assignment.rb +6 -6
- data/lib/rubocop/cop/style/copyright.rb +1 -1
- data/lib/rubocop/cop/style/data_inheritance.rb +75 -0
- data/lib/rubocop/cop/style/dir_empty.rb +60 -0
- data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +2 -2
- data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +2 -2
- data/lib/rubocop/cop/style/documentation.rb +10 -4
- data/lib/rubocop/cop/style/documentation_method.rb +4 -4
- data/lib/rubocop/cop/style/double_negation.rb +2 -2
- data/lib/rubocop/cop/style/each_with_object.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/eval_with_location.rb +4 -4
- data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
- data/lib/rubocop/cop/style/file_empty.rb +71 -0
- data/lib/rubocop/cop/style/file_read.rb +1 -1
- data/lib/rubocop/cop/style/file_write.rb +1 -1
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
- data/lib/rubocop/cop/style/guard_clause.rb +1 -1
- data/lib/rubocop/cop/style/hash_except.rb +4 -4
- data/lib/rubocop/cop/style/hash_like_case.rb +3 -9
- data/lib/rubocop/cop/style/hash_syntax.rb +5 -2
- data/lib/rubocop/cop/style/if_unless_modifier.rb +108 -15
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +2 -0
- data/lib/rubocop/cop/style/inverse_methods.rb +5 -5
- data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +2 -2
- data/lib/rubocop/cop/style/map_to_hash.rb +4 -1
- data/lib/rubocop/cop/style/map_to_set.rb +4 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +3 -7
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +44 -37
- data/lib/rubocop/cop/style/min_max.rb +3 -3
- data/lib/rubocop/cop/style/mixin_grouping.rb +4 -4
- data/lib/rubocop/cop/style/multiline_method_signature.rb +7 -4
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +1 -1
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +12 -7
- data/lib/rubocop/cop/style/nil_lambda.rb +2 -2
- data/lib/rubocop/cop/style/parallel_assignment.rb +26 -18
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +2 -3
- data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
- data/lib/rubocop/cop/style/redundant_condition.rb +2 -2
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +2 -2
- data/lib/rubocop/cop/style/redundant_interpolation.rb +2 -2
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +179 -0
- data/lib/rubocop/cop/style/redundant_parentheses.rb +2 -2
- data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -1
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +7 -8
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +11 -4
- data/lib/rubocop/cop/style/redundant_sort.rb +3 -3
- data/lib/rubocop/cop/style/redundant_string_escape.rb +3 -4
- data/lib/rubocop/cop/style/require_order.rb +1 -3
- data/lib/rubocop/cop/style/rescue_standard_error.rb +2 -2
- data/lib/rubocop/cop/style/safe_navigation.rb +2 -2
- data/lib/rubocop/cop/style/slicing_with_range.rb +1 -1
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +3 -3
- data/lib/rubocop/cop/style/stderr_puts.rb +1 -1
- data/lib/rubocop/cop/style/struct_inheritance.rb +1 -1
- data/lib/rubocop/cop/style/trailing_body_on_class.rb +1 -0
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +1 -1
- data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
- data/lib/rubocop/cop/style/unless_logical_operators.rb +1 -0
- data/lib/rubocop/cop/style/unpack_first.rb +3 -3
- data/lib/rubocop/cop/style/word_array.rb +17 -5
- data/lib/rubocop/cop/style/yoda_condition.rb +1 -1
- data/lib/rubocop/cop/style/zero_length_predicate.rb +9 -5
- data/lib/rubocop/cop/team.rb +11 -8
- data/lib/rubocop/cop/util.rb +13 -4
- data/lib/rubocop/cop/variable_force/variable.rb +5 -3
- data/lib/rubocop/cops_documentation_generator.rb +10 -3
- data/lib/rubocop/directive_comment.rb +3 -3
- data/lib/rubocop/ext/comment.rb +18 -0
- data/lib/rubocop/ext/regexp_node.rb +1 -1
- data/lib/rubocop/ext/regexp_parser.rb +1 -1
- data/lib/rubocop/formatter/junit_formatter.rb +4 -1
- data/lib/rubocop/formatter/simple_text_formatter.rb +1 -1
- data/lib/rubocop/options.rb +4 -1
- data/lib/rubocop/result_cache.rb +1 -1
- data/lib/rubocop/rspec/cop_helper.rb +1 -1
- data/lib/rubocop/rspec/shared_contexts.rb +4 -0
- data/lib/rubocop/rspec/support.rb +1 -0
- data/lib/rubocop/server/cache.rb +1 -1
- data/lib/rubocop/server/core.rb +1 -1
- data/lib/rubocop/server/helper.rb +1 -1
- data/lib/rubocop/server/server_command/exec.rb +1 -1
- data/lib/rubocop/target_ruby.rb +1 -1
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +8 -0
- metadata +20 -9
@@ -122,8 +122,8 @@ module RuboCop
|
|
122
122
|
end
|
123
123
|
|
124
124
|
def safe_to_register_offense?(block, except_key)
|
125
|
-
extracted =
|
126
|
-
if extracted.method?('in?') || extracted.method?('include?') ||
|
125
|
+
extracted = extract_body_if_negated(block.body)
|
126
|
+
if extracted.method?('in?') || extracted.method?('include?') ||
|
127
127
|
extracted.method?('exclude?')
|
128
128
|
return true
|
129
129
|
end
|
@@ -132,7 +132,7 @@ module RuboCop
|
|
132
132
|
except_key.sym_type? || except_key.str_type?
|
133
133
|
end
|
134
134
|
|
135
|
-
def
|
135
|
+
def extract_body_if_negated(body)
|
136
136
|
return body unless body.method?('!')
|
137
137
|
|
138
138
|
body.receiver
|
@@ -161,7 +161,7 @@ module RuboCop
|
|
161
161
|
|
162
162
|
def except_key(node)
|
163
163
|
key_argument = node.argument_list.first.source
|
164
|
-
body =
|
164
|
+
body = extract_body_if_negated(node.body)
|
165
165
|
lhs, _method_name, rhs = *body
|
166
166
|
return if [lhs, rhs].map(&:source).none?(key_argument)
|
167
167
|
|
@@ -37,6 +37,8 @@ module RuboCop
|
|
37
37
|
# end
|
38
38
|
#
|
39
39
|
class HashLikeCase < Base
|
40
|
+
include MinBranchesCount
|
41
|
+
|
40
42
|
MSG = 'Consider replacing `case-when` with a hash lookup.'
|
41
43
|
|
42
44
|
# @!method hash_like_case?(node)
|
@@ -49,7 +51,7 @@ module RuboCop
|
|
49
51
|
PATTERN
|
50
52
|
|
51
53
|
def on_case(node)
|
52
|
-
return
|
54
|
+
return unless min_branches_count?(node)
|
53
55
|
|
54
56
|
hash_like_case?(node) do |condition_nodes, body_nodes|
|
55
57
|
if nodes_of_same_type?(condition_nodes) && nodes_of_same_type?(body_nodes)
|
@@ -63,14 +65,6 @@ module RuboCop
|
|
63
65
|
def nodes_of_same_type?(nodes)
|
64
66
|
nodes.all? { |node| node.type == nodes.first.type }
|
65
67
|
end
|
66
|
-
|
67
|
-
def min_branches_count
|
68
|
-
length = cop_config['MinBranchesCount'] || 3
|
69
|
-
return length if length.is_a?(Integer) && length.positive?
|
70
|
-
|
71
|
-
warn Rainbow('`MinBranchesCount` needs to be a positive integer!').red
|
72
|
-
exit!
|
73
|
-
end
|
74
68
|
end
|
75
69
|
end
|
76
70
|
end
|
@@ -88,6 +88,9 @@ module RuboCop
|
|
88
88
|
# {foo: foo, bar: bar}
|
89
89
|
#
|
90
90
|
# # good
|
91
|
+
# {foo: foo, bar:}
|
92
|
+
#
|
93
|
+
# # good
|
91
94
|
# {foo:, bar:}
|
92
95
|
#
|
93
96
|
# @example EnforcedShorthandSyntax: consistent
|
@@ -207,7 +210,7 @@ module RuboCop
|
|
207
210
|
return true if /\A[_a-z]\w*[?!]?\z/i.match?(sym_name)
|
208
211
|
|
209
212
|
# For more complicated hash keys, let the parser validate the syntax.
|
210
|
-
|
213
|
+
parse("{ #{sym_name}: :foo }").valid_syntax?
|
211
214
|
end
|
212
215
|
|
213
216
|
def check(pairs, delim, msg)
|
@@ -247,7 +250,7 @@ module RuboCop
|
|
247
250
|
end
|
248
251
|
|
249
252
|
def argument_without_space?(node)
|
250
|
-
node.argument? && node.
|
253
|
+
node.argument? && node.source_range.begin_pos == node.parent.loc.selector.end_pos
|
251
254
|
end
|
252
255
|
|
253
256
|
def autocorrect_hash_rockets(corrector, pair_node)
|
@@ -11,6 +11,32 @@ module RuboCop
|
|
11
11
|
# cop. The tab size is configured in the `IndentationWidth` of the
|
12
12
|
# `Layout/IndentationStyle` cop.
|
13
13
|
#
|
14
|
+
# One-line pattern matching is always allowed. To ensure that there are few cases
|
15
|
+
# where the match variable is not used, and to prevent oversights. The variable `x`
|
16
|
+
# becomes undefined and raises `NameError` when the following example is changed to
|
17
|
+
# the modifier form:
|
18
|
+
#
|
19
|
+
# [source,ruby]
|
20
|
+
# ----
|
21
|
+
# if [42] in [x]
|
22
|
+
# x # `x` is undefined when using modifier form.
|
23
|
+
# end
|
24
|
+
# ----
|
25
|
+
#
|
26
|
+
# NOTE: It is allowed when `defined?` argument has an undefined value,
|
27
|
+
# because using the modifier form causes the following incompatibility:
|
28
|
+
#
|
29
|
+
# [source,ruby]
|
30
|
+
# ----
|
31
|
+
# unless defined?(undefined_foo)
|
32
|
+
# undefined_foo = 'default_value'
|
33
|
+
# end
|
34
|
+
# undefined_foo # => 'default_value'
|
35
|
+
#
|
36
|
+
# undefined_bar = 'default_value' unless defined?(undefined_bar)
|
37
|
+
# undefined_bar # => nil
|
38
|
+
# ----
|
39
|
+
#
|
14
40
|
# @example
|
15
41
|
# # bad
|
16
42
|
# if condition
|
@@ -39,6 +65,7 @@ module RuboCop
|
|
39
65
|
include LineLengthHelp
|
40
66
|
include AllowedPattern
|
41
67
|
include RangeHelp
|
68
|
+
include CommentsHelp
|
42
69
|
extend AutoCorrector
|
43
70
|
|
44
71
|
MSG_USE_MODIFIER = 'Favor modifier `%<keyword>s` usage when having a ' \
|
@@ -51,12 +78,10 @@ module RuboCop
|
|
51
78
|
end
|
52
79
|
|
53
80
|
def on_if(node)
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
end
|
59
|
-
return unless msg
|
81
|
+
condition = node.condition
|
82
|
+
return if defined_nodes(condition).any? { |n| defined_argument_is_undefined?(node, n) } ||
|
83
|
+
pattern_matching_nodes(condition).any?
|
84
|
+
return unless (msg = message(node))
|
60
85
|
|
61
86
|
add_offense(node.loc.keyword, message: format(msg, keyword: node.keyword)) do |corrector|
|
62
87
|
autocorrect(corrector, node)
|
@@ -65,28 +90,81 @@ module RuboCop
|
|
65
90
|
|
66
91
|
private
|
67
92
|
|
93
|
+
def defined_nodes(condition)
|
94
|
+
if condition.defined_type?
|
95
|
+
[condition]
|
96
|
+
else
|
97
|
+
condition.each_descendant.select(&:defined_type?)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def defined_argument_is_undefined?(if_node, defined_node)
|
102
|
+
defined_argument = defined_node.first_argument
|
103
|
+
return false unless defined_argument.lvar_type? || defined_argument.send_type?
|
104
|
+
|
105
|
+
if_node.left_siblings.none? do |sibling|
|
106
|
+
sibling.respond_to?(:lvasgn_type?) && sibling.lvasgn_type? &&
|
107
|
+
sibling.name == defined_argument.node_parts[0]
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def pattern_matching_nodes(condition)
|
112
|
+
if condition.match_pattern_type? || condition.match_pattern_p_type?
|
113
|
+
[condition]
|
114
|
+
else
|
115
|
+
condition.each_descendant.select do |node|
|
116
|
+
node.match_pattern_type? || node.match_pattern_p_type?
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def message(node)
|
122
|
+
if single_line_as_modifier?(node) && !named_capture_in_condition?(node)
|
123
|
+
MSG_USE_MODIFIER
|
124
|
+
elsif too_long_due_to_modifier?(node)
|
125
|
+
MSG_USE_NORMAL
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
68
129
|
def autocorrect(corrector, node)
|
69
130
|
replacement = if node.modifier_form?
|
70
|
-
|
71
|
-
|
72
|
-
if last_argument.respond_to?(:heredoc?) && last_argument.heredoc?
|
73
|
-
heredoc = extract_heredoc_from(last_argument)
|
74
|
-
remove_heredoc(corrector, heredoc)
|
75
|
-
to_normal_form_with_heredoc(node, indent(node), heredoc)
|
76
|
-
else
|
77
|
-
to_normal_form(node, indent(node))
|
78
|
-
end
|
131
|
+
replacement_for_modifier_form(corrector, node)
|
79
132
|
else
|
80
133
|
to_modifier_form(node)
|
81
134
|
end
|
82
135
|
corrector.replace(node, replacement)
|
83
136
|
end
|
84
137
|
|
138
|
+
def replacement_for_modifier_form(corrector, node) # rubocop:disable Metrics/AbcSize
|
139
|
+
comment = comment_on_node_line(node)
|
140
|
+
if comment && too_long_due_to_comment_after_modifier?(node, comment)
|
141
|
+
remove_comment(corrector, node, comment)
|
142
|
+
|
143
|
+
return to_modifier_form_with_move_comment(node, indent(node), comment)
|
144
|
+
end
|
145
|
+
|
146
|
+
last_argument = node.if_branch.last_argument if node.if_branch.send_type?
|
147
|
+
if last_argument.respond_to?(:heredoc?) && last_argument.heredoc?
|
148
|
+
heredoc = extract_heredoc_from(last_argument)
|
149
|
+
remove_heredoc(corrector, heredoc)
|
150
|
+
|
151
|
+
return to_normal_form_with_heredoc(node, indent(node), heredoc)
|
152
|
+
end
|
153
|
+
|
154
|
+
to_normal_form(node, indent(node))
|
155
|
+
end
|
156
|
+
|
85
157
|
def too_long_due_to_modifier?(node)
|
86
158
|
node.modifier_form? && too_long_single_line?(node) &&
|
87
159
|
!another_statement_on_same_line?(node)
|
88
160
|
end
|
89
161
|
|
162
|
+
def too_long_due_to_comment_after_modifier?(node, comment)
|
163
|
+
source_length = processed_source.lines[node.first_line - 1].length
|
164
|
+
source_length >= max_line_length &&
|
165
|
+
source_length - comment.source_range.length <= max_line_length
|
166
|
+
end
|
167
|
+
|
90
168
|
def allowed_patterns
|
91
169
|
line_length_config = config.for_cop('Layout/LineLength')
|
92
170
|
line_length_config['AllowedPatterns'] || line_length_config['IgnoredPatterns'] || []
|
@@ -181,6 +259,13 @@ module RuboCop
|
|
181
259
|
RUBY
|
182
260
|
end
|
183
261
|
|
262
|
+
def to_modifier_form_with_move_comment(node, indentation, comment)
|
263
|
+
<<~RUBY.chomp
|
264
|
+
#{comment.source}
|
265
|
+
#{indentation}#{node.body.source} #{node.keyword} #{node.condition.source}
|
266
|
+
RUBY
|
267
|
+
end
|
268
|
+
|
184
269
|
def extract_heredoc_from(last_argument)
|
185
270
|
heredoc_body = last_argument.loc.heredoc_body
|
186
271
|
heredoc_end = last_argument.loc.heredoc_end
|
@@ -193,6 +278,14 @@ module RuboCop
|
|
193
278
|
corrector.remove(range_by_whole_lines(range, include_final_newline: true))
|
194
279
|
end
|
195
280
|
end
|
281
|
+
|
282
|
+
def comment_on_node_line(node)
|
283
|
+
processed_source.comments.find { |c| same_line?(c, node) }
|
284
|
+
end
|
285
|
+
|
286
|
+
def remove_comment(corrector, _node, comment)
|
287
|
+
corrector.remove(range_with_surrounding_space(range: comment.source_range, side: :left))
|
288
|
+
end
|
196
289
|
end
|
197
290
|
end
|
198
291
|
end
|
@@ -155,15 +155,15 @@ module RuboCop
|
|
155
155
|
end
|
156
156
|
|
157
157
|
def not_to_receiver(node, method_call)
|
158
|
-
Parser::Source::Range.new(node.
|
158
|
+
Parser::Source::Range.new(node.source_range.source_buffer,
|
159
159
|
node.loc.selector.begin_pos,
|
160
|
-
method_call.
|
160
|
+
method_call.source_range.begin_pos)
|
161
161
|
end
|
162
162
|
|
163
163
|
def end_parentheses(node, method_call)
|
164
|
-
Parser::Source::Range.new(node.
|
165
|
-
method_call.
|
166
|
-
node.
|
164
|
+
Parser::Source::Range.new(node.source_range.source_buffer,
|
165
|
+
method_call.source_range.end_pos,
|
166
|
+
node.source_range.end_pos)
|
167
167
|
end
|
168
168
|
|
169
169
|
# When comparing classes, `!(Integer < Numeric)` is not the same as
|
@@ -123,10 +123,10 @@ module RuboCop
|
|
123
123
|
end
|
124
124
|
|
125
125
|
def range(node)
|
126
|
-
buffer = node.
|
126
|
+
buffer = node.source_range.source_buffer
|
127
127
|
map_node = node.receiver.send_node
|
128
128
|
begin_pos = map_node.loc.selector.begin_pos
|
129
|
-
end_pos = node.
|
129
|
+
end_pos = node.source_range.end_pos
|
130
130
|
|
131
131
|
Parser::Source::Range.new(buffer, begin_pos, end_pos)
|
132
132
|
end
|
@@ -39,7 +39,10 @@ module RuboCop
|
|
39
39
|
|
40
40
|
# @!method map_to_h?(node)
|
41
41
|
def_node_matcher :map_to_h?, <<~PATTERN
|
42
|
-
|
42
|
+
{
|
43
|
+
$(send ({block numblock} $(send _ {:map :collect}) ...) :to_h)
|
44
|
+
$(send $(send _ {:map :collect} (block_pass sym)) :to_h)
|
45
|
+
}
|
43
46
|
PATTERN
|
44
47
|
|
45
48
|
def on_send(node)
|
@@ -32,7 +32,10 @@ module RuboCop
|
|
32
32
|
|
33
33
|
# @!method map_to_set?(node)
|
34
34
|
def_node_matcher :map_to_set?, <<~PATTERN
|
35
|
-
|
35
|
+
{
|
36
|
+
$(send ({block numblock} $(send _ {:map :collect}) ...) :to_set)
|
37
|
+
$(send $(send _ {:map :collect} (block_pass sym)) :to_set)
|
38
|
+
}
|
36
39
|
PATTERN
|
37
40
|
|
38
41
|
def on_send(node)
|
@@ -50,17 +50,13 @@ module RuboCop
|
|
50
50
|
return false unless (last_argument = node.last_argument)
|
51
51
|
return false if !last_argument.hash_type? || !last_argument.pairs.last&.value_omission?
|
52
52
|
|
53
|
-
|
54
|
-
end
|
55
|
-
|
56
|
-
def modifier_form?(node)
|
57
|
-
node.parent.respond_to?(:modifier_form?) && node.parent.modifier_form?
|
53
|
+
node.parent&.conditional? || !last_expression?(node)
|
58
54
|
end
|
59
55
|
|
60
56
|
# Require hash value omission be enclosed in parentheses to prevent the following issue:
|
61
57
|
# https://bugs.ruby-lang.org/issues/18396.
|
62
|
-
def
|
63
|
-
node.parent&.assignment? ? node.parent.right_sibling : node.right_sibling
|
58
|
+
def last_expression?(node)
|
59
|
+
!(node.parent&.assignment? ? node.parent.right_sibling : node.right_sibling)
|
64
60
|
end
|
65
61
|
|
66
62
|
def syntax_like_method_call?(node)
|
@@ -7,21 +7,19 @@ module RuboCop
|
|
7
7
|
# method calls containing parameters.
|
8
8
|
#
|
9
9
|
# In the default style (require_parentheses), macro methods are allowed.
|
10
|
-
# Additional methods can be added to the `AllowedMethods`
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
# the `IncludedMacros` list.
|
10
|
+
# Additional methods can be added to the `AllowedMethods` or
|
11
|
+
# `AllowedPatterns` list. These options are valid only in the default
|
12
|
+
# style. Macros can be included by either setting `IgnoreMacros` to false
|
13
|
+
# or adding specific macros to the `IncludedMacros` list.
|
15
14
|
#
|
16
|
-
# Precedence of options is
|
15
|
+
# Precedence of options is as follows:
|
17
16
|
#
|
18
17
|
# 1. `AllowedMethods`
|
19
18
|
# 2. `AllowedPatterns`
|
20
19
|
# 3. `IncludedMacros`
|
21
20
|
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
# precedence (that is, the method is allowed).
|
21
|
+
# If a method is listed in both `IncludedMacros` and `AllowedMethods`,
|
22
|
+
# then the latter takes precedence (that is, the method is allowed).
|
25
23
|
#
|
26
24
|
# In the alternative style (omit_parentheses), there are three additional
|
27
25
|
# options.
|
@@ -40,14 +38,29 @@ module RuboCop
|
|
40
38
|
# to `true` allows the presence of parentheses in such a method call
|
41
39
|
# even with arguments.
|
42
40
|
#
|
43
|
-
# NOTE:
|
44
|
-
# results in ambiguous or syntactically incorrect code.
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
#
|
50
|
-
#
|
41
|
+
# NOTE: The style of `omit_parentheses` allows parentheses in cases where
|
42
|
+
# omitting them results in ambiguous or syntactically incorrect code.
|
43
|
+
#
|
44
|
+
# Non-exhaustive list of examples:
|
45
|
+
#
|
46
|
+
# - Parentheses are required allowed in method calls with arguments inside
|
47
|
+
# literals, logical operators, setting default values in position and
|
48
|
+
# keyword arguments, chaining and more.
|
49
|
+
# - Parentheses are allowed in method calls with arguments inside
|
50
|
+
# operators to avoid ambiguity.
|
51
|
+
# triple-dot syntax introduced in Ruby 2.7 as omitting them starts an
|
52
|
+
# endless range.
|
53
|
+
# - Parentheses are allowed when forwarding arguments with the
|
54
|
+
# triple-dot syntax introduced in Ruby 2.7 as omitting them starts an
|
55
|
+
# endless range.
|
56
|
+
# - Parentheses are required in calls with arguments when inside an
|
57
|
+
# endless method definition introduced in Ruby 3.0.
|
58
|
+
# - Ruby 3.1's hash omission syntax allows parentheses if the method call
|
59
|
+
# is in conditionals and requires parentheses if the call
|
60
|
+
# is not the value-returning expression. See
|
61
|
+
# https://bugs.ruby-lang.org/issues/18396.
|
62
|
+
# - Parentheses are required in anonymous arguments, keyword arguments
|
63
|
+
# and block passing in Ruby 3.2.
|
51
64
|
#
|
52
65
|
# @example EnforcedStyle: require_parentheses (default)
|
53
66
|
#
|
@@ -80,34 +93,28 @@ module RuboCop
|
|
80
93
|
# array.delete e
|
81
94
|
#
|
82
95
|
# # bad
|
83
|
-
#
|
96
|
+
# action.enforce(strict: true)
|
84
97
|
#
|
85
98
|
# # good
|
86
|
-
#
|
99
|
+
# action.enforce strict: true
|
87
100
|
#
|
88
101
|
# # good
|
89
|
-
# #
|
90
|
-
#
|
102
|
+
# # Parentheses are allowed for code that can be ambiguous without
|
103
|
+
# # them.
|
104
|
+
# action.enforce(condition) || other_condition
|
91
105
|
#
|
92
106
|
# # good
|
93
|
-
# #
|
107
|
+
# # Parentheses are allowed for calls that won't produce valid Ruby
|
108
|
+
# # without them.
|
94
109
|
# yield path, File.basename(path)
|
95
110
|
#
|
96
111
|
# # good
|
97
|
-
# #
|
98
|
-
#
|
99
|
-
#
|
100
|
-
#
|
101
|
-
#
|
102
|
-
#
|
103
|
-
#
|
104
|
-
# # good
|
105
|
-
# # Operators methods calls with parens
|
106
|
-
# array&.[](index)
|
107
|
-
#
|
108
|
-
# # good
|
109
|
-
# # Operators methods without parens, if you prefer
|
110
|
-
# array.[] index
|
112
|
+
# # Omitting the parentheses in Ruby 3.1 hash omission syntax can lead
|
113
|
+
# # to ambiguous code. We allow them in conditionals and non-last
|
114
|
+
# # expressions. See https://bugs.ruby-lang.org/issues/18396
|
115
|
+
# if meets(criteria:, action:)
|
116
|
+
# safe_action(action) || dangerous_action(action)
|
117
|
+
# end
|
111
118
|
#
|
112
119
|
# @example IgnoreMacros: true (default)
|
113
120
|
#
|
@@ -226,7 +233,7 @@ module RuboCop
|
|
226
233
|
end
|
227
234
|
|
228
235
|
def args_end(node)
|
229
|
-
node.
|
236
|
+
node.source_range.end
|
230
237
|
end
|
231
238
|
|
232
239
|
def args_parenthesized?(node)
|
@@ -48,13 +48,13 @@ module RuboCop
|
|
48
48
|
when :return
|
49
49
|
argument_range(node)
|
50
50
|
else
|
51
|
-
node.
|
51
|
+
node.source_range
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
55
|
def argument_range(node)
|
56
|
-
first_argument_range = node.children.first.
|
57
|
-
last_argument_range = node.children.last.
|
56
|
+
first_argument_range = node.children.first.source_range
|
57
|
+
last_argument_range = node.children.last.source_range
|
58
58
|
|
59
59
|
first_argument_range.join(last_argument_range)
|
60
60
|
end
|
@@ -51,9 +51,9 @@ module RuboCop
|
|
51
51
|
private
|
52
52
|
|
53
53
|
def range_to_remove_for_subsequent_mixin(mixins, node)
|
54
|
-
range = node.
|
54
|
+
range = node.source_range
|
55
55
|
prev_mixin = mixins.each_cons(2) { |m, n| break m if n == node }
|
56
|
-
between = prev_mixin.
|
56
|
+
between = prev_mixin.source_range.end.join(range.begin)
|
57
57
|
# if separated from previous mixin with only whitespace?
|
58
58
|
unless /\S/.match?(between.source)
|
59
59
|
range = range.join(between) # then remove that too
|
@@ -75,7 +75,7 @@ module RuboCop
|
|
75
75
|
message = format(MSG, mixin: send_node.method_name, suffix: 'a single statement')
|
76
76
|
|
77
77
|
add_offense(send_node, message: message) do |corrector|
|
78
|
-
range = send_node.
|
78
|
+
range = send_node.source_range
|
79
79
|
mixins = sibling_mixins(send_node)
|
80
80
|
if send_node == mixins.first
|
81
81
|
correction = group_mixins(send_node, mixins)
|
@@ -94,7 +94,7 @@ module RuboCop
|
|
94
94
|
message = format(MSG, mixin: send_node.method_name, suffix: 'separate statements')
|
95
95
|
|
96
96
|
add_offense(send_node, message: message) do |corrector|
|
97
|
-
range = send_node.
|
97
|
+
range = send_node.source_range
|
98
98
|
correction = separate_mixins(send_node)
|
99
99
|
|
100
100
|
corrector.replace(range, correction)
|
@@ -28,14 +28,17 @@ module RuboCop
|
|
28
28
|
return unless node.arguments?
|
29
29
|
return if opening_line(node) == closing_line(node)
|
30
30
|
return if correction_exceeds_max_line_length?(node)
|
31
|
+
return unless (begin_of_arguments = node.arguments.loc.begin)
|
31
32
|
|
32
|
-
add_offense(node)
|
33
|
+
add_offense(node) do |corrector|
|
34
|
+
autocorrect(corrector, node, begin_of_arguments)
|
35
|
+
end
|
33
36
|
end
|
34
37
|
alias on_defs on_def
|
35
38
|
|
36
39
|
private
|
37
40
|
|
38
|
-
def autocorrect(corrector, node)
|
41
|
+
def autocorrect(corrector, node, begin_of_arguments)
|
39
42
|
arguments = node.arguments
|
40
43
|
joined_arguments = arguments.map(&:source).join(', ')
|
41
44
|
last_line_source_of_arguments = last_line_source_of_arguments(arguments)
|
@@ -47,7 +50,7 @@ module RuboCop
|
|
47
50
|
end
|
48
51
|
|
49
52
|
corrector.remove(arguments_range(node))
|
50
|
-
corrector.insert_after(
|
53
|
+
corrector.insert_after(begin_of_arguments, joined_arguments)
|
51
54
|
end
|
52
55
|
|
53
56
|
def last_line_source_of_arguments(arguments)
|
@@ -75,7 +78,7 @@ module RuboCop
|
|
75
78
|
end
|
76
79
|
|
77
80
|
def indentation_width(node)
|
78
|
-
processed_source.line_indentation(node.
|
81
|
+
processed_source.line_indentation(node.source_range.line)
|
79
82
|
end
|
80
83
|
|
81
84
|
def definition_width(node)
|
@@ -48,13 +48,11 @@ module RuboCop
|
|
48
48
|
|
49
49
|
def on_if(node)
|
50
50
|
return unless if_else?(node)
|
51
|
-
|
52
|
-
condition = unwrap_begin_nodes(node.condition)
|
53
|
-
|
51
|
+
return unless (condition = unwrap_begin_nodes(node.condition))
|
54
52
|
return if double_negation?(condition) || !negated_condition?(condition)
|
55
53
|
|
56
|
-
|
57
|
-
add_offense(node, message:
|
54
|
+
message = message(node)
|
55
|
+
add_offense(node, message: message) do |corrector|
|
58
56
|
unless corrected_ancestor?(node)
|
59
57
|
correct_negated_condition(corrector, condition)
|
60
58
|
swap_branches(corrector, node)
|
@@ -73,7 +71,8 @@ module RuboCop
|
|
73
71
|
end
|
74
72
|
|
75
73
|
def unwrap_begin_nodes(node)
|
76
|
-
node = node.children.first while node.begin_type? || node.kwbegin_type?
|
74
|
+
node = node.children.first while node && (node.begin_type? || node.kwbegin_type?)
|
75
|
+
|
77
76
|
node
|
78
77
|
end
|
79
78
|
|
@@ -82,6 +81,12 @@ module RuboCop
|
|
82
81
|
(node.negation_method? || NEGATED_EQUALITY_METHODS.include?(node.method_name))
|
83
82
|
end
|
84
83
|
|
84
|
+
def message(node)
|
85
|
+
type = node.ternary? ? 'ternary' : 'if-else'
|
86
|
+
|
87
|
+
format(MSG, type: type)
|
88
|
+
end
|
89
|
+
|
85
90
|
def corrected_ancestor?(node)
|
86
91
|
node.each_ancestor(:if).any? { |ancestor| @corrected_nodes&.include?(ancestor) }
|
87
92
|
end
|
@@ -112,7 +117,7 @@ module RuboCop
|
|
112
117
|
if node.ternary?
|
113
118
|
node.if_branch
|
114
119
|
else
|
115
|
-
range_between(node.condition.
|
120
|
+
range_between(node.condition.source_range.end_pos, node.loc.else.begin_pos)
|
116
121
|
end
|
117
122
|
end
|
118
123
|
|
@@ -57,9 +57,9 @@ module RuboCop
|
|
57
57
|
|
58
58
|
def autocorrect(corrector, node)
|
59
59
|
range = if node.single_line?
|
60
|
-
range_with_surrounding_space(node.body.
|
60
|
+
range_with_surrounding_space(node.body.source_range)
|
61
61
|
else
|
62
|
-
range_by_whole_lines(node.body.
|
62
|
+
range_by_whole_lines(node.body.source_range, include_final_newline: true)
|
63
63
|
end
|
64
64
|
|
65
65
|
corrector.remove(range)
|