rubocop 1.40.0 → 1.41.1
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 +19 -0
- data/lib/rubocop/config.rb +28 -5
- data/lib/rubocop/config_loader.rb +9 -0
- data/lib/rubocop/config_validator.rb +1 -1
- data/lib/rubocop/cop/badge.rb +9 -4
- data/lib/rubocop/cop/base.rb +25 -9
- data/lib/rubocop/cop/commissioner.rb +8 -3
- data/lib/rubocop/cop/cop.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/cop_description.rb +3 -1
- data/lib/rubocop/cop/layout/class_structure.rb +0 -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 +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/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/redundant_cop_disable_directive.rb +3 -1
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +1 -1
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +8 -19
- 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/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 +5 -1
- 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 +1 -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 +6 -3
- data/lib/rubocop/cop/style/alias.rb +9 -1
- data/lib/rubocop/cop/style/concat_array_literals.rb +66 -0
- data/lib/rubocop/cop/style/documentation.rb +11 -5
- data/lib/rubocop/cop/style/guard_clause.rb +6 -2
- 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/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_string_escape.rb +2 -1
- data/lib/rubocop/cop/style/require_order.rb +61 -9
- data/lib/rubocop/cop/style/semicolon.rb +2 -1
- data/lib/rubocop/cop/util.rb +31 -4
- 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 +20 -14
- data/lib/rubocop/target_finder.rb +1 -1
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +3 -1
- metadata +6 -4
- data/lib/rubocop/optimized_patterns.rb +0 -38
@@ -128,6 +128,7 @@ module RuboCop
|
|
128
128
|
end
|
129
129
|
end
|
130
130
|
|
131
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
131
132
|
def each_already_disabled(cop, line_ranges)
|
132
133
|
line_ranges.each_cons(2) do |previous_range, range|
|
133
134
|
next if ignore_offense?(range)
|
@@ -152,9 +153,10 @@ module RuboCop
|
|
152
153
|
cop
|
153
154
|
end
|
154
155
|
|
155
|
-
yield comment, redundant
|
156
|
+
yield comment, redundant if redundant
|
156
157
|
end
|
157
158
|
end
|
159
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
158
160
|
|
159
161
|
def find_redundant_cop(cop, range)
|
160
162
|
cop_offenses = offenses_to_check.select { |offense| offense.cop_name == cop }
|
@@ -42,7 +42,7 @@ module RuboCop
|
|
42
42
|
MSG = 'Unnecessary enabling of %<cop>s.'
|
43
43
|
|
44
44
|
def on_new_investigation
|
45
|
-
return if processed_source.blank?
|
45
|
+
return if processed_source.blank? || !processed_source.raw_source.include?('enable')
|
46
46
|
|
47
47
|
offenses = processed_source.comment_config.extra_enabled_comments
|
48
48
|
offenses.each { |comment, cop_names| register_offense(comment, cop_names) }
|
@@ -45,13 +45,12 @@ module RuboCop
|
|
45
45
|
bad_method?(node) do |safe_nav, method|
|
46
46
|
return if nil_methods.include?(method) || PLUS_MINUS_METHODS.include?(node.method_name)
|
47
47
|
|
48
|
-
method_chain = method_chain(node)
|
49
48
|
location =
|
50
49
|
Parser::Source::Range.new(node.source_range.source_buffer,
|
51
50
|
safe_nav.source_range.end_pos,
|
52
|
-
|
51
|
+
node.source_range.end_pos)
|
53
52
|
add_offense(location) do |corrector|
|
54
|
-
autocorrect(corrector, offense_range: location, send_node:
|
53
|
+
autocorrect(corrector, offense_range: location, send_node: node)
|
55
54
|
end
|
56
55
|
end
|
57
56
|
end
|
@@ -63,12 +62,12 @@ module RuboCop
|
|
63
62
|
# @return [String]
|
64
63
|
def add_safe_navigation_operator(offense_range:, send_node:)
|
65
64
|
source =
|
66
|
-
if
|
65
|
+
if brackets?(send_node)
|
67
66
|
format(
|
68
67
|
'%<method_name>s(%<arguments>s)%<method_chain>s',
|
69
|
-
arguments:
|
70
|
-
method_name:
|
71
|
-
method_chain:
|
68
|
+
arguments: send_node.arguments.map(&:source).join(', '),
|
69
|
+
method_name: send_node.method_name,
|
70
|
+
method_chain: send_node.source_range.end.join(send_node.source_range.end).source
|
72
71
|
)
|
73
72
|
else
|
74
73
|
offense_range.source
|
@@ -90,18 +89,8 @@ module RuboCop
|
|
90
89
|
)
|
91
90
|
end
|
92
91
|
|
93
|
-
def
|
94
|
-
|
95
|
-
chain = chain.parent if chain.send_type? && chain.parent&.call_type?
|
96
|
-
chain
|
97
|
-
end
|
98
|
-
|
99
|
-
def find_brackets(send_node)
|
100
|
-
return send_node if send_node.method?(:[]) || send_node.method?(:[]=)
|
101
|
-
|
102
|
-
send_node.descendants.detect do |node|
|
103
|
-
node.send_type? && (node.method?(:[]) || node.method?(:[]=))
|
104
|
-
end
|
92
|
+
def brackets?(send_node)
|
93
|
+
send_node.method?(:[]) || send_node.method?(:[]=)
|
105
94
|
end
|
106
95
|
end
|
107
96
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Metrics
|
6
|
-
# Checks if the length a class exceeds some maximum value.
|
6
|
+
# Checks if the length of a class exceeds some maximum value.
|
7
7
|
# Comment lines can optionally be ignored.
|
8
8
|
# The maximum allowed length is configurable.
|
9
9
|
#
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Metrics
|
6
|
-
# Checks if the length a module exceeds some maximum value.
|
6
|
+
# Checks if the length of a module exceeds some maximum value.
|
7
7
|
# Comment lines can optionally be ignored.
|
8
8
|
# The maximum allowed length is configurable.
|
9
9
|
#
|
@@ -58,8 +58,8 @@ module RuboCop
|
|
58
58
|
end
|
59
59
|
|
60
60
|
def normalize_foldable_types(types)
|
61
|
-
types.
|
62
|
-
types.
|
61
|
+
types.push(:str, :dstr) if types.delete(:heredoc)
|
62
|
+
types.push(:send, :csend) if types.delete(:method_call)
|
63
63
|
types
|
64
64
|
end
|
65
65
|
|
@@ -28,7 +28,7 @@ module RuboCop
|
|
28
28
|
|
29
29
|
each_bad_alignment(items, base_column) do |current|
|
30
30
|
expr = current.source_range
|
31
|
-
if @current_offenses
|
31
|
+
if @current_offenses&.any? { |o| within?(expr, o.location) }
|
32
32
|
# If this offense is within a line range that is already being
|
33
33
|
# realigned by autocorrect, we report the offense without
|
34
34
|
# autocorrecting it. Two rewrites in the same area by the same
|
@@ -7,11 +7,11 @@ module RuboCop
|
|
7
7
|
SIGILS = '@$' # if a variable starts with a sigil it will be removed
|
8
8
|
|
9
9
|
def allowed_identifier?(name)
|
10
|
-
allowed_identifiers.include?(name.to_s.delete(SIGILS))
|
10
|
+
!allowed_identifiers.empty? && allowed_identifiers.include?(name.to_s.delete(SIGILS))
|
11
11
|
end
|
12
12
|
|
13
13
|
def allowed_identifiers
|
14
|
-
cop_config.fetch('AllowedIdentifiers'
|
14
|
+
cop_config.fetch('AllowedIdentifiers') { [] }
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
@@ -41,18 +41,25 @@ module RuboCop
|
|
41
41
|
def split_comment(comment)
|
42
42
|
# Sort keywords by reverse length so that if a keyword is in a phrase
|
43
43
|
# but also on its own, both will match properly.
|
44
|
-
keywords_regex = Regexp.new(
|
45
|
-
Regexp.union(keywords.sort_by { |w| -w.length }).source,
|
46
|
-
Regexp::IGNORECASE
|
47
|
-
)
|
48
|
-
regex = /^(# ?)(\b#{keywords_regex}\b)(\s*:)?(\s+)?(\S+)?/i
|
49
|
-
|
50
44
|
match = comment.text.match(regex)
|
51
45
|
return false unless match
|
52
46
|
|
53
47
|
match.captures
|
54
48
|
end
|
55
49
|
|
50
|
+
KEYWORDS_REGEX_CACHE = {} # rubocop:disable Layout/ClassStructure, Style/MutableConstant
|
51
|
+
private_constant :KEYWORDS_REGEX_CACHE
|
52
|
+
|
53
|
+
def regex
|
54
|
+
KEYWORDS_REGEX_CACHE[keywords] ||= begin
|
55
|
+
keywords_regex = Regexp.new(
|
56
|
+
Regexp.union(keywords.sort_by { |w| -w.length }).source,
|
57
|
+
Regexp::IGNORECASE
|
58
|
+
)
|
59
|
+
/^(# ?)(\b#{keywords_regex}\b)(\s*:)?(\s+)?(\S+)?/i
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
56
63
|
def keyword_appearance?
|
57
64
|
keyword && (colon || space)
|
58
65
|
end
|
@@ -20,19 +20,30 @@ module RuboCop
|
|
20
20
|
style_detected(possibilities)
|
21
21
|
end
|
22
22
|
|
23
|
+
SYMBOL_TO_STRING_CACHE = Hash.new do |hash, key|
|
24
|
+
hash[key] = key.to_s if key.is_a?(Symbol)
|
25
|
+
end
|
26
|
+
private_constant :SYMBOL_TO_STRING_CACHE
|
27
|
+
|
28
|
+
# rubocop:disable Metrics
|
23
29
|
def style_detected(detected)
|
24
30
|
return if no_acceptable_style?
|
25
31
|
|
26
|
-
#
|
27
|
-
#
|
28
|
-
|
32
|
+
# This logic is more complex than it needs to be
|
33
|
+
# to avoid allocating Arrays in the hot code path.
|
34
|
+
updated_list =
|
35
|
+
if detected_style
|
36
|
+
if detected_style.size == 1 && detected_style.include?(SYMBOL_TO_STRING_CACHE[detected])
|
37
|
+
detected_style
|
38
|
+
else
|
39
|
+
detected_as_strings = SYMBOL_TO_STRING_CACHE.values_at(*detected)
|
40
|
+
detected_style & detected_as_strings
|
41
|
+
end
|
42
|
+
else
|
43
|
+
# We haven't observed any specific style yet.
|
44
|
+
SYMBOL_TO_STRING_CACHE.values_at(*detected)
|
45
|
+
end
|
29
46
|
|
30
|
-
updated_list = if detected_style
|
31
|
-
detected_style & detected_as_strings
|
32
|
-
else
|
33
|
-
# We haven't observed any specific style yet.
|
34
|
-
detected_as_strings
|
35
|
-
end
|
36
47
|
if updated_list.empty?
|
37
48
|
no_acceptable_style!
|
38
49
|
else
|
@@ -40,6 +51,7 @@ module RuboCop
|
|
40
51
|
config_to_allow_offenses[style_parameter_name] = updated_list.first
|
41
52
|
end
|
42
53
|
end
|
54
|
+
# rubocop:enable Metrics
|
43
55
|
|
44
56
|
def no_acceptable_style?
|
45
57
|
config_to_allow_offenses['Enabled'] == false
|
@@ -7,12 +7,12 @@ module RuboCop
|
|
7
7
|
module FirstElementLineBreak
|
8
8
|
private
|
9
9
|
|
10
|
-
def check_method_line_break(node, children)
|
10
|
+
def check_method_line_break(node, children, ignore_last: false)
|
11
11
|
return if children.empty?
|
12
12
|
|
13
13
|
return unless method_uses_parens?(node, children.first)
|
14
14
|
|
15
|
-
check_children_line_break(node, children)
|
15
|
+
check_children_line_break(node, children, ignore_last: ignore_last)
|
16
16
|
end
|
17
17
|
|
18
18
|
def method_uses_parens?(node, limit)
|
@@ -20,7 +20,7 @@ module RuboCop
|
|
20
20
|
/\s*\(\s*$/.match?(source)
|
21
21
|
end
|
22
22
|
|
23
|
-
def check_children_line_break(node, children, start = node)
|
23
|
+
def check_children_line_break(node, children, start = node, ignore_last: false)
|
24
24
|
return if children.empty?
|
25
25
|
|
26
26
|
line = start.first_line
|
@@ -28,8 +28,8 @@ module RuboCop
|
|
28
28
|
min = first_by_line(children)
|
29
29
|
return if line != min.first_line
|
30
30
|
|
31
|
-
|
32
|
-
return if line ==
|
31
|
+
max_line = last_line(children, ignore_last: ignore_last)
|
32
|
+
return if line == max_line
|
33
33
|
|
34
34
|
add_offense(min) { |corrector| EmptyLineCorrector.insert_before(corrector, min) }
|
35
35
|
end
|
@@ -38,8 +38,12 @@ module RuboCop
|
|
38
38
|
nodes.min_by(&:first_line)
|
39
39
|
end
|
40
40
|
|
41
|
-
def
|
42
|
-
|
41
|
+
def last_line(nodes, ignore_last:)
|
42
|
+
if ignore_last
|
43
|
+
nodes.map(&:first_line)
|
44
|
+
else
|
45
|
+
nodes.map(&:last_line)
|
46
|
+
end.max
|
43
47
|
end
|
44
48
|
end
|
45
49
|
end
|
@@ -45,17 +45,21 @@ module RuboCop
|
|
45
45
|
|
46
46
|
private
|
47
47
|
|
48
|
+
# rubocop:disable Metrics/AbcSize
|
48
49
|
def register_offense(node, message, replacement)
|
49
50
|
add_offense(node.value, message: message) do |corrector|
|
50
51
|
if (def_node = def_node_that_require_parentheses(node))
|
51
52
|
white_spaces = range_between(def_node.loc.selector.end_pos,
|
52
53
|
def_node.first_argument.source_range.begin_pos)
|
53
54
|
corrector.replace(white_spaces, '(')
|
54
|
-
|
55
|
+
|
56
|
+
last_argument = def_node.arguments.last
|
57
|
+
corrector.insert_after(last_argument, ')') if node == last_argument.pairs.last
|
55
58
|
end
|
56
59
|
corrector.replace(node, replacement)
|
57
60
|
end
|
58
61
|
end
|
62
|
+
# rubocop:enable Metrics/AbcSize
|
59
63
|
|
60
64
|
def ignore_mixed_hash_shorthand_syntax?(hash_node)
|
61
65
|
target_ruby_version <= 3.0 || enforced_shorthand_syntax != 'consistent' ||
|
@@ -57,7 +57,14 @@ module RuboCop
|
|
57
57
|
def indentation_difference(line)
|
58
58
|
return 0 unless tab_indentation_width
|
59
59
|
|
60
|
-
|
60
|
+
index =
|
61
|
+
if line.match?(/^[^\t]/)
|
62
|
+
0
|
63
|
+
else
|
64
|
+
line.index(/[^\t]/) || 0
|
65
|
+
end
|
66
|
+
|
67
|
+
index * (tab_indentation_width - 1)
|
61
68
|
end
|
62
69
|
|
63
70
|
def extend_uri_end_position(line, end_position)
|
@@ -59,13 +59,15 @@ module RuboCop
|
|
59
59
|
end
|
60
60
|
|
61
61
|
def complexity(body)
|
62
|
-
|
62
|
+
score = 1
|
63
|
+
body.each_node(:lvasgn, *self.class::COUNTED_NODES) do |node|
|
63
64
|
if node.lvasgn_type?
|
64
65
|
reset_on_lvasgn(node)
|
65
|
-
|
66
|
+
else
|
67
|
+
score += complexity_score_for(node)
|
66
68
|
end
|
67
|
-
score + complexity_score_for(node)
|
68
69
|
end
|
70
|
+
score
|
69
71
|
end
|
70
72
|
end
|
71
73
|
end
|
@@ -10,8 +10,8 @@ module RuboCop
|
|
10
10
|
module MultilineElementLineBreaks
|
11
11
|
private
|
12
12
|
|
13
|
-
def check_line_breaks(_node, children)
|
14
|
-
return if all_on_same_line?(children)
|
13
|
+
def check_line_breaks(_node, children, ignore_last: false)
|
14
|
+
return if all_on_same_line?(children, ignore_last: ignore_last)
|
15
15
|
|
16
16
|
last_seen_line = -1
|
17
17
|
children.each do |child|
|
@@ -23,9 +23,11 @@ module RuboCop
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
def all_on_same_line?(nodes)
|
26
|
+
def all_on_same_line?(nodes, ignore_last: false)
|
27
27
|
return true if nodes.empty?
|
28
28
|
|
29
|
+
return same_line?(nodes.first, nodes.last) if ignore_last
|
30
|
+
|
29
31
|
nodes.first.first_line == nodes.last.last_line
|
30
32
|
end
|
31
33
|
end
|
@@ -97,9 +97,7 @@ module RuboCop
|
|
97
97
|
# @return [String]
|
98
98
|
def whitespace_between(node)
|
99
99
|
if node.children.length >= 2
|
100
|
-
node.source
|
101
|
-
node.children[0].loc.expression.end_pos...node.children[1].loc.expression.begin_pos
|
102
|
-
]
|
100
|
+
node.children[0].source_range.end.join(node.children[1].source_range.begin).source
|
103
101
|
else
|
104
102
|
' '
|
105
103
|
end
|
@@ -111,7 +109,7 @@ module RuboCop
|
|
111
109
|
# @param [RuboCop::AST::ArrayNode] node
|
112
110
|
# @return [String]
|
113
111
|
def whitespace_leading(node)
|
114
|
-
node.
|
112
|
+
node.loc.begin.end.join(node.children[0].source_range.begin).source
|
115
113
|
end
|
116
114
|
|
117
115
|
# Provides trailing whitespace for building a bracketed array.
|
@@ -120,7 +118,7 @@ module RuboCop
|
|
120
118
|
# @param [RuboCop::AST::ArrayNode] node
|
121
119
|
# @return [String]
|
122
120
|
def whitespace_trailing(node)
|
123
|
-
node.
|
121
|
+
node.children[-1].source_range.end.join(node.loc.end.begin).source
|
124
122
|
end
|
125
123
|
end
|
126
124
|
end
|
@@ -4,8 +4,8 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
# Common functionality for checking `rescue` nodes.
|
6
6
|
module RescueNode
|
7
|
-
def
|
8
|
-
@modifier_locations
|
7
|
+
def modifier_locations
|
8
|
+
@modifier_locations ||= processed_source.tokens.select(&:rescue_modifier?).map!(&:pos)
|
9
9
|
end
|
10
10
|
|
11
11
|
private
|
@@ -13,7 +13,7 @@ module RuboCop
|
|
13
13
|
def rescue_modifier?(node)
|
14
14
|
return false unless node.respond_to?(:resbody_type?)
|
15
15
|
|
16
|
-
node.resbody_type? &&
|
16
|
+
node.resbody_type? && modifier_locations.include?(node.loc.keyword)
|
17
17
|
end
|
18
18
|
|
19
19
|
# @deprecated Use ResbodyNode#exceptions instead
|
@@ -56,7 +56,7 @@ module RuboCop
|
|
56
56
|
|
57
57
|
def if_body_source(if_body)
|
58
58
|
if if_body.call_type? &&
|
59
|
-
if_body.last_argument&.hash_type? && if_body.last_argument.pairs.last
|
59
|
+
if_body.last_argument&.hash_type? && if_body.last_argument.pairs.last&.value_omission?
|
60
60
|
"#{method_source(if_body)}(#{if_body.arguments.map(&:source).join(', ')})"
|
61
61
|
else
|
62
62
|
if_body.source
|
@@ -108,7 +108,7 @@ module RuboCop
|
|
108
108
|
return if node.body.nil?
|
109
109
|
|
110
110
|
node.body.each_descendant(:lvar, :lvasgn).any? do |lvar|
|
111
|
-
!lvar.parent.block_pass_type? && lvar.
|
111
|
+
!lvar.parent.block_pass_type? && lvar.node_parts[0].to_s == last_argument
|
112
112
|
end
|
113
113
|
end
|
114
114
|
|
@@ -30,6 +30,8 @@ module RuboCop
|
|
30
30
|
MSG = 'Use CamelCase for classes and modules.'
|
31
31
|
|
32
32
|
def on_class(node)
|
33
|
+
return unless node.loc.name.source.include?('_')
|
34
|
+
|
33
35
|
allowed = /#{cop_config['AllowedNames'].join('|')}/
|
34
36
|
name = node.loc.name.source.gsub(allowed, '')
|
35
37
|
return unless /_/.match?(name)
|
@@ -207,7 +207,10 @@ module RuboCop
|
|
207
207
|
end
|
208
208
|
|
209
209
|
def scan_for_words(input)
|
210
|
-
mask_input(input)
|
210
|
+
masked_input = mask_input(input)
|
211
|
+
return EMPTY_ARRAY unless masked_input.match?(@flagged_terms_regex)
|
212
|
+
|
213
|
+
masked_input.enum_for(:scan, @flagged_terms_regex).map do
|
211
214
|
match = Regexp.last_match
|
212
215
|
WordLocation.new(match.to_s, match.offset(0).first)
|
213
216
|
end
|
data/lib/rubocop/cop/registry.rb
CHANGED
@@ -28,6 +28,9 @@ module RuboCop
|
|
28
28
|
|
29
29
|
@enrollment_queue = cops
|
30
30
|
@options = options
|
31
|
+
|
32
|
+
@enabled_cache = {}.compare_by_identity
|
33
|
+
@disabled_cache = {}.compare_by_identity
|
31
34
|
end
|
32
35
|
|
33
36
|
def enlist(cop)
|
@@ -61,7 +64,7 @@ module RuboCop
|
|
61
64
|
|
62
65
|
# @return [Boolean] Checks if given name is department
|
63
66
|
def department?(name)
|
64
|
-
departments.include?
|
67
|
+
departments.include?(name.to_sym)
|
65
68
|
end
|
66
69
|
|
67
70
|
def contains_cop_matching?(names)
|
@@ -150,11 +153,11 @@ module RuboCop
|
|
150
153
|
end
|
151
154
|
|
152
155
|
def enabled(config)
|
153
|
-
select { |cop| enabled?(cop, config) }
|
156
|
+
@enabled_cache[config] ||= select { |cop| enabled?(cop, config) }
|
154
157
|
end
|
155
158
|
|
156
159
|
def disabled(config)
|
157
|
-
reject { |cop| enabled?(cop, config) }
|
160
|
+
@disabled_cache[config] ||= reject { |cop| enabled?(cop, config) }
|
158
161
|
end
|
159
162
|
|
160
163
|
def enabled?(cop, config)
|
@@ -7,6 +7,11 @@ module RuboCop
|
|
7
7
|
# depending on configuration.
|
8
8
|
# It also flags uses of `alias :symbol` rather than `alias bareword`.
|
9
9
|
#
|
10
|
+
# However, it will always enforce `method_alias` when used `alias`
|
11
|
+
# in an instance method definition and in a singleton method definition.
|
12
|
+
# If used in a block, always enforce `alias_method`
|
13
|
+
# unless it is an `instance_eval` block.
|
14
|
+
#
|
10
15
|
# @example EnforcedStyle: prefer_alias (default)
|
11
16
|
# # bad
|
12
17
|
# alias_method :bar, :foo
|
@@ -22,6 +27,7 @@ module RuboCop
|
|
22
27
|
#
|
23
28
|
# # good
|
24
29
|
# alias_method :bar, :foo
|
30
|
+
#
|
25
31
|
class Alias < Base
|
26
32
|
include ConfigurableEnforcedStyle
|
27
33
|
extend AutoCorrector
|
@@ -71,7 +77,9 @@ module RuboCop
|
|
71
77
|
end
|
72
78
|
|
73
79
|
def alias_method_possible?(node)
|
74
|
-
scope_type(node) != :instance_eval &&
|
80
|
+
scope_type(node) != :instance_eval &&
|
81
|
+
node.children.none?(&:gvar_type?) &&
|
82
|
+
node&.parent&.type != :def
|
75
83
|
end
|
76
84
|
|
77
85
|
def add_offense_for_args(node, &block)
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Enforces the use of `Array#push(item)` instead of `Array#concat([item])`
|
7
|
+
# to avoid redundant array literals.
|
8
|
+
#
|
9
|
+
# @safety
|
10
|
+
# This cop is unsafe, as it can produce false positives if the receiver
|
11
|
+
# is not an `Array` object.
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
#
|
15
|
+
# # bad
|
16
|
+
# list.concat([foo])
|
17
|
+
# list.concat([bar, baz])
|
18
|
+
# list.concat([qux, quux], [corge])
|
19
|
+
#
|
20
|
+
# # good
|
21
|
+
# list.push(foo)
|
22
|
+
# list.push(bar, baz)
|
23
|
+
# list.push(qux, quux, corge)
|
24
|
+
#
|
25
|
+
class ConcatArrayLiterals < Base
|
26
|
+
extend AutoCorrector
|
27
|
+
|
28
|
+
MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
|
29
|
+
MSG_FOR_PERCENT_LITERALS =
|
30
|
+
'Use `push` with elements as arguments without array brackets instead of `%<current>s`.'
|
31
|
+
RESTRICT_ON_SEND = %i[concat].freeze
|
32
|
+
|
33
|
+
def on_send(node)
|
34
|
+
return if node.arguments.empty?
|
35
|
+
return unless node.arguments.all?(&:array_type?)
|
36
|
+
|
37
|
+
offense = offense_range(node)
|
38
|
+
current = offense.source
|
39
|
+
|
40
|
+
if node.arguments.any?(&:percent_literal?)
|
41
|
+
message = format(MSG_FOR_PERCENT_LITERALS, current: current)
|
42
|
+
else
|
43
|
+
prefer = preferred_method(node)
|
44
|
+
message = format(MSG, prefer: prefer, current: current)
|
45
|
+
end
|
46
|
+
|
47
|
+
add_offense(offense, message: message) do |corrector|
|
48
|
+
corrector.replace(offense, prefer)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def offense_range(node)
|
55
|
+
node.loc.selector.join(node.source_range.end)
|
56
|
+
end
|
57
|
+
|
58
|
+
def preferred_method(node)
|
59
|
+
new_arguments = node.arguments.map { |arg| arg.children.map(&:source) }.join(', ')
|
60
|
+
|
61
|
+
"push(#{new_arguments})"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -86,6 +86,11 @@ module RuboCop
|
|
86
86
|
(send nil? {:public_constant :private_constant} ({sym str} _))
|
87
87
|
PATTERN
|
88
88
|
|
89
|
+
# @!method include_statement?(node)
|
90
|
+
def_node_matcher :include_statement?, <<~PATTERN
|
91
|
+
(send nil? {:include :extend :prepend} const)
|
92
|
+
PATTERN
|
93
|
+
|
89
94
|
def on_class(node)
|
90
95
|
return unless node.body
|
91
96
|
|
@@ -103,7 +108,7 @@ module RuboCop
|
|
103
108
|
return if documentation_comment?(node)
|
104
109
|
return if constant_allowed?(node)
|
105
110
|
return if nodoc_self_or_outer_module?(node)
|
106
|
-
return if
|
111
|
+
return if include_statement_only?(body)
|
107
112
|
|
108
113
|
range = range_between(node.loc.expression.begin_pos, node.loc.name.end_pos)
|
109
114
|
message = format(MSG, type: node.type, identifier: identifier(node))
|
@@ -115,9 +120,10 @@ module RuboCop
|
|
115
120
|
(compact_namespace?(node) && nodoc_comment?(outer_module(node).first))
|
116
121
|
end
|
117
122
|
|
118
|
-
def
|
119
|
-
|
120
|
-
|
123
|
+
def include_statement_only?(body)
|
124
|
+
return true if include_statement?(body)
|
125
|
+
|
126
|
+
body.respond_to?(:children) && body.children.all? { |node| include_statement_only?(node) }
|
121
127
|
end
|
122
128
|
|
123
129
|
def namespace?(node)
|
@@ -176,7 +182,7 @@ module RuboCop
|
|
176
182
|
end
|
177
183
|
|
178
184
|
def qualify_const(node)
|
179
|
-
return if node.nil? || node.cbase_type?
|
185
|
+
return if node.nil? || node.cbase_type? || node.self_type? || node.send_type?
|
180
186
|
|
181
187
|
[qualify_const(node.namespace), node.short_name].compact
|
182
188
|
end
|
@@ -187,9 +187,9 @@ module RuboCop
|
|
187
187
|
if_branch = node.if_branch
|
188
188
|
else_branch = node.else_branch
|
189
189
|
|
190
|
-
if if_branch&.send_type? && if_branch.last_argument
|
190
|
+
if if_branch&.send_type? && heredoc?(if_branch.last_argument)
|
191
191
|
autocorrect_heredoc_argument(corrector, node, if_branch, else_branch, guard)
|
192
|
-
elsif else_branch&.send_type? && else_branch.last_argument
|
192
|
+
elsif else_branch&.send_type? && heredoc?(else_branch.last_argument)
|
193
193
|
autocorrect_heredoc_argument(corrector, node, else_branch, if_branch, guard)
|
194
194
|
else
|
195
195
|
corrector.remove(node.loc.end)
|
@@ -201,6 +201,10 @@ module RuboCop
|
|
201
201
|
end
|
202
202
|
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
203
203
|
|
204
|
+
def heredoc?(argument)
|
205
|
+
argument.respond_to?(:heredoc?) && argument.heredoc?
|
206
|
+
end
|
207
|
+
|
204
208
|
def autocorrect_heredoc_argument(corrector, node, heredoc_branch, leave_branch, guard)
|
205
209
|
remove_whole_lines(corrector, leave_branch.source_range)
|
206
210
|
remove_whole_lines(corrector, node.loc.else)
|