rubocop 1.71.2 → 1.72.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 +1 -1
- data/config/default.yml +28 -0
- data/lib/rubocop/cli/command/suggest_extensions.rb +7 -1
- data/lib/rubocop/comment_config.rb +1 -1
- data/lib/rubocop/config.rb +4 -0
- data/lib/rubocop/config_loader.rb +44 -8
- data/lib/rubocop/config_loader_resolver.rb +21 -7
- data/lib/rubocop/cop/internal_affairs/location_exists.rb +116 -0
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/plugin.rb +33 -0
- data/lib/rubocop/cop/internal_affairs/undefined_config.rb +7 -1
- data/lib/rubocop/cop/internal_affairs.rb +1 -16
- data/lib/rubocop/cop/layout/block_alignment.rb +2 -0
- data/lib/rubocop/cop/layout/else_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +22 -2
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
- data/lib/rubocop/cop/lint/cop_directive_syntax.rb +84 -0
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_type_conversion.rb +231 -0
- data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +111 -0
- data/lib/rubocop/cop/lint/useless_constant_scoping.rb +74 -0
- data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +7 -7
- data/lib/rubocop/cop/mixin/alignment.rb +2 -2
- data/lib/rubocop/cop/mixin/comments_help.rb +1 -1
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +18 -18
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +74 -74
- data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
- data/lib/rubocop/cop/mixin/range_help.rb +3 -3
- data/lib/rubocop/cop/mixin/string_help.rb +1 -1
- data/lib/rubocop/cop/naming/predicate_name.rb +44 -0
- data/lib/rubocop/cop/style/redundant_format.rb +222 -0
- data/lib/rubocop/cop/style/redundant_parentheses.rb +19 -3
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/cop/utils/format_string.rb +7 -5
- data/lib/rubocop/directive_comment.rb +35 -2
- data/lib/rubocop/lsp/runtime.rb +2 -0
- data/lib/rubocop/lsp/server.rb +0 -2
- data/lib/rubocop/options.rb +26 -11
- data/lib/rubocop/path_util.rb +4 -0
- data/lib/rubocop/plugin/configuration_integrator.rb +141 -0
- data/lib/rubocop/plugin/load_error.rb +26 -0
- data/lib/rubocop/plugin/loader.rb +100 -0
- data/lib/rubocop/plugin/not_supported_error.rb +29 -0
- data/lib/rubocop/plugin.rb +39 -0
- data/lib/rubocop/rake_task.rb +4 -1
- data/lib/rubocop/rspec/cop_helper.rb +7 -0
- data/lib/rubocop/server/cache.rb +35 -2
- data/lib/rubocop/server/cli.rb +2 -2
- data/lib/rubocop/version.rb +17 -2
- data/lib/rubocop.rb +5 -0
- data/lib/ruby_lsp/rubocop/addon.rb +7 -10
- data/lib/ruby_lsp/rubocop/{wraps_built_in_lsp_runtime.rb → runtime_adapter.rb} +5 -8
- metadata +35 -9
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# rubocop:disable Lint/RedundantCopDisableDirective
|
4
|
+
# rubocop:disable Style/DoubleCopDisableDirective
|
5
|
+
module RuboCop
|
6
|
+
module Cop
|
7
|
+
module Lint
|
8
|
+
# Checks that `# rubocop:enable ...` and `# rubocop:disable ...` statements
|
9
|
+
# are strictly formatted.
|
10
|
+
#
|
11
|
+
# A comment can be added to the directive by prefixing it with `--`.
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
# # bad
|
15
|
+
# # rubocop:disable Layout/LineLength Style/Encoding
|
16
|
+
# # ^ missing comma
|
17
|
+
#
|
18
|
+
# # bad
|
19
|
+
# # rubocop:disable
|
20
|
+
#
|
21
|
+
# # bad
|
22
|
+
# # rubocop:disable Layout/LineLength # rubocop:disable Style/Encoding
|
23
|
+
#
|
24
|
+
# # bad
|
25
|
+
# # rubocop:wrongmode Layout/LineLength
|
26
|
+
#
|
27
|
+
# # good
|
28
|
+
# # rubocop:disable Layout/LineLength
|
29
|
+
#
|
30
|
+
# # good
|
31
|
+
# # rubocop:disable Layout/LineLength, Style/Encoding
|
32
|
+
#
|
33
|
+
# # good
|
34
|
+
# # rubocop:disable all
|
35
|
+
#
|
36
|
+
# # good
|
37
|
+
# # rubocop:disable Layout/LineLength -- This is a good comment.
|
38
|
+
#
|
39
|
+
class CopDirectiveSyntax < Base
|
40
|
+
COMMON_MSG = 'Malformed directive comment detected.'
|
41
|
+
|
42
|
+
MISSING_MODE_NAME_MSG = 'The mode name is missing.'
|
43
|
+
INVALID_MODE_NAME_MSG = 'The mode name must be one of `enable`, `disable`, or `todo`.'
|
44
|
+
MISSING_COP_NAME_MSG = 'The cop name is missing.'
|
45
|
+
MALFORMED_COP_NAMES_MSG = 'Cop names must be separated by commas. ' \
|
46
|
+
'Comment in the directive must start with `--`.'
|
47
|
+
|
48
|
+
def on_new_investigation
|
49
|
+
processed_source.comments.each do |comment|
|
50
|
+
directive_comment = DirectiveComment.new(comment)
|
51
|
+
next unless directive_comment.start_with_marker?
|
52
|
+
next unless directive_comment.malformed?
|
53
|
+
|
54
|
+
message = offense_message(directive_comment)
|
55
|
+
add_offense(comment, message: message)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
# rubocop:disable Metrics/MethodLength
|
62
|
+
def offense_message(directive_comment)
|
63
|
+
comment = directive_comment.comment
|
64
|
+
after_marker = comment.text.sub(DirectiveComment::DIRECTIVE_MARKER_REGEXP, '')
|
65
|
+
mode = after_marker.split(' ', 2).first
|
66
|
+
additional_msg = if mode.nil?
|
67
|
+
MISSING_MODE_NAME_MSG
|
68
|
+
elsif !DirectiveComment::AVAILABLE_MODES.include?(mode)
|
69
|
+
INVALID_MODE_NAME_MSG
|
70
|
+
elsif directive_comment.missing_cop_name?
|
71
|
+
MISSING_COP_NAME_MSG
|
72
|
+
else
|
73
|
+
MALFORMED_COP_NAMES_MSG
|
74
|
+
end
|
75
|
+
|
76
|
+
"#{COMMON_MSG} #{additional_msg}"
|
77
|
+
end
|
78
|
+
# rubocop:enable Metrics/MethodLength
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
# rubocop:enable Lint/RedundantCopDisableDirective
|
84
|
+
# rubocop:enable Style/DoubleCopDisableDirective
|
@@ -7,7 +7,7 @@ module RuboCop
|
|
7
7
|
# expected fields for format/sprintf/#% and what is actually
|
8
8
|
# passed as arguments.
|
9
9
|
#
|
10
|
-
# In addition it checks whether different formats are used in the same
|
10
|
+
# In addition, it checks whether different formats are used in the same
|
11
11
|
# format string. Do not mix numbered, unnumbered, and named formats in
|
12
12
|
# the same format string.
|
13
13
|
#
|
@@ -0,0 +1,231 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
# Checks for redundant uses of `to_s`, `to_sym`, `to_i`, `to_f`, `to_r`, `to_c`,
|
7
|
+
# `to_a`, `to_h`, and `to_set`.
|
8
|
+
#
|
9
|
+
# When one of these methods is called on an object of the same type, that object
|
10
|
+
# is returned, making the call unnecessary. The cop detects conversion methods called
|
11
|
+
# on object literals, class constructors, class `[]` methods, and the `Kernel` methods
|
12
|
+
# `String()`, `Integer()`, `Float()`, `Rational()`, `Complex()` and `Array()`.
|
13
|
+
#
|
14
|
+
# Specifically, these cases are detected for each conversion method:
|
15
|
+
#
|
16
|
+
# * `to_s` when called on a string literal, interpolated string, heredoc,
|
17
|
+
# or with `String.new` or `String()`.
|
18
|
+
# * `to_sym` when called on a symbol literal or interpolated symbol.
|
19
|
+
# * `to_i` when called on an integer literal or with `Integer()`.
|
20
|
+
# * `to_f` when called on a float literal of with `Float()`.
|
21
|
+
# * `to_r` when called on a rational literal or with `Rational()`.
|
22
|
+
# * `to_c` when called on a complex literal of with `Complex()`.
|
23
|
+
# * `to_a` when called on an array literal, or with `Array.new`, `Array()` or `Array[]`.
|
24
|
+
# * `to_h` when called on a hash literal, or with `Hash.new`, `Hash()` or `Hash[]`.
|
25
|
+
# * `to_set` when called on `Set.new` or `Set[]`.
|
26
|
+
#
|
27
|
+
# In all cases, chaining one same `to_*` conversion methods listed above is redundant.
|
28
|
+
#
|
29
|
+
# The cop can also register an offense for chaining conversion methods on methods that are
|
30
|
+
# expected to return a specific type regardless of receiver (eg. `foo.inspect.to_s`).
|
31
|
+
#
|
32
|
+
# @example
|
33
|
+
# # bad
|
34
|
+
# "text".to_s
|
35
|
+
# :sym.to_sym
|
36
|
+
# 42.to_i
|
37
|
+
# 8.5.to_f
|
38
|
+
# 12r.to_r
|
39
|
+
# 1i.to_c
|
40
|
+
# [].to_a
|
41
|
+
# {}.to_h
|
42
|
+
# Set.new.to_s
|
43
|
+
#
|
44
|
+
# # good
|
45
|
+
# "text"
|
46
|
+
# :sym
|
47
|
+
# 42
|
48
|
+
# 8.5
|
49
|
+
# 12r
|
50
|
+
# 1i
|
51
|
+
# []
|
52
|
+
# {}
|
53
|
+
# Set.new
|
54
|
+
#
|
55
|
+
# # bad - chaining the same conversion
|
56
|
+
# foo.to_s.to_s
|
57
|
+
#
|
58
|
+
# # good
|
59
|
+
# foo.to_s
|
60
|
+
#
|
61
|
+
# # bad - chaining a conversion to a method that is expected to return the same type
|
62
|
+
# inspect.to_s
|
63
|
+
#
|
64
|
+
# # good
|
65
|
+
# inspect
|
66
|
+
#
|
67
|
+
class RedundantTypeConversion < Base
|
68
|
+
extend AutoCorrector
|
69
|
+
|
70
|
+
MSG = 'Redundant `%<method>s` detected.'
|
71
|
+
|
72
|
+
# Maps conversion methods to the node types for the literals of that type
|
73
|
+
LITERAL_NODE_TYPES = {
|
74
|
+
to_s: %i[str dstr],
|
75
|
+
to_sym: %i[sym dsym],
|
76
|
+
to_i: %i[int],
|
77
|
+
to_f: %i[float],
|
78
|
+
to_r: %i[rational],
|
79
|
+
to_c: %i[complex],
|
80
|
+
to_a: %i[array],
|
81
|
+
to_h: %i[hash],
|
82
|
+
to_set: [] # sets don't have a literal or node type
|
83
|
+
}.freeze
|
84
|
+
|
85
|
+
# Maps each conversion method to the pattern matcher for that type's constructors
|
86
|
+
# Not every type has a constructor, for instance Symbol.
|
87
|
+
CONSTRUCTOR_MAPPING = {
|
88
|
+
to_s: 'string_constructor?',
|
89
|
+
to_i: 'integer_constructor?',
|
90
|
+
to_f: 'float_constructor?',
|
91
|
+
to_r: 'rational_constructor?',
|
92
|
+
to_c: 'complex_constructor?',
|
93
|
+
to_a: 'array_constructor?',
|
94
|
+
to_h: 'hash_constructor?',
|
95
|
+
to_set: 'set_constructor?'
|
96
|
+
}.freeze
|
97
|
+
|
98
|
+
# Methods that already are expected to return a given type, which makes a further
|
99
|
+
# conversion redundant.
|
100
|
+
TYPED_METHODS = { to_s: %i[inspect] }.freeze
|
101
|
+
|
102
|
+
CONVERSION_METHODS = Set[*LITERAL_NODE_TYPES.keys].freeze
|
103
|
+
RESTRICT_ON_SEND = CONVERSION_METHODS
|
104
|
+
|
105
|
+
private_constant :LITERAL_NODE_TYPES, :CONSTRUCTOR_MAPPING
|
106
|
+
|
107
|
+
# @!method type_constructor?(node, type_symbol)
|
108
|
+
def_node_matcher :type_constructor?, <<~PATTERN
|
109
|
+
(send {nil? (const {cbase nil?} :Kernel)} %1 ...)
|
110
|
+
PATTERN
|
111
|
+
|
112
|
+
# @!method string_constructor?(node)
|
113
|
+
def_node_matcher :string_constructor?, <<~PATTERN
|
114
|
+
{
|
115
|
+
(send (const {cbase nil?} :String) :new ...)
|
116
|
+
#type_constructor?(:String)
|
117
|
+
}
|
118
|
+
PATTERN
|
119
|
+
|
120
|
+
# @!method integer_constructor?(node)
|
121
|
+
def_node_matcher :integer_constructor?, <<~PATTERN
|
122
|
+
#type_constructor?(:Integer)
|
123
|
+
PATTERN
|
124
|
+
|
125
|
+
# @!method float_constructor?(node)
|
126
|
+
def_node_matcher :float_constructor?, <<~PATTERN
|
127
|
+
#type_constructor?(:Float)
|
128
|
+
PATTERN
|
129
|
+
|
130
|
+
# @!method rational_constructor?(node)
|
131
|
+
def_node_matcher :rational_constructor?, <<~PATTERN
|
132
|
+
#type_constructor?(:Rational)
|
133
|
+
PATTERN
|
134
|
+
|
135
|
+
# @!method complex_constructor?(node)
|
136
|
+
def_node_matcher :complex_constructor?, <<~PATTERN
|
137
|
+
#type_constructor?(:Complex)
|
138
|
+
PATTERN
|
139
|
+
|
140
|
+
# @!method array_constructor?(node)
|
141
|
+
def_node_matcher :array_constructor?, <<~PATTERN
|
142
|
+
{
|
143
|
+
(send (const {cbase nil?} :Array) {:new :[]} ...)
|
144
|
+
#type_constructor?(:Array)
|
145
|
+
}
|
146
|
+
PATTERN
|
147
|
+
|
148
|
+
# @!method hash_constructor?(node)
|
149
|
+
def_node_matcher :hash_constructor?, <<~PATTERN
|
150
|
+
{
|
151
|
+
(block (send (const {cbase nil?} :Hash) :new) ...)
|
152
|
+
(send (const {cbase nil?} :Hash) {:new :[]} ...)
|
153
|
+
(send {nil? (const {cbase nil?} :Kernel)} :Hash ...)
|
154
|
+
}
|
155
|
+
PATTERN
|
156
|
+
|
157
|
+
# @!method set_constructor?(node)
|
158
|
+
def_node_matcher :set_constructor?, <<~PATTERN
|
159
|
+
{
|
160
|
+
(send (const {cbase nil?} :Set) {:new :[]} ...)
|
161
|
+
}
|
162
|
+
PATTERN
|
163
|
+
|
164
|
+
# rubocop:disable Metrics/AbcSize
|
165
|
+
def on_send(node)
|
166
|
+
return if hash_or_set_with_block?(node)
|
167
|
+
|
168
|
+
receiver = find_receiver(node)
|
169
|
+
return unless literal_receiver?(node, receiver) ||
|
170
|
+
constructor?(node, receiver) ||
|
171
|
+
chained_conversion?(node, receiver) ||
|
172
|
+
chained_to_typed_method?(node, receiver)
|
173
|
+
|
174
|
+
message = format(MSG, method: node.method_name)
|
175
|
+
|
176
|
+
add_offense(node.loc.selector, message: message) do |corrector|
|
177
|
+
corrector.remove(node.loc.dot.join(node.loc.selector))
|
178
|
+
end
|
179
|
+
end
|
180
|
+
# rubocop:enable Metrics/AbcSize
|
181
|
+
alias on_csend on_send
|
182
|
+
|
183
|
+
private
|
184
|
+
|
185
|
+
def hash_or_set_with_block?(node)
|
186
|
+
return false if !node.method?(:to_h) && !node.method?(:to_set)
|
187
|
+
|
188
|
+
node.parent&.any_block_type? || node.last_argument&.block_pass_type?
|
189
|
+
end
|
190
|
+
|
191
|
+
def find_receiver(node)
|
192
|
+
receiver = node.receiver
|
193
|
+
return unless receiver
|
194
|
+
|
195
|
+
while receiver.begin_type?
|
196
|
+
break unless receiver.children.one?
|
197
|
+
|
198
|
+
receiver = receiver.children.first
|
199
|
+
end
|
200
|
+
|
201
|
+
receiver
|
202
|
+
end
|
203
|
+
|
204
|
+
def literal_receiver?(node, receiver)
|
205
|
+
return false unless receiver
|
206
|
+
|
207
|
+
receiver.type?(*LITERAL_NODE_TYPES[node.method_name])
|
208
|
+
end
|
209
|
+
|
210
|
+
def constructor?(node, receiver)
|
211
|
+
matcher = CONSTRUCTOR_MAPPING[node.method_name]
|
212
|
+
return false unless matcher
|
213
|
+
|
214
|
+
public_send(matcher, receiver)
|
215
|
+
end
|
216
|
+
|
217
|
+
def chained_conversion?(node, receiver)
|
218
|
+
return false unless receiver&.call_type?
|
219
|
+
|
220
|
+
receiver.method?(node.method_name)
|
221
|
+
end
|
222
|
+
|
223
|
+
def chained_to_typed_method?(node, receiver)
|
224
|
+
return false unless receiver&.call_type?
|
225
|
+
|
226
|
+
TYPED_METHODS.fetch(node.method_name, []).include?(receiver.method_name)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
# Checks for cases where exceptions unrelated to the numeric constructors `Integer()`,
|
7
|
+
# `Float()`, `BigDecimal()`, `Complex()`, and `Rational()` may be unintentionally swallowed.
|
8
|
+
#
|
9
|
+
# @safety
|
10
|
+
# The cop is unsafe for autocorrection because unexpected errors occurring in the argument
|
11
|
+
# passed to numeric constructor (e.g., `Integer()`) can lead to incompatible behavior.
|
12
|
+
# For example, changing it to `Integer(potential_exception_method_call, exception: false)`
|
13
|
+
# ensures that exceptions raised by `potential_exception_method_call` are not ignored.
|
14
|
+
#
|
15
|
+
# [source,ruby]
|
16
|
+
# ----
|
17
|
+
# Integer(potential_exception_method_call) rescue nil
|
18
|
+
# ----
|
19
|
+
#
|
20
|
+
# @example
|
21
|
+
#
|
22
|
+
# # bad
|
23
|
+
# Integer(arg) rescue nil
|
24
|
+
#
|
25
|
+
# # bad
|
26
|
+
# begin
|
27
|
+
# Integer(arg)
|
28
|
+
# rescue
|
29
|
+
# nil
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# # bad
|
33
|
+
# begin
|
34
|
+
# Integer(arg)
|
35
|
+
# rescue
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# # good
|
39
|
+
# Integer(arg, exception: false)
|
40
|
+
#
|
41
|
+
class SuppressedExceptionInNumberConversion < Base
|
42
|
+
extend AutoCorrector
|
43
|
+
extend TargetRubyVersion
|
44
|
+
|
45
|
+
MSG = 'Use `%<prefer>s` instead.'
|
46
|
+
EXPECTED_EXCEPTION_CLASSES = %w[ArgumentError TypeError ::ArgumentError ::TypeError].freeze
|
47
|
+
|
48
|
+
# @!method numeric_constructor_rescue_nil(node)
|
49
|
+
def_node_matcher :numeric_constructor_rescue_nil, <<~PATTERN
|
50
|
+
(rescue
|
51
|
+
$#numeric_method?
|
52
|
+
(resbody nil? nil? (nil)) nil?)
|
53
|
+
PATTERN
|
54
|
+
|
55
|
+
# @!method begin_numeric_constructor_rescue_nil(node)
|
56
|
+
def_node_matcher :begin_numeric_constructor_rescue_nil, <<~PATTERN
|
57
|
+
(kwbegin
|
58
|
+
(rescue
|
59
|
+
$#numeric_method?
|
60
|
+
(resbody $_? nil?
|
61
|
+
{(nil) nil?}) nil?))
|
62
|
+
PATTERN
|
63
|
+
|
64
|
+
# @!method numeric_method?(node)
|
65
|
+
def_node_matcher :numeric_method?, <<~PATTERN
|
66
|
+
{
|
67
|
+
(call #constructor_receiver? {:Integer :BigDecimal :Complex :Rational}
|
68
|
+
_ _?)
|
69
|
+
(call #constructor_receiver? :Float
|
70
|
+
_)
|
71
|
+
}
|
72
|
+
PATTERN
|
73
|
+
|
74
|
+
# @!method constructor_receiver?(node)
|
75
|
+
def_node_matcher :constructor_receiver?, <<~PATTERN
|
76
|
+
{nil? (const {nil? cbase} :Kernel)}
|
77
|
+
PATTERN
|
78
|
+
|
79
|
+
minimum_target_ruby_version 2.6
|
80
|
+
|
81
|
+
# rubocop:disable Metrics/AbcSize
|
82
|
+
def on_rescue(node)
|
83
|
+
if (method, exception_classes = begin_numeric_constructor_rescue_nil(node.parent))
|
84
|
+
return unless expected_exception_classes_only?(exception_classes)
|
85
|
+
|
86
|
+
node = node.parent
|
87
|
+
else
|
88
|
+
return unless (method = numeric_constructor_rescue_nil(node))
|
89
|
+
end
|
90
|
+
|
91
|
+
arguments = method.arguments.map(&:source) << 'exception: false'
|
92
|
+
prefer = "#{method.method_name}(#{arguments.join(', ')})"
|
93
|
+
prefer = "#{method.receiver.source}#{method.loc.dot.source}#{prefer}" if method.receiver
|
94
|
+
|
95
|
+
add_offense(node, message: format(MSG, prefer: prefer)) do |corrector|
|
96
|
+
corrector.replace(node, prefer)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
# rubocop:enable Metrics/AbcSize
|
100
|
+
|
101
|
+
private
|
102
|
+
|
103
|
+
def expected_exception_classes_only?(exception_classes)
|
104
|
+
return true unless (arguments = exception_classes.first)
|
105
|
+
|
106
|
+
(arguments.values.map(&:source) - EXPECTED_EXCEPTION_CLASSES).none?
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
# Checks for useless constant scoping. Private constants must be defined using
|
7
|
+
# `private_constant` or `class << self`. Even if `private` access modifier is used,
|
8
|
+
# it is public scope despite its appearance.
|
9
|
+
#
|
10
|
+
# It does not support autocorrection due to behavior change and multiple ways to fix it.
|
11
|
+
# Or a public constant may be intended.
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
#
|
15
|
+
# # bad
|
16
|
+
# class Foo
|
17
|
+
# private
|
18
|
+
# PRIVATE_CONST = 42
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# # good
|
22
|
+
# class Foo
|
23
|
+
# PRIVATE_CONST = 42
|
24
|
+
# private_constant :PRIVATE_CONST
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# # good
|
28
|
+
# class Foo
|
29
|
+
# class << self
|
30
|
+
# private
|
31
|
+
# PRIVATE_CONST = 42
|
32
|
+
# end
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# # good
|
36
|
+
# class Foo
|
37
|
+
# PUBLIC_CONST = 42 # If private scope is not intended.
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
class UselessConstantScoping < Base
|
41
|
+
MSG = 'Useless `private` access modifier for constant scope.'
|
42
|
+
|
43
|
+
# @!method private_constants(node)
|
44
|
+
def_node_matcher :private_constants, <<~PATTERN
|
45
|
+
(send nil? :private_constant $...)
|
46
|
+
PATTERN
|
47
|
+
|
48
|
+
def on_casgn(node)
|
49
|
+
return if node.each_ancestor(:sclass).any?
|
50
|
+
return unless after_private_modifier?(node.left_siblings)
|
51
|
+
return if private_constantize?(node.right_siblings, node.name)
|
52
|
+
|
53
|
+
add_offense(node)
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def after_private_modifier?(left_siblings)
|
59
|
+
left_siblings.compact.select(&:send_type?).any? { |node| node.command?(:private) }
|
60
|
+
end
|
61
|
+
|
62
|
+
def private_constantize?(right_siblings, const_value)
|
63
|
+
private_constant_arguments = right_siblings.map { |node| private_constants(node) }
|
64
|
+
|
65
|
+
private_constant_values = private_constant_arguments.flatten.filter_map do |constant|
|
66
|
+
constant.value.to_sym if constant.respond_to?(:value)
|
67
|
+
end
|
68
|
+
|
69
|
+
private_constant_values.include?(const_value)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -26,6 +26,13 @@ module RuboCop
|
|
26
26
|
extend NodePattern::Macros
|
27
27
|
include RuboCop::AST::Sexp
|
28
28
|
|
29
|
+
VAR_SETTER_TO_GETTER = {
|
30
|
+
lvasgn: :lvar,
|
31
|
+
ivasgn: :ivar,
|
32
|
+
cvasgn: :cvar,
|
33
|
+
gvasgn: :gvar
|
34
|
+
}.freeze
|
35
|
+
|
29
36
|
# Plug into the calculator
|
30
37
|
def initialize(node, discount_repeated_attributes: false)
|
31
38
|
super(node)
|
@@ -114,13 +121,6 @@ module RuboCop
|
|
114
121
|
calls.fetch(value) { yield [calls, value] }
|
115
122
|
end
|
116
123
|
|
117
|
-
VAR_SETTER_TO_GETTER = {
|
118
|
-
lvasgn: :lvar,
|
119
|
-
ivasgn: :ivar,
|
120
|
-
cvasgn: :cvar,
|
121
|
-
gvasgn: :gvar
|
122
|
-
}.freeze
|
123
|
-
|
124
124
|
# @returns `[receiver, method | nil]` for the given setter `node`
|
125
125
|
# or `nil` if it is not a setter.
|
126
126
|
def setter_to_getter(node)
|
@@ -5,10 +5,10 @@ module RuboCop
|
|
5
5
|
# This module checks for nodes that should be aligned to the left or right.
|
6
6
|
# This amount is determined by the instance variable @column_delta.
|
7
7
|
module Alignment
|
8
|
-
private
|
9
|
-
|
10
8
|
SPACE = ' '
|
11
9
|
|
10
|
+
private
|
11
|
+
|
12
12
|
attr_reader :column_delta
|
13
13
|
|
14
14
|
def configured_indentation_width
|
@@ -11,6 +11,24 @@ module RuboCop
|
|
11
11
|
DO_NOT_MIX_OMIT_VALUE_MSG = "#{DO_NOT_MIX_MSG_PREFIX} #{OMIT_HASH_VALUE_MSG}"
|
12
12
|
DO_NOT_MIX_EXPLICIT_VALUE_MSG = "#{DO_NOT_MIX_MSG_PREFIX} #{EXPLICIT_HASH_VALUE_MSG}"
|
13
13
|
|
14
|
+
DefNode = Struct.new(:node) do
|
15
|
+
def selector
|
16
|
+
if node.loc.respond_to?(:selector)
|
17
|
+
node.loc.selector
|
18
|
+
else
|
19
|
+
node.loc.keyword
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def first_argument
|
24
|
+
node.first_argument
|
25
|
+
end
|
26
|
+
|
27
|
+
def last_argument
|
28
|
+
node.last_argument
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
14
32
|
def on_hash_for_mixed_shorthand(hash_node)
|
15
33
|
return if ignore_mixed_hash_shorthand_syntax?(hash_node)
|
16
34
|
|
@@ -212,24 +230,6 @@ module RuboCop
|
|
212
230
|
register_offense(pair_node, OMIT_HASH_VALUE_MSG, replacement)
|
213
231
|
end
|
214
232
|
end
|
215
|
-
|
216
|
-
DefNode = Struct.new(:node) do
|
217
|
-
def selector
|
218
|
-
if node.loc.respond_to?(:selector)
|
219
|
-
node.loc.selector
|
220
|
-
else
|
221
|
-
node.loc.keyword
|
222
|
-
end
|
223
|
-
end
|
224
|
-
|
225
|
-
def first_argument
|
226
|
-
node.first_argument
|
227
|
-
end
|
228
|
-
|
229
|
-
def last_argument
|
230
|
-
node.last_argument
|
231
|
-
end
|
232
|
-
end
|
233
233
|
end
|
234
234
|
end
|
235
235
|
# rubocop:enable Metrics/ModuleLength
|