rubocop 1.40.0 → 1.43.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/LICENSE.txt +1 -1
- data/README.md +2 -2
- data/config/default.yml +52 -2
- data/lib/rubocop/cli.rb +1 -1
- data/lib/rubocop/config.rb +34 -11
- data/lib/rubocop/config_loader.rb +9 -0
- data/lib/rubocop/config_loader_resolver.rb +5 -1
- data/lib/rubocop/config_validator.rb +1 -1
- data/lib/rubocop/cop/badge.rb +9 -4
- data/lib/rubocop/cop/base.rb +83 -66
- data/lib/rubocop/cop/commissioner.rb +8 -3
- data/lib/rubocop/cop/cop.rb +29 -29
- data/lib/rubocop/cop/corrector.rb +23 -11
- data/lib/rubocop/cop/gemspec/dependency_version.rb +16 -18
- data/lib/rubocop/cop/internal_affairs/cop_description.rb +3 -1
- data/lib/rubocop/cop/layout/class_structure.rb +32 -11
- data/lib/rubocop/cop/layout/comment_indentation.rb +3 -1
- 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 +7 -2
- data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +5 -0
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +11 -5
- 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_block_layout.rb +1 -1
- 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/space_around_keyword.rb +1 -1
- data/lib/rubocop/cop/layout/trailing_empty_lines.rb +1 -1
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +11 -4
- data/lib/rubocop/cop/lint/constant_resolution.rb +4 -0
- data/lib/rubocop/cop/lint/debugger.rb +3 -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/non_atomic_file_operation.rb +10 -5
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +19 -0
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +3 -1
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +1 -1
- data/lib/rubocop/cop/lint/regexp_as_condition.rb +6 -0
- data/lib/rubocop/cop/lint/require_parentheses.rb +3 -1
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +8 -19
- data/lib/rubocop/cop/lint/unused_method_argument.rb +2 -1
- data/lib/rubocop/cop/lint/useless_rescue.rb +71 -0
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +5 -3
- data/lib/rubocop/cop/metrics/class_length.rb +1 -1
- data/lib/rubocop/cop/metrics/module_length.rb +1 -1
- data/lib/rubocop/cop/metrics/parameter_lists.rb +27 -0
- data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -4
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +2 -2
- 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 +14 -2
- 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/preceding_following_alignment.rb +1 -1
- 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 +2 -1
- data/lib/rubocop/cop/naming/block_forwarding.rb +1 -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 +28 -25
- data/lib/rubocop/cop/security/compound_hash.rb +2 -1
- data/lib/rubocop/cop/style/alias.rb +9 -1
- data/lib/rubocop/cop/style/block_comments.rb +1 -1
- data/lib/rubocop/cop/style/concat_array_literals.rb +86 -0
- data/lib/rubocop/cop/style/documentation.rb +11 -5
- data/lib/rubocop/cop/style/guard_clause.rb +17 -9
- data/lib/rubocop/cop/style/hash_each_methods.rb +13 -1
- data/lib/rubocop/cop/style/hash_syntax.rb +11 -7
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +15 -0
- data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -3
- 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/map_to_set.rb +61 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +12 -9
- data/lib/rubocop/cop/style/method_def_parentheses.rb +11 -4
- data/lib/rubocop/cop/style/min_max_comparison.rb +73 -0
- data/lib/rubocop/cop/style/missing_else.rb +13 -1
- data/lib/rubocop/cop/style/operator_method_call.rb +15 -1
- data/lib/rubocop/cop/style/redundant_constant_base.rb +13 -0
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +39 -0
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +2 -1
- data/lib/rubocop/cop/style/redundant_string_escape.rb +6 -3
- data/lib/rubocop/cop/style/require_order.rb +63 -9
- data/lib/rubocop/cop/style/select_by_regexp.rb +6 -2
- data/lib/rubocop/cop/style/semicolon.rb +2 -1
- data/lib/rubocop/cop/style/signal_exception.rb +8 -6
- data/lib/rubocop/cop/style/string_hash_keys.rb +4 -1
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -4
- data/lib/rubocop/cop/style/word_array.rb +41 -0
- data/lib/rubocop/cop/style/yoda_expression.rb +81 -0
- data/lib/rubocop/cop/style/zero_length_predicate.rb +31 -14
- data/lib/rubocop/cop/team.rb +29 -29
- data/lib/rubocop/cop/util.rb +31 -4
- data/lib/rubocop/cop/variable_force.rb +0 -3
- data/lib/rubocop/cops_documentation_generator.rb +33 -11
- data/lib/rubocop/directive_comment.rb +1 -1
- data/lib/rubocop/file_patterns.rb +43 -0
- data/lib/rubocop/formatter.rb +2 -0
- data/lib/rubocop/options.rb +1 -1
- data/lib/rubocop/path_util.rb +38 -22
- data/lib/rubocop/result_cache.rb +1 -1
- data/lib/rubocop/runner.rb +10 -3
- data/lib/rubocop/target_finder.rb +1 -1
- data/lib/rubocop/target_ruby.rb +0 -1
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +7 -1
- metadata +16 -10
- data/lib/rubocop/optimized_patterns.rb +0 -38
@@ -34,43 +34,55 @@ module RuboCop
|
|
34
34
|
class ZeroLengthPredicate < Base
|
35
35
|
extend AutoCorrector
|
36
36
|
|
37
|
-
ZERO_MSG = 'Use `empty?` instead of `%<
|
38
|
-
NONZERO_MSG = 'Use `!empty?` instead of `%<
|
37
|
+
ZERO_MSG = 'Use `empty?` instead of `%<current>s`.'
|
38
|
+
NONZERO_MSG = 'Use `!empty?` instead of `%<current>s`.'
|
39
39
|
|
40
40
|
RESTRICT_ON_SEND = %i[size length].freeze
|
41
41
|
|
42
42
|
def on_send(node)
|
43
43
|
check_zero_length_predicate(node)
|
44
|
-
|
44
|
+
check_zero_length_comparison(node)
|
45
|
+
check_nonzero_length_comparison(node)
|
45
46
|
end
|
46
47
|
|
47
48
|
private
|
48
49
|
|
49
50
|
def check_zero_length_predicate(node)
|
50
|
-
|
51
|
-
return unless zero_length_predicate
|
51
|
+
return unless (length_method = zero_length_predicate(node.parent))
|
52
52
|
|
53
|
-
|
53
|
+
offense = node.loc.selector.join(node.parent.source_range.end)
|
54
|
+
message = format(ZERO_MSG, current: "#{length_method}.zero?")
|
55
|
+
|
56
|
+
add_offense(offense, message: message) do |corrector|
|
57
|
+
corrector.replace(offense, 'empty?')
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def check_zero_length_comparison(node)
|
62
|
+
zero_length_comparison = zero_length_comparison(node.parent)
|
63
|
+
return unless zero_length_comparison
|
64
|
+
|
65
|
+
lhs, opr, rhs = zero_length_comparison
|
54
66
|
|
55
67
|
return if non_polymorphic_collection?(node.parent)
|
56
68
|
|
57
69
|
add_offense(
|
58
|
-
node.parent, message: format(ZERO_MSG,
|
70
|
+
node.parent, message: format(ZERO_MSG, current: "#{lhs} #{opr} #{rhs}")
|
59
71
|
) do |corrector|
|
60
72
|
corrector.replace(node.parent, replacement(node.parent))
|
61
73
|
end
|
62
74
|
end
|
63
75
|
|
64
|
-
def
|
65
|
-
|
66
|
-
return unless
|
76
|
+
def check_nonzero_length_comparison(node)
|
77
|
+
nonzero_length_comparison = nonzero_length_comparison(node.parent)
|
78
|
+
return unless nonzero_length_comparison
|
67
79
|
|
68
|
-
lhs, opr, rhs =
|
80
|
+
lhs, opr, rhs = nonzero_length_comparison
|
69
81
|
|
70
82
|
return if non_polymorphic_collection?(node.parent)
|
71
83
|
|
72
84
|
add_offense(
|
73
|
-
node.parent, message: format(NONZERO_MSG,
|
85
|
+
node.parent, message: format(NONZERO_MSG, current: "#{lhs} #{opr} #{rhs}")
|
74
86
|
) do |corrector|
|
75
87
|
corrector.replace(node.parent, replacement(node.parent))
|
76
88
|
end
|
@@ -78,14 +90,19 @@ module RuboCop
|
|
78
90
|
|
79
91
|
# @!method zero_length_predicate(node)
|
80
92
|
def_node_matcher :zero_length_predicate, <<~PATTERN
|
93
|
+
(send (send (...) ${:length :size}) :zero?)
|
94
|
+
PATTERN
|
95
|
+
|
96
|
+
# @!method zero_length_comparison(node)
|
97
|
+
def_node_matcher :zero_length_comparison, <<~PATTERN
|
81
98
|
{(send (send (...) ${:length :size}) $:== (int $0))
|
82
99
|
(send (int $0) $:== (send (...) ${:length :size}))
|
83
100
|
(send (send (...) ${:length :size}) $:< (int $1))
|
84
101
|
(send (int $1) $:> (send (...) ${:length :size}))}
|
85
102
|
PATTERN
|
86
103
|
|
87
|
-
# @!method
|
88
|
-
def_node_matcher :
|
104
|
+
# @!method nonzero_length_comparison(node)
|
105
|
+
def_node_matcher :nonzero_length_comparison, <<~PATTERN
|
89
106
|
{(send (send (...) ${:length :size}) ${:> :!=} (int $0))
|
90
107
|
(send (int $0) ${:< :!=} (send (...) ${:length :size}))}
|
91
108
|
PATTERN
|
data/lib/rubocop/cop/team.rb
CHANGED
@@ -10,20 +10,6 @@ module RuboCop
|
|
10
10
|
# first the ones needed for autocorrection (if any), then the rest
|
11
11
|
# (unless autocorrections happened).
|
12
12
|
class Team
|
13
|
-
attr_reader :errors, :warnings, :updated_source_file, :cops
|
14
|
-
|
15
|
-
alias updated_source_file? updated_source_file
|
16
|
-
|
17
|
-
def initialize(cops, config = nil, options = {})
|
18
|
-
@cops = cops
|
19
|
-
@config = config
|
20
|
-
@options = options
|
21
|
-
reset
|
22
|
-
@ready = true
|
23
|
-
|
24
|
-
validate_config
|
25
|
-
end
|
26
|
-
|
27
13
|
# @return [Team]
|
28
14
|
def self.new(cop_or_classes, config, options = {})
|
29
15
|
# Support v0 api:
|
@@ -47,6 +33,35 @@ module RuboCop
|
|
47
33
|
end
|
48
34
|
end
|
49
35
|
|
36
|
+
# @return [Array<Force>] needed for the given cops
|
37
|
+
def self.forces_for(cops)
|
38
|
+
needed = Hash.new { |h, k| h[k] = [] }
|
39
|
+
cops.each do |cop|
|
40
|
+
forces = cop.class.joining_forces
|
41
|
+
if forces.is_a?(Array)
|
42
|
+
forces.each { |force| needed[force] << cop }
|
43
|
+
elsif forces
|
44
|
+
needed[forces] << cop
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
needed.map { |force_class, joining_cops| force_class.new(joining_cops) }
|
49
|
+
end
|
50
|
+
|
51
|
+
attr_reader :errors, :warnings, :updated_source_file, :cops
|
52
|
+
|
53
|
+
alias updated_source_file? updated_source_file
|
54
|
+
|
55
|
+
def initialize(cops, config = nil, options = {})
|
56
|
+
@cops = cops
|
57
|
+
@config = config
|
58
|
+
@options = options
|
59
|
+
reset
|
60
|
+
@ready = true
|
61
|
+
|
62
|
+
validate_config
|
63
|
+
end
|
64
|
+
|
50
65
|
def autocorrect?
|
51
66
|
@options[:autocorrect]
|
52
67
|
end
|
@@ -94,21 +109,6 @@ module RuboCop
|
|
94
109
|
@forces ||= self.class.forces_for(cops)
|
95
110
|
end
|
96
111
|
|
97
|
-
# @return [Array<Force>] needed for the given cops
|
98
|
-
def self.forces_for(cops)
|
99
|
-
needed = Hash.new { |h, k| h[k] = [] }
|
100
|
-
cops.each do |cop|
|
101
|
-
forces = cop.class.joining_forces
|
102
|
-
if forces.is_a?(Array)
|
103
|
-
forces.each { |force| needed[force] << cop }
|
104
|
-
elsif forces
|
105
|
-
needed[forces] << cop
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
needed.map { |force_class, joining_cops| force_class.new(joining_cops) }
|
110
|
-
end
|
111
|
-
|
112
112
|
def external_dependency_checksum
|
113
113
|
keys = cops.map(&:external_dependency_checksum).compact
|
114
114
|
Digest::SHA1.hexdigest(keys.join)
|
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,8 +172,11 @@ 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
|
@@ -162,6 +185,10 @@ module RuboCop
|
|
162
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
|
@@ -108,7 +108,6 @@ module RuboCop
|
|
108
108
|
:skip_children
|
109
109
|
end
|
110
110
|
|
111
|
-
# rubocop:disable Layout/ClassStructure
|
112
111
|
NODE_HANDLER_METHOD_NAMES = [
|
113
112
|
[VARIABLE_ASSIGNMENT_TYPE, :process_variable_assignment],
|
114
113
|
[REGEXP_NAMED_CAPTURE_TYPE, :process_regexp_named_captures],
|
@@ -123,8 +122,6 @@ module RuboCop
|
|
123
122
|
*SCOPE_TYPES.product([:process_scope])
|
124
123
|
].to_h.freeze
|
125
124
|
private_constant :NODE_HANDLER_METHOD_NAMES
|
126
|
-
# rubocop:enable Layout/ClassStructure
|
127
|
-
|
128
125
|
def node_handler_method_name(node)
|
129
126
|
NODE_HANDLER_METHOD_NAMES[node.type]
|
130
127
|
end
|
@@ -33,7 +33,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
33
33
|
cops.with_department(department).sort!
|
34
34
|
end
|
35
35
|
|
36
|
-
def cops_body(cop, description, examples_objects, safety_objects, pars) # rubocop:disable Metrics/AbcSize
|
36
|
+
def cops_body(cop, description, examples_objects, safety_objects, see_objects, pars) # rubocop:disable Metrics/AbcSize, Metrics/ParameterLists
|
37
37
|
check_examples_to_have_the_default_enforced_style!(examples_objects, cop)
|
38
38
|
|
39
39
|
content = h2(cop.cop_name)
|
@@ -42,8 +42,8 @@ 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)
|
46
|
-
content << references(cop)
|
45
|
+
content << configurations(cop.department, pars)
|
46
|
+
content << references(cop, see_objects)
|
47
47
|
content
|
48
48
|
end
|
49
49
|
|
@@ -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
|
@@ -216,21 +224,34 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
216
224
|
end
|
217
225
|
end
|
218
226
|
|
219
|
-
def references(cop)
|
227
|
+
def references(cop, see_objects) # rubocop:disable Metrics/AbcSize
|
220
228
|
cop_config = config.for_cop(cop)
|
221
229
|
urls = RuboCop::Cop::MessageAnnotator.new(config, cop.name, cop_config, {}).urls
|
222
|
-
return '' if urls.empty?
|
230
|
+
return '' if urls.empty? && see_objects.empty?
|
223
231
|
|
224
232
|
content = h3('References')
|
225
233
|
content << urls.map { |url| "* #{url}" }.join("\n")
|
226
|
-
content << "\n"
|
234
|
+
content << "\n" unless urls.empty?
|
235
|
+
content << see_objects.map { |see| "* #{see.name}" }.join("\n")
|
236
|
+
content << "\n" unless see_objects.empty?
|
227
237
|
content
|
228
238
|
end
|
229
239
|
|
240
|
+
def footer_for_department(department)
|
241
|
+
return '' unless department == :Layout
|
242
|
+
|
243
|
+
filename = "#{department_to_basename(department)}_footer.adoc"
|
244
|
+
file = "#{Dir.pwd}/docs/modules/ROOT/partials/#{filename}"
|
245
|
+
return '' unless File.exist?(file)
|
246
|
+
|
247
|
+
"\ninclude::../partials/#{filename}[]\n"
|
248
|
+
end
|
249
|
+
|
230
250
|
def print_cops_of_department(department)
|
231
251
|
selected_cops = cops_of_department(department)
|
232
252
|
content = +"= #{department}\n"
|
233
253
|
selected_cops.each { |cop| content << print_cop_with_doc(cop) }
|
254
|
+
content << footer_for_department(department)
|
234
255
|
file_name = "#{Dir.pwd}/docs/modules/ROOT/pages/#{department_to_basename(department)}.adoc"
|
235
256
|
File.open(file_name, 'w') do |file|
|
236
257
|
puts "* generated #{file_name}"
|
@@ -238,7 +259,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
238
259
|
end
|
239
260
|
end
|
240
261
|
|
241
|
-
def print_cop_with_doc(cop)
|
262
|
+
def print_cop_with_doc(cop) # rubocop:todo Metrics/AbcSize, Metrics/MethodLength
|
242
263
|
cop_config = config.for_cop(cop)
|
243
264
|
non_display_keys = %w[
|
244
265
|
Description Enabled StyleGuide Reference Safe SafeAutoCorrect VersionAdded
|
@@ -246,13 +267,14 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
246
267
|
]
|
247
268
|
pars = cop_config.reject { |k| non_display_keys.include? k }
|
248
269
|
description = 'No documentation'
|
249
|
-
examples_object = safety_object = []
|
270
|
+
examples_object = safety_object = see_object = []
|
250
271
|
cop_code(cop) do |code_object|
|
251
272
|
description = code_object.docstring unless code_object.docstring.blank?
|
252
273
|
examples_object = code_object.tags('example')
|
253
274
|
safety_object = code_object.tags('safety')
|
275
|
+
see_object = code_object.tags('see')
|
254
276
|
end
|
255
|
-
cops_body(cop, description, examples_object, safety_object, pars)
|
277
|
+
cops_body(cop, description, examples_object, safety_object, see_object, pars)
|
256
278
|
end
|
257
279
|
|
258
280
|
def cop_code(cop)
|
@@ -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
|
data/lib/rubocop/formatter.rb
CHANGED
data/lib/rubocop/options.rb
CHANGED
@@ -465,7 +465,7 @@ module RuboCop
|
|
465
465
|
|
466
466
|
# This module contains help texts for command line options.
|
467
467
|
# @api private
|
468
|
-
module OptionsHelp
|
468
|
+
module OptionsHelp
|
469
469
|
MAX_EXCL = RuboCop::Options::DEFAULT_MAXIMUM_EXCLUSION_ITEMS.to_s
|
470
470
|
FORMATTER_OPTION_LIST = RuboCop::Formatter::FormatterSet::BUILTIN_FORMATTERS_FOR_KEYS.keys
|
471
471
|
|
data/lib/rubocop/path_util.rb
CHANGED
@@ -3,33 +3,44 @@
|
|
3
3
|
module RuboCop
|
4
4
|
# Common methods and behaviors for dealing with paths.
|
5
5
|
module PathUtil
|
6
|
+
class << self
|
7
|
+
attr_accessor :relative_paths_cache
|
8
|
+
end
|
9
|
+
self.relative_paths_cache = Hash.new { |hash, key| hash[key] = {} }
|
10
|
+
|
6
11
|
module_function
|
7
12
|
|
8
13
|
def relative_path(path, base_dir = Dir.pwd)
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
14
|
+
PathUtil.relative_paths_cache[base_dir][path] ||=
|
15
|
+
# Optimization for the common case where path begins with the base
|
16
|
+
# dir. Just cut off the first part.
|
17
|
+
if path.start_with?(base_dir)
|
18
|
+
base_dir_length = base_dir.length
|
19
|
+
result_length = path.length - base_dir_length - 1
|
20
|
+
path[base_dir_length + 1, result_length]
|
21
|
+
else
|
22
|
+
path_name = Pathname.new(File.expand_path(path))
|
23
|
+
begin
|
24
|
+
path_name.relative_path_from(Pathname.new(base_dir)).to_s
|
25
|
+
rescue ArgumentError
|
26
|
+
path
|
27
|
+
end
|
28
|
+
end
|
23
29
|
end
|
24
30
|
|
25
|
-
|
26
|
-
|
27
|
-
base_dir = Dir.pwd
|
31
|
+
SMART_PATH_CACHE = {} # rubocop:disable Style/MutableConstant
|
32
|
+
private_constant :SMART_PATH_CACHE
|
28
33
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
34
|
+
def smart_path(path)
|
35
|
+
SMART_PATH_CACHE[path] ||= begin
|
36
|
+
# Ideally, we calculate this relative to the project root.
|
37
|
+
base_dir = Dir.pwd
|
38
|
+
|
39
|
+
if path.start_with? base_dir
|
40
|
+
relative_path(path, base_dir)
|
41
|
+
else
|
42
|
+
path
|
43
|
+
end
|
33
44
|
end
|
34
45
|
end
|
35
46
|
|
@@ -40,7 +51,7 @@ module RuboCop
|
|
40
51
|
matches =
|
41
52
|
if pattern == path
|
42
53
|
true
|
43
|
-
elsif
|
54
|
+
elsif glob?(pattern)
|
44
55
|
File.fnmatch?(pattern, path, File::FNM_PATHNAME | File::FNM_EXTGLOB)
|
45
56
|
end
|
46
57
|
|
@@ -62,6 +73,11 @@ module RuboCop
|
|
62
73
|
%r{\A([A-Z]:)?/}i.match?(path)
|
63
74
|
end
|
64
75
|
|
76
|
+
# Returns true for a glob
|
77
|
+
def glob?(path)
|
78
|
+
path.match?(/[*{\[?]/)
|
79
|
+
end
|
80
|
+
|
65
81
|
def hidden_file_in_not_hidden_dir?(pattern, path)
|
66
82
|
hidden_file?(path) &&
|
67
83
|
File.fnmatch?(
|
data/lib/rubocop/result_cache.rb
CHANGED
@@ -53,7 +53,7 @@ module RuboCop
|
|
53
53
|
def remove_oldest_files(files, dirs, cache_root, verbose)
|
54
54
|
# Add 1 to half the number of files, so that we remove the file if
|
55
55
|
# there's only 1 left.
|
56
|
-
remove_count =
|
56
|
+
remove_count = (files.length / 2) + 1
|
57
57
|
puts "Removing the #{remove_count} oldest files from #{cache_root}" if verbose
|
58
58
|
sorted = files.sort_by { |path| File.mtime(path) }
|
59
59
|
remove_files(sorted, dirs, remove_count)
|
data/lib/rubocop/runner.rb
CHANGED
@@ -27,6 +27,11 @@ module RuboCop
|
|
27
27
|
# @api private
|
28
28
|
MAX_ITERATIONS = 200
|
29
29
|
|
30
|
+
# @api private
|
31
|
+
REDUNDANT_COP_DISABLE_DIRECTIVE_RULES = %w[
|
32
|
+
Lint/RedundantCopDisableDirective RedundantCopDisableDirective Lint
|
33
|
+
].freeze
|
34
|
+
|
30
35
|
attr_reader :errors, :warnings
|
31
36
|
attr_writer :aborting
|
32
37
|
|
@@ -194,7 +199,9 @@ module RuboCop
|
|
194
199
|
end
|
195
200
|
|
196
201
|
def check_for_redundant_disables?(source)
|
197
|
-
|
202
|
+
return false if source.disabled_line_ranges.empty? || except_redundant_cop_disable_directive?
|
203
|
+
|
204
|
+
!@options[:only]
|
198
205
|
end
|
199
206
|
|
200
207
|
def redundant_cop_disable_directive(file)
|
@@ -205,8 +212,8 @@ module RuboCop
|
|
205
212
|
yield cop if cop.relevant_file?(file)
|
206
213
|
end
|
207
214
|
|
208
|
-
def
|
209
|
-
@options[:except]
|
215
|
+
def except_redundant_cop_disable_directive?
|
216
|
+
@options[:except] && (@options[:except] & REDUNDANT_COP_DISABLE_DIRECTIVE_RULES).any?
|
210
217
|
end
|
211
218
|
|
212
219
|
def file_started(file)
|
@@ -88,7 +88,7 @@ module RuboCop
|
|
88
88
|
patterns.map! { |dir| File.join(dir, '*') }
|
89
89
|
# We need this special case to avoid creating the pattern
|
90
90
|
# /**/* which searches the entire file system.
|
91
|
-
patterns = [File.join(
|
91
|
+
patterns = [File.join(base_dir, '**/*')] if patterns.empty?
|
92
92
|
|
93
93
|
Dir.glob(patterns, flags).select { |path| FileTest.file?(path) }
|
94
94
|
end
|
data/lib/rubocop/target_ruby.rb
CHANGED
data/lib/rubocop/version.rb
CHANGED
data/lib/rubocop.rb
CHANGED
@@ -23,8 +23,8 @@ require_relative 'rubocop/ext/processed_source'
|
|
23
23
|
|
24
24
|
require_relative 'rubocop/error'
|
25
25
|
require_relative 'rubocop/file_finder'
|
26
|
+
require_relative 'rubocop/file_patterns'
|
26
27
|
require_relative 'rubocop/name_similarity'
|
27
|
-
require_relative 'rubocop/optimized_patterns'
|
28
28
|
require_relative 'rubocop/path_util'
|
29
29
|
require_relative 'rubocop/platform'
|
30
30
|
require_relative 'rubocop/string_interpreter'
|
@@ -399,6 +399,7 @@ require_relative 'rubocop/cop/lint/useless_access_modifier'
|
|
399
399
|
require_relative 'rubocop/cop/lint/useless_assignment'
|
400
400
|
require_relative 'rubocop/cop/lint/useless_else_without_rescue'
|
401
401
|
require_relative 'rubocop/cop/lint/useless_method_definition'
|
402
|
+
require_relative 'rubocop/cop/lint/useless_rescue'
|
402
403
|
require_relative 'rubocop/cop/lint/useless_ruby2_keywords'
|
403
404
|
require_relative 'rubocop/cop/lint/useless_setter_call'
|
404
405
|
require_relative 'rubocop/cop/lint/useless_times'
|
@@ -470,6 +471,7 @@ require_relative 'rubocop/cop/style/combinable_loops'
|
|
470
471
|
require_relative 'rubocop/cop/style/command_literal'
|
471
472
|
require_relative 'rubocop/cop/style/comment_annotation'
|
472
473
|
require_relative 'rubocop/cop/style/commented_keyword'
|
474
|
+
require_relative 'rubocop/cop/style/concat_array_literals'
|
473
475
|
require_relative 'rubocop/cop/style/conditional_assignment'
|
474
476
|
require_relative 'rubocop/cop/style/constant_visibility'
|
475
477
|
require_relative 'rubocop/cop/style/copyright'
|
@@ -537,14 +539,17 @@ require_relative 'rubocop/cop/style/lambda_call'
|
|
537
539
|
require_relative 'rubocop/cop/style/line_end_concatenation'
|
538
540
|
require_relative 'rubocop/cop/style/magic_comment_format'
|
539
541
|
require_relative 'rubocop/cop/style/map_to_hash'
|
542
|
+
require_relative 'rubocop/cop/style/map_to_set'
|
540
543
|
require_relative 'rubocop/cop/style/method_call_without_args_parentheses'
|
541
544
|
require_relative 'rubocop/cop/style/method_call_with_args_parentheses'
|
545
|
+
require_relative 'rubocop/cop/style/min_max_comparison'
|
542
546
|
require_relative 'rubocop/cop/style/multiline_in_pattern_then'
|
543
547
|
require_relative 'rubocop/cop/style/numbered_parameters'
|
544
548
|
require_relative 'rubocop/cop/style/open_struct_use'
|
545
549
|
require_relative 'rubocop/cop/style/operator_method_call'
|
546
550
|
require_relative 'rubocop/cop/style/redundant_assignment'
|
547
551
|
require_relative 'rubocop/cop/style/redundant_constant_base'
|
552
|
+
require_relative 'rubocop/cop/style/redundant_double_splat_hash_braces'
|
548
553
|
require_relative 'rubocop/cop/style/redundant_each'
|
549
554
|
require_relative 'rubocop/cop/style/redundant_fetch_block'
|
550
555
|
require_relative 'rubocop/cop/style/redundant_file_extension_in_require'
|
@@ -673,6 +678,7 @@ require_relative 'rubocop/cop/style/while_until_do'
|
|
673
678
|
require_relative 'rubocop/cop/style/while_until_modifier'
|
674
679
|
require_relative 'rubocop/cop/style/word_array'
|
675
680
|
require_relative 'rubocop/cop/style/yoda_condition'
|
681
|
+
require_relative 'rubocop/cop/style/yoda_expression'
|
676
682
|
require_relative 'rubocop/cop/style/zero_length_predicate'
|
677
683
|
|
678
684
|
require_relative 'rubocop/cop/security/compound_hash'
|