sonicop 26.8.111 → 26.8.113
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/CONFORMANCE.md +64 -31
- data/Cargo.lock +94 -19
- data/Cargo.toml +13 -8
- data/NOTICE +15 -3
- data/README.ja.md +145 -57
- data/README.md +140 -48
- data/build.rs +155 -0
- data/lib/sonicop/runner.rb +7 -1
- data/lib/sonicop/version.rb +1 -1
- data/src/cli.rs +216 -45
- data/src/config/inheritance.rs +637 -64
- data/src/config/mod.rs +130 -1
- data/src/config/paths.rs +550 -48
- data/src/cop_name.rs +18 -1
- data/src/diagnostic.rs +168 -3
- data/src/directives.rs +398 -77
- data/src/display_width.rs +82 -42
- data/src/display_width_table.rs +506 -0
- data/src/engine.rs +1532 -51
- data/src/formatter.rs +10 -1
- data/src/lib.rs +2 -0
- data/src/main.rs +112 -1
- data/src/nul_bytes.rs +245 -47
- data/src/parser.rs +37 -0
- data/src/profile.rs +174 -24
- data/src/ruby_version.rs +167 -21
- data/src/rules/bundler/duplicated_group.rs +3 -2
- data/src/rules/bundler/gem_comment.rs +5 -4
- data/src/rules/gemspec/attribute_assignment.rs +4 -3
- data/src/rules/gemspec/deprecated_attribute_assignment.rs +7 -6
- data/src/rules/gemspec/duplicated_assignment.rs +4 -3
- data/src/rules/gemspec/require_mfa.rs +10 -9
- data/src/rules/gemspec/required_ruby_version.rs +3 -2
- data/src/rules/gemspec/support.rs +28 -8
- data/src/rules/layout/access_modifier_indentation.rs +13 -6
- data/src/rules/layout/argument_alignment.rs +19 -7
- data/src/rules/layout/array_alignment.rs +1 -2
- data/src/rules/layout/block_alignment.rs +74 -30
- data/src/rules/layout/block_end_newline.rs +5 -5
- data/src/rules/layout/class_structure.rs +13 -4
- data/src/rules/layout/closing_heredoc_indentation.rs +24 -5
- data/src/rules/layout/closing_parenthesis_indentation.rs +3 -3
- data/src/rules/layout/comment_indentation.rs +2 -1
- data/src/rules/layout/condition_position.rs +3 -2
- data/src/rules/layout/def_end_alignment.rs +10 -6
- data/src/rules/layout/dot_position.rs +1 -2
- data/src/rules/layout/else_alignment.rs +24 -14
- data/src/rules/layout/empty_line_after_guard_clause.rs +8 -7
- data/src/rules/layout/empty_line_after_multiline_condition.rs +5 -5
- data/src/rules/layout/empty_line_between_defs.rs +8 -6
- data/src/rules/layout/empty_lines_around_access_modifier.rs +22 -10
- data/src/rules/layout/empty_lines_around_arguments.rs +4 -4
- data/src/rules/layout/empty_lines_around_body.rs +8 -2
- data/src/rules/layout/empty_lines_around_exception_handling_keywords.rs +1 -2
- data/src/rules/layout/empty_lines_around_method_body.rs +3 -2
- data/src/rules/layout/end_alignment.rs +32 -7
- data/src/rules/layout/end_of_line.rs +14 -1
- data/src/rules/layout/extra_spacing.rs +9 -11
- data/src/rules/layout/first_array_element_indentation.rs +1 -2
- data/src/rules/layout/first_hash_element_indentation.rs +8 -6
- data/src/rules/layout/hash_alignment.rs +113 -19
- data/src/rules/layout/heredoc_argument_closing_parenthesis.rs +6 -5
- data/src/rules/layout/heredoc_indentation.rs +4 -3
- data/src/rules/layout/indentation_style.rs +6 -4
- data/src/rules/layout/indentation_width.rs +76 -16
- data/src/rules/layout/initial_indentation.rs +18 -5
- data/src/rules/layout/line_continuation_leading_space.rs +4 -3
- data/src/rules/layout/line_continuation_spacing.rs +4 -3
- data/src/rules/layout/line_length.rs +417 -43
- data/src/rules/layout/mod.rs +1 -1
- data/src/rules/layout/multiline_assignment_layout.rs +20 -3
- data/src/rules/layout/multiline_block_layout.rs +1 -2
- data/src/rules/layout/multiline_expression.rs +60 -31
- data/src/rules/layout/multiline_hash_brace_layout.rs +4 -3
- data/src/rules/layout/multiline_method_call_indentation.rs +1 -1
- data/src/rules/layout/multiline_operation_indentation.rs +3 -3
- data/src/rules/layout/redundant_line_break.rs +16 -5
- data/src/rules/layout/rescue_ensure_alignment.rs +20 -12
- data/src/rules/layout/single_line_block_chain.rs +13 -4
- data/src/rules/layout/space_around_block_parameters.rs +16 -2
- data/src/rules/layout/space_around_equals_in_parameter_default.rs +1 -2
- data/src/rules/layout/space_around_keyword.rs +22 -4
- data/src/rules/layout/space_around_operators.rs +34 -2
- data/src/rules/layout/space_before_brackets.rs +13 -6
- data/src/rules/layout/space_before_comma.rs +3 -2
- data/src/rules/layout/space_inside_array_literal_brackets.rs +25 -10
- data/src/rules/layout/space_inside_array_percent_literal.rs +7 -1
- data/src/rules/layout/space_inside_parens.rs +170 -87
- data/src/rules/layout/space_inside_range_literal.rs +53 -19
- data/src/rules/layout/space_inside_reference_brackets.rs +65 -3
- data/src/rules/layout/space_inside_string_interpolation.rs +147 -48
- data/src/rules/layout/support.rs +172 -26
- data/src/rules/layout/tokens.rs +47 -7
- data/src/rules/layout/trailing_whitespace.rs +5 -2
- data/src/rules/lint/access_modifier.rs +50 -5
- data/src/rules/lint/ambiguity.rs +97 -7
- data/src/rules/lint/ambiguous_block_association.rs +29 -12
- data/src/rules/lint/ambiguous_operator.rs +8 -0
- data/src/rules/lint/ambiguous_operator_precedence.rs +18 -1
- data/src/rules/lint/ambiguous_range.rs +15 -1
- data/src/rules/lint/ambiguous_regexp_literal.rs +40 -1
- data/src/rules/lint/array_literal_in_regexp.rs +13 -5
- data/src/rules/lint/assignment_in_condition.rs +3 -2
- data/src/rules/lint/blocks.rs +2 -1
- data/src/rules/lint/boolean_symbol.rs +4 -4
- data/src/rules/lint/constant_definition_in_block.rs +1 -2
- data/src/rules/lint/constant_reassignment.rs +9 -13
- data/src/rules/lint/constant_resolution.rs +8 -0
- data/src/rules/lint/cop_directives.rs +28 -4
- data/src/rules/lint/debugger.rs +59 -9
- data/src/rules/lint/deprecated_open_ssl_constant.rs +1 -2
- data/src/rules/lint/disjunctive_assignment_in_constructor.rs +2 -2
- data/src/rules/lint/duplicate_branch.rs +16 -6
- data/src/rules/lint/duplicate_case_condition.rs +5 -5
- data/src/rules/lint/duplicate_hash_key.rs +8 -4
- data/src/rules/lint/duplicate_match_pattern.rs +7 -5
- data/src/rules/lint/duplicate_methods.rs +133 -54
- data/src/rules/lint/duplicate_require.rs +1 -2
- data/src/rules/lint/duplicate_set_element.rs +19 -5
- data/src/rules/lint/empty_conditional_body.rs +19 -3
- data/src/rules/lint/empty_expression.rs +16 -1
- data/src/rules/lint/empty_in_pattern.rs +3 -2
- data/src/rules/lint/empty_when.rs +4 -4
- data/src/rules/lint/ensure_return.rs +3 -2
- data/src/rules/lint/float_comparison.rs +8 -6
- data/src/rules/lint/flow.rs +8 -5
- data/src/rules/lint/format_parameter_mismatch.rs +4 -3
- data/src/rules/lint/hash_compare_by_identity.rs +5 -4
- data/src/rules/lint/heredoc_method_call_position.rs +3 -2
- data/src/rules/lint/implicit_string_concatenation.rs +33 -3
- data/src/rules/lint/ineffective_access_modifier.rs +5 -4
- data/src/rules/lint/inherit_exception.rs +4 -3
- data/src/rules/lint/literal_as_condition.rs +51 -31
- data/src/rules/lint/literal_assignment_in_condition.rs +4 -3
- data/src/rules/lint/literal_in_interpolation.rs +66 -5
- data/src/rules/lint/literals.rs +10 -8
- data/src/rules/lint/missing_cop_enable_directive.rs +95 -18
- data/src/rules/lint/mod.rs +1 -0
- data/src/rules/lint/nested_method_definition.rs +36 -11
- data/src/rules/lint/nil_receiver.rs +420 -0
- data/src/rules/lint/no_return_in_begin_end_blocks.rs +2 -2
- data/src/rules/lint/node_equality.rs +8 -5
- data/src/rules/lint/non_atomic_file_operation.rs +9 -3
- data/src/rules/lint/non_deterministic_require_order.rs +5 -3
- data/src/rules/lint/non_local_exit_from_iterator.rs +22 -9
- data/src/rules/lint/number_conversion.rs +1 -1
- data/src/rules/lint/out_of_range_regexp_ref.rs +6 -4
- data/src/rules/lint/parentheses_as_grouped_expression.rs +5 -0
- data/src/rules/lint/redundant_cop_enable_directive.rs +3 -1
- data/src/rules/lint/redundant_dir_glob_sort.rs +1 -2
- data/src/rules/lint/redundant_safe_navigation.rs +47 -22
- data/src/rules/lint/redundant_splat_expansion.rs +4 -2
- data/src/rules/lint/redundant_string_coercion.rs +3 -2
- data/src/rules/lint/redundant_type_conversion.rs +16 -4
- data/src/rules/lint/regexp.rs +1 -3
- data/src/rules/lint/regexp_source.rs +2 -2
- data/src/rules/lint/regexp_tree.rs +38 -5
- data/src/rules/lint/require_range_parentheses.rs +5 -5
- data/src/rules/lint/rescue_exception.rs +4 -3
- data/src/rules/lint/rescue_type.rs +3 -2
- data/src/rules/lint/return_in_void_context.rs +8 -3
- data/src/rules/lint/safe_navigation_chain.rs +47 -11
- data/src/rules/lint/self_assignment.rs +20 -2
- data/src/rules/lint/shadowed_argument.rs +2 -2
- data/src/rules/lint/shadowed_exception.rs +2 -2
- data/src/rules/lint/suppressed_exception.rs +21 -3
- data/src/rules/lint/suppressed_exception_in_number_conversion.rs +4 -3
- data/src/rules/lint/symbol_conversion.rs +56 -8
- data/src/rules/lint/syntax.rs +195 -5
- data/src/rules/lint/top_level_return_with_argument.rs +11 -1
- data/src/rules/lint/triple_quotes.rs +3 -2
- data/src/rules/lint/unescaped_bracket_in_regexp.rs +1 -1
- data/src/rules/lint/unexpected_block_arity.rs +23 -5
- data/src/rules/lint/unified_integer.rs +18 -12
- data/src/rules/lint/unmodified_reduce_accumulator.rs +36 -7
- data/src/rules/lint/unreachable_code.rs +4 -4
- data/src/rules/lint/unreachable_loop.rs +26 -10
- data/src/rules/lint/unreachable_pattern_branch.rs +7 -5
- data/src/rules/lint/unused_block_argument.rs +2 -2
- data/src/rules/lint/unused_method_argument.rs +1 -2
- data/src/rules/lint/useless_assignment.rs +3 -2
- data/src/rules/lint/useless_constant_scoping.rs +3 -2
- data/src/rules/lint/useless_else_without_rescue.rs +4 -3
- data/src/rules/lint/useless_rescue.rs +5 -4
- data/src/rules/lint/useless_ruby2_keywords.rs +2 -1
- data/src/rules/lint/useless_setter_call.rs +5 -4
- data/src/rules/lint/useless_times.rs +4 -3
- data/src/rules/lint/variable_force.rs +307 -79
- data/src/rules/lint/void.rs +32 -20
- data/src/rules/metrics/abc_size.rs +197 -7
- data/src/rules/metrics/block_length.rs +19 -10
- data/src/rules/metrics/block_nesting.rs +1 -2
- data/src/rules/metrics/class_length.rs +16 -4
- data/src/rules/metrics/collection_literal_length.rs +2 -1
- data/src/rules/metrics/complexity.rs +52 -14
- data/src/rules/metrics/fragments.rs +10 -14
- data/src/rules/metrics/locals.rs +35 -14
- data/src/rules/metrics/method_length.rs +14 -6
- data/src/rules/metrics/parameter_lists.rs +7 -6
- data/src/rules/metrics/perceived_complexity.rs +1 -3
- data/src/rules/metrics/support.rs +94 -4
- data/src/rules/mod.rs +525 -80
- data/src/rules/naming/ascii_identifiers.rs +3 -3
- data/src/rules/naming/binary_operator_parameter_name.rs +5 -4
- data/src/rules/naming/block_forwarding.rs +9 -8
- data/src/rules/naming/constant_name.rs +56 -18
- data/src/rules/naming/file_name.rs +174 -43
- data/src/rules/naming/method_name.rs +8 -1
- data/src/rules/naming/predicate_method.rs +42 -14
- data/src/rules/naming/predicate_prefix.rs +70 -4
- data/src/rules/naming/rescued_exceptions_variable_name.rs +14 -11
- data/src/rules/naming/support.rs +54 -295
- data/src/rules/naming/variable_name.rs +17 -4
- data/src/rules/naming/variable_number.rs +9 -10
- data/src/rules/node_ext.rs +1 -1
- data/src/rules/ruby_literal.rs +8 -3
- data/src/rules/security/compound_hash.rs +3 -2
- data/src/rules/security/open.rs +5 -4
- data/src/rules/send_node.rs +134 -0
- data/src/rules/single_line.rs +4 -4
- data/src/rules/style/access_modifier_declarations.rs +76 -22
- data/src/rules/style/accessor_grouping.rs +44 -6
- data/src/rules/style/alias.rs +4 -3
- data/src/rules/style/and_or.rs +2 -2
- data/src/rules/style/arguments_forwarding.rs +5 -5
- data/src/rules/style/array_coercion.rs +5 -5
- data/src/rules/style/array_first_last.rs +19 -4
- data/src/rules/style/array_intersect.rs +26 -8
- data/src/rules/style/array_intersect_with_single_element.rs +1 -1
- data/src/rules/style/ascii_comments.rs +2 -0
- data/src/rules/style/attr.rs +1 -1
- data/src/rules/style/auto_resource_cleanup.rs +1 -1
- data/src/rules/style/bitwise_predicate.rs +2 -2
- data/src/rules/style/block_args.rs +1 -1
- data/src/rules/style/block_comments.rs +11 -2
- data/src/rules/style/block_delimiters.rs +154 -10
- data/src/rules/style/case_equality.rs +7 -2
- data/src/rules/style/case_like_if.rs +26 -2
- data/src/rules/style/class_and_module_children.rs +162 -10
- data/src/rules/style/class_methods.rs +1 -1
- data/src/rules/style/class_methods_definitions.rs +9 -0
- data/src/rules/style/collection_compact.rs +4 -4
- data/src/rules/style/combinable_defined.rs +2 -2
- data/src/rules/style/combinable_loops.rs +9 -11
- data/src/rules/style/comments.rs +6 -3
- data/src/rules/style/comparable_clamp.rs +2 -2
- data/src/rules/style/concat_array_literals.rs +3 -3
- data/src/rules/style/conditional.rs +12 -1
- data/src/rules/style/conditional_assignment.rs +133 -4
- data/src/rules/style/constant_visibility.rs +3 -3
- data/src/rules/style/copyright.rs +64 -3
- data/src/rules/style/data_inheritance.rs +1 -1
- data/src/rules/style/def_with_parentheses.rs +1 -1
- data/src/rules/style/document_dynamic_eval_definition.rs +50 -12
- data/src/rules/style/documentation.rs +1 -1
- data/src/rules/style/each_for_simple_loop.rs +1 -1
- data/src/rules/style/each_with_object.rs +4 -4
- data/src/rules/style/empty_block_parameter.rs +1 -1
- data/src/rules/style/empty_case_condition.rs +6 -6
- data/src/rules/style/empty_class_definition.rs +1 -1
- data/src/rules/style/empty_else.rs +1 -1
- data/src/rules/style/empty_heredoc.rs +14 -1
- data/src/rules/style/empty_lambda_parameter.rs +1 -1
- data/src/rules/style/empty_literal.rs +34 -2
- data/src/rules/style/empty_method.rs +1 -1
- data/src/rules/style/empty_string_inside_interpolation.rs +1 -1
- data/src/rules/style/endless.rs +11 -3
- data/src/rules/style/env_home.rs +1 -1
- data/src/rules/style/eval_with_location.rs +6 -0
- data/src/rules/style/even_odd.rs +1 -1
- data/src/rules/style/exact_regexp_match.rs +1 -1
- data/src/rules/style/expand_path_arguments.rs +3 -3
- data/src/rules/style/explicit_block_argument.rs +3 -3
- data/src/rules/style/file_open.rs +5 -0
- data/src/rules/style/file_open_call.rs +3 -3
- data/src/rules/style/file_write.rs +1 -1
- data/src/rules/style/for.rs +1 -1
- data/src/rules/style/format_sequences.rs +6 -0
- data/src/rules/style/format_string.rs +75 -11
- data/src/rules/style/format_string_token.rs +61 -12
- data/src/rules/style/frozen_string_literal_comment.rs +62 -4
- data/src/rules/style/guard_clause.rs +8 -7
- data/src/rules/style/hash_as_last_array_item.rs +4 -4
- data/src/rules/style/hash_each_methods.rs +1 -1
- data/src/rules/style/hash_like_case.rs +8 -8
- data/src/rules/style/hash_lookup_method.rs +43 -3
- data/src/rules/style/hash_subset.rs +16 -10
- data/src/rules/style/hash_syntax.rs +609 -71
- data/src/rules/style/hash_transform.rs +20 -18
- data/src/rules/style/hash_transform_keys.rs +7 -0
- data/src/rules/style/hash_transform_values.rs +7 -0
- data/src/rules/style/identical_conditional_branches.rs +54 -5
- data/src/rules/style/if_inside_else.rs +19 -3
- data/src/rules/style/if_unless_modifier.rs +13 -14
- data/src/rules/style/if_with_boolean_literal_branches.rs +1 -1
- data/src/rules/style/if_with_semicolon.rs +7 -1
- data/src/rules/style/implicit_runtime_error.rs +7 -0
- data/src/rules/style/in_pattern_then.rs +2 -2
- data/src/rules/style/infinite_loop.rs +6 -0
- data/src/rules/style/inline_comment.rs +4 -1
- data/src/rules/style/inverse_methods.rs +12 -2
- data/src/rules/style/invertible_unless_condition.rs +12 -12
- data/src/rules/style/it_block_parameter.rs +5 -2
- data/src/rules/style/keyword_arguments_merging.rs +8 -2
- data/src/rules/style/keyword_parameters_order.rs +1 -1
- data/src/rules/style/line_end_concatenation.rs +1 -1
- data/src/rules/style/magic_comment_format.rs +14 -6
- data/src/rules/style/map_chain.rs +1 -1
- data/src/rules/style/map_compact_with_conditional_block.rs +3 -3
- data/src/rules/style/map_into_array.rs +7 -7
- data/src/rules/style/map_join.rs +3 -3
- data/src/rules/style/method_call_with_args_parentheses.rs +7 -7
- data/src/rules/style/method_call_without_args_parentheses.rs +2 -2
- data/src/rules/style/method_def_parentheses.rs +2 -3
- data/src/rules/style/min_max.rs +3 -3
- data/src/rules/style/min_max_comparison.rs +2 -2
- data/src/rules/style/missing_else.rs +1 -1
- data/src/rules/style/missing_respond_to_missing.rs +1 -1
- data/src/rules/style/mixin_grouping.rs +6 -7
- data/src/rules/style/multiline_block_chain.rs +6 -8
- data/src/rules/style/multiline_if_then.rs +1 -1
- data/src/rules/style/multiline_in_pattern_then.rs +16 -3
- data/src/rules/style/multiline_method_signature.rs +1 -1
- data/src/rules/style/multiline_when_then.rs +2 -2
- data/src/rules/style/mutable_constant.rs +31 -35
- data/src/rules/style/negated_if.rs +2 -2
- data/src/rules/style/negated_if_else_condition.rs +5 -3
- data/src/rules/style/negated_while.rs +1 -1
- data/src/rules/style/negative_array_index.rs +25 -3
- data/src/rules/style/nested_modifier.rs +1 -1
- data/src/rules/style/nested_parenthesized_calls.rs +2 -2
- data/src/rules/style/nested_ternary_operator.rs +2 -2
- data/src/rules/style/next.rs +12 -12
- data/src/rules/style/nil_lambda.rs +2 -2
- data/src/rules/style/nodes.rs +21 -0
- data/src/rules/style/non_nil_check.rs +82 -2
- data/src/rules/style/numbered_parameters.rs +4 -1
- data/src/rules/style/numbered_parameters_limit.rs +2 -2
- data/src/rules/style/numeric_literals.rs +17 -1
- data/src/rules/style/numeric_predicate.rs +25 -6
- data/src/rules/style/one_line_conditional.rs +24 -7
- data/src/rules/style/operator_method_call.rs +5 -0
- data/src/rules/style/optional_arguments.rs +1 -1
- data/src/rules/style/or_assignment.rs +1 -1
- data/src/rules/style/parallel_assignment.rs +20 -9
- data/src/rules/style/parens.rs +1 -1
- data/src/rules/style/parentheses_around_condition.rs +3 -3
- data/src/rules/style/partition_instead_of_double_select.rs +3 -3
- data/src/rules/style/percent.rs +18 -9
- data/src/rules/style/percent_q_literals.rs +40 -7
- data/src/rules/style/preferred_hash_methods.rs +1 -1
- data/src/rules/style/quoted_symbols.rs +6 -0
- data/src/rules/style/raise_args.rs +26 -20
- data/src/rules/style/random_with_offset.rs +1 -1
- data/src/rules/style/reduce_to_hash.rs +6 -6
- data/src/rules/style/redundant_argument.rs +1 -1
- data/src/rules/style/redundant_assignment.rs +5 -5
- data/src/rules/style/redundant_begin.rs +5 -3
- data/src/rules/style/redundant_capital_w.rs +3 -2
- data/src/rules/style/redundant_condition.rs +17 -8
- data/src/rules/style/redundant_current_directory_in_path.rs +2 -2
- data/src/rules/style/redundant_double_splat_hash_braces.rs +15 -5
- data/src/rules/style/redundant_exception.rs +3 -1
- data/src/rules/style/redundant_file_extension_in_require.rs +2 -2
- data/src/rules/style/redundant_format.rs +98 -20
- data/src/rules/style/redundant_freeze.rs +1 -1
- data/src/rules/style/redundant_heredoc_delimiter_quotes.rs +1 -1
- data/src/rules/style/redundant_initialize.rs +6 -3
- data/src/rules/style/redundant_interpolation.rs +8 -8
- data/src/rules/style/redundant_interpolation_unfreeze.rs +10 -3
- data/src/rules/style/redundant_line_continuation.rs +10 -7
- data/src/rules/style/redundant_parentheses.rs +96 -19
- data/src/rules/style/redundant_regexp_argument.rs +1 -1
- data/src/rules/style/redundant_regexp_character_class.rs +4 -3
- data/src/rules/style/redundant_regexp_escape.rs +3 -2
- data/src/rules/style/redundant_return.rs +1 -2
- data/src/rules/style/redundant_self.rs +28 -16
- data/src/rules/style/redundant_sort.rs +1 -1
- data/src/rules/style/redundant_sort_by.rs +1 -1
- data/src/rules/style/redundant_string_escape.rs +6 -5
- data/src/rules/style/regexp_literal.rs +3 -2
- data/src/rules/style/require_order.rs +2 -2
- data/src/rules/style/rescue_modifier.rs +9 -4
- data/src/rules/style/rescue_standard_error.rs +1 -1
- data/src/rules/style/return_nil.rs +2 -2
- data/src/rules/style/return_nil_in_predicate_method_definition.rs +2 -2
- data/src/rules/style/safe_navigation.rs +2 -2
- data/src/rules/style/safe_navigation_chain_length.rs +8 -1
- data/src/rules/style/sample.rs +3 -3
- data/src/rules/style/select_by.rs +6 -2
- data/src/rules/style/select_by_range.rs +1 -1
- data/src/rules/style/semicolon.rs +77 -4
- data/src/rules/style/signal_exception.rs +60 -3
- data/src/rules/style/single_argument_dig.rs +10 -2
- data/src/rules/style/single_line_block_params.rs +14 -4
- data/src/rules/style/single_line_do_end_block.rs +13 -12
- data/src/rules/style/single_line_methods.rs +2 -2
- data/src/rules/style/slicing_with_range.rs +2 -2
- data/src/rules/style/sole_nested_conditional.rs +4 -4
- data/src/rules/style/special_global_vars.rs +2 -2
- data/src/rules/style/stabby_lambda_parentheses.rs +1 -1
- data/src/rules/style/statement_modifier.rs +3 -2
- data/src/rules/style/static_class.rs +7 -1
- data/src/rules/style/string_concatenation.rs +12 -7
- data/src/rules/style/string_hash_keys.rs +3 -2
- data/src/rules/style/string_literals.rs +3 -3
- data/src/rules/style/string_literals_in_interpolation.rs +4 -1
- data/src/rules/style/struct_inheritance.rs +3 -3
- data/src/rules/style/super_arguments.rs +15 -7
- data/src/rules/style/super_with_args_parentheses.rs +49 -12
- data/src/rules/style/swap_values.rs +1 -1
- data/src/rules/style/symbol_array.rs +9 -2
- data/src/rules/style/symbol_proc.rs +3 -3
- data/src/rules/style/tally_method.rs +4 -4
- data/src/rules/style/ternary_parentheses.rs +30 -15
- data/src/rules/style/top_level_method_definition.rs +10 -5
- data/src/rules/style/trailing_body.rs +1 -1
- data/src/rules/style/trailing_comma.rs +206 -10
- data/src/rules/style/trailing_comma_in_arguments.rs +9 -10
- data/src/rules/style/trailing_comma_in_array_literal.rs +2 -1
- data/src/rules/style/trailing_comma_in_hash_literal.rs +2 -1
- data/src/rules/style/trailing_method_end_statement.rs +6 -1
- data/src/rules/style/trailing_underscore_variable.rs +4 -5
- data/src/rules/style/trivial_accessors.rs +2 -2
- data/src/rules/style/unless_logical_operators.rs +1 -1
- data/src/rules/style/unpack_first.rs +11 -2
- data/src/rules/style/when_then.rs +4 -4
- data/src/rules/style/while_until_do.rs +1 -1
- data/src/rules/style/while_until_modifier.rs +3 -3
- data/src/rules/style/word_array.rs +9 -7
- data/src/rules/style/yoda_condition.rs +2 -2
- data/src/rules/style/zero_length_predicate.rs +5 -0
- data/src/rules/support.rs +128 -11
- data/src/source.rs +18 -15
- metadata +5 -1
|
@@ -84,7 +84,7 @@ fn skipped(node: Node<'_>, context: &RuleContext<'_>) -> bool {
|
|
|
84
84
|
if is_dstr(source) {
|
|
85
85
|
return true;
|
|
86
86
|
}
|
|
87
|
-
inside_interpolation(node) || quoted_label_key(node, context)
|
|
87
|
+
inside_interpolation(node, context) || quoted_label_key(node, context)
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
/// RuboCop's `on_dstr`, which only reports under `ConsistentQuotesInMultiline`: a literal the
|
|
@@ -286,10 +286,10 @@ pub(super) fn has_interpolation(node: Node<'_>) -> bool {
|
|
|
286
286
|
/// RuboCop's `StringHelp#inside_interpolation?`: from the innermost interpolation outwards, is the
|
|
287
287
|
/// literal owned by a `dstr`, `dsym` or `regexp`? The walk continues past the first interpolation
|
|
288
288
|
/// because a command literal nested in a string -- `"#{`cmd #{'x'}`}"` -- is still inside one.
|
|
289
|
-
pub(super) fn inside_interpolation(node: Node<'_>) -> bool {
|
|
289
|
+
pub(super) fn inside_interpolation(node: Node<'_>, context: &RuleContext<'_>) -> bool {
|
|
290
290
|
let mut current = node;
|
|
291
291
|
let mut interpolated = false;
|
|
292
|
-
while let Some(parent) =
|
|
292
|
+
while let Some(parent) = context.parent(current) {
|
|
293
293
|
if parent.kind_str() == "interpolation" {
|
|
294
294
|
interpolated = true;
|
|
295
295
|
} else if interpolated && INTERPOLATION_OWNERS.contains(&parent.kind_str()) {
|
|
@@ -7,6 +7,9 @@ use super::string_literals::{
|
|
|
7
7
|
};
|
|
8
8
|
|
|
9
9
|
pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
10
|
+
if context.nodes_of("interpolation").next().is_none() {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
10
13
|
let style: String = context
|
|
11
14
|
.setting("EnforcedStyle")
|
|
12
15
|
.unwrap_or_else(|| "single_quotes".to_owned());
|
|
@@ -26,7 +29,7 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
26
29
|
|| has_interpolation(node)
|
|
27
30
|
|| is_dstr(source)
|
|
28
31
|
|| quoted_label_key(node, context)
|
|
29
|
-
|| !inside_interpolation(node)
|
|
32
|
+
|| !inside_interpolation(node, context)
|
|
30
33
|
|| !wrong_quotes(source, single_quotes)
|
|
31
34
|
{
|
|
32
35
|
continue;
|
|
@@ -13,7 +13,7 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
13
13
|
let Some(superclass) = node.field("superclass") else {
|
|
14
14
|
continue;
|
|
15
15
|
};
|
|
16
|
-
let Some(parent) = super::nodes::
|
|
16
|
+
let Some(parent) = super::nodes::children_in(superclass, context).into_iter().next() else {
|
|
17
17
|
continue;
|
|
18
18
|
};
|
|
19
19
|
if !is_struct_constructor(context, parent) {
|
|
@@ -94,7 +94,7 @@ fn correct_parent(
|
|
|
94
94
|
// `class_node.body.nil?`: a body holding nothing but comments is no body upstream.
|
|
95
95
|
if class_node
|
|
96
96
|
.field("body")
|
|
97
|
-
.is_none_or(|body| super::nodes::
|
|
97
|
+
.is_none_or(|body| super::nodes::children_in(body, context).is_empty())
|
|
98
98
|
{
|
|
99
99
|
edits.push(empty_body_removal(context, class_node, parent));
|
|
100
100
|
return;
|
|
@@ -150,7 +150,7 @@ fn unparenthesized_arguments(context: &RuleContext<'_>, parent: Node<'_>) -> Opt
|
|
|
150
150
|
if arguments.child(0).is_some_and(|open| open.kind_str() == "(") {
|
|
151
151
|
return None;
|
|
152
152
|
}
|
|
153
|
-
let joined = super::nodes::
|
|
153
|
+
let joined = super::nodes::children_in(arguments, context)
|
|
154
154
|
.into_iter()
|
|
155
155
|
.map(|argument| context.source.node_text(argument))
|
|
156
156
|
.collect::<Vec<_>>()
|
|
@@ -78,7 +78,7 @@ fn definition_parameters(definition: Node<'_>, context: &RuleContext<'_>) -> Vec
|
|
|
78
78
|
return Vec::new();
|
|
79
79
|
};
|
|
80
80
|
let mut found = Vec::new();
|
|
81
|
-
for child in super::nodes::
|
|
81
|
+
for child in super::nodes::children_in(list, context) {
|
|
82
82
|
match unfolded_defaults(child) {
|
|
83
83
|
Some(names) => found.extend(names.into_iter().map(|name| Parameter {
|
|
84
84
|
kind: "optional_parameter".to_owned(),
|
|
@@ -205,13 +205,21 @@ fn same_argument(
|
|
|
205
205
|
if argument.kind_str() != "pair" {
|
|
206
206
|
return false;
|
|
207
207
|
}
|
|
208
|
-
let
|
|
208
|
+
let Some(key) = argument.field("key") else {
|
|
209
209
|
return false;
|
|
210
210
|
};
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
211
|
+
match argument.field("value") {
|
|
212
|
+
// `sym_node.source == lvar_node.source`: only the `name:` shorthand spelling.
|
|
213
|
+
Some(value) => {
|
|
214
|
+
context.source.node_text(key) == context.source.node_text(value)
|
|
215
|
+
&& symbol_name(key, context) == parameter.name.as_deref()
|
|
216
|
+
&& value.kind_str() == "identifier"
|
|
217
|
+
}
|
|
218
|
+
// **`a:` with no value is the same pair spelled shorter.** The parser fills the
|
|
219
|
+
// omitted value in with the variable of that name, so `super(a:)` passes `a` --
|
|
220
|
+
// the grammar leaves the field empty instead.
|
|
221
|
+
None => symbol_name(key, context) == parameter.name.as_deref(),
|
|
222
|
+
}
|
|
215
223
|
}
|
|
216
224
|
// `keyword_rest_arg_same?`.
|
|
217
225
|
"hash_splat_parameter" => match ¶meter.name {
|
|
@@ -272,7 +280,7 @@ fn block_reassigned(context: &RuleContext<'_>, definition: Node<'_>, name: &str)
|
|
|
272
280
|
{
|
|
273
281
|
return true;
|
|
274
282
|
}
|
|
275
|
-
crate::rules::
|
|
283
|
+
crate::rules::push_named_children_in(node, context, &mut stack);
|
|
276
284
|
}
|
|
277
285
|
false
|
|
278
286
|
}
|
|
@@ -8,22 +8,59 @@ const MSG: &str = "Use parentheses for `super` with arguments.";
|
|
|
8
8
|
/// upstream and never reaches this cop, which is why only the calls that carry an argument list
|
|
9
9
|
/// are walked here.
|
|
10
10
|
pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
// **`super \\\n +bar` is a `super` with one argument upstream.** The parser reads the sign as
|
|
12
|
+
// belonging to the operand; the grammar reads the whole line as a binary expression whose left
|
|
13
|
+
// operand is the keyword, so the call never appears and the offense went unreported.
|
|
14
|
+
for node in context.nodes_of_any(&["call", "binary"]) {
|
|
15
|
+
let (keyword, arguments) = match node.kind_str() {
|
|
16
|
+
"binary" => {
|
|
17
|
+
let (Some(left), Some(right), Some(operator)) =
|
|
18
|
+
(node.field("left"), node.field("right"), node.field("operator"))
|
|
19
|
+
else {
|
|
20
|
+
continue;
|
|
21
|
+
};
|
|
22
|
+
if left.kind_str() != "super" {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
// Only a sign the parser folds into the operand makes the line an argument:
|
|
26
|
+
// `super == bar` is a comparison, and `super + 1` an addition, wherever the
|
|
27
|
+
// spacing puts them. The sign has to hug its operand and stand apart from the
|
|
28
|
+
// keyword, which is the spelling `super \` + `-1` has after the continuation.
|
|
29
|
+
let text = context.source.node_text(operator);
|
|
30
|
+
let source = context.source.text();
|
|
31
|
+
let hugs = !source[operator.end_byte()..].starts_with([' ', '\t']);
|
|
32
|
+
if !matches!(text, "+" | "-") || !hugs {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
(left, right)
|
|
36
|
+
}
|
|
37
|
+
_ => {
|
|
38
|
+
let Some(keyword) = node.field("method") else {
|
|
39
|
+
continue;
|
|
40
|
+
};
|
|
41
|
+
if keyword.kind_str() != "super" {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
let Some(arguments) = node.field("arguments") else {
|
|
45
|
+
continue;
|
|
46
|
+
};
|
|
47
|
+
(keyword, arguments)
|
|
48
|
+
}
|
|
14
49
|
};
|
|
15
|
-
|
|
50
|
+
// `node.parenthesized?`: the parser reads a `(` written apart from the keyword as the
|
|
51
|
+
// argument's own grouping rather than as the call's parentheses, so `super (x)` has no
|
|
52
|
+
// `loc.begin` and is an offense. The grammar puts that `(` inside the argument list either
|
|
53
|
+
// way, which leaves the space between the two as what tells them apart.
|
|
54
|
+
if arguments.start_byte() == keyword.end_byte()
|
|
55
|
+
&& context.source.node_text(arguments).starts_with('(')
|
|
56
|
+
{
|
|
16
57
|
continue;
|
|
17
58
|
}
|
|
18
|
-
|
|
19
|
-
|
|
59
|
+
// A binary's right operand is the single argument; a list holds them all.
|
|
60
|
+
let written = match node.kind_str() {
|
|
61
|
+
"binary" => vec![arguments],
|
|
62
|
+
_ => super::nodes::children_in(arguments, context),
|
|
20
63
|
};
|
|
21
|
-
// `node.parenthesized?`: the argument list starts at the paren when there is one, so its
|
|
22
|
-
// first byte is what decides.
|
|
23
|
-
if context.source.node_text(arguments).starts_with('(') {
|
|
24
|
-
continue;
|
|
25
|
-
}
|
|
26
|
-
let written = super::nodes::children(arguments);
|
|
27
64
|
let (Some(first), Some(last)) = (written.first(), written.last()) else {
|
|
28
65
|
continue;
|
|
29
66
|
};
|
|
@@ -26,7 +26,7 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
26
26
|
let Some(parent) = node.parent() else {
|
|
27
27
|
continue;
|
|
28
28
|
};
|
|
29
|
-
let statements: Vec<Node<'_>> = super::nodes::
|
|
29
|
+
let statements: Vec<Node<'_>> = super::nodes::children_in(parent, context)
|
|
30
30
|
.into_iter()
|
|
31
31
|
.filter(|child| child.kind_str() != "comment")
|
|
32
32
|
.collect();
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
use tree_sitter::Node;
|
|
2
2
|
|
|
3
3
|
use crate::diagnostic::{Edit, Offense};
|
|
4
|
+
use crate::ruby_version::RubyVersion;
|
|
4
5
|
use crate::rules::RuleContext;
|
|
5
6
|
|
|
6
7
|
use super::literal::{node_value, to_string_literal, to_symbol_literal, trim_interpolation_escape};
|
|
@@ -17,13 +18,19 @@ const ARRAY_MSG: &str = "Use %<prefer>s for an array of symbols.";
|
|
|
17
18
|
/// The characters `complex_content?` refuses to leave inside a percent literal.
|
|
18
19
|
const DELIMITERS: [char; 4] = ['[', ']', '(', ')'];
|
|
19
20
|
|
|
21
|
+
/// `minimum_target_ruby_version 2.0`: `%i[…]` arrived in 2.0.
|
|
22
|
+
const MINIMUM: RubyVersion = RubyVersion::new(2, 0);
|
|
23
|
+
|
|
20
24
|
pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
25
|
+
if context.target_ruby_version() < MINIMUM {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
21
28
|
let style: String = context
|
|
22
29
|
.setting("EnforcedStyle")
|
|
23
30
|
.unwrap_or_else(|| "percent".to_owned());
|
|
24
31
|
|
|
25
32
|
for node in context.nodes_of("array") {
|
|
26
|
-
let items = nodes::
|
|
33
|
+
let items = nodes::children_in(node, context);
|
|
27
34
|
if items.is_empty() || !items.iter().all(|item| is_symbol(context, *item)) {
|
|
28
35
|
continue;
|
|
29
36
|
}
|
|
@@ -82,7 +89,7 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
82
89
|
fn is_symbol(context: &RuleContext<'_>, node: Node<'_>) -> bool {
|
|
83
90
|
matches!(node.kind_str(), "simple_symbol" | "delimited_symbol")
|
|
84
91
|
&& !interpolated(node)
|
|
85
|
-
&& !context.source.node_text(node)
|
|
92
|
+
&& !crate::rules::support::quoted_spans_lines(context.source.node_text(node))
|
|
86
93
|
}
|
|
87
94
|
|
|
88
95
|
fn interpolated(node: Node<'_>) -> bool {
|
|
@@ -144,7 +144,7 @@ fn block_parameter(
|
|
|
144
144
|
let Some(parameters) = parameters else {
|
|
145
145
|
return implicit_parameter(context, locals, block);
|
|
146
146
|
};
|
|
147
|
-
let written = super::nodes::
|
|
147
|
+
let written = super::nodes::children_in(parameters, context);
|
|
148
148
|
let [only] = written.as_slice() else {
|
|
149
149
|
return None;
|
|
150
150
|
};
|
|
@@ -183,7 +183,7 @@ fn scan_implicit(
|
|
|
183
183
|
uses_it: &mut bool,
|
|
184
184
|
locals: &LocalVariables<'_, '_>,
|
|
185
185
|
) {
|
|
186
|
-
for child in super::nodes::
|
|
186
|
+
for child in super::nodes::children_in(node, context) {
|
|
187
187
|
// A nested block's implicit parameters are its own.
|
|
188
188
|
if matches!(child.kind_str(), "block" | "do_block" | "lambda") {
|
|
189
189
|
continue;
|
|
@@ -207,7 +207,7 @@ fn scan_implicit(
|
|
|
207
207
|
/// passed to it.
|
|
208
208
|
fn single_call(context: &RuleContext<'_>, block: Node<'_>, parameter: &str) -> Option<String> {
|
|
209
209
|
let body = block.field("body")?;
|
|
210
|
-
let statements = super::nodes::
|
|
210
|
+
let statements = super::nodes::children_in(body, context);
|
|
211
211
|
let [only] = statements.as_slice() else {
|
|
212
212
|
return None;
|
|
213
213
|
};
|
|
@@ -124,14 +124,14 @@ fn counts_into_hash(context: &RuleContext<'_>, block: Node<'_>) -> bool {
|
|
|
124
124
|
&& left
|
|
125
125
|
.field("object")
|
|
126
126
|
.is_some_and(|object| names(object, &hash, context))
|
|
127
|
-
&& matches!(super::nodes::
|
|
127
|
+
&& matches!(super::nodes::children_in(left, context).as_slice(),
|
|
128
128
|
[_, index] if names(*index, &element, context))
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
/// The element and hash names a block takes, whether declared or numbered.
|
|
132
132
|
fn two_parameters(context: &RuleContext<'_>, block: Node<'_>) -> Option<(String, String)> {
|
|
133
133
|
match block.field("parameters") {
|
|
134
|
-
Some(parameters) => match super::nodes::
|
|
134
|
+
Some(parameters) => match super::nodes::children_in(parameters, context).as_slice() {
|
|
135
135
|
[element, hash]
|
|
136
136
|
if element.kind_str() == "identifier" && hash.kind_str() == "identifier" =>
|
|
137
137
|
{
|
|
@@ -223,7 +223,7 @@ fn counts_block_value(context: &RuleContext<'_>, block: Node<'_>) -> bool {
|
|
|
223
223
|
/// The one name a block reads its value by, declared or implicit.
|
|
224
224
|
fn single_parameter(context: &RuleContext<'_>, block: Node<'_>) -> Option<String> {
|
|
225
225
|
match block.field("parameters") {
|
|
226
|
-
Some(parameters) => match super::nodes::
|
|
226
|
+
Some(parameters) => match super::nodes::children_in(parameters, context).as_slice() {
|
|
227
227
|
[only] if only.kind_str() == "identifier" => {
|
|
228
228
|
Some(context.source.node_text(*only).to_owned())
|
|
229
229
|
}
|
|
@@ -244,7 +244,7 @@ fn implicit_name(context: &RuleContext<'_>, block: Node<'_>) -> String {
|
|
|
244
244
|
if node.kind_str() == "identifier" && context.source.node_text(node) == "it" {
|
|
245
245
|
return "it".to_owned();
|
|
246
246
|
}
|
|
247
|
-
crate::rules::
|
|
247
|
+
crate::rules::push_named_children_in(node, context, &mut stack);
|
|
248
248
|
}
|
|
249
249
|
"_1".to_owned()
|
|
250
250
|
}
|
|
@@ -19,6 +19,14 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
19
19
|
let Some(condition) = node.field("condition") else {
|
|
20
20
|
continue;
|
|
21
21
|
};
|
|
22
|
+
// `not x ? a : b` is `not(x ? a : b)` upstream whatever the parentheses around `x`: the
|
|
23
|
+
// keyword binds looser than `?:`. The grammar agrees only while `x` is bare -- once it is
|
|
24
|
+
// parenthesized it hoists the conditional above the `not`, which would make the cop wrap
|
|
25
|
+
// `not (x)` and grow another pair of parentheses on every pass.
|
|
26
|
+
let condition = match keyword_not(condition, context) {
|
|
27
|
+
Some(operand) => operand,
|
|
28
|
+
None => condition,
|
|
29
|
+
};
|
|
22
30
|
if only_closing_parenthesis_is_last_line(context, condition)
|
|
23
31
|
|| condition_as_parenthesized_one_line_pattern_matching(condition)
|
|
24
32
|
{
|
|
@@ -68,6 +76,16 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
68
76
|
}
|
|
69
77
|
}
|
|
70
78
|
|
|
79
|
+
/// The operand of a `not` written as the condition, which upstream reads as standing outside the
|
|
80
|
+
/// conditional entirely. `!` is not one of these -- it binds tighter than `?:` and stays inside.
|
|
81
|
+
fn keyword_not<'tree>(node: Node<'tree>, context: &RuleContext<'_>) -> Option<Node<'tree>> {
|
|
82
|
+
if node.kind_str() != "unary" {
|
|
83
|
+
return None;
|
|
84
|
+
}
|
|
85
|
+
let operator = node.child(0)?;
|
|
86
|
+
(context.source.node_text(operator) == "not").then(|| node.field("operand"))?
|
|
87
|
+
}
|
|
88
|
+
|
|
71
89
|
/// `only_closing_parenthesis_is_last_line?`: a condition whose last line is nothing but `)` is
|
|
72
90
|
/// spread over lines on purpose, and pulling the parentheses off it would run the lines together.
|
|
73
91
|
fn only_closing_parenthesis_is_last_line(context: &RuleContext<'_>, condition: Node<'_>) -> bool {
|
|
@@ -105,17 +123,18 @@ fn parenthesized_modifier_condition(condition: Node<'_>) -> bool {
|
|
|
105
123
|
/// `safe_assignment?`: `(begin {equals_asgn? #setter_method?})`, the parenthesized assignment that
|
|
106
124
|
/// says the assignment was meant.
|
|
107
125
|
fn is_safe_assignment(context: &RuleContext<'_>, condition: Node<'_>) -> bool {
|
|
108
|
-
let children = super::nodes::
|
|
126
|
+
let children = super::nodes::children_in(condition, context);
|
|
109
127
|
let [only] = children.as_slice() else {
|
|
110
128
|
return false;
|
|
111
129
|
};
|
|
112
|
-
only.kind_str() == "assignment"
|
|
130
|
+
only.kind_str() == "assignment"
|
|
131
|
+
&& !super::nodes::is_match_assignment(*only, context.source.text())
|
|
113
132
|
}
|
|
114
133
|
|
|
115
134
|
/// `complex_condition?`: a parenthesized condition is complex when anything written inside it is.
|
|
116
135
|
fn complex_condition(context: &RuleContext<'_>, condition: Node<'_>) -> bool {
|
|
117
136
|
if condition.kind_str() == "parenthesized_statements" {
|
|
118
|
-
return super::nodes::
|
|
137
|
+
return super::nodes::children_in(condition, context)
|
|
119
138
|
.into_iter()
|
|
120
139
|
.any(|child| complex_condition(context, child));
|
|
121
140
|
}
|
|
@@ -137,11 +156,9 @@ fn non_complex_expression(context: &RuleContext<'_>, node: Node<'_>) -> bool {
|
|
|
137
156
|
.is_some_and(|operator| context.source.node_text(operator) == "defined?"),
|
|
138
157
|
// A call carrying a block is a `block` node upstream rather than a `send`, and no `block`
|
|
139
158
|
// is ever simple.
|
|
140
|
-
"call" if node.field("block").is_none() => {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
})
|
|
144
|
-
}
|
|
159
|
+
"call" if node.field("block").is_none() => node.field("method").is_some_and(|method| {
|
|
160
|
+
!super::nodes::is_operator_method(context.source.node_text(method))
|
|
161
|
+
}),
|
|
145
162
|
// `a.b = 1` is a `send` named `b=`, which is no operator; `a[0] = 1` is `:[]=`, which is.
|
|
146
163
|
"assignment" => node
|
|
147
164
|
.field("left")
|
|
@@ -153,14 +170,12 @@ fn non_complex_expression(context: &RuleContext<'_>, node: Node<'_>) -> bool {
|
|
|
153
170
|
/// `unsafe_autocorrect?`: `and`, `or` and `not` all bind looser than the ternary, so the
|
|
154
171
|
/// parentheses are what make the condition one.
|
|
155
172
|
fn unsafe_autocorrect(context: &RuleContext<'_>, condition: Node<'_>) -> bool {
|
|
156
|
-
super::nodes::
|
|
173
|
+
super::nodes::children_in(condition, context)
|
|
157
174
|
.into_iter()
|
|
158
175
|
.any(|child| match child.kind_str() {
|
|
159
|
-
"binary" | "unary" => child
|
|
160
|
-
.
|
|
161
|
-
|
|
162
|
-
matches!(context.source.node_text(operator), "and" | "or" | "not")
|
|
163
|
-
}),
|
|
176
|
+
"binary" | "unary" => child.field("operator").is_some_and(|operator| {
|
|
177
|
+
matches!(context.source.node_text(operator), "and" | "or" | "not")
|
|
178
|
+
}),
|
|
164
179
|
_ => false,
|
|
165
180
|
})
|
|
166
181
|
}
|
|
@@ -218,7 +233,7 @@ fn correct_parenthesized(context: &RuleContext<'_>, condition: Node<'_>) -> Vec<
|
|
|
218
233
|
safe: true,
|
|
219
234
|
});
|
|
220
235
|
}
|
|
221
|
-
if let Some(call) = super::nodes::
|
|
236
|
+
if let Some(call) = super::nodes::children_in(condition, context).last().copied() {
|
|
222
237
|
edits.extend(parenthesize_condition_arguments(context, call));
|
|
223
238
|
}
|
|
224
239
|
edits
|
|
@@ -12,10 +12,15 @@ const MSG: &str = "Do not define methods at the top-level.";
|
|
|
12
12
|
/// statement list, which is the same as having `program` for a parent here.
|
|
13
13
|
pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
14
14
|
for node in context.nodes_of_any(&["method", "singleton_method", "call"]) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
// `node.parent&.begin_type? ? node.parent.root? : node.root?`: a definition wrapped in
|
|
16
|
+
// parentheses is a `begin` at the top level upstream, and counts as written there.
|
|
17
|
+
if !node.parent().is_some_and(|parent| match parent.kind_str() {
|
|
18
|
+
"program" => true,
|
|
19
|
+
"parenthesized_statements" => parent
|
|
20
|
+
.parent()
|
|
21
|
+
.is_some_and(|outer| outer.kind_str() == "program"),
|
|
22
|
+
_ => false,
|
|
23
|
+
}) {
|
|
19
24
|
continue;
|
|
20
25
|
}
|
|
21
26
|
if node.kind_str() == "call" && !defines_a_method(node, context) {
|
|
@@ -40,5 +45,5 @@ fn defines_a_method(node: Node<'_>, context: &RuleContext<'_>) -> bool {
|
|
|
40
45
|
return true;
|
|
41
46
|
}
|
|
42
47
|
node.field("arguments")
|
|
43
|
-
.is_some_and(|arguments| super::nodes::
|
|
48
|
+
.is_some_and(|arguments| super::nodes::children_in(arguments, context).len() == 1)
|
|
44
49
|
}
|
|
@@ -18,7 +18,7 @@ pub(super) fn check(
|
|
|
18
18
|
let Some(body) = node.field("body") else {
|
|
19
19
|
return;
|
|
20
20
|
};
|
|
21
|
-
let statements = super::nodes::
|
|
21
|
+
let statements = super::nodes::children_in(body, context);
|
|
22
22
|
let (Some(first), Some(last)) = (statements.first(), statements.last()) else {
|
|
23
23
|
return;
|
|
24
24
|
};
|