rubocop 1.86.0 → 1.86.2
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/config/default.yml +14 -3
- data/lib/rubocop/cli/command/auto_generate_config.rb +27 -1
- data/lib/rubocop/cli/command/list_enabled_cops_for.rb +40 -0
- data/lib/rubocop/cli/command/show_docs_url.rb +3 -7
- data/lib/rubocop/cli/command/suggest_extensions.rb +1 -1
- data/lib/rubocop/cli.rb +4 -7
- data/lib/rubocop/comment_config.rb +12 -15
- data/lib/rubocop/config.rb +13 -9
- data/lib/rubocop/config_loader_resolver.rb +2 -1
- data/lib/rubocop/cop/autocorrect_logic.rb +2 -1
- data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +1 -5
- data/lib/rubocop/cop/correctors.rb +28 -0
- data/lib/rubocop/cop/documentation.rb +2 -3
- data/lib/rubocop/cop/exclude_limit.rb +31 -5
- data/lib/rubocop/cop/gemspec/require_mfa.rb +3 -3
- data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +1 -0
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +1 -1
- data/lib/rubocop/cop/layout/end_alignment.rb +4 -2
- data/lib/rubocop/cop/layout/line_length.rb +5 -3
- data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +26 -1
- data/lib/rubocop/cop/lint/duplicate_methods.rb +10 -5
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +3 -13
- data/lib/rubocop/cop/lint/require_relative_self_path.rb +2 -0
- data/lib/rubocop/cop/lint/syntax.rb +25 -1
- data/lib/rubocop/cop/lint/unused_method_argument.rb +10 -0
- data/lib/rubocop/cop/lint/useless_assignment.rb +3 -8
- data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +33 -8
- data/lib/rubocop/cop/mixin/configurable_max.rb +6 -5
- data/lib/rubocop/cop/mixin.rb +85 -0
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -1
- data/lib/rubocop/cop/offense.rb +8 -0
- data/lib/rubocop/cop/registry.rb +19 -24
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +14 -2
- data/lib/rubocop/cop/style/copyright.rb +21 -10
- data/lib/rubocop/cop/style/date_time.rb +2 -2
- data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +6 -1
- data/lib/rubocop/cop/style/guard_clause.rb +9 -6
- data/lib/rubocop/cop/style/hash_lookup_method.rb +12 -7
- data/lib/rubocop/cop/style/if_inside_else.rb +16 -7
- data/lib/rubocop/cop/style/module_member_existence_check.rb +7 -14
- data/lib/rubocop/cop/style/one_class_per_file.rb +24 -4
- data/lib/rubocop/cop/style/reduce_to_hash.rb +16 -0
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +16 -0
- data/lib/rubocop/cop/style/redundant_parentheses.rb +4 -1
- data/lib/rubocop/cop/style/redundant_self.rb +2 -2
- data/lib/rubocop/cop/style/redundant_struct_keyword_init.rb +10 -0
- data/lib/rubocop/cop/style/regexp_literal.rb +29 -0
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +4 -2
- data/lib/rubocop/cop/style/symbol_proc.rb +3 -3
- data/lib/rubocop/cop/style/while_until_modifier.rb +16 -0
- data/lib/rubocop/cop/team.rb +86 -35
- data/lib/rubocop/formatter/disabled_config_formatter.rb +4 -1
- data/lib/rubocop/lsp/runtime.rb +1 -2
- data/lib/rubocop/mcp/server.rb +2 -0
- data/lib/rubocop/options.rb +8 -4
- data/lib/rubocop/rspec/cop_helper.rb +8 -0
- data/lib/rubocop/rspec/shared_contexts.rb +21 -0
- data/lib/rubocop/runner.rb +77 -55
- data/lib/rubocop/target_finder.rb +13 -6
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +7 -96
- metadata +7 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: dfb5d2d113d00eb380202a0e76f462318033838aa240febe88bd2861b1bf6609
|
|
4
|
+
data.tar.gz: 9463407310a9babcc5869f9b1db0ca273ed036a3b440b5c27438cba855bee4ec
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5084465b6aa455c8ecd75e8b8f1e52f92e966d64117d2d88ad343ca535eb6fdc02f05056e6f21ac86e2344ec52cc1db2d69f8bf14a76b76bdee86a2bd5971520
|
|
7
|
+
data.tar.gz: 2101bc8bb5b392fa971f9a881e96b03321442b5067b4952413d806363bb89389cb2631671bfa6af0e30203800cff947d587ac0c68ef1651fdec455cc453faa18
|
data/config/default.yml
CHANGED
|
@@ -529,6 +529,10 @@ Layout/ClosingParenthesisIndentation:
|
|
|
529
529
|
Description: 'Checks the indentation of hanging closing parentheses.'
|
|
530
530
|
Enabled: true
|
|
531
531
|
VersionAdded: '0.49'
|
|
532
|
+
VersionChanged: '1.86'
|
|
533
|
+
# By default the indentation width from `Layout/IndentationWidth` is used,
|
|
534
|
+
# but it can be overridden by setting this parameter.
|
|
535
|
+
IndentationWidth: ~
|
|
532
536
|
|
|
533
537
|
Layout/CommentIndentation:
|
|
534
538
|
Description: 'Indentation of comments.'
|
|
@@ -537,7 +541,10 @@ Layout/CommentIndentation:
|
|
|
537
541
|
# with a comment on the preceding line.
|
|
538
542
|
AllowForAlignment: false
|
|
539
543
|
VersionAdded: '0.49'
|
|
540
|
-
VersionChanged: '1.
|
|
544
|
+
VersionChanged: '1.86'
|
|
545
|
+
# By default the indentation width from `Layout/IndentationWidth` is used,
|
|
546
|
+
# but it can be overridden by setting this parameter.
|
|
547
|
+
IndentationWidth: ~
|
|
541
548
|
|
|
542
549
|
Layout/ConditionPosition:
|
|
543
550
|
Description: >-
|
|
@@ -4796,7 +4803,6 @@ Style/ModuleMemberExistenceCheck:
|
|
|
4796
4803
|
Description: 'Checks for usage of `Module` methods returning arrays that can be replaced with equivalent predicates.'
|
|
4797
4804
|
Enabled: pending
|
|
4798
4805
|
VersionAdded: '1.82'
|
|
4799
|
-
AllowedMethods: []
|
|
4800
4806
|
|
|
4801
4807
|
Style/MultilineBlockChain:
|
|
4802
4808
|
Description: 'Avoid multi-line chains of blocks.'
|
|
@@ -5112,7 +5118,11 @@ Style/OneClassPerFile:
|
|
|
5112
5118
|
Description: 'Checks that each source file defines at most one top-level class or module.'
|
|
5113
5119
|
Enabled: pending
|
|
5114
5120
|
VersionAdded: '1.85'
|
|
5121
|
+
VersionChanged: '1.86'
|
|
5115
5122
|
AllowedClasses: []
|
|
5123
|
+
Exclude:
|
|
5124
|
+
- 'spec/**/*'
|
|
5125
|
+
- 'test/**/*'
|
|
5116
5126
|
|
|
5117
5127
|
Style/OneLineConditional:
|
|
5118
5128
|
Description: >-
|
|
@@ -5557,9 +5567,10 @@ Style/RedundantStringEscape:
|
|
|
5557
5567
|
|
|
5558
5568
|
Style/RedundantStructKeywordInit:
|
|
5559
5569
|
Description: 'Checks for redundant `keyword_init` option for `Struct.new`.'
|
|
5560
|
-
Enabled:
|
|
5570
|
+
Enabled: false
|
|
5561
5571
|
SafeAutoCorrect: false
|
|
5562
5572
|
VersionAdded: '1.85'
|
|
5573
|
+
VersionChanged: '1.86'
|
|
5563
5574
|
|
|
5564
5575
|
Style/RegexpLiteral:
|
|
5565
5576
|
Description: 'Use / or %r around regular expressions.'
|
|
@@ -24,13 +24,39 @@ module RuboCop
|
|
|
24
24
|
|
|
25
25
|
def run
|
|
26
26
|
add_formatter
|
|
27
|
+
use_temporary_cache
|
|
28
|
+
reset_auto_gen_tmp_dir
|
|
27
29
|
reset_config_and_auto_gen_file
|
|
28
30
|
line_length_contents = maybe_run_line_length_cop
|
|
29
|
-
run_all_cops(line_length_contents)
|
|
31
|
+
result = run_all_cops(line_length_contents)
|
|
32
|
+
reset_auto_gen_tmp_dir
|
|
33
|
+
result
|
|
30
34
|
end
|
|
31
35
|
|
|
32
36
|
private
|
|
33
37
|
|
|
38
|
+
def use_temporary_cache
|
|
39
|
+
# Use a separate cache directory to ensure MinDigits and Max values are calculated.
|
|
40
|
+
# This allows parallel execution (which requires cache) while ensuring MinDigits
|
|
41
|
+
# and Max values are computed, since the cache starts empty.
|
|
42
|
+
@options[:cache_root] = auto_gen_tmp_dir.join('cache').to_s
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def reset_auto_gen_tmp_dir
|
|
46
|
+
auto_gen_tmp_dir.rmtree if auto_gen_tmp_dir.exist?
|
|
47
|
+
auto_gen_tmp_dir.mkpath
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def auto_gen_tmp_dir
|
|
51
|
+
@auto_gen_tmp_dir ||= Pathname.new(
|
|
52
|
+
RuboCop::CacheConfig.root_dir_from_toplevel_config
|
|
53
|
+
).join('auto-gen-tmp').tap do |path|
|
|
54
|
+
path.mkpath
|
|
55
|
+
# Set the temp directory path for ExcludeLimit to use
|
|
56
|
+
RuboCop::ExcludeLimit.tmp_dir = path
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
34
60
|
def maybe_run_line_length_cop
|
|
35
61
|
if only_exclude?
|
|
36
62
|
skip_line_length_cop(PHASE_1_SKIPPED_ONLY_EXCLUDE)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
class CLI
|
|
5
|
+
module Command
|
|
6
|
+
# Lists the cops that will inspect the given file or directory.
|
|
7
|
+
# @api private
|
|
8
|
+
class ListEnabledCopsFor < Base
|
|
9
|
+
self.command_name = :list_enabled_cops_for
|
|
10
|
+
|
|
11
|
+
def initialize(env)
|
|
12
|
+
super
|
|
13
|
+
|
|
14
|
+
# Load the configs so the require()s are done for custom cops
|
|
15
|
+
@config = @config_store.for(@options[:list_enabled_cops_for])
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def run
|
|
19
|
+
print_available_cops
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def print_available_cops
|
|
25
|
+
registry = Cop::Registry.global
|
|
26
|
+
|
|
27
|
+
registry.departments.sort.each do |department|
|
|
28
|
+
puts cops_of_department(registry, department).sort
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def cops_of_department(registry, department)
|
|
33
|
+
registry.with_department(department)
|
|
34
|
+
.map(&:cop_name)
|
|
35
|
+
.select { |cop_name| @config.cop_enabled?(cop_name) }
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -25,10 +25,10 @@ module RuboCop
|
|
|
25
25
|
puts Cop::Documentation.default_base_url if cops_array.empty?
|
|
26
26
|
|
|
27
27
|
cops_array.each do |cop_name|
|
|
28
|
-
cop =
|
|
29
|
-
next
|
|
28
|
+
cop = Cop::Registry.global.find_by_cop_name(cop_name)
|
|
29
|
+
next unless cop
|
|
30
30
|
|
|
31
|
-
url = Cop::Documentation.url_for(cop
|
|
31
|
+
url = Cop::Documentation.url_for(cop, @config)
|
|
32
32
|
puts url if url
|
|
33
33
|
end
|
|
34
34
|
|
|
@@ -38,10 +38,6 @@ module RuboCop
|
|
|
38
38
|
def cops_array
|
|
39
39
|
@cops_array ||= @options[:show_docs_url]
|
|
40
40
|
end
|
|
41
|
-
|
|
42
|
-
def registry_hash
|
|
43
|
-
@registry_hash ||= Cop::Registry.global.to_h
|
|
44
|
-
end
|
|
45
41
|
end
|
|
46
42
|
end
|
|
47
43
|
end
|
|
@@ -60,7 +60,7 @@ module RuboCop
|
|
|
60
60
|
def print_opt_out_instruction
|
|
61
61
|
puts
|
|
62
62
|
puts 'You can opt out of this message by adding the following to your config ' \
|
|
63
|
-
'(see https://docs.rubocop.org/rubocop/
|
|
63
|
+
'(see https://docs.rubocop.org/rubocop/plugins.html#plugin-suggestions ' \
|
|
64
64
|
'for more options):'
|
|
65
65
|
puts ' AllCops:'
|
|
66
66
|
puts ' SuggestExtensions: false'
|
data/lib/rubocop/cli.rb
CHANGED
|
@@ -13,7 +13,7 @@ module RuboCop
|
|
|
13
13
|
DEFAULT_PARALLEL_OPTIONS = %i[
|
|
14
14
|
color config debug display_style_guide display_time display_only_fail_level_offenses
|
|
15
15
|
display_only_failed editor_mode except extra_details fail_level fix_layout format formatters
|
|
16
|
-
ignore_disable_comments lint only only_guide_cops require safe
|
|
16
|
+
ignore_disable_comments lint only only_guide_cops out require safe
|
|
17
17
|
autocorrect safe_autocorrect autocorrect_all
|
|
18
18
|
].freeze
|
|
19
19
|
|
|
@@ -200,18 +200,15 @@ module RuboCop
|
|
|
200
200
|
RuboCop::LSP.enable if @options[:editor_mode]
|
|
201
201
|
end
|
|
202
202
|
|
|
203
|
-
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
204
203
|
def handle_exiting_options
|
|
205
204
|
return unless Options::EXITING_OPTIONS.any? { |o| @options.key? o }
|
|
206
205
|
|
|
207
206
|
run_command(:version) if @options[:version] || @options[:verbose_version]
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
run_command(:mcp) if @options[:mcp]
|
|
207
|
+
%i[show_cops list_enabled_cops_for show_docs_url lsp mcp].each do |name|
|
|
208
|
+
run_command(name) if @options[name]
|
|
209
|
+
end
|
|
212
210
|
raise Finished
|
|
213
211
|
end
|
|
214
|
-
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
215
212
|
|
|
216
213
|
def apply_default_formatter
|
|
217
214
|
# This must be done after the options have already been processed,
|
|
@@ -95,7 +95,8 @@ module RuboCop
|
|
|
95
95
|
end
|
|
96
96
|
end
|
|
97
97
|
|
|
98
|
-
|
|
98
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
99
|
+
def analyze
|
|
99
100
|
return {} if @no_directives
|
|
100
101
|
|
|
101
102
|
analyses = Hash.new { |hash, key| hash[key] = CopAnalysis.new([], nil) }
|
|
@@ -103,9 +104,9 @@ module RuboCop
|
|
|
103
104
|
|
|
104
105
|
each_directive do |directive|
|
|
105
106
|
if directive.push?
|
|
106
|
-
|
|
107
|
-
@stack.push(
|
|
108
|
-
apply_push(analyses,
|
|
107
|
+
restore_point = analyses.transform_values(&:dup)
|
|
108
|
+
@stack.push(restore_point)
|
|
109
|
+
apply_push(analyses, resolve_push_cops(directive), directive.line_number)
|
|
109
110
|
elsif directive.pop?
|
|
110
111
|
pop_state(analyses, directive.line_number) if @stack.any?
|
|
111
112
|
else
|
|
@@ -121,10 +122,7 @@ module RuboCop
|
|
|
121
122
|
hash[cop_name] = cop_line_ranges(analysis)
|
|
122
123
|
end
|
|
123
124
|
end
|
|
124
|
-
|
|
125
|
-
def snapshot_cops(analyses, cop_names)
|
|
126
|
-
cop_names.to_h { |name| [name, analyses[name].dup] }
|
|
127
|
-
end
|
|
125
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
128
126
|
|
|
129
127
|
def resolve_push_cops(directive)
|
|
130
128
|
directive.push_args.transform_values do |names|
|
|
@@ -155,13 +153,12 @@ module RuboCop
|
|
|
155
153
|
end
|
|
156
154
|
|
|
157
155
|
def pop_state(analyses, line)
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
new_range =
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
analyses[cop] = CopAnalysis.new(ranges, new_start)
|
|
156
|
+
restore_point = @stack.pop
|
|
157
|
+
(restore_point.keys | analyses.keys).each do |cop|
|
|
158
|
+
current = analyses[cop]
|
|
159
|
+
new_range = current.start_line_number ? [current.start_line_number..(line - 1)] : []
|
|
160
|
+
new_start = restore_point[cop]&.start_line_number ? line : nil
|
|
161
|
+
analyses[cop] = CopAnalysis.new(current.line_ranges + new_range, new_start)
|
|
165
162
|
end
|
|
166
163
|
end
|
|
167
164
|
|
data/lib/rubocop/config.rb
CHANGED
|
@@ -217,6 +217,9 @@ module RuboCop
|
|
|
217
217
|
for_all_cops['StringLiteralsFrozenByDefault']
|
|
218
218
|
end
|
|
219
219
|
|
|
220
|
+
# Returns true if the file matches any include pattern. If a block is given, the block is called
|
|
221
|
+
# to determine if the pattern is relevant (true returned by the block) or should be skipped
|
|
222
|
+
# (false returned).
|
|
220
223
|
def file_to_include?(file)
|
|
221
224
|
relative_file_path = path_relative_to_config(file)
|
|
222
225
|
|
|
@@ -228,11 +231,9 @@ module RuboCop
|
|
|
228
231
|
absolute_file_path = File.expand_path(file)
|
|
229
232
|
|
|
230
233
|
patterns_to_include.any? do |pattern|
|
|
231
|
-
if block_given?
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
match_path?(pattern, relative_file_path) || match_path?(pattern, absolute_file_path)
|
|
235
|
-
end
|
|
234
|
+
next if block_given? && !yield(pattern)
|
|
235
|
+
|
|
236
|
+
match_relative_or_absolute_path?(pattern, relative_file_path, absolute_file_path)
|
|
236
237
|
end
|
|
237
238
|
end
|
|
238
239
|
|
|
@@ -242,10 +243,7 @@ module RuboCop
|
|
|
242
243
|
# `bundler-console` conveys `Bundler::Console`).
|
|
243
244
|
return true if File.extname(file) == '.gemspec'
|
|
244
245
|
|
|
245
|
-
file_to_include?(file)
|
|
246
|
-
/[A-Z]/.match?(pattern.to_s) &&
|
|
247
|
-
(match_path?(pattern, relative_path) || match_path?(pattern, absolute_path))
|
|
248
|
-
end
|
|
246
|
+
file_to_include?(file) { |pattern| /[A-Z]/.match?(pattern.to_s) }
|
|
249
247
|
end
|
|
250
248
|
|
|
251
249
|
# Returns true if there's a chance that an Include pattern matches hidden
|
|
@@ -345,6 +343,12 @@ module RuboCop
|
|
|
345
343
|
|
|
346
344
|
private
|
|
347
345
|
|
|
346
|
+
def match_relative_or_absolute_path?(pattern, relative_file_path, absolute_file_path)
|
|
347
|
+
should_use_absolute_path = absolute?(pattern.to_s) || pattern.to_s.start_with?('..') ||
|
|
348
|
+
relative_file_path.start_with?('..')
|
|
349
|
+
match_path?(pattern, should_use_absolute_path ? absolute_file_path : relative_file_path)
|
|
350
|
+
end
|
|
351
|
+
|
|
348
352
|
# @return [Float, nil] The Rails version as a `major.minor` Float.
|
|
349
353
|
def target_rails_version_from_bundler_lock_file
|
|
350
354
|
@target_rails_version_from_bundler_lock_file ||= read_rails_version_from_bundler_lock_file
|
|
@@ -45,6 +45,7 @@ module RuboCop
|
|
|
45
45
|
base_config.each do |k, v|
|
|
46
46
|
next unless v.is_a?(Hash)
|
|
47
47
|
|
|
48
|
+
only_base_has_include = v.key?('Include') && !hash.dig(k, 'Include')
|
|
48
49
|
if hash.key?(k)
|
|
49
50
|
v = merge(v, hash[k],
|
|
50
51
|
cop_name: k, file: file, debug: debug,
|
|
@@ -52,7 +53,7 @@ module RuboCop
|
|
|
52
53
|
inherit_mode: determine_inherit_mode(hash, k))
|
|
53
54
|
end
|
|
54
55
|
hash[k] = v
|
|
55
|
-
fix_include_paths(base_config.loaded_path, hash, path, k, v) if
|
|
56
|
+
fix_include_paths(base_config.loaded_path, hash, path, k, v) if only_base_has_include
|
|
56
57
|
end
|
|
57
58
|
end
|
|
58
59
|
end
|
|
@@ -50,7 +50,8 @@ module RuboCop
|
|
|
50
50
|
|
|
51
51
|
def disable_offense(offense_range)
|
|
52
52
|
unbreakable_range = multiline_ranges(offense_range)&.find do |range|
|
|
53
|
-
|
|
53
|
+
offense_range.overlaps?(range) &&
|
|
54
|
+
eol_comment_would_be_inside_literal?(offense_range, range)
|
|
54
55
|
end
|
|
55
56
|
|
|
56
57
|
if unbreakable_range
|
|
@@ -59,11 +59,7 @@ module RuboCop
|
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
def content_if_comment_present(corrector, node)
|
|
62
|
-
|
|
63
|
-
children(node).last.source_range,
|
|
64
|
-
side: :right
|
|
65
|
-
).end.resize(1)
|
|
66
|
-
if range.source == '#'
|
|
62
|
+
if processed_source.comment_at_line(children(node).last.last_line)
|
|
67
63
|
select_content_to_be_inserted_after_last_element(corrector, node)
|
|
68
64
|
else
|
|
69
65
|
node.loc.end.source
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop # rubocop:disable Style/Documentation
|
|
5
|
+
# Autoloads corrector classes used by cops. Classes are autoloaded to reduce the number of
|
|
6
|
+
# required classes because they're referenced only when autocorrection is performed.
|
|
7
|
+
|
|
8
|
+
# rubocop:disable Layout/LineLength
|
|
9
|
+
autoload :AlignmentCorrector, 'rubocop/cop/correctors/alignment_corrector'
|
|
10
|
+
autoload :ConditionCorrector, 'rubocop/cop/correctors/condition_corrector'
|
|
11
|
+
autoload :EachToForCorrector, 'rubocop/cop/correctors/each_to_for_corrector'
|
|
12
|
+
autoload :EmptyLineCorrector, 'rubocop/cop/correctors/empty_line_corrector'
|
|
13
|
+
autoload :ForToEachCorrector, 'rubocop/cop/correctors/for_to_each_corrector'
|
|
14
|
+
autoload :IfThenCorrector, 'rubocop/cop/correctors/if_then_corrector'
|
|
15
|
+
autoload :LambdaLiteralToMethodCorrector, 'rubocop/cop/correctors/lambda_literal_to_method_corrector'
|
|
16
|
+
autoload :LineBreakCorrector, 'rubocop/cop/correctors/line_break_corrector'
|
|
17
|
+
autoload :MultilineLiteralBraceCorrector, 'rubocop/cop/correctors/multiline_literal_brace_corrector'
|
|
18
|
+
autoload :OrderedGemCorrector, 'rubocop/cop/correctors/ordered_gem_corrector'
|
|
19
|
+
autoload :ParenthesesCorrector, 'rubocop/cop/correctors/parentheses_corrector'
|
|
20
|
+
autoload :PercentLiteralCorrector, 'rubocop/cop/correctors/percent_literal_corrector'
|
|
21
|
+
autoload :PunctuationCorrector, 'rubocop/cop/correctors/punctuation_corrector'
|
|
22
|
+
autoload :RequireLibraryCorrector, 'rubocop/cop/correctors/require_library_corrector'
|
|
23
|
+
autoload :SpaceCorrector, 'rubocop/cop/correctors/space_corrector'
|
|
24
|
+
autoload :StringLiteralCorrector, 'rubocop/cop/correctors/string_literal_corrector'
|
|
25
|
+
autoload :UnusedArgCorrector, 'rubocop/cop/correctors/unused_arg_corrector'
|
|
26
|
+
# rubocop:enable Layout/LineLength
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -55,10 +55,9 @@ module RuboCop
|
|
|
55
55
|
|
|
56
56
|
# @api private
|
|
57
57
|
def builtin?(cop_class)
|
|
58
|
-
|
|
59
|
-
return false unless (m = cop_class.instance_methods(false).first)
|
|
58
|
+
return false unless (name = cop_class.name)
|
|
60
59
|
|
|
61
|
-
path, _line =
|
|
60
|
+
path, _line = Module.const_source_location(name)
|
|
62
61
|
path.start_with?(__dir__)
|
|
63
62
|
end
|
|
64
63
|
end
|
|
@@ -4,16 +4,42 @@ module RuboCop
|
|
|
4
4
|
# Allows specified configuration options to have an exclude limit
|
|
5
5
|
# ie. a maximum value tracked that it can be used by `--auto-gen-config`.
|
|
6
6
|
module ExcludeLimit
|
|
7
|
+
class << self
|
|
8
|
+
attr_accessor :tmp_dir
|
|
9
|
+
|
|
10
|
+
# Reads the aggregated exclude limit values for a cop from tmp files.
|
|
11
|
+
# Returns a hash like { 'Max' => 81 } or an empty hash if no values were written.
|
|
12
|
+
def read_limits(cop_name)
|
|
13
|
+
cop_dir = cop_dir_for(cop_name)
|
|
14
|
+
return {} unless cop_dir&.directory?
|
|
15
|
+
|
|
16
|
+
limits = {}
|
|
17
|
+
cop_dir.children.each do |filepath|
|
|
18
|
+
next unless filepath.file?
|
|
19
|
+
|
|
20
|
+
values = filepath.readlines.map(&:to_i)
|
|
21
|
+
limits[filepath.basename.to_s] = values.max unless values.empty?
|
|
22
|
+
end
|
|
23
|
+
limits
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Returns the tmp directory path for a given cop, or nil if tmp_dir is not set.
|
|
27
|
+
def cop_dir_for(cop_name)
|
|
28
|
+
tmp_dir&.join(cop_name.tr('/', '-'))
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
7
32
|
# Sets up a configuration option to have an exclude limit tracked.
|
|
8
33
|
# The parameter name given is transformed into a method name (eg. `Max`
|
|
9
34
|
# becomes `self.max=` and `MinDigits` becomes `self.min_digits=`).
|
|
10
35
|
def exclude_limit(parameter_name, method_name: transform(parameter_name))
|
|
11
36
|
define_method(:"#{method_name}=") do |value|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
37
|
+
cop_dir = RuboCop::ExcludeLimit.cop_dir_for(self.class.badge.to_s)
|
|
38
|
+
return unless cop_dir
|
|
39
|
+
|
|
40
|
+
cop_dir.mkpath
|
|
41
|
+
filepath = cop_dir.join(parameter_name)
|
|
42
|
+
filepath.write("#{value}\n", mode: 'a')
|
|
17
43
|
end
|
|
18
44
|
end
|
|
19
45
|
|
|
@@ -70,7 +70,7 @@ module RuboCop
|
|
|
70
70
|
def_node_matcher :metadata, <<~PATTERN
|
|
71
71
|
`{
|
|
72
72
|
(send _ :metadata= $_)
|
|
73
|
-
(send (send _ :metadata) :[]= (str "rubygems_mfa_required") $_)
|
|
73
|
+
(send (send _ :metadata) :[]= {(str "rubygems_mfa_required") (sym :rubygems_mfa_required)} $_)
|
|
74
74
|
}
|
|
75
75
|
PATTERN
|
|
76
76
|
|
|
@@ -78,13 +78,13 @@ module RuboCop
|
|
|
78
78
|
def_node_search :metadata_assignment, <<~PATTERN
|
|
79
79
|
`{
|
|
80
80
|
(send _ :metadata= _)
|
|
81
|
-
(send (send _ :metadata) :[]=
|
|
81
|
+
(send (send _ :metadata) :[]= {str sym} _)
|
|
82
82
|
}
|
|
83
83
|
PATTERN
|
|
84
84
|
|
|
85
85
|
# @!method rubygems_mfa_required(node)
|
|
86
86
|
def_node_search :rubygems_mfa_required, <<~PATTERN
|
|
87
|
-
(pair (str "rubygems_mfa_required") $_)
|
|
87
|
+
(pair {(str "rubygems_mfa_required") (sym :rubygems_mfa_required)} $_)
|
|
88
88
|
PATTERN
|
|
89
89
|
|
|
90
90
|
# @!method true_string?(node)
|
|
@@ -111,7 +111,7 @@ module RuboCop
|
|
|
111
111
|
def contains_guard_clause?(node)
|
|
112
112
|
return false unless (branch = node.if_branch)
|
|
113
113
|
|
|
114
|
-
guard_clause_branch?(branch)
|
|
114
|
+
branch.guard_clause? || guard_clause_branch?(branch)
|
|
115
115
|
end
|
|
116
116
|
|
|
117
117
|
def next_line_empty_or_allowed_directive_comment?(line)
|
|
@@ -123,6 +123,7 @@ module RuboCop
|
|
|
123
123
|
AlignmentCorrector.align_end(corrector, processed_source, node, alignment_node(node))
|
|
124
124
|
end
|
|
125
125
|
|
|
126
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
|
126
127
|
def check_assignment(node, rhs)
|
|
127
128
|
# If there are method calls chained to the right hand side of the
|
|
128
129
|
# assignment, we let rhs be the receiver of those method calls before
|
|
@@ -131,13 +132,14 @@ module RuboCop
|
|
|
131
132
|
|
|
132
133
|
# If `rhs` is a `begin` node or a logical operator,
|
|
133
134
|
# unwrap to find the leading conditional.
|
|
134
|
-
rhs = rhs.child_nodes.first while rhs
|
|
135
|
+
rhs = rhs.child_nodes.first while rhs&.type?(:begin, :or, :and)
|
|
135
136
|
|
|
136
|
-
return unless rhs
|
|
137
|
+
return unless rhs&.conditional?
|
|
137
138
|
return if rhs.if_type? && rhs.ternary?
|
|
138
139
|
|
|
139
140
|
check_asgn_alignment(node, rhs)
|
|
140
141
|
end
|
|
142
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
|
141
143
|
|
|
142
144
|
def check_asgn_alignment(outer_node, inner_node)
|
|
143
145
|
align_with = {
|
|
@@ -406,9 +406,11 @@ module RuboCop
|
|
|
406
406
|
end
|
|
407
407
|
|
|
408
408
|
def string_delimiter(node)
|
|
409
|
-
delimiter = node.loc
|
|
410
|
-
|
|
411
|
-
|
|
409
|
+
delimiter = if node.loc?(:begin)
|
|
410
|
+
node.loc.begin
|
|
411
|
+
elsif node.parent&.dstr_type? && node.parent.loc?(:begin)
|
|
412
|
+
node.parent.loc.begin
|
|
413
|
+
end&.source
|
|
412
414
|
|
|
413
415
|
delimiter if %w[' "].include?(delimiter)
|
|
414
416
|
end
|
|
@@ -158,7 +158,7 @@ module RuboCop
|
|
|
158
158
|
@base = find_hash_pair_alignment_base(node)
|
|
159
159
|
return false if !@base && inside_multiline_chain_arg?(node)
|
|
160
160
|
|
|
161
|
-
@base ||= lhs.source_range
|
|
161
|
+
@base ||= first_dot_alignment_base(node, rhs) || lhs.source_range
|
|
162
162
|
return if aligned_with_first_line_dot?(node, rhs)
|
|
163
163
|
|
|
164
164
|
calculate_column_delta_offense(rhs, @base.column)
|
|
@@ -172,6 +172,31 @@ module RuboCop
|
|
|
172
172
|
first_call.loc.dot.join(first_call.loc.selector)
|
|
173
173
|
end
|
|
174
174
|
|
|
175
|
+
def first_dot_alignment_base(node, rhs)
|
|
176
|
+
return unless rhs.source.start_with?('.', '&.')
|
|
177
|
+
|
|
178
|
+
first_call = first_call_has_a_dot(node)
|
|
179
|
+
dot = first_call.loc.dot
|
|
180
|
+
return unless dot
|
|
181
|
+
return if first_call == node
|
|
182
|
+
|
|
183
|
+
after_block_base = after_multiline_block_base(first_call, node)
|
|
184
|
+
return after_block_base if after_block_base
|
|
185
|
+
|
|
186
|
+
return unless same_line?(dot, first_call.receiver.source_range)
|
|
187
|
+
|
|
188
|
+
dot.join(first_call.loc.selector)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def after_multiline_block_base(first_call, node)
|
|
192
|
+
return unless first_call.block_node&.multiline?
|
|
193
|
+
|
|
194
|
+
after_block = first_call.block_node.parent
|
|
195
|
+
return unless after_block&.call_type? && after_block.loc?(:dot) && after_block != node
|
|
196
|
+
|
|
197
|
+
after_block.loc.dot.join(after_block.loc.selector)
|
|
198
|
+
end
|
|
199
|
+
|
|
175
200
|
def inside_multiline_chain_arg?(node)
|
|
176
201
|
enclosing_call = find_enclosing_chain_call(node)
|
|
177
202
|
return false unless enclosing_call
|
|
@@ -308,7 +308,7 @@ module RuboCop
|
|
|
308
308
|
def anonymous_class_block(node)
|
|
309
309
|
first_block = node.each_ancestor(:block).first
|
|
310
310
|
return unless class_or_module_new_block?(first_block)
|
|
311
|
-
return if first_block.parent&.type?(:lvasgn
|
|
311
|
+
return if first_block.parent&.type?(:lvasgn)
|
|
312
312
|
return if node.each_ancestor(:sclass).any? { |s| !s.children.first.self_type? }
|
|
313
313
|
|
|
314
314
|
first_block
|
|
@@ -316,15 +316,20 @@ module RuboCop
|
|
|
316
316
|
|
|
317
317
|
def anon_block_scope_id(anon_block)
|
|
318
318
|
parent = anon_block.parent
|
|
319
|
-
return unless parent&.
|
|
319
|
+
return unless parent&.type?(:any_block, :begin, :call, :casgn, :any_def)
|
|
320
320
|
|
|
321
|
-
if parent
|
|
322
|
-
"#{
|
|
323
|
-
|
|
321
|
+
if (receiver = named_receiver(parent))
|
|
322
|
+
"#{receiver.source}.#{parent.method_name}"
|
|
323
|
+
elsif !parent.begin_type? || parent.parent&.any_block_type?
|
|
324
324
|
source_location(anon_block)
|
|
325
325
|
end
|
|
326
326
|
end
|
|
327
327
|
|
|
328
|
+
def named_receiver(node)
|
|
329
|
+
receiver = node.receiver
|
|
330
|
+
receiver unless class_or_module_new_block?(receiver)
|
|
331
|
+
end
|
|
332
|
+
|
|
328
333
|
def found_sclass_method(node, name)
|
|
329
334
|
singleton_ancestor = node.each_ancestor.find(&:sclass_type?)
|
|
330
335
|
return unless singleton_ancestor
|
|
@@ -63,19 +63,9 @@ module RuboCop
|
|
|
63
63
|
end
|
|
64
64
|
|
|
65
65
|
def spaces_before_left_parenthesis(node)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
else
|
|
70
|
-
0
|
|
71
|
-
end
|
|
72
|
-
without_receiver = node.source[receiver_length..]
|
|
73
|
-
|
|
74
|
-
# Escape question mark if any.
|
|
75
|
-
method_regexp = Regexp.escape(node.method_name)
|
|
76
|
-
|
|
77
|
-
match = without_receiver.match(/^\s*&?\.?\s*#{method_regexp}(\s+)\(/)
|
|
78
|
-
match ? match.captures[0].length : 0
|
|
66
|
+
return 0 if node.parenthesized?
|
|
67
|
+
|
|
68
|
+
node.first_argument.source_range.begin_pos - node.loc.selector.end_pos
|
|
79
69
|
end
|
|
80
70
|
|
|
81
71
|
def space_range(expr, space_length)
|