rubocop 1.89.0 → 1.90.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/config/default.yml +74 -7
- data/exe/rubocop +1 -1
- data/lib/rubocop/cached_data.rb +7 -2
- data/lib/rubocop/cli/command/execute_runner.rb +31 -0
- data/lib/rubocop/cli.rb +2 -4
- data/lib/rubocop/comment_config/directive_range.rb +32 -0
- data/lib/rubocop/comment_config/disable_next.rb +97 -0
- data/lib/rubocop/comment_config.rb +46 -30
- data/lib/rubocop/config.rb +23 -5
- data/lib/rubocop/config_loader.rb +1 -2
- data/lib/rubocop/config_loader_resolver.rb +1 -2
- data/lib/rubocop/config_validator.rb +1 -2
- data/lib/rubocop/cop/autocorrect_logic.rb +8 -0
- data/lib/rubocop/cop/base.rb +34 -2
- data/lib/rubocop/cop/corrector.rb +3 -3
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -2
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +1 -2
- data/lib/rubocop/cop/layout/block_alignment.rb +1 -2
- data/lib/rubocop/cop/layout/class_structure.rb +102 -26
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +1 -2
- data/lib/rubocop/cop/layout/empty_line_after_magic_comment.rb +63 -5
- data/lib/rubocop/cop/layout/end_alignment.rb +1 -2
- data/lib/rubocop/cop/layout/extra_spacing.rb +105 -3
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +21 -1
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -2
- data/lib/rubocop/cop/layout/line_length.rb +1 -2
- data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -2
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +5 -5
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +1 -2
- data/lib/rubocop/cop/layout/space_around_operators.rb +7 -0
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +2 -4
- data/lib/rubocop/cop/lint/ambiguous_range.rb +1 -2
- data/lib/rubocop/cop/lint/argument_mismatch.rb +89 -0
- data/lib/rubocop/cop/lint/constant_reassignment.rb +17 -11
- data/lib/rubocop/cop/lint/cop_directive_syntax.rb +84 -8
- data/lib/rubocop/cop/lint/deprecated_reference.rb +11 -2
- data/lib/rubocop/cop/lint/duplicate_methods.rb +112 -14
- data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -2
- data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -2
- data/lib/rubocop/cop/lint/interpolation_check.rb +1 -2
- data/lib/rubocop/cop/lint/literal_as_condition.rb +3 -6
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +3 -6
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +25 -12
- data/lib/rubocop/cop/lint/name_typo.rb +53 -6
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +15 -0
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +98 -19
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +47 -7
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +1 -2
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +1 -2
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +1 -2
- data/lib/rubocop/cop/lint/redundant_type_conversion.rb +1 -2
- data/lib/rubocop/cop/lint/redundant_with_index.rb +1 -2
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +1 -2
- data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +2 -4
- data/lib/rubocop/cop/lint/super_argument_mismatch.rb +179 -0
- data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +1 -2
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +1 -2
- data/lib/rubocop/cop/lint/unreachable_code.rb +1 -2
- data/lib/rubocop/cop/lint/unused_private_method.rb +94 -17
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +1 -2
- data/lib/rubocop/cop/lint/useless_assignment.rb +1 -2
- data/lib/rubocop/cop/lint/useless_constant_scoping.rb +36 -0
- data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
- data/lib/rubocop/cop/lint/useless_rescue.rb +1 -2
- data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +61 -7
- data/lib/rubocop/cop/lint/void.rb +1 -2
- data/lib/rubocop/cop/lint.rb +2 -0
- data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -2
- data/lib/rubocop/cop/migration/department_name.rb +1 -2
- data/lib/rubocop/cop/mixin/comments_help.rb +1 -2
- data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +1 -2
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +1 -2
- data/lib/rubocop/cop/mixin/hash_subset.rb +1 -2
- data/lib/rubocop/cop/mixin/indexed_method_arity.rb +94 -0
- data/lib/rubocop/cop/mixin/line_length_help.rb +7 -1
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +51 -6
- data/lib/rubocop/cop/mixin/range_help.rb +1 -2
- data/lib/rubocop/cop/mixin/statement_modifier.rb +13 -7
- data/lib/rubocop/cop/mixin/trailing_comma.rb +2 -4
- data/lib/rubocop/cop/mixin.rb +4 -0
- data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +16 -0
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +2 -4
- data/lib/rubocop/cop/naming/method_name.rb +5 -2
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +1 -2
- data/lib/rubocop/cop/offense.rb +27 -4
- data/lib/rubocop/cop/registry.rb +34 -10
- data/lib/rubocop/cop/style/accessor_grouping.rb +1 -2
- data/lib/rubocop/cop/style/arguments_forwarding.rb +3 -6
- data/lib/rubocop/cop/style/array_first_last.rb +1 -2
- data/lib/rubocop/cop/style/bitwise_predicate.rb +1 -2
- data/lib/rubocop/cop/style/block_delimiters.rb +3 -6
- data/lib/rubocop/cop/style/case_like_if.rb +2 -4
- data/lib/rubocop/cop/style/class_and_module_children.rb +1 -2
- data/lib/rubocop/cop/style/combinable_loops.rb +1 -2
- data/lib/rubocop/cop/style/concat_array_literals.rb +1 -2
- data/lib/rubocop/cop/style/conditional_assignment.rb +1 -2
- data/lib/rubocop/cop/style/constant_visibility.rb +1 -2
- data/lib/rubocop/cop/style/copyright.rb +1 -2
- data/lib/rubocop/cop/style/directive_scope.rb +171 -0
- data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +36 -10
- data/lib/rubocop/cop/style/empty_case_condition.rb +1 -2
- data/lib/rubocop/cop/style/format_string_token.rb +1 -2
- data/lib/rubocop/cop/style/guard_clause.rb +1 -2
- data/lib/rubocop/cop/style/hash_each_methods.rb +1 -2
- data/lib/rubocop/cop/style/hash_syntax.rb +1 -2
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +2 -4
- data/lib/rubocop/cop/style/if_inside_else.rb +1 -2
- data/lib/rubocop/cop/style/if_unless_modifier.rb +1 -2
- data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +1 -2
- data/lib/rubocop/cop/style/map_to_hash.rb +1 -2
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +2 -4
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +1 -2
- data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -2
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +1 -2
- data/lib/rubocop/cop/style/negative_array_index.rb +2 -4
- data/lib/rubocop/cop/style/nil_comparison.rb +1 -2
- data/lib/rubocop/cop/style/operator_method_call.rb +1 -2
- data/lib/rubocop/cop/style/parallel_assignment.rb +1 -2
- data/lib/rubocop/cop/style/redundant_assignment.rb +1 -2
- data/lib/rubocop/cop/style/redundant_condition.rb +2 -4
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +1 -2
- data/lib/rubocop/cop/style/redundant_each.rb +1 -2
- data/lib/rubocop/cop/style/redundant_format.rb +2 -4
- data/lib/rubocop/cop/style/redundant_parentheses.rb +2 -4
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +1 -2
- data/lib/rubocop/cop/style/redundant_return.rb +1 -2
- data/lib/rubocop/cop/style/redundant_self_assignment.rb +1 -2
- data/lib/rubocop/cop/style/redundant_string_escape.rb +1 -2
- data/lib/rubocop/cop/style/rescue_modifier.rb +1 -2
- data/lib/rubocop/cop/style/safe_navigation.rb +1 -2
- data/lib/rubocop/cop/style/sample.rb +11 -6
- data/lib/rubocop/cop/style/select_by_regexp.rb +1 -2
- data/lib/rubocop/cop/style/semicolon.rb +2 -4
- data/lib/rubocop/cop/style/single_line_do_end_block.rb +1 -2
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +1 -2
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +2 -0
- data/lib/rubocop/cop/style/string_concatenation.rb +18 -5
- data/lib/rubocop/cop/style/super_arguments.rb +1 -2
- data/lib/rubocop/cop/style/symbol_proc.rb +1 -2
- data/lib/rubocop/cop/style/time_now.rb +41 -0
- data/lib/rubocop/cop/style/yoda_condition.rb +1 -2
- data/lib/rubocop/cop/style.rb +2 -0
- data/lib/rubocop/cop/team.rb +11 -3
- data/lib/rubocop/cop/util.rb +2 -4
- data/lib/rubocop/cop/variable_force/variable.rb +1 -2
- data/lib/rubocop/cops_documentation_generator.rb +3 -6
- data/lib/rubocop/directive_comment.rb +37 -3
- data/lib/rubocop/formatter/emacs_style_formatter.rb +3 -1
- data/lib/rubocop/formatter/html_formatter.rb +2 -4
- data/lib/rubocop/formatter/json_formatter.rb +11 -6
- data/lib/rubocop/formatter/junit_formatter.rb +26 -9
- data/lib/rubocop/formatter/offense_count_formatter.rb +1 -2
- data/lib/rubocop/formatter/simple_text_formatter.rb +4 -3
- data/lib/rubocop/formatter/tap_formatter.rb +3 -1
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -2
- data/lib/rubocop/lockfile.rb +18 -0
- data/lib/rubocop/lsp/diagnostic.rb +4 -8
- data/lib/rubocop/lsp/routes.rb +48 -19
- data/lib/rubocop/mcp/server.rb +1 -2
- data/lib/rubocop/options.rb +10 -6
- data/lib/rubocop/path_util.rb +1 -2
- data/lib/rubocop/plugin/configuration_integrator.rb +6 -3
- data/lib/rubocop/rake_task.rb +1 -2
- data/lib/rubocop/rspec/expect_offense.rb +2 -4
- data/lib/rubocop/rspec/shared_contexts.rb +4 -2
- data/lib/rubocop/runner.rb +26 -23
- data/lib/rubocop/server/cache.rb +1 -2
- data/lib/rubocop/server/cli.rb +2 -4
- data/lib/rubocop/server.rb +14 -0
- data/lib/rubocop/target_finder.rb +4 -1
- data/lib/rubocop/todo_audit.rb +111 -0
- data/lib/rubocop/version.rb +3 -5
- data/lib/rubocop.rb +3 -0
- data/lib/ruby_lsp/rubocop/addon.rb +1 -2
- metadata +13 -5
|
@@ -5,6 +5,7 @@ module RuboCop
|
|
|
5
5
|
# and provides a way to check if each cop is enabled at arbitrary line.
|
|
6
6
|
class CommentConfig
|
|
7
7
|
extend SimpleForwardable
|
|
8
|
+
include DisableNext
|
|
8
9
|
|
|
9
10
|
CONFIG_DISABLED_LINE_RANGE_MIN = -Float::INFINITY
|
|
10
11
|
|
|
@@ -25,8 +26,6 @@ module RuboCop
|
|
|
25
26
|
end
|
|
26
27
|
end
|
|
27
28
|
|
|
28
|
-
CopAnalysis = Struct.new(:line_ranges, :start_line_number)
|
|
29
|
-
|
|
30
29
|
attr_reader :processed_source
|
|
31
30
|
|
|
32
31
|
def_delegators :@processed_source, :config, :registry
|
|
@@ -35,14 +34,25 @@ module RuboCop
|
|
|
35
34
|
@processed_source = processed_source
|
|
36
35
|
@no_directives = !processed_source.raw_source.include?('rubocop')
|
|
37
36
|
@stack = []
|
|
37
|
+
@detached_next_directives = []
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
def cop_enabled_at_line?(cop, line_number)
|
|
41
|
+
cop_enabled_at_lines?(cop, line_number, line_number)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Whether the cop is enabled for all of the given line span. The cop
|
|
45
|
+
# counts as disabled for the span when any of its disabled ranges
|
|
46
|
+
# overlaps it, so that a directive on any line of a multi-line offense
|
|
47
|
+
# suppresses the offense.
|
|
48
|
+
def cop_enabled_at_lines?(cop, first_line, last_line)
|
|
41
49
|
cop = cop.cop_name if cop.respond_to?(:cop_name)
|
|
42
50
|
disabled_line_ranges = cop_disabled_line_ranges[cop]
|
|
43
51
|
return true unless disabled_line_ranges
|
|
44
52
|
|
|
45
|
-
disabled_line_ranges.none?
|
|
53
|
+
disabled_line_ranges.none? do |range|
|
|
54
|
+
range.end >= first_line && range.begin <= last_line
|
|
55
|
+
end
|
|
46
56
|
end
|
|
47
57
|
|
|
48
58
|
def cop_opted_in?(cop)
|
|
@@ -88,7 +98,9 @@ module RuboCop
|
|
|
88
98
|
def extra_enabled_comments_with_names(extras:, names:)
|
|
89
99
|
each_directive do |directive|
|
|
90
100
|
next unless comment_only_line?(directive.line_number)
|
|
91
|
-
next
|
|
101
|
+
# Push/pop and next-statement directives close themselves, so they
|
|
102
|
+
# play no part in the disable/enable pairing.
|
|
103
|
+
next if directive.push? || directive.pop? || directive.disable_next?
|
|
92
104
|
|
|
93
105
|
if directive.enabled_all?
|
|
94
106
|
handle_enable_all(directive, names, extras)
|
|
@@ -100,7 +112,7 @@ module RuboCop
|
|
|
100
112
|
extras
|
|
101
113
|
end
|
|
102
114
|
|
|
103
|
-
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
115
|
+
# rubocop:disable-next Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
104
116
|
def analyze
|
|
105
117
|
return {} if @no_directives
|
|
106
118
|
|
|
@@ -111,9 +123,11 @@ module RuboCop
|
|
|
111
123
|
if directive.push?
|
|
112
124
|
restore_point = analyses.transform_values(&:dup)
|
|
113
125
|
@stack.push(restore_point)
|
|
114
|
-
apply_push(analyses, resolve_push_cops(directive), directive
|
|
126
|
+
apply_push(analyses, resolve_push_cops(directive), directive)
|
|
115
127
|
elsif directive.pop?
|
|
116
128
|
pop_state(analyses, directive.line_number) if @stack.any?
|
|
129
|
+
elsif directive.disable_next?
|
|
130
|
+
apply_disable_next(analyses, directive)
|
|
117
131
|
else
|
|
118
132
|
directive.cop_names.each do |cop_name|
|
|
119
133
|
cop_name = qualified_cop_name(cop_name)
|
|
@@ -129,7 +143,6 @@ module RuboCop
|
|
|
129
143
|
hash[cop_name] = cop_line_ranges(analysis)
|
|
130
144
|
end
|
|
131
145
|
end
|
|
132
|
-
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
133
146
|
|
|
134
147
|
def resolve_push_cops(directive)
|
|
135
148
|
directive.push_args.transform_values do |names|
|
|
@@ -143,32 +156,36 @@ module RuboCop
|
|
|
143
156
|
cops.map { |c| qualified_cop_name(c) }
|
|
144
157
|
end
|
|
145
158
|
|
|
146
|
-
def apply_push(analyses, resolved_cops,
|
|
159
|
+
def apply_push(analyses, resolved_cops, directive)
|
|
147
160
|
resolved_cops.each do |op, cops|
|
|
148
|
-
cops.each { |cop| apply_cop_op(analyses, op, cop,
|
|
161
|
+
cops.each { |cop| apply_cop_op(analyses, op, cop, directive) }
|
|
149
162
|
end
|
|
150
163
|
end
|
|
151
164
|
|
|
152
|
-
def apply_cop_op(analyses, operation, cop,
|
|
165
|
+
def apply_cop_op(analyses, operation, cop, directive)
|
|
153
166
|
analysis = analyses[cop]
|
|
167
|
+
line = directive.line_number
|
|
154
168
|
if operation == '-' && !analysis.start_line_number
|
|
155
|
-
analyses[cop] = CopAnalysis.new(analysis.line_ranges, line)
|
|
169
|
+
analyses[cop] = CopAnalysis.new(analysis.line_ranges, line, directive)
|
|
156
170
|
elsif operation == '+' && analysis.start_line_number
|
|
157
|
-
analyses[cop] =
|
|
158
|
-
CopAnalysis.new(analysis.line_ranges + [analysis.start_line_number..line], nil)
|
|
171
|
+
analyses[cop] = CopAnalysis.new(analysis.close(line), nil)
|
|
159
172
|
end
|
|
160
173
|
end
|
|
161
174
|
|
|
162
175
|
def pop_state(analyses, line)
|
|
163
176
|
restore_point = @stack.pop
|
|
164
177
|
(restore_point.keys | analyses.keys).each do |cop|
|
|
165
|
-
|
|
166
|
-
new_range = current.start_line_number ? [current.start_line_number..(line - 1)] : []
|
|
167
|
-
new_start = restore_point[cop]&.start_line_number ? line : nil
|
|
168
|
-
analyses[cop] = CopAnalysis.new(current.line_ranges + new_range, new_start)
|
|
178
|
+
analyses[cop] = popped_analysis(analyses[cop], restore_point[cop], line)
|
|
169
179
|
end
|
|
170
180
|
end
|
|
171
181
|
|
|
182
|
+
def popped_analysis(current, restored, line)
|
|
183
|
+
ranges = current.close(line - 1)
|
|
184
|
+
return CopAnalysis.new(ranges, nil) unless restored&.start_line_number
|
|
185
|
+
|
|
186
|
+
CopAnalysis.new(ranges, line, restored.start_directive)
|
|
187
|
+
end
|
|
188
|
+
|
|
172
189
|
def inject_disabled_cops_directives(analyses)
|
|
173
190
|
registry.disabled_names(config).each do |cop_name|
|
|
174
191
|
analyses[cop_name] = analyze_cop(
|
|
@@ -193,27 +210,21 @@ module RuboCop
|
|
|
193
210
|
return analysis unless directive.disabled?
|
|
194
211
|
|
|
195
212
|
line = directive.line_number
|
|
196
|
-
|
|
213
|
+
range = DirectiveRange.new(line, line, directive)
|
|
214
|
+
CopAnalysis.new(analysis.line_ranges + [range], analysis.start_line_number,
|
|
215
|
+
analysis.start_directive)
|
|
197
216
|
end
|
|
198
217
|
|
|
199
218
|
def analyze_disabled(analysis, directive)
|
|
200
|
-
|
|
201
|
-
start_line = analysis.start_line_number
|
|
202
|
-
new_ranges = start_line ? analysis.line_ranges + [start_line..line] : analysis.line_ranges
|
|
203
|
-
CopAnalysis.new(new_ranges, line)
|
|
219
|
+
CopAnalysis.new(analysis.close(directive.line_number), directive.line_number, directive)
|
|
204
220
|
end
|
|
205
221
|
|
|
206
222
|
def analyze_rest(analysis, directive)
|
|
207
|
-
|
|
208
|
-
start_line = analysis.start_line_number
|
|
209
|
-
new_ranges = start_line ? analysis.line_ranges + [start_line..line] : analysis.line_ranges
|
|
210
|
-
CopAnalysis.new(new_ranges, nil)
|
|
223
|
+
CopAnalysis.new(analysis.close(directive.line_number), nil)
|
|
211
224
|
end
|
|
212
225
|
|
|
213
226
|
def cop_line_ranges(analysis)
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
analysis.line_ranges + [(analysis.start_line_number..Float::INFINITY)]
|
|
227
|
+
analysis.close(Float::INFINITY)
|
|
217
228
|
end
|
|
218
229
|
|
|
219
230
|
def each_directive
|
|
@@ -226,7 +237,12 @@ module RuboCop
|
|
|
226
237
|
end
|
|
227
238
|
|
|
228
239
|
def qualified_cop_name(cop_name)
|
|
229
|
-
|
|
240
|
+
# A directive naming a cop under the wrong department is not honored -
|
|
241
|
+
# the mistake is surfaced by `Lint/RedundantCopDisableDirective` (with a
|
|
242
|
+
# did-you-mean hint) instead of a stderr warning that is easy to miss
|
|
243
|
+
# and disappears entirely on cached runs.
|
|
244
|
+
Cop::Registry.qualified_cop_name(cop_name.strip, processed_source.file_path,
|
|
245
|
+
correct_namespace: false)
|
|
230
246
|
end
|
|
231
247
|
|
|
232
248
|
# `Style/DisableCopsWithinSourceCodeDirective` cannot be disabled via
|
data/lib/rubocop/config.rb
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# FIXME: Moving Rails department code to RuboCop Rails will remove
|
|
4
4
|
# the following rubocop:disable comment.
|
|
5
|
-
# rubocop:disable Metrics/ClassLength
|
|
5
|
+
# rubocop:disable-next Metrics/ClassLength
|
|
6
6
|
module RuboCop
|
|
7
7
|
# This class represents the configuration of the RuboCop application
|
|
8
8
|
# and all its cops. A Config is associated with a YAML configuration
|
|
@@ -27,7 +27,7 @@ module RuboCop
|
|
|
27
27
|
config
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
-
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
30
|
+
# rubocop:disable-next Metrics/AbcSize, Metrics/MethodLength
|
|
31
31
|
def initialize(hash = RuboCop::ConfigLoader.default_configuration, loaded_path = nil)
|
|
32
32
|
@loaded_path = loaded_path
|
|
33
33
|
@for_cop = Hash.new do |h, cop|
|
|
@@ -72,7 +72,6 @@ module RuboCop
|
|
|
72
72
|
@badge_config_cache = {}.compare_by_identity
|
|
73
73
|
@clusivity_config_exists_cache = {}
|
|
74
74
|
end
|
|
75
|
-
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
|
76
75
|
|
|
77
76
|
def loaded_plugins
|
|
78
77
|
@loaded_plugins ||= ConfigLoader.loaded_plugins
|
|
@@ -168,7 +167,11 @@ module RuboCop
|
|
|
168
167
|
department_config = self[badge.department_name]
|
|
169
168
|
cop_config = for_cop(badge.to_s)
|
|
170
169
|
if department_config
|
|
171
|
-
department_config.merge(cop_config)
|
|
170
|
+
merged_config = department_config.merge(cop_config)
|
|
171
|
+
if department_config['Exclude'] && cop_config['Exclude']
|
|
172
|
+
merged_config['Exclude'] = department_config['Exclude'] | cop_config['Exclude']
|
|
173
|
+
end
|
|
174
|
+
merged_config
|
|
172
175
|
else
|
|
173
176
|
cop_config
|
|
174
177
|
end
|
|
@@ -352,6 +355,14 @@ module RuboCop
|
|
|
352
355
|
@gem_versions_in_target ||= read_gem_versions_from_target_lockfile
|
|
353
356
|
end
|
|
354
357
|
|
|
358
|
+
# Returns the names of the target's gems that are sourced from a local path
|
|
359
|
+
# (i.e. `path:` dependencies and the project's own gem when the `Gemfile`
|
|
360
|
+
# uses `gemspec`), whose code therefore lives in the project itself.
|
|
361
|
+
# @returns [Array<String>, nil] The gem names, or nil without a lockfile.
|
|
362
|
+
def path_sourced_gems_in_target
|
|
363
|
+
@path_sourced_gems_in_target ||= read_path_sourced_gems_from_target_lockfile
|
|
364
|
+
end
|
|
365
|
+
|
|
355
366
|
def inspect # :nodoc:
|
|
356
367
|
"#<#{self.class.name}:#{object_id} @loaded_path=#{loaded_path}>"
|
|
357
368
|
end
|
|
@@ -396,6 +407,14 @@ module RuboCop
|
|
|
396
407
|
Lockfile.new(lockfile_path).gem_versions
|
|
397
408
|
end
|
|
398
409
|
|
|
410
|
+
# @returns [Array<String>, nil] The names of the gems sourced from a local path.
|
|
411
|
+
def read_path_sourced_gems_from_target_lockfile
|
|
412
|
+
lockfile_path = bundler_lock_file_path
|
|
413
|
+
return nil unless lockfile_path
|
|
414
|
+
|
|
415
|
+
Lockfile.new(lockfile_path).path_sourced_gem_names
|
|
416
|
+
end
|
|
417
|
+
|
|
399
418
|
def enable_cop?(qualified_cop_name, cop_options)
|
|
400
419
|
# If the cop is explicitly enabled or `Lint/Syntax`, the other checks can be skipped.
|
|
401
420
|
return true if cop_options['Enabled'] == true || qualified_cop_name == 'Lint/Syntax'
|
|
@@ -454,4 +473,3 @@ module RuboCop
|
|
|
454
473
|
end
|
|
455
474
|
end
|
|
456
475
|
end
|
|
457
|
-
# rubocop:enable Metrics/ClassLength
|
|
@@ -49,7 +49,7 @@ module RuboCop
|
|
|
49
49
|
FileFinder.root_level = nil
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
-
# rubocop:disable Metrics/AbcSize
|
|
52
|
+
# rubocop:disable-next Metrics/AbcSize
|
|
53
53
|
def load_file(file, check: true)
|
|
54
54
|
path = file_path(file)
|
|
55
55
|
|
|
@@ -73,7 +73,6 @@ module RuboCop
|
|
|
73
73
|
|
|
74
74
|
Config.create(hash, path, check: check)
|
|
75
75
|
end
|
|
76
|
-
# rubocop:enable Metrics/AbcSize
|
|
77
76
|
|
|
78
77
|
def load_yaml_configuration(absolute_path)
|
|
79
78
|
file_contents = read_file(absolute_path)
|
|
@@ -115,7 +115,7 @@ module RuboCop
|
|
|
115
115
|
# with the addition that any value that is a hash, and occurs in both
|
|
116
116
|
# arguments, will also be merged. And so on.
|
|
117
117
|
#
|
|
118
|
-
# rubocop:disable Metrics/AbcSize
|
|
118
|
+
# rubocop:disable-next Metrics/AbcSize
|
|
119
119
|
def merge(base_hash, derived_hash, **opts)
|
|
120
120
|
result = base_hash.merge(derived_hash)
|
|
121
121
|
keys_appearing_in_both = base_hash.keys & derived_hash.keys
|
|
@@ -132,7 +132,6 @@ module RuboCop
|
|
|
132
132
|
end
|
|
133
133
|
result
|
|
134
134
|
end
|
|
135
|
-
# rubocop:enable Metrics/AbcSize
|
|
136
135
|
|
|
137
136
|
# An `Enabled: true` setting in user configuration for a cop overrides an
|
|
138
137
|
# `Enabled: false` setting for its department.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
# Handles validation of configuration, for example cop names, parameter
|
|
5
5
|
# names, and Ruby versions.
|
|
6
|
-
# rubocop:disable Metrics/ClassLength
|
|
6
|
+
# rubocop:disable-next Metrics/ClassLength
|
|
7
7
|
class ConfigValidator
|
|
8
8
|
extend SimpleForwardable
|
|
9
9
|
|
|
@@ -324,5 +324,4 @@ module RuboCop
|
|
|
324
324
|
"is supposed to be #{supposed_values} and #{Rainbow(value).yellow} is not."
|
|
325
325
|
end
|
|
326
326
|
end
|
|
327
|
-
# rubocop:enable Metrics/ClassLength
|
|
328
327
|
end
|
|
@@ -12,6 +12,14 @@ module RuboCop
|
|
|
12
12
|
autocorrect_requested? && disable_uncorrectable? && autocorrect_enabled?
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
+
# Whether a correction exists but is skipped because it is unsafe in a
|
|
16
|
+
# safe autocorrect run, while `--disable-uncorrectable` asks for a todo
|
|
17
|
+
# comment on everything this run cannot correct.
|
|
18
|
+
def skipped_unsafe_correction_with_disable_uncorrectable?
|
|
19
|
+
autocorrect_requested? && disable_uncorrectable? &&
|
|
20
|
+
@options.fetch(:safe_autocorrect, false) && !safe_autocorrect?
|
|
21
|
+
end
|
|
22
|
+
|
|
15
23
|
def autocorrect_requested?
|
|
16
24
|
@options.fetch(:autocorrect, false)
|
|
17
25
|
end
|
data/lib/rubocop/cop/base.rb
CHANGED
|
@@ -127,6 +127,8 @@ module RuboCop
|
|
|
127
127
|
# in the `on_new_investigation` callback.
|
|
128
128
|
# If your cop does autocorrections, be aware that your instance may be called
|
|
129
129
|
# multiple times with the same `processed_source.path` but different content.
|
|
130
|
+
# Note that under `--parallel` each worker process has its own cop
|
|
131
|
+
# instances, so state persists only within a worker's share of the files.
|
|
130
132
|
def self.support_multiple_source?
|
|
131
133
|
false
|
|
132
134
|
end
|
|
@@ -208,13 +210,15 @@ module RuboCop
|
|
|
208
210
|
severity = find_severity(range_to_pass, severity)
|
|
209
211
|
message = find_message(range_to_pass, message)
|
|
210
212
|
|
|
211
|
-
status, corrector =
|
|
213
|
+
status, corrector = enabled_lines?(range) ? correct(range, &block) : :disabled
|
|
214
|
+
justification = suppression_reason(range) if status == :disabled
|
|
212
215
|
|
|
213
216
|
# Since this range may be generated from Ruby code embedded in some
|
|
214
217
|
# template file, we convert it to location info in the original file.
|
|
215
218
|
range = range_for_original(range)
|
|
216
219
|
|
|
217
|
-
current_offenses << Offense.new(severity, range, message, name, status, corrector
|
|
220
|
+
current_offenses << Offense.new(severity, range, message, name, status, corrector,
|
|
221
|
+
justification: justification)
|
|
218
222
|
end
|
|
219
223
|
|
|
220
224
|
# This method should be overridden when a cop's behavior depends
|
|
@@ -445,6 +449,10 @@ module RuboCop
|
|
|
445
449
|
def use_corrector(range, corrector)
|
|
446
450
|
if autocorrect?
|
|
447
451
|
attempt_correction(range, corrector)
|
|
452
|
+
elsif skipped_unsafe_correction_with_disable_uncorrectable?
|
|
453
|
+
# The unsafe correction will not run, so the offense is
|
|
454
|
+
# uncorrectable for this run and gets a todo comment.
|
|
455
|
+
attempt_correction(range, nil)
|
|
448
456
|
elsif corrector && (always_autocorrect? || (contextual_autocorrect? && !LSP.enabled?))
|
|
449
457
|
:uncorrected
|
|
450
458
|
else
|
|
@@ -524,6 +532,30 @@ module RuboCop
|
|
|
524
532
|
@processed_source.comment_config.cop_enabled_at_line?(self, line_number)
|
|
525
533
|
end
|
|
526
534
|
|
|
535
|
+
# A multi-line offense is suppressed by a directive on any line of its
|
|
536
|
+
# range, not only its first line, matching the intuition that the
|
|
537
|
+
# directive is attached to the offending code.
|
|
538
|
+
def enabled_lines?(range)
|
|
539
|
+
return true if @options[:ignore_disable_comments] || !@processed_source
|
|
540
|
+
|
|
541
|
+
comment_config = @processed_source.comment_config
|
|
542
|
+
comment_config.cop_enabled_at_lines?(self, range.first_line, range.last_line)
|
|
543
|
+
end
|
|
544
|
+
|
|
545
|
+
# The `--` reason on the directive that suppresses offenses on this
|
|
546
|
+
# range, or `nil` when the directive carries none.
|
|
547
|
+
def suppression_reason(range)
|
|
548
|
+
covering = covering_disabled_range(range)
|
|
549
|
+
covering.directive.reason if covering.respond_to?(:directive)
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
def covering_disabled_range(range)
|
|
553
|
+
disabled_ranges = @processed_source.comment_config.cop_disabled_line_ranges[cop_name]
|
|
554
|
+
disabled_ranges&.find do |disabled_range|
|
|
555
|
+
disabled_range.end >= range.first_line && disabled_range.begin <= range.last_line
|
|
556
|
+
end
|
|
557
|
+
end
|
|
558
|
+
|
|
527
559
|
def find_severity(_range, severity)
|
|
528
560
|
custom_severity || severity || default_severity
|
|
529
561
|
end
|
|
@@ -46,7 +46,7 @@ module RuboCop
|
|
|
46
46
|
|
|
47
47
|
# Removes `size` characters prior to the source range.
|
|
48
48
|
#
|
|
49
|
-
# @param [Parser::Source::Range, RuboCop::AST::Node]
|
|
49
|
+
# @param [Parser::Source::Range, RuboCop::AST::Node] node_or_range
|
|
50
50
|
# @param [Integer] size
|
|
51
51
|
def remove_preceding(node_or_range, size)
|
|
52
52
|
range = to_range(node_or_range)
|
|
@@ -58,7 +58,7 @@ module RuboCop
|
|
|
58
58
|
# If `size` is greater than the size of `range`, the removed region can
|
|
59
59
|
# overrun the end of `range`.
|
|
60
60
|
#
|
|
61
|
-
# @param [Parser::Source::Range, RuboCop::AST::Node]
|
|
61
|
+
# @param [Parser::Source::Range, RuboCop::AST::Node] node_or_range
|
|
62
62
|
# @param [Integer] size
|
|
63
63
|
def remove_leading(node_or_range, size)
|
|
64
64
|
range = to_range(node_or_range)
|
|
@@ -70,7 +70,7 @@ module RuboCop
|
|
|
70
70
|
# If `size` is greater than the size of `range`, the removed region can
|
|
71
71
|
# overrun the beginning of `range`.
|
|
72
72
|
#
|
|
73
|
-
# @param [Parser::Source::Range, RuboCop::AST::Node]
|
|
73
|
+
# @param [Parser::Source::Range, RuboCop::AST::Node] node_or_range
|
|
74
74
|
# @param [Integer] size
|
|
75
75
|
def remove_trailing(node_or_range, size)
|
|
76
76
|
range = to_range(node_or_range)
|
|
@@ -146,7 +146,7 @@ module RuboCop
|
|
|
146
146
|
end
|
|
147
147
|
end
|
|
148
148
|
|
|
149
|
-
# rubocop:disable Metrics/MethodLength
|
|
149
|
+
# rubocop:disable-next Metrics/MethodLength
|
|
150
150
|
def formatted_message(offense_type, directive, actual_name, method_name)
|
|
151
151
|
case offense_type
|
|
152
152
|
when :wrong_name
|
|
@@ -166,7 +166,6 @@ module RuboCop
|
|
|
166
166
|
format(MSG, method: method_name)
|
|
167
167
|
end
|
|
168
168
|
end
|
|
169
|
-
# rubocop:enable Metrics/MethodLength
|
|
170
169
|
|
|
171
170
|
def remove_receiver(current)
|
|
172
171
|
current.delete_prefix('self.')
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module InternalAffairs
|
|
6
|
-
# rubocop:disable InternalAffairs/RedundantSourceRange -- node here is a `NodePattern::Node`
|
|
6
|
+
# rubocop:disable-next InternalAffairs/RedundantSourceRange -- node here is a `NodePattern::Node`
|
|
7
7
|
class NodePatternGroups
|
|
8
8
|
# Walks an AST that has been processed by `InternalAffairs::NodePatternGroups::Processor`
|
|
9
9
|
# in order to find `node_type` and `node_sequence` nodes that can be replaced with a node
|
|
@@ -125,7 +125,6 @@ module RuboCop
|
|
|
125
125
|
end
|
|
126
126
|
end
|
|
127
127
|
end
|
|
128
|
-
# rubocop:enable InternalAffairs/RedundantSourceRange
|
|
129
128
|
end
|
|
130
129
|
end
|
|
131
130
|
end
|
|
@@ -281,7 +281,7 @@ module RuboCop
|
|
|
281
281
|
end
|
|
282
282
|
end
|
|
283
283
|
|
|
284
|
-
# rubocop:disable Metrics/AbcSize
|
|
284
|
+
# rubocop:disable-next Metrics/AbcSize
|
|
285
285
|
def do_line_begins_inside_argument?(node, do_loc)
|
|
286
286
|
line_begin_pos = do_loc.begin_pos - do_loc.column
|
|
287
287
|
first_char_pos = line_begin_pos + (do_loc.source_line =~ /\S/)
|
|
@@ -292,7 +292,6 @@ module RuboCop
|
|
|
292
292
|
first_char_pos < argument.source_range.end_pos
|
|
293
293
|
end
|
|
294
294
|
end
|
|
295
|
-
# rubocop:enable Metrics/AbcSize
|
|
296
295
|
|
|
297
296
|
# The continuation line indentation is only an unmeaningful alignment target when
|
|
298
297
|
# it is dictated by an opening delimiter, i.e. the line begins inside `(` or `[`.
|
|
@@ -190,33 +190,58 @@ module RuboCop
|
|
|
190
190
|
|
|
191
191
|
# Validates code style on class declaration.
|
|
192
192
|
# Add offense when find a node out of expected order.
|
|
193
|
+
# A node is out of order when its category is expected earlier than
|
|
194
|
+
# the highest-priority category seen so far, so that a low-priority element
|
|
195
|
+
# (even an unmovable one) cannot mask disorder among the elements that follow it.
|
|
196
|
+
# Consecutive elements of the same category are reported only once,
|
|
197
|
+
# on the first element of the group.
|
|
193
198
|
def on_class(class_node)
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
199
|
+
# Corrections are registered in reverse source order because an insertion at
|
|
200
|
+
# a given position lands before any insertion already made there;
|
|
201
|
+
# this keeps the source order of nodes moved before the same anchor.
|
|
202
|
+
out_of_order_elements(class_node).reverse_each do |node, category, previous|
|
|
203
|
+
message = format(MSG, category: category, previous: previous)
|
|
204
|
+
|
|
205
|
+
add_offense(node, message: message) do |corrector|
|
|
206
|
+
autocorrect(corrector, node)
|
|
200
207
|
end
|
|
201
|
-
previous = index
|
|
202
208
|
end
|
|
203
209
|
end
|
|
204
210
|
alias on_sclass on_class
|
|
205
211
|
|
|
206
212
|
private
|
|
207
213
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
214
|
+
def out_of_order_elements(class_node)
|
|
215
|
+
out_of_order = []
|
|
216
|
+
max_index = -1
|
|
217
|
+
previous_category = nil
|
|
218
|
+
walk_over_nested_class_definition(class_node) do |node, category|
|
|
219
|
+
index = expected_order.index(category)
|
|
220
|
+
if index < max_index && category != previous_category
|
|
221
|
+
out_of_order << [node, category, expected_order[max_index]]
|
|
222
|
+
end
|
|
223
|
+
max_index = index if index > max_index
|
|
224
|
+
previous_category = category
|
|
212
225
|
end
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
current_range = source_range_with_comment(node)
|
|
216
|
-
previous_range = source_range_with_comment(previous)
|
|
226
|
+
out_of_order
|
|
227
|
+
end
|
|
217
228
|
|
|
218
|
-
|
|
219
|
-
|
|
229
|
+
# Autocorrect by moving the node, together with the contiguous group of
|
|
230
|
+
# same-category elements that follows it, to its expected position.
|
|
231
|
+
def autocorrect(corrector, node)
|
|
232
|
+
return if dynamic_constant?(node)
|
|
233
|
+
|
|
234
|
+
anchor = insertion_anchor(node)
|
|
235
|
+
return unless anchor
|
|
236
|
+
|
|
237
|
+
anchor_range = source_range_with_comment(anchor)
|
|
238
|
+
# Reversed for the same reason offenses are registered in reverse source order:
|
|
239
|
+
# the last insertion at a position comes first.
|
|
240
|
+
movable_group(node).reverse_each do |group_node|
|
|
241
|
+
current_range = source_range_with_comment(group_node)
|
|
242
|
+
corrector.insert_before(anchor_range, current_range.source)
|
|
243
|
+
corrector.remove(current_range)
|
|
244
|
+
end
|
|
220
245
|
end
|
|
221
246
|
|
|
222
247
|
# Classifies a node to match with something in the {expected_order}
|
|
@@ -302,15 +327,6 @@ module RuboCop
|
|
|
302
327
|
end
|
|
303
328
|
end
|
|
304
329
|
|
|
305
|
-
def ignore_for_autocorrect?(node, sibling)
|
|
306
|
-
classification = classify(node)
|
|
307
|
-
sibling_class = classify(sibling)
|
|
308
|
-
|
|
309
|
-
ignore?(sibling, sibling_class) ||
|
|
310
|
-
classification == sibling_class ||
|
|
311
|
-
dynamic_constant?(node)
|
|
312
|
-
end
|
|
313
|
-
|
|
314
330
|
def humanize_node(node)
|
|
315
331
|
if node.def_type?
|
|
316
332
|
return :initializer if node.method?(:initialize)
|
|
@@ -328,6 +344,66 @@ module RuboCop
|
|
|
328
344
|
!(expression.method?(:freeze) && expression.receiver&.recursive_basic_literal?)
|
|
329
345
|
end
|
|
330
346
|
|
|
347
|
+
# The expected position of the node: the first left sibling within its movable span
|
|
348
|
+
# whose category is expected to appear after the node's.
|
|
349
|
+
# Requiring a strictly later category keeps the order of elements sharing a category stable.
|
|
350
|
+
def insertion_anchor(node)
|
|
351
|
+
index = expected_order.index(classify(node))
|
|
352
|
+
|
|
353
|
+
movable_span(node).find do |sibling|
|
|
354
|
+
classification = classify(sibling)
|
|
355
|
+
|
|
356
|
+
!ignore?(sibling, classification) && expected_order.index(classification) > index
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
# The node together with the contiguous same-category right siblings,
|
|
361
|
+
# so that the whole group moves in a single pass while the offense is
|
|
362
|
+
# reported only on its first element.
|
|
363
|
+
def movable_group(node)
|
|
364
|
+
classification = classify(node)
|
|
365
|
+
group = [node]
|
|
366
|
+
|
|
367
|
+
node.right_siblings.each do |sibling|
|
|
368
|
+
break unless classify(sibling) == classification
|
|
369
|
+
break if ignore?(sibling, classification) || dynamic_constant?(sibling)
|
|
370
|
+
|
|
371
|
+
group << sibling
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
group
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
# Left siblings the node may be reordered with: those after the last barrier.
|
|
378
|
+
# Ignored elements within the span are simply jumped over.
|
|
379
|
+
def movable_span(node)
|
|
380
|
+
left_siblings = node.left_siblings
|
|
381
|
+
barrier_index = left_siblings.rindex { |sibling| barrier?(node, sibling) }
|
|
382
|
+
|
|
383
|
+
barrier_index ? left_siblings[(barrier_index + 1)..] : left_siblings
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
# A dynamic constant blocks every element: the cop does not move such constants,
|
|
387
|
+
# and letting other elements jump over one would change execution order just the same.
|
|
388
|
+
# A bare visibility modifier blocks only the elements whose meaning depends on
|
|
389
|
+
# the visibility section they appear in.
|
|
390
|
+
def barrier?(node, sibling)
|
|
391
|
+
dynamic_constant?(sibling) || (visibility_dependent?(node) && visibility_block?(sibling))
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
# Whether moving the node across a bare visibility modifier would change its meaning.
|
|
395
|
+
# This is the case for `def` nodes and for macros whose category is classified by visibility
|
|
396
|
+
# (e.g. `attr_accessor` when the expected order lists `private_attribute_macros`).
|
|
397
|
+
# Inline visibility (`private def foo`, `def self.foo`) travels with the node.
|
|
398
|
+
def visibility_dependent?(node)
|
|
399
|
+
return true if node.def_type?
|
|
400
|
+
return false if !node.send_type? || node.def_modifier?
|
|
401
|
+
|
|
402
|
+
key = find_category(node.method_name) || node.method_name.to_s
|
|
403
|
+
|
|
404
|
+
VISIBILITY_SCOPES.any? { |visibility| expected_order.include?("#{visibility}_#{key}") }
|
|
405
|
+
end
|
|
406
|
+
|
|
331
407
|
def private_constant?(node)
|
|
332
408
|
return false unless node.casgn_type? && node.namespace.nil?
|
|
333
409
|
return false unless (parent = node.parent)
|
|
@@ -161,7 +161,7 @@ module RuboCop
|
|
|
161
161
|
next_sibling.if_type? && contains_guard_clause?(next_sibling)
|
|
162
162
|
end
|
|
163
163
|
|
|
164
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
|
164
|
+
# rubocop:disable-next Metrics/CyclomaticComplexity
|
|
165
165
|
def last_heredoc_argument(node)
|
|
166
166
|
n = last_heredoc_argument_node(node)
|
|
167
167
|
n = n.children.first while n.respond_to?(:begin_type?) && n.begin_type?
|
|
@@ -176,7 +176,6 @@ module RuboCop
|
|
|
176
176
|
|
|
177
177
|
last_heredoc_argument(n.receiver) if n.respond_to?(:receiver)
|
|
178
178
|
end
|
|
179
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|
|
180
179
|
|
|
181
180
|
def last_heredoc_argument_node(node)
|
|
182
181
|
return node unless node.respond_to?(:if_branch)
|