rubocop 1.32.0 → 1.33.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 +2 -2
- data/config/default.yml +45 -16
- data/config/obsoletion.yml +23 -1
- data/lib/rubocop/cache_config.rb +29 -0
- data/lib/rubocop/cli/command/auto_genenerate_config.rb +2 -2
- data/lib/rubocop/cli/command/init_dotfile.rb +1 -1
- data/lib/rubocop/config_finder.rb +68 -0
- data/lib/rubocop/config_loader.rb +5 -45
- data/lib/rubocop/config_obsoletion/changed_parameter.rb +5 -0
- data/lib/rubocop/config_obsoletion/parameter_rule.rb +4 -0
- data/lib/rubocop/config_obsoletion.rb +7 -2
- data/lib/rubocop/cop/layout/block_end_newline.rb +32 -5
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +6 -1
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +21 -8
- data/lib/rubocop/cop/lint/debugger.rb +11 -1
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +60 -1
- data/lib/rubocop/cop/lint/number_conversion.rb +24 -8
- data/lib/rubocop/cop/metrics/abc_size.rb +3 -1
- data/lib/rubocop/cop/metrics/block_length.rb +6 -7
- data/lib/rubocop/cop/metrics/method_length.rb +8 -8
- data/lib/rubocop/cop/mixin/allowed_methods.rb +15 -1
- data/lib/rubocop/cop/mixin/allowed_pattern.rb +9 -1
- data/lib/rubocop/cop/mixin/comments_help.rb +5 -1
- data/lib/rubocop/cop/mixin/method_complexity.rb +4 -9
- data/lib/rubocop/cop/naming/predicate_name.rb +24 -3
- data/lib/rubocop/cop/style/block_delimiters.rb +26 -7
- data/lib/rubocop/cop/style/class_and_module_children.rb +4 -4
- data/lib/rubocop/cop/style/class_equality_comparison.rb +32 -7
- data/lib/rubocop/cop/style/empty_heredoc.rb +15 -1
- data/lib/rubocop/cop/style/format_string_token.rb +21 -8
- data/lib/rubocop/cop/style/hash_except.rb +0 -4
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +5 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +7 -7
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +11 -6
- data/lib/rubocop/cop/style/numeric_predicate.rb +28 -8
- data/lib/rubocop/cop/style/redundant_condition.rb +19 -4
- data/lib/rubocop/cop/style/redundant_sort.rb +21 -6
- data/lib/rubocop/cop/style/symbol_proc.rb +29 -9
- data/lib/rubocop/result_cache.rb +22 -20
- data/lib/rubocop/server/cache.rb +33 -1
- data/lib/rubocop/server/cli.rb +19 -2
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +0 -1
- metadata +5 -4
- data/lib/rubocop/cop/mixin/ignored_methods.rb +0 -52
@@ -15,9 +15,19 @@ module RuboCop
|
|
15
15
|
# [source,yaml]
|
16
16
|
# ----
|
17
17
|
# Lint/Debugger:
|
18
|
-
#
|
18
|
+
# DebuggerMethods:
|
19
|
+
# WebConsole: ~
|
19
20
|
# ----
|
20
21
|
#
|
22
|
+
# You can also add your own methods by adding a new category:
|
23
|
+
#
|
24
|
+
# [source,yaml]
|
25
|
+
# ----
|
26
|
+
# Lint/Debugger:
|
27
|
+
# DebuggerMethods:
|
28
|
+
# MyDebugger:
|
29
|
+
# MyDebugger.debug_this
|
30
|
+
# ----
|
21
31
|
#
|
22
32
|
# @example
|
23
33
|
#
|
@@ -4,6 +4,9 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module Lint
|
6
6
|
# Checks for the presence of `if`, `elsif` and `unless` branches without a body.
|
7
|
+
#
|
8
|
+
# NOTE: empty `else` branches are handled by `Style/EmptyElse`.
|
9
|
+
#
|
7
10
|
# @example
|
8
11
|
# # bad
|
9
12
|
# if condition
|
@@ -53,7 +56,9 @@ module RuboCop
|
|
53
56
|
# end
|
54
57
|
#
|
55
58
|
class EmptyConditionalBody < Base
|
59
|
+
extend AutoCorrector
|
56
60
|
include CommentsHelp
|
61
|
+
include RangeHelp
|
57
62
|
|
58
63
|
MSG = 'Avoid `%<keyword>s` branches without a body.'
|
59
64
|
|
@@ -61,7 +66,61 @@ module RuboCop
|
|
61
66
|
return if node.body
|
62
67
|
return if cop_config['AllowComments'] && contains_comments?(node)
|
63
68
|
|
64
|
-
add_offense(node, message: format(MSG, keyword: node.keyword))
|
69
|
+
add_offense(node, message: format(MSG, keyword: node.keyword)) do |corrector|
|
70
|
+
autocorrect(corrector, node)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def autocorrect(corrector, node)
|
77
|
+
remove_comments(corrector, node)
|
78
|
+
remove_empty_branch(corrector, node)
|
79
|
+
correct_other_branches(corrector, node)
|
80
|
+
end
|
81
|
+
|
82
|
+
def remove_comments(corrector, node)
|
83
|
+
comments_in_range(node).each do |comment|
|
84
|
+
range = range_by_whole_lines(comment.loc.expression, include_final_newline: true)
|
85
|
+
corrector.remove(range)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def remove_empty_branch(corrector, node)
|
90
|
+
corrector.remove(deletion_range(branch_range(node)))
|
91
|
+
end
|
92
|
+
|
93
|
+
def correct_other_branches(corrector, node)
|
94
|
+
return unless (node.if? || node.unless?) && node.else_branch
|
95
|
+
|
96
|
+
if node.else_branch.if_type?
|
97
|
+
# Replace an orphaned `elsif` with `if`
|
98
|
+
corrector.replace(node.else_branch.loc.keyword, 'if')
|
99
|
+
else
|
100
|
+
# Flip orphaned `else`
|
101
|
+
corrector.replace(node.loc.else, "#{node.inverse_keyword} #{node.condition.source}")
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def branch_range(node)
|
106
|
+
if node.loc.else
|
107
|
+
node.source_range.with(end_pos: node.loc.else.begin_pos - 1)
|
108
|
+
else
|
109
|
+
node.source_range
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def deletion_range(range)
|
114
|
+
# Collect a range between the start of the `if` node and the next relevant node,
|
115
|
+
# including final new line.
|
116
|
+
# Based on `RangeHelp#range_by_whole_lines` but allows the `if` to not start
|
117
|
+
# on the first column.
|
118
|
+
buffer = @processed_source.buffer
|
119
|
+
|
120
|
+
last_line = buffer.source_line(range.last_line)
|
121
|
+
end_offset = last_line.length - range.last_column + 1
|
122
|
+
|
123
|
+
range.adjust(end_pos: end_offset).intersect(buffer.source_range)
|
65
124
|
end
|
66
125
|
end
|
67
126
|
end
|
@@ -16,8 +16,8 @@ module RuboCop
|
|
16
16
|
# NOTE: Some values cannot be converted properly using one of the `Kernel`
|
17
17
|
# method (for instance, `Time` and `DateTime` values are allowed by this
|
18
18
|
# cop by default). Similarly, Rails' duration methods do not work well
|
19
|
-
# with `Integer()` and can be
|
20
|
-
# there are no methods to
|
19
|
+
# with `Integer()` and can be allowed with `AllowedMethods`. By default,
|
20
|
+
# there are no methods to allowed.
|
21
21
|
#
|
22
22
|
# @safety
|
23
23
|
# Autocorrection is unsafe because it is not guaranteed that the
|
@@ -46,12 +46,22 @@ module RuboCop
|
|
46
46
|
# foo.try { |i| Float(i) }
|
47
47
|
# bar.send { |i| Complex(i) }
|
48
48
|
#
|
49
|
-
# @example
|
49
|
+
# @example AllowedMethods: [] (default)
|
50
50
|
#
|
51
51
|
# # bad
|
52
52
|
# 10.minutes.to_i
|
53
53
|
#
|
54
|
-
# @example
|
54
|
+
# @example AllowedMethods: [minutes]
|
55
|
+
#
|
56
|
+
# # good
|
57
|
+
# 10.minutes.to_i
|
58
|
+
#
|
59
|
+
# @example AllowedPatterns: [] (default)
|
60
|
+
#
|
61
|
+
# # bad
|
62
|
+
# 10.minutes.to_i
|
63
|
+
#
|
64
|
+
# @example AllowedPatterns: [/min*/]
|
55
65
|
#
|
56
66
|
# # good
|
57
67
|
# 10.minutes.to_i
|
@@ -62,7 +72,8 @@ module RuboCop
|
|
62
72
|
# Time.now.to_datetime.to_i
|
63
73
|
class NumberConversion < Base
|
64
74
|
extend AutoCorrector
|
65
|
-
include
|
75
|
+
include AllowedMethods
|
76
|
+
include AllowedPattern
|
66
77
|
|
67
78
|
CONVERSION_METHOD_CLASS_MAPPING = {
|
68
79
|
to_i: "#{Integer.name}(%<number_object>s, 10)",
|
@@ -97,7 +108,7 @@ module RuboCop
|
|
97
108
|
|
98
109
|
def handle_conversion_method(node)
|
99
110
|
to_method(node) do |receiver, to_method|
|
100
|
-
next if receiver.nil? ||
|
111
|
+
next if receiver.nil? || allow_receiver?(receiver)
|
101
112
|
|
102
113
|
message = format(
|
103
114
|
MSG,
|
@@ -141,9 +152,10 @@ module RuboCop
|
|
141
152
|
corrector.remove(node.loc.end)
|
142
153
|
end
|
143
154
|
|
144
|
-
def
|
155
|
+
def allow_receiver?(receiver)
|
145
156
|
if receiver.numeric_type? || (receiver.send_type? &&
|
146
|
-
(conversion_method?(receiver.method_name) ||
|
157
|
+
(conversion_method?(receiver.method_name) ||
|
158
|
+
allowed_method_name?(receiver.method_name)))
|
147
159
|
true
|
148
160
|
elsif (receiver = top_receiver(receiver))
|
149
161
|
receiver.const_type? && ignored_class?(receiver.const_name)
|
@@ -152,6 +164,10 @@ module RuboCop
|
|
152
164
|
end
|
153
165
|
end
|
154
166
|
|
167
|
+
def allowed_method_name?(name)
|
168
|
+
allowed_method?(name) || matches_allowed_pattern?(name)
|
169
|
+
end
|
170
|
+
|
155
171
|
def top_receiver(node)
|
156
172
|
receiver = node
|
157
173
|
receiver = receiver.receiver until receiver.receiver.nil?
|
@@ -33,7 +33,9 @@ module RuboCop
|
|
33
33
|
# render 'pages/search/page'
|
34
34
|
# end
|
35
35
|
#
|
36
|
-
# This cop also takes into account `
|
36
|
+
# This cop also takes into account `AllowedMethods` (defaults to `[]`)
|
37
|
+
# And `AllowedPatterns` (defaults to `[]`)
|
38
|
+
#
|
37
39
|
class AbcSize < Base
|
38
40
|
include MethodComplexity
|
39
41
|
|
@@ -14,8 +14,8 @@ module RuboCop
|
|
14
14
|
#
|
15
15
|
#
|
16
16
|
# NOTE: The `ExcludedMethods` configuration is deprecated and only kept
|
17
|
-
# for backwards compatibility. Please use `
|
18
|
-
# By default, there are no methods to
|
17
|
+
# for backwards compatibility. Please use `AllowedMethods` and `AllowedPatterns`
|
18
|
+
# instead. By default, there are no methods to allowed.
|
19
19
|
#
|
20
20
|
# @example CountAsOne: ['array', 'heredoc']
|
21
21
|
#
|
@@ -38,14 +38,13 @@ module RuboCop
|
|
38
38
|
# NOTE: This cop does not apply for `Struct` definitions.
|
39
39
|
class BlockLength < Base
|
40
40
|
include CodeLength
|
41
|
-
include
|
42
|
-
|
43
|
-
ignored_methods deprecated_key: 'ExcludedMethods'
|
41
|
+
include AllowedMethods
|
42
|
+
include AllowedPattern
|
44
43
|
|
45
44
|
LABEL = 'Block'
|
46
45
|
|
47
46
|
def on_block(node)
|
48
|
-
return if
|
47
|
+
return if allowed_method?(node.method_name) || matches_allowed_pattern?(node.method_name)
|
49
48
|
return if method_receiver_excluded?(node)
|
50
49
|
return if node.class_constructor? || node.struct_constructor?
|
51
50
|
|
@@ -59,7 +58,7 @@ module RuboCop
|
|
59
58
|
node_receiver = node.receiver&.source&.gsub(/\s+/, '')
|
60
59
|
node_method = String(node.method_name)
|
61
60
|
|
62
|
-
|
61
|
+
allowed_methods.any? do |config|
|
63
62
|
next unless config.is_a?(String)
|
64
63
|
|
65
64
|
receiver, method = config.split('.')
|
@@ -4,16 +4,17 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module Metrics
|
6
6
|
# Checks if the length of a method exceeds some maximum value.
|
7
|
-
# Comment lines can optionally be
|
7
|
+
# Comment lines can optionally be allowed.
|
8
8
|
# The maximum allowed length is configurable.
|
9
9
|
#
|
10
10
|
# You can set literals you want to fold with `CountAsOne`.
|
11
11
|
# Available are: 'array', 'hash', and 'heredoc'. Each literal
|
12
12
|
# will be counted as one line regardless of its actual size.
|
13
13
|
#
|
14
|
-
# NOTE: The `ExcludedMethods` configuration is
|
15
|
-
#
|
16
|
-
#
|
14
|
+
# NOTE: The `ExcludedMethods` and `IgnoredMethods` configuration is
|
15
|
+
# deprecated and only kept for backwards compatibility.
|
16
|
+
# Please use `AllowedMethods` and `AllowedPatterns` instead.
|
17
|
+
# By default, there are no methods to allowed.
|
17
18
|
#
|
18
19
|
# @example CountAsOne: ['array', 'heredoc']
|
19
20
|
#
|
@@ -35,14 +36,13 @@ module RuboCop
|
|
35
36
|
#
|
36
37
|
class MethodLength < Base
|
37
38
|
include CodeLength
|
38
|
-
include
|
39
|
-
|
40
|
-
ignored_methods deprecated_key: 'ExcludedMethods'
|
39
|
+
include AllowedMethods
|
40
|
+
include AllowedPattern
|
41
41
|
|
42
42
|
LABEL = 'Method'
|
43
43
|
|
44
44
|
def on_def(node)
|
45
|
-
return if
|
45
|
+
return if allowed_method?(node.method_name) || matches_allowed_pattern?(node.method_name)
|
46
46
|
|
47
47
|
check_code_length(node)
|
48
48
|
end
|
@@ -12,10 +12,24 @@ module RuboCop
|
|
12
12
|
allowed_methods.include?(name.to_s)
|
13
13
|
end
|
14
14
|
|
15
|
+
# @deprecated Use allowed_method? instead
|
16
|
+
alias ignored_method? allowed_method?
|
17
|
+
|
15
18
|
# @api public
|
16
19
|
def allowed_methods
|
17
|
-
|
20
|
+
deprecated_values = cop_config_deprecated_values
|
21
|
+
if deprecated_values.any?(Regexp)
|
22
|
+
cop_config.fetch('AllowedMethods', [])
|
23
|
+
else
|
24
|
+
Array(cop_config['AllowedMethods']).concat(deprecated_values)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def cop_config_deprecated_values
|
29
|
+
Array(cop_config['IgnoredMethods']).concat(Array(cop_config['ExcludedMethods']))
|
18
30
|
end
|
19
31
|
end
|
32
|
+
# @deprecated IgnoredMethods class has been replaced with AllowedMethods.
|
33
|
+
IgnoredMethods = AllowedMethods
|
20
34
|
end
|
21
35
|
end
|
@@ -30,7 +30,15 @@ module RuboCop
|
|
30
30
|
def allowed_patterns
|
31
31
|
# Since there could be a pattern specified in the default config, merge the two
|
32
32
|
# arrays together.
|
33
|
-
Array(cop_config['AllowedPatterns']).concat(Array(cop_config['IgnoredPatterns']))
|
33
|
+
patterns = Array(cop_config['AllowedPatterns']).concat(Array(cop_config['IgnoredPatterns']))
|
34
|
+
deprecated_values = cop_config_deprecated_methods_values
|
35
|
+
return patterns unless deprecated_values.any?(Regexp)
|
36
|
+
|
37
|
+
Array(patterns.concat(deprecated_values))
|
38
|
+
end
|
39
|
+
|
40
|
+
def cop_config_deprecated_methods_values
|
41
|
+
Array(cop_config['IgnoredMethods']).concat(Array(cop_config['ExcludedMethods']))
|
34
42
|
end
|
35
43
|
end
|
36
44
|
|
@@ -12,10 +12,14 @@ module RuboCop
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def contains_comments?(node)
|
15
|
+
comments_in_range(node).any?
|
16
|
+
end
|
17
|
+
|
18
|
+
def comments_in_range(node)
|
15
19
|
start_line = node.source_range.line
|
16
20
|
end_line = find_end_line(node)
|
17
21
|
|
18
|
-
processed_source.each_comment_in_lines(start_line...end_line)
|
22
|
+
processed_source.each_comment_in_lines(start_line...end_line)
|
19
23
|
end
|
20
24
|
|
21
25
|
private
|
@@ -6,21 +6,16 @@ module RuboCop
|
|
6
6
|
#
|
7
7
|
# This module handles measurement and reporting of complexity in methods.
|
8
8
|
module MethodComplexity
|
9
|
-
include
|
9
|
+
include AllowedMethods
|
10
|
+
include AllowedPattern
|
10
11
|
include Metrics::Utils::RepeatedCsendDiscount
|
11
12
|
extend NodePattern::Macros
|
12
13
|
extend ExcludeLimit
|
13
14
|
|
14
15
|
exclude_limit 'Max'
|
15
16
|
|
16
|
-
# Ensure cops that include `MethodComplexity` have the config
|
17
|
-
# `attr_accessor`s that `ignored_method?` needs.
|
18
|
-
def self.included(base)
|
19
|
-
base.extend(IgnoredMethods::Config)
|
20
|
-
end
|
21
|
-
|
22
17
|
def on_def(node)
|
23
|
-
return if
|
18
|
+
return if allowed_method?(node.method_name) || matches_allowed_pattern?(node.method_name)
|
24
19
|
|
25
20
|
check_complexity(node, node.method_name)
|
26
21
|
end
|
@@ -28,7 +23,7 @@ module RuboCop
|
|
28
23
|
|
29
24
|
def on_block(node)
|
30
25
|
define_method?(node) do |name|
|
31
|
-
return if
|
26
|
+
return if allowed_method?(name) || matches_allowed_pattern?(name)
|
32
27
|
|
33
28
|
check_complexity(node, name)
|
34
29
|
end
|
@@ -3,9 +3,30 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Naming
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
6
|
+
# Checks that predicate methods names end with a question mark and
|
7
|
+
# do not start with a forbidden prefix.
|
8
|
+
#
|
9
|
+
# A method is determined to be a predicate method if its name starts
|
10
|
+
# with one of the prefixes defined in the `NamePrefix` configuration.
|
11
|
+
# You can change what prefixes are considered by changing this option.
|
12
|
+
# Any method name that starts with one of these prefixes is required by
|
13
|
+
# the cop to end with a `?`. Other methods can be allowed by adding to
|
14
|
+
# the `AllowedMethods` configuration.
|
15
|
+
#
|
16
|
+
# NOTE: The `is_a?` method is allowed by default.
|
17
|
+
#
|
18
|
+
# If `ForbiddenPrefixes` is set, methods that start with the configured
|
19
|
+
# prefixes will not be allowed and will be removed by autocorrection.
|
20
|
+
#
|
21
|
+
# In other words, if `ForbiddenPrefixes` is empty, a method named `is_foo`
|
22
|
+
# will register an offense only due to the lack of question mark (and will be
|
23
|
+
# autocorrected to `is_foo?`). If `ForbiddenPrefixes` contains `is_`,
|
24
|
+
# `is_foo` will register an offense both because the ? is missing and because of
|
25
|
+
# the `is_` prefix, and will be corrected to `foo?`.
|
26
|
+
#
|
27
|
+
# NOTE: `ForbiddenPrefixes` is only applied to prefixes in `NamePrefix`;
|
28
|
+
# a prefix in the former but not the latter will not be considered by
|
29
|
+
# this cop.
|
9
30
|
#
|
10
31
|
# @example
|
11
32
|
# # bad
|
@@ -10,7 +10,7 @@ module RuboCop
|
|
10
10
|
# Methods that can be either procedural or functional and cannot be
|
11
11
|
# categorised from their usage alone is ignored.
|
12
12
|
# `lambda`, `proc`, and `it` are their defaults.
|
13
|
-
# Additional methods can be added to the `
|
13
|
+
# Additional methods can be added to the `AllowedMethods`.
|
14
14
|
#
|
15
15
|
# @example EnforcedStyle: line_count_based (default)
|
16
16
|
# # bad - single line block
|
@@ -66,7 +66,7 @@ module RuboCop
|
|
66
66
|
# x
|
67
67
|
# }.inspect
|
68
68
|
#
|
69
|
-
# # The AllowBracesOnProceduralOneLiners option is
|
69
|
+
# # The AllowBracesOnProceduralOneLiners option is allowed unless the
|
70
70
|
# # EnforcedStyle is set to `semantic`. If so:
|
71
71
|
#
|
72
72
|
# # If the AllowBracesOnProceduralOneLiners option is unspecified, or
|
@@ -116,7 +116,7 @@ module RuboCop
|
|
116
116
|
#
|
117
117
|
# # Methods listed in the BracesRequiredMethods list, such as 'sig'
|
118
118
|
# # in this example, will require `{...}` braces. This option takes
|
119
|
-
# # precedence over all other configurations except
|
119
|
+
# # precedence over all other configurations except AllowedMethods.
|
120
120
|
#
|
121
121
|
# # bad
|
122
122
|
# sig do
|
@@ -138,7 +138,7 @@ module RuboCop
|
|
138
138
|
# puts foo
|
139
139
|
# end
|
140
140
|
#
|
141
|
-
# @example
|
141
|
+
# @example AllowedMethods: ['lambda', 'proc', 'it' ] (default)
|
142
142
|
#
|
143
143
|
# # good
|
144
144
|
# foo = lambda do |x|
|
@@ -149,9 +149,26 @@ module RuboCop
|
|
149
149
|
# x * 100
|
150
150
|
# end
|
151
151
|
#
|
152
|
+
# @example AllowedPatterns: [] (default)
|
153
|
+
#
|
154
|
+
# # bad
|
155
|
+
# things.map { |thing|
|
156
|
+
# something = thing.some_method
|
157
|
+
# process(something)
|
158
|
+
# }
|
159
|
+
#
|
160
|
+
# @example AllowedPatterns: [/map/]
|
161
|
+
#
|
162
|
+
# # good
|
163
|
+
# things.map { |thing|
|
164
|
+
# something = thing.some_method
|
165
|
+
# process(something)
|
166
|
+
# }
|
167
|
+
#
|
152
168
|
class BlockDelimiters < Base
|
153
169
|
include ConfigurableEnforcedStyle
|
154
|
-
include
|
170
|
+
include AllowedMethods
|
171
|
+
include AllowedPattern
|
155
172
|
include RangeHelp
|
156
173
|
extend AutoCorrector
|
157
174
|
|
@@ -330,12 +347,14 @@ module RuboCop
|
|
330
347
|
end
|
331
348
|
|
332
349
|
def special_method?(method_name)
|
333
|
-
|
350
|
+
allowed_method?(method_name) ||
|
351
|
+
matches_allowed_pattern?(method_name) ||
|
352
|
+
braces_required_method?(method_name)
|
334
353
|
end
|
335
354
|
|
336
355
|
def special_method_proper_block_style?(node)
|
337
356
|
method_name = node.method_name
|
338
|
-
return true if
|
357
|
+
return true if allowed_method?(method_name) || matches_allowed_pattern?(method_name)
|
339
358
|
return node.braces? if braces_required_method?(method_name)
|
340
359
|
end
|
341
360
|
|
@@ -117,10 +117,10 @@ module RuboCop
|
|
117
117
|
end
|
118
118
|
|
119
119
|
def remove_end(corrector, body)
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
120
|
+
remove_begin_pos = body.loc.end.begin_pos - leading_spaces(body).size
|
121
|
+
adjustment = processed_source.raw_source[remove_begin_pos] == ';' ? 0 : 1
|
122
|
+
range = range_between(remove_begin_pos, body.loc.end.end_pos + adjustment)
|
123
|
+
|
124
124
|
corrector.remove(range)
|
125
125
|
end
|
126
126
|
|
@@ -5,8 +5,8 @@ module RuboCop
|
|
5
5
|
module Style
|
6
6
|
# Enforces the use of `Object#instance_of?` instead of class comparison
|
7
7
|
# for equality.
|
8
|
-
# `==`, `equal?`, and `eql?` methods are
|
9
|
-
# These are customizable with `
|
8
|
+
# `==`, `equal?`, and `eql?` methods are allowed by default.
|
9
|
+
# These are customizable with `AllowedMethods` option.
|
10
10
|
#
|
11
11
|
# @example
|
12
12
|
# # bad
|
@@ -18,7 +18,7 @@ module RuboCop
|
|
18
18
|
# # good
|
19
19
|
# var.instance_of?(Date)
|
20
20
|
#
|
21
|
-
# @example
|
21
|
+
# @example AllowedMethods: [] (default)
|
22
22
|
# # good
|
23
23
|
# var.instance_of?(Date)
|
24
24
|
#
|
@@ -28,7 +28,7 @@ module RuboCop
|
|
28
28
|
# var.class.eql?(Date)
|
29
29
|
# var.class.name == 'Date'
|
30
30
|
#
|
31
|
-
# @example
|
31
|
+
# @example AllowedMethods: [`==`]
|
32
32
|
# # good
|
33
33
|
# var.instance_of?(Date)
|
34
34
|
# var.class == Date
|
@@ -38,9 +38,30 @@ module RuboCop
|
|
38
38
|
# var.class.equal?(Date)
|
39
39
|
# var.class.eql?(Date)
|
40
40
|
#
|
41
|
+
# @example AllowedPatterns: [] (default)
|
42
|
+
# # good
|
43
|
+
# var.instance_of?(Date)
|
44
|
+
#
|
45
|
+
# # bad
|
46
|
+
# var.class == Date
|
47
|
+
# var.class.equal?(Date)
|
48
|
+
# var.class.eql?(Date)
|
49
|
+
# var.class.name == 'Date'
|
50
|
+
#
|
51
|
+
# @example AllowedPatterns: [`/eq/`]
|
52
|
+
# # good
|
53
|
+
# var.instance_of?(Date)
|
54
|
+
# var.class.equal?(Date)
|
55
|
+
# var.class.eql?(Date)
|
56
|
+
#
|
57
|
+
# # bad
|
58
|
+
# var.class == Date
|
59
|
+
# var.class.name == 'Date'
|
60
|
+
#
|
41
61
|
class ClassEqualityComparison < Base
|
42
62
|
include RangeHelp
|
43
|
-
include
|
63
|
+
include AllowedMethods
|
64
|
+
include AllowedPattern
|
44
65
|
extend AutoCorrector
|
45
66
|
|
46
67
|
MSG = 'Use `instance_of?(%<class_name>s)` instead of comparing classes.'
|
@@ -56,7 +77,9 @@ module RuboCop
|
|
56
77
|
|
57
78
|
def on_send(node)
|
58
79
|
def_node = node.each_ancestor(:def, :defs).first
|
59
|
-
return if def_node &&
|
80
|
+
return if def_node &&
|
81
|
+
(allowed_method?(def_node.method_name) ||
|
82
|
+
matches_allowed_pattern?(def_node.method_name))
|
60
83
|
|
61
84
|
class_comparison_candidate?(node) do |receiver_node, class_node|
|
62
85
|
range = offense_range(receiver_node, node)
|
@@ -74,7 +97,9 @@ module RuboCop
|
|
74
97
|
if node.children.first.method?(:name)
|
75
98
|
return class_node.receiver.source if class_node.receiver
|
76
99
|
|
77
|
-
class_node.source.delete('"').delete("'")
|
100
|
+
value = class_node.source.delete('"').delete("'")
|
101
|
+
value.prepend('::') if class_node.each_ancestor(:class, :module).any?
|
102
|
+
value
|
78
103
|
else
|
79
104
|
class_node.source
|
80
105
|
end
|
@@ -48,11 +48,25 @@ module RuboCop
|
|
48
48
|
add_offense(node) do |corrector|
|
49
49
|
heredoc_end = node.loc.heredoc_end
|
50
50
|
|
51
|
-
corrector.replace(node,
|
51
|
+
corrector.replace(node, preferred_string_literal)
|
52
52
|
corrector.remove(range_by_whole_lines(heredoc_body, include_final_newline: true))
|
53
53
|
corrector.remove(range_by_whole_lines(heredoc_end, include_final_newline: true))
|
54
54
|
end
|
55
55
|
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def preferred_string_literal
|
60
|
+
enforce_double_quotes? ? '""' : "''"
|
61
|
+
end
|
62
|
+
|
63
|
+
def enforce_double_quotes?
|
64
|
+
string_literals_config['EnforcedStyle'] == 'double_quotes'
|
65
|
+
end
|
66
|
+
|
67
|
+
def string_literals_config
|
68
|
+
config.for_cop('Style/StringLiterals')
|
69
|
+
end
|
56
70
|
end
|
57
71
|
end
|
58
72
|
end
|
@@ -11,8 +11,8 @@ module RuboCop
|
|
11
11
|
# The reason is that _unannotated_ format is very similar
|
12
12
|
# to encoded URLs or Date/Time formatting strings.
|
13
13
|
#
|
14
|
-
# This cop can be customized
|
15
|
-
# By default, there are no methods to
|
14
|
+
# This cop can be customized allowed methods with `AllowedMethods`.
|
15
|
+
# By default, there are no methods to allowed.
|
16
16
|
#
|
17
17
|
# @example EnforcedStyle: annotated (default)
|
18
18
|
#
|
@@ -62,23 +62,34 @@ module RuboCop
|
|
62
62
|
# # good
|
63
63
|
# format('%06d', 10)
|
64
64
|
#
|
65
|
-
# @example
|
65
|
+
# @example AllowedMethods: [] (default)
|
66
66
|
#
|
67
67
|
# # bad
|
68
68
|
# redirect('foo/%{bar_id}')
|
69
69
|
#
|
70
|
-
# @example
|
70
|
+
# @example AllowedMethods: [redirect]
|
71
|
+
#
|
72
|
+
# # good
|
73
|
+
# redirect('foo/%{bar_id}')
|
74
|
+
#
|
75
|
+
# @example AllowedPatterns: [] (default)
|
76
|
+
#
|
77
|
+
# # bad
|
78
|
+
# redirect('foo/%{bar_id}')
|
79
|
+
#
|
80
|
+
# @example AllowedPatterns: [/redirect/]
|
71
81
|
#
|
72
82
|
# # good
|
73
83
|
# redirect('foo/%{bar_id}')
|
74
84
|
#
|
75
85
|
class FormatStringToken < Base
|
76
86
|
include ConfigurableEnforcedStyle
|
77
|
-
include
|
87
|
+
include AllowedMethods
|
88
|
+
include AllowedPattern
|
78
89
|
extend AutoCorrector
|
79
90
|
|
80
91
|
def on_str(node)
|
81
|
-
return if format_string_token?(node) ||
|
92
|
+
return if format_string_token?(node) || use_allowed_method?(node)
|
82
93
|
|
83
94
|
detections = collect_detections(node)
|
84
95
|
return if detections.empty?
|
@@ -103,9 +114,11 @@ module RuboCop
|
|
103
114
|
!node.value.include?('%') || node.each_ancestor(:xstr, :regexp).any?
|
104
115
|
end
|
105
116
|
|
106
|
-
def
|
117
|
+
def use_allowed_method?(node)
|
107
118
|
send_parent = node.each_ancestor(:send).first
|
108
|
-
send_parent &&
|
119
|
+
send_parent &&
|
120
|
+
(allowed_method?(send_parent.method_name) ||
|
121
|
+
matches_allowed_pattern?(send_parent.method_name))
|
109
122
|
end
|
110
123
|
|
111
124
|
def check_sequence(detected_sequence, token_range)
|