rubocop 1.64.1 → 1.65.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/config/default.yml +11 -1
- data/lib/rubocop/config_loader.rb +1 -1
- data/lib/rubocop/config_loader_resolver.rb +9 -3
- data/lib/rubocop/cop/cop.rb +20 -2
- data/lib/rubocop/cop/gemspec/add_runtime_dependency.rb +38 -0
- data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +2 -2
- data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +3 -3
- data/lib/rubocop/cop/layout/case_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_after_multiline_condition.rb +1 -1
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +1 -1
- data/lib/rubocop/cop/layout/line_length.rb +20 -20
- data/lib/rubocop/cop/layout/space_around_operators.rb +3 -0
- data/lib/rubocop/cop/legacy/corrector.rb +12 -2
- data/lib/rubocop/cop/lint/duplicate_case_condition.rb +1 -1
- data/lib/rubocop/cop/lint/empty_when.rb +1 -1
- data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +14 -7
- data/lib/rubocop/cop/lint/literal_as_condition.rb +1 -1
- data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -1
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +2 -9
- data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -0
- data/lib/rubocop/cop/lint/void.rb +5 -0
- data/lib/rubocop/cop/metrics/block_nesting.rb +19 -7
- data/lib/rubocop/cop/mixin/alignment.rb +5 -1
- data/lib/rubocop/cop/mixin/allowed_methods.rb +7 -1
- data/lib/rubocop/cop/mixin/allowed_pattern.rb +15 -3
- data/lib/rubocop/cop/mixin/configurable_max.rb +5 -1
- data/lib/rubocop/cop/mixin/rescue_node.rb +4 -0
- data/lib/rubocop/cop/style/arguments_forwarding.rb +1 -1
- data/lib/rubocop/cop/style/hash_except.rb +8 -5
- data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +77 -43
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +5 -0
- data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
- data/lib/rubocop/cop/style/redundant_begin.rb +1 -1
- data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +1 -1
- data/lib/rubocop/cop/style/send_with_literal_method_name.rb +15 -1
- data/lib/rubocop/cop/style/super_arguments.rb +28 -10
- data/lib/rubocop/cop/style/symbol_proc.rb +8 -1
- data/lib/rubocop/cop/style/zero_length_predicate.rb +28 -24
- data/lib/rubocop/cop/team.rb +8 -0
- data/lib/rubocop/cop/util.rb +7 -1
- data/lib/rubocop/cops_documentation_generator.rb +1 -1
- data/lib/rubocop/ext/regexp_parser.rb +4 -21
- data/lib/rubocop/formatter/html_formatter.rb +3 -1
- data/lib/rubocop/rspec/shared_contexts.rb +20 -0
- data/lib/rubocop/rspec/support.rb +1 -0
- data/lib/rubocop/server/cache.rb +10 -0
- data/lib/rubocop/server/client_command/exec.rb +2 -2
- data/lib/rubocop/server/client_command/start.rb +1 -1
- data/lib/rubocop/server/core.rb +4 -0
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +1 -0
- metadata +11 -10
@@ -23,9 +23,9 @@ module RuboCop
|
|
23
23
|
# {foo: 1, bar: 2, baz: 3}.reject {|k, v| k == :bar }
|
24
24
|
# {foo: 1, bar: 2, baz: 3}.select {|k, v| k != :bar }
|
25
25
|
# {foo: 1, bar: 2, baz: 3}.filter {|k, v| k != :bar }
|
26
|
-
# {foo: 1, bar: 2, baz: 3}.reject {|k, v| %i[
|
27
|
-
# {foo: 1, bar: 2, baz: 3}.select {|k, v| !%i[
|
28
|
-
# {foo: 1, bar: 2, baz: 3}.filter {|k, v| !%i[
|
26
|
+
# {foo: 1, bar: 2, baz: 3}.reject {|k, v| %i[bar].include?(k) }
|
27
|
+
# {foo: 1, bar: 2, baz: 3}.select {|k, v| !%i[bar].include?(k) }
|
28
|
+
# {foo: 1, bar: 2, baz: 3}.filter {|k, v| !%i[bar].include?(k) }
|
29
29
|
#
|
30
30
|
# # good
|
31
31
|
# {foo: 1, bar: 2, baz: 3}.except(:bar)
|
@@ -73,8 +73,9 @@ module RuboCop
|
|
73
73
|
PATTERN
|
74
74
|
|
75
75
|
def on_send(node)
|
76
|
+
method_name = node.method_name
|
76
77
|
block = node.parent
|
77
|
-
return unless bad_method?(block) && semantically_except_method?(node, block)
|
78
|
+
return unless bad_method?(method_name, block) && semantically_except_method?(node, block)
|
78
79
|
|
79
80
|
except_key = except_key(block)
|
80
81
|
return if except_key.nil? || !safe_to_register_offense?(block, except_key)
|
@@ -91,7 +92,7 @@ module RuboCop
|
|
91
92
|
private
|
92
93
|
|
93
94
|
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
94
|
-
def bad_method?(block)
|
95
|
+
def bad_method?(method_name, block)
|
95
96
|
if active_support_extensions_enabled?
|
96
97
|
bad_method_with_active_support?(block) do |key_arg, send_node|
|
97
98
|
if send_node.method?(:in?) && send_node.receiver&.source != key_arg.source
|
@@ -103,6 +104,8 @@ module RuboCop
|
|
103
104
|
end
|
104
105
|
else
|
105
106
|
bad_method_with_poro?(block) do |key_arg, send_node|
|
107
|
+
return false if method_name == :reject && block.body.method?(:!)
|
108
|
+
|
106
109
|
!send_node.method?(:include?) || send_node.first_argument&.source == key_arg.source
|
107
110
|
end
|
108
111
|
end
|
@@ -4,6 +4,7 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
6
|
# Prefer `select` or `reject` over `map { ... }.compact`.
|
7
|
+
# This cop also handles `filter_map { ... }`, similar to `map { ... }.compact`.
|
7
8
|
#
|
8
9
|
# @example
|
9
10
|
#
|
@@ -11,6 +12,9 @@ module RuboCop
|
|
11
12
|
# array.map { |e| some_condition? ? e : next }.compact
|
12
13
|
#
|
13
14
|
# # bad
|
15
|
+
# array.filter_map { |e| some_condition? ? e : next }
|
16
|
+
#
|
17
|
+
# # bad
|
14
18
|
# array.map do |e|
|
15
19
|
# if some_condition?
|
16
20
|
# e
|
@@ -40,55 +44,73 @@ module RuboCop
|
|
40
44
|
class MapCompactWithConditionalBlock < Base
|
41
45
|
extend AutoCorrector
|
42
46
|
|
43
|
-
MSG = 'Replace `
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
47
|
+
MSG = 'Replace `%<current>s` with `%<method>s`.'
|
48
|
+
RESTRICT_ON_SEND = %i[compact filter_map].freeze
|
49
|
+
|
50
|
+
# @!method conditional_block(node)
|
51
|
+
def_node_matcher :conditional_block, <<~RUBY
|
52
|
+
(block
|
53
|
+
(call _ {:map :filter_map})
|
54
|
+
(args
|
55
|
+
$(arg _))
|
56
|
+
{
|
57
|
+
(if $_ $(lvar _) {next nil?})
|
58
|
+
(if $_ {next nil?} $(lvar _))
|
59
|
+
(if $_ (next $(lvar _)) {next nil nil?})
|
60
|
+
(if $_ {next nil nil?} (next $(lvar _)))
|
61
|
+
(begin
|
62
|
+
{
|
63
|
+
(if $_ next nil?)
|
64
|
+
(if $_ nil? next)
|
65
|
+
}
|
66
|
+
$(lvar _))
|
67
|
+
(begin
|
68
|
+
{
|
69
|
+
(if $_ (next $(lvar _)) nil?)
|
70
|
+
(if $_ nil? (next $(lvar _)))
|
71
|
+
}
|
72
|
+
(nil))
|
73
|
+
})
|
70
74
|
RUBY
|
71
75
|
|
72
76
|
def on_send(node)
|
73
|
-
|
74
|
-
|
75
|
-
return
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
)
|
85
|
-
end
|
77
|
+
map_candidate = node.children.first
|
78
|
+
if (block_argument, condition, return_value = conditional_block(map_candidate))
|
79
|
+
return unless node.method?(:compact) && node.arguments.empty?
|
80
|
+
|
81
|
+
range = map_with_compact_range(node)
|
82
|
+
elsif (block_argument, condition, return_value = conditional_block(node.parent))
|
83
|
+
return unless node.method?(:filter_map)
|
84
|
+
|
85
|
+
range = filter_map_range(node)
|
86
|
+
else
|
87
|
+
return
|
86
88
|
end
|
89
|
+
|
90
|
+
inspect(node, block_argument, condition, return_value, range)
|
87
91
|
end
|
88
92
|
alias on_csend on_send
|
89
93
|
|
90
94
|
private
|
91
95
|
|
96
|
+
def inspect(node, block_argument_node, condition_node, return_value_node, range)
|
97
|
+
return unless returns_block_argument?(block_argument_node, return_value_node)
|
98
|
+
return if condition_node.parent.elsif?
|
99
|
+
|
100
|
+
method = truthy_branch?(return_value_node) ? 'select' : 'reject'
|
101
|
+
current = current(node)
|
102
|
+
|
103
|
+
add_offense(range, message: format(MSG, current: current, method: method)) do |corrector|
|
104
|
+
return if part_of_ignored_node?(node) || ignored_node?(node)
|
105
|
+
|
106
|
+
corrector.replace(
|
107
|
+
range, "#{method} { |#{block_argument_node.source}| #{condition_node.source} }"
|
108
|
+
)
|
109
|
+
|
110
|
+
ignore_node(node)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
92
114
|
def returns_block_argument?(block_argument_node, return_value_node)
|
93
115
|
block_argument_node.name == return_value_node.children.first
|
94
116
|
end
|
@@ -123,10 +145,22 @@ module RuboCop
|
|
123
145
|
end
|
124
146
|
end
|
125
147
|
|
126
|
-
def
|
127
|
-
|
148
|
+
def current(node)
|
149
|
+
if node.method?(:compact)
|
150
|
+
map_or_filter_map_method = node.children.first
|
151
|
+
|
152
|
+
"#{map_or_filter_map_method.method_name} { ... }.compact"
|
153
|
+
else
|
154
|
+
'filter_map { ... }'
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def map_with_compact_range(node)
|
159
|
+
node.receiver.send_node.loc.selector.begin.join(node.source_range.end)
|
160
|
+
end
|
128
161
|
|
129
|
-
|
162
|
+
def filter_map_range(node)
|
163
|
+
node.loc.selector.join(node.parent.source_range.end)
|
130
164
|
end
|
131
165
|
end
|
132
166
|
end
|
@@ -18,6 +18,7 @@ module RuboCop
|
|
18
18
|
return if inside_endless_method_def?(node)
|
19
19
|
return if require_parentheses_for_hash_value_omission?(node)
|
20
20
|
return if syntax_like_method_call?(node)
|
21
|
+
return if method_call_before_constant_resolution?(node)
|
21
22
|
return if super_call_without_arguments?(node)
|
22
23
|
return if legitimate_call_with_parentheses?(node)
|
23
24
|
return if allowed_camel_case_method_call?(node)
|
@@ -63,6 +64,10 @@ module RuboCop
|
|
63
64
|
node.implicit_call? || node.operator_method?
|
64
65
|
end
|
65
66
|
|
67
|
+
def method_call_before_constant_resolution?(node)
|
68
|
+
node.parent&.const_type?
|
69
|
+
end
|
70
|
+
|
66
71
|
def super_call_without_arguments?(node)
|
67
72
|
node.super_type? && node.arguments.none?
|
68
73
|
end
|
@@ -9,7 +9,7 @@ module RuboCop
|
|
9
9
|
#
|
10
10
|
# String interpolation is always kept in double quotes.
|
11
11
|
#
|
12
|
-
#
|
12
|
+
# NOTE: `Lint/SymbolConversion` can be used in parallel to ensure that symbols
|
13
13
|
# are not quoted that don't need to be. This cop is for configuring the quoting
|
14
14
|
# style to use for symbols that require quotes.
|
15
15
|
#
|
@@ -6,7 +6,7 @@ module RuboCop
|
|
6
6
|
# Checks for the presence of superfluous `.rb` extension in
|
7
7
|
# the filename provided to `require` and `require_relative`.
|
8
8
|
#
|
9
|
-
#
|
9
|
+
# NOTE: If the extension is omitted, Ruby tries adding '.rb', '.so',
|
10
10
|
# and so on to the name until found. If the file named cannot be found,
|
11
11
|
# a `LoadError` will be raised.
|
12
12
|
# There is an edge case where `foo.so` file is loaded instead of a `LoadError`
|
@@ -7,6 +7,20 @@ module RuboCop
|
|
7
7
|
# Since the `send` method can be used to call private methods, by default,
|
8
8
|
# only the `public_send` method is detected.
|
9
9
|
#
|
10
|
+
# NOTE: Writer methods with names ending in `=` are always permitted because their
|
11
|
+
# behavior differs as follows:
|
12
|
+
#
|
13
|
+
# [source,ruby]
|
14
|
+
# ----
|
15
|
+
# def foo=(foo)
|
16
|
+
# @foo = foo
|
17
|
+
# 42
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# self.foo = 1 # => 1
|
21
|
+
# send(:foo=, 1) # => 42
|
22
|
+
# ----
|
23
|
+
#
|
10
24
|
# @safety
|
11
25
|
# This cop is not safe because it can incorrectly detect based on the receiver.
|
12
26
|
# Additionally, when `AllowSend` is set to `true`, it cannot determine whether
|
@@ -43,7 +57,7 @@ module RuboCop
|
|
43
57
|
MSG = 'Use `%<method_name>s` method call directly instead.'
|
44
58
|
RESTRICT_ON_SEND = %i[public_send send __send__].freeze
|
45
59
|
STATIC_METHOD_NAME_NODE_TYPES = %i[sym str].freeze
|
46
|
-
METHOD_NAME_PATTERN = /\A[a-zA-Z_][a-zA-Z0-9_]*[
|
60
|
+
METHOD_NAME_PATTERN = /\A[a-zA-Z_][a-zA-Z0-9_]*[!?]?\z/.freeze
|
47
61
|
RESERVED_WORDS = %i[
|
48
62
|
BEGIN END alias and begin break case class def defined? do else elsif end ensure
|
49
63
|
false for if in module next nil not or redo rescue retry return self super then true
|
@@ -3,8 +3,25 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
# Checks for redundant argument forwarding when calling super
|
7
|
-
#
|
6
|
+
# Checks for redundant argument forwarding when calling super with arguments identical to
|
7
|
+
# the method definition.
|
8
|
+
#
|
9
|
+
# Using zero arity `super` within a `define_method` block results in `RuntimeError`:
|
10
|
+
#
|
11
|
+
# [source,ruby]
|
12
|
+
# ----
|
13
|
+
# def m
|
14
|
+
# define_method(:foo) { super() } # => OK
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# def m
|
18
|
+
# define_method(:foo) { super } # => RuntimeError
|
19
|
+
# end
|
20
|
+
# ----
|
21
|
+
#
|
22
|
+
# Furthermore, any arguments accompanied by a block may potentially be delegating to
|
23
|
+
# `define_method`, therefore, `super` used within these blocks will be allowed.
|
24
|
+
# This approach might result in false negatives, yet ensuring safe detection takes precedence.
|
8
25
|
#
|
9
26
|
# @example
|
10
27
|
# # bad
|
@@ -44,8 +61,10 @@ module RuboCop
|
|
44
61
|
|
45
62
|
def on_super(super_node)
|
46
63
|
def_node = super_node.ancestors.find do |node|
|
47
|
-
#
|
48
|
-
|
64
|
+
# When defining dynamic methods, implicitly calling `super` is not possible.
|
65
|
+
# Since there is a possibility of delegation to `define_method`,
|
66
|
+
# `super` used within the block is always allowed.
|
67
|
+
break if node.block_type?
|
49
68
|
|
50
69
|
break node if DEF_TYPES.include?(node.type)
|
51
70
|
end
|
@@ -127,6 +146,11 @@ module RuboCop
|
|
127
146
|
# https://bugs.ruby-lang.org/issues/20505
|
128
147
|
def block_reassigned?(def_node, block_arg_name)
|
129
148
|
def_node.each_node(*ASSIGN_TYPES).any? do |assign_node|
|
149
|
+
# TODO: Since `Symbol#name` is supported from Ruby 3.0, the inheritance check for
|
150
|
+
# `AST::Node` can be removed when requiring Ruby 3.0+.
|
151
|
+
lhs = assign_node.node_parts[0]
|
152
|
+
next if lhs.is_a?(AST::Node) && !lhs.respond_to?(:name)
|
153
|
+
|
130
154
|
assign_node.name == block_arg_name
|
131
155
|
end
|
132
156
|
end
|
@@ -135,12 +159,6 @@ module RuboCop
|
|
135
159
|
def_arg.forward_arg_type? && super_arg.forwarded_args_type?
|
136
160
|
end
|
137
161
|
|
138
|
-
def define_method?(node)
|
139
|
-
return false unless node.block_type?
|
140
|
-
|
141
|
-
node.method?(:define_method) || node.method?(:define_singleton_method)
|
142
|
-
end
|
143
|
-
|
144
162
|
def preprocess_super_args(super_args)
|
145
163
|
super_args.flat_map do |node|
|
146
164
|
if node.hash_type? && !node.braces?
|
@@ -223,7 +223,14 @@ module RuboCop
|
|
223
223
|
end
|
224
224
|
|
225
225
|
def autocorrect_without_args(corrector, node)
|
226
|
-
|
226
|
+
if node.send_node.lambda_literal?
|
227
|
+
if node.send_node.loc.selector.source == '->'
|
228
|
+
corrector.replace(node, "lambda(&:#{node.body.method_name})")
|
229
|
+
return
|
230
|
+
else
|
231
|
+
autocorrect_lambda_block(corrector, node)
|
232
|
+
end
|
233
|
+
end
|
227
234
|
|
228
235
|
corrector.replace(block_range_with_space(node), "(&:#{node.body.method_name})")
|
229
236
|
end
|
@@ -47,15 +47,16 @@ module RuboCop
|
|
47
47
|
check_zero_length_comparison(node)
|
48
48
|
check_nonzero_length_comparison(node)
|
49
49
|
end
|
50
|
+
alias on_csend on_send
|
50
51
|
|
51
52
|
private
|
52
53
|
|
53
54
|
def check_zero_length_predicate(node)
|
54
|
-
return unless
|
55
|
+
return unless zero_length_predicate?(node.parent)
|
55
56
|
return if non_polymorphic_collection?(node.parent)
|
56
57
|
|
57
58
|
offense = node.loc.selector.join(node.parent.source_range.end)
|
58
|
-
message = format(ZERO_MSG, current:
|
59
|
+
message = format(ZERO_MSG, current: offense.source)
|
59
60
|
|
60
61
|
add_offense(offense, message: message) do |corrector|
|
61
62
|
corrector.replace(offense, 'empty?')
|
@@ -92,44 +93,47 @@ module RuboCop
|
|
92
93
|
end
|
93
94
|
end
|
94
95
|
|
95
|
-
# @!method zero_length_predicate(node)
|
96
|
-
def_node_matcher :zero_length_predicate
|
97
|
-
(
|
96
|
+
# @!method zero_length_predicate?(node)
|
97
|
+
def_node_matcher :zero_length_predicate?, <<~PATTERN
|
98
|
+
(call (call (...) {:length :size}) :zero?)
|
98
99
|
PATTERN
|
99
100
|
|
100
101
|
# @!method zero_length_comparison(node)
|
101
102
|
def_node_matcher :zero_length_comparison, <<~PATTERN
|
102
|
-
{(
|
103
|
-
(
|
104
|
-
(
|
105
|
-
(
|
103
|
+
{(call (call (...) ${:length :size}) $:== (int $0))
|
104
|
+
(call (int $0) $:== (call (...) ${:length :size}))
|
105
|
+
(call (call (...) ${:length :size}) $:< (int $1))
|
106
|
+
(call (int $1) $:> (call (...) ${:length :size}))}
|
106
107
|
PATTERN
|
107
108
|
|
108
109
|
# @!method nonzero_length_comparison(node)
|
109
110
|
def_node_matcher :nonzero_length_comparison, <<~PATTERN
|
110
|
-
{(
|
111
|
-
(
|
111
|
+
{(call (call (...) ${:length :size}) ${:> :!=} (int $0))
|
112
|
+
(call (int $0) ${:< :!=} (call (...) ${:length :size}))}
|
112
113
|
PATTERN
|
113
114
|
|
114
115
|
def replacement(node)
|
115
|
-
|
116
|
-
|
116
|
+
length_node = zero_length_node(node)
|
117
|
+
if length_node&.receiver
|
118
|
+
return "#{length_node.receiver.source}#{length_node.loc.dot.source}empty?"
|
119
|
+
end
|
117
120
|
|
118
|
-
|
121
|
+
other_length_node = other_length_node(node)
|
122
|
+
"!#{other_length_node.receiver.source}#{other_length_node.loc.dot.source}empty?"
|
119
123
|
end
|
120
124
|
|
121
|
-
# @!method
|
122
|
-
def_node_matcher :
|
123
|
-
{(send (
|
124
|
-
(send (int 0) :== (
|
125
|
-
(send (
|
126
|
-
(send (int 1) :> (
|
125
|
+
# @!method zero_length_node(node)
|
126
|
+
def_node_matcher :zero_length_node, <<~PATTERN
|
127
|
+
{(send $(call _ _) :== (int 0))
|
128
|
+
(send (int 0) :== $(call _ _))
|
129
|
+
(send $(call _ _) :< (int 1))
|
130
|
+
(send (int 1) :> $(call _ _))}
|
127
131
|
PATTERN
|
128
132
|
|
129
|
-
# @!method
|
130
|
-
def_node_matcher :
|
131
|
-
{(
|
132
|
-
(
|
133
|
+
# @!method other_length_node(node)
|
134
|
+
def_node_matcher :other_length_node, <<~PATTERN
|
135
|
+
{(call $(call _ _) _ _)
|
136
|
+
(call _ _ $(call _ _))}
|
133
137
|
PATTERN
|
134
138
|
|
135
139
|
# Some collection like objects in the Ruby standard library
|
data/lib/rubocop/cop/team.rb
CHANGED
@@ -74,6 +74,10 @@ module RuboCop
|
|
74
74
|
# @deprecated. Use investigate
|
75
75
|
# @return Array<offenses>
|
76
76
|
def inspect_file(processed_source)
|
77
|
+
warn Rainbow(<<~WARNING).yellow, uplevel: 1
|
78
|
+
`inspect_file` is deprecated. Use `investigate` instead.
|
79
|
+
WARNING
|
80
|
+
|
77
81
|
investigate(processed_source).offenses
|
78
82
|
end
|
79
83
|
|
@@ -108,6 +112,10 @@ module RuboCop
|
|
108
112
|
|
109
113
|
# @deprecated
|
110
114
|
def forces
|
115
|
+
warn Rainbow(<<~WARNING).yellow, uplevel: 1
|
116
|
+
`forces` is deprecated.
|
117
|
+
WARNING
|
118
|
+
|
111
119
|
@forces ||= self.class.forces_for(cops)
|
112
120
|
end
|
113
121
|
|
data/lib/rubocop/cop/util.rb
CHANGED
@@ -20,6 +20,10 @@ module RuboCop
|
|
20
20
|
|
21
21
|
# @deprecated Use `ProcessedSource#line_with_comment?`, `contains_comment?` or similar
|
22
22
|
def comment_lines?(node)
|
23
|
+
warn Rainbow(<<~WARNING).yellow, uplevel: 1
|
24
|
+
`comment_lines?` is deprecated. Use `ProcessedSource#line_with_comment?`, `contains_comment?` or similar instead.
|
25
|
+
WARNING
|
26
|
+
|
23
27
|
processed_source[line_range(node)].any? { |line| comment_line?(line) }
|
24
28
|
end
|
25
29
|
|
@@ -173,7 +177,9 @@ module RuboCop
|
|
173
177
|
def same_line?(node1, node2)
|
174
178
|
line1 = line(node1)
|
175
179
|
line2 = line(node2)
|
176
|
-
|
180
|
+
return false unless line1 && line2
|
181
|
+
|
182
|
+
line1 == line2
|
177
183
|
end
|
178
184
|
|
179
185
|
def indent(node, offset: 0)
|
@@ -306,7 +306,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
306
306
|
filename = "#{department_to_basename(department)}.adoc"
|
307
307
|
content = +"=== Department xref:#{filename}[#{type_title}]\n\n"
|
308
308
|
cops_of_department(department).each do |cop|
|
309
|
-
anchor = cop.cop_name.
|
309
|
+
anchor = cop.cop_name.delete('/').downcase
|
310
310
|
content << "* xref:#{filename}##{anchor}[#{cop.cop_name}]\n"
|
311
311
|
end
|
312
312
|
|
@@ -22,26 +22,9 @@ module RuboCop
|
|
22
22
|
module Base
|
23
23
|
attr_accessor :origin
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
@expression ||= origin.adjust(begin_pos: ts, end_pos: ts + full_length)
|
29
|
-
end
|
30
|
-
# Please remove this `else` branch when support for regexp_parser 1.8 will be dropped.
|
31
|
-
# It's for compatibility with regexp_parser 1.8 and will never be maintained.
|
32
|
-
else
|
33
|
-
attr_accessor :source
|
34
|
-
|
35
|
-
def start_index
|
36
|
-
# ts is a byte index; convert it to a character index
|
37
|
-
@start_index ||= source.byteslice(0, ts).length
|
38
|
-
end
|
39
|
-
|
40
|
-
# Shortcut to `loc.expression`
|
41
|
-
def expression
|
42
|
-
end_pos = start_index + full_length
|
43
|
-
@expression ||= origin.adjust(begin_pos: start_index, end_pos: end_pos)
|
44
|
-
end
|
25
|
+
# Shortcut to `loc.expression`
|
26
|
+
def expression
|
27
|
+
@expression ||= origin.adjust(begin_pos: ts, end_pos: ts + full_length)
|
45
28
|
end
|
46
29
|
|
47
30
|
# @returns a location map like `parser` does, with:
|
@@ -69,8 +52,8 @@ module RuboCop
|
|
69
52
|
|
70
53
|
body = expression.adjust(end_pos: -q.text.length)
|
71
54
|
q.origin = origin
|
72
|
-
q.source = source if q.respond_to?(:source=) # for regexp_parser 1.8
|
73
55
|
q_loc = q.expression
|
56
|
+
|
74
57
|
{ body: body, quantifier: q_loc }
|
75
58
|
end
|
76
59
|
end
|
@@ -52,7 +52,9 @@ module RuboCop
|
|
52
52
|
|
53
53
|
template = File.read(TEMPLATE_PATH, encoding: Encoding::UTF_8)
|
54
54
|
erb = ERB.new(template)
|
55
|
-
html = erb.result(context.binding).lines.map
|
55
|
+
html = erb.result(context.binding).lines.map do |line|
|
56
|
+
line.match?(/\A\s*\z/) ? "\n" : line
|
57
|
+
end.join
|
56
58
|
|
57
59
|
output.write html
|
58
60
|
end
|
@@ -50,6 +50,26 @@ RSpec.shared_context 'isolated environment' do # rubocop:disable Metrics/BlockLe
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
+
# Workaround for https://github.com/rubocop/rubocop/issues/12978,
|
54
|
+
# there should already be no gemfile in the temp directory
|
55
|
+
RSpec.shared_context 'isolated bundler' do
|
56
|
+
around do |example|
|
57
|
+
# No bundler env and reset cached gemfile path
|
58
|
+
Bundler.with_unbundled_env do
|
59
|
+
old_values = Bundler.instance_variables.to_h do |name|
|
60
|
+
[name, Bundler.instance_variable_get(name)]
|
61
|
+
end
|
62
|
+
Bundler.instance_variables.each { |name| Bundler.remove_instance_variable(name) }
|
63
|
+
example.call
|
64
|
+
ensure
|
65
|
+
Bundler.instance_variables.each { |name| Bundler.remove_instance_variable(name) }
|
66
|
+
old_values.each do |name, value|
|
67
|
+
Bundler.instance_variable_set(name, value)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
53
73
|
RSpec.shared_context 'maintain registry' do
|
54
74
|
around(:each) { |example| RuboCop::Cop::Registry.with_temporary_global { example.run } }
|
55
75
|
|
@@ -13,6 +13,7 @@ RSpec.configure do |config|
|
|
13
13
|
config.include HostEnvironmentSimulatorHelper
|
14
14
|
config.include_context 'config', :config
|
15
15
|
config.include_context 'isolated environment', :isolated_environment
|
16
|
+
config.include_context 'isolated bundler', :isolated_bundler
|
16
17
|
config.include_context 'lsp', :lsp
|
17
18
|
config.include_context 'maintain registry', :restore_registry
|
18
19
|
config.include_context 'ruby 2.0', :ruby20
|
data/lib/rubocop/server/cache.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'digest'
|
3
4
|
require 'pathname'
|
4
5
|
require_relative '../cache_config'
|
5
6
|
require_relative '../config_finder'
|
@@ -19,6 +20,7 @@ module RuboCop
|
|
19
20
|
# @api private
|
20
21
|
class Cache
|
21
22
|
GEMFILE_NAMES = %w[Gemfile gems.rb].freeze
|
23
|
+
LOCKFILE_NAMES = %w[Gemfile.lock gems.locked].freeze
|
22
24
|
|
23
25
|
class << self
|
24
26
|
attr_accessor :cache_root_path
|
@@ -41,6 +43,14 @@ module RuboCop
|
|
41
43
|
@project_dir_cache_key ||= project_dir[1..].tr('/', '+')
|
42
44
|
end
|
43
45
|
|
46
|
+
def restart_key
|
47
|
+
lockfile_path = LOCKFILE_NAMES.map do |lockfile_name|
|
48
|
+
Pathname(project_dir).join(lockfile_name)
|
49
|
+
end.find(&:exist?)
|
50
|
+
|
51
|
+
Digest::SHA1.hexdigest(lockfile_path&.read || RuboCop::Version::STRING)
|
52
|
+
end
|
53
|
+
|
44
54
|
def dir
|
45
55
|
Pathname.new(File.join(cache_path, project_dir_cache_key)).tap do |d|
|
46
56
|
d.mkpath unless d.exist?
|
@@ -41,7 +41,7 @@ module RuboCop
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def incompatible_version?
|
44
|
-
Cache.version_path.read !=
|
44
|
+
Cache.version_path.read != Cache.restart_key
|
45
45
|
end
|
46
46
|
|
47
47
|
def stderr
|
@@ -54,7 +54,7 @@ module RuboCop
|
|
54
54
|
end
|
55
55
|
|
56
56
|
status = Cache.status_path.read
|
57
|
-
raise "RuboCop server: '#{status}' is not a valid status!"
|
57
|
+
raise "RuboCop server: '#{status}' is not a valid status!" unless /\A\d+\z/.match?(status)
|
58
58
|
|
59
59
|
status.to_i
|
60
60
|
end
|