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
@@ -31,22 +31,26 @@ module RuboCop
|
|
31
31
|
def on_masgn(node)
|
32
32
|
lhs, rhs = *node
|
33
33
|
lhs_elements = *lhs
|
34
|
+
rhs = rhs.body if rhs.rescue_type?
|
34
35
|
rhs_elements = Array(rhs).compact # edge case for one constant
|
35
36
|
|
36
37
|
return if allowed_lhs?(lhs) || allowed_rhs?(rhs) ||
|
37
38
|
allowed_masign?(lhs_elements, rhs_elements)
|
38
39
|
|
39
|
-
|
40
|
+
range = node.source_range.begin.join(rhs.source_range.end)
|
41
|
+
|
42
|
+
add_offense(range) do |corrector|
|
43
|
+
autocorrect(corrector, node, lhs, rhs)
|
44
|
+
end
|
40
45
|
end
|
41
46
|
|
42
47
|
private
|
43
48
|
|
44
|
-
def autocorrect(corrector, node)
|
45
|
-
|
46
|
-
|
47
|
-
right_elements = Array(right).compact
|
49
|
+
def autocorrect(corrector, node, lhs, rhs)
|
50
|
+
left_elements = *lhs
|
51
|
+
right_elements = Array(rhs).compact
|
48
52
|
order = find_valid_order(left_elements, right_elements)
|
49
|
-
correction = assignment_corrector(node, order)
|
53
|
+
correction = assignment_corrector(node, rhs, order)
|
50
54
|
|
51
55
|
corrector.replace(correction.correction_range, correction.correction)
|
52
56
|
end
|
@@ -77,14 +81,19 @@ module RuboCop
|
|
77
81
|
node.block_type? || node.send_type?
|
78
82
|
end
|
79
83
|
|
80
|
-
def assignment_corrector(node, order)
|
81
|
-
|
84
|
+
def assignment_corrector(node, rhs, order)
|
85
|
+
if node.parent&.rescue_type?
|
86
|
+
_assignment, modifier = *node.parent
|
87
|
+
else
|
88
|
+
_assignment, modifier = *rhs.parent
|
89
|
+
end
|
90
|
+
|
82
91
|
if modifier_statement?(node.parent)
|
83
|
-
ModifierCorrector.new(node, config, order)
|
92
|
+
ModifierCorrector.new(node, rhs, modifier, config, order)
|
84
93
|
elsif rescue_modifier?(modifier)
|
85
|
-
RescueCorrector.new(node, config, order)
|
94
|
+
RescueCorrector.new(node, rhs, modifier, config, order)
|
86
95
|
else
|
87
|
-
GenericCorrector.new(node, config, order)
|
96
|
+
GenericCorrector.new(node, rhs, modifier, config, order)
|
88
97
|
end
|
89
98
|
end
|
90
99
|
|
@@ -181,10 +190,12 @@ module RuboCop
|
|
181
190
|
class GenericCorrector
|
182
191
|
include Alignment
|
183
192
|
|
184
|
-
attr_reader :
|
193
|
+
attr_reader :node, :rhs, :rescue_result, :config
|
185
194
|
|
186
|
-
def initialize(node, config, new_elements)
|
195
|
+
def initialize(node, rhs, modifier, config, new_elements)
|
187
196
|
@node = node
|
197
|
+
@rhs = rhs
|
198
|
+
_, _, @rescue_result = *modifier
|
188
199
|
@config = config
|
189
200
|
@new_elements = new_elements
|
190
201
|
end
|
@@ -228,13 +239,10 @@ module RuboCop
|
|
228
239
|
# protected by rescue
|
229
240
|
class RescueCorrector < GenericCorrector
|
230
241
|
def correction
|
231
|
-
_node, rescue_clause = *node.parent
|
232
|
-
_, _, rescue_result = *rescue_clause
|
233
|
-
|
234
242
|
# If the parallel assignment uses a rescue modifier and it is the
|
235
243
|
# only contents of a method, then we want to make use of the
|
236
244
|
# implicit begin
|
237
|
-
if
|
245
|
+
if rhs.parent.parent.parent&.def_type?
|
238
246
|
super + def_correction(rescue_result)
|
239
247
|
else
|
240
248
|
begin_correction(rescue_result)
|
@@ -242,7 +250,7 @@ module RuboCop
|
|
242
250
|
end
|
243
251
|
|
244
252
|
def correction_range
|
245
|
-
|
253
|
+
rhs.parent.parent.source_range
|
246
254
|
end
|
247
255
|
|
248
256
|
private
|
@@ -92,9 +92,8 @@ module RuboCop
|
|
92
92
|
|
93
93
|
def contains_delimiter?(node, delimiters)
|
94
94
|
delimiters_regexp = Regexp.union(delimiters)
|
95
|
-
|
96
|
-
|
97
|
-
.any? { |s| delimiters_regexp.match?(s) }
|
95
|
+
|
96
|
+
node.children.map { |n| string_source(n) }.compact.any?(delimiters_regexp)
|
98
97
|
end
|
99
98
|
|
100
99
|
def string_source(node)
|
@@ -44,7 +44,7 @@ module RuboCop
|
|
44
44
|
|
45
45
|
# Report offense only if changing case doesn't change semantics,
|
46
46
|
# i.e., if the string would become dynamic or has special characters.
|
47
|
-
ast =
|
47
|
+
ast = parse(corrected(node.source)).ast
|
48
48
|
return if node.children != ast.children
|
49
49
|
|
50
50
|
add_offense(node.loc.begin) do |corrector|
|
@@ -70,8 +70,8 @@ module RuboCop
|
|
70
70
|
end
|
71
71
|
|
72
72
|
def range_of_offense(node)
|
73
|
-
return node.
|
74
|
-
return node.
|
73
|
+
return node.source_range unless node.ternary?
|
74
|
+
return node.source_range if node.ternary? && branches_have_method?(node)
|
75
75
|
|
76
76
|
range_between(node.loc.question.begin_pos, node.loc.colon.end_pos)
|
77
77
|
end
|
@@ -33,11 +33,11 @@ module RuboCop
|
|
33
33
|
private
|
34
34
|
|
35
35
|
def opening_brace(node)
|
36
|
-
node.loc.begin.join(node.children.first.
|
36
|
+
node.loc.begin.join(node.children.first.source_range.begin)
|
37
37
|
end
|
38
38
|
|
39
39
|
def closing_brace(node)
|
40
|
-
node.children.last.
|
40
|
+
node.children.last.source_range.end.join(node.loc.end)
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
@@ -97,7 +97,7 @@ module RuboCop
|
|
97
97
|
end
|
98
98
|
|
99
99
|
def autocorrect_variable_interpolation(corrector, embedded_node, node)
|
100
|
-
replacement = "#{embedded_node.
|
100
|
+
replacement = "#{embedded_node.source}.to_s"
|
101
101
|
|
102
102
|
corrector.replace(node, replacement)
|
103
103
|
end
|
@@ -107,7 +107,7 @@ module RuboCop
|
|
107
107
|
|
108
108
|
source = if require_parentheses?(embedded_var)
|
109
109
|
receiver = range_between(
|
110
|
-
embedded_var.
|
110
|
+
embedded_var.source_range.begin_pos, embedded_var.loc.selector.end_pos
|
111
111
|
)
|
112
112
|
arguments = embedded_var.arguments.map(&:source).join(', ')
|
113
113
|
|
@@ -0,0 +1,179 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Check for redundant line continuation.
|
7
|
+
#
|
8
|
+
# This cop marks a line continuation as redundant if removing the backslash
|
9
|
+
# does not result in a syntax error.
|
10
|
+
# However, a backslash at the end of a comment or
|
11
|
+
# for string concatenation is not redundant and is not considered an offense.
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
# # bad
|
15
|
+
# foo. \
|
16
|
+
# bar
|
17
|
+
# foo \
|
18
|
+
# &.bar \
|
19
|
+
# .baz
|
20
|
+
#
|
21
|
+
# # good
|
22
|
+
# foo.
|
23
|
+
# bar
|
24
|
+
# foo
|
25
|
+
# &.bar
|
26
|
+
# .baz
|
27
|
+
#
|
28
|
+
# # bad
|
29
|
+
# [foo, \
|
30
|
+
# bar]
|
31
|
+
# {foo: \
|
32
|
+
# bar}
|
33
|
+
#
|
34
|
+
# # good
|
35
|
+
# [foo,
|
36
|
+
# bar]
|
37
|
+
# {foo:
|
38
|
+
# bar}
|
39
|
+
#
|
40
|
+
# # bad
|
41
|
+
# foo(bar, \
|
42
|
+
# baz)
|
43
|
+
#
|
44
|
+
# # good
|
45
|
+
# foo(bar,
|
46
|
+
# baz)
|
47
|
+
#
|
48
|
+
# # also good - backslash in string concatenation is not redundant
|
49
|
+
# foo('bar' \
|
50
|
+
# 'baz')
|
51
|
+
#
|
52
|
+
# # also good - backslash at the end of a comment is not redundant
|
53
|
+
# foo(bar, # \
|
54
|
+
# baz)
|
55
|
+
#
|
56
|
+
# # also good - backslash at the line following the newline begins with a + or -,
|
57
|
+
# # it is not redundant
|
58
|
+
# 1 \
|
59
|
+
# + 2 \
|
60
|
+
# - 3
|
61
|
+
#
|
62
|
+
# # also good - backslash with newline between the method name and its arguments,
|
63
|
+
# # it is not redundant.
|
64
|
+
# some_method \
|
65
|
+
# (argument)
|
66
|
+
#
|
67
|
+
class RedundantLineContinuation < Base
|
68
|
+
include MatchRange
|
69
|
+
extend AutoCorrector
|
70
|
+
|
71
|
+
MSG = 'Redundant line continuation.'
|
72
|
+
ALLOWED_STRING_TOKENS = %i[tSTRING tSTRING_CONTENT].freeze
|
73
|
+
|
74
|
+
def on_new_investigation
|
75
|
+
return unless processed_source.ast
|
76
|
+
|
77
|
+
each_match_range(processed_source.ast.source_range, /(\\\n)/) do |range|
|
78
|
+
next if require_line_continuation?(range)
|
79
|
+
next unless redundant_line_continuation?(range)
|
80
|
+
|
81
|
+
add_offense(range) do |corrector|
|
82
|
+
corrector.remove_leading(range, 1)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def require_line_continuation?(range)
|
90
|
+
!ends_with_backslash_without_comment?(range.source_line) ||
|
91
|
+
string_concatenation?(range.source_line) ||
|
92
|
+
start_with_arithmetic_operator?(processed_source[range.line]) ||
|
93
|
+
inside_string_literal_or_method_with_argument?(range)
|
94
|
+
end
|
95
|
+
|
96
|
+
def ends_with_backslash_without_comment?(source_line)
|
97
|
+
source_line.gsub(/#.+/, '').end_with?('\\')
|
98
|
+
end
|
99
|
+
|
100
|
+
def string_concatenation?(source_line)
|
101
|
+
/["']\s*\\\z/.match?(source_line)
|
102
|
+
end
|
103
|
+
|
104
|
+
def inside_string_literal_or_method_with_argument?(range)
|
105
|
+
processed_source.tokens.each_cons(2).any? do |token, next_token|
|
106
|
+
inside_string_literal?(range, token) || method_with_argument?(token, next_token)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def redundant_line_continuation?(range)
|
111
|
+
return true unless (node = find_node_for_line(range.line))
|
112
|
+
return false if argument_newline?(node)
|
113
|
+
|
114
|
+
source = node.parent ? node.parent.source : node.source
|
115
|
+
parse(source.gsub(/\\\n/, "\n")).valid_syntax?
|
116
|
+
end
|
117
|
+
|
118
|
+
def inside_string_literal?(range, token)
|
119
|
+
ALLOWED_STRING_TOKENS.include?(token.type) && token.pos.overlaps?(range)
|
120
|
+
end
|
121
|
+
|
122
|
+
# A method call without parentheses such as the following cannot remove `\`:
|
123
|
+
#
|
124
|
+
# do_something \
|
125
|
+
# argument
|
126
|
+
def method_with_argument?(current_token, next_token)
|
127
|
+
current_token.type == :tIDENTIFIER && next_token.type == :tIDENTIFIER
|
128
|
+
end
|
129
|
+
|
130
|
+
def argument_newline?(node)
|
131
|
+
node = node.children.first if node.root? && node.begin_type?
|
132
|
+
|
133
|
+
if argument_is_method?(node)
|
134
|
+
argument_newline?(node.first_argument)
|
135
|
+
else
|
136
|
+
return false unless method_call_with_arguments?(node)
|
137
|
+
|
138
|
+
node.loc.selector.line != node.first_argument.loc.line
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def find_node_for_line(line)
|
143
|
+
processed_source.ast.each_node do |node|
|
144
|
+
return node if same_line?(node, line)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def same_line?(node, line)
|
149
|
+
return unless (source_range = node.source_range)
|
150
|
+
|
151
|
+
if node.is_a?(AST::StrNode)
|
152
|
+
if node.heredoc?
|
153
|
+
(node.loc.heredoc_body.line..node.loc.heredoc_body.last_line).cover?(line)
|
154
|
+
else
|
155
|
+
(source_range.line..source_range.last_line).cover?(line)
|
156
|
+
end
|
157
|
+
else
|
158
|
+
source_range.line == line
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def argument_is_method?(node)
|
163
|
+
return false unless node.send_type?
|
164
|
+
return false unless (first_argument = node.first_argument)
|
165
|
+
|
166
|
+
method_call_with_arguments?(first_argument)
|
167
|
+
end
|
168
|
+
|
169
|
+
def method_call_with_arguments?(node)
|
170
|
+
node.call_type? && !node.arguments.empty?
|
171
|
+
end
|
172
|
+
|
173
|
+
def start_with_arithmetic_operator?(source_line)
|
174
|
+
%r{\A\s*[+\-*/%]}.match?(source_line)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
@@ -98,7 +98,7 @@ module RuboCop
|
|
98
98
|
end
|
99
99
|
|
100
100
|
def like_method_argument_parentheses?(node)
|
101
|
-
node.send_type? && node.arguments.one? &&
|
101
|
+
node.send_type? && node.arguments.one? && !node.parenthesized? &&
|
102
102
|
!node.arithmetic_operation? && node.first_argument.begin_type?
|
103
103
|
end
|
104
104
|
|
@@ -153,7 +153,7 @@ module RuboCop
|
|
153
153
|
|
154
154
|
return if node.send_type? && !method_call_with_redundant_parentheses?(node)
|
155
155
|
|
156
|
-
offense(begin_node, '
|
156
|
+
offense(begin_node, 'a unary operation')
|
157
157
|
end
|
158
158
|
|
159
159
|
def offense(node, msg)
|
@@ -63,7 +63,7 @@ module RuboCop
|
|
63
63
|
next if expr.type != :set || expr.expressions.size != 1
|
64
64
|
next if expr.negative?
|
65
65
|
next if %i[set posixclass nonposixclass].include?(expr.expressions.first.type)
|
66
|
-
next if
|
66
|
+
next if multiple_codepoints?(expr.expressions.first)
|
67
67
|
|
68
68
|
yield expr
|
69
69
|
end
|
@@ -74,13 +74,13 @@ module RuboCop
|
|
74
74
|
|
75
75
|
non_redundant =
|
76
76
|
whitespace_in_free_space_mode?(node, class_elem) ||
|
77
|
-
backslash_b?(class_elem) ||
|
77
|
+
backslash_b?(class_elem) || octal_requiring_char_class?(class_elem) ||
|
78
78
|
requires_escape_outside_char_class?(class_elem)
|
79
79
|
|
80
80
|
!non_redundant
|
81
81
|
end
|
82
82
|
|
83
|
-
def
|
83
|
+
def multiple_codepoints?(expression)
|
84
84
|
expression.respond_to?(:codepoints) && expression.codepoints.count >= 2
|
85
85
|
end
|
86
86
|
|
@@ -104,11 +104,10 @@ module RuboCop
|
|
104
104
|
elem == '\b'
|
105
105
|
end
|
106
106
|
|
107
|
-
def
|
108
|
-
#
|
109
|
-
#
|
110
|
-
|
111
|
-
elem == '\0'
|
107
|
+
def octal_requiring_char_class?(elem)
|
108
|
+
# The octal escapes \1 to \7 only work inside a character class
|
109
|
+
# because they would be a backreference outside it.
|
110
|
+
elem.match?(/\A\\[1-7]\z/)
|
112
111
|
end
|
113
112
|
|
114
113
|
def requires_escape_outside_char_class?(elem)
|
@@ -74,11 +74,18 @@ module RuboCop
|
|
74
74
|
|
75
75
|
def char_class_begins_or_ends_with_escaped_hyphen?(node, index)
|
76
76
|
# The hyphen character is allowed to be escaped within a character class
|
77
|
-
# but it's not
|
77
|
+
# but it's not necessary to escape hyphen if it's the first or last character
|
78
78
|
# within the character class. This method checks if that's the case.
|
79
79
|
# e.g. "[0-9\\-]" or "[\\-0-9]" would return true
|
80
|
-
contents_range(node).source
|
81
|
-
|
80
|
+
content = contents_range(node).source
|
81
|
+
|
82
|
+
if content[index + 2] == ']'
|
83
|
+
true
|
84
|
+
elsif content[index - 1] == '['
|
85
|
+
index < 2 || content[index - 2] != '\\'
|
86
|
+
else
|
87
|
+
false
|
88
|
+
end
|
82
89
|
end
|
83
90
|
|
84
91
|
def delimiter?(node, char)
|
@@ -100,7 +107,7 @@ module RuboCop
|
|
100
107
|
end
|
101
108
|
end
|
102
109
|
# Please remove this `else` branch when support for regexp_parser 1.8 will be dropped.
|
103
|
-
# It's for compatibility with
|
110
|
+
# It's for compatibility with regexp_parser 1.8 and will never be maintained.
|
104
111
|
else
|
105
112
|
def each_escape(node)
|
106
113
|
node.parsed_tree&.traverse&.reduce(0) do |char_class_depth, (event, expr)|
|
@@ -129,13 +129,13 @@ module RuboCop
|
|
129
129
|
end
|
130
130
|
|
131
131
|
def offense_range(sort_node, node)
|
132
|
-
range_between(sort_node.loc.selector.begin_pos, node.
|
132
|
+
range_between(sort_node.loc.selector.begin_pos, node.source_range.end_pos)
|
133
133
|
end
|
134
134
|
|
135
135
|
def message(node, sorter, accessor)
|
136
136
|
accessor_source = range_between(
|
137
137
|
node.loc.selector.begin_pos,
|
138
|
-
node.
|
138
|
+
node.source_range.end_pos
|
139
139
|
).source
|
140
140
|
|
141
141
|
format(MSG,
|
@@ -146,7 +146,7 @@ module RuboCop
|
|
146
146
|
|
147
147
|
def autocorrect(corrector, node, sort_node, sorter, accessor)
|
148
148
|
# Remove accessor, e.g. `first` or `[-1]`.
|
149
|
-
corrector.remove(range_between(accessor_start(node), node.
|
149
|
+
corrector.remove(range_between(accessor_start(node), node.source_range.end_pos))
|
150
150
|
# Replace "sort" or "sort_by" with the appropriate min/max method.
|
151
151
|
corrector.replace(sort_node.loc.selector, suggestion(sorter, accessor, arg_value(node)))
|
152
152
|
# Replace to avoid syntax errors when followed by a logical operator.
|
@@ -36,7 +36,6 @@ module RuboCop
|
|
36
36
|
# STR
|
37
37
|
class RedundantStringEscape < Base
|
38
38
|
include MatchRange
|
39
|
-
include RangeHelp
|
40
39
|
extend AutoCorrector
|
41
40
|
|
42
41
|
MSG = 'Redundant escape of %<char>s inside string literal.'
|
@@ -64,10 +63,10 @@ module RuboCop
|
|
64
63
|
def str_contents_range(node)
|
65
64
|
if heredoc?(node)
|
66
65
|
node.loc.heredoc_body
|
66
|
+
elsif node.str_type?
|
67
|
+
node.source_range
|
67
68
|
elsif begin_loc_present?(node)
|
68
69
|
contents_range(node)
|
69
|
-
else
|
70
|
-
node.loc.expression
|
71
70
|
end
|
72
71
|
end
|
73
72
|
|
@@ -139,7 +138,7 @@ module RuboCop
|
|
139
138
|
|
140
139
|
def heredoc_with_disabled_interpolation?(node)
|
141
140
|
if heredoc?(node)
|
142
|
-
node.
|
141
|
+
node.source.end_with?("'")
|
143
142
|
elsif node.parent&.dstr_type?
|
144
143
|
heredoc_with_disabled_interpolation?(node.parent)
|
145
144
|
else
|
@@ -125,9 +125,7 @@ module RuboCop
|
|
125
125
|
end
|
126
126
|
|
127
127
|
def in_same_section?(node1, node2)
|
128
|
-
!node1.
|
129
|
-
end_pos: node2.location.expression.end_pos
|
130
|
-
).source.include?("\n\n")
|
128
|
+
!node1.source_range.with(end_pos: node2.source_range.end_pos).source.include?("\n\n")
|
131
129
|
end
|
132
130
|
end
|
133
131
|
end
|
@@ -105,11 +105,11 @@ module RuboCop
|
|
105
105
|
private
|
106
106
|
|
107
107
|
def offense_for_implicit_enforced_style(node, error)
|
108
|
-
range = node.loc.keyword.join(error.
|
108
|
+
range = node.loc.keyword.join(error.source_range)
|
109
109
|
|
110
110
|
add_offense(range, message: MSG_IMPLICIT) do |corrector|
|
111
111
|
error = rescue_standard_error?(node)
|
112
|
-
range = range_between(node.loc.keyword.end_pos, error.
|
112
|
+
range = range_between(node.loc.keyword.end_pos, error.source_range.end_pos)
|
113
113
|
|
114
114
|
corrector.remove(range)
|
115
115
|
end
|
@@ -297,11 +297,11 @@ module RuboCop
|
|
297
297
|
end
|
298
298
|
|
299
299
|
def begin_range(node, method_call)
|
300
|
-
range_between(node.
|
300
|
+
range_between(node.source_range.begin_pos, method_call.source_range.begin_pos)
|
301
301
|
end
|
302
302
|
|
303
303
|
def end_range(node, method_call)
|
304
|
-
range_between(method_call.
|
304
|
+
range_between(method_call.source_range.end_pos, node.source_range.end_pos)
|
305
305
|
end
|
306
306
|
|
307
307
|
def add_safe_nav_to_all_methods_in_chain(corrector,
|
@@ -8,7 +8,7 @@ module RuboCop
|
|
8
8
|
#
|
9
9
|
# @safety
|
10
10
|
# This cop is unsafe because `x..-1` and `x..` are only guaranteed to
|
11
|
-
# be equivalent for `Array#[]`, and the cop cannot determine what class
|
11
|
+
# be equivalent for `Array#[]`, `String#[]`, and the cop cannot determine what class
|
12
12
|
# the receiver is.
|
13
13
|
#
|
14
14
|
# For example:
|
@@ -167,7 +167,7 @@ module RuboCop
|
|
167
167
|
corrector.insert_before(condition,
|
168
168
|
"#{'!' if node.unless?}#{replace_condition(node.condition)} && ")
|
169
169
|
|
170
|
-
corrector.remove(node.condition
|
170
|
+
corrector.remove(node.condition)
|
171
171
|
corrector.remove(range_with_surrounding_space(node.loc.keyword, newlines: false))
|
172
172
|
corrector.replace(if_branch.loc.keyword, 'if')
|
173
173
|
end
|
@@ -187,7 +187,7 @@ module RuboCop
|
|
187
187
|
return if end_pos > begin_pos
|
188
188
|
|
189
189
|
corrector.replace(range_between(end_pos, begin_pos), '(')
|
190
|
-
corrector.insert_after(condition.last_argument
|
190
|
+
corrector.insert_after(condition.last_argument, ')')
|
191
191
|
end
|
192
192
|
|
193
193
|
def insert_bang(corrector, node, is_modify_form)
|
@@ -240,7 +240,7 @@ module RuboCop
|
|
240
240
|
end
|
241
241
|
|
242
242
|
def outer_condition_modify_form?(node, if_branch)
|
243
|
-
node.condition.
|
243
|
+
node.condition.source_range.begin_pos > if_branch.condition.source_range.begin_pos
|
244
244
|
end
|
245
245
|
end
|
246
246
|
end
|
@@ -144,7 +144,7 @@ module RuboCop
|
|
144
144
|
end
|
145
145
|
|
146
146
|
def range_for_parentheses(offense, left)
|
147
|
-
range_between(offense.source_range.begin_pos - 1, left.
|
147
|
+
range_between(offense.source_range.begin_pos - 1, left.source_range.end_pos - 1)
|
148
148
|
end
|
149
149
|
end
|
150
150
|
end
|
@@ -52,9 +52,9 @@ module RuboCop
|
|
52
52
|
private
|
53
53
|
|
54
54
|
def first_element_range(node, unpack_call)
|
55
|
-
Parser::Source::Range.new(node.
|
56
|
-
unpack_call.
|
57
|
-
node.
|
55
|
+
Parser::Source::Range.new(node.source_range.source_buffer,
|
56
|
+
unpack_call.source_range.end_pos,
|
57
|
+
node.source_range.end_pos)
|
58
58
|
end
|
59
59
|
end
|
60
60
|
end
|