rubocop 1.23.0 → 1.25.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/LICENSE.txt +1 -1
- data/README.md +2 -3
- data/config/default.yml +60 -12
- data/lib/rubocop/cli/command/auto_genenerate_config.rb +1 -1
- data/lib/rubocop/cli/command/init_dotfile.rb +1 -1
- data/lib/rubocop/cli/command/show_docs_url.rb +48 -0
- data/lib/rubocop/cli/command/suggest_extensions.rb +1 -1
- data/lib/rubocop/cli.rb +1 -0
- data/lib/rubocop/config_loader_resolver.rb +1 -1
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -1
- data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/if_then_corrector.rb +55 -0
- data/lib/rubocop/cop/documentation.rb +19 -2
- data/lib/rubocop/cop/gemspec/require_mfa.rb +8 -10
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +10 -3
- data/lib/rubocop/cop/generator.rb +4 -3
- data/lib/rubocop/cop/internal_affairs/redundant_method_dispatch_node.rb +47 -0
- data/lib/rubocop/cop/internal_affairs/undefined_config.rb +3 -1
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/layout/argument_alignment.rb +36 -9
- data/lib/rubocop/cop/layout/comment_indentation.rb +31 -2
- data/lib/rubocop/cop/layout/dot_position.rb +4 -0
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +5 -1
- data/lib/rubocop/cop/layout/hash_alignment.rb +7 -2
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/space_after_colon.rb +1 -1
- data/lib/rubocop/cop/layout/space_before_first_arg.rb +4 -0
- data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +5 -1
- data/lib/rubocop/cop/lint/constant_definition_in_block.rb +1 -1
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +16 -4
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +6 -0
- data/lib/rubocop/cop/lint/each_with_object_argument.rb +1 -1
- data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +10 -5
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +7 -4
- data/lib/rubocop/cop/metrics/block_length.rb +1 -0
- data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +0 -9
- data/lib/rubocop/cop/metrics/method_length.rb +1 -0
- data/lib/rubocop/cop/metrics/module_length.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +1 -1
- data/lib/rubocop/cop/mixin/enforce_superclass.rb +5 -0
- data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +4 -3
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +82 -0
- data/lib/rubocop/cop/naming/block_forwarding.rb +121 -0
- data/lib/rubocop/cop/naming/method_parameter_name.rb +1 -1
- data/lib/rubocop/cop/security/open.rb +11 -1
- data/lib/rubocop/cop/style/character_literal.rb +8 -1
- data/lib/rubocop/cop/style/collection_compact.rb +31 -13
- data/lib/rubocop/cop/style/combinable_loops.rb +2 -2
- data/lib/rubocop/cop/style/empty_case_condition.rb +10 -0
- data/lib/rubocop/cop/style/file_read.rb +112 -0
- data/lib/rubocop/cop/style/file_write.rb +124 -0
- data/lib/rubocop/cop/style/hash_conversion.rb +2 -1
- data/lib/rubocop/cop/style/hash_syntax.rb +36 -0
- data/lib/rubocop/cop/style/hash_transform_keys.rb +6 -6
- data/lib/rubocop/cop/style/hash_transform_values.rb +6 -6
- data/lib/rubocop/cop/style/if_inside_else.rb +15 -0
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +1 -1
- data/lib/rubocop/cop/style/map_to_hash.rb +68 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +20 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +3 -1
- data/lib/rubocop/cop/style/method_def_parentheses.rb +17 -13
- data/lib/rubocop/cop/style/numeric_literals.rb +10 -1
- data/lib/rubocop/cop/style/one_line_conditional.rb +18 -39
- data/lib/rubocop/cop/style/redundant_begin.rb +2 -6
- data/lib/rubocop/cop/style/redundant_interpolation.rb +17 -3
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +5 -1
- data/lib/rubocop/cop/style/redundant_self.rb +1 -1
- data/lib/rubocop/cop/style/safe_navigation.rb +1 -5
- data/lib/rubocop/cop/style/sample.rb +5 -3
- data/lib/rubocop/cop/style/single_line_block_params.rb +2 -2
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +3 -1
- data/lib/rubocop/cop/style/swap_values.rb +2 -0
- data/lib/rubocop/cop/style/ternary_parentheses.rb +16 -2
- data/lib/rubocop/cop/team.rb +1 -1
- data/lib/rubocop/cop/util.rb +9 -1
- data/lib/rubocop/formatter/disabled_config_formatter.rb +16 -2
- data/lib/rubocop/options.rb +6 -1
- data/lib/rubocop/remote_config.rb +1 -3
- data/lib/rubocop/result_cache.rb +1 -1
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +7 -0
- metadata +15 -7
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# This cop looks for uses of `map.to_h` or `collect.to_h` that could be
|
7
|
+
# written with just `to_h` in Ruby >= 2.6.
|
8
|
+
#
|
9
|
+
# NOTE: `Style/HashTransformKeys` and `Style/HashTransformValues` will
|
10
|
+
# also change this pattern if only hash keys or hash values are being
|
11
|
+
# transformed.
|
12
|
+
#
|
13
|
+
# @safety
|
14
|
+
# This cop is unsafe, as it can produce false positives if the receiver
|
15
|
+
# is not an `Enumerable`.
|
16
|
+
#
|
17
|
+
# @example
|
18
|
+
# # bad
|
19
|
+
# something.map { |v| [v, v * 2] }.to_h
|
20
|
+
#
|
21
|
+
# # good
|
22
|
+
# something.to_h { |v| [v, v * 2] }
|
23
|
+
#
|
24
|
+
# # bad
|
25
|
+
# {foo: bar}.collect { |k, v| [k.to_s, v.do_something] }.to_h
|
26
|
+
#
|
27
|
+
# # good
|
28
|
+
# {foo: bar}.to_h { |k, v| [k.to_s, v.do_something] }
|
29
|
+
#
|
30
|
+
class MapToHash < Base
|
31
|
+
extend AutoCorrector
|
32
|
+
extend TargetRubyVersion
|
33
|
+
include RangeHelp
|
34
|
+
|
35
|
+
minimum_target_ruby_version 2.6
|
36
|
+
|
37
|
+
MSG = 'Pass a block to `to_h` instead of calling `%<method>s.to_h`.'
|
38
|
+
RESTRICT_ON_SEND = %i[to_h].freeze
|
39
|
+
|
40
|
+
# @!method map_to_h?(node)
|
41
|
+
def_node_matcher :map_to_h?, <<~PATTERN
|
42
|
+
$(send (block $(send _ {:map :collect}) ...) :to_h)
|
43
|
+
PATTERN
|
44
|
+
|
45
|
+
def on_send(node)
|
46
|
+
return unless (to_h_node, map_node = map_to_h?(node))
|
47
|
+
|
48
|
+
message = format(MSG, method: map_node.loc.selector.source)
|
49
|
+
add_offense(map_node.loc.selector, message: message) do |corrector|
|
50
|
+
# If the `to_h` call already has a block, do not auto-correct.
|
51
|
+
next if to_h_node.block_node
|
52
|
+
|
53
|
+
autocorrect(corrector, to_h_node, map_node)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def autocorrect(corrector, to_h, map)
|
60
|
+
removal_range = range_between(to_h.loc.dot.begin_pos, to_h.loc.selector.end_pos)
|
61
|
+
|
62
|
+
corrector.remove(range_with_surrounding_space(range: removal_range, side: :left))
|
63
|
+
corrector.replace(map.loc.selector, 'to_h')
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -13,9 +13,11 @@ module RuboCop
|
|
13
13
|
|
14
14
|
private
|
15
15
|
|
16
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
16
17
|
def omit_parentheses(node)
|
17
18
|
return unless node.parenthesized?
|
18
19
|
return if inside_endless_method_def?(node)
|
20
|
+
return if require_parentheses_for_hash_value_omission?(node)
|
19
21
|
return if syntax_like_method_call?(node)
|
20
22
|
return if super_call_without_arguments?(node)
|
21
23
|
return if allowed_camel_case_method_call?(node)
|
@@ -26,6 +28,7 @@ module RuboCop
|
|
26
28
|
auto_correct(corrector, node)
|
27
29
|
end
|
28
30
|
end
|
31
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
29
32
|
|
30
33
|
def auto_correct(corrector, node)
|
31
34
|
if parentheses_at_the_end_of_multiline_call?(node)
|
@@ -45,6 +48,23 @@ module RuboCop
|
|
45
48
|
node.each_ancestor(:def, :defs).any?(&:endless?) && node.arguments.any?
|
46
49
|
end
|
47
50
|
|
51
|
+
def require_parentheses_for_hash_value_omission?(node)
|
52
|
+
return false unless (last_argument = node.last_argument)
|
53
|
+
return false if !last_argument.hash_type? || !last_argument.pairs.last&.value_omission?
|
54
|
+
|
55
|
+
modifier_form?(node) || exist_next_line_expression?(node)
|
56
|
+
end
|
57
|
+
|
58
|
+
def modifier_form?(node)
|
59
|
+
node.parent.respond_to?(:modifier_form?) && node.parent.modifier_form?
|
60
|
+
end
|
61
|
+
|
62
|
+
# Require hash value omission be enclosed in parentheses to prevent the following issue:
|
63
|
+
# https://bugs.ruby-lang.org/issues/18396.
|
64
|
+
def exist_next_line_expression?(node)
|
65
|
+
node.parent&.assignment? ? node.parent.right_sibling : node.right_sibling
|
66
|
+
end
|
67
|
+
|
48
68
|
def syntax_like_method_call?(node)
|
49
69
|
node.implicit_call? || node.operator_method?
|
50
70
|
end
|
@@ -43,9 +43,11 @@ module RuboCop
|
|
43
43
|
# NOTE: Parentheses are still allowed in cases where omitting them
|
44
44
|
# results in ambiguous or syntactically incorrect code. For example,
|
45
45
|
# parentheses are required around a method with arguments when inside an
|
46
|
-
# endless method definition introduced in Ruby 3.0.
|
46
|
+
# endless method definition introduced in Ruby 3.0. Parentheses are also
|
47
47
|
# allowed when forwarding arguments with the triple-dot syntax introduced
|
48
48
|
# in Ruby 2.7 as omitting them starts an endless range.
|
49
|
+
# And Ruby 3.1's hash omission syntax has a case that requires parentheses
|
50
|
+
# because of the following issue: https://bugs.ruby-lang.org/issues/18396.
|
49
51
|
#
|
50
52
|
# @example EnforcedStyle: require_parentheses (default)
|
51
53
|
#
|
@@ -6,8 +6,13 @@ module RuboCop
|
|
6
6
|
# This cop checks for parentheses around the arguments in method
|
7
7
|
# definitions. Both instance and class/singleton methods are checked.
|
8
8
|
#
|
9
|
-
#
|
10
|
-
#
|
9
|
+
# Regardless of style, parentheses are necessary for:
|
10
|
+
#
|
11
|
+
# 1. Endless methods
|
12
|
+
# 2. Argument lists containing a `forward-arg` (`...`)
|
13
|
+
# 3. Argument lists containing an anonymous block forwarding (`&`)
|
14
|
+
#
|
15
|
+
# Removing the parens would be a syntax error here.
|
11
16
|
#
|
12
17
|
# @example EnforcedStyle: require_parentheses (default)
|
13
18
|
# # The `require_parentheses` style requires method definitions
|
@@ -121,21 +126,13 @@ module RuboCop
|
|
121
126
|
corrector.remove(arg_node.loc.end)
|
122
127
|
end
|
123
128
|
|
124
|
-
def correct_definition(def_node, corrector)
|
125
|
-
arguments_range = def_node.arguments.source_range
|
126
|
-
args_with_space = range_with_surrounding_space(range: arguments_range, side: :left)
|
127
|
-
leading_space = range_between(args_with_space.begin_pos, arguments_range.begin_pos)
|
128
|
-
corrector.replace(leading_space, '(')
|
129
|
-
corrector.insert_after(arguments_range, ')')
|
130
|
-
end
|
131
|
-
|
132
129
|
def forced_parentheses?(node)
|
133
130
|
# Regardless of style, parentheses are necessary for:
|
134
131
|
# 1. Endless methods
|
135
132
|
# 2. Argument lists containing a `forward-arg` (`...`)
|
133
|
+
# 3. Argument lists containing an anonymous block forwarding (`&`)
|
136
134
|
# Removing the parens would be a syntax error here.
|
137
|
-
|
138
|
-
node.endless? || node.arguments.any?(&:forward_arg_type?)
|
135
|
+
node.endless? || node.arguments.any?(&:forward_arg_type?) || anonymous_block_arg?(node)
|
139
136
|
end
|
140
137
|
|
141
138
|
def require_parentheses?(args)
|
@@ -151,7 +148,8 @@ module RuboCop
|
|
151
148
|
location = node.arguments.source_range
|
152
149
|
|
153
150
|
add_offense(location, message: MSG_MISSING) do |corrector|
|
154
|
-
|
151
|
+
add_parentheses(node.arguments, corrector)
|
152
|
+
|
155
153
|
unexpected_style_detected 'require_no_parentheses'
|
156
154
|
end
|
157
155
|
end
|
@@ -163,6 +161,12 @@ module RuboCop
|
|
163
161
|
unexpected_style_detected 'require_parentheses'
|
164
162
|
end
|
165
163
|
end
|
164
|
+
|
165
|
+
def anonymous_block_arg?(node)
|
166
|
+
return false unless (last_argument = node.arguments.last)
|
167
|
+
|
168
|
+
last_argument.blockarg_type? && last_argument.name.nil?
|
169
|
+
end
|
166
170
|
end
|
167
171
|
end
|
168
172
|
end
|
@@ -27,6 +27,11 @@ module RuboCop
|
|
27
27
|
# # bad
|
28
28
|
# 10_000_00 # typical representation of $10,000 in cents
|
29
29
|
#
|
30
|
+
# @example AllowedNumbers: [3000]
|
31
|
+
#
|
32
|
+
# # good
|
33
|
+
# 3000 # You can specify allowed numbers. (e.g. port number)
|
34
|
+
#
|
30
35
|
class NumericLiterals < Base
|
31
36
|
include IntegerNode
|
32
37
|
extend AutoCorrector
|
@@ -51,9 +56,9 @@ module RuboCop
|
|
51
56
|
|
52
57
|
def check(node)
|
53
58
|
int = integer_part(node)
|
54
|
-
|
55
59
|
# TODO: handle non-decimal literals as well
|
56
60
|
return if int.start_with?('0')
|
61
|
+
return if allowed_numbers.include?(int)
|
57
62
|
return unless int.size >= min_digits
|
58
63
|
|
59
64
|
case int
|
@@ -99,6 +104,10 @@ module RuboCop
|
|
99
104
|
def min_digits
|
100
105
|
cop_config['MinDigits']
|
101
106
|
end
|
107
|
+
|
108
|
+
def allowed_numbers
|
109
|
+
cop_config.fetch('AllowedNumbers', []).map(&:to_s)
|
110
|
+
end
|
102
111
|
end
|
103
112
|
end
|
104
113
|
end
|
@@ -45,7 +45,7 @@ module RuboCop
|
|
45
45
|
|
46
46
|
message = message(node)
|
47
47
|
add_offense(node, message: message) do |corrector|
|
48
|
-
corrector
|
48
|
+
autocorrect(corrector, node)
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
@@ -55,55 +55,30 @@ module RuboCop
|
|
55
55
|
format(MSG, keyword: node.keyword)
|
56
56
|
end
|
57
57
|
|
58
|
-
def
|
58
|
+
def autocorrect(corrector, node)
|
59
59
|
if always_multiline? || cannot_replace_to_ternary?(node)
|
60
|
-
|
60
|
+
IfThenCorrector.new(node, indentation: indentation_width).call(corrector)
|
61
61
|
else
|
62
|
-
|
63
|
-
return replaced_node unless node.parent
|
64
|
-
return "(#{replaced_node})" if %i[and or].include?(node.parent.type)
|
65
|
-
return "(#{replaced_node})" if node.parent.send_type? && node.parent.operator_method?
|
66
|
-
|
67
|
-
replaced_node
|
62
|
+
corrector.replace(node, ternary_correction(node))
|
68
63
|
end
|
69
64
|
end
|
70
65
|
|
71
|
-
def
|
72
|
-
|
73
|
-
end
|
66
|
+
def ternary_correction(node)
|
67
|
+
replaced_node = ternary_replacement(node)
|
74
68
|
|
75
|
-
|
76
|
-
node.
|
77
|
-
|
69
|
+
return replaced_node unless node.parent
|
70
|
+
return "(#{replaced_node})" if %i[and or].include?(node.parent.type)
|
71
|
+
return "(#{replaced_node})" if node.parent.send_type? && node.parent.operator_method?
|
78
72
|
|
79
|
-
|
80
|
-
indentation = ' ' * node.source_range.column if indentation.nil?
|
81
|
-
if_branch_source = node.if_branch&.source || 'nil'
|
82
|
-
elsif_indentation = indentation if node.respond_to?(:elsif?) && node.elsif?
|
83
|
-
if_branch = <<~RUBY
|
84
|
-
#{elsif_indentation}#{node.keyword} #{node.condition.source}
|
85
|
-
#{indentation}#{branch_body_indentation}#{if_branch_source}
|
86
|
-
RUBY
|
87
|
-
else_branch = else_branch_to_multiline(node.else_branch, indentation)
|
88
|
-
if_branch + else_branch
|
73
|
+
replaced_node
|
89
74
|
end
|
90
75
|
|
91
|
-
def
|
92
|
-
|
93
|
-
'end'
|
94
|
-
elsif else_branch.if_type? && else_branch.elsif?
|
95
|
-
multiline_replacement(else_branch, indentation)
|
96
|
-
else
|
97
|
-
<<~RUBY.chomp
|
98
|
-
#{indentation}else
|
99
|
-
#{indentation}#{branch_body_indentation}#{else_branch.source}
|
100
|
-
#{indentation}end
|
101
|
-
RUBY
|
102
|
-
end
|
76
|
+
def always_multiline?
|
77
|
+
@config.for_cop('Style/OneLineConditional')['AlwaysCorrectToMultiline']
|
103
78
|
end
|
104
79
|
|
105
|
-
def
|
106
|
-
|
80
|
+
def cannot_replace_to_ternary?(node)
|
81
|
+
node.elsif_conditional?
|
107
82
|
end
|
108
83
|
|
109
84
|
def ternary_replacement(node)
|
@@ -141,6 +116,10 @@ module RuboCop
|
|
141
116
|
|
142
117
|
node.respond_to?(:arguments?) && node.arguments? && !node.parenthesized_call?
|
143
118
|
end
|
119
|
+
|
120
|
+
def indentation_width
|
121
|
+
@config.for_cop('Layout/IndentationWidth')['Width']
|
122
|
+
end
|
144
123
|
end
|
145
124
|
end
|
146
125
|
end
|
@@ -97,7 +97,7 @@ module RuboCop
|
|
97
97
|
offense_range = node.loc.begin
|
98
98
|
|
99
99
|
add_offense(offense_range) do |corrector|
|
100
|
-
if
|
100
|
+
if node.parent&.assignment?
|
101
101
|
replace_begin_with_statement(corrector, offense_range, node)
|
102
102
|
else
|
103
103
|
corrector.remove(offense_range)
|
@@ -170,11 +170,7 @@ module RuboCop
|
|
170
170
|
end
|
171
171
|
|
172
172
|
def valid_begin_assignment?(node)
|
173
|
-
|
174
|
-
end
|
175
|
-
|
176
|
-
def any_ancestor_assignment_node?(node)
|
177
|
-
node.each_ancestor.any?(&:assignment?)
|
173
|
+
node.parent&.assignment? && !node.children.one?
|
178
174
|
end
|
179
175
|
end
|
180
176
|
end
|
@@ -82,10 +82,20 @@ module RuboCop
|
|
82
82
|
end
|
83
83
|
|
84
84
|
def autocorrect_single_variable_interpolation(corrector, embedded_node, node)
|
85
|
-
|
86
|
-
replacement = "#{variable_loc.expression.source}.to_s"
|
85
|
+
embedded_var = embedded_node.children.first
|
87
86
|
|
88
|
-
|
87
|
+
source = if require_parentheses?(embedded_var)
|
88
|
+
receiver = range_between(
|
89
|
+
embedded_var.loc.expression.begin_pos, embedded_var.loc.selector.end_pos
|
90
|
+
)
|
91
|
+
arguments = embedded_var.arguments.map(&:source).join(', ')
|
92
|
+
|
93
|
+
"#{receiver.source}(#{arguments})"
|
94
|
+
else
|
95
|
+
embedded_var.source
|
96
|
+
end
|
97
|
+
|
98
|
+
corrector.replace(node, "#{source}.to_s")
|
89
99
|
end
|
90
100
|
|
91
101
|
def autocorrect_other(corrector, embedded_node, node)
|
@@ -97,6 +107,10 @@ module RuboCop
|
|
97
107
|
corrector.replace(embedded_loc.begin, '(')
|
98
108
|
corrector.replace(embedded_loc.end, ').to_s')
|
99
109
|
end
|
110
|
+
|
111
|
+
def require_parentheses?(node)
|
112
|
+
node.send_type? && !node.arguments.count.zero? && !node.parenthesized_call?
|
113
|
+
end
|
100
114
|
end
|
101
115
|
end
|
102
116
|
end
|
@@ -80,7 +80,11 @@ module RuboCop
|
|
80
80
|
end
|
81
81
|
|
82
82
|
def without_character_class(loc)
|
83
|
-
loc.source[1..-2]
|
83
|
+
without_character_class = loc.source[1..-2]
|
84
|
+
|
85
|
+
# Adds `\` to prevent auto-correction that changes to an interpolated string when `[#]`.
|
86
|
+
# e.g. From `/[#]{0}/` to `/#{0}/`
|
87
|
+
loc.source == '[#]' ? "\\#{without_character_class}" : without_character_class
|
84
88
|
end
|
85
89
|
|
86
90
|
def whitespace_in_free_space_mode?(node, elem)
|
@@ -218,11 +218,7 @@ module RuboCop
|
|
218
218
|
def find_matching_receiver_invocation(method_chain, checked_variable)
|
219
219
|
return nil unless method_chain
|
220
220
|
|
221
|
-
receiver =
|
222
|
-
method_chain.send_node.receiver
|
223
|
-
else
|
224
|
-
method_chain.receiver
|
225
|
-
end
|
221
|
+
receiver = method_chain.receiver
|
226
222
|
|
227
223
|
return receiver if receiver == checked_variable
|
228
224
|
|
@@ -91,11 +91,12 @@ module RuboCop
|
|
91
91
|
second.int_type? ? second.to_a.first : :unknown
|
92
92
|
end
|
93
93
|
|
94
|
-
|
94
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
95
|
+
def range_size(range_node)
|
95
96
|
vals = range_node.to_a
|
96
|
-
return :unknown unless vals.all?
|
97
|
+
return :unknown unless vals.all? { |val| val.nil? || val.int_type? }
|
97
98
|
|
98
|
-
low, high = vals.map { |val| val.children[0] }
|
99
|
+
low, high = vals.map { |val| val.nil? ? 0 : val.children[0] }
|
99
100
|
return :unknown unless low.zero? && high >= 0
|
100
101
|
|
101
102
|
case range_node.type
|
@@ -105,6 +106,7 @@ module RuboCop
|
|
105
106
|
(low..high).size
|
106
107
|
end
|
107
108
|
end
|
109
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
108
110
|
|
109
111
|
def source_range(shuffle_node, node)
|
110
112
|
Parser::Source::Range.new(shuffle_node.source_range.source_buffer,
|
@@ -39,7 +39,7 @@ module RuboCop
|
|
39
39
|
return unless eligible_method?(node)
|
40
40
|
return unless eligible_arguments?(node)
|
41
41
|
|
42
|
-
method_name = node.
|
42
|
+
method_name = node.method_name
|
43
43
|
return if args_match?(method_name, node.arguments)
|
44
44
|
|
45
45
|
preferred_block_arguments = build_preferred_arguments_map(node, target_args(method_name))
|
@@ -81,7 +81,7 @@ module RuboCop
|
|
81
81
|
end
|
82
82
|
|
83
83
|
def eligible_method?(node)
|
84
|
-
node.
|
84
|
+
node.receiver && method_names.include?(node.method_name)
|
85
85
|
end
|
86
86
|
|
87
87
|
def methods
|
@@ -82,7 +82,9 @@ module RuboCop
|
|
82
82
|
end
|
83
83
|
|
84
84
|
def autocorrect(corrector, node, if_branch)
|
85
|
-
|
85
|
+
if node.condition.or_type? || node.condition.assignment?
|
86
|
+
corrector.wrap(node.condition, '(', ')')
|
87
|
+
end
|
86
88
|
|
87
89
|
correct_from_unless_to_if(corrector, node) if node.unless?
|
88
90
|
|
@@ -67,7 +67,10 @@ module RuboCop
|
|
67
67
|
MSG_COMPLEX = '%<command>s parentheses for ternary expressions with complex conditions.'
|
68
68
|
|
69
69
|
def on_if(node)
|
70
|
-
|
70
|
+
condition = node.condition
|
71
|
+
|
72
|
+
return if only_closing_parenthesis_is_last_line?(condition)
|
73
|
+
return if condition_as_parenthesized_one_line_pattern_matching?(condition)
|
71
74
|
return unless node.ternary? && !infinite_loop? && offense?(node)
|
72
75
|
|
73
76
|
message = message(node)
|
@@ -77,11 +80,22 @@ module RuboCop
|
|
77
80
|
end
|
78
81
|
end
|
79
82
|
|
83
|
+
private
|
84
|
+
|
80
85
|
def only_closing_parenthesis_is_last_line?(condition)
|
81
86
|
condition.source.split("\n").last == ')'
|
82
87
|
end
|
83
88
|
|
84
|
-
|
89
|
+
def condition_as_parenthesized_one_line_pattern_matching?(condition)
|
90
|
+
return false unless condition.parenthesized_call?
|
91
|
+
return false unless (first_child = condition.children.first)
|
92
|
+
|
93
|
+
if target_ruby_version >= 3.0
|
94
|
+
first_child.match_pattern_p_type?
|
95
|
+
else
|
96
|
+
first_child.match_pattern_type? # For Ruby 2.7's one line pattern matching AST.
|
97
|
+
end
|
98
|
+
end
|
85
99
|
|
86
100
|
def autocorrect(corrector, node)
|
87
101
|
condition = node.condition
|
data/lib/rubocop/cop/team.rb
CHANGED
data/lib/rubocop/cop/util.rb
CHANGED
@@ -30,8 +30,15 @@ module RuboCop
|
|
30
30
|
node.loc.respond_to?(:end) && node.loc.end && node.loc.end.is?(')')
|
31
31
|
end
|
32
32
|
|
33
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
33
34
|
def add_parentheses(node, corrector)
|
34
|
-
if
|
35
|
+
if node.args_type?
|
36
|
+
arguments_range = node.source_range
|
37
|
+
args_with_space = range_with_surrounding_space(range: arguments_range, side: :left)
|
38
|
+
leading_space = range_between(args_with_space.begin_pos, arguments_range.begin_pos)
|
39
|
+
corrector.replace(leading_space, '(')
|
40
|
+
corrector.insert_after(arguments_range, ')')
|
41
|
+
elsif !node.respond_to?(:arguments)
|
35
42
|
corrector.wrap(node, '(', ')')
|
36
43
|
elsif node.arguments.empty?
|
37
44
|
corrector.insert_after(node, '()')
|
@@ -43,6 +50,7 @@ module RuboCop
|
|
43
50
|
corrector.insert_after(args_end(node), ')')
|
44
51
|
end
|
45
52
|
end
|
53
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
46
54
|
|
47
55
|
def args_begin(node)
|
48
56
|
loc = node.loc
|
@@ -121,9 +121,14 @@ module RuboCop
|
|
121
121
|
output_buffer.puts "# Offense count: #{offense_count}" if show_offense_counts?
|
122
122
|
|
123
123
|
cop_class = Cop::Registry.global.find_by_cop_name(cop_name)
|
124
|
-
output_buffer.puts '# Cop supports --auto-correct.' if cop_class&.support_autocorrect?
|
125
|
-
|
126
124
|
default_cfg = default_config(cop_name)
|
125
|
+
|
126
|
+
if supports_safe_auto_correct?(cop_class, default_cfg)
|
127
|
+
output_buffer.puts '# Cop supports --auto-correct.'
|
128
|
+
elsif supports_unsafe_autocorrect?(cop_class, default_cfg)
|
129
|
+
output_buffer.puts '# Cop supports --auto-correct-all.'
|
130
|
+
end
|
131
|
+
|
127
132
|
return unless default_cfg
|
128
133
|
|
129
134
|
params = cop_config_params(default_cfg, cfg)
|
@@ -132,6 +137,15 @@ module RuboCop
|
|
132
137
|
output_cop_param_comments(output_buffer, params, default_cfg)
|
133
138
|
end
|
134
139
|
|
140
|
+
def supports_safe_auto_correct?(cop_class, default_cfg)
|
141
|
+
cop_class&.support_autocorrect? &&
|
142
|
+
(default_cfg.nil? || default_cfg['Safe'] || default_cfg['Safe'].nil?)
|
143
|
+
end
|
144
|
+
|
145
|
+
def supports_unsafe_autocorrect?(cop_class, default_cfg)
|
146
|
+
cop_class&.support_autocorrect? && !default_cfg.nil? && default_cfg['Safe'] == false
|
147
|
+
end
|
148
|
+
|
135
149
|
def cop_config_params(default_cfg, cfg)
|
136
150
|
default_cfg.keys -
|
137
151
|
%w[Description StyleGuide Reference Enabled Exclude Safe
|
data/lib/rubocop/options.rb
CHANGED
@@ -15,7 +15,7 @@ module RuboCop
|
|
15
15
|
'root of the project. RuboCop will use this path to determine which ' \
|
16
16
|
'cops are enabled (via eg. Include/Exclude), and so that certain cops ' \
|
17
17
|
'like Naming/FileName can be checked.'
|
18
|
-
EXITING_OPTIONS = %i[version verbose_version show_cops].freeze
|
18
|
+
EXITING_OPTIONS = %i[version verbose_version show_cops show_docs_url].freeze
|
19
19
|
DEFAULT_MAXIMUM_EXCLUSION_ITEMS = 15
|
20
20
|
|
21
21
|
def initialize
|
@@ -188,6 +188,9 @@ module RuboCop
|
|
188
188
|
option(opts, '--show-cops [COP1,COP2,...]') do |list|
|
189
189
|
@options[:show_cops] = list.nil? ? [] : list.split(',')
|
190
190
|
end
|
191
|
+
option(opts, '--show-docs-url [COP1,COP2,...]') do |list|
|
192
|
+
@options[:show_docs_url] = list.nil? ? [] : list.split(',')
|
193
|
+
end
|
191
194
|
end
|
192
195
|
end
|
193
196
|
|
@@ -475,6 +478,8 @@ module RuboCop
|
|
475
478
|
show_cops: ['Shows the given cops, or all cops by',
|
476
479
|
'default, and their configurations for the',
|
477
480
|
'current directory.'],
|
481
|
+
show_docs_url: ['Display url to documentation for the given',
|
482
|
+
'cops, or base url by default.'],
|
478
483
|
fail_fast: ['Inspect files in order of modification',
|
479
484
|
'time and stop after the first file',
|
480
485
|
'containing offenses.'],
|
data/lib/rubocop/result_cache.rb
CHANGED
@@ -179,7 +179,7 @@ module RuboCop
|
|
179
179
|
.select { |path| File.file?(path) }
|
180
180
|
.sort!
|
181
181
|
.each do |path|
|
182
|
-
content = File.
|
182
|
+
content = File.binread(path)
|
183
183
|
digest << Zlib.crc32(content).to_s # mtime not reliable
|
184
184
|
end
|
185
185
|
digest << RuboCop::Version::STRING << RuboCop::AST::Version::STRING
|
data/lib/rubocop/version.rb
CHANGED