rubocop 0.27.1 → 0.28.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 +44 -4
- data/Gemfile +1 -1
- data/README.md +16 -1
- data/config/default.yml +15 -1
- data/config/disabled.yml +5 -0
- data/config/enabled.yml +10 -2
- data/lib/rubocop.rb +3 -0
- data/lib/rubocop/config.rb +1 -1
- data/lib/rubocop/cop/mixin/access_modifier_node.rb +2 -2
- data/lib/rubocop/cop/mixin/autocorrect_unless_changing_ast.rb +10 -26
- data/lib/rubocop/cop/mixin/on_method_def.rb +1 -1
- data/lib/rubocop/cop/mixin/string_help.rb +10 -1
- data/lib/rubocop/cop/style/align_hash.rb +2 -2
- data/lib/rubocop/cop/style/ascii_identifiers.rb +1 -1
- data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +21 -19
- data/lib/rubocop/cop/style/else_alignment.rb +29 -16
- data/lib/rubocop/cop/style/empty_else.rb +47 -0
- data/lib/rubocop/cop/style/empty_lines_around_block_body.rb +38 -0
- data/lib/rubocop/cop/style/extra_spacing.rb +35 -0
- data/lib/rubocop/cop/style/indentation_width.rb +1 -1
- data/lib/rubocop/cop/style/leading_comment_space.rb +1 -1
- data/lib/rubocop/cop/style/line_end_concatenation.rb +5 -1
- data/lib/rubocop/cop/style/multiline_operation_indentation.rb +20 -4
- data/lib/rubocop/cop/style/negated_while.rb +3 -1
- data/lib/rubocop/cop/style/perl_backrefs.rb +8 -3
- data/lib/rubocop/cop/style/single_line_block_params.rb +7 -1
- data/lib/rubocop/cop/style/special_global_vars.rb +8 -3
- data/lib/rubocop/cop/style/string_literals.rb +4 -11
- data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +2 -7
- data/lib/rubocop/cop/style/symbol_proc.rb +14 -6
- data/lib/rubocop/cop/style/unneeded_capital_w.rb +2 -1
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/cop/variable_force.rb +3 -3
- data/lib/rubocop/cop/variable_force/scope.rb +1 -1
- data/lib/rubocop/cop/variable_force/variable.rb +1 -1
- data/lib/rubocop/formatter/html_formatter.rb +1 -1
- data/lib/rubocop/options.rb +13 -6
- data/lib/rubocop/rake_task.rb +0 -1
- data/lib/rubocop/runner.rb +19 -6
- data/lib/rubocop/target_finder.rb +32 -1
- data/lib/rubocop/version.rb +1 -1
- data/relnotes/v0.28.0.md +90 -0
- data/spec/project_spec.rb +1 -0
- data/spec/rubocop/cli_spec.rb +115 -24
- data/spec/rubocop/comment_config_spec.rb +1 -1
- data/spec/rubocop/cop/lint/assignment_in_condition_spec.rb +0 -1
- data/spec/rubocop/cop/lint/block_alignment_spec.rb +4 -4
- data/spec/rubocop/cop/lint/unused_method_argument_spec.rb +1 -1
- data/spec/rubocop/cop/lint/useless_assignment_spec.rb +2 -3
- data/spec/rubocop/cop/lint/useless_setter_call_spec.rb +1 -1
- data/spec/rubocop/cop/lint/void_spec.rb +0 -1
- data/spec/rubocop/cop/style/access_modifier_indentation_spec.rb +2 -2
- data/spec/rubocop/cop/style/blocks_spec.rb +8 -0
- data/spec/rubocop/cop/style/braces_around_hash_parameters_spec.rb +196 -215
- data/spec/rubocop/cop/style/case_indentation_spec.rb +4 -4
- data/spec/rubocop/cop/style/documentation_spec.rb +0 -1
- data/spec/rubocop/cop/style/else_alignment_spec.rb +63 -4
- data/spec/rubocop/cop/style/empty_else_spec.rb +100 -0
- data/spec/rubocop/cop/style/empty_lines_around_block_body_spec.rb +103 -0
- data/spec/rubocop/cop/style/empty_lines_around_method_body_spec.rb +1 -1
- data/spec/rubocop/cop/style/end_of_line_spec.rb +2 -2
- data/spec/rubocop/cop/style/extra_spacing_spec.rb +68 -0
- data/spec/rubocop/cop/style/leading_comment_space_spec.rb +5 -0
- data/spec/rubocop/cop/style/line_end_concatenation_spec.rb +8 -0
- data/spec/rubocop/cop/style/multiline_operation_indentation_spec.rb +35 -2
- data/spec/rubocop/cop/style/negated_if_spec.rb +1 -1
- data/spec/rubocop/cop/style/negated_while_spec.rb +5 -3
- data/spec/rubocop/cop/style/percent_q_literals_spec.rb +1 -1
- data/spec/rubocop/cop/style/perl_backrefs_spec.rb +5 -0
- data/spec/rubocop/cop/style/signal_exception_spec.rb +0 -1
- data/spec/rubocop/cop/style/single_line_block_params_spec.rb +13 -1
- data/spec/rubocop/cop/style/special_global_vars_spec.rb +5 -0
- data/spec/rubocop/cop/style/string_literals_spec.rb +11 -1
- data/spec/rubocop/cop/style/symbol_proc_spec.rb +20 -1
- data/spec/rubocop/cop/style/tab_spec.rb +2 -2
- data/spec/rubocop/cop/style/trailing_comma_spec.rb +1 -1
- data/spec/rubocop/cop/style/unneeded_capital_w_spec.rb +5 -0
- data/spec/rubocop/cop/team_spec.rb +2 -2
- data/spec/rubocop/formatter/offense_count_formatter_spec.rb +0 -1
- data/spec/rubocop/options_spec.rb +2 -0
- data/spec/rubocop/target_finder_spec.rb +23 -2
- metadata +12 -2
@@ -21,27 +21,28 @@ module RuboCop
|
|
21
21
|
else_range = node.loc.else
|
22
22
|
return unless begins_its_line?(else_range)
|
23
23
|
|
24
|
-
base_range
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
24
|
+
check_alignment(base_range(node, base), else_range)
|
25
|
+
|
26
|
+
return if else_range.source != 'elsif'
|
27
|
+
|
28
|
+
# If the `else` part is actually an `elsif`, we check the `elsif`
|
29
|
+
# node in case it contains an `else` within, because that `else`
|
30
|
+
# should have the same alignment (base).
|
31
|
+
_condition, _if_body, else_body = *node
|
32
|
+
on_if(else_body, base)
|
33
|
+
# The `elsif` node will get an `on_if` call from the framework later,
|
34
|
+
# but we're done here, so we set it to ignored.
|
35
|
+
ignore_node(else_body)
|
35
36
|
end
|
36
37
|
|
37
38
|
def on_rescue(node)
|
38
39
|
return unless node.loc.else
|
39
40
|
|
40
41
|
parent = node.parent
|
42
|
+
parent = parent.parent if parent.type == :ensure
|
41
43
|
base = case parent.type
|
42
44
|
when :def, :defs then base_for_method_definition(parent)
|
43
|
-
when :kwbegin
|
44
|
-
when :ensure then parent.parent.loc.begin
|
45
|
+
when :kwbegin then parent.loc.begin
|
45
46
|
else node.loc.keyword
|
46
47
|
end
|
47
48
|
check_alignment(base, node.loc.else)
|
@@ -55,6 +56,18 @@ module RuboCop
|
|
55
56
|
|
56
57
|
private
|
57
58
|
|
59
|
+
def base_range(node, base)
|
60
|
+
if base
|
61
|
+
base.loc.expression
|
62
|
+
else
|
63
|
+
base = node
|
64
|
+
until %w(if unless).include?(base.loc.keyword.source)
|
65
|
+
base = base.parent
|
66
|
+
end
|
67
|
+
base.loc.keyword
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
58
71
|
def base_for_method_definition(node)
|
59
72
|
parent = node.parent
|
60
73
|
if parent && parent.type == :send
|
@@ -81,14 +94,14 @@ module RuboCop
|
|
81
94
|
ignore_node(rhs)
|
82
95
|
end
|
83
96
|
|
84
|
-
def check_alignment(
|
97
|
+
def check_alignment(base_range, else_range)
|
85
98
|
return unless begins_its_line?(else_range)
|
86
99
|
|
87
|
-
@column_delta =
|
100
|
+
@column_delta = base_range.column - else_range.column
|
88
101
|
return if @column_delta == 0
|
89
102
|
|
90
103
|
add_offense(else_range, else_range,
|
91
|
-
format(MSG, else_range.source,
|
104
|
+
format(MSG, else_range.source, base_range.source[/^\S*/]))
|
92
105
|
end
|
93
106
|
end
|
94
107
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Checks for empty else-clauses, possibly including comments and/or an
|
7
|
+
# explicit `nil`.
|
8
|
+
class EmptyElse < Cop
|
9
|
+
include OnNormalIfUnless
|
10
|
+
|
11
|
+
MSG = 'Redundant empty `else`-clause.'
|
12
|
+
|
13
|
+
def on_normal_if_unless(node)
|
14
|
+
check(node, if_else_clause(node))
|
15
|
+
end
|
16
|
+
|
17
|
+
def on_case(node)
|
18
|
+
check(node, case_else_clause(node))
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def check(node, else_clause)
|
24
|
+
return unless node.loc.else
|
25
|
+
return if else_clause && else_clause.type != :nil
|
26
|
+
|
27
|
+
add_offense(node, :else, MSG)
|
28
|
+
end
|
29
|
+
|
30
|
+
def if_else_clause(node)
|
31
|
+
keyword = node.loc.keyword
|
32
|
+
if keyword.is?('if')
|
33
|
+
node.children[2]
|
34
|
+
elsif keyword.is?('elsif')
|
35
|
+
node.children[2]
|
36
|
+
elsif keyword.is?('unless')
|
37
|
+
node.children[1]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def case_else_clause(node)
|
42
|
+
node.children.last
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# This cops checks if empty lines around the bodies of blocks match
|
7
|
+
# the configuration.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
#
|
11
|
+
# something do
|
12
|
+
#
|
13
|
+
# ...
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
class EmptyLinesAroundBlockBody < Cop
|
17
|
+
include EmptyLinesAroundBody
|
18
|
+
|
19
|
+
KIND = 'block'
|
20
|
+
|
21
|
+
def on_block(node)
|
22
|
+
check(node)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def check(node)
|
28
|
+
start_line = node.loc.begin.line
|
29
|
+
end_line = node.loc.end.line
|
30
|
+
|
31
|
+
return if start_line == end_line
|
32
|
+
|
33
|
+
check_source(start_line, end_line)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# This cop checks for extra/unnecessary whitespace.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
#
|
10
|
+
# name = "RuboCop"
|
11
|
+
# website = "https://github.com/bbatsov/rubocop"
|
12
|
+
class ExtraSpacing < Cop
|
13
|
+
MSG = 'Unnecessary spacing detected.'
|
14
|
+
|
15
|
+
def investigate(processed_source)
|
16
|
+
processed_source.tokens.each_cons(2) do |t1, t2|
|
17
|
+
next unless t1.pos.line == t2.pos.line
|
18
|
+
next unless t2.pos.begin_pos - 1 > t1.pos.end_pos
|
19
|
+
buffer = processed_source.buffer
|
20
|
+
start_pos = t1.pos.end_pos
|
21
|
+
end_pos = t2.pos.begin_pos - 1
|
22
|
+
range = Parser::Source::Range.new(buffer, start_pos, end_pos)
|
23
|
+
add_offense(range, range, MSG)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def autocorrect(range)
|
28
|
+
@corrections << lambda do |corrector|
|
29
|
+
corrector.remove(range)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -94,7 +94,7 @@ module RuboCop
|
|
94
94
|
latest_when = nil
|
95
95
|
branches.compact.each do |b|
|
96
96
|
if b.type == :when
|
97
|
-
# TODO: Revert to the original
|
97
|
+
# TODO: Revert to the original expression once the fix in Rubinius
|
98
98
|
# is released.
|
99
99
|
#
|
100
100
|
# Originally this expression was:
|
@@ -12,7 +12,7 @@ module RuboCop
|
|
12
12
|
|
13
13
|
def investigate(processed_source)
|
14
14
|
processed_source.comments.each do |comment|
|
15
|
-
next unless comment.text =~ /^#+[^#\s
|
15
|
+
next unless comment.text =~ /^#+[^#\s=:+-]/
|
16
16
|
next if comment.text.start_with?('#!') && comment.loc.line == 1
|
17
17
|
|
18
18
|
add_offense(comment, :expression)
|
@@ -63,7 +63,11 @@ module RuboCop
|
|
63
63
|
return false unless node.loc.respond_to?(:begin)
|
64
64
|
|
65
65
|
# we care only about quotes-delimited literals
|
66
|
-
|
66
|
+
if node.loc.begin
|
67
|
+
["'", '"'].include?(node.loc.begin.source)
|
68
|
+
elsif node.children.any?
|
69
|
+
node.children.map { |child| string_type?(child) }.all?
|
70
|
+
end
|
67
71
|
end
|
68
72
|
|
69
73
|
def final_node_is_string_type?(node)
|
@@ -12,7 +12,7 @@ module RuboCop
|
|
12
12
|
# b
|
13
13
|
# something
|
14
14
|
# end
|
15
|
-
class MultilineOperationIndentation < Cop
|
15
|
+
class MultilineOperationIndentation < Cop # rubocop:disable ClassLength
|
16
16
|
include ConfigurableEnforcedStyle
|
17
17
|
include AutocorrectAlignment
|
18
18
|
|
@@ -51,7 +51,9 @@ module RuboCop
|
|
51
51
|
|
52
52
|
def incorrect_style_detected(range, node, lhs, rhs)
|
53
53
|
add_offense(range, range, message(node, lhs, rhs)) do
|
54
|
-
|
54
|
+
if offending_range(node, lhs, rhs, alternative_style)
|
55
|
+
unrecognized_style_detected
|
56
|
+
else
|
55
57
|
opposite_style_detected
|
56
58
|
end
|
57
59
|
end
|
@@ -105,7 +107,11 @@ module RuboCop
|
|
105
107
|
# d <-- d is indented relative to a
|
106
108
|
def left_hand_side(receiver)
|
107
109
|
lhs = receiver
|
108
|
-
|
110
|
+
while lhs.parent && lhs.parent.type == :send
|
111
|
+
_receiver, method_name, *_args = *lhs.parent
|
112
|
+
break if operator?(method_name)
|
113
|
+
lhs = lhs.parent
|
114
|
+
end
|
109
115
|
lhs
|
110
116
|
end
|
111
117
|
|
@@ -151,7 +157,17 @@ module RuboCop
|
|
151
157
|
end
|
152
158
|
|
153
159
|
def assignment?(node)
|
154
|
-
node.each_ancestor.find
|
160
|
+
node.each_ancestor.find do |a|
|
161
|
+
case a.type
|
162
|
+
when :send
|
163
|
+
_receiver, method_name, *_args = *a
|
164
|
+
# The []= operator is the only assignment operator that is parsed
|
165
|
+
# as a :send node.
|
166
|
+
method_name == :[]=
|
167
|
+
when *ASGN_NODES
|
168
|
+
true
|
169
|
+
end
|
170
|
+
end
|
155
171
|
end
|
156
172
|
|
157
173
|
def not_for_this_cop?(node)
|
@@ -30,7 +30,9 @@ module RuboCop
|
|
30
30
|
def autocorrect(node)
|
31
31
|
@corrections << lambda do |corrector|
|
32
32
|
condition, _body, _rest = *node
|
33
|
-
#
|
33
|
+
# Look inside parentheses around the condition, if any.
|
34
|
+
condition, _ = *condition while condition.type == :begin
|
35
|
+
# Unwrap the negated portion of the condition (a send node).
|
34
36
|
pos_condition, _method, = *condition
|
35
37
|
corrector.replace(
|
36
38
|
node.loc.keyword,
|
@@ -15,9 +15,14 @@ module RuboCop
|
|
15
15
|
def autocorrect(node)
|
16
16
|
@corrections << lambda do |corrector|
|
17
17
|
backref, = *node
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
parent_type = node.parent ? node.parent.type : nil
|
19
|
+
if [:dstr, :xstr, :regexp].include?(parent_type)
|
20
|
+
corrector.replace(node.loc.expression,
|
21
|
+
"{Regexp.last_match[#{backref}]}")
|
22
|
+
else
|
23
|
+
corrector.replace(node.loc.expression,
|
24
|
+
"Regexp.last_match[#{backref}]")
|
25
|
+
end
|
21
26
|
end
|
22
27
|
end
|
23
28
|
end
|
@@ -53,7 +53,13 @@ module RuboCop
|
|
53
53
|
def args_match?(method_name, args)
|
54
54
|
actual_args = args.flat_map(&:to_a)
|
55
55
|
|
56
|
-
|
56
|
+
# Prepending an underscore to mark an unused parameter is allowed, so
|
57
|
+
# we remove any leading underscores before comparing.
|
58
|
+
actual_args_no_underscores = actual_args.map do |arg|
|
59
|
+
arg.to_s.sub(/^_+/, '')
|
60
|
+
end
|
61
|
+
|
62
|
+
actual_args_no_underscores == target_args(method_name)
|
57
63
|
end
|
58
64
|
end
|
59
65
|
end
|
@@ -73,9 +73,14 @@ module RuboCop
|
|
73
73
|
def autocorrect(node)
|
74
74
|
@corrections << lambda do |corrector|
|
75
75
|
global_var, = *node
|
76
|
-
|
77
|
-
|
78
|
-
|
76
|
+
parent_type = node.parent ? node.parent.type : nil
|
77
|
+
if [:dstr, :xstr, :regexp].include?(parent_type)
|
78
|
+
corrector.replace(node.loc.expression,
|
79
|
+
"{#{PREFERRED_VARS[global_var].first}}")
|
80
|
+
else
|
81
|
+
corrector.replace(node.loc.expression,
|
82
|
+
PREFERRED_VARS[global_var].first)
|
83
|
+
end
|
79
84
|
end
|
80
85
|
end
|
81
86
|
end
|
@@ -8,17 +8,6 @@ module RuboCop
|
|
8
8
|
include ConfigurableEnforcedStyle
|
9
9
|
include StringLiteralsHelp
|
10
10
|
|
11
|
-
def on_dstr(node)
|
12
|
-
# A dstr node with dstr and str children is a concatenated
|
13
|
-
# string. Don't ignore the whole thing.
|
14
|
-
return if node.children.find { |child| child.type == :str }
|
15
|
-
|
16
|
-
# Dynamic strings can not use single quotes, and quotes inside
|
17
|
-
# interpolation expressions are checked by the
|
18
|
-
# StringLiteralsInInterpolation cop, so ignore.
|
19
|
-
ignore_node(node)
|
20
|
-
end
|
21
|
-
|
22
11
|
private
|
23
12
|
|
24
13
|
def message(*)
|
@@ -32,6 +21,10 @@ module RuboCop
|
|
32
21
|
end
|
33
22
|
|
34
23
|
def offense?(node)
|
24
|
+
# If it's a string within an interpolation, then it's not an offense
|
25
|
+
# for this cop.
|
26
|
+
return false if inside_interpolation?(node)
|
27
|
+
|
35
28
|
wrong_quotes?(node, style)
|
36
29
|
end
|
37
30
|
end
|
@@ -19,13 +19,8 @@ module RuboCop
|
|
19
19
|
|
20
20
|
def offense?(node)
|
21
21
|
# If it's not a string within an interpolation, then it's not an
|
22
|
-
# offense for this cop.
|
23
|
-
|
24
|
-
begin_found = false
|
25
|
-
return false unless node.each_ancestor.find do |a|
|
26
|
-
begin_found = true if a.type == :begin
|
27
|
-
begin_found && a.type == :dstr
|
28
|
-
end
|
22
|
+
# offense for this cop.
|
23
|
+
return false unless inside_interpolation?(node)
|
29
24
|
|
30
25
|
wrong_quotes?(node, style)
|
31
26
|
end
|
@@ -14,13 +14,18 @@ module RuboCop
|
|
14
14
|
class SymbolProc < Cop
|
15
15
|
MSG = 'Pass `&:%s` as an argument to `%s` instead of a block.'
|
16
16
|
|
17
|
+
PROC_NODE = s(:send, s(:const, nil, :Proc), :new)
|
18
|
+
|
17
19
|
def on_block(node)
|
18
20
|
block_send, block_args, block_body = *node
|
19
21
|
|
20
22
|
_breceiver, bmethod_name, bargs = *block_send
|
21
23
|
|
22
|
-
# we should
|
23
|
-
|
24
|
+
# TODO: Rails-specific handling that we should probably make
|
25
|
+
# configurable - https://github.com/bbatsov/rubocop/issues/1485
|
26
|
+
# we should ignore lambdas & procs
|
27
|
+
return if block_send == PROC_NODE
|
28
|
+
return if [:lambda, :proc].include?(bmethod_name)
|
24
29
|
return if ignored_method?(bmethod_name)
|
25
30
|
# File.open(file) { |f| f.readlines }
|
26
31
|
return if bargs
|
@@ -36,13 +41,16 @@ module RuboCop
|
|
36
41
|
|
37
42
|
def autocorrect(node)
|
38
43
|
@corrections << lambda do |corrector|
|
39
|
-
|
44
|
+
_block_method, _block_args, block_body = *node
|
40
45
|
_receiver, method_name, _args = *block_body
|
41
46
|
|
42
|
-
|
43
|
-
|
47
|
+
block_range =
|
48
|
+
Parser::Source::Range.new(node.loc.expression.source_buffer,
|
49
|
+
node.loc.begin.begin_pos,
|
50
|
+
node.loc.end.end_pos)
|
44
51
|
|
45
|
-
corrector.replace(
|
52
|
+
corrector.replace(range_with_surrounding_space(block_range, :left),
|
53
|
+
"(&:#{method_name})")
|
46
54
|
end
|
47
55
|
end
|
48
56
|
|