rubocop 1.21.0 → 1.22.0
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 +43 -6
- data/lib/rubocop/config.rb +5 -0
- data/lib/rubocop/config_loader.rb +2 -0
- data/lib/rubocop/config_validator.rb +9 -1
- data/lib/rubocop/cop/base.rb +1 -1
- data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +34 -11
- data/lib/rubocop/cop/bundler/ordered_gems.rb +3 -12
- data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +11 -10
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +3 -12
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +1 -1
- data/lib/rubocop/cop/generator.rb +14 -8
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
- data/lib/rubocop/cop/layout/dot_position.rb +25 -2
- data/lib/rubocop/cop/layout/line_length.rb +7 -5
- data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -0
- data/lib/rubocop/cop/layout/space_inside_parens.rb +74 -24
- data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +5 -1
- data/lib/rubocop/cop/lint/ambiguous_range.rb +7 -7
- 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/deprecated_class_methods.rb +4 -4
- data/lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb +24 -1
- data/lib/rubocop/cop/lint/else_layout.rb +9 -5
- data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +12 -3
- 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 +5 -0
- 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 +49 -0
- 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/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 +3 -2
- data/lib/rubocop/cop/metrics/abc_size.rb +6 -0
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +5 -1
- data/lib/rubocop/cop/mixin/heredoc.rb +1 -3
- data/lib/rubocop/cop/mixin/ordered_gem_node.rb +9 -1
- data/lib/rubocop/cop/mixin/percent_array.rb +6 -1
- data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
- 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/and_or.rb +4 -3
- 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/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 +6 -5
- data/lib/rubocop/cop/style/combinable_loops.rb +3 -2
- data/lib/rubocop/cop/style/commented_keyword.rb +4 -1
- data/lib/rubocop/cop/style/date_time.rb +5 -0
- data/lib/rubocop/cop/style/double_negation.rb +15 -5
- data/lib/rubocop/cop/style/float_division.rb +10 -2
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +6 -1
- data/lib/rubocop/cop/style/global_std_stream.rb +4 -0
- data/lib/rubocop/cop/style/hash_each_methods.rb +5 -0
- data/lib/rubocop/cop/style/hash_transform_keys.rb +4 -6
- data/lib/rubocop/cop/style/hash_transform_values.rb +4 -6
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +18 -16
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +15 -2
- 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/line_end_concatenation.rb +13 -0
- data/lib/rubocop/cop/style/module_function.rb +8 -9
- data/lib/rubocop/cop/style/mutable_constant.rb +12 -7
- 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/preferred_hash_methods.rb +9 -4
- data/lib/rubocop/cop/style/redundant_argument.rb +14 -7
- 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 +0 -1
- 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_sort.rb +47 -29
- data/lib/rubocop/cop/style/safe_navigation.rb +13 -2
- data/lib/rubocop/cop/style/select_by_regexp.rb +106 -0
- data/lib/rubocop/cop/style/single_argument_dig.rb +5 -0
- data/lib/rubocop/cop/style/slicing_with_range.rb +13 -0
- data/lib/rubocop/cop/style/special_global_vars.rb +4 -0
- data/lib/rubocop/cop/style/static_class.rb +4 -3
- data/lib/rubocop/cop/style/string_chars.rb +4 -2
- data/lib/rubocop/cop/style/string_concatenation.rb +4 -0
- data/lib/rubocop/cop/style/string_hash_keys.rb +4 -0
- data/lib/rubocop/cop/style/struct_inheritance.rb +3 -2
- data/lib/rubocop/cop/style/swap_values.rb +4 -2
- 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/yoda_condition.rb +20 -0
- data/lib/rubocop/cop/style/zero_length_predicate.rb +6 -0
- data/lib/rubocop/cop/util.rb +2 -2
- data/lib/rubocop/cops_documentation_generator.rb +17 -5
- data/lib/rubocop/options.rb +126 -112
- data/lib/rubocop/rspec/cop_helper.rb +1 -1
- data/lib/rubocop/rspec/expect_offense.rb +6 -2
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +5 -0
- metadata +10 -5
@@ -7,26 +7,28 @@ module RuboCop
|
|
7
7
|
# each branch of a conditional expression. Such expressions should normally
|
8
8
|
# be placed outside the conditional expression - before or after it.
|
9
9
|
#
|
10
|
-
# This cop is marked unsafe auto-correction as the order of method invocations
|
11
|
-
# must be guaranteed in the following case:
|
12
|
-
#
|
13
|
-
# [source,ruby]
|
14
|
-
# ----
|
15
|
-
# if method_that_modifies_global_state # 1
|
16
|
-
# method_that_relies_on_global_state # 2
|
17
|
-
# foo # 3
|
18
|
-
# else
|
19
|
-
# method_that_relies_on_global_state # 2
|
20
|
-
# bar # 3
|
21
|
-
# end
|
22
|
-
# ----
|
23
|
-
#
|
24
|
-
# In such a case, auto-correction may change the invocation order.
|
25
|
-
#
|
26
10
|
# NOTE: The cop is poorly named and some people might think that it actually
|
27
11
|
# checks for duplicated conditional branches. The name will probably be changed
|
28
12
|
# in a future major RuboCop release.
|
29
13
|
#
|
14
|
+
# @safety
|
15
|
+
# Auto-correction is unsafe because changing the order of method invocations
|
16
|
+
# may change the behaviour of the code. For example:
|
17
|
+
#
|
18
|
+
# [source,ruby]
|
19
|
+
# ----
|
20
|
+
# if method_that_modifies_global_state # 1
|
21
|
+
# method_that_relies_on_global_state # 2
|
22
|
+
# foo # 3
|
23
|
+
# else
|
24
|
+
# method_that_relies_on_global_state # 2
|
25
|
+
# bar # 3
|
26
|
+
# end
|
27
|
+
# ----
|
28
|
+
#
|
29
|
+
# In this example, `method_that_relies_on_global_state` will be moved before
|
30
|
+
# `method_that_modifies_global_state`, which changes the behaviour of the program.
|
31
|
+
#
|
30
32
|
# @example
|
31
33
|
# # bad
|
32
34
|
# if condition
|
@@ -6,8 +6,10 @@ module RuboCop
|
|
6
6
|
# This cop checks for redundant `if` with boolean literal branches.
|
7
7
|
# It checks only conditions to return boolean value (`true` or `false`) for safe detection.
|
8
8
|
# The conditions to be checked are comparison methods, predicate methods, and double negative.
|
9
|
-
#
|
10
|
-
#
|
9
|
+
#
|
10
|
+
# @safety
|
11
|
+
# Auto-correction is unsafe because there is no guarantee that all predicate methods
|
12
|
+
# will return a boolean value. Those methods can be allowed with `AllowedMethods` config.
|
11
13
|
#
|
12
14
|
# @example
|
13
15
|
# # bad
|
@@ -23,6 +25,17 @@ module RuboCop
|
|
23
25
|
# # good
|
24
26
|
# foo == bar
|
25
27
|
#
|
28
|
+
# @example
|
29
|
+
# # bad
|
30
|
+
# if foo.do_something?
|
31
|
+
# true
|
32
|
+
# else
|
33
|
+
# false
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# # good (but potentially an unsafe correction)
|
37
|
+
# foo.do_something?
|
38
|
+
#
|
26
39
|
# @example AllowedMethods: ['nonzero?']
|
27
40
|
# # good
|
28
41
|
# num.nonzero? ? true : false
|
@@ -5,9 +5,10 @@ module RuboCop
|
|
5
5
|
module Style
|
6
6
|
# Use `Kernel#loop` for infinite loops.
|
7
7
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
8
|
+
# @safety
|
9
|
+
# This cop is unsafe as the rule should not necessarily apply if the loop
|
10
|
+
# body might raise a `StopIteration` exception; contrary to other infinite
|
11
|
+
# loops, `Kernel#loop` silently rescues that and returns `nil`.
|
11
12
|
#
|
12
13
|
# @example
|
13
14
|
# # bad
|
@@ -5,11 +5,18 @@ module RuboCop
|
|
5
5
|
module Style
|
6
6
|
# This cop check for usages of not (`not` or `!`) called on a method
|
7
7
|
# when an inverse of that method can be used instead.
|
8
|
+
#
|
8
9
|
# Methods that can be inverted by a not (`not` or `!`) should be defined
|
9
|
-
# in `InverseMethods
|
10
|
+
# in `InverseMethods`.
|
11
|
+
#
|
10
12
|
# Methods that are inverted by inverting the return
|
11
13
|
# of the block that is passed to the method should be defined in
|
12
|
-
# `InverseBlocks
|
14
|
+
# `InverseBlocks`.
|
15
|
+
#
|
16
|
+
# @safety
|
17
|
+
# This cop is unsafe because it cannot be guaranteed that the method
|
18
|
+
# and its inverse method are both defined on receiver, and also are
|
19
|
+
# actually inverse of each other.
|
13
20
|
#
|
14
21
|
# @example
|
15
22
|
# # bad
|
@@ -6,6 +6,19 @@ module RuboCop
|
|
6
6
|
# This cop checks for string literal concatenation at
|
7
7
|
# the end of a line.
|
8
8
|
#
|
9
|
+
# @safety
|
10
|
+
# This cop is unsafe because it cannot be guaranteed that the
|
11
|
+
# receiver is a string, in which case replacing `<<` with `\`
|
12
|
+
# would result in a syntax error.
|
13
|
+
#
|
14
|
+
# For example, this would be a false positive:
|
15
|
+
# [source,ruby]
|
16
|
+
# ----
|
17
|
+
# array << 'foo' <<
|
18
|
+
# 'bar' <<
|
19
|
+
# 'baz'
|
20
|
+
# ----
|
21
|
+
#
|
9
22
|
# @example
|
10
23
|
#
|
11
24
|
# # bad
|
@@ -6,7 +6,14 @@ module RuboCop
|
|
6
6
|
# This cop checks for use of `extend self` or `module_function` in a
|
7
7
|
# module.
|
8
8
|
#
|
9
|
-
# Supported styles are: module_function, extend_self, forbidden.
|
9
|
+
# Supported styles are: module_function, extend_self, forbidden. `forbidden`
|
10
|
+
# style prohibits the usage of both styles.
|
11
|
+
#
|
12
|
+
# NOTE: the cop won't be activated when the module contains any private methods.
|
13
|
+
#
|
14
|
+
# @safety
|
15
|
+
# Autocorrection is unsafe (and is disabled by default) because `extend self`
|
16
|
+
# and `module_function` do not behave exactly the same.
|
10
17
|
#
|
11
18
|
# @example EnforcedStyle: module_function (default)
|
12
19
|
# # bad
|
@@ -21,9 +28,6 @@ module RuboCop
|
|
21
28
|
# # ...
|
22
29
|
# end
|
23
30
|
#
|
24
|
-
# In case there are private methods, the cop won't be activated.
|
25
|
-
# Otherwise, it forces to change the flow of the default code.
|
26
|
-
#
|
27
31
|
# @example EnforcedStyle: module_function (default)
|
28
32
|
# # good
|
29
33
|
# module Test
|
@@ -46,8 +50,6 @@ module RuboCop
|
|
46
50
|
# # ...
|
47
51
|
# end
|
48
52
|
#
|
49
|
-
# The option `forbidden` prohibits the usage of both styles.
|
50
|
-
#
|
51
53
|
# @example EnforcedStyle: forbidden
|
52
54
|
# # bad
|
53
55
|
# module Test
|
@@ -68,9 +70,6 @@ module RuboCop
|
|
68
70
|
# private
|
69
71
|
# # ...
|
70
72
|
# end
|
71
|
-
#
|
72
|
-
# These offenses are not safe to auto-correct since there are different
|
73
|
-
# implications to each approach.
|
74
73
|
class ModuleFunction < Base
|
75
74
|
include ConfigurableEnforcedStyle
|
76
75
|
extend AutoCorrector
|
@@ -21,8 +21,17 @@ module RuboCop
|
|
21
21
|
#
|
22
22
|
# NOTE: Regexp and Range literals are frozen objects since Ruby 3.0.
|
23
23
|
#
|
24
|
-
# NOTE: From Ruby 3.0,
|
25
|
-
#
|
24
|
+
# NOTE: From Ruby 3.0, interpolated strings are not frozen when
|
25
|
+
# `# frozen-string-literal: true` is used, so this cop enforces explicit
|
26
|
+
# freezing for such strings.
|
27
|
+
#
|
28
|
+
# NOTE: From Ruby 3.0, this cop allows explicit freezing of constants when
|
29
|
+
# the `shareable_constant_value` directive is used.
|
30
|
+
#
|
31
|
+
# @safety
|
32
|
+
# This cop's autocorrection is unsafe since any mutations on objects that
|
33
|
+
# are made frozen will change from being accepted to raising `FrozenError`,
|
34
|
+
# and will need to be manually refactored.
|
26
35
|
#
|
27
36
|
# @example EnforcedStyle: literals (default)
|
28
37
|
# # bad
|
@@ -71,10 +80,6 @@ module RuboCop
|
|
71
80
|
# # shareable_constant_value: literal
|
72
81
|
# CONST = [1, 2, 3]
|
73
82
|
#
|
74
|
-
# NOTE: This special directive helps to create constants
|
75
|
-
# that hold only immutable objects, or Ractor-shareable
|
76
|
-
# constants. - ruby docs
|
77
|
-
#
|
78
83
|
class MutableConstant < Base
|
79
84
|
# Handles magic comment shareable_constant_value with O(n ^ 2) complexity
|
80
85
|
# n - number of lines in the source
|
@@ -93,7 +98,7 @@ module RuboCop
|
|
93
98
|
end
|
94
99
|
|
95
100
|
# Identifies the most recent magic comment with valid shareable constant values
|
96
|
-
#
|
101
|
+
# that's in scope for this node
|
97
102
|
def magic_comment_in_scope(node)
|
98
103
|
processed_source_till_node(node).reverse_each.find do |line|
|
99
104
|
MagicComment.parse(line).valid_shareable_constant_value?
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# This cop checks for numbered parameters.
|
7
|
+
#
|
8
|
+
# It can either restrict the use of numbered parameters to
|
9
|
+
# single-lined blocks, or disallow completely numbered parameters.
|
10
|
+
#
|
11
|
+
# @example EnforcedStyle: allow_single_line (default)
|
12
|
+
# # bad
|
13
|
+
# collection.each do
|
14
|
+
# puts _1
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# # good
|
18
|
+
# collection.each { puts _1 }
|
19
|
+
#
|
20
|
+
# @example EnforcedStyle: disallow
|
21
|
+
# # bad
|
22
|
+
# collection.each { puts _1 }
|
23
|
+
#
|
24
|
+
# # good
|
25
|
+
# collection.each { |item| puts item }
|
26
|
+
#
|
27
|
+
class NumberedParameters < Base
|
28
|
+
include ConfigurableEnforcedStyle
|
29
|
+
extend TargetRubyVersion
|
30
|
+
|
31
|
+
MSG_DISALLOW = 'Avoid using numbered parameters.'
|
32
|
+
MSG_MULTI_LINE = 'Avoid using numbered parameters for multi-line blocks.'
|
33
|
+
|
34
|
+
minimum_target_ruby_version 2.7
|
35
|
+
|
36
|
+
def on_numblock(node)
|
37
|
+
if style == :disallow
|
38
|
+
add_offense(node, message: MSG_DISALLOW)
|
39
|
+
elsif node.multiline?
|
40
|
+
add_offense(node, message: MSG_MULTI_LINE)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# This cop detects use of an excessive amount of numbered parameters in a
|
7
|
+
# single block. Having too many numbered parameters can make code too
|
8
|
+
# cryptic and hard to read.
|
9
|
+
#
|
10
|
+
# The cop defaults to registering an offense if there is more than 1 numbered
|
11
|
+
# parameter but this maximum can be configured by setting `Max`.
|
12
|
+
#
|
13
|
+
# @example Max: 1 (default)
|
14
|
+
# # bad
|
15
|
+
# foo { _1.call(_2, _3, _4) }
|
16
|
+
#
|
17
|
+
# # good
|
18
|
+
# foo { do_something(_1) }
|
19
|
+
class NumberedParametersLimit < Base
|
20
|
+
extend TargetRubyVersion
|
21
|
+
extend ExcludeLimit
|
22
|
+
|
23
|
+
DEFAULT_MAX_VALUE = 1
|
24
|
+
|
25
|
+
minimum_target_ruby_version 2.7
|
26
|
+
exclude_limit 'Max'
|
27
|
+
|
28
|
+
MSG = 'Avoid using more than %<max>i numbered %<parameter>s; %<count>i detected.'
|
29
|
+
|
30
|
+
def on_numblock(node)
|
31
|
+
_send_node, param_count, * = *node
|
32
|
+
return if param_count <= max_count
|
33
|
+
|
34
|
+
parameter = max_count > 1 ? 'parameters' : 'parameter'
|
35
|
+
message = format(MSG, max: max_count, parameter: parameter, count: param_count)
|
36
|
+
add_offense(node, message: message) { self.max = param_count }
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def max_count
|
42
|
+
max = cop_config.fetch('Max', DEFAULT_MAX_VALUE)
|
43
|
+
|
44
|
+
# Ruby does not allow more than 9 numbered parameters
|
45
|
+
[max, 9].min
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -58,18 +58,17 @@ module RuboCop
|
|
58
58
|
|
59
59
|
case int
|
60
60
|
when /^\d+$/
|
61
|
-
|
62
|
-
|
63
|
-
register_offense(node)
|
61
|
+
register_offense(node) { self.min_digits = int.size + 1 }
|
64
62
|
when /\d{4}/, short_group_regex
|
65
|
-
|
66
|
-
|
67
|
-
register_offense(node)
|
63
|
+
register_offense(node) { self.config_to_allow_offenses = { 'Enabled' => false } }
|
68
64
|
end
|
69
65
|
end
|
70
66
|
|
71
|
-
def register_offense(node)
|
72
|
-
add_offense(node)
|
67
|
+
def register_offense(node, &_block)
|
68
|
+
add_offense(node) do |corrector|
|
69
|
+
yield
|
70
|
+
corrector.replace(node, format_number(node))
|
71
|
+
end
|
73
72
|
end
|
74
73
|
|
75
74
|
def short_group_regex
|
@@ -16,6 +16,11 @@ module RuboCop
|
|
16
16
|
# populated with objects which can be compared with integers, but are
|
17
17
|
# not themselves `Integer` polymorphic.
|
18
18
|
#
|
19
|
+
# @safety
|
20
|
+
# This cop is unsafe because it cannot be guaranteed that the receiver
|
21
|
+
# defines the predicates or can be compared to a number, which may lead
|
22
|
+
# to a false positive for non-standard classes.
|
23
|
+
#
|
19
24
|
# @example EnforcedStyle: predicate (default)
|
20
25
|
# # bad
|
21
26
|
#
|
@@ -6,6 +6,10 @@ module RuboCop
|
|
6
6
|
# This cop checks for optional arguments to methods
|
7
7
|
# that do not come at the end of the argument list.
|
8
8
|
#
|
9
|
+
# @safety
|
10
|
+
# This cop is unsafe because changing a method signature will
|
11
|
+
# implicitly change behaviour.
|
12
|
+
#
|
9
13
|
# @example
|
10
14
|
# # bad
|
11
15
|
# def foo(a = 1, b, c)
|
@@ -7,6 +7,10 @@ module RuboCop
|
|
7
7
|
# boolean arguments when defining methods. `respond_to_missing?` method is allowed by default.
|
8
8
|
# These are customizable with `AllowedMethods` option.
|
9
9
|
#
|
10
|
+
# @safety
|
11
|
+
# This cop is unsafe because changing a method signature will
|
12
|
+
# implicitly change behaviour.
|
13
|
+
#
|
10
14
|
# @example
|
11
15
|
# # bad
|
12
16
|
# def some_method(bar = false)
|
@@ -33,8 +37,8 @@ module RuboCop
|
|
33
37
|
class OptionalBooleanParameter < Base
|
34
38
|
include AllowedMethods
|
35
39
|
|
36
|
-
MSG = '
|
37
|
-
|
40
|
+
MSG = 'Prefer keyword arguments for arguments with a boolean default value; ' \
|
41
|
+
'use `%<replacement>s` instead of `%<original>s`.'
|
38
42
|
|
39
43
|
def on_def(node)
|
40
44
|
return if allowed_method?(node.method_name)
|
@@ -42,11 +46,17 @@ module RuboCop
|
|
42
46
|
node.arguments.each do |arg|
|
43
47
|
next unless arg.optarg_type?
|
44
48
|
|
45
|
-
|
46
|
-
add_offense(arg) if BOOLEAN_TYPES.include?(value.type)
|
49
|
+
add_offense(arg, message: format_message(arg)) if arg.default_value.boolean_type?
|
47
50
|
end
|
48
51
|
end
|
49
52
|
alias on_defs on_def
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def format_message(argument)
|
57
|
+
source = argument.source
|
58
|
+
format(MSG, original: source, replacement: source.sub(/\s+=/, ':'))
|
59
|
+
end
|
50
60
|
end
|
51
61
|
end
|
52
62
|
end
|
@@ -3,10 +3,15 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
# This cop
|
7
|
-
# Hash#has_value
|
8
|
-
#
|
9
|
-
# names
|
6
|
+
# This cop checks for uses of methods `Hash#has_key?` and
|
7
|
+
# `Hash#has_value?`, and suggests using `Hash#key?` and `Hash#value?` instead.
|
8
|
+
#
|
9
|
+
# It is configurable to enforce the verbose method names, by using the
|
10
|
+
# `EnforcedStyle: verbose` configuration.
|
11
|
+
#
|
12
|
+
# @safety
|
13
|
+
# This cop is unsafe because it cannot be guaranteed that the receiver
|
14
|
+
# is a `Hash` or responds to the replacement methods.
|
10
15
|
#
|
11
16
|
# @example EnforcedStyle: short (default)
|
12
17
|
# # bad
|
@@ -5,22 +5,29 @@ module RuboCop
|
|
5
5
|
module Style
|
6
6
|
# This cop checks for a redundant argument passed to certain methods.
|
7
7
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
# 1. This cop matches for method names only and hence cannot tell apart
|
11
|
-
# methods with same name in different classes.
|
12
|
-
# 2. This cop is limited to methods with single parameter.
|
13
|
-
# 3. This cop is unsafe if certain special global variables (e.g. `$;`, `$/`) are set.
|
14
|
-
# That depends on the nature of the target methods, of course.
|
8
|
+
# NOTE: This cop is limited to methods with single parameter.
|
15
9
|
#
|
16
10
|
# Method names and their redundant arguments can be configured like this:
|
17
11
|
#
|
12
|
+
# [source,yaml]
|
13
|
+
# ----
|
18
14
|
# Methods:
|
19
15
|
# join: ''
|
20
16
|
# split: ' '
|
21
17
|
# chomp: "\n"
|
22
18
|
# chomp!: "\n"
|
23
19
|
# foo: 2
|
20
|
+
# ----
|
21
|
+
#
|
22
|
+
# @safety
|
23
|
+
# This cop is unsafe because of the following limitations:
|
24
|
+
#
|
25
|
+
# 1. This cop matches by method names only and hence cannot tell apart
|
26
|
+
# methods with same name in different classes.
|
27
|
+
# 2. This cop may be unsafe if certain special global variables (e.g. `$;`, `$/`) are set.
|
28
|
+
# That depends on the nature of the target methods, of course. For example, the default
|
29
|
+
# argument to join is `$OUTPUT_FIELD_SEPARATOR` (or `$,`) rather than `''`, and if that
|
30
|
+
# global is changed, `''` is no longer a redundant argument.
|
24
31
|
#
|
25
32
|
# @example
|
26
33
|
# # bad
|
@@ -9,6 +9,10 @@ module RuboCop
|
|
9
9
|
# In such cases `fetch(key, value)` method is faster
|
10
10
|
# than `fetch(key) { value }`.
|
11
11
|
#
|
12
|
+
# @safety
|
13
|
+
# This cop is unsafe because it cannot be guaranteed that the receiver
|
14
|
+
# does not have a different implementation of `fetch`.
|
15
|
+
#
|
12
16
|
# @example SafeForConstants: false (default)
|
13
17
|
# # bad
|
14
18
|
# hash.fetch(:key) { 5 }
|
@@ -25,6 +25,7 @@ module RuboCop
|
|
25
25
|
# require_relative '../foo.so'
|
26
26
|
#
|
27
27
|
class RedundantFileExtensionInRequire < Base
|
28
|
+
include RangeHelp
|
28
29
|
extend AutoCorrector
|
29
30
|
|
30
31
|
MSG = 'Redundant `.rb` file extension detected.'
|
@@ -39,13 +40,21 @@ module RuboCop
|
|
39
40
|
require_call?(node) do |name_node|
|
40
41
|
return unless name_node.value.end_with?('.rb')
|
41
42
|
|
42
|
-
|
43
|
-
correction = name_node.value.delete_suffix('.rb')
|
43
|
+
extension_range = extension_range(name_node)
|
44
44
|
|
45
|
-
|
45
|
+
add_offense(extension_range) do |corrector|
|
46
|
+
corrector.remove(extension_range)
|
46
47
|
end
|
47
48
|
end
|
48
49
|
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def extension_range(name_node)
|
54
|
+
end_of_path_string = name_node.source_range.end_pos
|
55
|
+
|
56
|
+
range_between(end_of_path_string - 4, end_of_path_string - 1)
|
57
|
+
end
|
49
58
|
end
|
50
59
|
end
|
51
60
|
end
|
@@ -59,7 +59,6 @@ module RuboCop
|
|
59
59
|
(begin (send {float int} {:+ :- :* :** :/ :% :<<} _))
|
60
60
|
(begin (send !{(str _) array} {:+ :- :* :** :/ :%} {float int}))
|
61
61
|
(begin (send _ {:== :=== :!= :<= :>= :< :>} _))
|
62
|
-
(send (const {nil? cbase} :ENV) :[] _)
|
63
62
|
(send _ {:count :length :size} ...)
|
64
63
|
(block (send _ {:count :length :size} ...) ...)
|
65
64
|
}
|
@@ -100,6 +100,10 @@ module RuboCop
|
|
100
100
|
add_lhs_to_local_variables_scopes(rhs, lhs)
|
101
101
|
end
|
102
102
|
|
103
|
+
def on_in_pattern(node)
|
104
|
+
add_match_var_scopes(node)
|
105
|
+
end
|
106
|
+
|
103
107
|
def on_send(node)
|
104
108
|
return unless node.self_receiver? && regular_method_call?(node)
|
105
109
|
return if node.parent&.mlhs_type?
|
@@ -185,6 +189,12 @@ module RuboCop
|
|
185
189
|
add_lhs_to_local_variables_scopes(rhs, child.to_a.first)
|
186
190
|
end
|
187
191
|
end
|
192
|
+
|
193
|
+
def add_match_var_scopes(in_pattern_node)
|
194
|
+
in_pattern_node.each_descendant(:match_var) do |match_var_node|
|
195
|
+
@local_variables_scopes[in_pattern_node] << match_var_node.children.first
|
196
|
+
end
|
197
|
+
end
|
188
198
|
end
|
189
199
|
end
|
190
200
|
end
|
@@ -6,9 +6,10 @@ module RuboCop
|
|
6
6
|
# This cop checks for places where redundant assignments are made for in place
|
7
7
|
# modification methods.
|
8
8
|
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
9
|
+
# @safety
|
10
|
+
# This cop is unsafe, because it can produce false positives for
|
11
|
+
# user defined methods having one of the expected names, but not modifying
|
12
|
+
# its receiver in place.
|
12
13
|
#
|
13
14
|
# @example
|
14
15
|
# # bad
|
@@ -12,6 +12,33 @@ module RuboCop
|
|
12
12
|
# `Enumerable#max_by` can replace `Enumerable#sort_by` calls
|
13
13
|
# after which only the first or last element is used.
|
14
14
|
#
|
15
|
+
# @safety
|
16
|
+
# This cop is unsafe, because `sort...last` and `max` may not return the
|
17
|
+
# same element in all cases.
|
18
|
+
#
|
19
|
+
# In an enumerable where there are multiple elements where `a <=> b == 0`,
|
20
|
+
# or where the transformation done by the `sort_by` block has the
|
21
|
+
# same result, `sort.last` and `max` (or `sort_by.last` and `max_by`)
|
22
|
+
# will return different elements. `sort.last` will return the last
|
23
|
+
# element but `max` will return the first element.
|
24
|
+
#
|
25
|
+
# For example:
|
26
|
+
#
|
27
|
+
# [source,ruby]
|
28
|
+
# ----
|
29
|
+
# class MyString < String; end
|
30
|
+
# strings = [MyString.new('test'), 'test']
|
31
|
+
# strings.sort.last.class #=> String
|
32
|
+
# strings.max.class #=> MyString
|
33
|
+
# ----
|
34
|
+
#
|
35
|
+
# [source,ruby]
|
36
|
+
# ----
|
37
|
+
# words = %w(dog horse mouse)
|
38
|
+
# words.sort_by { |word| word.length }.last #=> 'mouse'
|
39
|
+
# words.max_by { |word| word.length } #=> 'horse'
|
40
|
+
# ----
|
41
|
+
#
|
15
42
|
# @example
|
16
43
|
# # bad
|
17
44
|
# [2, 1, 3].sort.first
|
@@ -75,48 +102,39 @@ module RuboCop
|
|
75
102
|
MATCHER
|
76
103
|
|
77
104
|
def on_send(node)
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
ancestor = node.parent
|
82
|
-
elsif (sort_node, sorter, accessor = redundant_sort?(node.parent&.parent))
|
83
|
-
return if use_size_method_in_block?(sort_node)
|
84
|
-
|
85
|
-
ancestor = node.parent.parent
|
86
|
-
else
|
87
|
-
return
|
88
|
-
end
|
105
|
+
ancestor, sort_node, sorter, accessor =
|
106
|
+
find_redundant_sort(node.parent, node.parent&.parent)
|
107
|
+
return unless ancestor
|
89
108
|
|
90
109
|
register_offense(ancestor, sort_node, sorter, accessor)
|
91
110
|
end
|
92
111
|
|
93
112
|
private
|
94
113
|
|
95
|
-
def
|
96
|
-
|
97
|
-
|
114
|
+
def find_redundant_sort(*nodes)
|
115
|
+
nodes.each do |node|
|
116
|
+
if (sort_node, sorter, accessor = redundant_sort?(node))
|
117
|
+
return [node, sort_node, sorter, accessor]
|
118
|
+
end
|
119
|
+
end
|
98
120
|
|
99
|
-
|
121
|
+
nil
|
100
122
|
end
|
101
123
|
|
102
|
-
def register_offense(
|
103
|
-
message = message(
|
124
|
+
def register_offense(node, sort_node, sorter, accessor)
|
125
|
+
message = message(node, sorter, accessor)
|
104
126
|
|
105
|
-
add_offense(offense_range(sort_node,
|
106
|
-
|
107
|
-
|
108
|
-
end
|
109
|
-
|
110
|
-
def autocorrect(corrector, node, sort_node, sorter, accessor)
|
111
|
-
# Remove accessor, e.g. `first` or `[-1]`.
|
112
|
-
corrector.remove(range_between(accessor_start(node), node.loc.expression.end_pos))
|
127
|
+
add_offense(offense_range(sort_node, node), message: message) do |corrector|
|
128
|
+
# Remove accessor, e.g. `first` or `[-1]`.
|
129
|
+
corrector.remove(range_between(accessor_start(node), node.loc.expression.end_pos))
|
113
130
|
|
114
|
-
|
115
|
-
|
131
|
+
# Replace "sort" or "sort_by" with the appropriate min/max method.
|
132
|
+
corrector.replace(sort_node.loc.selector, suggestion(sorter, accessor, arg_value(node)))
|
133
|
+
end
|
116
134
|
end
|
117
135
|
|
118
|
-
def offense_range(sort_node,
|
119
|
-
range_between(sort_node.loc.selector.begin_pos,
|
136
|
+
def offense_range(sort_node, node)
|
137
|
+
range_between(sort_node.loc.selector.begin_pos, node.loc.expression.end_pos)
|
120
138
|
end
|
121
139
|
|
122
140
|
def message(node, sorter, accessor)
|