rubocop 1.91.0 → 1.92.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 +3 -1
- data/lib/rubocop/cached_data.rb +47 -7
- data/lib/rubocop/changed_files.rb +35 -13
- data/lib/rubocop/cli/command/cop_names.rb +57 -0
- data/lib/rubocop/cli/command/execute_runner.rb +2 -2
- data/lib/rubocop/cli/command/explain.rb +34 -0
- data/lib/rubocop/cli/command/show_cops.rb +6 -0
- data/lib/rubocop/cli/command/show_docs_url.rb +6 -4
- data/lib/rubocop/cli.rb +3 -2
- data/lib/rubocop/comment_config.rb +17 -8
- data/lib/rubocop/config_loader.rb +6 -3
- data/lib/rubocop/config_loader_resolver.rb +37 -12
- data/lib/rubocop/config_obsoletion/removed_cop.rb +1 -1
- data/lib/rubocop/config_validator.rb +11 -0
- data/lib/rubocop/cop/autocorrect_logic.rb +10 -5
- data/lib/rubocop/cop/base.rb +42 -21
- data/lib/rubocop/cop/bundler/gem_comment.rb +0 -1
- data/lib/rubocop/cop/bundler/ordered_gems.rb +0 -8
- data/lib/rubocop/cop/cop_documentation.rb +81 -0
- data/lib/rubocop/cop/cop_explanation.rb +140 -0
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +13 -1
- data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +22 -7
- data/lib/rubocop/cop/correctors/empty_line_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +23 -2
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +45 -8
- data/lib/rubocop/cop/documentation.rb +1 -1
- data/lib/rubocop/cop/gemspec/dependency_version.rb +0 -6
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +0 -6
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +2 -5
- data/lib/rubocop/cop/internal_affairs/node_type_group.rb +0 -7
- data/lib/rubocop/cop/internal_affairs/redundant_context_config_parameter.rb +1 -7
- data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +1 -7
- data/lib/rubocop/cop/layout/block_alignment.rb +27 -0
- data/lib/rubocop/cop/layout/case_indentation.rb +25 -9
- data/lib/rubocop/cop/layout/class_structure.rb +9 -1
- data/lib/rubocop/cop/layout/def_end_alignment.rb +4 -0
- data/lib/rubocop/cop/layout/empty_line_after_multiline_condition.rb +14 -5
- data/lib/rubocop/cop/layout/empty_lines.rb +5 -2
- data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -0
- data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +23 -1
- data/lib/rubocop/cop/layout/end_alignment.rb +16 -10
- data/lib/rubocop/cop/layout/extra_spacing.rb +4 -0
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -0
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +5 -3
- data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +6 -0
- data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +4 -0
- data/lib/rubocop/cop/layout/hash_alignment.rb +16 -12
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -0
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +15 -0
- data/lib/rubocop/cop/layout/indentation_style.rb +4 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +2 -2
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +8 -1
- data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +25 -9
- data/lib/rubocop/cop/layout/line_length.rb +52 -18
- data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +12 -0
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +8 -1
- data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +7 -0
- data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +6 -0
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +14 -0
- data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +4 -0
- data/lib/rubocop/cop/layout/redundant_line_break.rb +22 -1
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +15 -2
- data/lib/rubocop/cop/layout/single_line_block_chain.rb +10 -2
- data/lib/rubocop/cop/layout/space_after_not.rb +5 -0
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +6 -11
- data/lib/rubocop/cop/layout/space_around_keyword.rb +10 -0
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +4 -1
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +15 -2
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +31 -8
- data/lib/rubocop/cop/lint/ambiguous_operator.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +2 -1
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +3 -1
- data/lib/rubocop/cop/lint/literal_as_condition.rb +15 -0
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +63 -19
- data/lib/rubocop/cop/lint/loop.rb +24 -2
- data/lib/rubocop/cop/lint/misplaced_magic_comment.rb +71 -11
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +18 -3
- data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +12 -1
- data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +13 -2
- data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +18 -1
- data/lib/rubocop/cop/lint/useless_assignment.rb +14 -7
- data/lib/rubocop/cop/lint/void.rb +8 -1
- data/lib/rubocop/cop/metrics/class_length.rb +4 -2
- data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +0 -4
- data/lib/rubocop/cop/metrics/module_length.rb +4 -2
- data/lib/rubocop/cop/mixin/alignment.rb +4 -0
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +17 -14
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +5 -1
- data/lib/rubocop/cop/mixin/code_length.rb +10 -2
- data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +12 -1
- data/lib/rubocop/cop/mixin/endless_method_body_help.rb +69 -0
- data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +2 -2
- data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +15 -1
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +26 -2
- data/lib/rubocop/cop/mixin/min_branches_count.rb +3 -1
- data/lib/rubocop/cop/mixin/multiline_element_line_breaks.rb +11 -1
- data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +9 -0
- data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
- data/lib/rubocop/cop/mixin/pattern_matching_help.rb +35 -0
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +17 -2
- data/lib/rubocop/cop/mixin/project_index_help.rb +15 -0
- data/lib/rubocop/cop/mixin/reparsed_equivalence.rb +13 -3
- data/lib/rubocop/cop/mixin/statement_modifier.rb +22 -2
- data/lib/rubocop/cop/mixin.rb +2 -0
- data/lib/rubocop/cop/naming/accessor_method_name.rb +0 -16
- data/lib/rubocop/cop/naming/block_forwarding.rb +1 -1
- data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +9 -2
- data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +5 -3
- data/lib/rubocop/cop/naming/predicate_prefix.rb +7 -22
- data/lib/rubocop/cop/offense.rb +59 -3
- data/lib/rubocop/cop/registry.rb +1 -1
- data/lib/rubocop/cop/security/json_load.rb +16 -4
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +7 -0
- data/lib/rubocop/cop/style/alias.rb +18 -5
- data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +4 -3
- data/lib/rubocop/cop/style/and_or.rb +4 -0
- data/lib/rubocop/cop/style/arguments_forwarding.rb +4 -1
- data/lib/rubocop/cop/style/attr.rb +3 -4
- data/lib/rubocop/cop/style/bitwise_predicate.rb +6 -4
- data/lib/rubocop/cop/style/block_delimiters.rb +29 -3
- data/lib/rubocop/cop/style/case_like_if.rb +6 -3
- data/lib/rubocop/cop/style/class_and_module_children.rb +54 -16
- data/lib/rubocop/cop/style/class_methods_definitions.rb +8 -0
- data/lib/rubocop/cop/style/combinable_loops.rb +85 -11
- data/lib/rubocop/cop/style/concat_array_literals.rb +46 -7
- data/lib/rubocop/cop/style/conditional_assignment.rb +4 -0
- data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +65 -9
- data/lib/rubocop/cop/style/double_negation.rb +11 -0
- data/lib/rubocop/cop/style/empty_literal.rb +1 -1
- data/lib/rubocop/cop/style/empty_method.rb +3 -1
- data/lib/rubocop/cop/style/endless_method.rb +67 -6
- data/lib/rubocop/cop/style/exact_regexp_match.rb +45 -8
- data/lib/rubocop/cop/style/explicit_block_argument.rb +50 -10
- data/lib/rubocop/cop/style/float_division.rb +22 -2
- data/lib/rubocop/cop/style/for.rb +40 -2
- data/lib/rubocop/cop/style/format_string.rb +28 -6
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +2 -1
- data/lib/rubocop/cop/style/guard_clause.rb +9 -1
- data/lib/rubocop/cop/style/hash_conversion.rb +28 -8
- data/lib/rubocop/cop/style/hash_lookup_method.rb +32 -9
- data/lib/rubocop/cop/style/hash_syntax.rb +16 -3
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +22 -3
- data/lib/rubocop/cop/style/if_inside_else.rb +21 -1
- data/lib/rubocop/cop/style/if_unless_modifier.rb +19 -20
- data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +4 -0
- data/lib/rubocop/cop/style/if_with_semicolon.rb +47 -4
- data/lib/rubocop/cop/style/inverse_methods.rb +24 -2
- data/lib/rubocop/cop/style/it_block_parameter.rb +32 -3
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +3 -1
- data/lib/rubocop/cop/style/lambda.rb +18 -0
- data/lib/rubocop/cop/style/lambda_call.rb +7 -2
- data/lib/rubocop/cop/style/map_into_array.rb +1 -2
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +45 -10
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +25 -2
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +26 -3
- data/lib/rubocop/cop/style/method_def_parentheses.rb +29 -3
- data/lib/rubocop/cop/style/missing_else.rb +7 -1
- data/lib/rubocop/cop/style/multiline_if_modifier.rb +45 -5
- data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +7 -0
- data/lib/rubocop/cop/style/multiline_method_signature.rb +2 -5
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +7 -3
- data/lib/rubocop/cop/style/multiline_when_then.rb +7 -0
- data/lib/rubocop/cop/style/mutable_constant.rb +28 -1
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +2 -1
- data/lib/rubocop/cop/style/negative_array_index.rb +9 -1
- data/lib/rubocop/cop/style/nested_modifier.rb +27 -8
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +26 -8
- data/lib/rubocop/cop/style/next.rb +24 -10
- data/lib/rubocop/cop/style/nil_comparison.rb +16 -4
- data/lib/rubocop/cop/style/non_nil_check.rb +1 -1
- data/lib/rubocop/cop/style/not.rb +10 -5
- data/lib/rubocop/cop/style/numeric_predicate.rb +21 -5
- data/lib/rubocop/cop/style/one_line_conditional.rb +13 -2
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +14 -3
- data/lib/rubocop/cop/style/reduce_to_hash.rb +17 -1
- data/lib/rubocop/cop/style/redundant_begin.rb +20 -3
- data/lib/rubocop/cop/style/redundant_condition.rb +30 -13
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +6 -0
- data/lib/rubocop/cop/style/redundant_exception.rb +15 -3
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +9 -1
- data/lib/rubocop/cop/style/redundant_freeze.rb +10 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +12 -1
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +7 -0
- data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +20 -0
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +4 -0
- data/lib/rubocop/cop/style/regexp_literal.rb +75 -26
- data/lib/rubocop/cop/style/require_order.rb +9 -0
- data/lib/rubocop/cop/style/rescue_modifier.rb +5 -9
- data/lib/rubocop/cop/style/return_nil.rb +17 -2
- data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +11 -1
- data/lib/rubocop/cop/style/sample.rb +9 -8
- data/lib/rubocop/cop/style/self_assignment.rb +12 -15
- data/lib/rubocop/cop/style/semicolon.rb +16 -5
- data/lib/rubocop/cop/style/single_line_methods.rb +16 -4
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +29 -5
- data/lib/rubocop/cop/style/string_concatenation.rb +9 -3
- data/lib/rubocop/cop/style/super_arguments.rb +3 -0
- data/lib/rubocop/cop/style/symbol_proc.rb +23 -5
- data/lib/rubocop/cop/style/ternary_parentheses.rb +23 -1
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +23 -19
- data/lib/rubocop/cop/style/while_until_modifier.rb +1 -1
- data/lib/rubocop/cop/style/yoda_condition.rb +24 -9
- data/lib/rubocop/cop/style/yoda_expression.rb +10 -1
- data/lib/rubocop/cop/team.rb +10 -5
- data/lib/rubocop/cop/variable_force/assignment.rb +1 -1
- data/lib/rubocop/cop/variable_force/variable.rb +14 -1
- data/lib/rubocop/formatter/base_formatter.rb +22 -0
- data/lib/rubocop/formatter/formatter_set.rb +4 -0
- data/lib/rubocop/formatter/json_formatter.rb +71 -1
- data/lib/rubocop/formatter/offense_count_formatter.rb +3 -1
- data/lib/rubocop/formatter/pacman_formatter.rb +3 -1
- data/lib/rubocop/formatter/sarif_formatter.rb +12 -7
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +3 -1
- data/lib/rubocop/lsp/runtime.rb +47 -11
- data/lib/rubocop/lsp/stdin_runner.rb +11 -5
- data/lib/rubocop/lsp.rb +5 -2
- data/lib/rubocop/mcp/autocorrection_request.rb +52 -0
- data/lib/rubocop/mcp/explain_tool.rb +68 -0
- data/lib/rubocop/mcp/scope.rb +65 -0
- data/lib/rubocop/mcp/server.rb +184 -76
- data/lib/rubocop/mcp/source_files.rb +35 -0
- data/lib/rubocop/offense_limit.rb +30 -0
- data/lib/rubocop/options.rb +45 -10
- data/lib/rubocop/plugin/configuration_integrator.rb +12 -5
- data/lib/rubocop/remote_config.rb +4 -1
- data/lib/rubocop/result_cache.rb +20 -13
- data/lib/rubocop/runner.rb +109 -41
- data/lib/rubocop/server/cache.rb +2 -2
- data/lib/rubocop/util.rb +69 -0
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +5 -0
- metadata +16 -5
|
@@ -142,12 +142,6 @@ module RuboCop
|
|
|
142
142
|
end
|
|
143
143
|
end
|
|
144
144
|
|
|
145
|
-
def offending_prefixes_for(node, method_name)
|
|
146
|
-
predicate_prefixes.reject do |prefix|
|
|
147
|
-
allowed_method_name?(method_name, prefix) ||
|
|
148
|
-
(use_sorbet_sigs? && !sorbet_sig?(node, return_type: 'T::Boolean'))
|
|
149
|
-
end
|
|
150
|
-
end
|
|
151
145
|
alias on_defs on_def
|
|
152
146
|
|
|
153
147
|
def validate_config
|
|
@@ -162,6 +156,13 @@ module RuboCop
|
|
|
162
156
|
|
|
163
157
|
private
|
|
164
158
|
|
|
159
|
+
def offending_prefixes_for(node, method_name)
|
|
160
|
+
prefixes = predicate_prefixes.reject { |p| allowed_method_name?(method_name, p) }
|
|
161
|
+
return prefixes if prefixes.empty? || !use_sorbet_sigs?
|
|
162
|
+
|
|
163
|
+
sorbet_sig?(node, return_type: 'T::Boolean') ? prefixes : []
|
|
164
|
+
end
|
|
165
|
+
|
|
165
166
|
# @!method sorbet_return_type(node)
|
|
166
167
|
def_node_matcher :sorbet_return_type, <<~PATTERN
|
|
167
168
|
(block (send nil? :sig) args (send _ :returns $_type))
|
|
@@ -210,22 +211,6 @@ module RuboCop
|
|
|
210
211
|
def method_definition_macro?(macro_name)
|
|
211
212
|
cop_config['MethodDefinitionMacros'].include?(macro_name.to_s)
|
|
212
213
|
end
|
|
213
|
-
|
|
214
|
-
# When `AllCops/UseProjectIndex` is enabled, methods that override a
|
|
215
|
-
# method defined by an ancestor elsewhere in the project are not
|
|
216
|
-
# reported: renaming an override breaks the inherited contract.
|
|
217
|
-
def overrides_inherited_method?(node)
|
|
218
|
-
return false unless project_index
|
|
219
|
-
return false unless (namespace_node = node.each_ancestor(:class, :module).first)
|
|
220
|
-
|
|
221
|
-
declaration = resolve_constant_in_index(namespace_node.identifier)
|
|
222
|
-
return false unless declaration.is_a?(Rubydex::Namespace)
|
|
223
|
-
|
|
224
|
-
scope = node.defs_type? ? indexed_singleton_of(declaration) : declaration
|
|
225
|
-
!scope.nil? && inherited_index_member?(scope, "#{node.method_name}()")
|
|
226
|
-
rescue StandardError
|
|
227
|
-
false
|
|
228
|
-
end
|
|
229
214
|
end
|
|
230
215
|
end
|
|
231
216
|
end
|
data/lib/rubocop/cop/offense.rb
CHANGED
|
@@ -86,6 +86,9 @@ module RuboCop
|
|
|
86
86
|
|
|
87
87
|
NO_LOCATION = PseudoSourceRange.new(1, 0, '', 0, 0).freeze
|
|
88
88
|
|
|
89
|
+
EMPTY_CORRECTIONS = [].freeze
|
|
90
|
+
private_constant :EMPTY_CORRECTIONS
|
|
91
|
+
|
|
89
92
|
# @api public
|
|
90
93
|
#
|
|
91
94
|
# @!attribute [r] justification
|
|
@@ -96,9 +99,43 @@ module RuboCop
|
|
|
96
99
|
# or the directive carries no reason
|
|
97
100
|
attr_reader :justification
|
|
98
101
|
|
|
102
|
+
# @api public
|
|
103
|
+
#
|
|
104
|
+
# @!attribute [r] corrections
|
|
105
|
+
#
|
|
106
|
+
# @return [Array<Correction>]
|
|
107
|
+
# the individual edits that autocorrecting this offense would make, in
|
|
108
|
+
# source order. Empty when the offense has no correction. Unlike
|
|
109
|
+
# {#corrector}, this survives serialization, so it is available on a
|
|
110
|
+
# cache hit and in parallel runs.
|
|
111
|
+
attr_reader :corrections
|
|
112
|
+
|
|
113
|
+
# @api public
|
|
114
|
+
#
|
|
115
|
+
# @!attribute [r] correction_safe
|
|
116
|
+
#
|
|
117
|
+
# @return [Boolean]
|
|
118
|
+
# whether autocorrection would apply {#corrections} in a normal `-a`
|
|
119
|
+
# run. A cop marked `Safe: false` or `SafeAutoCorrect: false` still
|
|
120
|
+
# builds its correction, but only `-A` applies it, so a consumer that
|
|
121
|
+
# applies edits itself has to make the same distinction.
|
|
122
|
+
attr_reader :correction_safe
|
|
123
|
+
|
|
124
|
+
# A single edit of an autocorrection: the source range it replaces and
|
|
125
|
+
# the text it replaces it with. An insertion has an empty range, a
|
|
126
|
+
# removal an empty replacement.
|
|
127
|
+
#
|
|
128
|
+
# @api public
|
|
129
|
+
Correction = Struct.new(:begin_pos, :end_pos, :replacement) do
|
|
130
|
+
def length
|
|
131
|
+
end_pos - begin_pos
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
99
135
|
# @api private
|
|
100
136
|
def initialize(severity, location, message, cop_name, # rubocop:disable Metrics/ParameterLists
|
|
101
|
-
status = :uncorrected, corrector = nil, justification: nil
|
|
137
|
+
status = :uncorrected, corrector = nil, justification: nil,
|
|
138
|
+
corrections: nil, correction_safe: true)
|
|
102
139
|
@severity = RuboCop::Cop::Severity.new(severity)
|
|
103
140
|
@location = location
|
|
104
141
|
|
|
@@ -112,15 +149,21 @@ module RuboCop
|
|
|
112
149
|
@status = status
|
|
113
150
|
@corrector = corrector
|
|
114
151
|
@justification = justification.freeze
|
|
152
|
+
@corrections = (corrections || corrections_from(corrector)).freeze
|
|
153
|
+
@correction_safe = correction_safe
|
|
115
154
|
freeze
|
|
116
155
|
end
|
|
117
156
|
|
|
118
157
|
def marshal_dump
|
|
119
|
-
[@severity, @location, @message, @cop_name, @status, @justification
|
|
158
|
+
[@severity, @location, @message, @cop_name, @status, @justification, @corrections,
|
|
159
|
+
@correction_safe]
|
|
120
160
|
end
|
|
121
161
|
|
|
122
162
|
def marshal_load(array)
|
|
123
|
-
@severity, @location, @message, @cop_name, @status, @justification
|
|
163
|
+
@severity, @location, @message, @cop_name, @status, @justification, @corrections,
|
|
164
|
+
@correction_safe = array
|
|
165
|
+
@corrections ||= EMPTY_CORRECTIONS
|
|
166
|
+
@correction_safe = true if @correction_safe.nil?
|
|
124
167
|
@line = @location.line
|
|
125
168
|
@column = @location.column
|
|
126
169
|
end
|
|
@@ -276,6 +319,19 @@ module RuboCop
|
|
|
276
319
|
end
|
|
277
320
|
0
|
|
278
321
|
end
|
|
322
|
+
|
|
323
|
+
private
|
|
324
|
+
|
|
325
|
+
# Extracted eagerly rather than on demand because the offense is frozen,
|
|
326
|
+
# and because a corrector cannot be serialized - the cache and parallel
|
|
327
|
+
# workers would otherwise hand back offenses that have lost their edits.
|
|
328
|
+
def corrections_from(corrector)
|
|
329
|
+
return EMPTY_CORRECTIONS unless corrector
|
|
330
|
+
|
|
331
|
+
corrector.as_replacements.map do |range, replacement|
|
|
332
|
+
Correction.new(range.begin_pos, range.end_pos, replacement.freeze).freeze
|
|
333
|
+
end
|
|
334
|
+
end
|
|
279
335
|
end
|
|
280
336
|
end
|
|
281
337
|
end
|
data/lib/rubocop/cop/registry.rb
CHANGED
|
@@ -22,6 +22,13 @@ module RuboCop
|
|
|
22
22
|
# passing the `create_additions` keyword argument emits a deprecation warning, with the
|
|
23
23
|
# goal of being secure by default in the next major version 3.0.0.
|
|
24
24
|
#
|
|
25
|
+
# NOTE: Before `json` gem version 2.17.0, `JSON.load` only takes options as its third
|
|
26
|
+
# argument. A hash passed as the second argument is taken as the `proc` argument, so
|
|
27
|
+
# its `create_additions` option is ignored. Which `json` version runs can't be told
|
|
28
|
+
# statically (the lockfile may resolve a newer one than the default gem loaded in
|
|
29
|
+
# production), so options passed as the second argument are always reported. Pass
|
|
30
|
+
# `nil` as the second argument instead.
|
|
31
|
+
#
|
|
25
32
|
# @safety
|
|
26
33
|
# This cop's autocorrection is unsafe because it's potentially dangerous.
|
|
27
34
|
# If using a stream, like `JSON.load(open('file'))`, you will need to call
|
|
@@ -33,13 +40,16 @@ module RuboCop
|
|
|
33
40
|
# JSON.load('{}')
|
|
34
41
|
# JSON.restore('{}')
|
|
35
42
|
#
|
|
43
|
+
# # bad - ignored by `json` older than 2.17.0
|
|
44
|
+
# JSON.load('{}', create_additions: false)
|
|
45
|
+
#
|
|
36
46
|
# # good
|
|
37
47
|
# JSON.parse('{}')
|
|
38
48
|
# JSON.unsafe_load('{}')
|
|
39
49
|
#
|
|
40
50
|
# # good - explicit use of `create_additions` option
|
|
41
|
-
# JSON.load('{}', create_additions: true)
|
|
42
|
-
# JSON.load('{}', create_additions: false)
|
|
51
|
+
# JSON.load('{}', nil, create_additions: true)
|
|
52
|
+
# JSON.load('{}', nil, create_additions: false)
|
|
43
53
|
#
|
|
44
54
|
class JSONLoad < Base
|
|
45
55
|
extend AutoCorrector
|
|
@@ -51,8 +61,10 @@ module RuboCop
|
|
|
51
61
|
def_node_matcher :insecure_json_load, <<~PATTERN
|
|
52
62
|
(
|
|
53
63
|
send (const {nil? cbase} :JSON) ${:load :restore}
|
|
54
|
-
|
|
55
|
-
|
|
64
|
+
{
|
|
65
|
+
_ hash
|
|
66
|
+
| ... !`(pair (sym :create_additions) _)
|
|
67
|
+
}
|
|
56
68
|
)
|
|
57
69
|
PATTERN
|
|
58
70
|
|
|
@@ -187,11 +187,18 @@ module RuboCop
|
|
|
187
187
|
def allowed?(node)
|
|
188
188
|
!node.access_modifier? ||
|
|
189
189
|
node.parent&.type?(:pair, :any_block) ||
|
|
190
|
+
dynamic_method_list?(node) ||
|
|
190
191
|
allow_modifiers_on_symbols?(node) ||
|
|
191
192
|
allow_modifiers_on_attrs?(node) ||
|
|
192
193
|
allow_modifiers_on_alias_method?(node)
|
|
193
194
|
end
|
|
194
195
|
|
|
196
|
+
# `private(*names)` with a list computed at runtime names no definition
|
|
197
|
+
# the modifier could be grouped with.
|
|
198
|
+
def dynamic_method_list?(node)
|
|
199
|
+
node.arguments.any?(&:splat_type?) && !access_modifier_with_symbol?(node)
|
|
200
|
+
end
|
|
201
|
+
|
|
195
202
|
def autocorrect(corrector, node)
|
|
196
203
|
case style
|
|
197
204
|
when :group
|
|
@@ -60,7 +60,7 @@ module RuboCop
|
|
|
60
60
|
add_offense(node.loc.keyword, message: MSG_ALIAS) do |corrector|
|
|
61
61
|
autocorrect(corrector, node)
|
|
62
62
|
end
|
|
63
|
-
elsif node.children.
|
|
63
|
+
elsif node.children.all? { |arg| !bareword?(arg) && bareword_symbol?(arg) }
|
|
64
64
|
add_offense_for_args(node) { |corrector| autocorrect(corrector, node) }
|
|
65
65
|
end
|
|
66
66
|
end
|
|
@@ -97,7 +97,7 @@ module RuboCop
|
|
|
97
97
|
|
|
98
98
|
def add_offense_for_args(node, &block)
|
|
99
99
|
existing_args = node.children.map(&:source).join(' ')
|
|
100
|
-
preferred_args = node.children.map { |
|
|
100
|
+
preferred_args = node.children.map { |node| bareword_for(node) }.join(' ')
|
|
101
101
|
arg_ranges = node.children.map(&:source_range)
|
|
102
102
|
msg = format(MSG_SYMBOL_ARGS, prefer: preferred_args, current: existing_args)
|
|
103
103
|
add_offense(arg_ranges.reduce(&:join), message: msg, &block)
|
|
@@ -138,6 +138,15 @@ module RuboCop
|
|
|
138
138
|
!sym_node.source.start_with?(':') || sym_node.dsym_type?
|
|
139
139
|
end
|
|
140
140
|
|
|
141
|
+
def bareword_symbol?(sym_node)
|
|
142
|
+
return false unless sym_node.sym_type?
|
|
143
|
+
|
|
144
|
+
value = sym_node.value.to_s
|
|
145
|
+
return true if value.match?(/\A[A-Za-z_]\w*[?!=]?\z/)
|
|
146
|
+
|
|
147
|
+
!sym_node.source.start_with?(':"', ":'") && !value.start_with?('@', '$')
|
|
148
|
+
end
|
|
149
|
+
|
|
141
150
|
def correct_alias_method_to_alias(corrector, send_node)
|
|
142
151
|
new, old = *send_node.arguments
|
|
143
152
|
replacement = "alias #{identifier(new)} #{identifier(old)}"
|
|
@@ -153,17 +162,21 @@ module RuboCop
|
|
|
153
162
|
end
|
|
154
163
|
|
|
155
164
|
def correct_alias_with_symbol_args(corrector, node)
|
|
156
|
-
corrector.replace(node.new_identifier, node.new_identifier
|
|
157
|
-
corrector.replace(node.old_identifier, node.old_identifier
|
|
165
|
+
corrector.replace(node.new_identifier, bareword_for(node.new_identifier))
|
|
166
|
+
corrector.replace(node.old_identifier, bareword_for(node.old_identifier))
|
|
158
167
|
end
|
|
159
168
|
|
|
160
169
|
def identifier(node)
|
|
161
|
-
if node
|
|
170
|
+
if bareword_symbol?(node)
|
|
162
171
|
":#{node.children.first}"
|
|
163
172
|
else
|
|
164
173
|
node.source
|
|
165
174
|
end
|
|
166
175
|
end
|
|
176
|
+
|
|
177
|
+
def bareword_for(sym_node)
|
|
178
|
+
sym_node.value.to_s
|
|
179
|
+
end
|
|
167
180
|
end
|
|
168
181
|
end
|
|
169
182
|
end
|
|
@@ -39,9 +39,9 @@ module RuboCop
|
|
|
39
39
|
# @!method ambiguous_endless_method_body(node)
|
|
40
40
|
def_node_matcher :ambiguous_endless_method_body, <<~PATTERN
|
|
41
41
|
^${
|
|
42
|
-
(if _ <
|
|
43
|
-
({and or}
|
|
44
|
-
({while until} _
|
|
42
|
+
(if _ <any_def _>)
|
|
43
|
+
({and or} any_def _)
|
|
44
|
+
({while until} _ any_def)
|
|
45
45
|
}
|
|
46
46
|
PATTERN
|
|
47
47
|
|
|
@@ -57,6 +57,7 @@ module RuboCop
|
|
|
57
57
|
correct_to_multiline(corrector, node)
|
|
58
58
|
end
|
|
59
59
|
end
|
|
60
|
+
alias on_defs on_def
|
|
60
61
|
|
|
61
62
|
private
|
|
62
63
|
|
|
@@ -48,6 +48,10 @@ module RuboCop
|
|
|
48
48
|
|
|
49
49
|
MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
|
|
50
50
|
|
|
51
|
+
def self.autocorrect_incompatible_with
|
|
52
|
+
[Style::MethodCallWithArgsParentheses, Style::ReturnNilInPredicateMethodDefinition]
|
|
53
|
+
end
|
|
54
|
+
|
|
51
55
|
def on_and(node)
|
|
52
56
|
process_logical_operator(node) if style == :always
|
|
53
57
|
end
|
|
@@ -153,7 +153,7 @@ module RuboCop
|
|
|
153
153
|
BLOCK_MSG = 'Use anonymous block arguments forwarding (`&`).'
|
|
154
154
|
|
|
155
155
|
def self.autocorrect_incompatible_with
|
|
156
|
-
[Naming::BlockForwarding, Style::MethodDefParentheses]
|
|
156
|
+
[Naming::BlockForwarding, Style::EndlessMethod, Style::MethodDefParentheses]
|
|
157
157
|
end
|
|
158
158
|
|
|
159
159
|
def on_def(node)
|
|
@@ -377,6 +377,7 @@ module RuboCop
|
|
|
377
377
|
def add_parens_if_missing(node, corrector)
|
|
378
378
|
return if parentheses?(node)
|
|
379
379
|
return if node.send_type? && node.method?(:[])
|
|
380
|
+
return unless (@parenthesized_nodes ||= Set.new.compare_by_identity).add?(node)
|
|
380
381
|
|
|
381
382
|
add_parentheses(node, corrector)
|
|
382
383
|
end
|
|
@@ -499,6 +500,8 @@ module RuboCop
|
|
|
499
500
|
end
|
|
500
501
|
|
|
501
502
|
def offensive_block_forwarding?
|
|
503
|
+
return false if @send_node.block_literal?
|
|
504
|
+
|
|
502
505
|
@block_arg ? forwarded_block_arg : allow_offense_for_no_block?
|
|
503
506
|
end
|
|
504
507
|
|
|
@@ -50,10 +50,9 @@ module RuboCop
|
|
|
50
50
|
def autocorrect(corrector, node)
|
|
51
51
|
attr_name, setter = *node.arguments
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
remove = range_between(attr_expr.end_pos, node_expr.end_pos) if setter&.boolean_type?
|
|
53
|
+
if setter&.boolean_type?
|
|
54
|
+
remove = range_between(attr_name.source_range.end_pos, setter.source_range.end_pos)
|
|
55
|
+
end
|
|
57
56
|
|
|
58
57
|
corrector.replace(node.loc.selector, replacement_method(node))
|
|
59
58
|
corrector.remove(remove) if remove
|
|
@@ -66,16 +66,18 @@ module RuboCop
|
|
|
66
66
|
|
|
67
67
|
# @!method bit_operation?(node)
|
|
68
68
|
def_node_matcher :bit_operation?, <<~PATTERN
|
|
69
|
-
|
|
70
|
-
(send _ :& _))
|
|
69
|
+
{
|
|
70
|
+
(begin (send _ :& _))
|
|
71
|
+
(send _ :& _)
|
|
72
|
+
}
|
|
71
73
|
PATTERN
|
|
72
74
|
|
|
73
75
|
# rubocop:disable-next Metrics/AbcSize
|
|
74
76
|
def on_send(node)
|
|
75
|
-
return unless node.receiver
|
|
77
|
+
return unless bit_operation?(node.receiver)
|
|
76
78
|
return unless (preferred_method = preferred_method(node))
|
|
77
79
|
|
|
78
|
-
bit_operation = node.receiver.children.first
|
|
80
|
+
bit_operation = node.receiver.begin_type? ? node.receiver.children.first : node.receiver
|
|
79
81
|
lhs, _operator, rhs = *bit_operation
|
|
80
82
|
|
|
81
83
|
preferred = if preferred_method == 'allbits?' && lhs.source == node.first_argument.source
|
|
@@ -177,7 +177,7 @@ module RuboCop
|
|
|
177
177
|
BRACES_REQUIRED_MESSAGE = "Brace delimiters `{...}` required for '%<method_name>s' method."
|
|
178
178
|
|
|
179
179
|
def self.autocorrect_incompatible_with
|
|
180
|
-
[Style::RedundantBegin]
|
|
180
|
+
[Layout::SpaceBeforeBlockBraces, Style::MethodCallWithArgsParentheses, Style::RedundantBegin]
|
|
181
181
|
end
|
|
182
182
|
|
|
183
183
|
def on_send(node)
|
|
@@ -196,6 +196,8 @@ module RuboCop
|
|
|
196
196
|
end
|
|
197
197
|
end
|
|
198
198
|
alias on_csend on_send
|
|
199
|
+
alias on_super on_send
|
|
200
|
+
alias on_yield on_send
|
|
199
201
|
|
|
200
202
|
def on_block(node)
|
|
201
203
|
return if part_of_ignored_node?(node)
|
|
@@ -292,7 +294,7 @@ module RuboCop
|
|
|
292
294
|
corrector.replace(b, '{')
|
|
293
295
|
corrector.replace(e, '}')
|
|
294
296
|
|
|
295
|
-
corrector
|
|
297
|
+
wrap_body_with_begin(corrector, node.body) if begin_required?(node)
|
|
296
298
|
end
|
|
297
299
|
|
|
298
300
|
def whitespace_before?(range)
|
|
@@ -372,6 +374,7 @@ module RuboCop
|
|
|
372
374
|
# rubocop:disable-next Metrics/CyclomaticComplexity -- inlined special_method checks to avoid double evaluation
|
|
373
375
|
def proper_block_style?(node)
|
|
374
376
|
return true if require_do_end?(node)
|
|
377
|
+
return true if collection_of_for_loop?(node)
|
|
375
378
|
|
|
376
379
|
method_name = node.method_name
|
|
377
380
|
return true if allowed_method?(method_name) || matches_allowed_pattern?(method_name)
|
|
@@ -398,6 +401,10 @@ module RuboCop
|
|
|
398
401
|
!modifier_rescue?(body)
|
|
399
402
|
end
|
|
400
403
|
|
|
404
|
+
def collection_of_for_loop?(node)
|
|
405
|
+
node.parent&.for_type? && node.parent.collection == node
|
|
406
|
+
end
|
|
407
|
+
|
|
401
408
|
def modifier_rescue?(rescue_node)
|
|
402
409
|
return false if rescue_node.body.nil? || rescue_node.else_branch
|
|
403
410
|
return false unless rescue_node.resbody_branches.one?
|
|
@@ -438,11 +445,20 @@ module RuboCop
|
|
|
438
445
|
end
|
|
439
446
|
|
|
440
447
|
def correction_would_break_code?(node)
|
|
441
|
-
return
|
|
448
|
+
return loop_condition?(node) if node.braces?
|
|
442
449
|
|
|
443
450
|
node.send_node.arguments? && !node.send_node.parenthesized?
|
|
444
451
|
end
|
|
445
452
|
|
|
453
|
+
# A `do` in the condition of `while` or `until` is taken as the start of
|
|
454
|
+
# the loop body. Inside the body of another block it is unambiguous again.
|
|
455
|
+
def loop_condition?(node)
|
|
456
|
+
ancestors = node.each_ancestor.take_while { |ancestor| !ancestor.any_block_type? }
|
|
457
|
+
[node, *ancestors].each_cons(2).any? do |child, parent|
|
|
458
|
+
parent.type?(:while, :until) && parent.condition.equal?(child)
|
|
459
|
+
end
|
|
460
|
+
end
|
|
461
|
+
|
|
446
462
|
def functional_method?(method_name)
|
|
447
463
|
functional_methods.include?(method_name)
|
|
448
464
|
end
|
|
@@ -490,6 +506,16 @@ module RuboCop
|
|
|
490
506
|
node.type?(:array, :range)
|
|
491
507
|
end
|
|
492
508
|
|
|
509
|
+
def wrap_body_with_begin(corrector, body)
|
|
510
|
+
heredoc_ends = body.each_node(:any_str).select(&:heredoc?).map do |str|
|
|
511
|
+
str.loc.heredoc_end
|
|
512
|
+
end
|
|
513
|
+
body_end = [body.source_range, *heredoc_ends].max_by(&:end_pos)
|
|
514
|
+
|
|
515
|
+
corrector.insert_before(body, "begin\n")
|
|
516
|
+
corrector.insert_after(body_end, "\nend")
|
|
517
|
+
end
|
|
518
|
+
|
|
493
519
|
def begin_required?(block_node)
|
|
494
520
|
# If the block contains `rescue` or `ensure`, it needs to be wrapped in
|
|
495
521
|
# `begin`...`end` when changing `do-end` to `{}`.
|
|
@@ -54,6 +54,10 @@ module RuboCop
|
|
|
54
54
|
|
|
55
55
|
MSG = 'Convert `if-elsif` to `case-when`.'
|
|
56
56
|
|
|
57
|
+
def self.autocorrect_incompatible_with
|
|
58
|
+
[Style::IfInsideElse]
|
|
59
|
+
end
|
|
60
|
+
|
|
57
61
|
def on_if(node)
|
|
58
62
|
return unless should_check?(node)
|
|
59
63
|
|
|
@@ -224,10 +228,9 @@ module RuboCop
|
|
|
224
228
|
end
|
|
225
229
|
|
|
226
230
|
def branch_conditions(node)
|
|
227
|
-
conditions = []
|
|
228
|
-
while node&.if_type? &&
|
|
231
|
+
conditions = [node.condition]
|
|
232
|
+
while (node = node.else_branch)&.if_type? && node.elsif?
|
|
229
233
|
conditions << node.condition
|
|
230
|
-
node = node.else_branch
|
|
231
234
|
end
|
|
232
235
|
conditions
|
|
233
236
|
end
|
|
@@ -65,6 +65,12 @@ module RuboCop
|
|
|
65
65
|
NESTED_MSG = 'Use nested module/class definitions instead of compact style.'
|
|
66
66
|
COMPACT_MSG = 'Use compact module/class definition instead of nested style.'
|
|
67
67
|
|
|
68
|
+
# `Style/StructInheritance` turns a class definition into a constant assignment in
|
|
69
|
+
# the same pass, which the compacted `class` keyword would then precede.
|
|
70
|
+
def self.autocorrect_incompatible_with
|
|
71
|
+
[Style::StructInheritance]
|
|
72
|
+
end
|
|
73
|
+
|
|
68
74
|
def on_class(node)
|
|
69
75
|
return if node.parent_class && style_for_classes != :nested
|
|
70
76
|
|
|
@@ -117,7 +123,10 @@ module RuboCop
|
|
|
117
123
|
end
|
|
118
124
|
|
|
119
125
|
def heuristic_namespace_keyword(node)
|
|
120
|
-
|
|
126
|
+
left_sibling = node.left_sibling
|
|
127
|
+
return 'module' unless left_sibling.is_a?(AST::Node)
|
|
128
|
+
|
|
129
|
+
class_definition = left_sibling.each_node(:class).find do |class_node|
|
|
121
130
|
class_node.identifier == node.identifier.namespace
|
|
122
131
|
end
|
|
123
132
|
|
|
@@ -194,33 +203,62 @@ module RuboCop
|
|
|
194
203
|
"#{node.body.children.first.const_name}"
|
|
195
204
|
end
|
|
196
205
|
|
|
197
|
-
# rubocop:disable-next Metrics/AbcSize
|
|
198
206
|
def remove_end(corrector, body)
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
adjustment = processed_source.raw_source[remove_begin_pos] == ';' ? 0 : 1
|
|
205
|
-
range = range_between(remove_begin_pos, body.loc.end.end_pos + adjustment)
|
|
207
|
+
range = if same_line?(body.loc.name, body.loc.end)
|
|
208
|
+
single_line_end_range(body)
|
|
209
|
+
else
|
|
210
|
+
multiline_end_range(body)
|
|
211
|
+
end
|
|
206
212
|
|
|
207
213
|
corrector.remove(range)
|
|
208
214
|
end
|
|
209
215
|
|
|
210
|
-
def
|
|
211
|
-
|
|
216
|
+
def single_line_end_range(body)
|
|
217
|
+
raw = processed_source.raw_source
|
|
218
|
+
pos = body.loc.end.begin_pos
|
|
219
|
+
pos -= 1 while raw[pos - 1] == ' '
|
|
220
|
+
pos -= 1 if raw[pos - 1] == ';'
|
|
221
|
+
range_between(pos, body.loc.end.end_pos)
|
|
222
|
+
end
|
|
212
223
|
|
|
213
|
-
|
|
214
|
-
|
|
224
|
+
def multiline_end_range(body)
|
|
225
|
+
remove_begin_pos = body.loc.end.begin_pos - leading_spaces(body).size
|
|
226
|
+
adjustment = processed_source.raw_source[remove_begin_pos] == ';' ? 0 : 1
|
|
227
|
+
range_between(remove_begin_pos, body.loc.end.end_pos + adjustment)
|
|
228
|
+
end
|
|
215
229
|
|
|
216
|
-
|
|
217
|
-
|
|
230
|
+
def unindent(corrector, node)
|
|
231
|
+
column_delta = unindent_column_delta(node)
|
|
232
|
+
return unless column_delta&.negative?
|
|
233
|
+
|
|
234
|
+
range = unindentable_range(node.body)
|
|
235
|
+
return unless range
|
|
218
236
|
|
|
219
237
|
AlignmentCorrector.correct(
|
|
220
|
-
corrector, processed_source,
|
|
238
|
+
corrector, processed_source, range, column_delta, tab_indentation: true
|
|
221
239
|
)
|
|
222
240
|
end
|
|
223
241
|
|
|
242
|
+
def unindent_column_delta(node)
|
|
243
|
+
body = node.body.children.last
|
|
244
|
+
return unless body
|
|
245
|
+
|
|
246
|
+
node_indentation = spaces_size(leading_spaces(node))
|
|
247
|
+
body_indentation = spaces_size(leading_spaces(body))
|
|
248
|
+
|
|
249
|
+
node_indentation + configured_indentation_width - body_indentation
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def unindentable_range(body)
|
|
253
|
+
first_line = body.loc.name.line + 1
|
|
254
|
+
last_line = body.loc.end.line - 1
|
|
255
|
+
return if first_line > last_line
|
|
256
|
+
|
|
257
|
+
buffer = processed_source.buffer
|
|
258
|
+
range_between(buffer.line_range(first_line).begin_pos,
|
|
259
|
+
buffer.line_range(last_line).end_pos)
|
|
260
|
+
end
|
|
261
|
+
|
|
224
262
|
def leading_spaces(node)
|
|
225
263
|
node.source_range.source_line[/\A\s*/]
|
|
226
264
|
end
|
|
@@ -72,6 +72,7 @@ module RuboCop
|
|
|
72
72
|
return unless def_self_style?
|
|
73
73
|
return unless node.identifier.self_type?
|
|
74
74
|
return unless all_methods_public?(node)
|
|
75
|
+
return unless def_nodes(node).all? { |def_node| no_code_after?(def_node.source_range) }
|
|
75
76
|
|
|
76
77
|
add_offense(node, message: MSG_SCLASS) do |corrector|
|
|
77
78
|
autocorrect_sclass(node, corrector)
|
|
@@ -112,6 +113,13 @@ module RuboCop
|
|
|
112
113
|
end
|
|
113
114
|
end
|
|
114
115
|
|
|
116
|
+
def no_code_after?(range)
|
|
117
|
+
trailing = processed_source.lines[range.last_line - 1][range.last_column..].to_s.strip
|
|
118
|
+
trailing = trailing.sub(/\A;+\s*/, '')
|
|
119
|
+
|
|
120
|
+
trailing.empty? || trailing.start_with?('#')
|
|
121
|
+
end
|
|
122
|
+
|
|
115
123
|
def autocorrect_sclass(node, corrector)
|
|
116
124
|
rewritten_defs = []
|
|
117
125
|
|