rubocop 1.32.0 → 1.34.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 +2 -2
- data/config/default.yml +51 -16
- data/config/obsoletion.yml +23 -1
- data/lib/rubocop/cache_config.rb +29 -0
- data/lib/rubocop/cli/command/auto_genenerate_config.rb +2 -2
- data/lib/rubocop/cli/command/init_dotfile.rb +1 -1
- data/lib/rubocop/cli/command/suggest_extensions.rb +53 -15
- data/lib/rubocop/config_finder.rb +68 -0
- data/lib/rubocop/config_loader.rb +12 -40
- data/lib/rubocop/config_loader_resolver.rb +1 -5
- data/lib/rubocop/config_obsoletion/changed_parameter.rb +5 -0
- data/lib/rubocop/config_obsoletion/parameter_rule.rb +4 -0
- data/lib/rubocop/config_obsoletion.rb +7 -2
- data/lib/rubocop/cop/cop.rb +1 -1
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +28 -0
- data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +61 -0
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/layout/block_end_newline.rb +33 -5
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +6 -1
- data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -1
- data/lib/rubocop/cop/legacy/corrections_proxy.rb +1 -1
- data/lib/rubocop/cop/legacy/corrector.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +21 -8
- data/lib/rubocop/cop/lint/debugger.rb +26 -16
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +65 -1
- data/lib/rubocop/cop/lint/number_conversion.rb +24 -8
- data/lib/rubocop/cop/lint/shadowed_exception.rb +15 -0
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +9 -1
- data/lib/rubocop/cop/metrics/abc_size.rb +3 -1
- data/lib/rubocop/cop/metrics/block_length.rb +6 -7
- data/lib/rubocop/cop/metrics/method_length.rb +8 -8
- data/lib/rubocop/cop/mixin/allowed_methods.rb +15 -1
- data/lib/rubocop/cop/mixin/allowed_pattern.rb +9 -1
- data/lib/rubocop/cop/mixin/comments_help.rb +5 -1
- data/lib/rubocop/cop/mixin/enforce_superclass.rb +2 -1
- data/lib/rubocop/cop/mixin/method_complexity.rb +4 -9
- data/lib/rubocop/cop/mixin/range_help.rb +2 -2
- data/lib/rubocop/cop/naming/predicate_name.rb +24 -3
- data/lib/rubocop/cop/style/block_delimiters.rb +26 -7
- data/lib/rubocop/cop/style/class_and_module_children.rb +4 -4
- data/lib/rubocop/cop/style/class_equality_comparison.rb +32 -7
- data/lib/rubocop/cop/style/double_negation.rb +2 -0
- data/lib/rubocop/cop/style/empty_heredoc.rb +15 -1
- data/lib/rubocop/cop/style/format_string_token.rb +21 -8
- data/lib/rubocop/cop/style/hash_except.rb +0 -4
- data/lib/rubocop/cop/style/if_unless_modifier.rb +1 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +5 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +7 -7
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +11 -6
- data/lib/rubocop/cop/style/numeric_literals.rb +16 -1
- data/lib/rubocop/cop/style/numeric_predicate.rb +28 -8
- data/lib/rubocop/cop/style/redundant_condition.rb +19 -4
- data/lib/rubocop/cop/style/redundant_parentheses.rb +15 -22
- data/lib/rubocop/cop/style/redundant_sort.rb +21 -6
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +14 -3
- data/lib/rubocop/cop/style/symbol_proc.rb +34 -9
- data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -13
- data/lib/rubocop/ext/range.rb +15 -0
- data/lib/rubocop/feature_loader.rb +90 -0
- data/lib/rubocop/formatter/clang_style_formatter.rb +1 -1
- data/lib/rubocop/formatter/disabled_config_formatter.rb +1 -1
- data/lib/rubocop/formatter/html_formatter.rb +1 -1
- data/lib/rubocop/formatter/markdown_formatter.rb +1 -1
- data/lib/rubocop/formatter/tap_formatter.rb +1 -1
- data/lib/rubocop/result_cache.rb +22 -20
- data/lib/rubocop/server/cache.rb +33 -1
- data/lib/rubocop/server/cli.rb +19 -2
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +2 -1
- metadata +13 -9
- data/lib/rubocop/cop/mixin/ignored_methods.rb +0 -52
@@ -8,14 +8,14 @@ module RuboCop
|
|
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
|
-
# This cop can be customized
|
12
|
-
# By default, there are no methods to
|
11
|
+
# This cop can be customized allowed methods with `AllowedMethods`.
|
12
|
+
# By default, there are no methods to allowed.
|
13
13
|
#
|
14
14
|
# This cop disregards `#nonzero?` as its value is truthy or falsey,
|
15
15
|
# but not `true` and `false`, and thus not always interchangeable with
|
16
16
|
# `!= 0`.
|
17
17
|
#
|
18
|
-
# This cop
|
18
|
+
# This cop allows comparisons to global variables, since they are often
|
19
19
|
# populated with objects which can be compared with integers, but are
|
20
20
|
# not themselves `Integer` polymorphic.
|
21
21
|
#
|
@@ -46,13 +46,13 @@ module RuboCop
|
|
46
46
|
# 0 > foo
|
47
47
|
# bar.baz > 0
|
48
48
|
#
|
49
|
-
# @example
|
49
|
+
# @example AllowedMethods: [] (default) with EnforcedStyle: predicate
|
50
50
|
# # bad
|
51
51
|
# foo == 0
|
52
52
|
# 0 > foo
|
53
53
|
# bar.baz > 0
|
54
54
|
#
|
55
|
-
# @example
|
55
|
+
# @example AllowedMethods: [==] with EnforcedStyle: predicate
|
56
56
|
# # good
|
57
57
|
# foo == 0
|
58
58
|
#
|
@@ -60,9 +60,25 @@ module RuboCop
|
|
60
60
|
# 0 > foo
|
61
61
|
# bar.baz > 0
|
62
62
|
#
|
63
|
+
# @example AllowedPatterns: [] (default) with EnforcedStyle: comparison
|
64
|
+
# # bad
|
65
|
+
# foo.zero?
|
66
|
+
# foo.negative?
|
67
|
+
# bar.baz.positive?
|
68
|
+
#
|
69
|
+
# @example AllowedPatterns: [/zero/] with EnforcedStyle: predicate
|
70
|
+
# # good
|
71
|
+
# # bad
|
72
|
+
# foo.zero?
|
73
|
+
#
|
74
|
+
# # bad
|
75
|
+
# foo.negative?
|
76
|
+
# bar.baz.positive?
|
77
|
+
#
|
63
78
|
class NumericPredicate < Base
|
64
79
|
include ConfigurableEnforcedStyle
|
65
|
-
include
|
80
|
+
include AllowedMethods
|
81
|
+
include AllowedPattern
|
66
82
|
extend AutoCorrector
|
67
83
|
|
68
84
|
MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
|
@@ -75,9 +91,9 @@ module RuboCop
|
|
75
91
|
numeric, replacement = check(node)
|
76
92
|
return unless numeric
|
77
93
|
|
78
|
-
return if
|
94
|
+
return if allowed_method_name?(node.method_name) ||
|
79
95
|
node.each_ancestor(:send, :block).any? do |ancestor|
|
80
|
-
|
96
|
+
allowed_method_name?(ancestor.method_name)
|
81
97
|
end
|
82
98
|
|
83
99
|
message = format(MSG, prefer: replacement, current: node.source)
|
@@ -88,6 +104,10 @@ module RuboCop
|
|
88
104
|
|
89
105
|
private
|
90
106
|
|
107
|
+
def allowed_method_name?(name)
|
108
|
+
allowed_method?(name) || matches_allowed_pattern?(name)
|
109
|
+
end
|
110
|
+
|
91
111
|
def check(node)
|
92
112
|
numeric, operator =
|
93
113
|
if style == :predicate
|
@@ -154,16 +154,22 @@ module RuboCop
|
|
154
154
|
if_branch.method?(else_branch.method_name) && if_branch.receiver == else_branch.receiver
|
155
155
|
end
|
156
156
|
|
157
|
-
def if_source(if_branch)
|
157
|
+
def if_source(if_branch, arithmetic_operation)
|
158
158
|
if branches_have_method?(if_branch.parent) && if_branch.parenthesized?
|
159
159
|
if_branch.source.delete_suffix(')')
|
160
|
+
elsif arithmetic_operation
|
161
|
+
argument_source = if_branch.first_argument.source
|
162
|
+
|
163
|
+
"#{if_branch.receiver.source} #{if_branch.method_name} (#{argument_source}"
|
160
164
|
else
|
161
165
|
if_branch.source
|
162
166
|
end
|
163
167
|
end
|
164
168
|
|
165
|
-
def else_source(else_branch)
|
166
|
-
if
|
169
|
+
def else_source(else_branch, arithmetic_operation) # rubocop:disable Metrics/AbcSize
|
170
|
+
if arithmetic_operation
|
171
|
+
"#{else_branch.first_argument.source})"
|
172
|
+
elsif branches_have_method?(else_branch.parent)
|
167
173
|
else_source_if_has_method(else_branch)
|
168
174
|
elsif require_parentheses?(else_branch)
|
169
175
|
"(#{else_branch.source})"
|
@@ -198,7 +204,12 @@ module RuboCop
|
|
198
204
|
|
199
205
|
def make_ternary_form(node)
|
200
206
|
_condition, if_branch, else_branch = *node
|
201
|
-
|
207
|
+
arithmetic_operation = use_arithmetic_operation?(if_branch)
|
208
|
+
|
209
|
+
ternary_form = [
|
210
|
+
if_source(if_branch, arithmetic_operation),
|
211
|
+
else_source(else_branch, arithmetic_operation)
|
212
|
+
].join(' || ')
|
202
213
|
ternary_form += ')' if branches_have_method?(node) && if_branch.parenthesized?
|
203
214
|
|
204
215
|
if node.parent&.send_type?
|
@@ -227,6 +238,10 @@ module RuboCop
|
|
227
238
|
node.hash_type? && !node.braces?
|
228
239
|
end
|
229
240
|
|
241
|
+
def use_arithmetic_operation?(node)
|
242
|
+
node.respond_to?(:arithmetic_operation?) && node.arithmetic_operation?
|
243
|
+
end
|
244
|
+
|
230
245
|
def without_argument_parentheses_method?(node)
|
231
246
|
node.send_type? && !node.arguments.empty? &&
|
232
247
|
!node.parenthesized? && !node.operator_method? && !node.assignment_method?
|
@@ -57,8 +57,8 @@ module RuboCop
|
|
57
57
|
def allowed_expression?(node)
|
58
58
|
allowed_ancestor?(node) ||
|
59
59
|
allowed_method_call?(node) ||
|
60
|
-
|
61
|
-
|
60
|
+
allowed_multiple_expression?(node) ||
|
61
|
+
allowed_ternary?(node)
|
62
62
|
end
|
63
63
|
|
64
64
|
def allowed_ancestor?(node)
|
@@ -80,6 +80,19 @@ module RuboCop
|
|
80
80
|
!ancestor.begin_type? && !ancestor.def_type? && !ancestor.block_type?
|
81
81
|
end
|
82
82
|
|
83
|
+
def allowed_ternary?(node)
|
84
|
+
return unless node&.parent&.if_type?
|
85
|
+
|
86
|
+
node.parent.ternary? && ternary_parentheses_required?
|
87
|
+
end
|
88
|
+
|
89
|
+
def ternary_parentheses_required?
|
90
|
+
config = @config.for_cop('Style/TernaryParentheses')
|
91
|
+
allowed_styles = %w[require_parentheses require_parentheses_when_complex]
|
92
|
+
|
93
|
+
config.fetch('Enabled') && allowed_styles.include?(config['EnforcedStyle'])
|
94
|
+
end
|
95
|
+
|
83
96
|
def like_method_argument_parentheses?(node)
|
84
97
|
node.send_type? && node.arguments.one? &&
|
85
98
|
!node.arithmetic_operation? && node.first_argument.begin_type?
|
@@ -153,26 +166,6 @@ module RuboCop
|
|
153
166
|
node.parent&.keyword?
|
154
167
|
end
|
155
168
|
|
156
|
-
def allowed_array_or_hash_element?(node)
|
157
|
-
# Don't flag
|
158
|
-
# ```
|
159
|
-
# { a: (1
|
160
|
-
# ), }
|
161
|
-
# ```
|
162
|
-
hash_or_array_element?(node) && only_closing_paren_before_comma?(node)
|
163
|
-
end
|
164
|
-
|
165
|
-
def hash_or_array_element?(node)
|
166
|
-
node.each_ancestor(:array, :hash).any?
|
167
|
-
end
|
168
|
-
|
169
|
-
def only_closing_paren_before_comma?(node)
|
170
|
-
source_buffer = node.source_range.source_buffer
|
171
|
-
line_range = source_buffer.line_range(node.loc.end.line)
|
172
|
-
|
173
|
-
/^\s*\)\s*,/.match?(line_range.source)
|
174
|
-
end
|
175
|
-
|
176
169
|
def disallowed_literal?(begin_node, node)
|
177
170
|
node.literal? && !node.range_type? && !raised_to_power_negative_numeric?(begin_node, node)
|
178
171
|
end
|
@@ -123,13 +123,8 @@ module RuboCop
|
|
123
123
|
|
124
124
|
def register_offense(node, sort_node, sorter, accessor)
|
125
125
|
message = message(node, sorter, accessor)
|
126
|
-
|
127
126
|
add_offense(offense_range(sort_node, node), message: message) do |corrector|
|
128
|
-
|
129
|
-
corrector.remove(range_between(accessor_start(node), node.loc.expression.end_pos))
|
130
|
-
|
131
|
-
# Replace "sort" or "sort_by" with the appropriate min/max method.
|
132
|
-
corrector.replace(sort_node.loc.selector, suggestion(sorter, accessor, arg_value(node)))
|
127
|
+
autocorrect(corrector, node, sort_node, sorter, accessor)
|
133
128
|
end
|
134
129
|
end
|
135
130
|
|
@@ -149,6 +144,20 @@ module RuboCop
|
|
149
144
|
accessor_source: accessor_source)
|
150
145
|
end
|
151
146
|
|
147
|
+
def autocorrect(corrector, node, sort_node, sorter, accessor)
|
148
|
+
# Remove accessor, e.g. `first` or `[-1]`.
|
149
|
+
corrector.remove(range_between(accessor_start(node), node.loc.expression.end_pos))
|
150
|
+
# Replace "sort" or "sort_by" with the appropriate min/max method.
|
151
|
+
corrector.replace(sort_node.loc.selector, suggestion(sorter, accessor, arg_value(node)))
|
152
|
+
# Replace to avoid syntax errors when followed by a logical operator.
|
153
|
+
replace_with_logical_operator(corrector, node) if with_logical_operator?(node)
|
154
|
+
end
|
155
|
+
|
156
|
+
def replace_with_logical_operator(corrector, node)
|
157
|
+
corrector.insert_after(node.child_nodes.first, " #{node.parent.loc.operator.source}")
|
158
|
+
corrector.remove(node.parent.loc.operator)
|
159
|
+
end
|
160
|
+
|
152
161
|
def suggestion(sorter, accessor, arg)
|
153
162
|
base(accessor, arg) + suffix(sorter)
|
154
163
|
end
|
@@ -187,6 +196,12 @@ module RuboCop
|
|
187
196
|
node.loc.selector.begin_pos
|
188
197
|
end
|
189
198
|
end
|
199
|
+
|
200
|
+
def with_logical_operator?(node)
|
201
|
+
return unless (parent = node.parent)
|
202
|
+
|
203
|
+
parent.or_type? || parent.and_type?
|
204
|
+
end
|
190
205
|
end
|
191
206
|
end
|
192
207
|
end
|
@@ -148,7 +148,18 @@ module RuboCop
|
|
148
148
|
)
|
149
149
|
corrector.replace(range, and_operator)
|
150
150
|
corrector.remove(range_by_whole_lines(node.loc.end, include_final_newline: true))
|
151
|
-
|
151
|
+
|
152
|
+
wrap_condition(corrector, if_branch.condition)
|
153
|
+
end
|
154
|
+
|
155
|
+
def wrap_condition(corrector, condition)
|
156
|
+
# Handle `send` and `block` nodes that need to be wrapped in parens
|
157
|
+
# FIXME: autocorrection prevents syntax errors by wrapping the entire node in parens,
|
158
|
+
# but wrapping the argument list would be a more ergonomic correction.
|
159
|
+
node_to_check = condition&.block_type? ? condition.send_node : condition
|
160
|
+
return unless wrap_condition?(node_to_check)
|
161
|
+
|
162
|
+
corrector.wrap(condition, '(', ')')
|
152
163
|
end
|
153
164
|
|
154
165
|
def correct_for_outer_condition_modify_form_style(corrector, node, if_branch)
|
@@ -207,7 +218,7 @@ module RuboCop
|
|
207
218
|
end
|
208
219
|
|
209
220
|
def require_parentheses?(condition)
|
210
|
-
condition.
|
221
|
+
condition.call_type? && !condition.arguments.empty? && !condition.parenthesized? &&
|
211
222
|
!condition.comparison_method?
|
212
223
|
end
|
213
224
|
|
@@ -219,7 +230,7 @@ module RuboCop
|
|
219
230
|
|
220
231
|
def wrap_condition?(node)
|
221
232
|
node.and_type? || node.or_type? ||
|
222
|
-
(node.
|
233
|
+
(node.call_type? && node.arguments.any? && !node.parenthesized?)
|
223
234
|
end
|
224
235
|
|
225
236
|
def replace_condition(condition)
|
@@ -7,13 +7,13 @@ module RuboCop
|
|
7
7
|
#
|
8
8
|
# If you prefer a style that allows block for method with arguments,
|
9
9
|
# please set `true` to `AllowMethodsWithArguments`.
|
10
|
-
# respond_to , and `define_method?` methods are
|
11
|
-
# These are customizable with `
|
10
|
+
# respond_to , and `define_method?` methods are allowed by default.
|
11
|
+
# These are customizable with `AllowedMethods` option.
|
12
12
|
#
|
13
13
|
# @safety
|
14
14
|
# This cop is unsafe because `proc`s and blocks work differently
|
15
15
|
# when additional arguments are passed in. A block will silently
|
16
|
-
#
|
16
|
+
# allow additional arguments, but a `proc` will raise
|
17
17
|
# an `ArgumentError`.
|
18
18
|
#
|
19
19
|
# For example:
|
@@ -71,15 +71,25 @@ module RuboCop
|
|
71
71
|
# # some comment
|
72
72
|
# end
|
73
73
|
#
|
74
|
-
# @example
|
74
|
+
# @example AllowedMethods: [respond_to, define_method] (default)
|
75
75
|
# # good
|
76
76
|
# respond_to { |foo| foo.bar }
|
77
77
|
# define_method(:foo) { |foo| foo.bar }
|
78
78
|
#
|
79
|
+
#
|
80
|
+
# @example AllowedPatterns: [] (default)
|
81
|
+
# # bad
|
82
|
+
# something.map { |s| s.upcase }
|
83
|
+
#
|
84
|
+
# @example AllowedPatterns: [/map/] (default)
|
85
|
+
# # good
|
86
|
+
# something.map { |s| s.upcase }
|
87
|
+
#
|
79
88
|
class SymbolProc < Base
|
80
89
|
include CommentsHelp
|
81
90
|
include RangeHelp
|
82
|
-
include
|
91
|
+
include AllowedMethods
|
92
|
+
include AllowedPattern
|
83
93
|
extend AutoCorrector
|
84
94
|
|
85
95
|
MSG = 'Pass `&:%<method>s` as an argument to `%<block_method>s` instead of a block.'
|
@@ -103,15 +113,17 @@ module RuboCop
|
|
103
113
|
[Layout::SpaceBeforeBlockBraces]
|
104
114
|
end
|
105
115
|
|
106
|
-
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
116
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
107
117
|
def on_block(node)
|
108
118
|
symbol_proc?(node) do |dispatch_node, arguments_node, method_name|
|
109
119
|
# TODO: Rails-specific handling that we should probably make
|
110
120
|
# configurable - https://github.com/rubocop/rubocop/issues/1485
|
111
|
-
# we should
|
121
|
+
# we should allow lambdas & procs
|
112
122
|
return if proc_node?(dispatch_node)
|
123
|
+
return if unsafe_hash_usage?(dispatch_node)
|
124
|
+
return if unsafe_array_usage?(dispatch_node)
|
113
125
|
return if %i[lambda proc].include?(dispatch_node.method_name)
|
114
|
-
return if
|
126
|
+
return if allowed_method_name?(dispatch_node.method_name)
|
115
127
|
return if allow_if_method_has_argument?(node.send_node)
|
116
128
|
return if node.block_type? && destructuring_block_argument?(arguments_node)
|
117
129
|
return if allow_comments? && contains_comments?(node)
|
@@ -119,7 +131,7 @@ module RuboCop
|
|
119
131
|
register_offense(node, method_name, dispatch_node.method_name)
|
120
132
|
end
|
121
133
|
end
|
122
|
-
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
134
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
123
135
|
alias on_numblock on_block
|
124
136
|
|
125
137
|
def destructuring_block_argument?(argument_node)
|
@@ -128,6 +140,19 @@ module RuboCop
|
|
128
140
|
|
129
141
|
private
|
130
142
|
|
143
|
+
# See: https://github.com/rubocop/rubocop/issues/10864
|
144
|
+
def unsafe_hash_usage?(node)
|
145
|
+
node.receiver&.hash_type? && %i[reject select].include?(node.method_name)
|
146
|
+
end
|
147
|
+
|
148
|
+
def unsafe_array_usage?(node)
|
149
|
+
node.receiver&.array_type? && %i[min max].include?(node.method_name)
|
150
|
+
end
|
151
|
+
|
152
|
+
def allowed_method_name?(name)
|
153
|
+
allowed_method?(name) || matches_allowed_pattern?(name)
|
154
|
+
end
|
155
|
+
|
131
156
|
def register_offense(node, method_name, block_method_name)
|
132
157
|
block_start = node.loc.begin.begin_pos
|
133
158
|
block_end = node.loc.end.end_pos
|
@@ -71,7 +71,7 @@ module RuboCop
|
|
71
71
|
|
72
72
|
return if only_closing_parenthesis_is_last_line?(condition)
|
73
73
|
return if condition_as_parenthesized_one_line_pattern_matching?(condition)
|
74
|
-
return unless node.ternary? &&
|
74
|
+
return unless node.ternary? && offense?(node)
|
75
75
|
|
76
76
|
message = message(node)
|
77
77
|
|
@@ -166,22 +166,10 @@ module RuboCop
|
|
166
166
|
style == :require_parentheses_when_complex
|
167
167
|
end
|
168
168
|
|
169
|
-
def redundant_parentheses_enabled?
|
170
|
-
@config.for_cop('Style/RedundantParentheses').fetch('Enabled')
|
171
|
-
end
|
172
|
-
|
173
169
|
def parenthesized?(node)
|
174
170
|
node.begin_type?
|
175
171
|
end
|
176
172
|
|
177
|
-
# When this cop is configured to enforce parentheses and the
|
178
|
-
# `RedundantParentheses` cop is enabled, it will cause an infinite loop
|
179
|
-
# as they compete to add and remove the parentheses respectively.
|
180
|
-
def infinite_loop?
|
181
|
-
(require_parentheses? || require_parentheses_when_complex?) &&
|
182
|
-
redundant_parentheses_enabled?
|
183
|
-
end
|
184
|
-
|
185
173
|
def unsafe_autocorrect?(condition)
|
186
174
|
condition.children.any? do |child|
|
187
175
|
unparenthesized_method_call?(child) || below_ternary_precedence?(child)
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Ext
|
5
|
+
# Extensions to Parser::Source::Range
|
6
|
+
module Range
|
7
|
+
# Adds `Range#single_line?` to parallel `Node#single_line?`
|
8
|
+
def single_line?
|
9
|
+
first_line == last_line
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Parser::Source::Range.include RuboCop::Ext::Range
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
# This class handles loading files (a.k.a. features in Ruby) specified
|
5
|
+
# by `--require` command line option and `require` directive in the config.
|
6
|
+
#
|
7
|
+
# Normally, the given string is directly passed to `require`. If a string
|
8
|
+
# beginning with `.` is given, it is assumed to be relative to the given
|
9
|
+
# directory.
|
10
|
+
#
|
11
|
+
# If a string containing `-` is given, it will be used as is, but if we
|
12
|
+
# cannot find the file to load, we will replace `-` with `/` and try it
|
13
|
+
# again as when Bundler loads gems.
|
14
|
+
#
|
15
|
+
# @api private
|
16
|
+
class FeatureLoader
|
17
|
+
class << self
|
18
|
+
# @param [String] config_directory_path
|
19
|
+
# @param [String] feature
|
20
|
+
def load(config_directory_path:, feature:)
|
21
|
+
new(config_directory_path: config_directory_path, feature: feature).load
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param [String] config_directory_path
|
26
|
+
# @param [String] feature
|
27
|
+
def initialize(config_directory_path:, feature:)
|
28
|
+
@config_directory_path = config_directory_path
|
29
|
+
@feature = feature
|
30
|
+
end
|
31
|
+
|
32
|
+
def load
|
33
|
+
# Don't use `::Kernel.require(target)` to prevent the following error:
|
34
|
+
# https://github.com/rubocop/rubocop/issues/10893
|
35
|
+
require(target)
|
36
|
+
rescue ::LoadError => e
|
37
|
+
raise if e.path != target
|
38
|
+
|
39
|
+
begin
|
40
|
+
::Kernel.require(namespaced_target)
|
41
|
+
rescue ::LoadError => error_for_namespaced_target
|
42
|
+
raise e if error_for_namespaced_target.path == namespaced_target
|
43
|
+
|
44
|
+
raise error_for_namespaced_target
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
# @return [String]
|
51
|
+
def namespaced_feature
|
52
|
+
@feature.tr('-', '/')
|
53
|
+
end
|
54
|
+
|
55
|
+
# @return [String]
|
56
|
+
def namespaced_target
|
57
|
+
if relative?
|
58
|
+
relative(namespaced_feature)
|
59
|
+
else
|
60
|
+
namespaced_feature
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# @param [String]
|
65
|
+
# @return [String]
|
66
|
+
def relative(feature)
|
67
|
+
::File.join(@config_directory_path, feature)
|
68
|
+
end
|
69
|
+
|
70
|
+
# @return [Boolean]
|
71
|
+
def relative?
|
72
|
+
@feature.start_with?('.')
|
73
|
+
end
|
74
|
+
|
75
|
+
# @param [LoadError] error
|
76
|
+
# @return [Boolean]
|
77
|
+
def seems_cannot_load_such_file_error?(error)
|
78
|
+
error.path == target
|
79
|
+
end
|
80
|
+
|
81
|
+
# @return [String]
|
82
|
+
def target
|
83
|
+
if relative?
|
84
|
+
relative(@feature)
|
85
|
+
else
|
86
|
+
@feature
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
data/lib/rubocop/result_cache.rb
CHANGED
@@ -4,6 +4,7 @@ require 'digest/sha1'
|
|
4
4
|
require 'find'
|
5
5
|
require 'etc'
|
6
6
|
require 'zlib'
|
7
|
+
require_relative 'cache_config'
|
7
8
|
|
8
9
|
module RuboCop
|
9
10
|
# Provides functionality for caching RuboCop runs.
|
@@ -13,6 +14,12 @@ module RuboCop
|
|
13
14
|
fix_layout autocorrect safe_autocorrect autocorrect_all
|
14
15
|
cache fail_fast stdin parallel].freeze
|
15
16
|
|
17
|
+
DL_EXTENSIONS = ::RbConfig::CONFIG
|
18
|
+
.values_at('DLEXT', 'DLEXT2')
|
19
|
+
.reject { |ext| !ext || ext.empty? }
|
20
|
+
.map { |ext| ".#{ext}" }
|
21
|
+
.freeze
|
22
|
+
|
16
23
|
# Remove old files so that the cache doesn't grow too big. When the
|
17
24
|
# threshold MaxFilesInCache has been exceeded, the oldest 50% of all the
|
18
25
|
# files in the cache are removed. The reason for removing so much is that
|
@@ -67,24 +74,9 @@ module RuboCop
|
|
67
74
|
end
|
68
75
|
|
69
76
|
def self.cache_root(config_store)
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
# Include user ID in the path to make sure the user has write
|
74
|
-
# access.
|
75
|
-
File.join(ENV.fetch('XDG_CACHE_HOME'), Process.uid.to_s)
|
76
|
-
else
|
77
|
-
# On FreeBSD, the /home path is a symbolic link to /usr/home
|
78
|
-
# and the $HOME environment variable returns the /home path.
|
79
|
-
#
|
80
|
-
# As $HOME is a built-in environment variable, FreeBSD users
|
81
|
-
# always get a warning message.
|
82
|
-
#
|
83
|
-
# To avoid raising warn log messages on FreeBSD, we retrieve
|
84
|
-
# the real path of the home folder.
|
85
|
-
File.join(File.realpath(Dir.home), '.cache')
|
86
|
-
end
|
87
|
-
File.join(root, 'rubocop_cache')
|
77
|
+
CacheConfig.root_dir do
|
78
|
+
config_store.for_pwd.for_all_cops['CacheRootDirectory']
|
79
|
+
end
|
88
80
|
end
|
89
81
|
|
90
82
|
def self.allow_symlinks_in_cache_location?(config_store)
|
@@ -188,14 +180,24 @@ module RuboCop
|
|
188
180
|
.select { |path| File.file?(path) }
|
189
181
|
.sort!
|
190
182
|
.each do |path|
|
191
|
-
|
192
|
-
digest << Zlib.crc32(content).to_s # mtime not reliable
|
183
|
+
digest << digest(path)
|
193
184
|
end
|
194
185
|
digest << RuboCop::Version::STRING << RuboCop::AST::Version::STRING
|
195
186
|
digest.hexdigest
|
196
187
|
end
|
197
188
|
end
|
198
189
|
|
190
|
+
def digest(path)
|
191
|
+
content = if path.end_with?(*DL_EXTENSIONS)
|
192
|
+
# Shared libraries often contain timestamps of when
|
193
|
+
# they were compiled and other non-stable data.
|
194
|
+
File.basename(path)
|
195
|
+
else
|
196
|
+
File.binread(path) # mtime not reliable
|
197
|
+
end
|
198
|
+
Zlib.crc32(content).to_s
|
199
|
+
end
|
200
|
+
|
199
201
|
def rubocop_extra_features
|
200
202
|
lib_root = File.join(File.dirname(__FILE__), '..')
|
201
203
|
exe_root = File.join(lib_root, '..', 'exe')
|