sonicop 26.8.112 → 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/Cargo.lock +11 -11
- data/Cargo.toml +4 -4
- data/README.ja.md +36 -23
- data/README.md +38 -26
- data/lib/sonicop/version.rb +1 -1
- data/src/config/inheritance.rs +45 -3
- data/src/engine.rs +11 -7
- data/src/lib.rs +1 -0
- data/src/nul_bytes.rs +2 -6
- data/src/parser.rs +37 -0
- data/src/profile.rs +13 -1
- 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 +3 -2
- data/src/rules/layout/array_alignment.rs +1 -2
- data/src/rules/layout/block_end_newline.rs +5 -5
- data/src/rules/layout/class_structure.rs +5 -3
- data/src/rules/layout/closing_heredoc_indentation.rs +4 -3
- data/src/rules/layout/closing_parenthesis_indentation.rs +1 -2
- data/src/rules/layout/condition_position.rs +3 -2
- data/src/rules/layout/def_end_alignment.rs +2 -2
- data/src/rules/layout/dot_position.rs +1 -2
- data/src/rules/layout/empty_line_after_guard_clause.rs +3 -6
- data/src/rules/layout/empty_line_after_multiline_condition.rs +5 -5
- data/src/rules/layout/empty_lines_around_access_modifier.rs +2 -3
- data/src/rules/layout/empty_lines_around_arguments.rs +4 -4
- 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 +2 -2
- data/src/rules/layout/extra_spacing.rs +7 -6
- 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 +4 -4
- 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 +4 -3
- data/src/rules/layout/indentation_width.rs +14 -13
- data/src/rules/layout/line_continuation_leading_space.rs +4 -3
- data/src/rules/layout/line_continuation_spacing.rs +2 -2
- data/src/rules/layout/line_length.rs +101 -57
- data/src/rules/layout/multiline_assignment_layout.rs +4 -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 +3 -2
- data/src/rules/layout/single_line_block_chain.rs +4 -3
- data/src/rules/layout/space_around_block_parameters.rs +1 -2
- data/src/rules/layout/space_around_equals_in_parameter_default.rs +1 -2
- data/src/rules/layout/space_around_operators.rs +1 -2
- data/src/rules/layout/space_before_brackets.rs +6 -5
- data/src/rules/layout/space_before_comma.rs +3 -2
- data/src/rules/layout/space_inside_range_literal.rs +8 -6
- data/src/rules/layout/support.rs +9 -7
- data/src/rules/layout/tokens.rs +15 -6
- data/src/rules/lint/access_modifier.rs +19 -10
- data/src/rules/lint/ambiguity.rs +2 -2
- data/src/rules/lint/ambiguous_block_association.rs +7 -10
- data/src/rules/lint/ambiguous_regexp_literal.rs +7 -5
- data/src/rules/lint/array_literal_in_regexp.rs +4 -3
- 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 +2 -1
- 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 +6 -5
- data/src/rules/lint/duplicate_case_condition.rs +5 -5
- data/src/rules/lint/duplicate_hash_key.rs +4 -3
- data/src/rules/lint/duplicate_match_pattern.rs +7 -5
- data/src/rules/lint/duplicate_methods.rs +4 -3
- data/src/rules/lint/duplicate_require.rs +1 -2
- data/src/rules/lint/duplicate_set_element.rs +3 -2
- data/src/rules/lint/empty_conditional_body.rs +4 -3
- 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/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 +7 -5
- 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 +5 -3
- data/src/rules/lint/literal_assignment_in_condition.rs +4 -3
- data/src/rules/lint/literal_in_interpolation.rs +5 -5
- data/src/rules/lint/literals.rs +10 -8
- 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 +1 -1
- data/src/rules/lint/non_deterministic_require_order.rs +5 -3
- data/src/rules/lint/non_local_exit_from_iterator.rs +3 -2
- 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/redundant_dir_glob_sort.rs +1 -2
- data/src/rules/lint/redundant_safe_navigation.rs +4 -3
- data/src/rules/lint/redundant_splat_expansion.rs +4 -2
- data/src/rules/lint/redundant_string_coercion.rs +3 -2
- data/src/rules/lint/regexp_source.rs +2 -2
- 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 +2 -2
- data/src/rules/lint/safe_navigation_chain.rs +3 -2
- data/src/rules/lint/self_assignment.rs +3 -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_in_number_conversion.rs +4 -3
- data/src/rules/lint/symbol_conversion.rs +6 -5
- data/src/rules/lint/syntax.rs +4 -3
- 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 +3 -2
- data/src/rules/lint/unmodified_reduce_accumulator.rs +7 -6
- data/src/rules/lint/unreachable_pattern_branch.rs +4 -4
- 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 +146 -100
- data/src/rules/lint/void.rs +5 -4
- data/src/rules/metrics/block_nesting.rs +1 -2
- data/src/rules/metrics/collection_literal_length.rs +2 -1
- data/src/rules/metrics/complexity.rs +18 -13
- data/src/rules/metrics/fragments.rs +10 -14
- data/src/rules/metrics/locals.rs +23 -12
- data/src/rules/metrics/parameter_lists.rs +7 -6
- data/src/rules/metrics/support.rs +1 -1
- data/src/rules/mod.rs +464 -62
- data/src/rules/naming/ascii_identifiers.rs +3 -3
- data/src/rules/naming/block_forwarding.rs +9 -8
- data/src/rules/naming/constant_name.rs +1 -1
- data/src/rules/naming/predicate_method.rs +6 -5
- data/src/rules/naming/predicate_prefix.rs +10 -8
- data/src/rules/naming/rescued_exceptions_variable_name.rs +8 -6
- data/src/rules/naming/support.rs +7 -5
- data/src/rules/naming/variable_number.rs +4 -4
- data/src/rules/node_ext.rs +1 -1
- data/src/rules/ruby_literal.rs +3 -2
- 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 +1 -1
- data/src/rules/style/alias.rs +1 -2
- 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 +3 -3
- data/src/rules/style/array_intersect.rs +2 -2
- data/src/rules/style/array_intersect_with_single_element.rs +1 -1
- 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_delimiters.rs +7 -6
- data/src/rules/style/case_equality.rs +3 -2
- data/src/rules/style/case_like_if.rs +1 -1
- data/src/rules/style/class_and_module_children.rs +7 -5
- data/src/rules/style/class_methods.rs +1 -1
- 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 +1 -1
- 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 +8 -1
- data/src/rules/style/constant_visibility.rs +3 -3
- data/src/rules/style/copyright.rs +1 -1
- 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 +1 -1
- 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 +1 -1
- data/src/rules/style/empty_lambda_parameter.rs +1 -1
- data/src/rules/style/empty_literal.rs +2 -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 +1 -1
- data/src/rules/style/env_home.rs +1 -1
- 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_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_string.rs +2 -2
- data/src/rules/style/format_string_token.rs +6 -6
- 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 +3 -3
- data/src/rules/style/hash_subset.rs +16 -10
- data/src/rules/style/hash_syntax.rs +4 -4
- data/src/rules/style/hash_transform.rs +20 -18
- data/src/rules/style/identical_conditional_branches.rs +4 -5
- data/src/rules/style/if_inside_else.rs +3 -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 +1 -1
- data/src/rules/style/in_pattern_then.rs +2 -2
- data/src/rules/style/inverse_methods.rs +2 -2
- data/src/rules/style/invertible_unless_condition.rs +3 -3
- data/src/rules/style/it_block_parameter.rs +1 -1
- data/src/rules/style/keyword_arguments_merging.rs +2 -2
- data/src/rules/style/keyword_parameters_order.rs +1 -1
- data/src/rules/style/magic_comment_format.rs +3 -2
- 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 +1 -1
- data/src/rules/style/multiline_block_chain.rs +2 -2
- data/src/rules/style/multiline_if_then.rs +1 -1
- data/src/rules/style/multiline_in_pattern_then.rs +1 -1
- 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 +3 -3
- data/src/rules/style/negated_if.rs +2 -2
- data/src/rules/style/negated_if_else_condition.rs +2 -2
- data/src/rules/style/negated_while.rs +1 -1
- data/src/rules/style/negative_array_index.rs +2 -2
- 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 +1 -1
- 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 +2 -2
- data/src/rules/style/numbered_parameters_limit.rs +2 -2
- data/src/rules/style/one_line_conditional.rs +4 -4
- 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 +9 -10
- 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 +9 -7
- data/src/rules/style/percent_q_literals.rs +4 -3
- data/src/rules/style/preferred_hash_methods.rs +1 -1
- 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 +2 -2
- data/src/rules/style/redundant_capital_w.rs +3 -2
- data/src/rules/style/redundant_condition.rs +9 -7
- data/src/rules/style/redundant_current_directory_in_path.rs +2 -2
- data/src/rules/style/redundant_double_splat_hash_braces.rs +4 -4
- data/src/rules/style/redundant_file_extension_in_require.rs +2 -2
- data/src/rules/style/redundant_format.rs +16 -14
- 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 +2 -2
- data/src/rules/style/redundant_interpolation.rs +2 -2
- data/src/rules/style/redundant_interpolation_unfreeze.rs +2 -2
- data/src/rules/style/redundant_line_continuation.rs +5 -4
- data/src/rules/style/redundant_parentheses.rs +16 -15
- 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 +11 -11
- 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 +1 -1
- 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/sample.rs +3 -3
- data/src/rules/style/select_by.rs +2 -2
- data/src/rules/style/select_by_range.rs +1 -1
- data/src/rules/style/semicolon.rs +5 -4
- data/src/rules/style/single_argument_dig.rs +1 -1
- data/src/rules/style/single_line_block_params.rs +7 -6
- 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 +1 -1
- data/src/rules/style/string_concatenation.rs +9 -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 +1 -1
- data/src/rules/style/struct_inheritance.rs +3 -3
- data/src/rules/style/super_arguments.rs +2 -2
- data/src/rules/style/super_with_args_parentheses.rs +1 -1
- data/src/rules/style/swap_values.rs +1 -1
- data/src/rules/style/symbol_array.rs +1 -1
- 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 +4 -4
- data/src/rules/style/top_level_method_definition.rs +1 -1
- data/src/rules/style/trailing_body.rs +1 -1
- data/src/rules/style/trailing_comma_in_array_literal.rs +1 -1
- data/src/rules/style/trailing_comma_in_hash_literal.rs +1 -1
- data/src/rules/style/trailing_method_end_statement.rs +1 -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 +1 -1
- 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 +3 -3
- data/src/rules/style/yoda_condition.rs +2 -2
- data/src/rules/support.rs +33 -8
- metadata +2 -1
|
@@ -23,6 +23,7 @@ use super::support::{begins_its_line, character_column, line_indentation};
|
|
|
23
23
|
use crate::rules::RuleContext;
|
|
24
24
|
use crate::rules::lint::locals::LocalVariables;
|
|
25
25
|
use crate::rules::node_ext::NodeExt;
|
|
26
|
+
use crate::rules::send_node::named_children_iter;
|
|
26
27
|
|
|
27
28
|
/// Which of the nodes upstream's parser builds for one piece of source this stands for.
|
|
28
29
|
#[derive(Clone, Copy, Eq, PartialEq)]
|
|
@@ -44,6 +45,10 @@ enum Role {
|
|
|
44
45
|
pub(super) struct UpNode<'tree> {
|
|
45
46
|
node: Node<'tree>,
|
|
46
47
|
role: Role,
|
|
48
|
+
/// The file's node index, carried so that climbing to a parent is a lookup rather than a walk
|
|
49
|
+
/// down from the root of the tree. Every step of every chain this cop family follows asks for
|
|
50
|
+
/// one, and `Node::parent` was the largest cost of the three cops together.
|
|
51
|
+
index: &'tree crate::rules::AstIndex<'tree>,
|
|
47
52
|
}
|
|
48
53
|
|
|
49
54
|
/// The node types the ported code asks about by name.
|
|
@@ -114,11 +119,11 @@ fn block_of<'tree>(node: Node<'tree>) -> Option<Node<'tree>> {
|
|
|
114
119
|
|
|
115
120
|
/// Whether the call was fused into the setter `send` its assignment builds, which leaves it
|
|
116
121
|
/// without a node of its own upstream.
|
|
117
|
-
fn is_fused_setter_target(node: Node<'_>) -> bool {
|
|
122
|
+
fn is_fused_setter_target(node: Node<'_>, index: &crate::rules::AstIndex<'_>) -> bool {
|
|
118
123
|
if !matches!(node.kind_str(), "call" | "element_reference") {
|
|
119
124
|
return false;
|
|
120
125
|
}
|
|
121
|
-
|
|
126
|
+
index.parent(node).is_some_and(|parent| {
|
|
122
127
|
parent.kind_str() == "assignment"
|
|
123
128
|
&& parent
|
|
124
129
|
.field("left")
|
|
@@ -129,19 +134,20 @@ fn is_fused_setter_target(node: Node<'_>) -> bool {
|
|
|
129
134
|
impl<'tree> UpNode<'tree> {
|
|
130
135
|
/// The node a reference from elsewhere -- a receiver, an argument -- resolves to. A call
|
|
131
136
|
/// written with a block is the `block` node there.
|
|
132
|
-
pub(super) fn of(node: Node<'tree>) -> Self {
|
|
137
|
+
pub(super) fn of(node: Node<'tree>, index: &'tree crate::rules::AstIndex<'tree>) -> Self {
|
|
133
138
|
let role = if block_of(node).is_some() {
|
|
134
139
|
Role::Block
|
|
135
140
|
} else {
|
|
136
141
|
Role::Plain
|
|
137
142
|
};
|
|
138
|
-
Self { node, role }
|
|
143
|
+
Self { node, role, index }
|
|
139
144
|
}
|
|
140
145
|
|
|
141
|
-
pub(super) fn plain(node: Node<'tree>) -> Self {
|
|
146
|
+
pub(super) fn plain(node: Node<'tree>, index: &'tree crate::rules::AstIndex<'tree>) -> Self {
|
|
142
147
|
Self {
|
|
143
148
|
node,
|
|
144
149
|
role: Role::Plain,
|
|
150
|
+
index,
|
|
145
151
|
}
|
|
146
152
|
}
|
|
147
153
|
|
|
@@ -226,13 +232,19 @@ impl<'tree> UpNode<'tree> {
|
|
|
226
232
|
return None;
|
|
227
233
|
}
|
|
228
234
|
match node.kind_str() {
|
|
229
|
-
"call" | "method_call" => node
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
"
|
|
235
|
+
"call" | "method_call" => node
|
|
236
|
+
.field("receiver")
|
|
237
|
+
.map(|receiver| Self::of(receiver, self.index)),
|
|
238
|
+
"element_reference" => node
|
|
239
|
+
.field("object")
|
|
240
|
+
.map(|object| Self::of(object, self.index)),
|
|
241
|
+
"binary" => node.field("left").map(|left| Self::of(left, self.index)),
|
|
242
|
+
"unary" => node
|
|
243
|
+
.field("operand")
|
|
244
|
+
.map(|operand| Self::of(operand, self.index)),
|
|
233
245
|
"assignment" => {
|
|
234
246
|
let left = node.field("left")?;
|
|
235
|
-
Self::plain(left).receiver(context)
|
|
247
|
+
Self::plain(left, self.index).receiver(context)
|
|
236
248
|
}
|
|
237
249
|
_ => None,
|
|
238
250
|
}
|
|
@@ -342,29 +354,29 @@ impl<'tree> UpNode<'tree> {
|
|
|
342
354
|
}
|
|
343
355
|
match self.node.kind_str() {
|
|
344
356
|
"call" | "method_call" => match self.node.field("arguments") {
|
|
345
|
-
Some(list) => fold_arguments(list, &children_of(list)),
|
|
357
|
+
Some(list) => fold_arguments(list, &children_of(list), self.index),
|
|
346
358
|
None => Vec::new(),
|
|
347
359
|
},
|
|
348
360
|
"element_reference" => {
|
|
349
361
|
let indices: Vec<Node<'tree>> =
|
|
350
362
|
children_of(self.node).into_iter().skip(1).collect();
|
|
351
|
-
fold_arguments(self.node, &indices)
|
|
363
|
+
fold_arguments(self.node, &indices, self.index)
|
|
352
364
|
}
|
|
353
365
|
"binary" if plain_kind(context, self.node) == UpKind::Send => self
|
|
354
366
|
.node
|
|
355
367
|
.field("right")
|
|
356
|
-
.map_or_else(Vec::new, |right| vec![Self::of(right)]),
|
|
368
|
+
.map_or_else(Vec::new, |right| vec![Self::of(right, self.index)]),
|
|
357
369
|
"assignment" => {
|
|
358
370
|
let Some(left) = self.node.field("left") else {
|
|
359
371
|
return Vec::new();
|
|
360
372
|
};
|
|
361
373
|
let mut arguments = if left.kind_str() == "element_reference" {
|
|
362
|
-
Self::plain(left).arguments(context)
|
|
374
|
+
Self::plain(left, self.index).arguments(context)
|
|
363
375
|
} else {
|
|
364
376
|
Vec::new()
|
|
365
377
|
};
|
|
366
378
|
if let Some(right) = self.node.field("right") {
|
|
367
|
-
arguments.push(Self::of(right));
|
|
379
|
+
arguments.push(Self::of(right, self.index));
|
|
368
380
|
}
|
|
369
381
|
arguments
|
|
370
382
|
}
|
|
@@ -385,13 +397,14 @@ impl<'tree> UpNode<'tree> {
|
|
|
385
397
|
(self.role == Role::Plain && block_of(self.node).is_some()).then_some(Self {
|
|
386
398
|
node: self.node,
|
|
387
399
|
role: Role::Block,
|
|
400
|
+
index: self.index,
|
|
388
401
|
})
|
|
389
402
|
}
|
|
390
403
|
|
|
391
404
|
/// `BlockNode#send_node`.
|
|
392
405
|
pub(super) fn send_node(self) -> Self {
|
|
393
406
|
match self.role {
|
|
394
|
-
Role::Block => Self::plain(self.node),
|
|
407
|
+
Role::Block => Self::plain(self.node, self.index),
|
|
395
408
|
_ => self,
|
|
396
409
|
}
|
|
397
410
|
}
|
|
@@ -431,7 +444,7 @@ impl<'tree> UpNode<'tree> {
|
|
|
431
444
|
|
|
432
445
|
/// Whether the call was fused into the setter send its assignment builds.
|
|
433
446
|
pub(super) fn is_fused_setter_target(self) -> bool {
|
|
434
|
-
self.role == Role::Plain && is_fused_setter_target(self.node)
|
|
447
|
+
self.role == Role::Plain && is_fused_setter_target(self.node, self.index)
|
|
435
448
|
}
|
|
436
449
|
|
|
437
450
|
/// One of the node's own fields, for the few places the ported code reads a part the model
|
|
@@ -449,6 +462,7 @@ impl<'tree> UpNode<'tree> {
|
|
|
449
462
|
return Some(Self {
|
|
450
463
|
node,
|
|
451
464
|
role: Role::Block,
|
|
465
|
+
index: self.index,
|
|
452
466
|
});
|
|
453
467
|
}
|
|
454
468
|
let mut cursor = node.walk();
|
|
@@ -461,12 +475,12 @@ impl<'tree> UpNode<'tree> {
|
|
|
461
475
|
|
|
462
476
|
pub(super) fn parent(self) -> Option<Self> {
|
|
463
477
|
match self.role {
|
|
464
|
-
Role::Block | Role::Array => raw_parent(self.node),
|
|
478
|
+
Role::Block | Role::Array => raw_parent(self.node, self.index),
|
|
465
479
|
Role::Hash => {
|
|
466
480
|
if self.node.kind_str() == "argument_list" {
|
|
467
|
-
raw_parent(self.node)
|
|
481
|
+
raw_parent(self.node, self.index)
|
|
468
482
|
} else {
|
|
469
|
-
Some(Self::plain(self.node))
|
|
483
|
+
Some(Self::plain(self.node, self.index))
|
|
470
484
|
}
|
|
471
485
|
}
|
|
472
486
|
Role::Plain => {
|
|
@@ -474,15 +488,17 @@ impl<'tree> UpNode<'tree> {
|
|
|
474
488
|
return Some(Self {
|
|
475
489
|
node: self.node,
|
|
476
490
|
role: Role::Block,
|
|
491
|
+
index: self.index,
|
|
477
492
|
});
|
|
478
493
|
}
|
|
479
494
|
if is_lone_assigned_splat(self.node) {
|
|
480
495
|
return Some(Self {
|
|
481
496
|
node: self.node,
|
|
482
497
|
role: Role::Array,
|
|
498
|
+
index: self.index,
|
|
483
499
|
});
|
|
484
500
|
}
|
|
485
|
-
raw_parent(self.node)
|
|
501
|
+
raw_parent(self.node, self.index)
|
|
486
502
|
}
|
|
487
503
|
}
|
|
488
504
|
}
|
|
@@ -523,7 +539,11 @@ fn children_of<'tree>(node: Node<'tree>) -> Vec<Node<'tree>> {
|
|
|
523
539
|
}
|
|
524
540
|
|
|
525
541
|
/// Groups a run of `key: value` pairs into the one `hash` argument upstream's parser folds it into.
|
|
526
|
-
fn fold_arguments<'tree>(
|
|
542
|
+
fn fold_arguments<'tree>(
|
|
543
|
+
container: Node<'tree>,
|
|
544
|
+
children: &[Node<'tree>],
|
|
545
|
+
own_index: &'tree crate::rules::AstIndex<'tree>,
|
|
546
|
+
) -> Vec<UpNode<'tree>> {
|
|
527
547
|
let mut arguments = Vec::new();
|
|
528
548
|
let mut index = 0;
|
|
529
549
|
while index < children.len() {
|
|
@@ -534,10 +554,11 @@ fn fold_arguments<'tree>(container: Node<'tree>, children: &[Node<'tree>]) -> Ve
|
|
|
534
554
|
arguments.push(UpNode {
|
|
535
555
|
node: container,
|
|
536
556
|
role: Role::Hash,
|
|
557
|
+
index: own_index,
|
|
537
558
|
});
|
|
538
559
|
continue;
|
|
539
560
|
}
|
|
540
|
-
arguments.push(UpNode::of(children[index]));
|
|
561
|
+
arguments.push(UpNode::of(children[index], own_index));
|
|
541
562
|
index += 1;
|
|
542
563
|
}
|
|
543
564
|
arguments
|
|
@@ -563,32 +584,37 @@ fn hash_run_range(container: Node<'_>) -> Range<usize> {
|
|
|
563
584
|
|
|
564
585
|
/// Climbs to the node upstream would call this one's parent, stepping over the containers the
|
|
565
586
|
/// parser has no node for.
|
|
566
|
-
fn raw_parent<'tree>(
|
|
587
|
+
fn raw_parent<'tree>(
|
|
588
|
+
node: Node<'tree>,
|
|
589
|
+
index: &'tree crate::rules::AstIndex<'tree>,
|
|
590
|
+
) -> Option<UpNode<'tree>> {
|
|
567
591
|
let mut current = node;
|
|
568
592
|
loop {
|
|
569
|
-
let parent =
|
|
593
|
+
let parent = index.parent_in_tree(current)?;
|
|
570
594
|
if parent.kind_str() == "block" || parent.kind_str() == "do_block" {
|
|
571
595
|
// The body of a literal block hangs off the `block` node upstream, whose own parent is
|
|
572
596
|
// the parent of the call the block was written on.
|
|
573
597
|
return Some(UpNode {
|
|
574
|
-
node:
|
|
598
|
+
node: index.parent_in_tree(parent)?,
|
|
575
599
|
role: Role::Block,
|
|
600
|
+
index,
|
|
576
601
|
});
|
|
577
602
|
}
|
|
578
603
|
if is_hash_element(current) && HASH_CONTAINERS.contains(&parent.kind_str()) {
|
|
579
604
|
return Some(UpNode {
|
|
580
605
|
node: parent,
|
|
581
606
|
role: Role::Hash,
|
|
607
|
+
index,
|
|
582
608
|
});
|
|
583
609
|
}
|
|
584
610
|
if TRANSPARENT.contains(&parent.kind_str())
|
|
585
|
-
|| is_fused_setter_target(parent)
|
|
611
|
+
|| is_fused_setter_target(parent, index)
|
|
586
612
|
|| is_defined_parentheses(parent)
|
|
587
613
|
{
|
|
588
614
|
current = parent;
|
|
589
615
|
continue;
|
|
590
616
|
}
|
|
591
|
-
return Some(UpNode::plain(parent));
|
|
617
|
+
return Some(UpNode::plain(parent, index));
|
|
592
618
|
}
|
|
593
619
|
}
|
|
594
620
|
|
|
@@ -974,7 +1000,10 @@ impl<'tree> Mixin<'_, 'tree> {
|
|
|
974
1000
|
pub(super) fn assignment_rhs(&self, node: UpNode<'tree>) -> Option<UpNode<'tree>> {
|
|
975
1001
|
match node.kind(self.context) {
|
|
976
1002
|
UpKind::Send | UpKind::Csend => node.last_argument(self.context),
|
|
977
|
-
_ => node
|
|
1003
|
+
_ => node
|
|
1004
|
+
.node
|
|
1005
|
+
.field("right")
|
|
1006
|
+
.map(|right| UpNode::of(right, node.index)),
|
|
978
1007
|
}
|
|
979
1008
|
}
|
|
980
1009
|
|
|
@@ -1046,8 +1075,8 @@ fn is_numbered_block(context: &RuleContext<'_>, call: Node<'_>) -> bool {
|
|
|
1046
1075
|
if matches!(node.kind_str(), "block" | "do_block") {
|
|
1047
1076
|
continue;
|
|
1048
1077
|
}
|
|
1049
|
-
let
|
|
1050
|
-
stack.extend(node
|
|
1078
|
+
let _cursor = node.walk();
|
|
1079
|
+
stack.extend(named_children_iter(node, context));
|
|
1051
1080
|
}
|
|
1052
1081
|
false
|
|
1053
1082
|
}
|
|
@@ -4,6 +4,7 @@ use super::multiline_brace::{Literal, Messages, check_brace_layout, delimiters};
|
|
|
4
4
|
use crate::diagnostic::Offense;
|
|
5
5
|
use crate::rules::RuleContext;
|
|
6
6
|
use crate::rules::node_ext::NodeExt;
|
|
7
|
+
use crate::rules::send_node::named_children_of;
|
|
7
8
|
|
|
8
9
|
const MESSAGES: Messages = Messages {
|
|
9
10
|
same_line: "Closing hash brace must be on the same line as the last hash element when opening \
|
|
@@ -21,10 +22,10 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
21
22
|
let Some((open, close)) = delimiters(node, &["{"]) else {
|
|
22
23
|
continue;
|
|
23
24
|
};
|
|
24
|
-
let
|
|
25
|
+
let _cursor = node.walk();
|
|
25
26
|
// Each pair is a child of its own here: only a *brace-less* run folds into one `hash`.
|
|
26
|
-
let elements = node
|
|
27
|
-
.
|
|
27
|
+
let elements = named_children_of(node, context)
|
|
28
|
+
.into_iter()
|
|
28
29
|
.filter(|child| !matches!(child.kind_str(), "comment" | "heredoc_body"))
|
|
29
30
|
.map(|child| vec![child])
|
|
30
31
|
.collect();
|
|
@@ -38,7 +38,7 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
38
38
|
};
|
|
39
39
|
|
|
40
40
|
for ts in context.nodes_of_any(&["call", "method_call", "assignment"]) {
|
|
41
|
-
let node = UpNode::plain(ts);
|
|
41
|
+
let node = UpNode::plain(ts, context.ast_index());
|
|
42
42
|
if !matches!(node.kind(context), UpKind::Send | UpKind::Csend) {
|
|
43
43
|
continue;
|
|
44
44
|
}
|
|
@@ -15,13 +15,13 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
15
15
|
.is_none_or(|style| style == "aligned");
|
|
16
16
|
|
|
17
17
|
for ts in context.nodes_of_any(&["binary", "assignment"]) {
|
|
18
|
-
let node = UpNode::plain(ts);
|
|
18
|
+
let node = UpNode::plain(ts, context.ast_index());
|
|
19
19
|
let checked = match node.kind(context) {
|
|
20
20
|
// `on_and` / `on_or`.
|
|
21
21
|
UpKind::And | UpKind::Or => {
|
|
22
22
|
let (Some(lhs), Some(rhs)) = (
|
|
23
|
-
ts.field("left").map(UpNode::of),
|
|
24
|
-
ts.field("right").map(UpNode::of),
|
|
23
|
+
ts.field("left").map(|left| UpNode::of(left, context.ast_index())),
|
|
24
|
+
ts.field("right").map(|right| UpNode::of(right, context.ast_index())),
|
|
25
25
|
) else {
|
|
26
26
|
continue;
|
|
27
27
|
};
|
|
@@ -5,11 +5,12 @@ use tree_sitter::Node;
|
|
|
5
5
|
use crate::diagnostic::{Edit, Offense};
|
|
6
6
|
use crate::rules::RuleContext;
|
|
7
7
|
use crate::rules::node_ext::NodeExt;
|
|
8
|
-
use crate::rules::send_node::{is_plain_send,
|
|
8
|
+
use crate::rules::send_node::{is_plain_send, send_range};
|
|
9
9
|
use crate::rules::single_line::{
|
|
10
10
|
descendants, is_suitable_as_single_line, last_byte, max_line_length, to_single_line,
|
|
11
11
|
};
|
|
12
12
|
use crate::rules::support::{Verification, verified_by_reparse};
|
|
13
|
+
use crate::rules::send_node::named_children_of;
|
|
13
14
|
|
|
14
15
|
const MSG: &str = "Redundant line break detected.";
|
|
15
16
|
|
|
@@ -293,7 +294,7 @@ fn is_top(node: Node<'_>, context: &RuleContext<'_>) -> bool {
|
|
|
293
294
|
/// an `or` is ever inspected.
|
|
294
295
|
fn spine_has_send(node: Node<'_>, context: &RuleContext<'_>) -> bool {
|
|
295
296
|
if is_logical(node, context) {
|
|
296
|
-
return
|
|
297
|
+
return named_children_of(node, context)
|
|
297
298
|
.into_iter()
|
|
298
299
|
.any(|child| spine_has_send(child, context));
|
|
299
300
|
}
|
|
@@ -3,6 +3,7 @@ use tree_sitter::Node;
|
|
|
3
3
|
use crate::diagnostic::{Edit, Offense};
|
|
4
4
|
use crate::rules::RuleContext;
|
|
5
5
|
use crate::rules::node_ext::NodeExt;
|
|
6
|
+
use crate::rules::send_node::all_children_iter;
|
|
6
7
|
|
|
7
8
|
const MSG: &str = "Put method call on a separate line if chained to a single line block.";
|
|
8
9
|
|
|
@@ -73,10 +74,10 @@ fn block_of<'tree>(receiver: Node<'tree>) -> Option<Node<'tree>> {
|
|
|
73
74
|
fn dot_of<'tree>(
|
|
74
75
|
node: Node<'tree>,
|
|
75
76
|
receiver: Node<'_>,
|
|
76
|
-
context: &RuleContext<'_>,
|
|
77
|
+
context: &'tree RuleContext<'_>,
|
|
77
78
|
) -> Option<Node<'tree>> {
|
|
78
|
-
let
|
|
79
|
-
node
|
|
79
|
+
let _cursor = node.walk();
|
|
80
|
+
all_children_iter(node, context)
|
|
80
81
|
.filter(|child| !child.is_named() && child.start_byte() >= receiver.end_byte())
|
|
81
82
|
.find(|child| DOTS.contains(&context.source.node_text(*child)))
|
|
82
83
|
}
|
|
@@ -194,8 +194,7 @@ fn delimiters<'tree>(parameters: Node<'tree>) -> (Option<Node<'tree>>, Option<No
|
|
|
194
194
|
|
|
195
195
|
fn block_arguments<'tree>(parameters: Node<'tree>) -> Vec<Node<'tree>> {
|
|
196
196
|
let mut cursor = parameters.walk();
|
|
197
|
-
parameters
|
|
198
|
-
.named_children(&mut cursor)
|
|
197
|
+
parameters.named_children(&mut cursor)
|
|
199
198
|
.filter(|child| !matches!(child.kind_str(), "comment" | "heredoc_body"))
|
|
200
199
|
.collect()
|
|
201
200
|
}
|
|
@@ -65,8 +65,7 @@ fn optional_parameters(name: Node<'_>, value: Node<'_>) -> Vec<(usize, usize)> {
|
|
|
65
65
|
.filter(|left| left.kind_str() == "left_assignment_list")
|
|
66
66
|
.and_then(|left| {
|
|
67
67
|
let mut cursor = left.walk();
|
|
68
|
-
let parts: Vec<Node<'_>> = left
|
|
69
|
-
.named_children(&mut cursor)
|
|
68
|
+
let parts: Vec<Node<'_>> = left.named_children(&mut cursor)
|
|
70
69
|
.filter(|part| !matches!(part.kind_str(), "comment" | "heredoc_body"))
|
|
71
70
|
.collect();
|
|
72
71
|
match (parts.len() == 2, value.field("right")) {
|
|
@@ -407,8 +407,7 @@ fn pairs_on_same_line(pair: Node<'_>) -> bool {
|
|
|
407
407
|
return false;
|
|
408
408
|
};
|
|
409
409
|
let mut cursor = parent.walk();
|
|
410
|
-
let lines: Vec<usize> = parent
|
|
411
|
-
.named_children(&mut cursor)
|
|
410
|
+
let lines: Vec<usize> = parent.named_children(&mut cursor)
|
|
412
411
|
.filter(|child| child.kind_str() == "pair")
|
|
413
412
|
.map(|child| child.start_position().row)
|
|
414
413
|
.collect();
|
|
@@ -3,7 +3,8 @@ use tree_sitter::Node;
|
|
|
3
3
|
use crate::diagnostic::{Edit, Offense};
|
|
4
4
|
use crate::rules::RuleContext;
|
|
5
5
|
use crate::rules::node_ext::NodeExt;
|
|
6
|
-
use crate::rules::send_node::
|
|
6
|
+
use crate::rules::send_node::named_children_of;
|
|
7
|
+
use crate::rules::send_node::all_children_iter;
|
|
7
8
|
|
|
8
9
|
const MSG: &str = "Remove the space before the opening brackets.";
|
|
9
10
|
|
|
@@ -56,7 +57,7 @@ fn index_gap(node: Node<'_>, context: &RuleContext<'_>) -> Option<(usize, usize)
|
|
|
56
57
|
return None;
|
|
57
58
|
}
|
|
58
59
|
let arguments = node.field("arguments")?;
|
|
59
|
-
let children =
|
|
60
|
+
let children = named_children_of(arguments, context);
|
|
60
61
|
let [argument] = children.as_slice() else {
|
|
61
62
|
return None;
|
|
62
63
|
};
|
|
@@ -72,8 +73,8 @@ fn index_gap(node: Node<'_>, context: &RuleContext<'_>) -> Option<(usize, usize)
|
|
|
72
73
|
}
|
|
73
74
|
|
|
74
75
|
/// `node.loc.selector`, which for an index read begins at the `[`.
|
|
75
|
-
fn opening_bracket<'tree>(node: Node<'tree>, context: &RuleContext<'_>) -> Option<Node<'tree>> {
|
|
76
|
-
let
|
|
77
|
-
node
|
|
76
|
+
fn opening_bracket<'tree>(node: Node<'tree>, context: &'tree RuleContext<'_>) -> Option<Node<'tree>> {
|
|
77
|
+
let _cursor = node.walk();
|
|
78
|
+
all_children_iter(node, context)
|
|
78
79
|
.find(|child| !child.is_named() && context.source.node_text(*child) == "[")
|
|
79
80
|
}
|
|
@@ -4,6 +4,7 @@ use super::support::whitespace_before;
|
|
|
4
4
|
use crate::diagnostic::{Edit, Offense};
|
|
5
5
|
use crate::rules::RuleContext;
|
|
6
6
|
use crate::rules::node_ext::NodeExt;
|
|
7
|
+
use crate::rules::send_node::all_children_iter;
|
|
7
8
|
|
|
8
9
|
pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
9
10
|
let text = context.source.text();
|
|
@@ -17,8 +18,8 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
17
18
|
let block_braces: Vec<usize> = context
|
|
18
19
|
.nodes_of("block")
|
|
19
20
|
.filter_map(|node| {
|
|
20
|
-
let
|
|
21
|
-
node
|
|
21
|
+
let _cursor = node.walk();
|
|
22
|
+
all_children_iter(node, context)
|
|
22
23
|
.find(|child| child.kind_str() == "{")
|
|
23
24
|
.map(|child| child.start_byte())
|
|
24
25
|
})
|
|
@@ -5,6 +5,8 @@ use tree_sitter::Node;
|
|
|
5
5
|
use crate::diagnostic::{Edit, Offense};
|
|
6
6
|
use crate::rules::RuleContext;
|
|
7
7
|
use crate::rules::node_ext::NodeExt;
|
|
8
|
+
use crate::rules::send_node::named_children_of;
|
|
9
|
+
use crate::rules::send_node::all_children_of;
|
|
8
10
|
|
|
9
11
|
const MSG: &str = "Space inside range literal.";
|
|
10
12
|
|
|
@@ -14,9 +16,9 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
14
16
|
if is_flip_flop(context, node) {
|
|
15
17
|
continue;
|
|
16
18
|
}
|
|
17
|
-
let
|
|
18
|
-
let Some(operator) = node
|
|
19
|
-
.
|
|
19
|
+
let _cursor = node.walk();
|
|
20
|
+
let Some(operator) = all_children_of(node, context)
|
|
21
|
+
.into_iter()
|
|
20
22
|
.find(|child| matches!(child.kind_str(), ".." | "..."))
|
|
21
23
|
else {
|
|
22
24
|
continue;
|
|
@@ -83,9 +85,9 @@ fn is_flip_flop(context: &RuleContext<'_>, node: Node<'_>) -> bool {
|
|
|
83
85
|
while let Some(parent) = current.parent_of(context) {
|
|
84
86
|
match parent.kind_str() {
|
|
85
87
|
"parenthesized_statements" => {
|
|
86
|
-
let
|
|
87
|
-
if parent
|
|
88
|
-
.
|
|
88
|
+
let _cursor = parent.walk();
|
|
89
|
+
if named_children_of(parent, context)
|
|
90
|
+
.into_iter()
|
|
89
91
|
.filter(|child| !matches!(child.kind_str(), "comment" | "heredoc_body"))
|
|
90
92
|
.count()
|
|
91
93
|
!= 1
|
data/src/rules/layout/support.rs
CHANGED
|
@@ -8,6 +8,8 @@ use tree_sitter::Node;
|
|
|
8
8
|
use crate::diagnostic::{Edit, Offense};
|
|
9
9
|
use crate::rules::RuleContext;
|
|
10
10
|
use crate::rules::node_ext::NodeExt;
|
|
11
|
+
use crate::rules::send_node::all_children_of;
|
|
12
|
+
use crate::rules::send_node::named_children_of;
|
|
11
13
|
pub(super) use crate::rules::support::final_pos;
|
|
12
14
|
|
|
13
15
|
/// The run of spaces and tabs ending at `offset`.
|
|
@@ -518,13 +520,13 @@ pub(super) fn holds_block_comment(context: &RuleContext<'_>, expr: &Range<usize>
|
|
|
518
520
|
/// This is `each_argument_node`, which walks each argument's subtree but stops at anything that is
|
|
519
521
|
/// a method call upstream -- so a literal nested inside another call belongs to that call instead.
|
|
520
522
|
pub(super) fn argument_literals<'tree>(
|
|
521
|
-
context: &RuleContext<'_>,
|
|
523
|
+
context: &'tree RuleContext<'_>,
|
|
522
524
|
call: Node<'tree>,
|
|
523
525
|
kinds: &[&str],
|
|
524
526
|
) -> Vec<(Node<'tree>, Node<'tree>)> {
|
|
525
|
-
let
|
|
526
|
-
let Some(list) = call
|
|
527
|
-
.
|
|
527
|
+
let _cursor = call.walk();
|
|
528
|
+
let Some(list) = all_children_of(call, context)
|
|
529
|
+
.into_iter()
|
|
528
530
|
.find(|child| child.kind_str() == "argument_list")
|
|
529
531
|
else {
|
|
530
532
|
return Vec::new();
|
|
@@ -893,9 +895,9 @@ pub(super) fn heredoc_terminators(context: &RuleContext<'_>) -> Vec<(usize, Rang
|
|
|
893
895
|
.enumerate()
|
|
894
896
|
.filter_map(|(index, body)| {
|
|
895
897
|
let opener = *openers.get(index)?;
|
|
896
|
-
let
|
|
897
|
-
let terminator = body
|
|
898
|
-
.
|
|
898
|
+
let _cursor = body.walk();
|
|
899
|
+
let terminator = named_children_of(body, context)
|
|
900
|
+
.into_iter()
|
|
899
901
|
.find(|child| child.kind_str() == "heredoc_end")?;
|
|
900
902
|
Some((opener, terminator.byte_range()))
|
|
901
903
|
})
|
data/src/rules/layout/tokens.rs
CHANGED
|
@@ -182,8 +182,7 @@ impl Builder<'_, '_> {
|
|
|
182
182
|
self.push(node);
|
|
183
183
|
return;
|
|
184
184
|
}
|
|
185
|
-
|
|
186
|
-
for child in node.children(&mut cursor) {
|
|
185
|
+
for child in children_of(self.context, node) {
|
|
187
186
|
self.walk(child);
|
|
188
187
|
}
|
|
189
188
|
}
|
|
@@ -208,8 +207,7 @@ impl Builder<'_, '_> {
|
|
|
208
207
|
return;
|
|
209
208
|
}
|
|
210
209
|
let mut offset = from;
|
|
211
|
-
|
|
212
|
-
for child in node.children(&mut cursor) {
|
|
210
|
+
for child in children_of(self.context, node) {
|
|
213
211
|
if child.end_byte() <= from {
|
|
214
212
|
continue;
|
|
215
213
|
}
|
|
@@ -229,8 +227,7 @@ impl Builder<'_, '_> {
|
|
|
229
227
|
|
|
230
228
|
/// The two delimiters of an empty percent literal, emitted as neighbours.
|
|
231
229
|
fn emit_delimiters(&mut self, node: Node<'_>, from: usize) {
|
|
232
|
-
|
|
233
|
-
for child in node.children(&mut cursor) {
|
|
230
|
+
for child in children_of(self.context, node) {
|
|
234
231
|
if child.end_byte() <= from {
|
|
235
232
|
continue;
|
|
236
233
|
}
|
|
@@ -387,3 +384,15 @@ fn opens_a_command_argument(node: Node<'_>) -> bool {
|
|
|
387
384
|
.and_then(|list| list.parent())
|
|
388
385
|
.is_some_and(|parent| parent.kind_str() == "call")
|
|
389
386
|
}
|
|
387
|
+
|
|
388
|
+
/// A node's children, from the file's index. Collected rather than iterated because the walk
|
|
389
|
+
/// takes `&mut self`, and a list of nodes is far cheaper than the cursor walk it replaces.
|
|
390
|
+
fn children_of<'node>(context: &'node RuleContext<'_>, node: Node<'node>) -> Vec<Node<'node>> {
|
|
391
|
+
match context.children(node) {
|
|
392
|
+
Some(children) => children.collect(),
|
|
393
|
+
None => {
|
|
394
|
+
let mut cursor = node.walk();
|
|
395
|
+
node.children(&mut cursor).collect()
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
@@ -10,6 +10,8 @@ use tree_sitter::Node;
|
|
|
10
10
|
|
|
11
11
|
use crate::rules::RuleContext;
|
|
12
12
|
use crate::rules::node_ext::NodeExt;
|
|
13
|
+
use crate::rules::send_node::named_children_iter;
|
|
14
|
+
use crate::rules::send_node::named_children_of;
|
|
13
15
|
|
|
14
16
|
/// The names `bare_access_modifier_declaration?` matches, interned so a visibility can be carried
|
|
15
17
|
/// around as a `&'static str` rather than borrowed from the source it was read out of.
|
|
@@ -33,7 +35,7 @@ pub(in crate::rules) fn send_name<'a>(
|
|
|
33
35
|
context: &'a RuleContext<'_>,
|
|
34
36
|
) -> Option<&'a str> {
|
|
35
37
|
match node.kind_str() {
|
|
36
|
-
"identifier" if is_send_identifier(node) => Some(context.source.node_text(node)),
|
|
38
|
+
"identifier" if is_send_identifier(node, context) => Some(context.source.node_text(node)),
|
|
37
39
|
"call" if node.field("block").is_none() => {
|
|
38
40
|
let method = node.field("method")?;
|
|
39
41
|
crate::rules::send_node::is_plain_send(node, context)
|
|
@@ -76,11 +78,11 @@ pub(super) fn bare_access_modifier(
|
|
|
76
78
|
/// What this cannot tell is a read of a local variable, which is an `lvar` upstream and a plain
|
|
77
79
|
/// identifier here as well. Only a file that assigned `private` (or one of its siblings) to a
|
|
78
80
|
/// local could be misread, and the name would have to be one of five.
|
|
79
|
-
fn is_send_identifier(node: Node<'_>) -> bool {
|
|
80
|
-
let Some(parent) =
|
|
81
|
+
fn is_send_identifier(node: Node<'_>, context: &RuleContext<'_>) -> bool {
|
|
82
|
+
let Some(parent) = context.parent(node) else {
|
|
81
83
|
return true;
|
|
82
84
|
};
|
|
83
|
-
let field = field_name(node, parent);
|
|
85
|
+
let field = field_name(node, parent, context.ast_index());
|
|
84
86
|
match parent.kind_str() {
|
|
85
87
|
"call" => field != Some("method"),
|
|
86
88
|
"method" | "singleton_method" => field != Some("name"),
|
|
@@ -106,7 +108,14 @@ fn is_send_identifier(node: Node<'_>) -> bool {
|
|
|
106
108
|
}
|
|
107
109
|
}
|
|
108
110
|
|
|
109
|
-
fn field_name<'tree>(
|
|
111
|
+
fn field_name<'tree>(
|
|
112
|
+
node: Node<'tree>,
|
|
113
|
+
parent: Node<'tree>,
|
|
114
|
+
index: &super::super::AstIndex<'_>,
|
|
115
|
+
) -> Option<&'static str> {
|
|
116
|
+
if index.knows(node) {
|
|
117
|
+
return index.field_name_of(node);
|
|
118
|
+
}
|
|
110
119
|
let mut cursor = parent.walk();
|
|
111
120
|
if !cursor.goto_first_child() {
|
|
112
121
|
return None;
|
|
@@ -193,9 +202,9 @@ fn branch_repeats_condition(
|
|
|
193
202
|
context: &RuleContext<'_>,
|
|
194
203
|
) -> bool {
|
|
195
204
|
let text = context.source.node_text(condition);
|
|
196
|
-
let
|
|
197
|
-
let branches: Vec<Node<'_>> = conditional
|
|
198
|
-
.
|
|
205
|
+
let _cursor = conditional.walk();
|
|
206
|
+
let branches: Vec<Node<'_>> = named_children_of(conditional, context)
|
|
207
|
+
.into_iter()
|
|
199
208
|
.filter(|child| child.id() != condition.id())
|
|
200
209
|
.collect();
|
|
201
210
|
branches.into_iter().any(|branch| {
|
|
@@ -203,8 +212,8 @@ fn branch_repeats_condition(
|
|
|
203
212
|
// statement is that statement, and one holding several is a `begin` no condition matches.
|
|
204
213
|
let branch = match branch.kind_str() {
|
|
205
214
|
"then" | "else" => {
|
|
206
|
-
let
|
|
207
|
-
let mut children = branch
|
|
215
|
+
let _cursor = branch.walk();
|
|
216
|
+
let mut children = named_children_iter(branch, context);
|
|
208
217
|
match (children.next(), children.next()) {
|
|
209
218
|
(Some(only), None) => only,
|
|
210
219
|
_ => return false,
|