rubocop 1.69.2 → 1.71.1
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/LICENSE.txt +1 -1
- data/README.md +2 -2
- data/config/default.yml +36 -2
- data/lib/rubocop/cli/command/execute_runner.rb +3 -3
- data/lib/rubocop/cli/command/show_cops.rb +24 -2
- data/lib/rubocop/comment_config.rb +1 -1
- data/lib/rubocop/config.rb +13 -4
- data/lib/rubocop/config_loader.rb +4 -0
- data/lib/rubocop/config_loader_resolver.rb +14 -3
- data/lib/rubocop/config_validator.rb +18 -8
- data/lib/rubocop/cop/autocorrect_logic.rb +1 -1
- data/lib/rubocop/cop/base.rb +6 -0
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -1
- data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/cop_enabled.rb +85 -0
- data/lib/rubocop/cop/internal_affairs/location_expression.rb +2 -1
- data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +3 -2
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +63 -0
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +131 -0
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +229 -0
- data/lib/rubocop/cop/internal_affairs/node_type_multiple_predicates.rb +126 -0
- data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +4 -3
- data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +90 -0
- data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +3 -1
- data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +5 -4
- data/lib/rubocop/cop/internal_affairs.rb +4 -0
- data/lib/rubocop/cop/layout/access_modifier_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/argument_alignment.rb +2 -8
- data/lib/rubocop/cop/layout/block_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/class_structure.rb +9 -9
- data/lib/rubocop/cop/layout/dot_position.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +7 -5
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +1 -0
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +1 -1
- data/lib/rubocop/cop/layout/end_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/extra_spacing.rb +1 -1
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +3 -8
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -7
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +2 -7
- data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +1 -1
- data/lib/rubocop/cop/layout/first_parameter_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/hash_alignment.rb +6 -4
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +1 -0
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +7 -1
- data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/line_length.rb +1 -0
- data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +25 -0
- data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -0
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/redundant_line_break.rb +7 -6
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/single_line_block_chain.rb +1 -1
- data/lib/rubocop/cop/layout/space_after_colon.rb +2 -2
- data/lib/rubocop/cop/layout/space_after_comma.rb +1 -1
- data/lib/rubocop/cop/layout/space_after_method_name.rb +1 -1
- data/lib/rubocop/cop/layout/space_after_semicolon.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -0
- data/lib/rubocop/cop/layout/space_around_operators.rb +3 -3
- data/lib/rubocop/cop/layout/space_before_comma.rb +1 -1
- data/lib/rubocop/cop/layout/space_before_semicolon.rb +1 -1
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +5 -3
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
- data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +119 -0
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +1 -3
- data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +1 -1
- data/lib/rubocop/cop/lint/constant_definition_in_block.rb +3 -3
- data/lib/rubocop/cop/lint/constant_reassignment.rb +148 -0
- data/lib/rubocop/cop/lint/debugger.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_set_element.rb +20 -7
- data/lib/rubocop/cop/lint/float_comparison.rb +5 -2
- data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -1
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +1 -1
- data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +24 -6
- data/lib/rubocop/cop/lint/missing_super.rb +2 -2
- data/lib/rubocop/cop/lint/mixed_case_range.rb +1 -1
- data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -1
- data/lib/rubocop/cop/lint/nested_method_definition.rb +8 -4
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
- data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +4 -3
- data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +1 -1
- data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +18 -31
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +2 -1
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -5
- data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_string_coercion.rb +2 -2
- data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +8 -1
- data/lib/rubocop/cop/lint/shared_mutable_default.rb +65 -0
- data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
- data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/syntax.rb +4 -1
- data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +1 -4
- data/lib/rubocop/cop/lint/unexpected_block_arity.rb +1 -1
- data/lib/rubocop/cop/lint/unreachable_code.rb +1 -1
- data/lib/rubocop/cop/lint/unreachable_loop.rb +1 -1
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +4 -4
- data/lib/rubocop/cop/lint/useless_assignment.rb +1 -1
- data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
- data/lib/rubocop/cop/lint/useless_numeric_operation.rb +2 -1
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +2 -2
- data/lib/rubocop/cop/lint/void.rb +4 -3
- data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
- data/lib/rubocop/cop/metrics/collection_literal_length.rb +7 -0
- data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +1 -1
- data/lib/rubocop/cop/metrics/method_length.rb +8 -1
- data/lib/rubocop/cop/metrics/module_length.rb +1 -1
- data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +11 -11
- data/lib/rubocop/cop/mixin/comments_help.rb +3 -1
- data/lib/rubocop/cop/mixin/dig_help.rb +1 -1
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -1
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +4 -4
- data/lib/rubocop/cop/mixin/hash_subset.rb +188 -0
- data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +48 -24
- data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
- data/lib/rubocop/cop/mixin/statement_modifier.rb +8 -3
- data/lib/rubocop/cop/mixin/string_help.rb +1 -1
- data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -1
- data/lib/rubocop/cop/mixin/trailing_comma.rb +3 -3
- data/lib/rubocop/cop/naming/block_forwarding.rb +19 -15
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +3 -3
- data/lib/rubocop/cop/security/compound_hash.rb +1 -0
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +34 -5
- data/lib/rubocop/cop/style/and_or.rb +1 -1
- data/lib/rubocop/cop/style/arguments_forwarding.rb +39 -23
- data/lib/rubocop/cop/style/array_first_last.rb +18 -2
- data/lib/rubocop/cop/style/block_delimiters.rb +7 -20
- data/lib/rubocop/cop/style/class_and_module_children.rb +6 -3
- data/lib/rubocop/cop/style/collection_methods.rb +1 -1
- data/lib/rubocop/cop/style/combinable_defined.rb +1 -1
- data/lib/rubocop/cop/style/combinable_loops.rb +2 -2
- data/lib/rubocop/cop/style/concat_array_literals.rb +1 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +6 -4
- data/lib/rubocop/cop/style/documentation.rb +1 -1
- data/lib/rubocop/cop/style/double_negation.rb +3 -3
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +4 -7
- data/lib/rubocop/cop/style/empty_else.rb +4 -2
- data/lib/rubocop/cop/style/empty_literal.rb +1 -1
- data/lib/rubocop/cop/style/empty_method.rb +1 -1
- data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
- data/lib/rubocop/cop/style/exact_regexp_match.rb +3 -10
- data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
- data/lib/rubocop/cop/style/exponential_notation.rb +1 -1
- data/lib/rubocop/cop/style/fetch_env_var.rb +1 -1
- data/lib/rubocop/cop/style/float_division.rb +8 -4
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
- data/lib/rubocop/cop/style/hash_each_methods.rb +3 -6
- data/lib/rubocop/cop/style/hash_except.rb +24 -148
- data/lib/rubocop/cop/style/hash_slice.rb +80 -0
- data/lib/rubocop/cop/style/hash_syntax.rb +6 -3
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +22 -3
- data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -3
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +1 -1
- data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -2
- data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
- data/lib/rubocop/cop/style/inverse_methods.rb +6 -6
- data/lib/rubocop/cop/style/it_assignment.rb +36 -0
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +1 -1
- data/lib/rubocop/cop/style/map_into_array.rb +1 -1
- data/lib/rubocop/cop/style/map_to_hash.rb +1 -1
- data/lib/rubocop/cop/style/map_to_set.rb +3 -2
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +19 -12
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -0
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -1
- data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +2 -4
- data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/missing_else.rb +2 -0
- data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -1
- data/lib/rubocop/cop/style/multiple_comparison.rb +26 -20
- data/lib/rubocop/cop/style/mutable_constant.rb +3 -3
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +1 -1
- data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
- data/lib/rubocop/cop/style/object_then.rb +13 -15
- data/lib/rubocop/cop/style/open_struct_use.rb +5 -5
- data/lib/rubocop/cop/style/parallel_assignment.rb +1 -5
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +2 -2
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
- data/lib/rubocop/cop/style/proc.rb +1 -2
- data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
- data/lib/rubocop/cop/style/raise_args.rb +6 -4
- data/lib/rubocop/cop/style/random_with_offset.rb +3 -3
- data/lib/rubocop/cop/style/redundant_begin.rb +1 -1
- data/lib/rubocop/cop/style/redundant_condition.rb +2 -2
- data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +2 -1
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +6 -10
- data/lib/rubocop/cop/style/redundant_each.rb +1 -1
- data/lib/rubocop/cop/style/redundant_exception.rb +2 -2
- data/lib/rubocop/cop/style/redundant_freeze.rb +2 -2
- data/lib/rubocop/cop/style/redundant_initialize.rb +12 -3
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +34 -13
- data/lib/rubocop/cop/style/redundant_parentheses.rb +10 -10
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +3 -0
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +1 -1
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +1 -1
- data/lib/rubocop/cop/style/redundant_self_assignment.rb +14 -28
- data/lib/rubocop/cop/style/redundant_sort.rb +2 -2
- data/lib/rubocop/cop/style/redundant_string_escape.rb +2 -2
- data/lib/rubocop/cop/style/return_nil.rb +1 -1
- data/lib/rubocop/cop/style/safe_navigation.rb +2 -2
- data/lib/rubocop/cop/style/semicolon.rb +1 -1
- data/lib/rubocop/cop/style/send_with_literal_method_name.rb +2 -1
- data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
- data/lib/rubocop/cop/style/single_line_do_end_block.rb +1 -2
- data/lib/rubocop/cop/style/single_line_methods.rb +3 -4
- data/lib/rubocop/cop/style/slicing_with_range.rb +40 -11
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +2 -2
- data/lib/rubocop/cop/style/string_concatenation.rb +1 -1
- data/lib/rubocop/cop/style/string_literals.rb +1 -1
- data/lib/rubocop/cop/style/string_methods.rb +1 -1
- data/lib/rubocop/cop/style/super_arguments.rb +65 -17
- data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/top_level_method_definition.rb +1 -1
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -1
- data/lib/rubocop/cop/style/yoda_condition.rb +8 -4
- data/lib/rubocop/cop/style/yoda_expression.rb +2 -1
- data/lib/rubocop/cop/util.rb +11 -4
- data/lib/rubocop/cop/variable_force/variable.rb +1 -1
- data/lib/rubocop/cop/variable_force/variable_table.rb +3 -3
- data/lib/rubocop/cops_documentation_generator.rb +13 -13
- data/lib/rubocop/directive_comment.rb +9 -8
- data/lib/rubocop/formatter/formatter_set.rb +1 -1
- data/lib/rubocop/lsp/diagnostic.rb +189 -0
- data/lib/rubocop/lsp/logger.rb +2 -2
- data/lib/rubocop/lsp/routes.rb +7 -23
- data/lib/rubocop/lsp/runtime.rb +15 -49
- data/lib/rubocop/lsp/stdin_runner.rb +83 -0
- data/lib/rubocop/options.rb +2 -1
- data/lib/rubocop/path_util.rb +11 -8
- data/lib/rubocop/result_cache.rb +13 -13
- data/lib/rubocop/rspec/expect_offense.rb +6 -2
- data/lib/rubocop/rspec/shared_contexts.rb +4 -1
- data/lib/rubocop/rspec/support.rb +1 -2
- data/lib/rubocop/runner.rb +5 -6
- data/lib/rubocop/target_finder.rb +1 -0
- data/lib/rubocop/target_ruby.rb +15 -0
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +6 -0
- data/lib/ruby_lsp/rubocop/addon.rb +78 -0
- data/lib/ruby_lsp/rubocop/wraps_built_in_lsp_runtime.rb +50 -0
- metadata +23 -11
- data/lib/rubocop/rspec/host_environment_simulation_helper.rb +0 -28
@@ -0,0 +1,131 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module InternalAffairs
|
6
|
+
# rubocop:disable InternalAffairs/RedundantSourceRange - node here is a `NodePattern::Node`
|
7
|
+
class NodePatternGroups
|
8
|
+
# Walks an AST that has been processed by `InternalAffairs::NodePatternGroups::Processor`
|
9
|
+
# in order to find `node_type` and `node_sequence` nodes that can be replaced with a node
|
10
|
+
# group in `InternalAffairs/NodePatternGroups`.
|
11
|
+
#
|
12
|
+
# Calling `ASTWalker#walk` sets `node_groups` with an array of `NodeGroup` structs
|
13
|
+
# that contain metadata about nodes that can be replaced, including location data. That
|
14
|
+
# metadata is used by the cop to register offenses and perform corrections.
|
15
|
+
class ASTWalker
|
16
|
+
# Struct to contain data about parts of a node pattern that can be replaced
|
17
|
+
NodeGroup = Struct.new(
|
18
|
+
:name, # The name of the node group that will be inserted
|
19
|
+
:union, # The entire `union` node
|
20
|
+
:node_types, # An array of `node_type` nodes that will be removed
|
21
|
+
:sequence?, # The pattern matches a node type with given attributes
|
22
|
+
:start_index, # The index in the union of the first node type to remove
|
23
|
+
:offense_range, # The range to mark an offense on
|
24
|
+
:ranges, # Range of each element to remove, since they may not be adjacent
|
25
|
+
:pipe, # Is the union delimited by pipes?
|
26
|
+
:other_elements?, # Does the union have other elements other than those to remove?
|
27
|
+
keyword_init: true
|
28
|
+
)
|
29
|
+
|
30
|
+
def initialize
|
31
|
+
reset!
|
32
|
+
end
|
33
|
+
|
34
|
+
def reset!
|
35
|
+
@node_groups = []
|
36
|
+
end
|
37
|
+
|
38
|
+
attr_reader :node_groups
|
39
|
+
|
40
|
+
# Recursively walk the AST in a depth-first manner.
|
41
|
+
# Only `union` nodes are handled further.
|
42
|
+
def walk(node)
|
43
|
+
return if node.nil?
|
44
|
+
|
45
|
+
on_union(node) if node.type == :union
|
46
|
+
|
47
|
+
node.child_nodes.each do |child|
|
48
|
+
walk(child)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Search `union` nodes for `node_type` and `node_sequence` nodes that can be
|
53
|
+
# collapsed into a node group.
|
54
|
+
# * `node_type` nodes are nodes with no further configuration (ie. `send`)
|
55
|
+
# * `node_sequence` nodes are nodes with further configuration (ie. `(send ...)`)
|
56
|
+
#
|
57
|
+
# Each group of types that can be collapsed will have a `NodeGroup` record added
|
58
|
+
# to `node_groups`, which is then used by the cop.
|
59
|
+
def on_union(node)
|
60
|
+
all_node_types = each_child_node(node, :node_type, :node_sequence).to_a
|
61
|
+
|
62
|
+
each_node_group(all_node_types) do |group_name, node_types|
|
63
|
+
next unless sequences_match?(node_types)
|
64
|
+
|
65
|
+
node_groups << node_group_data(
|
66
|
+
group_name, node, node_types,
|
67
|
+
all_node_types.index(node_types.first),
|
68
|
+
(node.children - node_types).any?
|
69
|
+
)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def each_child_node(node, *types)
|
76
|
+
return to_enum(__method__, node, *types) unless block_given?
|
77
|
+
|
78
|
+
node.children.each do |child|
|
79
|
+
yield child if types.empty? || types.include?(child.type)
|
80
|
+
end
|
81
|
+
|
82
|
+
self
|
83
|
+
end
|
84
|
+
|
85
|
+
def each_node_group(types_to_check)
|
86
|
+
# Find all node groups where all of the members are present in the union
|
87
|
+
type_names = types_to_check.map(&:child)
|
88
|
+
|
89
|
+
NODE_GROUPS.select { |_, group| group & type_names == group }.each_key do |name|
|
90
|
+
nodes = get_relevant_nodes(types_to_check, name)
|
91
|
+
|
92
|
+
yield name, nodes
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def get_relevant_nodes(node_types, group_name)
|
97
|
+
node_types.each_with_object([]) do |node_type, arr|
|
98
|
+
next unless NODE_GROUPS[group_name].include?(node_type.child)
|
99
|
+
|
100
|
+
arr << node_type
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def node_group_data(name, union, node_types, start_index, other)
|
105
|
+
NodeGroup.new(
|
106
|
+
name: name,
|
107
|
+
union: union,
|
108
|
+
node_types: node_types,
|
109
|
+
sequence?: node_types.first.type == :node_sequence,
|
110
|
+
start_index: start_index,
|
111
|
+
pipe: union.source_range.source['|'],
|
112
|
+
other_elements?: other
|
113
|
+
)
|
114
|
+
end
|
115
|
+
|
116
|
+
def sequences_match?(types)
|
117
|
+
# Ensure all given types have the same type and the same sequence
|
118
|
+
# ie. `(send ...)` and `(csend ...) is a match
|
119
|
+
# `(send)` and `(csend ...)` is not a match
|
120
|
+
# `send` and `(csend ...)` is not a match
|
121
|
+
|
122
|
+
types.each_cons(2).all? do |left, right|
|
123
|
+
left.type == right.type && left.children[1..] == right.children[1..]
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
# rubocop:enable InternalAffairs/RedundantSourceRange
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,229 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module InternalAffairs
|
6
|
+
# Use node groups (`any_block`, `argument`, `boolean`, `call`, `numeric`, `range`)
|
7
|
+
# in node patterns instead of a union (`{ ... }`) of the member types of the group.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# def_node_matcher :my_matcher, <<~PATTERN
|
12
|
+
# {send csend}
|
13
|
+
# PATTERN
|
14
|
+
#
|
15
|
+
# # good
|
16
|
+
# def_node_matcher :my_matcher, <<~PATTERN
|
17
|
+
# call
|
18
|
+
# PATTERN
|
19
|
+
#
|
20
|
+
class NodePatternGroups < Base
|
21
|
+
require_relative 'node_pattern_groups/ast_processor'
|
22
|
+
require_relative 'node_pattern_groups/ast_walker'
|
23
|
+
|
24
|
+
include RangeHelp
|
25
|
+
extend AutoCorrector
|
26
|
+
|
27
|
+
MSG = 'Replace `%<names>s` in node pattern union with `%<replacement>s`.'
|
28
|
+
RESTRICT_ON_SEND = %i[def_node_matcher def_node_search].freeze
|
29
|
+
NODE_GROUPS = {
|
30
|
+
any_block: %i[block numblock],
|
31
|
+
argument: %i[arg optarg restarg kwarg kwoptarg kwrestarg blockarg forward_arg shadowarg],
|
32
|
+
boolean: %i[true false],
|
33
|
+
call: %i[send csend],
|
34
|
+
numeric: %i[int float rational complex],
|
35
|
+
range: %i[irange erange]
|
36
|
+
}.freeze
|
37
|
+
|
38
|
+
def on_new_investigation
|
39
|
+
@walker = ASTWalker.new
|
40
|
+
end
|
41
|
+
|
42
|
+
# When a Node Pattern matcher is defined, investigate the pattern string to search
|
43
|
+
# for node types that can be replaced with a node group (ie. `{send csend}` can be
|
44
|
+
# replaced with `call`).
|
45
|
+
#
|
46
|
+
# In order to deal with node patterns in an efficient and non-brittle way, we will
|
47
|
+
# parse the Node Pattern string given to this `send` node using
|
48
|
+
# `RuboCop::AST::NodePattern::Parser::WithMeta`. `WithMeta` is important! We need
|
49
|
+
# location information so that we can calculate the exact locations within the
|
50
|
+
# pattern to report and correct.
|
51
|
+
#
|
52
|
+
# The resulting AST is processed by `NodePatternGroups::ASTProccessor` which rewrites
|
53
|
+
# the AST slightly to handle node sequences (ie. `(send _ :foo ...)`). See the
|
54
|
+
# documentation of that class for more details.
|
55
|
+
#
|
56
|
+
# Then the processed AST is walked, and metadata is collected for node types that
|
57
|
+
# can be replaced with a node group.
|
58
|
+
#
|
59
|
+
# Finally, the metadata is used to register offenses and make corrections, using
|
60
|
+
# the location data captured earlier. The ranges captured while parsing the Node
|
61
|
+
# Pattern are offset using the string argument to this `send` node to ensure
|
62
|
+
# that offenses are registered at the correct location.
|
63
|
+
#
|
64
|
+
def on_send(node)
|
65
|
+
pattern_node = node.arguments[1]
|
66
|
+
return unless acceptable_heredoc?(pattern_node) || pattern_node.str_type?
|
67
|
+
|
68
|
+
process_pattern(pattern_node)
|
69
|
+
return if node_groups.nil?
|
70
|
+
|
71
|
+
apply_range_offsets(pattern_node)
|
72
|
+
|
73
|
+
node_groups.each_with_index do |group, index|
|
74
|
+
register_offense(group, index)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def after_send(_)
|
79
|
+
@walker.reset!
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def node_groups
|
85
|
+
@walker.node_groups
|
86
|
+
end
|
87
|
+
|
88
|
+
# rubocop:disable InternalAffairs/RedundantSourceRange -- `node` here is a NodePatternNode
|
89
|
+
def register_offense(group, index)
|
90
|
+
replacement = replacement(group)
|
91
|
+
message = format(
|
92
|
+
MSG,
|
93
|
+
names: group.node_types.map { |node| node.source_range.source }.join('`, `'),
|
94
|
+
replacement: replacement
|
95
|
+
)
|
96
|
+
|
97
|
+
add_offense(group.offense_range, message: message) do |corrector|
|
98
|
+
# Only correct one group at a time to avoid clobbering.
|
99
|
+
# Other offenses will be corrected in the subsequent iterations of the
|
100
|
+
# correction loop.
|
101
|
+
next if index.positive?
|
102
|
+
|
103
|
+
if group.other_elements?
|
104
|
+
replace_types_with_node_group(corrector, group, replacement)
|
105
|
+
else
|
106
|
+
replace_union(corrector, group, replacement)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def replacement(group)
|
112
|
+
if group.sequence?
|
113
|
+
# If the original nodes were in a sequence (ie. wrapped in parentheses),
|
114
|
+
# use it to generate the resulting NodePattern syntax.
|
115
|
+
first_node_type = group.node_types.first
|
116
|
+
template = first_node_type.source_range.source
|
117
|
+
template.sub(first_node_type.child.to_s, group.name.to_s)
|
118
|
+
else
|
119
|
+
group.name
|
120
|
+
end
|
121
|
+
end
|
122
|
+
# rubocop:enable InternalAffairs/RedundantSourceRange
|
123
|
+
|
124
|
+
# When there are other elements in the union, remove the node types that can be replaced.
|
125
|
+
def replace_types_with_node_group(corrector, group, replacement)
|
126
|
+
ranges = group.ranges.map.with_index do |range, index|
|
127
|
+
# Collect whitespace and pipes preceding each element
|
128
|
+
range_for_full_union_element(range, index, group.pipe)
|
129
|
+
end
|
130
|
+
|
131
|
+
ranges.each { |range| corrector.remove(range) }
|
132
|
+
|
133
|
+
corrector.insert_before(ranges.first, replacement)
|
134
|
+
end
|
135
|
+
|
136
|
+
# If the union contains pipes, remove the pipe character as well.
|
137
|
+
# Unfortunately we don't get the location of the pipe in `loc` object, so we have
|
138
|
+
# to find it.
|
139
|
+
def range_for_full_union_element(range, index, pipe)
|
140
|
+
if index.positive?
|
141
|
+
range = if pipe
|
142
|
+
range_with_preceding_pipe(range)
|
143
|
+
else
|
144
|
+
range_with_surrounding_space(range: range, side: :left, newlines: true)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
range
|
149
|
+
end
|
150
|
+
|
151
|
+
# Collect a preceding pipe and any whitespace left of the pipe
|
152
|
+
def range_with_preceding_pipe(range)
|
153
|
+
pos = range.begin_pos - 1
|
154
|
+
|
155
|
+
while pos
|
156
|
+
unless processed_source.buffer.source[pos].match?(/[\s|]/)
|
157
|
+
return range.with(begin_pos: pos + 1)
|
158
|
+
end
|
159
|
+
|
160
|
+
pos -= 1
|
161
|
+
end
|
162
|
+
|
163
|
+
range
|
164
|
+
end
|
165
|
+
|
166
|
+
# When there are no other elements, the entire union can be replaced
|
167
|
+
def replace_union(corrector, group, replacement)
|
168
|
+
corrector.replace(group.ranges.first, replacement)
|
169
|
+
end
|
170
|
+
|
171
|
+
# rubocop:disable Metrics/AbcSize
|
172
|
+
# Calculate the ranges for each node within the pattern string that will
|
173
|
+
# be replaced or removed. Takes the offset of the string node into account.
|
174
|
+
def apply_range_offsets(pattern_node)
|
175
|
+
range, offset = range_with_offset(pattern_node)
|
176
|
+
|
177
|
+
node_groups.each do |node_group|
|
178
|
+
node_group.ranges ||= []
|
179
|
+
node_group.offense_range = pattern_range(range, node_group.union, offset)
|
180
|
+
|
181
|
+
if node_group.other_elements?
|
182
|
+
node_group.node_types.each do |node_type|
|
183
|
+
node_group.ranges << pattern_range(range, node_type, offset)
|
184
|
+
end
|
185
|
+
else
|
186
|
+
node_group.ranges << node_group.offense_range
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
# rubocop:enable Metrics/AbcSize
|
191
|
+
|
192
|
+
def pattern_range(range, node, offset)
|
193
|
+
begin_pos = node.source_range.begin_pos
|
194
|
+
end_pos = node.source_range.end_pos
|
195
|
+
size = end_pos - begin_pos
|
196
|
+
|
197
|
+
range.adjust(begin_pos: begin_pos + offset).resize(size)
|
198
|
+
end
|
199
|
+
|
200
|
+
def range_with_offset(pattern_node)
|
201
|
+
if pattern_node.heredoc?
|
202
|
+
[pattern_node.loc.heredoc_body, 0]
|
203
|
+
else
|
204
|
+
[pattern_node.source_range, pattern_node.loc.begin.size]
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
# A heredoc can be a `dstr` without interpolation, but if there is interpolation
|
209
|
+
# there'll be a `begin` node, in which case, we cannot evaluate the pattern.
|
210
|
+
def acceptable_heredoc?(node)
|
211
|
+
node.type?(:str, :dstr) && node.heredoc? && node.each_child_node(:begin).none?
|
212
|
+
end
|
213
|
+
|
214
|
+
def process_pattern(pattern_node)
|
215
|
+
parser = RuboCop::AST::NodePattern::Parser::WithMeta.new
|
216
|
+
ast = parser.parse(pattern_value(pattern_node))
|
217
|
+
ast = ASTProcessor.new.process(ast)
|
218
|
+
@walker.walk(ast)
|
219
|
+
rescue RuboCop::AST::NodePattern::Invalid
|
220
|
+
# if the pattern is invalid, no offenses will be registered
|
221
|
+
end
|
222
|
+
|
223
|
+
def pattern_value(pattern_node)
|
224
|
+
pattern_node.heredoc? ? pattern_node.loc.heredoc_body.source : pattern_node.value
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module InternalAffairs
|
6
|
+
# Use `node.type?(:foo, :bar)` instead of `node.foo_type? || node.bar_type?`,
|
7
|
+
# and `!node.type?(:foo, :bar)` instead of `!node.foo_type? && !node.bar_type?`.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
#
|
11
|
+
# # bad
|
12
|
+
# node.str_type? || node.sym_type?
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# node.type?(:str, :sym)
|
16
|
+
#
|
17
|
+
# # bad
|
18
|
+
# node.type?(:str, :sym) || node.boolean_type?
|
19
|
+
#
|
20
|
+
# # good
|
21
|
+
# node.type?(:str, :sym, :boolean)
|
22
|
+
#
|
23
|
+
# # bad
|
24
|
+
# !node.str_type? && !node.sym_type?
|
25
|
+
#
|
26
|
+
# # good
|
27
|
+
# !node.type?(:str, :sym)
|
28
|
+
#
|
29
|
+
# # bad
|
30
|
+
# !node.type?(:str, :sym) && !node.boolean_type?
|
31
|
+
#
|
32
|
+
# # good
|
33
|
+
# !node.type?(:str, :sym, :boolean)
|
34
|
+
#
|
35
|
+
class NodeTypeMultiplePredicates < Base
|
36
|
+
extend AutoCorrector
|
37
|
+
|
38
|
+
MSG_OR = 'Use `%<replacement>s` instead of checking for multiple node types.'
|
39
|
+
MSG_AND = 'Use `%<replacement>s` instead of checking against multiple node types.'
|
40
|
+
|
41
|
+
# @!method one_of_node_types?(node)
|
42
|
+
def_node_matcher :one_of_node_types?, <<~PATTERN
|
43
|
+
(or $(call _receiver #type_predicate?) (call _receiver #type_predicate?))
|
44
|
+
PATTERN
|
45
|
+
|
46
|
+
# @!method or_another_type?(node)
|
47
|
+
def_node_matcher :or_another_type?, <<~PATTERN
|
48
|
+
(or {
|
49
|
+
$(call _receiver :type? sym+) (call _receiver #type_predicate?) |
|
50
|
+
(call _receiver #type_predicate?) $(call _receiver :type? sym+)
|
51
|
+
})
|
52
|
+
PATTERN
|
53
|
+
|
54
|
+
# @!method none_of_node_types?(node)
|
55
|
+
def_node_matcher :none_of_node_types?, <<~PATTERN
|
56
|
+
(and
|
57
|
+
(send $(call _receiver #type_predicate?) :!)
|
58
|
+
(send (call _receiver #type_predicate?) :!)
|
59
|
+
)
|
60
|
+
PATTERN
|
61
|
+
|
62
|
+
# @!method and_not_another_type?(node)
|
63
|
+
def_node_matcher :and_not_another_type?, <<~PATTERN
|
64
|
+
(and {
|
65
|
+
(send $(call _receiver :type? sym+) :!) (send (call _receiver #type_predicate?) :!) |
|
66
|
+
(send (call _receiver #type_predicate?) :!) (send $(call _receiver :type? sym+) :!)
|
67
|
+
})
|
68
|
+
PATTERN
|
69
|
+
|
70
|
+
def on_or(node)
|
71
|
+
return unless (send_node = one_of_node_types?(node) || or_another_type?(node))
|
72
|
+
return unless send_node.receiver
|
73
|
+
|
74
|
+
replacement = replacement(node, send_node)
|
75
|
+
add_offense(node, message: format(MSG_OR, replacement: replacement)) do |corrector|
|
76
|
+
corrector.replace(node, replacement)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def on_and(node)
|
81
|
+
return unless (send_node = none_of_node_types?(node) || and_not_another_type?(node))
|
82
|
+
return unless send_node.receiver
|
83
|
+
|
84
|
+
replacement = "!#{replacement(node, send_node)}"
|
85
|
+
|
86
|
+
add_offense(node, message: format(MSG_AND, replacement: replacement)) do |corrector|
|
87
|
+
corrector.replace(node, replacement)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def type_predicate?(method_name)
|
94
|
+
method_name.end_with?('_type?')
|
95
|
+
end
|
96
|
+
|
97
|
+
def replacement(node, send_node)
|
98
|
+
send_node = send_node.children.first if send_node.method?(:!)
|
99
|
+
|
100
|
+
types = types(node)
|
101
|
+
receiver = send_node.receiver.source
|
102
|
+
dot = send_node.loc.dot.source
|
103
|
+
|
104
|
+
"#{receiver}#{dot}type?(:#{types.join(', :')})"
|
105
|
+
end
|
106
|
+
|
107
|
+
def types(node)
|
108
|
+
[types_in_branch(node.lhs), types_in_branch(node.rhs)]
|
109
|
+
end
|
110
|
+
|
111
|
+
def types_in_branch(branch)
|
112
|
+
branch = branch.children.first if branch.method?(:!)
|
113
|
+
|
114
|
+
if branch.method?(:type?)
|
115
|
+
branch.arguments.map(&:value)
|
116
|
+
elsif branch.method?(:defined_type?)
|
117
|
+
# `node.defined_type?` relates to `node.type == :defined?`
|
118
|
+
'defined?'
|
119
|
+
else
|
120
|
+
branch.method_name.to_s.delete_suffix('_type?')
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -21,16 +21,17 @@ module RuboCop
|
|
21
21
|
|
22
22
|
# @!method node_type_check(node)
|
23
23
|
def_node_matcher :node_type_check, <<~PATTERN
|
24
|
-
(send (
|
24
|
+
(send (call _ :type) :== (sym $_))
|
25
25
|
PATTERN
|
26
26
|
|
27
27
|
def on_send(node)
|
28
|
-
node_type_check(node) do |
|
28
|
+
node_type_check(node) do |node_type|
|
29
29
|
return unless Parser::Meta::NODE_TYPES.include?(node_type)
|
30
30
|
|
31
31
|
message = format(MSG, type: node_type)
|
32
32
|
add_offense(node, message: message) do |corrector|
|
33
|
-
range = node.
|
33
|
+
range = node.receiver.loc.selector.join(node.source_range.end)
|
34
|
+
|
34
35
|
corrector.replace(range, "#{node_type}_type?")
|
35
36
|
end
|
36
37
|
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module InternalAffairs
|
6
|
+
# Checks for cops that define `on_send` without define `on_csend`.
|
7
|
+
#
|
8
|
+
# Although in some cases it can be predetermined that safe navigation
|
9
|
+
# will never be used with the code checked by a specific cop, in general
|
10
|
+
# it is good practice to handle safe navigation methods if handling any
|
11
|
+
# `send` node.
|
12
|
+
#
|
13
|
+
# NOTE: It is expected to disable this cop for cops that check for method calls
|
14
|
+
# on receivers that cannot be nil (`self`, a literal, a constant), and
|
15
|
+
# method calls that will never have a receiver (ruby keywords like `raise`,
|
16
|
+
# macros like `attr_reader`, DSL methods, etc.), and other checks that wouldn't
|
17
|
+
# make sense to support safe navigation.
|
18
|
+
#
|
19
|
+
# @example
|
20
|
+
# # bad
|
21
|
+
# class MyCop < RuboCop::Cop:Base
|
22
|
+
# def on_send(node)
|
23
|
+
# # ...
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# # good - explicit method definition
|
28
|
+
# class MyCop < RuboCop::Cop:Base
|
29
|
+
# def on_send(node)
|
30
|
+
# # ...
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# def on_csend(node)
|
34
|
+
# # ...
|
35
|
+
# end
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# # good - alias
|
39
|
+
# class MyCop < RuboCop::Cop:Base
|
40
|
+
# def on_send(node)
|
41
|
+
# # ...
|
42
|
+
# end
|
43
|
+
# alias on_csend on_send
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# # good - alias_method
|
47
|
+
# class MyCop < RuboCop::Cop:Base
|
48
|
+
# def on_send(node)
|
49
|
+
# # ...
|
50
|
+
# end
|
51
|
+
# alias_method :on_csend, :on_send
|
52
|
+
# end
|
53
|
+
class OnSendWithoutOnCSend < Base
|
54
|
+
RESTRICT_ON_SEND = %i[alias_method].freeze
|
55
|
+
MSG = 'Cop defines `on_send` but not `on_csend`.'
|
56
|
+
|
57
|
+
def on_new_investigation
|
58
|
+
@on_send_definition = nil
|
59
|
+
@on_csend_definition = nil
|
60
|
+
end
|
61
|
+
|
62
|
+
def on_investigation_end
|
63
|
+
return unless @on_send_definition && !@on_csend_definition
|
64
|
+
|
65
|
+
add_offense(@on_send_definition)
|
66
|
+
end
|
67
|
+
|
68
|
+
def on_def(node)
|
69
|
+
@on_send_definition = node if node.method?(:on_send)
|
70
|
+
@on_csend_definition = node if node.method?(:on_csend)
|
71
|
+
end
|
72
|
+
|
73
|
+
def on_alias(node)
|
74
|
+
@on_send_definition = node if node.new_identifier.value == :on_send
|
75
|
+
@on_csend_definition = node if node.new_identifier.value == :on_csend
|
76
|
+
end
|
77
|
+
|
78
|
+
def on_send(node) # rubocop:disable InternalAffairs/OnSendWithoutOnCSend
|
79
|
+
new_identifier = node.first_argument
|
80
|
+
return unless new_identifier.basic_literal?
|
81
|
+
|
82
|
+
new_identifier = new_identifier.value
|
83
|
+
|
84
|
+
@on_send_definition = node if new_identifier == :on_send
|
85
|
+
@on_csend_definition = node if new_identifier == :on_csend
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -47,7 +47,7 @@ module RuboCop
|
|
47
47
|
# @!method redundant_source_range(node)
|
48
48
|
def_node_matcher :redundant_source_range, <<~PATTERN
|
49
49
|
{
|
50
|
-
(
|
50
|
+
(call $(call _ :source_range) :source)
|
51
51
|
(send nil? :add_offense $(send _ :source_range) ...)
|
52
52
|
(send _ {
|
53
53
|
:replace :insert_before :insert_before_multi :insert_after :insert_after_multi
|
@@ -59,6 +59,7 @@ module RuboCop
|
|
59
59
|
|
60
60
|
def on_send(node)
|
61
61
|
return unless (source_range = redundant_source_range(node))
|
62
|
+
return unless source_range.receiver
|
62
63
|
return if source_range.receiver.send_type? && source_range.receiver.method?(:buffer)
|
63
64
|
|
64
65
|
selector = source_range.loc.selector
|
@@ -67,6 +68,7 @@ module RuboCop
|
|
67
68
|
corrector.remove(source_range.loc.dot.join(selector))
|
68
69
|
end
|
69
70
|
end
|
71
|
+
alias on_csend on_send
|
70
72
|
end
|
71
73
|
end
|
72
74
|
end
|
@@ -34,8 +34,8 @@ module RuboCop
|
|
34
34
|
# @!method single_line_comparison(node)
|
35
35
|
def_node_matcher :single_line_comparison, <<~PATTERN
|
36
36
|
{
|
37
|
-
(send (
|
38
|
-
(send (
|
37
|
+
(send (call $_receiver {:line :first_line}) {:== :!=} (call _receiver :last_line))
|
38
|
+
(send (call $_receiver :last_line) {:== :!=} (call _receiver {:line :first_line}))
|
39
39
|
}
|
40
40
|
PATTERN
|
41
41
|
|
@@ -43,7 +43,8 @@ module RuboCop
|
|
43
43
|
return unless (receiver = single_line_comparison(node))
|
44
44
|
|
45
45
|
bang = node.method?(:!=) ? '!' : ''
|
46
|
-
|
46
|
+
dot = receiver.parent.loc.dot.source
|
47
|
+
preferred = "#{bang}#{extract_receiver(receiver)}#{dot}single_line?"
|
47
48
|
|
48
49
|
add_offense(node, message: format(MSG, preferred: preferred)) do |corrector|
|
49
50
|
corrector.replace(node, preferred)
|
@@ -53,7 +54,7 @@ module RuboCop
|
|
53
54
|
private
|
54
55
|
|
55
56
|
def extract_receiver(node)
|
56
|
-
node = node.receiver if node.
|
57
|
+
node = node.receiver if node.call_type? && %i[loc source_range].include?(node.method_name)
|
57
58
|
node.source
|
58
59
|
end
|
59
60
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'internal_affairs/cop_description'
|
4
|
+
require_relative 'internal_affairs/cop_enabled'
|
4
5
|
require_relative 'internal_affairs/create_empty_file'
|
5
6
|
require_relative 'internal_affairs/empty_line_between_expect_offense_and_correction'
|
6
7
|
require_relative 'internal_affairs/example_description'
|
@@ -14,9 +15,12 @@ require_relative 'internal_affairs/method_name_equal'
|
|
14
15
|
require_relative 'internal_affairs/node_destructuring'
|
15
16
|
require_relative 'internal_affairs/node_first_or_last_argument'
|
16
17
|
require_relative 'internal_affairs/node_matcher_directive'
|
18
|
+
require_relative 'internal_affairs/node_pattern_groups'
|
19
|
+
require_relative 'internal_affairs/node_type_multiple_predicates'
|
17
20
|
require_relative 'internal_affairs/node_type_predicate'
|
18
21
|
require_relative 'internal_affairs/numblock_handler'
|
19
22
|
require_relative 'internal_affairs/offense_location_keyword'
|
23
|
+
require_relative 'internal_affairs/on_send_without_on_csend'
|
20
24
|
require_relative 'internal_affairs/operator_keyword'
|
21
25
|
require_relative 'internal_affairs/processed_source_buffer_name'
|
22
26
|
require_relative 'internal_affairs/redundant_context_config_parameter'
|
@@ -4,7 +4,7 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module Layout
|
6
6
|
# Bare access modifiers (those not applying to specific methods) should be
|
7
|
-
# indented as deep as method definitions, or as deep as the class
|
7
|
+
# indented as deep as method definitions, or as deep as the `class`/`module`
|
8
8
|
# keyword, depending on configuration.
|
9
9
|
#
|
10
10
|
# @example EnforcedStyle: indent (default)
|