rubocop 1.39.0 → 1.41.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 +65 -9
- data/exe/rubocop +1 -1
- data/lib/rubocop/comment_config.rb +5 -0
- data/lib/rubocop/config.rb +33 -9
- data/lib/rubocop/config_loader.rb +14 -5
- data/lib/rubocop/config_loader_resolver.rb +1 -1
- data/lib/rubocop/config_validator.rb +1 -1
- data/lib/rubocop/cop/badge.rb +9 -4
- data/lib/rubocop/cop/base.rb +26 -17
- data/lib/rubocop/cop/commissioner.rb +8 -3
- data/lib/rubocop/cop/cop.rb +1 -1
- data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +22 -6
- data/lib/rubocop/cop/internal_affairs/cop_description.rb +3 -1
- data/lib/rubocop/cop/internal_affairs/lambda_or_proc.rb +46 -0
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/layout/empty_lines.rb +2 -0
- data/lib/rubocop/cop/layout/extra_spacing.rb +10 -6
- data/lib/rubocop/cop/layout/first_array_element_line_break.rb +38 -2
- data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +49 -2
- data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +61 -2
- data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +52 -2
- data/lib/rubocop/cop/layout/indentation_style.rb +3 -1
- data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +5 -0
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +7 -1
- data/lib/rubocop/cop/layout/line_length.rb +2 -0
- data/lib/rubocop/cop/layout/multiline_array_line_breaks.rb +51 -2
- data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +49 -2
- data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +53 -2
- data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +58 -2
- data/lib/rubocop/cop/layout/redundant_line_break.rb +2 -2
- data/lib/rubocop/cop/layout/trailing_empty_lines.rb +1 -1
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +6 -2
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +11 -1
- data/lib/rubocop/cop/lint/constant_resolution.rb +4 -0
- data/lib/rubocop/cop/lint/debugger.rb +3 -1
- data/lib/rubocop/cop/lint/deprecated_constants.rb +8 -1
- data/lib/rubocop/cop/lint/duplicate_branch.rb +0 -2
- data/lib/rubocop/cop/lint/duplicate_methods.rb +19 -8
- data/lib/rubocop/cop/lint/empty_block.rb +1 -5
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +1 -1
- data/lib/rubocop/cop/lint/interpolation_check.rb +4 -3
- data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +10 -5
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +5 -0
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +13 -3
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +1 -1
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +10 -12
- data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +5 -4
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +4 -3
- data/lib/rubocop/cop/lint/void.rb +6 -6
- data/lib/rubocop/cop/metrics/block_length.rb +9 -4
- data/lib/rubocop/cop/metrics/class_length.rb +10 -5
- data/lib/rubocop/cop/metrics/method_length.rb +9 -4
- data/lib/rubocop/cop/metrics/module_length.rb +10 -5
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +6 -3
- data/lib/rubocop/cop/mixin/alignment.rb +1 -1
- data/lib/rubocop/cop/mixin/allowed_identifiers.rb +2 -2
- data/lib/rubocop/cop/mixin/annotation_comment.rb +13 -6
- data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +21 -9
- data/lib/rubocop/cop/mixin/first_element_line_break.rb +11 -7
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +28 -5
- data/lib/rubocop/cop/mixin/line_length_help.rb +8 -1
- data/lib/rubocop/cop/mixin/method_complexity.rb +5 -3
- data/lib/rubocop/cop/mixin/multiline_element_line_breaks.rb +5 -3
- data/lib/rubocop/cop/mixin/percent_array.rb +3 -5
- data/lib/rubocop/cop/mixin/require_library.rb +2 -0
- data/lib/rubocop/cop/mixin/rescue_node.rb +3 -3
- data/lib/rubocop/cop/mixin/statement_modifier.rb +15 -1
- data/lib/rubocop/cop/naming/class_and_module_camel_case.rb +2 -0
- data/lib/rubocop/cop/naming/inclusive_language.rb +4 -1
- data/lib/rubocop/cop/registry.rb +29 -14
- data/lib/rubocop/cop/style/array_intersect.rb +111 -0
- data/lib/rubocop/cop/style/concat_array_literals.rb +66 -0
- data/lib/rubocop/cop/style/documentation.rb +1 -1
- data/lib/rubocop/cop/style/guard_clause.rb +36 -5
- data/lib/rubocop/cop/style/if_with_semicolon.rb +4 -4
- data/lib/rubocop/cop/style/inverse_methods.rb +2 -0
- data/lib/rubocop/cop/style/line_end_concatenation.rb +4 -1
- data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
- data/lib/rubocop/cop/style/redundant_argument.rb +3 -0
- data/lib/rubocop/cop/style/redundant_constant_base.rb +85 -0
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +39 -0
- data/lib/rubocop/cop/style/redundant_return.rb +7 -0
- data/lib/rubocop/cop/style/redundant_sort.rb +1 -1
- data/lib/rubocop/cop/style/require_order.rb +140 -0
- data/lib/rubocop/cop/style/safe_navigation.rb +35 -6
- data/lib/rubocop/cop/style/select_by_regexp.rb +8 -4
- data/lib/rubocop/cop/style/semicolon.rb +2 -1
- data/lib/rubocop/cop/style/string_literals.rb +1 -5
- data/lib/rubocop/cop/style/symbol_proc.rb +2 -4
- data/lib/rubocop/cop/team.rb +1 -1
- data/lib/rubocop/cop/util.rb +32 -5
- data/lib/rubocop/cop/variable_force/assignment.rb +1 -1
- data/lib/rubocop/cop/variable_force.rb +20 -29
- data/lib/rubocop/cops_documentation_generator.rb +22 -3
- data/lib/rubocop/directive_comment.rb +1 -1
- data/lib/rubocop/file_patterns.rb +43 -0
- data/lib/rubocop/formatter/disabled_config_formatter.rb +17 -6
- data/lib/rubocop/formatter/html_formatter.rb +1 -1
- data/lib/rubocop/formatter.rb +3 -1
- data/lib/rubocop/options.rb +8 -0
- data/lib/rubocop/path_util.rb +34 -16
- data/lib/rubocop/result_cache.rb +1 -1
- data/lib/rubocop/rspec/cop_helper.rb +4 -1
- data/lib/rubocop/rspec/support.rb +2 -2
- data/lib/rubocop/server/core.rb +1 -1
- data/lib/rubocop/target_finder.rb +1 -1
- data/lib/rubocop/target_ruby.rb +1 -1
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +16 -6
- metadata +10 -3
@@ -0,0 +1,140 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Sort `require` and `require_relative` in alphabetical order.
|
7
|
+
#
|
8
|
+
# @safety
|
9
|
+
# This cop's autocorrection is unsafe because it will obviously change the execution order.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# # bad
|
13
|
+
# require 'b'
|
14
|
+
# require 'a'
|
15
|
+
#
|
16
|
+
# # good
|
17
|
+
# require 'a'
|
18
|
+
# require 'b'
|
19
|
+
#
|
20
|
+
# # bad
|
21
|
+
# require_relative 'b'
|
22
|
+
# require_relative 'a'
|
23
|
+
#
|
24
|
+
# # good
|
25
|
+
# require_relative 'a'
|
26
|
+
# require_relative 'b'
|
27
|
+
#
|
28
|
+
# # good (sorted within each section separated by a blank line)
|
29
|
+
# require 'a'
|
30
|
+
# require 'd'
|
31
|
+
#
|
32
|
+
# require 'b'
|
33
|
+
# require 'c'
|
34
|
+
#
|
35
|
+
# # good
|
36
|
+
# require 'b'
|
37
|
+
# require_relative 'c'
|
38
|
+
# require 'a'
|
39
|
+
#
|
40
|
+
# # bad
|
41
|
+
# require 'a'
|
42
|
+
# require 'c' if foo
|
43
|
+
# require 'b'
|
44
|
+
#
|
45
|
+
# # good
|
46
|
+
# require 'a'
|
47
|
+
# require 'b'
|
48
|
+
# require 'c' if foo
|
49
|
+
#
|
50
|
+
# # bad
|
51
|
+
# require 'c'
|
52
|
+
# if foo
|
53
|
+
# require 'd'
|
54
|
+
# require 'b'
|
55
|
+
# end
|
56
|
+
# require 'a'
|
57
|
+
#
|
58
|
+
# # good
|
59
|
+
# require 'c'
|
60
|
+
# if foo
|
61
|
+
# require 'b'
|
62
|
+
# require 'd'
|
63
|
+
# end
|
64
|
+
# require 'a'
|
65
|
+
#
|
66
|
+
class RequireOrder < Base
|
67
|
+
extend AutoCorrector
|
68
|
+
|
69
|
+
include RangeHelp
|
70
|
+
|
71
|
+
RESTRICT_ON_SEND = %i[require require_relative].freeze
|
72
|
+
|
73
|
+
MSG = 'Sort `%<name>s` in alphabetical order.'
|
74
|
+
|
75
|
+
# @!method if_inside_only_require(node)
|
76
|
+
def_node_matcher :if_inside_only_require, <<~PATTERN
|
77
|
+
{
|
78
|
+
(if _ _ $(send nil? {:require :require_relative} _))
|
79
|
+
(if _ $(send nil? {:require :require_relative} _) _)
|
80
|
+
}
|
81
|
+
PATTERN
|
82
|
+
|
83
|
+
def on_send(node)
|
84
|
+
return unless node.arguments?
|
85
|
+
return if not_modifier_form?(node.parent)
|
86
|
+
|
87
|
+
previous_older_sibling = find_previous_older_sibling(node)
|
88
|
+
return unless previous_older_sibling
|
89
|
+
|
90
|
+
add_offense(node, message: format(MSG, name: node.method_name)) do |corrector|
|
91
|
+
swap(
|
92
|
+
range_with_comments_and_lines(previous_older_sibling),
|
93
|
+
range_with_comments_and_lines(node.parent.if_type? ? node.parent : node),
|
94
|
+
corrector: corrector
|
95
|
+
)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
def not_modifier_form?(node)
|
102
|
+
node.if_type? && !node.modifier_form?
|
103
|
+
end
|
104
|
+
|
105
|
+
def find_previous_older_sibling(node) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity
|
106
|
+
search_node(node).left_siblings.reverse.find do |sibling|
|
107
|
+
sibling = sibling_node(sibling)
|
108
|
+
break unless sibling&.send_type? && sibling&.method?(node.method_name)
|
109
|
+
break unless sibling.arguments? && !sibling.receiver
|
110
|
+
break unless in_same_section?(sibling, node)
|
111
|
+
|
112
|
+
node.first_argument.source < sibling.first_argument.source
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def search_node(node)
|
117
|
+
node.parent.if_type? ? node.parent : node
|
118
|
+
end
|
119
|
+
|
120
|
+
def sibling_node(node)
|
121
|
+
return if not_modifier_form?(node)
|
122
|
+
|
123
|
+
node.if_type? ? if_inside_only_require(node) : node
|
124
|
+
end
|
125
|
+
|
126
|
+
def in_same_section?(node1, node2)
|
127
|
+
!node1.location.expression.with(
|
128
|
+
end_pos: node2.location.expression.end_pos
|
129
|
+
).source.include?("\n\n")
|
130
|
+
end
|
131
|
+
|
132
|
+
def swap(range1, range2, corrector:)
|
133
|
+
inserted = range2.source
|
134
|
+
corrector.insert_before(range1, inserted)
|
135
|
+
corrector.remove(range2)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -50,6 +50,11 @@ module RuboCop
|
|
50
50
|
# foo && foo.bar { |e| e.something }
|
51
51
|
# foo && foo.bar(param) { |e| e.something }
|
52
52
|
#
|
53
|
+
# foo ? foo.bar : nil
|
54
|
+
# foo.nil? ? nil : foo.bar
|
55
|
+
# !foo.nil? ? foo.bar : nil
|
56
|
+
# !foo ? nil : foo.bar
|
57
|
+
#
|
53
58
|
# # good
|
54
59
|
# foo&.bar
|
55
60
|
# foo&.bar&.baz
|
@@ -105,6 +110,17 @@ module RuboCop
|
|
105
110
|
}
|
106
111
|
PATTERN
|
107
112
|
|
113
|
+
# @!method ternary_safe_navigation_candidate(node)
|
114
|
+
def_node_matcher :ternary_safe_navigation_candidate, <<~PATTERN
|
115
|
+
{
|
116
|
+
(if (send $_ {:nil? :!}) nil $_)
|
117
|
+
|
118
|
+
(if (send (send $_ :nil?) :!) $_ nil)
|
119
|
+
|
120
|
+
(if $_ $_ nil)
|
121
|
+
}
|
122
|
+
PATTERN
|
123
|
+
|
108
124
|
# @!method not_nil_check?(node)
|
109
125
|
def_node_matcher :not_nil_check?, '(send (send $_ :nil?) :!)'
|
110
126
|
|
@@ -118,9 +134,11 @@ module RuboCop
|
|
118
134
|
check_node(node)
|
119
135
|
end
|
120
136
|
|
137
|
+
private
|
138
|
+
|
121
139
|
def check_node(node)
|
122
140
|
checked_variable, receiver, method_chain, method = extract_parts(node)
|
123
|
-
return
|
141
|
+
return if receiver != checked_variable || receiver.nil?
|
124
142
|
return if use_var_only_in_unless_modifier?(node, checked_variable)
|
125
143
|
return if chain_length(method_chain, method) > max_chain_length
|
126
144
|
return if unsafe_method_used?(method_chain, method)
|
@@ -133,10 +151,8 @@ module RuboCop
|
|
133
151
|
node.if_type? && node.unless? && !method_called?(variable)
|
134
152
|
end
|
135
153
|
|
136
|
-
private
|
137
|
-
|
138
154
|
def autocorrect(corrector, node)
|
139
|
-
body = node
|
155
|
+
body = extract_body(node)
|
140
156
|
method_call = method_call(node)
|
141
157
|
|
142
158
|
corrector.remove(begin_range(node, body))
|
@@ -147,6 +163,14 @@ module RuboCop
|
|
147
163
|
add_safe_nav_to_all_methods_in_chain(corrector, method_call, body)
|
148
164
|
end
|
149
165
|
|
166
|
+
def extract_body(node)
|
167
|
+
if node.if_type? && node.ternary?
|
168
|
+
node.branches.find { |branch| !branch.nil_type? }
|
169
|
+
else
|
170
|
+
node.node_parts[1]
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
150
174
|
def handle_comments(corrector, node, method_call)
|
151
175
|
comments = comments(node)
|
152
176
|
return if comments.empty?
|
@@ -174,7 +198,7 @@ module RuboCop
|
|
174
198
|
end
|
175
199
|
|
176
200
|
def allowed_if_condition?(node)
|
177
|
-
node.else? || node.elsif?
|
201
|
+
node.else? || node.elsif?
|
178
202
|
end
|
179
203
|
|
180
204
|
def method_call(node)
|
@@ -192,7 +216,12 @@ module RuboCop
|
|
192
216
|
end
|
193
217
|
|
194
218
|
def extract_parts_from_if(node)
|
195
|
-
variable, receiver =
|
219
|
+
variable, receiver =
|
220
|
+
if node.ternary?
|
221
|
+
ternary_safe_navigation_candidate(node)
|
222
|
+
else
|
223
|
+
modifier_if_safe_navigation_candidate(node)
|
224
|
+
end
|
196
225
|
|
197
226
|
checked_variable, matching_receiver, method = extract_common_parts(receiver, variable)
|
198
227
|
|
@@ -49,7 +49,8 @@ module RuboCop
|
|
49
49
|
MSG = 'Prefer `%<replacement>s` to `%<original_method>s` with a regexp match.'
|
50
50
|
RESTRICT_ON_SEND = %i[select find_all reject].freeze
|
51
51
|
REPLACEMENTS = { select: 'grep', find_all: 'grep', reject: 'grep_v' }.freeze
|
52
|
-
|
52
|
+
OPPOSITE_REPLACEMENTS = { select: 'grep_v', find_all: 'grep_v', reject: 'grep' }.freeze
|
53
|
+
REGEXP_METHODS = %i[match? =~ !~].to_set.freeze
|
53
54
|
|
54
55
|
# @!method regexp_match?(node)
|
55
56
|
def_node_matcher :regexp_match?, <<~PATTERN
|
@@ -90,8 +91,10 @@ module RuboCop
|
|
90
91
|
return unless (regexp_method_send_node = extract_send_node(block_node))
|
91
92
|
return if match_predicate_without_receiver?(regexp_method_send_node)
|
92
93
|
|
94
|
+
opposite = regexp_method_send_node.send_type? && regexp_method_send_node.method?(:!~)
|
93
95
|
regexp = find_regexp(regexp_method_send_node, block_node)
|
94
|
-
|
96
|
+
|
97
|
+
register_offense(node, block_node, regexp, opposite)
|
95
98
|
end
|
96
99
|
|
97
100
|
private
|
@@ -102,8 +105,9 @@ module RuboCop
|
|
102
105
|
node.hash_type? || creates_hash?(node) || env_const?(node)
|
103
106
|
end
|
104
107
|
|
105
|
-
def register_offense(node, block_node, regexp)
|
106
|
-
|
108
|
+
def register_offense(node, block_node, regexp, opposite)
|
109
|
+
method_name = node.method_name.to_sym
|
110
|
+
replacement = opposite ? OPPOSITE_REPLACEMENTS[method_name] : REPLACEMENTS[method_name]
|
107
111
|
message = format(MSG, replacement: replacement, original_method: node.method_name)
|
108
112
|
|
109
113
|
add_offense(block_node, message: message) do |corrector|
|
@@ -37,13 +37,14 @@ module RuboCop
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def on_new_investigation
|
40
|
-
return if processed_source.blank?
|
40
|
+
return if processed_source.blank? || !processed_source.raw_source.include?(';')
|
41
41
|
|
42
42
|
check_for_line_terminator_or_opener
|
43
43
|
end
|
44
44
|
|
45
45
|
def on_begin(node)
|
46
46
|
return if cop_config['AllowAsExpressionSeparator']
|
47
|
+
return unless node.source.include?(';')
|
47
48
|
|
48
49
|
exprs = node.children
|
49
50
|
|
@@ -95,11 +95,7 @@ module RuboCop
|
|
95
95
|
end
|
96
96
|
|
97
97
|
def offense?(node)
|
98
|
-
|
99
|
-
# for this cop.
|
100
|
-
return false if inside_interpolation?(node)
|
101
|
-
|
102
|
-
wrong_quotes?(node)
|
98
|
+
wrong_quotes?(node) && !inside_interpolation?(node)
|
103
99
|
end
|
104
100
|
|
105
101
|
def consistent_multiline?
|
@@ -7,7 +7,7 @@ module RuboCop
|
|
7
7
|
#
|
8
8
|
# If you prefer a style that allows block for method with arguments,
|
9
9
|
# please set `true` to `AllowMethodsWithArguments`.
|
10
|
-
#
|
10
|
+
# `define_method?` methods are allowed by default.
|
11
11
|
# These are customizable with `AllowedMethods` option.
|
12
12
|
#
|
13
13
|
# @safety
|
@@ -72,12 +72,10 @@ module RuboCop
|
|
72
72
|
# # some comment
|
73
73
|
# end
|
74
74
|
#
|
75
|
-
# @example AllowedMethods: [
|
75
|
+
# @example AllowedMethods: [define_method] (default)
|
76
76
|
# # good
|
77
|
-
# respond_to { |foo| foo.bar }
|
78
77
|
# define_method(:foo) { |foo| foo.bar }
|
79
78
|
#
|
80
|
-
#
|
81
79
|
# @example AllowedPatterns: [] (default)
|
82
80
|
# # bad
|
83
81
|
# something.map { |s| s.upcase }
|
data/lib/rubocop/cop/team.rb
CHANGED
@@ -38,7 +38,7 @@ module RuboCop
|
|
38
38
|
new(cops, config, options)
|
39
39
|
end
|
40
40
|
|
41
|
-
# @return [Array<Cop::
|
41
|
+
# @return [Array<Cop::Base>]
|
42
42
|
def self.mobilize_cops(cop_classes, config, options = {})
|
43
43
|
cop_classes = Registry.new(cop_classes.to_a, options) unless cop_classes.is_a?(Registry)
|
44
44
|
|
data/lib/rubocop/cop/util.rb
CHANGED
@@ -52,6 +52,21 @@ module RuboCop
|
|
52
52
|
end
|
53
53
|
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
54
54
|
|
55
|
+
def any_descendant?(node, *types)
|
56
|
+
if block_given?
|
57
|
+
node.each_descendant(*types) do |descendant|
|
58
|
+
return true if yield(descendant)
|
59
|
+
end
|
60
|
+
else
|
61
|
+
# Use a block version to avoid allocating enumerators.
|
62
|
+
node.each_descendant do # rubocop:disable Lint/UnreachableLoop
|
63
|
+
return true
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
false
|
68
|
+
end
|
69
|
+
|
55
70
|
def args_begin(node)
|
56
71
|
loc = node.loc
|
57
72
|
selector = if node.super_type? || node.yield_type?
|
@@ -71,14 +86,19 @@ module RuboCop
|
|
71
86
|
def on_node(syms, sexp, excludes = [], &block)
|
72
87
|
return to_enum(:on_node, syms, sexp, excludes) unless block
|
73
88
|
|
74
|
-
yield sexp if
|
75
|
-
return if
|
89
|
+
yield sexp if include_or_equal?(syms, sexp.type)
|
90
|
+
return if include_or_equal?(excludes, sexp.type)
|
76
91
|
|
77
92
|
sexp.each_child_node { |elem| on_node(syms, elem, excludes, &block) }
|
78
93
|
end
|
79
94
|
|
95
|
+
LINE_BEGINS_REGEX_CACHE = Hash.new do |hash, index|
|
96
|
+
hash[index] = /^\s{#{index}}\S/
|
97
|
+
end
|
98
|
+
private_constant :LINE_BEGINS_REGEX_CACHE
|
99
|
+
|
80
100
|
def begins_its_line?(range)
|
81
|
-
range.source_line.
|
101
|
+
range.source_line.match?(LINE_BEGINS_REGEX_CACHE[range.column])
|
82
102
|
end
|
83
103
|
|
84
104
|
# Returns, for example, a bare `if` node if the given node is an `if`
|
@@ -152,16 +172,23 @@ module RuboCop
|
|
152
172
|
' ' * (node.loc.column + offset)
|
153
173
|
end
|
154
174
|
|
175
|
+
@to_supported_styles_cache = {}
|
176
|
+
|
155
177
|
def to_supported_styles(enforced_style)
|
156
|
-
enforced_style
|
178
|
+
@to_supported_styles_cache[enforced_style] ||=
|
179
|
+
enforced_style.sub(/^Enforced/, 'Supported').sub('Style', 'Styles')
|
157
180
|
end
|
158
181
|
|
159
182
|
private
|
160
183
|
|
161
184
|
def compatible_external_encoding_for?(src)
|
162
|
-
src = src.dup if
|
185
|
+
src = src.dup if RUBY_ENGINE == 'jruby'
|
163
186
|
src.force_encoding(Encoding.default_external).valid_encoding?
|
164
187
|
end
|
188
|
+
|
189
|
+
def include_or_equal?(source, target)
|
190
|
+
source == target || (source.is_a?(Array) && source.include?(target))
|
191
|
+
end
|
165
192
|
end
|
166
193
|
end
|
167
194
|
end
|
@@ -83,7 +83,7 @@ module RuboCop
|
|
83
83
|
end
|
84
84
|
|
85
85
|
def multiple_assignment_node
|
86
|
-
grandparent_node = node.parent
|
86
|
+
grandparent_node = node.parent&.parent
|
87
87
|
return nil unless grandparent_node
|
88
88
|
return nil unless grandparent_node.type == MULTIPLE_ASSIGNMENT_TYPE
|
89
89
|
return nil unless node.parent.type == MULTIPLE_LEFT_HAND_SIDE_TYPE
|
@@ -108,34 +108,26 @@ module RuboCop
|
|
108
108
|
:skip_children
|
109
109
|
end
|
110
110
|
|
111
|
-
# rubocop:disable
|
111
|
+
# rubocop:disable Layout/ClassStructure
|
112
|
+
NODE_HANDLER_METHOD_NAMES = [
|
113
|
+
[VARIABLE_ASSIGNMENT_TYPE, :process_variable_assignment],
|
114
|
+
[REGEXP_NAMED_CAPTURE_TYPE, :process_regexp_named_captures],
|
115
|
+
[MULTIPLE_ASSIGNMENT_TYPE, :process_variable_multiple_assignment],
|
116
|
+
[VARIABLE_REFERENCE_TYPE, :process_variable_referencing],
|
117
|
+
[RESCUE_TYPE, :process_rescue],
|
118
|
+
[ZERO_ARITY_SUPER_TYPE, :process_zero_arity_super],
|
119
|
+
[SEND_TYPE, :process_send],
|
120
|
+
*ARGUMENT_DECLARATION_TYPES.product([:process_variable_declaration]),
|
121
|
+
*OPERATOR_ASSIGNMENT_TYPES.product([:process_variable_operator_assignment]),
|
122
|
+
*LOOP_TYPES.product([:process_loop]),
|
123
|
+
*SCOPE_TYPES.product([:process_scope])
|
124
|
+
].to_h.freeze
|
125
|
+
private_constant :NODE_HANDLER_METHOD_NAMES
|
126
|
+
# rubocop:enable Layout/ClassStructure
|
127
|
+
|
112
128
|
def node_handler_method_name(node)
|
113
|
-
|
114
|
-
when VARIABLE_ASSIGNMENT_TYPE
|
115
|
-
:process_variable_assignment
|
116
|
-
when REGEXP_NAMED_CAPTURE_TYPE
|
117
|
-
:process_regexp_named_captures
|
118
|
-
when MULTIPLE_ASSIGNMENT_TYPE
|
119
|
-
:process_variable_multiple_assignment
|
120
|
-
when VARIABLE_REFERENCE_TYPE
|
121
|
-
:process_variable_referencing
|
122
|
-
when RESCUE_TYPE
|
123
|
-
:process_rescue
|
124
|
-
when ZERO_ARITY_SUPER_TYPE
|
125
|
-
:process_zero_arity_super
|
126
|
-
when SEND_TYPE
|
127
|
-
:process_send
|
128
|
-
when *ARGUMENT_DECLARATION_TYPES
|
129
|
-
:process_variable_declaration
|
130
|
-
when *OPERATOR_ASSIGNMENT_TYPES
|
131
|
-
:process_variable_operator_assignment
|
132
|
-
when *LOOP_TYPES
|
133
|
-
:process_loop
|
134
|
-
when *SCOPE_TYPES
|
135
|
-
:process_scope
|
136
|
-
end
|
129
|
+
NODE_HANDLER_METHOD_NAMES[node.type]
|
137
130
|
end
|
138
|
-
# rubocop:enable Metrics/MethodLength, Metrics/CyclomaticComplexity
|
139
131
|
|
140
132
|
def process_variable_declaration(node)
|
141
133
|
variable_name = node.children.first
|
@@ -358,13 +350,12 @@ module RuboCop
|
|
358
350
|
end
|
359
351
|
end
|
360
352
|
|
361
|
-
# Use Node#equal? for accurate check.
|
362
353
|
def scanned_node?(node)
|
363
|
-
scanned_nodes.
|
354
|
+
scanned_nodes.include?(node)
|
364
355
|
end
|
365
356
|
|
366
357
|
def scanned_nodes
|
367
|
-
@scanned_nodes ||=
|
358
|
+
@scanned_nodes ||= Set.new.compare_by_identity
|
368
359
|
end
|
369
360
|
|
370
361
|
# Hooks invoked by VariableTable.
|
@@ -42,7 +42,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
42
42
|
content << "#{description}\n"
|
43
43
|
content << safety_object(safety_objects) if safety_objects.any? { |s| !s.text.blank? }
|
44
44
|
content << examples(examples_objects) if examples_objects.any?
|
45
|
-
content << configurations(pars)
|
45
|
+
content << configurations(cop.department, pars)
|
46
46
|
content << references(cop)
|
47
47
|
content
|
48
48
|
end
|
@@ -136,7 +136,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
136
136
|
content
|
137
137
|
end
|
138
138
|
|
139
|
-
def configurations(pars)
|
139
|
+
def configurations(department, pars)
|
140
140
|
return '' if pars.empty?
|
141
141
|
|
142
142
|
header = ['Name', 'Default value', 'Configurable values']
|
@@ -147,12 +147,20 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
147
147
|
content = configs.map do |name|
|
148
148
|
configurable = configurable_values(pars, name)
|
149
149
|
default = format_table_value(pars[name])
|
150
|
-
|
150
|
+
|
151
|
+
[configuration_name(department, name), default, configurable]
|
151
152
|
end
|
152
153
|
|
153
154
|
h3('Configurable attributes') + to_table(header, content)
|
154
155
|
end
|
155
156
|
|
157
|
+
def configuration_name(department, name)
|
158
|
+
return name unless name == 'AllowMultilineFinalElement'
|
159
|
+
|
160
|
+
filename = "#{department_to_basename(department)}.adoc"
|
161
|
+
"xref:#{filename}#allowmultilinefinalelement[AllowMultilineFinalElement]"
|
162
|
+
end
|
163
|
+
|
156
164
|
# rubocop:disable Metrics/CyclomaticComplexity,Metrics/MethodLength
|
157
165
|
def configurable_values(pars, name)
|
158
166
|
case name
|
@@ -227,10 +235,21 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
227
235
|
content
|
228
236
|
end
|
229
237
|
|
238
|
+
def footer_for_department(department)
|
239
|
+
return '' unless department == :Layout
|
240
|
+
|
241
|
+
filename = "#{department_to_basename(department)}_footer.adoc"
|
242
|
+
file = "#{Dir.pwd}/docs/modules/ROOT/partials/#{filename}"
|
243
|
+
return '' unless File.exist?(file)
|
244
|
+
|
245
|
+
"\ninclude::../partials/#{filename}[]\n"
|
246
|
+
end
|
247
|
+
|
230
248
|
def print_cops_of_department(department)
|
231
249
|
selected_cops = cops_of_department(department)
|
232
250
|
content = +"= #{department}\n"
|
233
251
|
selected_cops.each { |cop| content << print_cop_with_doc(cop) }
|
252
|
+
content << footer_for_department(department)
|
234
253
|
file_name = "#{Dir.pwd}/docs/modules/ROOT/pages/#{department_to_basename(department)}.adoc"
|
235
254
|
File.open(file_name, 'w') do |file|
|
236
255
|
puts "* generated #{file_name}"
|
@@ -35,7 +35,7 @@ module RuboCop
|
|
35
35
|
|
36
36
|
# Checks if this directive relates to single line
|
37
37
|
def single_line?
|
38
|
-
!
|
38
|
+
!comment.text.start_with?(DIRECTIVE_COMMENT_REGEXP)
|
39
39
|
end
|
40
40
|
|
41
41
|
# Checks if this directive contains all the given cop names
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
# A wrapper around patterns array to perform optimized search.
|
5
|
+
#
|
6
|
+
# For projects with a large set of rubocop todo files, most items in `Exclude`/`Include`
|
7
|
+
# are exact file names. It is wasteful to linearly check the list of patterns over and over
|
8
|
+
# to check if the file is relevant to the cop.
|
9
|
+
#
|
10
|
+
# This class partitions an array of patterns into a set of exact match strings and the rest
|
11
|
+
# of the patterns. This way we can firstly do a cheap check in the set and then proceed via
|
12
|
+
# the costly patterns check, if needed.
|
13
|
+
# @api private
|
14
|
+
class FilePatterns
|
15
|
+
@cache = {}.compare_by_identity
|
16
|
+
|
17
|
+
def self.from(patterns)
|
18
|
+
@cache[patterns] ||= new(patterns)
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize(patterns)
|
22
|
+
@strings = Set.new
|
23
|
+
@patterns = []
|
24
|
+
partition_patterns(patterns)
|
25
|
+
end
|
26
|
+
|
27
|
+
def match?(path)
|
28
|
+
@strings.include?(path) || @patterns.any? { |pattern| PathUtil.match_path?(pattern, path) }
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def partition_patterns(patterns)
|
34
|
+
patterns.each do |pattern|
|
35
|
+
if pattern.is_a?(String) && !pattern.match?(/[*{\[?]/)
|
36
|
+
@strings << pattern
|
37
|
+
else
|
38
|
+
@patterns << pattern
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -65,6 +65,10 @@ module RuboCop
|
|
65
65
|
@options.fetch(:offense_counts, true)
|
66
66
|
end
|
67
67
|
|
68
|
+
def auto_gen_enforced_style?
|
69
|
+
@options.fetch(:auto_gen_enforced_style, true)
|
70
|
+
end
|
71
|
+
|
68
72
|
def command
|
69
73
|
command = 'rubocop --auto-gen-config'
|
70
74
|
|
@@ -79,6 +83,8 @@ module RuboCop
|
|
79
83
|
|
80
84
|
command += ' --no-auto-gen-timestamp' unless show_timestamp?
|
81
85
|
|
86
|
+
command += ' --no-auto-gen-enforced-style' unless auto_gen_enforced_style?
|
87
|
+
|
82
88
|
command
|
83
89
|
end
|
84
90
|
|
@@ -172,17 +178,22 @@ module RuboCop
|
|
172
178
|
end
|
173
179
|
|
174
180
|
def output_cop_config(output_buffer, cfg, cop_name)
|
175
|
-
|
176
|
-
# limit is exceeded.
|
177
|
-
cfg_without_enabled = cfg.reject { |key| key == 'Enabled' }
|
178
|
-
|
181
|
+
filtered_cfg = filtered_config(cfg)
|
179
182
|
output_buffer.puts "#{cop_name}:"
|
180
|
-
|
183
|
+
filtered_cfg.each do |key, value|
|
181
184
|
value = value[0] if value.is_a?(Array)
|
182
185
|
output_buffer.puts " #{key}: #{value}"
|
183
186
|
end
|
184
187
|
|
185
|
-
output_offending_files(output_buffer,
|
188
|
+
output_offending_files(output_buffer, filtered_cfg, cop_name)
|
189
|
+
end
|
190
|
+
|
191
|
+
def filtered_config(cfg)
|
192
|
+
# 'Enabled' option will be put into file only if exclude
|
193
|
+
# limit is exceeded.
|
194
|
+
rejected_keys = ['Enabled']
|
195
|
+
rejected_keys << 'EnforcedStyle' unless auto_gen_enforced_style?
|
196
|
+
cfg.reject { |key| rejected_keys.include?(key) }
|
186
197
|
end
|
187
198
|
|
188
199
|
def output_offending_files(output_buffer, cfg, cop_name)
|
data/lib/rubocop/formatter.rb
CHANGED
@@ -6,6 +6,7 @@ module RuboCop
|
|
6
6
|
|
7
7
|
require_relative 'formatter/base_formatter'
|
8
8
|
require_relative 'formatter/simple_text_formatter'
|
9
|
+
|
9
10
|
# relies on simple text
|
10
11
|
require_relative 'formatter/clang_style_formatter'
|
11
12
|
require_relative 'formatter/disabled_config_formatter'
|
@@ -18,11 +19,12 @@ module RuboCop
|
|
18
19
|
require_relative 'formatter/junit_formatter'
|
19
20
|
require_relative 'formatter/markdown_formatter'
|
20
21
|
require_relative 'formatter/offense_count_formatter'
|
22
|
+
require_relative 'formatter/pacman_formatter'
|
21
23
|
require_relative 'formatter/progress_formatter'
|
22
24
|
require_relative 'formatter/quiet_formatter'
|
23
25
|
require_relative 'formatter/tap_formatter'
|
24
26
|
require_relative 'formatter/worst_offenders_formatter'
|
25
|
-
|
27
|
+
|
26
28
|
# relies on progress formatter
|
27
29
|
require_relative 'formatter/auto_gen_config_formatter'
|
28
30
|
|