rubocop 1.18.1 → 1.22.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/config/default.yml +116 -23
- data/lib/rubocop/cli.rb +18 -0
- data/lib/rubocop/config.rb +5 -0
- data/lib/rubocop/config_loader.rb +5 -3
- data/lib/rubocop/config_loader_resolver.rb +22 -7
- data/lib/rubocop/config_validator.rb +27 -6
- data/lib/rubocop/cop/base.rb +3 -3
- data/lib/rubocop/cop/bundler/gem_comment.rb +3 -3
- data/lib/rubocop/cop/bundler/gem_filename.rb +103 -0
- data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +45 -21
- data/lib/rubocop/cop/bundler/ordered_gems.rb +3 -12
- data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +2 -2
- data/lib/rubocop/cop/correctors/line_break_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +11 -10
- data/lib/rubocop/cop/correctors/require_library_corrector.rb +23 -0
- data/lib/rubocop/cop/documentation.rb +1 -1
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +3 -12
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +31 -24
- data/lib/rubocop/cop/generator.rb +14 -8
- data/lib/rubocop/cop/internal_affairs/inherit_deprecated_cop_class.rb +34 -0
- data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +60 -0
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/undefined_config.rb +71 -0
- data/lib/rubocop/cop/internal_affairs.rb +3 -0
- data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/assignment_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/block_alignment.rb +3 -3
- data/lib/rubocop/cop/layout/class_structure.rb +7 -2
- data/lib/rubocop/cop/layout/dot_position.rb +34 -5
- data/lib/rubocop/cop/layout/empty_comment.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +9 -0
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +7 -4
- data/lib/rubocop/cop/layout/end_alignment.rb +9 -2
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/hash_alignment.rb +22 -18
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +1 -1
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +0 -7
- data/lib/rubocop/cop/layout/indentation_style.rb +2 -2
- data/lib/rubocop/cop/layout/indentation_width.rb +1 -1
- data/lib/rubocop/cop/layout/leading_comment_space.rb +2 -2
- data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +36 -17
- data/lib/rubocop/cop/layout/line_length.rb +9 -7
- data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +3 -3
- data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +3 -0
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -0
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +23 -10
- data/lib/rubocop/cop/layout/single_line_block_chain.rb +15 -4
- data/lib/rubocop/cop/layout/space_after_not.rb +1 -0
- data/lib/rubocop/cop/layout/space_around_equals_in_parameter_default.rb +2 -1
- data/lib/rubocop/cop/layout/space_around_keyword.rb +2 -2
- data/lib/rubocop/cop/layout/space_around_operators.rb +12 -1
- data/lib/rubocop/cop/layout/space_before_brackets.rb +1 -0
- data/lib/rubocop/cop/layout/space_before_comment.rb +2 -2
- data/lib/rubocop/cop/layout/space_inside_parens.rb +78 -32
- data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +1 -1
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +24 -1
- data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +111 -0
- data/lib/rubocop/cop/lint/ambiguous_range.rb +105 -0
- data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +5 -2
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +7 -5
- data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +18 -5
- data/lib/rubocop/cop/lint/boolean_symbol.rb +5 -0
- data/lib/rubocop/cop/lint/debugger.rb +2 -4
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +4 -4
- data/lib/rubocop/cop/lint/deprecated_constants.rb +3 -2
- data/lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb +24 -1
- data/lib/rubocop/cop/lint/duplicate_branch.rb +2 -1
- data/lib/rubocop/cop/lint/duplicate_methods.rb +8 -5
- data/lib/rubocop/cop/lint/else_layout.rb +10 -6
- data/lib/rubocop/cop/lint/empty_in_pattern.rb +1 -1
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -1
- data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -1
- data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +12 -3
- data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +67 -0
- data/lib/rubocop/cop/lint/interpolation_check.rb +5 -0
- data/lib/rubocop/cop/lint/loop.rb +4 -3
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +5 -1
- data/lib/rubocop/cop/lint/number_conversion.rb +12 -1
- data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -1
- data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +4 -2
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +17 -0
- data/lib/rubocop/cop/lint/percent_string_array.rb +10 -0
- data/lib/rubocop/cop/lint/raise_exception.rb +4 -0
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +5 -4
- data/lib/rubocop/cop/lint/require_relative_self_path.rb +50 -0
- data/lib/rubocop/cop/lint/shadowed_argument.rb +1 -1
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +1 -1
- data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/triple_quotes.rb +1 -1
- data/lib/rubocop/cop/lint/unexpected_block_arity.rb +8 -3
- data/lib/rubocop/cop/lint/unused_method_argument.rb +2 -3
- data/lib/rubocop/cop/lint/useless_method_definition.rb +3 -2
- data/lib/rubocop/cop/lint/useless_setter_call.rb +7 -4
- data/lib/rubocop/cop/lint/useless_times.rb +5 -4
- data/lib/rubocop/cop/metrics/abc_size.rb +6 -0
- data/lib/rubocop/cop/metrics/parameter_lists.rb +5 -2
- data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
- data/lib/rubocop/cop/mixin/annotation_comment.rb +57 -34
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +2 -2
- data/lib/rubocop/cop/mixin/code_length.rb +1 -1
- data/lib/rubocop/cop/mixin/documentation_comment.rb +5 -2
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -2
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +23 -1
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +9 -4
- data/lib/rubocop/cop/mixin/heredoc.rb +5 -0
- data/lib/rubocop/cop/mixin/multiline_element_indentation.rb +1 -1
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +2 -2
- data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
- data/lib/rubocop/cop/mixin/ordered_gem_node.rb +9 -1
- data/lib/rubocop/cop/mixin/percent_array.rb +18 -7
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +9 -1
- data/lib/rubocop/cop/mixin/require_library.rb +59 -0
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
- data/lib/rubocop/cop/mixin/space_before_punctuation.rb +2 -2
- data/lib/rubocop/cop/mixin/statement_modifier.rb +1 -1
- data/lib/rubocop/cop/mixin/string_literals_help.rb +5 -1
- data/lib/rubocop/cop/mixin/trailing_body.rb +1 -1
- data/lib/rubocop/cop/naming/ascii_identifiers.rb +0 -3
- data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
- data/lib/rubocop/cop/naming/constant_name.rb +1 -1
- data/lib/rubocop/cop/naming/inclusive_language.rb +27 -10
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +5 -4
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +7 -0
- data/lib/rubocop/cop/security/io_methods.rb +49 -0
- data/lib/rubocop/cop/security/json_load.rb +8 -7
- data/lib/rubocop/cop/security/open.rb +4 -0
- data/lib/rubocop/cop/security/yaml_load.rb +4 -0
- data/lib/rubocop/cop/style/accessor_grouping.rb +2 -2
- data/lib/rubocop/cop/style/and_or.rb +5 -0
- data/lib/rubocop/cop/style/arguments_forwarding.rb +13 -2
- data/lib/rubocop/cop/style/array_coercion.rb +21 -3
- data/lib/rubocop/cop/style/ascii_comments.rb +0 -3
- data/lib/rubocop/cop/style/block_delimiters.rb +50 -2
- data/lib/rubocop/cop/style/case_equality.rb +6 -9
- data/lib/rubocop/cop/style/case_like_if.rb +5 -0
- data/lib/rubocop/cop/style/class_and_module_children.rb +9 -0
- data/lib/rubocop/cop/style/collection_compact.rb +7 -5
- data/lib/rubocop/cop/style/collection_methods.rb +8 -6
- data/lib/rubocop/cop/style/combinable_loops.rb +3 -2
- data/lib/rubocop/cop/style/comment_annotation.rb +55 -25
- data/lib/rubocop/cop/style/commented_keyword.rb +9 -3
- data/lib/rubocop/cop/style/conditional_assignment.rb +19 -5
- data/lib/rubocop/cop/style/date_time.rb +5 -0
- data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +1 -1
- data/lib/rubocop/cop/style/documentation.rb +23 -8
- data/lib/rubocop/cop/style/double_cop_disable_directive.rb +1 -7
- data/lib/rubocop/cop/style/double_negation.rb +27 -6
- data/lib/rubocop/cop/style/empty_method.rb +1 -1
- data/lib/rubocop/cop/style/encoding.rb +26 -15
- data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
- data/lib/rubocop/cop/style/explicit_block_argument.rb +46 -11
- data/lib/rubocop/cop/style/float_division.rb +10 -2
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +14 -3
- data/lib/rubocop/cop/style/global_std_stream.rb +4 -0
- data/lib/rubocop/cop/style/hash_as_last_array_item.rb +11 -0
- data/lib/rubocop/cop/style/hash_each_methods.rb +5 -0
- data/lib/rubocop/cop/style/hash_except.rb +4 -3
- data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
- data/lib/rubocop/cop/style/hash_transform_keys.rb +4 -9
- data/lib/rubocop/cop/style/hash_transform_values.rb +4 -6
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +32 -5
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +18 -4
- data/lib/rubocop/cop/style/infinite_loop.rb +4 -3
- data/lib/rubocop/cop/style/inverse_methods.rb +9 -2
- data/lib/rubocop/cop/style/lambda_call.rb +1 -1
- data/lib/rubocop/cop/style/line_end_concatenation.rb +14 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +6 -6
- data/lib/rubocop/cop/style/method_def_parentheses.rb +10 -1
- data/lib/rubocop/cop/style/missing_else.rb +7 -0
- data/lib/rubocop/cop/style/module_function.rb +8 -9
- data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +1 -1
- data/lib/rubocop/cop/style/multiline_when_then.rb +1 -1
- data/lib/rubocop/cop/style/mutable_constant.rb +79 -14
- data/lib/rubocop/cop/style/negated_if.rb +1 -1
- data/lib/rubocop/cop/style/negated_unless.rb +1 -1
- data/lib/rubocop/cop/style/non_nil_check.rb +2 -2
- data/lib/rubocop/cop/style/not.rb +2 -2
- data/lib/rubocop/cop/style/numbered_parameters.rb +46 -0
- data/lib/rubocop/cop/style/numbered_parameters_limit.rb +50 -0
- data/lib/rubocop/cop/style/numeric_literals.rb +7 -8
- data/lib/rubocop/cop/style/numeric_predicate.rb +5 -0
- data/lib/rubocop/cop/style/optional_arguments.rb +4 -0
- data/lib/rubocop/cop/style/optional_boolean_parameter.rb +14 -4
- data/lib/rubocop/cop/style/parallel_assignment.rb +1 -1
- data/lib/rubocop/cop/style/percent_q_literals.rb +2 -2
- data/lib/rubocop/cop/style/preferred_hash_methods.rb +9 -4
- data/lib/rubocop/cop/style/quoted_symbols.rb +10 -6
- data/lib/rubocop/cop/style/raise_args.rb +1 -1
- data/lib/rubocop/cop/style/redundant_argument.rb +19 -9
- data/lib/rubocop/cop/style/redundant_begin.rb +25 -0
- data/lib/rubocop/cop/style/redundant_condition.rb +2 -3
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +4 -0
- data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +12 -3
- data/lib/rubocop/cop/style/redundant_freeze.rb +4 -4
- data/lib/rubocop/cop/style/redundant_interpolation.rb +1 -1
- data/lib/rubocop/cop/style/redundant_percent_q.rb +2 -3
- data/lib/rubocop/cop/style/redundant_self.rb +10 -0
- data/lib/rubocop/cop/style/redundant_self_assignment.rb +4 -3
- data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +83 -0
- data/lib/rubocop/cop/style/redundant_sort.rb +53 -20
- data/lib/rubocop/cop/style/regexp_literal.rb +3 -3
- data/lib/rubocop/cop/style/return_nil.rb +2 -1
- data/lib/rubocop/cop/style/safe_navigation.rb +13 -2
- data/lib/rubocop/cop/style/select_by_regexp.rb +139 -0
- data/lib/rubocop/cop/style/semicolon.rb +32 -24
- data/lib/rubocop/cop/style/single_argument_dig.rb +5 -0
- data/lib/rubocop/cop/style/single_line_block_params.rb +3 -1
- data/lib/rubocop/cop/style/single_line_methods.rb +25 -15
- data/lib/rubocop/cop/style/slicing_with_range.rb +13 -0
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +4 -0
- data/lib/rubocop/cop/style/special_global_vars.rb +25 -0
- data/lib/rubocop/cop/style/static_class.rb +5 -5
- data/lib/rubocop/cop/style/string_chars.rb +4 -2
- data/lib/rubocop/cop/style/string_concatenation.rb +5 -1
- data/lib/rubocop/cop/style/string_hash_keys.rb +4 -0
- data/lib/rubocop/cop/style/struct_inheritance.rb +4 -0
- data/lib/rubocop/cop/style/swap_values.rb +4 -2
- data/lib/rubocop/cop/style/symbol_array.rb +3 -3
- data/lib/rubocop/cop/style/symbol_proc.rb +26 -0
- data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +19 -0
- data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
- data/lib/rubocop/cop/style/word_array.rb +23 -5
- data/lib/rubocop/cop/style/yoda_condition.rb +24 -7
- data/lib/rubocop/cop/style/zero_length_predicate.rb +6 -0
- data/lib/rubocop/cop/util.rb +22 -6
- data/lib/rubocop/cops_documentation_generator.rb +17 -5
- data/lib/rubocop/formatter/git_hub_actions_formatter.rb +1 -1
- data/lib/rubocop/magic_comment.rb +44 -15
- data/lib/rubocop/options.rb +127 -113
- data/lib/rubocop/rake_task.rb +1 -1
- data/lib/rubocop/result_cache.rb +3 -3
- data/lib/rubocop/rspec/cop_helper.rb +1 -1
- data/lib/rubocop/rspec/expect_offense.rb +6 -2
- data/lib/rubocop/rspec/parallel_formatter.rb +90 -0
- data/lib/rubocop/rspec/support.rb +1 -0
- data/lib/rubocop/runner.rb +2 -3
- data/lib/rubocop/target_finder.rb +1 -1
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +14 -2
- metadata +21 -5
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
# This cop checks for ambiguous ranges.
|
7
|
+
#
|
8
|
+
# Ranges have quite low precedence, which leads to unexpected behaviour when
|
9
|
+
# using a range with other operators. This cop avoids that by making ranges
|
10
|
+
# explicit by requiring parenthesis around complex range boundaries (anything
|
11
|
+
# that is not a basic literal: numerics, strings, symbols, etc.).
|
12
|
+
#
|
13
|
+
# This cop can be configured with `RequireParenthesesForMethodChains` in order to
|
14
|
+
# specify whether method chains (including `self.foo`) should be wrapped in parens
|
15
|
+
# by this cop.
|
16
|
+
#
|
17
|
+
# NOTE: Regardless of this configuration, if a method receiver is a basic literal
|
18
|
+
# value, it will be wrapped in order to prevent the ambiguity of `1..2.to_a`.
|
19
|
+
#
|
20
|
+
# @safety
|
21
|
+
# The cop auto-corrects by wrapping the entire boundary in parentheses, which
|
22
|
+
# makes the outcome more explicit but is possible to not be the intention of the
|
23
|
+
# programmer. For this reason, this cop's auto-correct is unsafe (it will not
|
24
|
+
# change the behaviour of the code, but will not necessarily match the
|
25
|
+
# intent of the program).
|
26
|
+
#
|
27
|
+
# @example
|
28
|
+
# # bad
|
29
|
+
# x || 1..2
|
30
|
+
# (x || 1..2)
|
31
|
+
# 1..2.to_a
|
32
|
+
#
|
33
|
+
# # good, unambiguous
|
34
|
+
# 1..2
|
35
|
+
# 'a'..'z'
|
36
|
+
# :bar..:baz
|
37
|
+
# MyClass::MIN..MyClass::MAX
|
38
|
+
# @min..@max
|
39
|
+
# a..b
|
40
|
+
# -a..b
|
41
|
+
#
|
42
|
+
# # good, ambiguity removed
|
43
|
+
# x || (1..2)
|
44
|
+
# (x || 1)..2
|
45
|
+
# (x || 1)..(y || 2)
|
46
|
+
# (1..2).to_a
|
47
|
+
#
|
48
|
+
# @example RequireParenthesesForMethodChains: false (default)
|
49
|
+
# # good
|
50
|
+
# a.foo..b.bar
|
51
|
+
# (a.foo)..(b.bar)
|
52
|
+
#
|
53
|
+
# @example RequireParenthesesForMethodChains: true
|
54
|
+
# # bad
|
55
|
+
# a.foo..b.bar
|
56
|
+
#
|
57
|
+
# # good
|
58
|
+
# (a.foo)..(b.bar)
|
59
|
+
class AmbiguousRange < Base
|
60
|
+
extend AutoCorrector
|
61
|
+
|
62
|
+
MSG = 'Wrap complex range boundaries with parentheses to avoid ambiguity.'
|
63
|
+
|
64
|
+
def on_irange(node)
|
65
|
+
each_boundary(node) do |boundary|
|
66
|
+
next if acceptable?(boundary)
|
67
|
+
|
68
|
+
add_offense(boundary) do |corrector|
|
69
|
+
corrector.wrap(boundary, '(', ')')
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
alias on_erange on_irange
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def each_boundary(range)
|
78
|
+
yield range.begin if range.begin
|
79
|
+
yield range.end if range.end
|
80
|
+
end
|
81
|
+
|
82
|
+
def acceptable?(node)
|
83
|
+
node.begin_type? ||
|
84
|
+
node.basic_literal? ||
|
85
|
+
node.variable? || node.const_type? || node.self_type? ||
|
86
|
+
(node.call_type? && acceptable_call?(node))
|
87
|
+
end
|
88
|
+
|
89
|
+
def acceptable_call?(node)
|
90
|
+
return true if node.unary_operation?
|
91
|
+
|
92
|
+
# Require parentheses when making a method call on a literal
|
93
|
+
# to avoid the ambiguity of `1..2.to_a`.
|
94
|
+
return false if node.receiver&.basic_literal?
|
95
|
+
|
96
|
+
require_parentheses_for_method_chain? || node.receiver.nil?
|
97
|
+
end
|
98
|
+
|
99
|
+
def require_parentheses_for_method_chain?
|
100
|
+
!cop_config['RequireParenthesesForMethodChains']
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -46,12 +46,11 @@ module RuboCop
|
|
46
46
|
node = processed_source.ast.each_node(:regexp).find do |regexp_node|
|
47
47
|
regexp_node.source_range.begin_pos == diagnostic.location.begin_pos
|
48
48
|
end
|
49
|
-
|
50
49
|
find_offense_node(node.parent, node)
|
51
50
|
end
|
52
51
|
|
53
52
|
def find_offense_node(node, regexp_receiver)
|
54
|
-
return node
|
53
|
+
return node if first_argument_is_regexp?(node) || !node.parent
|
55
54
|
|
56
55
|
if (node.parent.send_type? && node.receiver) ||
|
57
56
|
method_chain_to_regexp_receiver?(node, regexp_receiver)
|
@@ -61,6 +60,10 @@ module RuboCop
|
|
61
60
|
node
|
62
61
|
end
|
63
62
|
|
63
|
+
def first_argument_is_regexp?(node)
|
64
|
+
node.send_type? && node.first_argument&.regexp_type?
|
65
|
+
end
|
66
|
+
|
64
67
|
def method_chain_to_regexp_receiver?(node, regexp_receiver)
|
65
68
|
return false unless (parent = node.parent)
|
66
69
|
return false unless (parent_receiver = parent.receiver)
|
@@ -49,7 +49,7 @@ module RuboCop
|
|
49
49
|
def on_if(node)
|
50
50
|
return if node.condition.block_type?
|
51
51
|
|
52
|
-
traverse_node(node.condition
|
52
|
+
traverse_node(node.condition) do |asgn_node|
|
53
53
|
next :skip_children if skip_children?(asgn_node)
|
54
54
|
next if allowed_construct?(asgn_node)
|
55
55
|
|
@@ -83,13 +83,15 @@ module RuboCop
|
|
83
83
|
(safe_assignment_allowed? && safe_assignment?(asgn_node))
|
84
84
|
end
|
85
85
|
|
86
|
-
|
87
|
-
|
88
|
-
|
86
|
+
def traverse_node(node, &block)
|
87
|
+
# if the node is a block, any assignments are irrelevant
|
88
|
+
return if node.block_type?
|
89
|
+
|
90
|
+
result = yield node if ASGN_TYPES.include?(node.type)
|
89
91
|
|
90
92
|
return if result == :skip_children
|
91
93
|
|
92
|
-
node.each_child_node { |child| traverse_node(child,
|
94
|
+
node.each_child_node { |child| traverse_node(child, &block) }
|
93
95
|
end
|
94
96
|
end
|
95
97
|
end
|
@@ -5,15 +5,28 @@ module RuboCop
|
|
5
5
|
module Lint
|
6
6
|
# This cop checks for places where binary operator has identical operands.
|
7
7
|
#
|
8
|
-
# It covers arithmetic operators:
|
8
|
+
# It covers arithmetic operators: `-`, `/`, `%`;
|
9
9
|
# comparison operators: `==`, `===`, `=~`, `>`, `>=`, `<`, `<=`;
|
10
|
-
# bitwise operators: `|`, `^`,
|
10
|
+
# bitwise operators: `|`, `^`, `&`;
|
11
11
|
# boolean operators: `&&`, `||`
|
12
12
|
# and "spaceship" operator - `<=>`.
|
13
13
|
#
|
14
|
-
#
|
15
|
-
#
|
14
|
+
# Simple arithmetic operations are allowed by this cop: `+`, `*`, `**`, `<<` and `>>`.
|
15
|
+
# Although these can be rewritten in a different way, it should not be necessary to
|
16
|
+
# do so. This does not include operations such as `-` or `/` where the result will
|
17
|
+
# always be the same (`x - x` will always be 0; `x / x` will always be 1), and
|
18
|
+
# thus are legitimate offenses.
|
19
|
+
#
|
20
|
+
# @safety
|
21
|
+
# This cop is unsafe as it does not consider side effects when calling methods
|
22
|
+
# and thus can generate false positives, for example:
|
23
|
+
#
|
24
|
+
# [source,ruby]
|
25
|
+
# ----
|
16
26
|
# if wr.take_char == '\0' && wr.take_char == '\0'
|
27
|
+
# # ...
|
28
|
+
# end
|
29
|
+
# ----
|
17
30
|
#
|
18
31
|
# @example
|
19
32
|
# # bad
|
@@ -24,7 +37,7 @@ module RuboCop
|
|
24
37
|
# do_something
|
25
38
|
# end
|
26
39
|
#
|
27
|
-
# def
|
40
|
+
# def child?
|
28
41
|
# left_child || left_child
|
29
42
|
# end
|
30
43
|
#
|
@@ -6,6 +6,11 @@ module RuboCop
|
|
6
6
|
# This cop checks for `:true` and `:false` symbols.
|
7
7
|
# In most cases it would be a typo.
|
8
8
|
#
|
9
|
+
# @safety
|
10
|
+
# Autocorrection is unsafe for this cop because code relying
|
11
|
+
# on `:true` or `:false` symbols will break when those are
|
12
|
+
# changed to actual booleans.
|
13
|
+
#
|
9
14
|
# @example
|
10
15
|
#
|
11
16
|
# # bad
|
@@ -7,8 +7,8 @@ module RuboCop
|
|
7
7
|
# not be kept for production code.
|
8
8
|
#
|
9
9
|
# The cop can be configured using `DebuggerMethods`. By default, a number of gems
|
10
|
-
# debug entrypoints are configured (`Kernel`, `Byebug`, `Capybara`, `
|
11
|
-
# and `WebConsole`). Additional methods can be added.
|
10
|
+
# debug entrypoints are configured (`Kernel`, `Byebug`, `Capybara`, `debug.rb`,
|
11
|
+
# `Pry`, `Rails`, `RubyJard`, and `WebConsole`). Additional methods can be added.
|
12
12
|
#
|
13
13
|
# Specific default groups can be disabled if necessary:
|
14
14
|
#
|
@@ -57,8 +57,6 @@ module RuboCop
|
|
57
57
|
class Debugger < Base
|
58
58
|
MSG = 'Remove debugger entry point `%<source>s`.'
|
59
59
|
|
60
|
-
RESTRICT_ON_SEND = [].freeze
|
61
|
-
|
62
60
|
# @!method kernel?(node)
|
63
61
|
def_node_matcher :kernel?, <<~PATTERN
|
64
62
|
(const {nil? cbase} :Kernel)
|
@@ -58,12 +58,12 @@ module RuboCop
|
|
58
58
|
end
|
59
59
|
|
60
60
|
def to_s
|
61
|
-
[class_constant, method].compact.join(
|
61
|
+
[class_constant, method].compact.join(delimiter)
|
62
62
|
end
|
63
63
|
|
64
64
|
private
|
65
65
|
|
66
|
-
def
|
66
|
+
def delimiter
|
67
67
|
CLASS_METHOD_DELIMETER
|
68
68
|
end
|
69
69
|
end
|
@@ -81,12 +81,12 @@ module RuboCop
|
|
81
81
|
end
|
82
82
|
|
83
83
|
def to_s
|
84
|
-
[class_constant, method].compact.join(
|
84
|
+
[class_constant, method].compact.join(delimiter)
|
85
85
|
end
|
86
86
|
|
87
87
|
private
|
88
88
|
|
89
|
-
def
|
89
|
+
def delimiter
|
90
90
|
instance_method? ? INSTANCE_METHOD_DELIMETER : CLASS_METHOD_DELIMETER
|
91
91
|
end
|
92
92
|
|
@@ -42,11 +42,12 @@ module RuboCop
|
|
42
42
|
# Maybe further investigation of RuboCop AST will lead to an essential solution.
|
43
43
|
return unless node.loc
|
44
44
|
|
45
|
-
constant = node.absolute? ? constant_name(node, node.short_name
|
45
|
+
constant = node.absolute? ? constant_name(node, node.short_name) : node.source
|
46
46
|
return unless (deprecated_constant = deprecated_constants[constant])
|
47
47
|
|
48
48
|
alternative = deprecated_constant['Alternative']
|
49
49
|
version = deprecated_constant['DeprecatedVersion']
|
50
|
+
return if target_ruby_version < version.to_f
|
50
51
|
|
51
52
|
add_offense(node, message: message(alternative, node.source, version)) do |corrector|
|
52
53
|
corrector.replace(node, alternative)
|
@@ -56,7 +57,7 @@ module RuboCop
|
|
56
57
|
private
|
57
58
|
|
58
59
|
def constant_name(node, nested_constant_name)
|
59
|
-
return nested_constant_name unless node.namespace.const_type?
|
60
|
+
return nested_constant_name.to_s unless node.namespace.const_type?
|
60
61
|
|
61
62
|
constant_name(node.namespace, "#{node.namespace.short_name}::#{nested_constant_name}")
|
62
63
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Lint
|
6
|
-
# This cop checks constructors for disjunctive assignments that should
|
6
|
+
# This cop checks constructors for disjunctive assignments (`||=`) that should
|
7
7
|
# be plain assignments.
|
8
8
|
#
|
9
9
|
# So far, this cop is only concerned with disjunctive assignment of
|
@@ -12,6 +12,29 @@ module RuboCop
|
|
12
12
|
# In ruby, an instance variable is nil until a value is assigned, so the
|
13
13
|
# disjunction is unnecessary. A plain assignment has the same effect.
|
14
14
|
#
|
15
|
+
# @safety
|
16
|
+
# This cop is unsafe because it can register a false positive when a
|
17
|
+
# method is redefined in a subclass that calls super. For example:
|
18
|
+
#
|
19
|
+
# [source,ruby]
|
20
|
+
# ----
|
21
|
+
# class Base
|
22
|
+
# def initialize
|
23
|
+
# @config ||= 'base'
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# class Derived < Base
|
28
|
+
# def initialize
|
29
|
+
# @config = 'derived'
|
30
|
+
# super
|
31
|
+
# end
|
32
|
+
# end
|
33
|
+
# ----
|
34
|
+
#
|
35
|
+
# Without the disjunctive assignment, `Derived` will be unable to override
|
36
|
+
# the value for `@config`.
|
37
|
+
#
|
15
38
|
# @example
|
16
39
|
# # bad
|
17
40
|
# def initialize
|
@@ -4,7 +4,7 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module Lint
|
6
6
|
# This cop checks that there are no repeated bodies
|
7
|
-
# within `if/unless`, `case-when` and `rescue` constructs.
|
7
|
+
# within `if/unless`, `case-when`, `case-in` and `rescue` constructs.
|
8
8
|
#
|
9
9
|
# With `IgnoreLiteralBranches: true`, branches are not registered
|
10
10
|
# as offenses if they return a basic literal value (string, symbol,
|
@@ -97,6 +97,7 @@ module RuboCop
|
|
97
97
|
end
|
98
98
|
alias on_if on_branching_statement
|
99
99
|
alias on_case on_branching_statement
|
100
|
+
alias on_case_match on_branching_statement
|
100
101
|
alias on_rescue on_branching_statement
|
101
102
|
|
102
103
|
private
|
@@ -135,11 +135,14 @@ module RuboCop
|
|
135
135
|
def found_instance_method(node, name)
|
136
136
|
return unless (scope = node.parent_module_name)
|
137
137
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
138
|
+
# Humanize the scope
|
139
|
+
scope = scope.sub(
|
140
|
+
/(?:(?<name>.*)::)#<Class:\k<name>>|#<Class:(?<name>.*)>(?:::)?/,
|
141
|
+
'\k<name>.'
|
142
|
+
)
|
143
|
+
scope << '#' unless scope.end_with?('.')
|
144
|
+
|
145
|
+
found_method(node, "#{scope}#{name}")
|
143
146
|
end
|
144
147
|
|
145
148
|
def found_method(node, method_name)
|
@@ -49,6 +49,9 @@ module RuboCop
|
|
49
49
|
def on_if(node)
|
50
50
|
return if node.ternary?
|
51
51
|
|
52
|
+
# If the if is on a single line, it'll be handled by `Style/OneLineConditional`
|
53
|
+
return if node.single_line?
|
54
|
+
|
52
55
|
check(node)
|
53
56
|
end
|
54
57
|
|
@@ -66,13 +69,10 @@ module RuboCop
|
|
66
69
|
|
67
70
|
def check_else(node)
|
68
71
|
else_branch = node.else_branch
|
69
|
-
|
70
|
-
return unless else_branch.begin_type?
|
71
|
-
|
72
|
-
first_else = else_branch.children.first
|
72
|
+
first_else = else_branch.begin_type? ? else_branch.children.first : else_branch
|
73
73
|
|
74
74
|
return unless first_else
|
75
|
-
return unless first_else
|
75
|
+
return unless same_line?(first_else, node.loc.else)
|
76
76
|
|
77
77
|
add_offense(first_else) { |corrector| autocorrect(corrector, node, first_else) }
|
78
78
|
end
|
@@ -81,9 +81,13 @@ module RuboCop
|
|
81
81
|
corrector.insert_after(node.loc.else, "\n")
|
82
82
|
|
83
83
|
blank_range = range_between(node.loc.else.end_pos, first_else.loc.expression.begin_pos)
|
84
|
-
indentation = indent(node
|
84
|
+
indentation = indent(node, offset: indentation_width)
|
85
85
|
corrector.replace(blank_range, indentation)
|
86
86
|
end
|
87
|
+
|
88
|
+
def indentation_width
|
89
|
+
@config.for_cop('Layout/IndentationWidth')['Width'] || 2
|
90
|
+
end
|
87
91
|
end
|
88
92
|
end
|
89
93
|
end
|
@@ -51,7 +51,7 @@ module RuboCop
|
|
51
51
|
|
52
52
|
def on_case_match(node)
|
53
53
|
node.in_pattern_branches.each do |branch|
|
54
|
-
next if branch.body || cop_config['AllowComments'] && comment_lines?(node)
|
54
|
+
next if branch.body || (cop_config['AllowComments'] && comment_lines?(node))
|
55
55
|
|
56
56
|
add_offense(branch)
|
57
57
|
end
|
@@ -118,7 +118,7 @@ module RuboCop
|
|
118
118
|
end
|
119
119
|
|
120
120
|
def correct_arguments?(arguments)
|
121
|
-
arguments.size == 1 || arguments.size == 2 && arguments[1].hash_type?
|
121
|
+
arguments.size == 1 || (arguments.size == 2 && arguments[1].hash_type?)
|
122
122
|
end
|
123
123
|
|
124
124
|
def build_kwargs(node)
|
@@ -3,10 +3,19 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Lint
|
6
|
-
# Prefer using `Hash#compare_by_identity` than using `object_id`
|
6
|
+
# Prefer using `Hash#compare_by_identity` rather than using `object_id`
|
7
|
+
# for hash keys.
|
7
8
|
#
|
8
|
-
# This cop
|
9
|
-
#
|
9
|
+
# This cop looks for hashes being keyed by objects' `object_id`, using
|
10
|
+
# one of these methods: `key?`, `has_key?`, `fetch`, `[]` and `[]=`.
|
11
|
+
#
|
12
|
+
# @safety
|
13
|
+
# This cop is unsafe. Although unlikely, the hash could store both object
|
14
|
+
# ids and other values that need be compared by value, and thus
|
15
|
+
# could be a false positive.
|
16
|
+
#
|
17
|
+
# Furthermore, this cop cannot guarantee that the receiver of one of the
|
18
|
+
# methods (`key?`, etc.) is actually a hash.
|
10
19
|
#
|
11
20
|
# @example
|
12
21
|
# # bad
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
#
|
7
|
+
# This cop checks for `IO.select` that is incompatible with Fiber Scheduler since Ruby 3.0.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
#
|
11
|
+
# # bad
|
12
|
+
# IO.select([io], [], [], timeout)
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# io.wait_readable(timeout)
|
16
|
+
#
|
17
|
+
# # bad
|
18
|
+
# IO.select([], [io], [], timeout)
|
19
|
+
#
|
20
|
+
# # good
|
21
|
+
# io.wait_writable(timeout)
|
22
|
+
#
|
23
|
+
class IncompatibleIoSelectWithFiberScheduler < Base
|
24
|
+
extend AutoCorrector
|
25
|
+
|
26
|
+
MSG = 'Use `%<preferred>s` instead of `%<current>s`.'
|
27
|
+
RESTRICT_ON_SEND = %i[select].freeze
|
28
|
+
|
29
|
+
# @!method io_select(node)
|
30
|
+
def_node_matcher :io_select, <<~PATTERN
|
31
|
+
(send
|
32
|
+
(const {nil? cbase} :IO) :select $_ $_ {(array) nil} $...)
|
33
|
+
PATTERN
|
34
|
+
|
35
|
+
def on_send(node)
|
36
|
+
return unless (read, write, timeout = io_select(node))
|
37
|
+
return unless scheduler_compatible?(read, write) || scheduler_compatible?(write, read)
|
38
|
+
|
39
|
+
preferred = preferred_method(read, write, timeout)
|
40
|
+
message = format(MSG, preferred: preferred, current: node.source)
|
41
|
+
|
42
|
+
add_offense(node, message: message) do |corrector|
|
43
|
+
corrector.replace(node, preferred)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def scheduler_compatible?(io1, io2)
|
50
|
+
return false unless io1.array_type? && io1.values.size == 1
|
51
|
+
|
52
|
+
io2.array_type? ? io2.values.empty? : io2.nil_type?
|
53
|
+
end
|
54
|
+
|
55
|
+
def preferred_method(read, write, timeout)
|
56
|
+
timeout_argument = timeout.empty? ? '' : "(#{timeout[0].source})"
|
57
|
+
|
58
|
+
if read.array_type? && read.values[0]
|
59
|
+
"#{read.values[0].source}.wait_readable#{timeout_argument}"
|
60
|
+
else
|
61
|
+
"#{write.values[0].source}.wait_writable#{timeout_argument}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -5,6 +5,11 @@ module RuboCop
|
|
5
5
|
module Lint
|
6
6
|
# This cop checks for interpolation in a single quoted string.
|
7
7
|
#
|
8
|
+
# @safety
|
9
|
+
# This cop is generally safe, but is marked as unsafe because
|
10
|
+
# it is possible to actually intentionally have text inside
|
11
|
+
# `#{...}` in a single quoted string.
|
12
|
+
#
|
8
13
|
# @example
|
9
14
|
#
|
10
15
|
# # bad
|
@@ -5,9 +5,10 @@ module RuboCop
|
|
5
5
|
module Lint
|
6
6
|
# This cop checks for uses of `begin...end while/until something`.
|
7
7
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
# loop body
|
8
|
+
# @safety
|
9
|
+
# The cop is unsafe because behaviour can change in some cases, including
|
10
|
+
# if a local variable inside the loop body is accessed outside of it, or if the
|
11
|
+
# loop body raises a `StopIteration` exception (which `Kernel#loop` rescues).
|
11
12
|
#
|
12
13
|
# @example
|
13
14
|
#
|
@@ -14,7 +14,11 @@ module RuboCop
|
|
14
14
|
# `Dir.glob` and `Dir[]` sort globbed results by default in Ruby 3.0.
|
15
15
|
# So all bad cases are acceptable when Ruby 3.0 or higher are used.
|
16
16
|
#
|
17
|
-
# This cop will be deprecated and removed when supporting only Ruby 3.0 and higher.
|
17
|
+
# NOTE: This cop will be deprecated and removed when supporting only Ruby 3.0 and higher.
|
18
|
+
#
|
19
|
+
# @safety
|
20
|
+
# This cop is unsafe in the case where sorting files changes existing
|
21
|
+
# expected behaviour.
|
18
22
|
#
|
19
23
|
# @example
|
20
24
|
#
|
@@ -18,6 +18,11 @@ module RuboCop
|
|
18
18
|
# cop by default). Similarly, Rails' duration methods do not work well
|
19
19
|
# with `Integer()` and can be ignored with `IgnoredMethods`.
|
20
20
|
#
|
21
|
+
# @safety
|
22
|
+
# Autocorrection is unsafe because it is not guaranteed that the
|
23
|
+
# replacement `Kernel` methods are able to properly handle the
|
24
|
+
# input if it is not a standard class.
|
25
|
+
#
|
21
26
|
# @example
|
22
27
|
#
|
23
28
|
# # bad
|
@@ -60,6 +65,7 @@ module RuboCop
|
|
60
65
|
'class parsing, instead of using '\
|
61
66
|
'`%<current>s`, use stricter '\
|
62
67
|
'`%<corrected_method>s`.'
|
68
|
+
CONVERSION_METHODS = %i[Integer Float Complex to_i to_f to_c].freeze
|
63
69
|
METHODS = CONVERSION_METHOD_CLASS_MAPPING.keys.map(&:inspect).join(' ')
|
64
70
|
|
65
71
|
# @!method to_method(node)
|
@@ -127,7 +133,8 @@ module RuboCop
|
|
127
133
|
end
|
128
134
|
|
129
135
|
def ignore_receiver?(receiver)
|
130
|
-
if receiver.
|
136
|
+
if receiver.numeric_type? || (receiver.send_type? &&
|
137
|
+
(conversion_method?(receiver.method_name) || ignored_method?(receiver.method_name)))
|
131
138
|
true
|
132
139
|
elsif (receiver = top_receiver(receiver))
|
133
140
|
receiver.const_type? && ignored_class?(receiver.const_name)
|
@@ -142,6 +149,10 @@ module RuboCop
|
|
142
149
|
receiver
|
143
150
|
end
|
144
151
|
|
152
|
+
def conversion_method?(method_name)
|
153
|
+
CONVERSION_METHODS.include?(method_name)
|
154
|
+
end
|
155
|
+
|
145
156
|
def ignored_classes
|
146
157
|
cop_config.fetch('IgnoredClasses', [])
|
147
158
|
end
|
@@ -10,7 +10,7 @@ module RuboCop
|
|
10
10
|
# ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-darwin19]
|
11
11
|
# -e:1: warning: `_1' is reserved for numbered parameter; consider another name
|
12
12
|
#
|
13
|
-
#
|
13
|
+
# Assigning to a numbered parameter (from `_1` to `_9`) causes an error in Ruby 3.0.
|
14
14
|
#
|
15
15
|
# % ruby -ve '_1 = :value'
|
16
16
|
# ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin19]
|
@@ -9,8 +9,10 @@ module RuboCop
|
|
9
9
|
# should always be the same. If constants are assigned in multiple
|
10
10
|
# locations, the result may vary depending on the order of `require`.
|
11
11
|
#
|
12
|
-
#
|
13
|
-
#
|
12
|
+
# @safety
|
13
|
+
# This cop is unsafe because code that is already conditionally
|
14
|
+
# assigning a constant may have its behaviour changed by
|
15
|
+
# auto-correction.
|
14
16
|
#
|
15
17
|
# @example
|
16
18
|
#
|
@@ -6,6 +6,23 @@ module RuboCop
|
|
6
6
|
# This cops looks for references of Regexp captures that are out of range
|
7
7
|
# and thus always returns nil.
|
8
8
|
#
|
9
|
+
# @safety
|
10
|
+
# This cop is unsafe because it is naive in how it determines what
|
11
|
+
# references are available based on the last encountered regexp, but
|
12
|
+
# it cannot handle some cases, such as conditional regexp matches, which
|
13
|
+
# leads to false positives, such as:
|
14
|
+
#
|
15
|
+
# [source,ruby]
|
16
|
+
# ----
|
17
|
+
# foo ? /(c)(b)/ =~ str : /(b)/ =~ str
|
18
|
+
# do_something if $2
|
19
|
+
# # $2 is defined for the first condition but not the second, however
|
20
|
+
# # the cop will mark this as an offense.
|
21
|
+
# ----
|
22
|
+
#
|
23
|
+
# This might be a good indication of code that should be refactored,
|
24
|
+
# however.
|
25
|
+
#
|
9
26
|
# @example
|
10
27
|
#
|
11
28
|
# /(foo)bar/ =~ 'foobar'
|