rubocop 1.61.0 → 1.62.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 +6 -0
- data/lib/rubocop/cli/command/auto_generate_config.rb +12 -3
- data/lib/rubocop/config.rb +4 -0
- data/lib/rubocop/cop/base.rb +5 -1
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +3 -1
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +122 -28
- data/lib/rubocop/cop/layout/empty_line_after_magic_comment.rb +14 -7
- data/lib/rubocop/cop/layout/redundant_line_break.rb +8 -2
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_with_index.rb +1 -0
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +7 -2
- data/lib/rubocop/cop/lint/useless_times.rb +1 -1
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
- data/lib/rubocop/cop/style/class_vars.rb +3 -3
- data/lib/rubocop/cop/style/for.rb +2 -0
- data/lib/rubocop/cop/style/hash_each_methods.rb +1 -1
- data/lib/rubocop/cop/style/multiline_method_signature.rb +10 -1
- data/lib/rubocop/cop/style/nil_comparison.rb +2 -0
- data/lib/rubocop/cop/style/raise_args.rb +1 -1
- data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +4 -3
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +1 -1
- data/lib/rubocop/cop/utils/regexp_ranges.rb +1 -1
- data/lib/rubocop/directive_comment.rb +10 -8
- data/lib/rubocop/magic_comment.rb +1 -1
- data/lib/rubocop/rspec/cop_helper.rb +8 -2
- data/lib/rubocop/rspec/expect_offense.rb +8 -8
- data/lib/rubocop/rspec/shared_contexts.rb +26 -11
- data/lib/rubocop/rspec/support.rb +1 -0
- data/lib/rubocop/runner.rb +9 -2
- data/lib/rubocop/target_finder.rb +84 -78
- data/lib/rubocop/target_ruby.rb +6 -4
- data/lib/rubocop/version.rb +18 -3
- metadata +10 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8daa4ef7dd74b8608039d7dfda5f1e3fe739738949390a6f1347acaccf7bd1c4
|
4
|
+
data.tar.gz: 271a978db956def596a5b06a7fd69d189d807b27db0acdda03fd6200b95ef541
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 484294f43781f114ba01470b22331ef17648219e26dc4ba2f28073f609c909af2997c47e1f1aad62860124f6f4594a2e536cd793f05352a78d588f979732a290
|
7
|
+
data.tar.gz: 6a8313e61422bcd568eea747c0f9a88f61f50620b4dd4f478da0bdd3e067c1aa8bcf70e15744e02118d4c525eb0632fae3cc19caf73db6db1f63ea76dbb84b45
|
data/README.md
CHANGED
@@ -53,7 +53,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
|
|
53
53
|
in your `Gemfile`:
|
54
54
|
|
55
55
|
```rb
|
56
|
-
gem 'rubocop', '~> 1.
|
56
|
+
gem 'rubocop', '~> 1.62', require: false
|
57
57
|
```
|
58
58
|
|
59
59
|
See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
|
data/config/default.yml
CHANGED
@@ -144,6 +144,12 @@ AllCops:
|
|
144
144
|
# Ruby version is still unresolved, RuboCop will use the oldest officially
|
145
145
|
# supported Ruby version (currently Ruby 2.7).
|
146
146
|
TargetRubyVersion: ~
|
147
|
+
# You can specify the parser engine. There are two options available:
|
148
|
+
# - `parser_whitequark` ... https://github.com/whitequark/parser
|
149
|
+
# - `parser_prism` ... https://github.com/ruby/prism (`Prism::Translation::Parser`)
|
150
|
+
# By default, `parser` is used. For the `TargetRubyVersion` value, `parser` can be specified for versions `2.0` and above.
|
151
|
+
# `parser_prism` can be specified for versions `3.3` and above. `parser_prism` is faster but still considered experimental.
|
152
|
+
ParserEngine: parser_whitequark
|
147
153
|
# Determines if a notification for extension libraries should be shown when
|
148
154
|
# rubocop is run. Keys are the name of the extension, and values are an array
|
149
155
|
# of gems in the Gemfile that the extension is suggested for, if not already
|
@@ -17,7 +17,10 @@ module RuboCop
|
|
17
17
|
|
18
18
|
PHASE_1_OVERRIDDEN = '(skipped because the default Layout/LineLength:Max is overridden)'
|
19
19
|
PHASE_1_DISABLED = '(skipped because Layout/LineLength is disabled)'
|
20
|
-
|
20
|
+
PHASE_1_SKIPPED_ONLY_COPS =
|
21
|
+
'(skipped because a list of cops is passed to the `--only` flag)'
|
22
|
+
PHASE_1_SKIPPED_ONLY_EXCLUDE =
|
23
|
+
'(skipped because only excludes will be generated due to `--auto-gen-only-exclude` flag)'
|
21
24
|
|
22
25
|
def run
|
23
26
|
add_formatter
|
@@ -29,12 +32,14 @@ module RuboCop
|
|
29
32
|
private
|
30
33
|
|
31
34
|
def maybe_run_line_length_cop
|
32
|
-
if
|
35
|
+
if only_exclude?
|
36
|
+
skip_line_length_cop(PHASE_1_SKIPPED_ONLY_EXCLUDE)
|
37
|
+
elsif !line_length_enabled?(@config_store.for_pwd)
|
33
38
|
skip_line_length_cop(PHASE_1_DISABLED)
|
34
39
|
elsif !same_max_line_length?(@config_store.for_pwd, ConfigLoader.default_configuration)
|
35
40
|
skip_line_length_cop(PHASE_1_OVERRIDDEN)
|
36
41
|
elsif options_has_only_flag?
|
37
|
-
skip_line_length_cop(
|
42
|
+
skip_line_length_cop(PHASE_1_SKIPPED_ONLY_COPS)
|
38
43
|
else
|
39
44
|
run_line_length_cop
|
40
45
|
end
|
@@ -65,6 +70,10 @@ module RuboCop
|
|
65
70
|
@options[:only]
|
66
71
|
end
|
67
72
|
|
73
|
+
def only_exclude?
|
74
|
+
@options[:auto_gen_only_exclude]
|
75
|
+
end
|
76
|
+
|
68
77
|
# Do an initial run with only Layout/LineLength so that cops that
|
69
78
|
# depend on Layout/LineLength:Max get the correct value for that
|
70
79
|
# parameter.
|
data/lib/rubocop/config.rb
CHANGED
@@ -244,6 +244,10 @@ module RuboCop
|
|
244
244
|
end
|
245
245
|
end
|
246
246
|
|
247
|
+
def parser_engine
|
248
|
+
@parser_engine ||= for_all_cops.fetch('ParserEngine', :parser_whitequark).to_sym
|
249
|
+
end
|
250
|
+
|
247
251
|
def target_rails_version
|
248
252
|
@target_rails_version ||=
|
249
253
|
if for_all_cops['TargetRailsVersion']
|
data/lib/rubocop/cop/base.rb
CHANGED
@@ -232,6 +232,10 @@ module RuboCop
|
|
232
232
|
@config.target_ruby_version
|
233
233
|
end
|
234
234
|
|
235
|
+
def parser_engine
|
236
|
+
@config.parser_engine
|
237
|
+
end
|
238
|
+
|
235
239
|
def target_rails_version
|
236
240
|
@config.target_rails_version
|
237
241
|
end
|
@@ -254,7 +258,7 @@ module RuboCop
|
|
254
258
|
|
255
259
|
# There should be very limited reasons for a Cop to do it's own parsing
|
256
260
|
def parse(source, path = nil)
|
257
|
-
ProcessedSource.new(source, target_ruby_version, path)
|
261
|
+
ProcessedSource.new(source, target_ruby_version, path, parser_engine: parser_engine)
|
258
262
|
end
|
259
263
|
|
260
264
|
# @api private
|
@@ -76,7 +76,9 @@ module RuboCop
|
|
76
76
|
PATTERN
|
77
77
|
|
78
78
|
def on_new_investigation
|
79
|
-
|
79
|
+
return if processed_source.ast && required_ruby_version?(processed_source.ast)
|
80
|
+
|
81
|
+
add_global_offense(MISSING_MSG)
|
80
82
|
end
|
81
83
|
|
82
84
|
def on_send(node)
|
@@ -26,10 +26,18 @@ module RuboCop
|
|
26
26
|
MSG = 'Precede `%<method>s` with a `@!method` YARD directive.'
|
27
27
|
MSG_WRONG_NAME = '`@!method` YARD directive has invalid method name, ' \
|
28
28
|
'use `%<expected>s` instead of `%<actual>s`.'
|
29
|
+
MSG_MISSING_SCOPE_SELF = 'Follow the `@!method` YARD directive with ' \
|
30
|
+
'`@!scope class` if it is a class method.'
|
31
|
+
MSG_WRONG_SCOPE_SELF = 'Do not use the `@!scope class` YARD directive if it ' \
|
32
|
+
'is not a class method.'
|
29
33
|
MSG_TOO_MANY = 'Multiple `@!method` YARD directives found for this matcher.'
|
30
34
|
|
31
35
|
RESTRICT_ON_SEND = %i[def_node_matcher def_node_search].to_set.freeze
|
32
|
-
|
36
|
+
REGEXP_METHOD = /
|
37
|
+
^\s*\#\s*
|
38
|
+
@!method\s+(?<receiver>self\.)?(?<method_name>[a-z0-9_]+[?!]?)(?:\((?<args>.*)\))?
|
39
|
+
/x.freeze
|
40
|
+
REGEXP_SCOPE = /^\s*\#\s*@!scope class/.freeze
|
33
41
|
|
34
42
|
# @!method pattern_matcher?(node)
|
35
43
|
def_node_matcher :pattern_matcher?, <<~PATTERN
|
@@ -40,14 +48,15 @@ module RuboCop
|
|
40
48
|
return if node.arguments.none?
|
41
49
|
return unless valid_method_name?(node)
|
42
50
|
|
43
|
-
actual_name = node.first_argument.value
|
51
|
+
actual_name = node.first_argument.value.to_s
|
52
|
+
|
53
|
+
# Ignore cases where the method has a receiver that isn't self
|
54
|
+
return if actual_name.include?('.') && !actual_name.start_with?('self.')
|
55
|
+
|
44
56
|
directives = method_directives(node)
|
45
57
|
return too_many_directives(node) if directives.size > 1
|
46
58
|
|
47
|
-
|
48
|
-
return if directive_correct?(directive, actual_name)
|
49
|
-
|
50
|
-
register_offense(node, directive, actual_name)
|
59
|
+
process_directive(node, actual_name, directives.first)
|
51
60
|
end
|
52
61
|
|
53
62
|
private
|
@@ -58,44 +67,112 @@ module RuboCop
|
|
58
67
|
|
59
68
|
def method_directives(node)
|
60
69
|
comments = processed_source.ast_with_comments[node]
|
61
|
-
|
62
|
-
|
63
|
-
match = comment.text.match(REGEXP)
|
70
|
+
group_comments(comments).filter_map do |comment_method, comment_scope|
|
71
|
+
match = comment_method.text.match(REGEXP_METHOD)
|
64
72
|
next unless match
|
65
73
|
|
66
|
-
{
|
74
|
+
{
|
75
|
+
node_method: comment_method,
|
76
|
+
node_scope: comment_scope,
|
77
|
+
method_name: match[:method_name],
|
78
|
+
args: match[:args],
|
79
|
+
receiver: match[:receiver],
|
80
|
+
has_scope_directive: comment_scope&.text&.match?(REGEXP_SCOPE)
|
81
|
+
}
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def group_comments(comments)
|
86
|
+
result = []
|
87
|
+
comments.each.with_index do |comment, index|
|
88
|
+
# Grab the scope directive if it is preceded by a method directive
|
89
|
+
if comment.text.include?('@!method')
|
90
|
+
result << if (next_comment = comments[index + 1])&.text&.include?('@!scope')
|
91
|
+
[comment, next_comment]
|
92
|
+
else
|
93
|
+
[comment, nil]
|
94
|
+
end
|
95
|
+
end
|
67
96
|
end
|
97
|
+
result
|
68
98
|
end
|
69
99
|
|
70
100
|
def too_many_directives(node)
|
71
101
|
add_offense(node, message: MSG_TOO_MANY)
|
72
102
|
end
|
73
103
|
|
74
|
-
def
|
75
|
-
|
104
|
+
def process_directive(node, actual_name, directive)
|
105
|
+
return unless (offense_type = directive_offense_type(directive, actual_name))
|
106
|
+
|
107
|
+
register_offense(offense_type, node, directive, actual_name)
|
108
|
+
end
|
109
|
+
|
110
|
+
def directive_offense_type(directive, actual_name)
|
111
|
+
return :missing_directive unless directive
|
112
|
+
|
113
|
+
return :wrong_scope if wrong_scope(directive, actual_name)
|
114
|
+
return :no_scope if no_scope(directive, actual_name)
|
115
|
+
|
116
|
+
# The method directive being prefixed by 'self.' is always an offense.
|
117
|
+
# The matched method_name does not contain the receiver but the
|
118
|
+
# def_node_match method name may so it must be removed.
|
119
|
+
if directive[:method_name] != remove_receiver(actual_name) || directive[:receiver]
|
120
|
+
:wrong_name
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def wrong_scope(directive, actual_name)
|
125
|
+
!actual_name.start_with?('self.') && directive[:has_scope_directive]
|
126
|
+
end
|
127
|
+
|
128
|
+
def no_scope(directive, actual_name)
|
129
|
+
actual_name.start_with?('self.') && !directive[:has_scope_directive]
|
76
130
|
end
|
77
131
|
|
78
|
-
def register_offense(node, directive, actual_name)
|
79
|
-
message = formatted_message(directive, actual_name, node.method_name)
|
132
|
+
def register_offense(offense_type, node, directive, actual_name)
|
133
|
+
message = formatted_message(offense_type, directive, actual_name, node.method_name)
|
80
134
|
|
81
135
|
add_offense(node, message: message) do |corrector|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
136
|
+
case offense_type
|
137
|
+
when :wrong_name
|
138
|
+
correct_method_directive(corrector, directive, actual_name)
|
139
|
+
when :wrong_scope
|
140
|
+
remove_scope_directive(corrector, directive)
|
141
|
+
when :no_scope
|
142
|
+
insert_scope_directive(corrector, directive[:node_method])
|
143
|
+
when :missing_directive
|
144
|
+
insert_method_directive(corrector, node, actual_name)
|
86
145
|
end
|
87
146
|
end
|
88
147
|
end
|
89
148
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
149
|
+
# rubocop:disable Metrics/MethodLength
|
150
|
+
def formatted_message(offense_type, directive, actual_name, method_name)
|
151
|
+
case offense_type
|
152
|
+
when :wrong_name
|
153
|
+
# Add the receiver to the name when showing an offense
|
154
|
+
current_name = if directive[:receiver]
|
155
|
+
directive[:receiver] + directive[:method_name]
|
156
|
+
else
|
157
|
+
directive[:method_name]
|
158
|
+
end
|
159
|
+
# The correct name will never include a receiver, remove it
|
160
|
+
format(MSG_WRONG_NAME, expected: remove_receiver(actual_name), actual: current_name)
|
161
|
+
when :wrong_scope
|
162
|
+
MSG_WRONG_SCOPE_SELF
|
163
|
+
when :no_scope
|
164
|
+
MSG_MISSING_SCOPE_SELF
|
165
|
+
when :missing_directive
|
94
166
|
format(MSG, method: method_name)
|
95
167
|
end
|
96
168
|
end
|
169
|
+
# rubocop:enable Metrics/MethodLength
|
170
|
+
|
171
|
+
def remove_receiver(current)
|
172
|
+
current.delete_prefix('self.')
|
173
|
+
end
|
97
174
|
|
98
|
-
def
|
175
|
+
def insert_method_directive(corrector, node, actual_name)
|
99
176
|
# If the pattern matcher uses arguments (`%1`, `%2`, etc.), include them in the directive
|
100
177
|
arguments = pattern_arguments(node.arguments[1].source)
|
101
178
|
|
@@ -107,6 +184,14 @@ module RuboCop
|
|
107
184
|
corrector.insert_before(range, directive)
|
108
185
|
end
|
109
186
|
|
187
|
+
def insert_scope_directive(corrector, node)
|
188
|
+
range = range_with_surrounding_space(node.source_range, side: :left, newlines: false)
|
189
|
+
indentation = range.source.match(/^\s*/)[0]
|
190
|
+
directive = "\n#{indentation}# @!scope class"
|
191
|
+
|
192
|
+
corrector.insert_after(node, directive)
|
193
|
+
end
|
194
|
+
|
110
195
|
def pattern_arguments(pattern)
|
111
196
|
arguments = %w[node]
|
112
197
|
max_pattern_var = pattern.scan(/(?<=%)\d+/).map(&:to_i).max
|
@@ -134,12 +219,21 @@ module RuboCop
|
|
134
219
|
end
|
135
220
|
end
|
136
221
|
|
137
|
-
def
|
138
|
-
correct = "@!method #{actual_name}"
|
139
|
-
|
222
|
+
def correct_method_directive(corrector, directive, actual_name)
|
223
|
+
correct = "@!method #{remove_receiver(actual_name)}"
|
224
|
+
current_name = (directive[:receiver] || '') + directive[:method_name]
|
225
|
+
regexp = /@!method\s+#{Regexp.escape(current_name)}/
|
226
|
+
|
227
|
+
replacement = directive[:node_method].text.gsub(regexp, correct)
|
228
|
+
corrector.replace(directive[:node_method], replacement)
|
229
|
+
end
|
140
230
|
|
141
|
-
|
142
|
-
|
231
|
+
def remove_scope_directive(corrector, directive)
|
232
|
+
range = range_by_whole_lines(
|
233
|
+
directive[:node_scope].source_range,
|
234
|
+
include_final_newline: true
|
235
|
+
)
|
236
|
+
corrector.remove(range)
|
143
237
|
end
|
144
238
|
end
|
145
239
|
end
|
@@ -27,9 +27,9 @@ module RuboCop
|
|
27
27
|
MSG = 'Add an empty line after magic comments.'
|
28
28
|
|
29
29
|
def on_new_investigation
|
30
|
-
return unless processed_source
|
31
|
-
|
32
|
-
return if
|
30
|
+
return unless (last_magic_comment = last_magic_comment(processed_source))
|
31
|
+
return unless (next_line = processed_source[last_magic_comment.loc.line])
|
32
|
+
return if next_line.strip.empty?
|
33
33
|
|
34
34
|
offending_range = offending_range(last_magic_comment)
|
35
35
|
|
@@ -46,18 +46,25 @@ module RuboCop
|
|
46
46
|
|
47
47
|
# Find the last magic comment in the source file.
|
48
48
|
#
|
49
|
-
# Take all comments that precede the first line of code
|
49
|
+
# Take all comments that precede the first line of code (or just take
|
50
|
+
# them all in the case when there is no code), select the
|
50
51
|
# magic comments, and return the last magic comment in the file.
|
51
52
|
#
|
52
53
|
# @return [Parser::Source::Comment] if magic comments exist before code
|
53
54
|
# @return [nil] otherwise
|
54
55
|
def last_magic_comment(source)
|
55
|
-
source
|
56
|
-
.comments
|
57
|
-
.take_while { |comment| comment.loc.line < source.ast.loc.line }
|
56
|
+
comments_before_code(source)
|
58
57
|
.reverse
|
59
58
|
.find { |comment| MagicComment.parse(comment.text).any? }
|
60
59
|
end
|
60
|
+
|
61
|
+
def comments_before_code(source)
|
62
|
+
if source.ast
|
63
|
+
source.comments.take_while { |comment| comment.loc.line < source.ast.loc.line }
|
64
|
+
else
|
65
|
+
source.comments
|
66
|
+
end
|
67
|
+
end
|
61
68
|
end
|
62
69
|
end
|
63
70
|
end
|
@@ -84,8 +84,14 @@ module RuboCop
|
|
84
84
|
end
|
85
85
|
|
86
86
|
def offense?(node)
|
87
|
-
node.multiline?
|
88
|
-
|
87
|
+
return false if !node.multiline? || too_long?(node) || !suitable_as_single_line?(node)
|
88
|
+
return require_backslash?(node) if node.and_type? || node.or_type?
|
89
|
+
|
90
|
+
!index_access_call_chained?(node) && !configured_to_not_be_inspected?(node)
|
91
|
+
end
|
92
|
+
|
93
|
+
def require_backslash?(node)
|
94
|
+
processed_source.lines[node.loc.operator.line - 1].end_with?('\\')
|
89
95
|
end
|
90
96
|
|
91
97
|
def index_access_call_chained?(node)
|
@@ -116,7 +116,7 @@ module RuboCop
|
|
116
116
|
|
117
117
|
def incorrect_style_detected(token1, token2,
|
118
118
|
expect_space, is_empty_braces)
|
119
|
-
brace = (token1.
|
119
|
+
brace = (token1.left_brace? ? token1 : token2).pos
|
120
120
|
range = expect_space ? brace : space_range(brace)
|
121
121
|
detected_style = expect_space ? 'no_space' : 'space'
|
122
122
|
|
@@ -51,8 +51,13 @@ module RuboCop
|
|
51
51
|
enum_conversion_call?(node) do |method_node, arguments|
|
52
52
|
next if method_node.call_type? &&
|
53
53
|
!method_node.method?(:__method__) && !method_node.method?(:__callee__)
|
54
|
-
|
55
|
-
|
54
|
+
|
55
|
+
valid = if method_name?(method_node, def_node.method_name)
|
56
|
+
arguments_match?(arguments, def_node)
|
57
|
+
else
|
58
|
+
def_node.arguments.empty?
|
59
|
+
end
|
60
|
+
return if valid
|
56
61
|
|
57
62
|
add_offense(node)
|
58
63
|
end
|
@@ -189,7 +189,7 @@ module RuboCop
|
|
189
189
|
case node.type
|
190
190
|
when :casgn then _scope, _lhs, rhs = *node
|
191
191
|
when :op_asgn then _lhs, _op, rhs = *node
|
192
|
-
when :send
|
192
|
+
when :send, :csend then rhs = node.last_argument
|
193
193
|
else _lhs, rhs = *node
|
194
194
|
end
|
195
195
|
rhs
|
@@ -54,9 +54,9 @@ module RuboCop
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def on_send(node)
|
57
|
-
|
58
|
-
|
59
|
-
)
|
57
|
+
return unless (first_argument = node.first_argument)
|
58
|
+
|
59
|
+
add_offense(first_argument, message: format(MSG, class_var: first_argument.source))
|
60
60
|
end
|
61
61
|
end
|
62
62
|
end
|
@@ -40,7 +40,7 @@ module RuboCop
|
|
40
40
|
|
41
41
|
MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
|
42
42
|
UNUSED_BLOCK_ARG_MSG = "#{MSG.chop} and remove the unused `%<unused_code>s` block argument."
|
43
|
-
ARRAY_CONVERTER_METHODS = %i[assoc flatten rassoc sort sort_by to_a].freeze
|
43
|
+
ARRAY_CONVERTER_METHODS = %i[assoc chunk flatten rassoc sort sort_by to_a].freeze
|
44
44
|
|
45
45
|
# @!method kv_each(node)
|
46
46
|
def_node_matcher :kv_each, <<~PATTERN
|
@@ -38,6 +38,7 @@ module RuboCop
|
|
38
38
|
|
39
39
|
private
|
40
40
|
|
41
|
+
# rubocop:disable Metrics/AbcSize
|
41
42
|
def autocorrect(corrector, node, begin_of_arguments)
|
42
43
|
arguments = node.arguments
|
43
44
|
joined_arguments = arguments.map(&:source).join(', ')
|
@@ -49,9 +50,17 @@ module RuboCop
|
|
49
50
|
corrector.remove(range_by_whole_lines(arguments.loc.end, include_final_newline: true))
|
50
51
|
end
|
51
52
|
|
52
|
-
|
53
|
+
arguments_range = arguments_range(node)
|
54
|
+
# If the method name isn't on the same line as def, move it directly after def
|
55
|
+
if arguments_range.first_line != opening_line(node)
|
56
|
+
corrector.remove(node.loc.name)
|
57
|
+
corrector.insert_after(node.loc.keyword, " #{node.loc.name.source}")
|
58
|
+
end
|
59
|
+
|
60
|
+
corrector.remove(arguments_range)
|
53
61
|
corrector.insert_after(begin_of_arguments, joined_arguments)
|
54
62
|
end
|
63
|
+
# rubocop:enable Metrics/AbcSize
|
55
64
|
|
56
65
|
def last_line_source_of_arguments(arguments)
|
57
66
|
processed_source[arguments.last_line - 1].strip
|
@@ -80,7 +80,7 @@ module RuboCop
|
|
80
80
|
|
81
81
|
def correction_exploded_to_compact(node)
|
82
82
|
exception_node, *message_nodes = *node.arguments
|
83
|
-
return
|
83
|
+
return if message_nodes.size > 1
|
84
84
|
|
85
85
|
argument = message_nodes.first.source
|
86
86
|
exception_class = exception_node.receiver&.source || exception_node.source
|
@@ -22,10 +22,11 @@ module RuboCop
|
|
22
22
|
|
23
23
|
def on_send(node)
|
24
24
|
return unless node.method?(:require_relative)
|
25
|
-
return unless node.first_argument
|
26
|
-
return unless
|
25
|
+
return unless (first_argument = node.first_argument)
|
26
|
+
return unless first_argument.str_content&.start_with?(CURRENT_DIRECTORY_PATH)
|
27
|
+
return unless (index = first_argument.source.index(CURRENT_DIRECTORY_PATH))
|
27
28
|
|
28
|
-
begin_pos =
|
29
|
+
begin_pos = first_argument.source_range.begin.begin_pos + index
|
29
30
|
range = range_between(begin_pos, begin_pos + 2)
|
30
31
|
|
31
32
|
add_offense(range) do |corrector|
|
@@ -72,7 +72,7 @@ module RuboCop
|
|
72
72
|
ALLOWED_STRING_TOKENS = %i[tSTRING tSTRING_CONTENT].freeze
|
73
73
|
ARGUMENT_TYPES = %i[
|
74
74
|
kFALSE kNIL kSELF kTRUE tCONSTANT tCVAR tFLOAT tGVAR tIDENTIFIER tINTEGER tIVAR
|
75
|
-
tLBRACK tLCURLY tLPAREN_ARG tSTRING tSTRING_BEG tSYMBOL tXSTRING_BEG
|
75
|
+
tLABEL tLBRACK tLCURLY tLPAREN_ARG tSTRING tSTRING_BEG tSYMBOL tXSTRING_BEG
|
76
76
|
].freeze
|
77
77
|
|
78
78
|
def on_new_investigation
|
@@ -6,9 +6,11 @@ module RuboCop
|
|
6
6
|
# cops it contains.
|
7
7
|
class DirectiveComment
|
8
8
|
# @api private
|
9
|
-
|
9
|
+
LINT_DEPARTMENT = 'Lint'
|
10
10
|
# @api private
|
11
|
-
|
11
|
+
LINT_REDUNDANT_DIRECTIVE_COP = "#{LINT_DEPARTMENT}/RedundantCopDisableDirective"
|
12
|
+
# @api private
|
13
|
+
LINT_SYNTAX_COP = "#{LINT_DEPARTMENT}/Syntax"
|
12
14
|
# @api private
|
13
15
|
COP_NAME_PATTERN = '([A-Z]\w+/)*(?:[A-Z]\w+)'
|
14
16
|
# @api private
|
@@ -118,9 +120,10 @@ module RuboCop
|
|
118
120
|
end
|
119
121
|
|
120
122
|
def parsed_cop_names
|
121
|
-
splitted_cops_string.map do |name|
|
123
|
+
cops = splitted_cops_string.map do |name|
|
122
124
|
department?(name) ? cop_names_for_department(name) : name
|
123
125
|
end.flatten
|
126
|
+
cops - [LINT_SYNTAX_COP]
|
124
127
|
end
|
125
128
|
|
126
129
|
def department?(name)
|
@@ -128,17 +131,16 @@ module RuboCop
|
|
128
131
|
end
|
129
132
|
|
130
133
|
def all_cop_names
|
131
|
-
|
134
|
+
exclude_lint_department_cops(cop_registry.names)
|
132
135
|
end
|
133
136
|
|
134
137
|
def cop_names_for_department(department)
|
135
138
|
names = cop_registry.names_for_department(department)
|
136
|
-
|
137
|
-
has_redundant_directive_cop ? exclude_redundant_directive_cop(names) : names
|
139
|
+
department == LINT_DEPARTMENT ? exclude_lint_department_cops(names) : names
|
138
140
|
end
|
139
141
|
|
140
|
-
def
|
141
|
-
cops - [
|
142
|
+
def exclude_lint_department_cops(cops)
|
143
|
+
cops - [LINT_REDUNDANT_DIRECTIVE_COP, LINT_SYNTAX_COP]
|
142
144
|
end
|
143
145
|
end
|
144
146
|
end
|
@@ -268,7 +268,7 @@ module RuboCop
|
|
268
268
|
|
269
269
|
# Rewrite the comment without a given token type
|
270
270
|
def without(type)
|
271
|
-
if @comment.match?(/\A#\s*#{self.class::KEYWORDS[type.to_sym]}/)
|
271
|
+
if @comment.match?(/\A#\s*#{self.class::KEYWORDS[type.to_sym]}/io)
|
272
272
|
''
|
273
273
|
else
|
274
274
|
@comment
|
@@ -6,7 +6,11 @@ require 'tempfile'
|
|
6
6
|
module CopHelper
|
7
7
|
extend RSpec::SharedContext
|
8
8
|
|
9
|
-
let(:ruby_version)
|
9
|
+
let(:ruby_version) do
|
10
|
+
# The minimum version Prism can parse is 3.3.
|
11
|
+
ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : RuboCop::TargetRuby::DEFAULT_VERSION
|
12
|
+
end
|
13
|
+
let(:parser_engine) { ENV.fetch('PARSER_ENGINE', :parser_whitequark).to_sym }
|
10
14
|
let(:rails_version) { false }
|
11
15
|
|
12
16
|
def inspect_source(source, file = nil)
|
@@ -28,7 +32,9 @@ module CopHelper
|
|
28
32
|
file = file.path
|
29
33
|
end
|
30
34
|
|
31
|
-
processed_source = RuboCop::ProcessedSource.new(
|
35
|
+
processed_source = RuboCop::ProcessedSource.new(
|
36
|
+
source, ruby_version, file, parser_engine: parser_engine
|
37
|
+
)
|
32
38
|
processed_source.config = configuration
|
33
39
|
processed_source.registry = registry
|
34
40
|
processed_source
|
@@ -126,7 +126,7 @@ module RuboCop
|
|
126
126
|
@offenses
|
127
127
|
end
|
128
128
|
|
129
|
-
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity
|
129
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity
|
130
130
|
def expect_correction(correction, loop: true, source: nil)
|
131
131
|
if source
|
132
132
|
expected_annotations = parse_annotations(source, raise_error: false)
|
@@ -148,7 +148,6 @@ module RuboCop
|
|
148
148
|
|
149
149
|
break corrected_source unless loop
|
150
150
|
break corrected_source if @last_corrector.empty?
|
151
|
-
break corrected_source if corrected_source == @processed_source.buffer.source
|
152
151
|
|
153
152
|
if iteration > RuboCop::Runner::MAX_ITERATIONS
|
154
153
|
raise RuboCop::Runner::InfiniteCorrectionLoop.new(@processed_source.path, [@offenses])
|
@@ -163,19 +162,20 @@ module RuboCop
|
|
163
162
|
|
164
163
|
expect(new_source).to eq(correction)
|
165
164
|
end
|
166
|
-
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity
|
165
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity
|
167
166
|
|
168
167
|
def expect_no_corrections
|
169
168
|
raise '`expect_no_corrections` must follow `expect_offense`' unless @processed_source
|
170
169
|
|
171
170
|
return if @last_corrector.empty?
|
172
171
|
|
173
|
-
#
|
174
|
-
# we need to run the actual corrections
|
175
|
-
|
172
|
+
# This is just here for a pretty diff if the source actually got changed
|
176
173
|
new_source = @last_corrector.rewrite
|
177
|
-
|
178
174
|
expect(new_source).to eq(@processed_source.buffer.source)
|
175
|
+
|
176
|
+
# There is an infinite loop if a corrector is present that did not make
|
177
|
+
# any changes. It will cause the same offense/correction on the next loop.
|
178
|
+
raise RuboCop::Runner::InfiniteCorrectionLoop.new(@processed_source.path, [@offenses])
|
179
179
|
end
|
180
180
|
|
181
181
|
def expect_no_offenses(source, file = nil)
|
@@ -212,7 +212,7 @@ module RuboCop
|
|
212
212
|
|
213
213
|
# Parsed representation of code annotated with the `^^^ Message` style
|
214
214
|
class AnnotatedSource
|
215
|
-
ANNOTATION_PATTERN = /\A\s*(\^+|\^{})
|
215
|
+
ANNOTATION_PATTERN = /\A\s*(\^+|\^{}) ?/.freeze
|
216
216
|
ABBREV = "[...]\n"
|
217
217
|
|
218
218
|
# @param annotated_source [String] string passed to the matchers
|
@@ -139,49 +139,64 @@ RSpec.shared_context 'lsp' do
|
|
139
139
|
end
|
140
140
|
|
141
141
|
RSpec.shared_context 'ruby 2.0' do
|
142
|
-
|
142
|
+
# Prism supports parsing Ruby 3.3+.
|
143
|
+
let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.0 }
|
143
144
|
end
|
144
145
|
|
145
146
|
RSpec.shared_context 'ruby 2.1' do
|
146
|
-
|
147
|
+
# Prism supports parsing Ruby 3.3+.
|
148
|
+
let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.1 }
|
147
149
|
end
|
148
150
|
|
149
151
|
RSpec.shared_context 'ruby 2.2' do
|
150
|
-
|
152
|
+
# Prism supports parsing Ruby 3.3+.
|
153
|
+
let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.2 }
|
151
154
|
end
|
152
155
|
|
153
156
|
RSpec.shared_context 'ruby 2.3' do
|
154
|
-
|
157
|
+
# Prism supports parsing Ruby 3.3+.
|
158
|
+
let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.3 }
|
155
159
|
end
|
156
160
|
|
157
161
|
RSpec.shared_context 'ruby 2.4' do
|
158
|
-
|
162
|
+
# Prism supports parsing Ruby 3.3+.
|
163
|
+
let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.4 }
|
159
164
|
end
|
160
165
|
|
161
166
|
RSpec.shared_context 'ruby 2.5' do
|
162
|
-
|
167
|
+
# Prism supports parsing Ruby 3.3+.
|
168
|
+
let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.5 }
|
163
169
|
end
|
164
170
|
|
165
171
|
RSpec.shared_context 'ruby 2.6' do
|
166
|
-
|
172
|
+
# Prism supports parsing Ruby 3.3+.
|
173
|
+
let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.6 }
|
167
174
|
end
|
168
175
|
|
169
176
|
RSpec.shared_context 'ruby 2.7' do
|
170
|
-
|
177
|
+
# Prism supports parsing Ruby 3.3+.
|
178
|
+
let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.7 }
|
171
179
|
end
|
172
180
|
|
173
181
|
RSpec.shared_context 'ruby 3.0' do
|
174
|
-
|
182
|
+
# Prism supports parsing Ruby 3.3+.
|
183
|
+
let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 3.0 }
|
175
184
|
end
|
176
185
|
|
177
186
|
RSpec.shared_context 'ruby 3.1' do
|
178
|
-
|
187
|
+
# Prism supports parsing Ruby 3.3+.
|
188
|
+
let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 3.1 }
|
179
189
|
end
|
180
190
|
|
181
191
|
RSpec.shared_context 'ruby 3.2' do
|
182
|
-
|
192
|
+
# Prism supports parsing Ruby 3.3+.
|
193
|
+
let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 3.2 }
|
183
194
|
end
|
184
195
|
|
185
196
|
RSpec.shared_context 'ruby 3.3' do
|
186
197
|
let(:ruby_version) { 3.3 }
|
187
198
|
end
|
199
|
+
|
200
|
+
RSpec.shared_context 'ruby 3.4' do
|
201
|
+
let(:ruby_version) { 3.4 }
|
202
|
+
end
|
data/lib/rubocop/runner.rb
CHANGED
@@ -467,15 +467,21 @@ module RuboCop
|
|
467
467
|
end
|
468
468
|
end
|
469
469
|
|
470
|
+
# rubocop:disable Metrics/MethodLength
|
470
471
|
def get_processed_source(file)
|
471
472
|
config = @config_store.for_file(file)
|
472
473
|
ruby_version = config.target_ruby_version
|
474
|
+
parser_engine = config.parser_engine
|
473
475
|
|
474
476
|
processed_source = if @options[:stdin]
|
475
|
-
ProcessedSource.new(
|
477
|
+
ProcessedSource.new(
|
478
|
+
@options[:stdin], ruby_version, file, parser_engine: parser_engine
|
479
|
+
)
|
476
480
|
else
|
477
481
|
begin
|
478
|
-
ProcessedSource.from_file(
|
482
|
+
ProcessedSource.from_file(
|
483
|
+
file, ruby_version, parser_engine: parser_engine
|
484
|
+
)
|
479
485
|
rescue Errno::ENOENT
|
480
486
|
raise RuboCop::Error, "No such file or directory: #{file}"
|
481
487
|
end
|
@@ -484,6 +490,7 @@ module RuboCop
|
|
484
490
|
processed_source.registry = mobilized_cop_classes(config)
|
485
491
|
processed_source
|
486
492
|
end
|
493
|
+
# rubocop:enable Metrics/MethodLength
|
487
494
|
|
488
495
|
# A Cop::Team instance is stateful and may change when inspecting.
|
489
496
|
# The "standby" team for a given config is an initialized but
|
@@ -1,8 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module RuboCop
|
4
|
-
# This class finds target files to inspect by scanning the directory tree
|
5
|
-
# and picking ruby files.
|
4
|
+
# This class finds target files to inspect by scanning the directory tree and picking ruby files.
|
6
5
|
# @api private
|
7
6
|
class TargetFinder
|
8
7
|
HIDDEN_PATH_SUBSTRING = "#{File::SEPARATOR}."
|
@@ -12,21 +11,8 @@ module RuboCop
|
|
12
11
|
@options = options
|
13
12
|
end
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
end
|
18
|
-
|
19
|
-
def debug?
|
20
|
-
@options[:debug]
|
21
|
-
end
|
22
|
-
|
23
|
-
def fail_fast?
|
24
|
-
@options[:fail_fast]
|
25
|
-
end
|
26
|
-
|
27
|
-
# Generate a list of target files by expanding globbing patterns
|
28
|
-
# (if any). If args is empty, recursively find all Ruby source
|
29
|
-
# files under the current directory
|
14
|
+
# Generate a list of target files by expanding globbing patterns (if any). If args is empty,
|
15
|
+
# recursively find all Ruby source files under the current directory
|
30
16
|
# @return [Array] array of file paths
|
31
17
|
def find(args, mode)
|
32
18
|
return target_files_in_dir if args.empty?
|
@@ -44,12 +30,11 @@ module RuboCop
|
|
44
30
|
files.map { |f| File.expand_path(f) }.uniq
|
45
31
|
end
|
46
32
|
|
47
|
-
# Finds all Ruby source files under the current or other supplied
|
48
|
-
#
|
49
|
-
#
|
50
|
-
#
|
51
|
-
#
|
52
|
-
# so you can include other Ruby files like Rakefiles and gemspecs.
|
33
|
+
# Finds all Ruby source files under the current or other supplied directory. A Ruby source file
|
34
|
+
# is defined as a file with the `.rb` extension or a file with no extension that has a ruby
|
35
|
+
# shebang line as its first line.
|
36
|
+
# It is possible to specify includes and excludes using the config file, so you can include
|
37
|
+
# other Ruby files like Rakefiles and gemspecs.
|
53
38
|
# @param base_dir Root directory under which to search for
|
54
39
|
# ruby source files
|
55
40
|
# @return [Array] Array of filenames
|
@@ -66,20 +51,10 @@ module RuboCop
|
|
66
51
|
target_files.sort_by!(&order)
|
67
52
|
end
|
68
53
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
end && ruby_file?(file)
|
74
|
-
|
75
|
-
base_dir_config.file_to_include?(file)
|
76
|
-
end
|
77
|
-
|
78
|
-
# Search for files recursively starting at the given base directory using
|
79
|
-
# the given flags that determine how the match is made. Excluded files will
|
80
|
-
# be removed later by the caller, but as an optimization find_files removes
|
81
|
-
# the top level directories that are excluded in configuration in the
|
82
|
-
# normal way (dir/**/*).
|
54
|
+
# Search for files recursively starting at the given base directory using the given flags that
|
55
|
+
# determine how the match is made. Excluded files will be removed later by the caller, but as an
|
56
|
+
# optimization find_files removes the top level directories that are excluded in configuration
|
57
|
+
# in the normal way (dir/**/*).
|
83
58
|
def find_files(base_dir, flags)
|
84
59
|
# get all wanted directories first to improve speed of finding all files
|
85
60
|
exclude_pattern = combined_exclude_glob_patterns(base_dir)
|
@@ -93,6 +68,17 @@ module RuboCop
|
|
93
68
|
Dir.glob(patterns, flags).select { |path| FileTest.file?(path) }
|
94
69
|
end
|
95
70
|
|
71
|
+
private
|
72
|
+
|
73
|
+
def to_inspect?(file, hidden_files, base_dir_config)
|
74
|
+
return false if base_dir_config.file_to_exclude?(file)
|
75
|
+
return true if !hidden_files.bsearch do |hidden_file|
|
76
|
+
file <=> hidden_file
|
77
|
+
end && ruby_file?(file)
|
78
|
+
|
79
|
+
base_dir_config.file_to_include?(file)
|
80
|
+
end
|
81
|
+
|
96
82
|
def wanted_dir_patterns(base_dir, exclude_pattern, flags)
|
97
83
|
# Escape glob characters in base_dir to avoid unwanted behavior.
|
98
84
|
base_dir = base_dir.gsub(/[\\\{\}\[\]\*\?]/) do |reserved_glob_character|
|
@@ -124,21 +110,6 @@ module RuboCop
|
|
124
110
|
"#{base_dir}/{#{patterns.join(',')}}"
|
125
111
|
end
|
126
112
|
|
127
|
-
def ruby_extension?(file)
|
128
|
-
ruby_extensions.include?(File.extname(file))
|
129
|
-
end
|
130
|
-
|
131
|
-
def ruby_extensions
|
132
|
-
@ruby_extensions ||= begin
|
133
|
-
ext_patterns = all_cops_include.select { |pattern| pattern.start_with?('**/*.') }
|
134
|
-
ext_patterns.map { |pattern| pattern.sub('**/*', '') }
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
def ruby_filename?(file)
|
139
|
-
ruby_filenames.include?(File.basename(file))
|
140
|
-
end
|
141
|
-
|
142
113
|
def ruby_filenames
|
143
114
|
@ruby_filenames ||= begin
|
144
115
|
file_patterns = all_cops_include.reject { |pattern| pattern.start_with?('**/*.') }
|
@@ -150,53 +121,72 @@ module RuboCop
|
|
150
121
|
@all_cops_include ||= @config_store.for_pwd.for_all_cops['Include'].map(&:to_s)
|
151
122
|
end
|
152
123
|
|
153
|
-
def
|
154
|
-
|
124
|
+
def process_explicit_path(path, mode)
|
125
|
+
files = path.include?('*') ? Dir[path] : [path]
|
155
126
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
warn("Unprocessable file #{file}: #{e.class}, #{e.message}") if debug?
|
127
|
+
if mode == :only_recognized_file_types || force_exclusion?
|
128
|
+
files.select! { |file| included_file?(file) }
|
129
|
+
end
|
160
130
|
|
161
|
-
|
131
|
+
force_exclusion? ? without_excluded(files) : files
|
162
132
|
end
|
163
133
|
|
164
|
-
def
|
165
|
-
|
134
|
+
def without_excluded(files)
|
135
|
+
files.reject do |file|
|
136
|
+
# When --ignore-parent-exclusion is given, we must look at the configuration associated with
|
137
|
+
# the file, but in the default case when --ignore-parent-exclusion is not given, can safely
|
138
|
+
# look only at the configuration for the current directory, since it's only the Exclude
|
139
|
+
# parameters we're going to check.
|
140
|
+
config = @config_store.for(ignore_parent_exclusion? ? file : '.')
|
141
|
+
config.file_to_exclude?(file)
|
142
|
+
end
|
166
143
|
end
|
167
144
|
|
168
|
-
def
|
169
|
-
|
145
|
+
def included_file?(file)
|
146
|
+
ruby_file?(file) || configured_include?(file)
|
170
147
|
end
|
171
148
|
|
172
149
|
def ruby_file?(file)
|
173
150
|
stdin? || ruby_extension?(file) || ruby_filename?(file) || ruby_executable?(file)
|
174
151
|
end
|
175
152
|
|
176
|
-
def
|
177
|
-
@
|
153
|
+
def stdin?
|
154
|
+
@options.key?(:stdin)
|
178
155
|
end
|
179
156
|
|
180
|
-
def
|
181
|
-
|
157
|
+
def ruby_extension?(file)
|
158
|
+
ruby_extensions.include?(File.extname(file))
|
182
159
|
end
|
183
160
|
|
184
|
-
def
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
files.select! { |file| included_file?(file) }
|
161
|
+
def ruby_extensions
|
162
|
+
@ruby_extensions ||= begin
|
163
|
+
ext_patterns = all_cops_include.select { |pattern| pattern.start_with?('**/*.') }
|
164
|
+
ext_patterns.map { |pattern| pattern.sub('**/*', '') }
|
189
165
|
end
|
166
|
+
end
|
190
167
|
|
191
|
-
|
168
|
+
def ruby_filename?(file)
|
169
|
+
ruby_filenames.include?(File.basename(file))
|
170
|
+
end
|
192
171
|
|
193
|
-
|
194
|
-
|
195
|
-
config.file_to_exclude?(file)
|
196
|
-
end
|
172
|
+
def configured_include?(file)
|
173
|
+
@config_store.for_pwd.file_to_include?(file)
|
197
174
|
end
|
198
175
|
|
199
|
-
|
176
|
+
def ruby_executable?(file)
|
177
|
+
return false unless File.extname(file).empty? && File.exist?(file)
|
178
|
+
|
179
|
+
first_line = File.open(file, &:readline)
|
180
|
+
/#!.*(#{ruby_interpreters(file).join('|')})/.match?(first_line)
|
181
|
+
rescue EOFError, ArgumentError => e
|
182
|
+
warn("Unprocessable file #{file}: #{e.class}, #{e.message}") if debug?
|
183
|
+
|
184
|
+
false
|
185
|
+
end
|
186
|
+
|
187
|
+
def ruby_interpreters(file)
|
188
|
+
@config_store.for(file).for_all_cops['RubyInterpreters']
|
189
|
+
end
|
200
190
|
|
201
191
|
def order
|
202
192
|
if fail_fast?
|
@@ -206,5 +196,21 @@ module RuboCop
|
|
206
196
|
:itself
|
207
197
|
end
|
208
198
|
end
|
199
|
+
|
200
|
+
def force_exclusion?
|
201
|
+
@options[:force_exclusion]
|
202
|
+
end
|
203
|
+
|
204
|
+
def ignore_parent_exclusion?
|
205
|
+
@options[:ignore_parent_exclusion]
|
206
|
+
end
|
207
|
+
|
208
|
+
def debug?
|
209
|
+
@options[:debug]
|
210
|
+
end
|
211
|
+
|
212
|
+
def fail_fast?
|
213
|
+
@options[:fail_fast]
|
214
|
+
end
|
209
215
|
end
|
210
216
|
end
|
data/lib/rubocop/target_ruby.rb
CHANGED
@@ -4,7 +4,7 @@ module RuboCop
|
|
4
4
|
# The kind of Ruby that code inspected by RuboCop is written in.
|
5
5
|
# @api private
|
6
6
|
class TargetRuby
|
7
|
-
KNOWN_RUBIES = [2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 3.0, 3.1, 3.2, 3.3].freeze
|
7
|
+
KNOWN_RUBIES = [2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 3.0, 3.1, 3.2, 3.3, 3.4].freeze
|
8
8
|
DEFAULT_VERSION = 2.7
|
9
9
|
|
10
10
|
OBSOLETE_RUBIES = {
|
@@ -96,18 +96,20 @@ module RuboCop
|
|
96
96
|
end
|
97
97
|
|
98
98
|
def version_from_gemspec_file(file)
|
99
|
-
processed_source = ProcessedSource.from_file(
|
99
|
+
processed_source = ProcessedSource.from_file(
|
100
|
+
file, DEFAULT_VERSION, parser_engine: @config.parser_engine
|
101
|
+
)
|
100
102
|
required_ruby_version(processed_source.ast).first
|
101
103
|
end
|
102
104
|
|
103
105
|
def version_from_right_hand_side(right_hand_side)
|
104
106
|
gem_requirement_versions = gem_requirement_versions(right_hand_side)
|
105
107
|
|
106
|
-
if right_hand_side.array_type?
|
108
|
+
if right_hand_side.array_type? && right_hand_side.children.all?(&:str_type?)
|
107
109
|
version_from_array(right_hand_side)
|
108
110
|
elsif gem_requirement_versions
|
109
111
|
gem_requirement_versions.map(&:value)
|
110
|
-
|
112
|
+
elsif right_hand_side.str_type?
|
111
113
|
right_hand_side.value
|
112
114
|
end
|
113
115
|
end
|
data/lib/rubocop/version.rb
CHANGED
@@ -3,9 +3,9 @@
|
|
3
3
|
module RuboCop
|
4
4
|
# This module holds the RuboCop version information.
|
5
5
|
module Version
|
6
|
-
STRING = '1.
|
6
|
+
STRING = '1.62.1'
|
7
7
|
|
8
|
-
MSG = '%<version>s (using
|
8
|
+
MSG = '%<version>s (using %<parser_version>s, ' \
|
9
9
|
'rubocop-ast %<rubocop_ast_version>s, ' \
|
10
10
|
'running on %<ruby_engine>s %<ruby_version>s)%<server_mode>s [%<ruby_platform>s]'
|
11
11
|
|
@@ -20,7 +20,7 @@ module RuboCop
|
|
20
20
|
# @api private
|
21
21
|
def self.version(debug: false, env: nil)
|
22
22
|
if debug
|
23
|
-
verbose_version = format(MSG, version: STRING, parser_version:
|
23
|
+
verbose_version = format(MSG, version: STRING, parser_version: parser_version,
|
24
24
|
rubocop_ast_version: RuboCop::AST::Version::STRING,
|
25
25
|
ruby_engine: RUBY_ENGINE, ruby_version: RUBY_VERSION,
|
26
26
|
server_mode: server_mode,
|
@@ -39,6 +39,21 @@ module RuboCop
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
+
# @api private
|
43
|
+
def self.parser_version
|
44
|
+
config_path = ConfigFinder.find_config_path(Dir.pwd)
|
45
|
+
yaml = YAML.safe_load(
|
46
|
+
File.read(config_path), permitted_classes: [Regexp, Symbol], aliases: true
|
47
|
+
)
|
48
|
+
|
49
|
+
if yaml.dig('AllCops', 'ParserEngine') == 'parser_prism'
|
50
|
+
require 'prism'
|
51
|
+
"Prism #{Prism::VERSION}"
|
52
|
+
else
|
53
|
+
"Parser #{Parser::VERSION}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
42
57
|
# @api private
|
43
58
|
def self.extension_versions(env)
|
44
59
|
features = Util.silence_warnings do
|
metadata
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubocop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.62.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bozhidar Batsov
|
8
8
|
- Jonas Arvidsson
|
9
9
|
- Yuji Nakayama
|
10
|
-
autorequire:
|
10
|
+
autorequire:
|
11
11
|
bindir: exe
|
12
12
|
cert_chain: []
|
13
|
-
date: 2024-
|
13
|
+
date: 2024-03-11 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: json
|
@@ -134,7 +134,7 @@ dependencies:
|
|
134
134
|
requirements:
|
135
135
|
- - ">="
|
136
136
|
- !ruby/object:Gem::Version
|
137
|
-
version: 1.
|
137
|
+
version: 1.31.1
|
138
138
|
- - "<"
|
139
139
|
- !ruby/object:Gem::Version
|
140
140
|
version: '2.0'
|
@@ -144,7 +144,7 @@ dependencies:
|
|
144
144
|
requirements:
|
145
145
|
- - ">="
|
146
146
|
- !ruby/object:Gem::Version
|
147
|
-
version: 1.
|
147
|
+
version: 1.31.1
|
148
148
|
- - "<"
|
149
149
|
- !ruby/object:Gem::Version
|
150
150
|
version: '2.0'
|
@@ -1031,12 +1031,12 @@ licenses:
|
|
1031
1031
|
- MIT
|
1032
1032
|
metadata:
|
1033
1033
|
homepage_uri: https://rubocop.org/
|
1034
|
-
changelog_uri: https://github.com/rubocop/rubocop/releases/tag/v1.
|
1034
|
+
changelog_uri: https://github.com/rubocop/rubocop/releases/tag/v1.62.1
|
1035
1035
|
source_code_uri: https://github.com/rubocop/rubocop/
|
1036
|
-
documentation_uri: https://docs.rubocop.org/rubocop/1.
|
1036
|
+
documentation_uri: https://docs.rubocop.org/rubocop/1.62/
|
1037
1037
|
bug_tracker_uri: https://github.com/rubocop/rubocop/issues
|
1038
1038
|
rubygems_mfa_required: 'true'
|
1039
|
-
post_install_message:
|
1039
|
+
post_install_message:
|
1040
1040
|
rdoc_options: []
|
1041
1041
|
require_paths:
|
1042
1042
|
- lib
|
@@ -1051,8 +1051,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
1051
1051
|
- !ruby/object:Gem::Version
|
1052
1052
|
version: '0'
|
1053
1053
|
requirements: []
|
1054
|
-
rubygems_version: 3.
|
1055
|
-
signing_key:
|
1054
|
+
rubygems_version: 3.4.22
|
1055
|
+
signing_key:
|
1056
1056
|
specification_version: 4
|
1057
1057
|
summary: Automatic Ruby code style checking tool.
|
1058
1058
|
test_files: []
|