rubocop 0.90.0 → 0.93.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 +2 -2
- data/config/default.yml +79 -3
- data/lib/rubocop.rb +20 -5
- data/lib/rubocop/cached_data.rb +2 -1
- data/lib/rubocop/cli/command/execute_runner.rb +8 -0
- data/lib/rubocop/comment_config.rb +9 -5
- data/lib/rubocop/config_loader.rb +3 -3
- data/lib/rubocop/config_regeneration.rb +33 -0
- data/lib/rubocop/config_store.rb +3 -3
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +5 -1
- data/lib/rubocop/cop/bundler/gem_comment.rb +1 -0
- data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +2 -0
- data/lib/rubocop/cop/correctors/line_break_corrector.rb +2 -2
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +10 -10
- data/lib/rubocop/cop/generator.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/method_name_equal.rb +1 -0
- data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +1 -0
- data/lib/rubocop/cop/internal_affairs/offense_location_keyword.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 +1 -0
- data/lib/rubocop/cop/layout/array_alignment.rb +1 -0
- data/lib/rubocop/cop/layout/begin_end_alignment.rb +77 -0
- data/lib/rubocop/cop/layout/case_indentation.rb +4 -7
- data/lib/rubocop/cop/layout/class_structure.rb +1 -1
- data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/dot_position.rb +6 -9
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +2 -2
- data/lib/rubocop/cop/layout/empty_line_after_multiline_condition.rb +4 -12
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +13 -8
- data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +2 -2
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +1 -2
- data/lib/rubocop/cop/layout/end_alignment.rb +5 -10
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +26 -4
- data/lib/rubocop/cop/layout/space_around_equals_in_parameter_default.rb +4 -13
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +7 -7
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +0 -4
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +6 -21
- data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +3 -8
- data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +2 -2
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +2 -0
- data/lib/rubocop/cop/lint/ambiguous_operator.rb +2 -0
- data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +18 -1
- data/lib/rubocop/cop/lint/big_decimal_new.rb +1 -2
- data/lib/rubocop/cop/lint/boolean_symbol.rb +3 -0
- data/lib/rubocop/cop/lint/constant_definition_in_block.rb +74 -0
- data/lib/rubocop/cop/lint/debugger.rb +2 -3
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -3
- data/lib/rubocop/cop/lint/duplicate_methods.rb +2 -4
- data/lib/rubocop/cop/lint/duplicate_require.rb +7 -2
- data/lib/rubocop/cop/lint/duplicate_rescue_exception.rb +2 -4
- data/lib/rubocop/cop/lint/each_with_object_argument.rb +1 -0
- data/lib/rubocop/cop/lint/empty_file.rb +1 -4
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +2 -0
- data/lib/rubocop/cop/lint/float_comparison.rb +2 -2
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +2 -2
- data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +37 -0
- data/lib/rubocop/cop/lint/identity_comparison.rb +51 -0
- data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +2 -5
- data/lib/rubocop/cop/lint/inherit_exception.rb +2 -2
- data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -0
- data/lib/rubocop/cop/lint/multiple_comparison.rb +3 -1
- data/lib/rubocop/cop/lint/number_conversion.rb +1 -0
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +1 -2
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -1
- data/lib/rubocop/cop/lint/raise_exception.rb +1 -0
- data/lib/rubocop/cop/lint/rand_one.rb +2 -1
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +22 -12
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +14 -4
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +1 -0
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +78 -0
- data/lib/rubocop/cop/lint/rescue_type.rb +0 -1
- data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +3 -1
- data/lib/rubocop/cop/lint/shadowed_exception.rb +6 -6
- data/lib/rubocop/cop/lint/struct_new_override.rb +1 -0
- data/lib/rubocop/cop/lint/to_json.rb +16 -5
- data/lib/rubocop/cop/lint/unreachable_loop.rb +3 -6
- data/lib/rubocop/cop/lint/uri_escape_unescape.rb +3 -1
- data/lib/rubocop/cop/lint/uri_regexp.rb +2 -1
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +3 -9
- data/lib/rubocop/cop/lint/useless_method_definition.rb +20 -27
- data/lib/rubocop/cop/lint/useless_times.rb +106 -0
- data/lib/rubocop/cop/metrics/block_length.rb +3 -1
- data/lib/rubocop/cop/metrics/class_length.rb +14 -6
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +25 -16
- data/lib/rubocop/cop/mixin/comments_help.rb +3 -9
- data/lib/rubocop/cop/mixin/configurable_naming.rb +2 -2
- data/lib/rubocop/cop/mixin/configurable_numbering.rb +3 -3
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +9 -0
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +10 -2
- data/lib/rubocop/cop/mixin/rescue_node.rb +1 -0
- data/lib/rubocop/cop/mixin/statement_modifier.rb +9 -3
- data/lib/rubocop/cop/mixin/visibility_help.rb +4 -16
- data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +1 -1
- data/lib/rubocop/cop/naming/file_name.rb +1 -1
- data/lib/rubocop/cop/offense.rb +15 -2
- 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 +7 -11
- data/lib/rubocop/cop/style/accessor_grouping.rb +3 -0
- data/lib/rubocop/cop/style/alias.rb +2 -0
- data/lib/rubocop/cop/style/array_coercion.rb +4 -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/auto_resource_cleanup.rb +2 -0
- data/lib/rubocop/cop/style/case_equality.rb +3 -0
- data/lib/rubocop/cop/style/case_like_if.rb +20 -4
- data/lib/rubocop/cop/style/class_and_module_children.rb +2 -0
- data/lib/rubocop/cop/style/class_check.rb +6 -9
- data/lib/rubocop/cop/style/class_equality_comparison.rb +64 -0
- data/lib/rubocop/cop/style/class_methods_definitions.rb +42 -16
- data/lib/rubocop/cop/style/class_vars.rb +1 -2
- data/lib/rubocop/cop/style/combinable_loops.rb +13 -11
- data/lib/rubocop/cop/style/comment_annotation.rb +6 -0
- data/lib/rubocop/cop/style/commented_keyword.rb +7 -8
- data/lib/rubocop/cop/style/conditional_assignment.rb +49 -60
- data/lib/rubocop/cop/style/date_time.rb +12 -1
- data/lib/rubocop/cop/style/dir.rb +1 -0
- data/lib/rubocop/cop/style/double_negation.rb +1 -0
- data/lib/rubocop/cop/style/empty_literal.rb +3 -1
- data/lib/rubocop/cop/style/eval_with_location.rb +1 -3
- data/lib/rubocop/cop/style/even_odd.rb +1 -0
- data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -2
- data/lib/rubocop/cop/style/explicit_block_argument.rb +7 -3
- data/lib/rubocop/cop/style/float_division.rb +2 -0
- data/lib/rubocop/cop/style/for.rb +0 -4
- data/lib/rubocop/cop/style/format_string.rb +1 -4
- data/lib/rubocop/cop/style/format_string_token.rb +1 -1
- data/lib/rubocop/cop/style/hash_as_last_array_item.rb +24 -5
- data/lib/rubocop/cop/style/hash_transform_keys.rb +5 -11
- data/lib/rubocop/cop/style/hash_transform_values.rb +5 -11
- data/lib/rubocop/cop/style/if_unless_modifier.rb +0 -4
- data/lib/rubocop/cop/style/implicit_runtime_error.rb +1 -0
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +1 -6
- data/lib/rubocop/cop/style/lambda_call.rb +3 -1
- data/lib/rubocop/cop/style/method_def_parentheses.rb +0 -4
- data/lib/rubocop/cop/style/mixin_usage.rb +8 -27
- data/lib/rubocop/cop/style/multiline_block_chain.rb +2 -2
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +14 -1
- data/lib/rubocop/cop/style/multiline_when_then.rb +1 -0
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +2 -0
- data/lib/rubocop/cop/style/nil_comparison.rb +2 -0
- data/lib/rubocop/cop/style/non_nil_check.rb +2 -0
- data/lib/rubocop/cop/style/not.rb +1 -0
- data/lib/rubocop/cop/style/numeric_predicate.rb +1 -3
- data/lib/rubocop/cop/style/one_line_conditional.rb +3 -1
- data/lib/rubocop/cop/style/optional_boolean_parameter.rb +12 -1
- data/lib/rubocop/cop/style/preferred_hash_methods.rb +2 -0
- data/lib/rubocop/cop/style/raise_args.rb +2 -3
- data/lib/rubocop/cop/style/random_with_offset.rb +4 -3
- data/lib/rubocop/cop/style/redundant_assignment.rb +1 -9
- data/lib/rubocop/cop/style/redundant_begin.rb +36 -8
- data/lib/rubocop/cop/style/redundant_condition.rb +5 -1
- data/lib/rubocop/cop/style/redundant_conditional.rb +4 -5
- data/lib/rubocop/cop/style/redundant_exception.rb +1 -3
- data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +1 -0
- data/lib/rubocop/cop/style/redundant_freeze.rb +2 -1
- data/lib/rubocop/cop/style/redundant_interpolation.rb +6 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +14 -6
- data/lib/rubocop/cop/style/redundant_percent_q.rb +9 -11
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +39 -24
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -15
- data/lib/rubocop/cop/style/redundant_return.rb +17 -17
- data/lib/rubocop/cop/style/redundant_self.rb +7 -9
- data/lib/rubocop/cop/style/redundant_self_assignment.rb +2 -2
- data/lib/rubocop/cop/style/redundant_sort.rb +12 -29
- data/lib/rubocop/cop/style/redundant_sort_by.rb +5 -9
- data/lib/rubocop/cop/style/rescue_standard_error.rb +20 -16
- data/lib/rubocop/cop/style/safe_navigation.rb +5 -0
- data/lib/rubocop/cop/style/sample.rb +2 -1
- data/lib/rubocop/cop/style/send.rb +2 -3
- data/lib/rubocop/cop/style/signal_exception.rb +2 -0
- data/lib/rubocop/cop/style/single_argument_dig.rb +1 -0
- data/lib/rubocop/cop/style/slicing_with_range.rb +2 -1
- data/lib/rubocop/cop/style/stderr_puts.rb +1 -0
- data/lib/rubocop/cop/style/string_concatenation.rb +17 -3
- data/lib/rubocop/cop/style/strip.rb +1 -0
- data/lib/rubocop/cop/style/ternary_parentheses.rb +2 -3
- data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +4 -3
- data/lib/rubocop/cop/style/unpack_first.rb +1 -0
- data/lib/rubocop/cop/style/zero_length_predicate.rb +1 -5
- data/lib/rubocop/cop/util.rb +0 -1
- data/lib/rubocop/cop/variable_force/branch.rb +0 -4
- data/lib/rubocop/core_ext/string.rb +1 -1
- data/lib/rubocop/directive_comment.rb +32 -0
- data/lib/rubocop/ext/regexp_node.rb +23 -7
- data/lib/rubocop/formatter/disabled_config_formatter.rb +12 -5
- data/lib/rubocop/options.rb +37 -17
- data/lib/rubocop/result_cache.rb +38 -15
- data/lib/rubocop/rspec/cop_helper.rb +1 -1
- data/lib/rubocop/rspec/expect_offense.rb +5 -5
- data/lib/rubocop/runner.rb +37 -18
- data/lib/rubocop/target_finder.rb +27 -26
- data/lib/rubocop/target_ruby.rb +1 -1
- data/lib/rubocop/version.rb +6 -1
- metadata +19 -18
- data/lib/rubocop/cop/mixin/regexp_literal_help.rb +0 -43
- data/lib/rubocop/cop/tokens_util.rb +0 -84
@@ -53,8 +53,8 @@ module RuboCop
|
|
53
53
|
MSG = 'Method `%<method>s` is defined at both %<defined>s and ' \
|
54
54
|
'%<current>s.'
|
55
55
|
|
56
|
-
|
57
|
-
|
56
|
+
RESTRICT_ON_SEND = %i[alias_method attr_reader attr_writer
|
57
|
+
attr_accessor attr].freeze
|
58
58
|
|
59
59
|
def initialize(config = nil, options = nil)
|
60
60
|
super
|
@@ -100,8 +100,6 @@ module RuboCop
|
|
100
100
|
|
101
101
|
def_node_matcher :sym_name, '(sym $_name)'
|
102
102
|
def on_send(node)
|
103
|
-
return unless METHOD_DEF_METHODS.include?(node.method_name)
|
104
|
-
|
105
103
|
if (name = alias_method?(node))
|
106
104
|
return if node.ancestors.any?(&:if_type?)
|
107
105
|
return if possible_dsl?(node)
|
@@ -15,9 +15,14 @@ module RuboCop
|
|
15
15
|
# require 'foo'
|
16
16
|
# require 'bar'
|
17
17
|
#
|
18
|
+
# # good
|
19
|
+
# require 'foo'
|
20
|
+
# require_relative 'foo'
|
21
|
+
#
|
18
22
|
class DuplicateRequire < Base
|
19
23
|
MSG = 'Duplicate `%<method>s` detected.'
|
20
24
|
REQUIRE_METHODS = %i[require require_relative].freeze
|
25
|
+
RESTRICT_ON_SEND = REQUIRE_METHODS
|
21
26
|
|
22
27
|
def_node_matcher :require_call?, <<~PATTERN
|
23
28
|
(send {nil? (const _ :Kernel)} {:#{REQUIRE_METHODS.join(' :')}} _)
|
@@ -30,8 +35,8 @@ module RuboCop
|
|
30
35
|
end
|
31
36
|
|
32
37
|
def on_send(node)
|
33
|
-
return unless
|
34
|
-
return if @required[node.parent].add?(node.first_argument)
|
38
|
+
return unless require_call?(node)
|
39
|
+
return if @required[node.parent].add?("#{node.method_name}#{node.first_argument}")
|
35
40
|
|
36
41
|
add_offense(node, message: format(MSG, method: node.method_name))
|
37
42
|
end
|
@@ -33,10 +33,8 @@ module RuboCop
|
|
33
33
|
def on_rescue(node)
|
34
34
|
return if rescue_modifier?(node)
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
resbodies.each_with_object(Set.new) do |resbody, previous|
|
39
|
-
rescued_exceptions = rescued_exceptions(resbody)
|
36
|
+
node.resbody_branches.each_with_object(Set.new) do |resbody, previous|
|
37
|
+
rescued_exceptions = resbody.exceptions
|
40
38
|
|
41
39
|
rescued_exceptions.each do |exception|
|
42
40
|
add_offense(exception) unless previous.add?(exception)
|
@@ -23,6 +23,7 @@ module RuboCop
|
|
23
23
|
# sum = numbers.each_with_object(num) { |e, a| a += e }
|
24
24
|
class EachWithObjectArgument < Base
|
25
25
|
MSG = 'The argument to each_with_object cannot be immutable.'
|
26
|
+
RESTRICT_ON_SEND = %i[each_with_object].freeze
|
26
27
|
|
27
28
|
def_node_matcher :each_with_object?, <<~PATTERN
|
28
29
|
({send csend} _ :each_with_object $_)
|
@@ -35,9 +35,9 @@ module RuboCop
|
|
35
35
|
FLOAT_RETURNING_METHODS = %i[to_f Float fdiv].freeze
|
36
36
|
FLOAT_INSTANCE_METHODS = %i[@- abs magnitude modulo next_float prev_float quo].to_set.freeze
|
37
37
|
|
38
|
-
|
39
|
-
return unless EQUALITY_METHODS.include?(node.method_name)
|
38
|
+
RESTRICT_ON_SEND = EQUALITY_METHODS
|
40
39
|
|
40
|
+
def on_send(node)
|
41
41
|
lhs, _method, rhs = *node
|
42
42
|
add_offense(node) if float?(lhs) || float?(rhs)
|
43
43
|
end
|
@@ -44,10 +44,10 @@ module RuboCop
|
|
44
44
|
KERNEL = 'Kernel'
|
45
45
|
SHOVEL = '<<'
|
46
46
|
STRING_TYPES = %i[str dstr].freeze
|
47
|
-
|
47
|
+
RESTRICT_ON_SEND = %i[format sprintf %].freeze
|
48
48
|
|
49
49
|
def on_send(node)
|
50
|
-
return unless
|
50
|
+
return unless format_string?(node)
|
51
51
|
|
52
52
|
if invalid_format_string?(node)
|
53
53
|
add_offense(node.loc.selector, message: MSG_INVALID)
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
# Prefer using `Hash#compare_by_identity` than using `object_id` for hash keys.
|
7
|
+
#
|
8
|
+
# This cop is marked as unsafe as a hash possibly can contain other keys
|
9
|
+
# besides `object_id`s.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# # bad
|
13
|
+
# hash = {}
|
14
|
+
# hash[foo.object_id] = :bar
|
15
|
+
# hash.key?(baz.object_id)
|
16
|
+
#
|
17
|
+
# # good
|
18
|
+
# hash = {}.compare_by_identity
|
19
|
+
# hash[foo] = :bar
|
20
|
+
# hash.key?(baz)
|
21
|
+
#
|
22
|
+
class HashCompareByIdentity < Base
|
23
|
+
RESTRICT_ON_SEND = %i[key? has_key? fetch [] []=].freeze
|
24
|
+
|
25
|
+
MSG = 'Use `Hash#compare_by_identity` instead of using `object_id` for keys.'
|
26
|
+
|
27
|
+
def_node_matcher :id_as_hash_key?, <<~PATTERN
|
28
|
+
(send _ {:key? :has_key? :fetch :[] :[]=} (send _ :object_id) ...)
|
29
|
+
PATTERN
|
30
|
+
|
31
|
+
def on_send(node)
|
32
|
+
add_offense(node) if id_as_hash_key?(node)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
#
|
7
|
+
# Prefer `equal?` over `==` when comparing `object_id`.
|
8
|
+
#
|
9
|
+
# `Object#equal?` is provided to compare objects for identity, and in contrast
|
10
|
+
# `Object#==` is provided for the purpose of doing value comparison.
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
# # bad
|
14
|
+
# foo.object_id == bar.object_id
|
15
|
+
#
|
16
|
+
# # good
|
17
|
+
# foo.equal?(bar)
|
18
|
+
#
|
19
|
+
class IdentityComparison < Base
|
20
|
+
extend AutoCorrector
|
21
|
+
|
22
|
+
MSG = 'Use `equal?` instead `==` when comparing `object_id`.'
|
23
|
+
RESTRICT_ON_SEND = %i[==].freeze
|
24
|
+
|
25
|
+
def on_send(node)
|
26
|
+
return unless compare_between_object_id_by_double_equal?(node)
|
27
|
+
|
28
|
+
add_offense(node) do |corrector|
|
29
|
+
receiver = node.receiver.receiver
|
30
|
+
argument = node.first_argument.receiver
|
31
|
+
return unless receiver && argument
|
32
|
+
|
33
|
+
replacement = "#{receiver.source}.equal?(#{argument.source})"
|
34
|
+
|
35
|
+
corrector.replace(node, replacement)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def compare_between_object_id_by_double_equal?(node)
|
42
|
+
object_id_method?(node.receiver) && object_id_method?(node.first_argument)
|
43
|
+
end
|
44
|
+
|
45
|
+
def object_id_method?(node)
|
46
|
+
node.send_type? && node.method?(:object_id)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -58,12 +58,9 @@ module RuboCop
|
|
58
58
|
PATTERN
|
59
59
|
|
60
60
|
def on_class(node)
|
61
|
-
check_node(node.
|
62
|
-
end
|
63
|
-
|
64
|
-
def on_module(node)
|
65
|
-
check_node(node.children[1]) # module body
|
61
|
+
check_node(node.body)
|
66
62
|
end
|
63
|
+
alias on_module on_class
|
67
64
|
|
68
65
|
private
|
69
66
|
|
@@ -56,6 +56,8 @@ module RuboCop
|
|
56
56
|
SystemExit
|
57
57
|
].freeze
|
58
58
|
|
59
|
+
RESTRICT_ON_SEND = %i[new].freeze
|
60
|
+
|
59
61
|
def_node_matcher :class_new_call?, <<~PATTERN
|
60
62
|
(send
|
61
63
|
(const {cbase nil?} :Class) :new
|
@@ -74,8 +76,6 @@ module RuboCop
|
|
74
76
|
end
|
75
77
|
|
76
78
|
def on_send(node)
|
77
|
-
return unless node.method?(:new)
|
78
|
-
|
79
79
|
constant = class_new_call?(node)
|
80
80
|
return unless constant && illegal_class_name?(constant)
|
81
81
|
|
@@ -25,9 +25,11 @@ module RuboCop
|
|
25
25
|
extend AutoCorrector
|
26
26
|
|
27
27
|
MSG = 'Use the `&&` operator to compare multiple values.'
|
28
|
+
COMPARISON_METHODS = %i[< > <= >=].freeze
|
29
|
+
RESTRICT_ON_SEND = COMPARISON_METHODS
|
28
30
|
|
29
31
|
def_node_matcher :multiple_compare?, <<~PATTERN
|
30
|
-
(send (send _ {:< :> :<= :>=} $_) {
|
32
|
+
(send (send _ {:< :> :<= :>=} $_) {:#{COMPARISON_METHODS.join(' :')}} _)
|
31
33
|
PATTERN
|
32
34
|
|
33
35
|
def on_send(node)
|
@@ -32,6 +32,7 @@ module RuboCop
|
|
32
32
|
'class parsing, instead of using '\
|
33
33
|
'%<number_object>s.%<to_method>s, use stricter '\
|
34
34
|
'%<corrected_method>s.'
|
35
|
+
RESTRICT_ON_SEND = CONVERSION_METHOD_CLASS_MAPPING.keys.freeze
|
35
36
|
|
36
37
|
def_node_matcher :to_method, <<~PATTERN
|
37
38
|
(send $_ ${:to_i :to_f :to_c})
|
@@ -25,6 +25,7 @@ module RuboCop
|
|
25
25
|
REGEXP_ARGUMENT_METHODS = %i[=~ match grep gsub gsub! sub sub! [] slice slice! index rindex
|
26
26
|
scan partition rpartition start_with? end_with?].to_set.freeze
|
27
27
|
REGEXP_CAPTURE_METHODS = (REGEXP_RECEIVER_METHODS + REGEXP_ARGUMENT_METHODS).freeze
|
28
|
+
RESTRICT_ON_SEND = REGEXP_CAPTURE_METHODS
|
28
29
|
|
29
30
|
def on_new_investigation
|
30
31
|
@valid_ref = 0
|
@@ -35,8 +36,6 @@ module RuboCop
|
|
35
36
|
end
|
36
37
|
|
37
38
|
def on_send(node)
|
38
|
-
return unless REGEXP_CAPTURE_METHODS.include?(node.method_name)
|
39
|
-
|
40
39
|
@valid_ref = nil
|
41
40
|
|
42
41
|
if node.receiver&.regexp_type?
|
@@ -23,13 +23,14 @@ module RuboCop
|
|
23
23
|
class RandOne < Base
|
24
24
|
MSG = '`%<method>s` always returns `0`. ' \
|
25
25
|
'Perhaps you meant `rand(2)` or `rand`?'
|
26
|
+
RESTRICT_ON_SEND = %i[rand].freeze
|
26
27
|
|
27
28
|
def_node_matcher :rand_one?, <<~PATTERN
|
28
29
|
(send {(const {nil? cbase} :Kernel) nil?} :rand {(int {-1 1}) (float {-1.0 1.0})})
|
29
30
|
PATTERN
|
30
31
|
|
31
32
|
def on_send(node)
|
32
|
-
return unless
|
33
|
+
return unless rand_one?(node)
|
33
34
|
|
34
35
|
add_offense(node)
|
35
36
|
end
|
@@ -56,19 +56,29 @@ module RuboCop
|
|
56
56
|
|
57
57
|
private
|
58
58
|
|
59
|
+
def previous_line_blank?(range)
|
60
|
+
processed_source.buffer.source_line(range.line - 1).blank?
|
61
|
+
end
|
62
|
+
|
59
63
|
def comment_range_with_surrounding_space(range)
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
64
|
+
if previous_line_blank?(range)
|
65
|
+
# When the previous line is blank, it should be retained
|
66
|
+
range_with_surrounding_space(range: range, side: :right)
|
67
|
+
else
|
68
|
+
# Eat the entire comment, the preceding space, and the preceding
|
69
|
+
# newline if there is one.
|
70
|
+
original_begin = range.begin_pos
|
71
|
+
range = range_with_surrounding_space(range: range,
|
72
|
+
side: :left,
|
73
|
+
newlines: true)
|
74
|
+
|
75
|
+
range_with_surrounding_space(range: range,
|
76
|
+
side: :right,
|
77
|
+
# Special for a comment that
|
78
|
+
# begins the file: remove
|
79
|
+
# the newline at the end.
|
80
|
+
newlines: original_begin.zero?)
|
81
|
+
end
|
72
82
|
end
|
73
83
|
|
74
84
|
def directive_range_in_list(range, ranges)
|
@@ -45,18 +45,28 @@ module RuboCop
|
|
45
45
|
return if processed_source.blank?
|
46
46
|
|
47
47
|
offenses = processed_source.comment_config.extra_enabled_comments
|
48
|
-
offenses.each
|
48
|
+
offenses.each { |comment, cop_names| register_offense(comment, cop_names) }
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def register_offense(comment, cop_names)
|
54
|
+
directive = DirectiveComment.new(comment)
|
55
|
+
|
56
|
+
cop_names.each do |name|
|
49
57
|
add_offense(
|
50
58
|
range_of_offense(comment, name),
|
51
59
|
message: format(MSG, cop: all_or_name(name))
|
52
60
|
) do |corrector|
|
53
|
-
|
61
|
+
if directive.match?(cop_names)
|
62
|
+
corrector.remove(range_with_surrounding_space(range: directive.range, side: :right))
|
63
|
+
else
|
64
|
+
corrector.remove(range_with_comma(comment, name))
|
65
|
+
end
|
54
66
|
end
|
55
67
|
end
|
56
68
|
end
|
57
69
|
|
58
|
-
private
|
59
|
-
|
60
70
|
def range_of_offense(comment, name)
|
61
71
|
start_pos = comment_start(comment) + cop_name_indention(comment, name)
|
62
72
|
range_between(start_pos, start_pos + name.size)
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
# This cop checks for redundant safe navigation calls.
|
7
|
+
# `instance_of?`, `kind_of?`, `is_a?`, `eql?`, `respond_to?`, and `equal?` methods
|
8
|
+
# are checked by default. These are customizable with `AllowedMethods` option.
|
9
|
+
#
|
10
|
+
# This cop is marked as unsafe, because auto-correction can change the
|
11
|
+
# return type of the expression. An offending expression that previously
|
12
|
+
# could return `nil` will be auto-corrected to never return `nil`.
|
13
|
+
#
|
14
|
+
# In the example below, the safe navigation operator (`&.`) is unnecessary
|
15
|
+
# because `NilClass` has methods like `respond_to?` and `is_a?`.
|
16
|
+
#
|
17
|
+
# @example
|
18
|
+
# # bad
|
19
|
+
# do_something if attrs&.respond_to?(:[])
|
20
|
+
#
|
21
|
+
# # good
|
22
|
+
# do_something if attrs.respond_to?(:[])
|
23
|
+
#
|
24
|
+
# # bad
|
25
|
+
# while node&.is_a?(BeginNode)
|
26
|
+
# node = node.parent
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# # good
|
30
|
+
# while node.is_a?(BeginNode)
|
31
|
+
# node = node.parent
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# # good - without `&.` this will always return `true`
|
35
|
+
# foo&.respond_to?(:to_a)
|
36
|
+
#
|
37
|
+
class RedundantSafeNavigation < Base
|
38
|
+
include AllowedMethods
|
39
|
+
include RangeHelp
|
40
|
+
extend AutoCorrector
|
41
|
+
|
42
|
+
MSG = 'Redundant safe navigation detected.'
|
43
|
+
|
44
|
+
NIL_SPECIFIC_METHODS = (nil.methods - Object.new.methods).to_set.freeze
|
45
|
+
|
46
|
+
def_node_matcher :respond_to_nil_specific_method?, <<~PATTERN
|
47
|
+
(csend _ :respond_to? (sym %NIL_SPECIFIC_METHODS))
|
48
|
+
PATTERN
|
49
|
+
|
50
|
+
def on_csend(node)
|
51
|
+
return unless check?(node) && allowed_method?(node.method_name)
|
52
|
+
return if respond_to_nil_specific_method?(node)
|
53
|
+
|
54
|
+
range = range_between(node.loc.dot.begin_pos, node.source_range.end_pos)
|
55
|
+
add_offense(range) do |corrector|
|
56
|
+
corrector.replace(node.loc.dot, '.')
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def check?(node)
|
63
|
+
parent = node.parent
|
64
|
+
return false unless parent
|
65
|
+
|
66
|
+
condition?(parent, node) ||
|
67
|
+
parent.and_type? ||
|
68
|
+
parent.or_type? ||
|
69
|
+
(parent.send_type? && parent.negation_method?)
|
70
|
+
end
|
71
|
+
|
72
|
+
def condition?(parent, node)
|
73
|
+
(parent.conditional? || parent.post_condition_loop?) && parent.condition == node
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|