rubocop 1.31.2 → 1.32.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/README.md +1 -1
- data/config/default.yml +23 -0
- data/lib/rubocop/cli.rb +1 -0
- data/lib/rubocop/config.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/useless_restrict_on_send.rb +7 -1
- data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +57 -13
- data/lib/rubocop/cop/layout/line_length.rb +2 -0
- data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +4 -1
- data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +45 -0
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +7 -0
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +10 -4
- data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +55 -24
- data/lib/rubocop/cop/lint/number_conversion.rb +7 -1
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +7 -0
- data/lib/rubocop/cop/lint/require_range_parentheses.rb +57 -0
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +35 -1
- data/lib/rubocop/cop/metrics/block_length.rb +1 -0
- data/lib/rubocop/cop/metrics/method_length.rb +1 -0
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +4 -0
- data/lib/rubocop/cop/mixin/percent_array.rb +60 -1
- data/lib/rubocop/cop/naming/predicate_name.rb +8 -0
- data/lib/rubocop/cop/style/class_equality_comparison.rb +22 -0
- data/lib/rubocop/cop/style/empty_else.rb +37 -0
- data/lib/rubocop/cop/style/empty_heredoc.rb +59 -0
- data/lib/rubocop/cop/style/fetch_env_var.rb +10 -177
- data/lib/rubocop/cop/style/format_string_token.rb +6 -0
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +2 -0
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +12 -0
- data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +9 -0
- data/lib/rubocop/cop/style/numeric_predicate.rb +20 -6
- data/lib/rubocop/cop/style/semicolon.rb +27 -3
- data/lib/rubocop/cop/style/symbol_array.rb +2 -3
- data/lib/rubocop/cop/style/symbol_proc.rb +9 -1
- data/lib/rubocop/cop/style/top_level_method_definition.rb +2 -0
- data/lib/rubocop/cop/style/trivial_accessors.rb +3 -0
- data/lib/rubocop/cop/style/word_array.rb +2 -3
- data/lib/rubocop/options.rb +3 -6
- data/lib/rubocop/rspec/shared_contexts.rb +14 -14
- data/lib/rubocop/rspec/support.rb +14 -0
- data/lib/rubocop/runner.rb +4 -0
- data/lib/rubocop/server/client_command/base.rb +1 -1
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +3 -0
- metadata +8 -5
@@ -46,6 +46,8 @@ module RuboCop
|
|
46
46
|
if node.send_type?
|
47
47
|
args = process_args(node.arguments)
|
48
48
|
return extract_breakable_node_from_elements(node, args, max)
|
49
|
+
elsif node.def_type?
|
50
|
+
return extract_breakable_node_from_elements(node, node.arguments, max)
|
49
51
|
elsif node.array_type? || node.hash_type?
|
50
52
|
return extract_breakable_node_from_elements(node, node.children, max)
|
51
53
|
end
|
@@ -216,6 +218,8 @@ module RuboCop
|
|
216
218
|
|
217
219
|
# @api private
|
218
220
|
def already_on_multiple_lines?(node)
|
221
|
+
return node.first_line != node.arguments.last.last_line if node.def_type?
|
222
|
+
|
219
223
|
node.first_line != node.last_line
|
220
224
|
end
|
221
225
|
end
|
@@ -44,13 +44,26 @@ module RuboCop
|
|
44
44
|
no_acceptable_style! if brackets_required
|
45
45
|
|
46
46
|
bracketed_array = build_bracketed_array(node)
|
47
|
-
message =
|
47
|
+
message = build_message_for_bracketed_array(bracketed_array)
|
48
48
|
|
49
49
|
add_offense(node, message: message) do |corrector|
|
50
50
|
corrector.replace(node, bracketed_array)
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
|
+
# @param [String] preferred_array_code
|
55
|
+
# @return [String]
|
56
|
+
def build_message_for_bracketed_array(preferred_array_code)
|
57
|
+
format(
|
58
|
+
self.class::ARRAY_MSG,
|
59
|
+
prefer: if preferred_array_code.include?("\n")
|
60
|
+
'an array literal `[...]`'
|
61
|
+
else
|
62
|
+
"`#{preferred_array_code}`"
|
63
|
+
end
|
64
|
+
)
|
65
|
+
end
|
66
|
+
|
54
67
|
def check_bracketed_array(node, literal_prefix)
|
55
68
|
return if allowed_bracket_array?(node)
|
56
69
|
|
@@ -63,6 +76,52 @@ module RuboCop
|
|
63
76
|
percent_literal_corrector.correct(corrector, node, literal_prefix)
|
64
77
|
end
|
65
78
|
end
|
79
|
+
|
80
|
+
# @param [RuboCop::AST::ArrayNode] node
|
81
|
+
# @param [Array<String>] elements
|
82
|
+
# @return [String]
|
83
|
+
def build_bracketed_array_with_appropriate_whitespace(elements:, node:)
|
84
|
+
[
|
85
|
+
'[',
|
86
|
+
whitespace_leading(node),
|
87
|
+
elements.join(",#{whitespace_between(node)}"),
|
88
|
+
whitespace_trailing(node),
|
89
|
+
']'
|
90
|
+
].join
|
91
|
+
end
|
92
|
+
|
93
|
+
# Provides whitespace between elements for building a bracketed array.
|
94
|
+
# %w[ a b c ]
|
95
|
+
# ^^^
|
96
|
+
# @param [RuboCop::AST::ArrayNode] node
|
97
|
+
# @return [String]
|
98
|
+
def whitespace_between(node)
|
99
|
+
if node.children.length >= 2
|
100
|
+
node.source[
|
101
|
+
node.children[0].loc.expression.end_pos...node.children[1].loc.expression.begin_pos
|
102
|
+
]
|
103
|
+
else
|
104
|
+
' '
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Provides leading whitespace for building a bracketed array.
|
109
|
+
# %w[ a b c ]
|
110
|
+
# ^^
|
111
|
+
# @param [RuboCop::AST::ArrayNode] node
|
112
|
+
# @return [String]
|
113
|
+
def whitespace_leading(node)
|
114
|
+
node.source[node.loc.begin.end_pos...node.children[0].loc.expression.begin_pos]
|
115
|
+
end
|
116
|
+
|
117
|
+
# Provides trailing whitespace for building a bracketed array.
|
118
|
+
# %w[ a b c ]
|
119
|
+
# ^^^^
|
120
|
+
# @param [RuboCop::AST::ArrayNode] node
|
121
|
+
# @return [String]
|
122
|
+
def whitespace_trailing(node)
|
123
|
+
node.source[node.children[-1].loc.expression.end_pos...node.loc.end.begin_pos]
|
124
|
+
end
|
66
125
|
end
|
67
126
|
end
|
68
127
|
end
|
@@ -4,6 +4,8 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module Naming
|
6
6
|
# Makes sure that predicates are named properly.
|
7
|
+
# `is_a?` method is allowed by default.
|
8
|
+
# These are customizable with `AllowedMethods` option.
|
7
9
|
#
|
8
10
|
# @example
|
9
11
|
# # bad
|
@@ -27,6 +29,12 @@ module RuboCop
|
|
27
29
|
# # good
|
28
30
|
# def value?
|
29
31
|
# end
|
32
|
+
#
|
33
|
+
# @example AllowedMethods: ['is_a?'] (default)
|
34
|
+
# # good
|
35
|
+
# def is_a?(value)
|
36
|
+
# end
|
37
|
+
#
|
30
38
|
class PredicateName < Base
|
31
39
|
include AllowedMethods
|
32
40
|
|
@@ -5,6 +5,8 @@ module RuboCop
|
|
5
5
|
module Style
|
6
6
|
# Enforces the use of `Object#instance_of?` instead of class comparison
|
7
7
|
# for equality.
|
8
|
+
# `==`, `equal?`, and `eql?` methods are ignored by default.
|
9
|
+
# These are customizable with `IgnoredMethods` option.
|
8
10
|
#
|
9
11
|
# @example
|
10
12
|
# # bad
|
@@ -16,6 +18,26 @@ module RuboCop
|
|
16
18
|
# # good
|
17
19
|
# var.instance_of?(Date)
|
18
20
|
#
|
21
|
+
# @example IgnoreMethods: [] (default)
|
22
|
+
# # good
|
23
|
+
# var.instance_of?(Date)
|
24
|
+
#
|
25
|
+
# # bad
|
26
|
+
# var.class == Date
|
27
|
+
# var.class.equal?(Date)
|
28
|
+
# var.class.eql?(Date)
|
29
|
+
# var.class.name == 'Date'
|
30
|
+
#
|
31
|
+
# @example IgnoreMethods: [`==`]
|
32
|
+
# # good
|
33
|
+
# var.instance_of?(Date)
|
34
|
+
# var.class == Date
|
35
|
+
# var.class.name == 'Date'
|
36
|
+
#
|
37
|
+
# # bad
|
38
|
+
# var.class.equal?(Date)
|
39
|
+
# var.class.eql?(Date)
|
40
|
+
#
|
19
41
|
class ClassEqualityComparison < Base
|
20
42
|
include RangeHelp
|
21
43
|
include IgnoredMethods
|
@@ -89,6 +89,41 @@ module RuboCop
|
|
89
89
|
# if condition
|
90
90
|
# statement
|
91
91
|
# end
|
92
|
+
#
|
93
|
+
# @example AllowComments: false (default)
|
94
|
+
#
|
95
|
+
# # bad
|
96
|
+
# if condition
|
97
|
+
# statement
|
98
|
+
# else
|
99
|
+
# # something comment
|
100
|
+
# nil
|
101
|
+
# end
|
102
|
+
#
|
103
|
+
# # bad
|
104
|
+
# if condition
|
105
|
+
# statement
|
106
|
+
# else
|
107
|
+
# # something comment
|
108
|
+
# end
|
109
|
+
#
|
110
|
+
# @example AllowComments: true
|
111
|
+
#
|
112
|
+
# # good
|
113
|
+
# if condition
|
114
|
+
# statement
|
115
|
+
# else
|
116
|
+
# # something comment
|
117
|
+
# nil
|
118
|
+
# end
|
119
|
+
#
|
120
|
+
# # good
|
121
|
+
# if condition
|
122
|
+
# statement
|
123
|
+
# else
|
124
|
+
# # something comment
|
125
|
+
# end
|
126
|
+
#
|
92
127
|
class EmptyElse < Base
|
93
128
|
include OnNormalIfUnless
|
94
129
|
include ConfigurableEnforcedStyle
|
@@ -108,6 +143,8 @@ module RuboCop
|
|
108
143
|
private
|
109
144
|
|
110
145
|
def check(node)
|
146
|
+
return if cop_config['AllowComments'] && comment_in_else?(node.loc)
|
147
|
+
|
111
148
|
empty_check(node) if empty_style?
|
112
149
|
nil_check(node) if nil_style?
|
113
150
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Checks for using empty heredoc to reduce redundancy.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
#
|
10
|
+
# # bad
|
11
|
+
# <<~EOS
|
12
|
+
# EOS
|
13
|
+
#
|
14
|
+
# <<-EOS
|
15
|
+
# EOS
|
16
|
+
#
|
17
|
+
# <<EOS
|
18
|
+
# EOS
|
19
|
+
#
|
20
|
+
# # good
|
21
|
+
# ''
|
22
|
+
#
|
23
|
+
# # bad
|
24
|
+
# do_something(<<~EOS)
|
25
|
+
# EOS
|
26
|
+
#
|
27
|
+
# do_something(<<-EOS)
|
28
|
+
# EOS
|
29
|
+
#
|
30
|
+
# do_something(<<EOS)
|
31
|
+
# EOS
|
32
|
+
#
|
33
|
+
# # good
|
34
|
+
# do_something('')
|
35
|
+
#
|
36
|
+
class EmptyHeredoc < Base
|
37
|
+
include Heredoc
|
38
|
+
include RangeHelp
|
39
|
+
extend AutoCorrector
|
40
|
+
|
41
|
+
MSG = 'Use an empty string literal instead of heredoc.'
|
42
|
+
|
43
|
+
def on_heredoc(node)
|
44
|
+
heredoc_body = node.loc.heredoc_body
|
45
|
+
|
46
|
+
return unless heredoc_body.source.empty?
|
47
|
+
|
48
|
+
add_offense(node) do |corrector|
|
49
|
+
heredoc_end = node.loc.heredoc_end
|
50
|
+
|
51
|
+
corrector.replace(node, "''")
|
52
|
+
corrector.remove(range_by_whole_lines(heredoc_body, include_final_newline: true))
|
53
|
+
corrector.remove(range_by_whole_lines(heredoc_end, include_final_newline: true))
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -9,32 +9,15 @@ module RuboCop
|
|
9
9
|
# On the other hand, `ENV.fetch` raises KeyError or returns the explicitly
|
10
10
|
# specified default value.
|
11
11
|
#
|
12
|
-
# When an `ENV[]` is the LHS of `||`, the autocorrect makes the RHS
|
13
|
-
# the default value of `ENV.fetch`.
|
14
|
-
#
|
15
12
|
# @example
|
16
13
|
# # bad
|
17
14
|
# ENV['X']
|
18
|
-
# ENV['X'] || 'string literal'
|
19
|
-
# ENV['X'] || some_method
|
20
15
|
# x = ENV['X']
|
21
16
|
#
|
22
|
-
# ENV['X'] || y.map do |a|
|
23
|
-
# puts a * 2
|
24
|
-
# end
|
25
|
-
#
|
26
17
|
# # good
|
27
18
|
# ENV.fetch('X')
|
28
|
-
# ENV.fetch('X', 'string literal')
|
29
|
-
# ENV.fetch('X') { some_method }
|
30
19
|
# x = ENV.fetch('X')
|
31
20
|
#
|
32
|
-
# ENV.fetch('X') do
|
33
|
-
# y.map do |a|
|
34
|
-
# puts a * 2
|
35
|
-
# end
|
36
|
-
# end
|
37
|
-
#
|
38
21
|
# # also good
|
39
22
|
# !ENV['X']
|
40
23
|
# ENV['X'].some_method # (e.g. `.nil?`)
|
@@ -42,48 +25,20 @@ module RuboCop
|
|
42
25
|
class FetchEnvVar < Base
|
43
26
|
extend AutoCorrector
|
44
27
|
|
45
|
-
|
46
|
-
MSG_DEFAULT_NIL = 'Use `ENV.fetch(%<key>s)` or `ENV.fetch(%<key>s, nil)` instead of `ENV[%<key>s]`.'
|
47
|
-
MSG_DEFAULT_RHS_SECOND_ARG_OF_FETCH = 'Use `ENV.fetch(%<key>s, %<default>s)` instead of `ENV[%<key>s] || %<default>s`.'
|
48
|
-
MSG_DEFAULT_RHS_SINGLE_LINE_BLOCK = 'Use `ENV.fetch(%<key>s) { %<default>s }` instead of `ENV[%<key>s] || %<default>s`.'
|
49
|
-
MSG_DEFAULT_RHS_MULTILINE_BLOCK = 'Use `ENV.fetch(%<key>s)` with a block containing `%<default>s ...`'
|
50
|
-
# rubocop:enable Layout/LineLength
|
28
|
+
MSG = 'Use `ENV.fetch(%<key>s)` or `ENV.fetch(%<key>s, nil)` instead of `ENV[%<key>s]`.'
|
51
29
|
|
52
30
|
# @!method env_with_bracket?(node)
|
53
31
|
def_node_matcher :env_with_bracket?, <<~PATTERN
|
54
32
|
(send (const nil? :ENV) :[] $_)
|
55
33
|
PATTERN
|
56
34
|
|
57
|
-
# @!method operand_of_or?(node)
|
58
|
-
def_node_matcher :operand_of_or?, <<~PATTERN
|
59
|
-
(^or ...)
|
60
|
-
PATTERN
|
61
|
-
|
62
|
-
# @!method block_control?(node)
|
63
|
-
def_node_matcher :block_control?, <<~PATTERN
|
64
|
-
({next | break | retry | redo})
|
65
|
-
PATTERN
|
66
|
-
|
67
|
-
# @!method offensive_nodes(node)
|
68
|
-
def_node_search :offensive_nodes, <<~PATTERN
|
69
|
-
[#env_with_bracket? #offensive?]
|
70
|
-
PATTERN
|
71
|
-
|
72
35
|
def on_send(node)
|
73
36
|
env_with_bracket?(node) do |name_node|
|
74
37
|
break unless offensive?(node)
|
75
38
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
if default_to_rhs?(target_node)
|
81
|
-
default_rhs(target_node, target_name_node)
|
82
|
-
else
|
83
|
-
default_nil(target_node, target_name_node)
|
84
|
-
end
|
85
|
-
else
|
86
|
-
default_nil(node, name_node)
|
39
|
+
message = format(MSG, key: name_node.source)
|
40
|
+
add_offense(node, message: message) do |corrector|
|
41
|
+
corrector.replace(node, new_code(name_node))
|
87
42
|
end
|
88
43
|
end
|
89
44
|
end
|
@@ -130,17 +85,6 @@ module RuboCop
|
|
130
85
|
!(allowed_var?(node) || allowable_use?(node))
|
131
86
|
end
|
132
87
|
|
133
|
-
def or_chain_root(node)
|
134
|
-
while operand_of_or?(ancestor_or ||= node.parent)
|
135
|
-
ancestor_or = ancestor_or.parent
|
136
|
-
end
|
137
|
-
ancestor_or
|
138
|
-
end
|
139
|
-
|
140
|
-
def default_to_rhs?(node)
|
141
|
-
operand_of_or?(node) && !right_end_of_or_chains?(node) && rhs_can_be_default_value?(node)
|
142
|
-
end
|
143
|
-
|
144
88
|
# Check if the node is a receiver and receives a message with dot syntax.
|
145
89
|
def message_chained_with_dot?(node)
|
146
90
|
return false if node.root?
|
@@ -157,8 +101,9 @@ module RuboCop
|
|
157
101
|
# it simply checks whether the variable is set.
|
158
102
|
# - Receiving a message with dot syntax, e.g. `ENV['X'].nil?`.
|
159
103
|
# - `ENV['key']` assigned by logical AND/OR assignment.
|
104
|
+
# - `ENV['key']` is the LHS of a `||`.
|
160
105
|
def allowable_use?(node)
|
161
|
-
used_as_flag?(node) || message_chained_with_dot?(node) || assigned?(node)
|
106
|
+
used_as_flag?(node) || message_chained_with_dot?(node) || assigned?(node) || or_lhs?(node)
|
162
107
|
end
|
163
108
|
|
164
109
|
# The following are allowed cases:
|
@@ -172,127 +117,15 @@ module RuboCop
|
|
172
117
|
node == lhs
|
173
118
|
end
|
174
119
|
|
175
|
-
def
|
176
|
-
return false unless
|
177
|
-
|
178
|
-
node.parent.lhs == node
|
179
|
-
end
|
180
|
-
|
181
|
-
def right_end_of_or_chains?(node)
|
182
|
-
!(left_end_of_or_chains?(node) || node.parent&.parent&.or_type?)
|
183
|
-
end
|
184
|
-
|
185
|
-
def conterpart_rhs_of(node)
|
186
|
-
left_end_of_or_chains?(node) ? node.parent.rhs : node.parent.parent.rhs
|
187
|
-
end
|
188
|
-
|
189
|
-
def rhs_can_be_default_value?(node)
|
190
|
-
!rhs_is_block_control?(node)
|
191
|
-
end
|
120
|
+
def or_lhs?(node)
|
121
|
+
return false unless (parent = node.parent)&.or_type?
|
192
122
|
|
193
|
-
|
194
|
-
block_control?(conterpart_rhs_of(node))
|
123
|
+
parent.lhs == node || parent.parent&.or_type?
|
195
124
|
end
|
196
125
|
|
197
|
-
def
|
126
|
+
def new_code(name_node)
|
198
127
|
"ENV.fetch(#{name_node.source}, nil)"
|
199
128
|
end
|
200
|
-
|
201
|
-
def new_code_default_rhs_single_line(node, name_node)
|
202
|
-
parent = node.parent
|
203
|
-
if parent.rhs.basic_literal?
|
204
|
-
"ENV.fetch(#{name_node.source}, #{parent.rhs.source})"
|
205
|
-
else
|
206
|
-
"ENV.fetch(#{name_node.source}) { #{parent.rhs.source} }"
|
207
|
-
end
|
208
|
-
end
|
209
|
-
|
210
|
-
def new_code_default_rhs_multiline(node, name_node)
|
211
|
-
env_indent = indent(node.parent)
|
212
|
-
default = node.parent.rhs.source.split("\n").map do |line|
|
213
|
-
"#{env_indent}#{line}"
|
214
|
-
end.join("\n")
|
215
|
-
<<~NEW_CODE.chomp
|
216
|
-
ENV.fetch(#{name_node.source}) do
|
217
|
-
#{configured_indentation}#{default}
|
218
|
-
#{env_indent}end
|
219
|
-
NEW_CODE
|
220
|
-
end
|
221
|
-
|
222
|
-
def new_code_default_rhs(node, name_node)
|
223
|
-
if node.parent.rhs.single_line?
|
224
|
-
new_code_default_rhs_single_line(node, name_node)
|
225
|
-
else
|
226
|
-
new_code_default_rhs_multiline(node, name_node)
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
|
-
def default_rhs(node, name_node)
|
231
|
-
if left_end_of_or_chains?(node)
|
232
|
-
default_rhs_in_same_or(node, name_node)
|
233
|
-
else
|
234
|
-
default_rhs_in_outer_or(node, name_node)
|
235
|
-
end
|
236
|
-
end
|
237
|
-
|
238
|
-
# Adds an offense and sets `nil` to the default value of `ENV.fetch`.
|
239
|
-
# `ENV['X']` --> `ENV.fetch('X', nil)`
|
240
|
-
def default_nil(node, name_node)
|
241
|
-
message = format(MSG_DEFAULT_NIL, key: name_node.source)
|
242
|
-
|
243
|
-
add_offense(node, message: message) do |corrector|
|
244
|
-
corrector.replace(node, new_code_default_nil(name_node))
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
# Adds an offense and makes the RHS the default value of `ENV.fetch`.
|
249
|
-
# `ENV['X'] || y` --> `ENV.fetch('X') { y }`
|
250
|
-
def default_rhs_in_same_or(node, name_node)
|
251
|
-
template = message_template_for(node.parent.rhs)
|
252
|
-
message = format(template,
|
253
|
-
key: name_node.source,
|
254
|
-
default: first_line_of(node.parent.rhs.source))
|
255
|
-
|
256
|
-
add_offense(node, message: message) do |corrector|
|
257
|
-
corrector.replace(node.parent, new_code_default_rhs(node, name_node))
|
258
|
-
end
|
259
|
-
end
|
260
|
-
|
261
|
-
# Adds an offense and makes the RHS the default value of `ENV.fetch`.
|
262
|
-
# `z || ENV['X'] || y` --> `z || ENV.fetch('X') { y }`
|
263
|
-
def default_rhs_in_outer_or(node, name_node)
|
264
|
-
parent = node.parent
|
265
|
-
grand_parent = parent.parent
|
266
|
-
|
267
|
-
template = message_template_for(grand_parent.rhs)
|
268
|
-
message = format(template,
|
269
|
-
key: name_node.source,
|
270
|
-
default: first_line_of(grand_parent.rhs.source))
|
271
|
-
|
272
|
-
add_offense(node, message: message) do |corrector|
|
273
|
-
lhs_code = parent.lhs.source
|
274
|
-
rhs_code = new_code_default_rhs(parent, name_node)
|
275
|
-
corrector.replace(grand_parent, "#{lhs_code} || #{rhs_code}")
|
276
|
-
end
|
277
|
-
end
|
278
|
-
|
279
|
-
def message_template_for(rhs)
|
280
|
-
if rhs.multiline?
|
281
|
-
MSG_DEFAULT_RHS_MULTILINE_BLOCK
|
282
|
-
elsif rhs.basic_literal?
|
283
|
-
MSG_DEFAULT_RHS_SECOND_ARG_OF_FETCH
|
284
|
-
else
|
285
|
-
MSG_DEFAULT_RHS_SINGLE_LINE_BLOCK
|
286
|
-
end
|
287
|
-
end
|
288
|
-
|
289
|
-
def configured_indentation
|
290
|
-
' ' * (config.for_cop('Layout/IndentationWidth')['Width'] || 2)
|
291
|
-
end
|
292
|
-
|
293
|
-
def first_line_of(source)
|
294
|
-
source.split("\n").first
|
295
|
-
end
|
296
129
|
end
|
297
130
|
end
|
298
131
|
end
|
@@ -12,6 +12,7 @@ module RuboCop
|
|
12
12
|
# to encoded URLs or Date/Time formatting strings.
|
13
13
|
#
|
14
14
|
# This cop can be customized ignored methods with `IgnoredMethods`.
|
15
|
+
# By default, there are no methods to ignored.
|
15
16
|
#
|
16
17
|
# @example EnforcedStyle: annotated (default)
|
17
18
|
#
|
@@ -61,6 +62,11 @@ module RuboCop
|
|
61
62
|
# # good
|
62
63
|
# format('%06d', 10)
|
63
64
|
#
|
65
|
+
# @example IgnoredMethods: [] (default)
|
66
|
+
#
|
67
|
+
# # bad
|
68
|
+
# redirect('foo/%{bar_id}')
|
69
|
+
#
|
64
70
|
# @example IgnoredMethods: [redirect]
|
65
71
|
#
|
66
72
|
# # good
|
@@ -6,6 +6,8 @@ module RuboCop
|
|
6
6
|
# 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
|
+
# `nonzero?` method is allowed by default.
|
10
|
+
# These are customizable with `AllowedMethods` option.
|
9
11
|
#
|
10
12
|
# @safety
|
11
13
|
# Autocorrection is unsafe because there is no guarantee that all predicate methods
|
@@ -5,12 +5,24 @@ module RuboCop
|
|
5
5
|
module Style
|
6
6
|
# Checks for unwanted parentheses in parameterless method calls.
|
7
7
|
#
|
8
|
+
# This cop can be customized ignored methods with `IgnoredMethods`.
|
9
|
+
# By default, there are no methods to ignored.
|
10
|
+
#
|
8
11
|
# @example
|
9
12
|
# # bad
|
10
13
|
# object.some_method()
|
11
14
|
#
|
12
15
|
# # good
|
13
16
|
# object.some_method
|
17
|
+
#
|
18
|
+
# @example IgnoredMethods: [] (default)
|
19
|
+
# # bad
|
20
|
+
# object.foo()
|
21
|
+
#
|
22
|
+
# @example IgnoredMethods: [foo]
|
23
|
+
# # good
|
24
|
+
# object.foo()
|
25
|
+
#
|
14
26
|
class MethodCallWithoutArgsParentheses < Base
|
15
27
|
include IgnoredMethods
|
16
28
|
extend AutoCorrector
|
@@ -5,6 +5,10 @@ module RuboCop
|
|
5
5
|
module Style
|
6
6
|
# Checks for unparenthesized method calls in the argument list
|
7
7
|
# of a parenthesized method call.
|
8
|
+
# `be`, `be_a`, `be_an`, `be_between`, `be_falsey`, `be_kind_of`, `be_instance_of`,
|
9
|
+
# `be_truthy`, `be_within`, `eq`, `eql`, `end_with`, `include`, `match`, `raise_error`,
|
10
|
+
# `respond_to`, and `start_with` methods are allowed by default.
|
11
|
+
# These are customizable with `AllowedMethods` option.
|
8
12
|
#
|
9
13
|
# @example
|
10
14
|
# # good
|
@@ -12,6 +16,11 @@ module RuboCop
|
|
12
16
|
#
|
13
17
|
# # bad
|
14
18
|
# method1(method2 arg)
|
19
|
+
#
|
20
|
+
# @example AllowedMethods: [foo]
|
21
|
+
# # good
|
22
|
+
# method1(foo arg)
|
23
|
+
#
|
15
24
|
class NestedParenthesizedCalls < Base
|
16
25
|
include RangeHelp
|
17
26
|
include AllowedMethods
|
@@ -6,13 +6,16 @@ module RuboCop
|
|
6
6
|
# Checks for usage of comparison operators (`==`,
|
7
7
|
# `>`, `<`) to test numbers as zero, positive, or negative.
|
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
|
-
#
|
11
|
+
# This cop can be customized ignored methods with `IgnoredMethods`.
|
12
|
+
# By default, there are no methods to ignored.
|
13
|
+
#
|
14
|
+
# This cop disregards `#nonzero?` as its value is truthy or falsey,
|
12
15
|
# but not `true` and `false`, and thus not always interchangeable with
|
13
16
|
# `!= 0`.
|
14
17
|
#
|
15
|
-
#
|
18
|
+
# This cop ignores comparisons to global variables, since they are often
|
16
19
|
# populated with objects which can be compared with integers, but are
|
17
20
|
# not themselves `Integer` polymorphic.
|
18
21
|
#
|
@@ -23,29 +26,40 @@ module RuboCop
|
|
23
26
|
#
|
24
27
|
# @example EnforcedStyle: predicate (default)
|
25
28
|
# # bad
|
26
|
-
#
|
27
29
|
# foo == 0
|
28
30
|
# 0 > foo
|
29
31
|
# bar.baz > 0
|
30
32
|
#
|
31
33
|
# # good
|
32
|
-
#
|
33
34
|
# foo.zero?
|
34
35
|
# foo.negative?
|
35
36
|
# bar.baz.positive?
|
36
37
|
#
|
37
38
|
# @example EnforcedStyle: comparison
|
38
39
|
# # bad
|
39
|
-
#
|
40
40
|
# foo.zero?
|
41
41
|
# foo.negative?
|
42
42
|
# bar.baz.positive?
|
43
43
|
#
|
44
44
|
# # good
|
45
|
+
# foo == 0
|
46
|
+
# 0 > foo
|
47
|
+
# bar.baz > 0
|
48
|
+
#
|
49
|
+
# @example IgnoredMethods: [] (default) with EnforcedStyle: predicate
|
50
|
+
# # bad
|
51
|
+
# foo == 0
|
52
|
+
# 0 > foo
|
53
|
+
# bar.baz > 0
|
45
54
|
#
|
55
|
+
# @example IgnoredMethods: [==] with EnforcedStyle: predicate
|
56
|
+
# # good
|
46
57
|
# foo == 0
|
58
|
+
#
|
59
|
+
# # bad
|
47
60
|
# 0 > foo
|
48
61
|
# bar.baz > 0
|
62
|
+
#
|
49
63
|
class NumericPredicate < Base
|
50
64
|
include ConfigurableEnforcedStyle
|
51
65
|
include IgnoredMethods
|