rubocop 1.65.1 → 1.66.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 +67 -67
- data/config/default.yml +18 -2
- data/exe/rubocop +4 -3
- data/lib/rubocop/comment_config.rb +8 -4
- data/lib/rubocop/config.rb +20 -4
- data/lib/rubocop/config_loader_resolver.rb +1 -2
- data/lib/rubocop/config_validator.rb +9 -5
- data/lib/rubocop/cop/base.rb +4 -0
- data/lib/rubocop/cop/correctors/line_break_corrector.rb +2 -0
- data/lib/rubocop/cop/documentation.rb +18 -1
- data/lib/rubocop/cop/internal_affairs/empty_line_between_expect_offense_and_correction.rb +2 -1
- data/lib/rubocop/cop/internal_affairs/undefined_config.rb +11 -1
- data/lib/rubocop/cop/layout/block_alignment.rb +30 -12
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +2 -1
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +8 -3
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +0 -3
- data/lib/rubocop/cop/layout/line_length.rb +14 -14
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +27 -6
- data/lib/rubocop/cop/lint/float_comparison.rb +1 -3
- data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +4 -2
- data/lib/rubocop/cop/lint/useless_assignment.rb +18 -11
- data/lib/rubocop/cop/lint/useless_numeric_operation.rb +77 -0
- data/lib/rubocop/cop/lint/void.rb +30 -8
- data/lib/rubocop/cop/metrics/block_length.rb +6 -5
- data/lib/rubocop/cop/metrics/class_length.rb +6 -5
- data/lib/rubocop/cop/metrics/method_length.rb +6 -5
- data/lib/rubocop/cop/metrics/module_length.rb +6 -5
- data/lib/rubocop/cop/mixin/annotation_comment.rb +0 -2
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +19 -9
- data/lib/rubocop/cop/mixin/line_length_help.rb +7 -2
- data/lib/rubocop/cop/mixin/string_literals_help.rb +12 -0
- data/lib/rubocop/cop/naming/accessor_method_name.rb +5 -0
- data/lib/rubocop/cop/naming/predicate_name.rb +1 -1
- data/lib/rubocop/cop/style/alias.rb +1 -1
- data/lib/rubocop/cop/style/arguments_forwarding.rb +8 -3
- data/lib/rubocop/cop/style/empty_else.rb +5 -5
- data/lib/rubocop/cop/style/empty_heredoc.rb +1 -14
- data/lib/rubocop/cop/style/empty_literal.rb +32 -23
- data/lib/rubocop/cop/style/format_string_token.rb +2 -2
- data/lib/rubocop/cop/style/guard_clause.rb +2 -0
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +1 -1
- data/lib/rubocop/cop/style/if_with_semicolon.rb +38 -6
- data/lib/rubocop/cop/style/in_pattern_then.rb +6 -2
- data/lib/rubocop/cop/style/magic_comment_format.rb +8 -3
- data/lib/rubocop/cop/style/map_into_array.rb +11 -2
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -2
- data/lib/rubocop/cop/style/multiple_comparison.rb +3 -11
- data/lib/rubocop/cop/style/numeric_predicate.rb +2 -2
- data/lib/rubocop/cop/style/one_line_conditional.rb +1 -1
- data/lib/rubocop/cop/style/parallel_assignment.rb +5 -4
- data/lib/rubocop/cop/style/quoted_symbols.rb +0 -2
- data/lib/rubocop/cop/style/redundant_condition.rb +3 -2
- data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +46 -0
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +4 -1
- data/lib/rubocop/cop/style/safe_navigation.rb +2 -2
- data/lib/rubocop/cop/team.rb +6 -2
- data/lib/rubocop/formatter/junit_formatter.rb +70 -23
- data/lib/rubocop/lockfile.rb +6 -4
- data/lib/rubocop/remote_config.rb +5 -1
- data/lib/rubocop/result_cache.rb +2 -8
- data/lib/rubocop/rspec/shared_contexts.rb +2 -2
- data/lib/rubocop/server/cache.rb +1 -1
- data/lib/rubocop/target_ruby.rb +7 -3
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +2 -1
- metadata +12 -30
@@ -51,7 +51,6 @@ module RuboCop
|
|
51
51
|
# # defined inside a method call.
|
52
52
|
#
|
53
53
|
# # bad
|
54
|
-
# # consistent
|
55
54
|
# array = [
|
56
55
|
# :value
|
57
56
|
# ]
|
@@ -72,13 +71,11 @@ module RuboCop
|
|
72
71
|
# # brackets are indented to the same position.
|
73
72
|
#
|
74
73
|
# # bad
|
75
|
-
# # align_brackets
|
76
74
|
# and_now_for_something = [
|
77
75
|
# :completely_different
|
78
76
|
# ]
|
79
77
|
#
|
80
78
|
# # good
|
81
|
-
# # align_brackets
|
82
79
|
# and_now_for_something = [
|
83
80
|
# :completely_different
|
84
81
|
# ]
|
@@ -25,20 +25,20 @@ module RuboCop
|
|
25
25
|
# * `Layout/ArrayAlignment`
|
26
26
|
# * `Layout/BlockAlignment`
|
27
27
|
# * `Layout/BlockEndNewline`
|
28
|
-
# * `
|
29
|
-
# * `
|
30
|
-
# * `
|
31
|
-
# * `
|
32
|
-
# * `
|
33
|
-
# * `
|
34
|
-
# * `
|
35
|
-
# * `
|
36
|
-
# * `
|
37
|
-
# * `
|
38
|
-
# * `
|
39
|
-
# * `
|
40
|
-
# * `
|
41
|
-
# * `Layout
|
28
|
+
# * `Layout/ClosingParenthesisIndentation`
|
29
|
+
# * `Layout/FirstArgumentIndentation`
|
30
|
+
# * `Layout/FirstArrayElementIndentation`
|
31
|
+
# * `Layout/FirstHashElementIndentation`
|
32
|
+
# * `Layout/FirstParameterIndentation`
|
33
|
+
# * `Layout/HashAlignment`
|
34
|
+
# * `Layout/IndentationWidth`
|
35
|
+
# * `Layout/MultilineArrayLineBreaks`
|
36
|
+
# * `Layout/MultilineBlockLayout`
|
37
|
+
# * `Layout/MultilineHashBraceLayout`
|
38
|
+
# * `Layout/MultilineHashKeyLineBreaks`
|
39
|
+
# * `Layout/MultilineMethodArgumentLineBreaks`
|
40
|
+
# * `Layout/MultilineMethodParameterLineBreaks`
|
41
|
+
# * `Layout//ParameterAlignment`
|
42
42
|
# * `Style/BlockDelimiters`
|
43
43
|
#
|
44
44
|
# Together, these cops will pretty print hashes, arrays,
|
@@ -67,19 +67,31 @@ module RuboCop
|
|
67
67
|
|
68
68
|
MSG = 'Avoid `%<keyword>s` branches without a body.'
|
69
69
|
|
70
|
+
# rubocop:disable Metrics/AbcSize
|
70
71
|
def on_if(node)
|
71
72
|
return if node.body || same_line?(node.loc.begin, node.loc.end)
|
72
73
|
return if cop_config['AllowComments'] && contains_comments?(node)
|
73
74
|
|
74
|
-
|
75
|
+
range = offense_range(node)
|
76
|
+
|
77
|
+
add_offense(range, message: format(MSG, keyword: node.keyword)) do |corrector|
|
75
78
|
next if node.parent&.call_type?
|
76
79
|
|
77
80
|
autocorrect(corrector, node)
|
78
81
|
end
|
79
82
|
end
|
83
|
+
# rubocop:enable Metrics/AbcSize
|
80
84
|
|
81
85
|
private
|
82
86
|
|
87
|
+
def offense_range(node)
|
88
|
+
if node.loc.else
|
89
|
+
node.source_range.begin.join(node.loc.else.begin)
|
90
|
+
else
|
91
|
+
node.source_range
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
83
95
|
def autocorrect(corrector, node)
|
84
96
|
remove_comments(corrector, node)
|
85
97
|
remove_empty_branch(corrector, node)
|
@@ -93,13 +105,22 @@ module RuboCop
|
|
93
105
|
end
|
94
106
|
end
|
95
107
|
|
108
|
+
# rubocop:disable Metrics/AbcSize
|
96
109
|
def remove_empty_branch(corrector, node)
|
97
|
-
if empty_if_branch?(node) && else_branch?(node)
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
110
|
+
range = if empty_if_branch?(node) && else_branch?(node)
|
111
|
+
branch_range(node)
|
112
|
+
elsif same_line?(node, else_kw_loc = node.loc.else)
|
113
|
+
node.source_range.begin.join(else_kw_loc.begin)
|
114
|
+
elsif node.parent&.loc.respond_to?(:end) &&
|
115
|
+
same_line?(node, end_loc = node.parent.loc.end)
|
116
|
+
node.source_range.begin.join(end_loc.begin)
|
117
|
+
else
|
118
|
+
deletion_range(branch_range(node))
|
119
|
+
end
|
120
|
+
|
121
|
+
corrector.remove(range)
|
102
122
|
end
|
123
|
+
# rubocop:enable Metrics/AbcSize
|
103
124
|
|
104
125
|
def correct_other_branches(corrector, node)
|
105
126
|
return unless require_other_branches_correction?(node)
|
@@ -66,9 +66,7 @@ module RuboCop
|
|
66
66
|
end
|
67
67
|
|
68
68
|
def literal_zero?(node)
|
69
|
-
|
70
|
-
# replace this condition with `node&.numeric_type? && node.value.zero?`.
|
71
|
-
node&.numeric_type? && node.node_parts[0].zero?
|
69
|
+
node&.numeric_type? && node.value.zero?
|
72
70
|
end
|
73
71
|
|
74
72
|
# rubocop:disable Metrics/PerceivedComplexity
|
@@ -40,9 +40,9 @@ module RuboCop
|
|
40
40
|
end
|
41
41
|
|
42
42
|
add_offense(range, message: message) do |corrector|
|
43
|
-
|
43
|
+
range = lhs_node.source_range.end.join(rhs_node.source_range.begin)
|
44
44
|
|
45
|
-
corrector.replace(range,
|
45
|
+
corrector.replace(range, ' + ')
|
46
46
|
end
|
47
47
|
end
|
48
48
|
end
|
@@ -92,6 +92,8 @@ module RuboCop
|
|
92
92
|
end
|
93
93
|
|
94
94
|
def str_content(node)
|
95
|
+
return unless node.respond_to?(:str_type?)
|
96
|
+
|
95
97
|
if node.str_type?
|
96
98
|
node.children[0]
|
97
99
|
else
|
@@ -16,15 +16,14 @@ module RuboCop
|
|
16
16
|
# reassignments and properly handles varied cases such as branch, loop,
|
17
17
|
# rescue, ensure, etc.
|
18
18
|
#
|
19
|
+
# This cop's autocorrection avoids cases like `a ||= 1` because removing assignment from
|
20
|
+
# operator assignment can cause NameError if this assignment has been used to declare
|
21
|
+
# a local variable. For example, replacing `a ||= 1` with `a || 1` may cause
|
22
|
+
# "undefined local variable or method `a' for main:Object (NameError)".
|
23
|
+
#
|
19
24
|
# NOTE: Given the assignment `foo = 1, bar = 2`, removing unused variables
|
20
25
|
# can lead to a syntax error, so this case is not autocorrected.
|
21
26
|
#
|
22
|
-
# @safety
|
23
|
-
# This cop's autocorrection is unsafe because removing assignment from
|
24
|
-
# operator assignment can cause NameError if this assignment has been used to declare
|
25
|
-
# local variable. For example, replacing `a ||= 1` to `a || 1` may cause
|
26
|
-
# "undefined local variable or method `a' for main:Object (NameError)".
|
27
|
-
#
|
28
27
|
# @example
|
29
28
|
#
|
30
29
|
# # bad
|
@@ -53,24 +52,32 @@ module RuboCop
|
|
53
52
|
scope.variables.each_value { |variable| check_for_unused_assignments(variable) }
|
54
53
|
end
|
55
54
|
|
56
|
-
# rubocop:disable Metrics/AbcSize
|
55
|
+
# rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
|
57
56
|
def check_for_unused_assignments(variable)
|
58
57
|
return if variable.should_be_unused?
|
59
58
|
|
60
59
|
variable.assignments.reverse_each do |assignment|
|
61
|
-
|
60
|
+
assignment_node = assignment.node
|
61
|
+
next if assignment.used? || part_of_ignored_node?(assignment_node)
|
62
62
|
|
63
63
|
message = message_for_useless_assignment(assignment)
|
64
64
|
range = offense_range(assignment)
|
65
65
|
|
66
66
|
add_offense(range, message: message) do |corrector|
|
67
|
-
|
67
|
+
# In cases like `x = 1, y = 2`, where removing a variable would cause a syntax error,
|
68
|
+
# and where changing `x ||= 1` to `x = 1` would cause `NameError`,
|
69
|
+
# the autocorrect will be skipped, even if the variable is unused.
|
70
|
+
if sequential_assignment?(assignment_node) || assignment_node.parent&.or_asgn_type?
|
71
|
+
next
|
72
|
+
end
|
73
|
+
|
74
|
+
autocorrect(corrector, assignment)
|
68
75
|
end
|
69
76
|
|
70
|
-
ignore_node(
|
77
|
+
ignore_node(assignment_node) if chained_assignment?(assignment_node)
|
71
78
|
end
|
72
79
|
end
|
73
|
-
# rubocop:enable Metrics/AbcSize
|
80
|
+
# rubocop:enable Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
|
74
81
|
|
75
82
|
def message_for_useless_assignment(assignment)
|
76
83
|
variable = assignment.variable
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
# Certain numeric operations have no impact, being:
|
7
|
+
# Adding or subtracting 0, multiplying or dividing by 1 or raising to the power of 1.
|
8
|
+
# These are probably leftover from debugging, or are mistakes.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
#
|
12
|
+
# # bad
|
13
|
+
# x + 0
|
14
|
+
# x - 0
|
15
|
+
# x * 1
|
16
|
+
# x / 1
|
17
|
+
# x ** 1
|
18
|
+
#
|
19
|
+
# # good
|
20
|
+
# x
|
21
|
+
#
|
22
|
+
# # bad
|
23
|
+
# x += 0
|
24
|
+
# x -= 0
|
25
|
+
# x *= 1
|
26
|
+
# x /= 1
|
27
|
+
# x **= 1
|
28
|
+
#
|
29
|
+
# # good
|
30
|
+
# x = x
|
31
|
+
#
|
32
|
+
class UselessNumericOperation < Base
|
33
|
+
extend AutoCorrector
|
34
|
+
MSG = 'Do not apply inconsequential numeric operations to variables.'
|
35
|
+
RESTRICT_ON_SEND = %i[+ - * / **].freeze
|
36
|
+
|
37
|
+
# @!method useless_operation?(node)
|
38
|
+
def_node_matcher :useless_operation?, '(send (send nil? $_) $_ (int $_))'
|
39
|
+
|
40
|
+
# @!method useless_abbreviated_assignment?(node)
|
41
|
+
def_node_matcher :useless_abbreviated_assignment?, '(op-asgn (lvasgn $_) $_ (int $_))'
|
42
|
+
|
43
|
+
def on_send(node)
|
44
|
+
return unless useless_operation?(node)
|
45
|
+
|
46
|
+
variable, operation, number = useless_operation?(node)
|
47
|
+
return unless useless?(operation, number)
|
48
|
+
|
49
|
+
add_offense(node) do |corrector|
|
50
|
+
corrector.replace(node, variable)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def on_op_asgn(node)
|
55
|
+
return unless useless_abbreviated_assignment?(node)
|
56
|
+
|
57
|
+
variable, operation, number = useless_abbreviated_assignment?(node)
|
58
|
+
return unless useless?(operation, number)
|
59
|
+
|
60
|
+
add_offense(node) do |corrector|
|
61
|
+
corrector.replace(node, "#{variable} = #{variable}")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def useless?(operation, number)
|
68
|
+
if number.zero?
|
69
|
+
true if %i[+ -].include?(operation)
|
70
|
+
elsif number == 1
|
71
|
+
true if %i[* / **].include?(operation)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -66,7 +66,6 @@ module RuboCop
|
|
66
66
|
BINARY_OPERATORS = %i[* / % + - == === != < > <= >= <=>].freeze
|
67
67
|
UNARY_OPERATORS = %i[+@ -@ ~ !].freeze
|
68
68
|
OPERATORS = (BINARY_OPERATORS + UNARY_OPERATORS).freeze
|
69
|
-
VOID_CONTEXT_TYPES = %i[def for block].freeze
|
70
69
|
NONMUTATING_METHODS_WITH_BANG_VERSION = %i[capitalize chomp chop compact
|
71
70
|
delete_prefix delete_suffix downcase
|
72
71
|
encode flatten gsub lstrip merge next
|
@@ -86,7 +85,6 @@ module RuboCop
|
|
86
85
|
check_void_op(node.body) { node.method?(:each) }
|
87
86
|
check_expression(node.body)
|
88
87
|
end
|
89
|
-
|
90
88
|
alias on_numblock on_block
|
91
89
|
|
92
90
|
def on_begin(node)
|
@@ -94,6 +92,10 @@ module RuboCop
|
|
94
92
|
end
|
95
93
|
alias on_kwbegin on_begin
|
96
94
|
|
95
|
+
def on_ensure(node)
|
96
|
+
check_ensure(node)
|
97
|
+
end
|
98
|
+
|
97
99
|
private
|
98
100
|
|
99
101
|
def check_begin(node)
|
@@ -193,12 +195,24 @@ module RuboCop
|
|
193
195
|
end
|
194
196
|
end
|
195
197
|
|
198
|
+
def check_ensure(node)
|
199
|
+
return unless (body = node.body)
|
200
|
+
# NOTE: the `begin` node case is already handled via `on_begin`
|
201
|
+
return if body.begin_type?
|
202
|
+
|
203
|
+
check_void_op(body) do
|
204
|
+
block_node = node.each_ancestor(:block).first
|
205
|
+
block_node&.method?(:each)
|
206
|
+
end
|
207
|
+
|
208
|
+
check_expression(body)
|
209
|
+
end
|
210
|
+
|
196
211
|
def in_void_context?(node)
|
197
212
|
parent = node.parent
|
198
|
-
|
199
213
|
return false unless parent && parent.children.last == node
|
200
214
|
|
201
|
-
|
215
|
+
parent.respond_to?(:void_context?) && parent.void_context?
|
202
216
|
end
|
203
217
|
|
204
218
|
def autocorrect_void_op(corrector, node)
|
@@ -231,15 +245,23 @@ module RuboCop
|
|
231
245
|
def entirely_literal?(node)
|
232
246
|
case node.type
|
233
247
|
when :array
|
234
|
-
|
248
|
+
all_values_entirely_literal?(node)
|
235
249
|
when :hash
|
236
|
-
|
237
|
-
|
238
|
-
node.
|
250
|
+
all_keys_entirely_literal?(node) && all_values_entirely_literal?(node)
|
251
|
+
when :send, :csend
|
252
|
+
node.method?(:freeze) && node.receiver && entirely_literal?(node.receiver)
|
239
253
|
else
|
240
254
|
node.literal?
|
241
255
|
end
|
242
256
|
end
|
257
|
+
|
258
|
+
def all_keys_entirely_literal?(node)
|
259
|
+
node.each_key.all? { |key| entirely_literal?(key) }
|
260
|
+
end
|
261
|
+
|
262
|
+
def all_values_entirely_literal?(node)
|
263
|
+
node.each_value.all? { |value| entirely_literal?(value) }
|
264
|
+
end
|
243
265
|
end
|
244
266
|
end
|
245
267
|
end
|
@@ -9,8 +9,9 @@ module RuboCop
|
|
9
9
|
# The cop can be configured to ignore blocks passed to certain methods.
|
10
10
|
#
|
11
11
|
# You can set constructs you want to fold with `CountAsOne`.
|
12
|
-
#
|
13
|
-
#
|
12
|
+
#
|
13
|
+
# Available are: 'array', 'hash', 'heredoc', and 'method_call'.
|
14
|
+
# Each construct will be counted as one line regardless of its actual size.
|
14
15
|
#
|
15
16
|
# NOTE: This cop does not apply for `Struct` definitions.
|
16
17
|
#
|
@@ -18,7 +19,7 @@ module RuboCop
|
|
18
19
|
# for backwards compatibility. Please use `AllowedMethods` and `AllowedPatterns`
|
19
20
|
# instead. By default, there are no methods to allowed.
|
20
21
|
#
|
21
|
-
# @example CountAsOne: ['array', 'heredoc', 'method_call']
|
22
|
+
# @example CountAsOne: ['array', 'hash', 'heredoc', 'method_call']
|
22
23
|
#
|
23
24
|
# something do
|
24
25
|
# array = [ # +1
|
@@ -26,7 +27,7 @@ module RuboCop
|
|
26
27
|
# 2
|
27
28
|
# ]
|
28
29
|
#
|
29
|
-
# hash = { # +
|
30
|
+
# hash = { # +1
|
30
31
|
# key: 'value'
|
31
32
|
# }
|
32
33
|
#
|
@@ -39,7 +40,7 @@ module RuboCop
|
|
39
40
|
# 1,
|
40
41
|
# 2
|
41
42
|
# )
|
42
|
-
# end #
|
43
|
+
# end # 4 points
|
43
44
|
#
|
44
45
|
class BlockLength < Base
|
45
46
|
include CodeLength
|
@@ -8,12 +8,13 @@ module RuboCop
|
|
8
8
|
# The maximum allowed length is configurable.
|
9
9
|
#
|
10
10
|
# You can set constructs you want to fold with `CountAsOne`.
|
11
|
-
#
|
12
|
-
#
|
11
|
+
#
|
12
|
+
# Available are: 'array', 'hash', 'heredoc', and 'method_call'.
|
13
|
+
# Each construct will be counted as one line regardless of its actual size.
|
13
14
|
#
|
14
15
|
# NOTE: This cop also applies for `Struct` definitions.
|
15
16
|
#
|
16
|
-
# @example CountAsOne: ['array', 'heredoc', 'method_call']
|
17
|
+
# @example CountAsOne: ['array', 'hash', 'heredoc', 'method_call']
|
17
18
|
#
|
18
19
|
# class Foo
|
19
20
|
# ARRAY = [ # +1
|
@@ -21,7 +22,7 @@ module RuboCop
|
|
21
22
|
# 2
|
22
23
|
# ]
|
23
24
|
#
|
24
|
-
# HASH = { # +
|
25
|
+
# HASH = { # +1
|
25
26
|
# key: 'value'
|
26
27
|
# }
|
27
28
|
#
|
@@ -34,7 +35,7 @@ module RuboCop
|
|
34
35
|
# 1,
|
35
36
|
# 2
|
36
37
|
# )
|
37
|
-
# end #
|
38
|
+
# end # 4 points
|
38
39
|
#
|
39
40
|
class ClassLength < Base
|
40
41
|
include CodeLength
|
@@ -8,15 +8,16 @@ module RuboCop
|
|
8
8
|
# The maximum allowed length is configurable.
|
9
9
|
#
|
10
10
|
# You can set constructs you want to fold with `CountAsOne`.
|
11
|
-
#
|
12
|
-
#
|
11
|
+
#
|
12
|
+
# Available are: 'array', 'hash', 'heredoc', and 'method_call'.
|
13
|
+
# Each construct will be counted as one line regardless of its actual size.
|
13
14
|
#
|
14
15
|
# NOTE: The `ExcludedMethods` and `IgnoredMethods` configuration is
|
15
16
|
# deprecated and only kept for backwards compatibility.
|
16
17
|
# Please use `AllowedMethods` and `AllowedPatterns` instead.
|
17
18
|
# By default, there are no methods to allowed.
|
18
19
|
#
|
19
|
-
# @example CountAsOne: ['array', 'heredoc', 'method_call']
|
20
|
+
# @example CountAsOne: ['array', 'hash', 'heredoc', 'method_call']
|
20
21
|
#
|
21
22
|
# def m
|
22
23
|
# array = [ # +1
|
@@ -24,7 +25,7 @@ module RuboCop
|
|
24
25
|
# 2
|
25
26
|
# ]
|
26
27
|
#
|
27
|
-
# hash = { # +
|
28
|
+
# hash = { # +1
|
28
29
|
# key: 'value'
|
29
30
|
# }
|
30
31
|
#
|
@@ -37,7 +38,7 @@ module RuboCop
|
|
37
38
|
# 1,
|
38
39
|
# 2
|
39
40
|
# )
|
40
|
-
# end #
|
41
|
+
# end # 4 points
|
41
42
|
#
|
42
43
|
class MethodLength < Base
|
43
44
|
include CodeLength
|
@@ -8,10 +8,11 @@ module RuboCop
|
|
8
8
|
# The maximum allowed length is configurable.
|
9
9
|
#
|
10
10
|
# You can set constructs you want to fold with `CountAsOne`.
|
11
|
-
# Available are: 'array', 'hash', 'heredoc', and 'method_call'. Each construct
|
12
|
-
# will be counted as one line regardless of its actual size.
|
13
11
|
#
|
14
|
-
#
|
12
|
+
# Available are: 'array', 'hash', 'heredoc', and 'method_call'.
|
13
|
+
# Each construct will be counted as one line regardless of its actual size.
|
14
|
+
#
|
15
|
+
# @example CountAsOne: ['array', 'hash', 'heredoc', 'method_call']
|
15
16
|
#
|
16
17
|
# module M
|
17
18
|
# ARRAY = [ # +1
|
@@ -19,7 +20,7 @@ module RuboCop
|
|
19
20
|
# 2
|
20
21
|
# ]
|
21
22
|
#
|
22
|
-
# HASH = { # +
|
23
|
+
# HASH = { # +1
|
23
24
|
# key: 'value'
|
24
25
|
# }
|
25
26
|
#
|
@@ -32,7 +33,7 @@ module RuboCop
|
|
32
33
|
# 1,
|
33
34
|
# 2
|
34
35
|
# )
|
35
|
-
# end #
|
36
|
+
# end # 4 points
|
36
37
|
#
|
37
38
|
class ModuleLength < Base
|
38
39
|
include CodeLength
|
@@ -4,8 +4,6 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
# Representation of an annotation comment in source code (eg. `# TODO: blah blah blah`).
|
6
6
|
class AnnotationComment
|
7
|
-
extend Forwardable
|
8
|
-
|
9
7
|
attr_reader :comment, :margin, :keyword, :colon, :space, :note
|
10
8
|
|
11
9
|
# @param [Parser::Source::Comment] comment
|
@@ -20,7 +20,7 @@ module RuboCop
|
|
20
20
|
|
21
21
|
def frozen_string_literal?(node)
|
22
22
|
frozen_string = if target_ruby_version >= 3.0
|
23
|
-
uninterpolated_string?(node) ||
|
23
|
+
uninterpolated_string?(node) || uninterpolated_heredoc?(node)
|
24
24
|
else
|
25
25
|
FROZEN_STRING_LITERAL_TYPES_RUBY27.include?(node.type)
|
26
26
|
end
|
@@ -32,29 +32,39 @@ module RuboCop
|
|
32
32
|
node.str_type? || (node.dstr_type? && node.each_descendant(:begin).none?)
|
33
33
|
end
|
34
34
|
|
35
|
-
def
|
35
|
+
def uninterpolated_heredoc?(node)
|
36
36
|
return false unless node.dstr_type? && node.heredoc?
|
37
37
|
|
38
38
|
node.children.all?(&:str_type?)
|
39
39
|
end
|
40
|
+
alias frozen_heredoc? uninterpolated_heredoc?
|
40
41
|
|
41
42
|
def frozen_string_literals_enabled?
|
42
43
|
ruby_version = processed_source.ruby_version
|
43
44
|
return false unless ruby_version
|
44
45
|
|
46
|
+
# Check if a magic string literal comment specifies what to do
|
47
|
+
magic_comments = leading_comment_lines.filter_map { |line| MagicComment.parse(line) }
|
48
|
+
if (literal_magic_comment = magic_comments.find(&:frozen_string_literal_specified?))
|
49
|
+
return literal_magic_comment.frozen_string_literal?
|
50
|
+
end
|
51
|
+
|
45
52
|
# TODO: Ruby officially abandon making frozen string literals default
|
46
53
|
# for Ruby 3.0.
|
47
54
|
# https://bugs.ruby-lang.org/issues/11473#note-53
|
48
|
-
# Whether frozen string literals will be the default after Ruby
|
49
|
-
# or not is still unclear as of
|
55
|
+
# Whether frozen string literals will be the default after Ruby 4.0
|
56
|
+
# or not is still unclear as of July 2024.
|
50
57
|
# It may be necessary to add this code in the future.
|
51
58
|
#
|
52
|
-
# return
|
59
|
+
# return ruby_version >= 4.0 if string_literals_frozen_by_default?.nil?
|
53
60
|
#
|
54
|
-
# And the above `ruby_version >=
|
55
|
-
# Ruby
|
56
|
-
# See https://bugs.ruby-lang.org/issues/
|
57
|
-
|
61
|
+
# And the above `ruby_version >= 4.0` is undecided whether it will be
|
62
|
+
# Ruby 4.0 or others.
|
63
|
+
# See https://bugs.ruby-lang.org/issues/20205 for details.
|
64
|
+
# For now, offer a configuration value to override behavior is using RUBYOPT.
|
65
|
+
return false if string_literals_frozen_by_default?.nil?
|
66
|
+
|
67
|
+
string_literals_frozen_by_default?
|
58
68
|
end
|
59
69
|
|
60
70
|
def frozen_string_literals_disabled?
|
@@ -91,8 +91,13 @@ module RuboCop
|
|
91
91
|
end
|
92
92
|
|
93
93
|
def uri_regexp
|
94
|
-
@uri_regexp ||=
|
95
|
-
|
94
|
+
@uri_regexp ||= begin
|
95
|
+
# Ruby 3.4 changes the default parser to RFC3986 which warns on make_regexp.
|
96
|
+
# Additionally, the RFC2396_PARSER alias is only available on 3.4 for now.
|
97
|
+
# Extra info at https://github.com/ruby/uri/issues/118
|
98
|
+
parser = defined?(URI::RFC2396_PARSER) ? URI::RFC2396_PARSER : URI::DEFAULT_PARSER
|
99
|
+
parser.make_regexp(config.for_cop('Layout/LineLength')['URISchemes'])
|
100
|
+
end
|
96
101
|
end
|
97
102
|
|
98
103
|
def valid_uri?(uri_ish_string)
|
@@ -16,6 +16,18 @@ module RuboCop
|
|
16
16
|
!/" | \\[^'\\] | \#[@{$]/x.match?(src)
|
17
17
|
end
|
18
18
|
end
|
19
|
+
|
20
|
+
def preferred_string_literal
|
21
|
+
enforce_double_quotes? ? '""' : "''"
|
22
|
+
end
|
23
|
+
|
24
|
+
def enforce_double_quotes?
|
25
|
+
string_literals_config['EnforcedStyle'] == 'double_quotes'
|
26
|
+
end
|
27
|
+
|
28
|
+
def string_literals_config
|
29
|
+
config.for_cop('Style/StringLiterals')
|
30
|
+
end
|
19
31
|
end
|
20
32
|
end
|
21
33
|
end
|
@@ -40,6 +40,7 @@ module RuboCop
|
|
40
40
|
MSG_WRITER = 'Do not prefix writer method names with `set_`.'
|
41
41
|
|
42
42
|
def on_def(node)
|
43
|
+
return unless proper_attribute_name?(node)
|
43
44
|
return unless bad_reader_name?(node) || bad_writer_name?(node)
|
44
45
|
|
45
46
|
message = message(node)
|
@@ -58,6 +59,10 @@ module RuboCop
|
|
58
59
|
end
|
59
60
|
end
|
60
61
|
|
62
|
+
def proper_attribute_name?(node)
|
63
|
+
!node.method_name.to_s.end_with?('!', '?', '=')
|
64
|
+
end
|
65
|
+
|
61
66
|
def bad_reader_name?(node)
|
62
67
|
node.method_name.to_s.start_with?('get_') && !node.arguments?
|
63
68
|
end
|