rubocop 1.32.0 → 1.35.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/README.md +2 -2
- data/config/default.yml +73 -16
- data/config/obsoletion.yml +23 -1
- data/lib/rubocop/cache_config.rb +29 -0
- data/lib/rubocop/cli/command/{auto_genenerate_config.rb → auto_generate_config.rb} +2 -2
- data/lib/rubocop/cli/command/init_dotfile.rb +1 -1
- data/lib/rubocop/cli/command/suggest_extensions.rb +53 -15
- data/lib/rubocop/config.rb +1 -1
- data/lib/rubocop/config_finder.rb +68 -0
- data/lib/rubocop/config_loader.rb +12 -40
- data/lib/rubocop/config_loader_resolver.rb +1 -5
- data/lib/rubocop/config_obsoletion/changed_parameter.rb +5 -0
- data/lib/rubocop/config_obsoletion/parameter_rule.rb +4 -0
- data/lib/rubocop/config_obsoletion.rb +7 -2
- data/lib/rubocop/cop/cop.rb +1 -1
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +58 -0
- data/lib/rubocop/cop/gemspec/require_mfa.rb +1 -1
- data/lib/rubocop/cop/generator/require_file_injector.rb +2 -2
- data/lib/rubocop/cop/internal_affairs/numblock_handler.rb +69 -0
- data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +62 -0
- data/lib/rubocop/cop/internal_affairs.rb +2 -0
- data/lib/rubocop/cop/layout/block_alignment.rb +2 -0
- data/lib/rubocop/cop/layout/block_end_newline.rb +35 -5
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +5 -2
- data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +2 -0
- data/lib/rubocop/cop/layout/end_of_line.rb +4 -4
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +6 -1
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/indentation_width.rb +2 -0
- data/lib/rubocop/cop/layout/line_length.rb +4 -1
- data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +2 -0
- data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +2 -0
- data/lib/rubocop/cop/legacy/corrections_proxy.rb +1 -1
- data/lib/rubocop/cop/legacy/corrector.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +21 -8
- data/lib/rubocop/cop/lint/debugger.rb +26 -16
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +4 -4
- data/lib/rubocop/cop/lint/empty_block.rb +1 -1
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +65 -1
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +9 -9
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +4 -0
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +25 -6
- data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +6 -6
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +12 -0
- data/lib/rubocop/cop/lint/number_conversion.rb +24 -8
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +9 -3
- data/lib/rubocop/cop/lint/redundant_with_index.rb +13 -10
- data/lib/rubocop/cop/lint/redundant_with_object.rb +12 -11
- data/lib/rubocop/cop/lint/shadowed_exception.rb +15 -0
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +10 -1
- data/lib/rubocop/cop/lint/unreachable_loop.rb +7 -1
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +6 -4
- data/lib/rubocop/cop/lint/void.rb +2 -0
- data/lib/rubocop/cop/metrics/abc_size.rb +3 -1
- data/lib/rubocop/cop/metrics/block_length.rb +6 -7
- data/lib/rubocop/cop/metrics/method_length.rb +8 -8
- data/lib/rubocop/cop/mixin/allowed_methods.rb +15 -1
- data/lib/rubocop/cop/mixin/allowed_pattern.rb +9 -1
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
- data/lib/rubocop/cop/mixin/comments_help.rb +5 -1
- data/lib/rubocop/cop/mixin/enforce_superclass.rb +2 -1
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +76 -1
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +1 -1
- data/lib/rubocop/cop/mixin/method_complexity.rb +8 -13
- data/lib/rubocop/cop/mixin/multiline_element_indentation.rb +1 -1
- data/lib/rubocop/cop/mixin/range_help.rb +4 -5
- data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
- data/lib/rubocop/cop/naming/constant_name.rb +2 -2
- data/lib/rubocop/cop/naming/predicate_name.rb +24 -3
- data/lib/rubocop/cop/style/arguments_forwarding.rb +2 -2
- data/lib/rubocop/cop/style/block_delimiters.rb +26 -7
- data/lib/rubocop/cop/style/class_and_module_children.rb +4 -4
- data/lib/rubocop/cop/style/class_equality_comparison.rb +32 -7
- data/lib/rubocop/cop/style/class_methods_definitions.rb +2 -1
- data/lib/rubocop/cop/style/collection_methods.rb +2 -0
- data/lib/rubocop/cop/style/combinable_loops.rb +3 -1
- data/lib/rubocop/cop/style/double_negation.rb +2 -0
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
- data/lib/rubocop/cop/style/each_with_object.rb +39 -8
- data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
- data/lib/rubocop/cop/style/empty_heredoc.rb +15 -1
- data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
- data/lib/rubocop/cop/style/for.rb +2 -0
- data/lib/rubocop/cop/style/format_string_token.rb +21 -8
- data/lib/rubocop/cop/style/guard_clause.rb +27 -16
- data/lib/rubocop/cop/style/hash_each_methods.rb +3 -1
- data/lib/rubocop/cop/style/hash_except.rb +0 -4
- data/lib/rubocop/cop/style/hash_syntax.rb +17 -0
- data/lib/rubocop/cop/style/if_unless_modifier.rb +1 -1
- data/lib/rubocop/cop/style/inverse_methods.rb +8 -6
- data/lib/rubocop/cop/style/magic_comment_format.rb +307 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +2 -2
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +5 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +7 -7
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +11 -6
- data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +4 -1
- data/lib/rubocop/cop/style/multiline_block_chain.rb +3 -1
- data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +1 -1
- data/lib/rubocop/cop/style/next.rb +3 -5
- data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
- data/lib/rubocop/cop/style/numeric_literals.rb +16 -1
- data/lib/rubocop/cop/style/numeric_predicate.rb +28 -8
- data/lib/rubocop/cop/style/object_then.rb +2 -0
- data/lib/rubocop/cop/style/proc.rb +4 -1
- data/lib/rubocop/cop/style/redundant_begin.rb +2 -0
- data/lib/rubocop/cop/style/redundant_condition.rb +19 -4
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +15 -22
- data/lib/rubocop/cop/style/redundant_self.rb +2 -0
- data/lib/rubocop/cop/style/redundant_sort.rb +21 -6
- data/lib/rubocop/cop/style/redundant_sort_by.rb +24 -8
- data/lib/rubocop/cop/style/safe_navigation.rb +4 -2
- data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +14 -5
- data/lib/rubocop/cop/style/symbol_array.rb +1 -1
- data/lib/rubocop/cop/style/symbol_proc.rb +34 -9
- data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -13
- data/lib/rubocop/cop/style/top_level_method_definition.rb +3 -1
- data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
- data/lib/rubocop/cop/style/word_array.rb +1 -1
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/ext/range.rb +15 -0
- data/lib/rubocop/feature_loader.rb +94 -0
- data/lib/rubocop/formatter/clang_style_formatter.rb +1 -1
- data/lib/rubocop/formatter/disabled_config_formatter.rb +1 -1
- data/lib/rubocop/formatter/html_formatter.rb +3 -3
- data/lib/rubocop/formatter/markdown_formatter.rb +1 -1
- data/lib/rubocop/formatter/tap_formatter.rb +1 -1
- data/lib/rubocop/result_cache.rb +22 -20
- data/lib/rubocop/server/cache.rb +36 -1
- data/lib/rubocop/server/cli.rb +19 -2
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +5 -3
- metadata +15 -9
- data/lib/rubocop/cop/mixin/ignored_methods.rb +0 -52
@@ -130,7 +130,7 @@ module RuboCop
|
|
130
130
|
call_as_argument_or_chain?(node) ||
|
131
131
|
hash_literal_in_arguments?(node) ||
|
132
132
|
node.descendants.any? do |n|
|
133
|
-
n.forwarded_args_type? ||
|
133
|
+
n.forwarded_args_type? || ambiguous_literal?(n) || logical_operator?(n) ||
|
134
134
|
call_with_braced_block?(n)
|
135
135
|
end
|
136
136
|
end
|
@@ -166,7 +166,7 @@ module RuboCop
|
|
166
166
|
previous.parenthesized? || allowed_chained_call_with_parentheses?(previous)
|
167
167
|
end
|
168
168
|
|
169
|
-
def
|
169
|
+
def ambiguous_literal?(node)
|
170
170
|
splat?(node) || ternary_if?(node) || regexp_slash_literal?(node) || unary_literal?(node)
|
171
171
|
end
|
172
172
|
|
@@ -12,7 +12,7 @@ module RuboCop
|
|
12
12
|
private
|
13
13
|
|
14
14
|
def require_parentheses(node)
|
15
|
-
return if
|
15
|
+
return if allowed_method_name?(node.method_name)
|
16
16
|
return if matches_allowed_pattern?(node.method_name)
|
17
17
|
return if eligible_for_parentheses_omission?(node)
|
18
18
|
return unless node.arguments? && !node.parenthesized?
|
@@ -24,6 +24,10 @@ module RuboCop
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
+
def allowed_method_name?(name)
|
28
|
+
allowed_method?(name) || matches_allowed_pattern?(name)
|
29
|
+
end
|
30
|
+
|
27
31
|
def eligible_for_parentheses_omission?(node)
|
28
32
|
node.operator_method? || node.setter_method? || ignored_macro?(node)
|
29
33
|
end
|
@@ -6,8 +6,8 @@ module RuboCop
|
|
6
6
|
# Enforces the presence (default) or absence of parentheses in
|
7
7
|
# method calls containing parameters.
|
8
8
|
#
|
9
|
-
# In the default style (require_parentheses), macro methods are
|
10
|
-
# Additional methods can be added to the `
|
9
|
+
# In the default style (require_parentheses), macro methods are allowed.
|
10
|
+
# Additional methods can be added to the `AllowedMethods`
|
11
11
|
# or `AllowedPatterns` list. These options are
|
12
12
|
# valid only in the default style. Macros can be included by
|
13
13
|
# either setting `IgnoreMacros` to false or adding specific macros to
|
@@ -15,13 +15,13 @@ module RuboCop
|
|
15
15
|
#
|
16
16
|
# Precedence of options is all follows:
|
17
17
|
#
|
18
|
-
# 1. `
|
18
|
+
# 1. `AllowedMethods`
|
19
19
|
# 2. `AllowedPatterns`
|
20
20
|
# 3. `IncludedMacros`
|
21
21
|
#
|
22
22
|
# eg. If a method is listed in both
|
23
|
-
# `IncludedMacros` and `
|
24
|
-
# precedence (that is, the method is
|
23
|
+
# `IncludedMacros` and `AllowedMethods`, then the latter takes
|
24
|
+
# precedence (that is, the method is allowed).
|
25
25
|
#
|
26
26
|
# In the alternative style (omit_parentheses), there are three additional
|
27
27
|
# options.
|
@@ -65,7 +65,7 @@ module RuboCop
|
|
65
65
|
# # Setter methods don't need parens
|
66
66
|
# foo.bar = baz
|
67
67
|
#
|
68
|
-
# # okay with `puts` listed in `
|
68
|
+
# # okay with `puts` listed in `AllowedMethods`
|
69
69
|
# puts 'test'
|
70
70
|
#
|
71
71
|
# # okay with `^assert` listed in `AllowedPatterns`
|
@@ -197,7 +197,7 @@ module RuboCop
|
|
197
197
|
require_relative 'method_call_with_args_parentheses/require_parentheses'
|
198
198
|
|
199
199
|
include ConfigurableEnforcedStyle
|
200
|
-
include
|
200
|
+
include AllowedMethods
|
201
201
|
include AllowedPattern
|
202
202
|
include RequireParentheses
|
203
203
|
include OmitParentheses
|
@@ -5,8 +5,8 @@ module RuboCop
|
|
5
5
|
module Style
|
6
6
|
# Checks for unwanted parentheses in parameterless method calls.
|
7
7
|
#
|
8
|
-
# This cop can be customized
|
9
|
-
# By default, there are no methods to
|
8
|
+
# This cop can be customized allowed methods with `AllowedMethods`.
|
9
|
+
# By default, there are no methods to allowed.
|
10
10
|
#
|
11
11
|
# @example
|
12
12
|
# # bad
|
@@ -15,16 +15,17 @@ module RuboCop
|
|
15
15
|
# # good
|
16
16
|
# object.some_method
|
17
17
|
#
|
18
|
-
# @example
|
18
|
+
# @example AllowedMethods: [] (default)
|
19
19
|
# # bad
|
20
20
|
# object.foo()
|
21
21
|
#
|
22
|
-
# @example
|
22
|
+
# @example AllowedMethods: [foo]
|
23
23
|
# # good
|
24
24
|
# object.foo()
|
25
25
|
#
|
26
26
|
class MethodCallWithoutArgsParentheses < Base
|
27
|
-
include
|
27
|
+
include AllowedMethods
|
28
|
+
include AllowedPattern
|
28
29
|
extend AutoCorrector
|
29
30
|
|
30
31
|
MSG = 'Do not use parentheses for method calls with no arguments.'
|
@@ -33,7 +34,7 @@ module RuboCop
|
|
33
34
|
return unless !node.arguments? && node.parenthesized?
|
34
35
|
return if ineligible_node?(node)
|
35
36
|
return if default_argument?(node)
|
36
|
-
return if
|
37
|
+
return if allowed_method_name?(node.method_name)
|
37
38
|
return if same_name_assignment?(node)
|
38
39
|
|
39
40
|
register_offense(node)
|
@@ -56,6 +57,10 @@ module RuboCop
|
|
56
57
|
node.parent&.optarg_type?
|
57
58
|
end
|
58
59
|
|
60
|
+
def allowed_method_name?(name)
|
61
|
+
allowed_method?(name) || matches_allowed_pattern?(name)
|
62
|
+
end
|
63
|
+
|
59
64
|
def same_name_assignment?(node)
|
60
65
|
any_assignment?(node) do |asgn_node|
|
61
66
|
next variable_in_mass_assignment?(node.method_name, asgn_node) if asgn_node.masgn_type?
|
@@ -35,12 +35,15 @@ module RuboCop
|
|
35
35
|
ignore_node(node.send_node)
|
36
36
|
end
|
37
37
|
|
38
|
+
alias on_numblock on_block
|
39
|
+
|
38
40
|
def on_send(node)
|
39
41
|
return if ignored_node?(node)
|
40
42
|
|
41
43
|
receiver = node.receiver
|
42
44
|
|
43
|
-
return unless receiver&.block_type?
|
45
|
+
return unless (receiver&.block_type? || receiver&.numblock_type?) &&
|
46
|
+
receiver.loc.end.is?('end')
|
44
47
|
|
45
48
|
range = range_between(receiver.loc.end.begin_pos, node.source_range.end_pos)
|
46
49
|
|
@@ -31,7 +31,7 @@ module RuboCop
|
|
31
31
|
node.send_node.each_node(:send) do |send_node|
|
32
32
|
receiver = send_node.receiver
|
33
33
|
|
34
|
-
next unless receiver&.block_type? && receiver&.multiline?
|
34
|
+
next unless (receiver&.block_type? || receiver&.numblock_type?) && receiver&.multiline?
|
35
35
|
|
36
36
|
range = range_between(receiver.loc.end.begin_pos, node.send_node.source_range.end_pos)
|
37
37
|
|
@@ -42,6 +42,8 @@ module RuboCop
|
|
42
42
|
break
|
43
43
|
end
|
44
44
|
end
|
45
|
+
|
46
|
+
alias on_numblock on_block
|
45
47
|
end
|
46
48
|
end
|
47
49
|
end
|
@@ -49,7 +49,7 @@ module RuboCop
|
|
49
49
|
|
50
50
|
# Requires `then` for write `in` and its body on the same line.
|
51
51
|
def require_then?(in_pattern_node)
|
52
|
-
return true
|
52
|
+
return true unless in_pattern_node.pattern.single_line?
|
53
53
|
return false unless in_pattern_node.body
|
54
54
|
|
55
55
|
same_line?(in_pattern_node, in_pattern_node.body)
|
@@ -71,6 +71,8 @@ module RuboCop
|
|
71
71
|
check(node)
|
72
72
|
end
|
73
73
|
|
74
|
+
alias on_numblock on_block
|
75
|
+
|
74
76
|
def on_while(node)
|
75
77
|
check(node)
|
76
78
|
end
|
@@ -223,11 +225,7 @@ module RuboCop
|
|
223
225
|
adjustment = delta + @reindented_lines[lineno]
|
224
226
|
@reindented_lines[lineno] = adjustment
|
225
227
|
|
226
|
-
if adjustment.positive?
|
227
|
-
corrector.remove_leading(buffer.line_range(lineno), adjustment)
|
228
|
-
elsif adjustment.negative?
|
229
|
-
corrector.insert_before(buffer.line_range(lineno), ' ' * -adjustment)
|
230
|
-
end
|
228
|
+
corrector.remove_leading(buffer.line_range(lineno), adjustment) if adjustment.positive?
|
231
229
|
end
|
232
230
|
end
|
233
231
|
end
|
@@ -3,9 +3,17 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
# Checks for big numeric literals without _ between groups
|
6
|
+
# Checks for big numeric literals without `_` between groups
|
7
7
|
# of digits in them.
|
8
8
|
#
|
9
|
+
# Additional allowed patterns can be added by adding regexps to
|
10
|
+
# the `AllowedPatterns` configuration. All regexps are treated
|
11
|
+
# as anchored even if the patterns do not contain anchors (so
|
12
|
+
# `\d{4}_\d{4}` will allow `1234_5678` but not `1234_5678_9012`).
|
13
|
+
#
|
14
|
+
# NOTE: Even if `AllowedPatterns` are given, autocorrection will
|
15
|
+
# only correct to the standard pattern of an `_` every 3 digits.
|
16
|
+
#
|
9
17
|
# @example
|
10
18
|
#
|
11
19
|
# # bad
|
@@ -34,6 +42,7 @@ module RuboCop
|
|
34
42
|
#
|
35
43
|
class NumericLiterals < Base
|
36
44
|
include IntegerNode
|
45
|
+
include AllowedPattern
|
37
46
|
extend AutoCorrector
|
38
47
|
|
39
48
|
MSG = 'Use underscores(_) as thousands separator and separate every 3 digits with them.'
|
@@ -59,6 +68,7 @@ module RuboCop
|
|
59
68
|
# TODO: handle non-decimal literals as well
|
60
69
|
return if int.start_with?('0')
|
61
70
|
return if allowed_numbers.include?(int)
|
71
|
+
return if matches_allowed_pattern?(int)
|
62
72
|
return unless int.size >= min_digits
|
63
73
|
|
64
74
|
case int
|
@@ -108,6 +118,11 @@ module RuboCop
|
|
108
118
|
def allowed_numbers
|
109
119
|
cop_config.fetch('AllowedNumbers', []).map(&:to_s)
|
110
120
|
end
|
121
|
+
|
122
|
+
def allowed_patterns
|
123
|
+
# Convert the patterns to be anchored
|
124
|
+
super.map { |regexp| Regexp.new(/\A#{regexp}\z/) }
|
125
|
+
end
|
111
126
|
end
|
112
127
|
end
|
113
128
|
end
|
@@ -8,14 +8,14 @@ module RuboCop
|
|
8
8
|
# These can be replaced by their respective predicate methods.
|
9
9
|
# This cop can also be configured to do the reverse.
|
10
10
|
#
|
11
|
-
# This cop can be customized
|
12
|
-
# By default, there are no methods to
|
11
|
+
# This cop can be customized allowed methods with `AllowedMethods`.
|
12
|
+
# By default, there are no methods to allowed.
|
13
13
|
#
|
14
14
|
# This cop disregards `#nonzero?` as its value is truthy or falsey,
|
15
15
|
# but not `true` and `false`, and thus not always interchangeable with
|
16
16
|
# `!= 0`.
|
17
17
|
#
|
18
|
-
# This cop
|
18
|
+
# This cop allows comparisons to global variables, since they are often
|
19
19
|
# populated with objects which can be compared with integers, but are
|
20
20
|
# not themselves `Integer` polymorphic.
|
21
21
|
#
|
@@ -46,13 +46,13 @@ module RuboCop
|
|
46
46
|
# 0 > foo
|
47
47
|
# bar.baz > 0
|
48
48
|
#
|
49
|
-
# @example
|
49
|
+
# @example AllowedMethods: [] (default) with EnforcedStyle: predicate
|
50
50
|
# # bad
|
51
51
|
# foo == 0
|
52
52
|
# 0 > foo
|
53
53
|
# bar.baz > 0
|
54
54
|
#
|
55
|
-
# @example
|
55
|
+
# @example AllowedMethods: [==] with EnforcedStyle: predicate
|
56
56
|
# # good
|
57
57
|
# foo == 0
|
58
58
|
#
|
@@ -60,9 +60,25 @@ module RuboCop
|
|
60
60
|
# 0 > foo
|
61
61
|
# bar.baz > 0
|
62
62
|
#
|
63
|
+
# @example AllowedPatterns: [] (default) with EnforcedStyle: comparison
|
64
|
+
# # bad
|
65
|
+
# foo.zero?
|
66
|
+
# foo.negative?
|
67
|
+
# bar.baz.positive?
|
68
|
+
#
|
69
|
+
# @example AllowedPatterns: [/zero/] with EnforcedStyle: predicate
|
70
|
+
# # good
|
71
|
+
# # bad
|
72
|
+
# foo.zero?
|
73
|
+
#
|
74
|
+
# # bad
|
75
|
+
# foo.negative?
|
76
|
+
# bar.baz.positive?
|
77
|
+
#
|
63
78
|
class NumericPredicate < Base
|
64
79
|
include ConfigurableEnforcedStyle
|
65
|
-
include
|
80
|
+
include AllowedMethods
|
81
|
+
include AllowedPattern
|
66
82
|
extend AutoCorrector
|
67
83
|
|
68
84
|
MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
|
@@ -75,9 +91,9 @@ module RuboCop
|
|
75
91
|
numeric, replacement = check(node)
|
76
92
|
return unless numeric
|
77
93
|
|
78
|
-
return if
|
94
|
+
return if allowed_method_name?(node.method_name) ||
|
79
95
|
node.each_ancestor(:send, :block).any? do |ancestor|
|
80
|
-
|
96
|
+
allowed_method_name?(ancestor.method_name)
|
81
97
|
end
|
82
98
|
|
83
99
|
message = format(MSG, prefer: replacement, current: node.source)
|
@@ -88,6 +104,10 @@ module RuboCop
|
|
88
104
|
|
89
105
|
private
|
90
106
|
|
107
|
+
def allowed_method_name?(name)
|
108
|
+
allowed_method?(name) || matches_allowed_pattern?(name)
|
109
|
+
end
|
110
|
+
|
91
111
|
def check(node)
|
92
112
|
numeric, operator =
|
93
113
|
if style == :predicate
|
@@ -19,7 +19,8 @@ module RuboCop
|
|
19
19
|
MSG = 'Use `proc` instead of `Proc.new`.'
|
20
20
|
|
21
21
|
# @!method proc_new?(node)
|
22
|
-
def_node_matcher :proc_new?,
|
22
|
+
def_node_matcher :proc_new?,
|
23
|
+
'({block numblock} $(send (const {nil? cbase} :Proc) :new) ...)'
|
23
24
|
|
24
25
|
def on_block(node)
|
25
26
|
proc_new?(node) do |block_method|
|
@@ -28,6 +29,8 @@ module RuboCop
|
|
28
29
|
end
|
29
30
|
end
|
30
31
|
end
|
32
|
+
|
33
|
+
alias on_numblock on_block
|
31
34
|
end
|
32
35
|
end
|
33
36
|
end
|
@@ -154,16 +154,22 @@ module RuboCop
|
|
154
154
|
if_branch.method?(else_branch.method_name) && if_branch.receiver == else_branch.receiver
|
155
155
|
end
|
156
156
|
|
157
|
-
def if_source(if_branch)
|
157
|
+
def if_source(if_branch, arithmetic_operation)
|
158
158
|
if branches_have_method?(if_branch.parent) && if_branch.parenthesized?
|
159
159
|
if_branch.source.delete_suffix(')')
|
160
|
+
elsif arithmetic_operation
|
161
|
+
argument_source = if_branch.first_argument.source
|
162
|
+
|
163
|
+
"#{if_branch.receiver.source} #{if_branch.method_name} (#{argument_source}"
|
160
164
|
else
|
161
165
|
if_branch.source
|
162
166
|
end
|
163
167
|
end
|
164
168
|
|
165
|
-
def else_source(else_branch)
|
166
|
-
if
|
169
|
+
def else_source(else_branch, arithmetic_operation) # rubocop:disable Metrics/AbcSize
|
170
|
+
if arithmetic_operation
|
171
|
+
"#{else_branch.first_argument.source})"
|
172
|
+
elsif branches_have_method?(else_branch.parent)
|
167
173
|
else_source_if_has_method(else_branch)
|
168
174
|
elsif require_parentheses?(else_branch)
|
169
175
|
"(#{else_branch.source})"
|
@@ -198,7 +204,12 @@ module RuboCop
|
|
198
204
|
|
199
205
|
def make_ternary_form(node)
|
200
206
|
_condition, if_branch, else_branch = *node
|
201
|
-
|
207
|
+
arithmetic_operation = use_arithmetic_operation?(if_branch)
|
208
|
+
|
209
|
+
ternary_form = [
|
210
|
+
if_source(if_branch, arithmetic_operation),
|
211
|
+
else_source(else_branch, arithmetic_operation)
|
212
|
+
].join(' || ')
|
202
213
|
ternary_form += ')' if branches_have_method?(node) && if_branch.parenthesized?
|
203
214
|
|
204
215
|
if node.parent&.send_type?
|
@@ -227,6 +238,10 @@ module RuboCop
|
|
227
238
|
node.hash_type? && !node.braces?
|
228
239
|
end
|
229
240
|
|
241
|
+
def use_arithmetic_operation?(node)
|
242
|
+
node.respond_to?(:arithmetic_operation?) && node.arithmetic_operation?
|
243
|
+
end
|
244
|
+
|
230
245
|
def without_argument_parentheses_method?(node)
|
231
246
|
node.send_type? && !node.arguments.empty? &&
|
232
247
|
!node.parenthesized? && !node.operator_method? && !node.assignment_method?
|
@@ -50,7 +50,7 @@ module RuboCop
|
|
50
50
|
${nil? #basic_literal? #const_type?})
|
51
51
|
PATTERN
|
52
52
|
|
53
|
-
def on_block(node)
|
53
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
54
54
|
redundant_fetch_block_candidate?(node) do |send, body|
|
55
55
|
return if should_not_check?(send, body)
|
56
56
|
|
@@ -57,8 +57,8 @@ module RuboCop
|
|
57
57
|
def allowed_expression?(node)
|
58
58
|
allowed_ancestor?(node) ||
|
59
59
|
allowed_method_call?(node) ||
|
60
|
-
|
61
|
-
|
60
|
+
allowed_multiple_expression?(node) ||
|
61
|
+
allowed_ternary?(node)
|
62
62
|
end
|
63
63
|
|
64
64
|
def allowed_ancestor?(node)
|
@@ -80,6 +80,19 @@ module RuboCop
|
|
80
80
|
!ancestor.begin_type? && !ancestor.def_type? && !ancestor.block_type?
|
81
81
|
end
|
82
82
|
|
83
|
+
def allowed_ternary?(node)
|
84
|
+
return unless node&.parent&.if_type?
|
85
|
+
|
86
|
+
node.parent.ternary? && ternary_parentheses_required?
|
87
|
+
end
|
88
|
+
|
89
|
+
def ternary_parentheses_required?
|
90
|
+
config = @config.for_cop('Style/TernaryParentheses')
|
91
|
+
allowed_styles = %w[require_parentheses require_parentheses_when_complex]
|
92
|
+
|
93
|
+
config.fetch('Enabled') && allowed_styles.include?(config['EnforcedStyle'])
|
94
|
+
end
|
95
|
+
|
83
96
|
def like_method_argument_parentheses?(node)
|
84
97
|
node.send_type? && node.arguments.one? &&
|
85
98
|
!node.arithmetic_operation? && node.first_argument.begin_type?
|
@@ -153,26 +166,6 @@ module RuboCop
|
|
153
166
|
node.parent&.keyword?
|
154
167
|
end
|
155
168
|
|
156
|
-
def allowed_array_or_hash_element?(node)
|
157
|
-
# Don't flag
|
158
|
-
# ```
|
159
|
-
# { a: (1
|
160
|
-
# ), }
|
161
|
-
# ```
|
162
|
-
hash_or_array_element?(node) && only_closing_paren_before_comma?(node)
|
163
|
-
end
|
164
|
-
|
165
|
-
def hash_or_array_element?(node)
|
166
|
-
node.each_ancestor(:array, :hash).any?
|
167
|
-
end
|
168
|
-
|
169
|
-
def only_closing_paren_before_comma?(node)
|
170
|
-
source_buffer = node.source_range.source_buffer
|
171
|
-
line_range = source_buffer.line_range(node.loc.end.line)
|
172
|
-
|
173
|
-
/^\s*\)\s*,/.match?(line_range.source)
|
174
|
-
end
|
175
|
-
|
176
169
|
def disallowed_literal?(begin_node, node)
|
177
170
|
node.literal? && !node.range_type? && !raised_to_power_negative_numeric?(begin_node, node)
|
178
171
|
end
|
@@ -120,6 +120,8 @@ module RuboCop
|
|
120
120
|
add_scope(node, @local_variables_scopes[node])
|
121
121
|
end
|
122
122
|
|
123
|
+
alias on_numblock on_block
|
124
|
+
|
123
125
|
def on_if(node)
|
124
126
|
# Allow conditional nodes to use `self` in the condition if that variable
|
125
127
|
# name is used in an `lvasgn` or `masgn` within the `if`.
|
@@ -123,13 +123,8 @@ module RuboCop
|
|
123
123
|
|
124
124
|
def register_offense(node, sort_node, sorter, accessor)
|
125
125
|
message = message(node, sorter, accessor)
|
126
|
-
|
127
126
|
add_offense(offense_range(sort_node, node), message: message) do |corrector|
|
128
|
-
|
129
|
-
corrector.remove(range_between(accessor_start(node), node.loc.expression.end_pos))
|
130
|
-
|
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)))
|
127
|
+
autocorrect(corrector, node, sort_node, sorter, accessor)
|
133
128
|
end
|
134
129
|
end
|
135
130
|
|
@@ -149,6 +144,20 @@ module RuboCop
|
|
149
144
|
accessor_source: accessor_source)
|
150
145
|
end
|
151
146
|
|
147
|
+
def autocorrect(corrector, node, sort_node, sorter, accessor)
|
148
|
+
# Remove accessor, e.g. `first` or `[-1]`.
|
149
|
+
corrector.remove(range_between(accessor_start(node), node.loc.expression.end_pos))
|
150
|
+
# Replace "sort" or "sort_by" with the appropriate min/max method.
|
151
|
+
corrector.replace(sort_node.loc.selector, suggestion(sorter, accessor, arg_value(node)))
|
152
|
+
# Replace to avoid syntax errors when followed by a logical operator.
|
153
|
+
replace_with_logical_operator(corrector, node) if with_logical_operator?(node)
|
154
|
+
end
|
155
|
+
|
156
|
+
def replace_with_logical_operator(corrector, node)
|
157
|
+
corrector.insert_after(node.child_nodes.first, " #{node.parent.loc.operator.source}")
|
158
|
+
corrector.remove(node.parent.loc.operator)
|
159
|
+
end
|
160
|
+
|
152
161
|
def suggestion(sorter, accessor, arg)
|
153
162
|
base(accessor, arg) + suffix(sorter)
|
154
163
|
end
|
@@ -187,6 +196,12 @@ module RuboCop
|
|
187
196
|
node.loc.selector.begin_pos
|
188
197
|
end
|
189
198
|
end
|
199
|
+
|
200
|
+
def with_logical_operator?(node)
|
201
|
+
return unless (parent = node.parent)
|
202
|
+
|
203
|
+
parent.or_type? || parent.and_type?
|
204
|
+
end
|
190
205
|
end
|
191
206
|
end
|
192
207
|
end
|
@@ -19,18 +19,24 @@ module RuboCop
|
|
19
19
|
include RangeHelp
|
20
20
|
extend AutoCorrector
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
# @!method redundant_sort_by(node)
|
25
|
-
def_node_matcher :redundant_sort_by, <<~PATTERN
|
26
|
-
(block $(send _ :sort_by) (args (arg $_x)) (lvar _x))
|
27
|
-
PATTERN
|
22
|
+
MSG_BLOCK = 'Use `sort` instead of `sort_by { |%<var>s| %<var>s }`.'
|
23
|
+
MSG_NUMBLOCK = 'Use `sort` instead of `sort_by { _1 }`.'
|
28
24
|
|
29
25
|
def on_block(node)
|
30
|
-
|
26
|
+
redundant_sort_by_block(node) do |send, var_name|
|
31
27
|
range = sort_by_range(send, node)
|
32
28
|
|
33
|
-
add_offense(range, message: format(
|
29
|
+
add_offense(range, message: format(MSG_BLOCK, var: var_name)) do |corrector|
|
30
|
+
corrector.replace(range, 'sort')
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def on_numblock(node)
|
36
|
+
redundant_sort_by_numblock(node) do |send|
|
37
|
+
range = sort_by_range(send, node)
|
38
|
+
|
39
|
+
add_offense(range, message: format(MSG_NUMBLOCK)) do |corrector|
|
34
40
|
corrector.replace(range, 'sort')
|
35
41
|
end
|
36
42
|
end
|
@@ -38,6 +44,16 @@ module RuboCop
|
|
38
44
|
|
39
45
|
private
|
40
46
|
|
47
|
+
# @!method redundant_sort_by_block(node)
|
48
|
+
def_node_matcher :redundant_sort_by_block, <<~PATTERN
|
49
|
+
(block $(send _ :sort_by) (args (arg $_x)) (lvar _x))
|
50
|
+
PATTERN
|
51
|
+
|
52
|
+
# @!method redundant_sort_by_numblock(node)
|
53
|
+
def_node_matcher :redundant_sort_by_numblock, <<~PATTERN
|
54
|
+
(numblock $(send _ :sort_by) 1 (lvar :_1))
|
55
|
+
PATTERN
|
56
|
+
|
41
57
|
def sort_by_range(send, node)
|
42
58
|
range_between(send.loc.selector.begin_pos, node.loc.end.end_pos)
|
43
59
|
end
|
@@ -141,7 +141,7 @@ module RuboCop
|
|
141
141
|
|
142
142
|
corrector.remove(begin_range(node, body))
|
143
143
|
corrector.remove(end_range(node, body))
|
144
|
-
corrector.insert_before(method_call.loc.dot, '&')
|
144
|
+
corrector.insert_before(method_call.loc.dot, '&') unless method_call.safe_navigation?
|
145
145
|
handle_comments(corrector, node, method_call)
|
146
146
|
|
147
147
|
add_safe_nav_to_all_methods_in_chain(corrector, method_call, body)
|
@@ -250,7 +250,9 @@ module RuboCop
|
|
250
250
|
end
|
251
251
|
|
252
252
|
def unsafe_method?(send_node)
|
253
|
-
negated?(send_node) ||
|
253
|
+
negated?(send_node) ||
|
254
|
+
send_node.assignment? ||
|
255
|
+
(!send_node.dot? && !send_node.safe_navigation?)
|
254
256
|
end
|
255
257
|
|
256
258
|
def negated?(send_node)
|