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
|
@@ -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
|
|
@@ -35,15 +35,13 @@ module RuboCop
|
|
|
35
35
|
ASSIGNMENT_TYPES = %i[lvasgn ivasgn cvasgn gvasgn].freeze
|
|
36
36
|
|
|
37
37
|
def on_def(node)
|
|
38
|
-
return
|
|
38
|
+
return if !node.body || node.void_context?
|
|
39
39
|
|
|
40
40
|
last_expr = last_expression(node.body)
|
|
41
41
|
return unless setter_call_to_local_variable?(last_expr)
|
|
42
42
|
|
|
43
|
-
tracker = MethodVariableTracker.new(node.body)
|
|
44
43
|
receiver, = *last_expr
|
|
45
|
-
|
|
46
|
-
return unless tracker.contain_local_object?(variable_name)
|
|
44
|
+
return unless contain_local_object?(node.body, receiver)
|
|
47
45
|
|
|
48
46
|
loc_name = receiver.loc.name
|
|
49
47
|
|
|
@@ -66,6 +64,11 @@ module RuboCop
|
|
|
66
64
|
expression.is_a?(Array) ? expression.last : expression
|
|
67
65
|
end
|
|
68
66
|
|
|
67
|
+
def contain_local_object?(body, receiver)
|
|
68
|
+
variable_name, = *receiver
|
|
69
|
+
MethodVariableTracker.new(body).contain_local_object?(variable_name)
|
|
70
|
+
end
|
|
71
|
+
|
|
69
72
|
# This class tracks variable assignments in a method body
|
|
70
73
|
# and if a variable contains object passed as argument at the end of
|
|
71
74
|
# the method.
|
|
@@ -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
|
|
@@ -76,11 +76,7 @@ module RuboCop
|
|
|
76
76
|
def extract_first_element_over_column_limit(node, elements, max)
|
|
77
77
|
line = node.first_line
|
|
78
78
|
|
|
79
|
-
|
|
80
|
-
# can result in changed behavior or a syntax error.
|
|
81
|
-
if node.call_type? && !node.parenthesized? && !first_argument_is_heredoc?(node)
|
|
82
|
-
elements = elements.drop(1)
|
|
83
|
-
end
|
|
79
|
+
elements = elements.drop(1) unless first_element_movable?(node)
|
|
84
80
|
|
|
85
81
|
i = 0
|
|
86
82
|
i += 1 while within_column_limit?(elements[i], max, line)
|
|
@@ -93,23 +89,35 @@ module RuboCop
|
|
|
93
89
|
end
|
|
94
90
|
|
|
95
91
|
# @api private
|
|
96
|
-
|
|
97
|
-
|
|
92
|
+
# If a method call or definition is not parenthesized, the first element cannot be moved,
|
|
93
|
+
# because it can result in changed behavior or a syntax error.
|
|
94
|
+
def first_element_movable?(node)
|
|
95
|
+
return !node.arguments.loc.begin.nil? if node.any_def_type?
|
|
96
|
+
return true if !node.call_type? || node.parenthesized?
|
|
98
97
|
|
|
99
|
-
first_argument.respond_to?(:heredoc?) && first_argument.heredoc?
|
|
98
|
+
node.first_argument.respond_to?(:heredoc?) && node.first_argument.heredoc?
|
|
100
99
|
end
|
|
101
100
|
|
|
102
101
|
# @api private
|
|
103
102
|
# If a `send` or `csend` node contains a heredoc argument, splitting cannot happen
|
|
104
103
|
# after the heredoc or else it will cause a syntax error.
|
|
105
104
|
def shift_elements_for_heredoc_arg(node, elements, index)
|
|
106
|
-
return index unless node.type?(:call, :array)
|
|
105
|
+
return index unless node.type?(:call, :array, :hash)
|
|
106
|
+
return index unless (heredoc_pos = heredoc_begin_position(node))
|
|
107
|
+
|
|
108
|
+
last_safe = elements.rindex { |element| element.source_range.begin_pos <= heredoc_pos }
|
|
109
|
+
return nil if last_safe.nil? ||
|
|
110
|
+
(last_safe.zero? && elements.first.source_range.end_pos > heredoc_pos)
|
|
107
111
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
return nil if heredoc_index.zero?
|
|
112
|
+
[index, last_safe + 1].min
|
|
113
|
+
end
|
|
111
114
|
|
|
112
|
-
|
|
115
|
+
# @api private
|
|
116
|
+
def heredoc_begin_position(node)
|
|
117
|
+
children = node.call_type? ? node.arguments : node.children
|
|
118
|
+
children.flat_map { |child| [child, *child.each_descendant(:any_str)] }
|
|
119
|
+
.find { |descendant| descendant.type?(:any_str) && descendant.heredoc? }
|
|
120
|
+
&.source_range&.begin_pos
|
|
113
121
|
end
|
|
114
122
|
|
|
115
123
|
# @api private
|
|
@@ -128,9 +136,7 @@ module RuboCop
|
|
|
128
136
|
# or redundant edits, we only mark one offense at a time.
|
|
129
137
|
return true if contained_by_breakable_collection_on_same_line?(node)
|
|
130
138
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
false
|
|
139
|
+
contained_by_multiline_collection_that_could_be_broken_up?(node)
|
|
134
140
|
end
|
|
135
141
|
|
|
136
142
|
# @api private
|
|
@@ -145,9 +151,7 @@ module RuboCop
|
|
|
145
151
|
# break before the second argument and the rest of the
|
|
146
152
|
# argument will get auto-formatted onto separate lines
|
|
147
153
|
# by other cops.
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
starts_with_bracket && has_second_element
|
|
154
|
+
starts_with_bracket && elements.length >= 2
|
|
151
155
|
end
|
|
152
156
|
|
|
153
157
|
# @api private
|
|
@@ -5,6 +5,8 @@ module RuboCop
|
|
|
5
5
|
# Checks for code on multiple lines that could be rewritten on a single line
|
|
6
6
|
# without changing semantics or exceeding the `Max` parameter of `Layout/LineLength`.
|
|
7
7
|
module CheckSingleLineSuitability
|
|
8
|
+
include LineLengthHelp
|
|
9
|
+
|
|
8
10
|
def suitable_as_single_line?(node)
|
|
9
11
|
!too_long?(node) &&
|
|
10
12
|
!comment_within?(node) &&
|
|
@@ -14,10 +16,14 @@ module RuboCop
|
|
|
14
16
|
private
|
|
15
17
|
|
|
16
18
|
def too_long?(node)
|
|
19
|
+
too_long_as_single_line?(node.first_line..node.last_line)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def too_long_as_single_line?(line_range)
|
|
17
23
|
return false unless max_line_length
|
|
18
24
|
|
|
19
|
-
lines = processed_source.lines[(
|
|
20
|
-
to_single_line(lines.join("\n"))
|
|
25
|
+
lines = processed_source.lines[(line_range.begin - 1)...line_range.end]
|
|
26
|
+
line_length(to_single_line(lines.join("\n"))) > max_line_length
|
|
21
27
|
end
|
|
22
28
|
|
|
23
29
|
def to_single_line(source)
|
|
@@ -59,12 +59,20 @@ module RuboCop
|
|
|
59
59
|
return node.loc.name if node.casgn_type?
|
|
60
60
|
|
|
61
61
|
if LSP.enabled?
|
|
62
|
-
|
|
63
|
-
node.source_range.begin.join(end_range)
|
|
62
|
+
node.source_range.begin.join(header_end(node))
|
|
64
63
|
else
|
|
65
64
|
node.source_range
|
|
66
65
|
end
|
|
67
66
|
end
|
|
67
|
+
|
|
68
|
+
# Where the header of a definition ends: the name of a class, module or
|
|
69
|
+
# method, the `self` of `class << self`, or the opening of a block.
|
|
70
|
+
def header_end(node)
|
|
71
|
+
return node.loc.name if node.loc?(:name)
|
|
72
|
+
return node.identifier.source_range if node.sclass_type?
|
|
73
|
+
|
|
74
|
+
node.loc.begin
|
|
75
|
+
end
|
|
68
76
|
end
|
|
69
77
|
end
|
|
70
78
|
end
|
|
@@ -66,7 +66,7 @@ module RuboCop
|
|
|
66
66
|
# the line at which the parent node ends.
|
|
67
67
|
# rubocop:disable-next Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
68
68
|
def find_end_line(node)
|
|
69
|
-
if node.if_type?
|
|
69
|
+
if node.if_type? && !node.modifier_form?
|
|
70
70
|
if node.else?
|
|
71
71
|
node.loc.else.line
|
|
72
72
|
elsif node.ternary?
|
|
@@ -5,7 +5,7 @@ module RuboCop
|
|
|
5
5
|
module Layout
|
|
6
6
|
# Common functionality for checking if presence/absence of empty lines
|
|
7
7
|
# around some kind of body matches the configuration.
|
|
8
|
-
module EmptyLinesAroundBody
|
|
8
|
+
module EmptyLinesAroundBody # rubocop:disable Metrics/ModuleLength
|
|
9
9
|
extend NodePattern::Macros
|
|
10
10
|
include ConfigurableEnforcedStyle
|
|
11
11
|
include RangeHelp
|
|
@@ -14,6 +14,8 @@ module RuboCop
|
|
|
14
14
|
MSG_MISSING = 'Empty line missing at %<kind>s body %<location>s.'
|
|
15
15
|
MSG_DEFERRED = 'Empty line missing before first %<type>s definition'
|
|
16
16
|
|
|
17
|
+
LEADING_DOT_TYPES = %i[tDOT tANDDOT].to_set.freeze
|
|
18
|
+
|
|
17
19
|
private
|
|
18
20
|
|
|
19
21
|
# @!method constant_definition?(node)
|
|
@@ -29,6 +31,7 @@ module RuboCop
|
|
|
29
31
|
|
|
30
32
|
first_line = adjusted_first_line || node.source_range.first_line
|
|
31
33
|
last_line = node.source_range.last_line
|
|
34
|
+
return if first_line >= last_line
|
|
32
35
|
|
|
33
36
|
case style
|
|
34
37
|
when :empty_lines_except_namespace
|
|
@@ -99,12 +102,20 @@ module RuboCop
|
|
|
99
102
|
return unless yield(processed_source.lines[line])
|
|
100
103
|
|
|
101
104
|
offset = style == :empty_lines && msg.include?('end.') ? 2 : 1
|
|
105
|
+
return if style == :empty_lines && leading_dot_line?(line + offset)
|
|
106
|
+
|
|
102
107
|
range = source_range(processed_source.buffer, line + offset, 0)
|
|
103
108
|
add_offense(range, message: msg) do |corrector|
|
|
104
109
|
EmptyLineCorrector.correct(corrector, [style, range])
|
|
105
110
|
end
|
|
106
111
|
end
|
|
107
112
|
|
|
113
|
+
def leading_dot_line?(line)
|
|
114
|
+
first_token = processed_source.sorted_tokens.find { |token| token.line == line }
|
|
115
|
+
|
|
116
|
+
LEADING_DOT_TYPES.include?(first_token&.type)
|
|
117
|
+
end
|
|
118
|
+
|
|
108
119
|
def check_deferred_empty_line(body)
|
|
109
120
|
node = first_empty_line_required_child(body)
|
|
110
121
|
return unless node
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
# Common functionality for checking whether a method body can become the
|
|
6
|
+
# body of an endless method definition without changing its meaning.
|
|
7
|
+
module EndlessMethodBodyHelp
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
def endless_method_body?(body)
|
|
11
|
+
return false if body.type?(:begin, :kwbegin, :rescue, :ensure, :masgn)
|
|
12
|
+
return false if low_precedence_body?(body)
|
|
13
|
+
return false if ends_with_omitted_hash_value?(body) || ends_with_anonymous_argument?(body)
|
|
14
|
+
return false if body.assignment? && multiple_values?(assigned_value(body))
|
|
15
|
+
|
|
16
|
+
!command_disallowed_in_endless_body?(body)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# `def foo = bar and baz` parses as `(def foo = bar) and baz`.
|
|
20
|
+
def low_precedence_body?(body)
|
|
21
|
+
body.type?(:any_match_pattern, :while_post, :until_post) ||
|
|
22
|
+
(body.type?(:and, :or) && body.semantic_operator?) ||
|
|
23
|
+
(body.type?(:if, :while, :until) && body.modifier_form?)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# `foo = 1, 2` and `foo = *bar` assign an array without brackets.
|
|
27
|
+
def multiple_values?(node)
|
|
28
|
+
node.array_type? && !node.bracketed?
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def ends_with_omitted_hash_value?(body)
|
|
32
|
+
body.each_descendant(:pair).any? do |pair|
|
|
33
|
+
pair.value_omission? && pair.source_range.end_pos == body.source_range.end_pos
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def ends_with_anonymous_argument?(body)
|
|
38
|
+
forwarding = %i[forwarded_restarg forwarded_kwrestarg block_pass]
|
|
39
|
+
|
|
40
|
+
body.each_descendant(*forwarding).any? do |argument|
|
|
41
|
+
argument.source_range.end_pos == body.source_range.end_pos &&
|
|
42
|
+
(!argument.block_pass_type? || argument.children.first.nil?)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def command_disallowed_in_endless_body?(body)
|
|
47
|
+
return true if body.assignment? && command_call?(assigned_value(body))
|
|
48
|
+
return true if body_disallowed_in_argument?(body)
|
|
49
|
+
return true if negated_command_call?(body)
|
|
50
|
+
|
|
51
|
+
body.each_node(:any_block).any? do |block|
|
|
52
|
+
block.keywords? && command_call?(block.send_node)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def body_disallowed_in_argument?(body)
|
|
57
|
+
command_body_in_argument?(body) || do_end_block_body_in_command_argument?(body)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# `private def foo = bar baz` parses only on Ruby 4.0+, and only as the sole argument.
|
|
61
|
+
def command_body_in_argument?(body)
|
|
62
|
+
return false unless command_call?(body)
|
|
63
|
+
|
|
64
|
+
call = argument_receiving_call(body.parent)
|
|
65
|
+
return false if call.nil?
|
|
66
|
+
|
|
67
|
+
target_ruby_version < 4.0 || !call.arguments.one?
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def argument_receiving_call(def_node)
|
|
71
|
+
call = def_node.parent
|
|
72
|
+
return unless call&.call_type?
|
|
73
|
+
|
|
74
|
+
call if call.arguments.any? { |argument| argument.equal?(def_node) }
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def do_end_block_body_in_command_argument?(body)
|
|
78
|
+
call = argument_receiving_call(body.parent)
|
|
79
|
+
return false if call.nil? || call.parenthesized?
|
|
80
|
+
|
|
81
|
+
body.each_node(:any_block).any? do |block|
|
|
82
|
+
block.keywords? && !block.send_node.lambda_literal?
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def assigned_value(node)
|
|
87
|
+
while node.assignment? || node.rescue_type?
|
|
88
|
+
node = node.rescue_type? ? node.body : node.children.last
|
|
89
|
+
end
|
|
90
|
+
node
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def command_call?(node)
|
|
94
|
+
node = node.send_node if node.any_block_type?
|
|
95
|
+
return false unless node.type?(:call, :super, :yield)
|
|
96
|
+
|
|
97
|
+
node.arguments? && !node.parenthesized? && !node.operator_method? && !node.setter_method?
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def negated_command_call?(node)
|
|
101
|
+
node.send_type? && node.prefix_bang? && command_call?(node.receiver)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
@@ -7,9 +7,9 @@ module RuboCop
|
|
|
7
7
|
SIGILS = '@$' # if a variable starts with a sigil it will be removed
|
|
8
8
|
|
|
9
9
|
def forbidden_identifier?(name)
|
|
10
|
-
|
|
10
|
+
return false if forbidden_identifiers.empty?
|
|
11
11
|
|
|
12
|
-
forbidden_identifiers.
|
|
12
|
+
forbidden_identifiers.include?(name.to_s.delete(SIGILS))
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def forbidden_identifiers
|
|
@@ -55,13 +55,21 @@ module RuboCop
|
|
|
55
55
|
# Common functionality for checking alignment of hash values.
|
|
56
56
|
module ValueAlignment
|
|
57
57
|
def checkable_layout?(node)
|
|
58
|
-
!node.pairs_on_same_line? && !node.mixed_delimiters? && alignable_values?(node)
|
|
58
|
+
!node.pairs_on_same_line? && !node.mixed_delimiters? && alignable_values?(node) &&
|
|
59
|
+
!pair_after_kwsplat_on_same_line?(node)
|
|
59
60
|
end
|
|
60
61
|
|
|
62
|
+
# With several enforced styles, deltas are computed even for a hash this style
|
|
63
|
+
# can't check. A pair that doesn't begin its line can't be moved without
|
|
64
|
+
# deleting whatever precedes it, so it's left alone.
|
|
61
65
|
def deltas(first_pair, current_pair)
|
|
66
|
+
return {} unless current_pair.equal?(first_pair) ||
|
|
67
|
+
Util.begins_its_line?(current_pair.source_range)
|
|
68
|
+
|
|
62
69
|
key_delta = key_delta(first_pair, current_pair)
|
|
63
|
-
|
|
64
|
-
|
|
70
|
+
shift = separator_shift(current_pair, key_delta)
|
|
71
|
+
separator_delta = separator_delta(first_pair, current_pair, shift)
|
|
72
|
+
value_delta = value_delta(first_pair, current_pair) - shift - separator_delta
|
|
65
73
|
|
|
66
74
|
{ key: key_delta, separator: separator_delta, value: value_delta }
|
|
67
75
|
end
|
|
@@ -78,9 +86,22 @@ module RuboCop
|
|
|
78
86
|
pair.value && pair.key.last_line != pair.value.first_line
|
|
79
87
|
end
|
|
80
88
|
|
|
81
|
-
def
|
|
89
|
+
def pair_after_kwsplat_on_same_line?(node)
|
|
90
|
+
first_pair = node.pairs.first
|
|
91
|
+
|
|
92
|
+
node.children.each_cons(2).any? do |previous, current|
|
|
93
|
+
current.pair_type? && !current.equal?(first_pair) &&
|
|
94
|
+
previous.last_line == current.first_line
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def separator_shift(current_pair, key_delta)
|
|
99
|
+
current_pair.key.multiline? ? 0 : key_delta
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def separator_delta(first_pair, current_pair, shift)
|
|
82
103
|
if current_pair.hash_rocket?
|
|
83
|
-
hash_rocket_delta(first_pair, current_pair) -
|
|
104
|
+
hash_rocket_delta(first_pair, current_pair) - shift
|
|
84
105
|
else
|
|
85
106
|
0
|
|
86
107
|
end
|
|
@@ -152,6 +173,17 @@ module RuboCop
|
|
|
152
173
|
{}
|
|
153
174
|
end
|
|
154
175
|
|
|
176
|
+
# Keys are right-aligned by the column their last line ends on.
|
|
177
|
+
# A key spanning several lines ends on a line other than the one it starts on,
|
|
178
|
+
# so moving its first line would never change that column and the correction
|
|
179
|
+
# would be repeated on every pass. Such pairs are left alone, and so is every pair
|
|
180
|
+
# when the first key spans several lines, since there is then no column to right-align to.
|
|
181
|
+
def deltas(first_pair, current_pair)
|
|
182
|
+
return {} if first_pair.key.multiline? || current_pair.key.multiline?
|
|
183
|
+
|
|
184
|
+
super
|
|
185
|
+
end
|
|
186
|
+
|
|
155
187
|
private
|
|
156
188
|
|
|
157
189
|
def key_delta(first_pair, current_pair)
|
|
@@ -163,7 +195,10 @@ module RuboCop
|
|
|
163
195
|
end
|
|
164
196
|
|
|
165
197
|
def value_delta(first_pair, current_pair)
|
|
166
|
-
|
|
198
|
+
return 0 if first_pair.equal?(current_pair) || current_pair.value_omission?
|
|
199
|
+
|
|
200
|
+
expected_value_column = first_pair.loc.operator.end.column + 1
|
|
201
|
+
expected_value_column - current_pair.value.loc.column
|
|
167
202
|
end
|
|
168
203
|
end
|
|
169
204
|
|
|
@@ -11,6 +11,15 @@ module RuboCop
|
|
|
11
11
|
DO_NOT_MIX_OMIT_VALUE_MSG = "#{DO_NOT_MIX_MSG_PREFIX} #{OMIT_HASH_VALUE_MSG}"
|
|
12
12
|
DO_NOT_MIX_EXPLICIT_VALUE_MSG = "#{DO_NOT_MIX_MSG_PREFIX} #{EXPLICIT_HASH_VALUE_MSG}"
|
|
13
13
|
|
|
14
|
+
# A keyword parameter can be named after a keyword, as in `def foo(if:)`,
|
|
15
|
+
# but the parameter can only be referenced by an omitted hash value,
|
|
16
|
+
# so `{ if: }` has no explicit form: `{ if: if }` is invalid Ruby.
|
|
17
|
+
KEYWORDS = %i[
|
|
18
|
+
__ENCODING__ __FILE__ __LINE__ BEGIN END alias and begin break case class def do
|
|
19
|
+
else elsif end ensure false for if in module next nil not or redo rescue retry
|
|
20
|
+
return self super then true undef unless until when while yield
|
|
21
|
+
].to_set.freeze
|
|
22
|
+
|
|
14
23
|
DefNode = Struct.new(:node) do
|
|
15
24
|
def selector
|
|
16
25
|
if node.loc?(:selector)
|
|
@@ -53,7 +62,7 @@ module RuboCop
|
|
|
53
62
|
replacement = "#{hash_key_source}:"
|
|
54
63
|
self.config_to_allow_offenses = { 'Enabled' => false }
|
|
55
64
|
else
|
|
56
|
-
return
|
|
65
|
+
return if !node.value_omission? || keyword_value?(node)
|
|
57
66
|
|
|
58
67
|
message = EXPLICIT_HASH_VALUE_MSG
|
|
59
68
|
replacement = "#{hash_key_source}: #{hash_key_source}"
|
|
@@ -97,7 +106,16 @@ module RuboCop
|
|
|
97
106
|
end
|
|
98
107
|
|
|
99
108
|
def hash_rockets_enforced?(hash_node)
|
|
100
|
-
style == :hash_rockets || force_hash_rockets?(hash_node.pairs)
|
|
109
|
+
style == :hash_rockets || force_hash_rockets?(hash_node.pairs) ||
|
|
110
|
+
no_mixed_keys_enforces_hash_rockets?(hash_node.pairs)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def no_mixed_keys_enforces_hash_rockets?(pairs)
|
|
114
|
+
case style
|
|
115
|
+
when :no_mixed_keys then !sym_indices?(pairs) || pairs.first.delimiter == '=>'
|
|
116
|
+
when :ruby19_no_mixed_keys then !sym_indices?(pairs)
|
|
117
|
+
else false
|
|
118
|
+
end
|
|
101
119
|
end
|
|
102
120
|
|
|
103
121
|
def enforced_shorthand_syntax
|
|
@@ -210,6 +228,8 @@ module RuboCop
|
|
|
210
228
|
def mixed_shorthand_syntax_check(hash_value_type_breakdown)
|
|
211
229
|
if hash_with_values_that_cant_be_omitted?(hash_value_type_breakdown)
|
|
212
230
|
each_omitted_value_pair(hash_value_type_breakdown) do |pair_node|
|
|
231
|
+
next if keyword_value?(pair_node)
|
|
232
|
+
|
|
213
233
|
hash_key_source = pair_node.key.source
|
|
214
234
|
replacement = "#{hash_key_source}: #{hash_key_source}"
|
|
215
235
|
register_offense(pair_node, DO_NOT_MIX_EXPLICIT_VALUE_MSG, replacement)
|
|
@@ -233,6 +253,10 @@ module RuboCop
|
|
|
233
253
|
register_offense(pair_node, OMIT_HASH_VALUE_MSG, replacement)
|
|
234
254
|
end
|
|
235
255
|
end
|
|
256
|
+
|
|
257
|
+
def keyword_value?(pair_node)
|
|
258
|
+
KEYWORDS.include?(pair_node.key.value)
|
|
259
|
+
end
|
|
236
260
|
end
|
|
237
261
|
end
|
|
238
262
|
# rubocop:enable Metrics/ModuleLength
|
|
@@ -32,7 +32,9 @@ module RuboCop
|
|
|
32
32
|
branches << node.if_branch
|
|
33
33
|
|
|
34
34
|
else_branch = node.else_branch
|
|
35
|
-
|
|
35
|
+
if else_branch&.if_type? && else_branch.elsif?
|
|
36
|
+
if_conditional_branches(else_branch, branches)
|
|
37
|
+
end
|
|
36
38
|
branches
|
|
37
39
|
end
|
|
38
40
|
end
|
|
@@ -11,8 +11,10 @@ module RuboCop
|
|
|
11
11
|
return if all_on_same_line?(children, ignore_last: ignore_last)
|
|
12
12
|
|
|
13
13
|
last_seen_line = -1
|
|
14
|
-
children.
|
|
14
|
+
children.each_with_index do |child, index|
|
|
15
15
|
if last_seen_line >= child.first_line
|
|
16
|
+
next if heredoc_opened_before?(children.first(index), child)
|
|
17
|
+
|
|
16
18
|
add_offense(child) { |corrector| EmptyLineCorrector.insert_before(corrector, child) }
|
|
17
19
|
else
|
|
18
20
|
last_seen_line = child.last_line
|
|
@@ -27,6 +29,14 @@ module RuboCop
|
|
|
27
29
|
|
|
28
30
|
nodes.first.first_line == nodes.last.last_line
|
|
29
31
|
end
|
|
32
|
+
|
|
33
|
+
def heredoc_opened_before?(previous_children, child)
|
|
34
|
+
previous_children.any? do |previous|
|
|
35
|
+
previous.each_node(:any_str).any? do |str|
|
|
36
|
+
str.heredoc? && same_line?(str, child)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
30
40
|
end
|
|
31
41
|
end
|
|
32
42
|
end
|
|
@@ -15,6 +15,7 @@ module RuboCop
|
|
|
15
15
|
# If the last node is or contains a conflicting HEREDOC, we don't want
|
|
16
16
|
# to adjust the brace layout because this will result in invalid code.
|
|
17
17
|
return if last_line_heredoc?(node.children.last)
|
|
18
|
+
return if heredoc_opened_on_closing_brace_line?(node)
|
|
18
19
|
|
|
19
20
|
check(node)
|
|
20
21
|
end
|
|
@@ -136,6 +137,14 @@ module RuboCop
|
|
|
136
137
|
|
|
137
138
|
node.children.any? { |child| last_line_heredoc?(child, parent) }
|
|
138
139
|
end
|
|
140
|
+
|
|
141
|
+
def heredoc_opened_on_closing_brace_line?(node)
|
|
142
|
+
closing_brace_line = node.loc.end.line
|
|
143
|
+
|
|
144
|
+
node.each_descendant(:any_str).any? do |str|
|
|
145
|
+
str.heredoc? && str.first_line == closing_brace_line
|
|
146
|
+
end
|
|
147
|
+
end
|
|
139
148
|
end
|
|
140
149
|
end
|
|
141
150
|
end
|