rubocop 1.66.1 → 1.68.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/config/default.yml +55 -6
- data/config/internal_affairs.yml +11 -0
- data/lib/rubocop/cached_data.rb +12 -4
- data/lib/rubocop/cli/command/auto_generate_config.rb +6 -7
- data/lib/rubocop/cli/command/execute_runner.rb +1 -1
- data/lib/rubocop/cli/command/lsp.rb +2 -2
- data/lib/rubocop/cli/command/version.rb +2 -2
- data/lib/rubocop/config_loader_resolver.rb +3 -3
- data/lib/rubocop/config_validator.rb +2 -1
- data/lib/rubocop/cop/autocorrect_logic.rb +22 -2
- 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/alignment_corrector.rb +1 -12
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +10 -0
- 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 +56 -1
- data/lib/rubocop/cop/layout/space_before_brackets.rb +5 -5
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +4 -0
- 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_branch.rb +39 -4
- 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/non_atomic_file_operation.rb +7 -0
- 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_chain.rb +9 -0
- data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +107 -41
- data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +88 -0
- data/lib/rubocop/cop/lint/uri_regexp.rb +25 -7
- data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +4 -1
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +10 -0
- data/lib/rubocop/cop/mixin/endless_method_rewriter.rb +24 -0
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +3 -1
- 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/block_forwarding.rb +1 -1
- 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 +4 -5
- 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/ambiguous_endless_method_definition.rb +79 -0
- data/lib/rubocop/cop/style/arguments_forwarding.rb +46 -6
- data/lib/rubocop/cop/style/bitwise_predicate.rb +100 -0
- data/lib/rubocop/cop/style/block_delimiters.rb +31 -3
- data/lib/rubocop/cop/style/collection_compact.rb +10 -10
- data/lib/rubocop/cop/style/combinable_defined.rb +115 -0
- 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/endless_method.rb +1 -14
- data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
- data/lib/rubocop/cop/style/guard_clause.rb +15 -2
- 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/keyword_arguments_merging.rb +67 -0
- data/lib/rubocop/cop/style/lambda.rb +1 -1
- data/lib/rubocop/cop/style/map_into_array.rb +59 -8
- 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/multiple_comparison.rb +28 -39
- 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 +23 -5
- data/lib/rubocop/cop/style/redundant_parentheses.rb +9 -11
- 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 +104 -50
- data/lib/rubocop/cop/style/safe_navigation_chain_length.rb +52 -0
- 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 +26 -5
- 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/cop/variable_force/assignment.rb +18 -3
- data/lib/rubocop/cop/variable_force/branch.rb +1 -1
- data/lib/rubocop/cop/variable_force/variable.rb +5 -1
- data/lib/rubocop/cop/variable_force/variable_table.rb +2 -2
- data/lib/rubocop/cops_documentation_generator.rb +81 -40
- data/lib/rubocop/file_finder.rb +9 -4
- data/lib/rubocop/formatter/disabled_config_formatter.rb +1 -1
- 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 +17 -6
- data/lib/rubocop/server/cache.rb +6 -1
- data/lib/rubocop/server/core.rb +1 -0
- data/lib/rubocop/target_ruby.rb +13 -13
- data/lib/rubocop/version.rb +28 -7
- data/lib/rubocop/yaml_duplication_checker.rb +20 -27
- data/lib/rubocop.rb +10 -0
- metadata +13 -4
data/lib/rubocop/cop/team.rb
CHANGED
@@ -9,11 +9,17 @@ module RuboCop
|
|
9
9
|
# For performance reasons, Team will first dispatch cops & forces in two groups,
|
10
10
|
# first the ones needed for autocorrection (if any), then the rest
|
11
11
|
# (unless autocorrections happened).
|
12
|
+
# rubocop:disable Metrics/ClassLength
|
12
13
|
class Team
|
13
14
|
# @return [Team]
|
14
15
|
def self.new(cop_or_classes, config, options = {})
|
15
16
|
# Support v0 api:
|
16
|
-
|
17
|
+
if cop_or_classes.first.is_a?(Class)
|
18
|
+
warn Rainbow(<<~WARNING).yellow, uplevel: 1
|
19
|
+
`Team.new` with cop classes is deprecated. Use `Team.mobilize` instead.
|
20
|
+
WARNING
|
21
|
+
return mobilize(cop_or_classes, config, options)
|
22
|
+
end
|
17
23
|
|
18
24
|
super
|
19
25
|
end
|
@@ -279,5 +285,6 @@ module RuboCop
|
|
279
285
|
end
|
280
286
|
end
|
281
287
|
end
|
288
|
+
# rubocop:enable Metrics/ClassLength
|
282
289
|
end
|
283
290
|
end
|
data/lib/rubocop/cop/util.rb
CHANGED
@@ -9,9 +9,10 @@ module RuboCop
|
|
9
9
|
|
10
10
|
MULTIPLE_LEFT_HAND_SIDE_TYPE = :mlhs
|
11
11
|
|
12
|
-
attr_reader :node, :variable, :referenced, :references
|
12
|
+
attr_reader :node, :variable, :referenced, :references, :reassigned
|
13
13
|
|
14
14
|
alias referenced? referenced
|
15
|
+
alias reassigned? reassigned
|
15
16
|
|
16
17
|
def initialize(node, variable)
|
17
18
|
unless VARIABLE_ASSIGNMENT_TYPES.include?(node.type)
|
@@ -24,6 +25,7 @@ module RuboCop
|
|
24
25
|
@variable = variable
|
25
26
|
@referenced = false
|
26
27
|
@references = []
|
28
|
+
@reassigned = false
|
27
29
|
end
|
28
30
|
|
29
31
|
def name
|
@@ -39,8 +41,14 @@ module RuboCop
|
|
39
41
|
@referenced = true
|
40
42
|
end
|
41
43
|
|
44
|
+
def reassigned!
|
45
|
+
return if referenced?
|
46
|
+
|
47
|
+
@reassigned = true
|
48
|
+
end
|
49
|
+
|
42
50
|
def used?
|
43
|
-
@variable.captured_by_block? || @referenced
|
51
|
+
(!reassigned? && @variable.captured_by_block?) || @referenced
|
44
52
|
end
|
45
53
|
|
46
54
|
def regexp_named_capture?
|
@@ -102,6 +110,7 @@ module RuboCop
|
|
102
110
|
end
|
103
111
|
|
104
112
|
def multiple_assignment_node
|
113
|
+
return nil unless node.parent&.mlhs_type?
|
105
114
|
return nil unless (grandparent_node = node.parent&.parent)
|
106
115
|
if (node = find_multiple_assignment_node(grandparent_node))
|
107
116
|
return node
|
@@ -119,7 +128,13 @@ module RuboCop
|
|
119
128
|
end
|
120
129
|
|
121
130
|
def for_assignment_node
|
122
|
-
node.
|
131
|
+
return unless (parent_node = node.parent)
|
132
|
+
return parent_node if parent_node.for_type?
|
133
|
+
|
134
|
+
grandparent_node = parent_node.parent
|
135
|
+
return grandparent_node if parent_node.mlhs_type? && grandparent_node&.for_type?
|
136
|
+
|
137
|
+
nil
|
123
138
|
end
|
124
139
|
|
125
140
|
def find_multiple_assignment_node(grandparent_node)
|
@@ -29,7 +29,11 @@ module RuboCop
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def assign(node)
|
32
|
-
|
32
|
+
assignment = Assignment.new(node, self)
|
33
|
+
|
34
|
+
@assignments.last&.reassigned! unless captured_by_block?
|
35
|
+
|
36
|
+
@assignments << assignment
|
33
37
|
end
|
34
38
|
|
35
39
|
def referenced?
|
@@ -61,8 +61,8 @@ module RuboCop
|
|
61
61
|
"at #{node.source_range}, #{node.inspect}"
|
62
62
|
end
|
63
63
|
|
64
|
-
variable.assign(node)
|
65
64
|
mark_variable_as_captured_by_block_if_so(variable)
|
65
|
+
variable.assign(node)
|
66
66
|
end
|
67
67
|
|
68
68
|
def reference_variable(name, node)
|
@@ -87,8 +87,8 @@ module RuboCop
|
|
87
87
|
# So just skip.
|
88
88
|
return unless variable
|
89
89
|
|
90
|
-
variable.reference!(node)
|
91
90
|
mark_variable_as_captured_by_block_if_so(variable)
|
91
|
+
variable.reference!(node)
|
92
92
|
end
|
93
93
|
|
94
94
|
def find_variable(name)
|
@@ -1,23 +1,49 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'fileutils'
|
4
|
+
require 'yard'
|
4
5
|
|
5
6
|
# Class for generating documentation of all cops departments
|
6
7
|
# @api private
|
7
8
|
class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
8
9
|
include ::RuboCop::Cop::Documentation
|
10
|
+
CopData = Struct.new(
|
11
|
+
:cop, :description, :example_objects, :safety_objects, :see_objects, :config, keyword_init: true
|
12
|
+
)
|
13
|
+
|
14
|
+
STRUCTURE = {
|
15
|
+
name: ->(data) { cop_header(data.cop) },
|
16
|
+
required_ruby_version: ->(data) { required_ruby_version(data.cop) },
|
17
|
+
properties: ->(data) { properties(data.cop) },
|
18
|
+
description: ->(data) { "#{data.description}\n" },
|
19
|
+
safety: ->(data) { safety_object(data.safety_objects, data.cop) },
|
20
|
+
examples: ->(data) { examples(data.example_objects, data.cop) },
|
21
|
+
configuration: ->(data) { configurations(data.cop.department, data.config, data.cop) },
|
22
|
+
references: ->(data) { references(data.cop, data.see_objects) }
|
23
|
+
}.freeze
|
24
|
+
|
9
25
|
# This class will only generate documentation for cops that belong to one of
|
10
26
|
# the departments given in the `departments` array. E.g. if we only wanted
|
11
27
|
# documentation for Lint cops:
|
12
28
|
#
|
13
29
|
# CopsDocumentationGenerator.new(departments: ['Lint']).call
|
14
30
|
#
|
15
|
-
|
31
|
+
# You can append additional information:
|
32
|
+
#
|
33
|
+
# callback = ->(data) { required_rails_version(data.cop) }
|
34
|
+
# CopsDocumentationGenerator.new(extra_info: { ruby_version: callback }).call
|
35
|
+
#
|
36
|
+
# This will insert the string returned from the lambda _after_ the section from RuboCop itself.
|
37
|
+
# See `CopsDocumentationGenerator::STRUCTURE` for available sections.
|
38
|
+
#
|
39
|
+
def initialize(departments: [], extra_info: {}, base_dir: Dir.pwd)
|
16
40
|
@departments = departments.map(&:to_sym).sort!
|
41
|
+
@extra_info = extra_info
|
17
42
|
@cops = RuboCop::Cop::Registry.global
|
18
43
|
@config = RuboCop::ConfigLoader.default_configuration
|
19
|
-
@
|
20
|
-
|
44
|
+
@base_dir = base_dir
|
45
|
+
@docs_path = "#{base_dir}/docs/modules/ROOT"
|
46
|
+
FileUtils.mkdir_p("#{@docs_path}/pages")
|
21
47
|
end
|
22
48
|
|
23
49
|
def call
|
@@ -37,24 +63,21 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
37
63
|
cops.with_department(department).sort!
|
38
64
|
end
|
39
65
|
|
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)
|
66
|
+
def cops_body(data)
|
67
|
+
check_examples_to_have_the_default_enforced_style!(data.example_objects, data.cop)
|
68
|
+
|
69
|
+
content = +''
|
70
|
+
STRUCTURE.each do |section, block|
|
71
|
+
content << instance_exec(data, &block)
|
72
|
+
content << @extra_info[section].call(data) if @extra_info[section]
|
73
|
+
end
|
51
74
|
content
|
52
75
|
end
|
53
76
|
|
54
|
-
def check_examples_to_have_the_default_enforced_style!(
|
55
|
-
return if
|
77
|
+
def check_examples_to_have_the_default_enforced_style!(example_objects, cop)
|
78
|
+
return if example_objects.none?
|
56
79
|
|
57
|
-
examples_describing_enforced_style =
|
80
|
+
examples_describing_enforced_style = example_objects.map(&:name).grep(/EnforcedStyle:/)
|
58
81
|
return if examples_describing_enforced_style.none?
|
59
82
|
|
60
83
|
if examples_describing_enforced_style.index { |name| name.match?('default') }.nonzero?
|
@@ -66,16 +89,20 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
66
89
|
raise "Specify the default EnforcedStyle for #{cop.cop_name}"
|
67
90
|
end
|
68
91
|
|
69
|
-
def examples(
|
70
|
-
|
92
|
+
def examples(example_objects, cop)
|
93
|
+
return '' if example_objects.none?
|
94
|
+
|
95
|
+
example_objects.each_with_object(cop_subsection('Examples', cop).dup) do |example, content|
|
71
96
|
content << "\n" unless content.end_with?("\n\n")
|
72
|
-
content <<
|
97
|
+
content << example_header(example.name, cop) unless example.name == ''
|
73
98
|
content << code_example(example)
|
74
99
|
end
|
75
100
|
end
|
76
101
|
|
77
|
-
def safety_object(
|
78
|
-
|
102
|
+
def safety_object(safety_objects, cop)
|
103
|
+
return '' if safety_objects.all? { |s| s.text.blank? }
|
104
|
+
|
105
|
+
safety_objects.each_with_object(cop_subsection('Safety', cop).dup) do |safety_object, content|
|
79
106
|
next if safety_object.text.blank?
|
80
107
|
|
81
108
|
content << "\n" unless content.end_with?("\n\n")
|
@@ -115,22 +142,25 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
115
142
|
end
|
116
143
|
# rubocop:enable Metrics/MethodLength
|
117
144
|
|
118
|
-
def
|
145
|
+
def cop_header(cop)
|
119
146
|
content = +"\n"
|
120
|
-
content << "
|
147
|
+
content << "[##{to_anchor(cop.cop_name)}]\n"
|
148
|
+
content << "== #{cop.cop_name}\n"
|
121
149
|
content << "\n"
|
122
150
|
content
|
123
151
|
end
|
124
152
|
|
125
|
-
def
|
153
|
+
def cop_subsection(title, cop)
|
126
154
|
content = +"\n"
|
155
|
+
content << "[##{to_anchor(title)}-#{to_anchor(cop.cop_name)}]\n"
|
127
156
|
content << "=== #{title}\n"
|
128
157
|
content << "\n"
|
129
158
|
content
|
130
159
|
end
|
131
160
|
|
132
|
-
def
|
133
|
-
content = +"
|
161
|
+
def example_header(title, cop)
|
162
|
+
content = +"[##{to_anchor(title)}-#{to_anchor(cop.cop_name)}]\n"
|
163
|
+
content << "==== #{title}\n"
|
134
164
|
content << "\n"
|
135
165
|
content
|
136
166
|
end
|
@@ -142,7 +172,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
142
172
|
content
|
143
173
|
end
|
144
174
|
|
145
|
-
def configurations(department, pars)
|
175
|
+
def configurations(department, pars, cop)
|
146
176
|
return '' if pars.empty?
|
147
177
|
|
148
178
|
header = ['Name', 'Default value', 'Configurable values']
|
@@ -157,7 +187,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
157
187
|
[configuration_name(department, name), default, configurable]
|
158
188
|
end
|
159
189
|
|
160
|
-
|
190
|
+
cop_subsection('Configurable attributes', cop) + to_table(header, content)
|
161
191
|
end
|
162
192
|
|
163
193
|
def configuration_name(department, name)
|
@@ -218,7 +248,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
218
248
|
else
|
219
249
|
wrap_backtick(val.nil? ? '<none>' : val)
|
220
250
|
end
|
221
|
-
value.gsub("#{
|
251
|
+
value.gsub("#{@base_dir}/", '').rstrip
|
222
252
|
end
|
223
253
|
|
224
254
|
def wrap_backtick(value)
|
@@ -235,7 +265,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
235
265
|
urls = RuboCop::Cop::MessageAnnotator.new(config, cop.name, cop_config, {}).urls
|
236
266
|
return '' if urls.empty? && see_objects.empty?
|
237
267
|
|
238
|
-
content =
|
268
|
+
content = cop_subsection('References', cop)
|
239
269
|
content << urls.map { |url| "* #{url}" }.join("\n")
|
240
270
|
content << "\n" unless urls.empty?
|
241
271
|
content << see_objects.map { |see| "* #{see.name}" }.join("\n")
|
@@ -247,7 +277,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
247
277
|
return '' unless department == :Layout
|
248
278
|
|
249
279
|
filename = "#{department_to_basename(department)}_footer.adoc"
|
250
|
-
file = "#{
|
280
|
+
file = "#{docs_path}/partials/#{filename}"
|
251
281
|
return '' unless File.exist?(file)
|
252
282
|
|
253
283
|
"\ninclude::../partials/#{filename}[]\n"
|
@@ -267,7 +297,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
267
297
|
HEADER
|
268
298
|
selected_cops.each { |cop| content << print_cop_with_doc(cop) }
|
269
299
|
content << footer_for_department(department)
|
270
|
-
file_name = "#{docs_path}/#{department_to_basename(department)}.adoc"
|
300
|
+
file_name = "#{docs_path}/pages/#{department_to_basename(department)}.adoc"
|
271
301
|
File.open(file_name, 'w') do |file|
|
272
302
|
puts "* generated #{file_name}"
|
273
303
|
file.write("#{content.strip}\n")
|
@@ -283,14 +313,16 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
283
313
|
]
|
284
314
|
pars = cop_config.reject { |k| non_display_keys.include? k }
|
285
315
|
description = 'No documentation'
|
286
|
-
|
316
|
+
example_objects = safety_objects = see_objects = []
|
287
317
|
cop_code(cop) do |code_object|
|
288
318
|
description = code_object.docstring unless code_object.docstring.blank?
|
289
|
-
|
290
|
-
|
291
|
-
|
319
|
+
example_objects = code_object.tags('example')
|
320
|
+
safety_objects = code_object.tags('safety')
|
321
|
+
see_objects = code_object.tags('see')
|
292
322
|
end
|
293
|
-
|
323
|
+
data = CopData.new(cop: cop, description: description, example_objects: example_objects,
|
324
|
+
safety_objects: safety_objects, see_objects: see_objects, config: pars)
|
325
|
+
cops_body(data)
|
294
326
|
end
|
295
327
|
|
296
328
|
def cop_code(cop)
|
@@ -306,7 +338,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
306
338
|
filename = "#{department_to_basename(department)}.adoc"
|
307
339
|
content = +"=== Department xref:#{filename}[#{type_title}]\n\n"
|
308
340
|
cops_of_department(department).each do |cop|
|
309
|
-
anchor = cop.cop_name
|
341
|
+
anchor = to_anchor(cop.cop_name)
|
310
342
|
content << "* xref:#{filename}##{anchor}[#{cop.cop_name}]\n"
|
311
343
|
end
|
312
344
|
|
@@ -314,7 +346,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
314
346
|
end
|
315
347
|
|
316
348
|
def print_table_of_contents
|
317
|
-
path = "#{docs_path}/cops.adoc"
|
349
|
+
path = "#{docs_path}/pages/cops.adoc"
|
318
350
|
|
319
351
|
File.write(path, table_contents) and return unless File.exist?(path)
|
320
352
|
|
@@ -338,4 +370,13 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
338
370
|
|
339
371
|
status == 'pending' ? 'Pending' : 'Enabled'
|
340
372
|
end
|
373
|
+
|
374
|
+
# HTML anchor are somewhat limited in what characters they can contain, just
|
375
|
+
# accept a known-good subset. As long as it's consistent it doesn't matter.
|
376
|
+
#
|
377
|
+
# Style/AccessModifierDeclarations => styleaccessmodifierdeclarations
|
378
|
+
# OnlyFor: [] (default) => onlyfor_-__-_default_
|
379
|
+
def to_anchor(title)
|
380
|
+
title.delete('/').tr(' ', '-').gsub(/[^a-zA-Z0-9-]/, '_').downcase
|
381
|
+
end
|
341
382
|
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
|
@@ -10,7 +10,7 @@ module RuboCop
|
|
10
10
|
HEADING = <<~COMMENTS
|
11
11
|
# This configuration was generated by
|
12
12
|
# `%<command>s`
|
13
|
-
# %<timestamp>susing RuboCop version #{Version
|
13
|
+
# %<timestamp>susing RuboCop version #{Version::STRING}.
|
14
14
|
# The point is for the user to remove these configuration records
|
15
15
|
# one by one as the offenses are removed from the code base.
|
16
16
|
# Note that changes in the inspected code, or installation of new
|
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
@@ -139,7 +139,7 @@ module RuboCop
|
|
139
139
|
offenses = process_file(file)
|
140
140
|
yield file
|
141
141
|
|
142
|
-
if offenses.any? { |o| considered_failure?(o) }
|
142
|
+
if offenses.any? { |o| considered_failure?(o) && offense_displayed?(o) }
|
143
143
|
break false if @options[:fail_fast]
|
144
144
|
|
145
145
|
next false
|
@@ -362,6 +362,13 @@ 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
|
+
location = if ruby_extractor.is_a?(Proc)
|
367
|
+
ruby_extractor.source_location
|
368
|
+
else
|
369
|
+
ruby_extractor.method(:call).source_location
|
370
|
+
end
|
371
|
+
raise Error, "Ruby extractor #{location[0]} failed to process #{processed_source.path}."
|
365
372
|
end
|
366
373
|
end
|
367
374
|
|
@@ -433,18 +440,22 @@ module RuboCop
|
|
433
440
|
!offense.corrected? && offense.severity >= minimum_severity_to_fail
|
434
441
|
end
|
435
442
|
|
436
|
-
def
|
443
|
+
def offense_displayed?(offense)
|
437
444
|
if @options[:display_only_fail_level_offenses]
|
438
|
-
|
445
|
+
considered_failure?(offense)
|
439
446
|
elsif @options[:display_only_safe_correctable]
|
440
|
-
|
447
|
+
supports_safe_autocorrect?(offense)
|
441
448
|
elsif @options[:display_only_correctable]
|
442
|
-
|
449
|
+
offense.correctable?
|
443
450
|
else
|
444
|
-
|
451
|
+
true
|
445
452
|
end
|
446
453
|
end
|
447
454
|
|
455
|
+
def offenses_to_report(offenses)
|
456
|
+
offenses.select { |o| offense_displayed?(o) }
|
457
|
+
end
|
458
|
+
|
448
459
|
def supports_safe_autocorrect?(offense)
|
449
460
|
cop_class = Cop::Registry.global.find_by_cop_name(offense.cop_name)
|
450
461
|
default_cfg = default_config(offense.cop_name)
|
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)
|
@@ -273,7 +273,7 @@ module RuboCop
|
|
273
273
|
|
274
274
|
def rubocop_version_with_support
|
275
275
|
if supported?
|
276
|
-
RuboCop::Version
|
276
|
+
RuboCop::Version::STRING
|
277
277
|
else
|
278
278
|
OBSOLETE_RUBIES[version]
|
279
279
|
end
|
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.68.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 = {
|
@@ -17,11 +18,13 @@ module RuboCop
|
|
17
18
|
'rubocop-md' => 'markdown', 'rubocop-factory_bot' => 'factory_bot'
|
18
19
|
}.freeze
|
19
20
|
|
21
|
+
# NOTE: Marked as private but used by gems like standard.
|
20
22
|
# @api private
|
21
23
|
def self.version(debug: false, env: nil)
|
22
24
|
if debug
|
23
25
|
verbose_version = format(MSG, version: STRING, parser_version: parser_version,
|
24
26
|
rubocop_ast_version: RuboCop::AST::Version::STRING,
|
27
|
+
target_ruby_version: target_ruby_version(env),
|
25
28
|
ruby_engine: RUBY_ENGINE, ruby_version: RUBY_VERSION,
|
26
29
|
server_mode: server_mode,
|
27
30
|
ruby_platform: RUBY_PLATFORM)
|
@@ -39,6 +42,11 @@ module RuboCop
|
|
39
42
|
end
|
40
43
|
end
|
41
44
|
|
45
|
+
# @api private
|
46
|
+
def self.verbose(env: nil)
|
47
|
+
version(debug: true, env: env)
|
48
|
+
end
|
49
|
+
|
42
50
|
# @api private
|
43
51
|
def self.parser_version
|
44
52
|
config_path = ConfigFinder.find_config_path(Dir.pwd)
|
@@ -56,12 +64,7 @@ module RuboCop
|
|
56
64
|
|
57
65
|
# @api private
|
58
66
|
def self.extension_versions(env)
|
59
|
-
features =
|
60
|
-
# Suppress any config issues when loading the config (ie. deprecations,
|
61
|
-
# pending cops, etc.).
|
62
|
-
env.config_store.unvalidated.for_pwd.loaded_features.sort
|
63
|
-
end
|
64
|
-
|
67
|
+
features = config_for_pwd(env).loaded_features.sort
|
65
68
|
features.filter_map do |loaded_feature|
|
66
69
|
next unless (match = loaded_feature.match(/rubocop-(?<feature>.*)/))
|
67
70
|
|
@@ -83,6 +86,24 @@ module RuboCop
|
|
83
86
|
end
|
84
87
|
end
|
85
88
|
|
89
|
+
# @api private
|
90
|
+
def self.target_ruby_version(env)
|
91
|
+
if env
|
92
|
+
config_for_pwd(env).target_ruby_version
|
93
|
+
else
|
94
|
+
TargetRuby.new(Config.new).version
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# @api private
|
99
|
+
def self.config_for_pwd(env)
|
100
|
+
Util.silence_warnings do
|
101
|
+
# Suppress any config issues when loading the config (ie. deprecations,
|
102
|
+
# pending cops, etc.).
|
103
|
+
env.config_store.unvalidated.for_pwd
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
86
107
|
# Returns feature version in one of two ways:
|
87
108
|
#
|
88
109
|
# * Find by RuboCop core version style (e.g. rubocop-performance, rubocop-rspec)
|