rubocop 1.66.1 → 1.67.0
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 +15 -6
- data/config/internal_affairs.yml +11 -0
- data/lib/rubocop/cli/command/auto_generate_config.rb +6 -7
- data/lib/rubocop/cli/command/lsp.rb +2 -2
- data/lib/rubocop/config_loader_resolver.rb +3 -3
- data/lib/rubocop/config_validator.rb +2 -1
- data/lib/rubocop/cop/base.rb +6 -2
- data/lib/rubocop/cop/bundler/gem_version.rb +1 -0
- data/lib/rubocop/cop/cop.rb +8 -0
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/cop_description.rb +0 -4
- data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +6 -21
- data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +8 -1
- data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +0 -5
- data/lib/rubocop/cop/internal_affairs.rb +16 -0
- data/lib/rubocop/cop/layout/access_modifier_indentation.rb +5 -1
- data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +1 -1
- data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +8 -0
- data/lib/rubocop/cop/layout/indentation_width.rb +4 -5
- data/lib/rubocop/cop/layout/leading_comment_space.rb +28 -1
- data/lib/rubocop/cop/lint/ambiguous_range.rb +4 -1
- data/lib/rubocop/cop/lint/big_decimal_new.rb +4 -7
- data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_set_element.rb +74 -0
- data/lib/rubocop/cop/lint/ensure_return.rb +0 -3
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -1
- data/lib/rubocop/cop/lint/float_comparison.rb +1 -1
- data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +10 -4
- data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +5 -14
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +25 -2
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +5 -6
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +1 -1
- data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +105 -41
- data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/uri_regexp.rb +25 -7
- data/lib/rubocop/cop/mixin/percent_array.rb +1 -1
- data/lib/rubocop/cop/mixin/statement_modifier.rb +3 -2
- data/lib/rubocop/cop/naming/inclusive_language.rb +12 -3
- data/lib/rubocop/cop/naming/predicate_name.rb +1 -1
- data/lib/rubocop/cop/offense.rb +2 -2
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +12 -2
- data/lib/rubocop/cop/style/accessor_grouping.rb +10 -2
- data/lib/rubocop/cop/style/arguments_forwarding.rb +46 -6
- data/lib/rubocop/cop/style/block_delimiters.rb +14 -1
- data/lib/rubocop/cop/style/collection_compact.rb +10 -10
- data/lib/rubocop/cop/style/combinable_loops.rb +7 -0
- data/lib/rubocop/cop/style/commented_keyword.rb +7 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +1 -1
- data/lib/rubocop/cop/style/data_inheritance.rb +1 -1
- data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
- data/lib/rubocop/cop/style/guard_clause.rb +1 -1
- data/lib/rubocop/cop/style/hash_each_methods.rb +6 -0
- data/lib/rubocop/cop/style/hash_syntax.rb +2 -2
- data/lib/rubocop/cop/style/if_inside_else.rb +1 -1
- data/lib/rubocop/cop/style/if_with_semicolon.rb +7 -3
- data/lib/rubocop/cop/style/lambda.rb +1 -1
- data/lib/rubocop/cop/style/map_into_array.rb +53 -7
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +12 -7
- data/lib/rubocop/cop/style/multiline_memoization.rb +1 -1
- data/lib/rubocop/cop/style/nested_modifier.rb +1 -1
- data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
- data/lib/rubocop/cop/style/one_line_conditional.rb +4 -0
- data/lib/rubocop/cop/style/operator_method_call.rb +25 -6
- data/lib/rubocop/cop/style/redundant_begin.rb +4 -0
- data/lib/rubocop/cop/style/redundant_condition.rb +1 -1
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +3 -3
- data/lib/rubocop/cop/style/redundant_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/require_order.rb +1 -1
- data/lib/rubocop/cop/style/rescue_modifier.rb +13 -1
- data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +54 -12
- data/lib/rubocop/cop/style/safe_navigation.rb +92 -50
- data/lib/rubocop/cop/style/select_by_regexp.rb +9 -6
- data/lib/rubocop/cop/style/semicolon.rb +1 -1
- data/lib/rubocop/cop/style/struct_inheritance.rb +1 -1
- data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
- data/lib/rubocop/cop/team.rb +8 -1
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/cops_documentation_generator.rb +73 -34
- data/lib/rubocop/file_finder.rb +9 -4
- data/lib/rubocop/lsp/runtime.rb +2 -0
- data/lib/rubocop/lsp/server.rb +0 -1
- data/lib/rubocop/rspec/expect_offense.rb +1 -0
- data/lib/rubocop/runner.rb +3 -0
- data/lib/rubocop/server/cache.rb +6 -1
- data/lib/rubocop/server/core.rb +1 -0
- data/lib/rubocop/target_ruby.rb +12 -12
- data/lib/rubocop/version.rb +3 -1
- data/lib/rubocop/yaml_duplication_checker.rb +20 -27
- data/lib/rubocop.rb +2 -0
- metadata +10 -8
@@ -6,14 +6,38 @@ require 'fileutils'
|
|
6
6
|
# @api private
|
7
7
|
class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
8
8
|
include ::RuboCop::Cop::Documentation
|
9
|
+
CopData = Struct.new(
|
10
|
+
:cop, :description, :example_objects, :safety_objects, :see_objects, :config, keyword_init: true
|
11
|
+
)
|
12
|
+
|
13
|
+
STRUCTURE = {
|
14
|
+
name: ->(data) { cop_header(data.cop) },
|
15
|
+
required_ruby_version: ->(data) { required_ruby_version(data.cop) },
|
16
|
+
properties: ->(data) { properties(data.cop) },
|
17
|
+
description: ->(data) { "#{data.description}\n" },
|
18
|
+
safety: ->(data) { safety_object(data.safety_objects, data.cop) },
|
19
|
+
examples: ->(data) { examples(data.example_objects, data.cop) },
|
20
|
+
configuration: ->(data) { configurations(data.cop.department, data.config, data.cop) },
|
21
|
+
references: ->(data) { references(data.cop, data.see_objects) }
|
22
|
+
}.freeze
|
23
|
+
|
9
24
|
# This class will only generate documentation for cops that belong to one of
|
10
25
|
# the departments given in the `departments` array. E.g. if we only wanted
|
11
26
|
# documentation for Lint cops:
|
12
27
|
#
|
13
28
|
# CopsDocumentationGenerator.new(departments: ['Lint']).call
|
14
29
|
#
|
15
|
-
|
30
|
+
# You can append additional information:
|
31
|
+
#
|
32
|
+
# callback = ->(data) { required_rails_version(data.cop) }
|
33
|
+
# CopsDocumentationGenerator.new(extra_info: { ruby_version: callback }).call
|
34
|
+
#
|
35
|
+
# This will insert the string returned from the lambda _after_ the section from RuboCop itself.
|
36
|
+
# See `CopsDocumentationGenerator::STRUCTURE` for available sections.
|
37
|
+
#
|
38
|
+
def initialize(departments: [], extra_info: {})
|
16
39
|
@departments = departments.map(&:to_sym).sort!
|
40
|
+
@extra_info = extra_info
|
17
41
|
@cops = RuboCop::Cop::Registry.global
|
18
42
|
@config = RuboCop::ConfigLoader.default_configuration
|
19
43
|
@docs_path = "#{Dir.pwd}/docs/modules/ROOT/pages/"
|
@@ -37,24 +61,21 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
37
61
|
cops.with_department(department).sort!
|
38
62
|
end
|
39
63
|
|
40
|
-
def cops_body(
|
41
|
-
check_examples_to_have_the_default_enforced_style!(
|
42
|
-
|
43
|
-
content =
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
content << examples(examples_objects) if examples_objects.any?
|
49
|
-
content << configurations(cop.department, pars)
|
50
|
-
content << references(cop, see_objects)
|
64
|
+
def cops_body(data)
|
65
|
+
check_examples_to_have_the_default_enforced_style!(data.example_objects, data.cop)
|
66
|
+
|
67
|
+
content = +''
|
68
|
+
STRUCTURE.each do |section, block|
|
69
|
+
content << instance_exec(data, &block)
|
70
|
+
content << @extra_info[section].call(data) if @extra_info[section]
|
71
|
+
end
|
51
72
|
content
|
52
73
|
end
|
53
74
|
|
54
|
-
def check_examples_to_have_the_default_enforced_style!(
|
55
|
-
return if
|
75
|
+
def check_examples_to_have_the_default_enforced_style!(example_objects, cop)
|
76
|
+
return if example_objects.none?
|
56
77
|
|
57
|
-
examples_describing_enforced_style =
|
78
|
+
examples_describing_enforced_style = example_objects.map(&:name).grep(/EnforcedStyle:/)
|
58
79
|
return if examples_describing_enforced_style.none?
|
59
80
|
|
60
81
|
if examples_describing_enforced_style.index { |name| name.match?('default') }.nonzero?
|
@@ -66,16 +87,20 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
66
87
|
raise "Specify the default EnforcedStyle for #{cop.cop_name}"
|
67
88
|
end
|
68
89
|
|
69
|
-
def examples(
|
70
|
-
|
90
|
+
def examples(example_objects, cop)
|
91
|
+
return '' if example_objects.none?
|
92
|
+
|
93
|
+
example_objects.each_with_object(cop_subsection('Examples', cop).dup) do |example, content|
|
71
94
|
content << "\n" unless content.end_with?("\n\n")
|
72
|
-
content <<
|
95
|
+
content << example_header(example.name, cop) unless example.name == ''
|
73
96
|
content << code_example(example)
|
74
97
|
end
|
75
98
|
end
|
76
99
|
|
77
|
-
def safety_object(
|
78
|
-
|
100
|
+
def safety_object(safety_objects, cop)
|
101
|
+
return '' if safety_objects.all? { |s| s.text.blank? }
|
102
|
+
|
103
|
+
safety_objects.each_with_object(cop_subsection('Safety', cop).dup) do |safety_object, content|
|
79
104
|
next if safety_object.text.blank?
|
80
105
|
|
81
106
|
content << "\n" unless content.end_with?("\n\n")
|
@@ -115,22 +140,25 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
115
140
|
end
|
116
141
|
# rubocop:enable Metrics/MethodLength
|
117
142
|
|
118
|
-
def
|
143
|
+
def cop_header(cop)
|
119
144
|
content = +"\n"
|
120
|
-
content << "
|
145
|
+
content << "[##{to_anchor(cop.cop_name)}]\n"
|
146
|
+
content << "== #{cop.cop_name}\n"
|
121
147
|
content << "\n"
|
122
148
|
content
|
123
149
|
end
|
124
150
|
|
125
|
-
def
|
151
|
+
def cop_subsection(title, cop)
|
126
152
|
content = +"\n"
|
153
|
+
content << "[##{to_anchor(title)}-#{to_anchor(cop.cop_name)}]\n"
|
127
154
|
content << "=== #{title}\n"
|
128
155
|
content << "\n"
|
129
156
|
content
|
130
157
|
end
|
131
158
|
|
132
|
-
def
|
133
|
-
content =
|
159
|
+
def example_header(title, cop)
|
160
|
+
content = "[##{to_anchor(title)}-#{to_anchor(cop.cop_name)}]\n"
|
161
|
+
content << +"==== #{title}\n"
|
134
162
|
content << "\n"
|
135
163
|
content
|
136
164
|
end
|
@@ -142,7 +170,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
142
170
|
content
|
143
171
|
end
|
144
172
|
|
145
|
-
def configurations(department, pars)
|
173
|
+
def configurations(department, pars, cop)
|
146
174
|
return '' if pars.empty?
|
147
175
|
|
148
176
|
header = ['Name', 'Default value', 'Configurable values']
|
@@ -157,7 +185,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
157
185
|
[configuration_name(department, name), default, configurable]
|
158
186
|
end
|
159
187
|
|
160
|
-
|
188
|
+
cop_subsection('Configurable attributes', cop) + to_table(header, content)
|
161
189
|
end
|
162
190
|
|
163
191
|
def configuration_name(department, name)
|
@@ -235,7 +263,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
235
263
|
urls = RuboCop::Cop::MessageAnnotator.new(config, cop.name, cop_config, {}).urls
|
236
264
|
return '' if urls.empty? && see_objects.empty?
|
237
265
|
|
238
|
-
content =
|
266
|
+
content = cop_subsection('References', cop)
|
239
267
|
content << urls.map { |url| "* #{url}" }.join("\n")
|
240
268
|
content << "\n" unless urls.empty?
|
241
269
|
content << see_objects.map { |see| "* #{see.name}" }.join("\n")
|
@@ -283,14 +311,16 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
283
311
|
]
|
284
312
|
pars = cop_config.reject { |k| non_display_keys.include? k }
|
285
313
|
description = 'No documentation'
|
286
|
-
|
314
|
+
example_objects = safety_objects = see_objects = []
|
287
315
|
cop_code(cop) do |code_object|
|
288
316
|
description = code_object.docstring unless code_object.docstring.blank?
|
289
|
-
|
290
|
-
|
291
|
-
|
317
|
+
example_objects = code_object.tags('example')
|
318
|
+
safety_objects = code_object.tags('safety')
|
319
|
+
see_objects = code_object.tags('see')
|
292
320
|
end
|
293
|
-
|
321
|
+
data = CopData.new(cop: cop, description: description, example_objects: example_objects,
|
322
|
+
safety_objects: safety_objects, see_objects: see_objects, config: pars)
|
323
|
+
cops_body(data)
|
294
324
|
end
|
295
325
|
|
296
326
|
def cop_code(cop)
|
@@ -306,7 +336,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
306
336
|
filename = "#{department_to_basename(department)}.adoc"
|
307
337
|
content = +"=== Department xref:#{filename}[#{type_title}]\n\n"
|
308
338
|
cops_of_department(department).each do |cop|
|
309
|
-
anchor = cop.cop_name
|
339
|
+
anchor = to_anchor(cop.cop_name)
|
310
340
|
content << "* xref:#{filename}##{anchor}[#{cop.cop_name}]\n"
|
311
341
|
end
|
312
342
|
|
@@ -338,4 +368,13 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
338
368
|
|
339
369
|
status == 'pending' ? 'Pending' : 'Enabled'
|
340
370
|
end
|
371
|
+
|
372
|
+
# HTML anchor are somewhat limited in what characters they can contain, just
|
373
|
+
# accept a known-good subset. As long as it's consistent it doesn't matter.
|
374
|
+
#
|
375
|
+
# Style/AccessModifierDeclarations => styleaccessmodifierdeclarations
|
376
|
+
# OnlyFor: [] (default) => onlyfor_-__-_default_
|
377
|
+
def to_anchor(title)
|
378
|
+
title.delete('/').tr(' ', '-').gsub(/[^a-zA-Z0-9-]/, '_').downcase
|
379
|
+
end
|
341
380
|
end
|
data/lib/rubocop/file_finder.rb
CHANGED
@@ -23,15 +23,20 @@ module RuboCop
|
|
23
23
|
last_file
|
24
24
|
end
|
25
25
|
|
26
|
+
def traverse_directories_upwards(start_dir, stop_dir = nil)
|
27
|
+
Pathname.new(start_dir).expand_path.ascend do |dir|
|
28
|
+
yield(dir)
|
29
|
+
dir = dir.to_s
|
30
|
+
break if dir == stop_dir || dir == FileFinder.root_level
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
26
34
|
private
|
27
35
|
|
28
36
|
def traverse_files_upwards(filename, start_dir, stop_dir)
|
29
|
-
|
37
|
+
traverse_directories_upwards(start_dir, stop_dir) do |dir|
|
30
38
|
file = dir + filename
|
31
39
|
yield(file.to_s) if file.exist?
|
32
|
-
|
33
|
-
dir = dir.to_s
|
34
|
-
break if dir == stop_dir || dir == FileFinder.root_level
|
35
40
|
end
|
36
41
|
end
|
37
42
|
end
|
data/lib/rubocop/lsp/runtime.rb
CHANGED
data/lib/rubocop/lsp/server.rb
CHANGED
@@ -169,6 +169,7 @@ module RuboCop
|
|
169
169
|
raise 'Expected correction but no corrections were made' if new_source == source
|
170
170
|
|
171
171
|
expect(new_source).to eq(correction)
|
172
|
+
expect(@processed_source).to be_valid_syntax, 'Expected correction to be valid syntax'
|
172
173
|
end
|
173
174
|
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity
|
174
175
|
|
data/lib/rubocop/runner.rb
CHANGED
@@ -362,6 +362,9 @@ module RuboCop
|
|
362
362
|
self.class.ruby_extractors.find do |ruby_extractor|
|
363
363
|
result = ruby_extractor.call(processed_source)
|
364
364
|
break result if result
|
365
|
+
rescue StandardError
|
366
|
+
raise Error, "Ruby extractor #{ruby_extractor.source_location[0]} failed to process " \
|
367
|
+
"#{processed_source.path}."
|
365
368
|
end
|
366
369
|
end
|
367
370
|
|
data/lib/rubocop/server/cache.rb
CHANGED
@@ -43,13 +43,18 @@ module RuboCop
|
|
43
43
|
@project_dir_cache_key ||= project_dir[1..].tr('/', '+')
|
44
44
|
end
|
45
45
|
|
46
|
+
# rubocop:disable Metrics/AbcSize
|
46
47
|
def restart_key
|
47
48
|
lockfile_path = LOCKFILE_NAMES.map do |lockfile_name|
|
48
49
|
Pathname(project_dir).join(lockfile_name)
|
49
50
|
end.find(&:exist?)
|
51
|
+
version_data = lockfile_path&.read || RuboCop::Version::STRING
|
52
|
+
config_data = Pathname(ConfigFinder.find_config_path(Dir.pwd)).read
|
53
|
+
todo_data = (rubocop_todo = Pathname('.rubocop_todo.yml')).exist? ? rubocop_todo.read : ''
|
50
54
|
|
51
|
-
Digest::SHA1.hexdigest(
|
55
|
+
Digest::SHA1.hexdigest(version_data + config_data + todo_data)
|
52
56
|
end
|
57
|
+
# rubocop:enable Metrics/AbcSize
|
53
58
|
|
54
59
|
def dir
|
55
60
|
Pathname.new(File.join(cache_path, project_dir_cache_key)).tap do |d|
|
data/lib/rubocop/server/core.rb
CHANGED
data/lib/rubocop/target_ruby.rb
CHANGED
@@ -53,8 +53,6 @@ module RuboCop
|
|
53
53
|
class GemspecFile < Source
|
54
54
|
extend NodePattern::Macros
|
55
55
|
|
56
|
-
GEMSPEC_EXTENSION = '.gemspec'
|
57
|
-
|
58
56
|
# @!method required_ruby_version(node)
|
59
57
|
def_node_search :required_ruby_version, <<~PATTERN
|
60
58
|
(send _ :required_ruby_version= $_)
|
@@ -68,7 +66,7 @@ module RuboCop
|
|
68
66
|
PATTERN
|
69
67
|
|
70
68
|
def name
|
71
|
-
"`required_ruby_version` parameter (in #{
|
69
|
+
"`required_ruby_version` parameter (in #{gemspec_filepath})"
|
72
70
|
end
|
73
71
|
|
74
72
|
private
|
@@ -83,16 +81,18 @@ module RuboCop
|
|
83
81
|
find_minimal_known_ruby(right_hand_side)
|
84
82
|
end
|
85
83
|
|
86
|
-
def gemspec_filename
|
87
|
-
@gemspec_filename ||= begin
|
88
|
-
basename = Pathname.new(@config.base_dir_for_path_parameters).basename.to_s
|
89
|
-
"#{basename}#{GEMSPEC_EXTENSION}"
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
84
|
def gemspec_filepath
|
94
|
-
@gemspec_filepath
|
95
|
-
|
85
|
+
return @gemspec_filepath if defined?(@gemspec_filepath)
|
86
|
+
|
87
|
+
@gemspec_filepath =
|
88
|
+
@config.traverse_directories_upwards(@config.base_dir_for_path_parameters) do |dir|
|
89
|
+
# NOTE: Can't use `dir.glob` because of JRuby 9.4.8.0 incompatibility:
|
90
|
+
# https://github.com/jruby/jruby/issues/8358
|
91
|
+
candidates = Pathname.glob("#{dir}/*.gemspec")
|
92
|
+
# Bundler will use a gemspec whatever the filename is, as long as its the only one in
|
93
|
+
# the folder.
|
94
|
+
break candidates.first if candidates.one?
|
95
|
+
end
|
96
96
|
end
|
97
97
|
|
98
98
|
def version_from_gemspec_file(file)
|
data/lib/rubocop/version.rb
CHANGED
@@ -3,10 +3,11 @@
|
|
3
3
|
module RuboCop
|
4
4
|
# This module holds the RuboCop version information.
|
5
5
|
module Version
|
6
|
-
STRING = '1.
|
6
|
+
STRING = '1.67.0'
|
7
7
|
|
8
8
|
MSG = '%<version>s (using %<parser_version>s, ' \
|
9
9
|
'rubocop-ast %<rubocop_ast_version>s, ' \
|
10
|
+
'analyzing as Ruby %<target_ruby_version>s, ' \
|
10
11
|
'running on %<ruby_engine>s %<ruby_version>s)%<server_mode>s [%<ruby_platform>s]'
|
11
12
|
|
12
13
|
CANONICAL_FEATURE_NAMES = {
|
@@ -22,6 +23,7 @@ module RuboCop
|
|
22
23
|
if debug
|
23
24
|
verbose_version = format(MSG, version: STRING, parser_version: parser_version,
|
24
25
|
rubocop_ast_version: RuboCop::AST::Version::STRING,
|
26
|
+
target_ruby_version: TargetRuby.new(Config.new).version,
|
25
27
|
ruby_engine: RUBY_ENGINE, ruby_version: RUBY_VERSION,
|
26
28
|
server_mode: server_mode,
|
27
29
|
ruby_platform: RUBY_PLATFORM)
|
@@ -5,37 +5,30 @@ module RuboCop
|
|
5
5
|
# @api private
|
6
6
|
module YAMLDuplicationChecker
|
7
7
|
def self.check(yaml_string, filename, &on_duplicated)
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
YAML.parse(yaml_string, filename: filename)
|
13
|
-
else
|
14
|
-
YAML.parse(yaml_string, filename)
|
15
|
-
end
|
16
|
-
return unless tree
|
17
|
-
|
18
|
-
traverse(tree, &on_duplicated)
|
19
|
-
tree
|
8
|
+
handler = DuplicationCheckHandler.new(&on_duplicated)
|
9
|
+
parser = Psych::Parser.new(handler)
|
10
|
+
parser.parse(yaml_string, filename)
|
11
|
+
parser.handler.root.children[0]
|
20
12
|
end
|
21
13
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
yield(exist, key) if exist
|
28
|
-
keys << key
|
29
|
-
traverse(value, &on_duplicated)
|
30
|
-
end
|
31
|
-
else
|
32
|
-
children = tree.children
|
33
|
-
return unless children
|
14
|
+
class DuplicationCheckHandler < Psych::TreeBuilder # :nodoc:
|
15
|
+
def initialize(&block)
|
16
|
+
super()
|
17
|
+
@block = block
|
18
|
+
end
|
34
19
|
|
35
|
-
|
20
|
+
def end_mapping
|
21
|
+
mapping_node = super
|
22
|
+
# OPTIMIZE: Use a hash for faster lookup since there can
|
23
|
+
# be quite a few keys at the top-level.
|
24
|
+
keys = {}
|
25
|
+
mapping_node.children.each_slice(2) do |key, _value|
|
26
|
+
duplicate = keys[key.value]
|
27
|
+
@block.call(duplicate, key) if duplicate
|
28
|
+
keys[key.value] = key
|
29
|
+
end
|
30
|
+
mapping_node
|
36
31
|
end
|
37
32
|
end
|
38
|
-
|
39
|
-
private_class_method :traverse
|
40
33
|
end
|
41
34
|
end
|
data/lib/rubocop.rb
CHANGED
@@ -312,6 +312,7 @@ require_relative 'rubocop/cop/lint/duplicate_methods'
|
|
312
312
|
require_relative 'rubocop/cop/lint/duplicate_regexp_character_class_element'
|
313
313
|
require_relative 'rubocop/cop/lint/duplicate_require'
|
314
314
|
require_relative 'rubocop/cop/lint/duplicate_rescue_exception'
|
315
|
+
require_relative 'rubocop/cop/lint/duplicate_set_element'
|
315
316
|
require_relative 'rubocop/cop/lint/each_with_object_argument'
|
316
317
|
require_relative 'rubocop/cop/lint/else_layout'
|
317
318
|
require_relative 'rubocop/cop/lint/empty_block'
|
@@ -750,6 +751,7 @@ require_relative 'rubocop/config_store'
|
|
750
751
|
require_relative 'rubocop/config_validator'
|
751
752
|
require_relative 'rubocop/feature_loader'
|
752
753
|
require_relative 'rubocop/lockfile'
|
754
|
+
require_relative 'rubocop/lsp'
|
753
755
|
require_relative 'rubocop/target_finder'
|
754
756
|
require_relative 'rubocop/directive_comment'
|
755
757
|
require_relative 'rubocop/comment_config'
|
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.67.0
|
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-10-15 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: json
|
@@ -179,6 +179,7 @@ files:
|
|
179
179
|
- assets/output.css.erb
|
180
180
|
- assets/output.html.erb
|
181
181
|
- config/default.yml
|
182
|
+
- config/internal_affairs.yml
|
182
183
|
- config/obsoletion.yml
|
183
184
|
- exe/rubocop
|
184
185
|
- lib/rubocop.rb
|
@@ -425,6 +426,7 @@ files:
|
|
425
426
|
- lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb
|
426
427
|
- lib/rubocop/cop/lint/duplicate_require.rb
|
427
428
|
- lib/rubocop/cop/lint/duplicate_rescue_exception.rb
|
429
|
+
- lib/rubocop/cop/lint/duplicate_set_element.rb
|
428
430
|
- lib/rubocop/cop/lint/each_with_object_argument.rb
|
429
431
|
- lib/rubocop/cop/lint/else_layout.rb
|
430
432
|
- lib/rubocop/cop/lint/empty_block.rb
|
@@ -1017,12 +1019,12 @@ licenses:
|
|
1017
1019
|
- MIT
|
1018
1020
|
metadata:
|
1019
1021
|
homepage_uri: https://rubocop.org/
|
1020
|
-
changelog_uri: https://github.com/rubocop/rubocop/releases/tag/v1.
|
1022
|
+
changelog_uri: https://github.com/rubocop/rubocop/releases/tag/v1.67.0
|
1021
1023
|
source_code_uri: https://github.com/rubocop/rubocop/
|
1022
|
-
documentation_uri: https://docs.rubocop.org/rubocop/1.
|
1024
|
+
documentation_uri: https://docs.rubocop.org/rubocop/1.67/
|
1023
1025
|
bug_tracker_uri: https://github.com/rubocop/rubocop/issues
|
1024
1026
|
rubygems_mfa_required: 'true'
|
1025
|
-
post_install_message:
|
1027
|
+
post_install_message:
|
1026
1028
|
rdoc_options: []
|
1027
1029
|
require_paths:
|
1028
1030
|
- lib
|
@@ -1037,8 +1039,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
1037
1039
|
- !ruby/object:Gem::Version
|
1038
1040
|
version: '0'
|
1039
1041
|
requirements: []
|
1040
|
-
rubygems_version: 3.
|
1041
|
-
signing_key:
|
1042
|
+
rubygems_version: 3.3.7
|
1043
|
+
signing_key:
|
1042
1044
|
specification_version: 4
|
1043
1045
|
summary: Automatic Ruby code style checking tool.
|
1044
1046
|
test_files: []
|