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
|
@@ -26,7 +26,8 @@ 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 disable-next todo-next
|
|
29
|
+
AVAILABLE_MODES = %w[disable enable todo push pop disable-next todo-next enable-next
|
|
30
|
+
next].freeze
|
|
30
31
|
# @api private
|
|
31
32
|
# Longest first, so a `-next` mode is not matched as its prefix
|
|
32
33
|
# (`-` is a word boundary).
|
|
@@ -43,6 +44,8 @@ module RuboCop
|
|
|
43
44
|
.gsub(' ', '\s*')
|
|
44
45
|
)
|
|
45
46
|
# @api private
|
|
47
|
+
SIGNED_OPERATIONS = %w[+ -].freeze
|
|
48
|
+
# @api private
|
|
46
49
|
TRAILING_COMMENT_MARKER = '--'
|
|
47
50
|
# @api private
|
|
48
51
|
MALFORMED_DIRECTIVE_WITHOUT_COP_NAME_REGEXP = Regexp.new(
|
|
@@ -71,7 +74,7 @@ module RuboCop
|
|
|
71
74
|
# Checks if the comment is malformed as a `# rubocop:` directive
|
|
72
75
|
def malformed?
|
|
73
76
|
return true if !start_with_marker? || @match_data.nil?
|
|
74
|
-
return true if missing_cop_name?
|
|
77
|
+
return true if missing_cop_name? || invalid_signed_args?
|
|
75
78
|
|
|
76
79
|
tail = @match_data.post_match.lstrip
|
|
77
80
|
!(tail.empty? || tail.start_with?(TRAILING_COMMENT_MARKER))
|
|
@@ -84,6 +87,16 @@ module RuboCop
|
|
|
84
87
|
MALFORMED_DIRECTIVE_WITHOUT_COP_NAME_REGEXP.match?(comment.text)
|
|
85
88
|
end
|
|
86
89
|
|
|
90
|
+
# `push` and `next` arguments must be `+`/`-` prefixed cop names, and
|
|
91
|
+
# `pop` takes no arguments at all.
|
|
92
|
+
def invalid_signed_args?
|
|
93
|
+
return cops ? !cops.empty? : false if pop?
|
|
94
|
+
return false unless push? || next?
|
|
95
|
+
return false unless cops
|
|
96
|
+
|
|
97
|
+
cops.split.any? { |cop_spec| !cop_spec.start_with?('+', '-') }
|
|
98
|
+
end
|
|
99
|
+
|
|
87
100
|
# The text of the directive's optional `--` trailing comment, or `nil`
|
|
88
101
|
# when there is none.
|
|
89
102
|
def reason
|
|
@@ -150,7 +163,12 @@ module RuboCop
|
|
|
150
163
|
|
|
151
164
|
# Checks if this directive enables cops
|
|
152
165
|
def enabled?
|
|
153
|
-
mode == 'enable'
|
|
166
|
+
mode == 'enable' || enable_next?
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Checks if this directive enables cops for the next statement only
|
|
170
|
+
def enable_next?
|
|
171
|
+
mode == 'enable-next'
|
|
154
172
|
end
|
|
155
173
|
|
|
156
174
|
# Checks if this directive is a push
|
|
@@ -163,10 +181,17 @@ module RuboCop
|
|
|
163
181
|
mode == 'pop'
|
|
164
182
|
end
|
|
165
183
|
|
|
166
|
-
#
|
|
167
|
-
def
|
|
168
|
-
|
|
184
|
+
# Checks if this directive toggles cops for the next statement only
|
|
185
|
+
def next?
|
|
186
|
+
mode == 'next'
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# Returns the `+`/`-` arguments of a `push` or `next` directive as a hash
|
|
190
|
+
# of operations to cop names
|
|
191
|
+
def signed_args
|
|
192
|
+
@signed_args ||= parse_signed_args
|
|
169
193
|
end
|
|
194
|
+
alias push_args signed_args
|
|
170
195
|
|
|
171
196
|
# Checks if this directive enables all cops
|
|
172
197
|
def enabled_all?
|
|
@@ -210,6 +235,8 @@ module RuboCop
|
|
|
210
235
|
end
|
|
211
236
|
|
|
212
237
|
def directive_count
|
|
238
|
+
return signed_args.values.sum(&:count) if push? || next?
|
|
239
|
+
|
|
213
240
|
raw_cop_names.count
|
|
214
241
|
end
|
|
215
242
|
|
|
@@ -244,13 +271,15 @@ module RuboCop
|
|
|
244
271
|
cops - [LINT_REDUNDANT_DIRECTIVE_COP, LINT_SYNTAX_COP]
|
|
245
272
|
end
|
|
246
273
|
|
|
247
|
-
def
|
|
248
|
-
return {} unless push? && cops
|
|
274
|
+
def parse_signed_args
|
|
275
|
+
return {} unless (push? || next?) && cops
|
|
249
276
|
|
|
250
277
|
args = {}
|
|
251
278
|
cops.split.each do |cop_spec|
|
|
252
279
|
op = cop_spec[0]
|
|
253
280
|
cop_name = cop_spec[1..]
|
|
281
|
+
next unless SIGNED_OPERATIONS.include?(op)
|
|
282
|
+
|
|
254
283
|
args[op] ||= []
|
|
255
284
|
args[op] << cop_name
|
|
256
285
|
end
|
|
@@ -35,6 +35,7 @@ module RuboCop
|
|
|
35
35
|
# * `#file_started`
|
|
36
36
|
# * `#file_finished`
|
|
37
37
|
# * `#file_started`
|
|
38
|
+
# * `#file_problems` (only when a cop crashed or warned on the file)
|
|
38
39
|
# * `#file_finished`
|
|
39
40
|
# * `#finished`
|
|
40
41
|
#
|
|
@@ -88,6 +89,27 @@ module RuboCop
|
|
|
88
89
|
# @return [void]
|
|
89
90
|
def file_started(file, options); end
|
|
90
91
|
|
|
92
|
+
# @api public
|
|
93
|
+
#
|
|
94
|
+
# Invoked before `#file_finished` for a file that a cop crashed on or
|
|
95
|
+
# raised a warning for, or whose corrections went into an infinite loop.
|
|
96
|
+
# Optional: a formatter implementing the API by duck typing is skipped
|
|
97
|
+
# when it doesn't define it.
|
|
98
|
+
#
|
|
99
|
+
# @param file [String]
|
|
100
|
+
# the file path
|
|
101
|
+
#
|
|
102
|
+
# @param errors [Array(String)]
|
|
103
|
+
# the error messages as they're printed, without colors. A cop that
|
|
104
|
+
# crashes on every node of a kind has a message for each, naming the
|
|
105
|
+
# line and column.
|
|
106
|
+
#
|
|
107
|
+
# @param warnings [Array(String)]
|
|
108
|
+
# the warning messages, in the same form
|
|
109
|
+
#
|
|
110
|
+
# @return [void]
|
|
111
|
+
def file_problems(file, errors, warnings); end
|
|
112
|
+
|
|
91
113
|
# @api public
|
|
92
114
|
#
|
|
93
115
|
# Invoked at the end of inspecting each files.
|
|
@@ -23,6 +23,7 @@ module RuboCop
|
|
|
23
23
|
Enabled
|
|
24
24
|
Exclude
|
|
25
25
|
Include
|
|
26
|
+
Preview
|
|
26
27
|
Reference
|
|
27
28
|
References
|
|
28
29
|
Safe
|
|
@@ -93,6 +94,7 @@ module RuboCop
|
|
|
93
94
|
command += ' --auto-gen-only-exclude' if @options[:auto_gen_only_exclude]
|
|
94
95
|
command += ' --disable-pending-cops' if @options[:disable_pending_cops]
|
|
95
96
|
command += ' --enable-pending-cops' if @options[:enable_pending_cops]
|
|
97
|
+
command += preview_option
|
|
96
98
|
command += exclude_limit_option
|
|
97
99
|
command += ' --no-offense-counts' unless show_offense_counts?
|
|
98
100
|
|
|
@@ -103,6 +105,14 @@ module RuboCop
|
|
|
103
105
|
command
|
|
104
106
|
end
|
|
105
107
|
|
|
108
|
+
def preview_option
|
|
109
|
+
case @options[:preview]
|
|
110
|
+
when true then ' --preview'
|
|
111
|
+
when false then ' --no-preview'
|
|
112
|
+
else ''
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
106
116
|
def exclude_limit_option
|
|
107
117
|
if no_exclude_limit?
|
|
108
118
|
' --no-exclude-limit'
|
|
@@ -259,7 +269,7 @@ module RuboCop
|
|
|
259
269
|
config = ConfigStore.new.for(parent)
|
|
260
270
|
cfg = config[cop_name] || {}
|
|
261
271
|
|
|
262
|
-
if
|
|
272
|
+
if exclude_merges?(config, cfg)
|
|
263
273
|
offending_files
|
|
264
274
|
else
|
|
265
275
|
cop_exclude = cfg['Exclude']
|
|
@@ -272,6 +282,14 @@ module RuboCop
|
|
|
272
282
|
end
|
|
273
283
|
end
|
|
274
284
|
|
|
285
|
+
# `Preview` merges `Exclude` with the default configuration, so the excludes
|
|
286
|
+
# already in the configuration do not have to be copied into the todo file.
|
|
287
|
+
def exclude_merges?(config, cop_config)
|
|
288
|
+
merge_mode_for_exclude?(config) ||
|
|
289
|
+
merge_mode_for_exclude?(cop_config) ||
|
|
290
|
+
config.preview?(@options)
|
|
291
|
+
end
|
|
292
|
+
|
|
275
293
|
def merge_mode_for_exclude?(cfg)
|
|
276
294
|
Array(cfg.to_h.dig('inherit_mode', 'merge')).include?('Exclude')
|
|
277
295
|
end
|
|
@@ -23,6 +23,7 @@ module RuboCop
|
|
|
23
23
|
'[pa]cman' => 'PacmanFormatter',
|
|
24
24
|
'[p]rogress' => 'ProgressFormatter',
|
|
25
25
|
'[q]uiet' => 'QuietFormatter',
|
|
26
|
+
'[sa]rif' => 'SARIFFormatter',
|
|
26
27
|
'[s]imple' => 'SimpleTextFormatter',
|
|
27
28
|
'[t]ap' => 'TapFormatter',
|
|
28
29
|
'[w]orst' => 'WorstOffendersFormatter'
|
|
@@ -48,6 +49,10 @@ module RuboCop
|
|
|
48
49
|
each { |f| f.file_started(file, options) }
|
|
49
50
|
end
|
|
50
51
|
|
|
52
|
+
def file_problems(file, errors, warnings)
|
|
53
|
+
each { |f| f.file_problems(file, errors, warnings) if f.respond_to?(:file_problems) }
|
|
54
|
+
end
|
|
55
|
+
|
|
51
56
|
def file_finished(file, offenses)
|
|
52
57
|
each { |f| f.file_finished(file, offenses) }
|
|
53
58
|
offenses
|
|
@@ -57,7 +62,7 @@ module RuboCop
|
|
|
57
62
|
if output_path
|
|
58
63
|
dir_path = File.dirname(output_path)
|
|
59
64
|
FileUtils.mkdir_p(dir_path)
|
|
60
|
-
output = File.open(output_path, 'w') # rubocop:disable Style/FileOpen
|
|
65
|
+
output = File.open(output_path, 'w') # rubocop:disable Style/FileOpen -- the file is closed by `close_output_files`, not by a block
|
|
61
66
|
else
|
|
62
67
|
output = $stdout
|
|
63
68
|
end
|
|
@@ -15,6 +15,10 @@ module RuboCop
|
|
|
15
15
|
@offenses_for_files[file] = offenses unless offenses.empty?
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
+
def file_started(_file, options)
|
|
19
|
+
@config_store = options[:config_store]
|
|
20
|
+
end
|
|
21
|
+
|
|
18
22
|
def finished(_inspected_files)
|
|
19
23
|
@offenses_for_files.each do |file, offenses|
|
|
20
24
|
offenses.each do |offense|
|
|
@@ -31,11 +35,8 @@ module RuboCop
|
|
|
31
35
|
end
|
|
32
36
|
|
|
33
37
|
def minimum_severity_to_fail
|
|
34
|
-
@minimum_severity_to_fail ||=
|
|
35
|
-
|
|
36
|
-
name = options.fetch(:fail_level, :refactor)
|
|
37
|
-
RuboCop::Cop::Severity.new(name)
|
|
38
|
-
end
|
|
38
|
+
@minimum_severity_to_fail ||=
|
|
39
|
+
RuboCop::Cop::Severity.minimum_to_fail(options, @config_store&.for_pwd)
|
|
39
40
|
end
|
|
40
41
|
|
|
41
42
|
def github_severity(offense)
|
|
@@ -74,7 +74,7 @@ module RuboCop
|
|
|
74
74
|
end
|
|
75
75
|
|
|
76
76
|
# Make Kernel#binding public.
|
|
77
|
-
# rubocop:disable-next Lint/UselessMethodDefinition
|
|
77
|
+
# rubocop:disable-next Lint/UselessMethodDefinition -- redefined only to make `Kernel#binding` public
|
|
78
78
|
def binding
|
|
79
79
|
super
|
|
80
80
|
end
|
|
@@ -143,7 +143,7 @@ module RuboCop
|
|
|
143
143
|
}.freeze
|
|
144
144
|
|
|
145
145
|
# Make Kernel#binding public.
|
|
146
|
-
# rubocop:disable-next Lint/UselessMethodDefinition
|
|
146
|
+
# rubocop:disable-next Lint/UselessMethodDefinition -- redefined only to make `Kernel#binding` public
|
|
147
147
|
def binding
|
|
148
148
|
super
|
|
149
149
|
end
|
|
@@ -13,19 +13,29 @@ module RuboCop
|
|
|
13
13
|
def initialize(output, options = {})
|
|
14
14
|
super
|
|
15
15
|
@output_hash = { metadata: metadata_hash, files: [], summary: { offense_count: 0 } }
|
|
16
|
+
@problems = {}
|
|
16
17
|
end
|
|
17
18
|
|
|
18
19
|
def started(target_files)
|
|
19
20
|
output_hash[:summary][:target_file_count] = target_files.count
|
|
20
21
|
end
|
|
21
22
|
|
|
23
|
+
def file_problems(file, errors, warnings)
|
|
24
|
+
@problems[file] = hash_for_problems(file, errors, warnings)
|
|
25
|
+
end
|
|
26
|
+
|
|
22
27
|
def file_finished(file, offenses)
|
|
23
|
-
|
|
28
|
+
entry = hash_for_file(file, offenses)
|
|
29
|
+
problems = @problems.delete(file)
|
|
30
|
+
entry.merge!(problems) if problems
|
|
31
|
+
|
|
32
|
+
output_hash[:files] << entry
|
|
24
33
|
output_hash[:summary][:offense_count] += offenses.count
|
|
25
34
|
end
|
|
26
35
|
|
|
27
36
|
def finished(inspected_files)
|
|
28
37
|
output_hash[:summary][:inspected_file_count] = inspected_files.count
|
|
38
|
+
output_hash[:summary].merge!(problem_counts(output_hash[:files]))
|
|
29
39
|
output.write output_hash.to_json
|
|
30
40
|
end
|
|
31
41
|
|
|
@@ -46,6 +56,32 @@ module RuboCop
|
|
|
46
56
|
}
|
|
47
57
|
end
|
|
48
58
|
|
|
59
|
+
# A cop that crashes fails once per node it visits, so messages that
|
|
60
|
+
# differ only in their line and column are listed once, at the first place
|
|
61
|
+
# they happened. They name the file the way its entry does. The keys are
|
|
62
|
+
# absent when there's nothing to report, which keeps them additive for
|
|
63
|
+
# existing consumers.
|
|
64
|
+
def hash_for_problems(file, errors, warnings)
|
|
65
|
+
return {} if errors.empty? && warnings.empty?
|
|
66
|
+
|
|
67
|
+
path = smart_path(file)
|
|
68
|
+
location = /#{Regexp.escape(File.expand_path(file))}((?::\d+)*)/
|
|
69
|
+
|
|
70
|
+
{ errors: errors, warnings: warnings }.filter_map do |key, messages|
|
|
71
|
+
next if messages.empty?
|
|
72
|
+
|
|
73
|
+
messages = messages.uniq { |message| message.gsub(location, '') }
|
|
74
|
+
[key, messages.map { |message| message.gsub(location) { path + Regexp.last_match(1) } }]
|
|
75
|
+
end.to_h
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def problem_counts(files)
|
|
79
|
+
{
|
|
80
|
+
error_count: files.sum { |f| f[:errors]&.size.to_i },
|
|
81
|
+
warning_count: files.sum { |f| f[:warnings]&.size.to_i }
|
|
82
|
+
}.reject { |_, count| count.zero? }
|
|
83
|
+
end
|
|
84
|
+
|
|
49
85
|
def hash_for_offense(offense)
|
|
50
86
|
hash = {
|
|
51
87
|
severity: offense.severity.name,
|
|
@@ -63,9 +99,43 @@ module RuboCop
|
|
|
63
99
|
hash[:justification] = offense.justification
|
|
64
100
|
end
|
|
65
101
|
|
|
102
|
+
# The edits autocorrection would make, so a consumer can apply or review
|
|
103
|
+
# them without running autocorrection itself. Additive, and absent when
|
|
104
|
+
# the offense has no correction.
|
|
105
|
+
hash[:correction] = correction_for(offense) unless offense.corrections.empty?
|
|
106
|
+
|
|
66
107
|
hash
|
|
67
108
|
end
|
|
68
109
|
|
|
110
|
+
def correction_for(offense)
|
|
111
|
+
{ safe: offense.correction_safe, edits: edits_for(offense) }
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def edits_for(offense)
|
|
115
|
+
buffer = offense.location.source_buffer
|
|
116
|
+
|
|
117
|
+
offense.corrections.map do |correction|
|
|
118
|
+
# Built as a range so the columns follow the same 1-based convention
|
|
119
|
+
# as `hash_for_location`, end-exclusive column included.
|
|
120
|
+
range = ::Parser::Source::Range.new(buffer, correction.begin_pos, correction.end_pos)
|
|
121
|
+
|
|
122
|
+
hash_for_edit_range(range).merge!(
|
|
123
|
+
begin_pos: correction.begin_pos,
|
|
124
|
+
end_pos: correction.end_pos,
|
|
125
|
+
replacement: correction.replacement
|
|
126
|
+
)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def hash_for_edit_range(range)
|
|
131
|
+
{
|
|
132
|
+
start_line: range.line,
|
|
133
|
+
start_column: range.column + 1,
|
|
134
|
+
last_line: range.last_line,
|
|
135
|
+
last_column: range.last_column.zero? ? 1 : range.last_column
|
|
136
|
+
}
|
|
137
|
+
end
|
|
138
|
+
|
|
69
139
|
def hash_for_location(offense)
|
|
70
140
|
{
|
|
71
141
|
start_line: offense.line,
|
|
@@ -47,7 +47,7 @@ module RuboCop
|
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
-
# rubocop:disable-next Layout/LineLength,Metrics/AbcSize,Metrics/MethodLength
|
|
50
|
+
# rubocop:disable-next Layout/LineLength,Metrics/AbcSize,Metrics/MethodLength -- the XML is emitted line by line
|
|
51
51
|
def finished(_inspected_files)
|
|
52
52
|
output.puts %(<?xml version='1.0'?>)
|
|
53
53
|
output.puts %(<testsuites>)
|
|
@@ -14,6 +14,8 @@ module RuboCop
|
|
|
14
14
|
# --
|
|
15
15
|
# 29 Total in 5 files
|
|
16
16
|
class OffenseCountFormatter < BaseFormatter
|
|
17
|
+
include TextUtil
|
|
18
|
+
|
|
17
19
|
attr_reader :offense_counts
|
|
18
20
|
|
|
19
21
|
def started(target_files)
|
|
@@ -64,7 +66,7 @@ module RuboCop
|
|
|
64
66
|
output.puts "#{count.to_s.ljust(column_width)}#{cop_information(cop_name)}"
|
|
65
67
|
end
|
|
66
68
|
output.puts '--'
|
|
67
|
-
output.puts "#{total_count} Total in #{offending_files_count}
|
|
69
|
+
output.puts "#{total_count} Total in #{pluralize(offending_files_count, 'file')}"
|
|
68
70
|
|
|
69
71
|
output.puts
|
|
70
72
|
end
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'io/console'
|
|
4
|
+
|
|
3
5
|
module RuboCop
|
|
4
6
|
module Formatter
|
|
5
7
|
# This formatter prints a PACDOT per every file to be analyzed.
|
|
@@ -50,7 +52,7 @@ module RuboCop
|
|
|
50
52
|
|
|
51
53
|
def cols
|
|
52
54
|
@cols ||= begin
|
|
53
|
-
_height, width =
|
|
55
|
+
_height, width = output.winsize if output.tty?
|
|
54
56
|
width.nil? || width.zero? ? FALLBACK_TERMINAL_WIDTH : width
|
|
55
57
|
end
|
|
56
58
|
end
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'digest'
|
|
4
|
+
|
|
5
|
+
module RuboCop
|
|
6
|
+
module Formatter
|
|
7
|
+
# This formatter formats the report data in SARIF 2.1.0, the OASIS standard
|
|
8
|
+
# for static analysis results. It's understood by GitHub code scanning,
|
|
9
|
+
# Azure DevOps, and other tools that aggregate analyzer output.
|
|
10
|
+
#
|
|
11
|
+
# SARIF only knows three severity levels, so RuboCop's `info`, `refactor`
|
|
12
|
+
# and `convention` severities are all reported as `note`.
|
|
13
|
+
class SARIFFormatter < BaseFormatter
|
|
14
|
+
SCHEMA_URI = 'https://json.schemastore.org/sarif-2.1.0.json'
|
|
15
|
+
SARIF_VERSION = '2.1.0'
|
|
16
|
+
INFORMATION_URI = 'https://rubocop.org'
|
|
17
|
+
|
|
18
|
+
SEVERITY_LEVELS = {
|
|
19
|
+
info: 'note',
|
|
20
|
+
refactor: 'note',
|
|
21
|
+
convention: 'note',
|
|
22
|
+
warning: 'warning',
|
|
23
|
+
error: 'error',
|
|
24
|
+
fatal: 'error'
|
|
25
|
+
}.freeze
|
|
26
|
+
|
|
27
|
+
def initialize(output, options = {})
|
|
28
|
+
super
|
|
29
|
+
|
|
30
|
+
@rules = []
|
|
31
|
+
@rule_indexes = {}
|
|
32
|
+
@results = []
|
|
33
|
+
@config_store = nil
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def file_started(_file, options)
|
|
37
|
+
@config_store = options[:config_store]
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def file_finished(file, offenses)
|
|
41
|
+
line_hash_counts = Hash.new(0)
|
|
42
|
+
offenses.each do |offense|
|
|
43
|
+
@results << result_for(file, offense, line_hash_counts)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def finished(_inspected_files)
|
|
48
|
+
output.write(report.to_json)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
|
|
53
|
+
def report
|
|
54
|
+
{
|
|
55
|
+
'$schema': SCHEMA_URI,
|
|
56
|
+
version: SARIF_VERSION,
|
|
57
|
+
runs: [{ tool: { driver: driver }, results: @results }]
|
|
58
|
+
}
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def driver
|
|
62
|
+
{
|
|
63
|
+
name: 'RuboCop',
|
|
64
|
+
version: RuboCop::Version::STRING,
|
|
65
|
+
semanticVersion: RuboCop::Version::STRING,
|
|
66
|
+
informationUri: INFORMATION_URI,
|
|
67
|
+
rules: @rules
|
|
68
|
+
}
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def result_for(file, offense, line_hash_counts)
|
|
72
|
+
result = {
|
|
73
|
+
ruleId: offense.cop_name,
|
|
74
|
+
ruleIndex: rule_index_for(file, offense),
|
|
75
|
+
level: SEVERITY_LEVELS.fetch(offense.severity.name, 'warning'),
|
|
76
|
+
message: { text: offense.message },
|
|
77
|
+
locations: [location_for(file, offense)],
|
|
78
|
+
partialFingerprints: fingerprints_for(offense, line_hash_counts)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
# Suppressed offenses are only reported under `--display-suppressed`.
|
|
82
|
+
# SARIF has a first-class representation for them, so consumers can
|
|
83
|
+
# tell them apart from offenses that were never triggered.
|
|
84
|
+
result[:suppressions] = [suppression_for(offense)] if offense.disabled?
|
|
85
|
+
result
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# The URI is relative to the working directory, which is what consumers
|
|
89
|
+
# expect to resolve against their own checkout. No `uriBaseId`: it would
|
|
90
|
+
# have to be declared under `originalUriBaseIds` to mean anything, and
|
|
91
|
+
# every consumer that matters resolves relative paths without it.
|
|
92
|
+
def location_for(file, offense)
|
|
93
|
+
{
|
|
94
|
+
physicalLocation: {
|
|
95
|
+
artifactLocation: { uri: uri_for(file) },
|
|
96
|
+
region: region_for(offense)
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def region_for(offense)
|
|
102
|
+
# SARIF columns are 1-based and `endColumn` points at the character
|
|
103
|
+
# *after* the region, while `real_last_column` is the last character.
|
|
104
|
+
{
|
|
105
|
+
startLine: offense.first_line,
|
|
106
|
+
startColumn: offense.real_column,
|
|
107
|
+
endLine: offense.last_line,
|
|
108
|
+
endColumn: offense.real_last_column + 1
|
|
109
|
+
}
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# GitHub uses these to match an alert across runs. Without them it falls
|
|
113
|
+
# back to the file path, which makes alerts churn whenever a file moves.
|
|
114
|
+
# Repeats of the same hash within a file get a `:N` suffix, like GitHub's
|
|
115
|
+
# own fingerprints, so two offenses on one line don't merge into one alert.
|
|
116
|
+
# The first occurrence keeps the bare hash to match earlier reports.
|
|
117
|
+
def fingerprints_for(offense, line_hash_counts)
|
|
118
|
+
line_hash = Digest::SHA256.hexdigest("#{offense.cop_name}#{offense.location.source_line}")
|
|
119
|
+
count = line_hash_counts[line_hash] += 1
|
|
120
|
+
{ primaryLocationLineHash: count == 1 ? line_hash : "#{line_hash}:#{count}" }
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def suppression_for(offense)
|
|
124
|
+
suppression = { kind: 'inSource' }
|
|
125
|
+
suppression[:justification] = offense.justification if offense.justification
|
|
126
|
+
suppression
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def rule_index_for(file, offense)
|
|
130
|
+
@rule_indexes[offense.cop_name] ||= begin
|
|
131
|
+
@rules << rule_for(file, offense)
|
|
132
|
+
@rules.size - 1
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def rule_for(file, offense)
|
|
137
|
+
cop_class = Cop::Registry.global.find_by_cop_name(offense.cop_name)
|
|
138
|
+
description = description_for(file, offense)
|
|
139
|
+
help_uri = cop_class && Cop::Documentation.url_for(cop_class, config_for(file))
|
|
140
|
+
|
|
141
|
+
rule = {
|
|
142
|
+
id: offense.cop_name,
|
|
143
|
+
name: offense.cop_name,
|
|
144
|
+
shortDescription: { text: description },
|
|
145
|
+
fullDescription: { text: description },
|
|
146
|
+
help: help_for(description, help_uri),
|
|
147
|
+
defaultConfiguration: { level: default_level_for(file, offense, cop_class) },
|
|
148
|
+
properties: { tags: [offense.cop_name.split('/').first] }
|
|
149
|
+
}
|
|
150
|
+
rule[:helpUri] = help_uri if help_uri
|
|
151
|
+
rule
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def help_for(description, help_uri)
|
|
155
|
+
help = { text: description }
|
|
156
|
+
help[:markdown] = "#{description}\n\n[Documentation](#{help_uri})" if help_uri
|
|
157
|
+
help
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def description_for(file, offense)
|
|
161
|
+
cop_config(file, offense)['Description'] || offense.cop_name
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def default_level_for(file, offense, cop_class)
|
|
165
|
+
severity = cop_config(file, offense)['Severity'] ||
|
|
166
|
+
Cop::Base::DEPARTMENT_SEVERITIES.fetch(cop_class&.department, :convention)
|
|
167
|
+
|
|
168
|
+
SEVERITY_LEVELS.fetch(severity.to_sym, 'warning')
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def cop_config(file, offense)
|
|
172
|
+
config_for(file)&.for_cop(offense.cop_name) || {}
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# `file_started` is not called when a formatter is used directly through
|
|
176
|
+
# the API, so there may be no config to consult.
|
|
177
|
+
def config_for(file)
|
|
178
|
+
@config_store&.for_file(file)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def uri_for(file)
|
|
182
|
+
PathUtil.smart_path(file).tr('\\', '/')
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
@@ -14,6 +14,8 @@ module RuboCop
|
|
|
14
14
|
# --
|
|
15
15
|
# 29 Total in 2 files
|
|
16
16
|
class WorstOffendersFormatter < BaseFormatter
|
|
17
|
+
include TextUtil
|
|
18
|
+
|
|
17
19
|
attr_reader :offense_counts
|
|
18
20
|
|
|
19
21
|
def started(target_files)
|
|
@@ -46,7 +48,7 @@ module RuboCop
|
|
|
46
48
|
end
|
|
47
49
|
|
|
48
50
|
output.puts '--'
|
|
49
|
-
output.puts "#{total_count} Total in #{file_count}
|
|
51
|
+
output.puts "#{total_count} Total in #{pluralize(file_count, 'file')}"
|
|
50
52
|
|
|
51
53
|
output.puts
|
|
52
54
|
end
|
data/lib/rubocop/formatter.rb
CHANGED
|
@@ -24,6 +24,7 @@ module RuboCop
|
|
|
24
24
|
autoload :PacmanFormatter, 'rubocop/formatter/pacman_formatter'
|
|
25
25
|
autoload :ProgressFormatter, 'rubocop/formatter/progress_formatter'
|
|
26
26
|
autoload :QuietFormatter, 'rubocop/formatter/quiet_formatter'
|
|
27
|
+
autoload :SARIFFormatter, 'rubocop/formatter/sarif_formatter'
|
|
27
28
|
autoload :TapFormatter, 'rubocop/formatter/tap_formatter'
|
|
28
29
|
autoload :WorstOffendersFormatter, 'rubocop/formatter/worst_offenders_formatter'
|
|
29
30
|
|