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
data/src/rules/lint/ambiguity.rs
CHANGED
|
@@ -17,7 +17,7 @@ use tree_sitter::Node;
|
|
|
17
17
|
use crate::diagnostic::Edit;
|
|
18
18
|
use crate::rules::RuleContext;
|
|
19
19
|
use crate::rules::node_ext::NodeExt;
|
|
20
|
-
use crate::rules::send_node::
|
|
20
|
+
use crate::rules::send_node::named_children_iter;
|
|
21
21
|
|
|
22
22
|
/// One ambiguity the lexer would have warned about.
|
|
23
23
|
pub(super) struct Ambiguity<'tree> {
|
|
@@ -70,7 +70,7 @@ pub(super) fn scan<'tree>(
|
|
|
70
70
|
continue;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
let Some(first) =
|
|
73
|
+
let Some(first) = named_children_iter(list, context).next() else {
|
|
74
74
|
continue;
|
|
75
75
|
};
|
|
76
76
|
let text = context.source.node_text(first);
|
|
@@ -4,6 +4,8 @@ use tree_sitter::Node;
|
|
|
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::named_children_of;
|
|
8
|
+
use crate::rules::send_node::named_children_iter;
|
|
7
9
|
|
|
8
10
|
/// The enumerable methods a trailing `do` block was probably meant for.
|
|
9
11
|
const BLOCK_METHODS: &[&str] = &[
|
|
@@ -84,7 +86,7 @@ fn check_brace_block_argument(
|
|
|
84
86
|
let Some(arguments) = node.field("arguments") else {
|
|
85
87
|
return;
|
|
86
88
|
};
|
|
87
|
-
let list =
|
|
89
|
+
let list = named_children_of(arguments, context);
|
|
88
90
|
let (Some(&first), Some(&last)) = (list.first(), list.last()) else {
|
|
89
91
|
return;
|
|
90
92
|
};
|
|
@@ -173,7 +175,7 @@ fn check_do_block(
|
|
|
173
175
|
let Some(arguments) = call.field("arguments") else {
|
|
174
176
|
return;
|
|
175
177
|
};
|
|
176
|
-
let Some(&last) =
|
|
178
|
+
let Some(&last) = named_children_of(arguments, context).last() else {
|
|
177
179
|
return;
|
|
178
180
|
};
|
|
179
181
|
if parenthesized(call, arguments, context) {
|
|
@@ -202,7 +204,7 @@ fn check_do_block(
|
|
|
202
204
|
fn trailing_block_method<'tree>(
|
|
203
205
|
node: Node<'tree>,
|
|
204
206
|
end: usize,
|
|
205
|
-
context: &RuleContext<'_>,
|
|
207
|
+
context: &'tree RuleContext<'_>,
|
|
206
208
|
) -> Option<Node<'tree>> {
|
|
207
209
|
let mut stack = vec![node];
|
|
208
210
|
while let Some(current) = stack.pop() {
|
|
@@ -214,18 +216,13 @@ fn trailing_block_method<'tree>(
|
|
|
214
216
|
return Some(current);
|
|
215
217
|
}
|
|
216
218
|
let start = stack.len();
|
|
217
|
-
let
|
|
218
|
-
stack.extend(current
|
|
219
|
+
let _cursor = current.walk();
|
|
220
|
+
stack.extend(named_children_iter(current, context));
|
|
219
221
|
stack[start..].reverse();
|
|
220
222
|
}
|
|
221
223
|
None
|
|
222
224
|
}
|
|
223
225
|
|
|
224
|
-
fn named_children<'tree>(node: Node<'tree>) -> Vec<Node<'tree>> {
|
|
225
|
-
let mut cursor = node.walk();
|
|
226
|
-
node.named_children(&mut cursor).collect()
|
|
227
|
-
}
|
|
228
|
-
|
|
229
226
|
/// The block written on a call, which upstream holds one level above the call instead.
|
|
230
227
|
fn block_of(node: Node<'_>) -> Option<Node<'_>> {
|
|
231
228
|
(node.kind_str() == "call")
|
|
@@ -5,6 +5,8 @@ use crate::rules::RuleContext;
|
|
|
5
5
|
use crate::rules::node_ext::NodeExt;
|
|
6
6
|
|
|
7
7
|
use super::ambiguity::scan;
|
|
8
|
+
use crate::rules::send_node::named_children_of;
|
|
9
|
+
use crate::rules::send_node::named_children_iter;
|
|
8
10
|
|
|
9
11
|
const MSG: &str = "Ambiguous regexp literal. Parenthesize the method arguments if it's surely a \
|
|
10
12
|
regexp literal, or add a whitespace to the right of the `/` if it should be a division.";
|
|
@@ -31,8 +33,8 @@ fn matches_a_static_regexp(owner: Node<'_>, context: &RuleContext<'_>) -> bool {
|
|
|
31
33
|
let Some(arguments) = owner.field("arguments") else {
|
|
32
34
|
return false;
|
|
33
35
|
};
|
|
34
|
-
let
|
|
35
|
-
let Some(first) = arguments
|
|
36
|
+
let _cursor = arguments.walk();
|
|
37
|
+
let Some(first) = named_children_iter(arguments, context).next() else {
|
|
36
38
|
return false;
|
|
37
39
|
};
|
|
38
40
|
if first.kind_str() != "binary"
|
|
@@ -47,9 +49,9 @@ fn matches_a_static_regexp(owner: Node<'_>, context: &RuleContext<'_>) -> bool {
|
|
|
47
49
|
.field("left")
|
|
48
50
|
.filter(|left| left.kind_str() == "regex")
|
|
49
51
|
.is_some_and(|left| {
|
|
50
|
-
let
|
|
51
|
-
!left
|
|
52
|
-
.
|
|
52
|
+
let _cursor = left.walk();
|
|
53
|
+
!named_children_of(left, context)
|
|
54
|
+
.into_iter()
|
|
53
55
|
.any(|part| part.kind_str() == "interpolation")
|
|
54
56
|
})
|
|
55
57
|
}
|
|
@@ -3,9 +3,10 @@ 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::{has_interpolation,
|
|
6
|
+
use crate::rules::send_node::{has_interpolation, string_text, symbol_name};
|
|
7
7
|
|
|
8
8
|
use super::node_equality::numeric_value;
|
|
9
|
+
use crate::rules::send_node::named_children_of;
|
|
9
10
|
|
|
10
11
|
const MSG_CHARACTER_CLASS: &str =
|
|
11
12
|
"Use a character class instead of interpolating an array in a regexp.";
|
|
@@ -21,7 +22,7 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
21
22
|
{
|
|
22
23
|
continue;
|
|
23
24
|
}
|
|
24
|
-
let Some(array) =
|
|
25
|
+
let Some(array) = named_children_of(node, context)
|
|
25
26
|
.into_iter()
|
|
26
27
|
.rfind(|child| child.kind_str() != "comment")
|
|
27
28
|
// `%w[…]` and `%i[…]` are `array` nodes upstream. The grammar gives each percent form
|
|
@@ -30,7 +31,7 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
30
31
|
else {
|
|
31
32
|
continue;
|
|
32
33
|
};
|
|
33
|
-
let elements: Vec<Node<'_>> =
|
|
34
|
+
let elements: Vec<Node<'_>> = named_children_of(array, context)
|
|
34
35
|
.into_iter()
|
|
35
36
|
.filter(|child| child.kind_str() != "comment")
|
|
36
37
|
.collect();
|
|
@@ -6,6 +6,7 @@ use tree_sitter::Node;
|
|
|
6
6
|
use crate::diagnostic::{Edit, Offense};
|
|
7
7
|
use crate::rules::RuleContext;
|
|
8
8
|
use crate::rules::node_ext::NodeExt;
|
|
9
|
+
use crate::rules::send_node::named_children_iter;
|
|
9
10
|
|
|
10
11
|
const MSG_WITH_SAFE_ASSIGNMENT_ALLOWED: &str = "Use `==` if you meant to do a comparison or wrap the expression in parentheses to \
|
|
11
12
|
indicate you meant to assign in a condition.";
|
|
@@ -191,8 +192,8 @@ fn traverse(
|
|
|
191
192
|
}
|
|
192
193
|
Shape::Other => {}
|
|
193
194
|
}
|
|
194
|
-
let
|
|
195
|
-
let children: Vec<Node<'_>> = node
|
|
195
|
+
let _cursor = node.walk();
|
|
196
|
+
let children: Vec<Node<'_>> = named_children_iter(node, context).collect();
|
|
196
197
|
for child in children {
|
|
197
198
|
traverse(child, context, allow_safe, reported, offenses);
|
|
198
199
|
}
|
data/src/rules/lint/blocks.rs
CHANGED
|
@@ -14,6 +14,7 @@ use crate::rules::send_node::named_children;
|
|
|
14
14
|
|
|
15
15
|
use super::locals::LocalVariables;
|
|
16
16
|
use crate::rules::node_ext::NodeExt;
|
|
17
|
+
use crate::rules::send_node::named_children_of;
|
|
17
18
|
|
|
18
19
|
/// The kinds tree-sitter writes a block as. A `lambda` is `-> { }`, which upstream also reaches
|
|
19
20
|
/// through `on_block`.
|
|
@@ -87,7 +88,7 @@ fn scan(
|
|
|
87
88
|
highest: &mut usize,
|
|
88
89
|
it: &mut bool,
|
|
89
90
|
) {
|
|
90
|
-
for child in
|
|
91
|
+
for child in named_children_of(node, context) {
|
|
91
92
|
if BLOCK_KINDS.contains(&child.kind_str()) || child.kind_str() == "lambda" {
|
|
92
93
|
continue;
|
|
93
94
|
}
|
|
@@ -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::named_children_iter;
|
|
6
7
|
|
|
7
8
|
/// The node kinds a `sym` reaches tree-sitter as. A `%i[]` element is a `bare_symbol` instead,
|
|
8
9
|
/// which is how the percent literal upstream exempts stays exempt.
|
|
@@ -53,8 +54,8 @@ fn boolean_name<'a>(node: Node<'_>, context: &'a RuleContext<'_>) -> Option<&'a
|
|
|
53
54
|
|
|
54
55
|
/// The text between the quotes, when that is all there is between them.
|
|
55
56
|
fn quoted_content<'a>(node: Node<'_>, context: &'a RuleContext<'_>) -> Option<&'a str> {
|
|
56
|
-
let
|
|
57
|
-
let parts: Vec<Node<'_>> = node
|
|
57
|
+
let _cursor = node.walk();
|
|
58
|
+
let parts: Vec<Node<'_>> = named_children_iter(node, context).collect();
|
|
58
59
|
match parts.as_slice() {
|
|
59
60
|
[content] if content.kind_str() == "string_content" => Some(context.source.node_text(*content)),
|
|
60
61
|
_ => None,
|
|
@@ -68,8 +69,7 @@ fn colon_pair(pair: Node<'_>) -> bool {
|
|
|
68
69
|
|
|
69
70
|
fn separator(pair: Node<'_>) -> Option<Node<'_>> {
|
|
70
71
|
let mut cursor = pair.walk();
|
|
71
|
-
let separator = pair
|
|
72
|
-
.children(&mut cursor)
|
|
72
|
+
let separator = pair.children(&mut cursor)
|
|
73
73
|
.find(|child| !child.is_named() && matches!(child.kind_str(), ":" | "=>"))?;
|
|
74
74
|
Some(separator)
|
|
75
75
|
}
|
|
@@ -43,8 +43,7 @@ fn enclosing_block(node: Node<'_>) -> Option<Node<'_>> {
|
|
|
43
43
|
// statements one level further down again -- so nothing in such a block is written directly in
|
|
44
44
|
// it any more.
|
|
45
45
|
let mut cursor = body.walk();
|
|
46
|
-
if body
|
|
47
|
-
.named_children(&mut cursor)
|
|
46
|
+
if body.named_children(&mut cursor)
|
|
48
47
|
.any(|child| matches!(child.kind_str(), "rescue" | "else" | "ensure"))
|
|
49
48
|
{
|
|
50
49
|
return None;
|
|
@@ -7,6 +7,7 @@ use crate::rules::RuleContext;
|
|
|
7
7
|
use crate::rules::node_ext::NodeExt;
|
|
8
8
|
use crate::rules::send_node::{arguments, named_children, string_text, symbol_name};
|
|
9
9
|
use crate::rules::support::spurious_assignment_list;
|
|
10
|
+
use crate::rules::send_node::named_children_of;
|
|
10
11
|
|
|
11
12
|
/// The parts of a constant path, as `each_path` walks them.
|
|
12
13
|
struct ConstantPath {
|
|
@@ -45,7 +46,7 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
45
46
|
},
|
|
46
47
|
_ => namespaces.clone(),
|
|
47
48
|
};
|
|
48
|
-
let mut children =
|
|
49
|
+
let mut children = named_children_of(node, context);
|
|
49
50
|
children.reverse();
|
|
50
51
|
for child in children {
|
|
51
52
|
stack.push((child, inner.clone()));
|
|
@@ -223,7 +223,6 @@ fn sanitize_arguments(
|
|
|
223
223
|
/// `loc.double_colon`: the `::` the name was written after.
|
|
224
224
|
fn separator<'tree>(receiver: Node<'tree>, name: Node<'_>) -> Option<Node<'tree>> {
|
|
225
225
|
let mut cursor = receiver.walk();
|
|
226
|
-
receiver
|
|
227
|
-
.children(&mut cursor)
|
|
226
|
+
receiver.children(&mut cursor)
|
|
228
227
|
.find(|child| !child.is_named() && child.end_byte() <= name.start_byte())
|
|
229
228
|
}
|
|
@@ -2,8 +2,8 @@ use tree_sitter::Node;
|
|
|
2
2
|
|
|
3
3
|
use crate::diagnostic::{Edit, Offense};
|
|
4
4
|
use crate::rules::RuleContext;
|
|
5
|
-
use crate::rules::send_node::named_children;
|
|
6
5
|
use crate::rules::node_ext::NodeExt;
|
|
6
|
+
use crate::rules::send_node::named_children_of;
|
|
7
7
|
|
|
8
8
|
const MSG: &str = "Unnecessary disjunctive assignment. Use plain assignment.";
|
|
9
9
|
|
|
@@ -20,7 +20,7 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
20
20
|
};
|
|
21
21
|
// A body with a `rescue` or an `ensure` is one node of that type upstream rather than the
|
|
22
22
|
// `begin` this walks, so the very first line already fails the `or_asgn` test.
|
|
23
|
-
let lines =
|
|
23
|
+
let lines = named_children_of(body, context);
|
|
24
24
|
if lines
|
|
25
25
|
.iter()
|
|
26
26
|
.any(|line| matches!(line.kind_str(), "rescue" | "ensure" | "else"))
|
|
@@ -5,10 +5,11 @@ use tree_sitter::Node;
|
|
|
5
5
|
use crate::diagnostic::Offense;
|
|
6
6
|
use crate::rules::RuleContext;
|
|
7
7
|
use crate::rules::node_ext::NodeExt;
|
|
8
|
-
use crate::rules::send_node::named_children;
|
|
9
8
|
|
|
10
9
|
use super::node_equality::identical;
|
|
11
10
|
use super::statements::{body_children, statements};
|
|
11
|
+
use crate::rules::send_node::named_children_of;
|
|
12
|
+
use crate::rules::send_node::named_children_iter;
|
|
12
13
|
|
|
13
14
|
/// One branch, with what upstream would report it at.
|
|
14
15
|
struct Branch<'tree> {
|
|
@@ -53,7 +54,7 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
53
54
|
// `on_rescue`: the clauses of one body, which the grammar keeps as siblings rather than under
|
|
54
55
|
// a node of their own.
|
|
55
56
|
for container in context.nodes_of_any(&["begin", "body_statement", "block_body", "do"]) {
|
|
56
|
-
let clauses: Vec<Node<'_>> =
|
|
57
|
+
let clauses: Vec<Node<'_>> = named_children_of(container, context)
|
|
57
58
|
.into_iter()
|
|
58
59
|
.filter(|child| matches!(child.kind_str(), "rescue" | "else"))
|
|
59
60
|
.collect();
|
|
@@ -135,8 +136,8 @@ fn branches<'tree>(node: Node<'tree>, context: &'tree RuleContext<'_>) -> Vec<Br
|
|
|
135
136
|
let mut collected = Vec::new();
|
|
136
137
|
match node.kind_str() {
|
|
137
138
|
"case" | "case_match" => {
|
|
138
|
-
let
|
|
139
|
-
for clause in node
|
|
139
|
+
let _cursor = node.walk();
|
|
140
|
+
for clause in named_children_iter(node, context) {
|
|
140
141
|
match clause.kind_str() {
|
|
141
142
|
"when" | "in_clause" => collected.push(Branch {
|
|
142
143
|
nodes: clause.field("body").map(statements).unwrap_or_default(),
|
|
@@ -235,7 +236,7 @@ fn is_literal_branch(
|
|
|
235
236
|
return true;
|
|
236
237
|
}
|
|
237
238
|
let mut all = true;
|
|
238
|
-
crate::rules::walk_named(only, &mut |node| {
|
|
239
|
+
crate::rules::walk_named(only, context, &mut |node| {
|
|
239
240
|
if node.id() == only.id() || !all {
|
|
240
241
|
return;
|
|
241
242
|
}
|
|
@@ -5,15 +5,16 @@ use crate::rules::RuleContext;
|
|
|
5
5
|
|
|
6
6
|
use super::node_equality::identical;
|
|
7
7
|
use crate::rules::node_ext::NodeExt;
|
|
8
|
+
use crate::rules::send_node::named_children_of;
|
|
8
9
|
|
|
9
10
|
const MSG: &str = "Duplicate `when` condition detected.";
|
|
10
11
|
|
|
11
12
|
pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
12
13
|
for case in context.nodes_of("case") {
|
|
13
14
|
let mut seen: Vec<Node<'_>> = Vec::new();
|
|
14
|
-
let
|
|
15
|
-
let branches: Vec<Node<'_>> = case
|
|
16
|
-
.
|
|
15
|
+
let _cursor = case.walk();
|
|
16
|
+
let branches: Vec<Node<'_>> = named_children_of(case, context)
|
|
17
|
+
.into_iter()
|
|
17
18
|
.filter(|child| child.kind_str() == "when")
|
|
18
19
|
.collect();
|
|
19
20
|
for branch in branches {
|
|
@@ -35,8 +36,7 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
35
36
|
/// condition, so what upstream reports is the node inside it.
|
|
36
37
|
fn conditions<'tree>(branch: Node<'tree>) -> Vec<Node<'tree>> {
|
|
37
38
|
let mut cursor = branch.walk();
|
|
38
|
-
branch
|
|
39
|
-
.named_children(&mut cursor)
|
|
39
|
+
branch.named_children(&mut cursor)
|
|
40
40
|
.filter(|child| child.kind_str() == "pattern")
|
|
41
41
|
.filter_map(|pattern| pattern.named_child(0))
|
|
42
42
|
.collect()
|
|
@@ -6,6 +6,7 @@ use crate::rules::RuleContext;
|
|
|
6
6
|
use super::literals::{is_constant, recursive_basic_literal};
|
|
7
7
|
use super::node_equality::equality_key;
|
|
8
8
|
use crate::rules::node_ext::NodeExt;
|
|
9
|
+
use crate::rules::send_node::named_children_of;
|
|
9
10
|
|
|
10
11
|
const MSG: &str = "Duplicated key in hash literal.";
|
|
11
12
|
|
|
@@ -14,10 +15,10 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
14
15
|
// the argument list, so a call's keyword arguments are no hash node here -- and every duplicate
|
|
15
16
|
// written that way went unreported.
|
|
16
17
|
for hash in context.nodes_of_any(&["hash", "argument_list"]) {
|
|
17
|
-
let
|
|
18
|
+
let _cursor = hash.walk();
|
|
18
19
|
// `HashNode#keys`: a `**splat` entry is no pair and contributes no key.
|
|
19
|
-
let keys: Vec<_> = hash
|
|
20
|
-
.
|
|
20
|
+
let keys: Vec<_> = named_children_of(hash, context)
|
|
21
|
+
.into_iter()
|
|
21
22
|
.filter(|child| child.kind_str() == "pair")
|
|
22
23
|
.filter_map(|pair| pair.field("key"))
|
|
23
24
|
.filter(|key| recursive_basic_literal(*key, context) || is_constant(*key, context))
|
|
@@ -6,15 +6,17 @@ use crate::diagnostic::Offense;
|
|
|
6
6
|
use crate::rules::RuleContext;
|
|
7
7
|
use crate::rules::node_ext::NodeExt;
|
|
8
8
|
use crate::ruby_version::RubyVersion;
|
|
9
|
+
use crate::rules::send_node::named_children_of;
|
|
10
|
+
use crate::rules::send_node::named_children_iter;
|
|
9
11
|
|
|
10
12
|
pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
11
13
|
if context.target_ruby_version() < RubyVersion::new(2, 7) {
|
|
12
14
|
return;
|
|
13
15
|
}
|
|
14
16
|
for case in context.nodes_of("case_match") {
|
|
15
|
-
let
|
|
17
|
+
let _cursor = case.walk();
|
|
16
18
|
let mut seen: HashSet<String> = HashSet::new();
|
|
17
|
-
for branch in case
|
|
19
|
+
for branch in named_children_iter(case, context) {
|
|
18
20
|
if branch.kind_str() != "in_clause" {
|
|
19
21
|
continue;
|
|
20
22
|
}
|
|
@@ -52,9 +54,9 @@ fn pattern_identity(branch: Node<'_>, pattern: Node<'_>, context: &RuleContext<'
|
|
|
52
54
|
/// Upstream builds an alternation of three from an alternation of two, so its children are the run
|
|
53
55
|
/// up to the last alternative and that last one -- not the flat list the grammar keeps.
|
|
54
56
|
fn sorted_parts(pattern: Node<'_>, context: &RuleContext<'_>) -> Vec<String> {
|
|
55
|
-
let
|
|
56
|
-
let parts: Vec<Node<'_>> = pattern
|
|
57
|
-
.
|
|
57
|
+
let _cursor = pattern.walk();
|
|
58
|
+
let parts: Vec<Node<'_>> = named_children_of(pattern, context)
|
|
59
|
+
.into_iter()
|
|
58
60
|
.filter(|child| child.kind_str() != "comment")
|
|
59
61
|
.collect();
|
|
60
62
|
let mut sources: Vec<String> = if pattern.kind_str() == "alternative_pattern" && parts.len() > 2
|
|
@@ -8,6 +8,7 @@ use crate::rules::node_ext::NodeExt;
|
|
|
8
8
|
|
|
9
9
|
use super::blocks::BlockArgs;
|
|
10
10
|
use super::locals::LocalVariables;
|
|
11
|
+
use crate::rules::send_node::named_children_iter;
|
|
11
12
|
|
|
12
13
|
pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
13
14
|
let mut tracker = Tracker {
|
|
@@ -821,9 +822,9 @@ fn literal_arguments(context: &RuleContext<'_>, node: Node<'_>) -> Vec<String> {
|
|
|
821
822
|
let Some(arguments) = node.field("arguments") else {
|
|
822
823
|
return Vec::new();
|
|
823
824
|
};
|
|
824
|
-
let
|
|
825
|
+
let _cursor = arguments.walk();
|
|
825
826
|
let mut names = Vec::new();
|
|
826
|
-
for argument in arguments
|
|
827
|
+
for argument in named_children_iter(arguments, context) {
|
|
827
828
|
match symbol_name(context.source.node_text(argument)) {
|
|
828
829
|
Some(name) if matches!(argument.kind_str(), "simple_symbol" | "string") => {
|
|
829
830
|
names.push(name.to_owned());
|
|
@@ -861,7 +862,7 @@ fn attr_with_writer(node: Node<'_>) -> bool {
|
|
|
861
862
|
/// `literal_arguments` from answering.
|
|
862
863
|
fn attr_first_name(context: &RuleContext<'_>, node: Node<'_>) -> Option<String> {
|
|
863
864
|
let list = node.field("arguments")?;
|
|
864
|
-
let first = *crate::rules::send_node::
|
|
865
|
+
let first = *crate::rules::send_node::named_children_of(list, context).first()?;
|
|
865
866
|
if !matches!(first.kind_str(), "simple_symbol" | "string") {
|
|
866
867
|
return None;
|
|
867
868
|
}
|
|
@@ -156,7 +156,6 @@ fn body_parent(container: Node<'_>) -> Parent {
|
|
|
156
156
|
/// statements it holds.
|
|
157
157
|
fn split_body(container: Node<'_>) -> bool {
|
|
158
158
|
let mut cursor = container.walk();
|
|
159
|
-
container
|
|
160
|
-
.named_children(&mut cursor)
|
|
159
|
+
container.named_children(&mut cursor)
|
|
161
160
|
.any(|child| matches!(child.kind_str(), "rescue" | "else" | "ensure"))
|
|
162
161
|
}
|
|
@@ -6,6 +6,7 @@ use crate::rules::node_ext::NodeExt;
|
|
|
6
6
|
use crate::rules::send_node::{arguments, named_children};
|
|
7
7
|
|
|
8
8
|
use super::node_equality::identical;
|
|
9
|
+
use crate::rules::send_node::named_children_of;
|
|
9
10
|
|
|
10
11
|
pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
11
12
|
for node in context.nodes_of_any(&["call", "element_reference"]) {
|
|
@@ -41,12 +42,12 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
41
42
|
/// `set_init_elements`, paired with the name the message calls the class by.
|
|
42
43
|
fn set_init_elements<'tree>(
|
|
43
44
|
node: Node<'tree>,
|
|
44
|
-
context: &RuleContext<'_>,
|
|
45
|
+
context: &'tree RuleContext<'_>,
|
|
45
46
|
) -> Option<(String, Vec<Node<'tree>>)> {
|
|
46
47
|
if node.kind_str() == "element_reference" {
|
|
47
48
|
let object = node.field("object")?;
|
|
48
49
|
let name = set_class_name(object, context)?;
|
|
49
|
-
let elements =
|
|
50
|
+
let elements = named_children_of(node, context)
|
|
50
51
|
.into_iter()
|
|
51
52
|
.filter(|child| child.kind_str() != "comment" && child.id() != object.id())
|
|
52
53
|
.collect();
|
|
@@ -5,6 +5,7 @@ use crate::rules::RuleContext;
|
|
|
5
5
|
|
|
6
6
|
use super::statements::statements;
|
|
7
7
|
use crate::rules::node_ext::NodeExt;
|
|
8
|
+
use crate::rules::send_node::all_children_iter;
|
|
8
9
|
|
|
9
10
|
/// The three conditionals whose branch can be written empty. A modifier form always has a body.
|
|
10
11
|
const CONDITIONALS: &[&str] = &["if", "unless", "elsif"];
|
|
@@ -181,7 +182,7 @@ fn enclosing_end<'tree>(node: Node<'tree>, context: &RuleContext<'_>) -> Option<
|
|
|
181
182
|
/// `node.loc.begin`: the `then` or `;` the branch was introduced with. The grammar puts a `then`
|
|
182
183
|
/// inside the branch it opens, but a `;` stays beside the condition -- and a branch holding nothing
|
|
183
184
|
/// is no node at all, which leaves the `;` as the only trace of it.
|
|
184
|
-
fn then_keyword<'tree>(node: Node<'tree>, context: &RuleContext<'_>) -> Option<Node<'tree>> {
|
|
185
|
+
fn then_keyword<'tree>(node: Node<'tree>, context: &'tree RuleContext<'_>) -> Option<Node<'tree>> {
|
|
185
186
|
if let Some(first) = node
|
|
186
187
|
.field("consequence")
|
|
187
188
|
.and_then(|branch| branch.child(0))
|
|
@@ -190,8 +191,8 @@ fn then_keyword<'tree>(node: Node<'tree>, context: &RuleContext<'_>) -> Option<N
|
|
|
190
191
|
return Some(first);
|
|
191
192
|
}
|
|
192
193
|
let condition = node.field("condition")?;
|
|
193
|
-
let
|
|
194
|
-
node
|
|
194
|
+
let _cursor = node.walk();
|
|
195
|
+
all_children_iter(node, context).find(|child| {
|
|
195
196
|
child.start_byte() >= condition.end_byte()
|
|
196
197
|
&& matches!(context.source.node_text(*child), "then" | ";")
|
|
197
198
|
})
|
|
@@ -11,6 +11,7 @@ use super::comments_help::comment_search_lines;
|
|
|
11
11
|
use crate::ruby_version::RubyVersion;
|
|
12
12
|
|
|
13
13
|
use super::statements::statements;
|
|
14
|
+
use crate::rules::send_node::named_children_iter;
|
|
14
15
|
|
|
15
16
|
const MSG: &str = "Avoid `in` branches without a body.";
|
|
16
17
|
|
|
@@ -20,8 +21,8 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
20
21
|
}
|
|
21
22
|
let allow_comments: bool = context.setting("AllowComments").unwrap_or(true);
|
|
22
23
|
for case in context.nodes_of("case_match") {
|
|
23
|
-
let
|
|
24
|
-
let children: Vec<Node<'_>> = case
|
|
24
|
+
let _cursor = case.walk();
|
|
25
|
+
let children: Vec<Node<'_>> = named_children_iter(case, context).collect();
|
|
25
26
|
for (index, &branch) in children.iter().enumerate() {
|
|
26
27
|
if branch.kind_str() != "in_clause" || has_body(branch) {
|
|
27
28
|
continue;
|
|
@@ -8,14 +8,15 @@ use crate::rules::RuleContext;
|
|
|
8
8
|
use crate::rules::node_ext::NodeExt;
|
|
9
9
|
|
|
10
10
|
use super::comments_help::comment_search_lines;
|
|
11
|
+
use crate::rules::send_node::named_children_iter;
|
|
11
12
|
|
|
12
13
|
const MSG: &str = "Avoid `when` branches without a body.";
|
|
13
14
|
|
|
14
15
|
pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
15
16
|
let allow_comments: bool = context.setting("AllowComments").unwrap_or(true);
|
|
16
17
|
for case in context.nodes_of("case") {
|
|
17
|
-
let
|
|
18
|
-
let children: Vec<Node<'_>> = case
|
|
18
|
+
let _cursor = case.walk();
|
|
19
|
+
let children: Vec<Node<'_>> = named_children_iter(case, context).collect();
|
|
19
20
|
for (index, &branch) in children.iter().enumerate() {
|
|
20
21
|
if branch.kind_str() != "when" || has_body(branch) {
|
|
21
22
|
continue;
|
|
@@ -32,8 +33,7 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
32
33
|
/// the `;` or `then` that separates it from the body it does not have is no part of it.
|
|
33
34
|
fn reported_range(branch: Node<'_>) -> std::ops::Range<usize> {
|
|
34
35
|
let mut cursor = branch.walk();
|
|
35
|
-
let last = branch
|
|
36
|
-
.named_children(&mut cursor)
|
|
36
|
+
let last = branch.named_children(&mut cursor)
|
|
37
37
|
.filter(|child| child.kind_str() == "pattern")
|
|
38
38
|
.last();
|
|
39
39
|
branch.start_byte()..last.map_or_else(|| branch.end_byte(), |last| last.end_byte())
|
|
@@ -5,6 +5,7 @@ use crate::rules::RuleContext;
|
|
|
5
5
|
|
|
6
6
|
use super::statements::statements;
|
|
7
7
|
use crate::rules::node_ext::NodeExt;
|
|
8
|
+
use crate::rules::send_node::named_children_iter;
|
|
8
9
|
|
|
9
10
|
const MSG: &str = "Do not return from an `ensure` block.";
|
|
10
11
|
|
|
@@ -26,8 +27,8 @@ fn collect(
|
|
|
26
27
|
if node.kind_str() == "return" && !returns_from_inner_scope(node, ensure_node, context) {
|
|
27
28
|
offenses.push(context.offense(MSG, node.byte_range()));
|
|
28
29
|
}
|
|
29
|
-
let
|
|
30
|
-
let children: Vec<Node<'_>> = node
|
|
30
|
+
let _cursor = node.walk();
|
|
31
|
+
let children: Vec<Node<'_>> = named_children_iter(node, context).collect();
|
|
31
32
|
for child in children {
|
|
32
33
|
collect(child, ensure_node, context, offenses);
|
|
33
34
|
}
|
|
@@ -2,8 +2,10 @@ use tree_sitter::Node;
|
|
|
2
2
|
|
|
3
3
|
use crate::diagnostic::Offense;
|
|
4
4
|
use crate::rules::RuleContext;
|
|
5
|
-
use crate::rules::send_node::{Argument, arguments,
|
|
5
|
+
use crate::rules::send_node::{Argument, arguments, send_range};
|
|
6
6
|
use crate::rules::node_ext::NodeExt;
|
|
7
|
+
use crate::rules::send_node::named_children_of;
|
|
8
|
+
use crate::rules::send_node::named_children_iter;
|
|
7
9
|
|
|
8
10
|
const MSG_EQUALITY: &str = "Avoid equality comparisons of floats as they are unreliable.";
|
|
9
11
|
const MSG_INEQUALITY: &str = "Avoid inequality comparisons of floats as they are unreliable.";
|
|
@@ -52,15 +54,15 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
52
54
|
|
|
53
55
|
/// `on_case`: every condition of every `when` branch, taken on its own.
|
|
54
56
|
fn case_conditions(node: Node<'_>, context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
55
|
-
for branch in
|
|
57
|
+
for branch in named_children_of(node, context) {
|
|
56
58
|
if branch.kind_str() != "when" {
|
|
57
59
|
continue;
|
|
58
60
|
}
|
|
59
|
-
for pattern in
|
|
61
|
+
for pattern in named_children_of(branch, context) {
|
|
60
62
|
if pattern.kind_str() != "pattern" {
|
|
61
63
|
continue;
|
|
62
64
|
}
|
|
63
|
-
let Some(condition) =
|
|
65
|
+
let Some(condition) = named_children_iter(pattern, context).next() else {
|
|
64
66
|
continue;
|
|
65
67
|
};
|
|
66
68
|
if is_float(condition, context) && !literal_safe(condition, context) {
|
|
@@ -110,7 +112,7 @@ fn is_float(node: Node<'_>, context: &RuleContext<'_>) -> bool {
|
|
|
110
112
|
// The parser folds a sign into the numeric literal it stands before.
|
|
111
113
|
"unary" => signed_numeric(node, context).is_some_and(|operand| operand.kind_str() == "float"),
|
|
112
114
|
"binary" | "call" => float_send(node, context),
|
|
113
|
-
"parenthesized_statements" =>
|
|
115
|
+
"parenthesized_statements" => named_children_of(node, context)
|
|
114
116
|
.into_iter()
|
|
115
117
|
.next()
|
|
116
118
|
.is_some_and(|first| is_float(first, context)),
|
|
@@ -167,7 +169,7 @@ fn literal_safe(node: Node<'_>, context: &RuleContext<'_>) -> bool {
|
|
|
167
169
|
"nil" => true,
|
|
168
170
|
"integer" | "float" | "rational" | "complex" => is_zero(node, context),
|
|
169
171
|
"unary" => signed_numeric(node, context).is_some_and(|operand| is_zero(operand, context)),
|
|
170
|
-
"parenthesized_statements" =>
|
|
172
|
+
"parenthesized_statements" => named_children_of(node, context)
|
|
171
173
|
.into_iter()
|
|
172
174
|
.next()
|
|
173
175
|
.is_some_and(|first| literal_safe(first, context)),
|
|
@@ -9,6 +9,7 @@ use crate::rules::send_node::{arguments, is_plain_send};
|
|
|
9
9
|
use super::format_string::{is_valid, parse};
|
|
10
10
|
use super::literals::literal_type;
|
|
11
11
|
use crate::rules::node_ext::NodeExt;
|
|
12
|
+
use crate::rules::send_node::named_children_of;
|
|
12
13
|
|
|
13
14
|
const MSG_INVALID: &str = "Format string is invalid because formatting sequence types \
|
|
14
15
|
(numbered, named or unnumbered) are mixed.";
|
|
@@ -222,9 +223,9 @@ fn count_matches(call: &Call<'_>, context: &RuleContext<'_>) -> Count {
|
|
|
222
223
|
.is_some_and(|first| first.first.kind_str() == "array")
|
|
223
224
|
{
|
|
224
225
|
let list = call.given[0].first;
|
|
225
|
-
let
|
|
226
|
-
let passed = list
|
|
227
|
-
.
|
|
226
|
+
let _cursor = list.walk();
|
|
227
|
+
let passed = named_children_of(list, context)
|
|
228
|
+
.into_iter()
|
|
228
229
|
.filter(|child| child.kind_str() != "comment")
|
|
229
230
|
.count();
|
|
230
231
|
let Some(receiver) = call.receiver else {
|