rubocop 1.61.0 → 1.62.1
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|