rubocop 1.27.0 → 1.28.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 +50 -9
- data/config/obsoletion.yml +10 -1
- data/lib/rubocop/cli/command/suggest_extensions.rb +1 -1
- data/lib/rubocop/cop/gemspec/date_assignment.rb +2 -2
- data/lib/rubocop/cop/layout/case_indentation.rb +16 -0
- data/lib/rubocop/cop/layout/indentation_width.rb +2 -2
- data/lib/rubocop/cop/layout/line_length.rb +4 -4
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +19 -2
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_require.rb +10 -1
- data/lib/rubocop/cop/lint/unreachable_loop.rb +4 -4
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +16 -2
- data/lib/rubocop/cop/mixin/allowed_pattern.rb +40 -0
- data/lib/rubocop/cop/mixin/comments_help.rb +3 -1
- data/lib/rubocop/cop/naming/method_name.rb +5 -5
- data/lib/rubocop/cop/offense.rb +1 -1
- data/lib/rubocop/cop/security/compound_hash.rb +105 -0
- data/lib/rubocop/cop/style/fetch_env_var.rb +76 -0
- data/lib/rubocop/cop/style/guard_clause.rb +45 -0
- data/lib/rubocop/cop/style/if_unless_modifier.rb +5 -4
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +4 -4
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +33 -11
- data/lib/rubocop/cop/style/object_then.rb +69 -0
- data/lib/rubocop/cop/style/redundant_initialize.rb +39 -4
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +5 -0
- data/lib/rubocop/cop/style/single_argument_dig.rb +4 -0
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +7 -7
- data/lib/rubocop/cop/style/special_global_vars.rb +66 -8
- data/lib/rubocop/cop/style/symbol_proc.rb +24 -0
- data/lib/rubocop/cop/variable_force/branch.rb +1 -1
- data/lib/rubocop/options.rb +27 -1
- data/lib/rubocop/result_cache.rb +3 -3
- data/lib/rubocop/rspec/shared_contexts.rb +2 -2
- data/lib/rubocop/runner.rb +29 -3
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +4 -1
- metadata +9 -6
- data/lib/rubocop/cop/mixin/ignored_pattern.rb +0 -29
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Security
|
6
|
+
# This cop checks for implementations of the `hash` method which combine
|
7
|
+
# values using custom logic instead of delegating to `Array#hash`.
|
8
|
+
#
|
9
|
+
# Manually combining hashes is error prone and hard to follow, especially
|
10
|
+
# when there are many values. Poor implementations may also introduce
|
11
|
+
# performance or security concerns if they are prone to collisions.
|
12
|
+
# Delegating to `Array#hash` is clearer, faster, and safer.
|
13
|
+
#
|
14
|
+
# @safety
|
15
|
+
# This cop may be unsafe if the application logic depends on the hash
|
16
|
+
# value, however this is inadvisable anyway.
|
17
|
+
#
|
18
|
+
# @example
|
19
|
+
#
|
20
|
+
# # bad
|
21
|
+
# def hash
|
22
|
+
# @foo ^ @bar
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# # good
|
26
|
+
# def hash
|
27
|
+
# [@foo, @bar].hash
|
28
|
+
# end
|
29
|
+
class CompoundHash < Base
|
30
|
+
COMBINATOR_IN_HASH_MSG = 'Use `[...].hash` instead of combining hash values manually.'
|
31
|
+
MONUPLE_HASH_MSG =
|
32
|
+
'Delegate hash directly without wrapping in an array when only using a single value'
|
33
|
+
REDUNDANT_HASH_MSG = 'Calling .hash on elements of a hashed array is redundant'
|
34
|
+
|
35
|
+
# @!method hash_method_definition?(node)
|
36
|
+
def_node_matcher :hash_method_definition?, <<~PATTERN
|
37
|
+
{#static_hash_method_definition? | #dynamic_hash_method_definition?}
|
38
|
+
PATTERN
|
39
|
+
|
40
|
+
# @!method dynamic_hash_method_definition?(node)
|
41
|
+
def_node_matcher :dynamic_hash_method_definition?, <<~PATTERN
|
42
|
+
(block
|
43
|
+
(send _ {:define_method | :define_singleton_method}
|
44
|
+
(sym :hash))
|
45
|
+
(args)
|
46
|
+
_)
|
47
|
+
PATTERN
|
48
|
+
|
49
|
+
# @!method static_hash_method_definition?(node)
|
50
|
+
def_node_matcher :static_hash_method_definition?, <<~PATTERN
|
51
|
+
({def | defs _} :hash
|
52
|
+
(args)
|
53
|
+
_)
|
54
|
+
PATTERN
|
55
|
+
|
56
|
+
# @!method bad_hash_combinator?(node)
|
57
|
+
def_node_matcher :bad_hash_combinator?, <<~PATTERN
|
58
|
+
({send | op-asgn} _ {:^ | :+ | :* | :|} _)
|
59
|
+
PATTERN
|
60
|
+
|
61
|
+
# @!method monuple_hash?(node)
|
62
|
+
def_node_matcher :monuple_hash?, <<~PATTERN
|
63
|
+
(send (array _) :hash)
|
64
|
+
PATTERN
|
65
|
+
|
66
|
+
# @!method redundant_hash?(node)
|
67
|
+
def_node_matcher :redundant_hash?, <<~PATTERN
|
68
|
+
(
|
69
|
+
^^(send array ... :hash)
|
70
|
+
_ :hash
|
71
|
+
)
|
72
|
+
PATTERN
|
73
|
+
|
74
|
+
def contained_in_hash_method?(node, &block)
|
75
|
+
node.each_ancestor.any? do |ancestor|
|
76
|
+
hash_method_definition?(ancestor, &block)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def outer_bad_hash_combinator?(node)
|
81
|
+
bad_hash_combinator?(node) do
|
82
|
+
yield true if node.each_ancestor.none? { |ancestor| bad_hash_combinator?(ancestor) }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def on_send(node)
|
87
|
+
outer_bad_hash_combinator?(node) do
|
88
|
+
contained_in_hash_method?(node) do
|
89
|
+
add_offense(node, message: COMBINATOR_IN_HASH_MSG)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
monuple_hash?(node) do
|
94
|
+
add_offense(node, message: MONUPLE_HASH_MSG)
|
95
|
+
end
|
96
|
+
|
97
|
+
redundant_hash?(node) do
|
98
|
+
add_offense(node, message: REDUNDANT_HASH_MSG)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
alias on_op_asgn on_send
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# This cop suggests `ENV.fetch` for the replacement of `ENV[]`.
|
7
|
+
# `ENV[]` silently fails and returns `nil` when the environment variable is unset,
|
8
|
+
# which may cause unexpected behaviors when the developer forgets to set it.
|
9
|
+
# On the other hand, `ENV.fetch` raises KeyError or returns the explicitly
|
10
|
+
# specified default value.
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
# # bad
|
14
|
+
# ENV['X']
|
15
|
+
# ENV['X'] || z
|
16
|
+
# x = ENV['X']
|
17
|
+
#
|
18
|
+
# # good
|
19
|
+
# ENV.fetch('X')
|
20
|
+
# ENV.fetch('X', nil) || z
|
21
|
+
# x = ENV.fetch('X')
|
22
|
+
#
|
23
|
+
# # also good
|
24
|
+
# !ENV['X']
|
25
|
+
# ENV['X'].some_method # (e.g. `.nil?`)
|
26
|
+
#
|
27
|
+
class FetchEnvVar < Base
|
28
|
+
extend AutoCorrector
|
29
|
+
|
30
|
+
MSG = 'Use `ENV.fetch(%<key>s)` or `ENV.fetch(%<key>s, nil)` instead of `ENV[%<key>s]`.'
|
31
|
+
|
32
|
+
# @!method env_with_bracket?(node)
|
33
|
+
def_node_matcher :env_with_bracket?, <<~PATTERN
|
34
|
+
(send (const nil? :ENV) :[] $_)
|
35
|
+
PATTERN
|
36
|
+
|
37
|
+
def on_send(node)
|
38
|
+
env_with_bracket?(node) do |expression|
|
39
|
+
break if allowed_var?(expression)
|
40
|
+
break if allowable_use?(node)
|
41
|
+
|
42
|
+
add_offense(node, message: format(MSG, key: expression.source)) do |corrector|
|
43
|
+
corrector.replace(node, "ENV.fetch(#{expression.source}, nil)")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def allowed_var?(expression)
|
51
|
+
expression.str_type? && cop_config['AllowedVars'].include?(expression.value)
|
52
|
+
end
|
53
|
+
|
54
|
+
def used_as_flag?(node)
|
55
|
+
return false if node.root?
|
56
|
+
|
57
|
+
node.parent.if_type? || (node.parent.send_type? && node.parent.prefix_bang?)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Check if the node is a receiver and receives a message with dot syntax.
|
61
|
+
def message_chained_with_dot?(node)
|
62
|
+
return false if node.root?
|
63
|
+
|
64
|
+
node.parent.send_type? && node.parent.children.first == node && node.parent.dot?
|
65
|
+
end
|
66
|
+
|
67
|
+
# Allow if used as a flag (e.g., `if ENV['X']` or `!ENV['X']`) because
|
68
|
+
# it simply checks whether the variable is set.
|
69
|
+
# Also allow if receiving a message with dot syntax, e.g. `ENV['X'].nil?`.
|
70
|
+
def allowable_use?(node)
|
71
|
+
used_as_flag?(node) || message_chained_with_dot?(node)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -47,6 +47,37 @@ module RuboCop
|
|
47
47
|
# # good
|
48
48
|
# foo || raise('exception') if something
|
49
49
|
# ok
|
50
|
+
#
|
51
|
+
# @example AllowConsecutiveConditionals: false (default)
|
52
|
+
# # bad
|
53
|
+
# if foo?
|
54
|
+
# work
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# if bar? # <- reports an offense
|
58
|
+
# work
|
59
|
+
# end
|
60
|
+
#
|
61
|
+
# @example AllowConsecutiveConditionals: true
|
62
|
+
# # good
|
63
|
+
# if foo?
|
64
|
+
# work
|
65
|
+
# end
|
66
|
+
#
|
67
|
+
# if bar?
|
68
|
+
# work
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
# # bad
|
72
|
+
# if foo?
|
73
|
+
# work
|
74
|
+
# end
|
75
|
+
#
|
76
|
+
# do_someting
|
77
|
+
#
|
78
|
+
# if bar? # <- reports an offense
|
79
|
+
# work
|
80
|
+
# end
|
50
81
|
class GuardClause < Base
|
51
82
|
include MinBodyLength
|
52
83
|
include StatementModifier
|
@@ -89,10 +120,20 @@ module RuboCop
|
|
89
120
|
|
90
121
|
def check_ending_if(node)
|
91
122
|
return if accepted_form?(node, ending: true) || !min_body_length?(node)
|
123
|
+
return if allowed_consecutive_conditionals? &&
|
124
|
+
consecutive_conditionals?(node.parent, node)
|
92
125
|
|
93
126
|
register_offense(node, 'return', opposite_keyword(node))
|
94
127
|
end
|
95
128
|
|
129
|
+
def consecutive_conditionals?(parent, node)
|
130
|
+
parent.each_child_node.inject(false) do |if_type, child|
|
131
|
+
break if_type if node == child
|
132
|
+
|
133
|
+
child.if_type?
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
96
137
|
def opposite_keyword(node)
|
97
138
|
node.if? ? 'unless' : 'if'
|
98
139
|
end
|
@@ -135,6 +176,10 @@ module RuboCop
|
|
135
176
|
!node.else? || node.elsif?
|
136
177
|
end
|
137
178
|
end
|
179
|
+
|
180
|
+
def allowed_consecutive_conditionals?
|
181
|
+
cop_config.fetch('AllowConsecutiveConditionals', false)
|
182
|
+
end
|
138
183
|
end
|
139
184
|
end
|
140
185
|
end
|
@@ -37,7 +37,7 @@ module RuboCop
|
|
37
37
|
class IfUnlessModifier < Base
|
38
38
|
include StatementModifier
|
39
39
|
include LineLengthHelp
|
40
|
-
include
|
40
|
+
include AllowedPattern
|
41
41
|
include RangeHelp
|
42
42
|
extend AutoCorrector
|
43
43
|
|
@@ -87,8 +87,9 @@ module RuboCop
|
|
87
87
|
!another_statement_on_same_line?(node)
|
88
88
|
end
|
89
89
|
|
90
|
-
def
|
91
|
-
config.for_cop('Layout/LineLength')
|
90
|
+
def allowed_patterns
|
91
|
+
line_length_config = config.for_cop('Layout/LineLength')
|
92
|
+
line_length_config['AllowedPatterns'] || line_length_config['IgnoredPatterns'] || []
|
92
93
|
end
|
93
94
|
|
94
95
|
def too_long_single_line?(node)
|
@@ -105,7 +106,7 @@ module RuboCop
|
|
105
106
|
end
|
106
107
|
|
107
108
|
def too_long_line_based_on_config?(range, line)
|
108
|
-
return false if
|
109
|
+
return false if matches_allowed_pattern?(line)
|
109
110
|
|
110
111
|
too_long = too_long_line_based_on_ignore_cop_directives?(range, line)
|
111
112
|
return too_long unless too_long == :undetermined
|
@@ -13,7 +13,7 @@ module RuboCop
|
|
13
13
|
|
14
14
|
def require_parentheses(node)
|
15
15
|
return if ignored_method?(node.method_name)
|
16
|
-
return if
|
16
|
+
return if matches_allowed_pattern?(node.method_name)
|
17
17
|
return if eligible_for_parentheses_omission?(node)
|
18
18
|
return unless node.arguments? && !node.parenthesized?
|
19
19
|
|
@@ -8,7 +8,7 @@ module RuboCop
|
|
8
8
|
#
|
9
9
|
# In the default style (require_parentheses), macro methods are ignored.
|
10
10
|
# Additional methods can be added to the `IgnoredMethods`
|
11
|
-
# or `
|
11
|
+
# or `AllowedPatterns` list. These options are
|
12
12
|
# valid only in the default style. Macros can be included by
|
13
13
|
# either setting `IgnoreMacros` to false or adding specific macros to
|
14
14
|
# the `IncludedMacros` list.
|
@@ -16,7 +16,7 @@ module RuboCop
|
|
16
16
|
# Precedence of options is all follows:
|
17
17
|
#
|
18
18
|
# 1. `IgnoredMethods`
|
19
|
-
# 2. `
|
19
|
+
# 2. `AllowedPatterns`
|
20
20
|
# 3. `IncludedMacros`
|
21
21
|
#
|
22
22
|
# eg. If a method is listed in both
|
@@ -68,7 +68,7 @@ module RuboCop
|
|
68
68
|
# # okay with `puts` listed in `IgnoredMethods`
|
69
69
|
# puts 'test'
|
70
70
|
#
|
71
|
-
# # okay with `^assert` listed in `
|
71
|
+
# # okay with `^assert` listed in `AllowedPatterns`
|
72
72
|
# assert_equal 'test', x
|
73
73
|
#
|
74
74
|
# @example EnforcedStyle: omit_parentheses
|
@@ -198,7 +198,7 @@ module RuboCop
|
|
198
198
|
|
199
199
|
include ConfigurableEnforcedStyle
|
200
200
|
include IgnoredMethods
|
201
|
-
include
|
201
|
+
include AllowedPattern
|
202
202
|
include RequireParentheses
|
203
203
|
include OmitParentheses
|
204
204
|
extend AutoCorrector
|
@@ -6,7 +6,8 @@ module RuboCop
|
|
6
6
|
# This cop checks for multi-line ternary op expressions.
|
7
7
|
#
|
8
8
|
# NOTE: `return if ... else ... end` is syntax error. If `return` is used before
|
9
|
-
# multiline ternary operator expression, it
|
9
|
+
# multiline ternary operator expression, it will be auto-corrected to single-line
|
10
|
+
# ternary operator. The same is true for `break`, `next`, and method call.
|
10
11
|
#
|
11
12
|
# @example
|
12
13
|
# # bad
|
@@ -18,6 +19,10 @@ module RuboCop
|
|
18
19
|
# b :
|
19
20
|
# c
|
20
21
|
#
|
22
|
+
# return cond ?
|
23
|
+
# b :
|
24
|
+
# c
|
25
|
+
#
|
21
26
|
# # good
|
22
27
|
# a = cond ? b : c
|
23
28
|
# a = if cond
|
@@ -25,20 +30,39 @@ module RuboCop
|
|
25
30
|
# else
|
26
31
|
# c
|
27
32
|
# end
|
33
|
+
#
|
34
|
+
# return cond ? b : c
|
35
|
+
#
|
28
36
|
class MultilineTernaryOperator < Base
|
29
37
|
extend AutoCorrector
|
30
38
|
|
31
|
-
|
39
|
+
MSG_IF = 'Avoid multi-line ternary operators, use `if` or `unless` instead.'
|
40
|
+
MSG_SINGLE_LINE = 'Avoid multi-line ternary operators, use single-line instead.'
|
41
|
+
SINGLE_LINE_TYPES = %i[return break next send].freeze
|
32
42
|
|
33
43
|
def on_if(node)
|
34
44
|
return unless offense?(node)
|
35
45
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
next unless offense?(node)
|
46
|
+
message = enforce_single_line_ternary_operator?(node) ? MSG_SINGLE_LINE : MSG_IF
|
47
|
+
|
48
|
+
add_offense(node, message: message) do |corrector|
|
49
|
+
next unless offense?(node)
|
50
|
+
|
51
|
+
corrector.replace(node, replacement(node))
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
40
56
|
|
41
|
-
|
57
|
+
def offense?(node)
|
58
|
+
node.ternary? && node.multiline?
|
59
|
+
end
|
60
|
+
|
61
|
+
def replacement(node)
|
62
|
+
if enforce_single_line_ternary_operator?(node)
|
63
|
+
"#{node.condition.source} ? #{node.if_branch.source} : #{node.else_branch.source}"
|
64
|
+
else
|
65
|
+
<<~RUBY.chop
|
42
66
|
if #{node.condition.source}
|
43
67
|
#{node.if_branch.source}
|
44
68
|
else
|
@@ -48,10 +72,8 @@ module RuboCop
|
|
48
72
|
end
|
49
73
|
end
|
50
74
|
|
51
|
-
|
52
|
-
|
53
|
-
def offense?(node)
|
54
|
-
node.ternary? && node.multiline?
|
75
|
+
def enforce_single_line_ternary_operator?(node)
|
76
|
+
SINGLE_LINE_TYPES.include?(node.parent.type)
|
55
77
|
end
|
56
78
|
end
|
57
79
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# This cop enforces the use of consistent method names
|
7
|
+
# `Object#yield_self` or `Object#then`.
|
8
|
+
#
|
9
|
+
# @example EnforcedStyle: then (default)
|
10
|
+
#
|
11
|
+
# # bad
|
12
|
+
# obj.yield_self { |x| x.do_something }
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# obj.then { |x| x.do_something }
|
16
|
+
#
|
17
|
+
# @example EnforcedStyle: yield_self
|
18
|
+
#
|
19
|
+
# # bad
|
20
|
+
# obj.then { |x| x.do_something }
|
21
|
+
#
|
22
|
+
# # good
|
23
|
+
# obj.yield_self { |x| x.do_something }
|
24
|
+
#
|
25
|
+
class ObjectThen < Base
|
26
|
+
include ConfigurableEnforcedStyle
|
27
|
+
extend AutoCorrector
|
28
|
+
|
29
|
+
MSG = 'Prefer `%<prefer>s` over `%<current>s`.'
|
30
|
+
|
31
|
+
def on_block(node)
|
32
|
+
check_method_node(node.send_node)
|
33
|
+
end
|
34
|
+
|
35
|
+
def on_send(node)
|
36
|
+
return unless node.arguments.one? && node.first_argument.block_pass_type?
|
37
|
+
|
38
|
+
check_method_node(node)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def check_method_node(node)
|
44
|
+
return unless preferred_method(node)
|
45
|
+
|
46
|
+
message = message(node)
|
47
|
+
add_offense(node.loc.selector, message: message) do |corrector|
|
48
|
+
corrector.replace(node.loc.selector, style.to_s)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def preferred_method(node)
|
53
|
+
case style
|
54
|
+
when :then
|
55
|
+
node.method?(:yield_self)
|
56
|
+
when :yield_self
|
57
|
+
node.method?(:then)
|
58
|
+
else
|
59
|
+
false
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def message(node)
|
64
|
+
format(MSG, prefer: style.to_s, current: node.method_name)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -18,6 +18,10 @@ module RuboCop
|
|
18
18
|
# to purposely create an empty `initialize` method to override a superclass's
|
19
19
|
# initializer.
|
20
20
|
#
|
21
|
+
# @safety
|
22
|
+
# This cop is unsafe because if subclass overrides `initialize` method with
|
23
|
+
# a different arity than superclass.
|
24
|
+
#
|
21
25
|
# @example
|
22
26
|
# # bad
|
23
27
|
# def initialize
|
@@ -76,7 +80,25 @@ module RuboCop
|
|
76
80
|
# def initialize(...)
|
77
81
|
# end
|
78
82
|
#
|
83
|
+
# @example AllowComments: true (default)
|
84
|
+
#
|
85
|
+
# # good
|
86
|
+
# def initialize
|
87
|
+
# # Overriding to negate superclass `initialize` method.
|
88
|
+
# end
|
89
|
+
#
|
90
|
+
# @example AllowComments: false
|
91
|
+
#
|
92
|
+
# # bad
|
93
|
+
# def initialize
|
94
|
+
# # Overriding to negate superclass `initialize` method.
|
95
|
+
# end
|
96
|
+
#
|
79
97
|
class RedundantInitialize < Base
|
98
|
+
include CommentsHelp
|
99
|
+
include RangeHelp
|
100
|
+
extend AutoCorrector
|
101
|
+
|
80
102
|
MSG = 'Remove unnecessary `initialize` method.'
|
81
103
|
MSG_EMPTY = 'Remove unnecessary empty `initialize` method.'
|
82
104
|
|
@@ -86,28 +108,41 @@ module RuboCop
|
|
86
108
|
PATTERN
|
87
109
|
|
88
110
|
def on_def(node)
|
89
|
-
return
|
90
|
-
return if forwards?(node)
|
111
|
+
return if acceptable?(node)
|
91
112
|
|
92
113
|
if node.body.nil?
|
93
|
-
|
114
|
+
register_offense(node, MSG_EMPTY)
|
94
115
|
else
|
95
116
|
return if node.body.begin_type?
|
96
117
|
|
97
118
|
if (args, super_node = initialize_forwards?(node))
|
98
119
|
return unless same_args?(super_node, args)
|
99
120
|
|
100
|
-
|
121
|
+
register_offense(node, MSG)
|
101
122
|
end
|
102
123
|
end
|
103
124
|
end
|
104
125
|
|
105
126
|
private
|
106
127
|
|
128
|
+
def register_offense(node, message)
|
129
|
+
add_offense(node, message: message) do |corrector|
|
130
|
+
corrector.remove(range_by_whole_lines(node.source_range, include_final_newline: true))
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def acceptable?(node)
|
135
|
+
!node.method?(:initialize) || forwards?(node) || allow_comments?(node)
|
136
|
+
end
|
137
|
+
|
107
138
|
def forwards?(node)
|
108
139
|
node.arguments.each_child_node(:restarg, :kwrestarg, :forward_args, :forward_arg).any?
|
109
140
|
end
|
110
141
|
|
142
|
+
def allow_comments?(node)
|
143
|
+
cop_config['AllowComments'] && contains_comments?(node)
|
144
|
+
end
|
145
|
+
|
111
146
|
def same_args?(super_node, args)
|
112
147
|
return true if super_node.zsuper_type?
|
113
148
|
|
@@ -63,6 +63,7 @@ module RuboCop
|
|
63
63
|
next if expr.type != :set || expr.expressions.size != 1
|
64
64
|
next if expr.negative?
|
65
65
|
next if %i[set posixclass nonposixclass].include?(expr.expressions.first.type)
|
66
|
+
next if multiple_codepoins?(expr.expressions.first)
|
66
67
|
|
67
68
|
yield expr
|
68
69
|
end
|
@@ -79,6 +80,10 @@ module RuboCop
|
|
79
80
|
!non_redundant
|
80
81
|
end
|
81
82
|
|
83
|
+
def multiple_codepoins?(expression)
|
84
|
+
expression.respond_to?(:codepoints) && expression.codepoints.count >= 2
|
85
|
+
end
|
86
|
+
|
82
87
|
def without_character_class(loc)
|
83
88
|
without_character_class = loc.source[1..-2]
|
84
89
|
|
@@ -50,9 +50,13 @@ module RuboCop
|
|
50
50
|
|
51
51
|
message = format(MSG, receiver: receiver, argument: argument, original: node.source)
|
52
52
|
add_offense(node, message: message) do |corrector|
|
53
|
+
next if part_of_ignored_node?(node)
|
54
|
+
|
53
55
|
correct_access = "#{receiver}[#{argument}]"
|
54
56
|
corrector.replace(node, correct_access)
|
55
57
|
end
|
58
|
+
|
59
|
+
ignore_node(node)
|
56
60
|
end
|
57
61
|
end
|
58
62
|
end
|
@@ -110,9 +110,12 @@ module RuboCop
|
|
110
110
|
def autocorrect_outer_condition_basic(corrector, node, if_branch)
|
111
111
|
correct_from_unless_to_if(corrector, node) if node.unless?
|
112
112
|
|
113
|
+
outer_condition = node.condition
|
114
|
+
correct_outer_condition(corrector, outer_condition)
|
115
|
+
|
113
116
|
and_operator = if_branch.unless? ? ' && !' : ' && '
|
114
117
|
if if_branch.modifier_form?
|
115
|
-
correct_for_guard_condition_style(corrector,
|
118
|
+
correct_for_guard_condition_style(corrector, outer_condition, if_branch, and_operator)
|
116
119
|
else
|
117
120
|
correct_for_basic_condition_style(corrector, node, if_branch, and_operator)
|
118
121
|
correct_for_comment(corrector, node, if_branch)
|
@@ -136,10 +139,7 @@ module RuboCop
|
|
136
139
|
end
|
137
140
|
end
|
138
141
|
|
139
|
-
def correct_for_guard_condition_style(corrector,
|
140
|
-
outer_condition = node.condition
|
141
|
-
correct_outer_condition(corrector, outer_condition)
|
142
|
-
|
142
|
+
def correct_for_guard_condition_style(corrector, outer_condition, if_branch, and_operator)
|
143
143
|
condition = if_branch.condition
|
144
144
|
corrector.insert_after(outer_condition, "#{and_operator}#{replace_condition(condition)}")
|
145
145
|
|
@@ -177,7 +177,7 @@ module RuboCop
|
|
177
177
|
end
|
178
178
|
|
179
179
|
def correct_outer_condition(corrector, condition)
|
180
|
-
return unless
|
180
|
+
return unless require_parentheses?(condition)
|
181
181
|
|
182
182
|
end_pos = condition.loc.selector.end_pos
|
183
183
|
begin_pos = condition.first_argument.source_range.begin_pos
|
@@ -187,7 +187,7 @@ module RuboCop
|
|
187
187
|
corrector.insert_after(condition.last_argument.source_range, ')')
|
188
188
|
end
|
189
189
|
|
190
|
-
def
|
190
|
+
def require_parentheses?(condition)
|
191
191
|
condition.send_type? && !condition.arguments.empty? && !condition.parenthesized? &&
|
192
192
|
!condition.comparison_method?
|
193
193
|
end
|