rubocop 1.50.2 → 1.53.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +3 -3
- data/config/default.yml +76 -6
- data/lib/rubocop/cli/command/lsp.rb +19 -0
- data/lib/rubocop/cli.rb +3 -0
- data/lib/rubocop/config.rb +4 -0
- data/lib/rubocop/config_loader_resolver.rb +4 -3
- data/lib/rubocop/config_obsoletion.rb +2 -2
- data/lib/rubocop/cop/base.rb +5 -1
- data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
- data/lib/rubocop/cop/bundler/gem_version.rb +2 -2
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +1 -1
- data/lib/rubocop/cop/gemspec/dependency_version.rb +2 -2
- data/lib/rubocop/cop/gemspec/development_dependencies.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/cop_description.rb +32 -8
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +5 -5
- data/lib/rubocop/cop/layout/class_structure.rb +7 -0
- data/lib/rubocop/cop/layout/closing_heredoc_indentation.rb +1 -2
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +2 -0
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
- data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +2 -2
- data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -1
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +2 -0
- data/lib/rubocop/cop/layout/space_inside_range_literal.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +13 -1
- data/lib/rubocop/cop/lint/debugger.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_hash_key.rb +2 -1
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +46 -19
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +3 -4
- data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +1 -1
- data/lib/rubocop/cop/lint/identity_comparison.rb +0 -1
- data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -3
- data/lib/rubocop/cop/lint/inherit_exception.rb +9 -0
- data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
- data/lib/rubocop/cop/lint/missing_super.rb +34 -5
- data/lib/rubocop/cop/lint/mixed_case_range.rb +109 -0
- data/lib/rubocop/cop/lint/number_conversion.rb +5 -0
- data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +2 -2
- data/lib/rubocop/cop/lint/ordered_magic_comments.rb +0 -1
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +2 -2
- data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +120 -0
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +8 -3
- data/lib/rubocop/cop/lint/redundant_string_coercion.rb +1 -1
- data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +1 -2
- data/lib/rubocop/cop/lint/shadowed_exception.rb +5 -11
- data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
- data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +23 -9
- data/lib/rubocop/cop/lint/useless_assignment.rb +59 -1
- data/lib/rubocop/cop/lint/void.rb +63 -7
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -2
- data/lib/rubocop/cop/migration/department_name.rb +2 -2
- data/lib/rubocop/cop/mixin/allowed_receivers.rb +34 -0
- data/lib/rubocop/cop/mixin/comments_help.rb +7 -3
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -1
- data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
- data/lib/rubocop/cop/naming/block_forwarding.rb +1 -1
- data/lib/rubocop/cop/naming/constant_name.rb +1 -1
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +25 -10
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +11 -3
- data/lib/rubocop/cop/naming/variable_name.rb +6 -1
- data/lib/rubocop/cop/style/accessor_grouping.rb +5 -1
- data/lib/rubocop/cop/style/attr.rb +11 -1
- data/lib/rubocop/cop/style/begin_block.rb +1 -2
- data/lib/rubocop/cop/style/block_comments.rb +1 -1
- data/lib/rubocop/cop/style/block_delimiters.rb +3 -3
- data/lib/rubocop/cop/style/class_and_module_children.rb +1 -1
- data/lib/rubocop/cop/style/class_equality_comparison.rb +17 -39
- data/lib/rubocop/cop/style/collection_compact.rb +16 -6
- data/lib/rubocop/cop/style/colon_method_call.rb +2 -2
- data/lib/rubocop/cop/style/combinable_loops.rb +26 -6
- data/lib/rubocop/cop/style/conditional_assignment.rb +5 -3
- data/lib/rubocop/cop/style/copyright.rb +5 -2
- data/lib/rubocop/cop/style/dir.rb +1 -1
- data/lib/rubocop/cop/style/dir_empty.rb +8 -14
- data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +1 -1
- data/lib/rubocop/cop/style/documentation.rb +1 -1
- data/lib/rubocop/cop/style/eval_with_location.rb +5 -5
- data/lib/rubocop/cop/style/exact_regexp_match.rb +68 -0
- data/lib/rubocop/cop/style/file_read.rb +2 -2
- data/lib/rubocop/cop/style/guard_clause.rb +2 -0
- data/lib/rubocop/cop/style/hash_each_methods.rb +1 -22
- data/lib/rubocop/cop/style/hash_except.rb +19 -8
- data/lib/rubocop/cop/style/hash_transform_keys.rb +2 -2
- data/lib/rubocop/cop/style/hash_transform_values.rb +2 -2
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +6 -2
- data/lib/rubocop/cop/style/if_inside_else.rb +6 -0
- data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -0
- data/lib/rubocop/cop/style/invertible_unless_condition.rb +10 -6
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +3 -4
- data/lib/rubocop/cop/style/multiple_comparison.rb +14 -0
- data/lib/rubocop/cop/style/numeric_literals.rb +1 -1
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
- data/lib/rubocop/cop/style/preferred_hash_methods.rb +1 -1
- data/lib/rubocop/cop/style/redundant_array_constructor.rb +77 -0
- data/lib/rubocop/cop/style/redundant_begin.rb +1 -1
- data/lib/rubocop/cop/style/redundant_conditional.rb +1 -1
- data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +38 -0
- data/lib/rubocop/cop/style/redundant_filter_chain.rb +101 -0
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +7 -3
- data/lib/rubocop/cop/style/redundant_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +86 -0
- data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +46 -0
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +2 -1
- data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +3 -1
- data/lib/rubocop/cop/style/redundant_sort.rb +1 -1
- data/lib/rubocop/cop/style/redundant_string_escape.rb +2 -0
- data/lib/rubocop/cop/style/regexp_literal.rb +11 -2
- data/lib/rubocop/cop/style/require_order.rb +11 -5
- data/lib/rubocop/cop/style/rescue_modifier.rb +1 -3
- data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +81 -0
- data/lib/rubocop/cop/style/select_by_regexp.rb +15 -5
- data/lib/rubocop/cop/style/semicolon.rb +12 -1
- data/lib/rubocop/cop/style/signal_exception.rb +1 -1
- data/lib/rubocop/cop/style/single_line_methods.rb +1 -1
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +3 -1
- data/lib/rubocop/cop/style/special_global_vars.rb +3 -4
- data/lib/rubocop/cop/style/yaml_file_read.rb +66 -0
- data/lib/rubocop/cop/team.rb +1 -1
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/cop/utils/regexp_ranges.rb +100 -0
- data/lib/rubocop/cop/variable_force/assignment.rb +33 -1
- data/lib/rubocop/cop/variable_force/variable_table.rb +2 -2
- data/lib/rubocop/cop/variable_force.rb +1 -0
- data/lib/rubocop/cops_documentation_generator.rb +1 -1
- data/lib/rubocop/ext/regexp_parser.rb +4 -1
- data/lib/rubocop/lsp/logger.rb +22 -0
- data/lib/rubocop/lsp/routes.rb +223 -0
- data/lib/rubocop/lsp/runtime.rb +79 -0
- data/lib/rubocop/lsp/server.rb +62 -0
- data/lib/rubocop/lsp/severity.rb +27 -0
- data/lib/rubocop/options.rb +11 -1
- data/lib/rubocop/result_cache.rb +1 -1
- data/lib/rubocop/rspec/cop_helper.rb +1 -1
- data/lib/rubocop/server/client_command/exec.rb +2 -1
- data/lib/rubocop/target_ruby.rb +3 -2
- data/lib/rubocop/version.rb +10 -6
- data/lib/rubocop.rb +13 -0
- metadata +38 -6
@@ -411,7 +411,7 @@ module RuboCop
|
|
411
411
|
end
|
412
412
|
|
413
413
|
def correction_would_break_code?(node)
|
414
|
-
return unless node.keywords?
|
414
|
+
return false unless node.keywords?
|
415
415
|
|
416
416
|
node.send_node.arguments? && !node.send_node.parenthesized?
|
417
417
|
end
|
@@ -433,7 +433,7 @@ module RuboCop
|
|
433
433
|
end
|
434
434
|
|
435
435
|
def return_value_used?(node)
|
436
|
-
return unless node.parent
|
436
|
+
return false unless node.parent
|
437
437
|
|
438
438
|
# If there are parentheses around the block, check if that
|
439
439
|
# is being used.
|
@@ -445,7 +445,7 @@ module RuboCop
|
|
445
445
|
end
|
446
446
|
|
447
447
|
def return_value_of_scope?(node)
|
448
|
-
return unless node.parent
|
448
|
+
return false unless node.parent
|
449
449
|
|
450
450
|
conditional?(node.parent) || array_or_range?(node.parent) ||
|
451
451
|
node.parent.children.last == node
|
@@ -5,7 +5,7 @@ module RuboCop
|
|
5
5
|
module Style
|
6
6
|
# Enforces the use of `Object#instance_of?` instead of class comparison
|
7
7
|
# for equality.
|
8
|
-
# `==`, `equal?`, and `eql?`
|
8
|
+
# `==`, `equal?`, and `eql?` custom method definitions are allowed by default.
|
9
9
|
# These are customizable with `AllowedMethods` option.
|
10
10
|
#
|
11
11
|
# @example
|
@@ -18,53 +18,31 @@ module RuboCop
|
|
18
18
|
# # good
|
19
19
|
# var.instance_of?(Date)
|
20
20
|
#
|
21
|
-
# @example AllowedMethods: [] (default)
|
21
|
+
# @example AllowedMethods: ['==', 'equal?', 'eql?'] (default)
|
22
22
|
# # good
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
# var.class == Date
|
27
|
-
# var.class.equal?(Date)
|
28
|
-
# var.class.eql?(Date)
|
29
|
-
# var.class.name == 'Date'
|
30
|
-
# var.class.to_s == 'Date'
|
31
|
-
# var.class.inspect == 'Date'
|
23
|
+
# def ==(other)
|
24
|
+
# self.class == other.class && name == other.name
|
25
|
+
# end
|
32
26
|
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
# var.class == Date
|
37
|
-
# var.class.name == 'Date'
|
38
|
-
# var.class.to_s == 'Date'
|
39
|
-
# var.class.inspect == 'Date'
|
27
|
+
# def equal?(other)
|
28
|
+
# self.class.equal?(other.class) && name.equal?(other.name)
|
29
|
+
# end
|
40
30
|
#
|
41
|
-
#
|
42
|
-
#
|
43
|
-
#
|
31
|
+
# def eql?(other)
|
32
|
+
# self.class.eql?(other.class) && name.eql?(other.name)
|
33
|
+
# end
|
44
34
|
#
|
45
35
|
# @example AllowedPatterns: [] (default)
|
46
|
-
# # good
|
47
|
-
# var.instance_of?(Date)
|
48
|
-
#
|
49
36
|
# # bad
|
50
|
-
#
|
51
|
-
#
|
52
|
-
#
|
53
|
-
# var.class.name == 'Date'
|
54
|
-
# var.class.to_s == 'Date'
|
55
|
-
# var.class.inspect == 'Date'
|
37
|
+
# def eq(other)
|
38
|
+
# self.class.eq(other.class) && name.eq(other.name)
|
39
|
+
# end
|
56
40
|
#
|
57
41
|
# @example AllowedPatterns: ['eq']
|
58
42
|
# # good
|
59
|
-
#
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
63
|
-
# # bad
|
64
|
-
# var.class == Date
|
65
|
-
# var.class.name == 'Date'
|
66
|
-
# var.class.to_s == 'Date'
|
67
|
-
# var.class.inspect == 'Date'
|
43
|
+
# def eq(other)
|
44
|
+
# self.class.eq(other.class) && name.eq(other.name)
|
45
|
+
# end
|
68
46
|
#
|
69
47
|
class ClassEqualityComparison < Base
|
70
48
|
include RangeHelp
|
@@ -9,8 +9,8 @@ module RuboCop
|
|
9
9
|
# @safety
|
10
10
|
# It is unsafe by default because false positives may occur in the
|
11
11
|
# `nil` check of block arguments to the receiver object. Additionally,
|
12
|
-
#
|
13
|
-
#
|
12
|
+
# we can't know the type of the receiver object for sure, which may
|
13
|
+
# result in false positives as well.
|
14
14
|
#
|
15
15
|
# For example, `[[1, 2], [3, nil]].reject { |first, second| second.nil? }`
|
16
16
|
# and `[[1, 2], [3, nil]].compact` are not compatible. This will work fine
|
@@ -19,7 +19,9 @@ module RuboCop
|
|
19
19
|
# @example
|
20
20
|
# # bad
|
21
21
|
# array.reject(&:nil?)
|
22
|
+
# array.delete_if(&:nil?)
|
22
23
|
# array.reject { |e| e.nil? }
|
24
|
+
# array.delete_if { |e| e.nil? }
|
23
25
|
# array.select { |e| !e.nil? }
|
24
26
|
#
|
25
27
|
# # good
|
@@ -33,20 +35,25 @@ module RuboCop
|
|
33
35
|
# # good
|
34
36
|
# hash.compact!
|
35
37
|
#
|
38
|
+
# @example AllowedReceivers: ['params']
|
39
|
+
# # good
|
40
|
+
# params.reject(&:nil?)
|
41
|
+
#
|
36
42
|
class CollectionCompact < Base
|
43
|
+
include AllowedReceivers
|
37
44
|
include RangeHelp
|
38
45
|
extend AutoCorrector
|
39
46
|
extend TargetRubyVersion
|
40
47
|
|
41
48
|
MSG = 'Use `%<good>s` instead of `%<bad>s`.'
|
42
|
-
RESTRICT_ON_SEND = %i[reject reject! select select!].freeze
|
49
|
+
RESTRICT_ON_SEND = %i[reject delete_if reject! select select!].freeze
|
43
50
|
TO_ENUM_METHODS = %i[to_enum lazy].freeze
|
44
51
|
|
45
52
|
minimum_target_ruby_version 2.4
|
46
53
|
|
47
54
|
# @!method reject_method_with_block_pass?(node)
|
48
55
|
def_node_matcher :reject_method_with_block_pass?, <<~PATTERN
|
49
|
-
(send !nil? {:reject :reject!}
|
56
|
+
(send !nil? {:reject :delete_if :reject!}
|
50
57
|
(block_pass
|
51
58
|
(sym :nil?)))
|
52
59
|
PATTERN
|
@@ -55,7 +62,7 @@ module RuboCop
|
|
55
62
|
def_node_matcher :reject_method?, <<~PATTERN
|
56
63
|
(block
|
57
64
|
(send
|
58
|
-
!nil? {:reject :reject!})
|
65
|
+
!nil? {:reject :delete_if :reject!})
|
59
66
|
$(args ...)
|
60
67
|
(send
|
61
68
|
$(lvar _) :nil?))
|
@@ -74,7 +81,10 @@ module RuboCop
|
|
74
81
|
|
75
82
|
def on_send(node)
|
76
83
|
return unless (range = offense_range(node))
|
77
|
-
return if
|
84
|
+
return if allowed_receiver?(node.receiver)
|
85
|
+
if (target_ruby_version <= 3.0 || node.method?(:delete_if)) && to_enum_method?(node)
|
86
|
+
return
|
87
|
+
end
|
78
88
|
|
79
89
|
good = good_method_name(node)
|
80
90
|
message = format(MSG, good: good, bad: range.source)
|
@@ -3,8 +3,8 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
# Checks for methods invoked via the
|
7
|
-
# of the
|
6
|
+
# Checks for methods invoked via the `::` operator instead
|
7
|
+
# of the `.` operator (like `FileUtils::rmdir` instead of `FileUtils.rmdir`).
|
8
8
|
#
|
9
9
|
# @example
|
10
10
|
# # bad
|
@@ -57,38 +57,58 @@ module RuboCop
|
|
57
57
|
# end
|
58
58
|
#
|
59
59
|
class CombinableLoops < Base
|
60
|
+
extend AutoCorrector
|
61
|
+
|
62
|
+
include RangeHelp
|
63
|
+
|
60
64
|
MSG = 'Combine this loop with the previous loop.'
|
61
65
|
|
62
66
|
def on_block(node)
|
63
67
|
return unless node.parent&.begin_type?
|
64
68
|
return unless collection_looping_method?(node)
|
69
|
+
return unless same_collection_looping_block?(node, node.left_sibling)
|
65
70
|
|
66
|
-
add_offense(node)
|
71
|
+
add_offense(node) do |corrector|
|
72
|
+
combine_with_left_sibling(corrector, node)
|
73
|
+
end
|
67
74
|
end
|
68
75
|
|
69
76
|
alias on_numblock on_block
|
70
77
|
|
71
78
|
def on_for(node)
|
72
79
|
return unless node.parent&.begin_type?
|
80
|
+
return unless same_collection_looping_for?(node, node.left_sibling)
|
73
81
|
|
74
|
-
|
75
|
-
|
82
|
+
add_offense(node) do |corrector|
|
83
|
+
combine_with_left_sibling(corrector, node)
|
84
|
+
end
|
76
85
|
end
|
77
86
|
|
78
87
|
private
|
79
88
|
|
80
89
|
def collection_looping_method?(node)
|
81
|
-
|
82
|
-
method_name = node.method_name.to_s
|
90
|
+
method_name = node.method_name
|
83
91
|
method_name.start_with?('each') || method_name.end_with?('_each')
|
84
92
|
end
|
85
93
|
|
86
|
-
def
|
94
|
+
def same_collection_looping_block?(node, sibling)
|
87
95
|
(sibling&.block_type? || sibling&.numblock_type?) &&
|
88
96
|
sibling.send_node.method?(node.method_name) &&
|
89
97
|
sibling.receiver == node.receiver &&
|
90
98
|
sibling.send_node.arguments == node.send_node.arguments
|
91
99
|
end
|
100
|
+
|
101
|
+
def same_collection_looping_for?(node, sibling)
|
102
|
+
sibling&.for_type? && node.collection == sibling.collection
|
103
|
+
end
|
104
|
+
|
105
|
+
def combine_with_left_sibling(corrector, node)
|
106
|
+
corrector.replace(
|
107
|
+
node.left_sibling.body,
|
108
|
+
"#{node.left_sibling.body.source}\n#{node.body.source}"
|
109
|
+
)
|
110
|
+
corrector.remove(range_with_surrounding_space(range: node.source_range, side: :left))
|
111
|
+
end
|
92
112
|
end
|
93
113
|
end
|
94
114
|
end
|
@@ -350,7 +350,7 @@ module RuboCop
|
|
350
350
|
end
|
351
351
|
|
352
352
|
def ternary_condition?(node)
|
353
|
-
[node, node.children.first].any? { |n| n.if_type? && n.ternary? }
|
353
|
+
[node, node.children.first].compact.any? { |n| n.if_type? && n.ternary? }
|
354
354
|
end
|
355
355
|
|
356
356
|
def lhs_all_match?(branches)
|
@@ -361,7 +361,7 @@ module RuboCop
|
|
361
361
|
end
|
362
362
|
|
363
363
|
def assignment_types_match?(*nodes)
|
364
|
-
return unless assignment_type?(nodes.first)
|
364
|
+
return false unless assignment_type?(nodes.first)
|
365
365
|
|
366
366
|
nodes.map(&:type).uniq.one?
|
367
367
|
end
|
@@ -386,7 +386,7 @@ module RuboCop
|
|
386
386
|
def allowed_statements?(branches)
|
387
387
|
return false unless branches.all?
|
388
388
|
|
389
|
-
statements = branches.
|
389
|
+
statements = branches.filter_map { |branch| tail(branch) }
|
390
390
|
|
391
391
|
lhs_all_match?(statements) && statements.none?(&:masgn_type?) &&
|
392
392
|
assignment_types_match?(*statements)
|
@@ -440,6 +440,8 @@ module RuboCop
|
|
440
440
|
module ConditionalCorrectorHelper
|
441
441
|
def remove_whitespace_in_branches(corrector, branch, condition, column)
|
442
442
|
branch.each_node do |child|
|
443
|
+
next if child.source_range.nil?
|
444
|
+
|
443
445
|
white_space = white_space_range(child, column)
|
444
446
|
corrector.remove(white_space) if white_space.source.strip.empty?
|
445
447
|
end
|
@@ -8,8 +8,11 @@ module RuboCop
|
|
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:
|
10
10
|
#
|
11
|
-
#
|
12
|
-
#
|
11
|
+
# [source,yaml]
|
12
|
+
# ----
|
13
|
+
# Style/Copyright:
|
14
|
+
# Notice: '^Copyright (\(c\) )?2\d{3} Acme Inc'
|
15
|
+
# ----
|
13
16
|
#
|
14
17
|
# This regex string is treated as an unanchored regex. For each file
|
15
18
|
# that RuboCop scans, a comment that matches this regex must be found or
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
# Checks for places where the
|
6
|
+
# Checks for places where the `#\_\_dir\_\_` method can replace more
|
7
7
|
# complex constructs to retrieve a canonicalized absolute path to the
|
8
8
|
# current file.
|
9
9
|
#
|
@@ -19,18 +19,16 @@ module RuboCop
|
|
19
19
|
extend AutoCorrector
|
20
20
|
extend TargetRubyVersion
|
21
21
|
|
22
|
-
MSG = 'Use
|
23
|
-
RESTRICT_ON_SEND = %i[== > empty? none?].freeze
|
22
|
+
MSG = 'Use `%<replacement>s` instead.'
|
23
|
+
RESTRICT_ON_SEND = %i[== != > empty? none?].freeze
|
24
24
|
|
25
25
|
minimum_target_ruby_version 2.4
|
26
26
|
|
27
27
|
# @!method offensive?(node)
|
28
28
|
def_node_matcher :offensive?, <<~PATTERN
|
29
29
|
{
|
30
|
-
(send (send (send $(const {nil? cbase} :Dir) :entries $_) :size) {:== :>} (int 2))
|
31
|
-
(send (send (send $(const {nil? cbase} :Dir) :children $_) :size) {:== :>} (int 0))
|
32
|
-
(send (send (send (send $(const {nil? cbase} :Dir) :entries $_) :size) :!) {:== :>} (int 2))
|
33
|
-
(send (send (send (send $(const {nil? cbase} :Dir) :children $_) :size) :!) {:== :>} (int 0))
|
30
|
+
(send (send (send $(const {nil? cbase} :Dir) :entries $_) :size) {:== :!= :>} (int 2))
|
31
|
+
(send (send (send $(const {nil? cbase} :Dir) :children $_) :size) {:== :!= :>} (int 0))
|
34
32
|
(send (send $(const {nil? cbase} :Dir) :children $_) :empty?)
|
35
33
|
(send (send $(const {nil? cbase} :Dir) :each_child $_) :none?)
|
36
34
|
}
|
@@ -38,10 +36,9 @@ module RuboCop
|
|
38
36
|
|
39
37
|
def on_send(node)
|
40
38
|
offensive?(node) do |const_node, arg_node|
|
41
|
-
|
42
|
-
|
43
|
-
corrector.replace(node,
|
44
|
-
"#{bang(node)}#{const_node.source}.empty?(#{arg_node.source})")
|
39
|
+
replacement = "#{bang(node)}#{const_node.source}.empty?(#{arg_node.source})"
|
40
|
+
add_offense(node, message: format(MSG, replacement: replacement)) do |corrector|
|
41
|
+
corrector.replace(node, replacement)
|
45
42
|
end
|
46
43
|
end
|
47
44
|
end
|
@@ -49,10 +46,7 @@ module RuboCop
|
|
49
46
|
private
|
50
47
|
|
51
48
|
def bang(node)
|
52
|
-
if
|
53
|
-
(node.method?(:>) && !node.child_nodes.first.method?(:!))
|
54
|
-
'!'
|
55
|
-
end
|
49
|
+
'!' if %i[!= >].include? node.method_name
|
56
50
|
end
|
57
51
|
end
|
58
52
|
end
|
@@ -108,7 +108,7 @@ module RuboCop
|
|
108
108
|
comments = heredoc_comment_blocks(arg_node.loc.heredoc_body.line_span)
|
109
109
|
.concat(preceding_comment_blocks(arg_node.parent))
|
110
110
|
|
111
|
-
return if comments.none?
|
111
|
+
return false if comments.none?
|
112
112
|
|
113
113
|
regexp = comment_regexp(arg_node)
|
114
114
|
comments.any?(regexp) || regexp.match?(comments.join)
|
@@ -10,7 +10,7 @@ module RuboCop
|
|
10
10
|
# declarations.
|
11
11
|
#
|
12
12
|
# The documentation requirement is annulled if the class or module has
|
13
|
-
# a
|
13
|
+
# a `#:nodoc:` comment next to it. Likewise, `#:nodoc: all` does the
|
14
14
|
# same for all its children.
|
15
15
|
#
|
16
16
|
# @example
|
@@ -4,12 +4,12 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
6
|
# Ensures that eval methods (`eval`, `instance_eval`, `class_eval`
|
7
|
-
# and `module_eval`) are given filename and line number values (`
|
8
|
-
# and `
|
7
|
+
# and `module_eval`) are given filename and line number values (`\_\_FILE\_\_`
|
8
|
+
# and `\_\_LINE\_\_`). This data is used to ensure that any errors raised
|
9
9
|
# within the evaluated code will be given the correct identification
|
10
10
|
# in a backtrace.
|
11
11
|
#
|
12
|
-
# The cop also checks that the line number given relative to `
|
12
|
+
# The cop also checks that the line number given relative to `\_\_LINE\_\_` is
|
13
13
|
# correct.
|
14
14
|
#
|
15
15
|
# This cop will autocorrect incorrect or missing filename and line number
|
@@ -57,7 +57,7 @@ module RuboCop
|
|
57
57
|
extend AutoCorrector
|
58
58
|
|
59
59
|
MSG = 'Pass `__FILE__` and `__LINE__` to `%<method_name>s`.'
|
60
|
-
MSG_EVAL = 'Pass a binding, `__FILE__
|
60
|
+
MSG_EVAL = 'Pass a binding, `__FILE__`, and `__LINE__` to `eval`.'
|
61
61
|
MSG_INCORRECT_FILE = 'Incorrect file for `%<method_name>s`; ' \
|
62
62
|
'use `%<expected>s` instead of `%<actual>s`.'
|
63
63
|
MSG_INCORRECT_LINE = 'Incorrect line number for `%<method_name>s`; ' \
|
@@ -210,7 +210,7 @@ module RuboCop
|
|
210
210
|
def add_offense_for_missing_line(node, code)
|
211
211
|
register_offense(node) do |corrector|
|
212
212
|
line_str = missing_line(node, code)
|
213
|
-
corrector.insert_after(node.source_range.end, ", #{line_str}")
|
213
|
+
corrector.insert_after(node.last_argument.source_range.end, ", #{line_str}")
|
214
214
|
end
|
215
215
|
end
|
216
216
|
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Checks for exact regexp match inside Regexp literals.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
#
|
10
|
+
# # bad
|
11
|
+
# string =~ /\Astring\z/
|
12
|
+
# string === /\Astring\z/
|
13
|
+
# string.match(/\Astring\z/)
|
14
|
+
# string.match?(/\Astring\z/)
|
15
|
+
#
|
16
|
+
# # good
|
17
|
+
# string == 'string'
|
18
|
+
#
|
19
|
+
# # bad
|
20
|
+
# string !~ /\Astring\z/
|
21
|
+
#
|
22
|
+
# # good
|
23
|
+
# string != 'string'
|
24
|
+
#
|
25
|
+
class ExactRegexpMatch < Base
|
26
|
+
extend AutoCorrector
|
27
|
+
|
28
|
+
MSG = 'Use `%<prefer>s`.'
|
29
|
+
RESTRICT_ON_SEND = %i[=~ === !~ match match?].freeze
|
30
|
+
|
31
|
+
# @!method exact_regexp_match(node)
|
32
|
+
def_node_matcher :exact_regexp_match, <<~PATTERN
|
33
|
+
(send
|
34
|
+
_ {:=~ :=== :!~ :match :match?}
|
35
|
+
(regexp
|
36
|
+
(str $_)
|
37
|
+
(regopt)))
|
38
|
+
PATTERN
|
39
|
+
|
40
|
+
def on_send(node)
|
41
|
+
return unless (regexp = exact_regexp_match(node))
|
42
|
+
|
43
|
+
parsed_regexp = Regexp::Parser.parse(regexp)
|
44
|
+
return unless exact_match_pattern?(parsed_regexp)
|
45
|
+
|
46
|
+
prefer = "#{node.receiver.source} #{new_method(node)} '#{parsed_regexp[1].text}'"
|
47
|
+
|
48
|
+
add_offense(node, message: format(MSG, prefer: prefer)) do |corrector|
|
49
|
+
corrector.replace(node, prefer)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def exact_match_pattern?(parsed_regexp)
|
56
|
+
tokens = parsed_regexp.map(&:token)
|
57
|
+
return false unless tokens[0] == :bos && tokens[1] == :literal && tokens[2] == :eos
|
58
|
+
|
59
|
+
!parsed_regexp[1].quantifier
|
60
|
+
end
|
61
|
+
|
62
|
+
def new_method(node)
|
63
|
+
node.method?(:!~) ? '!=' : '=='
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -63,7 +63,7 @@ module RuboCop
|
|
63
63
|
|
64
64
|
# @!method block_read?(node)
|
65
65
|
def_node_matcher :block_read?, <<~PATTERN
|
66
|
-
(block _ (args (arg
|
66
|
+
(block _ (args (arg _name)) (send (lvar _name) :read))
|
67
67
|
PATTERN
|
68
68
|
|
69
69
|
def on_send(node)
|
@@ -100,7 +100,7 @@ module RuboCop
|
|
100
100
|
def file_open_read?(node)
|
101
101
|
return true if send_read?(node)
|
102
102
|
|
103
|
-
block_read?(node)
|
103
|
+
block_read?(node)
|
104
104
|
end
|
105
105
|
|
106
106
|
def read_method(mode)
|
@@ -187,6 +187,8 @@ module RuboCop
|
|
187
187
|
if_branch = node.if_branch
|
188
188
|
else_branch = node.else_branch
|
189
189
|
|
190
|
+
corrector.replace(node.loc.begin, "\n") if node.loc.begin&.is?('then')
|
191
|
+
|
190
192
|
if if_branch&.send_type? && heredoc?(if_branch.last_argument)
|
191
193
|
autocorrect_heredoc_argument(corrector, node, if_branch, else_branch, guard)
|
192
194
|
elsif else_branch&.send_type? && heredoc?(else_branch.last_argument)
|
@@ -28,6 +28,7 @@ module RuboCop
|
|
28
28
|
# execute(sql).keys.each { |v| p v }
|
29
29
|
# execute(sql).values.each { |v| p v }
|
30
30
|
class HashEachMethods < Base
|
31
|
+
include AllowedReceivers
|
31
32
|
include Lint::UnusedArgument
|
32
33
|
extend AutoCorrector
|
33
34
|
|
@@ -116,28 +117,6 @@ module RuboCop
|
|
116
117
|
def kv_range(outer_node)
|
117
118
|
outer_node.receiver.loc.selector.join(outer_node.loc.selector)
|
118
119
|
end
|
119
|
-
|
120
|
-
def allowed_receiver?(receiver)
|
121
|
-
receiver_name = receiver_name(receiver)
|
122
|
-
|
123
|
-
allowed_receivers.include?(receiver_name)
|
124
|
-
end
|
125
|
-
|
126
|
-
def receiver_name(receiver)
|
127
|
-
if receiver.send_type?
|
128
|
-
if receiver.receiver
|
129
|
-
"#{receiver_name(receiver.receiver)}.#{receiver.method_name}"
|
130
|
-
else
|
131
|
-
receiver.method_name.to_s
|
132
|
-
end
|
133
|
-
else
|
134
|
-
receiver.source
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
def allowed_receivers
|
139
|
-
cop_config.fetch('AllowedReceivers', [])
|
140
|
-
end
|
141
120
|
end
|
142
121
|
end
|
143
122
|
end
|
@@ -45,13 +45,13 @@ module RuboCop
|
|
45
45
|
(block
|
46
46
|
(send _ _)
|
47
47
|
(args
|
48
|
-
(arg _)
|
48
|
+
$(arg _)
|
49
49
|
(arg _))
|
50
50
|
{
|
51
|
-
(send
|
51
|
+
$(send
|
52
52
|
_ {:== :!= :eql? :include?} _)
|
53
53
|
(send
|
54
|
-
(send
|
54
|
+
$(send
|
55
55
|
_ {:== :!= :eql? :include?} _) :!)
|
56
56
|
})
|
57
57
|
PATTERN
|
@@ -61,13 +61,13 @@ module RuboCop
|
|
61
61
|
(block
|
62
62
|
(send _ _)
|
63
63
|
(args
|
64
|
-
(arg _)
|
64
|
+
$(arg _)
|
65
65
|
(arg _))
|
66
66
|
{
|
67
|
-
(send
|
67
|
+
$(send
|
68
68
|
_ {:== :!= :eql? :in? :include? :exclude?} _)
|
69
69
|
(send
|
70
|
-
(send
|
70
|
+
$(send
|
71
71
|
_ {:== :!= :eql? :in? :include? :exclude?} _) :!)
|
72
72
|
})
|
73
73
|
PATTERN
|
@@ -89,13 +89,24 @@ module RuboCop
|
|
89
89
|
|
90
90
|
private
|
91
91
|
|
92
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
92
93
|
def bad_method?(block)
|
93
94
|
if active_support_extensions_enabled?
|
94
|
-
bad_method_with_active_support?(block)
|
95
|
+
bad_method_with_active_support?(block) do |key_arg, send_node|
|
96
|
+
if send_node.method?(:in?) && send_node.receiver&.source != key_arg.source
|
97
|
+
return false
|
98
|
+
end
|
99
|
+
return true if !send_node.method?(:include?) && !send_node.method?(:exclude?)
|
100
|
+
|
101
|
+
send_node.first_argument&.source == key_arg.source
|
102
|
+
end
|
95
103
|
else
|
96
|
-
bad_method_with_poro?(block)
|
104
|
+
bad_method_with_poro?(block) do |key_arg, send_node|
|
105
|
+
!send_node.method?(:include?) || send_node.first_argument&.source == key_arg.source
|
106
|
+
end
|
97
107
|
end
|
98
108
|
end
|
109
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
99
110
|
|
100
111
|
def semantically_except_method?(send, block)
|
101
112
|
body = block.body
|
@@ -3,8 +3,8 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
# Looks for uses of
|
7
|
-
#
|
6
|
+
# Looks for uses of `\_.each_with_object({}) {...}`,
|
7
|
+
# `\_.map {...}.to_h`, and `Hash[\_.map {...}]` that are actually just
|
8
8
|
# transforming the keys of a hash, and tries to use a simpler & faster
|
9
9
|
# call to `transform_keys` instead.
|
10
10
|
# It should only be enabled on Ruby version 2.5 or newer.
|
@@ -3,8 +3,8 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
# Looks for uses of
|
7
|
-
#
|
6
|
+
# Looks for uses of `\_.each_with_object({}) {...}`,
|
7
|
+
# `\_.map {...}.to_h`, and `Hash[\_.map {...}]` that are actually just
|
8
8
|
# transforming the values of a hash, and tries to use a simpler & faster
|
9
9
|
# call to `transform_values` instead.
|
10
10
|
#
|