rubocop 1.56.0 → 1.57.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 +12 -6
- data/lib/rubocop/cli.rb +1 -1
- data/lib/rubocop/cop/autocorrect_logic.rb +3 -1
- data/lib/rubocop/cop/bundler/duplicated_group.rb +54 -8
- data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +7 -4
- data/lib/rubocop/cop/internal_affairs/example_description.rb +42 -22
- data/lib/rubocop/cop/internal_affairs/redundant_method_dispatch_node.rb +11 -2
- data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +2 -0
- data/lib/rubocop/cop/layout/dot_position.rb +1 -5
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +41 -8
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +3 -0
- data/lib/rubocop/cop/layout/indentation_width.rb +1 -1
- data/lib/rubocop/cop/layout/leading_comment_space.rb +1 -1
- data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +17 -9
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +13 -2
- data/lib/rubocop/cop/layout/redundant_line_break.rb +5 -3
- data/lib/rubocop/cop/layout/space_after_not.rb +1 -1
- data/lib/rubocop/cop/layout/space_inside_parens.rb +1 -1
- data/lib/rubocop/cop/lint/debugger.rb +10 -1
- data/lib/rubocop/cop/lint/empty_block.rb +1 -1
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
- data/lib/rubocop/cop/lint/mixed_case_range.rb +1 -1
- data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +10 -7
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -0
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +16 -4
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +11 -4
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +5 -3
- data/lib/rubocop/cop/lint/useless_assignment.rb +38 -12
- data/lib/rubocop/cop/metrics/block_length.rb +1 -1
- data/lib/rubocop/cop/metrics/class_length.rb +2 -2
- data/lib/rubocop/cop/metrics/method_length.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +2 -2
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +3 -2
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +5 -7
- data/lib/rubocop/cop/naming/file_name.rb +1 -1
- data/lib/rubocop/cop/style/arguments_forwarding.rb +22 -11
- data/lib/rubocop/cop/style/array_intersect.rb +13 -5
- data/lib/rubocop/cop/style/class_equality_comparison.rb +5 -0
- data/lib/rubocop/cop/style/collection_methods.rb +2 -0
- data/lib/rubocop/cop/style/combinable_loops.rb +3 -2
- data/lib/rubocop/cop/style/concat_array_literals.rb +1 -1
- data/lib/rubocop/cop/style/empty_case_condition.rb +6 -1
- data/lib/rubocop/cop/style/for.rb +1 -1
- data/lib/rubocop/cop/style/format_string.rb +24 -3
- data/lib/rubocop/cop/style/guard_clause.rb +26 -0
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +17 -3
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +3 -1
- data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -1
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +1 -1
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +3 -11
- data/lib/rubocop/cop/style/open_struct_use.rb +1 -1
- data/lib/rubocop/cop/style/operator_method_call.rb +6 -0
- data/lib/rubocop/cop/style/redundant_begin.rb +9 -1
- data/lib/rubocop/cop/style/redundant_conditional.rb +1 -9
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +69 -6
- data/lib/rubocop/cop/style/redundant_filter_chain.rb +18 -2
- data/lib/rubocop/cop/style/redundant_parentheses.rb +24 -6
- data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +5 -0
- data/lib/rubocop/cop/style/return_nil.rb +6 -2
- data/lib/rubocop/cop/style/single_line_do_end_block.rb +65 -0
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +3 -1
- data/lib/rubocop/cop/style/symbol_array.rb +12 -11
- data/lib/rubocop/cop/style/yoda_expression.rb +8 -7
- data/lib/rubocop/cop/utils/regexp_ranges.rb +26 -13
- data/lib/rubocop/file_finder.rb +4 -7
- data/lib/rubocop/lsp/routes.rb +4 -1
- data/lib/rubocop/magic_comment.rb +12 -10
- data/lib/rubocop/rspec/shared_contexts.rb +2 -3
- data/lib/rubocop/server/cache.rb +1 -0
- data/lib/rubocop/target_ruby.rb +9 -5
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +1 -0
- metadata +13 -12
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 28726dbde536af4bb4a8f7cc92d9c6ef3ddfa6c63b01a76317c2a9121a3318fa
|
|
4
|
+
data.tar.gz: 977ac77a446b41c15b0ce61795d1911d8620c47f439ab25274a5fd00586e79d2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5d87aae9334ac67e671b3b584ae853aa06e14893302a297315a1e746535863b0751b620d6dd35c96a7d3721b2be53cd01dde42b47f722af68365056f155a083e
|
|
7
|
+
data.tar.gz: 6ae78b00947a397723220aa271f260bdda5f44c4f45b7b4dabda984b9b176d344dc386391e79b2d40beb6a347fbde99f3aa970d4f6f23b91d441cced03f345a1
|
data/README.md
CHANGED
|
@@ -53,7 +53,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
|
|
|
53
53
|
in your `Gemfile`:
|
|
54
54
|
|
|
55
55
|
```rb
|
|
56
|
-
gem 'rubocop', '~> 1.
|
|
56
|
+
gem 'rubocop', '~> 1.57', require: false
|
|
57
57
|
```
|
|
58
58
|
|
|
59
59
|
See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
|
data/config/default.yml
CHANGED
|
@@ -2170,7 +2170,9 @@ Lint/RedundantRegexpQuantifiers:
|
|
|
2170
2170
|
Lint/RedundantRequireStatement:
|
|
2171
2171
|
Description: 'Checks for unnecessary `require` statement.'
|
|
2172
2172
|
Enabled: true
|
|
2173
|
+
SafeAutoCorrect: false
|
|
2173
2174
|
VersionAdded: '0.76'
|
|
2175
|
+
VersionChanged: '1.57'
|
|
2174
2176
|
|
|
2175
2177
|
Lint/RedundantSafeNavigation:
|
|
2176
2178
|
Description: 'Checks for redundant safe navigation calls.'
|
|
@@ -3354,7 +3356,9 @@ Style/ClassEqualityComparison:
|
|
|
3354
3356
|
Description: 'Enforces the use of `Object#instance_of?` instead of class comparison for equality.'
|
|
3355
3357
|
StyleGuide: '#instance-of-vs-class-comparison'
|
|
3356
3358
|
Enabled: true
|
|
3359
|
+
SafeAutoCorrect: false
|
|
3357
3360
|
VersionAdded: '0.93'
|
|
3361
|
+
VersionChanged: '1.57'
|
|
3358
3362
|
AllowedMethods:
|
|
3359
3363
|
- ==
|
|
3360
3364
|
- equal?
|
|
@@ -3409,6 +3413,7 @@ Style/CollectionMethods:
|
|
|
3409
3413
|
PreferredMethods:
|
|
3410
3414
|
collect: 'map'
|
|
3411
3415
|
collect!: 'map!'
|
|
3416
|
+
collect_concat: 'flat_map'
|
|
3412
3417
|
inject: 'reduce'
|
|
3413
3418
|
detect: 'find'
|
|
3414
3419
|
find_all: 'select'
|
|
@@ -4130,12 +4135,6 @@ Style/InvertibleUnlessCondition:
|
|
|
4130
4135
|
:none?: :any?
|
|
4131
4136
|
:even?: :odd?
|
|
4132
4137
|
:odd?: :even?
|
|
4133
|
-
# `ActiveSupport` defines some common inverse methods. They are listed below,
|
|
4134
|
-
# and not enabled by default.
|
|
4135
|
-
# :present?: :blank?
|
|
4136
|
-
# :blank?: :present?
|
|
4137
|
-
# :include?: :exclude?
|
|
4138
|
-
# :exclude?: :include?
|
|
4139
4138
|
|
|
4140
4139
|
Style/IpAddresses:
|
|
4141
4140
|
Description: "Don't include literal IP addresses in code."
|
|
@@ -4925,7 +4924,9 @@ Style/RedundantFilterChain:
|
|
|
4925
4924
|
Identifies usages of `any?`, `empty?`, `none?` or `one?` predicate methods chained to
|
|
4926
4925
|
`select`/`filter`/`find_all` and change them to use predicate method instead.
|
|
4927
4926
|
Enabled: pending
|
|
4927
|
+
SafeAutoCorrect: false
|
|
4928
4928
|
VersionAdded: '1.52'
|
|
4929
|
+
VersionChanged: '1.57'
|
|
4929
4930
|
|
|
4930
4931
|
Style/RedundantFreeze:
|
|
4931
4932
|
Description: "Checks usages of Object#freeze on immutable objects."
|
|
@@ -5187,6 +5188,11 @@ Style/SingleLineBlockParams:
|
|
|
5187
5188
|
- acc
|
|
5188
5189
|
- elem
|
|
5189
5190
|
|
|
5191
|
+
Style/SingleLineDoEndBlock:
|
|
5192
|
+
Description: 'Checks for single-line `do`...`end` blocks.'
|
|
5193
|
+
Enabled: pending
|
|
5194
|
+
VersionAdded: '1.57'
|
|
5195
|
+
|
|
5190
5196
|
Style/SingleLineMethods:
|
|
5191
5197
|
Description: 'Avoid single-line methods.'
|
|
5192
5198
|
StyleGuide: '#no-single-line-methods'
|
data/lib/rubocop/cli.rb
CHANGED
|
@@ -11,7 +11,7 @@ module RuboCop
|
|
|
11
11
|
STATUS_ERROR = 2
|
|
12
12
|
STATUS_INTERRUPTED = Signal.list['INT'] + 128
|
|
13
13
|
DEFAULT_PARALLEL_OPTIONS = %i[
|
|
14
|
-
color debug display_style_guide display_time display_only_fail_level_offenses
|
|
14
|
+
color config debug display_style_guide display_time display_only_fail_level_offenses
|
|
15
15
|
display_only_failed except extra_details fail_level fix_layout format
|
|
16
16
|
ignore_disable_comments lint only only_guide_cops require safe
|
|
17
17
|
autocorrect safe_autocorrect autocorrect_all
|
|
@@ -82,7 +82,9 @@ module RuboCop
|
|
|
82
82
|
node.array_type? && node.percent_literal?
|
|
83
83
|
end
|
|
84
84
|
|
|
85
|
-
percent_array.map(&:source_range).find
|
|
85
|
+
percent_array.map(&:source_range).find do |range|
|
|
86
|
+
offense_range.begin_pos > range.begin_pos && range.overlaps?(offense_range)
|
|
87
|
+
end
|
|
86
88
|
end
|
|
87
89
|
|
|
88
90
|
def range_of_first_line(range)
|
|
@@ -5,6 +5,24 @@ module RuboCop
|
|
|
5
5
|
module Bundler
|
|
6
6
|
# A Gem group, or a set of groups, should be listed only once in a Gemfile.
|
|
7
7
|
#
|
|
8
|
+
# For example, if the values of `source`, `git`, `platforms`, or `path`
|
|
9
|
+
# surrounding `group` are different, no offense will be registered:
|
|
10
|
+
#
|
|
11
|
+
# [source,ruby]
|
|
12
|
+
# -----
|
|
13
|
+
# platforms :ruby do
|
|
14
|
+
# group :default do
|
|
15
|
+
# gem 'openssl'
|
|
16
|
+
# end
|
|
17
|
+
# end
|
|
18
|
+
#
|
|
19
|
+
# platforms :jruby do
|
|
20
|
+
# group :default do
|
|
21
|
+
# gem 'jruby-openssl'
|
|
22
|
+
# end
|
|
23
|
+
# end
|
|
24
|
+
# -----
|
|
25
|
+
#
|
|
8
26
|
# @example
|
|
9
27
|
# # bad
|
|
10
28
|
# group :development do
|
|
@@ -42,27 +60,35 @@ module RuboCop
|
|
|
42
60
|
|
|
43
61
|
MSG = 'Gem group `%<group_name>s` already defined on line ' \
|
|
44
62
|
'%<line_of_first_occurrence>d of the Gemfile.'
|
|
63
|
+
SOURCE_BLOCK_NAMES = %i[source git platforms path].freeze
|
|
64
|
+
|
|
65
|
+
# @!method group_declarations(node)
|
|
66
|
+
def_node_search :group_declarations, '(send nil? :group ...)'
|
|
45
67
|
|
|
46
68
|
def on_new_investigation
|
|
47
69
|
return if processed_source.blank?
|
|
48
70
|
|
|
49
71
|
duplicated_group_nodes.each do |nodes|
|
|
50
72
|
nodes[1..].each do |node|
|
|
51
|
-
|
|
73
|
+
group_name = node.arguments.map(&:source).join(', ')
|
|
74
|
+
|
|
75
|
+
register_offense(node, group_name, nodes.first.first_line)
|
|
52
76
|
end
|
|
53
77
|
end
|
|
54
78
|
end
|
|
55
79
|
|
|
56
80
|
private
|
|
57
81
|
|
|
58
|
-
# @!method group_declarations(node)
|
|
59
|
-
def_node_search :group_declarations, '(send nil? :group ...)'
|
|
60
|
-
|
|
61
82
|
def duplicated_group_nodes
|
|
62
|
-
group_declarations(processed_source.ast)
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
83
|
+
group_declarations = group_declarations(processed_source.ast)
|
|
84
|
+
group_keys = group_declarations.group_by do |node|
|
|
85
|
+
source_key = find_source_key(node)
|
|
86
|
+
group_attributes = group_attributes(node).sort.join
|
|
87
|
+
|
|
88
|
+
"#{source_key}#{group_attributes}"
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
group_keys.values.select { |nodes| nodes.size > 1 }
|
|
66
92
|
end
|
|
67
93
|
|
|
68
94
|
def register_offense(node, group_name, line_of_first_occurrence)
|
|
@@ -75,6 +101,26 @@ module RuboCop
|
|
|
75
101
|
)
|
|
76
102
|
add_offense(offense_location, message: message)
|
|
77
103
|
end
|
|
104
|
+
|
|
105
|
+
def find_source_key(node)
|
|
106
|
+
source_block = node.each_ancestor(:block).find do |block_node|
|
|
107
|
+
SOURCE_BLOCK_NAMES.include?(block_node.method_name)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
return unless source_block
|
|
111
|
+
|
|
112
|
+
"#{source_block.method_name}#{source_block.send_node.first_argument&.source}"
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def group_attributes(node)
|
|
116
|
+
node.arguments.map do |argument|
|
|
117
|
+
if argument.hash_type?
|
|
118
|
+
argument.pairs.map(&:source).sort.join(', ')
|
|
119
|
+
else
|
|
120
|
+
argument.respond_to?(:value) ? argument.value.to_s : argument.source
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
78
124
|
end
|
|
79
125
|
end
|
|
80
126
|
end
|
|
@@ -14,12 +14,15 @@ module RuboCop
|
|
|
14
14
|
# Check for unparenthesized args' preceding and trailing whitespaces.
|
|
15
15
|
remove_unparenthesized_whitespace(corrector)
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
if block_node.block_type?
|
|
18
|
+
# Avoid correcting to `lambdado` by inserting whitespace
|
|
19
|
+
# if none exists before or after the lambda arguments.
|
|
20
|
+
insert_separating_space(corrector)
|
|
21
|
+
|
|
22
|
+
remove_arguments(corrector)
|
|
23
|
+
end
|
|
20
24
|
|
|
21
25
|
replace_selector(corrector)
|
|
22
|
-
remove_arguments(corrector)
|
|
23
26
|
|
|
24
27
|
replace_delimiters(corrector)
|
|
25
28
|
|
|
@@ -26,9 +26,7 @@ module RuboCop
|
|
|
26
26
|
# expect_no_offenses('...')
|
|
27
27
|
# end
|
|
28
28
|
class ExampleDescription < Base
|
|
29
|
-
|
|
30
|
-
attr_accessor :descriptions
|
|
31
|
-
end
|
|
29
|
+
extend AutoCorrector
|
|
32
30
|
|
|
33
31
|
MSG = 'Description does not match use of `%<method_name>s`.'
|
|
34
32
|
|
|
@@ -39,22 +37,31 @@ module RuboCop
|
|
|
39
37
|
expect_no_corrections
|
|
40
38
|
].to_set.freeze
|
|
41
39
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
EXPECT_NO_OFFENSES_DESCRIPTION_MAPPING = {
|
|
41
|
+
/\A(adds|registers|reports|finds) (an? )?offense/ => 'does not register an offense',
|
|
42
|
+
/\A(flags|handles|works)\b/ => 'does not register'
|
|
43
|
+
}.freeze
|
|
44
|
+
|
|
45
|
+
EXPECT_OFFENSE_DESCRIPTION_MAPPING = {
|
|
46
|
+
/\A(does not|doesn't) (register|find|flag|report)/ => 'registers',
|
|
47
|
+
/\A(does not|doesn't) add (a|an|any )?offense/ => 'registers an offense',
|
|
48
|
+
/\Aaccepts\b/ => 'registers'
|
|
49
|
+
}.freeze
|
|
46
50
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
/^accepts\b/
|
|
51
|
-
].freeze
|
|
51
|
+
EXPECT_NO_CORRECTIONS_DESCRIPTION_MAPPING = {
|
|
52
|
+
/\A(auto[- ]?)?correct/ => 'does not correct'
|
|
53
|
+
}.freeze
|
|
52
54
|
|
|
53
|
-
|
|
55
|
+
EXPECT_CORRECTION_DESCRIPTION_MAPPING = {
|
|
56
|
+
/\b(does not|doesn't) (auto[- ]?)?correct/ => 'autocorrects'
|
|
57
|
+
}.freeze
|
|
54
58
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
59
|
+
EXAMPLE_DESCRIPTION_MAPPING = {
|
|
60
|
+
expect_no_offenses: EXPECT_NO_OFFENSES_DESCRIPTION_MAPPING,
|
|
61
|
+
expect_offense: EXPECT_OFFENSE_DESCRIPTION_MAPPING,
|
|
62
|
+
expect_no_corrections: EXPECT_NO_CORRECTIONS_DESCRIPTION_MAPPING,
|
|
63
|
+
expect_correction: EXPECT_CORRECTION_DESCRIPTION_MAPPING
|
|
64
|
+
}.freeze
|
|
58
65
|
|
|
59
66
|
# @!method offense_example?(node)
|
|
60
67
|
def_node_matcher :offense_example?, <<~PATTERN
|
|
@@ -67,21 +74,34 @@ module RuboCop
|
|
|
67
74
|
|
|
68
75
|
def on_send(node)
|
|
69
76
|
parent = node.each_ancestor(:block).first
|
|
70
|
-
return unless parent && (
|
|
77
|
+
return unless parent && (current_description = offense_example?(parent))
|
|
71
78
|
|
|
72
79
|
method_name = node.method_name
|
|
73
80
|
message = format(MSG, method_name: method_name)
|
|
74
81
|
|
|
75
|
-
|
|
76
|
-
check_description(
|
|
82
|
+
description_map = EXAMPLE_DESCRIPTION_MAPPING[method_name]
|
|
83
|
+
check_description(current_description, description_map, message)
|
|
77
84
|
end
|
|
78
85
|
|
|
79
86
|
private
|
|
80
87
|
|
|
81
|
-
def check_description(
|
|
82
|
-
|
|
88
|
+
def check_description(current_description, description_map, message)
|
|
89
|
+
description_text = string_contents(current_description)
|
|
90
|
+
return unless (new_description = correct_description(description_text, description_map))
|
|
91
|
+
|
|
92
|
+
add_offense(current_description, message: message) do |corrector|
|
|
93
|
+
corrector.replace(current_description, "'#{new_description}'")
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def correct_description(current_description, description_map)
|
|
98
|
+
description_map.each do |incorrect_description_pattern, preferred_description|
|
|
99
|
+
if incorrect_description_pattern.match?(current_description)
|
|
100
|
+
return current_description.gsub(incorrect_description_pattern, preferred_description)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
83
103
|
|
|
84
|
-
|
|
104
|
+
nil
|
|
85
105
|
end
|
|
86
106
|
|
|
87
107
|
def string_contents(node)
|
|
@@ -14,6 +14,12 @@ module RuboCop
|
|
|
14
14
|
# node.method_name
|
|
15
15
|
#
|
|
16
16
|
# # bad
|
|
17
|
+
# node.send_node.method?(:method_name)
|
|
18
|
+
#
|
|
19
|
+
# # good
|
|
20
|
+
# node.method?(:method_name)
|
|
21
|
+
#
|
|
22
|
+
# # bad
|
|
17
23
|
# node.send_node.receiver
|
|
18
24
|
#
|
|
19
25
|
# # good
|
|
@@ -24,11 +30,14 @@ module RuboCop
|
|
|
24
30
|
extend AutoCorrector
|
|
25
31
|
|
|
26
32
|
MSG = 'Remove the redundant `send_node`.'
|
|
27
|
-
RESTRICT_ON_SEND = %i[method_name receiver].freeze
|
|
33
|
+
RESTRICT_ON_SEND = %i[method_name method? receiver].freeze
|
|
28
34
|
|
|
29
35
|
# @!method dispatch_method(node)
|
|
30
36
|
def_node_matcher :dispatch_method, <<~PATTERN
|
|
31
|
-
|
|
37
|
+
{
|
|
38
|
+
(send $(send _ :send_node) {:method_name :receiver})
|
|
39
|
+
(send $(send _ :send_node) :method? _)
|
|
40
|
+
}
|
|
32
41
|
PATTERN
|
|
33
42
|
|
|
34
43
|
def on_send(node)
|
|
@@ -32,7 +32,7 @@ module RuboCop
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def on_send(node)
|
|
35
|
-
return unless node.dot? ||
|
|
35
|
+
return unless node.dot? || node.safe_navigation?
|
|
36
36
|
|
|
37
37
|
return correct_style_detected if proper_dot_position?(node)
|
|
38
38
|
|
|
@@ -133,10 +133,6 @@ module RuboCop
|
|
|
133
133
|
# l.(1) has no selector, so we use the opening parenthesis instead
|
|
134
134
|
node.loc.selector || node.loc.begin
|
|
135
135
|
end
|
|
136
|
-
|
|
137
|
-
def ampersand_dot?(node)
|
|
138
|
-
node.loc.respond_to?(:dot) && node.loc.dot && node.loc.dot.is?('&.')
|
|
139
|
-
end
|
|
140
136
|
end
|
|
141
137
|
end
|
|
142
138
|
end
|
|
@@ -3,7 +3,23 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Layout
|
|
6
|
-
# Enforces empty line after guard clause
|
|
6
|
+
# Enforces empty line after guard clause.
|
|
7
|
+
#
|
|
8
|
+
# This cop allows `# :nocov:` directive after guard clause because
|
|
9
|
+
# SimpleCov excludes code from the coverage report by wrapping it in `# :nocov:`:
|
|
10
|
+
#
|
|
11
|
+
# [source,ruby]
|
|
12
|
+
# ----
|
|
13
|
+
# def foo
|
|
14
|
+
# # :nocov:
|
|
15
|
+
# return if condition
|
|
16
|
+
# # :nocov:
|
|
17
|
+
# bar
|
|
18
|
+
# end
|
|
19
|
+
# ----
|
|
20
|
+
#
|
|
21
|
+
# Refer to SimpleCov's documentation for more details:
|
|
22
|
+
# https://github.com/simplecov-ruby/simplecov#ignoringskipping-code
|
|
7
23
|
#
|
|
8
24
|
# @example
|
|
9
25
|
#
|
|
@@ -42,19 +58,22 @@ module RuboCop
|
|
|
42
58
|
|
|
43
59
|
MSG = 'Add empty line after guard clause.'
|
|
44
60
|
END_OF_HEREDOC_LINE = 1
|
|
61
|
+
SIMPLE_DIRECTIVE_COMMENT_PATTERN = /\A# *:nocov:\z/.freeze
|
|
45
62
|
|
|
46
63
|
def on_if(node)
|
|
47
64
|
return if correct_style?(node)
|
|
48
65
|
return if multiple_statements_on_line?(node)
|
|
49
66
|
|
|
50
67
|
if node.modifier_form? && (heredoc_node = last_heredoc_argument(node))
|
|
51
|
-
|
|
68
|
+
if next_line_empty_or_allowed_directive_comment?(heredoc_line(node, heredoc_node))
|
|
69
|
+
return
|
|
70
|
+
end
|
|
52
71
|
|
|
53
72
|
add_offense(heredoc_node.loc.heredoc_end) do |corrector|
|
|
54
73
|
autocorrect(corrector, heredoc_node)
|
|
55
74
|
end
|
|
56
75
|
else
|
|
57
|
-
return if
|
|
76
|
+
return if next_line_empty_or_allowed_directive_comment?(node.last_line)
|
|
58
77
|
|
|
59
78
|
add_offense(offense_location(node)) { |corrector| autocorrect(corrector, node) }
|
|
60
79
|
end
|
|
@@ -70,7 +89,7 @@ module RuboCop
|
|
|
70
89
|
end
|
|
71
90
|
|
|
72
91
|
next_line = node_range.last_line + 1
|
|
73
|
-
if
|
|
92
|
+
if next_line_allowed_directive_comment?(next_line)
|
|
74
93
|
node_range = processed_source.comment_at_line(next_line)
|
|
75
94
|
end
|
|
76
95
|
|
|
@@ -88,21 +107,21 @@ module RuboCop
|
|
|
88
107
|
node.if_branch&.guard_clause?
|
|
89
108
|
end
|
|
90
109
|
|
|
91
|
-
def
|
|
110
|
+
def next_line_empty_or_allowed_directive_comment?(line)
|
|
92
111
|
return true if next_line_empty?(line)
|
|
93
112
|
|
|
94
113
|
next_line = line + 1
|
|
95
|
-
|
|
114
|
+
next_line_allowed_directive_comment?(next_line) && next_line_empty?(next_line)
|
|
96
115
|
end
|
|
97
116
|
|
|
98
117
|
def next_line_empty?(line)
|
|
99
118
|
processed_source[line].blank?
|
|
100
119
|
end
|
|
101
120
|
|
|
102
|
-
def
|
|
121
|
+
def next_line_allowed_directive_comment?(line)
|
|
103
122
|
return false unless (comment = processed_source.comment_at_line(line))
|
|
104
123
|
|
|
105
|
-
DirectiveComment.new(comment).enabled?
|
|
124
|
+
DirectiveComment.new(comment).enabled? || simplecov_directive_comment?(comment)
|
|
106
125
|
end
|
|
107
126
|
|
|
108
127
|
def next_line_rescue_or_ensure?(node)
|
|
@@ -145,6 +164,8 @@ module RuboCop
|
|
|
145
164
|
|
|
146
165
|
if node.if_branch.and_type?
|
|
147
166
|
node.if_branch.children.first
|
|
167
|
+
elsif use_heredoc_in_condition?(node.condition)
|
|
168
|
+
node.condition
|
|
148
169
|
else
|
|
149
170
|
node.if_branch.children.last
|
|
150
171
|
end
|
|
@@ -161,6 +182,12 @@ module RuboCop
|
|
|
161
182
|
node.respond_to?(:heredoc?) && node.heredoc?
|
|
162
183
|
end
|
|
163
184
|
|
|
185
|
+
def use_heredoc_in_condition?(condition)
|
|
186
|
+
condition.descendants.any? do |descendant|
|
|
187
|
+
descendant.respond_to?(:heredoc?) && descendant.heredoc?
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
164
191
|
def offense_location(node)
|
|
165
192
|
if node.loc.respond_to?(:end) && node.loc.end
|
|
166
193
|
node.loc.end
|
|
@@ -175,6 +202,12 @@ module RuboCop
|
|
|
175
202
|
|
|
176
203
|
parent.begin_type? && parent.single_line?
|
|
177
204
|
end
|
|
205
|
+
|
|
206
|
+
# SimpleCov excludes code from the coverage report by wrapping it in `# :nocov:`:
|
|
207
|
+
# https://github.com/simplecov-ruby/simplecov#ignoringskipping-code
|
|
208
|
+
def simplecov_directive_comment?(comment)
|
|
209
|
+
SIMPLE_DIRECTIVE_COMMENT_PATTERN.match?(comment.text)
|
|
210
|
+
end
|
|
178
211
|
end
|
|
179
212
|
end
|
|
180
213
|
end
|
|
@@ -25,6 +25,9 @@ module RuboCop
|
|
|
25
25
|
include Alignment
|
|
26
26
|
include Heredoc
|
|
27
27
|
extend AutoCorrector
|
|
28
|
+
extend TargetRubyVersion
|
|
29
|
+
|
|
30
|
+
minimum_target_ruby_version 2.3
|
|
28
31
|
|
|
29
32
|
TYPE_MSG = 'Use %<indentation_width>d spaces for indentation in a ' \
|
|
30
33
|
'heredoc by using `<<~` instead of `%<current_indent_type>s`.'
|
|
@@ -354,7 +354,7 @@ module RuboCop
|
|
|
354
354
|
# Don't check indentation if the line doesn't start with the body.
|
|
355
355
|
# For example, lines like "else do_something".
|
|
356
356
|
first_char_pos_on_line = body_node.source_range.source_line =~ /\S/
|
|
357
|
-
|
|
357
|
+
body_node.loc.column != first_char_pos_on_line
|
|
358
358
|
end
|
|
359
359
|
|
|
360
360
|
def offending_range(body_node, indentation)
|
|
@@ -57,7 +57,7 @@ module RuboCop
|
|
|
57
57
|
|
|
58
58
|
def on_new_investigation
|
|
59
59
|
processed_source.comments.each do |comment|
|
|
60
|
-
next unless /\A#+[^#\s
|
|
60
|
+
next unless /\A(?!#\+\+|#--)(#+[^#\s=])/.match?(comment.text)
|
|
61
61
|
next if comment.loc.line == 1 && allowed_on_first_line?(comment)
|
|
62
62
|
next if doxygen_comment_style?(comment)
|
|
63
63
|
next if gemfile_ruby_comment?(comment)
|
|
@@ -57,16 +57,13 @@ module RuboCop
|
|
|
57
57
|
|
|
58
58
|
end_of_first_line = node.source_range.begin_pos - node.source_range.column
|
|
59
59
|
|
|
60
|
-
raw_lines(node)
|
|
60
|
+
lines = raw_lines(node)
|
|
61
|
+
lines.each_cons(2).with_index(node.first_line) do |(raw_line_one, raw_line_two), line_num|
|
|
61
62
|
end_of_first_line += raw_line_one.length
|
|
62
63
|
|
|
63
|
-
next unless continuation?(raw_line_one)
|
|
64
|
+
next unless continuation?(raw_line_one, line_num, node)
|
|
64
65
|
|
|
65
|
-
|
|
66
|
-
investigate_leading_style(raw_line_one, raw_line_two, end_of_first_line)
|
|
67
|
-
else
|
|
68
|
-
investigate_trailing_style(raw_line_one, raw_line_two, end_of_first_line)
|
|
69
|
-
end
|
|
66
|
+
investigate(raw_line_one, raw_line_two, end_of_first_line)
|
|
70
67
|
end
|
|
71
68
|
end
|
|
72
69
|
|
|
@@ -76,6 +73,14 @@ module RuboCop
|
|
|
76
73
|
processed_source.raw_source.lines[node.first_line - 1, line_range(node).size]
|
|
77
74
|
end
|
|
78
75
|
|
|
76
|
+
def investigate(first_line, second_line, end_of_first_line)
|
|
77
|
+
if enforced_style_leading?
|
|
78
|
+
investigate_leading_style(first_line, second_line, end_of_first_line)
|
|
79
|
+
else
|
|
80
|
+
investigate_trailing_style(first_line, second_line, end_of_first_line)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
79
84
|
def investigate_leading_style(first_line, second_line, end_of_first_line)
|
|
80
85
|
matches = first_line.match(LEADING_STYLE_OFFENSE)
|
|
81
86
|
return if matches.nil?
|
|
@@ -98,8 +103,11 @@ module RuboCop
|
|
|
98
103
|
end
|
|
99
104
|
end
|
|
100
105
|
|
|
101
|
-
def continuation?(line)
|
|
102
|
-
line.end_with?("\\\n")
|
|
106
|
+
def continuation?(line, line_num, node)
|
|
107
|
+
return false unless line.end_with?("\\\n")
|
|
108
|
+
|
|
109
|
+
# Ensure backslash isn't part of a token spanning to the next line.
|
|
110
|
+
node.children.none? { |c| c.first_line == line_num && c.multiline? }
|
|
103
111
|
end
|
|
104
112
|
|
|
105
113
|
def autocorrect(corrector, offense_range, insert_pos, spaces)
|
|
@@ -109,7 +109,7 @@ module RuboCop
|
|
|
109
109
|
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
110
110
|
|
|
111
111
|
def comment_ranges(comments)
|
|
112
|
-
comments.map(&:
|
|
112
|
+
comments.map(&:source_range)
|
|
113
113
|
end
|
|
114
114
|
|
|
115
115
|
def last_line(processed_source)
|
|
@@ -75,7 +75,7 @@ module RuboCop
|
|
|
75
75
|
def right_hand_side(send_node)
|
|
76
76
|
dot = send_node.loc.dot
|
|
77
77
|
selector = send_node.loc.selector
|
|
78
|
-
if send_node.dot? && selector && same_line?(dot, selector)
|
|
78
|
+
if (send_node.dot? || send_node.safe_navigation?) && selector && same_line?(dot, selector)
|
|
79
79
|
dot.join(selector)
|
|
80
80
|
elsif selector
|
|
81
81
|
selector
|
|
@@ -179,7 +179,7 @@ module RuboCop
|
|
|
179
179
|
# a.b
|
|
180
180
|
# .c
|
|
181
181
|
def semantic_alignment_base(node, rhs)
|
|
182
|
-
return unless rhs.source.start_with?('.')
|
|
182
|
+
return unless rhs.source.start_with?('.', '&.')
|
|
183
183
|
|
|
184
184
|
node = semantic_alignment_node(node)
|
|
185
185
|
return unless node&.loc&.selector
|
|
@@ -204,6 +204,10 @@ module RuboCop
|
|
|
204
204
|
dot_right_above = get_dot_right_above(node)
|
|
205
205
|
return dot_right_above if dot_right_above
|
|
206
206
|
|
|
207
|
+
if (multiline_block_chain_node = find_multiline_block_chain_node(node))
|
|
208
|
+
return multiline_block_chain_node
|
|
209
|
+
end
|
|
210
|
+
|
|
207
211
|
node = first_call_has_a_dot(node)
|
|
208
212
|
return if node.loc.dot.line != node.first_line
|
|
209
213
|
|
|
@@ -219,6 +223,13 @@ module RuboCop
|
|
|
219
223
|
end
|
|
220
224
|
end
|
|
221
225
|
|
|
226
|
+
def find_multiline_block_chain_node(node)
|
|
227
|
+
return unless (block_node = node.each_descendant(:block, :numblock).first)
|
|
228
|
+
return unless block_node.multiline? && block_node.parent.call_type?
|
|
229
|
+
|
|
230
|
+
block_node.parent
|
|
231
|
+
end
|
|
232
|
+
|
|
222
233
|
def first_call_has_a_dot(node)
|
|
223
234
|
# descend to root of method chain
|
|
224
235
|
node = node.receiver while node.receiver
|
|
@@ -106,9 +106,9 @@ module RuboCop
|
|
|
106
106
|
|
|
107
107
|
def suitable_as_single_line?(node)
|
|
108
108
|
!comment_within?(node) &&
|
|
109
|
-
node.each_descendant(:if, :case, :kwbegin, :def).none? &&
|
|
109
|
+
node.each_descendant(:if, :case, :kwbegin, :def, :defs).none? &&
|
|
110
110
|
node.each_descendant(:dstr, :str).none? { |n| n.heredoc? || n.value.include?("\n") } &&
|
|
111
|
-
node.each_descendant(:begin).none? { |b| !b.single_line? }
|
|
111
|
+
node.each_descendant(:begin, :sym).none? { |b| !b.single_line? }
|
|
112
112
|
end
|
|
113
113
|
|
|
114
114
|
def convertible_block?(node)
|
|
@@ -118,7 +118,9 @@ module RuboCop
|
|
|
118
118
|
end
|
|
119
119
|
|
|
120
120
|
def comment_within?(node)
|
|
121
|
-
processed_source.comments.map
|
|
121
|
+
comment_line_numbers = processed_source.comments.map { |comment| comment.loc.line }
|
|
122
|
+
|
|
123
|
+
comment_line_numbers.any? do |comment_line_number|
|
|
122
124
|
comment_line_number >= node.first_line && comment_line_number <= node.last_line
|
|
123
125
|
end
|
|
124
126
|
end
|