rubocop 1.65.1 → 1.66.1
Sign up to get free protection for your applications and to get access to all the features.
- 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 +1 -1
- data/lib/rubocop/config.rb +5 -1
- data/lib/rubocop/config_loader.rb +14 -8
- data/lib/rubocop/config_loader_resolver.rb +1 -2
- data/lib/rubocop/config_validator.rb +1 -1
- 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/node_matcher_directive.rb +1 -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 +6 -5
- data/lib/rubocop/cop/style/empty_heredoc.rb +1 -14
- data/lib/rubocop/cop/style/empty_literal.rb +31 -22
- 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 +45 -6
- data/lib/rubocop/cop/style/in_pattern_then.rb +6 -2
- data/lib/rubocop/cop/style/magic_comment_format.rb +1 -1
- data/lib/rubocop/cop/style/map_into_array.rb +12 -5
- 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/yaml_duplication_checker.rb +1 -0
- 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
|