rubocop 1.80.1 → 1.82.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 +35 -7
- data/config/obsoletion.yml +4 -0
- data/lib/rubocop/cli/command/auto_generate_config.rb +2 -2
- data/lib/rubocop/cli.rb +3 -3
- data/lib/rubocop/comment_config.rb +62 -17
- data/lib/rubocop/config_loader.rb +5 -2
- data/lib/rubocop/config_loader_resolver.rb +7 -6
- data/lib/rubocop/config_store.rb +5 -0
- data/lib/rubocop/cop/autocorrect_logic.rb +8 -4
- data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -2
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +2 -4
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -2
- data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +10 -5
- data/lib/rubocop/cop/internal_affairs/location_exists.rb +28 -2
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +3 -1
- data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +1 -1
- data/lib/rubocop/cop/layout/class_structure.rb +1 -1
- data/lib/rubocop/cop/layout/dot_position.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +3 -0
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +30 -12
- data/lib/rubocop/cop/layout/end_alignment.rb +4 -0
- data/lib/rubocop/cop/layout/hash_alignment.rb +2 -5
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +1 -4
- data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +12 -1
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
- data/lib/rubocop/cop/layout/line_length.rb +17 -5
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +2 -0
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +5 -1
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +6 -4
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +13 -3
- data/lib/rubocop/cop/layout/space_after_comma.rb +2 -10
- data/lib/rubocop/cop/layout/space_after_semicolon.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +47 -3
- data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +3 -2
- data/lib/rubocop/cop/lint/cop_directive_syntax.rb +14 -8
- data/lib/rubocop/cop/lint/debugger.rb +0 -2
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +4 -1
- data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +4 -4
- data/lib/rubocop/cop/lint/else_layout.rb +19 -0
- data/lib/rubocop/cop/lint/empty_interpolation.rb +11 -0
- data/lib/rubocop/cop/lint/literal_as_condition.rb +4 -0
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +16 -6
- data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +4 -0
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +23 -9
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -2
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +7 -1
- data/lib/rubocop/cop/lint/rescue_exception.rb +1 -4
- data/lib/rubocop/cop/lint/self_assignment.rb +10 -2
- data/lib/rubocop/cop/lint/shadowed_argument.rb +7 -7
- data/lib/rubocop/cop/lint/unreachable_code.rb +5 -3
- data/lib/rubocop/cop/lint/uri_escape_unescape.rb +2 -0
- data/lib/rubocop/cop/lint/useless_assignment.rb +44 -16
- data/lib/rubocop/cop/lint/useless_or.rb +15 -2
- data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +1 -1
- data/lib/rubocop/cop/lint/void.rb +7 -0
- data/lib/rubocop/cop/message_annotator.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -3
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +2 -4
- data/lib/rubocop/cop/mixin/code_length.rb +1 -1
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +1 -1
- data/lib/rubocop/cop/mixin/line_length_help.rb +21 -2
- data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
- data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +5 -4
- data/lib/rubocop/cop/mixin/statement_modifier.rb +0 -6
- data/lib/rubocop/cop/mixin/trailing_comma.rb +8 -5
- data/lib/rubocop/cop/naming/method_name.rb +4 -2
- data/lib/rubocop/cop/naming/predicate_method.rb +19 -6
- data/lib/rubocop/cop/security/json_load.rb +33 -11
- data/lib/rubocop/cop/style/array_intersect.rb +2 -2
- data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +47 -0
- data/lib/rubocop/cop/style/bare_percent_literals.rb +1 -2
- data/lib/rubocop/cop/style/case_equality.rb +11 -13
- data/lib/rubocop/cop/style/class_and_module_children.rb +1 -0
- data/lib/rubocop/cop/style/conditional_assignment.rb +8 -14
- data/lib/rubocop/cop/style/constant_visibility.rb +17 -12
- data/lib/rubocop/cop/style/double_negation.rb +1 -1
- data/lib/rubocop/cop/style/empty_method.rb +0 -6
- data/lib/rubocop/cop/style/endless_method.rb +15 -2
- data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
- data/lib/rubocop/cop/style/float_division.rb +15 -1
- data/lib/rubocop/cop/style/guard_clause.rb +0 -11
- data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
- data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -3
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +12 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +17 -4
- data/lib/rubocop/cop/style/module_member_existence_check.rb +74 -0
- data/lib/rubocop/cop/style/multiline_method_signature.rb +2 -4
- data/lib/rubocop/cop/style/nil_comparison.rb +9 -7
- data/lib/rubocop/cop/style/one_line_conditional.rb +17 -9
- data/lib/rubocop/cop/style/operator_method_call.rb +11 -2
- data/lib/rubocop/cop/style/parallel_assignment.rb +2 -2
- data/lib/rubocop/cop/style/redundant_argument.rb +2 -0
- data/lib/rubocop/cop/style/redundant_exception.rb +1 -1
- data/lib/rubocop/cop/style/redundant_format.rb +26 -5
- data/lib/rubocop/cop/style/redundant_interpolation.rb +11 -2
- data/lib/rubocop/cop/style/redundant_parentheses.rb +13 -10
- data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -2
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +9 -0
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -0
- data/lib/rubocop/cop/style/redundant_sort.rb +7 -7
- data/lib/rubocop/cop/style/safe_navigation.rb +6 -0
- data/lib/rubocop/cop/style/semicolon.rb +23 -7
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +8 -1
- data/lib/rubocop/cop/style/string_concatenation.rb +16 -12
- data/lib/rubocop/cop/style/super_arguments.rb +2 -2
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +45 -0
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +11 -11
- data/lib/rubocop/cop/style/unless_else.rb +10 -9
- data/lib/rubocop/cop/util.rb +2 -3
- data/lib/rubocop/cop/utils/format_string.rb +10 -0
- data/lib/rubocop/cops_documentation_generator.rb +4 -4
- data/lib/rubocop/directive_comment.rb +46 -3
- data/lib/rubocop/formatter/disabled_config_formatter.rb +1 -0
- data/lib/rubocop/lsp/diagnostic.rb +10 -14
- data/lib/rubocop/lsp/stdin_runner.rb +0 -16
- data/lib/rubocop/magic_comment.rb +20 -0
- data/lib/rubocop/rake_task.rb +1 -1
- data/lib/rubocop/remote_config.rb +7 -8
- data/lib/rubocop/result_cache.rb +38 -27
- data/lib/rubocop/rspec/shared_contexts.rb +2 -2
- data/lib/rubocop/rspec/support.rb +1 -1
- data/lib/rubocop/runner.rb +4 -0
- data/lib/rubocop/target_ruby.rb +11 -2
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +2 -0
- data/lib/ruby_lsp/rubocop/addon.rb +23 -8
- data/lib/ruby_lsp/rubocop/runtime_adapter.rb +49 -15
- metadata +9 -7
|
@@ -8,8 +8,8 @@ module RuboCop
|
|
|
8
8
|
MSG = 'Space missing after %<token>s.'
|
|
9
9
|
|
|
10
10
|
def on_new_investigation
|
|
11
|
-
each_missing_space(processed_source.tokens) do |token|
|
|
12
|
-
add_offense(token.pos, message: format(MSG, token: kind
|
|
11
|
+
each_missing_space(processed_source.tokens) do |token, kind|
|
|
12
|
+
add_offense(token.pos, message: format(MSG, token: kind)) do |corrector|
|
|
13
13
|
PunctuationCorrector.add_space(corrector, token)
|
|
14
14
|
end
|
|
15
15
|
end
|
|
@@ -19,11 +19,12 @@ module RuboCop
|
|
|
19
19
|
|
|
20
20
|
def each_missing_space(tokens)
|
|
21
21
|
tokens.each_cons(2) do |token1, token2|
|
|
22
|
-
|
|
22
|
+
kind = kind(token1, token2)
|
|
23
|
+
next unless kind
|
|
23
24
|
next unless space_missing?(token1, token2)
|
|
24
25
|
next unless space_required_before?(token2)
|
|
25
26
|
|
|
26
|
-
yield token1
|
|
27
|
+
yield token1, kind
|
|
27
28
|
end
|
|
28
29
|
end
|
|
29
30
|
|
|
@@ -100,12 +100,6 @@ module RuboCop
|
|
|
100
100
|
node.parent.send_type?
|
|
101
101
|
end
|
|
102
102
|
|
|
103
|
-
def max_line_length
|
|
104
|
-
return unless config.cop_enabled?('Layout/LineLength')
|
|
105
|
-
|
|
106
|
-
config.for_cop('Layout/LineLength')['Max']
|
|
107
|
-
end
|
|
108
|
-
|
|
109
103
|
def comment_disables_cop?(comment)
|
|
110
104
|
regexp_pattern = "# rubocop : (disable|todo) ([^,],)* (all|#{cop_name})"
|
|
111
105
|
Regexp.new(regexp_pattern.gsub(' ', '\s*')).match?(comment)
|
|
@@ -95,13 +95,16 @@ module RuboCop
|
|
|
95
95
|
node.multiline? && !allowed_multiline_argument?(node)
|
|
96
96
|
end
|
|
97
97
|
|
|
98
|
+
# rubocop:disable Metrics/AbcSize
|
|
98
99
|
def method_name_and_arguments_on_same_line?(node)
|
|
99
|
-
return false
|
|
100
|
+
return false if !node.call_type? || node.last_line != node.last_argument.last_line
|
|
101
|
+
return true if node.last_argument.hash_type? && node.last_argument.braces?
|
|
100
102
|
|
|
101
|
-
line = node.loc.selector
|
|
103
|
+
line = node.loc.selector&.line || node.loc.line
|
|
102
104
|
|
|
103
|
-
line == node.last_argument.last_line
|
|
105
|
+
line == node.last_argument.last_line
|
|
104
106
|
end
|
|
107
|
+
# rubocop:enable Metrics/AbcSize
|
|
105
108
|
|
|
106
109
|
# A single argument with the closing bracket on the same line as the end
|
|
107
110
|
# of the argument is not considered multiline, even if the argument
|
|
@@ -140,7 +143,7 @@ module RuboCop
|
|
|
140
143
|
end
|
|
141
144
|
|
|
142
145
|
def last_item_precedes_newline?(node)
|
|
143
|
-
after_last_item = node.children.last.source_range.end.join(node.
|
|
146
|
+
after_last_item = node.children.last.source_range.end.join(node.source_range.end)
|
|
144
147
|
|
|
145
148
|
after_last_item.source.start_with?(/,?\s*(#.*)?\n/)
|
|
146
149
|
end
|
|
@@ -185,7 +188,7 @@ module RuboCop
|
|
|
185
188
|
|
|
186
189
|
def heredoc?(node)
|
|
187
190
|
return false unless node.is_a?(RuboCop::AST::Node)
|
|
188
|
-
return true if node.loc
|
|
191
|
+
return true if node.loc?(:heredoc_body)
|
|
189
192
|
|
|
190
193
|
return heredoc_send?(node) if node.send_type?
|
|
191
194
|
|
|
@@ -147,7 +147,9 @@ module RuboCop
|
|
|
147
147
|
alias on_defs on_def
|
|
148
148
|
|
|
149
149
|
def on_alias(node)
|
|
150
|
-
|
|
150
|
+
return unless (new_identifier = node.new_identifier).sym_type?
|
|
151
|
+
|
|
152
|
+
handle_method_name(new_identifier, new_identifier.value)
|
|
151
153
|
end
|
|
152
154
|
|
|
153
155
|
private
|
|
@@ -232,7 +234,7 @@ module RuboCop
|
|
|
232
234
|
end
|
|
233
235
|
|
|
234
236
|
def range_position(node)
|
|
235
|
-
if node.loc
|
|
237
|
+
if node.loc?(:selector)
|
|
236
238
|
selector_end_pos = node.loc.selector.end_pos + 1
|
|
237
239
|
expr_end_pos = node.source_range.end_pos
|
|
238
240
|
|
|
@@ -14,7 +14,7 @@ module RuboCop
|
|
|
14
14
|
# method calls are assumed to return boolean values. The cop does not make an assessment
|
|
15
15
|
# if the return type is unknown (non-predicate method calls, variables, etc.).
|
|
16
16
|
#
|
|
17
|
-
# NOTE:
|
|
17
|
+
# NOTE: The `initialize` method and operator methods (`def ==`, etc.) are ignored.
|
|
18
18
|
#
|
|
19
19
|
# By default, the cop runs in `conservative` mode, which allows a method to be named
|
|
20
20
|
# with a question mark as long as at least one return value is boolean. In `aggressive`
|
|
@@ -113,6 +113,18 @@ module RuboCop
|
|
|
113
113
|
# true
|
|
114
114
|
# end
|
|
115
115
|
#
|
|
116
|
+
# @example AllowedMethods: [call] (default)
|
|
117
|
+
# # good
|
|
118
|
+
# def call
|
|
119
|
+
# foo == bar
|
|
120
|
+
# end
|
|
121
|
+
#
|
|
122
|
+
# @example AllowedPatterns: [\Afoo]
|
|
123
|
+
# # good
|
|
124
|
+
# def foo?
|
|
125
|
+
# 'foo'
|
|
126
|
+
# end
|
|
127
|
+
#
|
|
116
128
|
# @example AllowBangMethods: false (default)
|
|
117
129
|
# # bad
|
|
118
130
|
# def save!
|
|
@@ -149,7 +161,8 @@ module RuboCop
|
|
|
149
161
|
private
|
|
150
162
|
|
|
151
163
|
def allowed?(node)
|
|
152
|
-
|
|
164
|
+
node.method?(:initialize) ||
|
|
165
|
+
allowed_method?(node.method_name) ||
|
|
153
166
|
matches_allowed_pattern?(node.method_name) ||
|
|
154
167
|
allowed_bang_method?(node) ||
|
|
155
168
|
node.operator_method? ||
|
|
@@ -180,8 +193,7 @@ module RuboCop
|
|
|
180
193
|
return_values << extract_return_value(return_node)
|
|
181
194
|
end
|
|
182
195
|
|
|
183
|
-
|
|
184
|
-
return_values << last_value if last_value
|
|
196
|
+
return_values << last_value(node)
|
|
185
197
|
|
|
186
198
|
process_return_values(return_values)
|
|
187
199
|
end
|
|
@@ -234,8 +246,9 @@ module RuboCop
|
|
|
234
246
|
end
|
|
235
247
|
|
|
236
248
|
def last_value(node)
|
|
237
|
-
value = node.begin_type? ? node.children.last : node
|
|
238
|
-
|
|
249
|
+
value = node.begin_type? ? node.children.last || s(:nil) : node
|
|
250
|
+
|
|
251
|
+
value.return_type? ? extract_return_value(value) : value
|
|
239
252
|
end
|
|
240
253
|
|
|
241
254
|
def process_return_values(return_values)
|
|
@@ -6,22 +6,40 @@ module RuboCop
|
|
|
6
6
|
# Checks for the use of JSON class methods which have potential
|
|
7
7
|
# security issues.
|
|
8
8
|
#
|
|
9
|
+
# `JSON.load` and similar methods allow deserialization of arbitrary ruby objects:
|
|
10
|
+
#
|
|
11
|
+
# [source,ruby]
|
|
12
|
+
# ----
|
|
13
|
+
# require 'json/add/string'
|
|
14
|
+
# result = JSON.load('{ "json_class": "String", "raw": [72, 101, 108, 108, 111] }')
|
|
15
|
+
# pp result # => "Hello"
|
|
16
|
+
# ----
|
|
17
|
+
#
|
|
18
|
+
# Never use `JSON.load` for untrusted user input. Prefer `JSON.parse` unless you have
|
|
19
|
+
# a concrete use-case for `JSON.load`.
|
|
20
|
+
#
|
|
21
|
+
# NOTE: Starting with `json` gem version 2.8.0, triggering this behavior without explicitly
|
|
22
|
+
# passing the `create_additions` keyword argument emits a deprecation warning, with the
|
|
23
|
+
# goal of being secure by default in the next major version 3.0.0.
|
|
24
|
+
#
|
|
9
25
|
# @safety
|
|
10
26
|
# This cop's autocorrection is unsafe because it's potentially dangerous.
|
|
11
|
-
# If using a stream, like `JSON.load(open('file'))`,
|
|
27
|
+
# If using a stream, like `JSON.load(open('file'))`, you will need to call
|
|
12
28
|
# `#read` manually, like `JSON.parse(open('file').read)`.
|
|
13
|
-
# If reading single values (rather than proper JSON objects), like
|
|
14
|
-
# `JSON.load('false')`, it will need to pass the `quirks_mode: true`
|
|
15
|
-
# option, like `JSON.parse('false', quirks_mode: true)`.
|
|
16
29
|
# Other similar issues may apply.
|
|
17
30
|
#
|
|
18
31
|
# @example
|
|
19
32
|
# # bad
|
|
20
|
-
# JSON.load(
|
|
21
|
-
# JSON.restore(
|
|
33
|
+
# JSON.load('{}')
|
|
34
|
+
# JSON.restore('{}')
|
|
22
35
|
#
|
|
23
36
|
# # good
|
|
24
|
-
# JSON.parse(
|
|
37
|
+
# JSON.parse('{}')
|
|
38
|
+
# JSON.unsafe_load('{}')
|
|
39
|
+
#
|
|
40
|
+
# # good - explicit use of `create_additions` option
|
|
41
|
+
# JSON.load('{}', create_additions: true)
|
|
42
|
+
# JSON.load('{}', create_additions: false)
|
|
25
43
|
#
|
|
26
44
|
class JSONLoad < Base
|
|
27
45
|
extend AutoCorrector
|
|
@@ -29,13 +47,17 @@ module RuboCop
|
|
|
29
47
|
MSG = 'Prefer `JSON.parse` over `JSON.%<method>s`.'
|
|
30
48
|
RESTRICT_ON_SEND = %i[load restore].freeze
|
|
31
49
|
|
|
32
|
-
# @!method
|
|
33
|
-
def_node_matcher :
|
|
34
|
-
(
|
|
50
|
+
# @!method insecure_json_load(node)
|
|
51
|
+
def_node_matcher :insecure_json_load, <<~PATTERN
|
|
52
|
+
(
|
|
53
|
+
send (const {nil? cbase} :JSON) ${:load :restore}
|
|
54
|
+
...
|
|
55
|
+
!(hash `(sym $:create_additions))
|
|
56
|
+
)
|
|
35
57
|
PATTERN
|
|
36
58
|
|
|
37
59
|
def on_send(node)
|
|
38
|
-
|
|
60
|
+
insecure_json_load(node) do |method|
|
|
39
61
|
add_offense(node.loc.selector, message: format(MSG, method: method)) do |corrector|
|
|
40
62
|
corrector.replace(node.loc.selector, 'parse')
|
|
41
63
|
end
|
|
@@ -95,7 +95,7 @@ module RuboCop
|
|
|
95
95
|
$(call
|
|
96
96
|
{
|
|
97
97
|
(begin (send $_ :& $_))
|
|
98
|
-
(call
|
|
98
|
+
(call $!nil? :intersection $_)
|
|
99
99
|
}
|
|
100
100
|
$%1
|
|
101
101
|
)
|
|
@@ -107,7 +107,7 @@ module RuboCop
|
|
|
107
107
|
$(call
|
|
108
108
|
{
|
|
109
109
|
(begin (send $_ :& $_))
|
|
110
|
-
(call
|
|
110
|
+
(call $!nil? :intersection $_)
|
|
111
111
|
}
|
|
112
112
|
%ARRAY_SIZE_METHODS
|
|
113
113
|
)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Style
|
|
6
|
+
# Use `include?(element)` instead of `intersect?([element])`.
|
|
7
|
+
#
|
|
8
|
+
# @safety
|
|
9
|
+
# The receiver might not be an array.
|
|
10
|
+
#
|
|
11
|
+
# @example
|
|
12
|
+
# # bad
|
|
13
|
+
# array.intersect?([element])
|
|
14
|
+
#
|
|
15
|
+
# # good
|
|
16
|
+
# array.include?(element)
|
|
17
|
+
class ArrayIntersectWithSingleElement < Base
|
|
18
|
+
extend AutoCorrector
|
|
19
|
+
|
|
20
|
+
MSG = 'Use `include?(element)` instead of `intersect?([element])`.'
|
|
21
|
+
|
|
22
|
+
RESTRICT_ON_SEND = %i[intersect?].freeze
|
|
23
|
+
|
|
24
|
+
# @!method single_element(node)
|
|
25
|
+
def_node_matcher :single_element, <<~PATTERN
|
|
26
|
+
(send _ _ $(array $_))
|
|
27
|
+
PATTERN
|
|
28
|
+
|
|
29
|
+
def on_send(node)
|
|
30
|
+
array, element = single_element(node)
|
|
31
|
+
return unless array
|
|
32
|
+
|
|
33
|
+
add_offense(
|
|
34
|
+
node.source_range.with(begin_pos: node.loc.selector.begin_pos)
|
|
35
|
+
) do |corrector|
|
|
36
|
+
corrector.replace(node.loc.selector, 'include?')
|
|
37
|
+
corrector.replace(
|
|
38
|
+
array,
|
|
39
|
+
array.percent_literal? ? element.value.inspect : element.source
|
|
40
|
+
)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
alias on_csend on_send
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -3,31 +3,36 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Style
|
|
6
|
-
# Checks for uses of the case equality operator(
|
|
6
|
+
# Checks for uses of the case equality operator (`===`).
|
|
7
7
|
#
|
|
8
8
|
# If `AllowOnConstant` option is enabled, the cop will ignore violations when the receiver of
|
|
9
9
|
# the case equality operator is a constant.
|
|
10
|
-
|
|
10
|
+
#
|
|
11
11
|
# If `AllowOnSelfClass` option is enabled, the cop will ignore violations when the receiver of
|
|
12
12
|
# the case equality operator is `self.class`. Note intermediate variables are not accepted.
|
|
13
13
|
#
|
|
14
|
+
# NOTE: Regexp case equality (`/regexp/ === var`) is allowed because changing it to
|
|
15
|
+
# `/regexp/.match?(var)` needs to take into account `Regexp.last_match?`, `$~`, `$1`, etc.
|
|
16
|
+
# This potentially incompatible transformation is handled by `Performance/RegexpMatch` cop.
|
|
17
|
+
#
|
|
14
18
|
# @example
|
|
15
19
|
# # bad
|
|
16
20
|
# (1..100) === 7
|
|
17
|
-
# /something/ === some_string
|
|
18
21
|
#
|
|
19
22
|
# # good
|
|
20
|
-
# something.is_a?(Array)
|
|
21
23
|
# (1..100).include?(7)
|
|
22
|
-
# /something/.match?(some_string)
|
|
23
24
|
#
|
|
24
25
|
# @example AllowOnConstant: false (default)
|
|
25
26
|
# # bad
|
|
26
27
|
# Array === something
|
|
27
28
|
#
|
|
29
|
+
# # good
|
|
30
|
+
# something.is_a?(Array)
|
|
31
|
+
#
|
|
28
32
|
# @example AllowOnConstant: true
|
|
29
33
|
# # good
|
|
30
34
|
# Array === something
|
|
35
|
+
# something.is_a?(Array)
|
|
31
36
|
#
|
|
32
37
|
# @example AllowOnSelfClass: false (default)
|
|
33
38
|
# # bad
|
|
@@ -51,7 +56,7 @@ module RuboCop
|
|
|
51
56
|
|
|
52
57
|
def on_send(node)
|
|
53
58
|
case_equality?(node) do |lhs, rhs|
|
|
54
|
-
return if lhs.const_type? && !lhs.module_name?
|
|
59
|
+
return if lhs.regexp_type? || (lhs.const_type? && !lhs.module_name?)
|
|
55
60
|
|
|
56
61
|
add_offense(node.loc.selector) do |corrector|
|
|
57
62
|
replacement = replacement(lhs, rhs)
|
|
@@ -71,13 +76,6 @@ module RuboCop
|
|
|
71
76
|
|
|
72
77
|
def replacement(lhs, rhs)
|
|
73
78
|
case lhs.type
|
|
74
|
-
when :regexp
|
|
75
|
-
# The automatic correction from `a === b` to `a.match?(b)` needs to
|
|
76
|
-
# consider `Regexp.last_match?`, `$~`, `$1`, and etc.
|
|
77
|
-
# This correction is expected to be supported by `Performance/Regexp` cop.
|
|
78
|
-
# See: https://github.com/rubocop/rubocop-performance/issues/152
|
|
79
|
-
#
|
|
80
|
-
# So here is noop.
|
|
81
79
|
when :begin
|
|
82
80
|
begin_replacement(lhs, rhs)
|
|
83
81
|
when :const
|
|
@@ -213,9 +213,7 @@ module RuboCop
|
|
|
213
213
|
ASSIGN_TO_CONDITION_MSG = 'Assign variables inside of conditionals.'
|
|
214
214
|
VARIABLE_ASSIGNMENT_TYPES = %i[casgn cvasgn gvasgn ivasgn lvasgn].freeze
|
|
215
215
|
ASSIGNMENT_TYPES = VARIABLE_ASSIGNMENT_TYPES + %i[and_asgn or_asgn op_asgn masgn].freeze
|
|
216
|
-
LINE_LENGTH = 'Layout/LineLength'
|
|
217
216
|
ENABLED = 'Enabled'
|
|
218
|
-
MAX = 'Max'
|
|
219
217
|
SINGLE_LINE_CONDITIONS_ONLY = 'SingleLineConditionsOnly'
|
|
220
218
|
|
|
221
219
|
# The shovel operator `<<` does not have its own type. It is a `send`
|
|
@@ -399,7 +397,7 @@ module RuboCop
|
|
|
399
397
|
# of the longest line + the length of the corrected assignment is
|
|
400
398
|
# greater than the max configured line length
|
|
401
399
|
def correction_exceeds_line_limit?(node, branches)
|
|
402
|
-
return false unless
|
|
400
|
+
return false unless config.cop_enabled?('Layout/LineLength')
|
|
403
401
|
|
|
404
402
|
assignment = lhs(tail(branches[0]))
|
|
405
403
|
|
|
@@ -417,14 +415,6 @@ module RuboCop
|
|
|
417
415
|
assignment + longest_line
|
|
418
416
|
end
|
|
419
417
|
|
|
420
|
-
def line_length_cop_enabled?
|
|
421
|
-
config.for_cop(LINE_LENGTH)[ENABLED]
|
|
422
|
-
end
|
|
423
|
-
|
|
424
|
-
def max_line_length
|
|
425
|
-
config.for_cop(LINE_LENGTH)[MAX]
|
|
426
|
-
end
|
|
427
|
-
|
|
428
418
|
def single_line_conditions_only?
|
|
429
419
|
cop_config[SINGLE_LINE_CONDITIONS_ONLY]
|
|
430
420
|
end
|
|
@@ -444,7 +434,7 @@ module RuboCop
|
|
|
444
434
|
next if child.parent.dstr_type?
|
|
445
435
|
|
|
446
436
|
white_space = white_space_range(child, column)
|
|
447
|
-
corrector.remove(white_space) if white_space
|
|
437
|
+
corrector.remove(white_space) if white_space
|
|
448
438
|
end
|
|
449
439
|
|
|
450
440
|
if condition.loc.else && !same_line?(condition.else_branch, condition)
|
|
@@ -465,9 +455,13 @@ module RuboCop
|
|
|
465
455
|
|
|
466
456
|
def white_space_range(node, column)
|
|
467
457
|
expression = node.source_range
|
|
468
|
-
|
|
458
|
+
end_pos = expression.begin_pos
|
|
459
|
+
begin_pos = end_pos - (expression.column - column - 2)
|
|
460
|
+
|
|
461
|
+
return nil if begin_pos > end_pos
|
|
469
462
|
|
|
470
|
-
Parser::Source::Range.new(expression.source_buffer, begin_pos,
|
|
463
|
+
white_space = Parser::Source::Range.new(expression.source_buffer, begin_pos, end_pos)
|
|
464
|
+
white_space if white_space.source.strip.empty?
|
|
471
465
|
end
|
|
472
466
|
|
|
473
467
|
def assignment(node)
|
|
@@ -29,25 +29,30 @@ module RuboCop
|
|
|
29
29
|
# @example IgnoreModules: false (default)
|
|
30
30
|
# # bad
|
|
31
31
|
# class Foo
|
|
32
|
-
# MyClass = Struct.new
|
|
32
|
+
# MyClass = Struct.new
|
|
33
33
|
# end
|
|
34
34
|
#
|
|
35
35
|
# # good
|
|
36
36
|
# class Foo
|
|
37
|
-
# MyClass = Struct.new
|
|
37
|
+
# MyClass = Struct.new
|
|
38
38
|
# public_constant :MyClass
|
|
39
39
|
# end
|
|
40
40
|
#
|
|
41
41
|
# @example IgnoreModules: true
|
|
42
42
|
# # good
|
|
43
43
|
# class Foo
|
|
44
|
-
# MyClass = Struct.new
|
|
44
|
+
# MyClass = Struct.new
|
|
45
45
|
# end
|
|
46
46
|
#
|
|
47
47
|
class ConstantVisibility < Base
|
|
48
48
|
MSG = 'Explicitly make `%<constant_name>s` public or private using ' \
|
|
49
49
|
'either `#public_constant` or `#private_constant`.'
|
|
50
50
|
|
|
51
|
+
# @!method visibility_declaration_for(node)
|
|
52
|
+
def_node_matcher :visibility_declaration_for, <<~PATTERN
|
|
53
|
+
(send nil? {:public_constant :private_constant} $...)
|
|
54
|
+
PATTERN
|
|
55
|
+
|
|
51
56
|
def on_casgn(node)
|
|
52
57
|
return unless class_or_module_scope?(node)
|
|
53
58
|
return if visibility_declaration?(node)
|
|
@@ -77,20 +82,20 @@ module RuboCop
|
|
|
77
82
|
end
|
|
78
83
|
end
|
|
79
84
|
|
|
85
|
+
# rubocop:disable Metrics/AbcSize
|
|
80
86
|
def visibility_declaration?(node)
|
|
81
87
|
node.parent.each_child_node(:send).any? do |child|
|
|
82
|
-
visibility_declaration_for
|
|
83
|
-
end
|
|
84
|
-
end
|
|
88
|
+
next false unless (arguments = visibility_declaration_for(child))
|
|
85
89
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
+
arguments = arguments.first.children.first.to_a if arguments.first&.splat_type?
|
|
91
|
+
constant_values = arguments.map do |argument|
|
|
92
|
+
argument.value.to_sym if argument.respond_to?(:value)
|
|
93
|
+
end
|
|
90
94
|
|
|
91
|
-
|
|
92
|
-
|
|
95
|
+
constant_values.include?(node.name)
|
|
96
|
+
end
|
|
93
97
|
end
|
|
98
|
+
# rubocop:enable Metrics/AbcSize
|
|
94
99
|
end
|
|
95
100
|
end
|
|
96
101
|
end
|
|
@@ -144,7 +144,7 @@ module RuboCop
|
|
|
144
144
|
MSG_REQUIRE_ALWAYS = 'Use endless method definitions.'
|
|
145
145
|
|
|
146
146
|
def on_def(node)
|
|
147
|
-
return if node.assignment_method?
|
|
147
|
+
return if node.assignment_method? || use_heredoc?(node)
|
|
148
148
|
|
|
149
149
|
case style
|
|
150
150
|
when :allow_single_line, :allow_always
|
|
@@ -198,6 +198,13 @@ module RuboCop
|
|
|
198
198
|
add_offense(node) { |corrector| correct_to_multiline(corrector, node) }
|
|
199
199
|
end
|
|
200
200
|
|
|
201
|
+
def use_heredoc?(node)
|
|
202
|
+
return false unless (body = node.body)
|
|
203
|
+
return true if body.any_str_type? && body.heredoc?
|
|
204
|
+
|
|
205
|
+
body.each_descendant(:str).any?(&:heredoc?)
|
|
206
|
+
end
|
|
207
|
+
|
|
201
208
|
def correct_to_multiline(corrector, node)
|
|
202
209
|
replacement = <<~RUBY.strip
|
|
203
210
|
def #{node.method_name}#{arguments(node)}
|
|
@@ -225,7 +232,13 @@ module RuboCop
|
|
|
225
232
|
def too_long_when_made_endless?(node)
|
|
226
233
|
return false unless config.cop_enabled?('Layout/LineLength')
|
|
227
234
|
|
|
228
|
-
|
|
235
|
+
offset = modifier_offset(node)
|
|
236
|
+
|
|
237
|
+
endless_replacement(node).length + offset > max_line_length
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def modifier_offset(node)
|
|
241
|
+
same_line?(node.parent, node) ? node.loc.column - node.parent.loc.column : 0
|
|
229
242
|
end
|
|
230
243
|
end
|
|
231
244
|
end
|
|
@@ -7,9 +7,12 @@ module RuboCop
|
|
|
7
7
|
# It is recommended to either always use `fdiv` or coerce one side only.
|
|
8
8
|
# This cop also provides other options for code consistency.
|
|
9
9
|
#
|
|
10
|
+
# For `Regexp.last_match` and nth reference (e.g., `$1`), it assumes that the value
|
|
11
|
+
# is a string matched by a regular expression, and allows conversion with `#to_f`.
|
|
12
|
+
#
|
|
10
13
|
# @safety
|
|
11
14
|
# This cop is unsafe, because if the operand variable is a string object
|
|
12
|
-
# then
|
|
15
|
+
# then `#to_f` will be removed and an error will occur.
|
|
13
16
|
#
|
|
14
17
|
# [source,ruby]
|
|
15
18
|
# ----
|
|
@@ -84,6 +87,14 @@ module RuboCop
|
|
|
84
87
|
(send !nil? :to_f)
|
|
85
88
|
PATTERN
|
|
86
89
|
|
|
90
|
+
# @!method regexp_last_match?(node)
|
|
91
|
+
def_node_matcher :regexp_last_match?, <<~PATTERN
|
|
92
|
+
{
|
|
93
|
+
(send (const {nil? cbase} :Regexp) :last_match int)
|
|
94
|
+
(:nth_ref _)
|
|
95
|
+
}
|
|
96
|
+
PATTERN
|
|
97
|
+
|
|
87
98
|
def on_send(node)
|
|
88
99
|
return unless offense_condition?(node)
|
|
89
100
|
|
|
@@ -104,6 +115,9 @@ module RuboCop
|
|
|
104
115
|
private
|
|
105
116
|
|
|
106
117
|
def offense_condition?(node)
|
|
118
|
+
return false if regexp_last_match?(node.receiver.receiver) ||
|
|
119
|
+
regexp_last_match?(node.first_argument.receiver)
|
|
120
|
+
|
|
107
121
|
case style
|
|
108
122
|
when :left_coerce
|
|
109
123
|
right_coerce?(node)
|
|
@@ -45,17 +45,6 @@ module RuboCop
|
|
|
45
45
|
# ok
|
|
46
46
|
#
|
|
47
47
|
# # bad
|
|
48
|
-
# if something
|
|
49
|
-
# foo || raise('exception')
|
|
50
|
-
# else
|
|
51
|
-
# ok
|
|
52
|
-
# end
|
|
53
|
-
#
|
|
54
|
-
# # good
|
|
55
|
-
# foo || raise('exception') if something
|
|
56
|
-
# ok
|
|
57
|
-
#
|
|
58
|
-
# # bad
|
|
59
48
|
# define_method(:test) do
|
|
60
49
|
# if something
|
|
61
50
|
# work
|
|
@@ -207,14 +207,14 @@ module RuboCop
|
|
|
207
207
|
def too_long_line_based_on_config?(range, line)
|
|
208
208
|
return false if matches_allowed_pattern?(line)
|
|
209
209
|
|
|
210
|
-
too_long =
|
|
210
|
+
too_long = too_long_line_based_on_allow_cop_directives?(range, line)
|
|
211
211
|
return too_long unless too_long == :undetermined
|
|
212
212
|
|
|
213
213
|
too_long_line_based_on_allow_uri?(line)
|
|
214
214
|
end
|
|
215
215
|
|
|
216
|
-
def
|
|
217
|
-
if
|
|
216
|
+
def too_long_line_based_on_allow_cop_directives?(range, line)
|
|
217
|
+
if allow_cop_directives? && directive_on_source_line?(range.line - 1)
|
|
218
218
|
return line_length_without_directive(line) > max_line_length
|
|
219
219
|
end
|
|
220
220
|
|