rubocop 0.45.0 → 0.46.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rubocop might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/config/default.yml +17 -0
- data/config/enabled.yml +29 -2
- data/lib/rubocop.rb +6 -1
- data/lib/rubocop/config.rb +0 -10
- data/lib/rubocop/config_loader.rb +21 -9
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +69 -0
- data/lib/rubocop/cop/bundler/ordered_gems.rb +54 -0
- data/lib/rubocop/cop/cop.rb +1 -0
- data/lib/rubocop/cop/lint/debugger.rb +9 -1
- data/lib/rubocop/cop/lint/each_with_object_argument.rb +5 -6
- data/lib/rubocop/cop/lint/eval.rb +3 -7
- data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +6 -4
- data/lib/rubocop/cop/lint/unneeded_splat_expansion.rb +13 -4
- data/lib/rubocop/cop/lint/useless_comparison.rb +5 -9
- data/lib/rubocop/cop/lint/useless_setter_call.rb +1 -0
- data/lib/rubocop/cop/metrics/line_length.rb +16 -3
- data/lib/rubocop/cop/mixin/access_modifier_node.rb +9 -9
- data/lib/rubocop/cop/mixin/configurable_numbering.rb +14 -7
- data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +92 -20
- data/lib/rubocop/cop/performance/compare_with_block.rb +61 -0
- data/lib/rubocop/cop/performance/count.rb +21 -57
- data/lib/rubocop/cop/performance/detect.rb +15 -15
- data/lib/rubocop/cop/performance/flat_map.rb +23 -35
- data/lib/rubocop/cop/performance/sample.rb +84 -82
- data/lib/rubocop/cop/performance/string_replacement.rb +18 -43
- data/lib/rubocop/cop/rails/enum_uniqueness.rb +71 -0
- data/lib/rubocop/cop/rails/http_positional_arguments.rb +1 -1
- data/lib/rubocop/cop/rails/output.rb +8 -12
- data/lib/rubocop/cop/rails/read_write_attribute.rb +10 -6
- data/lib/rubocop/cop/rails/request_referer.rb +8 -9
- data/lib/rubocop/cop/rails/scope_args.rb +5 -11
- data/lib/rubocop/cop/style/access_modifier_indentation.rb +1 -1
- data/lib/rubocop/cop/style/and_or.rb +1 -1
- data/lib/rubocop/cop/style/array_join.rb +4 -8
- data/lib/rubocop/cop/style/block_comments.rb +1 -1
- data/lib/rubocop/cop/style/case_equality.rb +3 -3
- data/lib/rubocop/cop/style/character_literal.rb +2 -4
- data/lib/rubocop/cop/style/class_check.rb +6 -6
- data/lib/rubocop/cop/style/colon_method_call.rb +6 -6
- data/lib/rubocop/cop/style/each_with_object.rb +13 -17
- data/lib/rubocop/cop/style/empty_literal.rb +46 -36
- data/lib/rubocop/cop/style/empty_method.rb +96 -0
- data/lib/rubocop/cop/style/even_odd.rb +19 -50
- data/lib/rubocop/cop/style/hash_syntax.rb +4 -1
- data/lib/rubocop/cop/style/lambda.rb +8 -18
- data/lib/rubocop/cop/style/module_function.rb +14 -11
- data/lib/rubocop/cop/style/nil_comparison.rb +4 -7
- data/lib/rubocop/cop/style/non_nil_check.rb +18 -36
- data/lib/rubocop/cop/style/numeric_predicate.rb +9 -10
- data/lib/rubocop/cop/style/op_method.rb +7 -9
- data/lib/rubocop/cop/style/parallel_assignment.rb +1 -1
- data/lib/rubocop/cop/style/proc.rb +5 -9
- data/lib/rubocop/cop/style/redundant_freeze.rb +6 -7
- data/lib/rubocop/cop/style/send.rb +6 -3
- data/lib/rubocop/cop/style/space_inside_block_braces.rb +1 -1
- data/lib/rubocop/cop/style/special_global_vars.rb +3 -3
- data/lib/rubocop/cop/style/symbol_proc.rb +22 -43
- data/lib/rubocop/cop/style/ternary_parentheses.rb +67 -18
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/cop/variable_force/assignment.rb +2 -0
- data/lib/rubocop/cop/variable_force/locatable.rb +8 -6
- data/lib/rubocop/cop/variable_force/reference.rb +2 -0
- data/lib/rubocop/formatter/base_formatter.rb +4 -8
- data/lib/rubocop/formatter/fuubar_style_formatter.rb +6 -0
- data/lib/rubocop/node_pattern.rb +7 -5
- data/lib/rubocop/processed_source.rb +1 -0
- data/lib/rubocop/rspec/cop_helper.rb +4 -0
- data/lib/rubocop/rspec/host_environment_simulation_helper.rb +1 -1
- data/lib/rubocop/version.rb +1 -1
- metadata +7 -3
- data/lib/rubocop/cop/performance/sort_with_block.rb +0 -53
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop looks for duplicate values in enum declarations.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# enum status: { active: 0, archived: 0 }
|
11
|
+
#
|
12
|
+
# # good
|
13
|
+
# enum status: { active: 0, archived: 1 }
|
14
|
+
#
|
15
|
+
# # bad
|
16
|
+
# enum status: [:active, :archived, :active]
|
17
|
+
#
|
18
|
+
# # good
|
19
|
+
# enum status: [:active, :archived]
|
20
|
+
class EnumUniqueness < Cop
|
21
|
+
MSG = 'Duplicate value `%s` found in `%s` enum declaration.'.freeze
|
22
|
+
|
23
|
+
def on_send(node)
|
24
|
+
_receiver, method_name, *args = *node
|
25
|
+
|
26
|
+
return unless method_name == :enum
|
27
|
+
|
28
|
+
enum_name, enum_args = parse_args(args)
|
29
|
+
|
30
|
+
dupes = arr_dupes(enum_values(enum_args))
|
31
|
+
return if dupes.empty?
|
32
|
+
|
33
|
+
add_offense(node, :selector, format(MSG, dupes.join(','), enum_name))
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def enum_values(enum_args)
|
39
|
+
if enum_args.type == :array
|
40
|
+
enum_array_keys(enum_args)
|
41
|
+
else
|
42
|
+
enum_hash_values(enum_args)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def enum_array_keys(array_node)
|
47
|
+
array_node.each_child_node.map(&:source)
|
48
|
+
end
|
49
|
+
|
50
|
+
def enum_hash_values(hash_node)
|
51
|
+
hash_node.each_child_node.map do |child_node|
|
52
|
+
child_node.child_nodes.last.source
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def arr_dupes(array)
|
57
|
+
array.select { |element| array.count(element) > 1 }.uniq
|
58
|
+
end
|
59
|
+
|
60
|
+
def parse_args(args)
|
61
|
+
enum_config = args.first.each_child_node.first.child_nodes
|
62
|
+
|
63
|
+
enum_name = enum_config.first.source
|
64
|
+
enum_opts = enum_config.last
|
65
|
+
|
66
|
+
[enum_name, enum_opts]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -18,7 +18,7 @@ module RuboCop
|
|
18
18
|
'positional arguments for http call: `%s`.'.freeze
|
19
19
|
KEYWORD_ARGS = [
|
20
20
|
:headers, :env, :params, :body, :flash, :as,
|
21
|
-
:xhr, :session, :method
|
21
|
+
:xhr, :session, :method, :format
|
22
22
|
].freeze
|
23
23
|
HTTP_METHODS = [:get, :post, :put, :patch, :delete, :head].freeze
|
24
24
|
|
@@ -6,22 +6,18 @@ module RuboCop
|
|
6
6
|
# This cop checks for the use of output calls like puts and print
|
7
7
|
class Output < Cop
|
8
8
|
MSG = 'Do not write to stdout. ' \
|
9
|
-
|
9
|
+
"Use Rails's logger if you want to log.".freeze
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
:pp,
|
15
|
-
:pretty_print,
|
16
|
-
:ap].freeze
|
11
|
+
def_node_matcher :output?, <<-PATTERN
|
12
|
+
(send nil {:ap :p :pp :pretty_print :print :puts} $...)
|
13
|
+
PATTERN
|
17
14
|
|
18
15
|
def on_send(node)
|
19
|
-
|
20
|
-
|
21
|
-
!args.empty? &&
|
22
|
-
BLACKLIST.include?(method_name)
|
16
|
+
output?(node) do |args|
|
17
|
+
return if args.empty?
|
23
18
|
|
24
|
-
|
19
|
+
add_offense(node, :selector)
|
20
|
+
end
|
25
21
|
end
|
26
22
|
end
|
27
23
|
end
|
@@ -18,13 +18,17 @@ module RuboCop
|
|
18
18
|
class ReadWriteAttribute < Cop
|
19
19
|
MSG = 'Prefer `%s` over `%s`.'.freeze
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
21
|
+
def_node_matcher :read_write_attribute?, <<-PATTERN
|
22
|
+
{
|
23
|
+
(send nil :read_attribute _)
|
24
|
+
(send nil :write_attribute _ _)
|
25
|
+
}
|
26
|
+
PATTERN
|
26
27
|
|
27
|
-
|
28
|
+
def on_send(node)
|
29
|
+
read_write_attribute?(node) do
|
30
|
+
add_offense(node, :selector)
|
31
|
+
end
|
28
32
|
end
|
29
33
|
|
30
34
|
def message(node)
|
@@ -8,10 +8,15 @@ module RuboCop
|
|
8
8
|
class RequestReferer < Cop
|
9
9
|
include ConfigurableEnforcedStyle
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
def_node_matcher :referer?, <<-PATTERN
|
12
|
+
(send (send nil :request) ${:referer :referrer})
|
13
|
+
PATTERN
|
13
14
|
|
14
|
-
|
15
|
+
def on_send(node)
|
16
|
+
referer?(node) do |method_name|
|
17
|
+
return unless method_name == wrong_method_name
|
18
|
+
add_offense(node.source_range, node.source_range, message)
|
19
|
+
end
|
15
20
|
end
|
16
21
|
|
17
22
|
def autocorrect(node)
|
@@ -20,12 +25,6 @@ module RuboCop
|
|
20
25
|
|
21
26
|
private
|
22
27
|
|
23
|
-
def offense?(node)
|
24
|
-
return false unless node.receiver
|
25
|
-
receiver_name = node.receiver.method_name
|
26
|
-
receiver_name == :request && node.method_name == wrong_method_name
|
27
|
-
end
|
28
|
-
|
29
28
|
def message
|
30
29
|
"Use `request.#{style}` instead of `request.#{wrong_method_name}`."
|
31
30
|
end
|
@@ -16,18 +16,12 @@ module RuboCop
|
|
16
16
|
class ScopeArgs < Cop
|
17
17
|
MSG = 'Use `lambda`/`proc` instead of a plain method call.'.freeze
|
18
18
|
|
19
|
-
|
20
|
-
return unless node.command?(:scope)
|
21
|
-
|
22
|
-
_receiver, _method_name, *args = *node
|
23
|
-
|
24
|
-
return unless args.size == 2
|
19
|
+
def_node_matcher :scope?, '(send nil :scope _ $send)'
|
25
20
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
add_offense(second_arg, :expression)
|
21
|
+
def on_send(node)
|
22
|
+
scope?(node) do |second_arg|
|
23
|
+
add_offense(second_arg, :expression)
|
24
|
+
end
|
31
25
|
end
|
32
26
|
end
|
33
27
|
end
|
@@ -37,7 +37,7 @@ module RuboCop
|
|
37
37
|
def check_body(body, node)
|
38
38
|
return if body.nil? # Empty class etc.
|
39
39
|
|
40
|
-
modifiers = body.
|
40
|
+
modifiers = body.each_child_node.select { |c| modifier_node?(c) }
|
41
41
|
class_column = node.source_range.column
|
42
42
|
|
43
43
|
modifiers.each { |modifier| check_modifier(modifier, class_column) }
|
@@ -131,7 +131,7 @@ module RuboCop
|
|
131
131
|
end_paren = begin_paren
|
132
132
|
# Increment position of parenthesis, unless message is a predicate
|
133
133
|
# method followed by a non-whitespace char (e.g. is_a?String).
|
134
|
-
end_paren += 1 unless node.source =~
|
134
|
+
end_paren += 1 unless node.source =~ /\?\S/
|
135
135
|
range_between(begin_paren, end_paren)
|
136
136
|
end
|
137
137
|
end
|
@@ -11,18 +11,14 @@ module RuboCop
|
|
11
11
|
class ArrayJoin < Cop
|
12
12
|
MSG = 'Favor `Array#join` over `Array#*`.'.freeze
|
13
13
|
|
14
|
-
|
15
|
-
receiver_node, method_name, *arg_nodes = *node
|
16
|
-
return unless receiver_node && receiver_node.array_type? &&
|
17
|
-
method_name == :* && arg_nodes.first.str_type?
|
14
|
+
def_node_matcher :join_candidate?, '(send $array :* $str)'
|
18
15
|
|
19
|
-
|
16
|
+
def on_send(node)
|
17
|
+
join_candidate?(node) { add_offense(node, :selector) }
|
20
18
|
end
|
21
19
|
|
22
20
|
def autocorrect(node)
|
23
|
-
|
24
|
-
array = receiver_node.source
|
25
|
-
join_arg = arg_nodes.first.source
|
21
|
+
array, join_arg = join_candidate?(node).map(&:source)
|
26
22
|
|
27
23
|
lambda do |corrector|
|
28
24
|
corrector.replace(node.source_range, "#{array}.join(#{join_arg})")
|
@@ -7,10 +7,10 @@ module RuboCop
|
|
7
7
|
class CaseEquality < Cop
|
8
8
|
MSG = 'Avoid the use of the case equality operator `===`.'.freeze
|
9
9
|
|
10
|
-
|
11
|
-
_receiver, method_name, *_args = *node
|
10
|
+
def_node_matcher :case_equality?, '(send _ :=== _)'
|
12
11
|
|
13
|
-
|
12
|
+
def on_send(node)
|
13
|
+
case_equality?(node) { add_offense(node, :selector) }
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
@@ -32,13 +32,11 @@ module RuboCop
|
|
32
32
|
|
33
33
|
# Dummy implementation of method in ConfigurableEnforcedStyle that is
|
34
34
|
# called from StringHelp.
|
35
|
-
def opposite_style_detected
|
36
|
-
end
|
35
|
+
def opposite_style_detected; end
|
37
36
|
|
38
37
|
# Dummy implementation of method in ConfigurableEnforcedStyle that is
|
39
38
|
# called from StringHelp.
|
40
|
-
def correct_style_detected
|
41
|
-
end
|
39
|
+
def correct_style_detected; end
|
42
40
|
end
|
43
41
|
end
|
44
42
|
end
|
@@ -9,13 +9,13 @@ module RuboCop
|
|
9
9
|
|
10
10
|
MSG = 'Prefer `Object#%s` over `Object#%s`.'.freeze
|
11
11
|
|
12
|
-
|
13
|
-
_receiver, method_name, *_args = *node
|
14
|
-
return unless [:is_a?,
|
15
|
-
:kind_of?].include?(method_name)
|
12
|
+
def_node_matcher :class_check?, '(send _ ${:is_a? :kind_of?} _)'
|
16
13
|
|
17
|
-
|
18
|
-
|
14
|
+
def on_send(node)
|
15
|
+
class_check?(node) do |method_name|
|
16
|
+
return if style == method_name
|
17
|
+
add_offense(node, :selector)
|
18
|
+
end
|
19
19
|
end
|
20
20
|
|
21
21
|
def message(node)
|
@@ -8,15 +8,15 @@ module RuboCop
|
|
8
8
|
class ColonMethodCall < Cop
|
9
9
|
MSG = 'Do not use `::` for method calls.'.freeze
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
11
|
+
def_node_matcher :java_type_node?, <<-PATTERN
|
12
|
+
(send
|
13
|
+
(const nil :Java)
|
14
|
+
{:boolean :byte :char :double :float :int :long :short})
|
15
|
+
PATTERN
|
16
16
|
|
17
17
|
def on_send(node)
|
18
18
|
# ignore Java interop code like Java::int
|
19
|
-
return if
|
19
|
+
return if java_type_node?(node)
|
20
20
|
|
21
21
|
receiver, method_name, *_args = *node
|
22
22
|
|
@@ -20,19 +20,22 @@ module RuboCop
|
|
20
20
|
MSG = 'Use `each_with_object` instead of `%s`.'.freeze
|
21
21
|
METHODS = [:inject, :reduce].freeze
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
def_node_matcher :each_with_object_candidate?, <<-PATTERN
|
24
|
+
(block $(send _ {:inject :reduce} _) $_ $_)
|
25
|
+
PATTERN
|
26
26
|
|
27
|
-
|
28
|
-
|
27
|
+
def on_block(node)
|
28
|
+
each_with_object_candidate?(node) do |method, args, body|
|
29
|
+
_, method_name, method_arg = *method
|
30
|
+
return if simple_method_arg?(method_arg)
|
29
31
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
32
|
+
return_value = return_value(body)
|
33
|
+
return unless return_value
|
34
|
+
return unless first_argument_returned?(args, return_value)
|
35
|
+
return if accumulator_param_assigned_to?(body, args)
|
34
36
|
|
35
|
-
|
37
|
+
add_offense(node, method.loc.selector, format(MSG, method_name))
|
38
|
+
end
|
36
39
|
end
|
37
40
|
|
38
41
|
def autocorrect(node)
|
@@ -47,13 +50,6 @@ module RuboCop
|
|
47
50
|
|
48
51
|
private
|
49
52
|
|
50
|
-
def reduce_method?(method)
|
51
|
-
return false unless method.send_type?
|
52
|
-
|
53
|
-
_, method_name, _method_arg = *method
|
54
|
-
METHODS.include? method_name
|
55
|
-
end
|
56
|
-
|
57
53
|
def simple_method_arg?(method_arg)
|
58
54
|
method_arg && method_arg.basic_literal?
|
59
55
|
end
|
@@ -12,34 +12,21 @@ module RuboCop
|
|
12
12
|
HASH_MSG = 'Use hash literal `{}` instead of `Hash.new`.'.freeze
|
13
13
|
STR_MSG = 'Use string literal `%s` instead of `String.new`.'.freeze
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
# (const nil :Array) :new)
|
19
|
-
ARRAY_NODE = s(:send, s(:const, nil, :Array), :new)
|
20
|
-
|
21
|
-
# Empty hash node
|
22
|
-
#
|
23
|
-
# (send
|
24
|
-
# (const nil :Hash) :new)
|
25
|
-
HASH_NODE = s(:send, s(:const, nil, :Hash), :new)
|
26
|
-
|
27
|
-
# Empty string node
|
28
|
-
#
|
29
|
-
# (send
|
30
|
-
# (const nil :String) :new)
|
31
|
-
STR_NODE = s(:send, s(:const, nil, :String), :new)
|
15
|
+
def_node_matcher :array_node, '(send (const nil :Array) :new)'
|
16
|
+
def_node_matcher :hash_node, '(send (const nil :Hash) :new)'
|
17
|
+
def_node_matcher :str_node, '(send (const nil :String) :new)'
|
32
18
|
|
33
19
|
def on_send(node)
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
when HASH_NODE
|
20
|
+
array_node(node) { add_offense(node, :expression, ARR_MSG) }
|
21
|
+
|
22
|
+
hash_node(node) do
|
38
23
|
# If Hash.new takes a block, it can't be changed to {}.
|
39
24
|
return if node.parent && node.parent.block_type?
|
40
25
|
|
41
26
|
add_offense(node, :expression, HASH_MSG)
|
42
|
-
|
27
|
+
end
|
28
|
+
|
29
|
+
str_node(node) do
|
43
30
|
return if frozen_string_literals_enabled?(processed_source)
|
44
31
|
|
45
32
|
add_offense(node, :expression,
|
@@ -48,20 +35,9 @@ module RuboCop
|
|
48
35
|
end
|
49
36
|
|
50
37
|
def autocorrect(node)
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
when HASH_NODE
|
55
|
-
# `some_method {}` is not same as `some_method Hash.new`
|
56
|
-
# because the braces are interpreted as a block, so we avoid
|
57
|
-
# the correction. Parentheses around the arguments would
|
58
|
-
# solve the problem, but we let the user add those manually.
|
59
|
-
return if first_arg_in_method_call_without_parentheses?(node)
|
60
|
-
'{}'
|
61
|
-
when STR_NODE
|
62
|
-
preferred_string_literal
|
63
|
-
end
|
64
|
-
->(corrector) { corrector.replace(node.source_range, name) }
|
38
|
+
lambda do |corrector|
|
39
|
+
corrector.replace(replacement_range(node), correction(node))
|
40
|
+
end
|
65
41
|
end
|
66
42
|
|
67
43
|
private
|
@@ -84,6 +60,40 @@ module RuboCop
|
|
84
60
|
_receiver, _method_name, *args = *node.parent
|
85
61
|
node.object_id == args.first.object_id && !parentheses?(node.parent)
|
86
62
|
end
|
63
|
+
|
64
|
+
def replacement_range(node)
|
65
|
+
if hash_node(node) &&
|
66
|
+
first_arg_in_method_call_without_parentheses?(node)
|
67
|
+
# `some_method {}` is not same as `some_method Hash.new`
|
68
|
+
# because the braces are interpreted as a block. We will have
|
69
|
+
# to rewrite the arguments to wrap them in parenthesis.
|
70
|
+
_receiver, _method_name, *args = *node.parent
|
71
|
+
|
72
|
+
Parser::Source::Range.new(node.parent.loc.expression,
|
73
|
+
args[0].loc.expression.begin_pos - 1,
|
74
|
+
args[-1].loc.expression.end_pos)
|
75
|
+
else
|
76
|
+
node.source_range
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def correction(node)
|
81
|
+
if array_node(node)
|
82
|
+
'[]'
|
83
|
+
elsif str_node(node)
|
84
|
+
preferred_string_literal
|
85
|
+
elsif hash_node(node)
|
86
|
+
if first_arg_in_method_call_without_parentheses?(node)
|
87
|
+
# `some_method {}` is not same as `some_method Hash.new`
|
88
|
+
# because the braces are interpreted as a block. We will have
|
89
|
+
# to rewrite the arguments to wrap them in parenthesis.
|
90
|
+
_receiver, _method_name, *args = *node.parent
|
91
|
+
"(#{args[1..-1].map(&:source).unshift('{}').join(', ')})"
|
92
|
+
else
|
93
|
+
'{}'
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
87
97
|
end
|
88
98
|
end
|
89
99
|
end
|