rubocop 1.80.2 → 1.86.1
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/LICENSE.txt +1 -1
- data/README.md +2 -2
- data/config/default.yml +170 -19
- data/config/obsoletion.yml +9 -0
- data/lib/rubocop/cache_config.rb +29 -0
- data/lib/rubocop/cli/command/auto_generate_config.rb +3 -3
- data/lib/rubocop/cli/command/lsp.rb +1 -1
- data/lib/rubocop/cli/command/mcp.rb +19 -0
- data/lib/rubocop/cli/command/show_cops.rb +2 -2
- data/lib/rubocop/cli/command/show_docs_url.rb +1 -1
- data/lib/rubocop/cli.rb +28 -6
- data/lib/rubocop/comment_config.rb +62 -17
- data/lib/rubocop/config.rb +14 -10
- data/lib/rubocop/config_finder.rb +1 -1
- data/lib/rubocop/config_loader.rb +20 -21
- data/lib/rubocop/config_loader_resolver.rb +9 -7
- data/lib/rubocop/config_obsoletion/extracted_cop.rb +4 -2
- data/lib/rubocop/config_store.rb +6 -1
- data/lib/rubocop/config_validator.rb +1 -1
- data/lib/rubocop/cop/autocorrect_logic.rb +8 -4
- data/lib/rubocop/cop/bundler/gem_version.rb +28 -28
- data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -2
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +22 -6
- data/lib/rubocop/cop/correctors/condition_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +2 -2
- data/lib/rubocop/cop/documentation.rb +2 -3
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -2
- data/lib/rubocop/cop/gemspec/require_mfa.rb +1 -1
- data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +10 -5
- data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +8 -8
- data/lib/rubocop/cop/internal_affairs/itblock_handler.rb +69 -0
- data/lib/rubocop/cop/internal_affairs/location_exists.rb +28 -2
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +9 -9
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +3 -1
- data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +4 -4
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/layout/argument_alignment.rb +2 -2
- data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/case_indentation.rb +3 -1
- data/lib/rubocop/cop/layout/class_structure.rb +13 -6
- data/lib/rubocop/cop/layout/dot_position.rb +2 -2
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +12 -2
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +31 -13
- 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 +12 -2
- data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +16 -2
- data/lib/rubocop/cop/layout/empty_lines_around_module_body.rb +16 -2
- data/lib/rubocop/cop/layout/end_alignment.rb +8 -1
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +34 -1
- data/lib/rubocop/cop/layout/first_array_element_line_break.rb +26 -0
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +7 -1
- data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +25 -25
- data/lib/rubocop/cop/layout/hash_alignment.rb +3 -6
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +33 -3
- data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +111 -7
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
- data/lib/rubocop/cop/layout/line_length.rb +26 -9
- data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +57 -57
- data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +9 -2
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +2 -0
- data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +56 -56
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +204 -39
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +6 -4
- data/lib/rubocop/cop/layout/parameter_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -1
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +13 -3
- data/lib/rubocop/cop/layout/space_after_comma.rb +2 -10
- data/lib/rubocop/cop/layout/space_after_semicolon.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_keyword.rb +4 -2
- data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +9 -8
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +47 -3
- data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +3 -2
- data/lib/rubocop/cop/lint/constant_reassignment.rb +59 -9
- data/lib/rubocop/cop/lint/constant_resolution.rb +1 -1
- data/lib/rubocop/cop/lint/cop_directive_syntax.rb +14 -8
- data/lib/rubocop/cop/lint/data_define_override.rb +63 -0
- data/lib/rubocop/cop/lint/debugger.rb +0 -2
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +4 -1
- data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +4 -4
- data/lib/rubocop/cop/lint/duplicate_methods.rb +111 -12
- data/lib/rubocop/cop/lint/else_layout.rb +19 -0
- data/lib/rubocop/cop/lint/empty_block.rb +1 -1
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +6 -1
- data/lib/rubocop/cop/lint/empty_in_pattern.rb +8 -1
- data/lib/rubocop/cop/lint/empty_interpolation.rb +11 -0
- data/lib/rubocop/cop/lint/empty_when.rb +8 -1
- data/lib/rubocop/cop/lint/float_comparison.rb +1 -1
- data/lib/rubocop/cop/lint/interpolation_check.rb +7 -2
- data/lib/rubocop/cop/lint/literal_as_condition.rb +5 -1
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +16 -6
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +2 -0
- data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +4 -0
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -1
- data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +23 -9
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +0 -9
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -2
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +23 -6
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +8 -2
- data/lib/rubocop/cop/lint/rescue_exception.rb +1 -4
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +17 -0
- data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +7 -1
- data/lib/rubocop/cop/lint/self_assignment.rb +10 -2
- data/lib/rubocop/cop/lint/shadowed_argument.rb +7 -7
- data/lib/rubocop/cop/lint/struct_new_override.rb +17 -1
- data/lib/rubocop/cop/lint/syntax.rb +25 -1
- data/lib/rubocop/cop/lint/to_json.rb +12 -16
- data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +1 -0
- data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -0
- data/lib/rubocop/cop/lint/unreachable_code.rb +5 -3
- data/lib/rubocop/cop/lint/unreachable_pattern_branch.rb +113 -0
- data/lib/rubocop/cop/lint/unused_method_argument.rb +10 -0
- data/lib/rubocop/cop/lint/useless_assignment.rb +45 -17
- data/lib/rubocop/cop/lint/useless_constant_scoping.rb +4 -4
- data/lib/rubocop/cop/lint/useless_default_value_argument.rb +2 -0
- data/lib/rubocop/cop/lint/useless_or.rb +15 -2
- data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +24 -9
- data/lib/rubocop/cop/lint/void.rb +39 -12
- data/lib/rubocop/cop/message_annotator.rb +1 -1
- data/lib/rubocop/cop/metrics/block_nesting.rb +23 -0
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -3
- data/lib/rubocop/cop/migration/department_name.rb +12 -1
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +2 -2
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +4 -6
- data/lib/rubocop/cop/mixin/code_length.rb +1 -1
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +5 -5
- data/lib/rubocop/cop/mixin/hash_transform_method/autocorrection.rb +63 -0
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +10 -60
- data/lib/rubocop/cop/mixin/line_length_help.rb +21 -2
- data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
- data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +5 -4
- data/lib/rubocop/cop/mixin/statement_modifier.rb +0 -6
- data/lib/rubocop/cop/mixin/trailing_comma.rb +8 -5
- data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
- data/lib/rubocop/cop/naming/method_name.rb +4 -2
- data/lib/rubocop/cop/naming/predicate_method.rb +27 -4
- data/lib/rubocop/cop/naming/predicate_prefix.rb +11 -11
- data/lib/rubocop/cop/offense.rb +9 -1
- data/lib/rubocop/cop/registry.rb +20 -13
- data/lib/rubocop/cop/security/eval.rb +15 -2
- data/lib/rubocop/cop/security/json_load.rb +33 -11
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +15 -4
- data/lib/rubocop/cop/style/accessor_grouping.rb +4 -2
- data/lib/rubocop/cop/style/alias.rb +4 -1
- data/lib/rubocop/cop/style/and_or.rb +1 -0
- data/lib/rubocop/cop/style/arguments_forwarding.rb +25 -7
- data/lib/rubocop/cop/style/array_intersect.rb +2 -2
- data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +47 -0
- data/lib/rubocop/cop/style/array_join.rb +4 -2
- data/lib/rubocop/cop/style/ascii_comments.rb +6 -3
- data/lib/rubocop/cop/style/attr.rb +5 -2
- data/lib/rubocop/cop/style/bare_percent_literals.rb +4 -3
- data/lib/rubocop/cop/style/begin_block.rb +3 -1
- data/lib/rubocop/cop/style/block_delimiters.rb +27 -34
- data/lib/rubocop/cop/style/case_equality.rb +15 -13
- data/lib/rubocop/cop/style/class_and_module_children.rb +11 -2
- data/lib/rubocop/cop/style/collection_compact.rb +36 -16
- data/lib/rubocop/cop/style/colon_method_call.rb +3 -1
- data/lib/rubocop/cop/style/concat_array_literals.rb +2 -0
- data/lib/rubocop/cop/style/conditional_assignment.rb +8 -18
- data/lib/rubocop/cop/style/constant_visibility.rb +17 -12
- data/lib/rubocop/cop/style/copyright.rb +1 -1
- data/lib/rubocop/cop/style/documentation.rb +6 -6
- data/lib/rubocop/cop/style/documentation_method.rb +8 -8
- data/lib/rubocop/cop/style/double_negation.rb +1 -1
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
- data/lib/rubocop/cop/style/each_with_object.rb +2 -0
- data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
- data/lib/rubocop/cop/style/empty_class_definition.rb +119 -0
- data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
- data/lib/rubocop/cop/style/empty_method.rb +0 -6
- data/lib/rubocop/cop/style/encoding.rb +7 -1
- data/lib/rubocop/cop/style/end_block.rb +3 -1
- data/lib/rubocop/cop/style/endless_method.rb +23 -5
- data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
- data/lib/rubocop/cop/style/file_open.rb +84 -0
- data/lib/rubocop/cop/style/float_division.rb +15 -1
- data/lib/rubocop/cop/style/for.rb +3 -0
- data/lib/rubocop/cop/style/format_string_token.rb +49 -5
- data/lib/rubocop/cop/style/global_vars.rb +5 -2
- data/lib/rubocop/cop/style/guard_clause.rb +27 -22
- data/lib/rubocop/cop/style/hash_as_last_array_item.rb +27 -9
- data/lib/rubocop/cop/style/hash_lookup_method.rb +101 -0
- data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
- data/lib/rubocop/cop/style/hash_transform_keys.rb +17 -7
- data/lib/rubocop/cop/style/hash_transform_values.rb +17 -7
- data/lib/rubocop/cop/style/if_inside_else.rb +1 -5
- data/lib/rubocop/cop/style/if_unless_modifier.rb +57 -17
- data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +12 -12
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +4 -1
- data/lib/rubocop/cop/style/if_with_semicolon.rb +7 -5
- data/lib/rubocop/cop/style/inline_comment.rb +4 -1
- data/lib/rubocop/cop/style/ip_addresses.rb +1 -2
- data/lib/rubocop/cop/style/lambda_call.rb +8 -8
- data/lib/rubocop/cop/style/magic_comment_format.rb +2 -2
- data/lib/rubocop/cop/style/map_join.rb +123 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +15 -2
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +17 -4
- data/lib/rubocop/cop/style/method_def_parentheses.rb +2 -4
- data/lib/rubocop/cop/style/module_member_existence_check.rb +107 -0
- data/lib/rubocop/cop/style/multiline_if_then.rb +4 -4
- data/lib/rubocop/cop/style/multiline_method_signature.rb +2 -4
- data/lib/rubocop/cop/style/mutable_constant.rb +1 -1
- data/lib/rubocop/cop/style/negative_array_index.rb +220 -0
- data/lib/rubocop/cop/style/nil_comparison.rb +11 -10
- data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
- data/lib/rubocop/cop/style/non_nil_check.rb +5 -11
- data/lib/rubocop/cop/style/not.rb +2 -0
- data/lib/rubocop/cop/style/numeric_literals.rb +3 -2
- data/lib/rubocop/cop/style/one_class_per_file.rb +115 -0
- data/lib/rubocop/cop/style/one_line_conditional.rb +21 -12
- data/lib/rubocop/cop/style/operator_method_call.rb +11 -2
- data/lib/rubocop/cop/style/parallel_assignment.rb +6 -2
- data/lib/rubocop/cop/style/partition_instead_of_double_select.rb +270 -0
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +2 -0
- data/lib/rubocop/cop/style/predicate_with_kind.rb +84 -0
- data/lib/rubocop/cop/style/preferred_hash_methods.rb +12 -12
- data/lib/rubocop/cop/style/proc.rb +3 -2
- data/lib/rubocop/cop/style/raise_args.rb +1 -1
- data/lib/rubocop/cop/style/reduce_to_hash.rb +184 -0
- data/lib/rubocop/cop/style/redundant_argument.rb +2 -0
- data/lib/rubocop/cop/style/redundant_begin.rb +3 -3
- data/lib/rubocop/cop/style/redundant_condition.rb +5 -2
- data/lib/rubocop/cop/style/redundant_each.rb +3 -3
- data/lib/rubocop/cop/style/redundant_exception.rb +1 -1
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -1
- data/lib/rubocop/cop/style/redundant_format.rb +26 -5
- data/lib/rubocop/cop/style/redundant_interpolation.rb +11 -2
- data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +26 -10
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +16 -0
- data/lib/rubocop/cop/style/redundant_min_max_by.rb +93 -0
- data/lib/rubocop/cop/style/redundant_parentheses.rb +26 -22
- data/lib/rubocop/cop/style/redundant_percent_q.rb +5 -3
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +9 -0
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -0
- data/lib/rubocop/cop/style/redundant_return.rb +3 -1
- data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +0 -5
- data/lib/rubocop/cop/style/redundant_sort.rb +7 -7
- data/lib/rubocop/cop/style/redundant_struct_keyword_init.rb +114 -0
- data/lib/rubocop/cop/style/reverse_find.rb +51 -0
- data/lib/rubocop/cop/style/safe_navigation.rb +7 -7
- data/lib/rubocop/cop/style/select_by_kind.rb +158 -0
- data/lib/rubocop/cop/style/select_by_range.rb +197 -0
- data/lib/rubocop/cop/style/select_by_regexp.rb +51 -21
- data/lib/rubocop/cop/style/semicolon.rb +25 -7
- data/lib/rubocop/cop/style/single_line_block_params.rb +2 -2
- data/lib/rubocop/cop/style/single_line_do_end_block.rb +1 -1
- data/lib/rubocop/cop/style/single_line_methods.rb +3 -1
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +8 -1
- data/lib/rubocop/cop/style/special_global_vars.rb +6 -1
- data/lib/rubocop/cop/style/super_arguments.rb +2 -2
- data/lib/rubocop/cop/style/symbol_proc.rb +4 -3
- data/lib/rubocop/cop/style/tally_method.rb +181 -0
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +45 -0
- data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
- data/lib/rubocop/cop/style/trailing_method_end_statement.rb +1 -0
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +11 -11
- data/lib/rubocop/cop/style/unless_else.rb +10 -9
- data/lib/rubocop/cop/style/yoda_expression.rb +1 -1
- data/lib/rubocop/cop/team.rb +4 -4
- data/lib/rubocop/cop/util.rb +2 -3
- data/lib/rubocop/cop/utils/format_string.rb +10 -0
- data/lib/rubocop/cop/variable_force/branch.rb +30 -6
- data/lib/rubocop/cops_documentation_generator.rb +4 -4
- data/lib/rubocop/directive_comment.rb +48 -4
- data/lib/rubocop/formatter/clang_style_formatter.rb +5 -2
- data/lib/rubocop/formatter/disabled_config_formatter.rb +2 -1
- data/lib/rubocop/formatter/formatter_set.rb +2 -2
- data/lib/rubocop/formatter/junit_formatter.rb +1 -1
- data/lib/rubocop/formatter/simple_text_formatter.rb +0 -2
- data/lib/rubocop/formatter/tap_formatter.rb +5 -2
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -1
- data/lib/rubocop/formatter.rb +22 -21
- data/lib/rubocop/lsp/diagnostic.rb +18 -33
- data/lib/rubocop/lsp/disable_comment_edits.rb +135 -0
- data/lib/rubocop/lsp/routes.rb +12 -5
- data/lib/rubocop/lsp/runtime.rb +13 -3
- data/lib/rubocop/lsp/stdin_runner.rb +8 -17
- data/lib/rubocop/magic_comment.rb +20 -0
- data/lib/rubocop/mcp/server.rb +200 -0
- data/lib/rubocop/options.rb +10 -1
- data/lib/rubocop/path_util.rb +14 -2
- data/lib/rubocop/plugin/loader.rb +1 -1
- data/lib/rubocop/rake_task.rb +1 -1
- data/lib/rubocop/remote_config.rb +10 -8
- data/lib/rubocop/result_cache.rb +60 -37
- data/lib/rubocop/rspec/cop_helper.rb +8 -0
- data/lib/rubocop/rspec/shared_contexts.rb +18 -5
- data/lib/rubocop/rspec/support.rb +2 -1
- data/lib/rubocop/runner.rb +12 -3
- data/lib/rubocop/server/cache.rb +6 -29
- data/lib/rubocop/server/core.rb +2 -0
- data/lib/rubocop/target_finder.rb +1 -1
- data/lib/rubocop/target_ruby.rb +31 -14
- data/lib/rubocop/version.rb +2 -2
- data/lib/rubocop.rb +20 -0
- data/lib/ruby_lsp/rubocop/addon.rb +23 -8
- data/lib/ruby_lsp/rubocop/runtime_adapter.rb +49 -15
- metadata +33 -9
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Style
|
|
6
|
+
# Checks for manual counting patterns that can be replaced by `Enumerable#tally`.
|
|
7
|
+
#
|
|
8
|
+
# The cop detects the following patterns:
|
|
9
|
+
#
|
|
10
|
+
# - `each_with_object(Hash.new(0)) { |item, counts| counts[item] += 1 }`
|
|
11
|
+
# - `group_by(&:itself).transform_values(&:count)`
|
|
12
|
+
# - `group_by { |x| x }.transform_values(&:size)`
|
|
13
|
+
# - `group_by { |x| x }.transform_values { |v| v.length }`
|
|
14
|
+
#
|
|
15
|
+
# @safety
|
|
16
|
+
# This cop is unsafe because it cannot guarantee that the receiver
|
|
17
|
+
# is an `Enumerable` by static analysis, so the correction may
|
|
18
|
+
# not be actually equivalent.
|
|
19
|
+
#
|
|
20
|
+
# @example
|
|
21
|
+
# # bad
|
|
22
|
+
# array.each_with_object(Hash.new(0)) { |item, counts| counts[item] += 1 }
|
|
23
|
+
#
|
|
24
|
+
# # bad
|
|
25
|
+
# array.group_by(&:itself).transform_values(&:count)
|
|
26
|
+
#
|
|
27
|
+
# # bad
|
|
28
|
+
# array.group_by { |item| item }.transform_values(&:size)
|
|
29
|
+
#
|
|
30
|
+
# # bad
|
|
31
|
+
# array.group_by { |item| item }.transform_values { |v| v.length }
|
|
32
|
+
#
|
|
33
|
+
# # good
|
|
34
|
+
# array.tally
|
|
35
|
+
#
|
|
36
|
+
class TallyMethod < Base
|
|
37
|
+
extend AutoCorrector
|
|
38
|
+
extend TargetRubyVersion
|
|
39
|
+
include RangeHelp
|
|
40
|
+
|
|
41
|
+
minimum_target_ruby_version 2.7
|
|
42
|
+
|
|
43
|
+
MSG_EACH_WITH_OBJECT = 'Use `tally` instead of `each_with_object`.'
|
|
44
|
+
MSG_GROUP_BY = 'Use `tally` instead of `group_by` and `transform_values`.'
|
|
45
|
+
RESTRICT_ON_SEND = %i[each_with_object transform_values].freeze
|
|
46
|
+
COUNTING_METHODS = %i[count size length].to_set.freeze
|
|
47
|
+
|
|
48
|
+
# Pattern 1: collection.each_with_object(Hash.new(0)) { |elem, hash| hash[elem] += 1 }
|
|
49
|
+
# @!method tally_each_with_object?(node)
|
|
50
|
+
def_node_matcher :tally_each_with_object?, <<~PATTERN
|
|
51
|
+
{
|
|
52
|
+
(block
|
|
53
|
+
(call _ :each_with_object
|
|
54
|
+
(send (const {nil? cbase} :Hash) :new (int 0)))
|
|
55
|
+
(args (arg _elem) (arg _hash))
|
|
56
|
+
(op_asgn
|
|
57
|
+
(send (lvar _hash) :[] (lvar _elem)) :+ (int 1)))
|
|
58
|
+
(numblock
|
|
59
|
+
(call _ :each_with_object
|
|
60
|
+
(send (const {nil? cbase} :Hash) :new (int 0)))
|
|
61
|
+
2
|
|
62
|
+
(op_asgn
|
|
63
|
+
(send (lvar :_2) :[] (lvar :_1)) :+ (int 1)))
|
|
64
|
+
}
|
|
65
|
+
PATTERN
|
|
66
|
+
|
|
67
|
+
# Pattern 2: collection.group_by(&:itself).transform_values(&:count/size/length)
|
|
68
|
+
# @!method tally_group_by_symbol?(node)
|
|
69
|
+
def_node_matcher :tally_group_by_symbol?, <<~PATTERN
|
|
70
|
+
(call
|
|
71
|
+
(call _ :group_by (block_pass (sym :itself)))
|
|
72
|
+
:transform_values
|
|
73
|
+
(block_pass (sym %COUNTING_METHODS)))
|
|
74
|
+
PATTERN
|
|
75
|
+
|
|
76
|
+
# Pattern 3: collection.group_by { |x| x }.transform_values(&:count/size/length)
|
|
77
|
+
# @!method tally_group_by_identity_block?(node)
|
|
78
|
+
def_node_matcher :tally_group_by_identity_block?, <<~PATTERN
|
|
79
|
+
(call
|
|
80
|
+
{
|
|
81
|
+
(block (call _ :group_by) (args (arg _x)) (lvar _x))
|
|
82
|
+
(numblock (call _ :group_by) 1 (lvar :_1))
|
|
83
|
+
(itblock (call _ :group_by) :it (lvar :it))
|
|
84
|
+
}
|
|
85
|
+
:transform_values
|
|
86
|
+
(block_pass (sym %COUNTING_METHODS)))
|
|
87
|
+
PATTERN
|
|
88
|
+
|
|
89
|
+
# Pattern 4: collection.group_by(&:itself).transform_values { |v| v.count/size/length }
|
|
90
|
+
# collection.group_by { |x| x }.transform_values { |v| v.count/size/length }
|
|
91
|
+
# @!method tally_group_by_transform_block?(node)
|
|
92
|
+
def_node_matcher :tally_group_by_transform_block?, <<~PATTERN
|
|
93
|
+
{
|
|
94
|
+
(block
|
|
95
|
+
(call
|
|
96
|
+
{
|
|
97
|
+
(call _ :group_by (block_pass (sym :itself)))
|
|
98
|
+
(block (call _ :group_by) (args (arg _x)) (lvar _x))
|
|
99
|
+
(numblock (call _ :group_by) 1 (lvar :_1))
|
|
100
|
+
(itblock (call _ :group_by) :it (lvar :it))
|
|
101
|
+
}
|
|
102
|
+
:transform_values)
|
|
103
|
+
(args (arg _v))
|
|
104
|
+
(send (lvar _v) %COUNTING_METHODS))
|
|
105
|
+
(numblock
|
|
106
|
+
(call
|
|
107
|
+
{
|
|
108
|
+
(call _ :group_by (block_pass (sym :itself)))
|
|
109
|
+
(block (call _ :group_by) (args (arg _x)) (lvar _x))
|
|
110
|
+
(numblock (call _ :group_by) 1 (lvar :_1))
|
|
111
|
+
(itblock (call _ :group_by) :it (lvar :it))
|
|
112
|
+
}
|
|
113
|
+
:transform_values)
|
|
114
|
+
1
|
|
115
|
+
(send (lvar :_1) %COUNTING_METHODS))
|
|
116
|
+
(itblock
|
|
117
|
+
(call
|
|
118
|
+
{
|
|
119
|
+
(call _ :group_by (block_pass (sym :itself)))
|
|
120
|
+
(block (call _ :group_by) (args (arg _x)) (lvar _x))
|
|
121
|
+
(numblock (call _ :group_by) 1 (lvar :_1))
|
|
122
|
+
(itblock (call _ :group_by) :it (lvar :it))
|
|
123
|
+
}
|
|
124
|
+
:transform_values)
|
|
125
|
+
:it
|
|
126
|
+
(send (lvar :it) %COUNTING_METHODS))
|
|
127
|
+
}
|
|
128
|
+
PATTERN
|
|
129
|
+
def on_send(node)
|
|
130
|
+
if node.method?(:each_with_object)
|
|
131
|
+
check_each_with_object(node)
|
|
132
|
+
elsif node.method?(:transform_values)
|
|
133
|
+
check_transform_values(node)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
alias on_csend on_send
|
|
137
|
+
|
|
138
|
+
private
|
|
139
|
+
|
|
140
|
+
def check_each_with_object(node)
|
|
141
|
+
block_node = node.block_node
|
|
142
|
+
return unless block_node
|
|
143
|
+
return unless tally_each_with_object?(block_node)
|
|
144
|
+
|
|
145
|
+
add_offense(node.loc.selector, message: MSG_EACH_WITH_OBJECT) do |corrector|
|
|
146
|
+
corrector.replace(replacement_range(node, block_node), 'tally')
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def check_transform_values(node)
|
|
151
|
+
if tally_group_by_symbol?(node) || tally_group_by_identity_block?(node)
|
|
152
|
+
register_group_by_offense(node, node)
|
|
153
|
+
elsif (block_node = node.block_node) && tally_group_by_transform_block?(block_node)
|
|
154
|
+
register_group_by_offense(node, block_node)
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def register_group_by_offense(transform_node, end_node)
|
|
159
|
+
group_by_node = group_by_send_node(transform_node)
|
|
160
|
+
|
|
161
|
+
add_offense(group_by_node.loc.selector, message: MSG_GROUP_BY) do |corrector|
|
|
162
|
+
corrector.replace(replacement_range(group_by_node, end_node), 'tally')
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def group_by_send_node(transform_node)
|
|
167
|
+
receiver = transform_node.receiver
|
|
168
|
+
if receiver.type?(:any_block)
|
|
169
|
+
receiver.send_node
|
|
170
|
+
else
|
|
171
|
+
receiver
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def replacement_range(start_node, end_node)
|
|
176
|
+
range_between(start_node.loc.selector.begin_pos, end_node.source_range.end_pos)
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
@@ -10,6 +10,9 @@ module RuboCop
|
|
|
10
10
|
# for all parenthesized multi-line method calls with arguments.
|
|
11
11
|
# * `comma`: Requires a comma after the last argument, but only for
|
|
12
12
|
# parenthesized method calls where each argument is on its own line.
|
|
13
|
+
# * `diff_comma`: Requires a comma after the last argument, but only
|
|
14
|
+
# when that argument is followed by an immediate newline, even if
|
|
15
|
+
# there is an inline comment on the same line.
|
|
13
16
|
# * `no_comma`: Requires that there is no comma after the last
|
|
14
17
|
# argument.
|
|
15
18
|
#
|
|
@@ -75,6 +78,48 @@ module RuboCop
|
|
|
75
78
|
# 2,
|
|
76
79
|
# )
|
|
77
80
|
#
|
|
81
|
+
# @example EnforcedStyleForMultiline: diff_comma
|
|
82
|
+
# # bad
|
|
83
|
+
# method(1, 2,)
|
|
84
|
+
#
|
|
85
|
+
# # good
|
|
86
|
+
# method(1, 2)
|
|
87
|
+
#
|
|
88
|
+
# # good
|
|
89
|
+
# method(
|
|
90
|
+
# 1, 2,
|
|
91
|
+
# 3,
|
|
92
|
+
# )
|
|
93
|
+
#
|
|
94
|
+
# # good
|
|
95
|
+
# method(
|
|
96
|
+
# 1, 2, 3,
|
|
97
|
+
# )
|
|
98
|
+
#
|
|
99
|
+
# # good
|
|
100
|
+
# method(
|
|
101
|
+
# 1,
|
|
102
|
+
# 2,
|
|
103
|
+
# )
|
|
104
|
+
#
|
|
105
|
+
# # bad
|
|
106
|
+
# method(1, [
|
|
107
|
+
# 2,
|
|
108
|
+
# ],)
|
|
109
|
+
#
|
|
110
|
+
# # good
|
|
111
|
+
# method(1, [
|
|
112
|
+
# 2,
|
|
113
|
+
# ])
|
|
114
|
+
#
|
|
115
|
+
# # bad
|
|
116
|
+
# object[1, 2,
|
|
117
|
+
# 3, 4,]
|
|
118
|
+
#
|
|
119
|
+
# # good
|
|
120
|
+
# object[1, 2,
|
|
121
|
+
# 3, 4]
|
|
122
|
+
#
|
|
78
123
|
# @example EnforcedStyleForMultiline: no_comma (default)
|
|
79
124
|
# # bad
|
|
80
125
|
# method(1, 2,)
|
|
@@ -64,7 +64,7 @@ module RuboCop
|
|
|
64
64
|
|
|
65
65
|
MSG = 'Useless trailing comma present in block arguments.'
|
|
66
66
|
|
|
67
|
-
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
|
67
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler, InternalAffairs/ItblockHandler
|
|
68
68
|
# lambda literal (`->`) never has block arguments.
|
|
69
69
|
return if node.send_node.lambda_literal?
|
|
70
70
|
return unless useless_trailing_comma?(node)
|
|
@@ -7,26 +7,26 @@ module RuboCop
|
|
|
7
7
|
#
|
|
8
8
|
# @example
|
|
9
9
|
# # bad
|
|
10
|
-
# a, b, _ = foo
|
|
11
|
-
# a, b, _, = foo
|
|
12
|
-
# a, _, _ = foo
|
|
13
|
-
# a, _, _, = foo
|
|
10
|
+
# a, b, _ = foo
|
|
11
|
+
# a, b, _, = foo
|
|
12
|
+
# a, _, _ = foo
|
|
13
|
+
# a, _, _, = foo
|
|
14
14
|
#
|
|
15
15
|
# # good
|
|
16
|
-
# a, b, = foo
|
|
17
|
-
# a, = foo
|
|
18
|
-
# *a, b, _ = foo
|
|
16
|
+
# a, b, = foo
|
|
17
|
+
# a, = foo
|
|
18
|
+
# *a, b, _ = foo
|
|
19
19
|
# # => We need to know to not include 2 variables in a
|
|
20
|
-
# a, *b, _ = foo
|
|
21
|
-
# # => The correction `a, *b, = foo
|
|
20
|
+
# a, *b, _ = foo
|
|
21
|
+
# # => The correction `a, *b, = foo` is a syntax error
|
|
22
22
|
#
|
|
23
23
|
# @example AllowNamedUnderscoreVariables: true (default)
|
|
24
24
|
# # good
|
|
25
|
-
# a, b, _something = foo
|
|
25
|
+
# a, b, _something = foo
|
|
26
26
|
#
|
|
27
27
|
# @example AllowNamedUnderscoreVariables: false
|
|
28
28
|
# # bad
|
|
29
|
-
# a, b, _something = foo
|
|
29
|
+
# a, b, _something = foo
|
|
30
30
|
#
|
|
31
31
|
class TrailingUnderscoreVariable < Base
|
|
32
32
|
include SurroundingSpace
|
|
@@ -20,7 +20,6 @@ module RuboCop
|
|
|
20
20
|
# # do a different thing...
|
|
21
21
|
# end
|
|
22
22
|
class UnlessElse < Base
|
|
23
|
-
include RangeHelp
|
|
24
23
|
extend AutoCorrector
|
|
25
24
|
|
|
26
25
|
MSG = 'Do not use `unless` with `else`. Rewrite these with the positive case first.'
|
|
@@ -29,25 +28,27 @@ module RuboCop
|
|
|
29
28
|
return unless node.unless? && node.else?
|
|
30
29
|
|
|
31
30
|
add_offense(node) do |corrector|
|
|
32
|
-
body_range = range_between_condition_and_else(node, node.condition)
|
|
33
|
-
else_range = range_between_else_and_end(node)
|
|
34
|
-
|
|
35
31
|
next if part_of_ignored_node?(node)
|
|
36
32
|
|
|
37
33
|
corrector.replace(node.loc.keyword, 'if')
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
|
|
35
|
+
body_range = range_between_condition_and_else(node)
|
|
36
|
+
else_range = range_between_else_and_end(node)
|
|
37
|
+
|
|
38
|
+
corrector.swap(body_range, else_range)
|
|
40
39
|
end
|
|
41
40
|
|
|
42
41
|
ignore_node(node)
|
|
43
42
|
end
|
|
44
43
|
|
|
45
|
-
def range_between_condition_and_else(node
|
|
46
|
-
|
|
44
|
+
def range_between_condition_and_else(node)
|
|
45
|
+
range = node.loc.begin ? node.loc.begin.end : node.condition.source_range
|
|
46
|
+
|
|
47
|
+
range.end.join(node.loc.else.begin)
|
|
47
48
|
end
|
|
48
49
|
|
|
49
50
|
def range_between_else_and_end(node)
|
|
50
|
-
|
|
51
|
+
node.loc.else.end.join(node.loc.end.begin)
|
|
51
52
|
end
|
|
52
53
|
end
|
|
53
54
|
end
|
data/lib/rubocop/cop/team.rb
CHANGED
|
@@ -177,8 +177,8 @@ module RuboCop
|
|
|
177
177
|
# @return [Array<cop>]
|
|
178
178
|
def roundup_relevant_cops(processed_source)
|
|
179
179
|
cops.select do |cop|
|
|
180
|
-
next true if processed_source.comment_config.cop_opted_in?(cop)
|
|
181
180
|
next false if cop.excluded_file?(processed_source.file_path)
|
|
181
|
+
next true if processed_source.comment_config.cop_opted_in?(cop)
|
|
182
182
|
next false unless @registry.enabled?(cop, @config)
|
|
183
183
|
|
|
184
184
|
support_target_ruby_version?(cop) && support_target_rails_version?(cop)
|
|
@@ -211,10 +211,10 @@ module RuboCop
|
|
|
211
211
|
|
|
212
212
|
each_corrector(report) do |to_merge|
|
|
213
213
|
suppress_clobbering do
|
|
214
|
-
if
|
|
215
|
-
corrector.import!(to_merge, offset: offset)
|
|
216
|
-
else
|
|
214
|
+
if corrector.source_buffer == to_merge.source_buffer
|
|
217
215
|
corrector.merge!(to_merge)
|
|
216
|
+
else
|
|
217
|
+
corrector.import!(to_merge, offset: offset)
|
|
218
218
|
end
|
|
219
219
|
end
|
|
220
220
|
end
|
data/lib/rubocop/cop/util.rb
CHANGED
|
@@ -117,10 +117,9 @@ module RuboCop
|
|
|
117
117
|
# with calls chained to the end of it.
|
|
118
118
|
def first_part_of_call_chain(node)
|
|
119
119
|
while node
|
|
120
|
-
|
|
121
|
-
when :send
|
|
120
|
+
if node.call_type?
|
|
122
121
|
node = node.receiver
|
|
123
|
-
|
|
122
|
+
elsif node.any_block_type?
|
|
124
123
|
node = node.send_node
|
|
125
124
|
else
|
|
126
125
|
break
|
|
@@ -71,6 +71,16 @@ module RuboCop
|
|
|
71
71
|
name && @source.include?('{')
|
|
72
72
|
end
|
|
73
73
|
|
|
74
|
+
def variable_width?
|
|
75
|
+
!!width&.start_with?('*')
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def variable_width_argument_number
|
|
79
|
+
return unless variable_width?
|
|
80
|
+
|
|
81
|
+
width == '*' ? 1 : width.match(DIGIT_DOLLAR)['arg_number'].to_i
|
|
82
|
+
end
|
|
83
|
+
|
|
74
84
|
# Number of arguments required for the format sequence
|
|
75
85
|
def arity
|
|
76
86
|
@source.scan('*').count + 1
|
|
@@ -254,8 +254,8 @@ module RuboCop
|
|
|
254
254
|
end
|
|
255
255
|
end
|
|
256
256
|
|
|
257
|
-
# Mix-in module for
|
|
258
|
-
module
|
|
257
|
+
# Mix-in module for operator control structures.
|
|
258
|
+
module Operator
|
|
259
259
|
def always_run?
|
|
260
260
|
left_body?
|
|
261
261
|
end
|
|
@@ -263,7 +263,15 @@ module RuboCop
|
|
|
263
263
|
|
|
264
264
|
# left_body && right_body
|
|
265
265
|
class And < Base
|
|
266
|
-
include
|
|
266
|
+
include Operator
|
|
267
|
+
|
|
268
|
+
define_predicate :left_body?, child_index: 0
|
|
269
|
+
define_predicate :right_body?, child_index: 1
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
# left_body &&= right_body
|
|
273
|
+
class AndAsgn < Base
|
|
274
|
+
include Operator
|
|
267
275
|
|
|
268
276
|
define_predicate :left_body?, child_index: 0
|
|
269
277
|
define_predicate :right_body?, child_index: 1
|
|
@@ -271,7 +279,23 @@ module RuboCop
|
|
|
271
279
|
|
|
272
280
|
# left_body || right_body
|
|
273
281
|
class Or < Base
|
|
274
|
-
include
|
|
282
|
+
include Operator
|
|
283
|
+
|
|
284
|
+
define_predicate :left_body?, child_index: 0
|
|
285
|
+
define_predicate :right_body?, child_index: 1
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
# left_body ||= right_body
|
|
289
|
+
class OrAsgn < Base
|
|
290
|
+
include Operator
|
|
291
|
+
|
|
292
|
+
define_predicate :left_body?, child_index: 0
|
|
293
|
+
define_predicate :right_body?, child_index: 1
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
# e.g. left_body += right_body
|
|
297
|
+
class OpAsgn < Base
|
|
298
|
+
include Operator
|
|
275
299
|
|
|
276
300
|
define_predicate :left_body?, child_index: 0
|
|
277
301
|
define_predicate :right_body?, child_index: 1
|
|
@@ -322,8 +346,8 @@ module RuboCop
|
|
|
322
346
|
end
|
|
323
347
|
end
|
|
324
348
|
|
|
325
|
-
CLASSES_BY_TYPE = Base.classes.
|
|
326
|
-
|
|
349
|
+
CLASSES_BY_TYPE = Base.classes.to_h do |klass|
|
|
350
|
+
[klass.type, klass]
|
|
327
351
|
end
|
|
328
352
|
end
|
|
329
353
|
end
|
|
@@ -194,10 +194,10 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
|
194
194
|
|
|
195
195
|
def configurations(department, cop, cop_config)
|
|
196
196
|
header = ['Name', 'Default value', 'Configurable values']
|
|
197
|
-
configs = cop_config
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
197
|
+
configs = cop_config.each_key.reject do |key|
|
|
198
|
+
key == 'AllowMultipleStyles' ||
|
|
199
|
+
(key != 'SupportedTypes' && key.start_with?('Supported'))
|
|
200
|
+
end
|
|
201
201
|
return '' if configs.empty?
|
|
202
202
|
|
|
203
203
|
content = configs.map do |name|
|
|
@@ -14,11 +14,17 @@ module RuboCop
|
|
|
14
14
|
# @api private
|
|
15
15
|
COP_NAME_PATTERN = '([A-Za-z]\w+/)*(?:[A-Za-z]\w+)'
|
|
16
16
|
# @api private
|
|
17
|
+
COP_NAME_PATTERN_NC = '(?:[A-Za-z]\w+/)*[A-Za-z]\w+'
|
|
18
|
+
# @api private
|
|
19
|
+
COP_NAMES_PATTERN_NC = "(?:#{COP_NAME_PATTERN_NC} , )*#{COP_NAME_PATTERN_NC}"
|
|
20
|
+
# @api private
|
|
17
21
|
COP_NAMES_PATTERN = "(?:#{COP_NAME_PATTERN} , )*#{COP_NAME_PATTERN}"
|
|
18
22
|
# @api private
|
|
19
23
|
COPS_PATTERN = "(all|#{COP_NAMES_PATTERN})"
|
|
20
24
|
# @api private
|
|
21
|
-
|
|
25
|
+
PUSH_POP_ARGS_PATTERN = "([+\\-]#{COP_NAME_PATTERN_NC}(?:\\s+[+\\-]#{COP_NAME_PATTERN_NC})*)"
|
|
26
|
+
# @api private
|
|
27
|
+
AVAILABLE_MODES = %w[disable enable todo push pop].freeze
|
|
22
28
|
# @api private
|
|
23
29
|
DIRECTIVE_MARKER_PATTERN = '# rubocop : '
|
|
24
30
|
# @api private
|
|
@@ -27,7 +33,7 @@ module RuboCop
|
|
|
27
33
|
DIRECTIVE_HEADER_PATTERN = "#{DIRECTIVE_MARKER_PATTERN}((?:#{AVAILABLE_MODES.join('|')}))\\b"
|
|
28
34
|
# @api private
|
|
29
35
|
DIRECTIVE_COMMENT_REGEXP = Regexp.new(
|
|
30
|
-
"#{DIRECTIVE_HEADER_PATTERN}
|
|
36
|
+
"#{DIRECTIVE_HEADER_PATTERN}(?:\\s+#{COPS_PATTERN}|\\s+#{PUSH_POP_ARGS_PATTERN})?"
|
|
31
37
|
.gsub(' ', '\s*')
|
|
32
38
|
)
|
|
33
39
|
# @api private
|
|
@@ -46,7 +52,8 @@ module RuboCop
|
|
|
46
52
|
def initialize(comment, cop_registry = Cop::Registry.global)
|
|
47
53
|
@comment = comment
|
|
48
54
|
@cop_registry = cop_registry
|
|
49
|
-
|
|
55
|
+
match_data = comment.text.match(DIRECTIVE_COMMENT_REGEXP)
|
|
56
|
+
@match_data = match_data&.pre_match&.match?(/\A#\s*\z/) ? nil : match_data
|
|
50
57
|
@mode, @cops = match_captures
|
|
51
58
|
end
|
|
52
59
|
|
|
@@ -58,6 +65,7 @@ module RuboCop
|
|
|
58
65
|
# Checks if the comment is malformed as a `# rubocop:` directive
|
|
59
66
|
def malformed?
|
|
60
67
|
return true if !start_with_marker? || @match_data.nil?
|
|
68
|
+
return true if missing_cop_name?
|
|
61
69
|
|
|
62
70
|
tail = @match_data.post_match.lstrip
|
|
63
71
|
!(tail.empty? || tail.start_with?(TRAILING_COMMENT_MARKER))
|
|
@@ -65,6 +73,8 @@ module RuboCop
|
|
|
65
73
|
|
|
66
74
|
# Checks if the directive comment is missing a cop name
|
|
67
75
|
def missing_cop_name?
|
|
76
|
+
return false if push? || pop?
|
|
77
|
+
|
|
68
78
|
MALFORMED_DIRECTIVE_WITHOUT_COP_NAME_REGEXP.match?(comment.text)
|
|
69
79
|
end
|
|
70
80
|
|
|
@@ -88,7 +98,13 @@ module RuboCop
|
|
|
88
98
|
|
|
89
99
|
# Returns match captures to directive comment pattern
|
|
90
100
|
def match_captures
|
|
91
|
-
@match_captures ||= @match_data
|
|
101
|
+
@match_captures ||= @match_data && begin
|
|
102
|
+
captures = @match_data.captures
|
|
103
|
+
mode = captures[0]
|
|
104
|
+
# COPS_PATTERN is at captures[1], PUSH_POP_ARGS_PATTERN is at captures[4]
|
|
105
|
+
cops = captures[1] || captures[4]
|
|
106
|
+
[mode, cops]
|
|
107
|
+
end
|
|
92
108
|
end
|
|
93
109
|
|
|
94
110
|
# Checks if this directive disables cops
|
|
@@ -101,6 +117,21 @@ module RuboCop
|
|
|
101
117
|
mode == 'enable'
|
|
102
118
|
end
|
|
103
119
|
|
|
120
|
+
# Checks if this directive is a push
|
|
121
|
+
def push?
|
|
122
|
+
mode == 'push'
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Checks if this directive is a pop
|
|
126
|
+
def pop?
|
|
127
|
+
mode == 'pop'
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Returns the push arguments as a hash of cop names with their operations
|
|
131
|
+
def push_args
|
|
132
|
+
@push_args ||= parse_push_args
|
|
133
|
+
end
|
|
134
|
+
|
|
104
135
|
# Checks if this directive enables all cops
|
|
105
136
|
def enabled_all?
|
|
106
137
|
!disabled? && all_cops?
|
|
@@ -176,5 +207,18 @@ module RuboCop
|
|
|
176
207
|
def exclude_lint_department_cops(cops)
|
|
177
208
|
cops - [LINT_REDUNDANT_DIRECTIVE_COP, LINT_SYNTAX_COP]
|
|
178
209
|
end
|
|
210
|
+
|
|
211
|
+
def parse_push_args
|
|
212
|
+
return {} unless push? && cops
|
|
213
|
+
|
|
214
|
+
args = {}
|
|
215
|
+
cops.split.each do |cop_spec|
|
|
216
|
+
op = cop_spec[0]
|
|
217
|
+
cop_name = cop_spec[1..]
|
|
218
|
+
args[op] ||= []
|
|
219
|
+
args[op] << cop_name
|
|
220
|
+
end
|
|
221
|
+
args
|
|
222
|
+
end
|
|
179
223
|
end
|
|
180
224
|
end
|
|
@@ -47,8 +47,11 @@ module RuboCop
|
|
|
47
47
|
def report_highlighted_area(highlighted_area)
|
|
48
48
|
space_area = highlighted_area.source_buffer.slice(0...highlighted_area.begin_pos)
|
|
49
49
|
source_area = highlighted_area.source
|
|
50
|
-
output.puts("#{'
|
|
51
|
-
|
|
50
|
+
output.puts("#{to_whitespace(space_area)}#{'^' * Unicode::DisplayWidth.of(source_area)}")
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def to_whitespace(string)
|
|
54
|
+
"#{string.delete("^\t")}#{' ' * Unicode::DisplayWidth.of(string.delete("\t"))}"
|
|
52
55
|
end
|
|
53
56
|
end
|
|
54
57
|
end
|
|
@@ -27,6 +27,7 @@ module RuboCop
|
|
|
27
27
|
References
|
|
28
28
|
Safe
|
|
29
29
|
SafeAutoCorrect
|
|
30
|
+
Severity
|
|
30
31
|
StyleGuide
|
|
31
32
|
VersionAdded
|
|
32
33
|
VersionChanged
|
|
@@ -232,7 +233,7 @@ module RuboCop
|
|
|
232
233
|
|
|
233
234
|
def output_exclude_list(output_buffer, offending_files, cop_name)
|
|
234
235
|
require 'pathname'
|
|
235
|
-
parent = Pathname.new(
|
|
236
|
+
parent = Pathname.new(PathUtil.pwd)
|
|
236
237
|
|
|
237
238
|
output_buffer.puts ' Exclude:'
|
|
238
239
|
excludes(offending_files, cop_name, parent).each do |exclude_path|
|
|
@@ -57,7 +57,7 @@ module RuboCop
|
|
|
57
57
|
if output_path
|
|
58
58
|
dir_path = File.dirname(output_path)
|
|
59
59
|
FileUtils.mkdir_p(dir_path)
|
|
60
|
-
output = File.open(output_path, 'w')
|
|
60
|
+
output = File.open(output_path, 'w') # rubocop:disable Style/FileOpen
|
|
61
61
|
else
|
|
62
62
|
output = $stdout
|
|
63
63
|
end
|
|
@@ -86,7 +86,7 @@ module RuboCop
|
|
|
86
86
|
|
|
87
87
|
def builtin_formatter_class(specified_key)
|
|
88
88
|
matching_keys = BUILTIN_FORMATTERS_FOR_KEYS.keys.select do |key|
|
|
89
|
-
|
|
89
|
+
key.start_with?("[#{specified_key}]") || specified_key == key.delete('[]')
|
|
90
90
|
end
|
|
91
91
|
|
|
92
92
|
if matching_keys.empty?
|
|
@@ -93,7 +93,7 @@ module RuboCop
|
|
|
93
93
|
|
|
94
94
|
def classname_attribute_value(file)
|
|
95
95
|
@classname_attribute_value_cache ||= Hash.new do |hash, key|
|
|
96
|
-
hash[key] = key.delete_suffix('.rb').gsub("#{
|
|
96
|
+
hash[key] = key.delete_suffix('.rb').gsub("#{PathUtil.pwd}/", '').tr('/', '.')
|
|
97
97
|
end
|
|
98
98
|
@classname_attribute_value_cache[file]
|
|
99
99
|
end
|
|
@@ -39,8 +39,11 @@ module RuboCop
|
|
|
39
39
|
def report_highlighted_area(highlighted_area)
|
|
40
40
|
space_area = highlighted_area.source_buffer.slice(0...highlighted_area.begin_pos)
|
|
41
41
|
source_area = highlighted_area.source
|
|
42
|
-
output.puts("# #{'
|
|
43
|
-
|
|
42
|
+
output.puts("# #{to_whitespace(space_area)}#{'^' * Unicode::DisplayWidth.of(source_area)}")
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def to_whitespace(string)
|
|
46
|
+
"#{string.delete("^\t")}#{' ' * Unicode::DisplayWidth.of(string.delete("\t"))}"
|
|
44
47
|
end
|
|
45
48
|
|
|
46
49
|
def report_offense(file, offense)
|