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
|
@@ -10,6 +10,7 @@ use crate::diagnostic::{Edit, Offense};
|
|
|
10
10
|
use crate::rules::RuleContext;
|
|
11
11
|
use crate::rules::node_ext::NodeExt;
|
|
12
12
|
use crate::rules::send_node::{Argument, arguments, heredoc_body, is_plain_send};
|
|
13
|
+
use crate::rules::send_node::named_children_iter;
|
|
13
14
|
|
|
14
15
|
const MSG: &str = "Put the closing parenthesis for a method call with a HEREDOC parameter on the \
|
|
15
16
|
same line as the HEREDOC opening.";
|
|
@@ -73,7 +74,7 @@ fn extract_heredoc_argument<'tree>(
|
|
|
73
74
|
}
|
|
74
75
|
|
|
75
76
|
/// `extract_heredoc`: the heredoc a value is, opens a chain with, or holds under a hash key.
|
|
76
|
-
fn extract_heredoc<'tree>(node: Node<'tree>, context: &RuleContext<'_>) -> Option<Node<'tree>> {
|
|
77
|
+
fn extract_heredoc<'tree>(node: Node<'tree>, context: &'tree RuleContext<'_>) -> Option<Node<'tree>> {
|
|
77
78
|
if node.kind_str() == "heredoc_beginning" {
|
|
78
79
|
return Some(node);
|
|
79
80
|
}
|
|
@@ -84,8 +85,8 @@ fn extract_heredoc<'tree>(node: Node<'tree>, context: &RuleContext<'_>) -> Optio
|
|
|
84
85
|
// the brace-less form, whose `hash` upstream builds and the grammar does not.
|
|
85
86
|
let values: Vec<Node<'tree>> = match node.kind_str() {
|
|
86
87
|
"hash" => {
|
|
87
|
-
let
|
|
88
|
-
node
|
|
88
|
+
let _cursor = node.walk();
|
|
89
|
+
named_children_iter(node, context)
|
|
89
90
|
.filter(|child| child.kind_str() == "pair")
|
|
90
91
|
.filter_map(|pair| pair.field("value"))
|
|
91
92
|
.collect()
|
|
@@ -357,8 +358,8 @@ fn heredoc_terminator(node: Node<'_>, context: &RuleContext<'_>) -> Option<Range
|
|
|
357
358
|
return None;
|
|
358
359
|
}
|
|
359
360
|
let body = heredoc_body(node, context)?;
|
|
360
|
-
let
|
|
361
|
-
body
|
|
361
|
+
let _cursor = body.walk();
|
|
362
|
+
named_children_iter(body, context)
|
|
362
363
|
.find(|child| child.kind_str() == "heredoc_end")
|
|
363
364
|
.map(|child| child.byte_range())
|
|
364
365
|
}
|
|
@@ -8,6 +8,7 @@ use crate::diagnostic::{Edit, Offense};
|
|
|
8
8
|
use crate::ruby_version::RubyVersion;
|
|
9
9
|
use crate::rules::RuleContext;
|
|
10
10
|
use crate::rules::node_ext::NodeExt;
|
|
11
|
+
use crate::rules::send_node::named_children_of;
|
|
11
12
|
|
|
12
13
|
pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
13
14
|
// `minimum_target_ruby_version 2.3`: `<<~` is what the cop asks for, and it did not exist
|
|
@@ -101,9 +102,9 @@ fn heredocs<'ctx, 'tree>(
|
|
|
101
102
|
.enumerate()
|
|
102
103
|
.filter_map(|(index, node)| {
|
|
103
104
|
let opener = *openers.get(index)?;
|
|
104
|
-
let
|
|
105
|
-
let end = node
|
|
106
|
-
.
|
|
105
|
+
let _cursor = node.walk();
|
|
106
|
+
let end = named_children_of(node, context)
|
|
107
|
+
.into_iter()
|
|
107
108
|
.find(|child| child.kind_str() == "heredoc_end")?;
|
|
108
109
|
let first_body_line = context.source.line_column(node.start_byte()).0 + 1;
|
|
109
110
|
let terminator_line = context.source.line_column(end.start_byte()).0;
|
|
@@ -5,6 +5,7 @@ use std::ops::Range;
|
|
|
5
5
|
use crate::diagnostic::{Edit, Offense};
|
|
6
6
|
use crate::rules::RuleContext;
|
|
7
7
|
use crate::rules::node_ext::NodeExt;
|
|
8
|
+
use crate::rules::send_node::named_children_of;
|
|
8
9
|
|
|
9
10
|
pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
10
11
|
let tabs = context
|
|
@@ -77,11 +78,11 @@ fn string_literals(context: &RuleContext<'_>) -> Vec<Range<usize>> {
|
|
|
77
78
|
.map(|node| node.byte_range())
|
|
78
79
|
.collect();
|
|
79
80
|
for body in context.nodes_of("heredoc_body") {
|
|
80
|
-
let
|
|
81
|
+
let _cursor = body.walk();
|
|
81
82
|
// `loc.heredoc_body` stops at the start of the terminator's *line*, so the indentation a
|
|
82
83
|
// squiggly heredoc's terminator was written with is code as far as this cop is concerned.
|
|
83
|
-
let end = body
|
|
84
|
-
.
|
|
84
|
+
let end = named_children_of(body, context)
|
|
85
|
+
.into_iter()
|
|
85
86
|
.find(|child| child.kind_str() == "heredoc_end")
|
|
86
87
|
.map_or_else(
|
|
87
88
|
|| body.end_byte(),
|
|
@@ -11,7 +11,9 @@ use super::support::{
|
|
|
11
11
|
};
|
|
12
12
|
use crate::diagnostic::Offense;
|
|
13
13
|
use crate::rules::node_ext::NodeExt;
|
|
14
|
-
use crate::rules::{RuleContext,
|
|
14
|
+
use crate::rules::{RuleContext, push_named_children_in};
|
|
15
|
+
use crate::rules::send_node::named_children_of;
|
|
16
|
+
use crate::rules::send_node::all_children_of;
|
|
15
17
|
|
|
16
18
|
pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
17
19
|
let width: i64 = context
|
|
@@ -48,7 +50,7 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
48
50
|
let mut stack = vec![context.root_node()];
|
|
49
51
|
while let Some(node) = stack.pop() {
|
|
50
52
|
checker.visit(node, offenses);
|
|
51
|
-
|
|
53
|
+
push_named_children_in(node, context, &mut stack);
|
|
52
54
|
}
|
|
53
55
|
}
|
|
54
56
|
|
|
@@ -203,9 +205,9 @@ impl Checker<'_, '_> {
|
|
|
203
205
|
};
|
|
204
206
|
let row = |byte: usize| self.context.source.line_column(byte).0;
|
|
205
207
|
// `dot_on_new_line?`: the receiver stops on an earlier line than the dot.
|
|
206
|
-
let
|
|
207
|
-
let dot = call
|
|
208
|
-
.
|
|
208
|
+
let _cursor = call.walk();
|
|
209
|
+
let dot = all_children_of(call, self.context)
|
|
210
|
+
.into_iter()
|
|
209
211
|
.find(|child| !child.is_named() && matches!(child.kind_str(), "." | "&."));
|
|
210
212
|
if let Some(dot) = dot
|
|
211
213
|
&& call
|
|
@@ -281,9 +283,9 @@ impl Checker<'_, '_> {
|
|
|
281
283
|
}
|
|
282
284
|
|
|
283
285
|
fn on_case(&mut self, node: Node<'_>, branch_kind: &str, offenses: &mut Vec<Offense>) {
|
|
284
|
-
let
|
|
285
|
-
let branches: Vec<Node<'_>> = node
|
|
286
|
-
.
|
|
286
|
+
let _cursor = node.walk();
|
|
287
|
+
let branches: Vec<Node<'_>> = named_children_of(node, self.context)
|
|
288
|
+
.into_iter()
|
|
287
289
|
.filter(|child| child.kind_str() == branch_kind)
|
|
288
290
|
.collect();
|
|
289
291
|
let mut last_keyword = None;
|
|
@@ -345,9 +347,9 @@ impl Checker<'_, '_> {
|
|
|
345
347
|
if node.field("receiver").is_some() {
|
|
346
348
|
return;
|
|
347
349
|
}
|
|
348
|
-
let
|
|
349
|
-
let Some(list) = node
|
|
350
|
-
.
|
|
350
|
+
let _cursor = node.walk();
|
|
351
|
+
let Some(list) = all_children_of(node, self.context)
|
|
352
|
+
.into_iter()
|
|
351
353
|
.find(|child| child.kind_str() == "argument_list")
|
|
352
354
|
else {
|
|
353
355
|
return;
|
|
@@ -694,8 +696,7 @@ fn is_statement_container(node: Node<'_>) -> bool {
|
|
|
694
696
|
|
|
695
697
|
fn body_container<'tree>(owner: Node<'tree>) -> Option<Node<'tree>> {
|
|
696
698
|
let mut cursor = owner.walk();
|
|
697
|
-
owner
|
|
698
|
-
.named_children(&mut cursor)
|
|
699
|
+
owner.named_children(&mut cursor)
|
|
699
700
|
.find(|child| matches!(child.kind_str(), "body_statement" | "block_body" | "do"))
|
|
700
701
|
}
|
|
701
702
|
|
|
@@ -6,7 +6,8 @@ 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::
|
|
9
|
+
use crate::rules::send_node::named_children_of;
|
|
10
|
+
use crate::rules::send_node::named_children_iter;
|
|
10
11
|
|
|
11
12
|
/// Ruby's `\s`, which stays ASCII where this engine's would take in every Unicode blank.
|
|
12
13
|
const BLANK: &str = r"[ \t\r\n\x0B\x0C]";
|
|
@@ -130,7 +131,7 @@ fn is_continuation(one: &str, line: usize, node: Node<'_>, context: &RuleContext
|
|
|
130
131
|
if !one.ends_with("\\\n") {
|
|
131
132
|
return false;
|
|
132
133
|
}
|
|
133
|
-
|
|
134
|
+
named_children_iter(node, context).all(|child| {
|
|
134
135
|
let first = context.source.line_column(child.start_byte()).0;
|
|
135
136
|
let last = context.source.line_column(child.end_byte()).0;
|
|
136
137
|
!((first..last).contains(&line) && first != last)
|
|
@@ -145,7 +146,7 @@ fn is_dynamic_string(node: Node<'_>, context: &RuleContext<'_>) -> bool {
|
|
|
145
146
|
return true;
|
|
146
147
|
}
|
|
147
148
|
context.source.line_column(node.start_byte()).0 != context.source.line_column(node.end_byte()).0
|
|
148
|
-
||
|
|
149
|
+
|| named_children_of(node, context)
|
|
149
150
|
.iter()
|
|
150
151
|
.any(|child| child.kind_str() == "interpolation")
|
|
151
152
|
}
|
|
@@ -3,9 +3,9 @@ use std::ops::Range;
|
|
|
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;
|
|
7
6
|
|
|
8
7
|
use super::tokens::tokens;
|
|
8
|
+
use crate::rules::send_node::named_children_of;
|
|
9
9
|
|
|
10
10
|
pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
11
11
|
if !context.source.text().contains('\\') {
|
|
@@ -118,7 +118,7 @@ fn ignored_ranges(context: &RuleContext<'_>) -> Vec<Range<usize>> {
|
|
|
118
118
|
// interpolations one `str` node, where the grammar splits it at every escape.
|
|
119
119
|
for literal in context.nodes_of_any(&["regex", "subshell"]) {
|
|
120
120
|
let mut run: Option<Range<usize>> = None;
|
|
121
|
-
for child in
|
|
121
|
+
for child in named_children_of(literal, context) {
|
|
122
122
|
match child.kind_str() == "interpolation" {
|
|
123
123
|
true => ranges.extend(run.take()),
|
|
124
124
|
false => {
|
|
@@ -10,6 +10,7 @@ use crate::rules::node_ext::NodeExt;
|
|
|
10
10
|
use crate::rules::support::Interpolations;
|
|
11
11
|
use crate::rules::support::is_ruby_space_char;
|
|
12
12
|
use crate::source::is_protected;
|
|
13
|
+
use crate::rules::send_node::named_children_iter;
|
|
13
14
|
|
|
14
15
|
/// `Layout/IndentationStyle`'s `IndentationWidth` is unset by default, so RuboCop falls back to
|
|
15
16
|
/// `Layout/IndentationWidth`'s `Width`, which is 2. A cop only ever sees its own configuration
|
|
@@ -35,16 +36,6 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
35
36
|
true => rbs_annotation_lines(context),
|
|
36
37
|
false => HashSet::new(),
|
|
37
38
|
};
|
|
38
|
-
let allow_uri: bool = context.setting("AllowURI").unwrap_or(true);
|
|
39
|
-
let allow_qualified_name: bool = context.setting("AllowQualifiedName").unwrap_or(true);
|
|
40
|
-
// `allowed_line?`: a line matching one of these is never long, whatever it holds.
|
|
41
|
-
let allowed_patterns =
|
|
42
|
-
crate::rules::naming::support::forbidden_patterns_named(context, "AllowedPatterns");
|
|
43
|
-
let uri_pattern = match context.setting::<Vec<String>>("URISchemes") {
|
|
44
|
-
Some(schemes) if !schemes.is_empty() => uri_regex(&schemes),
|
|
45
|
-
_ => URI.clone(),
|
|
46
|
-
};
|
|
47
|
-
|
|
48
39
|
// RuboCop drops the `__END__` line and the data section behind it from the lines it walks, so
|
|
49
40
|
// a long line down there is not a long line of code.
|
|
50
41
|
let data_line = context
|
|
@@ -53,26 +44,39 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
53
44
|
.map_or(usize::MAX, |node| node.start_position().row + 1);
|
|
54
45
|
let last_line = context.source.line_count().min(data_line.saturating_sub(1));
|
|
55
46
|
|
|
56
|
-
// Building autocorrections walks a large part of the AST
|
|
57
|
-
//
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
47
|
+
// Building autocorrections walks a large part of the AST, and every break it finds is filed
|
|
48
|
+
// under a line. Only the lines that are over the limit are ever looked up again, so the lines
|
|
49
|
+
// are settled first and the walk below is held to them. Most files have none at all.
|
|
50
|
+
let candidate_lines: HashSet<usize> = (1..=last_line)
|
|
51
|
+
.filter(|line_number| {
|
|
52
|
+
let raw = context.source.line(*line_number);
|
|
53
|
+
let line = crate::rules::support::chomp(raw);
|
|
54
|
+
let length = line.chars().count() + indentation_difference(line);
|
|
55
|
+
length > max
|
|
56
|
+
&& !(*line_number == 1 && line.starts_with("#!"))
|
|
57
|
+
&& !rbs_lines.contains(line_number)
|
|
58
|
+
&& !(context.in_heredoc(
|
|
59
|
+
context.source.line_start(*line_number)
|
|
60
|
+
..context.source.line_start(*line_number) + line.len(),
|
|
61
|
+
) && (allow_all_heredocs || allowed_heredoc_lines.contains(line_number)))
|
|
62
|
+
})
|
|
63
|
+
.collect();
|
|
64
|
+
if candidate_lines.is_empty() {
|
|
71
65
|
return;
|
|
72
66
|
}
|
|
73
67
|
|
|
68
|
+
let allow_uri: bool = context.setting("AllowURI").unwrap_or(true);
|
|
69
|
+
let allow_qualified_name: bool = context.setting("AllowQualifiedName").unwrap_or(true);
|
|
70
|
+
// `allowed_line?`: a line matching one of these is never long, whatever it holds.
|
|
71
|
+
let allowed_patterns =
|
|
72
|
+
crate::rules::naming::support::forbidden_patterns_named(context, "AllowedPatterns");
|
|
73
|
+
let uri_pattern = match context.setting::<Vec<String>>("URISchemes") {
|
|
74
|
+
Some(schemes) if !schemes.is_empty() => uri_regex(&schemes),
|
|
75
|
+
_ => &*URI,
|
|
76
|
+
};
|
|
77
|
+
|
|
74
78
|
let allow_directives = allow_cop_directives(context);
|
|
75
|
-
let break_edits = line_break_edits(context, max);
|
|
79
|
+
let break_edits = line_break_edits(context, max, &candidate_lines);
|
|
76
80
|
let directive_lines = directive_lines(context);
|
|
77
81
|
let endless_method_lines = endless_method_lines(context);
|
|
78
82
|
|
|
@@ -122,10 +126,10 @@ pub(super) fn check(context: &RuleContext<'_>, offenses: &mut Vec<Offense>) {
|
|
|
122
126
|
(max, without)
|
|
123
127
|
} else if allow_uri || allow_qualified_name {
|
|
124
128
|
let uri = allow_uri
|
|
125
|
-
.then(|| excessive_range(line, MatchKind::Uri, max, indent,
|
|
129
|
+
.then(|| excessive_range(line, MatchKind::Uri, max, indent, uri_pattern))
|
|
126
130
|
.flatten();
|
|
127
131
|
let name = allow_qualified_name
|
|
128
|
-
.then(|| excessive_range(line, MatchKind::QualifiedName, max, indent,
|
|
132
|
+
.then(|| excessive_range(line, MatchKind::QualifiedName, max, indent, uri_pattern))
|
|
129
133
|
.flatten();
|
|
130
134
|
if exempted(uri, name, length, max) {
|
|
131
135
|
continue;
|
|
@@ -332,8 +336,7 @@ fn name_start(node: Node<'_>, object: Node<'_>) -> usize {
|
|
|
332
336
|
|
|
333
337
|
fn is_endless_method(node: Node<'_>) -> bool {
|
|
334
338
|
let mut cursor = node.walk();
|
|
335
|
-
!node
|
|
336
|
-
.children(&mut cursor)
|
|
339
|
+
!node.children(&mut cursor)
|
|
337
340
|
.any(|child| child.kind_str() == "end")
|
|
338
341
|
}
|
|
339
342
|
|
|
@@ -451,14 +454,23 @@ static QUALIFIED_NAME: LazyLock<Regex> = LazyLock::new(|| {
|
|
|
451
454
|
/// a `//` and the negative lookahead was only ever reachable without one.
|
|
452
455
|
/// `URISchemes`: the schemes `URI::DEFAULT_PARSER.make_regexp` is built from. Hard-coding
|
|
453
456
|
/// `https?` made a line holding any other scheme -- the config exists to name one -- too long.
|
|
454
|
-
|
|
457
|
+
/// The pattern is built from the configuration, so it cannot live in a `LazyLock` -- but the
|
|
458
|
+
/// configuration does not change between files, and `URISchemes` is set in the default
|
|
459
|
+
/// configuration, so this was compiling the RFC 2396 grammar once per file. It was the single
|
|
460
|
+
/// largest cop cost in a run over RuboCop's own tree.
|
|
461
|
+
fn uri_regex(schemes: &[String]) -> &'static Regex {
|
|
455
462
|
let escaped: Vec<String> = schemes.iter().map(|scheme| regex::escape(scheme)).collect();
|
|
456
|
-
|
|
463
|
+
crate::rules::regex_cache::compiled(&uri_regex_pattern(&escaped.join("|")))
|
|
464
|
+
.unwrap_or_else(|| &URI)
|
|
457
465
|
}
|
|
458
466
|
|
|
459
467
|
static URI: LazyLock<Regex> = LazyLock::new(|| build_uri_regex("https?"));
|
|
460
468
|
|
|
461
469
|
fn build_uri_regex(schemes: &str) -> Regex {
|
|
470
|
+
Regex::new(&uri_regex_pattern(schemes)).unwrap()
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
fn uri_regex_pattern(schemes: &str) -> String {
|
|
462
474
|
const ESCAPED: &str = r"%[a-fA-F\d]{2}";
|
|
463
475
|
let uric_no_slash = format!(r"(?:[\-_.!~*'()a-zA-Z\d;?:@&=+$,]|{ESCAPED})");
|
|
464
476
|
let uric = format!(r"(?:[\-_.!~*'()a-zA-Z\d;/?:@&=+$,\[\]]|{ESCAPED})");
|
|
@@ -470,10 +482,9 @@ fn build_uri_regex(schemes: &str) -> Regex {
|
|
|
470
482
|
let pchar = format!(r"(?:[\-_.!~*'()a-zA-Z\d:@&=+$,]|{ESCAPED})");
|
|
471
483
|
let segment = format!(r"{pchar}*(?:;{pchar}*)*");
|
|
472
484
|
let abs_path = format!(r"/{segment}(?:/{segment})*");
|
|
473
|
-
|
|
485
|
+
format!(
|
|
474
486
|
r"(?:{schemes}):(?:{uric_no_slash}{uric}*|(?:(?://(?:(?:(?:{userinfo}@)?(?:{host}(?::(?-u:\d)*)?))?|{reg_name}))?(?:{abs_path})?)(?:\?{uric}*)?)(?:\#{uric}*)?"
|
|
475
|
-
)
|
|
476
|
-
.unwrap()
|
|
487
|
+
)
|
|
477
488
|
}
|
|
478
489
|
|
|
479
490
|
/// Whether `URI.parse` accepts the string, which RuboCop uses to weed out RFC 2396 matches that
|
|
@@ -579,6 +590,7 @@ fn visit_order(node: Node<'_>, order: &HashMap<usize, u32>) -> (u32, u8) {
|
|
|
579
590
|
fn line_break_edits(
|
|
580
591
|
context: &RuleContext<'_>,
|
|
581
592
|
max: usize,
|
|
593
|
+
lines: &HashSet<usize>,
|
|
582
594
|
) -> HashMap<usize, (Edit, std::ops::Range<usize>)> {
|
|
583
595
|
let breaker = Breaker {
|
|
584
596
|
context,
|
|
@@ -599,10 +611,10 @@ fn line_break_edits(
|
|
|
599
611
|
// Reversed, so that the first semicolon on a line is the one whose position survives.
|
|
600
612
|
if context.source.text().contains(';') {
|
|
601
613
|
for offset in semicolon_break_positions(context).into_iter().rev() {
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
(offset..(offset + 1), "\n".to_owned())
|
|
605
|
-
|
|
614
|
+
let line = context.source.line_column(offset).0;
|
|
615
|
+
if lines.contains(&line) {
|
|
616
|
+
positions.insert(line, (offset..(offset + 1), "\n".to_owned()));
|
|
617
|
+
}
|
|
606
618
|
}
|
|
607
619
|
}
|
|
608
620
|
|
|
@@ -611,6 +623,9 @@ fn line_break_edits(
|
|
|
611
623
|
// element a break would otherwise go in front of.
|
|
612
624
|
if context.setting::<bool>("SplitStrings").unwrap_or(false) {
|
|
613
625
|
for node in context.nodes_of_any(&["string", "bare_string"]) {
|
|
626
|
+
if !lines.contains(&(node.start_position().row + 1)) {
|
|
627
|
+
continue;
|
|
628
|
+
}
|
|
614
629
|
let Some((offset, delimiter)) = breakable_string(context, node, max) else {
|
|
615
630
|
continue;
|
|
616
631
|
};
|
|
@@ -626,28 +641,58 @@ fn line_break_edits(
|
|
|
626
641
|
}
|
|
627
642
|
}
|
|
628
643
|
|
|
644
|
+
// A break is filed under the line of a node the break goes in front of, which lies inside
|
|
645
|
+
// `node` -- except for a block, whose break is filed under the line the call it hangs off
|
|
646
|
+
// begins on, and that call can start earlier. A node spanning no over-long line has nothing to
|
|
647
|
+
// contribute, and finding that out costs two integers rather than a search for the element.
|
|
648
|
+
let mut candidates: Vec<Node<'_>> = context
|
|
649
|
+
.nodes_of_any(BREAKABLE_KINDS)
|
|
650
|
+
.filter(|node| {
|
|
651
|
+
let first = match matches!(node.kind_str(), "block" | "do_block") {
|
|
652
|
+
true => node
|
|
653
|
+
.parent_of(context)
|
|
654
|
+
.unwrap_or(*node)
|
|
655
|
+
.start_position()
|
|
656
|
+
.row,
|
|
657
|
+
false => node.start_position().row,
|
|
658
|
+
};
|
|
659
|
+
(first + 1..=node.end_position().row + 1).any(|line| lines.contains(&line))
|
|
660
|
+
})
|
|
661
|
+
.collect();
|
|
662
|
+
if candidates.is_empty() {
|
|
663
|
+
return finish(positions);
|
|
664
|
+
}
|
|
629
665
|
let order = upstream_order(context.root_node());
|
|
630
|
-
let mut candidates: Vec<Node<'_>> = context.nodes_of_any(BREAKABLE_KINDS).collect();
|
|
631
666
|
candidates.sort_by_key(|node| visit_order(*node, &order));
|
|
632
667
|
|
|
633
668
|
for node in candidates {
|
|
634
669
|
if matches!(node.kind_str(), "block" | "do_block") {
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
);
|
|
670
|
+
// Upstream's block node starts at the receiver, not at the brace, so a call split
|
|
671
|
+
// over two lines files its break under the line the receiver is on.
|
|
672
|
+
let owner = node.parent_of(context).unwrap_or(node);
|
|
673
|
+
let line = owner.start_position().row + 1;
|
|
674
|
+
if lines.contains(&line)
|
|
675
|
+
&& let Some(offset) = breaker.block_break_position(node)
|
|
676
|
+
{
|
|
677
|
+
positions.insert(line, (offset..(offset + 1), "\n".to_owned()));
|
|
643
678
|
}
|
|
644
679
|
} else if let Some(element) = breaker.breakable_element(node) {
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
680
|
+
let line = element.start_position().row + 1;
|
|
681
|
+
if lines.contains(&line) {
|
|
682
|
+
positions
|
|
683
|
+
.entry(line)
|
|
684
|
+
.or_insert_with(|| (element.byte_range(), "\n".to_owned()));
|
|
685
|
+
}
|
|
648
686
|
}
|
|
649
687
|
}
|
|
650
688
|
|
|
689
|
+
finish(positions)
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
/// Turns each recorded break into the insertion it stands for.
|
|
693
|
+
fn finish(
|
|
694
|
+
positions: HashMap<usize, (std::ops::Range<usize>, String)>,
|
|
695
|
+
) -> HashMap<usize, (Edit, std::ops::Range<usize>)> {
|
|
651
696
|
positions
|
|
652
697
|
.into_iter()
|
|
653
698
|
.map(|(line, (anchor, replacement))| {
|
|
@@ -791,8 +836,7 @@ impl Breaker<'_, '_> {
|
|
|
791
836
|
let mut cursor = container.walk();
|
|
792
837
|
// A comment is a node of the tree but not of RuboCop's AST, and a heredoc's body hangs off
|
|
793
838
|
// the argument list it was opened in rather than off the opener, so neither is an element.
|
|
794
|
-
let children: Vec<Node<'t>> = container
|
|
795
|
-
.named_children(&mut cursor)
|
|
839
|
+
let children: Vec<Node<'t>> = container.named_children(&mut cursor)
|
|
796
840
|
.filter(|child| !matches!(child.kind_str(), "comment" | "heredoc_body"))
|
|
797
841
|
.collect();
|
|
798
842
|
// A literal hash's own pairs are its elements; only an argument list and an array literal
|
|
@@ -1200,8 +1244,8 @@ fn breakable_dstr(
|
|
|
1200
1244
|
max: usize,
|
|
1201
1245
|
delimiter: &'static str,
|
|
1202
1246
|
) -> Option<(usize, &'static str)> {
|
|
1203
|
-
let
|
|
1204
|
-
for child in node
|
|
1247
|
+
let _cursor = node.walk();
|
|
1248
|
+
for child in named_children_iter(node, context) {
|
|
1205
1249
|
if child.kind_str() != "interpolation" {
|
|
1206
1250
|
continue;
|
|
1207
1251
|
}
|
|
@@ -1227,8 +1271,8 @@ fn breakable_string_part(
|
|
|
1227
1271
|
delimiter: &'static str,
|
|
1228
1272
|
) -> Option<(usize, &'static str)> {
|
|
1229
1273
|
let parent_column = context.source.line_column(node.start_byte()).1 - 1;
|
|
1230
|
-
let
|
|
1231
|
-
for part in node
|
|
1274
|
+
let _cursor = node.walk();
|
|
1275
|
+
for part in named_children_iter(node, context) {
|
|
1232
1276
|
if part.kind_str() != "string_content" {
|
|
1233
1277
|
continue;
|
|
1234
1278
|
}
|
|
@@ -5,6 +5,7 @@ use crate::rules::RuleContext;
|
|
|
5
5
|
use crate::rules::lint::blocks::BlockArgs;
|
|
6
6
|
use crate::rules::lint::locals::LocalVariables;
|
|
7
7
|
use crate::rules::node_ext::NodeExt;
|
|
8
|
+
use crate::rules::send_node::all_children_iter;
|
|
8
9
|
|
|
9
10
|
const NEW_LINE_OFFENSE: &str = "Right hand side of multi-line assignment is on the same line as \
|
|
10
11
|
the assignment operator `=`.";
|
|
@@ -157,10 +158,10 @@ fn block_of(
|
|
|
157
158
|
}
|
|
158
159
|
|
|
159
160
|
/// `node.loc.operator`: the `=` or `+=` the assignment was written with.
|
|
160
|
-
fn operator<'tree>(node: Node<'tree>, context: &RuleContext<'_>) -> Option<Node<'tree>> {
|
|
161
|
+
fn operator<'tree>(node: Node<'tree>, context: &'tree RuleContext<'_>) -> Option<Node<'tree>> {
|
|
161
162
|
let left = node.field("left")?;
|
|
162
|
-
let
|
|
163
|
-
node
|
|
163
|
+
let _cursor = node.walk();
|
|
164
|
+
all_children_iter(node, context)
|
|
164
165
|
.filter(|child| !child.is_named() && child.start_byte() >= left.end_byte())
|
|
165
166
|
.find(|child| context.source.node_text(*child).ends_with('='))
|
|
166
167
|
}
|
|
@@ -131,8 +131,7 @@ fn argument_string(context: &RuleContext<'_>, arguments: Node<'_>) -> String {
|
|
|
131
131
|
|
|
132
132
|
fn parameter_nodes<'tree>(arguments: Node<'tree>) -> Vec<Node<'tree>> {
|
|
133
133
|
let mut cursor = arguments.walk();
|
|
134
|
-
arguments
|
|
135
|
-
.named_children(&mut cursor)
|
|
134
|
+
arguments.named_children(&mut cursor)
|
|
136
135
|
.filter(|child| !matches!(child.kind_str(), "comment" | "heredoc_body"))
|
|
137
136
|
.collect()
|
|
138
137
|
}
|