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
|
@@ -6,6 +6,7 @@ use crate::rules::send_node::{arguments, is_plain_send, send_range};
|
|
|
6
6
|
|
|
7
7
|
use super::locals::LocalVariables;
|
|
8
8
|
use crate::rules::node_ext::NodeExt;
|
|
9
|
+
use crate::rules::send_node::named_children_of;
|
|
9
10
|
|
|
10
11
|
const MSG: &str = "Use `Hash#compare_by_identity` instead of using `object_id` for keys.";
|
|
11
12
|
|
|
@@ -29,13 +30,13 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
29
30
|
/// reports it at.
|
|
30
31
|
fn keyed_call<'tree>(
|
|
31
32
|
node: Node<'tree>,
|
|
32
|
-
context: &RuleContext<'_>,
|
|
33
|
+
context: &'tree RuleContext<'_>,
|
|
33
34
|
) -> Option<(Node<'tree>, std::ops::Range<usize>)> {
|
|
34
35
|
if node.kind_str() == "element_reference" {
|
|
35
36
|
let object = node.field("object")?;
|
|
36
|
-
let
|
|
37
|
-
let key = node
|
|
38
|
-
.
|
|
37
|
+
let _cursor = node.walk();
|
|
38
|
+
let key = named_children_of(node, context)
|
|
39
|
+
.into_iter()
|
|
39
40
|
.find(|child| child.id() != object.id())?;
|
|
40
41
|
// `hash[k] = v` is one `[]=` send upstream, spanning the assignment rather than the
|
|
41
42
|
// brackets. Written in a multiple assignment the send holds no value and stops at the
|
|
@@ -5,7 +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::{arguments, heredoc_body
|
|
8
|
+
use crate::rules::send_node::{arguments, heredoc_body};
|
|
9
|
+
use crate::rules::send_node::named_children_of;
|
|
9
10
|
|
|
10
11
|
const MSG: &str =
|
|
11
12
|
"Put a method call with a HEREDOC receiver on the same line as the HEREDOC opening.";
|
|
@@ -70,7 +71,7 @@ fn heredoc_receiver<'tree>(node: Node<'tree>) -> Option<Node<'tree>> {
|
|
|
70
71
|
/// `heredoc.location.heredoc_end.end_pos`: where the terminator line ends.
|
|
71
72
|
fn heredoc_end(heredoc: Node<'_>, context: &RuleContext<'_>) -> Option<usize> {
|
|
72
73
|
let body = heredoc_body(heredoc, context)?;
|
|
73
|
-
|
|
74
|
+
named_children_of(body, context)
|
|
74
75
|
.into_iter()
|
|
75
76
|
.find(|child| child.kind_str() == "heredoc_end")
|
|
76
77
|
.map(|end| end.end_byte())
|
|
@@ -3,7 +3,9 @@ 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::{is_plain_send,
|
|
6
|
+
use crate::rules::send_node::{is_plain_send, string_text};
|
|
7
|
+
use crate::rules::send_node::named_children_of;
|
|
8
|
+
use crate::rules::send_node::all_children_of;
|
|
7
9
|
|
|
8
10
|
const FOR_ARRAY: &str =
|
|
9
11
|
" Or, if they were intended to be separate array elements, separate them with a comma.";
|
|
@@ -15,7 +17,7 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
15
17
|
// adjacent literals build: the parts of `"a\nb"` are fragments of a single literal, and the
|
|
16
18
|
// delimiter test upstream applies is what tells the two apart.
|
|
17
19
|
for node in context.nodes_of("chained_string") {
|
|
18
|
-
let parts =
|
|
20
|
+
let parts = named_children_of(node, context);
|
|
19
21
|
let suffix = suffix(node, context);
|
|
20
22
|
for pair in parts.windows(2) {
|
|
21
23
|
let (left, right) = (pair[0], pair[1]);
|
|
@@ -91,9 +93,9 @@ fn display(node: Node<'_>, context: &RuleContext<'_>) -> String {
|
|
|
91
93
|
/// nothing to `str_type?` -- so the recursion joins an empty string for it. Showing the source
|
|
92
94
|
/// instead puts `#{...}` in a message that upstream writes without it.
|
|
93
95
|
fn str_content(node: Node<'_>, context: &RuleContext<'_>) -> String {
|
|
94
|
-
let
|
|
95
|
-
let parts: Vec<String> = node
|
|
96
|
-
.
|
|
96
|
+
let _cursor = node.walk();
|
|
97
|
+
let parts: Vec<String> = all_children_of(node, context)
|
|
98
|
+
.into_iter()
|
|
97
99
|
.filter(|child| child.is_named() && child.kind_str() != "interpolation")
|
|
98
100
|
.map(|child| match child.kind_str() {
|
|
99
101
|
// **`str_content` reads the value, not the source.** A `\` closing a line joins it to
|
|
@@ -5,6 +5,7 @@ use crate::diagnostic::Offense;
|
|
|
5
5
|
use crate::rules::RuleContext;
|
|
6
6
|
use crate::rules::send_node::symbol_name;
|
|
7
7
|
use crate::rules::node_ext::NodeExt;
|
|
8
|
+
use crate::rules::send_node::named_children_iter;
|
|
8
9
|
|
|
9
10
|
const ALTERNATIVE_PRIVATE: &str =
|
|
10
11
|
"`private_class_method` or `private` inside a `class << self` block";
|
|
@@ -109,15 +110,15 @@ fn private_class_method_names(context: &RuleContext<'_>, node: Node<'_>) -> Vec<
|
|
|
109
110
|
.is_some_and(|method| context.source.node_text(method) == "private_class_method")
|
|
110
111
|
&& let Some(arguments) = current.field("arguments")
|
|
111
112
|
{
|
|
112
|
-
let
|
|
113
|
-
for argument in arguments
|
|
113
|
+
let _cursor = arguments.walk();
|
|
114
|
+
for argument in named_children_iter(arguments, context) {
|
|
114
115
|
if let Some(name) = symbol_name(argument, context) {
|
|
115
116
|
names.push(name.to_owned());
|
|
116
117
|
}
|
|
117
118
|
}
|
|
118
119
|
}
|
|
119
|
-
let
|
|
120
|
-
stack.extend(current
|
|
120
|
+
let _cursor = current.walk();
|
|
121
|
+
stack.extend(named_children_iter(current, context));
|
|
121
122
|
}
|
|
122
123
|
names
|
|
123
124
|
}
|
|
@@ -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_of;
|
|
6
7
|
|
|
7
8
|
pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
8
9
|
// The indirect inheritance the cop can also report needs `AllCops/UseProjectIndex` and the
|
|
@@ -103,9 +104,9 @@ fn shadowed_by_a_sibling_definition(
|
|
|
103
104
|
let Some(parent) = node.parent_of(context) else {
|
|
104
105
|
return false;
|
|
105
106
|
};
|
|
106
|
-
let
|
|
107
|
-
parent
|
|
108
|
-
.
|
|
107
|
+
let _cursor = parent.walk();
|
|
108
|
+
named_children_of(parent, context)
|
|
109
|
+
.into_iter()
|
|
109
110
|
.take_while(|sibling| sibling.id() != node.id())
|
|
110
111
|
.any(|sibling| {
|
|
111
112
|
matches!(sibling.kind_str(), "class" | "module")
|
|
@@ -10,6 +10,8 @@ use crate::rules::send_node::named_children;
|
|
|
10
10
|
use super::literals::{is_basic_literal, is_falsey_literal, is_literal, is_truthy_literal};
|
|
11
11
|
use super::statements::{Branch, statements};
|
|
12
12
|
use crate::rules::node_ext::NodeExt;
|
|
13
|
+
use crate::rules::send_node::{named_children_of};
|
|
14
|
+
use crate::rules::send_node::named_children_iter;
|
|
13
15
|
|
|
14
16
|
/// The nodes whose `condition` the parser rewrites: a range there becomes a flip-flop and a regexp
|
|
15
17
|
/// a match against `$_`, and neither is a literal any more.
|
|
@@ -315,11 +317,11 @@ fn check_case(node: Node<'_>, context: &RuleContext<'_>, offenses: &mut Vec<Offe
|
|
|
315
317
|
check_case_condition(condition, context, offenses);
|
|
316
318
|
return;
|
|
317
319
|
}
|
|
318
|
-
for branch in
|
|
320
|
+
for branch in named_children_of(node, context)
|
|
319
321
|
.into_iter()
|
|
320
322
|
.filter(|child| child.kind_str() == "when")
|
|
321
323
|
{
|
|
322
|
-
let conditions: Vec<Node<'_>> =
|
|
324
|
+
let conditions: Vec<Node<'_>> = named_children_of(branch, context)
|
|
323
325
|
.into_iter()
|
|
324
326
|
.filter(|child| child.kind_str() == "pattern")
|
|
325
327
|
.flat_map(named_children)
|
|
@@ -364,7 +366,7 @@ fn check_case_condition(
|
|
|
364
366
|
|
|
365
367
|
/// `primitive_array?`.
|
|
366
368
|
fn primitive_array(node: Node<'_>, context: &RuleContext<'_>) -> bool {
|
|
367
|
-
|
|
369
|
+
named_children_iter(node, context).all(|child| {
|
|
368
370
|
if child.kind_str() == "array" {
|
|
369
371
|
primitive_array(child, context)
|
|
370
372
|
} else {
|
|
@@ -4,6 +4,7 @@ use crate::diagnostic::Offense;
|
|
|
4
4
|
use crate::rules::RuleContext;
|
|
5
5
|
use crate::rules::node_ext::NodeExt;
|
|
6
6
|
use crate::rules::send_node::{has_interpolation, heredoc_body, named_children};
|
|
7
|
+
use crate::rules::send_node::named_children_of;
|
|
7
8
|
|
|
8
9
|
pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
9
10
|
for node in context.nodes_of_any(&[
|
|
@@ -86,11 +87,11 @@ fn all_literals(node: Node<'_>, context: &RuleContext<'_>) -> bool {
|
|
|
86
87
|
"chained_string" | "subshell" => false,
|
|
87
88
|
"string" => !has_interpolation(node),
|
|
88
89
|
"heredoc_beginning" => is_single_line_heredoc(node, context),
|
|
89
|
-
"array" | "string_array" | "symbol_array" | "right_assignment_list" =>
|
|
90
|
+
"array" | "string_array" | "symbol_array" | "right_assignment_list" => named_children_of(node, context)
|
|
90
91
|
.into_iter()
|
|
91
92
|
.filter(|child| child.kind_str() != "comment")
|
|
92
93
|
.all(|value| all_literals(value, context)),
|
|
93
|
-
"hash" =>
|
|
94
|
+
"hash" => named_children_of(node, context)
|
|
94
95
|
.into_iter()
|
|
95
96
|
.filter(|child| child.kind_str() != "comment")
|
|
96
97
|
.all(|pair| {
|
|
@@ -123,7 +124,7 @@ fn is_single_line_heredoc(node: Node<'_>, context: &RuleContext<'_>) -> bool {
|
|
|
123
124
|
let Some(body) = heredoc_body(node, context) else {
|
|
124
125
|
return false;
|
|
125
126
|
};
|
|
126
|
-
let content: Vec<Node<'_>> =
|
|
127
|
+
let content: Vec<Node<'_>> = named_children_of(body, context)
|
|
127
128
|
.into_iter()
|
|
128
129
|
.filter(|child| child.kind_str() != "heredoc_end")
|
|
129
130
|
.collect();
|
|
@@ -4,6 +4,7 @@ use crate::diagnostic::{Edit, Offense};
|
|
|
4
4
|
use crate::rules::RuleContext;
|
|
5
5
|
use crate::rules::node_ext::NodeExt;
|
|
6
6
|
use crate::rules::ruby_literal::{character_value, inspect_string, inspect_symbol, string_value};
|
|
7
|
+
use crate::rules::send_node::named_children_of;
|
|
7
8
|
|
|
8
9
|
const MSG: &str = "Literal interpolation detected.";
|
|
9
10
|
|
|
@@ -58,8 +59,7 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
58
59
|
/// evaluated and thrown away.
|
|
59
60
|
fn last_statement<'tree>(interpolation: Node<'tree>) -> Option<Node<'tree>> {
|
|
60
61
|
let mut cursor = interpolation.walk();
|
|
61
|
-
interpolation
|
|
62
|
-
.named_children(&mut cursor)
|
|
62
|
+
interpolation.named_children(&mut cursor)
|
|
63
63
|
.filter(|child| {
|
|
64
64
|
!matches!(
|
|
65
65
|
child.kind_str(),
|
|
@@ -370,9 +370,9 @@ fn array_value(node: Node<'_>, context: &RuleContext<'_>) -> String {
|
|
|
370
370
|
}
|
|
371
371
|
|
|
372
372
|
fn hash_value(node: Node<'_>, context: &RuleContext<'_>) -> String {
|
|
373
|
-
let
|
|
374
|
-
let pairs: Vec<String> = node
|
|
375
|
-
.
|
|
373
|
+
let _cursor = node.walk();
|
|
374
|
+
let pairs: Vec<String> = named_children_of(node, context)
|
|
375
|
+
.into_iter()
|
|
376
376
|
.map(|pair| {
|
|
377
377
|
let key = pair
|
|
378
378
|
.field("key")
|
data/src/rules/lint/literals.rs
CHANGED
|
@@ -11,6 +11,7 @@ use tree_sitter::Node;
|
|
|
11
11
|
use crate::rules::RuleContext;
|
|
12
12
|
use crate::rules::node_ext::NodeExt;
|
|
13
13
|
use crate::rules::send_node::has_interpolation;
|
|
14
|
+
use crate::rules::send_node::named_children_of;
|
|
14
15
|
|
|
15
16
|
/// `BASIC_LITERALS`: a literal whose value is the node itself.
|
|
16
17
|
const BASIC: &[&str] = &[
|
|
@@ -95,8 +96,9 @@ pub(crate) fn recursive_basic_literal(node: Node<'_>, context: &RuleContext<'_>)
|
|
|
95
96
|
|
|
96
97
|
/// `children.compact.all?(&:recursive_basic_literal?)`.
|
|
97
98
|
fn all_children(node: Node<'_>, context: &RuleContext<'_>) -> bool {
|
|
98
|
-
let
|
|
99
|
-
node
|
|
99
|
+
let _cursor = node.walk();
|
|
100
|
+
named_children_of(node, context)
|
|
101
|
+
.into_iter()
|
|
100
102
|
.filter(|child| child.kind_str() != "comment")
|
|
101
103
|
.all(|child| match child.kind_str() {
|
|
102
104
|
// The parts a quoted literal is written from are not nodes upstream at all: the text
|
|
@@ -189,9 +191,9 @@ fn string_type(node: Node<'_>, context: &RuleContext<'_>) -> &'static str {
|
|
|
189
191
|
if has_interpolation(node) {
|
|
190
192
|
return "dstr";
|
|
191
193
|
}
|
|
192
|
-
let
|
|
193
|
-
let broken = node
|
|
194
|
-
.
|
|
194
|
+
let _cursor = node.walk();
|
|
195
|
+
let broken = named_children_of(node, context)
|
|
196
|
+
.into_iter()
|
|
195
197
|
.filter(|child| child.kind_str() == "string_content")
|
|
196
198
|
.any(|child| context.source.node_text(child).contains('\n'));
|
|
197
199
|
if broken { "dstr" } else { "str" }
|
|
@@ -206,9 +208,9 @@ fn heredoc_type(node: Node<'_>, context: &RuleContext<'_>) -> &'static str {
|
|
|
206
208
|
if has_interpolation(body) {
|
|
207
209
|
return "dstr";
|
|
208
210
|
}
|
|
209
|
-
let
|
|
210
|
-
let lines: usize = body
|
|
211
|
-
.
|
|
211
|
+
let _cursor = body.walk();
|
|
212
|
+
let lines: usize = named_children_of(body, context)
|
|
213
|
+
.into_iter()
|
|
212
214
|
.filter(|child| child.kind_str() == "heredoc_content")
|
|
213
215
|
.map(|child| context.source.node_text(child).matches('\n').count())
|
|
214
216
|
.sum();
|
|
@@ -16,7 +16,7 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
16
16
|
continue;
|
|
17
17
|
}
|
|
18
18
|
for kwbegin in kwbegin_nodes(node) {
|
|
19
|
-
walk_named(kwbegin, &mut |inner| {
|
|
19
|
+
walk_named(kwbegin, context, &mut |inner| {
|
|
20
20
|
if inner.kind_str() != "return" || return_from_inner_scope(inner, kwbegin, context)
|
|
21
21
|
{
|
|
22
22
|
return;
|
|
@@ -84,7 +84,7 @@ fn return_from_inner_scope(node: Node<'_>, kwbegin: Node<'_>, context: &RuleCont
|
|
|
84
84
|
return false;
|
|
85
85
|
}
|
|
86
86
|
if matches!(ancestor.kind_str(), "method" | "singleton_method" | "lambda")
|
|
87
|
-
|| is_lambda(ancestor, context.source)
|
|
87
|
+
|| is_lambda(ancestor, context.source, context.ast_index())
|
|
88
88
|
{
|
|
89
89
|
return true;
|
|
90
90
|
}
|
|
@@ -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::all_children_of;
|
|
14
|
+
use crate::rules::send_node::named_children_of;
|
|
13
15
|
|
|
14
16
|
/// Whether the two operands are the same node. Upstream compares structurally rather than by
|
|
15
17
|
/// source -- `Node#==` looks at the type and the children -- so a difference in spacing is no
|
|
@@ -227,8 +229,9 @@ fn heredoc_parts<'tree>(body: Node<'tree>) -> Vec<Node<'tree>> {
|
|
|
227
229
|
}
|
|
228
230
|
|
|
229
231
|
fn operator_text(node: Node<'_>, context: &RuleContext<'_>) -> String {
|
|
230
|
-
let
|
|
231
|
-
node
|
|
232
|
+
let _cursor = node.walk();
|
|
233
|
+
all_children_of(node, context)
|
|
234
|
+
.into_iter()
|
|
232
235
|
.filter(|child| !child.is_named())
|
|
233
236
|
.map(|child| context.source.node_text(child))
|
|
234
237
|
.collect()
|
|
@@ -288,9 +291,9 @@ fn literal(node: Node<'_>, context: &RuleContext<'_>) -> Option<Literal> {
|
|
|
288
291
|
/// is a `dstr`/`dsym` upstream and has no value of its own, and an escape this cannot resolve
|
|
289
292
|
/// leaves the node to be compared structurally instead.
|
|
290
293
|
fn quoted_value(node: Node<'_>, context: &RuleContext<'_>) -> Option<Vec<u8>> {
|
|
291
|
-
let
|
|
292
|
-
if node
|
|
293
|
-
.
|
|
294
|
+
let _cursor = node.walk();
|
|
295
|
+
if named_children_of(node, context)
|
|
296
|
+
.into_iter()
|
|
294
297
|
.any(|child| child.kind_str() == "interpolation")
|
|
295
298
|
{
|
|
296
299
|
return None;
|
|
@@ -271,7 +271,7 @@ fn find_exist_call<'tree>(
|
|
|
271
271
|
return Some(node);
|
|
272
272
|
}
|
|
273
273
|
let mut children = Vec::new();
|
|
274
|
-
crate::rules::
|
|
274
|
+
crate::rules::push_named_children_in(node, context, &mut children);
|
|
275
275
|
children.reverse();
|
|
276
276
|
stack.extend(children);
|
|
277
277
|
}
|
|
@@ -3,11 +3,13 @@ use tree_sitter::Node;
|
|
|
3
3
|
use crate::diagnostic::{Edit, Offense};
|
|
4
4
|
use crate::ruby_version::RubyVersion;
|
|
5
5
|
use crate::rules::RuleContext;
|
|
6
|
-
use crate::rules::send_node::{arguments, is_plain_send,
|
|
6
|
+
use crate::rules::send_node::{arguments, is_plain_send, send_range};
|
|
7
7
|
|
|
8
8
|
use super::blocks::{BLOCK_KINDS, BlockArgs};
|
|
9
9
|
use super::locals::LocalVariables;
|
|
10
10
|
use crate::rules::node_ext::NodeExt;
|
|
11
|
+
use crate::rules::send_node::named_children_of;
|
|
12
|
+
use crate::rules::send_node::named_children_iter;
|
|
11
13
|
|
|
12
14
|
const MSG: &str = "Sort files before requiring them.";
|
|
13
15
|
|
|
@@ -190,7 +192,7 @@ fn is_method_require(node: Node<'_>, context: &RuleContext<'_>) -> bool {
|
|
|
190
192
|
if node.kind_str() != "block_argument" {
|
|
191
193
|
return false;
|
|
192
194
|
}
|
|
193
|
-
let Some(call) =
|
|
195
|
+
let Some(call) = named_children_iter(node, context).next() else {
|
|
194
196
|
return false;
|
|
195
197
|
};
|
|
196
198
|
if call.kind_str() != "call"
|
|
@@ -226,7 +228,7 @@ fn requires_variable(node: Node<'_>, name: &str, context: &RuleContext<'_>) -> b
|
|
|
226
228
|
return true;
|
|
227
229
|
}
|
|
228
230
|
}
|
|
229
|
-
|
|
231
|
+
named_children_of(node, context)
|
|
230
232
|
.into_iter()
|
|
231
233
|
.any(|child| requires_variable(child, name, context))
|
|
232
234
|
}
|
|
@@ -3,10 +3,11 @@ use tree_sitter::Node;
|
|
|
3
3
|
use crate::diagnostic::Offense;
|
|
4
4
|
use crate::rules::RuleContext;
|
|
5
5
|
use crate::rules::node_ext::NodeExt;
|
|
6
|
-
use crate::rules::send_node::{arguments, is_plain_send
|
|
6
|
+
use crate::rules::send_node::{arguments, is_plain_send};
|
|
7
7
|
|
|
8
8
|
use super::blocks::BlockArgs;
|
|
9
9
|
use super::locals::LocalVariables;
|
|
10
|
+
use crate::rules::send_node::named_children_of;
|
|
10
11
|
|
|
11
12
|
const MSG: &str = "Non-local exit from iterator, without return value. \
|
|
12
13
|
`next`, `break`, `Array#find`, `Array#any?`, etc. is preferred.";
|
|
@@ -15,7 +16,7 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
15
16
|
let locals = LocalVariables::new(context);
|
|
16
17
|
for node in context.nodes_of("return") {
|
|
17
18
|
// `return_value?`: a `return` handing back a value leaves the iterator on purpose.
|
|
18
|
-
if !
|
|
19
|
+
if !named_children_of(node, context).is_empty() {
|
|
19
20
|
continue;
|
|
20
21
|
}
|
|
21
22
|
let Some(keyword) = node.child(0).filter(|child| child.kind_str() == "return") else {
|
|
@@ -205,7 +205,7 @@ fn uses_safe_navigation(node: Node<'_>, context: &RuleContext<'_>) -> bool {
|
|
|
205
205
|
{
|
|
206
206
|
return true;
|
|
207
207
|
}
|
|
208
|
-
crate::rules::
|
|
208
|
+
crate::rules::push_named_children_in(current, context, &mut stack);
|
|
209
209
|
}
|
|
210
210
|
false
|
|
211
211
|
}
|
|
@@ -6,6 +6,8 @@ use crate::rules::send_node::{arguments, named_children};
|
|
|
6
6
|
|
|
7
7
|
use super::regexp::{captures, interpolates, pattern};
|
|
8
8
|
use crate::rules::node_ext::NodeExt;
|
|
9
|
+
use crate::rules::send_node::named_children_of;
|
|
10
|
+
use crate::rules::send_node::named_children_iter;
|
|
9
11
|
|
|
10
12
|
/// The methods that leave `$~` set, which is what makes a numbered reference after them valid.
|
|
11
13
|
/// `RESTRICT_ON_SEND` is this list, so a call to anything else leaves the state alone.
|
|
@@ -71,7 +73,7 @@ fn visit(node: Node<'_>, walk: &mut Walk, context: &RuleContext<'_>, offenses: &
|
|
|
71
73
|
}
|
|
72
74
|
}
|
|
73
75
|
"when" => {
|
|
74
|
-
walk.valid_ref =
|
|
76
|
+
walk.valid_ref = named_children_of(node, context)
|
|
75
77
|
.into_iter()
|
|
76
78
|
.filter(|child| child.kind_str() == "pattern")
|
|
77
79
|
.flat_map(named_children)
|
|
@@ -100,7 +102,7 @@ fn visit(node: Node<'_>, walk: &mut Walk, context: &RuleContext<'_>, offenses: &
|
|
|
100
102
|
// conditional puts its condition after its body here and before it upstream, for the same
|
|
101
103
|
// reason: the walk has to see them in the order the parser's children are listed.
|
|
102
104
|
let block = node.field("block");
|
|
103
|
-
let mut children =
|
|
105
|
+
let mut children = named_children_of(node, context);
|
|
104
106
|
if matches!(
|
|
105
107
|
node.kind_str(),
|
|
106
108
|
"if_modifier" | "unless_modifier" | "while_modifier" | "until_modifier"
|
|
@@ -198,7 +200,7 @@ fn is_capture_call(node: Node<'_>, context: &RuleContext<'_>) -> bool {
|
|
|
198
200
|
}
|
|
199
201
|
|
|
200
202
|
/// `regexp_first_argument?` and `regexp_receiver?`, which is what the state is taken from.
|
|
201
|
-
fn regexp_operand<'tree>(node: Node<'tree>, context: &RuleContext<'_>) -> Option<Node<'tree>> {
|
|
203
|
+
fn regexp_operand<'tree>(node: Node<'tree>, context: &'tree RuleContext<'_>) -> Option<Node<'tree>> {
|
|
202
204
|
let (name, first, receiver) = match node.kind_str() {
|
|
203
205
|
"call" => (
|
|
204
206
|
context
|
|
@@ -214,7 +216,7 @@ fn regexp_operand<'tree>(node: Node<'tree>, context: &RuleContext<'_>) -> Option
|
|
|
214
216
|
node.field("right"),
|
|
215
217
|
node.field("left"),
|
|
216
218
|
),
|
|
217
|
-
"element_reference" => ("[]",
|
|
219
|
+
"element_reference" => ("[]", named_children_iter(node, context).nth(1), node.child(0)),
|
|
218
220
|
_ => return None,
|
|
219
221
|
};
|
|
220
222
|
if let Some(first) = first
|
|
@@ -91,8 +91,7 @@ fn is_dir_glob(receiver: Node<'_>, context: &RuleContext<'_>) -> bool {
|
|
|
91
91
|
fn glob_arguments<'tree>(receiver: Node<'tree>) -> Vec<Node<'tree>> {
|
|
92
92
|
if receiver.kind_str() == "element_reference" {
|
|
93
93
|
let mut cursor = receiver.walk();
|
|
94
|
-
return receiver
|
|
95
|
-
.named_children(&mut cursor)
|
|
94
|
+
return receiver.named_children(&mut cursor)
|
|
96
95
|
.filter(|child| {
|
|
97
96
|
child.kind_str() != "comment"
|
|
98
97
|
&& receiver
|
|
@@ -2,13 +2,14 @@ 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::{arguments,
|
|
5
|
+
use crate::rules::send_node::{arguments, string_text, symbol_name};
|
|
6
6
|
|
|
7
7
|
use super::blocks::BLOCK_KINDS;
|
|
8
8
|
use super::literals::{is_literal, literal_type};
|
|
9
9
|
use super::nil_methods::NIL_METHODS;
|
|
10
10
|
use super::nil_receiver::cant_be_nil;
|
|
11
11
|
use crate::rules::node_ext::NodeExt;
|
|
12
|
+
use crate::rules::send_node::named_children_of;
|
|
12
13
|
|
|
13
14
|
const MSG: &str = "Redundant safe navigation detected, use `.` instead.";
|
|
14
15
|
const MSG_LITERAL: &str = "Redundant safe navigation with default literal detected.";
|
|
@@ -217,8 +218,8 @@ fn check_conversion_with_default(
|
|
|
217
218
|
.field("block")
|
|
218
219
|
.is_some_and(|block| BLOCK_KINDS.contains(&block.kind_str()));
|
|
219
220
|
let matched = match context.source.node_text(method) {
|
|
220
|
-
"to_h" => right.kind_str() == "hash" &&
|
|
221
|
-
"to_a" if !has_block => right.kind_str() == "array" &&
|
|
221
|
+
"to_h" => right.kind_str() == "hash" && named_children_of(right, context).is_empty(),
|
|
222
|
+
"to_a" if !has_block => right.kind_str() == "array" && named_children_of(right, context).is_empty(),
|
|
222
223
|
"to_i" if !has_block => {
|
|
223
224
|
right.kind_str() == "integer" && context.source.node_text(right) == "0"
|
|
224
225
|
}
|
|
@@ -9,6 +9,8 @@ use crate::rules::send_node::{is_plain_send, named_children, top_level_constant}
|
|
|
9
9
|
use super::literals::literal_type;
|
|
10
10
|
use super::statements::statements;
|
|
11
11
|
use crate::rules::node_ext::NodeExt;
|
|
12
|
+
use crate::rules::send_node::named_children_of;
|
|
13
|
+
use crate::rules::send_node::named_children_iter;
|
|
12
14
|
|
|
13
15
|
const MSG: &str = "Replace splat expansion with comma separated values.";
|
|
14
16
|
const ARRAY_PARAM_MSG: &str = "Pass array contents as separate arguments.";
|
|
@@ -48,7 +50,7 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
48
50
|
.setting::<bool>("AllowPercentLiteralArrayArgument")
|
|
49
51
|
.unwrap_or(true);
|
|
50
52
|
for node in context.nodes_of("splat_argument") {
|
|
51
|
-
let Some(expanded) =
|
|
53
|
+
let Some(expanded) = named_children_iter(node, context).next() else {
|
|
52
54
|
continue;
|
|
53
55
|
};
|
|
54
56
|
let (position, grandparent) = position_of(node);
|
|
@@ -67,7 +69,7 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
67
69
|
if !EXPANDABLE.contains(&kind) {
|
|
68
70
|
continue;
|
|
69
71
|
}
|
|
70
|
-
if kind == "array" &&
|
|
72
|
+
if kind == "array" && named_children_of(expanded, context).is_empty() {
|
|
71
73
|
continue;
|
|
72
74
|
}
|
|
73
75
|
}
|
|
@@ -2,11 +2,12 @@ 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::
|
|
5
|
+
use crate::rules::send_node::arguments;
|
|
6
6
|
|
|
7
7
|
use super::locals::LocalVariables;
|
|
8
8
|
use super::statements::statements;
|
|
9
9
|
use crate::rules::node_ext::NodeExt;
|
|
10
|
+
use crate::rules::send_node::named_children_of;
|
|
10
11
|
|
|
11
12
|
/// The receiverless calls whose arguments coerce on their own.
|
|
12
13
|
const PRINTERS: &[&str] = &["print", "puts", "warn"];
|
|
@@ -39,7 +40,7 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
39
40
|
let Some(list) = call.field("arguments") else {
|
|
40
41
|
continue;
|
|
41
42
|
};
|
|
42
|
-
for argument in
|
|
43
|
+
for argument in named_children_of(list, context) {
|
|
43
44
|
if let Some(offense) = coercion(argument, &context_name, context, &locals) {
|
|
44
45
|
offenses.push(offense);
|
|
45
46
|
}
|
|
@@ -11,9 +11,9 @@ use tree_sitter::Node;
|
|
|
11
11
|
|
|
12
12
|
use crate::rules::RuleContext;
|
|
13
13
|
use crate::rules::node_ext::NodeExt;
|
|
14
|
-
use crate::rules::send_node::named_children;
|
|
15
14
|
|
|
16
15
|
use super::regexp_tree::{self, Tree};
|
|
16
|
+
use crate::rules::send_node::named_children_of;
|
|
17
17
|
|
|
18
18
|
/// A regexp literal, parsed.
|
|
19
19
|
pub(super) struct Pattern {
|
|
@@ -48,7 +48,7 @@ pub(super) fn parse(node: Node<'_>, context: &RuleContext<'_>) -> Option<Pattern
|
|
|
48
48
|
let mut blanked = String::with_capacity(body.end - body.start);
|
|
49
49
|
let mut interpolations = Vec::new();
|
|
50
50
|
let mut cursor = body.start;
|
|
51
|
-
for child in
|
|
51
|
+
for child in named_children_of(node, context) {
|
|
52
52
|
if child.kind_str() != "interpolation" {
|
|
53
53
|
continue;
|
|
54
54
|
}
|
|
@@ -13,6 +13,7 @@ use crate::rules::RuleContext;
|
|
|
13
13
|
use crate::rules::node_ext::NodeExt;
|
|
14
14
|
|
|
15
15
|
use super::statements::{holds_statements, statements};
|
|
16
|
+
use crate::rules::send_node::all_children_iter;
|
|
16
17
|
|
|
17
18
|
pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
18
19
|
for node in context.nodes_of("range") {
|
|
@@ -53,9 +54,9 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
/// `node.loc.operator`.
|
|
56
|
-
fn operator<'tree>(node: Node<'tree>, context: &RuleContext<'_>) -> Option<Node<'tree>> {
|
|
57
|
-
let
|
|
58
|
-
node
|
|
57
|
+
fn operator<'tree>(node: Node<'tree>, context: &'tree RuleContext<'_>) -> Option<Node<'tree>> {
|
|
58
|
+
let _cursor = node.walk();
|
|
59
|
+
all_children_iter(node, context)
|
|
59
60
|
.find(|child| !child.is_named() && matches!(context.source.node_text(*child), ".." | "..."))
|
|
60
61
|
}
|
|
61
62
|
|
|
@@ -106,8 +107,7 @@ fn innermost<'tree>(node: Node<'tree>) -> Node<'tree> {
|
|
|
106
107
|
let mut current = node;
|
|
107
108
|
loop {
|
|
108
109
|
let mut cursor = current.walk();
|
|
109
|
-
let first = current
|
|
110
|
-
.named_children(&mut cursor)
|
|
110
|
+
let first = current.named_children(&mut cursor)
|
|
111
111
|
.find(|child| !skippable(*child));
|
|
112
112
|
match first {
|
|
113
113
|
Some(child) => current = child,
|
|
@@ -2,6 +2,7 @@ use super::rescue_clause::{body, const_name, end};
|
|
|
2
2
|
use crate::diagnostic::Offense;
|
|
3
3
|
use crate::rules::RuleContext;
|
|
4
4
|
use crate::rules::node_ext::NodeExt;
|
|
5
|
+
use crate::rules::send_node::named_children_of;
|
|
5
6
|
|
|
6
7
|
const MSG: &str =
|
|
7
8
|
"Avoid rescuing the `Exception` class. Perhaps you meant to rescue `StandardError`?";
|
|
@@ -11,9 +12,9 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
11
12
|
let Some(exceptions) = node.field("exceptions") else {
|
|
12
13
|
continue;
|
|
13
14
|
};
|
|
14
|
-
let
|
|
15
|
-
let targets_exception = exceptions
|
|
16
|
-
.
|
|
15
|
+
let _cursor = exceptions.walk();
|
|
16
|
+
let targets_exception = named_children_of(exceptions, context)
|
|
17
|
+
.into_iter()
|
|
17
18
|
.any(|exception| const_name(exception, context.source).as_deref() == Some("Exception"));
|
|
18
19
|
if !targets_exception {
|
|
19
20
|
continue;
|
|
@@ -5,6 +5,7 @@ use crate::rules::RuleContext;
|
|
|
5
5
|
|
|
6
6
|
use super::literals::literal_type;
|
|
7
7
|
use crate::rules::node_ext::NodeExt;
|
|
8
|
+
use crate::rules::send_node::named_children_iter;
|
|
8
9
|
|
|
9
10
|
/// `INVALID_TYPES`: the literals that name a value rather than a class, so that `rescue` raises a
|
|
10
11
|
/// `TypeError` when it tries to match against them.
|
|
@@ -21,8 +22,8 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
21
22
|
let Some(list) = clause.field("exceptions") else {
|
|
22
23
|
continue;
|
|
23
24
|
};
|
|
24
|
-
let
|
|
25
|
-
let exceptions: Vec<Node<'_>> = list
|
|
25
|
+
let _cursor = list.walk();
|
|
26
|
+
let exceptions: Vec<Node<'_>> = named_children_iter(list, context).collect();
|
|
26
27
|
let invalid: Vec<&Node<'_>> = exceptions
|
|
27
28
|
.iter()
|
|
28
29
|
.filter(|exception| is_invalid(**exception, context))
|