rubocop 1.91.0 → 1.92.2
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.rb +0 -4
- 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_obsoletion.rb +9 -0
- 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_after_module_inclusion.rb +1 -1
- 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 +21 -25
- data/lib/rubocop/cop/layout/extra_spacing.rb +21 -6
- 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 +176 -26
- 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 +16 -3
- 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_around_operators.rb +31 -4
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +16 -1
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +15 -2
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +32 -9
- data/lib/rubocop/cop/layout/space_inside_range_literal.rb +29 -11
- 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/interpolation_check.rb +20 -17
- 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/nested_percent_literal.rb +3 -0
- data/lib/rubocop/cop/lint/number_conversion.rb +3 -1
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +22 -1
- data/lib/rubocop/cop/lint/percent_string_array.rb +75 -9
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +39 -9
- data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +13 -2
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +11 -4
- 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/comments_help.rb +1 -1
- 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 +41 -6
- 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 +39 -5
- data/lib/rubocop/cop/mixin/trailing_comma.rb +1 -1
- 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 +37 -10
- 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_equality.rb +14 -3
- data/lib/rubocop/cop/style/case_like_if.rb +6 -3
- data/lib/rubocop/cop/style/class_and_module_children.rb +57 -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 +104 -11
- 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 +37 -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 +42 -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 +26 -2
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +26 -3
- data/lib/rubocop/cop/style/method_def_parentheses.rb +38 -4
- 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 +28 -5
- data/lib/rubocop/cop/style/one_line_conditional.rb +13 -2
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +19 -1
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +14 -3
- data/lib/rubocop/cop/style/quoted_symbols.rb +5 -7
- data/lib/rubocop/cop/style/raise_args.rb +80 -11
- data/lib/rubocop/cop/style/reduce_to_hash.rb +47 -33
- data/lib/rubocop/cop/style/redundant_begin.rb +45 -5
- 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 +27 -11
- 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.rb +9 -1
- 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 +42 -4
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +29 -5
- data/lib/rubocop/cop/style/string_concatenation.rb +21 -4
- 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 +36 -8
- data/lib/rubocop/remote_config.rb +4 -1
- data/lib/rubocop/result_cache.rb +20 -13
- data/lib/rubocop/runner.rb +110 -42
- 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
|
@@ -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,8 +122,10 @@ 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
|
|
128
|
+
@heredoc_openers = nil
|
|
111
129
|
|
|
112
130
|
return unless processed_source.raw_source.include?(';')
|
|
113
131
|
|
|
@@ -191,35 +209,69 @@ module RuboCop
|
|
|
191
209
|
def check_for_breakable_node(node)
|
|
192
210
|
breakable_node = extract_breakable_node(node, max)
|
|
193
211
|
return if breakable_node.nil?
|
|
212
|
+
return if compact_nested_array_break?(node, breakable_node)
|
|
194
213
|
|
|
195
214
|
line_index = breakable_node.first_line - 1
|
|
196
215
|
range = breakable_node.source_range
|
|
197
216
|
|
|
198
217
|
existing = breakable_range_by_line_index[line_index]
|
|
199
|
-
return if existing
|
|
218
|
+
return if existing || after_heredoc_opener?(range)
|
|
200
219
|
|
|
201
220
|
breakable_range_by_line_index[line_index] = range
|
|
202
221
|
end
|
|
203
222
|
|
|
223
|
+
def after_heredoc_opener?(range)
|
|
224
|
+
heredoc_openers.any? do |opener|
|
|
225
|
+
opener.line == range.line && opener.begin_pos < range.begin_pos
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def heredoc_openers
|
|
230
|
+
ast = processed_source.ast
|
|
231
|
+
return [] if ast.nil?
|
|
232
|
+
|
|
233
|
+
@heredoc_openers ||= ast.each_node(:any_str).select(&:heredoc?).map(&:source_range)
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def compact_nested_array_break?(node, breakable_node)
|
|
237
|
+
return false if !node.array_type? || !node.square_brackets?
|
|
238
|
+
return false unless breakable_node.equal?(node.children.first)
|
|
239
|
+
return false unless breakable_node.source.start_with?('[')
|
|
240
|
+
|
|
241
|
+
compact_array_brackets_enforced?
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def compact_array_brackets_enforced?
|
|
245
|
+
return false unless config.cop_enabled?('Layout/SpaceInsideArrayLiteralBrackets')
|
|
246
|
+
|
|
247
|
+
config.for_cop('Layout/SpaceInsideArrayLiteralBrackets')['EnforcedStyle'] == 'compact'
|
|
248
|
+
end
|
|
249
|
+
|
|
204
250
|
def check_for_breakable_semicolons(processed_source)
|
|
205
251
|
tokens = processed_source.tokens.select { |t| t.type == :tSEMI }
|
|
206
252
|
tokens.reverse_each do |token|
|
|
207
253
|
range = breakable_range_after_semicolon(token)
|
|
208
|
-
|
|
254
|
+
next if range.nil? || after_heredoc_opener?(range)
|
|
255
|
+
|
|
256
|
+
breakable_range_by_line_index[range.line - 1] = range
|
|
209
257
|
end
|
|
210
258
|
end
|
|
211
259
|
|
|
212
260
|
def check_for_breakable_block(block_node)
|
|
213
261
|
return unless block_node.single_line?
|
|
214
|
-
return if receiver_contains_heredoc?(block_node)
|
|
215
262
|
|
|
216
263
|
line_index = block_node.loc.line - 1
|
|
264
|
+
return if breakable_string_delimiters[line_index]
|
|
265
|
+
|
|
217
266
|
range = breakable_block_range(block_node)
|
|
218
267
|
pos = range.begin_pos + 1
|
|
268
|
+
range = range_between(pos, pos + 1)
|
|
269
|
+
return if after_heredoc_opener?(range)
|
|
219
270
|
|
|
220
|
-
breakable_range_by_line_index[line_index] =
|
|
271
|
+
breakable_range_by_line_index[line_index] = range
|
|
221
272
|
end
|
|
222
273
|
|
|
274
|
+
# rubocop:disable-next Metrics/AbcSize
|
|
223
275
|
def check_for_breakable_str(node)
|
|
224
276
|
line_index = node.loc.line - 1
|
|
225
277
|
return if breakable_range_by_line_index[line_index]
|
|
@@ -230,6 +282,7 @@ module RuboCop
|
|
|
230
282
|
|
|
231
283
|
breakable_range_by_line_index[line_index] = range_between(pos, pos + 1)
|
|
232
284
|
breakable_string_delimiters[line_index] = delimiter
|
|
285
|
+
breakable_strings[line_index] = node
|
|
233
286
|
end
|
|
234
287
|
|
|
235
288
|
def check_for_breakable_dstr(node) # rubocop:disable Metrics/AbcSize
|
|
@@ -253,7 +306,8 @@ module RuboCop
|
|
|
253
306
|
!node.heredoc? &&
|
|
254
307
|
# TODO: strings inside hashes, kwargs and arrays are currently ignored,
|
|
255
308
|
# but could be considered in the future
|
|
256
|
-
!node.parent&.type?(:pair, :kwoptarg, :array)
|
|
309
|
+
!node.parent&.type?(:pair, :kwoptarg, :array) &&
|
|
310
|
+
!after_heredoc_opener?(node.source_range)
|
|
257
311
|
end
|
|
258
312
|
|
|
259
313
|
def breakable_block_range(block_node)
|
|
@@ -282,7 +336,33 @@ module RuboCop
|
|
|
282
336
|
return if source_range.last_column < max
|
|
283
337
|
return unless (pos = breakable_string_range(node))
|
|
284
338
|
|
|
285
|
-
|
|
339
|
+
content_begin_pos = node.loc?(:begin) ? node.loc.begin.end_pos : source_range.begin_pos
|
|
340
|
+
if blank_left_part?(node, content_begin_pos, pos)
|
|
341
|
+
pos = breakable_string_range_at_limit(source_range)
|
|
342
|
+
end
|
|
343
|
+
pos.end_pos if pos && leaves_two_parts?(node, content_begin_pos, pos)
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
def leaves_two_parts?(node, content_begin_pos, pos)
|
|
347
|
+
pos.end_pos > content_begin_pos && !blank_rest?(node, pos.end_pos)
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
def blank_left_part?(node, content_begin_pos, pos)
|
|
351
|
+
return false unless pos.end_pos > content_begin_pos
|
|
352
|
+
return false unless starts_after_quote?(node)
|
|
353
|
+
|
|
354
|
+
blank_between?(content_begin_pos, pos.end_pos)
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
def starts_after_quote?(node)
|
|
358
|
+
return true if node.loc?(:begin)
|
|
359
|
+
|
|
360
|
+
quote = node.parent&.loc&.begin if node.parent&.dstr_type?
|
|
361
|
+
quote ? quote.end_pos == node.source_range.begin_pos : false
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
def blank_between?(begin_pos, end_pos)
|
|
365
|
+
range_between(begin_pos, end_pos).source.strip.empty?
|
|
286
366
|
end
|
|
287
367
|
|
|
288
368
|
# Locate where to break a string that is too long, ensuring that escape characters
|
|
@@ -294,24 +374,57 @@ module RuboCop
|
|
|
294
374
|
relevant_substr = largest_possible_string(node)
|
|
295
375
|
|
|
296
376
|
if (space_pos = breakable_space_position(node, relevant_substr))
|
|
297
|
-
|
|
298
|
-
|
|
377
|
+
# A space can separate codepoints inside a braced unicode escape.
|
|
378
|
+
escape_pos = escape_sequence_start(relevant_substr[0..space_pos])
|
|
379
|
+
source_range.resize(escape_pos || (space_pos + 1))
|
|
380
|
+
elsif (escape_pos = escape_sequence_start(relevant_substr))
|
|
299
381
|
source_range.resize(escape_pos)
|
|
300
382
|
else
|
|
301
|
-
|
|
302
|
-
return if adjustment.abs > source_range.size
|
|
303
|
-
|
|
304
|
-
source_range.adjust(end_pos: adjustment)
|
|
383
|
+
breakable_string_range_at_limit(source_range)
|
|
305
384
|
end
|
|
306
385
|
end
|
|
307
386
|
|
|
308
387
|
def breakable_space_position(node, substr)
|
|
309
388
|
limit = string_content_length(node) - 1
|
|
310
|
-
space_pos = substr.
|
|
311
|
-
space_pos =
|
|
389
|
+
space_pos = space_before_word(node, substr.length - 1)
|
|
390
|
+
space_pos = space_before_word(node, limit - 1) if space_pos && space_pos + 1 > limit
|
|
312
391
|
space_pos
|
|
313
392
|
end
|
|
314
393
|
|
|
394
|
+
def space_before_word(node, max_pos)
|
|
395
|
+
return if max_pos.negative?
|
|
396
|
+
|
|
397
|
+
node.source.rindex(/\s(?=\S)/, max_pos)
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
def escape_sequence_start(text)
|
|
401
|
+
text.match(ESCAPE_SEQUENCE_TAIL)&.begin(1)
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
def breakable_string_range_at_limit(source_range)
|
|
405
|
+
adjustment = max - source_range.last_column - 3
|
|
406
|
+
return if adjustment.abs > source_range.size
|
|
407
|
+
|
|
408
|
+
cut = source_range.adjust(end_pos: adjustment)
|
|
409
|
+
cut = cut.resize(size_before_whitespace_run(source_range.source, cut.size))
|
|
410
|
+
escape_pos = escape_sequence_start(cut.source)
|
|
411
|
+
|
|
412
|
+
escape_pos ? source_range.resize(escape_pos) : cut
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
def size_before_whitespace_run(text, size)
|
|
416
|
+
return size if size.zero?
|
|
417
|
+
return size unless text[size]&.match?(/\s/)
|
|
418
|
+
|
|
419
|
+
text.rindex(/\S/, size - 1) || size
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
def blank_rest?(node, break_pos)
|
|
423
|
+
offset = break_pos - node.source_range.begin_pos
|
|
424
|
+
|
|
425
|
+
node.source[offset...string_content_length(node)].strip.empty?
|
|
426
|
+
end
|
|
427
|
+
|
|
315
428
|
def string_content_length(node)
|
|
316
429
|
content_end = node.loc?(:end) ? node.loc.end.begin_pos : node.source_range.end_pos
|
|
317
430
|
|
|
@@ -320,7 +433,18 @@ module RuboCop
|
|
|
320
433
|
|
|
321
434
|
def breakable_dstr_begin_position(node)
|
|
322
435
|
source_range = node.source_range
|
|
323
|
-
|
|
436
|
+
return unless source_range.column < max && source_range.last_column >= max
|
|
437
|
+
return if opens_string?(node)
|
|
438
|
+
|
|
439
|
+
source_range.begin_pos
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
def opens_string?(begin_node)
|
|
443
|
+
quote = begin_node.parent.loc.begin
|
|
444
|
+
|
|
445
|
+
return false unless quote
|
|
446
|
+
|
|
447
|
+
blank_between?(quote.end_pos, begin_node.source_range.begin_pos)
|
|
324
448
|
end
|
|
325
449
|
|
|
326
450
|
def breakable_range_by_line_index
|
|
@@ -335,6 +459,10 @@ module RuboCop
|
|
|
335
459
|
@breakable_string_delimiters ||= {}
|
|
336
460
|
end
|
|
337
461
|
|
|
462
|
+
def breakable_strings
|
|
463
|
+
@breakable_strings ||= {}
|
|
464
|
+
end
|
|
465
|
+
|
|
338
466
|
def heredocs
|
|
339
467
|
@heredocs ||= extract_heredocs(processed_source.ast)
|
|
340
468
|
end
|
|
@@ -391,8 +519,36 @@ module RuboCop
|
|
|
391
519
|
"\n"
|
|
392
520
|
end
|
|
393
521
|
|
|
394
|
-
|
|
522
|
+
break_ranges(line_index).each do |range|
|
|
523
|
+
corrector.insert_before(range, insertion)
|
|
524
|
+
end
|
|
525
|
+
end
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
def break_ranges(line_index)
|
|
529
|
+
return [] if breakable_range.nil?
|
|
530
|
+
return [breakable_range] unless (node = breakable_strings[line_index])&.loc?(:end)
|
|
531
|
+
|
|
532
|
+
string_break_ranges(node, breakable_string_delimiters[line_index])
|
|
533
|
+
end
|
|
534
|
+
|
|
535
|
+
def string_break_ranges(node, delimiter)
|
|
536
|
+
ranges = [breakable_range]
|
|
537
|
+
pos = breakable_range.begin_pos
|
|
538
|
+
|
|
539
|
+
while (pos = next_string_break_position(node, pos, delimiter))
|
|
540
|
+
ranges << range_between(pos, pos + 1)
|
|
395
541
|
end
|
|
542
|
+
|
|
543
|
+
ranges
|
|
544
|
+
end
|
|
545
|
+
|
|
546
|
+
def next_string_break_position(node, pos, delimiter)
|
|
547
|
+
rest = parse("#{delimiter}#{node.source_range.with(begin_pos: pos).source}").ast
|
|
548
|
+
return unless rest&.str_type?
|
|
549
|
+
return unless (rest_pos = breakable_string_position(rest))
|
|
550
|
+
|
|
551
|
+
pos + rest_pos - delimiter.length
|
|
396
552
|
end
|
|
397
553
|
|
|
398
554
|
def excess_range(uri_range, line, line_index)
|
|
@@ -511,16 +667,10 @@ module RuboCop
|
|
|
511
667
|
# `Max` - end delimiter (quote) - continuation characters (space and slash)
|
|
512
668
|
max_length = max - 3
|
|
513
669
|
# 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)]
|
|
670
|
+
# within `Max`, whatever precedes the string on its line.
|
|
671
|
+
max_length -= node.loc.column
|
|
672
|
+
|
|
673
|
+
node.source[0, [max_length, 0].max]
|
|
524
674
|
end
|
|
525
675
|
end
|
|
526
676
|
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
|
|
@@ -56,6 +56,13 @@ module RuboCop
|
|
|
56
56
|
ARG_MSG = 'Block argument expression is not on the same line as the block start.'
|
|
57
57
|
PIPE_SIZE = '|'.length
|
|
58
58
|
|
|
59
|
+
# `Style/Lambda` moves the block arguments of `lambda` into `->(...)`, and
|
|
60
|
+
# `Style/ItBlockParameter` and `Style/HashEachMethods` remove some or all of them,
|
|
61
|
+
# in the same pass, while this cop moves them next to the block start.
|
|
62
|
+
def self.autocorrect_incompatible_with
|
|
63
|
+
[Style::HashEachMethods, Style::ItBlockParameter, Style::Lambda]
|
|
64
|
+
end
|
|
65
|
+
|
|
59
66
|
def on_block(node)
|
|
60
67
|
return if node.single_line?
|
|
61
68
|
|
|
@@ -155,7 +162,7 @@ module RuboCop
|
|
|
155
162
|
end
|
|
156
163
|
|
|
157
164
|
def include_trailing_comma?(args)
|
|
158
|
-
arg_count = args.each_descendant(
|
|
165
|
+
arg_count = args.each_descendant.count(&:argument_type?)
|
|
159
166
|
arg_count == 1 && args.source.include?(',')
|
|
160
167
|
end
|
|
161
168
|
end
|
|
@@ -106,6 +106,15 @@ module RuboCop
|
|
|
106
106
|
ALWAYS_SAME_LINE_MESSAGE = 'Closing hash brace must be on the same ' \
|
|
107
107
|
'line as the last hash element.'
|
|
108
108
|
|
|
109
|
+
# Moving the closing brace after a method call value while
|
|
110
|
+
# `Layout/MultilineMethodCallBraceLayout` moves that call's closing parenthesis
|
|
111
|
+
# before a comment in the same pass places the brace after the comment.
|
|
112
|
+
# Moving it while `Style/HashAsLastArrayItem` or `Style/RedundantDoubleSplatHashBraces`
|
|
113
|
+
# removes the braces in the same pass leaves the brace behind.
|
|
114
|
+
def self.autocorrect_incompatible_with
|
|
115
|
+
[Layout::MultilineMethodCallBraceLayout, Style::HashAsLastArrayItem, Style::RedundantDoubleSplatHashBraces]
|
|
116
|
+
end
|
|
117
|
+
|
|
109
118
|
def on_hash(node)
|
|
110
119
|
check_brace_layout(node)
|
|
111
120
|
end
|
|
@@ -106,6 +106,12 @@ module RuboCop
|
|
|
106
106
|
ALWAYS_SAME_LINE_MESSAGE = 'Closing method call brace must be on ' \
|
|
107
107
|
'the same line as the last argument.'
|
|
108
108
|
|
|
109
|
+
# Moving the closing parenthesis and removing it under `omit_parentheses` in the same pass
|
|
110
|
+
# leaves the moved parenthesis behind.
|
|
111
|
+
def self.autocorrect_incompatible_with
|
|
112
|
+
[Style::MethodCallWithArgsParentheses]
|
|
113
|
+
end
|
|
114
|
+
|
|
109
115
|
def on_send(node)
|
|
110
116
|
check_brace_layout(node)
|
|
111
117
|
end
|
|
@@ -73,14 +73,28 @@ module RuboCop
|
|
|
73
73
|
end
|
|
74
74
|
|
|
75
75
|
def find_pair_ancestor(node)
|
|
76
|
+
child = node
|
|
76
77
|
node.each_ancestor do |ancestor|
|
|
77
78
|
return ancestor if ancestor.pair_type?
|
|
78
79
|
break if grouped_expression?(ancestor) || inside_arg_list_parentheses?(node, ancestor)
|
|
80
|
+
break if inside_body?(ancestor, child)
|
|
81
|
+
|
|
82
|
+
child = ancestor
|
|
79
83
|
end
|
|
80
84
|
|
|
81
85
|
nil
|
|
82
86
|
end
|
|
83
87
|
|
|
88
|
+
# A block, `begin`, `if` or loop body is a separate set of statements, so
|
|
89
|
+
# a method chain in it is not the value of a hash pair the body is nested in.
|
|
90
|
+
# The send node of a block is still part of the value.
|
|
91
|
+
def inside_body?(ancestor, child)
|
|
92
|
+
return !child.equal?(ancestor.send_node) if ancestor.any_block_type?
|
|
93
|
+
return !ancestor.ternary? if ancestor.if_type?
|
|
94
|
+
|
|
95
|
+
ancestor.type?(:kwbegin, :while, :until, :for)
|
|
96
|
+
end
|
|
97
|
+
|
|
84
98
|
def unwrap_block_node(node)
|
|
85
99
|
node&.any_block_type? ? node.send_node : node
|
|
86
100
|
end
|
|
@@ -88,7 +102,7 @@ module RuboCop
|
|
|
88
102
|
def autocorrect(corrector, node)
|
|
89
103
|
if @send_node.block_node
|
|
90
104
|
correct_selector_only(corrector, node)
|
|
91
|
-
correct_block(corrector, @send_node.block_node)
|
|
105
|
+
correct_block(corrector, @send_node.block_node, node.first_line)
|
|
92
106
|
else
|
|
93
107
|
AlignmentCorrector.correct(corrector, processed_source, node, @column_delta)
|
|
94
108
|
end
|
|
@@ -100,10 +114,21 @@ module RuboCop
|
|
|
100
114
|
AlignmentCorrector.correct(corrector, processed_source, selector_range, @column_delta)
|
|
101
115
|
end
|
|
102
116
|
|
|
103
|
-
def correct_block(corrector, block_node)
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
117
|
+
def correct_block(corrector, block_node, selector_line)
|
|
118
|
+
lines_to_shift = block_lines(block_node) - [selector_line]
|
|
119
|
+
|
|
120
|
+
lines_to_shift.each do |line|
|
|
121
|
+
line_range = processed_source.buffer.line_range(line)
|
|
122
|
+
|
|
123
|
+
AlignmentCorrector.correct(corrector, processed_source, line_range, @column_delta)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def block_lines(block_node)
|
|
128
|
+
body = block_node.body
|
|
129
|
+
lines = body ? (body.first_line..body.last_line).to_a : []
|
|
130
|
+
|
|
131
|
+
(lines << block_node.loc.end.line).uniq
|
|
107
132
|
end
|
|
108
133
|
|
|
109
134
|
def relevant_node?(send_node)
|
|
@@ -118,6 +118,10 @@ module RuboCop
|
|
|
118
118
|
ALWAYS_SAME_LINE_MESSAGE = 'Closing method definition brace must be ' \
|
|
119
119
|
'on the same line as the last parameter.'
|
|
120
120
|
|
|
121
|
+
def self.autocorrect_incompatible_with
|
|
122
|
+
[Style::MultilineMethodSignature]
|
|
123
|
+
end
|
|
124
|
+
|
|
121
125
|
def on_def(node)
|
|
122
126
|
check_brace_layout(node.arguments)
|
|
123
127
|
end
|
|
@@ -54,6 +54,11 @@ module RuboCop
|
|
|
54
54
|
|
|
55
55
|
MSG = 'Redundant line break detected.'
|
|
56
56
|
|
|
57
|
+
def on_new_investigation
|
|
58
|
+
super
|
|
59
|
+
@offense_line_ranges = []
|
|
60
|
+
end
|
|
61
|
+
|
|
57
62
|
def on_lvasgn(node)
|
|
58
63
|
super unless end_with_percent_blank_string?(processed_source)
|
|
59
64
|
end
|
|
@@ -77,12 +82,15 @@ module RuboCop
|
|
|
77
82
|
end
|
|
78
83
|
|
|
79
84
|
def check_assignment(node, _rhs)
|
|
80
|
-
return unless offense?(node)
|
|
85
|
+
return unless offense?(node) && !part_of_ignored_node?(node)
|
|
81
86
|
|
|
82
87
|
register_offense(node)
|
|
83
88
|
end
|
|
84
89
|
|
|
85
90
|
def register_offense(node)
|
|
91
|
+
line_range = joined_line_range(node)
|
|
92
|
+
return if too_long_as_single_line?(line_range)
|
|
93
|
+
|
|
86
94
|
# The exact single-line correction is verified to parse equivalently
|
|
87
95
|
# before the offense is registered, so a join that would change how
|
|
88
96
|
# the code parses is never reported or offered.
|
|
@@ -92,6 +100,19 @@ module RuboCop
|
|
|
92
100
|
corrector.replace(node, to_single_line(node.source).strip)
|
|
93
101
|
end
|
|
94
102
|
ignore_node(node)
|
|
103
|
+
@offense_line_ranges.reject! { |range| line_range.cover?(range) }
|
|
104
|
+
@offense_line_ranges << line_range
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Offenses registered in the same pass that share a line with `node`
|
|
108
|
+
# get joined onto that line too, so the combined line has to fit.
|
|
109
|
+
def joined_line_range(node)
|
|
110
|
+
sharing_ranges = @offense_line_ranges.select do |range|
|
|
111
|
+
range.begin <= node.last_line && node.first_line <= range.end
|
|
112
|
+
end
|
|
113
|
+
lines = [node.first_line, node.last_line, *sharing_ranges.flat_map(&:minmax)]
|
|
114
|
+
|
|
115
|
+
lines.min..lines.max
|
|
95
116
|
end
|
|
96
117
|
|
|
97
118
|
def apply_reparse_correction(corrector, node)
|
|
@@ -22,6 +22,7 @@ module RuboCop
|
|
|
22
22
|
# puts 'error'
|
|
23
23
|
# end
|
|
24
24
|
class RescueEnsureAlignment < Base
|
|
25
|
+
include Alignment
|
|
25
26
|
include RangeHelp
|
|
26
27
|
include EndKeywordAlignment
|
|
27
28
|
extend AutoCorrector
|
|
@@ -74,9 +75,10 @@ module RuboCop
|
|
|
74
75
|
# Some inline node is sitting before current node.
|
|
75
76
|
return nil unless whitespace.source.strip.empty?
|
|
76
77
|
|
|
77
|
-
|
|
78
|
+
indentation = alignment_indentation(alignment_location)
|
|
79
|
+
return nil if indentation.nil?
|
|
78
80
|
|
|
79
|
-
corrector.replace(whitespace,
|
|
81
|
+
corrector.replace(whitespace, indentation)
|
|
80
82
|
end
|
|
81
83
|
|
|
82
84
|
def format_message(alignment_node, alignment_loc, kw_loc)
|
|
@@ -91,6 +93,17 @@ module RuboCop
|
|
|
91
93
|
)
|
|
92
94
|
end
|
|
93
95
|
|
|
96
|
+
# A run of spaces sized to the target column would be turned back into tabs by
|
|
97
|
+
# `Layout/IndentationStyle`, generally landing on a different column, so under
|
|
98
|
+
# tabs the target line's own indentation is reused. There is nothing to reuse
|
|
99
|
+
# when the target does not start its line.
|
|
100
|
+
def alignment_indentation(location)
|
|
101
|
+
return ' ' * location.column unless using_tabs?
|
|
102
|
+
return unless begins_its_line?(location)
|
|
103
|
+
|
|
104
|
+
location.source_line[/\A\s*/]
|
|
105
|
+
end
|
|
106
|
+
|
|
94
107
|
# rubocop:disable-next Metrics/AbcSize, Metrics/MethodLength
|
|
95
108
|
def alignment_source(node, starting_loc)
|
|
96
109
|
ending_loc =
|
|
@@ -102,7 +115,7 @@ module RuboCop
|
|
|
102
115
|
node.loc.name
|
|
103
116
|
when :sclass
|
|
104
117
|
node.identifier.source_range
|
|
105
|
-
when :masgn
|
|
118
|
+
when :masgn, :op_asgn, :or_asgn, :and_asgn
|
|
106
119
|
node.lhs.source_range
|
|
107
120
|
else
|
|
108
121
|
# It is a wrapper with receiver of object attribute or access modifier.
|
|
@@ -25,13 +25,17 @@ module RuboCop
|
|
|
25
25
|
|
|
26
26
|
MSG = 'Put method call on a separate line if chained to a single line block.'
|
|
27
27
|
|
|
28
|
+
# These cops rewrite a method chained to the block in the same pass,
|
|
29
|
+
# which must not start a line of its own.
|
|
28
30
|
def self.autocorrect_incompatible_with
|
|
29
|
-
[Style::MapToHash]
|
|
31
|
+
[Style::FloatDivision, Style::MapToHash, Style::MapToSet, Style::NilComparison, Style::RedundantSort]
|
|
30
32
|
end
|
|
31
33
|
|
|
32
34
|
def on_send(node)
|
|
33
35
|
range = offending_range(node)
|
|
34
|
-
|
|
36
|
+
return if !range || heredoc_opened_before?(node.receiver, range)
|
|
37
|
+
|
|
38
|
+
add_offense(range) { |corrector| corrector.insert_before(range, "\n") }
|
|
35
39
|
end
|
|
36
40
|
alias on_csend on_send
|
|
37
41
|
|
|
@@ -63,6 +67,10 @@ module RuboCop
|
|
|
63
67
|
# l.(1) has no selector, so we use the opening parenthesis instead
|
|
64
68
|
node.loc.selector || node.loc.begin
|
|
65
69
|
end
|
|
70
|
+
|
|
71
|
+
def heredoc_opened_before?(receiver, range)
|
|
72
|
+
receiver.each_node(:any_str).any? { |str| str.heredoc? && str.first_line == range.line }
|
|
73
|
+
end
|
|
66
74
|
end
|
|
67
75
|
end
|
|
68
76
|
end
|
|
@@ -20,6 +20,7 @@ module RuboCop
|
|
|
20
20
|
|
|
21
21
|
def on_send(node)
|
|
22
22
|
return unless node.prefix_bang? && whitespace_after_operator?(node)
|
|
23
|
+
return if unary_tilde?(node.receiver)
|
|
23
24
|
|
|
24
25
|
add_offense(node) do |corrector|
|
|
25
26
|
corrector.remove(
|
|
@@ -33,6 +34,10 @@ module RuboCop
|
|
|
33
34
|
def whitespace_after_operator?(node)
|
|
34
35
|
node.receiver.source_range.begin_pos - node.source_range.begin_pos > 1
|
|
35
36
|
end
|
|
37
|
+
|
|
38
|
+
def unary_tilde?(receiver)
|
|
39
|
+
receiver.send_type? && receiver.unary_operation? && receiver.method?(:~)
|
|
40
|
+
end
|
|
36
41
|
end
|
|
37
42
|
end
|
|
38
43
|
end
|
|
@@ -6,7 +6,8 @@ module RuboCop
|
|
|
6
6
|
# Checks the spacing inside and after block parameters pipes. Line breaks
|
|
7
7
|
# inside parameter pipes are checked by `Layout/MultilineBlockLayout` and
|
|
8
8
|
# not by this cop. Spaces inside a lambda's parameter parentheses are left
|
|
9
|
-
# to `Layout/SpaceInsideParens` when that cop
|
|
9
|
+
# to `Layout/SpaceInsideParens` when that cop is enabled, so the examples
|
|
10
|
+
# below apply to a lambda only when it is not.
|
|
10
11
|
#
|
|
11
12
|
# @example EnforcedStyleInsidePipes: no_space (default)
|
|
12
13
|
# # bad
|
|
@@ -35,7 +36,7 @@ module RuboCop
|
|
|
35
36
|
|
|
36
37
|
return unless node.arguments? && pipes?(arguments)
|
|
37
38
|
|
|
38
|
-
check_inside_pipes(arguments) unless
|
|
39
|
+
check_inside_pipes(arguments) unless checked_by_space_inside_parens?(arguments)
|
|
39
40
|
check_after_closing_pipe(arguments) if node.body
|
|
40
41
|
check_each_arg(arguments)
|
|
41
42
|
end
|
|
@@ -54,14 +55,8 @@ module RuboCop
|
|
|
54
55
|
'EnforcedStyleInsidePipes'
|
|
55
56
|
end
|
|
56
57
|
|
|
57
|
-
def
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
case config.for_enabled_cop('Layout/SpaceInsideParens')['EnforcedStyle']
|
|
61
|
-
when 'no_space' then style == :space
|
|
62
|
-
when 'space', 'compact' then style == :no_space
|
|
63
|
-
else false
|
|
64
|
-
end
|
|
58
|
+
def checked_by_space_inside_parens?(arguments)
|
|
59
|
+
arguments.loc.begin.source == '(' && config.cop_enabled?('Layout/SpaceInsideParens')
|
|
65
60
|
end
|
|
66
61
|
|
|
67
62
|
def check_inside_pipes(arguments)
|
|
@@ -153,7 +148,7 @@ module RuboCop
|
|
|
153
148
|
if node
|
|
154
149
|
corrector.insert_before(node, ' ')
|
|
155
150
|
else
|
|
156
|
-
corrector.insert_after(
|
|
151
|
+
corrector.insert_after(range_between(space_begin_pos, space_begin_pos), ' ')
|
|
157
152
|
end
|
|
158
153
|
end
|
|
159
154
|
end
|
|
@@ -209,6 +209,7 @@ module RuboCop
|
|
|
209
209
|
end
|
|
210
210
|
|
|
211
211
|
return unless space_after_missing?(range)
|
|
212
|
+
return if block_brace_with_no_space_style?(node, range)
|
|
212
213
|
|
|
213
214
|
add_offense(range, message: format(MSG_AFTER, range: range.source)) do |corrector|
|
|
214
215
|
corrector.insert_after(range, ' ')
|
|
@@ -233,6 +234,15 @@ module RuboCop
|
|
|
233
234
|
!/[\s;,#\\)}\].]/.match?(char)
|
|
234
235
|
end
|
|
235
236
|
|
|
237
|
+
def block_brace_with_no_space_style?(node, range)
|
|
238
|
+
return false unless (parent = node.parent)
|
|
239
|
+
return false unless parent.any_block_type? && parent.loc.begin&.begin_pos == range.end_pos
|
|
240
|
+
|
|
241
|
+
space_before_block_braces_config = config.for_cop('Layout/SpaceBeforeBlockBraces')
|
|
242
|
+
space_before_block_braces_config.fetch('Enabled', true) &&
|
|
243
|
+
space_before_block_braces_config['EnforcedStyle'] == 'no_space'
|
|
244
|
+
end
|
|
245
|
+
|
|
236
246
|
def accepted_opening_delimiter?(range, char)
|
|
237
247
|
return true unless char
|
|
238
248
|
|