rubocop 0.30.1 → 0.31.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/CHANGELOG.md +38 -0
- data/README.md +10 -0
- data/config/default.yml +8 -1
- data/config/enabled.yml +28 -0
- data/lib/rubocop.rb +7 -0
- data/lib/rubocop/cli.rb +3 -2
- data/lib/rubocop/config.rb +12 -18
- data/lib/rubocop/cop/autocorrect_logic.rb +1 -1
- data/lib/rubocop/cop/cop.rb +35 -23
- data/lib/rubocop/cop/lint/block_alignment.rb +1 -1
- data/lib/rubocop/cop/lint/def_end_alignment.rb +6 -0
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
- data/lib/rubocop/cop/lint/each_with_object_argument.rb +29 -0
- data/lib/rubocop/cop/lint/end_alignment.rb +5 -0
- data/lib/rubocop/cop/lint/require_parentheses.rb +1 -1
- data/lib/rubocop/cop/lint/space_before_first_arg.rb +1 -1
- data/lib/rubocop/cop/lint/string_conversion_in_interpolation.rb +1 -1
- data/lib/rubocop/cop/metrics/class_length.rb +1 -25
- data/lib/rubocop/cop/metrics/module_length.rb +24 -0
- data/lib/rubocop/cop/metrics/parameter_lists.rb +1 -1
- data/lib/rubocop/cop/mixin/autocorrect_alignment.rb +2 -2
- data/lib/rubocop/cop/mixin/autocorrect_unless_changing_ast.rb +2 -2
- data/lib/rubocop/cop/mixin/classish_length.rb +37 -0
- data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +1 -1
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +14 -1
- data/lib/rubocop/cop/mixin/min_body_length.rb +19 -0
- data/lib/rubocop/cop/mixin/on_method_def.rb +1 -0
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +2 -4
- data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -3
- data/lib/rubocop/cop/mixin/space_inside.rb +1 -1
- data/lib/rubocop/cop/mixin/statement_modifier.rb +14 -7
- data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -1
- data/lib/rubocop/cop/mixin/unused_argument.rb +1 -3
- data/lib/rubocop/cop/performance/count.rb +84 -0
- data/lib/rubocop/cop/performance/detect.rb +1 -1
- data/lib/rubocop/cop/performance/flat_map.rb +2 -1
- data/lib/rubocop/cop/performance/parallel_assignment.rb +79 -0
- data/lib/rubocop/cop/performance/reverse_each.rb +1 -3
- data/lib/rubocop/cop/performance/sample.rb +25 -18
- data/lib/rubocop/cop/performance/size.rb +1 -3
- data/lib/rubocop/cop/rails/action_filter.rb +1 -1
- data/lib/rubocop/cop/rails/delegate.rb +2 -5
- data/lib/rubocop/cop/rails/find_by.rb +1 -1
- data/lib/rubocop/cop/rails/find_each.rb +1 -3
- data/lib/rubocop/cop/rails/read_write_attribute.rb +1 -3
- data/lib/rubocop/cop/rails/time_zone.rb +29 -7
- data/lib/rubocop/cop/style/alias.rb +1 -1
- data/lib/rubocop/cop/style/align_hash.rb +11 -14
- data/lib/rubocop/cop/style/array_join.rb +11 -0
- data/lib/rubocop/cop/style/attr.rb +1 -3
- data/lib/rubocop/cop/style/bare_percent_literals.rb +1 -1
- data/lib/rubocop/cop/style/block_comments.rb +1 -1
- data/lib/rubocop/cop/style/block_delimiters.rb +2 -9
- data/lib/rubocop/cop/style/block_end_newline.rb +1 -1
- data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +1 -1
- data/lib/rubocop/cop/style/character_literal.rb +1 -1
- data/lib/rubocop/cop/style/class_check.rb +1 -1
- data/lib/rubocop/cop/style/class_methods.rb +1 -3
- data/lib/rubocop/cop/style/collection_methods.rb +1 -1
- data/lib/rubocop/cop/style/colon_method_call.rb +1 -3
- data/lib/rubocop/cop/style/command_literal.rb +2 -2
- data/lib/rubocop/cop/style/comment_annotation.rb +9 -2
- data/lib/rubocop/cop/style/copyright.rb +1 -1
- data/lib/rubocop/cop/style/def_with_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/deprecated_hash_methods.rb +1 -1
- data/lib/rubocop/cop/style/dot_position.rb +1 -1
- data/lib/rubocop/cop/style/empty_line_between_defs.rb +1 -3
- data/lib/rubocop/cop/style/empty_lines.rb +1 -1
- data/lib/rubocop/cop/style/empty_lines_around_access_modifier.rb +1 -1
- data/lib/rubocop/cop/style/empty_literal.rb +2 -6
- data/lib/rubocop/cop/style/encoding.rb +1 -1
- data/lib/rubocop/cop/style/even_odd.rb +2 -4
- data/lib/rubocop/cop/style/extra_spacing.rb +1 -3
- data/lib/rubocop/cop/style/guard_clause.rb +1 -11
- data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
- data/lib/rubocop/cop/style/if_unless_modifier.rb +11 -6
- data/lib/rubocop/cop/style/indentation_width.rb +11 -2
- data/lib/rubocop/cop/style/infinite_loop.rb +8 -8
- data/lib/rubocop/cop/style/lambda_call.rb +1 -1
- data/lib/rubocop/cop/style/leading_comment_space.rb +1 -3
- data/lib/rubocop/cop/style/line_end_concatenation.rb +5 -7
- data/lib/rubocop/cop/style/method_call_parentheses.rb +1 -8
- data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/multiline_block_chain.rb +2 -1
- data/lib/rubocop/cop/style/multiline_block_layout.rb +11 -8
- data/lib/rubocop/cop/style/multiline_if_then.rb +1 -1
- data/lib/rubocop/cop/style/multiline_operation_indentation.rb +3 -2
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +2 -1
- data/lib/rubocop/cop/style/negated_if.rb +1 -1
- data/lib/rubocop/cop/style/negated_while.rb +2 -2
- data/lib/rubocop/cop/style/next.rb +1 -11
- data/lib/rubocop/cop/style/nil_comparison.rb +3 -5
- data/lib/rubocop/cop/style/non_nil_check.rb +2 -2
- data/lib/rubocop/cop/style/not.rb +3 -5
- data/lib/rubocop/cop/style/numeric_literals.rb +2 -5
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +1 -1
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
- data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
- data/lib/rubocop/cop/style/perl_backrefs.rb +1 -1
- data/lib/rubocop/cop/style/proc.rb +1 -3
- data/lib/rubocop/cop/style/redundant_begin.rb +1 -1
- data/lib/rubocop/cop/style/redundant_exception.rb +6 -8
- data/lib/rubocop/cop/style/redundant_return.rb +1 -1
- data/lib/rubocop/cop/style/redundant_self.rb +2 -2
- data/lib/rubocop/cop/style/regexp_literal.rb +2 -2
- data/lib/rubocop/cop/style/self_assignment.rb +1 -1
- data/lib/rubocop/cop/style/semicolon.rb +2 -2
- 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/single_space_before_first_arg.rb +1 -1
- data/lib/rubocop/cop/style/space_after_colon.rb +1 -3
- data/lib/rubocop/cop/style/space_after_control_keyword.rb +1 -3
- data/lib/rubocop/cop/style/space_after_method_name.rb +1 -3
- data/lib/rubocop/cop/style/space_after_not.rb +1 -1
- data/lib/rubocop/cop/style/space_around_block_parameters.rb +34 -16
- data/lib/rubocop/cop/style/space_around_equals_in_parameter_default.rb +1 -3
- data/lib/rubocop/cop/style/space_around_operators.rb +3 -2
- data/lib/rubocop/cop/style/space_before_block_braces.rb +1 -1
- data/lib/rubocop/cop/style/space_before_comment.rb +1 -3
- data/lib/rubocop/cop/style/space_before_modifier_keyword.rb +1 -3
- data/lib/rubocop/cop/style/space_inside_block_braces.rb +5 -3
- data/lib/rubocop/cop/style/space_inside_hash_literal_braces.rb +1 -1
- data/lib/rubocop/cop/style/space_inside_range_literal.rb +1 -1
- data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
- data/lib/rubocop/cop/style/symbol_literal.rb +1 -1
- data/lib/rubocop/cop/style/symbol_proc.rb +1 -1
- data/lib/rubocop/cop/style/tab.rb +1 -1
- data/lib/rubocop/cop/style/trailing_blank_lines.rb +2 -2
- data/lib/rubocop/cop/style/trailing_comma.rb +1 -1
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +72 -0
- data/lib/rubocop/cop/style/trailing_whitespace.rb +1 -1
- data/lib/rubocop/cop/style/trivial_accessors.rb +5 -10
- data/lib/rubocop/cop/style/unneeded_capital_w.rb +1 -1
- data/lib/rubocop/cop/style/unneeded_percent_q.rb +1 -1
- data/lib/rubocop/cop/style/variable_interpolation.rb +2 -4
- data/lib/rubocop/cop/style/when_then.rb +1 -3
- data/lib/rubocop/cop/style/while_until_do.rb +5 -7
- data/lib/rubocop/cop/style/while_until_modifier.rb +4 -6
- data/lib/rubocop/cop/style/word_array.rb +1 -1
- data/lib/rubocop/cop/util.rb +6 -3
- data/lib/rubocop/formatter/progress_formatter.rb +3 -2
- data/lib/rubocop/formatter/simple_text_formatter.rb +1 -1
- data/lib/rubocop/rake_task.rb +2 -2
- data/lib/rubocop/runner.rb +2 -11
- data/lib/rubocop/string_util.rb +4 -2
- data/lib/rubocop/token.rb +3 -1
- data/lib/rubocop/version.rb +1 -1
- data/relnotes/v0.31.0.md +120 -0
- metadata +10 -2
@@ -0,0 +1,29 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
# This cop checks if each_with_object is called with an immutable
|
7
|
+
# argument. Since the argument is the object that the given block shall
|
8
|
+
# make calls on to build something based on the enumerable that
|
9
|
+
# each_with_object iterates over, an immutable argument makes no sense.
|
10
|
+
# It's definitely a bug.
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
#
|
14
|
+
# sum = numbers.each_with_object(0) { |e, a| a += e }
|
15
|
+
class EachWithObjectArgument < Cop
|
16
|
+
MSG = 'The argument to each_with_object can not be immutable.'
|
17
|
+
|
18
|
+
def on_send(node)
|
19
|
+
_receiver, method_name, *args = *node
|
20
|
+
return unless method_name == :each_with_object
|
21
|
+
return unless args.length == 1
|
22
|
+
|
23
|
+
arg = args.first
|
24
|
+
add_offense(node, :expression) if arg.int_type? || arg.float_type?
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -71,6 +71,11 @@ module RuboCop
|
|
71
71
|
def line_break_before_keyword?(whole_expression, rhs)
|
72
72
|
rhs.loc.keyword.line > whole_expression.line
|
73
73
|
end
|
74
|
+
|
75
|
+
def autocorrect(node)
|
76
|
+
align(node,
|
77
|
+
style == :variable ? node.each_ancestor(:lvasgn).first : node)
|
78
|
+
end
|
74
79
|
end
|
75
80
|
end
|
76
81
|
end
|
@@ -7,7 +7,7 @@ module RuboCop
|
|
7
7
|
# Comment lines can optionally be ignored.
|
8
8
|
# The maximum allowed length is configurable.
|
9
9
|
class ClassLength < Cop
|
10
|
-
include
|
10
|
+
include ClassishLength
|
11
11
|
|
12
12
|
def on_class(node)
|
13
13
|
check_code_length(node)
|
@@ -18,30 +18,6 @@ module RuboCop
|
|
18
18
|
def message(length, max_length)
|
19
19
|
format('Class definition is too long. [%d/%d]', length, max_length)
|
20
20
|
end
|
21
|
-
|
22
|
-
def code_length(node)
|
23
|
-
class_body_line_numbers = line_range(node).to_a[1...-1]
|
24
|
-
|
25
|
-
target_line_numbers = class_body_line_numbers -
|
26
|
-
line_numbers_of_inner_classes(node)
|
27
|
-
|
28
|
-
target_line_numbers.reduce(0) do |length, line_number|
|
29
|
-
source_line = processed_source[line_number]
|
30
|
-
next length if irrelevant_line(source_line)
|
31
|
-
length + 1
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def line_numbers_of_inner_classes(node)
|
36
|
-
line_numbers = Set.new
|
37
|
-
|
38
|
-
node.each_descendant(:class, :module) do |inner_node|
|
39
|
-
line_range = line_range(inner_node)
|
40
|
-
line_numbers.merge(line_range)
|
41
|
-
end
|
42
|
-
|
43
|
-
line_numbers.to_a
|
44
|
-
end
|
45
21
|
end
|
46
22
|
end
|
47
23
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Metrics
|
6
|
+
# This cop checks if the length a module exceeds some maximum value.
|
7
|
+
# Comment lines can optionally be ignored.
|
8
|
+
# The maximum allowed length is configurable.
|
9
|
+
class ModuleLength < Cop
|
10
|
+
include ClassishLength
|
11
|
+
|
12
|
+
def on_module(node)
|
13
|
+
check_code_length(node)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def message(length, max_length)
|
19
|
+
format('Module definition is too long. [%d/%d]', length, max_length)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -35,9 +35,9 @@ module RuboCop
|
|
35
35
|
# value of @column_delta. A local variable fixes the problem.
|
36
36
|
column_delta = @column_delta
|
37
37
|
|
38
|
-
|
38
|
+
return if block_comment_within?(expr)
|
39
39
|
|
40
|
-
|
40
|
+
lambda do |corrector|
|
41
41
|
each_line(expr) do |line_begin_pos|
|
42
42
|
autocorrect_line(corrector, line_begin_pos, expr, column_delta,
|
43
43
|
heredoc_ranges)
|
@@ -15,10 +15,10 @@ module RuboCop
|
|
15
15
|
|
16
16
|
# Make the correction only if it doesn't change the AST for the buffer.
|
17
17
|
if processed_source.ast != ProcessedSource.new(new_buffer_src).ast
|
18
|
-
|
18
|
+
return
|
19
19
|
end
|
20
20
|
|
21
|
-
|
21
|
+
correction(node)
|
22
22
|
end
|
23
23
|
|
24
24
|
private
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
# Common functionality for checking length of classes and modules.
|
6
|
+
module ClassishLength
|
7
|
+
include CodeLength
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def code_length(node)
|
12
|
+
body_line_numbers = line_range(node).to_a[1...-1]
|
13
|
+
|
14
|
+
target_line_numbers = body_line_numbers -
|
15
|
+
line_numbers_of_inner_thing(node, :module) -
|
16
|
+
line_numbers_of_inner_thing(node, :class)
|
17
|
+
|
18
|
+
target_line_numbers.reduce(0) do |length, line_number|
|
19
|
+
source_line = processed_source[line_number]
|
20
|
+
next length if irrelevant_line(source_line)
|
21
|
+
length + 1
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def line_numbers_of_inner_thing(node, type)
|
26
|
+
line_numbers = Set.new
|
27
|
+
|
28
|
+
node.each_descendant(:module, type) do |inner_node|
|
29
|
+
line_range = line_range(inner_node)
|
30
|
+
line_numbers.merge(line_range)
|
31
|
+
end
|
32
|
+
|
33
|
+
line_numbers.to_a
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -12,7 +12,7 @@ module RuboCop
|
|
12
12
|
MSG_MISSING = 'Empty line missing at %s body %s.'
|
13
13
|
|
14
14
|
def autocorrect(range)
|
15
|
-
|
15
|
+
lambda do |corrector|
|
16
16
|
case style
|
17
17
|
when :no_empty_lines then corrector.remove(range)
|
18
18
|
when :empty_lines then corrector.insert_before(range, "\n")
|
@@ -24,7 +24,7 @@ module RuboCop
|
|
24
24
|
|
25
25
|
if kw_loc.line != end_loc.line &&
|
26
26
|
kw_loc.column != end_loc.column + offset
|
27
|
-
add_offense(
|
27
|
+
add_offense(node, end_loc,
|
28
28
|
format(MSG, end_loc.line, end_loc.column,
|
29
29
|
alignment_base, kw_loc.line, kw_loc.column)) do
|
30
30
|
opposite_style_detected
|
@@ -37,6 +37,19 @@ module RuboCop
|
|
37
37
|
def parameter_name
|
38
38
|
'AlignWith'
|
39
39
|
end
|
40
|
+
|
41
|
+
def align(node, alignment_node)
|
42
|
+
source_buffer = node.loc.expression.source_buffer
|
43
|
+
begin_pos = node.loc.end.begin_pos
|
44
|
+
whitespace = Parser::Source::Range.new(source_buffer,
|
45
|
+
begin_pos - node.loc.end.column,
|
46
|
+
begin_pos)
|
47
|
+
return false unless whitespace.source.strip.empty?
|
48
|
+
|
49
|
+
column = alignment_node ? alignment_node.loc.expression.column : 0
|
50
|
+
|
51
|
+
->(corrector) { corrector.replace(whitespace, ' ' * column) }
|
52
|
+
end
|
40
53
|
end
|
41
54
|
end
|
42
55
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
# Common functionality for checking minimum body length.
|
6
|
+
module MinBodyLength
|
7
|
+
def min_body_length?(node)
|
8
|
+
(node.loc.end.line - node.loc.keyword.line) > min_body_length
|
9
|
+
end
|
10
|
+
|
11
|
+
def min_body_length
|
12
|
+
length = cop_config['MinBodyLength'] || 1
|
13
|
+
return length if length.is_a?(Integer) && length > 0
|
14
|
+
|
15
|
+
fail 'MinBodyLength needs to be a positive integer!'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -22,6 +22,7 @@ module RuboCop
|
|
22
22
|
def visibility_and_def_on_same_line?(receiver, method_name, args)
|
23
23
|
!receiver &&
|
24
24
|
[:public, :protected, :private,
|
25
|
+
:private_class_method, :public_class_method,
|
25
26
|
:module_function].include?(method_name) &&
|
26
27
|
args.size == 1 && [:def, :defs].include?(args.first.type)
|
27
28
|
end
|
@@ -11,7 +11,7 @@ module RuboCop
|
|
11
11
|
processed_source.tokens.each_cons(2) do |t1, t2|
|
12
12
|
next unless kind(t1) && t1.pos.line == t2.pos.line &&
|
13
13
|
t2.pos.column == t1.pos.column + offset &&
|
14
|
-
![:tRPAREN, :tRBRACK].include?(t2.type)
|
14
|
+
![:tRPAREN, :tRBRACK, :tPIPE].include?(t2.type)
|
15
15
|
|
16
16
|
add_offense(t1, t1.pos, format(MSG, kind(t1)))
|
17
17
|
end
|
@@ -24,9 +24,7 @@ module RuboCop
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def autocorrect(token)
|
27
|
-
|
28
|
-
corrector.replace(token.pos, token.pos.source + ' ')
|
29
|
-
end
|
27
|
+
->(corrector) { corrector.replace(token.pos, token.pos.source + ' ') }
|
30
28
|
end
|
31
29
|
end
|
32
30
|
end
|
@@ -6,7 +6,6 @@ module RuboCop
|
|
6
6
|
module StatementModifier
|
7
7
|
include IfNode
|
8
8
|
|
9
|
-
# TODO: Extremely ugly solution that needs lots of polish.
|
10
9
|
def fit_within_line_as_modifier_form?(node)
|
11
10
|
case node.loc.keyword.source
|
12
11
|
when 'if' then cond, body, _else = *node
|
@@ -19,8 +18,9 @@ module RuboCop
|
|
19
18
|
body_length = body_length(body)
|
20
19
|
|
21
20
|
return false if body_length == 0
|
22
|
-
|
23
21
|
return false if cond.each_node.any?(&:lvasgn_type?)
|
22
|
+
return false if body_has_comment?(body)
|
23
|
+
return false if end_keyword_has_comment?(node)
|
24
24
|
|
25
25
|
indentation = node.loc.keyword.column
|
26
26
|
kw_length = node.loc.keyword.size
|
@@ -28,7 +28,8 @@ module RuboCop
|
|
28
28
|
space = 1
|
29
29
|
total = indentation + body_length + space + kw_length + space +
|
30
30
|
cond_length
|
31
|
-
|
31
|
+
|
32
|
+
total <= max_line_length
|
32
33
|
end
|
33
34
|
|
34
35
|
def max_line_length
|
@@ -37,7 +38,7 @@ module RuboCop
|
|
37
38
|
end
|
38
39
|
|
39
40
|
def length(node)
|
40
|
-
node.loc.expression.source.lines.
|
41
|
+
node.loc.expression.source.lines.grep(/\S/).size
|
41
42
|
end
|
42
43
|
|
43
44
|
def body_length(body)
|
@@ -49,9 +50,15 @@ module RuboCop
|
|
49
50
|
end
|
50
51
|
|
51
52
|
def body_has_comment?(body)
|
52
|
-
comment_lines
|
53
|
-
|
54
|
-
|
53
|
+
comment_lines.include?(body.loc.expression.line)
|
54
|
+
end
|
55
|
+
|
56
|
+
def end_keyword_has_comment?(node)
|
57
|
+
comment_lines.include?(node.loc.end.line)
|
58
|
+
end
|
59
|
+
|
60
|
+
def comment_lines
|
61
|
+
@comment_lines ||= processed_source.comments.map(&:location).map(&:line)
|
55
62
|
end
|
56
63
|
end
|
57
64
|
end
|
@@ -17,7 +17,7 @@ module RuboCop
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def autocorrect(node)
|
20
|
-
|
20
|
+
lambda do |corrector|
|
21
21
|
replacement = node.loc.begin.is?('"') ? "'" : '"'
|
22
22
|
corrector.replace(node.loc.begin, replacement)
|
23
23
|
corrector.replace(node.loc.end, replacement)
|
@@ -26,9 +26,7 @@ module RuboCop
|
|
26
26
|
def autocorrect(node)
|
27
27
|
return if [:kwarg, :kwoptarg].include?(node.type)
|
28
28
|
|
29
|
-
|
30
|
-
corrector.insert_before(node.loc.name, '_')
|
31
|
-
end
|
29
|
+
->(corrector) { corrector.insert_before(node.loc.name, '_') }
|
32
30
|
end
|
33
31
|
end
|
34
32
|
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Performance
|
6
|
+
# This cop is used to identify usages of `count` on an
|
7
|
+
# `Enumerable` and change them to `size`.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# [1, 2, 3].select { |e| e > 2 }.size
|
12
|
+
# [1, 2, 3].reject { |e| e > 2 }.size
|
13
|
+
# [1, 2, 3].select { |e| e > 2 }.length
|
14
|
+
# [1, 2, 3].reject { |e| e > 2 }.length
|
15
|
+
# [1, 2, 3].select { |e| e > 2 }.count { |e| e.odd? }
|
16
|
+
# [1, 2, 3].reject { |e| e > 2 }.count { |e| e.even? }
|
17
|
+
#
|
18
|
+
# # good
|
19
|
+
# [1, 2, 3].count { |e| e > 2 }
|
20
|
+
# [1, 2, 3].count { |e| e < 2 }
|
21
|
+
# [1, 2, 3].count { |e| e > 2 && e.odd? }
|
22
|
+
# [1, 2, 3].count { |e| e < 2 && e.even? }
|
23
|
+
class Count < Cop
|
24
|
+
MSG = 'Use `count` instead of `%s...%s`.'
|
25
|
+
|
26
|
+
SELECTORS = [:reject, :select]
|
27
|
+
COUNTERS = [:count, :length, :size]
|
28
|
+
|
29
|
+
def on_send(node)
|
30
|
+
expression, first_method, second_method, third_method = parse(node)
|
31
|
+
|
32
|
+
return unless COUNTERS.include?(third_method)
|
33
|
+
|
34
|
+
begin_pos = if SELECTORS.include?(first_method)
|
35
|
+
return if second_method.is_a?(Symbol)
|
36
|
+
expression.loc.selector.begin_pos
|
37
|
+
else
|
38
|
+
return unless SELECTORS.include?(second_method)
|
39
|
+
expression.parent.loc.selector.begin_pos
|
40
|
+
end
|
41
|
+
|
42
|
+
return if node.parent && node.parent.block_type?
|
43
|
+
|
44
|
+
range = Parser::Source::Range.new(node.loc.expression.source_buffer,
|
45
|
+
begin_pos,
|
46
|
+
node.loc.expression.end_pos)
|
47
|
+
|
48
|
+
add_offense(node, range,
|
49
|
+
format(MSG, first_method || second_method, third_method))
|
50
|
+
end
|
51
|
+
|
52
|
+
def autocorrect(node)
|
53
|
+
expression, first_method, second_method, = parse(node)
|
54
|
+
|
55
|
+
return if first_method == :reject || second_method == :reject
|
56
|
+
|
57
|
+
selector = if SELECTORS.include?(first_method)
|
58
|
+
expression.loc.selector
|
59
|
+
else
|
60
|
+
expression.parent.loc.selector
|
61
|
+
end
|
62
|
+
|
63
|
+
lambda do |corrector|
|
64
|
+
range = Parser::Source::Range.new(node.loc.expression.source_buffer,
|
65
|
+
node.loc.dot.begin_pos,
|
66
|
+
node.loc.expression.end_pos)
|
67
|
+
corrector.remove(range)
|
68
|
+
corrector.replace(selector, 'count')
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def parse(node)
|
75
|
+
left, third_method = *node
|
76
|
+
expression, second_method = *left
|
77
|
+
_enumerable, first_method = *expression
|
78
|
+
|
79
|
+
[expression, first_method, second_method, third_method]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|