rubocop 1.9.0 → 1.12.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/README.md +14 -14
- data/assets/output.html.erb +1 -1
- data/config/default.yml +70 -17
- data/config/obsoletion.yml +4 -0
- data/lib/rubocop.rb +5 -0
- data/lib/rubocop/cli/command/execute_runner.rb +1 -1
- data/lib/rubocop/cli/command/suggest_extensions.rb +3 -2
- data/lib/rubocop/comment_config.rb +43 -94
- data/lib/rubocop/config.rb +4 -1
- data/lib/rubocop/cop/base.rb +1 -0
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +2 -1
- data/lib/rubocop/cop/bundler/gem_comment.rb +1 -0
- data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +1 -0
- data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -0
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +3 -6
- data/lib/rubocop/cop/exclude_limit.rb +26 -0
- data/lib/rubocop/cop/gemspec/date_assignment.rb +57 -0
- data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +2 -0
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -0
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +2 -0
- data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +2 -0
- data/lib/rubocop/cop/generator.rb +2 -2
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/internal_affairs/example_description.rb +1 -0
- data/lib/rubocop/cop/internal_affairs/method_name_equal.rb +1 -0
- data/lib/rubocop/cop/internal_affairs/node_destructuring.rb +2 -0
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +151 -0
- data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +1 -0
- data/lib/rubocop/cop/internal_affairs/offense_location_keyword.rb +2 -0
- data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +1 -0
- data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +1 -0
- data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +1 -0
- data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +3 -0
- data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +4 -0
- data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +2 -0
- data/lib/rubocop/cop/layout/access_modifier_indentation.rb +11 -8
- data/lib/rubocop/cop/layout/argument_alignment.rb +6 -5
- data/lib/rubocop/cop/layout/array_alignment.rb +7 -6
- data/lib/rubocop/cop/layout/assignment_indentation.rb +6 -3
- data/lib/rubocop/cop/layout/block_alignment.rb +1 -0
- data/lib/rubocop/cop/layout/block_end_newline.rb +4 -8
- data/lib/rubocop/cop/layout/class_structure.rb +1 -0
- data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +14 -15
- data/lib/rubocop/cop/layout/comment_indentation.rb +16 -16
- data/lib/rubocop/cop/layout/else_alignment.rb +9 -6
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +20 -3
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +37 -17
- data/lib/rubocop/cop/layout/extra_spacing.rb +2 -2
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +27 -7
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +9 -6
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +22 -15
- data/lib/rubocop/cop/layout/first_parameter_indentation.rb +6 -5
- data/lib/rubocop/cop/layout/indentation_consistency.rb +9 -6
- data/lib/rubocop/cop/layout/indentation_style.rb +27 -30
- data/lib/rubocop/cop/layout/indentation_width.rb +20 -9
- data/lib/rubocop/cop/layout/line_length.rb +2 -1
- data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +26 -0
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +18 -5
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +10 -5
- data/lib/rubocop/cop/layout/parameter_alignment.rb +6 -5
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +1 -1
- data/lib/rubocop/cop/layout/space_before_brackets.rb +9 -4
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +1 -1
- data/lib/rubocop/cop/lint/big_decimal_new.rb +1 -0
- data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -0
- data/lib/rubocop/cop/lint/constant_definition_in_block.rb +2 -0
- data/lib/rubocop/cop/lint/constant_resolution.rb +1 -0
- data/lib/rubocop/cop/lint/debugger.rb +60 -14
- data/lib/rubocop/cop/lint/deprecated_constants.rb +5 -0
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +14 -4
- data/lib/rubocop/cop/lint/duplicate_branch.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_methods.rb +3 -0
- data/lib/rubocop/cop/lint/duplicate_require.rb +3 -2
- data/lib/rubocop/cop/lint/each_with_object_argument.rb +1 -0
- data/lib/rubocop/cop/lint/else_layout.rb +1 -1
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -0
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +1 -0
- data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +1 -0
- data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -0
- data/lib/rubocop/cop/lint/inherit_exception.rb +1 -0
- data/lib/rubocop/cop/lint/multiple_comparison.rb +5 -4
- data/lib/rubocop/cop/lint/nested_method_definition.rb +3 -0
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -0
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +7 -0
- data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +3 -0
- data/lib/rubocop/cop/lint/number_conversion.rb +11 -2
- data/lib/rubocop/cop/lint/raise_exception.rb +2 -0
- data/lib/rubocop/cop/lint/rand_one.rb +1 -0
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +1 -2
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +1 -0
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +1 -0
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +7 -3
- data/lib/rubocop/cop/lint/redundant_string_coercion.rb +1 -0
- data/lib/rubocop/cop/lint/redundant_with_index.rb +1 -0
- data/lib/rubocop/cop/lint/redundant_with_object.rb +1 -0
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +1 -0
- data/lib/rubocop/cop/lint/safe_navigation_with_empty.rb +1 -0
- data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +1 -0
- data/lib/rubocop/cop/lint/shadowed_argument.rb +1 -0
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +1 -0
- data/lib/rubocop/cop/lint/struct_new_override.rb +1 -0
- data/lib/rubocop/cop/lint/suppressed_exception.rb +44 -1
- data/lib/rubocop/cop/lint/symbol_conversion.rb +91 -3
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +3 -0
- data/lib/rubocop/cop/lint/unified_integer.rb +1 -0
- data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +5 -0
- data/lib/rubocop/cop/lint/unreachable_code.rb +1 -0
- data/lib/rubocop/cop/lint/unreachable_loop.rb +1 -0
- data/lib/rubocop/cop/lint/unused_method_argument.rb +1 -0
- data/lib/rubocop/cop/lint/uri_escape_unescape.rb +1 -0
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +4 -0
- data/lib/rubocop/cop/lint/useless_setter_call.rb +1 -0
- data/lib/rubocop/cop/lint/useless_times.rb +3 -0
- data/lib/rubocop/cop/message_annotator.rb +4 -1
- data/lib/rubocop/cop/metrics/block_nesting.rb +2 -2
- data/lib/rubocop/cop/metrics/module_length.rb +1 -0
- data/lib/rubocop/cop/metrics/parameter_lists.rb +6 -2
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +6 -4
- data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +2 -0
- data/lib/rubocop/cop/mixin/alignment.rb +10 -3
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
- data/lib/rubocop/cop/mixin/code_length.rb +3 -1
- data/lib/rubocop/cop/mixin/comments_help.rb +5 -1
- data/lib/rubocop/cop/mixin/configurable_max.rb +1 -0
- data/lib/rubocop/cop/mixin/def_node.rb +1 -0
- data/lib/rubocop/cop/mixin/documentation_comment.rb +1 -1
- data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +3 -0
- data/lib/rubocop/cop/mixin/empty_parameter.rb +1 -0
- data/lib/rubocop/cop/mixin/enforce_superclass.rb +2 -0
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +1 -0
- data/lib/rubocop/cop/mixin/line_length_help.rb +11 -6
- data/lib/rubocop/cop/mixin/method_complexity.rb +4 -1
- data/lib/rubocop/cop/mixin/multiline_element_indentation.rb +3 -1
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +4 -23
- data/lib/rubocop/cop/mixin/negative_conditional.rb +3 -0
- data/lib/rubocop/cop/mixin/preferred_delimiters.rb +3 -3
- data/lib/rubocop/cop/mixin/rational_literal.rb +1 -0
- data/lib/rubocop/cop/mixin/safe_assignment.rb +5 -0
- data/lib/rubocop/cop/mixin/uncommunicative_name.rb +4 -6
- data/lib/rubocop/cop/mixin/visibility_help.rb +1 -0
- data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +1 -0
- data/lib/rubocop/cop/naming/constant_name.rb +2 -0
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +6 -0
- data/lib/rubocop/cop/naming/method_name.rb +3 -0
- data/lib/rubocop/cop/naming/predicate_name.rb +1 -0
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +10 -0
- data/lib/rubocop/cop/registry.rb +10 -1
- data/lib/rubocop/cop/security/eval.rb +1 -0
- data/lib/rubocop/cop/security/json_load.rb +1 -0
- data/lib/rubocop/cop/security/marshal_load.rb +1 -0
- data/lib/rubocop/cop/security/open.rb +1 -0
- data/lib/rubocop/cop/security/yaml_load.rb +1 -0
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +3 -2
- data/lib/rubocop/cop/style/alias.rb +1 -0
- data/lib/rubocop/cop/style/and_or.rb +3 -1
- data/lib/rubocop/cop/style/arguments_forwarding.rb +3 -0
- data/lib/rubocop/cop/style/array_coercion.rb +2 -0
- data/lib/rubocop/cop/style/array_join.rb +1 -0
- data/lib/rubocop/cop/style/attr.rb +1 -0
- data/lib/rubocop/cop/style/bisected_attr_accessor.rb +59 -71
- data/lib/rubocop/cop/style/bisected_attr_accessor/macro.rb +62 -0
- data/lib/rubocop/cop/style/case_equality.rb +2 -1
- data/lib/rubocop/cop/style/case_like_if.rb +15 -4
- data/lib/rubocop/cop/style/class_equality_comparison.rb +3 -0
- data/lib/rubocop/cop/style/collection_compact.rb +2 -0
- data/lib/rubocop/cop/style/colon_method_call.rb +1 -0
- data/lib/rubocop/cop/style/command_literal.rb +1 -1
- data/lib/rubocop/cop/style/commented_keyword.rb +10 -10
- data/lib/rubocop/cop/style/conditional_assignment.rb +2 -0
- data/lib/rubocop/cop/style/constant_visibility.rb +28 -0
- data/lib/rubocop/cop/style/date_time.rb +3 -0
- data/lib/rubocop/cop/style/dir.rb +1 -0
- data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +2 -2
- data/lib/rubocop/cop/style/documentation.rb +30 -3
- data/lib/rubocop/cop/style/documentation_method.rb +1 -0
- data/lib/rubocop/cop/style/double_negation.rb +3 -2
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -0
- data/lib/rubocop/cop/style/each_with_object.rb +1 -0
- data/lib/rubocop/cop/style/empty_literal.rb +9 -0
- data/lib/rubocop/cop/style/endless_method.rb +1 -0
- data/lib/rubocop/cop/style/eval_with_location.rb +90 -28
- data/lib/rubocop/cop/style/even_odd.rb +1 -0
- data/lib/rubocop/cop/style/expand_path_arguments.rb +3 -0
- data/lib/rubocop/cop/style/explicit_block_argument.rb +2 -1
- data/lib/rubocop/cop/style/exponential_notation.rb +6 -7
- data/lib/rubocop/cop/style/float_division.rb +4 -0
- data/lib/rubocop/cop/style/format_string.rb +2 -0
- data/lib/rubocop/cop/style/format_string_token.rb +1 -0
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +0 -3
- data/lib/rubocop/cop/style/global_std_stream.rb +1 -0
- data/lib/rubocop/cop/style/hash_conversion.rb +108 -0
- data/lib/rubocop/cop/style/hash_each_methods.rb +1 -0
- data/lib/rubocop/cop/style/hash_except.rb +1 -0
- data/lib/rubocop/cop/style/hash_like_case.rb +1 -0
- data/lib/rubocop/cop/style/hash_syntax.rb +16 -15
- data/lib/rubocop/cop/style/hash_transform_keys.rb +4 -0
- data/lib/rubocop/cop/style/hash_transform_values.rb +4 -0
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +37 -11
- data/lib/rubocop/cop/style/implicit_runtime_error.rb +1 -0
- data/lib/rubocop/cop/style/inverse_methods.rb +2 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +46 -2
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +19 -3
- data/lib/rubocop/cop/style/min_max.rb +1 -0
- data/lib/rubocop/cop/style/mixin_usage.rb +2 -0
- data/lib/rubocop/cop/style/module_function.rb +5 -0
- data/lib/rubocop/cop/style/multiline_method_signature.rb +10 -3
- data/lib/rubocop/cop/style/multiple_comparison.rb +21 -2
- data/lib/rubocop/cop/style/mutable_constant.rb +3 -0
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +16 -2
- data/lib/rubocop/cop/style/nil_comparison.rb +6 -1
- data/lib/rubocop/cop/style/nil_lambda.rb +1 -0
- data/lib/rubocop/cop/style/non_nil_check.rb +7 -0
- data/lib/rubocop/cop/style/numeric_literals.rb +6 -9
- data/lib/rubocop/cop/style/numeric_predicate.rb +4 -1
- data/lib/rubocop/cop/style/option_hash.rb +1 -0
- data/lib/rubocop/cop/style/or_assignment.rb +2 -0
- data/lib/rubocop/cop/style/parallel_assignment.rb +6 -0
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +1 -0
- data/lib/rubocop/cop/style/proc.rb +1 -0
- data/lib/rubocop/cop/style/random_with_offset.rb +5 -0
- data/lib/rubocop/cop/style/redundant_assignment.rb +1 -0
- data/lib/rubocop/cop/style/redundant_begin.rb +44 -4
- data/lib/rubocop/cop/style/redundant_conditional.rb +2 -0
- data/lib/rubocop/cop/style/redundant_exception.rb +2 -0
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +2 -0
- data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +1 -0
- data/lib/rubocop/cop/style/redundant_freeze.rb +1 -0
- data/lib/rubocop/cop/style/redundant_parentheses.rb +13 -0
- data/lib/rubocop/cop/style/redundant_return.rb +4 -0
- data/lib/rubocop/cop/style/redundant_self.rb +7 -3
- data/lib/rubocop/cop/style/redundant_self_assignment.rb +2 -0
- data/lib/rubocop/cop/style/redundant_sort.rb +1 -0
- data/lib/rubocop/cop/style/redundant_sort_by.rb +1 -0
- data/lib/rubocop/cop/style/regexp_literal.rb +1 -1
- data/lib/rubocop/cop/style/rescue_modifier.rb +17 -14
- data/lib/rubocop/cop/style/rescue_standard_error.rb +2 -0
- data/lib/rubocop/cop/style/return_nil.rb +6 -0
- data/lib/rubocop/cop/style/safe_navigation.rb +2 -0
- data/lib/rubocop/cop/style/sample.rb +1 -0
- data/lib/rubocop/cop/style/signal_exception.rb +3 -0
- data/lib/rubocop/cop/style/single_argument_dig.rb +1 -0
- data/lib/rubocop/cop/style/single_line_methods.rb +4 -1
- data/lib/rubocop/cop/style/slicing_with_range.rb +1 -0
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +20 -4
- data/lib/rubocop/cop/style/special_global_vars.rb +3 -3
- data/lib/rubocop/cop/style/stderr_puts.rb +1 -0
- data/lib/rubocop/cop/style/string_chars.rb +38 -0
- data/lib/rubocop/cop/style/string_concatenation.rb +1 -0
- data/lib/rubocop/cop/style/string_hash_keys.rb +2 -0
- data/lib/rubocop/cop/style/strip.rb +1 -0
- data/lib/rubocop/cop/style/struct_inheritance.rb +3 -0
- data/lib/rubocop/cop/style/symbol_proc.rb +25 -1
- data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -0
- data/lib/rubocop/cop/style/trailing_body_on_method_definition.rb +5 -0
- data/lib/rubocop/cop/style/trailing_method_end_statement.rb +1 -1
- data/lib/rubocop/cop/style/trivial_accessors.rb +1 -0
- data/lib/rubocop/cop/style/unless_logical_operators.rb +105 -0
- data/lib/rubocop/cop/style/unpack_first.rb +1 -0
- data/lib/rubocop/cop/style/yoda_condition.rb +1 -0
- data/lib/rubocop/cop/style/zero_length_predicate.rb +5 -0
- data/lib/rubocop/cop/util.rb +4 -1
- data/lib/rubocop/directive_comment.rb +69 -9
- data/lib/rubocop/ext/regexp_parser.rb +3 -6
- data/lib/rubocop/formatter/clang_style_formatter.rb +4 -2
- data/lib/rubocop/formatter/offense_count_formatter.rb +1 -1
- data/lib/rubocop/formatter/simple_text_formatter.rb +2 -1
- data/lib/rubocop/formatter/tap_formatter.rb +4 -2
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -1
- data/lib/rubocop/magic_comment.rb +1 -1
- data/lib/rubocop/name_similarity.rb +1 -1
- data/lib/rubocop/target_finder.rb +1 -0
- data/lib/rubocop/target_ruby.rb +21 -13
- data/lib/rubocop/version.rb +1 -1
- metadata +14 -7
@@ -22,6 +22,7 @@ module RuboCop
|
|
22
22
|
MSG = 'Avoid using `Marshal.%<method>s`.'
|
23
23
|
RESTRICT_ON_SEND = %i[load restore].freeze
|
24
24
|
|
25
|
+
# @!method marshal_load(node)
|
25
26
|
def_node_matcher :marshal_load, <<~PATTERN
|
26
27
|
(send (const {nil? cbase} :Marshal) ${:load :restore}
|
27
28
|
!(send (const {nil? cbase} :Marshal) :dump ...))
|
@@ -47,7 +47,7 @@ module RuboCop
|
|
47
47
|
#
|
48
48
|
# end
|
49
49
|
#
|
50
|
-
# @example AllowModifiersOnSymbols: true
|
50
|
+
# @example AllowModifiersOnSymbols: true (default)
|
51
51
|
# # good
|
52
52
|
# class Foo
|
53
53
|
#
|
@@ -77,8 +77,9 @@ module RuboCop
|
|
77
77
|
|
78
78
|
RESTRICT_ON_SEND = %i[private protected public module_function].freeze
|
79
79
|
|
80
|
+
# @!method access_modifier_with_symbol?(node)
|
80
81
|
def_node_matcher :access_modifier_with_symbol?, <<~PATTERN
|
81
|
-
(send nil? {:private :protected :public} (sym _))
|
82
|
+
(send nil? {:private :protected :public :module_function} (sym _))
|
82
83
|
PATTERN
|
83
84
|
|
84
85
|
def on_send(node)
|
@@ -94,7 +94,9 @@ module RuboCop
|
|
94
94
|
|
95
95
|
return unless correctable_send?(node)
|
96
96
|
|
97
|
-
|
97
|
+
whitespace_before_arg_range = whitespace_before_arg(node)
|
98
|
+
corrector.remove(whitespace_before_arg_range)
|
99
|
+
corrector.insert_before(whitespace_before_arg_range, '(')
|
98
100
|
corrector.insert_after(node.last_argument, ')')
|
99
101
|
end
|
100
102
|
|
@@ -47,14 +47,17 @@ module RuboCop
|
|
47
47
|
|
48
48
|
MSG = 'Use arguments forwarding.'
|
49
49
|
|
50
|
+
# @!method use_rest_arguments?(node)
|
50
51
|
def_node_matcher :use_rest_arguments?, <<~PATTERN
|
51
52
|
(args (restarg $_) $...)
|
52
53
|
PATTERN
|
53
54
|
|
55
|
+
# @!method only_rest_arguments?(node, name)
|
54
56
|
def_node_matcher :only_rest_arguments?, <<~PATTERN
|
55
57
|
(send _ _ (splat (lvar %1)))
|
56
58
|
PATTERN
|
57
59
|
|
60
|
+
# @!method forwarding_method_arguments?(node, rest_name, block_name, kwargs_name)
|
58
61
|
def_node_matcher :forwarding_method_arguments?, <<~PATTERN
|
59
62
|
{
|
60
63
|
(send _ _
|
@@ -26,10 +26,12 @@ module RuboCop
|
|
26
26
|
SPLAT_MSG = 'Use `Array(%<arg>s)` instead of `[*%<arg>s]`.'
|
27
27
|
CHECK_MSG = 'Use `Array(%<arg>s)` instead of explicit `Array` check.'
|
28
28
|
|
29
|
+
# @!method array_splat?(node)
|
29
30
|
def_node_matcher :array_splat?, <<~PATTERN
|
30
31
|
(array (splat $_))
|
31
32
|
PATTERN
|
32
33
|
|
34
|
+
# @!method unless_array?(node)
|
33
35
|
def_node_matcher :unless_array?, <<~PATTERN
|
34
36
|
(if
|
35
37
|
(send
|
@@ -19,47 +19,61 @@ module RuboCop
|
|
19
19
|
# end
|
20
20
|
#
|
21
21
|
class BisectedAttrAccessor < Base
|
22
|
-
|
22
|
+
require_relative 'bisected_attr_accessor/macro'
|
23
|
+
|
24
|
+
include RangeHelp
|
23
25
|
extend AutoCorrector
|
24
26
|
|
25
27
|
MSG = 'Combine both accessors into `attr_accessor %<name>s`.'
|
26
28
|
|
29
|
+
def on_new_investigation
|
30
|
+
@macros_to_rewrite = {}
|
31
|
+
end
|
32
|
+
|
27
33
|
def on_class(class_node)
|
28
|
-
|
29
|
-
|
30
|
-
|
34
|
+
@macros_to_rewrite[class_node] = Set.new
|
35
|
+
|
36
|
+
find_macros(class_node.body).each do |_visibility, macros|
|
37
|
+
bisected = find_bisection(macros)
|
38
|
+
next unless bisected.any?
|
31
39
|
|
32
|
-
|
33
|
-
|
40
|
+
macros.each do |macro|
|
41
|
+
attrs = macro.bisect(*bisected)
|
42
|
+
next if attrs.none?
|
43
|
+
|
44
|
+
@macros_to_rewrite[class_node] << macro
|
45
|
+
attrs.each { |attr| register_offense(attr) }
|
34
46
|
end
|
35
47
|
end
|
36
48
|
end
|
37
49
|
alias on_sclass on_class
|
38
50
|
alias on_module on_class
|
39
51
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
(reader_names ||= Set.new).add(name)
|
52
|
+
# Each offending macro is captured and registered in `on_class` but correction
|
53
|
+
# happens in `after_class` because a macro might have multiple attributes
|
54
|
+
# rewritten from it
|
55
|
+
def after_class(class_node)
|
56
|
+
@macros_to_rewrite[class_node].each do |macro|
|
57
|
+
node = macro.node
|
58
|
+
range = range_by_whole_lines(node.loc.expression, include_final_newline: true)
|
59
|
+
|
60
|
+
correct(range) do |corrector|
|
61
|
+
if macro.writer?
|
62
|
+
correct_writer(corrector, macro, node, range)
|
52
63
|
else
|
53
|
-
(
|
64
|
+
correct_reader(corrector, macro, node, range)
|
54
65
|
end
|
55
66
|
end
|
56
67
|
end
|
57
|
-
|
58
|
-
[reader_names, writer_names]
|
59
68
|
end
|
69
|
+
alias after_sclass after_class
|
70
|
+
alias after_module after_class
|
60
71
|
|
61
|
-
|
62
|
-
|
72
|
+
private
|
73
|
+
|
74
|
+
def find_macros(class_def)
|
75
|
+
# Find all the macros (`attr_reader`, `attr_writer`, etc.) in the class body
|
76
|
+
# and turn them into `Macro` objects so that they can be processed.
|
63
77
|
return [] if !class_def || class_def.def_type?
|
64
78
|
|
65
79
|
send_nodes =
|
@@ -69,66 +83,40 @@ module RuboCop
|
|
69
83
|
class_def.each_child_node(:send)
|
70
84
|
end
|
71
85
|
|
72
|
-
send_nodes.
|
86
|
+
send_nodes.each_with_object([]) do |node, macros|
|
87
|
+
macros << Macro.new(node) if Macro.macro?(node)
|
88
|
+
end.group_by(&:visibility)
|
73
89
|
end
|
74
90
|
|
75
|
-
def
|
76
|
-
|
77
|
-
|
78
|
-
|
91
|
+
def find_bisection(macros)
|
92
|
+
# Find which attributes are defined in both readers and writers so that they
|
93
|
+
# can be replaced with accessors.
|
94
|
+
readers, writers = macros.partition(&:reader?)
|
95
|
+
readers.flat_map(&:attr_names) & writers.flat_map(&:attr_names)
|
79
96
|
end
|
80
97
|
|
81
|
-
def
|
82
|
-
|
98
|
+
def register_offense(attr)
|
99
|
+
add_offense(attr, message: format(MSG, name: attr.source))
|
83
100
|
end
|
84
101
|
|
85
|
-
def
|
86
|
-
|
87
|
-
end
|
102
|
+
def correct_reader(corrector, macro, node, range)
|
103
|
+
attr_accessor = "attr_accessor #{macro.bisected_names.join(', ')}\n"
|
88
104
|
|
89
|
-
|
90
|
-
|
91
|
-
name = arg_node.source
|
92
|
-
|
93
|
-
next unless (attr_reader?(macro) && writer_names.include?(name)) ||
|
94
|
-
(attr_writer?(macro) && reader_names.include?(name))
|
95
|
-
|
96
|
-
add_offense(arg_node, message: format(MSG, name: name)) do |corrector|
|
97
|
-
macro = arg_node.parent
|
98
|
-
|
99
|
-
corrector.replace(macro, replacement(macro, arg_node))
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
def replacement(macro, node)
|
105
|
-
class_node = macro.each_ancestor(:class, :sclass, :module).first
|
106
|
-
reader_names, writer_names = accessor_names(class_node, node_visibility(macro))
|
107
|
-
|
108
|
-
rest_args = rest_args(macro.arguments, reader_names, writer_names)
|
109
|
-
|
110
|
-
if attr_reader?(macro)
|
111
|
-
attr_reader_replacement(macro, node, rest_args)
|
112
|
-
elsif rest_args.empty?
|
113
|
-
''
|
105
|
+
if macro.all_bisected?
|
106
|
+
corrector.replace(range, "#{indent(node)}#{attr_accessor}")
|
114
107
|
else
|
115
|
-
"#{
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
def rest_args(args, reader_names, writer_names)
|
120
|
-
args.reject do |arg|
|
121
|
-
name = arg.source
|
122
|
-
reader_names.include?(name) && writer_names.include?(name)
|
108
|
+
correction = "#{indent(node)}attr_reader #{macro.rest.join(', ')}"
|
109
|
+
corrector.insert_before(node, attr_accessor)
|
110
|
+
corrector.replace(node, correction)
|
123
111
|
end
|
124
112
|
end
|
125
113
|
|
126
|
-
def
|
127
|
-
if
|
128
|
-
|
114
|
+
def correct_writer(corrector, macro, node, range)
|
115
|
+
if macro.all_bisected?
|
116
|
+
corrector.remove(range)
|
129
117
|
else
|
130
|
-
"
|
131
|
-
|
118
|
+
correction = "attr_writer #{macro.rest.join(', ')}"
|
119
|
+
corrector.replace(node, correction)
|
132
120
|
end
|
133
121
|
end
|
134
122
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
class BisectedAttrAccessor
|
7
|
+
# Representation of an `attr_reader`, `attr_writer` or `attr` macro
|
8
|
+
# for use by `Style/BisectedAttrAccessor`.
|
9
|
+
# @api private
|
10
|
+
class Macro
|
11
|
+
include VisibilityHelp
|
12
|
+
|
13
|
+
attr_reader :node, :attrs, :bisection
|
14
|
+
|
15
|
+
def self.macro?(node)
|
16
|
+
node.method?(:attr_reader) || node.method?(:attr_writer) || node.method?(:attr)
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(node)
|
20
|
+
@node = node
|
21
|
+
@attrs = node.arguments.map do |attr|
|
22
|
+
[attr.source, attr]
|
23
|
+
end.to_h
|
24
|
+
@bisection = []
|
25
|
+
end
|
26
|
+
|
27
|
+
def bisect(*names)
|
28
|
+
@bisection = attrs.slice(*names).values
|
29
|
+
end
|
30
|
+
|
31
|
+
def attr_names
|
32
|
+
@attr_names ||= attrs.keys
|
33
|
+
end
|
34
|
+
|
35
|
+
def bisected_names
|
36
|
+
bisection.map(&:source)
|
37
|
+
end
|
38
|
+
|
39
|
+
def visibility
|
40
|
+
@visibility ||= node_visibility(node)
|
41
|
+
end
|
42
|
+
|
43
|
+
def reader?
|
44
|
+
node.method?(:attr_reader) || node.method?(:attr)
|
45
|
+
end
|
46
|
+
|
47
|
+
def writer?
|
48
|
+
node.method?(:attr_writer)
|
49
|
+
end
|
50
|
+
|
51
|
+
def all_bisected?
|
52
|
+
rest.none?
|
53
|
+
end
|
54
|
+
|
55
|
+
def rest
|
56
|
+
@rest ||= attr_names - bisected_names
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -35,6 +35,7 @@ module RuboCop
|
|
35
35
|
MSG = 'Avoid the use of the case equality operator `===`.'
|
36
36
|
RESTRICT_ON_SEND = %i[===].freeze
|
37
37
|
|
38
|
+
# @!method case_equality?(node)
|
38
39
|
def_node_matcher :case_equality?, '(send $#const? :=== $_)'
|
39
40
|
|
40
41
|
def on_send(node)
|
@@ -64,7 +65,7 @@ module RuboCop
|
|
64
65
|
# The automatic correction from `a === b` to `a.match?(b)` needs to
|
65
66
|
# consider `Regexp.last_match?`, `$~`, `$1`, and etc.
|
66
67
|
# This correction is expected to be supported by `Performance/Regexp` cop.
|
67
|
-
# See: https://github.com/rubocop
|
68
|
+
# See: https://github.com/rubocop/rubocop-performance/issues/152
|
68
69
|
#
|
69
70
|
# So here is noop.
|
70
71
|
when :begin
|
@@ -105,8 +105,7 @@ module RuboCop
|
|
105
105
|
when :===
|
106
106
|
node.arguments.first
|
107
107
|
when :include?, :cover?
|
108
|
-
|
109
|
-
node.arguments.first if receiver.range_type?
|
108
|
+
find_target_in_include_or_cover_node(node)
|
110
109
|
when :match, :match?, :=~
|
111
110
|
find_target_in_match_node(node)
|
112
111
|
end
|
@@ -124,6 +123,12 @@ module RuboCop
|
|
124
123
|
end
|
125
124
|
end
|
126
125
|
|
126
|
+
def find_target_in_include_or_cover_node(node)
|
127
|
+
return unless (receiver = node.receiver)
|
128
|
+
|
129
|
+
node.first_argument if deparenthesize(receiver).range_type?
|
130
|
+
end
|
131
|
+
|
127
132
|
def find_target_in_match_node(node)
|
128
133
|
argument = node.arguments.first
|
129
134
|
receiver = node.receiver
|
@@ -167,8 +172,7 @@ module RuboCop
|
|
167
172
|
lhs, _method, rhs = *node
|
168
173
|
lhs if rhs == target
|
169
174
|
when :include?, :cover?
|
170
|
-
|
171
|
-
receiver if receiver.range_type? && node.arguments.first == target
|
175
|
+
condition_from_include_or_cover_node(node, target)
|
172
176
|
end
|
173
177
|
end
|
174
178
|
# rubocop:enable Metrics/CyclomaticComplexity
|
@@ -184,6 +188,13 @@ module RuboCop
|
|
184
188
|
condition_from_binary_op(lhs, rhs, target)
|
185
189
|
end
|
186
190
|
|
191
|
+
def condition_from_include_or_cover_node(node, target)
|
192
|
+
return unless (receiver = node.receiver)
|
193
|
+
|
194
|
+
receiver = deparenthesize(receiver)
|
195
|
+
receiver if receiver.range_type? && node.first_argument == target
|
196
|
+
end
|
197
|
+
|
187
198
|
def condition_from_binary_op(lhs, rhs, target)
|
188
199
|
lhs = deparenthesize(lhs)
|
189
200
|
rhs = deparenthesize(rhs)
|
@@ -25,6 +25,7 @@ module RuboCop
|
|
25
25
|
|
26
26
|
RESTRICT_ON_SEND = %i[== equal? eql?].freeze
|
27
27
|
|
28
|
+
# @!method class_comparison_candidate?(node)
|
28
29
|
def_node_matcher :class_comparison_candidate?, <<~PATTERN
|
29
30
|
(send
|
30
31
|
{$(send _ :class) (send $(send _ :class) :name)}
|
@@ -49,6 +50,8 @@ module RuboCop
|
|
49
50
|
|
50
51
|
def class_name(class_node, node)
|
51
52
|
if node.children.first.method?(:name)
|
53
|
+
return class_node.receiver.source if class_node.receiver
|
54
|
+
|
52
55
|
class_node.source.delete('"').delete("'")
|
53
56
|
else
|
54
57
|
class_node.source
|