rubocop 1.6.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +3 -2
- data/config/default.yml +142 -19
- data/lib/rubocop.rb +15 -1
- data/lib/rubocop/cli/command/auto_genenerate_config.rb +5 -4
- data/lib/rubocop/comment_config.rb +6 -6
- data/lib/rubocop/config.rb +10 -7
- data/lib/rubocop/config_loader.rb +11 -14
- data/lib/rubocop/config_loader_resolver.rb +21 -4
- data/lib/rubocop/config_obsoletion.rb +5 -3
- data/lib/rubocop/config_obsoletion/extracted_cop.rb +6 -6
- data/lib/rubocop/config_store.rb +12 -1
- data/lib/rubocop/cop/base.rb +1 -1
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +3 -2
- data/lib/rubocop/cop/generator.rb +1 -3
- data/lib/rubocop/cop/internal_affairs.rb +6 -1
- data/lib/rubocop/cop/internal_affairs/empty_line_between_expect_offense_and_correction.rb +68 -0
- data/lib/rubocop/cop/internal_affairs/example_description.rb +89 -0
- data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +61 -0
- data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +64 -0
- data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +145 -0
- data/lib/rubocop/cop/layout/class_structure.rb +7 -2
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +19 -3
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +14 -0
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +3 -10
- data/lib/rubocop/cop/layout/space_around_equals_in_parameter_default.rb +1 -0
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +2 -0
- data/lib/rubocop/cop/layout/space_before_brackets.rb +62 -0
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +13 -10
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +2 -2
- data/lib/rubocop/cop/lint/ambiguous_assignment.rb +59 -0
- data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +7 -2
- data/lib/rubocop/cop/lint/deprecated_constants.rb +75 -0
- data/lib/rubocop/cop/lint/duplicate_branch.rb +64 -2
- data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +44 -0
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +10 -6
- data/lib/rubocop/cop/lint/number_conversion.rb +41 -6
- data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +47 -0
- data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +39 -0
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +2 -1
- data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +50 -0
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +50 -17
- data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -11
- data/lib/rubocop/cop/lint/symbol_conversion.rb +102 -0
- data/lib/rubocop/cop/lint/triple_quotes.rb +71 -0
- data/lib/rubocop/cop/lint/unreachable_loop.rb +17 -0
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
- data/lib/rubocop/cop/mixin/allowed_identifiers.rb +18 -0
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +5 -0
- data/lib/rubocop/cop/mixin/comments_help.rb +1 -11
- data/lib/rubocop/cop/mixin/first_element_line_break.rb +1 -1
- data/lib/rubocop/cop/mixin/uncommunicative_name.rb +5 -1
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +59 -5
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +38 -5
- data/lib/rubocop/cop/naming/variable_name.rb +2 -0
- data/lib/rubocop/cop/naming/variable_number.rb +2 -9
- data/lib/rubocop/cop/registry.rb +10 -0
- data/lib/rubocop/cop/severity.rb +3 -3
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +3 -1
- data/lib/rubocop/cop/style/ascii_comments.rb +1 -1
- data/lib/rubocop/cop/style/collection_methods.rb +14 -1
- data/lib/rubocop/cop/style/commented_keyword.rb +22 -5
- data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +49 -9
- data/lib/rubocop/cop/style/empty_literal.rb +6 -2
- data/lib/rubocop/cop/style/endless_method.rb +102 -0
- data/lib/rubocop/cop/style/eval_with_location.rb +63 -34
- data/lib/rubocop/cop/style/explicit_block_argument.rb +10 -0
- data/lib/rubocop/cop/style/float_division.rb +3 -0
- data/lib/rubocop/cop/style/for.rb +2 -0
- data/lib/rubocop/cop/style/format_string_token.rb +18 -2
- data/lib/rubocop/cop/style/hash_except.rb +95 -0
- data/lib/rubocop/cop/style/hash_like_case.rb +2 -1
- data/lib/rubocop/cop/style/if_inside_else.rb +22 -10
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +96 -0
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +12 -2
- data/lib/rubocop/cop/style/lambda_call.rb +2 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +7 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +16 -6
- data/lib/rubocop/cop/style/method_def_parentheses.rb +7 -0
- data/lib/rubocop/cop/style/multiline_method_signature.rb +26 -1
- data/lib/rubocop/cop/style/multiline_when_then.rb +3 -1
- data/lib/rubocop/cop/style/mutable_constant.rb +13 -3
- data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +4 -0
- data/lib/rubocop/cop/style/nil_comparison.rb +1 -0
- data/lib/rubocop/cop/style/non_nil_check.rb +23 -13
- data/lib/rubocop/cop/style/raise_args.rb +5 -2
- data/lib/rubocop/cop/style/redundant_argument.rb +7 -1
- data/lib/rubocop/cop/style/redundant_freeze.rb +8 -4
- data/lib/rubocop/cop/style/redundant_return.rb +1 -1
- data/lib/rubocop/cop/style/single_line_methods.rb +34 -2
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +29 -5
- data/lib/rubocop/cop/style/string_concatenation.rb +1 -1
- data/lib/rubocop/cop/style/symbol_proc.rb +5 -4
- data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/while_until_modifier.rb +2 -4
- data/lib/rubocop/cop/util.rb +3 -1
- data/lib/rubocop/formatter/git_hub_actions_formatter.rb +1 -0
- data/lib/rubocop/magic_comment.rb +30 -1
- data/lib/rubocop/options.rb +10 -10
- data/lib/rubocop/rspec/cop_helper.rb +0 -4
- data/lib/rubocop/rspec/expect_offense.rb +37 -22
- data/lib/rubocop/runner.rb +17 -1
- data/lib/rubocop/target_finder.rb +4 -2
- data/lib/rubocop/target_ruby.rb +47 -11
- data/lib/rubocop/util.rb +16 -0
- data/lib/rubocop/version.rb +8 -2
- metadata +26 -7
@@ -111,7 +111,8 @@ module RuboCop
|
|
111
111
|
braces_with_contents_inside(node, inner)
|
112
112
|
elsif style_for_empty_braces == :no_space
|
113
113
|
offense(range.begin_pos, range.end_pos,
|
114
|
-
'Space inside empty braces detected.'
|
114
|
+
'Space inside empty braces detected.',
|
115
|
+
'EnforcedStyleForEmptyBraces')
|
115
116
|
end
|
116
117
|
end
|
117
118
|
end
|
@@ -120,7 +121,8 @@ module RuboCop
|
|
120
121
|
return if style_for_empty_braces != :space
|
121
122
|
|
122
123
|
offense(left_brace.begin_pos, right_brace.end_pos,
|
123
|
-
'Space missing inside empty braces.'
|
124
|
+
'Space missing inside empty braces.',
|
125
|
+
'EnforcedStyleForEmptyBraces')
|
124
126
|
end
|
125
127
|
|
126
128
|
def braces_with_contents_inside(node, inner)
|
@@ -164,9 +166,9 @@ module RuboCop
|
|
164
166
|
if left_brace.end_pos == args_delimiter.begin_pos &&
|
165
167
|
cop_config['SpaceBeforeBlockParameters']
|
166
168
|
offense(left_brace.begin_pos, args_delimiter.end_pos,
|
167
|
-
'Space between { and | missing.')
|
168
|
-
|
169
|
-
|
169
|
+
'Space between { and | missing.')
|
170
|
+
else
|
171
|
+
correct_style_detected
|
170
172
|
end
|
171
173
|
else
|
172
174
|
# We indicate the position after the left brace. Otherwise it's
|
@@ -179,11 +181,11 @@ module RuboCop
|
|
179
181
|
|
180
182
|
def space_inside_left_brace(left_brace, args_delimiter)
|
181
183
|
if pipe?(args_delimiter)
|
182
|
-
|
184
|
+
if cop_config['SpaceBeforeBlockParameters']
|
185
|
+
correct_style_detected
|
186
|
+
else
|
183
187
|
offense(left_brace.end_pos, args_delimiter.begin_pos,
|
184
|
-
'Space between { and | detected.')
|
185
|
-
opposite_style_detected
|
186
|
-
end
|
188
|
+
'Space between { and | detected.')
|
187
189
|
end
|
188
190
|
else
|
189
191
|
brace_with_space = range_with_surrounding_space(range: left_brace,
|
@@ -220,7 +222,7 @@ module RuboCop
|
|
220
222
|
end
|
221
223
|
end
|
222
224
|
|
223
|
-
def offense(begin_pos, end_pos, msg)
|
225
|
+
def offense(begin_pos, end_pos, msg, style_param = 'EnforcedStyle')
|
224
226
|
range = range_between(begin_pos, end_pos)
|
225
227
|
add_offense(range, message: msg) do |corrector|
|
226
228
|
case range.source
|
@@ -229,6 +231,7 @@ module RuboCop
|
|
229
231
|
when '{|' then corrector.replace(range, '{ |')
|
230
232
|
else corrector.insert_before(range, ' ')
|
231
233
|
end
|
234
|
+
opposite_style_detected if style_param == 'EnforcedStyle'
|
232
235
|
end
|
233
236
|
end
|
234
237
|
|
@@ -112,13 +112,13 @@ module RuboCop
|
|
112
112
|
|
113
113
|
def incorrect_style_detected(token1, token2,
|
114
114
|
expect_space, is_empty_braces)
|
115
|
-
return unless ambiguous_or_unexpected_style_detected(style, token1.text == token2.text)
|
116
|
-
|
117
115
|
brace = (token1.text == '{' ? token1 : token2).pos
|
118
116
|
range = expect_space ? brace : space_range(brace)
|
117
|
+
detected_style = expect_space ? 'no_space' : 'space'
|
119
118
|
|
120
119
|
add_offense(range, message: message(brace, is_empty_braces, expect_space)) do |corrector|
|
121
120
|
autocorrect(corrector, range)
|
121
|
+
ambiguous_or_unexpected_style_detected(detected_style, token1.text == token2.text)
|
122
122
|
end
|
123
123
|
end
|
124
124
|
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
# This cop checks for mistyped shorthand assignments.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# x =- y
|
11
|
+
# x =+ y
|
12
|
+
# x =* y
|
13
|
+
# x =! y
|
14
|
+
#
|
15
|
+
# # good
|
16
|
+
# x -= y # or x = -y
|
17
|
+
# x += y # or x = +y
|
18
|
+
# x *= y # or x = *y
|
19
|
+
# x != y # or x = !y
|
20
|
+
#
|
21
|
+
class AmbiguousAssignment < Base
|
22
|
+
include RangeHelp
|
23
|
+
|
24
|
+
MSG = 'Suspicious assignment detected. Did you mean `%<op>s`?'
|
25
|
+
|
26
|
+
SIMPLE_ASSIGNMENT_TYPES = %i[lvasgn ivasgn cvasgn gvasgn casgn].freeze
|
27
|
+
|
28
|
+
MISTAKES = {
|
29
|
+
'=-' => '-=',
|
30
|
+
'=+' => '+=',
|
31
|
+
'=*' => '*=',
|
32
|
+
'=!' => '!='
|
33
|
+
}.freeze
|
34
|
+
|
35
|
+
def on_asgn(node)
|
36
|
+
return unless (rhs = rhs(node))
|
37
|
+
|
38
|
+
range = range_between(node.loc.operator.end_pos - 1, rhs.source_range.begin_pos + 1)
|
39
|
+
source = range.source
|
40
|
+
return unless MISTAKES.key?(source)
|
41
|
+
|
42
|
+
add_offense(range, message: format(MSG, op: MISTAKES[source]))
|
43
|
+
end
|
44
|
+
|
45
|
+
SIMPLE_ASSIGNMENT_TYPES.each { |asgn_type| alias_method :"on_#{asgn_type}", :on_asgn }
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def rhs(node)
|
50
|
+
if node.casgn_type?
|
51
|
+
node.children[2]
|
52
|
+
else
|
53
|
+
node.children[1]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -17,6 +17,7 @@ module RuboCop
|
|
17
17
|
#
|
18
18
|
# @example
|
19
19
|
# # bad
|
20
|
+
# x / x
|
20
21
|
# x.top >= x.top
|
21
22
|
#
|
22
23
|
# if a.x != 0 && a.x != 0
|
@@ -27,15 +28,19 @@ module RuboCop
|
|
27
28
|
# left_child || left_child
|
28
29
|
# end
|
29
30
|
#
|
31
|
+
# # good
|
32
|
+
# x + x
|
33
|
+
# 1 << 1
|
34
|
+
#
|
30
35
|
class BinaryOperatorWithIdenticalOperands < Base
|
31
36
|
MSG = 'Binary operator `%<op>s` has identical operands.'
|
32
|
-
|
37
|
+
ALLOWED_MATH_OPERATORS = %i[+ * ** << >>].to_set.freeze
|
33
38
|
|
34
39
|
def on_send(node)
|
35
40
|
return unless node.binary_operation?
|
36
41
|
|
37
42
|
lhs, operation, rhs = *node
|
38
|
-
return if
|
43
|
+
return if ALLOWED_MATH_OPERATORS.include?(node.method_name)
|
39
44
|
|
40
45
|
add_offense(node, message: format(MSG, op: operation)) if lhs == rhs
|
41
46
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
# This cop checks for deprecated constants.
|
7
|
+
#
|
8
|
+
# It has `DeprecatedConstants` config. If there is an alternative method, you can set
|
9
|
+
# alternative value as `Alternative`. And you can set the deprecated version as
|
10
|
+
# `DeprecatedVersion`. These options can be omitted if they are not needed.
|
11
|
+
#
|
12
|
+
# DeprecatedConstants:
|
13
|
+
# 'DEPRECATED_CONSTANT':
|
14
|
+
# Alternative: 'alternative_value'
|
15
|
+
# DeprecatedVersion: 'deprecated_version'
|
16
|
+
#
|
17
|
+
# By default, `NIL`, `TRUE`, `FALSE` and `Random::DEFAULT` are configured.
|
18
|
+
#
|
19
|
+
# @example
|
20
|
+
#
|
21
|
+
# # bad
|
22
|
+
# NIL
|
23
|
+
# TRUE
|
24
|
+
# FALSE
|
25
|
+
# Random::DEFAULT # Return value of Ruby 2 is `Random` instance, Ruby 3.0 is `Random` class.
|
26
|
+
#
|
27
|
+
# # good
|
28
|
+
# nil
|
29
|
+
# true
|
30
|
+
# false
|
31
|
+
# Random.new # `::DEFAULT` has been deprecated in Ruby 3, `.new` is compatible with Ruby 2.
|
32
|
+
#
|
33
|
+
class DeprecatedConstants < Base
|
34
|
+
extend AutoCorrector
|
35
|
+
|
36
|
+
SUGGEST_GOOD_MSG = 'Use `%<good>s` instead of `%<bad>s`%<deprecated_message>s.'
|
37
|
+
DO_NOT_USE_MSG = 'Do not use `%<bad>s`%<deprecated_message>s.'
|
38
|
+
|
39
|
+
def on_const(node)
|
40
|
+
constant = node.absolute? ? consntant_name(node, node.short_name.to_s) : node.source
|
41
|
+
return unless (deprecated_constant = deprecated_constants[constant])
|
42
|
+
|
43
|
+
alternative = deprecated_constant['Alternative']
|
44
|
+
version = deprecated_constant['DeprecatedVersion']
|
45
|
+
|
46
|
+
add_offense(node, message: message(alternative, node.source, version)) do |corrector|
|
47
|
+
corrector.replace(node, alternative)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def consntant_name(node, nested_constant_name)
|
54
|
+
return nested_constant_name unless node.namespace.const_type?
|
55
|
+
|
56
|
+
consntant_name(node.namespace, "#{node.namespace.short_name}::#{nested_constant_name}")
|
57
|
+
end
|
58
|
+
|
59
|
+
def message(good, bad, deprecated_version)
|
60
|
+
deprecated_message = ", deprecated since Ruby #{deprecated_version}" if deprecated_version
|
61
|
+
|
62
|
+
if good
|
63
|
+
format(SUGGEST_GOOD_MSG, good: good, bad: bad, deprecated_message: deprecated_message)
|
64
|
+
else
|
65
|
+
format(DO_NOT_USE_MSG, bad: bad, deprecated_message: deprecated_message)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def deprecated_constants
|
70
|
+
cop_config.fetch('DeprecatedConstants', {})
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -6,6 +6,15 @@ module RuboCop
|
|
6
6
|
# This cop checks that there are no repeated bodies
|
7
7
|
# within `if/unless`, `case-when` and `rescue` constructs.
|
8
8
|
#
|
9
|
+
# With `IgnoreLiteralBranches: true`, branches are not registered
|
10
|
+
# as offenses if they return a basic literal value (string, symbol,
|
11
|
+
# integer, float, rational, complex, `true`, `false`, or `nil`), or
|
12
|
+
# return an array, hash, regexp or range that only contains one of
|
13
|
+
# the above basic literal values.
|
14
|
+
#
|
15
|
+
# With `IgnoreConstantBranches: true`, branches are not registered
|
16
|
+
# as offenses if they return a constant value.
|
17
|
+
#
|
9
18
|
# @example
|
10
19
|
# # bad
|
11
20
|
# if foo
|
@@ -56,14 +65,33 @@ module RuboCop
|
|
56
65
|
# handle_error
|
57
66
|
# end
|
58
67
|
#
|
68
|
+
# @example IgnoreLiteralBranches: true
|
69
|
+
# # good
|
70
|
+
# case size
|
71
|
+
# when "small" then 100
|
72
|
+
# when "medium" then 250
|
73
|
+
# when "large" then 1000
|
74
|
+
# else 250
|
75
|
+
# end
|
76
|
+
#
|
77
|
+
# @example IgnoreLiteralBranches: true
|
78
|
+
# # good
|
79
|
+
# case size
|
80
|
+
# when "small" then SMALL_SIZE
|
81
|
+
# when "medium" then MEDIUM_SIZE
|
82
|
+
# when "large" then LARGE_SIZE
|
83
|
+
# else MEDIUM_SIZE
|
84
|
+
# end
|
85
|
+
#
|
59
86
|
class DuplicateBranch < Base
|
60
87
|
include RescueNode
|
61
88
|
|
62
89
|
MSG = 'Duplicate branch body detected.'
|
63
90
|
|
64
91
|
def on_branching_statement(node)
|
65
|
-
branches
|
66
|
-
|
92
|
+
branches(node).each_with_object(Set.new) do |branch, previous|
|
93
|
+
next unless consider_branch?(branch)
|
94
|
+
|
67
95
|
add_offense(offense_range(branch)) unless previous.add?(branch)
|
68
96
|
end
|
69
97
|
end
|
@@ -87,6 +115,40 @@ module RuboCop
|
|
87
115
|
parent.source_range
|
88
116
|
end
|
89
117
|
end
|
118
|
+
|
119
|
+
def branches(node)
|
120
|
+
node.branches.compact
|
121
|
+
end
|
122
|
+
|
123
|
+
def consider_branch?(branch)
|
124
|
+
return false if ignore_literal_branches? && literal_branch?(branch)
|
125
|
+
return false if ignore_constant_branches? && const_branch?(branch)
|
126
|
+
|
127
|
+
true
|
128
|
+
end
|
129
|
+
|
130
|
+
def ignore_literal_branches?
|
131
|
+
cop_config.fetch('IgnoreLiteralBranches', false)
|
132
|
+
end
|
133
|
+
|
134
|
+
def ignore_constant_branches?
|
135
|
+
cop_config.fetch('IgnoreConstantBranches', false)
|
136
|
+
end
|
137
|
+
|
138
|
+
def literal_branch?(branch) # rubocop:disable Metrics/CyclomaticComplexity
|
139
|
+
return false if !branch.literal? || branch.xstr_type?
|
140
|
+
return true if branch.basic_literal?
|
141
|
+
|
142
|
+
branch.each_descendant.all? do |node|
|
143
|
+
node.basic_literal? ||
|
144
|
+
node.pair_type? || # hash keys and values are contained within a `pair` node
|
145
|
+
(node.const_type? && ignore_constant_branches?)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def const_branch?(branch)
|
150
|
+
branch.const_type?
|
151
|
+
end
|
90
152
|
end
|
91
153
|
end
|
92
154
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
# This cop checks uses of lambda without a literal block.
|
7
|
+
# It emulates the following warning in Ruby 3.0:
|
8
|
+
#
|
9
|
+
# % ruby -vwe 'lambda(&proc {})'
|
10
|
+
# ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin19]
|
11
|
+
# -e:1: warning: lambda without a literal block is deprecated; use the proc without
|
12
|
+
# lambda instead
|
13
|
+
#
|
14
|
+
# This way, proc object is never converted to lambda.
|
15
|
+
# Auto-correction replaces with compatible proc argument.
|
16
|
+
#
|
17
|
+
# @example
|
18
|
+
#
|
19
|
+
# # bad
|
20
|
+
# lambda(&proc { do_something })
|
21
|
+
# lambda(&Proc.new { do_something })
|
22
|
+
#
|
23
|
+
# # good
|
24
|
+
# proc { do_something }
|
25
|
+
# Proc.new { do_something }
|
26
|
+
# lambda { do_something } # If you use lambda.
|
27
|
+
#
|
28
|
+
class LambdaWithoutLiteralBlock < Base
|
29
|
+
extend AutoCorrector
|
30
|
+
|
31
|
+
MSG = 'lambda without a literal block is deprecated; use the proc without lambda instead.'
|
32
|
+
RESTRICT_ON_SEND = %i[lambda].freeze
|
33
|
+
|
34
|
+
def on_send(node)
|
35
|
+
return if node.parent&.block_type? || !node.first_argument
|
36
|
+
|
37
|
+
add_offense(node) do |corrector|
|
38
|
+
corrector.replace(node, node.first_argument.source.delete('&'))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -11,6 +11,11 @@ module RuboCop
|
|
11
11
|
# that are hard to debug. To ensure this doesn't happen,
|
12
12
|
# always sort the list.
|
13
13
|
#
|
14
|
+
# `Dir.glob` and `Dir[]` sort globbed results by default in Ruby 3.0.
|
15
|
+
# So all bad cases are acceptable when Ruby 3.0 or higher are used.
|
16
|
+
#
|
17
|
+
# This cop will be deprecated and removed when supporting only Ruby 3.0 and higher.
|
18
|
+
#
|
14
19
|
# @example
|
15
20
|
#
|
16
21
|
# # bad
|
@@ -23,8 +28,6 @@ module RuboCop
|
|
23
28
|
# require file
|
24
29
|
# end
|
25
30
|
#
|
26
|
-
# @example
|
27
|
-
#
|
28
31
|
# # bad
|
29
32
|
# Dir.glob(Rails.root.join(__dir__, 'test', '*.rb')) do |file|
|
30
33
|
# require file
|
@@ -35,28 +38,28 @@ module RuboCop
|
|
35
38
|
# require file
|
36
39
|
# end
|
37
40
|
#
|
38
|
-
# @example
|
39
|
-
#
|
40
41
|
# # bad
|
41
42
|
# Dir['./lib/**/*.rb'].each(&method(:require))
|
42
43
|
#
|
43
44
|
# # good
|
44
45
|
# Dir['./lib/**/*.rb'].sort.each(&method(:require))
|
45
46
|
#
|
46
|
-
# @example
|
47
|
-
#
|
48
47
|
# # bad
|
49
48
|
# Dir.glob(Rails.root.join('test', '*.rb'), &method(:require))
|
50
49
|
#
|
51
50
|
# # good
|
52
51
|
# Dir.glob(Rails.root.join('test', '*.rb')).sort.each(&method(:require))
|
53
52
|
#
|
53
|
+
# # good - Respect intent if `sort` keyword option is specified in Ruby 3.0 or higher.
|
54
|
+
# Dir.glob(Rails.root.join(__dir__, 'test', '*.rb'), sort: false).each(&method(:require))
|
55
|
+
#
|
54
56
|
class NonDeterministicRequireOrder < Base
|
55
57
|
extend AutoCorrector
|
56
58
|
|
57
59
|
MSG = 'Sort files before requiring them.'
|
58
60
|
|
59
61
|
def on_block(node)
|
62
|
+
return if target_ruby_version >= 3.0
|
60
63
|
return unless node.body
|
61
64
|
return unless unsorted_dir_loop?(node.send_node)
|
62
65
|
|
@@ -70,6 +73,7 @@ module RuboCop
|
|
70
73
|
end
|
71
74
|
|
72
75
|
def on_block_pass(node)
|
76
|
+
return if target_ruby_version >= 3.0
|
73
77
|
return unless method_require?(node)
|
74
78
|
return unless unsorted_dir_pass?(node.parent)
|
75
79
|
|
@@ -25,12 +25,18 @@ module RuboCop
|
|
25
25
|
# '10'.to_i
|
26
26
|
# '10.2'.to_f
|
27
27
|
# '10'.to_c
|
28
|
+
# ['1', '2', '3'].map(&:to_i)
|
29
|
+
# foo.try(:to_f)
|
30
|
+
# bar.send(:to_c)
|
28
31
|
#
|
29
32
|
# # good
|
30
33
|
#
|
31
34
|
# Integer('10', 10)
|
32
35
|
# Float('10.2')
|
33
36
|
# Complex('10')
|
37
|
+
# ['1', '2', '3'].map { |i| Integer(i, 10) }
|
38
|
+
# foo.try { |i| Float(i) }
|
39
|
+
# bar.send { |i| Complex(i) }
|
34
40
|
#
|
35
41
|
# @example IgnoredMethods: [minutes]
|
36
42
|
#
|
@@ -52,22 +58,33 @@ module RuboCop
|
|
52
58
|
}.freeze
|
53
59
|
MSG = 'Replace unsafe number conversion with number '\
|
54
60
|
'class parsing, instead of using '\
|
55
|
-
'%<
|
61
|
+
'%<current>s, use stricter '\
|
56
62
|
'%<corrected_method>s.'
|
57
|
-
|
63
|
+
METHODS = CONVERSION_METHOD_CLASS_MAPPING.keys.map(&:inspect).join(' ')
|
58
64
|
|
59
65
|
def_node_matcher :to_method, <<~PATTERN
|
60
|
-
(send $_ ${
|
66
|
+
(send $_ ${#{METHODS}})
|
67
|
+
PATTERN
|
68
|
+
|
69
|
+
def_node_matcher :to_method_symbol, <<~PATTERN
|
70
|
+
{(send _ $_ ${(sym ${#{METHODS}})} ...)
|
71
|
+
(send _ $_ ${(block_pass (sym ${#{METHODS}}))} ...)}
|
61
72
|
PATTERN
|
62
73
|
|
63
74
|
def on_send(node)
|
75
|
+
handle_conversion_method(node)
|
76
|
+
handle_as_symbol(node)
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
def handle_conversion_method(node)
|
64
82
|
to_method(node) do |receiver, to_method|
|
65
83
|
next if receiver.nil? || ignore_receiver?(receiver)
|
66
84
|
|
67
85
|
message = format(
|
68
86
|
MSG,
|
69
|
-
|
70
|
-
to_method: to_method,
|
87
|
+
current: "#{receiver.source}.#{to_method}",
|
71
88
|
corrected_method: correct_method(node, receiver)
|
72
89
|
)
|
73
90
|
add_offense(node, message: message) do |corrector|
|
@@ -76,13 +93,31 @@ module RuboCop
|
|
76
93
|
end
|
77
94
|
end
|
78
95
|
|
79
|
-
|
96
|
+
def handle_as_symbol(node)
|
97
|
+
to_method_symbol(node) do |receiver, sym_node, to_method|
|
98
|
+
next if receiver.nil?
|
99
|
+
|
100
|
+
message = format(
|
101
|
+
MSG,
|
102
|
+
current: sym_node.source,
|
103
|
+
corrected_method: correct_sym_method(to_method)
|
104
|
+
)
|
105
|
+
add_offense(node, message: message) do |corrector|
|
106
|
+
corrector.replace(sym_node, correct_sym_method(to_method))
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
80
110
|
|
81
111
|
def correct_method(node, receiver)
|
82
112
|
format(CONVERSION_METHOD_CLASS_MAPPING[node.method_name],
|
83
113
|
number_object: receiver.source)
|
84
114
|
end
|
85
115
|
|
116
|
+
def correct_sym_method(to_method)
|
117
|
+
body = format(CONVERSION_METHOD_CLASS_MAPPING[to_method], number_object: 'i')
|
118
|
+
"{ |i| #{body} }"
|
119
|
+
end
|
120
|
+
|
86
121
|
def ignore_receiver?(receiver)
|
87
122
|
if receiver.send_type? && ignored_method?(receiver.method_name)
|
88
123
|
true
|