rubocop 1.91.0 → 1.92.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/config/default.yml +3 -1
- data/lib/rubocop/cached_data.rb +47 -7
- data/lib/rubocop/changed_files.rb +35 -13
- data/lib/rubocop/cli/command/cop_names.rb +57 -0
- data/lib/rubocop/cli/command/execute_runner.rb +2 -2
- data/lib/rubocop/cli/command/explain.rb +34 -0
- data/lib/rubocop/cli/command/show_cops.rb +6 -0
- data/lib/rubocop/cli/command/show_docs_url.rb +6 -4
- data/lib/rubocop/cli.rb +3 -2
- data/lib/rubocop/comment_config.rb +17 -8
- data/lib/rubocop/config_loader.rb +6 -3
- data/lib/rubocop/config_loader_resolver.rb +37 -12
- data/lib/rubocop/config_obsoletion/removed_cop.rb +1 -1
- data/lib/rubocop/config_validator.rb +11 -0
- data/lib/rubocop/cop/autocorrect_logic.rb +10 -5
- data/lib/rubocop/cop/base.rb +42 -21
- data/lib/rubocop/cop/bundler/gem_comment.rb +0 -1
- data/lib/rubocop/cop/bundler/ordered_gems.rb +0 -8
- data/lib/rubocop/cop/cop_documentation.rb +81 -0
- data/lib/rubocop/cop/cop_explanation.rb +140 -0
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +13 -1
- data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +22 -7
- data/lib/rubocop/cop/correctors/empty_line_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +23 -2
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +45 -8
- data/lib/rubocop/cop/documentation.rb +1 -1
- data/lib/rubocop/cop/gemspec/dependency_version.rb +0 -6
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +0 -6
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +2 -5
- data/lib/rubocop/cop/internal_affairs/node_type_group.rb +0 -7
- data/lib/rubocop/cop/internal_affairs/redundant_context_config_parameter.rb +1 -7
- data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +1 -7
- data/lib/rubocop/cop/layout/block_alignment.rb +27 -0
- data/lib/rubocop/cop/layout/case_indentation.rb +25 -9
- data/lib/rubocop/cop/layout/class_structure.rb +9 -1
- data/lib/rubocop/cop/layout/def_end_alignment.rb +4 -0
- data/lib/rubocop/cop/layout/empty_line_after_multiline_condition.rb +14 -5
- data/lib/rubocop/cop/layout/empty_lines.rb +5 -2
- data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -0
- data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +23 -1
- data/lib/rubocop/cop/layout/end_alignment.rb +16 -10
- data/lib/rubocop/cop/layout/extra_spacing.rb +4 -0
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -0
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +5 -3
- data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +6 -0
- data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +4 -0
- data/lib/rubocop/cop/layout/hash_alignment.rb +16 -12
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -0
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +15 -0
- data/lib/rubocop/cop/layout/indentation_style.rb +4 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +2 -2
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +8 -1
- data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +25 -9
- data/lib/rubocop/cop/layout/line_length.rb +52 -18
- data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +12 -0
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +8 -1
- data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +7 -0
- data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +6 -0
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +14 -0
- data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +4 -0
- data/lib/rubocop/cop/layout/redundant_line_break.rb +22 -1
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +15 -2
- data/lib/rubocop/cop/layout/single_line_block_chain.rb +10 -2
- data/lib/rubocop/cop/layout/space_after_not.rb +5 -0
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +6 -11
- data/lib/rubocop/cop/layout/space_around_keyword.rb +10 -0
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +4 -1
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +15 -2
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +31 -8
- data/lib/rubocop/cop/lint/ambiguous_operator.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +2 -1
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +3 -1
- data/lib/rubocop/cop/lint/literal_as_condition.rb +15 -0
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +63 -19
- data/lib/rubocop/cop/lint/loop.rb +24 -2
- data/lib/rubocop/cop/lint/misplaced_magic_comment.rb +71 -11
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +18 -3
- data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +12 -1
- data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +13 -2
- data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +18 -1
- data/lib/rubocop/cop/lint/useless_assignment.rb +14 -7
- data/lib/rubocop/cop/lint/void.rb +8 -1
- data/lib/rubocop/cop/metrics/class_length.rb +4 -2
- data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +0 -4
- data/lib/rubocop/cop/metrics/module_length.rb +4 -2
- data/lib/rubocop/cop/mixin/alignment.rb +4 -0
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +17 -14
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +5 -1
- data/lib/rubocop/cop/mixin/code_length.rb +10 -2
- data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +12 -1
- data/lib/rubocop/cop/mixin/endless_method_body_help.rb +69 -0
- data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +2 -2
- data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +15 -1
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +26 -2
- data/lib/rubocop/cop/mixin/min_branches_count.rb +3 -1
- data/lib/rubocop/cop/mixin/multiline_element_line_breaks.rb +11 -1
- data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +9 -0
- data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
- data/lib/rubocop/cop/mixin/pattern_matching_help.rb +35 -0
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +17 -2
- data/lib/rubocop/cop/mixin/project_index_help.rb +15 -0
- data/lib/rubocop/cop/mixin/reparsed_equivalence.rb +13 -3
- data/lib/rubocop/cop/mixin/statement_modifier.rb +22 -2
- data/lib/rubocop/cop/mixin.rb +2 -0
- data/lib/rubocop/cop/naming/accessor_method_name.rb +0 -16
- data/lib/rubocop/cop/naming/block_forwarding.rb +1 -1
- data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +9 -2
- data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +5 -3
- data/lib/rubocop/cop/naming/predicate_prefix.rb +7 -22
- data/lib/rubocop/cop/offense.rb +59 -3
- data/lib/rubocop/cop/registry.rb +1 -1
- data/lib/rubocop/cop/security/json_load.rb +16 -4
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +7 -0
- data/lib/rubocop/cop/style/alias.rb +18 -5
- data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +4 -3
- data/lib/rubocop/cop/style/and_or.rb +4 -0
- data/lib/rubocop/cop/style/arguments_forwarding.rb +4 -1
- data/lib/rubocop/cop/style/attr.rb +3 -4
- data/lib/rubocop/cop/style/bitwise_predicate.rb +6 -4
- data/lib/rubocop/cop/style/block_delimiters.rb +29 -3
- data/lib/rubocop/cop/style/case_like_if.rb +6 -3
- data/lib/rubocop/cop/style/class_and_module_children.rb +54 -16
- data/lib/rubocop/cop/style/class_methods_definitions.rb +8 -0
- data/lib/rubocop/cop/style/combinable_loops.rb +85 -11
- data/lib/rubocop/cop/style/concat_array_literals.rb +46 -7
- data/lib/rubocop/cop/style/conditional_assignment.rb +4 -0
- data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +65 -9
- data/lib/rubocop/cop/style/double_negation.rb +11 -0
- data/lib/rubocop/cop/style/empty_literal.rb +1 -1
- data/lib/rubocop/cop/style/empty_method.rb +3 -1
- data/lib/rubocop/cop/style/endless_method.rb +67 -6
- data/lib/rubocop/cop/style/exact_regexp_match.rb +45 -8
- data/lib/rubocop/cop/style/explicit_block_argument.rb +50 -10
- data/lib/rubocop/cop/style/float_division.rb +22 -2
- data/lib/rubocop/cop/style/for.rb +40 -2
- data/lib/rubocop/cop/style/format_string.rb +28 -6
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +2 -1
- data/lib/rubocop/cop/style/guard_clause.rb +9 -1
- data/lib/rubocop/cop/style/hash_conversion.rb +28 -8
- data/lib/rubocop/cop/style/hash_lookup_method.rb +32 -9
- data/lib/rubocop/cop/style/hash_syntax.rb +16 -3
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +22 -3
- data/lib/rubocop/cop/style/if_inside_else.rb +21 -1
- data/lib/rubocop/cop/style/if_unless_modifier.rb +19 -20
- data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +4 -0
- data/lib/rubocop/cop/style/if_with_semicolon.rb +47 -4
- data/lib/rubocop/cop/style/inverse_methods.rb +24 -2
- data/lib/rubocop/cop/style/it_block_parameter.rb +32 -3
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +3 -1
- data/lib/rubocop/cop/style/lambda.rb +18 -0
- data/lib/rubocop/cop/style/lambda_call.rb +7 -2
- data/lib/rubocop/cop/style/map_into_array.rb +1 -2
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +45 -10
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +25 -2
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +26 -3
- data/lib/rubocop/cop/style/method_def_parentheses.rb +29 -3
- data/lib/rubocop/cop/style/missing_else.rb +7 -1
- data/lib/rubocop/cop/style/multiline_if_modifier.rb +45 -5
- data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +7 -0
- data/lib/rubocop/cop/style/multiline_method_signature.rb +2 -5
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +7 -3
- data/lib/rubocop/cop/style/multiline_when_then.rb +7 -0
- data/lib/rubocop/cop/style/mutable_constant.rb +28 -1
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +2 -1
- data/lib/rubocop/cop/style/negative_array_index.rb +9 -1
- data/lib/rubocop/cop/style/nested_modifier.rb +27 -8
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +26 -8
- data/lib/rubocop/cop/style/next.rb +24 -10
- data/lib/rubocop/cop/style/nil_comparison.rb +16 -4
- data/lib/rubocop/cop/style/non_nil_check.rb +1 -1
- data/lib/rubocop/cop/style/not.rb +10 -5
- data/lib/rubocop/cop/style/numeric_predicate.rb +21 -5
- data/lib/rubocop/cop/style/one_line_conditional.rb +13 -2
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +14 -3
- data/lib/rubocop/cop/style/reduce_to_hash.rb +17 -1
- data/lib/rubocop/cop/style/redundant_begin.rb +20 -3
- data/lib/rubocop/cop/style/redundant_condition.rb +30 -13
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +6 -0
- data/lib/rubocop/cop/style/redundant_exception.rb +15 -3
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +9 -1
- data/lib/rubocop/cop/style/redundant_freeze.rb +10 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +12 -1
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +7 -0
- data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +20 -0
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +4 -0
- data/lib/rubocop/cop/style/regexp_literal.rb +75 -26
- data/lib/rubocop/cop/style/require_order.rb +9 -0
- data/lib/rubocop/cop/style/rescue_modifier.rb +5 -9
- data/lib/rubocop/cop/style/return_nil.rb +17 -2
- data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +11 -1
- data/lib/rubocop/cop/style/sample.rb +9 -8
- data/lib/rubocop/cop/style/self_assignment.rb +12 -15
- data/lib/rubocop/cop/style/semicolon.rb +16 -5
- data/lib/rubocop/cop/style/single_line_methods.rb +16 -4
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +29 -5
- data/lib/rubocop/cop/style/string_concatenation.rb +9 -3
- data/lib/rubocop/cop/style/super_arguments.rb +3 -0
- data/lib/rubocop/cop/style/symbol_proc.rb +23 -5
- data/lib/rubocop/cop/style/ternary_parentheses.rb +23 -1
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +23 -19
- data/lib/rubocop/cop/style/while_until_modifier.rb +1 -1
- data/lib/rubocop/cop/style/yoda_condition.rb +24 -9
- data/lib/rubocop/cop/style/yoda_expression.rb +10 -1
- data/lib/rubocop/cop/team.rb +10 -5
- data/lib/rubocop/cop/variable_force/assignment.rb +1 -1
- data/lib/rubocop/cop/variable_force/variable.rb +14 -1
- data/lib/rubocop/formatter/base_formatter.rb +22 -0
- data/lib/rubocop/formatter/formatter_set.rb +4 -0
- data/lib/rubocop/formatter/json_formatter.rb +71 -1
- data/lib/rubocop/formatter/offense_count_formatter.rb +3 -1
- data/lib/rubocop/formatter/pacman_formatter.rb +3 -1
- data/lib/rubocop/formatter/sarif_formatter.rb +12 -7
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +3 -1
- data/lib/rubocop/lsp/runtime.rb +47 -11
- data/lib/rubocop/lsp/stdin_runner.rb +11 -5
- data/lib/rubocop/lsp.rb +5 -2
- data/lib/rubocop/mcp/autocorrection_request.rb +52 -0
- data/lib/rubocop/mcp/explain_tool.rb +68 -0
- data/lib/rubocop/mcp/scope.rb +65 -0
- data/lib/rubocop/mcp/server.rb +184 -76
- data/lib/rubocop/mcp/source_files.rb +35 -0
- data/lib/rubocop/offense_limit.rb +30 -0
- data/lib/rubocop/options.rb +45 -10
- data/lib/rubocop/plugin/configuration_integrator.rb +12 -5
- data/lib/rubocop/remote_config.rb +4 -1
- data/lib/rubocop/result_cache.rb +20 -13
- data/lib/rubocop/runner.rb +109 -41
- data/lib/rubocop/server/cache.rb +2 -2
- data/lib/rubocop/util.rb +69 -0
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +5 -0
- metadata +16 -5
|
@@ -98,6 +98,8 @@ module RuboCop
|
|
|
98
98
|
end
|
|
99
99
|
elsif node.condition.falsey_literal?
|
|
100
100
|
add_offense(node.condition) do |corrector|
|
|
101
|
+
next if orphans_loop_control_keyword?(node)
|
|
102
|
+
|
|
101
103
|
corrector.replace(node, node.body.child_nodes.map(&:source).join("\n"))
|
|
102
104
|
end
|
|
103
105
|
end
|
|
@@ -127,6 +129,8 @@ module RuboCop
|
|
|
127
129
|
end
|
|
128
130
|
elsif node.condition.truthy_literal?
|
|
129
131
|
add_offense(node.condition) do |corrector|
|
|
132
|
+
next if orphans_loop_control_keyword?(node)
|
|
133
|
+
|
|
130
134
|
corrector.replace(node, node.body.child_nodes.map(&:source).join("\n"))
|
|
131
135
|
end
|
|
132
136
|
end
|
|
@@ -175,6 +179,15 @@ module RuboCop
|
|
|
175
179
|
|
|
176
180
|
private
|
|
177
181
|
|
|
182
|
+
# Unwrapping the body of a loop that runs once would leave a `break`,
|
|
183
|
+
# `next` or `redo` that belongs to it outside of any loop.
|
|
184
|
+
def orphans_loop_control_keyword?(node)
|
|
185
|
+
node.body.each_node(:next, :break, :redo).any? do |control|
|
|
186
|
+
inner = control.each_ancestor.take_while { |ancestor| !ancestor.equal?(node) }
|
|
187
|
+
inner.none? { |ancestor| ancestor.any_block_type? || ancestor.loop_keyword? }
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
178
191
|
def void_value_expression?(node)
|
|
179
192
|
node = node.children.last while node&.begin_type?
|
|
180
193
|
|
|
@@ -273,6 +286,8 @@ module RuboCop
|
|
|
273
286
|
"#{node.else_branch.source.sub('elsif', 'if')}\nend"
|
|
274
287
|
elsif node.else? || node.ternary?
|
|
275
288
|
node.else_branch.source
|
|
289
|
+
elsif node.value_used?
|
|
290
|
+
'nil'
|
|
276
291
|
else
|
|
277
292
|
'' # Equivalent to removing the node
|
|
278
293
|
end
|
|
@@ -24,30 +24,16 @@ module RuboCop
|
|
|
24
24
|
MSG = 'Literal interpolation detected.'
|
|
25
25
|
COMPOSITE = %i[array hash pair irange erange].freeze
|
|
26
26
|
|
|
27
|
-
# rubocop:disable-next Metrics/AbcSize
|
|
28
27
|
def on_interpolation(begin_node)
|
|
29
28
|
final_node = begin_node.children.last
|
|
30
29
|
return unless offending?(final_node)
|
|
31
|
-
|
|
32
|
-
# %W and %I split the content into words before expansion
|
|
33
|
-
# treating each interpolation as a word component, so
|
|
34
|
-
# interpolation should not be removed if the expanded value
|
|
35
|
-
# contains a space character.
|
|
36
|
-
expanded_value = autocorrected_value(final_node)
|
|
37
|
-
expanded_value = handle_special_regexp_chars(begin_node, expanded_value)
|
|
38
|
-
|
|
39
|
-
return if in_array_percent_literal?(begin_node) && /\s|\A\z/.match?(expanded_value)
|
|
30
|
+
return unless (expanded_value = correctable_value(begin_node, final_node))
|
|
40
31
|
|
|
41
32
|
add_offense(final_node) do |corrector|
|
|
42
33
|
next if final_node.dstr_type? # nested, fixed in next iteration
|
|
34
|
+
next if follows_literal_interpolation?(begin_node)
|
|
43
35
|
|
|
44
|
-
|
|
45
|
-
final_node.source.delete_prefix('"').delete_suffix('"')
|
|
46
|
-
else
|
|
47
|
-
expanded_value
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
corrector.replace(final_node.parent, replacement)
|
|
36
|
+
corrector.replace(final_node.parent, replacement(final_node, expanded_value))
|
|
51
37
|
end
|
|
52
38
|
end
|
|
53
39
|
|
|
@@ -73,6 +59,22 @@ module RuboCop
|
|
|
73
59
|
node.array_type? && grandparent.regexp_type?
|
|
74
60
|
end
|
|
75
61
|
|
|
62
|
+
def correctable_value(begin_node, final_node)
|
|
63
|
+
value = autocorrected_value(final_node)
|
|
64
|
+
value = handle_special_regexp_chars(begin_node, value)
|
|
65
|
+
return if starts_interpolation_after_hash_sign?(begin_node, value)
|
|
66
|
+
|
|
67
|
+
value = escape_trailing_hash_sign(begin_node, value)
|
|
68
|
+
|
|
69
|
+
# %W and %I split the content into words before expansion
|
|
70
|
+
# treating each interpolation as a word component, so
|
|
71
|
+
# interpolation should not be removed if the expanded value
|
|
72
|
+
# contains a space character.
|
|
73
|
+
return if in_array_percent_literal?(begin_node) && /\s|\A\z/.match?(value)
|
|
74
|
+
|
|
75
|
+
value
|
|
76
|
+
end
|
|
77
|
+
|
|
76
78
|
# rubocop:disable-next Metrics/MethodLength, Metrics/CyclomaticComplexity
|
|
77
79
|
def autocorrected_value(node)
|
|
78
80
|
case node.type
|
|
@@ -116,6 +118,17 @@ module RuboCop
|
|
|
116
118
|
end
|
|
117
119
|
end
|
|
118
120
|
|
|
121
|
+
def starts_interpolation_after_hash_sign?(begin_node, value)
|
|
122
|
+
source = processed_source.buffer.source
|
|
123
|
+
range = begin_node.source_range
|
|
124
|
+
# Removing an empty value puts the `#` right before what follows the interpolation.
|
|
125
|
+
following = "#{value}#{source[range.end_pos]}"
|
|
126
|
+
return false unless following.start_with?('{', '@', '$')
|
|
127
|
+
return false unless source[range.begin_pos - 1] == '#'
|
|
128
|
+
|
|
129
|
+
unescaped_hash_sign?(source[0...range.begin_pos])
|
|
130
|
+
end
|
|
131
|
+
|
|
119
132
|
def autocorrected_value_for_string(node)
|
|
120
133
|
return node.source.delete_prefix('"').delete_suffix('"') unless node.value.valid_encoding?
|
|
121
134
|
|
|
@@ -180,7 +193,9 @@ module RuboCop
|
|
|
180
193
|
end
|
|
181
194
|
|
|
182
195
|
def space_literal?(node)
|
|
183
|
-
|
|
196
|
+
# `String#blank?` misses Unicode spaces such as U+3000 that
|
|
197
|
+
# `Layout/TrailingWhitespace` treats as trailing whitespace.
|
|
198
|
+
node.str_type? && node.value.valid_encoding? && node.value.match?(/\A[[:space:]]*\z/)
|
|
184
199
|
end
|
|
185
200
|
|
|
186
201
|
def ends_heredoc_line?(node)
|
|
@@ -188,7 +203,8 @@ module RuboCop
|
|
|
188
203
|
return false unless grandparent&.dstr_type? && grandparent.heredoc?
|
|
189
204
|
|
|
190
205
|
line = processed_source.lines[node.last_line - 1]
|
|
191
|
-
|
|
206
|
+
|
|
207
|
+
line.size == node.parent.source_range.last_column
|
|
192
208
|
end
|
|
193
209
|
|
|
194
210
|
def in_array_percent_literal?(node)
|
|
@@ -198,6 +214,34 @@ module RuboCop
|
|
|
198
214
|
grandparent = parent.parent
|
|
199
215
|
grandparent&.array_type? && grandparent.percent_literal?
|
|
200
216
|
end
|
|
217
|
+
|
|
218
|
+
def escape_trailing_hash_sign(begin_node, value)
|
|
219
|
+
following = processed_source.buffer.source[begin_node.source_range.end_pos]
|
|
220
|
+
return value unless %w[{ @ $].include?(following) && unescaped_hash_sign?(value)
|
|
221
|
+
|
|
222
|
+
"#{value.delete_suffix('#')}\\#"
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def unescaped_hash_sign?(text)
|
|
226
|
+
text.end_with?('#') && text.delete_suffix('#')[/\\*\z/].length.even?
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
# Each interpolation is checked against the original source, so correcting it in the
|
|
230
|
+
# same pass as a preceding one that leaves a `#` (or nothing) could join that `#` and
|
|
231
|
+
# a `{` from this one. It's left for the next iteration instead.
|
|
232
|
+
def follows_literal_interpolation?(begin_node)
|
|
233
|
+
previous = begin_node.left_sibling
|
|
234
|
+
return false unless previous&.begin_type? && offending?(previous.children.last)
|
|
235
|
+
|
|
236
|
+
value = correctable_value(previous, previous.children.last)
|
|
237
|
+
value && (value.empty? || value.end_with?('#'))
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def replacement(node, expanded_value)
|
|
241
|
+
return expanded_value unless node.str_type? && !node.value.valid_encoding?
|
|
242
|
+
|
|
243
|
+
node.source.delete_prefix('"').delete_suffix('"')
|
|
244
|
+
end
|
|
201
245
|
end
|
|
202
246
|
end
|
|
203
247
|
end
|
|
@@ -42,6 +42,8 @@ module RuboCop
|
|
|
42
42
|
# break if some_condition
|
|
43
43
|
# end
|
|
44
44
|
class Loop < Base
|
|
45
|
+
include Alignment
|
|
46
|
+
include RangeHelp
|
|
45
47
|
extend AutoCorrector
|
|
46
48
|
|
|
47
49
|
MSG = 'Use `Kernel#loop` with `break` rather than `begin/end/until`(or `while`).'
|
|
@@ -62,7 +64,8 @@ module RuboCop
|
|
|
62
64
|
add_offense(node.loc.keyword) do |corrector|
|
|
63
65
|
corrector.replace(body.loc.begin, 'loop do')
|
|
64
66
|
corrector.remove(keyword_and_condition_range(node))
|
|
65
|
-
|
|
67
|
+
|
|
68
|
+
insert_break_line(corrector, node, body)
|
|
66
69
|
end
|
|
67
70
|
end
|
|
68
71
|
|
|
@@ -70,9 +73,28 @@ module RuboCop
|
|
|
70
73
|
node.body.loc.end.end.join(node.source_range.end)
|
|
71
74
|
end
|
|
72
75
|
|
|
76
|
+
def insert_break_line(corrector, node, body)
|
|
77
|
+
if body.single_line?
|
|
78
|
+
corrector.replace(space_before_end(body), build_break_line(node))
|
|
79
|
+
else
|
|
80
|
+
corrector.insert_before(body.loc.end, build_break_line(node))
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def space_before_end(body)
|
|
85
|
+
range = range_with_surrounding_space(range: body.loc.end, side: :left, newlines: false)
|
|
86
|
+
|
|
87
|
+
range.with(end_pos: body.loc.end.begin_pos)
|
|
88
|
+
end
|
|
89
|
+
|
|
73
90
|
def build_break_line(node)
|
|
74
91
|
conditional_keyword = node.while_post_type? ? 'unless' : 'if'
|
|
75
|
-
"break #{conditional_keyword} #{node.condition.source}\n#{indent(node)}"
|
|
92
|
+
break_line = "break #{conditional_keyword} #{node.condition.source}\n#{indent(node)}"
|
|
93
|
+
return break_line unless node.body.single_line?
|
|
94
|
+
|
|
95
|
+
# A single-line `begin ... end` keeps its body and `end` on one line,
|
|
96
|
+
# so the `break` has to start a line of its own.
|
|
97
|
+
"\n#{indent(node, offset: configured_indentation_width)}#{break_line}"
|
|
76
98
|
end
|
|
77
99
|
end
|
|
78
100
|
end
|
|
@@ -116,31 +116,88 @@ module RuboCop
|
|
|
116
116
|
end
|
|
117
117
|
|
|
118
118
|
def first_code_token
|
|
119
|
-
|
|
119
|
+
processed_source.sorted_tokens.find { |token| !token.comment? }
|
|
120
120
|
end
|
|
121
121
|
|
|
122
122
|
def check_encoding_comment(comment)
|
|
123
|
+
return unless misplaced_encoding_position?(comment)
|
|
124
|
+
|
|
125
|
+
add_offense(comment, message: MSG_ENCODING) do |corrector|
|
|
126
|
+
correct_encoding_comment(corrector, comment)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def misplaced_encoding_position?(comment)
|
|
123
131
|
line = comment.source_range.line
|
|
124
|
-
return if line == effective_encoding_line && comment_starts_line?(comment)
|
|
132
|
+
return false if line == effective_encoding_line && comment_starts_line?(comment)
|
|
133
|
+
|
|
125
134
|
# Leave `# frozen_string_literal: true` + `# encoding: x` runs at the
|
|
126
135
|
# very top to Lint/OrderedMagicComments, which already reorders them.
|
|
127
|
-
|
|
136
|
+
!preceded_only_by_magic_comments?(comment)
|
|
137
|
+
end
|
|
128
138
|
|
|
129
|
-
|
|
139
|
+
# With an effective encoding comment already in place, moving another
|
|
140
|
+
# one in would override it. Drop an identical duplicate and leave a
|
|
141
|
+
# conflicting one for a human to resolve.
|
|
142
|
+
def correct_encoding_comment(corrector, comment)
|
|
143
|
+
effective_comment = effective_encoding_comment
|
|
144
|
+
|
|
145
|
+
if effective_comment.nil?
|
|
130
146
|
move_comment(corrector, comment, effective_encoding_line)
|
|
147
|
+
elsif comment_encoding(effective_comment) == comment_encoding(comment)
|
|
148
|
+
corrector.remove(comment_removal_range(comment))
|
|
131
149
|
end
|
|
132
150
|
end
|
|
133
151
|
|
|
152
|
+
def comment_encoding(comment)
|
|
153
|
+
Encoding.find(MagicComment.parse(comment.text).encoding)
|
|
154
|
+
rescue ArgumentError
|
|
155
|
+
nil
|
|
156
|
+
end
|
|
157
|
+
|
|
134
158
|
def check_top_block_comment(comment, directive)
|
|
135
159
|
return unless first_code_token
|
|
136
160
|
return unless comment.source_range.begin_pos > first_code_token.begin_pos
|
|
137
161
|
|
|
138
162
|
message = format(MSG_AFTER_CODE, directive: directive)
|
|
139
163
|
add_offense(comment, message: message) do |corrector|
|
|
140
|
-
|
|
164
|
+
# Both would be inserted at the top, in no reliable order. Leave
|
|
165
|
+
# this one to the next pass, once the encoding comment is in place.
|
|
166
|
+
next if encoding_comment_moving_in?
|
|
167
|
+
|
|
168
|
+
move_comment(corrector, comment, top_block_insertion_line)
|
|
141
169
|
end
|
|
142
170
|
end
|
|
143
171
|
|
|
172
|
+
def encoding_comment_moving_in?
|
|
173
|
+
return false if effective_encoding_comment
|
|
174
|
+
|
|
175
|
+
processed_source.comments.any? do |comment|
|
|
176
|
+
known_encoding_comment?(comment) && misplaced_encoding_position?(comment)
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def effective_encoding_comment
|
|
181
|
+
processed_source.comments.find do |comment|
|
|
182
|
+
comment.source_range.line == effective_encoding_line &&
|
|
183
|
+
comment_starts_line?(comment) &&
|
|
184
|
+
MagicComment.parse(comment.text).encoding_specified?
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def known_encoding_comment?(comment)
|
|
189
|
+
return false unless magic_comment_shaped?(comment.text)
|
|
190
|
+
|
|
191
|
+
magic_comment = MagicComment.parse(comment.text)
|
|
192
|
+
magic_comment.encoding_specified? && known_encoding?(magic_comment.encoding)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# Insert below an effective encoding comment rather than above it,
|
|
196
|
+
# which would push it off the only lines where Ruby honors it.
|
|
197
|
+
def top_block_insertion_line
|
|
198
|
+
effective_encoding_comment ? effective_encoding_line + 1 : effective_encoding_line
|
|
199
|
+
end
|
|
200
|
+
|
|
144
201
|
def check_magic_comment_above_shebang
|
|
145
202
|
shebang_comment = processed_source.comments.find do |comment|
|
|
146
203
|
comment.source_range.line > 1 && comment.text.start_with?('#!') &&
|
|
@@ -166,12 +223,7 @@ module RuboCop
|
|
|
166
223
|
end
|
|
167
224
|
|
|
168
225
|
def move_comment(corrector, comment, target_line)
|
|
169
|
-
|
|
170
|
-
range_by_whole_lines(comment.source_range, include_final_newline: true)
|
|
171
|
-
else
|
|
172
|
-
range_with_surrounding_space(comment.source_range, side: :left)
|
|
173
|
-
end
|
|
174
|
-
corrector.remove(removal_range)
|
|
226
|
+
corrector.remove(comment_removal_range(comment))
|
|
175
227
|
target_range = processed_source.buffer.line_range(target_line)
|
|
176
228
|
if comment.source_range.line < target_line
|
|
177
229
|
corrector.insert_after(target_range, "\n#{comment.text}")
|
|
@@ -179,6 +231,14 @@ module RuboCop
|
|
|
179
231
|
corrector.insert_before(target_range, "#{comment.text}\n")
|
|
180
232
|
end
|
|
181
233
|
end
|
|
234
|
+
|
|
235
|
+
def comment_removal_range(comment)
|
|
236
|
+
if comment_starts_line?(comment)
|
|
237
|
+
range_by_whole_lines(comment.source_range, include_final_newline: true)
|
|
238
|
+
else
|
|
239
|
+
range_with_surrounding_space(comment.source_range, side: :left)
|
|
240
|
+
end
|
|
241
|
+
end
|
|
182
242
|
end
|
|
183
243
|
end
|
|
184
244
|
end
|
|
@@ -62,7 +62,7 @@ module RuboCop
|
|
|
62
62
|
each_missing_enable do |cop, line_range|
|
|
63
63
|
next if acceptable_range?(cop, line_range)
|
|
64
64
|
|
|
65
|
-
comment =
|
|
65
|
+
comment = opening_comment(line_range)
|
|
66
66
|
|
|
67
67
|
add_offense(comment, message: message(cop, comment))
|
|
68
68
|
end
|
|
@@ -73,14 +73,29 @@ module RuboCop
|
|
|
73
73
|
def each_missing_enable
|
|
74
74
|
processed_source.disabled_line_ranges.each do |cop, line_ranges|
|
|
75
75
|
line_ranges.each do |line_range|
|
|
76
|
-
# A `disable-next` scope closes itself with its statement.
|
|
77
|
-
next if
|
|
76
|
+
# A `disable-next` or `next` scope closes itself with its statement.
|
|
77
|
+
next if statement_scoped?(line_range)
|
|
78
78
|
|
|
79
79
|
yield cop, line_range
|
|
80
80
|
end
|
|
81
81
|
end
|
|
82
82
|
end
|
|
83
83
|
|
|
84
|
+
def statement_scoped?(line_range)
|
|
85
|
+
directive = line_range.respond_to?(:directive) && line_range.directive
|
|
86
|
+
directive && (directive.disable_next? || directive.next?)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# A disable suspended by `enable-next` or `next +Cop` reopens below the
|
|
90
|
+
# statement, on a code line, so the comment that opened it has to come
|
|
91
|
+
# from the range rather than from its first line.
|
|
92
|
+
def opening_comment(line_range)
|
|
93
|
+
directive = line_range.respond_to?(:directive) && line_range.directive
|
|
94
|
+
return directive.comment if directive
|
|
95
|
+
|
|
96
|
+
processed_source.comment_at_line(line_range.begin)
|
|
97
|
+
end
|
|
98
|
+
|
|
84
99
|
def acceptable_range?(cop, line_range)
|
|
85
100
|
# This has to remain a strict inequality to handle
|
|
86
101
|
# the case when max_range is Float::INFINITY
|
|
@@ -132,7 +132,7 @@ module RuboCop
|
|
|
132
132
|
|
|
133
133
|
def handle_as_symbol(node)
|
|
134
134
|
to_method_symbol(node) do |receiver, sym_node, to_method|
|
|
135
|
-
next if receiver.nil? || !node.arguments.one?
|
|
135
|
+
next if receiver.nil? || !node.arguments.one? || node.operator_method?
|
|
136
136
|
|
|
137
137
|
message = format(
|
|
138
138
|
MSG,
|
|
@@ -110,7 +110,7 @@ module RuboCop
|
|
|
110
110
|
# A pending cop that is not enabled in this run produces no
|
|
111
111
|
# offenses, so its directives cannot be judged - they typically
|
|
112
112
|
# prepare the code for the moment the cop gets enabled.
|
|
113
|
-
next if pending_cop_not_run?(cop)
|
|
113
|
+
next if pending_cop_not_run?(cop) || disabled_by_preview?(cop)
|
|
114
114
|
|
|
115
115
|
each_already_disabled(cop, line_ranges, &block)
|
|
116
116
|
each_line_range(cop, line_ranges, &block)
|
|
@@ -128,6 +128,17 @@ module RuboCop
|
|
|
128
128
|
!processed_source.registry.enabled_pending_cop?(cop_cfg, config, cop)
|
|
129
129
|
end
|
|
130
130
|
|
|
131
|
+
# A cop that only the `Preview` defaults disable runs again as soon as
|
|
132
|
+
# preview is turned off, so its directives are still needed.
|
|
133
|
+
def disabled_by_preview?(cop)
|
|
134
|
+
return false unless preview? && all_cop_names.include?(cop)
|
|
135
|
+
|
|
136
|
+
preview_defaults = ConfigLoader.default_configuration[cop]&.fetch('Preview', nil)
|
|
137
|
+
return false unless preview_defaults.is_a?(Hash) && preview_defaults['Enabled'] == false
|
|
138
|
+
|
|
139
|
+
!config.cop_enabled?(cop)
|
|
140
|
+
end
|
|
141
|
+
|
|
131
142
|
def each_line_range(cop, line_ranges)
|
|
132
143
|
line_ranges.each_with_index do |line_range, line_range_index|
|
|
133
144
|
next if should_skip_line_range?(cop, line_range)
|
|
@@ -28,6 +28,7 @@ module RuboCop
|
|
|
28
28
|
# end
|
|
29
29
|
#
|
|
30
30
|
class RedundantDirGlobSort < Base
|
|
31
|
+
include RangeHelp
|
|
31
32
|
extend AutoCorrector
|
|
32
33
|
extend TargetRubyVersion
|
|
33
34
|
|
|
@@ -46,8 +47,7 @@ module RuboCop
|
|
|
46
47
|
selector = node.loc.selector
|
|
47
48
|
|
|
48
49
|
add_offense(selector) do |corrector|
|
|
49
|
-
corrector.
|
|
50
|
-
corrector.remove(node.loc.dot)
|
|
50
|
+
autocorrect(corrector, node.loc.dot, selector)
|
|
51
51
|
end
|
|
52
52
|
end
|
|
53
53
|
|
|
@@ -67,6 +67,17 @@ module RuboCop
|
|
|
67
67
|
def sort_with_comparator?(node)
|
|
68
68
|
node.parent&.any_block_type? || node.last_argument&.block_pass_type?
|
|
69
69
|
end
|
|
70
|
+
|
|
71
|
+
def autocorrect(corrector, dot, selector)
|
|
72
|
+
range = dot.join(selector)
|
|
73
|
+
|
|
74
|
+
if processed_source.contains_comment?(range)
|
|
75
|
+
corrector.remove(dot)
|
|
76
|
+
corrector.remove(selector)
|
|
77
|
+
else
|
|
78
|
+
corrector.remove(range_with_surrounding_space(range, side: :left))
|
|
79
|
+
end
|
|
80
|
+
end
|
|
70
81
|
end
|
|
71
82
|
end
|
|
72
83
|
end
|
|
@@ -53,12 +53,22 @@ module RuboCop
|
|
|
53
53
|
return if node.each_descendant(:dstr).any?
|
|
54
54
|
|
|
55
55
|
regexp_constructor(node) do |text|
|
|
56
|
+
next unless verbatim_string?(text)
|
|
57
|
+
|
|
56
58
|
detect_offenses_in_tree(text, parse_regexp(text.value))
|
|
57
59
|
end
|
|
58
60
|
end
|
|
59
61
|
|
|
60
62
|
private
|
|
61
63
|
|
|
64
|
+
# Offsets into the string's value only point at the right place in the source
|
|
65
|
+
# when the string has no escape sequences, so anything else is left alone.
|
|
66
|
+
def verbatim_string?(node)
|
|
67
|
+
return false unless node.loc?(:begin) && node.loc?(:end)
|
|
68
|
+
|
|
69
|
+
node.loc.begin.end.join(node.loc.end.begin).source == node.value
|
|
70
|
+
end
|
|
71
|
+
|
|
62
72
|
# When a character class opens with a bare `]` (e.g. `[^]]`), `regexp_parser` parses
|
|
63
73
|
# `[^]` / `[]` as an empty set and reports the closing `]` as a separate literal.
|
|
64
74
|
# Ruby treats that `]` as the end of the class, not as an unescaped bracket,
|
|
@@ -97,7 +107,7 @@ module RuboCop
|
|
|
97
107
|
location = range_at_index(node, expr.ts, pos)
|
|
98
108
|
|
|
99
109
|
add_offense(location) do |corrector|
|
|
100
|
-
corrector.replace(location,
|
|
110
|
+
corrector.replace(location, escaped_bracket(node))
|
|
101
111
|
end
|
|
102
112
|
end
|
|
103
113
|
|
|
@@ -108,6 +118,13 @@ module RuboCop
|
|
|
108
118
|
adjustment = index + offset
|
|
109
119
|
node.loc.begin.end.adjust(begin_pos: adjustment, end_pos: adjustment + 1)
|
|
110
120
|
end
|
|
121
|
+
|
|
122
|
+
# A double-quoted string turns `\]` into `]`, so its backslash needs escaping too.
|
|
123
|
+
def escaped_bracket(node)
|
|
124
|
+
return '\]' if node.regexp_type? || node.single_quoted? || node.percent_literal?(:q)
|
|
125
|
+
|
|
126
|
+
'\\\\]'
|
|
127
|
+
end
|
|
111
128
|
end
|
|
112
129
|
end
|
|
113
130
|
end
|
|
@@ -212,16 +212,23 @@ module RuboCop
|
|
|
212
212
|
end
|
|
213
213
|
|
|
214
214
|
def remove_local_variable_assignment_part(corrector, node)
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
def variable_in_loop_condition?(assignment_node, variable)
|
|
219
|
-
return false if assignment_node.each_ancestor(:any_def).any?
|
|
215
|
+
expression = node.expression
|
|
216
|
+
assignment_part = node.loc.name.begin.join(expression.source_range.begin)
|
|
220
217
|
|
|
221
|
-
|
|
222
|
-
|
|
218
|
+
# `x = 1, 2` cannot become `1, 2`, so the values become an array literal.
|
|
219
|
+
if expression.array_type? && !expression.bracketed?
|
|
220
|
+
corrector.replace(assignment_part, '[')
|
|
221
|
+
corrector.insert_after(expression, ']')
|
|
222
|
+
else
|
|
223
|
+
corrector.remove(assignment_part)
|
|
223
224
|
end
|
|
225
|
+
end
|
|
224
226
|
|
|
227
|
+
def variable_in_loop_condition?(assignment_node, variable)
|
|
228
|
+
# A method defined inside the loop has its own scope, so the loop condition
|
|
229
|
+
# can only read the variable if the loop is nearer than any method definition.
|
|
230
|
+
loop_node = assignment_node.each_ancestor(*VariableForce::LOOP_TYPES, :any_def).first
|
|
231
|
+
return false if !loop_node || loop_node.any_def_type?
|
|
225
232
|
return false unless loop_node.respond_to?(:condition)
|
|
226
233
|
|
|
227
234
|
condition_node = loop_node.condition
|
|
@@ -271,7 +271,14 @@ module RuboCop
|
|
|
271
271
|
return if node.parent.type?(:if, :case, :when, :case_match, :in_pattern)
|
|
272
272
|
return if (def_node = node.each_ancestor(:any_def).first) && def_node.assignment_method?
|
|
273
273
|
|
|
274
|
-
|
|
274
|
+
range = range_with_surrounding_space(range: void_expression_range(node), side: :left)
|
|
275
|
+
corrector.remove(range)
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
def void_expression_range(node)
|
|
279
|
+
return node.source_range unless node.respond_to?(:heredoc?) && node.heredoc?
|
|
280
|
+
|
|
281
|
+
node.source_range.join(node.loc.heredoc_end)
|
|
275
282
|
end
|
|
276
283
|
|
|
277
284
|
def autocorrect_nonmutating_send(corrector, node, suggestion)
|
|
@@ -40,6 +40,8 @@ module RuboCop
|
|
|
40
40
|
class ClassLength < Base
|
|
41
41
|
include CodeLength
|
|
42
42
|
|
|
43
|
+
LABEL = 'Class'
|
|
44
|
+
|
|
43
45
|
def on_class(node)
|
|
44
46
|
check_code_length(node)
|
|
45
47
|
end
|
|
@@ -60,8 +62,8 @@ module RuboCop
|
|
|
60
62
|
|
|
61
63
|
private
|
|
62
64
|
|
|
63
|
-
def
|
|
64
|
-
|
|
65
|
+
def cop_label
|
|
66
|
+
LABEL
|
|
65
67
|
end
|
|
66
68
|
|
|
67
69
|
def find_expression_within_parent(parent)
|
|
@@ -38,6 +38,8 @@ module RuboCop
|
|
|
38
38
|
class ModuleLength < Base
|
|
39
39
|
include CodeLength
|
|
40
40
|
|
|
41
|
+
LABEL = 'Module'
|
|
42
|
+
|
|
41
43
|
def on_module(node)
|
|
42
44
|
check_code_length(node)
|
|
43
45
|
end
|
|
@@ -53,8 +55,8 @@ module RuboCop
|
|
|
53
55
|
(casgn nil? _ (any_block (send (const {nil? cbase} :Module) :new) ...))
|
|
54
56
|
PATTERN
|
|
55
57
|
|
|
56
|
-
def
|
|
57
|
-
|
|
58
|
+
def cop_label
|
|
59
|
+
LABEL
|
|
58
60
|
end
|
|
59
61
|
end
|
|
60
62
|
end
|
|
@@ -15,6 +15,10 @@ module RuboCop
|
|
|
15
15
|
cop_config['IndentationWidth'] || config.for_cop('Layout/IndentationWidth')['Width'] || 2
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
+
def using_tabs?
|
|
19
|
+
config.for_cop('Layout/IndentationStyle')['EnforcedStyle'] == 'tabs'
|
|
20
|
+
end
|
|
21
|
+
|
|
18
22
|
def indentation(node)
|
|
19
23
|
offset(node) + (SPACE * configured_indentation_width)
|
|
20
24
|
end
|