rubocop 1.91.0 → 1.92.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 +4 -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/badge.rb +1 -1
- 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 +37 -7
- data/lib/rubocop/cop/correctors/empty_line_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +25 -4
- data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +34 -0
- 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/argument_alignment.rb +5 -1
- 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 +29 -7
- data/lib/rubocop/cop/layout/def_end_alignment.rb +4 -0
- data/lib/rubocop/cop/layout/dot_position.rb +25 -15
- data/lib/rubocop/cop/layout/empty_line_after_multiline_condition.rb +21 -8
- 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 +9 -3
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +23 -1
- data/lib/rubocop/cop/layout/end_alignment.rb +19 -17
- data/lib/rubocop/cop/layout/extra_spacing.rb +4 -0
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +27 -1
- data/lib/rubocop/cop/layout/first_array_element_line_break.rb +15 -0
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +16 -8
- 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 +7 -3
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +15 -0
- data/lib/rubocop/cop/layout/indentation_consistency.rb +22 -5
- 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 +153 -21
- 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 +9 -0
- data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +6 -0
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +30 -5
- 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/layout/space_inside_reference_brackets.rb +2 -12
- 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/ambiguous_regexp_literal.rb +6 -1
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +3 -1
- data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +4 -0
- 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 +3 -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/safe_navigation_consistency.rb +47 -1
- data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -0
- 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/useless_setter_call.rb +7 -4
- 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 +23 -19
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +8 -2
- 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 +105 -0
- data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +2 -2
- data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +24 -5
- 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 +25 -4
- data/lib/rubocop/cop/mixin/visibility_help.rb +2 -1
- 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/naming/rescued_exceptions_variable_name.rb +1 -1
- 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 +37 -2
- 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 +6 -2
- data/lib/rubocop/cop/style/arguments_forwarding.rb +32 -3
- 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 +35 -3
- data/lib/rubocop/cop/style/case_like_if.rb +6 -3
- data/lib/rubocop/cop/style/class_and_module_children.rb +56 -16
- data/lib/rubocop/cop/style/class_methods_definitions.rb +15 -0
- data/lib/rubocop/cop/style/collection_querying.rb +79 -46
- data/lib/rubocop/cop/style/combinable_loops.rb +89 -11
- data/lib/rubocop/cop/style/concat_array_literals.rb +58 -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/empty_string_inside_interpolation.rb +53 -11
- data/lib/rubocop/cop/style/endless_method.rb +71 -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 +53 -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 +31 -22
- data/lib/rubocop/cop/style/hash_as_last_array_item.rb +4 -0
- 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 +32 -26
- 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 +94 -4
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +3 -1
- data/lib/rubocop/cop/style/lambda.rb +34 -1
- 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 +80 -13
- 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/mixin_grouping.rb +12 -3
- 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 +52 -7
- 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/parentheses_around_condition.rb +1 -1
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +14 -3
- data/lib/rubocop/cop/style/raise_args.rb +19 -9
- data/lib/rubocop/cop/style/reduce_to_hash.rb +17 -1
- data/lib/rubocop/cop/style/redundant_begin.rb +22 -4
- 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 +11 -3
- data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +24 -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/redundant_self_assignment_branch.rb +28 -0
- data/lib/rubocop/cop/style/redundant_sort.rb +38 -4
- data/lib/rubocop/cop/style/regexp_literal.rb +75 -26
- data/lib/rubocop/cop/style/require_order.rb +25 -8
- data/lib/rubocop/cop/style/rescue_modifier.rb +11 -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/send_with_literal_method_name.rb +4 -0
- data/lib/rubocop/cop/style/single_line_methods.rb +21 -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/struct_inheritance.rb +6 -0
- data/lib/rubocop/cop/style/super_arguments.rb +3 -0
- data/lib/rubocop/cop/style/symbol_proc.rb +24 -6
- 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/routes.rb +23 -23
- 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 +6 -6
- data/lib/rubocop/target_ruby.rb +21 -9
- data/lib/rubocop/util.rb +69 -0
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +5 -0
- metadata +16 -5
|
@@ -156,16 +156,22 @@ module RuboCop
|
|
|
156
156
|
if first_pair
|
|
157
157
|
return if same_line?(first_pair, left_brace)
|
|
158
158
|
|
|
159
|
-
|
|
160
|
-
check_based_on_longest_key(hash_node, left_brace, left_parenthesis)
|
|
161
|
-
else
|
|
162
|
-
check_first(first_pair, left_brace, left_parenthesis, 0)
|
|
163
|
-
end
|
|
159
|
+
check_first_pair(hash_node, first_pair, left_brace, left_parenthesis)
|
|
164
160
|
end
|
|
165
161
|
|
|
166
162
|
check_right_brace(hash_node.loc.end, first_pair, left_brace, left_parenthesis)
|
|
167
163
|
end
|
|
168
164
|
|
|
165
|
+
def check_first_pair(hash_node, first_pair, left_brace, left_parenthesis)
|
|
166
|
+
return unless begins_its_line?(first_pair.source_range)
|
|
167
|
+
|
|
168
|
+
if separator_style?(first_pair)
|
|
169
|
+
check_based_on_longest_key(hash_node, left_brace, left_parenthesis)
|
|
170
|
+
else
|
|
171
|
+
check_first(first_pair, left_brace, left_parenthesis, 0)
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
169
175
|
def check_right_brace(right_brace, first_pair, left_brace, left_parenthesis)
|
|
170
176
|
# if the right brace is on the same line as the last value, accept
|
|
171
177
|
return if /\S/.match?(right_brace.source_line[0...right_brace.column])
|
|
@@ -187,9 +193,11 @@ module RuboCop
|
|
|
187
193
|
end
|
|
188
194
|
|
|
189
195
|
def check_based_on_longest_key(hash_node, left_brace, left_parenthesis)
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
196
|
+
first_key = hash_node.keys.first
|
|
197
|
+
key_lengths = hash_node.keys.select(&:single_line?).map { |key| key.source_range.length }
|
|
198
|
+
offset = first_key.single_line? ? key_lengths.max - first_key.source_range.length : 0
|
|
199
|
+
|
|
200
|
+
check_first(hash_node.pairs.first, left_brace, left_parenthesis, offset)
|
|
193
201
|
end
|
|
194
202
|
|
|
195
203
|
# Returns the description of what the correct indentation is based on.
|
|
@@ -75,6 +75,12 @@ module RuboCop
|
|
|
75
75
|
|
|
76
76
|
MSG = 'Add a line break before the first argument of a multi-line method argument list.'
|
|
77
77
|
|
|
78
|
+
# A line break inserted after `(` while `Style/MethodCallWithArgsParentheses` removes
|
|
79
|
+
# the parentheses in the same pass leaves the method name alone on its line.
|
|
80
|
+
def self.autocorrect_incompatible_with
|
|
81
|
+
[Style::MethodCallWithArgsParentheses]
|
|
82
|
+
end
|
|
83
|
+
|
|
78
84
|
def on_send(node)
|
|
79
85
|
return if allowed_method?(node.method_name)
|
|
80
86
|
|
|
@@ -59,6 +59,10 @@ module RuboCop
|
|
|
59
59
|
|
|
60
60
|
MSG = 'Add a line break before the first parameter of a multi-line method parameter list.'
|
|
61
61
|
|
|
62
|
+
def self.autocorrect_incompatible_with
|
|
63
|
+
[Style::MethodDefParentheses]
|
|
64
|
+
end
|
|
65
|
+
|
|
62
66
|
def on_def(node)
|
|
63
67
|
check_method_line_break(node, node.arguments, ignore_last: ignore_last_element?)
|
|
64
68
|
end
|
|
@@ -215,7 +215,7 @@ module RuboCop
|
|
|
215
215
|
check_pairs(node)
|
|
216
216
|
end
|
|
217
217
|
|
|
218
|
-
attr_accessor :offenses_by, :column_deltas
|
|
218
|
+
attr_accessor :offenses_by, :column_deltas, :unalignable_styles
|
|
219
219
|
|
|
220
220
|
private
|
|
221
221
|
|
|
@@ -240,6 +240,7 @@ module RuboCop
|
|
|
240
240
|
def reset!
|
|
241
241
|
self.offenses_by = {}
|
|
242
242
|
self.column_deltas = Hash.new { |hash, key| hash[key] = {} }
|
|
243
|
+
self.unalignable_styles = []
|
|
243
244
|
end
|
|
244
245
|
|
|
245
246
|
def check_pairs(node)
|
|
@@ -265,7 +266,9 @@ module RuboCop
|
|
|
265
266
|
kwsplat_offenses = offenses_by.delete(KeywordSplatAlignment)
|
|
266
267
|
register_offenses_with_format(kwsplat_offenses, KeywordSplatAlignment)
|
|
267
268
|
|
|
268
|
-
|
|
269
|
+
candidates = offenses_by.reject { |style, _| unalignable_styles.include?(style) }
|
|
270
|
+
candidates = offenses_by if candidates.empty?
|
|
271
|
+
format, offenses = candidates.min_by { |_, v| v.length }
|
|
269
272
|
register_offenses_with_format(offenses, format)
|
|
270
273
|
end
|
|
271
274
|
|
|
@@ -283,10 +286,19 @@ module RuboCop
|
|
|
283
286
|
offenses_by[alignment.class] ||= []
|
|
284
287
|
return if good_alignment? delta
|
|
285
288
|
|
|
289
|
+
if key_out_of_line?(delta, node)
|
|
290
|
+
unalignable_styles << alignment.class
|
|
291
|
+
return
|
|
292
|
+
end
|
|
293
|
+
|
|
286
294
|
column_deltas[alignment.class][node] = delta
|
|
287
295
|
offenses_by[alignment.class].push(node)
|
|
288
296
|
end
|
|
289
297
|
|
|
298
|
+
def key_out_of_line?(delta, node)
|
|
299
|
+
(delta[:key] || 0) < -node.source_range.column
|
|
300
|
+
end
|
|
301
|
+
|
|
290
302
|
def ignore_hash_argument?(node)
|
|
291
303
|
case cop_config['EnforcedLastArgumentHashStyle']
|
|
292
304
|
when 'always_inspect' then false
|
|
@@ -325,18 +337,10 @@ module RuboCop
|
|
|
325
337
|
node.loc.operator)
|
|
326
338
|
else
|
|
327
339
|
delta_value = delta[:key] || 0
|
|
328
|
-
|
|
340
|
+
adjust(corrector, delta_value, node.source_range)
|
|
329
341
|
end
|
|
330
342
|
end
|
|
331
343
|
|
|
332
|
-
def correct_no_value(corrector, key_delta, key)
|
|
333
|
-
adjust(corrector, clamped_key_delta(key_delta, key), key)
|
|
334
|
-
end
|
|
335
|
-
|
|
336
|
-
def clamped_key_delta(key_delta, key)
|
|
337
|
-
[key_delta, -key.column].max
|
|
338
|
-
end
|
|
339
|
-
|
|
340
344
|
def correct_key_value(corrector, delta, key, value, separator)
|
|
341
345
|
# We can't use the instance variable inside the lambda. That would
|
|
342
346
|
# just give each lambda the same reference and they would all get the
|
|
@@ -345,7 +349,7 @@ module RuboCop
|
|
|
345
349
|
value_delta = delta[:value] || 0
|
|
346
350
|
key_delta = delta[:key] || 0
|
|
347
351
|
|
|
348
|
-
adjust(corrector,
|
|
352
|
+
adjust(corrector, key_delta, key)
|
|
349
353
|
adjust(corrector, separator_delta, separator)
|
|
350
354
|
adjust(corrector, value_delta, value)
|
|
351
355
|
end
|
|
@@ -57,8 +57,10 @@ module RuboCop
|
|
|
57
57
|
MSG = 'Put the closing parenthesis for a method call with a ' \
|
|
58
58
|
'HEREDOC parameter on the same line as the HEREDOC opening.'
|
|
59
59
|
|
|
60
|
+
# `Layout/MultilineMethodCallBraceLayout` can move the same closing parenthesis after
|
|
61
|
+
# the last argument in the same pass, and both insertions are kept.
|
|
60
62
|
def self.autocorrect_incompatible_with
|
|
61
|
-
[Style::TrailingCommaInArguments]
|
|
63
|
+
[Layout::MultilineMethodCallBraceLayout, Style::TrailingCommaInArguments]
|
|
62
64
|
end
|
|
63
65
|
|
|
64
66
|
def on_send(node)
|
|
@@ -117,6 +119,8 @@ module RuboCop
|
|
|
117
119
|
previous = heredoc
|
|
118
120
|
current = previous.parent
|
|
119
121
|
until send_missing_closing_parens?(current, previous, heredoc)
|
|
122
|
+
return if current&.any_block_type? && !current.send_node.equal?(previous)
|
|
123
|
+
|
|
120
124
|
previous = current
|
|
121
125
|
current = current.parent
|
|
122
126
|
return unless previous && current
|
|
@@ -229,8 +233,8 @@ module RuboCop
|
|
|
229
233
|
end
|
|
230
234
|
|
|
231
235
|
def find_most_bottom_of_heredoc_end(arguments)
|
|
232
|
-
arguments.filter_map do |
|
|
233
|
-
|
|
236
|
+
arguments.flat_map { |argument| argument.each_node(:any_str).to_a }.filter_map do |node|
|
|
237
|
+
node.loc.heredoc_end.end_pos if node.loc?(:heredoc_end)
|
|
234
238
|
end.max
|
|
235
239
|
end
|
|
236
240
|
|
|
@@ -55,6 +55,10 @@ module RuboCop
|
|
|
55
55
|
(send _ {:squish :squish!})
|
|
56
56
|
PATTERN
|
|
57
57
|
|
|
58
|
+
def on_new_investigation
|
|
59
|
+
@offending_heredoc_bodies = nil
|
|
60
|
+
end
|
|
61
|
+
|
|
58
62
|
def on_heredoc(node)
|
|
59
63
|
body = heredoc_body(node)
|
|
60
64
|
return if body.strip.empty?
|
|
@@ -77,6 +81,9 @@ module RuboCop
|
|
|
77
81
|
private
|
|
78
82
|
|
|
79
83
|
def register_offense(node, heredoc_indent_type)
|
|
84
|
+
return if within_offending_heredoc?(node)
|
|
85
|
+
|
|
86
|
+
offending_heredoc_bodies << node.loc.heredoc_body
|
|
80
87
|
message = message(heredoc_indent_type)
|
|
81
88
|
|
|
82
89
|
add_offense(node.loc.heredoc_body, message: message) do |corrector|
|
|
@@ -90,6 +97,14 @@ module RuboCop
|
|
|
90
97
|
end
|
|
91
98
|
end
|
|
92
99
|
|
|
100
|
+
def within_offending_heredoc?(node)
|
|
101
|
+
offending_heredoc_bodies.any? { |body| body.contains?(node.source_range) }
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def offending_heredoc_bodies
|
|
105
|
+
@offending_heredoc_bodies ||= []
|
|
106
|
+
end
|
|
107
|
+
|
|
93
108
|
def message(heredoc_indent_type)
|
|
94
109
|
current_indent_type = "<<#{heredoc_indent_type}"
|
|
95
110
|
|
|
@@ -178,10 +178,24 @@ module RuboCop
|
|
|
178
178
|
end
|
|
179
179
|
|
|
180
180
|
def check_normal_style(node)
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
181
|
+
items = node.children.reject { |child| bare_access_modifier?(child) }
|
|
182
|
+
|
|
183
|
+
check_alignment(items, base_column_for_normal_style(node) || governed_base_column(items))
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def governed_base_column(items)
|
|
187
|
+
return unless config.cop_enabled?('Layout/IndentationWidth')
|
|
188
|
+
return if items.empty? || indentation_width_enabled_at?(items.first)
|
|
189
|
+
|
|
190
|
+
governed_item = items.find { |item| indentation_width_enabled_at?(item) }
|
|
191
|
+
|
|
192
|
+
display_column(governed_item.source_range) if governed_item
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def indentation_width_enabled_at?(node)
|
|
196
|
+
comment_config = processed_source.comment_config
|
|
197
|
+
|
|
198
|
+
comment_config.cop_enabled_at_line?('Layout/IndentationWidth', node.first_line)
|
|
185
199
|
end
|
|
186
200
|
|
|
187
201
|
def check_indented_internal_methods_style(node)
|
|
@@ -197,7 +211,10 @@ module RuboCop
|
|
|
197
211
|
children_to_check.last << child
|
|
198
212
|
end
|
|
199
213
|
end
|
|
200
|
-
|
|
214
|
+
|
|
215
|
+
children_to_check.each do |group|
|
|
216
|
+
check_alignment(group, governed_base_column(group))
|
|
217
|
+
end
|
|
201
218
|
end
|
|
202
219
|
end
|
|
203
220
|
end
|
|
@@ -6,6 +6,9 @@ module RuboCop
|
|
|
6
6
|
# Checks that the indentation method is consistent.
|
|
7
7
|
# Either tabs only or spaces only are used for indentation.
|
|
8
8
|
#
|
|
9
|
+
# With `EnforcedStyle: tabs`, spaces that follow the indenting tabs are
|
|
10
|
+
# taken to be alignment rather than indentation, and are left alone.
|
|
11
|
+
#
|
|
9
12
|
# @example EnforcedStyle: spaces (default)
|
|
10
13
|
# # bad
|
|
11
14
|
# # This example uses a tab to indent bar.
|
|
@@ -67,7 +70,7 @@ module RuboCop
|
|
|
67
70
|
match = if style == :spaces
|
|
68
71
|
line.match(/\A\s*\t+/)
|
|
69
72
|
else
|
|
70
|
-
line.match(/\A
|
|
73
|
+
line.match(/\A +/)
|
|
71
74
|
end
|
|
72
75
|
return unless match
|
|
73
76
|
|
|
@@ -82,7 +82,7 @@ module RuboCop
|
|
|
82
82
|
|
|
83
83
|
# @!method access_modifier?(node)
|
|
84
84
|
def_node_matcher :access_modifier?, <<~PATTERN
|
|
85
|
-
[(send ...)
|
|
85
|
+
[(send ...) bare_access_modifier?]
|
|
86
86
|
PATTERN
|
|
87
87
|
|
|
88
88
|
def on_rescue(node)
|
|
@@ -250,7 +250,7 @@ module RuboCop
|
|
|
250
250
|
|
|
251
251
|
def check_members_for_normal_style(base, members)
|
|
252
252
|
members.first.children.each do |member|
|
|
253
|
-
next if member.send_type? && member.
|
|
253
|
+
next if member.send_type? && member.bare_access_modifier?
|
|
254
254
|
|
|
255
255
|
check_indentation(base, member)
|
|
256
256
|
end
|
|
@@ -111,6 +111,12 @@ module RuboCop
|
|
|
111
111
|
comments.map(&:source_range)
|
|
112
112
|
end
|
|
113
113
|
|
|
114
|
+
def output_record_separator_ranges(ast)
|
|
115
|
+
return [] if ast.nil?
|
|
116
|
+
|
|
117
|
+
ast.each_node(:gvar).select { |gvar| gvar.source == '$\\' }.map(&:source_range)
|
|
118
|
+
end
|
|
119
|
+
|
|
114
120
|
def last_line(processed_source)
|
|
115
121
|
last_token = processed_source.tokens.last
|
|
116
122
|
|
|
@@ -123,7 +129,8 @@ module RuboCop
|
|
|
123
129
|
|
|
124
130
|
def ignored_ranges
|
|
125
131
|
@ignored_ranges ||= ignored_literal_ranges(processed_source.ast) +
|
|
126
|
-
comment_ranges(processed_source.comments)
|
|
132
|
+
comment_ranges(processed_source.comments) +
|
|
133
|
+
output_record_separator_ranges(processed_source.ast)
|
|
127
134
|
end
|
|
128
135
|
|
|
129
136
|
def ignored_parent?(node)
|
|
@@ -87,10 +87,10 @@ module RuboCop
|
|
|
87
87
|
return if children.empty?
|
|
88
88
|
|
|
89
89
|
if style == :aligned && !always_indented?(node)
|
|
90
|
-
check_aligned(children, 1)
|
|
90
|
+
check_aligned(children, 1, children[0].loc.column)
|
|
91
91
|
else
|
|
92
92
|
check_indented(children)
|
|
93
|
-
check_aligned(children, 2)
|
|
93
|
+
check_aligned(children, 2, indented_column(children))
|
|
94
94
|
end
|
|
95
95
|
end
|
|
96
96
|
|
|
@@ -110,21 +110,37 @@ module RuboCop
|
|
|
110
110
|
PARENT_TYPES_FOR_INDENTED.include?(dstr_node.parent&.type)
|
|
111
111
|
end
|
|
112
112
|
|
|
113
|
-
def check_aligned(children, start_index)
|
|
113
|
+
def check_aligned(children, start_index, target_column)
|
|
114
114
|
base_column = children[start_index - 1].loc.column
|
|
115
|
-
children[start_index..].each do |
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
115
|
+
same_column_runs(children[start_index..]).each do |run|
|
|
116
|
+
column = run.first.loc.column
|
|
117
|
+
if column != base_column && column != target_column
|
|
118
|
+
register_misaligned_run(run, target_column - column)
|
|
119
|
+
end
|
|
120
|
+
base_column = column
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def same_column_runs(parts)
|
|
125
|
+
parts.chunk_while { |a, b| a.loc.column == b.loc.column }
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def register_misaligned_run(run, column_delta)
|
|
129
|
+
@column_delta = column_delta
|
|
130
|
+
add_offense(run.first, message: MSG_ALIGN) do |corrector|
|
|
131
|
+
run.each { |child| autocorrect(corrector, child) }
|
|
119
132
|
end
|
|
120
133
|
end
|
|
121
134
|
|
|
122
135
|
def check_indented(children)
|
|
123
|
-
@column_delta =
|
|
124
|
-
children[1].loc.column
|
|
136
|
+
@column_delta = indented_column(children) - children[1].loc.column
|
|
125
137
|
add_offense_and_correction(children[1], MSG_INDENT) if @column_delta != 0
|
|
126
138
|
end
|
|
127
139
|
|
|
140
|
+
def indented_column(children)
|
|
141
|
+
base_column(children[0]) + configured_indentation_width
|
|
142
|
+
end
|
|
143
|
+
|
|
128
144
|
def base_column(child)
|
|
129
145
|
grandparent = child.parent.parent
|
|
130
146
|
if grandparent&.pair_type?
|
|
@@ -72,6 +72,22 @@ module RuboCop
|
|
|
72
72
|
|
|
73
73
|
MSG = 'Line is too long. [%<length>d/%<max>d]'
|
|
74
74
|
|
|
75
|
+
# A trailing backslash, or a trailing unicode, hex, octal, meta or control escape whose
|
|
76
|
+
# payload may be incomplete. An even run of backslashes is complete on its own.
|
|
77
|
+
# Meta and control prefixes chain (`\M-\C-x`, `\c\M-x`), so a whole chain is one escape,
|
|
78
|
+
# and a braced unicode escape may hold several space-separated codepoints.
|
|
79
|
+
ESCAPE_SEQUENCE_TAIL = /
|
|
80
|
+
(?<!\\)(?:\\\\)*
|
|
81
|
+
(
|
|
82
|
+
\\(?:(?:[MC]-|c)\\)*
|
|
83
|
+
(?:u\{[\da-f\x20]*|u[\da-f]{0,4}|x[\da-f]{0,2}|[0-7]{0,3}|[MC]-?|c)?
|
|
84
|
+
)\z
|
|
85
|
+
/xi.freeze
|
|
86
|
+
|
|
87
|
+
def self.autocorrect_incompatible_with
|
|
88
|
+
[Style::MethodCallWithArgsParentheses, Style::MethodDefParentheses]
|
|
89
|
+
end
|
|
90
|
+
|
|
75
91
|
def on_block(node)
|
|
76
92
|
check_for_breakable_block(node)
|
|
77
93
|
end
|
|
@@ -106,6 +122,7 @@ module RuboCop
|
|
|
106
122
|
def on_new_investigation
|
|
107
123
|
@breakable_range_by_line_index = {}
|
|
108
124
|
@breakable_string_delimiters = {}
|
|
125
|
+
@breakable_strings = {}
|
|
109
126
|
@endless_methods_by_line = {}
|
|
110
127
|
@heredocs = nil
|
|
111
128
|
|
|
@@ -191,6 +208,7 @@ module RuboCop
|
|
|
191
208
|
def check_for_breakable_node(node)
|
|
192
209
|
breakable_node = extract_breakable_node(node, max)
|
|
193
210
|
return if breakable_node.nil?
|
|
211
|
+
return if compact_nested_array_break?(node, breakable_node)
|
|
194
212
|
|
|
195
213
|
line_index = breakable_node.first_line - 1
|
|
196
214
|
range = breakable_node.source_range
|
|
@@ -201,6 +219,20 @@ module RuboCop
|
|
|
201
219
|
breakable_range_by_line_index[line_index] = range
|
|
202
220
|
end
|
|
203
221
|
|
|
222
|
+
def compact_nested_array_break?(node, breakable_node)
|
|
223
|
+
return false if !node.array_type? || !node.square_brackets?
|
|
224
|
+
return false unless breakable_node.equal?(node.children.first)
|
|
225
|
+
return false unless breakable_node.source.start_with?('[')
|
|
226
|
+
|
|
227
|
+
compact_array_brackets_enforced?
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def compact_array_brackets_enforced?
|
|
231
|
+
return false unless config.cop_enabled?('Layout/SpaceInsideArrayLiteralBrackets')
|
|
232
|
+
|
|
233
|
+
config.for_cop('Layout/SpaceInsideArrayLiteralBrackets')['EnforcedStyle'] == 'compact'
|
|
234
|
+
end
|
|
235
|
+
|
|
204
236
|
def check_for_breakable_semicolons(processed_source)
|
|
205
237
|
tokens = processed_source.tokens.select { |t| t.type == :tSEMI }
|
|
206
238
|
tokens.reverse_each do |token|
|
|
@@ -214,12 +246,15 @@ module RuboCop
|
|
|
214
246
|
return if receiver_contains_heredoc?(block_node)
|
|
215
247
|
|
|
216
248
|
line_index = block_node.loc.line - 1
|
|
249
|
+
return if breakable_string_delimiters[line_index]
|
|
250
|
+
|
|
217
251
|
range = breakable_block_range(block_node)
|
|
218
252
|
pos = range.begin_pos + 1
|
|
219
253
|
|
|
220
254
|
breakable_range_by_line_index[line_index] = range_between(pos, pos + 1)
|
|
221
255
|
end
|
|
222
256
|
|
|
257
|
+
# rubocop:disable-next Metrics/AbcSize
|
|
223
258
|
def check_for_breakable_str(node)
|
|
224
259
|
line_index = node.loc.line - 1
|
|
225
260
|
return if breakable_range_by_line_index[line_index]
|
|
@@ -230,6 +265,7 @@ module RuboCop
|
|
|
230
265
|
|
|
231
266
|
breakable_range_by_line_index[line_index] = range_between(pos, pos + 1)
|
|
232
267
|
breakable_string_delimiters[line_index] = delimiter
|
|
268
|
+
breakable_strings[line_index] = node
|
|
233
269
|
end
|
|
234
270
|
|
|
235
271
|
def check_for_breakable_dstr(node) # rubocop:disable Metrics/AbcSize
|
|
@@ -282,7 +318,33 @@ module RuboCop
|
|
|
282
318
|
return if source_range.last_column < max
|
|
283
319
|
return unless (pos = breakable_string_range(node))
|
|
284
320
|
|
|
285
|
-
|
|
321
|
+
content_begin_pos = node.loc?(:begin) ? node.loc.begin.end_pos : source_range.begin_pos
|
|
322
|
+
if blank_left_part?(node, content_begin_pos, pos)
|
|
323
|
+
pos = breakable_string_range_at_limit(source_range)
|
|
324
|
+
end
|
|
325
|
+
pos.end_pos if pos && leaves_two_parts?(node, content_begin_pos, pos)
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
def leaves_two_parts?(node, content_begin_pos, pos)
|
|
329
|
+
pos.end_pos > content_begin_pos && !blank_rest?(node, pos.end_pos)
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
def blank_left_part?(node, content_begin_pos, pos)
|
|
333
|
+
return false unless pos.end_pos > content_begin_pos
|
|
334
|
+
return false unless starts_after_quote?(node)
|
|
335
|
+
|
|
336
|
+
blank_between?(content_begin_pos, pos.end_pos)
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
def starts_after_quote?(node)
|
|
340
|
+
return true if node.loc?(:begin)
|
|
341
|
+
|
|
342
|
+
quote = node.parent&.loc&.begin if node.parent&.dstr_type?
|
|
343
|
+
quote ? quote.end_pos == node.source_range.begin_pos : false
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
def blank_between?(begin_pos, end_pos)
|
|
347
|
+
range_between(begin_pos, end_pos).source.strip.empty?
|
|
286
348
|
end
|
|
287
349
|
|
|
288
350
|
# Locate where to break a string that is too long, ensuring that escape characters
|
|
@@ -294,24 +356,57 @@ module RuboCop
|
|
|
294
356
|
relevant_substr = largest_possible_string(node)
|
|
295
357
|
|
|
296
358
|
if (space_pos = breakable_space_position(node, relevant_substr))
|
|
297
|
-
|
|
298
|
-
|
|
359
|
+
# A space can separate codepoints inside a braced unicode escape.
|
|
360
|
+
escape_pos = escape_sequence_start(relevant_substr[0..space_pos])
|
|
361
|
+
source_range.resize(escape_pos || (space_pos + 1))
|
|
362
|
+
elsif (escape_pos = escape_sequence_start(relevant_substr))
|
|
299
363
|
source_range.resize(escape_pos)
|
|
300
364
|
else
|
|
301
|
-
|
|
302
|
-
return if adjustment.abs > source_range.size
|
|
303
|
-
|
|
304
|
-
source_range.adjust(end_pos: adjustment)
|
|
365
|
+
breakable_string_range_at_limit(source_range)
|
|
305
366
|
end
|
|
306
367
|
end
|
|
307
368
|
|
|
308
369
|
def breakable_space_position(node, substr)
|
|
309
370
|
limit = string_content_length(node) - 1
|
|
310
|
-
space_pos = substr.
|
|
311
|
-
space_pos =
|
|
371
|
+
space_pos = space_before_word(node, substr.length - 1)
|
|
372
|
+
space_pos = space_before_word(node, limit - 1) if space_pos && space_pos + 1 > limit
|
|
312
373
|
space_pos
|
|
313
374
|
end
|
|
314
375
|
|
|
376
|
+
def space_before_word(node, max_pos)
|
|
377
|
+
return if max_pos.negative?
|
|
378
|
+
|
|
379
|
+
node.source.rindex(/\s(?=\S)/, max_pos)
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
def escape_sequence_start(text)
|
|
383
|
+
text.match(ESCAPE_SEQUENCE_TAIL)&.begin(1)
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
def breakable_string_range_at_limit(source_range)
|
|
387
|
+
adjustment = max - source_range.last_column - 3
|
|
388
|
+
return if adjustment.abs > source_range.size
|
|
389
|
+
|
|
390
|
+
cut = source_range.adjust(end_pos: adjustment)
|
|
391
|
+
cut = cut.resize(size_before_whitespace_run(source_range.source, cut.size))
|
|
392
|
+
escape_pos = escape_sequence_start(cut.source)
|
|
393
|
+
|
|
394
|
+
escape_pos ? source_range.resize(escape_pos) : cut
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
def size_before_whitespace_run(text, size)
|
|
398
|
+
return size if size.zero?
|
|
399
|
+
return size unless text[size]&.match?(/\s/)
|
|
400
|
+
|
|
401
|
+
text.rindex(/\S/, size - 1) || size
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
def blank_rest?(node, break_pos)
|
|
405
|
+
offset = break_pos - node.source_range.begin_pos
|
|
406
|
+
|
|
407
|
+
node.source[offset...string_content_length(node)].strip.empty?
|
|
408
|
+
end
|
|
409
|
+
|
|
315
410
|
def string_content_length(node)
|
|
316
411
|
content_end = node.loc?(:end) ? node.loc.end.begin_pos : node.source_range.end_pos
|
|
317
412
|
|
|
@@ -320,7 +415,18 @@ module RuboCop
|
|
|
320
415
|
|
|
321
416
|
def breakable_dstr_begin_position(node)
|
|
322
417
|
source_range = node.source_range
|
|
323
|
-
|
|
418
|
+
return unless source_range.column < max && source_range.last_column >= max
|
|
419
|
+
return if opens_string?(node)
|
|
420
|
+
|
|
421
|
+
source_range.begin_pos
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
def opens_string?(begin_node)
|
|
425
|
+
quote = begin_node.parent.loc.begin
|
|
426
|
+
|
|
427
|
+
return false unless quote
|
|
428
|
+
|
|
429
|
+
blank_between?(quote.end_pos, begin_node.source_range.begin_pos)
|
|
324
430
|
end
|
|
325
431
|
|
|
326
432
|
def breakable_range_by_line_index
|
|
@@ -335,6 +441,10 @@ module RuboCop
|
|
|
335
441
|
@breakable_string_delimiters ||= {}
|
|
336
442
|
end
|
|
337
443
|
|
|
444
|
+
def breakable_strings
|
|
445
|
+
@breakable_strings ||= {}
|
|
446
|
+
end
|
|
447
|
+
|
|
338
448
|
def heredocs
|
|
339
449
|
@heredocs ||= extract_heredocs(processed_source.ast)
|
|
340
450
|
end
|
|
@@ -391,10 +501,38 @@ module RuboCop
|
|
|
391
501
|
"\n"
|
|
392
502
|
end
|
|
393
503
|
|
|
394
|
-
|
|
504
|
+
break_ranges(line_index).each do |range|
|
|
505
|
+
corrector.insert_before(range, insertion)
|
|
506
|
+
end
|
|
395
507
|
end
|
|
396
508
|
end
|
|
397
509
|
|
|
510
|
+
def break_ranges(line_index)
|
|
511
|
+
return [] if breakable_range.nil?
|
|
512
|
+
return [breakable_range] unless (node = breakable_strings[line_index])&.loc?(:end)
|
|
513
|
+
|
|
514
|
+
string_break_ranges(node, breakable_string_delimiters[line_index])
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
def string_break_ranges(node, delimiter)
|
|
518
|
+
ranges = [breakable_range]
|
|
519
|
+
pos = breakable_range.begin_pos
|
|
520
|
+
|
|
521
|
+
while (pos = next_string_break_position(node, pos, delimiter))
|
|
522
|
+
ranges << range_between(pos, pos + 1)
|
|
523
|
+
end
|
|
524
|
+
|
|
525
|
+
ranges
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
def next_string_break_position(node, pos, delimiter)
|
|
529
|
+
rest = parse("#{delimiter}#{node.source_range.with(begin_pos: pos).source}").ast
|
|
530
|
+
return unless rest&.str_type?
|
|
531
|
+
return unless (rest_pos = breakable_string_position(rest))
|
|
532
|
+
|
|
533
|
+
pos + rest_pos - delimiter.length
|
|
534
|
+
end
|
|
535
|
+
|
|
398
536
|
def excess_range(uri_range, line, line_index)
|
|
399
537
|
excessive_position = if uri_range && uri_range.begin < max
|
|
400
538
|
uri_range.end
|
|
@@ -511,16 +649,10 @@ module RuboCop
|
|
|
511
649
|
# `Max` - end delimiter (quote) - continuation characters (space and slash)
|
|
512
650
|
max_length = max - 3
|
|
513
651
|
# Offset by the string's starting column so the broken line actually fits
|
|
514
|
-
# within `Max
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
max_length -= if same_line?(node, node.parent)
|
|
519
|
-
column_offset_between(node.loc, node.parent.loc)
|
|
520
|
-
else
|
|
521
|
-
node.loc.column
|
|
522
|
-
end
|
|
523
|
-
node.source[0...(max_length)]
|
|
652
|
+
# within `Max`, whatever precedes the string on its line.
|
|
653
|
+
max_length -= node.loc.column
|
|
654
|
+
|
|
655
|
+
node.source[0, [max_length, 0].max]
|
|
524
656
|
end
|
|
525
657
|
end
|
|
526
658
|
end
|
|
@@ -106,6 +106,18 @@ module RuboCop
|
|
|
106
106
|
ALWAYS_SAME_LINE_MESSAGE = 'The closing array brace must be on the ' \
|
|
107
107
|
'same line as the last array element.'
|
|
108
108
|
|
|
109
|
+
# Moving the closing bracket after a hash literal or method call element while
|
|
110
|
+
# `Layout/MultilineHashBraceLayout` or `Layout/MultilineMethodCallBraceLayout` moves
|
|
111
|
+
# that element's closing brace in the same pass places the bracket after whatever
|
|
112
|
+
# follows the moved brace, such as a comment.
|
|
113
|
+
# Moving it while `Style/ConcatArrayLiterals` removes the brackets in the same pass
|
|
114
|
+
# leaves the bracket behind.
|
|
115
|
+
def self.autocorrect_incompatible_with
|
|
116
|
+
[
|
|
117
|
+
Layout::MultilineHashBraceLayout, Layout::MultilineMethodCallBraceLayout, Style::ConcatArrayLiterals
|
|
118
|
+
]
|
|
119
|
+
end
|
|
120
|
+
|
|
109
121
|
def on_array(node)
|
|
110
122
|
check_brace_layout(node)
|
|
111
123
|
end
|