rubocop 1.88.2 → 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 +139 -16
- 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 +81 -49
- data/lib/rubocop/config.rb +76 -5
- data/lib/rubocop/config_loader.rb +1 -2
- data/lib/rubocop/config_loader_resolver.rb +1 -2
- data/lib/rubocop/config_validator.rb +39 -3
- data/lib/rubocop/cop/autocorrect_logic.rb +8 -0
- data/lib/rubocop/cop/badge.rb +8 -0
- data/lib/rubocop/cop/base.rb +40 -6
- data/lib/rubocop/cop/bundler.rb +19 -0
- data/lib/rubocop/cop/corrector.rb +4 -4
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +55 -5
- data/lib/rubocop/cop/gemspec.rb +22 -0
- data/lib/rubocop/cop/generator/registration_injector.rb +188 -0
- data/lib/rubocop/cop/generator.rb +4 -0
- 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 +108 -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/first_array_element_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +3 -1
- data/lib/rubocop/cop/layout/leading_comment_space.rb +27 -0
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -2
- data/lib/rubocop/cop/layout/line_length.rb +84 -12
- data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -2
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +12 -2
- data/lib/rubocop/cop/layout/redundant_line_break.rb +77 -0
- 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 +31 -34
- data/lib/rubocop/cop/layout.rb +114 -0
- data/lib/rubocop/cop/lazy_loader.rb +41 -0
- data/lib/rubocop/cop/lint/ambiguous_assignment.rb +9 -7
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +71 -0
- 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 +18 -21
- data/lib/rubocop/cop/lint/constant_resolution.rb +25 -0
- data/lib/rubocop/cop/lint/cop_directive_syntax.rb +84 -8
- data/lib/rubocop/cop/lint/deprecated_reference.rb +194 -0
- data/lib/rubocop/cop/lint/duplicate_methods.rb +300 -22
- 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/inherit_exception.rb +53 -7
- data/lib/rubocop/cop/lint/interpolation_check.rb +1 -2
- data/lib/rubocop/cop/lint/literal_as_condition.rb +8 -6
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +4 -7
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +25 -12
- data/lib/rubocop/cop/lint/missing_super.rb +31 -1
- data/lib/rubocop/cop/lint/name_typo.rb +270 -0
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +15 -4
- 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 +8 -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 +38 -3
- data/lib/rubocop/cop/lint/unreachable_code.rb +1 -2
- data/lib/rubocop/cop/lint/unused_private_method.rb +234 -0
- 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/useless_ruby2_keywords.rb +2 -0
- data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +61 -7
- data/lib/rubocop/cop/lint/void.rb +18 -8
- data/lib/rubocop/cop/lint.rb +178 -0
- data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -2
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
- data/lib/rubocop/cop/metrics.rb +31 -0
- data/lib/rubocop/cop/migration/department_name.rb +1 -6
- data/lib/rubocop/cop/migration.rb +13 -0
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +23 -5
- 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/endless_method_rewriter.rb +13 -5
- data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +23 -6
- 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/project_index_help.rb +140 -0
- data/lib/rubocop/cop/mixin/range_help.rb +1 -2
- data/lib/rubocop/cop/mixin/reparsed_equivalence.rb +171 -0
- data/lib/rubocop/cop/mixin/statement_modifier.rb +46 -4
- data/lib/rubocop/cop/mixin/trailing_comma.rb +2 -4
- data/lib/rubocop/cop/mixin.rb +82 -77
- data/lib/rubocop/cop/naming/accessor_method_name.rb +24 -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/predicate_prefix.rb +33 -5
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +1 -2
- data/lib/rubocop/cop/naming/variable_number.rb +3 -1
- data/lib/rubocop/cop/naming.rb +31 -0
- data/lib/rubocop/cop/offense.rb +37 -10
- data/lib/rubocop/cop/registry.rb +180 -46
- data/lib/rubocop/cop/security.rb +19 -0
- 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/array_intersect.rb +24 -5
- 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 +79 -20
- 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 +23 -2
- data/lib/rubocop/cop/style/constant_visibility.rb +1 -2
- data/lib/rubocop/cop/style/copyright.rb +5 -1
- data/lib/rubocop/cop/style/directive_scope.rb +171 -0
- data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +76 -12
- data/lib/rubocop/cop/style/documentation.rb +47 -0
- data/lib/rubocop/cop/style/empty_case_condition.rb +1 -2
- data/lib/rubocop/cop/style/endless_method.rb +0 -10
- 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 +8 -50
- data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +1 -2
- data/lib/rubocop/cop/style/lambda.rb +4 -0
- data/lib/rubocop/cop/style/map_to_hash.rb +1 -2
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +22 -7
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +1 -2
- data/lib/rubocop/cop/style/missing_respond_to_missing.rb +30 -0
- data/lib/rubocop/cop/style/multiline_if_then.rb +7 -1
- data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -2
- data/lib/rubocop/cop/style/multiple_comparison.rb +33 -22
- data/lib/rubocop/cop/style/mutable_constant.rb +5 -0
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +1 -2
- data/lib/rubocop/cop/style/negative_array_index.rb +3 -3
- 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 +12 -2
- data/lib/rubocop/cop/style/redundant_condition.rb +2 -4
- data/lib/rubocop/cop/style/redundant_constant_base.rb +37 -1
- 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_file_extension_in_require.rb +9 -0
- data/lib/rubocop/cop/style/redundant_format.rb +14 -7
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +78 -135
- data/lib/rubocop/cop/style/redundant_parentheses.rb +65 -67
- 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 +11 -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 +21 -5
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +2 -0
- data/lib/rubocop/cop/style/static_class.rb +21 -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 +312 -0
- data/lib/rubocop/cop/team.rb +59 -6
- data/lib/rubocop/cop/util.rb +2 -4
- data/lib/rubocop/cop/variable_force/variable.rb +19 -8
- data/lib/rubocop/cops_documentation_generator.rb +4 -7
- data/lib/rubocop/directive_comment.rb +39 -3
- data/lib/rubocop/feature_loader.rb +0 -6
- 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 +89 -22
- data/lib/rubocop/lsp/runtime.rb +4 -0
- data/lib/rubocop/lsp/server.rb +4 -0
- data/lib/rubocop/lsp/stdin_runner.rb +20 -0
- 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/pending_cops_reporter.rb +1 -6
- data/lib/rubocop/plugin/configuration_integrator.rb +6 -3
- data/lib/rubocop/project_index_loader.rb +16 -0
- data/lib/rubocop/rake_task.rb +1 -2
- data/lib/rubocop/result_cache.rb +6 -4
- data/lib/rubocop/rspec/expect_offense.rb +2 -4
- data/lib/rubocop/rspec/shared_contexts.rb +16 -2
- data/lib/rubocop/runner.rb +71 -43
- data/lib/rubocop/server/cache.rb +11 -7
- 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/target_ruby.rb +1 -1
- data/lib/rubocop/todo_audit.rb +111 -0
- data/lib/rubocop/version.rb +3 -5
- data/lib/rubocop.rb +20 -626
- data/lib/ruby_lsp/rubocop/addon.rb +1 -2
- metadata +28 -5
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
class CommentConfig
|
|
5
|
+
# Handling of `disable-next` directives: computing the statement scope
|
|
6
|
+
# they apply to and tracking directives that attached to nothing.
|
|
7
|
+
# The scope is the whole statement starting on the next line bearing
|
|
8
|
+
# code. Comment-only lines between the directive and the code chain (so
|
|
9
|
+
# several directives can stack), while a blank line breaks the attachment.
|
|
10
|
+
# @api private
|
|
11
|
+
module DisableNext
|
|
12
|
+
# `disable-next` directives that suppress nothing: nothing follows
|
|
13
|
+
# them, or they sit at the end of a code line.
|
|
14
|
+
def detached_next_directives
|
|
15
|
+
cop_disabled_line_ranges # ensure the analysis that collects them ran
|
|
16
|
+
@detached_next_directives
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# The line range of the statement a `disable-next` directive on the
|
|
20
|
+
# given line scopes to (or would scope to), or `nil` when no statement
|
|
21
|
+
# is attached. A directive is only honored on a comment-only line.
|
|
22
|
+
# Stacked directives share the target, so the computation is memoized.
|
|
23
|
+
# @api private
|
|
24
|
+
def statement_scope_after(line)
|
|
25
|
+
return nil unless comment_only_line?(line)
|
|
26
|
+
|
|
27
|
+
code_line = attached_code_line(line)
|
|
28
|
+
return nil unless code_line
|
|
29
|
+
|
|
30
|
+
(@statement_bounds ||= {})[code_line] ||= statement_bounds_at(code_line)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def apply_disable_next(analyses, directive)
|
|
36
|
+
bounds = statement_scope_after(directive.line_number)
|
|
37
|
+
return @detached_next_directives << directive unless bounds
|
|
38
|
+
|
|
39
|
+
range = DirectiveRange.new(bounds.begin, bounds.end, directive)
|
|
40
|
+
directive.cop_names.each do |cop_name|
|
|
41
|
+
add_next_range(analyses, qualified_cop_name(cop_name), range)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def add_next_range(analyses, cop_name, range)
|
|
46
|
+
analysis = analyses[cop_name]
|
|
47
|
+
analyses[cop_name] = CopAnalysis.new(analysis.line_ranges + [range],
|
|
48
|
+
analysis.start_line_number, analysis.start_directive)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def attached_code_line(directive_line)
|
|
52
|
+
((directive_line + 1)..processed_source.lines.size).each do |line|
|
|
53
|
+
return line unless comment_only_line?(line)
|
|
54
|
+
return nil if processed_source[line - 1].blank?
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
nil
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def statement_bounds_at(line)
|
|
61
|
+
statement = statement_starting_at(line)
|
|
62
|
+
# A code line where no statement starts (e.g. a lone `end`) scopes
|
|
63
|
+
# the directive to that line alone.
|
|
64
|
+
return (line..line) unless statement
|
|
65
|
+
|
|
66
|
+
(line..statement_end_line(statement))
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def statement_start_line?(node, line)
|
|
70
|
+
# Synthetic nodes (e.g. parentheses-less argument lists) have no
|
|
71
|
+
# source range. `begin` nodes are sequences of statements, not
|
|
72
|
+
# statements themselves - taking one would scope the directive to
|
|
73
|
+
# everything up to the last statement of the sequence.
|
|
74
|
+
node.source_range && node.first_line == line && !node.begin_type?
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def statement_starting_at(line)
|
|
78
|
+
ast = processed_source.ast
|
|
79
|
+
return nil unless ast
|
|
80
|
+
|
|
81
|
+
ast.each_node.select { |node| statement_start_line?(node, line) }.max_by(&:last_line)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def statement_end_line(statement)
|
|
85
|
+
statement.each_node.filter_map do |node|
|
|
86
|
+
next unless node.source_range
|
|
87
|
+
|
|
88
|
+
heredoc?(node) ? node.loc.heredoc_end.line : node.last_line
|
|
89
|
+
end.max
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def heredoc?(node)
|
|
93
|
+
node.respond_to?(:heredoc?) && node.heredoc?
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
@@ -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)
|
|
@@ -55,8 +65,8 @@ module RuboCop
|
|
|
55
65
|
|
|
56
66
|
def extra_enabled_comments
|
|
57
67
|
disable_count = Hash.new(0)
|
|
58
|
-
registry.
|
|
59
|
-
disable_count[
|
|
68
|
+
registry.disabled_names(config).each do |cop_name|
|
|
69
|
+
disable_count[cop_name] += 1
|
|
60
70
|
end
|
|
61
71
|
extra_enabled_comments_with_names(extras: Hash.new { |h, k| h[k] = [] }, names: disable_count)
|
|
62
72
|
end
|
|
@@ -65,12 +75,32 @@ module RuboCop
|
|
|
65
75
|
non_comment_token_line_numbers.none?(line_number)
|
|
66
76
|
end
|
|
67
77
|
|
|
78
|
+
# The names of the cops that are opted in by an `enable` comment directive,
|
|
79
|
+
# used to mobilize cops disabled in the config on demand.
|
|
80
|
+
#
|
|
81
|
+
# @api private
|
|
82
|
+
# @return [Set<String>]
|
|
83
|
+
def opt_in_cops
|
|
84
|
+
@opt_in_cops ||= begin
|
|
85
|
+
cops = Set.new
|
|
86
|
+
each_directive do |directive|
|
|
87
|
+
next unless directive.enabled?
|
|
88
|
+
next if directive.all_cops?
|
|
89
|
+
|
|
90
|
+
cops.merge(directive.raw_cop_names)
|
|
91
|
+
end
|
|
92
|
+
cops
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
68
96
|
private
|
|
69
97
|
|
|
70
98
|
def extra_enabled_comments_with_names(extras:, names:)
|
|
71
99
|
each_directive do |directive|
|
|
72
100
|
next unless comment_only_line?(directive.line_number)
|
|
73
|
-
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?
|
|
74
104
|
|
|
75
105
|
if directive.enabled_all?
|
|
76
106
|
handle_enable_all(directive, names, extras)
|
|
@@ -82,20 +112,7 @@ module RuboCop
|
|
|
82
112
|
extras
|
|
83
113
|
end
|
|
84
114
|
|
|
85
|
-
|
|
86
|
-
@opt_in_cops ||= begin
|
|
87
|
-
cops = Set.new
|
|
88
|
-
each_directive do |directive|
|
|
89
|
-
next unless directive.enabled?
|
|
90
|
-
next if directive.all_cops?
|
|
91
|
-
|
|
92
|
-
cops.merge(directive.raw_cop_names)
|
|
93
|
-
end
|
|
94
|
-
cops
|
|
95
|
-
end
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
115
|
+
# rubocop:disable-next Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
99
116
|
def analyze
|
|
100
117
|
return {} if @no_directives
|
|
101
118
|
|
|
@@ -106,9 +123,11 @@ module RuboCop
|
|
|
106
123
|
if directive.push?
|
|
107
124
|
restore_point = analyses.transform_values(&:dup)
|
|
108
125
|
@stack.push(restore_point)
|
|
109
|
-
apply_push(analyses, resolve_push_cops(directive), directive
|
|
126
|
+
apply_push(analyses, resolve_push_cops(directive), directive)
|
|
110
127
|
elsif directive.pop?
|
|
111
128
|
pop_state(analyses, directive.line_number) if @stack.any?
|
|
129
|
+
elsif directive.disable_next?
|
|
130
|
+
apply_disable_next(analyses, directive)
|
|
112
131
|
else
|
|
113
132
|
directive.cop_names.each do |cop_name|
|
|
114
133
|
cop_name = qualified_cop_name(cop_name)
|
|
@@ -119,10 +138,11 @@ module RuboCop
|
|
|
119
138
|
|
|
120
139
|
analyses.each_with_object({}) do |element, hash|
|
|
121
140
|
cop_name, analysis = *element
|
|
141
|
+
next if prevent_directive_disabling?(cop_name)
|
|
142
|
+
|
|
122
143
|
hash[cop_name] = cop_line_ranges(analysis)
|
|
123
144
|
end
|
|
124
145
|
end
|
|
125
|
-
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
126
146
|
|
|
127
147
|
def resolve_push_cops(directive)
|
|
128
148
|
directive.push_args.transform_values do |names|
|
|
@@ -136,37 +156,41 @@ module RuboCop
|
|
|
136
156
|
cops.map { |c| qualified_cop_name(c) }
|
|
137
157
|
end
|
|
138
158
|
|
|
139
|
-
def apply_push(analyses, resolved_cops,
|
|
159
|
+
def apply_push(analyses, resolved_cops, directive)
|
|
140
160
|
resolved_cops.each do |op, cops|
|
|
141
|
-
cops.each { |cop| apply_cop_op(analyses, op, cop,
|
|
161
|
+
cops.each { |cop| apply_cop_op(analyses, op, cop, directive) }
|
|
142
162
|
end
|
|
143
163
|
end
|
|
144
164
|
|
|
145
|
-
def apply_cop_op(analyses, operation, cop,
|
|
165
|
+
def apply_cop_op(analyses, operation, cop, directive)
|
|
146
166
|
analysis = analyses[cop]
|
|
167
|
+
line = directive.line_number
|
|
147
168
|
if operation == '-' && !analysis.start_line_number
|
|
148
|
-
analyses[cop] = CopAnalysis.new(analysis.line_ranges, line)
|
|
169
|
+
analyses[cop] = CopAnalysis.new(analysis.line_ranges, line, directive)
|
|
149
170
|
elsif operation == '+' && analysis.start_line_number
|
|
150
|
-
analyses[cop] =
|
|
151
|
-
CopAnalysis.new(analysis.line_ranges + [analysis.start_line_number..line], nil)
|
|
171
|
+
analyses[cop] = CopAnalysis.new(analysis.close(line), nil)
|
|
152
172
|
end
|
|
153
173
|
end
|
|
154
174
|
|
|
155
175
|
def pop_state(analyses, line)
|
|
156
176
|
restore_point = @stack.pop
|
|
157
177
|
(restore_point.keys | analyses.keys).each do |cop|
|
|
158
|
-
|
|
159
|
-
new_range = current.start_line_number ? [current.start_line_number..(line - 1)] : []
|
|
160
|
-
new_start = restore_point[cop]&.start_line_number ? line : nil
|
|
161
|
-
analyses[cop] = CopAnalysis.new(current.line_ranges + new_range, new_start)
|
|
178
|
+
analyses[cop] = popped_analysis(analyses[cop], restore_point[cop], line)
|
|
162
179
|
end
|
|
163
180
|
end
|
|
164
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
|
+
|
|
165
189
|
def inject_disabled_cops_directives(analyses)
|
|
166
|
-
registry.
|
|
167
|
-
analyses[
|
|
168
|
-
analyses[
|
|
169
|
-
DirectiveComment.new(ConfigDisabledCopDirectiveComment.new(
|
|
190
|
+
registry.disabled_names(config).each do |cop_name|
|
|
191
|
+
analyses[cop_name] = analyze_cop(
|
|
192
|
+
analyses[cop_name],
|
|
193
|
+
DirectiveComment.new(ConfigDisabledCopDirectiveComment.new(cop_name))
|
|
170
194
|
)
|
|
171
195
|
end
|
|
172
196
|
end
|
|
@@ -186,27 +210,21 @@ module RuboCop
|
|
|
186
210
|
return analysis unless directive.disabled?
|
|
187
211
|
|
|
188
212
|
line = directive.line_number
|
|
189
|
-
|
|
213
|
+
range = DirectiveRange.new(line, line, directive)
|
|
214
|
+
CopAnalysis.new(analysis.line_ranges + [range], analysis.start_line_number,
|
|
215
|
+
analysis.start_directive)
|
|
190
216
|
end
|
|
191
217
|
|
|
192
218
|
def analyze_disabled(analysis, directive)
|
|
193
|
-
|
|
194
|
-
start_line = analysis.start_line_number
|
|
195
|
-
new_ranges = start_line ? analysis.line_ranges + [start_line..line] : analysis.line_ranges
|
|
196
|
-
CopAnalysis.new(new_ranges, line)
|
|
219
|
+
CopAnalysis.new(analysis.close(directive.line_number), directive.line_number, directive)
|
|
197
220
|
end
|
|
198
221
|
|
|
199
222
|
def analyze_rest(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, nil)
|
|
223
|
+
CopAnalysis.new(analysis.close(directive.line_number), nil)
|
|
204
224
|
end
|
|
205
225
|
|
|
206
226
|
def cop_line_ranges(analysis)
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
analysis.line_ranges + [(analysis.start_line_number..Float::INFINITY)]
|
|
227
|
+
analysis.close(Float::INFINITY)
|
|
210
228
|
end
|
|
211
229
|
|
|
212
230
|
def each_directive
|
|
@@ -219,7 +237,21 @@ module RuboCop
|
|
|
219
237
|
end
|
|
220
238
|
|
|
221
239
|
def qualified_cop_name(cop_name)
|
|
222
|
-
|
|
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)
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
# `Style/DisableCopsWithinSourceCodeDirective` cannot be disabled via
|
|
249
|
+
# directive comments when it is explicitly enabled with `Enabled: true`.
|
|
250
|
+
# This prevents users from bypassing the cop by writing a disable
|
|
251
|
+
# directive that targets this cop itself.
|
|
252
|
+
def prevent_directive_disabling?(cop_name)
|
|
253
|
+
cop_name == DirectiveComment::STYLE_DISABLE_COPS_DIRECTIVE_COP &&
|
|
254
|
+
config.dig(cop_name, 'Enabled') == true
|
|
223
255
|
end
|
|
224
256
|
|
|
225
257
|
def non_comment_token_line_numbers
|
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
|
|
@@ -209,6 +212,20 @@ module RuboCop
|
|
|
209
212
|
for_all_cops['NewCops'] == 'enable'
|
|
210
213
|
end
|
|
211
214
|
|
|
215
|
+
# Whether the given pending cop should be enabled, based on the `NewCops` setting of
|
|
216
|
+
# its department (if any) or of `AllCops`. A department may set `NewCops` to `enable`,
|
|
217
|
+
# `disable`, `pending`, or a version, in which case pending cops added in that version
|
|
218
|
+
# or earlier are enabled.
|
|
219
|
+
def enabled_new_cop?(qualified_cop_name)
|
|
220
|
+
setting = new_cops_setting_for(qualified_cop_name)
|
|
221
|
+
|
|
222
|
+
case setting.to_s
|
|
223
|
+
when 'enable' then true
|
|
224
|
+
when '', 'pending', 'disable' then false
|
|
225
|
+
else new_cops_version_covers?(setting, qualified_cop_name)
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
|
|
212
229
|
def active_support_extensions_enabled?
|
|
213
230
|
for_all_cops['ActiveSupportExtensionsEnabled']
|
|
214
231
|
end
|
|
@@ -326,6 +343,7 @@ module RuboCop
|
|
|
326
343
|
|
|
327
344
|
cop_metadata = self[qualified_cop_name]
|
|
328
345
|
next unless cop_metadata['Enabled'] == 'pending'
|
|
346
|
+
next if new_cops_covered?(qualified_cop_name)
|
|
329
347
|
|
|
330
348
|
pending_cops << CopConfig.new(qualified_cop_name, cop_metadata)
|
|
331
349
|
end
|
|
@@ -337,6 +355,14 @@ module RuboCop
|
|
|
337
355
|
@gem_versions_in_target ||= read_gem_versions_from_target_lockfile
|
|
338
356
|
end
|
|
339
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
|
+
|
|
340
366
|
def inspect # :nodoc:
|
|
341
367
|
"#<#{self.class.name}:#{object_id} @loaded_path=#{loaded_path}>"
|
|
342
368
|
end
|
|
@@ -381,6 +407,14 @@ module RuboCop
|
|
|
381
407
|
Lockfile.new(lockfile_path).gem_versions
|
|
382
408
|
end
|
|
383
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
|
+
|
|
384
418
|
def enable_cop?(qualified_cop_name, cop_options)
|
|
385
419
|
# If the cop is explicitly enabled or `Lint/Syntax`, the other checks can be skipped.
|
|
386
420
|
return true if cop_options['Enabled'] == true || qualified_cop_name == 'Lint/Syntax'
|
|
@@ -399,6 +433,43 @@ module RuboCop
|
|
|
399
433
|
|
|
400
434
|
self[cop_department.join('/')]
|
|
401
435
|
end
|
|
436
|
+
|
|
437
|
+
# The effective `NewCops` setting for the given cop: the department-level
|
|
438
|
+
# setting if present, otherwise the `AllCops` setting.
|
|
439
|
+
def new_cops_setting_for(qualified_cop_name)
|
|
440
|
+
department = department_of(qualified_cop_name)
|
|
441
|
+
setting = department['NewCops'] if department
|
|
442
|
+
|
|
443
|
+
setting || for_all_cops['NewCops']
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
# Whether the cop's pending status is resolved by a `NewCops` setting,
|
|
447
|
+
# so that it should not appear in the pending cops warning.
|
|
448
|
+
# Unlike `enabled_new_cop?`, `disable` counts as covered.
|
|
449
|
+
def new_cops_covered?(qualified_cop_name)
|
|
450
|
+
setting = new_cops_setting_for(qualified_cop_name)
|
|
451
|
+
|
|
452
|
+
case setting.to_s
|
|
453
|
+
when 'enable', 'disable' then true
|
|
454
|
+
when '', 'pending' then false
|
|
455
|
+
else new_cops_version_covers?(setting, qualified_cop_name)
|
|
456
|
+
end
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
def new_cops_version_covers?(new_cops_version, qualified_cop_name)
|
|
460
|
+
cop_metadata = self[qualified_cop_name]
|
|
461
|
+
version_added = comparable_version(cop_metadata['VersionAdded']) if cop_metadata
|
|
462
|
+
pinned_version = comparable_version(new_cops_version)
|
|
463
|
+
return false if version_added.nil? || pinned_version.nil?
|
|
464
|
+
|
|
465
|
+
version_added <= pinned_version
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
# Returns a `Gem::Version` for values like `'1.19'` or `1.19`, and `nil`
|
|
469
|
+
# for non-version values like `'N/A'` or `'<<next>>'`.
|
|
470
|
+
def comparable_version(value)
|
|
471
|
+
value = value.to_s
|
|
472
|
+
Gem::Version.new(value) if value.match?(/\A\d/) && Gem::Version.correct?(value)
|
|
473
|
+
end
|
|
402
474
|
end
|
|
403
475
|
end
|
|
404
|
-
# 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
|
|
|
@@ -16,6 +16,8 @@ module RuboCop
|
|
|
16
16
|
Reference References Safe SafeAutoCorrect].freeze
|
|
17
17
|
# @api private
|
|
18
18
|
NEW_COPS_VALUES = %w[pending disable enable].freeze
|
|
19
|
+
# @api private
|
|
20
|
+
NEW_COPS_VERSION_PATTERN = /\A\d+(\.\d+)*\z/.freeze
|
|
19
21
|
|
|
20
22
|
# @api private
|
|
21
23
|
CONFIG_CHECK_KEYS = %w[Enabled Safe SafeAutoCorrect AutoCorrect References].to_set.freeze
|
|
@@ -164,16 +166,48 @@ module RuboCop
|
|
|
164
166
|
end
|
|
165
167
|
|
|
166
168
|
def validate_new_cops_parameter
|
|
169
|
+
validate_all_cops_new_cops_parameter
|
|
170
|
+
validate_department_new_cops_parameters
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def validate_all_cops_new_cops_parameter
|
|
167
174
|
new_cop_parameter = @config.for_all_cops['NewCops']
|
|
168
175
|
return if new_cop_parameter.nil? || NEW_COPS_VALUES.include?(new_cop_parameter)
|
|
169
176
|
|
|
170
|
-
message = "invalid #{new_cop_parameter} for `NewCops` found in" \
|
|
177
|
+
message = "invalid #{new_cop_parameter} for `NewCops` found in " \
|
|
171
178
|
"#{smart_loaded_path}\n" \
|
|
172
179
|
"Valid choices are: #{NEW_COPS_VALUES.join(', ')}"
|
|
173
180
|
|
|
174
181
|
raise ValidationError, message
|
|
175
182
|
end
|
|
176
183
|
|
|
184
|
+
def validate_department_new_cops_parameters
|
|
185
|
+
@config.each do |name, section|
|
|
186
|
+
value = new_cops_value_for_department(name, section)
|
|
187
|
+
next if value.nil? || NEW_COPS_VALUES.include?(value) || new_cops_version_value?(value)
|
|
188
|
+
|
|
189
|
+
raise ValidationError,
|
|
190
|
+
"invalid #{value} for `NewCops` found in #{smart_loaded_path}\n" \
|
|
191
|
+
"Valid choices for a department are: #{NEW_COPS_VALUES.join(', ')}, " \
|
|
192
|
+
"or a version string like '1.50'"
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def new_cops_value_for_department(name, section)
|
|
197
|
+
return nil if name == 'AllCops' || !section.is_a?(Hash)
|
|
198
|
+
return nil unless Cop::Registry.global.department?(name)
|
|
199
|
+
|
|
200
|
+
section['NewCops']
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def new_cops_version_value?(value)
|
|
204
|
+
case value
|
|
205
|
+
when Float, Integer then true
|
|
206
|
+
when String then NEW_COPS_VERSION_PATTERN.match?(value)
|
|
207
|
+
else false
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
177
211
|
def validate_parameter_shape(valid_cop_names)
|
|
178
212
|
valid_cop_names.each do |name|
|
|
179
213
|
if @config[name].nil?
|
|
@@ -207,6 +241,9 @@ module RuboCop
|
|
|
207
241
|
|
|
208
242
|
@config[cop_name].each_key do |param|
|
|
209
243
|
next if COMMON_PARAMS.include?(param) || default_config.key?(param)
|
|
244
|
+
# Departments shipped as top-level sections in an extension's default configuration accept
|
|
245
|
+
# `NewCops`, like any other department.
|
|
246
|
+
next if param == 'NewCops' && Cop::Registry.global.department?(cop_name)
|
|
210
247
|
|
|
211
248
|
supported_params = default_config.keys - INTERNAL_PARAMS
|
|
212
249
|
|
|
@@ -287,5 +324,4 @@ module RuboCop
|
|
|
287
324
|
"is supposed to be #{supposed_values} and #{Rainbow(value).yellow} is not."
|
|
288
325
|
end
|
|
289
326
|
end
|
|
290
|
-
# rubocop:enable Metrics/ClassLength
|
|
291
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/badge.rb
CHANGED
|
@@ -52,6 +52,14 @@ module RuboCop
|
|
|
52
52
|
cop_name == other.cop_name && (!qualified? || department == other.department)
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
+
# Returns true if the badge's qualified name or the badge's department
|
|
56
|
+
# matches any of the given names.
|
|
57
|
+
def match_name?(given_names)
|
|
58
|
+
return false unless given_names
|
|
59
|
+
|
|
60
|
+
given_names.include?(to_s) || given_names.include?(department_name)
|
|
61
|
+
end
|
|
62
|
+
|
|
55
63
|
def to_s
|
|
56
64
|
@to_s ||= qualified? ? "#{department}/#{cop_name}" : cop_name
|
|
57
65
|
end
|