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
|
@@ -149,11 +149,7 @@ module RuboCop
|
|
|
149
149
|
def adjust_str(part)
|
|
150
150
|
case part.type
|
|
151
151
|
when :str
|
|
152
|
-
|
|
153
|
-
part.value.gsub(/(\\|"|#\{|#@|#\$)/, '\\\\\&')
|
|
154
|
-
else
|
|
155
|
-
part.value.inspect[1..-2]
|
|
156
|
-
end
|
|
152
|
+
adjust_str_literal(part)
|
|
157
153
|
when :dstr, :begin
|
|
158
154
|
part.children.map do |child|
|
|
159
155
|
adjust_str(child)
|
|
@@ -163,6 +159,19 @@ module RuboCop
|
|
|
163
159
|
end
|
|
164
160
|
end
|
|
165
161
|
|
|
162
|
+
def adjust_str_literal(part)
|
|
163
|
+
if single_quoted?(part)
|
|
164
|
+
part.value.gsub(/(\\|"|#\{|#@|#\$)/, '\\\\\&')
|
|
165
|
+
elsif double_quoted?(part)
|
|
166
|
+
# Reuse the source as written - rebuilding it from the value via
|
|
167
|
+
# `inspect` would rewrite the author's escape notation
|
|
168
|
+
# (e.g. `\x0a` into `\n`).
|
|
169
|
+
part.source[1..-2]
|
|
170
|
+
else
|
|
171
|
+
part.value.inspect[1..-2]
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
166
175
|
def handle_quotes(parts)
|
|
167
176
|
parts.map do |part|
|
|
168
177
|
part == '"' ? '\"' : part
|
|
@@ -173,6 +182,10 @@ module RuboCop
|
|
|
173
182
|
str_node.source.start_with?("'")
|
|
174
183
|
end
|
|
175
184
|
|
|
185
|
+
def double_quoted?(str_node)
|
|
186
|
+
str_node.source.start_with?('"')
|
|
187
|
+
end
|
|
188
|
+
|
|
176
189
|
def mode
|
|
177
190
|
cop_config['Mode'].to_sym
|
|
178
191
|
end
|
|
@@ -103,7 +103,7 @@ module RuboCop
|
|
|
103
103
|
end
|
|
104
104
|
end
|
|
105
105
|
|
|
106
|
-
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
106
|
+
# rubocop:disable-next Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
107
107
|
def arguments_identical?(def_node, super_node, def_args, super_args)
|
|
108
108
|
return false if argument_list_size_differs?(def_args, super_args, super_node)
|
|
109
109
|
|
|
@@ -120,7 +120,6 @@ module RuboCop
|
|
|
120
120
|
|
|
121
121
|
true
|
|
122
122
|
end
|
|
123
|
-
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
124
123
|
|
|
125
124
|
def argument_list_size_differs?(def_args, super_args, super_node)
|
|
126
125
|
# If the def node has a block argument and the super node has an explicit block,
|
|
@@ -167,7 +167,7 @@ module RuboCop
|
|
|
167
167
|
[Layout::SpaceBeforeBlockBraces]
|
|
168
168
|
end
|
|
169
169
|
|
|
170
|
-
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
170
|
+
# rubocop:disable-next Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
171
171
|
def on_block(node)
|
|
172
172
|
symbol_proc?(node) do |dispatch_node, arguments_node, method_name|
|
|
173
173
|
if active_support_extensions_enabled?
|
|
@@ -184,7 +184,6 @@ module RuboCop
|
|
|
184
184
|
register_offense(node, method_name, dispatch_node.method_name)
|
|
185
185
|
end
|
|
186
186
|
end
|
|
187
|
-
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
188
187
|
alias on_numblock on_block
|
|
189
188
|
alias on_itblock on_block
|
|
190
189
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Style
|
|
6
|
+
# Checks for `Time.new` without arguments, which is an implicit way
|
|
7
|
+
# to retrieve the current system time. Prefer the more explicit `Time.now`.
|
|
8
|
+
#
|
|
9
|
+
# @example
|
|
10
|
+
# # bad
|
|
11
|
+
# Time.new
|
|
12
|
+
#
|
|
13
|
+
# # good
|
|
14
|
+
# Time.now
|
|
15
|
+
#
|
|
16
|
+
# # good - `Time.new` with arguments constructs a specific time
|
|
17
|
+
# Time.new(2026, 8, 19)
|
|
18
|
+
#
|
|
19
|
+
class TimeNow < Base
|
|
20
|
+
extend AutoCorrector
|
|
21
|
+
|
|
22
|
+
MSG = 'Prefer `Time.now` over `Time.new` to retrieve the current time.'
|
|
23
|
+
RESTRICT_ON_SEND = %i[new].freeze
|
|
24
|
+
|
|
25
|
+
# @!method time_new?(node)
|
|
26
|
+
def_node_matcher :time_new?, <<~PATTERN
|
|
27
|
+
(call (const {nil? cbase} :Time) :new)
|
|
28
|
+
PATTERN
|
|
29
|
+
|
|
30
|
+
def on_send(node)
|
|
31
|
+
return unless time_new?(node)
|
|
32
|
+
|
|
33
|
+
add_offense(node) do |corrector|
|
|
34
|
+
corrector.replace(node.loc.selector.join(node.source_range.end), 'now')
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
alias on_csend on_send
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -122,7 +122,7 @@ module RuboCop
|
|
|
122
122
|
node.comparison_method? && !noncommutative_operator?(node)
|
|
123
123
|
end
|
|
124
124
|
|
|
125
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
|
125
|
+
# rubocop:disable-next Metrics/CyclomaticComplexity
|
|
126
126
|
def valid_yoda?(node)
|
|
127
127
|
return true unless (rhs = node.first_argument)
|
|
128
128
|
|
|
@@ -133,7 +133,6 @@ module RuboCop
|
|
|
133
133
|
|
|
134
134
|
enforce_yoda? ? constant_portion?(lhs) : constant_portion?(rhs)
|
|
135
135
|
end
|
|
136
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|
|
137
136
|
|
|
138
137
|
def message(node)
|
|
139
138
|
format(MSG, source: node.source)
|
data/lib/rubocop/cop/style.rb
CHANGED
|
@@ -58,6 +58,7 @@ module RuboCop
|
|
|
58
58
|
register_cop :DigChain, "#{__dir__}/style/dig_chain"
|
|
59
59
|
register_cop :Dir, "#{__dir__}/style/dir"
|
|
60
60
|
register_cop :DirEmpty, "#{__dir__}/style/dir_empty"
|
|
61
|
+
register_cop :DirectiveScope, "#{__dir__}/style/directive_scope"
|
|
61
62
|
register_cop :DisableCopsWithinSourceCodeDirective, "#{__dir__}/style/disable_cops_within_source_code_directive"
|
|
62
63
|
register_cop :DocumentationMethod, "#{__dir__}/style/documentation_method"
|
|
63
64
|
register_cop :Documentation, "#{__dir__}/style/documentation"
|
|
@@ -282,6 +283,7 @@ module RuboCop
|
|
|
282
283
|
register_cop :SymbolProc, "#{__dir__}/style/symbol_proc"
|
|
283
284
|
register_cop :TallyMethod, "#{__dir__}/style/tally_method"
|
|
284
285
|
register_cop :TernaryParentheses, "#{__dir__}/style/ternary_parentheses"
|
|
286
|
+
register_cop :TimeNow, "#{__dir__}/style/time_now"
|
|
285
287
|
register_cop :TopLevelMethodDefinition, "#{__dir__}/style/top_level_method_definition"
|
|
286
288
|
register_cop :TrailingBodyOnClass, "#{__dir__}/style/trailing_body_on_class"
|
|
287
289
|
register_cop :TrailingBodyOnMethodDefinition, "#{__dir__}/style/trailing_body_on_method_definition"
|
data/lib/rubocop/cop/team.rb
CHANGED
|
@@ -9,7 +9,7 @@ module RuboCop
|
|
|
9
9
|
# For performance reasons, Team will first dispatch cops & forces in two groups,
|
|
10
10
|
# first the ones needed for autocorrection (if any), then the rest
|
|
11
11
|
# (unless autocorrections happened).
|
|
12
|
-
# rubocop:disable Metrics/ClassLength
|
|
12
|
+
# rubocop:disable-next Metrics/ClassLength
|
|
13
13
|
class Team
|
|
14
14
|
InvestigationResult = Struct.new(:report, :corrector)
|
|
15
15
|
private_constant :InvestigationResult
|
|
@@ -211,7 +211,7 @@ module RuboCop
|
|
|
211
211
|
# run the other cops when no corrections are left
|
|
212
212
|
on_duty = roundup_relevant_cops(processed_source)
|
|
213
213
|
|
|
214
|
-
autocorrect_cops, other_cops = on_duty
|
|
214
|
+
autocorrect_cops, other_cops = partition_by_correcting(on_duty)
|
|
215
215
|
report = investigate_partial(autocorrect_cops, processed_source,
|
|
216
216
|
offset: offset, original: original)
|
|
217
217
|
|
|
@@ -251,6 +251,15 @@ module RuboCop
|
|
|
251
251
|
end
|
|
252
252
|
|
|
253
253
|
# @return [Array<cop>]
|
|
254
|
+
# A cop whose unsafe correction is skipped still inserts todo comments
|
|
255
|
+
# under `--disable-uncorrectable`, so it must run with the correcting
|
|
256
|
+
# cops - correctors of the later `other_cops` round are never applied.
|
|
257
|
+
def partition_by_correcting(cops)
|
|
258
|
+
cops.partition do |cop|
|
|
259
|
+
cop.autocorrect? || cop.skipped_unsafe_correction_with_disable_uncorrectable?
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
|
|
254
263
|
def roundup_relevant_cops(processed_source)
|
|
255
264
|
(cops + opted_in_standby_cops(processed_source)).select do |cop|
|
|
256
265
|
next false if cop.excluded_file?(processed_source.file_path)
|
|
@@ -395,6 +404,5 @@ module RuboCop
|
|
|
395
404
|
end
|
|
396
405
|
end
|
|
397
406
|
end
|
|
398
|
-
# rubocop:enable Metrics/ClassLength
|
|
399
407
|
end
|
|
400
408
|
end
|
data/lib/rubocop/cop/util.rb
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
# This module contains a collection of useful utility methods.
|
|
6
|
-
# rubocop:disable Metrics/ModuleLength
|
|
6
|
+
# rubocop:disable-next Metrics/ModuleLength
|
|
7
7
|
module Util
|
|
8
8
|
include PathUtil
|
|
9
9
|
|
|
@@ -35,7 +35,7 @@ module RuboCop
|
|
|
35
35
|
node.loc_is?(:end, ')')
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
-
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
38
|
+
# rubocop:disable-next Metrics/AbcSize, Metrics/MethodLength
|
|
39
39
|
def add_parentheses(node, corrector)
|
|
40
40
|
if node.args_type?
|
|
41
41
|
arguments_range = node.source_range
|
|
@@ -55,7 +55,6 @@ module RuboCop
|
|
|
55
55
|
corrector.insert_after(args_end(node), ')')
|
|
56
56
|
end
|
|
57
57
|
end
|
|
58
|
-
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
|
59
58
|
|
|
60
59
|
def any_descendant?(node, *types)
|
|
61
60
|
if block_given?
|
|
@@ -210,6 +209,5 @@ module RuboCop
|
|
|
210
209
|
source == target || (source.is_a?(Array) && source.include?(target))
|
|
211
210
|
end
|
|
212
211
|
end
|
|
213
|
-
# rubocop:enable Metrics/ModuleLength
|
|
214
212
|
end
|
|
215
213
|
end
|
|
@@ -47,7 +47,7 @@ module RuboCop
|
|
|
47
47
|
!@references.empty?
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
-
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
50
|
+
# rubocop:disable-next Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
51
51
|
def reference!(node)
|
|
52
52
|
reference = Reference.new(node, @scope)
|
|
53
53
|
@references << reference
|
|
@@ -72,7 +72,6 @@ module RuboCop
|
|
|
72
72
|
end
|
|
73
73
|
end
|
|
74
74
|
end
|
|
75
|
-
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
76
75
|
|
|
77
76
|
def in_modifier_conditional?(assignment, reference_node)
|
|
78
77
|
conditional = modifier_conditional_of(assignment.node)
|
|
@@ -137,7 +137,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
|
137
137
|
"NOTE: Requires Ruby version #{requirement}\n\n"
|
|
138
138
|
end
|
|
139
139
|
|
|
140
|
-
# rubocop:disable Metrics/MethodLength
|
|
140
|
+
# rubocop:disable-next Metrics/MethodLength
|
|
141
141
|
def properties(cop)
|
|
142
142
|
header = [
|
|
143
143
|
'Enabled by default', 'Safe', 'Supports autocorrection', 'Version Added',
|
|
@@ -160,7 +160,6 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
|
160
160
|
]]
|
|
161
161
|
"#{to_table(header, content)}\n"
|
|
162
162
|
end
|
|
163
|
-
# rubocop:enable Metrics/MethodLength
|
|
164
163
|
|
|
165
164
|
def cop_header(cop)
|
|
166
165
|
content = +"\n"
|
|
@@ -217,7 +216,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
|
217
216
|
"xref:#{filename}#allowmultilinefinalelement[AllowMultilineFinalElement]"
|
|
218
217
|
end
|
|
219
218
|
|
|
220
|
-
# rubocop:disable Metrics/CyclomaticComplexity,Metrics/MethodLength
|
|
219
|
+
# rubocop:disable-next Metrics/CyclomaticComplexity,Metrics/MethodLength
|
|
221
220
|
def configurable_values(cop_config, name)
|
|
222
221
|
case name
|
|
223
222
|
when /^Enforced/
|
|
@@ -244,7 +243,6 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
|
244
243
|
end
|
|
245
244
|
end
|
|
246
245
|
end
|
|
247
|
-
# rubocop:enable Metrics/CyclomaticComplexity,Metrics/MethodLength
|
|
248
246
|
|
|
249
247
|
def to_table(header, content)
|
|
250
248
|
table = ['|===', "| #{header.join(' | ')}\n\n"].join("\n")
|
|
@@ -303,7 +301,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
|
303
301
|
"\ninclude::../partials/#{filename}[]\n"
|
|
304
302
|
end
|
|
305
303
|
|
|
306
|
-
# rubocop:disable Metrics/MethodLength
|
|
304
|
+
# rubocop:disable-next Metrics/MethodLength
|
|
307
305
|
def print_cops_of_department(department)
|
|
308
306
|
selected_cops = cops_of_department(department)
|
|
309
307
|
content = +<<~HEADER
|
|
@@ -323,7 +321,6 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
|
323
321
|
file.write("#{content.strip}\n")
|
|
324
322
|
end
|
|
325
323
|
end
|
|
326
|
-
# rubocop:enable Metrics/MethodLength
|
|
327
324
|
|
|
328
325
|
def print_cop_with_doc(cop) # rubocop:todo Metrics/AbcSize, Metrics/MethodLength
|
|
329
326
|
cop_config = config.for_cop(cop)
|
|
@@ -26,13 +26,17 @@ module RuboCop
|
|
|
26
26
|
# @api private
|
|
27
27
|
PUSH_POP_ARGS_PATTERN = "([+\\-]#{COP_NAME_PATTERN_NC}(?:\\s+[+\\-]#{COP_NAME_PATTERN_NC})*)"
|
|
28
28
|
# @api private
|
|
29
|
-
AVAILABLE_MODES = %w[disable enable todo push pop].freeze
|
|
29
|
+
AVAILABLE_MODES = %w[disable enable todo push pop disable-next todo-next].freeze
|
|
30
|
+
# @api private
|
|
31
|
+
# Longest first, so a `-next` mode is not matched as its prefix
|
|
32
|
+
# (`-` is a word boundary).
|
|
33
|
+
MODES_PATTERN = AVAILABLE_MODES.sort_by { |mode| -mode.length }.join('|').freeze
|
|
30
34
|
# @api private
|
|
31
35
|
DIRECTIVE_MARKER_PATTERN = '# rubocop : '
|
|
32
36
|
# @api private
|
|
33
37
|
DIRECTIVE_MARKER_REGEXP = Regexp.new(DIRECTIVE_MARKER_PATTERN.gsub(' ', '\s*'))
|
|
34
38
|
# @api private
|
|
35
|
-
DIRECTIVE_HEADER_PATTERN = "#{DIRECTIVE_MARKER_PATTERN}((?:#{
|
|
39
|
+
DIRECTIVE_HEADER_PATTERN = "#{DIRECTIVE_MARKER_PATTERN}((?:#{MODES_PATTERN}))\\b"
|
|
36
40
|
# @api private
|
|
37
41
|
DIRECTIVE_COMMENT_REGEXP = Regexp.new(
|
|
38
42
|
"#{DIRECTIVE_HEADER_PATTERN}(?:\\s+#{COPS_PATTERN}|\\s+#{PUSH_POP_ARGS_PATTERN})?"
|
|
@@ -80,6 +84,18 @@ module RuboCop
|
|
|
80
84
|
MALFORMED_DIRECTIVE_WITHOUT_COP_NAME_REGEXP.match?(comment.text)
|
|
81
85
|
end
|
|
82
86
|
|
|
87
|
+
# The text of the directive's optional `--` trailing comment, or `nil`
|
|
88
|
+
# when there is none.
|
|
89
|
+
def reason
|
|
90
|
+
return unless @match_data
|
|
91
|
+
|
|
92
|
+
tail = @match_data.post_match.lstrip
|
|
93
|
+
return unless tail.start_with?(TRAILING_COMMENT_MARKER)
|
|
94
|
+
|
|
95
|
+
reason = tail.delete_prefix(TRAILING_COMMENT_MARKER).strip
|
|
96
|
+
reason unless reason.empty?
|
|
97
|
+
end
|
|
98
|
+
|
|
83
99
|
# Checks if this directive relates to single line
|
|
84
100
|
def single_line?
|
|
85
101
|
!comment.text.start_with?(DIRECTIVE_COMMENT_REGEXP)
|
|
@@ -98,6 +114,19 @@ module RuboCop
|
|
|
98
114
|
)
|
|
99
115
|
end
|
|
100
116
|
|
|
117
|
+
# `#range` stops at the cop list, so a `--` reason sits outside it. The reason documents the
|
|
118
|
+
# directive and means nothing once the directive is gone, so removal has to cover both. Any
|
|
119
|
+
# other trailing text is an ordinary comment and is left alone.
|
|
120
|
+
def range_with_reason
|
|
121
|
+
directive_range = range
|
|
122
|
+
trailing = Parser::Source::Range.new(
|
|
123
|
+
comment.source_range.source_buffer, directive_range.end_pos, comment.source_range.end_pos
|
|
124
|
+
)
|
|
125
|
+
return directive_range unless trailing.source.lstrip.start_with?(TRAILING_COMMENT_MARKER)
|
|
126
|
+
|
|
127
|
+
directive_range.with(end_pos: comment.source_range.end_pos)
|
|
128
|
+
end
|
|
129
|
+
|
|
101
130
|
# Returns match captures to directive comment pattern
|
|
102
131
|
def match_captures
|
|
103
132
|
@match_captures ||= @match_data && begin
|
|
@@ -111,7 +140,12 @@ module RuboCop
|
|
|
111
140
|
|
|
112
141
|
# Checks if this directive disables cops
|
|
113
142
|
def disabled?
|
|
114
|
-
%w[disable todo].include?(mode)
|
|
143
|
+
%w[disable todo].include?(mode) || disable_next?
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Checks if this directive disables cops for the next statement only
|
|
147
|
+
def disable_next?
|
|
148
|
+
%w[disable-next todo-next].include?(mode)
|
|
115
149
|
end
|
|
116
150
|
|
|
117
151
|
# Checks if this directive enables cops
|
|
@@ -23,7 +23,9 @@ module RuboCop
|
|
|
23
23
|
|
|
24
24
|
def message(offense)
|
|
25
25
|
message =
|
|
26
|
-
if offense.
|
|
26
|
+
if offense.disabled?
|
|
27
|
+
"[Suppressed] #{offense.message}"
|
|
28
|
+
elsif offense.corrected_with_todo?
|
|
27
29
|
"[Todo] #{offense.message}"
|
|
28
30
|
elsif offense.corrected?
|
|
29
31
|
"[Corrected] #{offense.message}"
|
|
@@ -74,11 +74,10 @@ module RuboCop
|
|
|
74
74
|
end
|
|
75
75
|
|
|
76
76
|
# Make Kernel#binding public.
|
|
77
|
-
# rubocop:disable Lint/UselessMethodDefinition
|
|
77
|
+
# rubocop:disable-next Lint/UselessMethodDefinition
|
|
78
78
|
def binding
|
|
79
79
|
super
|
|
80
80
|
end
|
|
81
|
-
# rubocop:enable Lint/UselessMethodDefinition
|
|
82
81
|
|
|
83
82
|
def decorated_message(offense)
|
|
84
83
|
offense.message.gsub(/`(.+?)`/) { "<code>#{escape(Regexp.last_match(1))}</code>" }
|
|
@@ -144,11 +143,10 @@ module RuboCop
|
|
|
144
143
|
}.freeze
|
|
145
144
|
|
|
146
145
|
# Make Kernel#binding public.
|
|
147
|
-
# rubocop:disable Lint/UselessMethodDefinition
|
|
146
|
+
# rubocop:disable-next Lint/UselessMethodDefinition
|
|
148
147
|
def binding
|
|
149
148
|
super
|
|
150
149
|
end
|
|
151
|
-
# rubocop:enable Lint/UselessMethodDefinition
|
|
152
150
|
end
|
|
153
151
|
end
|
|
154
152
|
end
|
|
@@ -47,7 +47,7 @@ module RuboCop
|
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
def hash_for_offense(offense)
|
|
50
|
-
{
|
|
50
|
+
hash = {
|
|
51
51
|
severity: offense.severity.name,
|
|
52
52
|
message: offense.message,
|
|
53
53
|
cop_name: offense.cop_name,
|
|
@@ -55,18 +55,23 @@ module RuboCop
|
|
|
55
55
|
correctable: offense.correctable?,
|
|
56
56
|
location: hash_for_location(offense)
|
|
57
57
|
}
|
|
58
|
+
|
|
59
|
+
# Suppressed offenses appear only under `--display-suppressed`, so
|
|
60
|
+
# these keys are additive for existing consumers.
|
|
61
|
+
if offense.disabled?
|
|
62
|
+
hash[:suppressed] = true
|
|
63
|
+
hash[:justification] = offense.justification
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
hash
|
|
58
67
|
end
|
|
59
68
|
|
|
60
|
-
# TODO: Consider better solution for Offense#real_column.
|
|
61
|
-
# The minimum value of `start_column: real_column` is 1.
|
|
62
|
-
# So, the minimum value of `last_column` should be 1.
|
|
63
|
-
# And non-zero value of `last_column` should be used as is.
|
|
64
69
|
def hash_for_location(offense)
|
|
65
70
|
{
|
|
66
71
|
start_line: offense.line,
|
|
67
72
|
start_column: offense.real_column,
|
|
68
73
|
last_line: offense.last_line,
|
|
69
|
-
last_column: offense.
|
|
74
|
+
last_column: offense.real_last_column,
|
|
70
75
|
length: offense.location.length,
|
|
71
76
|
# `line` and `column` exist for compatibility.
|
|
72
77
|
# Use `start_line` and `start_column` instead.
|
|
@@ -25,21 +25,21 @@ module RuboCop
|
|
|
25
25
|
super
|
|
26
26
|
|
|
27
27
|
@test_case_elements = []
|
|
28
|
+
@config_store = nil
|
|
28
29
|
|
|
29
30
|
reset_count
|
|
30
31
|
end
|
|
31
32
|
|
|
33
|
+
def file_started(_file, options)
|
|
34
|
+
@config_store = options[:config_store]
|
|
35
|
+
end
|
|
36
|
+
|
|
32
37
|
def file_finished(file, offenses)
|
|
33
38
|
@inspected_file_count += 1
|
|
39
|
+
@offense_count += offenses.count
|
|
34
40
|
|
|
35
|
-
|
|
36
|
-
# the original rubocop-junit-formatter.
|
|
37
|
-
# https://github.com/mikian/rubocop-junit-formatter/blob/v0.1.4/lib/rubocop/formatter/junit_formatter.rb#L9
|
|
38
|
-
#
|
|
39
|
-
# In the future, it would be preferable to return only enabled cops.
|
|
40
|
-
Cop::Registry.all.each do |cop|
|
|
41
|
+
cops_for(file).each do |cop|
|
|
41
42
|
target_offenses = offenses_for_cop(offenses, cop)
|
|
42
|
-
@offense_count += target_offenses.count
|
|
43
43
|
|
|
44
44
|
next unless relevant_for_output?(options, target_offenses)
|
|
45
45
|
|
|
@@ -47,7 +47,7 @@ module RuboCop
|
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
-
# rubocop:disable Layout/LineLength,Metrics/AbcSize,Metrics/MethodLength
|
|
50
|
+
# rubocop:disable-next Layout/LineLength,Metrics/AbcSize,Metrics/MethodLength
|
|
51
51
|
def finished(_inspected_files)
|
|
52
52
|
output.puts %(<?xml version='1.0'?>)
|
|
53
53
|
output.puts %(<testsuites>)
|
|
@@ -70,10 +70,17 @@ module RuboCop
|
|
|
70
70
|
output.puts %( </testsuite>)
|
|
71
71
|
output.puts %(</testsuites>)
|
|
72
72
|
end
|
|
73
|
-
# rubocop:enable Layout/LineLength,Metrics/AbcSize,Metrics/MethodLength
|
|
74
73
|
|
|
75
74
|
private
|
|
76
75
|
|
|
76
|
+
def cops_for(file)
|
|
77
|
+
# `file_started` is not called when this formatter is used directly through the API,
|
|
78
|
+
# in which case all cops are returned for compatibility.
|
|
79
|
+
return Cop::Registry.all if @config_store.nil?
|
|
80
|
+
|
|
81
|
+
registry.enabled(@config_store.for_file(file))
|
|
82
|
+
end
|
|
83
|
+
|
|
77
84
|
def relevant_for_output?(options, target_offenses)
|
|
78
85
|
!options[:display_only_failed] || target_offenses.any?
|
|
79
86
|
end
|
|
@@ -91,6 +98,16 @@ module RuboCop
|
|
|
91
98
|
end
|
|
92
99
|
end
|
|
93
100
|
|
|
101
|
+
# Filtering by badge keeps lazy-loaded cops unloaded; `Registry#enabled` then loads only
|
|
102
|
+
# the enabled cops, the same set the runner mobilizes.
|
|
103
|
+
def registry
|
|
104
|
+
@registry ||= Cop::Registry.global.filter_by_badge(options) do |badge|
|
|
105
|
+
next false if badge.department == :Test || badge.match_name?(options[:except])
|
|
106
|
+
|
|
107
|
+
options[:only].nil? || badge.match_name?(options[:only])
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
94
111
|
def classname_attribute_value(file)
|
|
95
112
|
@classname_attribute_value_cache ||= Hash.new do |hash, key|
|
|
96
113
|
hash[key] = key.delete_suffix('.rb').gsub("#{PathUtil.pwd}/", '').tr('/', '.')
|
|
@@ -52,7 +52,7 @@ module RuboCop
|
|
|
52
52
|
report_summary(@offense_counts, @offending_files_count)
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
-
# rubocop:disable Metrics/AbcSize
|
|
55
|
+
# rubocop:disable-next Metrics/AbcSize
|
|
56
56
|
def report_summary(offense_counts, offending_files_count)
|
|
57
57
|
per_cop_counts = ordered_offense_counts(offense_counts)
|
|
58
58
|
total_count = total_offense_count(offense_counts)
|
|
@@ -68,7 +68,6 @@ module RuboCop
|
|
|
68
68
|
|
|
69
69
|
output.puts
|
|
70
70
|
end
|
|
71
|
-
# rubocop:enable Metrics/AbcSize
|
|
72
71
|
|
|
73
72
|
def ordered_offense_counts(offense_counts)
|
|
74
73
|
offense_counts.sort_by { |k, v| [-v, k] }.to_h
|
|
@@ -86,7 +86,9 @@ module RuboCop
|
|
|
86
86
|
|
|
87
87
|
def message(offense)
|
|
88
88
|
message =
|
|
89
|
-
if offense.
|
|
89
|
+
if offense.disabled?
|
|
90
|
+
magenta('[Suppressed] ')
|
|
91
|
+
elsif offense.corrected_with_todo?
|
|
90
92
|
green('[Todo] ')
|
|
91
93
|
elsif offense.corrected?
|
|
92
94
|
green('[Corrected] ')
|
|
@@ -104,7 +106,7 @@ module RuboCop
|
|
|
104
106
|
include Colorizable
|
|
105
107
|
include TextUtil
|
|
106
108
|
|
|
107
|
-
# rubocop:disable Metrics/ParameterLists
|
|
109
|
+
# rubocop:disable-next Metrics/ParameterLists
|
|
108
110
|
def initialize(
|
|
109
111
|
file_count, offense_count, correction_count, correctable_count, rainbow,
|
|
110
112
|
safe_autocorrect: false
|
|
@@ -116,7 +118,6 @@ module RuboCop
|
|
|
116
118
|
@rainbow = rainbow
|
|
117
119
|
@safe_autocorrect = safe_autocorrect
|
|
118
120
|
end
|
|
119
|
-
# rubocop:enable Metrics/ParameterLists
|
|
120
121
|
|
|
121
122
|
def summary
|
|
122
123
|
if @correction_count.positive?
|
|
@@ -32,7 +32,7 @@ module RuboCop
|
|
|
32
32
|
report_summary(@offense_counts)
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
-
# rubocop:disable Metrics/AbcSize
|
|
35
|
+
# rubocop:disable-next Metrics/AbcSize
|
|
36
36
|
def report_summary(offense_counts)
|
|
37
37
|
per_file_counts = ordered_offense_counts(offense_counts)
|
|
38
38
|
total_count = total_offense_count(offense_counts)
|
|
@@ -50,7 +50,6 @@ module RuboCop
|
|
|
50
50
|
|
|
51
51
|
output.puts
|
|
52
52
|
end
|
|
53
|
-
# rubocop:enable Metrics/AbcSize
|
|
54
53
|
|
|
55
54
|
def ordered_offense_counts(offense_counts)
|
|
56
55
|
offense_counts.sort_by { |k, v| [-v, k] }.to_h
|
data/lib/rubocop/lockfile.rb
CHANGED
|
@@ -59,6 +59,18 @@ module RuboCop
|
|
|
59
59
|
end
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
+
# Names of gems sourced from a local path, i.e. `path:` dependencies and the
|
|
63
|
+
# project's own gem when the `Gemfile` uses `gemspec`. Git sources are not
|
|
64
|
+
# included: their code lives outside the project, like a released gem's.
|
|
65
|
+
# @return [Array<String>]
|
|
66
|
+
def path_sourced_gem_names
|
|
67
|
+
return [] unless parser
|
|
68
|
+
|
|
69
|
+
parser.specs.filter_map do |spec|
|
|
70
|
+
spec.name if path_source?(spec.source)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
62
74
|
# Whether this lockfile includes the named gem, directly or indirectly.
|
|
63
75
|
# @param [String] name
|
|
64
76
|
# @return [Boolean]
|
|
@@ -68,6 +80,12 @@ module RuboCop
|
|
|
68
80
|
|
|
69
81
|
private
|
|
70
82
|
|
|
83
|
+
# `Bundler::Source::Git` is a subclass of `Bundler::Source::Path`, but a git
|
|
84
|
+
# source is a remote one.
|
|
85
|
+
def path_source?(source)
|
|
86
|
+
source.is_a?(::Bundler::Source::Path) && !source.is_a?(::Bundler::Source::Git)
|
|
87
|
+
end
|
|
88
|
+
|
|
71
89
|
# @return [Bundler::LockfileParser, nil]
|
|
72
90
|
def parser
|
|
73
91
|
return @parser if defined?(@parser)
|