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
|
@@ -29,25 +29,30 @@ module RuboCop
|
|
|
29
29
|
# @example IgnoreModules: false (default)
|
|
30
30
|
# # bad
|
|
31
31
|
# class Foo
|
|
32
|
-
# MyClass = Struct.new
|
|
32
|
+
# MyClass = Struct.new
|
|
33
33
|
# end
|
|
34
34
|
#
|
|
35
35
|
# # good
|
|
36
36
|
# class Foo
|
|
37
|
-
# MyClass = Struct.new
|
|
37
|
+
# MyClass = Struct.new
|
|
38
38
|
# public_constant :MyClass
|
|
39
39
|
# end
|
|
40
40
|
#
|
|
41
41
|
# @example IgnoreModules: true
|
|
42
42
|
# # good
|
|
43
43
|
# class Foo
|
|
44
|
-
# MyClass = Struct.new
|
|
44
|
+
# MyClass = Struct.new
|
|
45
45
|
# end
|
|
46
46
|
#
|
|
47
47
|
class ConstantVisibility < Base
|
|
48
48
|
MSG = 'Explicitly make `%<constant_name>s` public or private using ' \
|
|
49
49
|
'either `#public_constant` or `#private_constant`.'
|
|
50
50
|
|
|
51
|
+
# @!method visibility_declaration_for(node)
|
|
52
|
+
def_node_matcher :visibility_declaration_for, <<~PATTERN
|
|
53
|
+
(send nil? {:public_constant :private_constant} $...)
|
|
54
|
+
PATTERN
|
|
55
|
+
|
|
51
56
|
def on_casgn(node)
|
|
52
57
|
return unless class_or_module_scope?(node)
|
|
53
58
|
return if visibility_declaration?(node)
|
|
@@ -77,20 +82,20 @@ module RuboCop
|
|
|
77
82
|
end
|
|
78
83
|
end
|
|
79
84
|
|
|
85
|
+
# rubocop:disable Metrics/AbcSize
|
|
80
86
|
def visibility_declaration?(node)
|
|
81
87
|
node.parent.each_child_node(:send).any? do |child|
|
|
82
|
-
visibility_declaration_for
|
|
83
|
-
end
|
|
84
|
-
end
|
|
88
|
+
next false unless (arguments = visibility_declaration_for(child))
|
|
85
89
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
+
arguments = arguments.first.children.first.to_a if arguments.first&.splat_type?
|
|
91
|
+
constant_values = arguments.map do |argument|
|
|
92
|
+
argument.value.to_sym if argument.respond_to?(:value)
|
|
93
|
+
end
|
|
90
94
|
|
|
91
|
-
|
|
92
|
-
|
|
95
|
+
constant_values.include?(node.name)
|
|
96
|
+
end
|
|
93
97
|
end
|
|
98
|
+
# rubocop:enable Metrics/AbcSize
|
|
94
99
|
end
|
|
95
100
|
end
|
|
96
101
|
end
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Style
|
|
6
|
-
#
|
|
6
|
+
# Checks that a copyright notice was given in each source file.
|
|
7
7
|
#
|
|
8
8
|
# The default regexp for an acceptable copyright notice can be found in
|
|
9
9
|
# config/default.yml. The default can be changed as follows:
|
|
@@ -62,12 +62,12 @@ module RuboCop
|
|
|
62
62
|
#
|
|
63
63
|
# @example AllowedConstants: ['ClassMethods']
|
|
64
64
|
#
|
|
65
|
-
#
|
|
66
|
-
#
|
|
67
|
-
#
|
|
68
|
-
#
|
|
69
|
-
#
|
|
70
|
-
#
|
|
65
|
+
# # good
|
|
66
|
+
# module A
|
|
67
|
+
# module ClassMethods
|
|
68
|
+
# # ...
|
|
69
|
+
# end
|
|
70
|
+
# end
|
|
71
71
|
#
|
|
72
72
|
class Documentation < Base
|
|
73
73
|
include DocumentationComment
|
|
@@ -97,14 +97,14 @@ module RuboCop
|
|
|
97
97
|
#
|
|
98
98
|
# @example AllowedMethods: ['method_missing', 'respond_to_missing?']
|
|
99
99
|
#
|
|
100
|
-
#
|
|
101
|
-
#
|
|
102
|
-
#
|
|
103
|
-
#
|
|
104
|
-
#
|
|
105
|
-
#
|
|
106
|
-
#
|
|
107
|
-
#
|
|
100
|
+
# # good
|
|
101
|
+
# class Foo
|
|
102
|
+
# def method_missing(name, *args)
|
|
103
|
+
# end
|
|
104
|
+
#
|
|
105
|
+
# def respond_to_missing?(symbol, include_private)
|
|
106
|
+
# end
|
|
107
|
+
# end
|
|
108
108
|
#
|
|
109
109
|
class DocumentationMethod < Base
|
|
110
110
|
include DocumentationComment
|
|
@@ -26,7 +26,7 @@ module RuboCop
|
|
|
26
26
|
|
|
27
27
|
MSG = 'Use `Integer#times` for a simple loop which iterates a fixed number of times.'
|
|
28
28
|
|
|
29
|
-
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
|
29
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler, InternalAffairs/ItblockHandler
|
|
30
30
|
return unless offending?(node)
|
|
31
31
|
|
|
32
32
|
send_node = node.send_node
|
|
@@ -28,7 +28,7 @@ module RuboCop
|
|
|
28
28
|
|
|
29
29
|
MSG = 'Omit pipes for the empty block parameters.'
|
|
30
30
|
|
|
31
|
-
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
|
31
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler, InternalAffairs/ItblockHandler
|
|
32
32
|
send_node = node.send_node
|
|
33
33
|
check(node) unless send_node.send_type? && send_node.lambda_literal?
|
|
34
34
|
end
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Style
|
|
6
|
+
# Enforces consistent style for empty class definitions.
|
|
7
|
+
#
|
|
8
|
+
# This cop can enforce either a standard class definition or `Class.new`
|
|
9
|
+
# for classes with no body.
|
|
10
|
+
#
|
|
11
|
+
# The supported styles are:
|
|
12
|
+
#
|
|
13
|
+
# * class_keyword (default) - prefer standard class definition over `Class.new`
|
|
14
|
+
# * class_new - prefer `Class.new` over class definition
|
|
15
|
+
#
|
|
16
|
+
# One difference between the two styles is that the `Class.new` form does not make
|
|
17
|
+
# the subclass name available to the base class's `inherited` callback.
|
|
18
|
+
# For this reason, `EnforcedStyle: class_keyword` is set as the default style.
|
|
19
|
+
# Class definitions without a superclass, which are not involved in inheritance,
|
|
20
|
+
# are not detected. This ensures safe detection regardless of the applied style.
|
|
21
|
+
# This avoids overlapping responsibilities with the `Lint/EmptyClass` cop.
|
|
22
|
+
#
|
|
23
|
+
# Use `AllowedParentClasses` to permit both styles for specific parent classes.
|
|
24
|
+
# For example, adding `StandardError` allows both `Error = Class.new(StandardError)`
|
|
25
|
+
# and `class Error < StandardError; end` regardless of the enforced style.
|
|
26
|
+
#
|
|
27
|
+
# @example EnforcedStyle: class_keyword (default)
|
|
28
|
+
# # bad
|
|
29
|
+
# FooError = Class.new(StandardError)
|
|
30
|
+
#
|
|
31
|
+
# # okish
|
|
32
|
+
# class FooError < StandardError; end
|
|
33
|
+
#
|
|
34
|
+
# # good
|
|
35
|
+
# class FooError < StandardError
|
|
36
|
+
# end
|
|
37
|
+
#
|
|
38
|
+
# @example EnforcedStyle: class_new
|
|
39
|
+
# # bad
|
|
40
|
+
# class FooError < StandardError
|
|
41
|
+
# end
|
|
42
|
+
#
|
|
43
|
+
# # bad
|
|
44
|
+
# class FooError < StandardError; end
|
|
45
|
+
#
|
|
46
|
+
# # good
|
|
47
|
+
# FooError = Class.new(StandardError)
|
|
48
|
+
#
|
|
49
|
+
# @example AllowedParentClasses: ['StandardError']
|
|
50
|
+
# # good - allowed regardless of EnforcedStyle
|
|
51
|
+
# FooError = Class.new(StandardError)
|
|
52
|
+
#
|
|
53
|
+
# # good - allowed regardless of EnforcedStyle
|
|
54
|
+
# class FooError < StandardError
|
|
55
|
+
# end
|
|
56
|
+
#
|
|
57
|
+
class EmptyClassDefinition < Base
|
|
58
|
+
include ConfigurableEnforcedStyle
|
|
59
|
+
extend AutoCorrector
|
|
60
|
+
|
|
61
|
+
MSG_CLASS_KEYWORD =
|
|
62
|
+
'Use the `class` keyword instead of `Class.new` to define an empty class.'
|
|
63
|
+
MSG_CLASS_NEW = 'Use `Class.new` instead of the `class` keyword to define an empty class.'
|
|
64
|
+
|
|
65
|
+
# @!method class_new_assignment(node)
|
|
66
|
+
def_node_matcher :class_new_assignment, <<~PATTERN
|
|
67
|
+
(casgn _ _ $(send (const _ :Class) :new _))
|
|
68
|
+
PATTERN
|
|
69
|
+
|
|
70
|
+
def on_casgn(node)
|
|
71
|
+
return unless %i[class_keyword class_definition].include?(style)
|
|
72
|
+
return unless (class_new_node = class_new_assignment(node))
|
|
73
|
+
return if (arg = class_new_node.first_argument) && !arg.const_type?
|
|
74
|
+
return if allowed_parent_class?(class_new_node.first_argument.source)
|
|
75
|
+
|
|
76
|
+
add_offense(node, message: MSG_CLASS_KEYWORD) do |corrector|
|
|
77
|
+
autocorrect_class_new(corrector, node, class_new_node)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def on_class(node)
|
|
82
|
+
return unless style == :class_new
|
|
83
|
+
return unless node.parent_class
|
|
84
|
+
return if (body = node.body) && !body.children.empty?
|
|
85
|
+
return if allowed_parent_class?(node.parent_class.source)
|
|
86
|
+
|
|
87
|
+
add_offense(node, message: MSG_CLASS_NEW) do |corrector|
|
|
88
|
+
autocorrect_class_definition(corrector, node)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
private
|
|
93
|
+
|
|
94
|
+
def allowed_parent_class?(parent_class_name)
|
|
95
|
+
allowed_parent_classes.include?(parent_class_name)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def allowed_parent_classes
|
|
99
|
+
cop_config.fetch('AllowedParentClasses', [])
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def autocorrect_class_new(corrector, node, class_new_node)
|
|
103
|
+
indent = ' ' * node.loc.column
|
|
104
|
+
class_name = node.name
|
|
105
|
+
parent_class_name = class_new_node.first_argument.source
|
|
106
|
+
|
|
107
|
+
corrector.replace(node, "class #{class_name} < #{parent_class_name}\n#{indent}end")
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def autocorrect_class_definition(corrector, node)
|
|
111
|
+
class_name = node.identifier.source
|
|
112
|
+
parent_class_name = node.parent_class.source
|
|
113
|
+
|
|
114
|
+
corrector.replace(node, "#{class_name} = Class.new(#{parent_class_name})")
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
@@ -23,7 +23,7 @@ module RuboCop
|
|
|
23
23
|
|
|
24
24
|
MSG = 'Omit parentheses for the empty lambda parameters.'
|
|
25
25
|
|
|
26
|
-
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
|
26
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler, InternalAffairs/ItblockHandler
|
|
27
27
|
send_node = node.send_node
|
|
28
28
|
return unless send_node.send_type?
|
|
29
29
|
|
|
@@ -3,12 +3,18 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Style
|
|
6
|
-
# Checks
|
|
6
|
+
# Checks that source files have no utf-8 encoding comments.
|
|
7
|
+
# Since Ruby 2.0, UTF-8 is the default source encoding, so
|
|
8
|
+
# these comments are no longer necessary and just add noise.
|
|
9
|
+
#
|
|
7
10
|
# @example
|
|
8
11
|
# # bad
|
|
9
12
|
# # encoding: UTF-8
|
|
10
13
|
# # coding: UTF-8
|
|
11
14
|
# # -*- coding: UTF-8 -*-
|
|
15
|
+
#
|
|
16
|
+
# # good
|
|
17
|
+
# # No encoding comment needed
|
|
12
18
|
class Encoding < Base
|
|
13
19
|
include RangeHelp
|
|
14
20
|
extend AutoCorrector
|
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Style
|
|
6
|
-
# Checks for END blocks.
|
|
6
|
+
# Checks for `END` blocks. `END` blocks are Perl-style constructs
|
|
7
|
+
# and `Kernel#at_exit` is the idiomatic Ruby alternative, as it's
|
|
8
|
+
# explicit and can be used anywhere.
|
|
7
9
|
#
|
|
8
10
|
# @example
|
|
9
11
|
# # bad
|
|
@@ -144,7 +144,7 @@ module RuboCop
|
|
|
144
144
|
MSG_REQUIRE_ALWAYS = 'Use endless method definitions.'
|
|
145
145
|
|
|
146
146
|
def on_def(node)
|
|
147
|
-
return if node.assignment_method?
|
|
147
|
+
return if node.assignment_method? || use_heredoc?(node)
|
|
148
148
|
|
|
149
149
|
case style
|
|
150
150
|
when :allow_single_line, :allow_always
|
|
@@ -157,6 +157,7 @@ module RuboCop
|
|
|
157
157
|
handle_require_always_style(node)
|
|
158
158
|
end
|
|
159
159
|
end
|
|
160
|
+
alias on_defs on_def
|
|
160
161
|
|
|
161
162
|
private
|
|
162
163
|
|
|
@@ -170,7 +171,7 @@ module RuboCop
|
|
|
170
171
|
end
|
|
171
172
|
|
|
172
173
|
def handle_require_single_line_style(node)
|
|
173
|
-
if node.endless? &&
|
|
174
|
+
if node.endless? && node.multiline?
|
|
174
175
|
add_offense(node, message: MSG_MULTI_LINE) do |corrector|
|
|
175
176
|
correct_to_multiline(corrector, node)
|
|
176
177
|
end
|
|
@@ -198,9 +199,16 @@ module RuboCop
|
|
|
198
199
|
add_offense(node) { |corrector| correct_to_multiline(corrector, node) }
|
|
199
200
|
end
|
|
200
201
|
|
|
202
|
+
def use_heredoc?(node)
|
|
203
|
+
return false unless (body = node.body)
|
|
204
|
+
return true if body.any_str_type? && body.heredoc?
|
|
205
|
+
|
|
206
|
+
body.each_descendant(:str).any?(&:heredoc?)
|
|
207
|
+
end
|
|
208
|
+
|
|
201
209
|
def correct_to_multiline(corrector, node)
|
|
202
210
|
replacement = <<~RUBY.strip
|
|
203
|
-
def #{node.method_name}#{arguments(node)}
|
|
211
|
+
def #{receiver(node)}#{node.method_name}#{arguments(node)}
|
|
204
212
|
#{node.body.source}
|
|
205
213
|
end
|
|
206
214
|
RUBY
|
|
@@ -210,10 +218,14 @@ module RuboCop
|
|
|
210
218
|
|
|
211
219
|
def endless_replacement(node)
|
|
212
220
|
<<~RUBY.strip
|
|
213
|
-
def #{node.method_name}#{arguments(node)} = #{node.body.source}
|
|
221
|
+
def #{receiver(node)}#{node.method_name}#{arguments(node)} = #{node.body.source}
|
|
214
222
|
RUBY
|
|
215
223
|
end
|
|
216
224
|
|
|
225
|
+
def receiver(node)
|
|
226
|
+
node.receiver ? "#{node.receiver.source}#{node.loc.operator.source}" : ''
|
|
227
|
+
end
|
|
228
|
+
|
|
217
229
|
def arguments(node, missing = '')
|
|
218
230
|
node.arguments.any? ? node.arguments.source : missing
|
|
219
231
|
end
|
|
@@ -225,7 +237,13 @@ module RuboCop
|
|
|
225
237
|
def too_long_when_made_endless?(node)
|
|
226
238
|
return false unless config.cop_enabled?('Layout/LineLength')
|
|
227
239
|
|
|
228
|
-
|
|
240
|
+
offset = modifier_offset(node)
|
|
241
|
+
|
|
242
|
+
endless_replacement(node).length + offset > max_line_length
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def modifier_offset(node)
|
|
246
|
+
same_line?(node.parent, node) ? node.loc.column - node.parent.loc.column : 0
|
|
229
247
|
end
|
|
230
248
|
end
|
|
231
249
|
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Style
|
|
6
|
+
# Checks for `File.open` without a block, which can leak file descriptors.
|
|
7
|
+
#
|
|
8
|
+
# When `File.open` is called without a block, the caller is responsible
|
|
9
|
+
# for closing the file descriptor. If it is not explicitly closed, it
|
|
10
|
+
# will only be closed when the garbage collector runs, which may lead
|
|
11
|
+
# to resource exhaustion. Using the block form ensures the file is
|
|
12
|
+
# automatically closed when the block exits.
|
|
13
|
+
#
|
|
14
|
+
# This cop only registers an offense when the result of `File.open` is
|
|
15
|
+
# assigned to a variable or has a method chained on it, as those are the
|
|
16
|
+
# clearest indicators that the block form should be used instead. When
|
|
17
|
+
# `File.open` is used as a return value or passed as an argument, the
|
|
18
|
+
# caller is likely managing the file descriptor intentionally.
|
|
19
|
+
#
|
|
20
|
+
# @safety
|
|
21
|
+
# This cop is unsafe because it relies on syntax heuristics and cannot
|
|
22
|
+
# verify whether the file descriptor is safely managed. For example, it
|
|
23
|
+
# still flags intentional one-shot reads (`File.open("f").read`) where
|
|
24
|
+
# the file descriptor is closed by the garbage collector.
|
|
25
|
+
#
|
|
26
|
+
# @example
|
|
27
|
+
# # bad
|
|
28
|
+
# f = File.open('file')
|
|
29
|
+
#
|
|
30
|
+
# # bad
|
|
31
|
+
# File.open('file').read
|
|
32
|
+
#
|
|
33
|
+
# # good
|
|
34
|
+
# File.open('file') do |f|
|
|
35
|
+
# f.read
|
|
36
|
+
# end
|
|
37
|
+
#
|
|
38
|
+
# # good
|
|
39
|
+
# File.open('file', &:read)
|
|
40
|
+
#
|
|
41
|
+
# # good - pass an open file object to an API that manages its lifecycle
|
|
42
|
+
# process(io: File.open('file'))
|
|
43
|
+
#
|
|
44
|
+
# # good - return an open file object for the caller to manage
|
|
45
|
+
# def json_key_io
|
|
46
|
+
# File.open('file')
|
|
47
|
+
# end
|
|
48
|
+
#
|
|
49
|
+
# # good - use File.read for one-shot reads
|
|
50
|
+
# File.read('file')
|
|
51
|
+
#
|
|
52
|
+
class FileOpen < Base
|
|
53
|
+
MSG = '`File.open` without a block may leak a file descriptor; use the block form.'
|
|
54
|
+
RESTRICT_ON_SEND = %i[open].freeze
|
|
55
|
+
|
|
56
|
+
# @!method file_open?(node)
|
|
57
|
+
def_node_matcher :file_open?, <<~PATTERN
|
|
58
|
+
(send (const {nil? cbase} :File) :open ...)
|
|
59
|
+
PATTERN
|
|
60
|
+
|
|
61
|
+
def on_send(node)
|
|
62
|
+
return unless file_open?(node)
|
|
63
|
+
return if node.block_argument?
|
|
64
|
+
return unless offensive_usage?(node)
|
|
65
|
+
|
|
66
|
+
add_offense(node)
|
|
67
|
+
end
|
|
68
|
+
alias on_csend on_send
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
|
|
72
|
+
def offensive_usage?(node)
|
|
73
|
+
return true unless node.value_used?
|
|
74
|
+
|
|
75
|
+
node.parent.lvasgn_type? || receiver_of_chained_call?(node)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def receiver_of_chained_call?(node)
|
|
79
|
+
node.parent.receiver == node
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -7,9 +7,12 @@ module RuboCop
|
|
|
7
7
|
# It is recommended to either always use `fdiv` or coerce one side only.
|
|
8
8
|
# This cop also provides other options for code consistency.
|
|
9
9
|
#
|
|
10
|
+
# For `Regexp.last_match` and nth reference (e.g., `$1`), it assumes that the value
|
|
11
|
+
# is a string matched by a regular expression, and allows conversion with `#to_f`.
|
|
12
|
+
#
|
|
10
13
|
# @safety
|
|
11
14
|
# This cop is unsafe, because if the operand variable is a string object
|
|
12
|
-
# then
|
|
15
|
+
# then `#to_f` will be removed and an error will occur.
|
|
13
16
|
#
|
|
14
17
|
# [source,ruby]
|
|
15
18
|
# ----
|
|
@@ -84,6 +87,14 @@ module RuboCop
|
|
|
84
87
|
(send !nil? :to_f)
|
|
85
88
|
PATTERN
|
|
86
89
|
|
|
90
|
+
# @!method regexp_last_match?(node)
|
|
91
|
+
def_node_matcher :regexp_last_match?, <<~PATTERN
|
|
92
|
+
{
|
|
93
|
+
(send (const {nil? cbase} :Regexp) :last_match int)
|
|
94
|
+
(:nth_ref _)
|
|
95
|
+
}
|
|
96
|
+
PATTERN
|
|
97
|
+
|
|
87
98
|
def on_send(node)
|
|
88
99
|
return unless offense_condition?(node)
|
|
89
100
|
|
|
@@ -104,6 +115,9 @@ module RuboCop
|
|
|
104
115
|
private
|
|
105
116
|
|
|
106
117
|
def offense_condition?(node)
|
|
118
|
+
return false if regexp_last_match?(node.receiver.receiver) ||
|
|
119
|
+
regexp_last_match?(node.first_argument.receiver)
|
|
120
|
+
|
|
107
121
|
case style
|
|
108
122
|
when :left_coerce
|
|
109
123
|
right_coerce?(node)
|
|
@@ -8,6 +8,9 @@ module RuboCop
|
|
|
8
8
|
# parameter. An `each` call with a block on a single line is always
|
|
9
9
|
# allowed.
|
|
10
10
|
#
|
|
11
|
+
# NOTE: `each` is preferred in idiomatic Ruby because `for` leaks
|
|
12
|
+
# its loop variable into the surrounding scope.
|
|
13
|
+
#
|
|
11
14
|
# @example EnforcedStyle: each (default)
|
|
12
15
|
# # bad
|
|
13
16
|
# def foo
|
|
@@ -18,6 +18,11 @@ module RuboCop
|
|
|
18
18
|
# of `EnforcedStyle`) are only considered if used in the format string argument to the
|
|
19
19
|
# methods `printf`, `sprintf`, `format` and `%`.
|
|
20
20
|
#
|
|
21
|
+
# NOTE: In `aggressive` mode, offenses are registered for all strings containing tokens,
|
|
22
|
+
# but autocorrection is only applied when the string appears in a known formatting context
|
|
23
|
+
# (`format`, `sprintf`, `printf`, or `%`). This is done in order to prevent false
|
|
24
|
+
# autocorrections for strings that are not actually format strings.
|
|
25
|
+
#
|
|
21
26
|
# NOTE: Tokens in the `unannotated` style (eg. `%s`) are always treated as if
|
|
22
27
|
# configured with `Conservative: true`. This is done in order to prevent false positives,
|
|
23
28
|
# because this format is very similar to encoded URLs or Date/Time formatting strings.
|
|
@@ -90,9 +95,25 @@ module RuboCop
|
|
|
90
95
|
# # good
|
|
91
96
|
# redirect('foo/%{bar_id}')
|
|
92
97
|
#
|
|
98
|
+
# @example Mode: aggressive (default), EnforcedStyle: annotated
|
|
99
|
+
#
|
|
100
|
+
# # bad
|
|
101
|
+
# "%{greeting}"
|
|
102
|
+
# foo("%{greeting}")
|
|
103
|
+
#
|
|
104
|
+
# # bad
|
|
105
|
+
# format("%{greeting}", greeting: 'Hello')
|
|
106
|
+
# printf("%{greeting}", greeting: 'Hello')
|
|
107
|
+
# sprintf("%{greeting}", greeting: 'Hello')
|
|
108
|
+
# "%{greeting}" % { greeting: 'Hello' }
|
|
109
|
+
#
|
|
110
|
+
# # good
|
|
111
|
+
# format("%<greeting>s", greeting: 'Hello')
|
|
112
|
+
# printf("%<greeting>s", greeting: 'Hello')
|
|
113
|
+
# sprintf("%<greeting>s", greeting: 'Hello')
|
|
114
|
+
# "%<greeting>s" % { greeting: 'Hello' }
|
|
115
|
+
#
|
|
93
116
|
# @example Mode: conservative, EnforcedStyle: annotated
|
|
94
|
-
# # In `conservative` mode, offenses are only registered for strings
|
|
95
|
-
# # given to a known formatting method.
|
|
96
117
|
#
|
|
97
118
|
# # good
|
|
98
119
|
# "%{greeting}"
|
|
@@ -104,6 +125,12 @@ module RuboCop
|
|
|
104
125
|
# sprintf("%{greeting}", greeting: 'Hello')
|
|
105
126
|
# "%{greeting}" % { greeting: 'Hello' }
|
|
106
127
|
#
|
|
128
|
+
# # good
|
|
129
|
+
# format("%<greeting>s", greeting: 'Hello')
|
|
130
|
+
# printf("%<greeting>s", greeting: 'Hello')
|
|
131
|
+
# sprintf("%<greeting>s", greeting: 'Hello')
|
|
132
|
+
# "%<greeting>s" % { greeting: 'Hello' }
|
|
133
|
+
#
|
|
107
134
|
class FormatStringToken < Base
|
|
108
135
|
include ConfigurableEnforcedStyle
|
|
109
136
|
include AllowedMethods
|
|
@@ -118,7 +145,7 @@ module RuboCop
|
|
|
118
145
|
return if allowed_unannotated?(detections)
|
|
119
146
|
|
|
120
147
|
detections.each do |detected_sequence, token_range|
|
|
121
|
-
check_sequence(detected_sequence, token_range)
|
|
148
|
+
check_sequence(node, detected_sequence, token_range)
|
|
122
149
|
end
|
|
123
150
|
end
|
|
124
151
|
|
|
@@ -143,17 +170,34 @@ module RuboCop
|
|
|
143
170
|
matches_allowed_pattern?(send_parent.method_name))
|
|
144
171
|
end
|
|
145
172
|
|
|
146
|
-
def check_sequence(detected_sequence, token_range)
|
|
173
|
+
def check_sequence(node, detected_sequence, token_range)
|
|
147
174
|
if detected_sequence.style == style
|
|
148
175
|
correct_style_detected
|
|
149
176
|
elsif correctable_sequence?(detected_sequence.type)
|
|
150
177
|
style_detected(detected_sequence.style)
|
|
151
|
-
|
|
178
|
+
register_offense(node, detected_sequence, token_range)
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def register_offense(node, detected_sequence, token_range)
|
|
183
|
+
msg = message(detected_sequence.style)
|
|
184
|
+
|
|
185
|
+
if format_string_context?(node)
|
|
186
|
+
add_offense(token_range, message: msg) do |corrector|
|
|
152
187
|
autocorrect_sequence(corrector, detected_sequence, token_range)
|
|
153
188
|
end
|
|
189
|
+
else
|
|
190
|
+
add_offense(token_range, message: msg)
|
|
154
191
|
end
|
|
155
192
|
end
|
|
156
193
|
|
|
194
|
+
def format_string_context?(node)
|
|
195
|
+
format_string_in_typical_context?(node) ||
|
|
196
|
+
node.each_ancestor(:dstr).any? do |dstr_node|
|
|
197
|
+
format_string_in_typical_context?(dstr_node)
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
157
201
|
def correctable_sequence?(detected_type)
|
|
158
202
|
detected_type == 's' || style == :annotated || style == :unannotated
|
|
159
203
|
end
|
|
@@ -3,7 +3,10 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Style
|
|
6
|
-
# Looks for uses of global variables.
|
|
6
|
+
# Looks for uses of global variables. Global variables introduce
|
|
7
|
+
# shared mutable state that makes code harder to test, debug,
|
|
8
|
+
# and reason about, since any part of the program can read or modify them.
|
|
9
|
+
#
|
|
7
10
|
# It does not report offenses for built-in global variables.
|
|
8
11
|
# Built-in global variables are allowed by default. Additionally
|
|
9
12
|
# users can allow additional variables via the AllowedVariables option.
|
|
@@ -54,7 +57,7 @@ module RuboCop
|
|
|
54
57
|
].map(&:to_sym)
|
|
55
58
|
|
|
56
59
|
def user_vars
|
|
57
|
-
cop_config['AllowedVariables'].map(&:to_sym)
|
|
60
|
+
@user_vars ||= cop_config['AllowedVariables'].map(&:to_sym).freeze
|
|
58
61
|
end
|
|
59
62
|
|
|
60
63
|
def allowed_var?(global_var)
|