rubocop 1.56.2 → 1.57.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/config/default.yml +12 -6
- data/lib/rubocop/cli/command/auto_generate_config.rb +10 -5
- data/lib/rubocop/cli.rb +1 -1
- data/lib/rubocop/cop/autocorrect_logic.rb +3 -1
- data/lib/rubocop/cop/bundler/duplicated_group.rb +1 -1
- 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/end_alignment.rb +7 -1
- 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/multiline_method_call_indentation.rb +18 -3
- data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -1
- 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 +0 -1
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -0
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +20 -4
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +11 -4
- data/lib/rubocop/cop/lint/useless_assignment.rb +37 -10
- data/lib/rubocop/cop/lint/void.rb +29 -11
- data/lib/rubocop/cop/metrics/block_length.rb +1 -1
- data/lib/rubocop/cop/metrics/class_length.rb +8 -3
- 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/comments_help.rb +16 -12
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +14 -11
- 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/style/arguments_forwarding.rb +8 -6
- 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/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 +25 -3
- 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/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 +93 -5
- data/lib/rubocop/cop/style/redundant_exception.rb +32 -12
- data/lib/rubocop/cop/style/redundant_filter_chain.rb +22 -5
- data/lib/rubocop/cop/style/redundant_parentheses.rb +38 -14
- data/lib/rubocop/cop/style/return_nil.rb +6 -2
- data/lib/rubocop/cop/style/single_argument_dig.rb +2 -1
- data/lib/rubocop/cop/style/single_line_do_end_block.rb +67 -0
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +3 -1
- data/lib/rubocop/cop/style/symbol_array.rb +10 -11
- data/lib/rubocop/cop/style/yoda_expression.rb +8 -7
- data/lib/rubocop/file_finder.rb +4 -7
- data/lib/rubocop/formatter/html_formatter.rb +4 -2
- 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/version.rb +1 -1
- data/lib/rubocop.rb +1 -0
- metadata +6 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: adf1db90b03283f492e0e10f234d54d6efc215a8b182965087313e3954d533dd
|
4
|
+
data.tar.gz: fa84dfd9d61e4834df9287e0ba0619622f4b7eb9e229e8de1172bc1742c04df5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 44a683eed5e4b9d26caf4d0c775a6f4ba00960b6aaeee29c3f610320d1471326d650e8fc41ee2725af07b4e6a50bf17d442232134522709ebb2a46ec5b80bf40
|
7
|
+
data.tar.gz: d4f5dda0dbf7689c55b39de3922c2bd1a0c40aa62ac1046f06c98a19e7f2719cfea11babd480ba4e9b9ff2203d20422a51f096165d5919bf564e009c3a91c087
|
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'
|
@@ -10,6 +10,7 @@ module RuboCop
|
|
10
10
|
|
11
11
|
AUTO_GENERATED_FILE = '.rubocop_todo.yml'
|
12
12
|
YAML_OPTIONAL_DOC_START = /\A---(\s+#|\s*\z)/.freeze
|
13
|
+
PLACEHOLDER = '###rubocop:inherit_here'
|
13
14
|
|
14
15
|
PHASE_1 = 'Phase 1 of 2: run Layout/LineLength cop'
|
15
16
|
PHASE_2 = 'Phase 2 of 2: run all cops'
|
@@ -125,15 +126,19 @@ module RuboCop
|
|
125
126
|
|
126
127
|
def existing_configuration(config_file)
|
127
128
|
File.read(config_file, encoding: Encoding::UTF_8)
|
128
|
-
.sub(/^inherit_from: *[^\n]+/,
|
129
|
-
.sub(/^inherit_from: *(\n *- *[^\n]+)+/,
|
129
|
+
.sub(/^inherit_from: *[^\n]+/, PLACEHOLDER)
|
130
|
+
.sub(/^inherit_from: *(\n *- *[^\n]+)+/, PLACEHOLDER)
|
130
131
|
end
|
131
132
|
|
132
133
|
def write_config_file(file_name, file_string, rubocop_yml_contents)
|
133
134
|
lines = /\S/.match?(rubocop_yml_contents) ? rubocop_yml_contents.split("\n", -1) : []
|
134
|
-
|
135
|
-
|
136
|
-
|
135
|
+
unless rubocop_yml_contents&.include?(PLACEHOLDER)
|
136
|
+
doc_start_index = lines.index { |line| YAML_OPTIONAL_DOC_START.match?(line) } || -1
|
137
|
+
lines.insert(doc_start_index + 1, PLACEHOLDER)
|
138
|
+
end
|
139
|
+
File.write(file_name, lines.join("\n")
|
140
|
+
.sub(/#{PLACEHOLDER}\n*/o, "inherit_from:#{file_string}\n\n")
|
141
|
+
.sub(/\n\n+\Z/, "\n"))
|
137
142
|
end
|
138
143
|
|
139
144
|
def relative_path_to_todo_from_options_config
|
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)
|
@@ -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
|
@@ -163,7 +163,13 @@ module RuboCop
|
|
163
163
|
when :keyword
|
164
164
|
node
|
165
165
|
when :variable
|
166
|
-
alignment_node_for_variable_style(node)
|
166
|
+
align_to = alignment_node_for_variable_style(node)
|
167
|
+
|
168
|
+
while (parent = align_to.parent) && parent.send_type? && same_line?(align_to, parent)
|
169
|
+
align_to = parent
|
170
|
+
end
|
171
|
+
|
172
|
+
align_to
|
167
173
|
else
|
168
174
|
start_line_range(node)
|
169
175
|
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)
|
@@ -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,10 +179,10 @@ 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
|
-
return unless node&.loc&.selector
|
185
|
+
return unless node&.loc&.selector && node.loc.dot
|
186
186
|
|
187
187
|
node.loc.dot.join(node.loc.selector)
|
188
188
|
end
|
@@ -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,17 @@ 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
|
+
if node.receiver.call_type?
|
231
|
+
node.receiver
|
232
|
+
else
|
233
|
+
block_node.parent
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
222
237
|
def first_call_has_a_dot(node)
|
223
238
|
# descend to root of method chain
|
224
239
|
node = node.receiver while node.receiver
|
@@ -108,7 +108,7 @@ module RuboCop
|
|
108
108
|
!comment_within?(node) &&
|
109
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)
|
@@ -168,7 +168,7 @@ module RuboCop
|
|
168
168
|
# follows, and that the rules for space inside don't apply.
|
169
169
|
return true if token2.comment?
|
170
170
|
|
171
|
-
|
171
|
+
!same_line?(token1, token2) || token1.space_after?
|
172
172
|
end
|
173
173
|
end
|
174
174
|
end
|
@@ -95,8 +95,11 @@ module RuboCop
|
|
95
95
|
def assumed_usage_context?(node)
|
96
96
|
# Basically, debugger methods are not used as a method argument without arguments.
|
97
97
|
return false unless node.arguments.empty? && node.each_ancestor(:send, :csend).any?
|
98
|
+
return true if assumed_argument?(node)
|
98
99
|
|
99
|
-
node.each_ancestor.none?
|
100
|
+
node.each_ancestor.none? do |ancestor|
|
101
|
+
ancestor.block_type? || ancestor.numblock_type? || ancestor.lambda_or_proc?
|
102
|
+
end
|
100
103
|
end
|
101
104
|
|
102
105
|
def chained_method_name(send_node)
|
@@ -109,6 +112,12 @@ module RuboCop
|
|
109
112
|
end
|
110
113
|
chained_method_name
|
111
114
|
end
|
115
|
+
|
116
|
+
def assumed_argument?(node)
|
117
|
+
parent = node.parent
|
118
|
+
|
119
|
+
parent.call_type? || parent.literal? || parent.pair_type?
|
120
|
+
end
|
112
121
|
end
|
113
122
|
end
|
114
123
|
end
|
@@ -5,7 +5,7 @@ module RuboCop
|
|
5
5
|
module Lint
|
6
6
|
# Checks for blocks without a body.
|
7
7
|
# Such empty blocks are typically an oversight or we should provide a comment
|
8
|
-
#
|
8
|
+
# to clarify what we're aiming for.
|
9
9
|
#
|
10
10
|
# Empty lambdas and procs are ignored by default.
|
11
11
|
#
|
@@ -34,7 +34,7 @@ module RuboCop
|
|
34
34
|
# interpolation should not be removed if the expanded value
|
35
35
|
# contains a space character.
|
36
36
|
expanded_value = autocorrected_value(final_node)
|
37
|
-
return if in_array_percent_literal?(begin_node) && /\s/.match?(expanded_value)
|
37
|
+
return if in_array_percent_literal?(begin_node) && /\s|\A\z/.match?(expanded_value)
|
38
38
|
|
39
39
|
add_offense(final_node) do |corrector|
|
40
40
|
return if final_node.dstr_type? # nested, fixed in next iteration
|
@@ -24,6 +24,10 @@ module RuboCop
|
|
24
24
|
#
|
25
25
|
# This cop target those features.
|
26
26
|
#
|
27
|
+
# @safety
|
28
|
+
# This cop's autocorrection is unsafe because if `require 'pp'` is removed from one file,
|
29
|
+
# `NameError` can be encountered when another file uses `PP.pp`.
|
30
|
+
#
|
27
31
|
# @example
|
28
32
|
# # bad
|
29
33
|
# require 'unloaded_feature'
|