rubocop 1.90.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 +241 -11
- data/config/obsoletion.yml +9 -0
- data/lib/rubocop/cached_data.rb +47 -7
- data/lib/rubocop/changed_files.rb +134 -0
- data/lib/rubocop/cli/command/cop_names.rb +57 -0
- data/lib/rubocop/cli/command/execute_runner.rb +23 -3
- 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 +11 -4
- data/lib/rubocop/comment_config/directive_range.rb +3 -1
- data/lib/rubocop/comment_config/disable_next.rb +49 -3
- data/lib/rubocop/comment_config/push_pop.rb +55 -0
- data/lib/rubocop/comment_config.rb +32 -53
- data/lib/rubocop/config.rb +10 -0
- data/lib/rubocop/config_loader.rb +18 -7
- data/lib/rubocop/config_loader_resolver.rb +79 -12
- data/lib/rubocop/config_obsoletion/cop_rule.rb +2 -1
- data/lib/rubocop/config_obsoletion/removed_cop.rb +9 -1
- data/lib/rubocop/config_obsoletion.rb +1 -1
- data/lib/rubocop/config_validator.rb +29 -3
- data/lib/rubocop/cop/autocorrect_logic.rb +10 -5
- data/lib/rubocop/cop/badge.rb +1 -1
- data/lib/rubocop/cop/base.rb +57 -24
- 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/correctors.rb +2 -2
- 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/gemspec/require_mfa.rb +1 -1
- data/lib/rubocop/cop/generator.rb +1 -1
- 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/on_send_without_on_csend.rb +1 -1
- 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/argument_alignment.rb +2 -0
- 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/comment_indentation.rb +8 -5
- data/lib/rubocop/cop/layout/def_end_alignment.rb +4 -0
- data/lib/rubocop/cop/layout/else_alignment.rb +1 -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_after_module_inclusion.rb +1 -1
- 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_array_element_indentation.rb +17 -4
- 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/first_parameter_indentation.rb +11 -0
- data/lib/rubocop/cop/layout/hash_alignment.rb +15 -10
- 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 +4 -4
- 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 +71 -19
- 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 +10 -4
- data/lib/rubocop/cop/layout/space_around_keyword.rb +10 -0
- data/lib/rubocop/cop/layout/space_around_operators.rb +5 -1
- 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/argument_mismatch.rb +14 -4
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +2 -0
- data/lib/rubocop/cop/lint/cop_directive_syntax.rb +88 -14
- data/lib/rubocop/cop/lint/duplicate_methods.rb +1 -1
- data/lib/rubocop/cop/lint/empty_block.rb +1 -1
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +3 -1
- data/lib/rubocop/cop/lint/literal_as_condition.rb +23 -2
- 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 +245 -0
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +19 -4
- data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -1
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +1 -1
- data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +17 -1
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +42 -17
- 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/lint.rb +1 -0
- 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/migration/department_name.rb +1 -1
- data/lib/rubocop/cop/mixin/alignment.rb +5 -1
- data/lib/rubocop/cop/mixin/annotation_comment.rb +1 -1
- 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 +26 -2
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +31 -3
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +1 -1
- 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 +29 -3
- 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 +4 -2
- data/lib/rubocop/cop/naming/accessor_method_name.rb +0 -16
- data/lib/rubocop/cop/naming/block_forwarding.rb +4 -1
- data/lib/rubocop/cop/naming/block_parameter_name.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 +10 -2
- data/lib/rubocop/cop/security/json_load.rb +16 -4
- data/lib/rubocop/cop/severity.rb +12 -0
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +10 -2
- 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 +6 -3
- 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 +9 -6
- 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/constant_visibility.rb +6 -2
- data/lib/rubocop/cop/style/data_inheritance.rb +14 -0
- data/lib/rubocop/cop/style/directive_scope.rb +154 -21
- data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +118 -18
- data/lib/rubocop/cop/style/documentation_method.rb +1 -9
- data/lib/rubocop/cop/style/double_negation.rb +11 -0
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
- data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
- data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
- data/lib/rubocop/cop/style/empty_literal.rb +1 -1
- data/lib/rubocop/cop/style/empty_method.rb +15 -3
- data/lib/rubocop/cop/style/endless_method.rb +91 -11
- 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/file_null.rb +2 -2
- data/lib/rubocop/cop/style/float_division.rb +28 -14
- data/lib/rubocop/cop/style/for.rb +44 -1
- data/lib/rubocop/cop/style/format_string.rb +28 -6
- data/lib/rubocop/cop/style/format_string_token.rb +1 -1
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +2 -1
- data/lib/rubocop/cop/style/guard_clause.rb +13 -1
- data/lib/rubocop/cop/style/hash_conversion.rb +28 -8
- data/lib/rubocop/cop/style/hash_lookup_method.rb +35 -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/magic_comment_format.rb +1 -1
- 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 +36 -12
- 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 +48 -8
- data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
- data/lib/rubocop/cop/style/non_nil_check.rb +18 -2
- data/lib/rubocop/cop/style/not.rb +10 -3
- data/lib/rubocop/cop/style/numeric_literal_prefix.rb +11 -1
- data/lib/rubocop/cop/style/numeric_predicate.rb +21 -5
- data/lib/rubocop/cop/style/one_line_conditional.rb +14 -3
- data/lib/rubocop/cop/style/parallel_assignment.rb +1 -1
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +6 -1
- 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 +34 -17
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +16 -1
- data/lib/rubocop/cop/style/redundant_exception.rb +15 -3
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +10 -2
- data/lib/rubocop/cop/style/redundant_freeze.rb +10 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +23 -2
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +7 -0
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +6 -5
- data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +25 -5
- 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_block_params.rb +1 -1
- data/lib/rubocop/cop/style/single_line_methods.rb +16 -4
- data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
- 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/struct_inheritance.rb +14 -0
- 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_comma_in_block_args.rb +1 -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/style.rb +0 -1
- data/lib/rubocop/cop/team.rb +10 -5
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/cop/variable_force/assignment.rb +1 -1
- data/lib/rubocop/cop/variable_force/variable.rb +14 -1
- data/lib/rubocop/cops_documentation_generator.rb +23 -2
- data/lib/rubocop/directive_comment.rb +37 -8
- data/lib/rubocop/formatter/base_formatter.rb +22 -0
- data/lib/rubocop/formatter/disabled_config_formatter.rb +19 -1
- data/lib/rubocop/formatter/formatter_set.rb +6 -1
- data/lib/rubocop/formatter/github_actions_formatter.rb +6 -5
- data/lib/rubocop/formatter/html_formatter.rb +2 -2
- data/lib/rubocop/formatter/json_formatter.rb +71 -1
- data/lib/rubocop/formatter/junit_formatter.rb +1 -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 +186 -0
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +3 -1
- data/lib/rubocop/formatter.rb +1 -0
- 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/magic_comment.rb +27 -0
- 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 +97 -4
- data/lib/rubocop/path_util.rb +1 -1
- data/lib/rubocop/plugin/configuration_integrator.rb +12 -5
- data/lib/rubocop/plugin/loader.rb +1 -1
- data/lib/rubocop/rake_task.rb +1 -1
- data/lib/rubocop/remote_config.rb +8 -5
- data/lib/rubocop/result_cache.rb +36 -18
- data/lib/rubocop/runner.rb +160 -49
- data/lib/rubocop/server/cache.rb +2 -2
- data/lib/rubocop/unified_diff.rb +257 -0
- data/lib/rubocop/util.rb +69 -0
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +9 -1
- metadata +21 -6
- data/lib/rubocop/cop/style/double_cop_disable_directive.rb +0 -46
data/config/obsoletion.yml
CHANGED
|
@@ -80,6 +80,11 @@ removed:
|
|
|
80
80
|
`Lint/BinaryOperatorWithIdenticalOperands`. Please use
|
|
81
81
|
`Lint/BinaryOperatorWithIdenticalOperands` instead
|
|
82
82
|
Style/BracesAroundHashParameters: true
|
|
83
|
+
Style/DoubleCopDisableDirective:
|
|
84
|
+
severity: warning
|
|
85
|
+
reason: >
|
|
86
|
+
it has been superseded by `Lint/CopDirectiveSyntax`. Please use
|
|
87
|
+
`Lint/CopDirectiveSyntax` instead
|
|
83
88
|
Style/MethodMissingSuper:
|
|
84
89
|
reason: >
|
|
85
90
|
it has been superseded by `Lint/MissingSuper`. Please use
|
|
@@ -149,6 +154,10 @@ changed_parameters:
|
|
|
149
154
|
parameters: IgnoreCopDirectives
|
|
150
155
|
alternative: AllowCopDirectives
|
|
151
156
|
severity: warning
|
|
157
|
+
- cops: Style/DisableCopsWithinSourceCodeDirective
|
|
158
|
+
parameters: AllowTrailingComment
|
|
159
|
+
alternative: AllowWithReason
|
|
160
|
+
severity: warning
|
|
152
161
|
- cops:
|
|
153
162
|
- Lint/BlockAlignment
|
|
154
163
|
- Layout/BlockAlignment
|
data/lib/rubocop/cached_data.rb
CHANGED
|
@@ -35,16 +35,44 @@ module RuboCop
|
|
|
35
35
|
cop_name: offense.cop_name,
|
|
36
36
|
status: status || offense.status
|
|
37
37
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
hash[:justification] = offense.justification if offense.justification
|
|
38
|
+
add_justification(hash, offense)
|
|
39
|
+
add_corrections(hash, offense)
|
|
41
40
|
hash
|
|
42
41
|
end
|
|
43
42
|
|
|
44
43
|
def message(offense)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
encode_to_utf8(offense.message)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def encode_to_utf8(value)
|
|
48
|
+
string = value.to_s
|
|
49
|
+
|
|
50
|
+
if string.encoding == ::Encoding::BINARY
|
|
51
|
+
string.dup.force_encoding(::Encoding::UTF_8).scrub
|
|
52
|
+
else
|
|
53
|
+
string.encode(::Encoding::UTF_8, invalid: :replace, undef: :replace)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Only offenses suppressed by a directive can carry one, so keep the key out of the
|
|
58
|
+
# common case rather than writing a null for every cached offense.
|
|
59
|
+
def add_justification(hash, offense)
|
|
60
|
+
return unless offense.justification
|
|
61
|
+
|
|
62
|
+
hash[:justification] = encode_to_utf8(offense.justification)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# A corrector cannot be serialized, so the edits it would make are cached
|
|
66
|
+
# separately; without this a cache hit would report no corrections.
|
|
67
|
+
def add_corrections(hash, offense)
|
|
68
|
+
return if offense.corrections.empty?
|
|
69
|
+
|
|
70
|
+
hash[:corrections] = offense.corrections.map do |correction|
|
|
71
|
+
{ begin_pos: correction.begin_pos,
|
|
72
|
+
end_pos: correction.end_pos,
|
|
73
|
+
replacement: encode_to_utf8(correction.replacement) }
|
|
74
|
+
end
|
|
75
|
+
hash[:correction_safe] = offense.correction_safe
|
|
48
76
|
end
|
|
49
77
|
|
|
50
78
|
# Restore an offense object loaded from a JSON file.
|
|
@@ -52,7 +80,19 @@ module RuboCop
|
|
|
52
80
|
offenses.map! do |o|
|
|
53
81
|
location = location_from_source_buffer(o)
|
|
54
82
|
Cop::Offense.new(o['severity'], location, o['message'], o['cop_name'], o['status'].to_sym,
|
|
55
|
-
justification: o['justification']
|
|
83
|
+
justification: o['justification'],
|
|
84
|
+
corrections: corrections_from_cache(o),
|
|
85
|
+
correction_safe: o.fetch('correction_safe', true))
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def corrections_from_cache(offense)
|
|
90
|
+
cached = offense['corrections']
|
|
91
|
+
return [] unless cached
|
|
92
|
+
|
|
93
|
+
cached.map do |correction|
|
|
94
|
+
Cop::Offense::Correction.new(correction['begin_pos'], correction['end_pos'],
|
|
95
|
+
correction['replacement']).freeze
|
|
56
96
|
end
|
|
57
97
|
end
|
|
58
98
|
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'open3'
|
|
4
|
+
|
|
5
|
+
module RuboCop
|
|
6
|
+
# Lists the files that differ from a git revision, for `--changed`.
|
|
7
|
+
#
|
|
8
|
+
# Shelling out to `git` keeps RuboCop free of a version control dependency,
|
|
9
|
+
# and means the answer is exactly what git would give on the command line.
|
|
10
|
+
#
|
|
11
|
+
# @api private
|
|
12
|
+
class ChangedFiles
|
|
13
|
+
DEFAULT_REVISION = 'HEAD'
|
|
14
|
+
FILESYSTEM_ENCODING = Encoding.find('filesystem')
|
|
15
|
+
|
|
16
|
+
# Whether git can resolve `name` to a commit in the current repository.
|
|
17
|
+
def self.revision?(name)
|
|
18
|
+
_stdout, _stderr, status =
|
|
19
|
+
Open3.capture3('git', 'rev-parse', '--verify', '--quiet', "#{name}^{commit}")
|
|
20
|
+
status.success?
|
|
21
|
+
rescue Errno::ENOENT
|
|
22
|
+
false
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def initialize(revision = nil)
|
|
26
|
+
@revision = revision || DEFAULT_REVISION
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Files that were added or modified since the revision, as absolute paths.
|
|
30
|
+
# Deleted files are left out - there is nothing left to inspect - and
|
|
31
|
+
# untracked files are included, since a file that is new to the working
|
|
32
|
+
# tree has changed as surely as one git already knows about.
|
|
33
|
+
#
|
|
34
|
+
# @return [Set<String>]
|
|
35
|
+
def paths
|
|
36
|
+
root = repository_root
|
|
37
|
+
|
|
38
|
+
(modified_paths + untracked_paths).to_set { |path| File.expand_path(path, root) }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# @return [Array<String>] the files among these that changed
|
|
42
|
+
def filter(files)
|
|
43
|
+
changed = paths
|
|
44
|
+
files.select { |file| changed.include?(file) }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
def repository_root
|
|
50
|
+
filesystem_path(git('rev-parse', '--show-toplevel').b.chomp)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def modified_paths(revision = @revision)
|
|
54
|
+
# `diff.relative` would make git report paths relative to the current
|
|
55
|
+
# directory rather than to the repository root.
|
|
56
|
+
split_paths(
|
|
57
|
+
git('-c', 'diff.relative=false', 'diff', '--name-only', '--diff-filter=d', '-z', revision)
|
|
58
|
+
)
|
|
59
|
+
rescue Error
|
|
60
|
+
raise unless revision == DEFAULT_REVISION && unborn_head?
|
|
61
|
+
|
|
62
|
+
# A repository without commits has no `HEAD` to diff against, but files
|
|
63
|
+
# can already be staged in it. Against the empty tree every one of them
|
|
64
|
+
# counts as changed, which is what the caller wants to hear rather than
|
|
65
|
+
# an error about `HEAD` not resolving.
|
|
66
|
+
modified_paths(empty_tree)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def unborn_head?
|
|
70
|
+
!self.class.revision?(DEFAULT_REVISION)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Hashed rather than hardcoded, since its id depends on the repository's
|
|
74
|
+
# object format (SHA-1 or SHA-256).
|
|
75
|
+
def empty_tree
|
|
76
|
+
git('hash-object', '-t', 'tree', '--stdin').chomp
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def untracked_paths
|
|
80
|
+
# Unlike `git diff`, `ls-files` only looks under the current directory, so
|
|
81
|
+
# the `:/` pathspec widens it to the whole repository, and `--full-name`
|
|
82
|
+
# anchors the paths to the repository root the way `git diff` does.
|
|
83
|
+
split_paths(
|
|
84
|
+
git('ls-files', '--others', '--exclude-standard', '--full-name', '-z', '--', ':/')
|
|
85
|
+
)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# The `-z` above is what makes these usable: without it git wraps any path
|
|
89
|
+
# that is not plain ASCII in quotes and octal escapes, and those files drop
|
|
90
|
+
# out of the comparison without a word.
|
|
91
|
+
def split_paths(output)
|
|
92
|
+
output.b.split("\0").reject(&:empty?).map { |path| filesystem_path(path) }
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# git hands back bytes, which Ruby tags with the encoding the process
|
|
96
|
+
# happens to have been started in - splitting those bytes as US-ASCII raises
|
|
97
|
+
# on any path that is not. They have to end up in the encoding `Dir.glob`
|
|
98
|
+
# uses, or a path with a non-ASCII character in it never matches the file
|
|
99
|
+
# list it is compared against.
|
|
100
|
+
#
|
|
101
|
+
# On POSIX those bytes are already the filesystem's own, so the encoding is
|
|
102
|
+
# simply corrected. Windows is the exception: git converts paths to UTF-8 on
|
|
103
|
+
# the way out, while Ruby reports file names in the local code page, so the
|
|
104
|
+
# two have to be reconciled.
|
|
105
|
+
def filesystem_path(path)
|
|
106
|
+
path = path.dup
|
|
107
|
+
|
|
108
|
+
return path.force_encoding(FILESYSTEM_ENCODING) unless Platform.windows?
|
|
109
|
+
|
|
110
|
+
path.force_encoding(Encoding::UTF_8).encode(FILESYSTEM_ENCODING)
|
|
111
|
+
rescue Encoding::UndefinedConversionError, Encoding::InvalidByteSequenceError
|
|
112
|
+
# A name the local code page cannot represent. Nothing good is left to do
|
|
113
|
+
# with it, and dropping it would be worse than reporting it as-is.
|
|
114
|
+
path.force_encoding(FILESYSTEM_ENCODING)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def git(*args)
|
|
118
|
+
stdout, stderr, status = Open3.capture3('git', *args)
|
|
119
|
+
|
|
120
|
+
raise Error, git_error_message(stderr) unless status.success?
|
|
121
|
+
|
|
122
|
+
stdout
|
|
123
|
+
rescue Errno::ENOENT
|
|
124
|
+
raise Error, '--changed requires git to be installed and on your PATH.'
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def git_error_message(stderr)
|
|
128
|
+
message = stderr.strip
|
|
129
|
+
message = 'git failed with no output on standard error.' if message.empty?
|
|
130
|
+
|
|
131
|
+
"--changed could not ask git which files changed: #{message}"
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
class CLI
|
|
5
|
+
module Command
|
|
6
|
+
# Shared handling for commands that take a list of cop names.
|
|
7
|
+
#
|
|
8
|
+
# Validation happens here rather than during option parsing because the
|
|
9
|
+
# registry is not complete until the configuration has been loaded, which
|
|
10
|
+
# is also why `--only` and `--except` are validated from the runner.
|
|
11
|
+
# @api private
|
|
12
|
+
module CopNames
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
# The cops among `names` that exist, so a command can report on what it
|
|
16
|
+
# understood before {#validate_cop_names!} objects to the rest.
|
|
17
|
+
def known_cop_classes(names)
|
|
18
|
+
names.filter_map { |name| cop_class_for(name) }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# @raise [IncorrectCopNameError] if any name is not a cop
|
|
22
|
+
def validate_cop_names!(names)
|
|
23
|
+
unknown = names.reject { |name| cop_class_for(name) }
|
|
24
|
+
return if unknown.empty?
|
|
25
|
+
|
|
26
|
+
raise IncorrectCopNameError, unknown.map { |name| unknown_cop_message(name) }.join("\n")
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Not memoized: the MCP server lives long enough for a plugin to register
|
|
30
|
+
# a cop after a lookup has missed it.
|
|
31
|
+
def cop_class_for(name)
|
|
32
|
+
Cop::Registry.global.find_by_cop_name(name)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def unknown_cop_message(name)
|
|
36
|
+
return department_message(name) if department?(name)
|
|
37
|
+
|
|
38
|
+
message = "Unrecognized cop: #{name}."
|
|
39
|
+
similar = NameSimilarity.find_similar_names(name, Cop::Registry.global.names)
|
|
40
|
+
return message if similar.empty?
|
|
41
|
+
|
|
42
|
+
"#{message}\nDid you mean? #{similar.join(', ')}"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def department?(name)
|
|
46
|
+
Cop::Registry.global.departments.any? { |department| department.to_s == name }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def department_message(name)
|
|
50
|
+
example = Cop::Registry.global.names.find { |cop| cop.start_with?("#{name}/") }
|
|
51
|
+
|
|
52
|
+
"#{name} is a department, not a cop. Name one of its cops, such as #{example}."
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -9,7 +9,7 @@ module RuboCop
|
|
|
9
9
|
include Formatter::TextUtil
|
|
10
10
|
|
|
11
11
|
# Combination of short and long formatter names.
|
|
12
|
-
INTEGRATION_FORMATTERS = %w[h html j json ju junit].freeze
|
|
12
|
+
INTEGRATION_FORMATTERS = %w[h html j json ju junit sa sarif].freeze
|
|
13
13
|
|
|
14
14
|
self.command_name = :execute_runner
|
|
15
15
|
|
|
@@ -28,7 +28,16 @@ module RuboCop
|
|
|
28
28
|
all_passed || @options[:auto_gen_config]
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
if @options[:diff]
|
|
32
|
+
print_diffs(runner.diffs)
|
|
33
|
+
else
|
|
34
|
+
maybe_print_corrected_source
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# A diff means autocorrectable offenses are still in the working
|
|
38
|
+
# tree, so the run has not passed even though they were "corrected"
|
|
39
|
+
# in memory.
|
|
40
|
+
all_pass_or_excluded &&= runner.diffs.empty?
|
|
32
41
|
|
|
33
42
|
merge_todo_audit_status(runner_status(runner, all_pass_or_excluded))
|
|
34
43
|
end
|
|
@@ -119,9 +128,20 @@ module RuboCop
|
|
|
119
128
|
"#{Gem.loaded_specs['rubocop'].metadata['bug_tracker_uri']}\n"
|
|
120
129
|
end
|
|
121
130
|
|
|
131
|
+
def print_diffs(diffs)
|
|
132
|
+
return if diffs.empty?
|
|
133
|
+
# Integration tools own stdout when they ask for a machine-readable
|
|
134
|
+
# format, so the diff would only corrupt their input.
|
|
135
|
+
return if INTEGRATION_FORMATTERS.include?(@options[:format])
|
|
136
|
+
|
|
137
|
+
output = @options[:stderr] ? $stderr : $stdout
|
|
138
|
+
output.puts
|
|
139
|
+
diffs.each { |diff| output.print(diff) }
|
|
140
|
+
end
|
|
141
|
+
|
|
122
142
|
def maybe_print_corrected_source
|
|
123
143
|
# Integration tools (like RubyMine) expect to have only the JSON result
|
|
124
|
-
# when specifying JSON format. Similar HTML and
|
|
144
|
+
# when specifying JSON format. Similar HTML, JUnit and SARIF are targeted as well.
|
|
125
145
|
# See: https://github.com/rubocop/rubocop/issues/8673
|
|
126
146
|
return if INTEGRATION_FORMATTERS.include?(@options[:format])
|
|
127
147
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
class CLI
|
|
5
|
+
module Command
|
|
6
|
+
# Explains what cops do, as described by {Cop::CopExplanation}.
|
|
7
|
+
# @api private
|
|
8
|
+
class Explain < Base
|
|
9
|
+
include CopNames
|
|
10
|
+
|
|
11
|
+
self.command_name = :explain
|
|
12
|
+
|
|
13
|
+
def initialize(env)
|
|
14
|
+
super
|
|
15
|
+
|
|
16
|
+
@config = @config_store.for(PathUtil.pwd)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def run
|
|
20
|
+
names = @options[:explain]
|
|
21
|
+
|
|
22
|
+
known_cop_classes(names).each_with_index do |cop_class, index|
|
|
23
|
+
puts if index.positive?
|
|
24
|
+
puts Cop::CopExplanation.new(cop_class, @config)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Checked after printing, so a typo in a list does not cost you the
|
|
28
|
+
# explanations you asked for alongside it.
|
|
29
|
+
validate_cop_names!(names)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -7,6 +7,8 @@ module RuboCop
|
|
|
7
7
|
# for the current directory.
|
|
8
8
|
# @api private
|
|
9
9
|
class ShowCops < Base
|
|
10
|
+
include CopNames
|
|
11
|
+
|
|
10
12
|
self.command_name = :show_cops
|
|
11
13
|
|
|
12
14
|
ExactMatcher = Struct.new(:pattern) do
|
|
@@ -38,6 +40,10 @@ module RuboCop
|
|
|
38
40
|
|
|
39
41
|
def run
|
|
40
42
|
print_available_cops
|
|
43
|
+
# Checked after printing, so a typo alongside good names still shows
|
|
44
|
+
# what was asked for. Wildcards are patterns, not names, so a pattern
|
|
45
|
+
# that matches nothing is not an error.
|
|
46
|
+
validate_cop_names!(@options[:show_cops].grep_v(/\*/))
|
|
41
47
|
end
|
|
42
48
|
|
|
43
49
|
private
|
|
@@ -7,6 +7,8 @@ module RuboCop
|
|
|
7
7
|
# or documentation base url by default.
|
|
8
8
|
# @api private
|
|
9
9
|
class ShowDocsUrl < Base
|
|
10
|
+
include CopNames
|
|
11
|
+
|
|
10
12
|
self.command_name = :show_docs_url
|
|
11
13
|
|
|
12
14
|
def initialize(env)
|
|
@@ -17,6 +19,9 @@ module RuboCop
|
|
|
17
19
|
|
|
18
20
|
def run
|
|
19
21
|
print_documentation_url
|
|
22
|
+
# Checked after printing, so a typo alongside good names still gives
|
|
23
|
+
# you the urls you asked for.
|
|
24
|
+
validate_cop_names!(cops_array)
|
|
20
25
|
end
|
|
21
26
|
|
|
22
27
|
private
|
|
@@ -24,10 +29,7 @@ module RuboCop
|
|
|
24
29
|
def print_documentation_url
|
|
25
30
|
puts Cop::Documentation.default_base_url if cops_array.empty?
|
|
26
31
|
|
|
27
|
-
cops_array.each do |
|
|
28
|
-
cop = Cop::Registry.global.find_by_cop_name(cop_name)
|
|
29
|
-
next unless cop
|
|
30
|
-
|
|
32
|
+
known_cop_classes(cops_array).each do |cop|
|
|
31
33
|
url = Cop::Documentation.url_for(cop, @config)
|
|
32
34
|
puts url if url
|
|
33
35
|
end
|
data/lib/rubocop/cli.rb
CHANGED
|
@@ -13,7 +13,8 @@ module RuboCop
|
|
|
13
13
|
DEFAULT_PARALLEL_OPTIONS = %i[
|
|
14
14
|
color config debug display_style_guide display_time display_only_fail_level_offenses
|
|
15
15
|
display_only_failed editor_mode except extra_details fail_level fix_layout format formatters
|
|
16
|
-
ignore_disable_comments lint only only_guide_cops out require
|
|
16
|
+
ignore_disable_comments lint max_offenses_per_cop only only_guide_cops out preview require
|
|
17
|
+
safe
|
|
17
18
|
autocorrect safe_autocorrect autocorrect_all
|
|
18
19
|
].freeze
|
|
19
20
|
|
|
@@ -183,12 +184,18 @@ module RuboCop
|
|
|
183
184
|
|
|
184
185
|
def set_options_to_config_loader
|
|
185
186
|
ConfigLoader.debug = @options[:debug]
|
|
186
|
-
ConfigLoader.disable_pending_cops = @options[:disable_pending_cops]
|
|
187
|
-
ConfigLoader.enable_pending_cops = @options[:enable_pending_cops]
|
|
188
187
|
ConfigLoader.ignore_parent_exclusion = @options[:ignore_parent_exclusion]
|
|
189
188
|
ConfigLoader.ignore_unrecognized_cops = @options[:ignore_unrecognized_cops]
|
|
189
|
+
set_cop_selection_options_to_config_loader
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# Options that decide which cops run, as opposed to how configuration is loaded.
|
|
193
|
+
def set_cop_selection_options_to_config_loader
|
|
194
|
+
ConfigLoader.disable_pending_cops = @options[:disable_pending_cops]
|
|
195
|
+
ConfigLoader.enable_pending_cops = @options[:enable_pending_cops]
|
|
190
196
|
ConfigLoader.enabled_by_default = @options[:enable_all_cops]
|
|
191
197
|
ConfigLoader.disabled_by_default = @options[:disable_all_cops]
|
|
198
|
+
ConfigLoader.preview = @options[:preview]
|
|
192
199
|
end
|
|
193
200
|
|
|
194
201
|
def set_options_to_pending_cops_reporter
|
|
@@ -204,7 +211,7 @@ module RuboCop
|
|
|
204
211
|
return unless Options::EXITING_OPTIONS.any? { |o| @options.key? o }
|
|
205
212
|
|
|
206
213
|
run_command(:version) if @options[:version] || @options[:verbose_version]
|
|
207
|
-
%i[show_cops list_enabled_cops_for show_docs_url lsp mcp].each do |name|
|
|
214
|
+
%i[show_cops list_enabled_cops_for show_docs_url explain lsp mcp].each do |name|
|
|
208
215
|
run_command(name) if @options[name]
|
|
209
216
|
end
|
|
210
217
|
raise Finished
|
|
@@ -22,8 +22,10 @@ module RuboCop
|
|
|
22
22
|
CopAnalysis = Struct.new(:line_ranges, :start_line_number, :start_directive) do
|
|
23
23
|
# The open range (if any) closed at the given line, appended to the
|
|
24
24
|
# accumulated ranges, each remembering the directive that opened it.
|
|
25
|
+
# Closing above the opening line (e.g. a `pop` directly below a
|
|
26
|
+
# statement whose disable a `next +Cop` suspended) yields no range.
|
|
25
27
|
def close(line)
|
|
26
|
-
return line_ranges
|
|
28
|
+
return line_ranges if !start_line_number || line < start_line_number
|
|
27
29
|
|
|
28
30
|
line_ranges + [DirectiveRange.new(start_line_number, line, start_directive)]
|
|
29
31
|
end
|
|
@@ -2,14 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
class CommentConfig
|
|
5
|
-
# Handling of `disable-next`
|
|
6
|
-
# they apply to and tracking
|
|
5
|
+
# Handling of next-statement directives (`disable-next`, `todo-next` and
|
|
6
|
+
# `next`): computing the statement scope they apply to and tracking
|
|
7
|
+
# directives that attached to nothing.
|
|
7
8
|
# The scope is the whole statement starting on the next line bearing
|
|
8
9
|
# code. Comment-only lines between the directive and the code chain (so
|
|
9
10
|
# several directives can stack), while a blank line breaks the attachment.
|
|
10
11
|
# @api private
|
|
11
12
|
module DisableNext
|
|
12
|
-
#
|
|
13
|
+
# Next-statement directives that affect nothing: nothing follows
|
|
13
14
|
# them, or they sit at the end of a code line.
|
|
14
15
|
def detached_next_directives
|
|
15
16
|
cop_disabled_line_ranges # ensure the analysis that collects them ran
|
|
@@ -48,6 +49,51 @@ module RuboCop
|
|
|
48
49
|
analysis.start_line_number, analysis.start_directive)
|
|
49
50
|
end
|
|
50
51
|
|
|
52
|
+
# Applies a `next` directive: `-` cops are disabled for the attached
|
|
53
|
+
# statement (exactly like `disable-next`), `+` cops have any open
|
|
54
|
+
# disable suspended for it. The `resolved_cops` come pre-expanded and
|
|
55
|
+
# qualified, mirroring `push`.
|
|
56
|
+
def apply_next_directive(analyses, resolved_cops, directive)
|
|
57
|
+
bounds = statement_scope_after(directive.line_number)
|
|
58
|
+
return @detached_next_directives << directive unless bounds
|
|
59
|
+
|
|
60
|
+
range = DirectiveRange.new(bounds.begin, bounds.end, directive)
|
|
61
|
+
resolved_cops.each do |op, cops|
|
|
62
|
+
cops.each do |cop|
|
|
63
|
+
if op == '-'
|
|
64
|
+
add_next_range(analyses, cop, range)
|
|
65
|
+
else
|
|
66
|
+
suspend_disable(analyses, cop, bounds)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Applies an `enable-next` directive: every listed cop (departments
|
|
73
|
+
# and `all` included) has any open disable suspended for the attached
|
|
74
|
+
# statement.
|
|
75
|
+
def apply_enable_next(analyses, directive)
|
|
76
|
+
bounds = statement_scope_after(directive.line_number)
|
|
77
|
+
return @detached_next_directives << directive unless bounds
|
|
78
|
+
|
|
79
|
+
directive.cop_names.each do |cop_name|
|
|
80
|
+
suspend_disable(analyses, qualified_cop_name(cop_name), bounds)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Punches a statement-sized hole into the currently open disable of the
|
|
85
|
+
# cop (whether opened by a directive or injected for a config-disabled
|
|
86
|
+
# cop): the open range closes just above the statement and reopens
|
|
87
|
+
# right below it, still attributed to its opening directive. Aligned
|
|
88
|
+
# with `push`, a `+` for a cop that is not disabled is a no-op.
|
|
89
|
+
def suspend_disable(analyses, cop, bounds)
|
|
90
|
+
analysis = analyses[cop]
|
|
91
|
+
return unless analysis.start_line_number
|
|
92
|
+
|
|
93
|
+
analyses[cop] = CopAnalysis.new(analysis.close(bounds.begin - 1),
|
|
94
|
+
bounds.end + 1, analysis.start_directive)
|
|
95
|
+
end
|
|
96
|
+
|
|
51
97
|
def attached_code_line(directive_line)
|
|
52
98
|
((directive_line + 1)..processed_source.lines.size).each do |line|
|
|
53
99
|
return line unless comment_only_line?(line)
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
class CommentConfig
|
|
5
|
+
# Handling of `push`/`pop` directives and their signed cop arguments:
|
|
6
|
+
# saving and restoring the per-cop analysis state, and resolving the
|
|
7
|
+
# `+`/`-` argument lists (shared with the `next` directive).
|
|
8
|
+
# @api private
|
|
9
|
+
module PushPop
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def resolve_push_cops(directive)
|
|
13
|
+
directive.push_args.transform_values do |names|
|
|
14
|
+
names.flat_map { |name| expand_cop_name(name) }
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def expand_cop_name(name)
|
|
19
|
+
registry = Cop::Registry.global
|
|
20
|
+
cops = registry.department?(name) ? registry.names_for_department(name) : [name]
|
|
21
|
+
cops.map { |c| qualified_cop_name(c) }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def apply_push(analyses, resolved_cops, directive)
|
|
25
|
+
resolved_cops.each do |op, cops|
|
|
26
|
+
cops.each { |cop| apply_cop_op(analyses, op, cop, directive) }
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def apply_cop_op(analyses, operation, cop, directive)
|
|
31
|
+
analysis = analyses[cop]
|
|
32
|
+
line = directive.line_number
|
|
33
|
+
if operation == '-' && !analysis.start_line_number
|
|
34
|
+
analyses[cop] = CopAnalysis.new(analysis.line_ranges, line, directive)
|
|
35
|
+
elsif operation == '+' && analysis.start_line_number
|
|
36
|
+
analyses[cop] = CopAnalysis.new(analysis.close(line), nil)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def pop_state(analyses, line)
|
|
41
|
+
restore_point = @stack.pop
|
|
42
|
+
(restore_point.keys | analyses.keys).each do |cop|
|
|
43
|
+
analyses[cop] = popped_analysis(analyses[cop], restore_point[cop], line)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def popped_analysis(current, restored, line)
|
|
48
|
+
ranges = current.close(line - 1)
|
|
49
|
+
return CopAnalysis.new(ranges, nil) unless restored&.start_line_number
|
|
50
|
+
|
|
51
|
+
CopAnalysis.new(ranges, line, restored.start_directive)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|