rubocop 1.41.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 +34 -2
- data/lib/rubocop/cli.rb +1 -1
- data/lib/rubocop/config.rb +7 -7
- data/lib/rubocop/config_loader_resolver.rb +5 -1
- data/lib/rubocop/cop/base.rb +62 -61
- data/lib/rubocop/cop/cop.rb +28 -28
- data/lib/rubocop/cop/corrector.rb +23 -11
- data/lib/rubocop/cop/gemspec/dependency_version.rb +16 -18
- 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/indentation_style.rb +4 -1
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +6 -6
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +5 -2
- 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/regexp_as_condition.rb +6 -0
- data/lib/rubocop/cop/lint/require_parentheses.rb +3 -1
- 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/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/mixin/annotation_comment.rb +1 -1
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +9 -1
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +1 -1
- data/lib/rubocop/cop/mixin/statement_modifier.rb +1 -0
- data/lib/rubocop/cop/naming/block_forwarding.rb +1 -1
- data/lib/rubocop/cop/registry.rb +22 -22
- 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 +22 -2
- data/lib/rubocop/cop/style/documentation.rb +10 -4
- data/lib/rubocop/cop/style/guard_clause.rb +12 -8
- 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/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_double_splat_hash_braces.rb +1 -1
- 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 +4 -2
- data/lib/rubocop/cop/style/select_by_regexp.rb +6 -2
- 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/variable_force.rb +0 -3
- data/lib/rubocop/cops_documentation_generator.rb +11 -8
- data/lib/rubocop/formatter.rb +2 -0
- data/lib/rubocop/path_util.rb +17 -7
- data/lib/rubocop/result_cache.rb +1 -1
- data/lib/rubocop/runner.rb +10 -3
- data/lib/rubocop/target_ruby.rb +0 -1
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +4 -0
- metadata +13 -9
@@ -31,15 +31,11 @@ module RuboCop
|
|
31
31
|
include RangeHelp
|
32
32
|
extend AutoCorrector
|
33
33
|
|
34
|
-
# rubocop:disable Metrics/AbcSize
|
35
34
|
def on_new_investigation
|
36
35
|
return unless processed_source.raw_source.include?('\\')
|
37
36
|
|
38
37
|
last_line = last_line(processed_source)
|
39
38
|
|
40
|
-
@ignored_ranges = string_literal_ranges(processed_source.ast) +
|
41
|
-
comment_ranges(processed_source.comments)
|
42
|
-
|
43
39
|
processed_source.raw_source.lines.each_with_index do |line, index|
|
44
40
|
break if index >= last_line
|
45
41
|
|
@@ -47,7 +43,6 @@ module RuboCop
|
|
47
43
|
investigate(line, line_number)
|
48
44
|
end
|
49
45
|
end
|
50
|
-
# rubocop:enable Metrics/AbcSize
|
51
46
|
|
52
47
|
private
|
53
48
|
|
@@ -120,7 +115,12 @@ module RuboCop
|
|
120
115
|
end
|
121
116
|
|
122
117
|
def ignore_range?(backtick_range)
|
123
|
-
|
118
|
+
ignored_ranges.any? { |range| range.contains?(backtick_range) }
|
119
|
+
end
|
120
|
+
|
121
|
+
def ignored_ranges
|
122
|
+
@ignored_ranges ||= string_literal_ranges(processed_source.ast) +
|
123
|
+
comment_ranges(processed_source.comments)
|
124
124
|
end
|
125
125
|
|
126
126
|
def no_space_style?
|
@@ -256,7 +256,7 @@ module RuboCop
|
|
256
256
|
# regular dotted method calls bind more tightly than operators
|
257
257
|
# so we need to climb up the AST past them
|
258
258
|
node.each_ancestor do |ancestor|
|
259
|
-
return true if ancestor.and_type? || ancestor.or_type?
|
259
|
+
return true if ancestor.and_type? || ancestor.or_type? || ancestor.range_type?
|
260
260
|
return false unless ancestor.send_type?
|
261
261
|
return true if ancestor.operator_method?
|
262
262
|
end
|
@@ -47,7 +47,6 @@ module RuboCop
|
|
47
47
|
MSG = 'Trailing whitespace detected.'
|
48
48
|
|
49
49
|
def on_new_investigation
|
50
|
-
@heredocs = extract_heredocs(processed_source.ast)
|
51
50
|
processed_source.lines.each_with_index do |line, index|
|
52
51
|
next unless line.end_with?(' ', "\t")
|
53
52
|
|
@@ -102,10 +101,14 @@ module RuboCop
|
|
102
101
|
end
|
103
102
|
|
104
103
|
def find_heredoc(line_number)
|
105
|
-
|
104
|
+
heredocs.each { |node, r| return node if r.include?(line_number) }
|
106
105
|
nil
|
107
106
|
end
|
108
107
|
|
108
|
+
def heredocs
|
109
|
+
@heredocs ||= extract_heredocs(processed_source.ast)
|
110
|
+
end
|
111
|
+
|
109
112
|
def extract_heredocs(ast)
|
110
113
|
return [] unless ast
|
111
114
|
|
@@ -68,6 +68,12 @@ module RuboCop
|
|
68
68
|
@valid_ref = regexp_conditions.map { |condition| check_regexp(condition) }.compact.max
|
69
69
|
end
|
70
70
|
|
71
|
+
def on_in_pattern(node)
|
72
|
+
regexp_patterns = patterns(node).select(&:regexp_type?)
|
73
|
+
|
74
|
+
@valid_ref = regexp_patterns.map { |pattern| check_regexp(pattern) }.compact.max
|
75
|
+
end
|
76
|
+
|
71
77
|
def on_nth_ref(node)
|
72
78
|
backref, = *node
|
73
79
|
return if @valid_ref.nil? || backref <= @valid_ref
|
@@ -84,6 +90,19 @@ module RuboCop
|
|
84
90
|
|
85
91
|
private
|
86
92
|
|
93
|
+
def patterns(pattern_node)
|
94
|
+
pattern = pattern_node.node_parts[0]
|
95
|
+
|
96
|
+
case pattern.type
|
97
|
+
when :array_pattern, :match_alt
|
98
|
+
pattern.children
|
99
|
+
when :match_as
|
100
|
+
patterns(pattern)
|
101
|
+
else
|
102
|
+
[pattern]
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
87
106
|
def check_regexp(node)
|
88
107
|
return if node.interpolation?
|
89
108
|
|
@@ -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 }
|
@@ -17,13 +17,19 @@ module RuboCop
|
|
17
17
|
# do_something
|
18
18
|
# end
|
19
19
|
class RegexpAsCondition < Base
|
20
|
+
include IgnoredNode
|
20
21
|
extend AutoCorrector
|
21
22
|
|
22
23
|
MSG = 'Do not use regexp literal as a condition. ' \
|
23
24
|
'The regexp literal matches `$_` implicitly.'
|
24
25
|
|
25
26
|
def on_match_current_line(node)
|
27
|
+
return if node.ancestors.none?(&:conditional?)
|
28
|
+
return if part_of_ignored_node?(node)
|
29
|
+
|
26
30
|
add_offense(node) { |corrector| corrector.replace(node, "#{node.source} =~ $_") }
|
31
|
+
|
32
|
+
ignore_node(node)
|
27
33
|
end
|
28
34
|
end
|
29
35
|
end
|
@@ -46,7 +46,9 @@ module RuboCop
|
|
46
46
|
private
|
47
47
|
|
48
48
|
def check_ternary(ternary, node)
|
49
|
-
|
49
|
+
if node.method?(:[]) || node.assignment_method? || !ternary.condition.operator_keyword?
|
50
|
+
return
|
51
|
+
end
|
50
52
|
|
51
53
|
range = range_between(node.source_range.begin_pos, ternary.condition.source_range.end_pos)
|
52
54
|
|
@@ -100,7 +100,8 @@ module RuboCop
|
|
100
100
|
|
101
101
|
unless variable.keyword_argument?
|
102
102
|
message << " If it's necessary, use `_` or `_#{variable.name}` " \
|
103
|
-
"as an argument name to indicate that it won't be used."
|
103
|
+
"as an argument name to indicate that it won't be used. " \
|
104
|
+
"If it's unnecessary, remove it."
|
104
105
|
end
|
105
106
|
|
106
107
|
scope = variable.scope
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
# Checks for useless `rescue`s, which only reraise rescued exceptions.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# def foo
|
11
|
+
# do_something
|
12
|
+
# rescue
|
13
|
+
# raise
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# # bad
|
17
|
+
# def foo
|
18
|
+
# do_something
|
19
|
+
# rescue => e
|
20
|
+
# raise # or 'raise e', or 'raise $!', or 'raise $ERROR_INFO'
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# # good
|
24
|
+
# def foo
|
25
|
+
# do_something
|
26
|
+
# rescue
|
27
|
+
# do_cleanup
|
28
|
+
# raise
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# # bad (latest rescue)
|
32
|
+
# def foo
|
33
|
+
# do_something
|
34
|
+
# rescue ArgumentError
|
35
|
+
# # noop
|
36
|
+
# rescue
|
37
|
+
# raise
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# # good (not the latest rescue)
|
41
|
+
# def foo
|
42
|
+
# do_something
|
43
|
+
# rescue ArgumentError
|
44
|
+
# raise
|
45
|
+
# rescue
|
46
|
+
# # noop
|
47
|
+
# end
|
48
|
+
#
|
49
|
+
class UselessRescue < Base
|
50
|
+
MSG = 'Useless `rescue` detected.'
|
51
|
+
|
52
|
+
def on_rescue(node)
|
53
|
+
resbody_node = node.resbody_branches.last
|
54
|
+
add_offense(resbody_node) if only_reraising?(resbody_node)
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def only_reraising?(resbody_node)
|
60
|
+
body = resbody_node.body
|
61
|
+
return false if body.nil? || !body.send_type? || !body.method?(:raise)
|
62
|
+
return true unless body.arguments?
|
63
|
+
return false if body.arguments.size > 1
|
64
|
+
|
65
|
+
exception_name = body.first_argument.source
|
66
|
+
[resbody_node.exception_variable&.source, '$!', '$ERROR_INFO'].include?(exception_name)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -77,10 +77,12 @@ module RuboCop
|
|
77
77
|
PATTERN
|
78
78
|
|
79
79
|
def on_send(node)
|
80
|
-
|
81
|
-
|
80
|
+
return unless (first_argument = node.first_argument)
|
81
|
+
|
82
|
+
if first_argument.def_type?
|
83
|
+
inspect_def(node, first_argument)
|
82
84
|
elsif node.first_argument.sym_type?
|
83
|
-
inspect_sym(node,
|
85
|
+
inspect_sym(node, first_argument)
|
84
86
|
end
|
85
87
|
end
|
86
88
|
|
@@ -9,6 +9,20 @@ module RuboCop
|
|
9
9
|
# Keyword arguments can optionally be excluded from the total count,
|
10
10
|
# as they add less complexity than positional or optional parameters.
|
11
11
|
#
|
12
|
+
# Any number of arguments for `initialize` method inside a block of
|
13
|
+
# `Struct.new` and `Data.define` like this is always allowed:
|
14
|
+
#
|
15
|
+
# [source,ruby]
|
16
|
+
# ----
|
17
|
+
# Struct.new(:one, :two, :three, :four, :five, keyword_init: true) do
|
18
|
+
# def initialize(one:, two:, three:, four:, five:)
|
19
|
+
# end
|
20
|
+
# end
|
21
|
+
# ----
|
22
|
+
#
|
23
|
+
# This is because checking the number of arguments of the `initialize` method
|
24
|
+
# does not make sense.
|
25
|
+
#
|
12
26
|
# NOTE: Explicit block argument `&block` is not counted to prevent
|
13
27
|
# erroneous change that is avoided by making block argument implicit.
|
14
28
|
#
|
@@ -63,6 +77,16 @@ module RuboCop
|
|
63
77
|
NAMED_KEYWORD_TYPES = %i[kwoptarg kwarg].freeze
|
64
78
|
private_constant :NAMED_KEYWORD_TYPES
|
65
79
|
|
80
|
+
# @!method struct_new_or_data_define_block?(node)
|
81
|
+
def_node_matcher :struct_new_or_data_define_block?, <<~PATTERN
|
82
|
+
(block
|
83
|
+
{
|
84
|
+
(send (const {nil? cbase} :Struct) :new ...)
|
85
|
+
(send (const {nil? cbase} :Data) :define ...)
|
86
|
+
}
|
87
|
+
(args) ...)
|
88
|
+
PATTERN
|
89
|
+
|
66
90
|
def on_def(node)
|
67
91
|
optargs = node.arguments.select(&:optarg_type?)
|
68
92
|
return if optargs.count <= max_optional_parameters
|
@@ -78,6 +102,9 @@ module RuboCop
|
|
78
102
|
alias on_defs on_def
|
79
103
|
|
80
104
|
def on_args(node)
|
105
|
+
parent = node.parent
|
106
|
+
return if parent.method?(:initialize) && struct_new_or_data_define_block?(parent.parent)
|
107
|
+
|
81
108
|
count = args_count(node)
|
82
109
|
return unless count > max_params
|
83
110
|
|
@@ -25,15 +25,15 @@ module RuboCop
|
|
25
25
|
# > http://c2.com/cgi/wiki?AbcMetric
|
26
26
|
CONDITION_NODES = CyclomaticComplexity::COUNTED_NODES.freeze
|
27
27
|
|
28
|
-
def self.calculate(node, discount_repeated_attributes: false)
|
29
|
-
new(node, discount_repeated_attributes: discount_repeated_attributes).calculate
|
30
|
-
end
|
31
|
-
|
32
28
|
# TODO: move to rubocop-ast
|
33
29
|
ARGUMENT_TYPES = %i[arg optarg restarg kwarg kwoptarg kwrestarg blockarg].freeze
|
34
30
|
|
35
31
|
private_constant :BRANCH_NODES, :CONDITION_NODES, :ARGUMENT_TYPES
|
36
32
|
|
33
|
+
def self.calculate(node, discount_repeated_attributes: false)
|
34
|
+
new(node, discount_repeated_attributes: discount_repeated_attributes).calculate
|
35
|
+
end
|
36
|
+
|
37
37
|
def initialize(node)
|
38
38
|
@assignment = 0
|
39
39
|
@branch = 0
|
@@ -47,7 +47,7 @@ module RuboCop
|
|
47
47
|
match.captures
|
48
48
|
end
|
49
49
|
|
50
|
-
KEYWORDS_REGEX_CACHE = {} # rubocop:disable
|
50
|
+
KEYWORDS_REGEX_CACHE = {} # rubocop:disable Style/MutableConstant
|
51
51
|
private_constant :KEYWORDS_REGEX_CACHE
|
52
52
|
|
53
53
|
def regex
|
@@ -3,6 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
# This module checks for Ruby 3.1's hash value omission syntax.
|
6
|
+
# rubocop:disable Metrics/ModuleLength
|
6
7
|
module HashShorthandSyntax
|
7
8
|
OMIT_HASH_VALUE_MSG = 'Omit the hash value.'
|
8
9
|
EXPLICIT_HASH_VALUE_MSG = 'Include the hash value.'
|
@@ -93,6 +94,8 @@ module RuboCop
|
|
93
94
|
end
|
94
95
|
|
95
96
|
def def_node_that_require_parentheses(node)
|
97
|
+
last_pair = node.parent.pairs.last
|
98
|
+
return unless last_pair.key.source == last_pair.value.source
|
96
99
|
return unless (send_node = find_ancestor_send_node(node))
|
97
100
|
return unless without_parentheses_call_expr_follows?(send_node)
|
98
101
|
|
@@ -104,7 +107,11 @@ module RuboCop
|
|
104
107
|
def find_ancestor_send_node(node)
|
105
108
|
ancestor = node.parent.parent
|
106
109
|
|
107
|
-
ancestor if ancestor&.call_type? && !
|
110
|
+
ancestor if ancestor&.call_type? && !brackets?(ancestor)
|
111
|
+
end
|
112
|
+
|
113
|
+
def brackets?(send_node)
|
114
|
+
send_node.method?(:[]) || send_node.method?(:[]=)
|
108
115
|
end
|
109
116
|
|
110
117
|
def use_element_of_hash_literal_as_receiver?(ancestor, parent)
|
@@ -184,4 +191,5 @@ module RuboCop
|
|
184
191
|
end
|
185
192
|
end
|
186
193
|
end
|
194
|
+
# rubocop:enable Metrics/ModuleLength
|
187
195
|
end
|
@@ -175,7 +175,7 @@ module RuboCop
|
|
175
175
|
|
176
176
|
def remove_optarg_equals(asgn_tokens, processed_source)
|
177
177
|
optargs = processed_source.ast.each_node(:optarg)
|
178
|
-
optarg_eql = optargs.
|
178
|
+
optarg_eql = optargs.to_set { |o| o.loc.operator.begin_pos }
|
179
179
|
asgn_tokens.reject { |t| optarg_eql.include?(t.begin_pos) }
|
180
180
|
end
|
181
181
|
end
|
@@ -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
|
|
data/lib/rubocop/cop/registry.rb
CHANGED
@@ -19,6 +19,28 @@ module RuboCop
|
|
19
19
|
class Registry
|
20
20
|
include Enumerable
|
21
21
|
|
22
|
+
def self.all
|
23
|
+
global.without_department(:Test).cops
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.qualified_cop_name(name, origin)
|
27
|
+
global.qualified_cop_name(name, origin)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Changes momentarily the global registry
|
31
|
+
# Intended for testing purposes
|
32
|
+
def self.with_temporary_global(temp_global = global.dup)
|
33
|
+
previous = @global
|
34
|
+
@global = temp_global
|
35
|
+
yield
|
36
|
+
ensure
|
37
|
+
@global = previous
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.reset!
|
41
|
+
@global = new
|
42
|
+
end
|
43
|
+
|
22
44
|
attr_reader :options
|
23
45
|
|
24
46
|
def initialize(cops = [], options = {})
|
@@ -238,28 +260,6 @@ module RuboCop
|
|
238
260
|
attr_reader :global
|
239
261
|
end
|
240
262
|
|
241
|
-
def self.all
|
242
|
-
global.without_department(:Test).cops
|
243
|
-
end
|
244
|
-
|
245
|
-
def self.qualified_cop_name(name, origin)
|
246
|
-
global.qualified_cop_name(name, origin)
|
247
|
-
end
|
248
|
-
|
249
|
-
# Changes momentarily the global registry
|
250
|
-
# Intended for testing purposes
|
251
|
-
def self.with_temporary_global(temp_global = global.dup)
|
252
|
-
previous = @global
|
253
|
-
@global = temp_global
|
254
|
-
yield
|
255
|
-
ensure
|
256
|
-
@global = previous
|
257
|
-
end
|
258
|
-
|
259
|
-
def self.reset!
|
260
|
-
@global = new
|
261
|
-
end
|
262
|
-
|
263
263
|
private
|
264
264
|
|
265
265
|
def initialize_copy(reg)
|
@@ -9,7 +9,8 @@ module RuboCop
|
|
9
9
|
# Manually combining hashes is error prone and hard to follow, especially
|
10
10
|
# when there are many values. Poor implementations may also introduce
|
11
11
|
# performance or security concerns if they are prone to collisions.
|
12
|
-
# Delegating to `Array#hash` is clearer
|
12
|
+
# Delegating to `Array#hash` is clearer and safer, although it might be slower
|
13
|
+
# depending on the use case.
|
13
14
|
#
|
14
15
|
# @safety
|
15
16
|
# This cop may be unsafe if the application logic depends on the hash
|
@@ -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)
|
@@ -32,7 +32,7 @@ module RuboCop
|
|
32
32
|
eq_begin, eq_end, contents = parts(comment)
|
33
33
|
|
34
34
|
corrector.remove(eq_begin)
|
35
|
-
unless contents.
|
35
|
+
unless contents.empty?
|
36
36
|
corrector.replace(
|
37
37
|
contents,
|
38
38
|
contents.source.gsub(/\A/, '# ').gsub(/\n\n/, "\n#\n").gsub(/\n(?=[^#])/, "\n# ")
|
@@ -30,6 +30,7 @@ module RuboCop
|
|
30
30
|
'Use `push` with elements as arguments without array brackets instead of `%<current>s`.'
|
31
31
|
RESTRICT_ON_SEND = %i[concat].freeze
|
32
32
|
|
33
|
+
# rubocop:disable Metrics
|
33
34
|
def on_send(node)
|
34
35
|
return if node.arguments.empty?
|
35
36
|
return unless node.arguments.all?(&:array_type?)
|
@@ -38,7 +39,12 @@ module RuboCop
|
|
38
39
|
current = offense.source
|
39
40
|
|
40
41
|
if node.arguments.any?(&:percent_literal?)
|
41
|
-
|
42
|
+
if percent_literals_includes_only_basic_literals?(node)
|
43
|
+
prefer = preferred_method(node)
|
44
|
+
message = format(MSG, prefer: prefer, current: current)
|
45
|
+
else
|
46
|
+
message = format(MSG_FOR_PERCENT_LITERALS, current: current)
|
47
|
+
end
|
42
48
|
else
|
43
49
|
prefer = preferred_method(node)
|
44
50
|
message = format(MSG, prefer: prefer, current: current)
|
@@ -48,6 +54,7 @@ module RuboCop
|
|
48
54
|
corrector.replace(offense, prefer)
|
49
55
|
end
|
50
56
|
end
|
57
|
+
# rubocop:enable Metrics
|
51
58
|
|
52
59
|
private
|
53
60
|
|
@@ -56,10 +63,23 @@ module RuboCop
|
|
56
63
|
end
|
57
64
|
|
58
65
|
def preferred_method(node)
|
59
|
-
new_arguments =
|
66
|
+
new_arguments =
|
67
|
+
node.arguments.map do |arg|
|
68
|
+
if arg.percent_literal?
|
69
|
+
arg.children.map(&:value).map(&:inspect)
|
70
|
+
else
|
71
|
+
arg.children.map(&:source)
|
72
|
+
end
|
73
|
+
end.join(', ')
|
60
74
|
|
61
75
|
"push(#{new_arguments})"
|
62
76
|
end
|
77
|
+
|
78
|
+
def percent_literals_includes_only_basic_literals?(node)
|
79
|
+
node.arguments.select(&:percent_literal?).all? do |arg|
|
80
|
+
arg.children.all? { |child| child.str_type? || child.sym_type? }
|
81
|
+
end
|
82
|
+
end
|
63
83
|
end
|
64
84
|
end
|
65
85
|
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)
|
@@ -189,14 +189,14 @@ module RuboCop
|
|
189
189
|
|
190
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)
|
196
196
|
return unless node.else?
|
197
197
|
|
198
198
|
corrector.remove(node.loc.else)
|
199
|
-
corrector.remove(
|
199
|
+
corrector.remove(range_of_branch_to_remove(node, guard))
|
200
200
|
end
|
201
201
|
end
|
202
202
|
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
@@ -206,20 +206,24 @@ module RuboCop
|
|
206
206
|
end
|
207
207
|
|
208
208
|
def autocorrect_heredoc_argument(corrector, node, heredoc_branch, leave_branch, guard)
|
209
|
+
return unless node.else?
|
210
|
+
|
209
211
|
remove_whole_lines(corrector, leave_branch.source_range)
|
210
212
|
remove_whole_lines(corrector, node.loc.else)
|
211
213
|
remove_whole_lines(corrector, node.loc.end)
|
212
|
-
remove_whole_lines(corrector,
|
214
|
+
remove_whole_lines(corrector, range_of_branch_to_remove(node, guard))
|
213
215
|
corrector.insert_after(
|
214
216
|
heredoc_branch.last_argument.loc.heredoc_end, "\n#{leave_branch.source}"
|
215
217
|
)
|
216
218
|
end
|
217
219
|
|
218
|
-
def
|
219
|
-
case guard
|
220
|
-
|
221
|
-
|
222
|
-
|
220
|
+
def range_of_branch_to_remove(node, guard)
|
221
|
+
branch = case guard
|
222
|
+
when :if then node.if_branch
|
223
|
+
when :else then node.else_branch
|
224
|
+
end
|
225
|
+
|
226
|
+
branch.source_range
|
223
227
|
end
|
224
228
|
|
225
229
|
def guard_clause_source(guard_clause)
|