rubocop 1.5.2 → 1.6.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/config/default.yml +5 -2
- data/config/obsoletion.yml +196 -0
- data/lib/rubocop.rb +10 -0
- data/lib/rubocop/cli/command/suggest_extensions.rb +16 -44
- data/lib/rubocop/config_obsoletion.rb +63 -263
- data/lib/rubocop/config_obsoletion/changed_enforced_styles.rb +33 -0
- data/lib/rubocop/config_obsoletion/changed_parameter.rb +21 -0
- data/lib/rubocop/config_obsoletion/cop_rule.rb +34 -0
- data/lib/rubocop/config_obsoletion/extracted_cop.rb +44 -0
- data/lib/rubocop/config_obsoletion/parameter_rule.rb +44 -0
- data/lib/rubocop/config_obsoletion/removed_cop.rb +41 -0
- data/lib/rubocop/config_obsoletion/renamed_cop.rb +34 -0
- data/lib/rubocop/config_obsoletion/rule.rb +41 -0
- data/lib/rubocop/config_obsoletion/split_cop.rb +27 -0
- data/lib/rubocop/config_validator.rb +11 -4
- data/lib/rubocop/cop/base.rb +17 -15
- data/lib/rubocop/cop/cop.rb +2 -2
- data/lib/rubocop/cop/correctors/string_literal_corrector.rb +6 -8
- data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -1
- data/lib/rubocop/cop/layout/line_length.rb +6 -16
- data/lib/rubocop/cop/migration/department_name.rb +1 -1
- data/lib/rubocop/cop/mixin/string_help.rb +4 -1
- data/lib/rubocop/cop/naming/accessor_method_name.rb +15 -1
- data/lib/rubocop/cop/style/character_literal.rb +10 -11
- data/lib/rubocop/cop/style/float_division.rb +44 -1
- data/lib/rubocop/cop/style/if_unless_modifier.rb +4 -0
- data/lib/rubocop/cop/style/ip_addresses.rb +1 -1
- data/lib/rubocop/cop/style/perl_backrefs.rb +86 -9
- data/lib/rubocop/cop/style/redundant_argument.rb +14 -1
- data/lib/rubocop/cop/style/single_line_block_params.rb +30 -7
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +12 -6
- data/lib/rubocop/cop/style/special_global_vars.rb +1 -13
- data/lib/rubocop/cop/style/string_concatenation.rb +19 -0
- data/lib/rubocop/cop/style/string_literals.rb +14 -8
- data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +4 -3
- data/lib/rubocop/formatter/emacs_style_formatter.rb +2 -0
- data/lib/rubocop/formatter/simple_text_formatter.rb +2 -0
- data/lib/rubocop/formatter/tap_formatter.rb +2 -0
- data/lib/rubocop/lockfile.rb +40 -0
- data/lib/rubocop/version.rb +1 -1
- metadata +14 -3
@@ -58,12 +58,13 @@ module RuboCop
|
|
58
58
|
# bar: "0000000000",
|
59
59
|
# baz: "0000000000",
|
60
60
|
# }
|
61
|
-
class LineLength <
|
61
|
+
class LineLength < Base
|
62
62
|
include CheckLineBreakable
|
63
63
|
include ConfigurableMax
|
64
64
|
include IgnoredPattern
|
65
65
|
include RangeHelp
|
66
66
|
include LineLengthHelp
|
67
|
+
extend AutoCorrector
|
67
68
|
|
68
69
|
MSG = 'Line is too long. [%<length>d/%<max>d]'
|
69
70
|
|
@@ -78,28 +79,16 @@ module RuboCop
|
|
78
79
|
alias on_hash on_potential_breakable_node
|
79
80
|
alias on_send on_potential_breakable_node
|
80
81
|
|
81
|
-
def
|
82
|
+
def on_new_investigation
|
82
83
|
check_for_breakable_semicolons(processed_source)
|
83
84
|
end
|
84
85
|
|
85
|
-
def
|
86
|
+
def on_investigation_end
|
86
87
|
processed_source.lines.each_with_index do |line, line_index|
|
87
88
|
check_line(line, line_index)
|
88
89
|
end
|
89
90
|
end
|
90
91
|
|
91
|
-
def correctable?
|
92
|
-
super && !breakable_range.nil?
|
93
|
-
end
|
94
|
-
|
95
|
-
def autocorrect(range)
|
96
|
-
return if range.nil?
|
97
|
-
|
98
|
-
lambda do |corrector|
|
99
|
-
corrector.insert_before(range, "\n")
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
92
|
private
|
104
93
|
|
105
94
|
attr_accessor :breakable_range
|
@@ -203,8 +192,9 @@ module RuboCop
|
|
203
192
|
|
204
193
|
self.breakable_range = breakable_range_by_line_index[line_index]
|
205
194
|
|
206
|
-
add_offense(
|
195
|
+
add_offense(loc, message: message) do |corrector|
|
207
196
|
self.max = line_length(line)
|
197
|
+
corrector.insert_before(breakable_range, "\n") unless breakable_range.nil?
|
208
198
|
end
|
209
199
|
end
|
210
200
|
|
@@ -71,7 +71,7 @@ module RuboCop
|
|
71
71
|
end
|
72
72
|
|
73
73
|
def qualified_legacy_cop_name(cop_name)
|
74
|
-
legacy_cop_names = RuboCop::ConfigObsoletion
|
74
|
+
legacy_cop_names = RuboCop::ConfigObsoletion.legacy_cop_names
|
75
75
|
|
76
76
|
legacy_cop_names.detect do |legacy_cop_name|
|
77
77
|
legacy_cop_name.split('/')[1] == cop_name
|
@@ -14,7 +14,10 @@ module RuboCop
|
|
14
14
|
return if part_of_ignored_node?(node)
|
15
15
|
|
16
16
|
if offense?(node)
|
17
|
-
add_offense(node)
|
17
|
+
add_offense(node) do |corrector|
|
18
|
+
opposite_style_detected
|
19
|
+
autocorrect(corrector, node) if respond_to?(:autocorrect, true)
|
20
|
+
end
|
18
21
|
else
|
19
22
|
correct_style_detected
|
20
23
|
end
|
@@ -3,7 +3,13 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Naming
|
6
|
-
# This cop makes sure that accessor methods are named properly.
|
6
|
+
# This cop makes sure that accessor methods are named properly. Applies
|
7
|
+
# to both instance and class methods.
|
8
|
+
#
|
9
|
+
# NOTE: Offenses are only registered for methods with the expected
|
10
|
+
# arity. Getters (`get_attribute`) must have no arguments to be
|
11
|
+
# registered, and setters (`set_attribute(value)`) must have exactly
|
12
|
+
# one.
|
7
13
|
#
|
8
14
|
# @example
|
9
15
|
# # bad
|
@@ -21,6 +27,14 @@ module RuboCop
|
|
21
27
|
# # good
|
22
28
|
# def attribute
|
23
29
|
# end
|
30
|
+
#
|
31
|
+
# # accepted, incorrect arity for getter
|
32
|
+
# def get_value(attr)
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# # accepted, incorrect arity for setter
|
36
|
+
# def set_value
|
37
|
+
# end
|
24
38
|
class AccessorMethodName < Base
|
25
39
|
MSG_READER = 'Do not prefix reader method names with `get_`.'
|
26
40
|
MSG_WRITER = 'Do not prefix writer method names with `set_`.'
|
@@ -14,8 +14,9 @@ module RuboCop
|
|
14
14
|
#
|
15
15
|
# # good
|
16
16
|
# ?\C-\M-d
|
17
|
-
class CharacterLiteral <
|
17
|
+
class CharacterLiteral < Base
|
18
18
|
include StringHelp
|
19
|
+
extend AutoCorrector
|
19
20
|
|
20
21
|
MSG = 'Do not use the character literal - ' \
|
21
22
|
'use string literal instead.'
|
@@ -26,17 +27,15 @@ module RuboCop
|
|
26
27
|
node.source.size.between?(2, 3)
|
27
28
|
end
|
28
29
|
|
29
|
-
def autocorrect(node)
|
30
|
-
|
31
|
-
string = node.source[1..-1]
|
30
|
+
def autocorrect(corrector, node)
|
31
|
+
string = node.source[1..-1]
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
end
|
33
|
+
# special character like \n
|
34
|
+
# or ' which needs to use "" or be escaped.
|
35
|
+
if string.length == 2 || string == "'"
|
36
|
+
corrector.replace(node, %("#{string}"))
|
37
|
+
elsif string.length == 1 # normal character
|
38
|
+
corrector.replace(node, "'#{string}'")
|
40
39
|
end
|
41
40
|
end
|
42
41
|
|
@@ -41,6 +41,8 @@ module RuboCop
|
|
41
41
|
# a.fdiv(b)
|
42
42
|
class FloatDivision < Base
|
43
43
|
include ConfigurableEnforcedStyle
|
44
|
+
extend AutoCorrector
|
45
|
+
|
44
46
|
MESSAGES = {
|
45
47
|
left_coerce: 'Prefer using `.to_f` on the left side.',
|
46
48
|
right_coerce: 'Prefer using `.to_f` on the right side.',
|
@@ -64,7 +66,20 @@ module RuboCop
|
|
64
66
|
PATTERN
|
65
67
|
|
66
68
|
def on_send(node)
|
67
|
-
|
69
|
+
return unless offense_condition?(node)
|
70
|
+
|
71
|
+
add_offense(node) do |corrector|
|
72
|
+
case style
|
73
|
+
when :left_coerce, :single_coerce
|
74
|
+
add_to_f_method(corrector, node.receiver)
|
75
|
+
remove_to_f_method(corrector, node.first_argument)
|
76
|
+
when :right_coerce
|
77
|
+
remove_to_f_method(corrector, node.receiver)
|
78
|
+
add_to_f_method(corrector, node.first_argument)
|
79
|
+
when :fdiv
|
80
|
+
correct_from_slash_to_fdiv(corrector, node, node.receiver, node.first_argument)
|
81
|
+
end
|
82
|
+
end
|
68
83
|
end
|
69
84
|
|
70
85
|
private
|
@@ -87,6 +102,34 @@ module RuboCop
|
|
87
102
|
def message(_node)
|
88
103
|
MESSAGES[style]
|
89
104
|
end
|
105
|
+
|
106
|
+
def add_to_f_method(corrector, node)
|
107
|
+
corrector.insert_after(node, '.to_f') unless node.send_type? && node.method?(:to_f)
|
108
|
+
end
|
109
|
+
|
110
|
+
def remove_to_f_method(corrector, send_node)
|
111
|
+
corrector.remove(send_node.loc.dot)
|
112
|
+
corrector.remove(send_node.loc.selector)
|
113
|
+
end
|
114
|
+
|
115
|
+
def correct_from_slash_to_fdiv(corrector, node, receiver, argument)
|
116
|
+
receiver_source = extract_receiver_source(receiver)
|
117
|
+
argument_source = extract_receiver_source(argument)
|
118
|
+
|
119
|
+
if argument.respond_to?(:parenthesized?) && !argument.parenthesized?
|
120
|
+
argument_source = "(#{argument_source})"
|
121
|
+
end
|
122
|
+
|
123
|
+
corrector.replace(node, "#{receiver_source}.fdiv#{argument_source}")
|
124
|
+
end
|
125
|
+
|
126
|
+
def extract_receiver_source(node)
|
127
|
+
if node.send_type? && node.method?(:to_f)
|
128
|
+
node.receiver.source
|
129
|
+
else
|
130
|
+
node.source
|
131
|
+
end
|
132
|
+
end
|
90
133
|
end
|
91
134
|
end
|
92
135
|
end
|
@@ -46,6 +46,10 @@ module RuboCop
|
|
46
46
|
MSG_USE_NORMAL =
|
47
47
|
'Modifier form of `%<keyword>s` makes the line too long.'
|
48
48
|
|
49
|
+
def self.autocorrect_incompatible_with
|
50
|
+
[Style::SoleNestedConditional]
|
51
|
+
end
|
52
|
+
|
49
53
|
def on_if(node)
|
50
54
|
msg = if single_line_as_modifier?(node) && !named_capture_in_condition?(node)
|
51
55
|
MSG_USE_MODIFIER
|
@@ -4,7 +4,8 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
6
|
# This cop looks for uses of Perl-style regexp match
|
7
|
-
# backreferences
|
7
|
+
# backreferences and their English versions like
|
8
|
+
# $1, $2, $&, &+, $MATCH, $PREMATCH, etc.
|
8
9
|
#
|
9
10
|
# @example
|
10
11
|
# # bad
|
@@ -15,19 +16,95 @@ module RuboCop
|
|
15
16
|
class PerlBackrefs < Base
|
16
17
|
extend AutoCorrector
|
17
18
|
|
18
|
-
|
19
|
+
MESSAGE_FORMAT = 'Prefer `%<preferred_expression>s` over `%<original_expression>s`.'
|
20
|
+
|
21
|
+
def on_back_ref(node)
|
22
|
+
on_back_ref_or_gvar_or_nth_ref(node)
|
23
|
+
end
|
24
|
+
|
25
|
+
def on_gvar(node)
|
26
|
+
on_back_ref_or_gvar_or_nth_ref(node)
|
27
|
+
end
|
19
28
|
|
20
29
|
def on_nth_ref(node)
|
21
|
-
|
22
|
-
|
23
|
-
parent_type = node.parent ? node.parent.type : nil
|
30
|
+
on_back_ref_or_gvar_or_nth_ref(node)
|
31
|
+
end
|
24
32
|
|
25
|
-
|
26
|
-
|
33
|
+
private
|
34
|
+
|
35
|
+
# @private
|
36
|
+
# @param [RuboCop::AST::Node] node
|
37
|
+
# @return [Boolean]
|
38
|
+
def derived_from_braceless_interpolation?(node)
|
39
|
+
%i[
|
40
|
+
dstr
|
41
|
+
regexp
|
42
|
+
xstr
|
43
|
+
].include?(node.parent&.type)
|
44
|
+
end
|
45
|
+
|
46
|
+
# @private
|
47
|
+
# @param [RuboCop::AST::Node] node
|
48
|
+
# @param [String] preferred_expression
|
49
|
+
# @return [String]
|
50
|
+
def format_message(node:, preferred_expression:)
|
51
|
+
original_expression = original_expression_of(node)
|
52
|
+
format(
|
53
|
+
MESSAGE_FORMAT,
|
54
|
+
original_expression: original_expression,
|
55
|
+
preferred_expression: preferred_expression
|
56
|
+
)
|
57
|
+
end
|
27
58
|
|
28
|
-
|
29
|
-
|
59
|
+
# @private
|
60
|
+
# @param [RuboCop::AST::Node] node
|
61
|
+
# @return [String]
|
62
|
+
def original_expression_of(node)
|
63
|
+
first = node.to_a.first
|
64
|
+
if first.is_a?(::Integer)
|
65
|
+
"$#{first}"
|
66
|
+
else
|
67
|
+
first.to_s
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# @private
|
72
|
+
# @param [RuboCop::AST::Node] node
|
73
|
+
# @return [String, nil]
|
74
|
+
def preferred_expression_to(node)
|
75
|
+
first = node.to_a.first
|
76
|
+
case first
|
77
|
+
when ::Integer
|
78
|
+
"Regexp.last_match(#{first})"
|
79
|
+
when :$&, :$MATCH
|
80
|
+
'Regexp.last_match(0)'
|
81
|
+
when :$`, :$PREMATCH
|
82
|
+
'Regexp.last_match.pre_match'
|
83
|
+
when :$', :$POSTMATCH
|
84
|
+
'Regexp.last_match.post_match'
|
85
|
+
when :$+, :$LAST_PAREN_MATCH
|
86
|
+
'Regexp.last_match(-1)'
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# @private
|
91
|
+
# @param [RuboCop::AST::Node] node
|
92
|
+
def on_back_ref_or_gvar_or_nth_ref(node)
|
93
|
+
preferred_expression = preferred_expression_to(node)
|
94
|
+
return unless preferred_expression
|
95
|
+
|
96
|
+
add_offense(
|
97
|
+
node,
|
98
|
+
message: format_message(
|
99
|
+
node: node,
|
100
|
+
preferred_expression: preferred_expression
|
101
|
+
)
|
102
|
+
) do |corrector|
|
103
|
+
if derived_from_braceless_interpolation?(node)
|
104
|
+
preferred_expression = "{#{preferred_expression}}"
|
30
105
|
end
|
106
|
+
|
107
|
+
corrector.replace(node, preferred_expression)
|
31
108
|
end
|
32
109
|
end
|
33
110
|
end
|
@@ -37,6 +37,9 @@ module RuboCop
|
|
37
37
|
# "first second".split
|
38
38
|
# A.foo
|
39
39
|
class RedundantArgument < Base
|
40
|
+
include RangeHelp
|
41
|
+
extend AutoCorrector
|
42
|
+
|
40
43
|
MSG = 'Argument %<arg>s is redundant because it is implied by default.'
|
41
44
|
|
42
45
|
def on_send(node)
|
@@ -44,7 +47,9 @@ module RuboCop
|
|
44
47
|
return if node.arguments.count != 1
|
45
48
|
return unless redundant_argument?(node)
|
46
49
|
|
47
|
-
add_offense(node, message: format(MSG, arg: node.arguments.first.source))
|
50
|
+
add_offense(node, message: format(MSG, arg: node.arguments.first.source)) do |corrector|
|
51
|
+
corrector.remove(argument_range(node))
|
52
|
+
end
|
48
53
|
end
|
49
54
|
|
50
55
|
private
|
@@ -69,6 +74,14 @@ module RuboCop
|
|
69
74
|
Parser::CurrentRuby.new(builder).parse(buffer)
|
70
75
|
end
|
71
76
|
end
|
77
|
+
|
78
|
+
def argument_range(node)
|
79
|
+
if node.parenthesized?
|
80
|
+
range_between(node.loc.begin.begin_pos, node.loc.end.end_pos)
|
81
|
+
else
|
82
|
+
range_with_surrounding_space(range: node.first_argument.source_range, newlines: false)
|
83
|
+
end
|
84
|
+
end
|
72
85
|
end
|
73
86
|
end
|
74
87
|
end
|
@@ -29,6 +29,8 @@ module RuboCop
|
|
29
29
|
# c + d
|
30
30
|
# end
|
31
31
|
class SingleLineBlockParams < Base
|
32
|
+
extend AutoCorrector
|
33
|
+
|
32
34
|
MSG = 'Name `%<method>s` block params `|%<params>s|`.'
|
33
35
|
|
34
36
|
def on_block(node)
|
@@ -37,20 +39,41 @@ module RuboCop
|
|
37
39
|
return unless eligible_method?(node)
|
38
40
|
return unless eligible_arguments?(node)
|
39
41
|
|
40
|
-
|
42
|
+
method_name = node.send_node.method_name
|
43
|
+
return if args_match?(method_name, node.arguments)
|
44
|
+
|
45
|
+
preferred_block_arguments = build_preferred_arguments_map(node, target_args(method_name))
|
46
|
+
joined_block_arguments = preferred_block_arguments.values.join(', ')
|
41
47
|
|
42
|
-
message =
|
48
|
+
message = format(MSG, method: method_name, params: joined_block_arguments)
|
43
49
|
|
44
|
-
add_offense(node.arguments, message: message)
|
50
|
+
add_offense(node.arguments, message: message) do |corrector|
|
51
|
+
autocorrect(corrector, node, preferred_block_arguments, joined_block_arguments)
|
52
|
+
end
|
45
53
|
end
|
46
54
|
|
47
55
|
private
|
48
56
|
|
49
|
-
def
|
50
|
-
|
51
|
-
arguments
|
57
|
+
def build_preferred_arguments_map(node, preferred_arguments)
|
58
|
+
preferred_arguments_map = {}
|
59
|
+
node.arguments.each_with_index do |current_lvar, index|
|
60
|
+
preferred_argument = preferred_arguments[index]
|
61
|
+
current_argument = current_lvar.source
|
62
|
+
preferred_argument = "_#{preferred_argument}" if current_argument.start_with?('_')
|
63
|
+
preferred_arguments_map[current_argument] = preferred_argument
|
64
|
+
end
|
65
|
+
|
66
|
+
preferred_arguments_map
|
67
|
+
end
|
68
|
+
|
69
|
+
def autocorrect(corrector, node, preferred_block_arguments, joined_block_arguments)
|
70
|
+
corrector.replace(node.arguments, "|#{joined_block_arguments}|")
|
52
71
|
|
53
|
-
|
72
|
+
node.each_descendant(:lvar) do |lvar|
|
73
|
+
if (preferred_lvar = preferred_block_arguments[lvar.source])
|
74
|
+
corrector.replace(lvar, preferred_lvar)
|
75
|
+
end
|
76
|
+
end
|
54
77
|
end
|
55
78
|
|
56
79
|
def eligible_arguments?(node)
|