rubocop 0.39.0 → 0.40.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 +11 -1
- data/config/default.yml +65 -2
- data/config/disabled.yml +0 -28
- data/config/enabled.yml +40 -0
- data/lib/rubocop.rb +3 -0
- data/lib/rubocop/ast_node.rb +28 -13
- data/lib/rubocop/cached_data.rb +15 -2
- data/lib/rubocop/cli.rb +24 -8
- data/lib/rubocop/config.rb +3 -3
- data/lib/rubocop/config_loader.rb +0 -7
- data/lib/rubocop/cop/cop.rb +2 -2
- data/lib/rubocop/cop/lint/condition_position.rb +3 -1
- data/lib/rubocop/cop/lint/else_layout.rb +3 -2
- data/lib/rubocop/cop/lint/end_alignment.rb +2 -2
- data/lib/rubocop/cop/lint/nested_method_definition.rb +15 -9
- data/lib/rubocop/cop/lint/require_parentheses.rb +1 -1
- data/lib/rubocop/cop/lint/unused_block_argument.rb +2 -0
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +86 -20
- data/lib/rubocop/cop/lint/useless_array_splat.rb +56 -0
- data/lib/rubocop/cop/metrics/method_length.rb +1 -1
- data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +11 -25
- data/lib/rubocop/cop/mixin/if_node.rb +4 -0
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +14 -12
- data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +75 -9
- data/lib/rubocop/cop/mixin/on_normal_if_unless.rb +1 -1
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -2
- data/lib/rubocop/cop/mixin/trailing_comma.rb +15 -5
- data/lib/rubocop/cop/performance/case_when_splat.rb +71 -44
- data/lib/rubocop/cop/performance/detect.rb +28 -18
- data/lib/rubocop/cop/performance/end_with.rb +1 -1
- data/lib/rubocop/cop/performance/redundant_merge.rb +29 -11
- data/lib/rubocop/cop/performance/start_with.rb +1 -1
- data/lib/rubocop/cop/performance/string_replacement.rb +39 -20
- data/lib/rubocop/cop/rails/action_filter.rb +1 -2
- data/lib/rubocop/cop/rails/date.rb +2 -5
- data/lib/rubocop/cop/rails/time_zone.rb +3 -6
- data/lib/rubocop/cop/rails/uniq_before_pluck.rb +57 -0
- data/lib/rubocop/cop/style/alias.rb +10 -3
- data/lib/rubocop/cop/style/align_parameters.rb +8 -2
- data/lib/rubocop/cop/style/and_or.rb +29 -21
- data/lib/rubocop/cop/style/class_and_module_children.rb +1 -1
- data/lib/rubocop/cop/style/collection_methods.rb +1 -2
- data/lib/rubocop/cop/style/comment_indentation.rb +1 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +13 -7
- data/lib/rubocop/cop/style/empty_case_condition.rb +96 -0
- data/lib/rubocop/cop/style/encoding.rb +9 -5
- data/lib/rubocop/cop/style/extra_spacing.rb +22 -7
- data/lib/rubocop/cop/style/file_name.rb +7 -2
- data/lib/rubocop/cop/style/guard_clause.rb +18 -10
- data/lib/rubocop/cop/style/if_inside_else.rb +1 -1
- data/lib/rubocop/cop/style/if_unless_modifier.rb +2 -1
- data/lib/rubocop/cop/style/indentation_width.rb +7 -4
- data/lib/rubocop/cop/style/lambda.rb +98 -30
- data/lib/rubocop/cop/style/line_end_concatenation.rb +5 -0
- data/lib/rubocop/cop/style/multiline_array_brace_layout.rb +34 -9
- data/lib/rubocop/cop/style/multiline_assignment_layout.rb +2 -1
- data/lib/rubocop/cop/style/multiline_hash_brace_layout.rb +42 -17
- data/lib/rubocop/cop/style/multiline_method_call_brace_layout.rb +39 -14
- data/lib/rubocop/cop/style/multiline_method_definition_brace_layout.rb +36 -15
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +8 -6
- data/lib/rubocop/cop/style/negated_while.rb +2 -1
- data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +15 -0
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +5 -8
- data/lib/rubocop/cop/style/next.rb +1 -1
- data/lib/rubocop/cop/style/not.rb +5 -2
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +2 -2
- data/lib/rubocop/cop/style/raise_args.rb +70 -7
- data/lib/rubocop/cop/style/redundant_exception.rb +34 -20
- data/lib/rubocop/cop/style/redundant_parentheses.rb +27 -1
- data/lib/rubocop/cop/style/space_after_colon.rb +14 -10
- data/lib/rubocop/cop/style/space_after_comma.rb +5 -0
- data/lib/rubocop/cop/style/space_after_not.rb +3 -4
- data/lib/rubocop/cop/style/space_after_semicolon.rb +5 -0
- data/lib/rubocop/cop/style/space_around_operators.rb +2 -1
- data/lib/rubocop/cop/style/special_global_vars.rb +4 -2
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/string_methods.rb +1 -2
- data/lib/rubocop/cop/style/symbol_proc.rb +7 -1
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +25 -0
- data/lib/rubocop/cop/style/word_array.rb +50 -22
- data/lib/rubocop/cop/util.rb +0 -4
- data/lib/rubocop/formatter/clang_style_formatter.rb +38 -22
- data/lib/rubocop/options.rb +45 -10
- data/lib/rubocop/path_util.rb +2 -34
- data/lib/rubocop/result_cache.rb +10 -4
- data/lib/rubocop/runner.rb +5 -3
- data/lib/rubocop/version.rb +1 -1
- metadata +7 -4
@@ -5,6 +5,10 @@ module RuboCop
|
|
5
5
|
module Cop
|
6
6
|
# Common functionality for checking if nodes.
|
7
7
|
module IfNode
|
8
|
+
def ternary?(node)
|
9
|
+
node.loc.respond_to?(:question)
|
10
|
+
end
|
11
|
+
|
8
12
|
def modifier_if?(node)
|
9
13
|
node.loc.respond_to?(:keyword) &&
|
10
14
|
%w(if unless).include?(node.loc.keyword.source) &&
|
@@ -1,8 +1,6 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require 'pp'
|
5
|
-
|
6
4
|
module RuboCop
|
7
5
|
module Cop
|
8
6
|
# Common functionality for checking multiline method calls and binary
|
@@ -36,16 +34,20 @@ module RuboCop
|
|
36
34
|
if operator?(method_name) && args.any?
|
37
35
|
args.first.source_range # not used for method calls
|
38
36
|
else
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
37
|
+
regular_method_right_hand_side(send_node)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def regular_method_right_hand_side(send_node)
|
42
|
+
dot = send_node.loc.dot
|
43
|
+
selector = send_node.loc.selector
|
44
|
+
if dot && selector && dot.line == selector.line
|
45
|
+
dot.join(selector)
|
46
|
+
elsif selector
|
47
|
+
selector
|
48
|
+
elsif dot.line == send_node.loc.begin.line
|
49
|
+
# lambda.(args)
|
50
|
+
dot.join(send_node.loc.begin)
|
49
51
|
end
|
50
52
|
end
|
51
53
|
|
@@ -3,21 +3,23 @@
|
|
3
3
|
|
4
4
|
module RuboCop
|
5
5
|
module Cop
|
6
|
-
# Common functionality for checking
|
7
|
-
#
|
6
|
+
# Common functionality for checking the closing brace of a literal is
|
7
|
+
# either on the same line as the last contained elements, or a new line.
|
8
8
|
module MultilineLiteralBraceLayout
|
9
|
+
include ConfigurableEnforcedStyle
|
10
|
+
|
9
11
|
def check_brace_layout(node)
|
10
12
|
return unless node.loc.begin # Ignore implicit literals.
|
11
13
|
return if children(node).empty? # Ignore empty literals.
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
add_offense(node, :expression, self.class::SAME_LINE_MESSAGE)
|
17
|
-
else
|
18
|
-
return unless closing_brace_on_same_line?(node)
|
15
|
+
# If the last node is or contains a conflicting HEREDOC, we don't want
|
16
|
+
# to adjust the brace layout because this will result in invalid code.
|
17
|
+
return if last_line_heredoc?(children(node).last)
|
19
18
|
|
20
|
-
|
19
|
+
case style
|
20
|
+
when :symmetrical then handle_symmetrical(node)
|
21
|
+
when :new_line then handle_new_line(node)
|
22
|
+
when :same_line then handle_same_line(node)
|
21
23
|
end
|
22
24
|
end
|
23
25
|
|
@@ -38,6 +40,30 @@ module RuboCop
|
|
38
40
|
|
39
41
|
private
|
40
42
|
|
43
|
+
def handle_new_line(node)
|
44
|
+
return unless closing_brace_on_same_line?(node)
|
45
|
+
|
46
|
+
add_offense(node, :expression, self.class::ALWAYS_NEW_LINE_MESSAGE)
|
47
|
+
end
|
48
|
+
|
49
|
+
def handle_same_line(node)
|
50
|
+
return if closing_brace_on_same_line?(node)
|
51
|
+
|
52
|
+
add_offense(node, :expression, self.class::ALWAYS_SAME_LINE_MESSAGE)
|
53
|
+
end
|
54
|
+
|
55
|
+
def handle_symmetrical(node)
|
56
|
+
if opening_brace_on_same_line?(node)
|
57
|
+
return if closing_brace_on_same_line?(node)
|
58
|
+
|
59
|
+
add_offense(node, :expression, self.class::SAME_LINE_MESSAGE)
|
60
|
+
else
|
61
|
+
return unless closing_brace_on_same_line?(node)
|
62
|
+
|
63
|
+
add_offense(node, :expression, self.class::NEW_LINE_MESSAGE)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
41
67
|
def children(node)
|
42
68
|
node.children
|
43
69
|
end
|
@@ -53,6 +79,46 @@ module RuboCop
|
|
53
79
|
def closing_brace_on_same_line?(node)
|
54
80
|
node.loc.end.line == children(node).last.loc.last_line
|
55
81
|
end
|
82
|
+
|
83
|
+
# Starting with the parent node and recursively for the parent node's
|
84
|
+
# children, check if the node is a HEREDOC and if the HEREDOC ends below
|
85
|
+
# or on the last line of the parent node.
|
86
|
+
#
|
87
|
+
# Example:
|
88
|
+
#
|
89
|
+
# # node is `b: ...` parameter
|
90
|
+
# # last_line_heredoc?(node) => false
|
91
|
+
# foo(a,
|
92
|
+
# b: {
|
93
|
+
# a: 1,
|
94
|
+
# c: <<-EOM
|
95
|
+
# baz
|
96
|
+
# EOM
|
97
|
+
# }
|
98
|
+
# )
|
99
|
+
#
|
100
|
+
# # node is `b: ...` parameter
|
101
|
+
# # last_line_heredoc?(node) => true
|
102
|
+
# foo(a,
|
103
|
+
# b: <<-EOM
|
104
|
+
# baz
|
105
|
+
# EOM
|
106
|
+
# )
|
107
|
+
def last_line_heredoc?(node, parent = nil)
|
108
|
+
parent ||= node
|
109
|
+
|
110
|
+
return false unless node.respond_to?(:loc)
|
111
|
+
|
112
|
+
if node.loc.respond_to?(:heredoc_end) &&
|
113
|
+
node.loc.heredoc_end.last_line >= parent.loc.last_line
|
114
|
+
return true
|
115
|
+
end
|
116
|
+
|
117
|
+
return false unless node.respond_to?(:children)
|
118
|
+
return false if node.children.empty?
|
119
|
+
|
120
|
+
node.children.any? { |child| last_line_heredoc?(child, parent) }
|
121
|
+
end
|
56
122
|
end
|
57
123
|
end
|
58
124
|
end
|
@@ -36,7 +36,7 @@ module RuboCop
|
|
36
36
|
extra_info)
|
37
37
|
end
|
38
38
|
elsif should_have_comma?(style, node)
|
39
|
-
put_comma(items, kind, sb)
|
39
|
+
put_comma(node, items, kind, sb)
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
@@ -87,10 +87,11 @@ module RuboCop
|
|
87
87
|
|
88
88
|
_receiver, _method_name, *args = *node
|
89
89
|
args.flat_map do |a|
|
90
|
-
# For each argument, if it is a multi-line hash,
|
90
|
+
# For each argument, if it is a multi-line hash without braces,
|
91
91
|
# then promote the hash elements to method arguments
|
92
92
|
# for the purpose of determining multi-line-ness.
|
93
|
-
if a.hash_type? && a.loc.first_line != a.loc.last_line
|
93
|
+
if a.hash_type? && a.loc.first_line != a.loc.last_line &&
|
94
|
+
!brackets?(a)
|
94
95
|
a.children
|
95
96
|
else
|
96
97
|
a
|
@@ -111,7 +112,7 @@ module RuboCop
|
|
111
112
|
"#{extra_info}.")
|
112
113
|
end
|
113
114
|
|
114
|
-
def put_comma(items, kind, sb)
|
115
|
+
def put_comma(node, items, kind, sb)
|
115
116
|
last_item = items.last
|
116
117
|
return if last_item.type == :block_pass
|
117
118
|
|
@@ -120,11 +121,20 @@ module RuboCop
|
|
120
121
|
ix += last_expr.source[ix..-1] =~ /\S/
|
121
122
|
range = Parser::Source::Range.new(sb, last_expr.begin_pos + ix,
|
122
123
|
last_expr.end_pos)
|
123
|
-
|
124
|
+
autocorrect_range = avoid_autocorrect?(elements(node)) ? nil : range
|
125
|
+
|
126
|
+
add_offense(autocorrect_range, range,
|
124
127
|
format(MSG, 'Put a', format(kind, 'a multiline') + '.'))
|
125
128
|
end
|
126
129
|
|
130
|
+
# By default, there's no reason to avoid auto-correct.
|
131
|
+
def avoid_autocorrect?(_)
|
132
|
+
false
|
133
|
+
end
|
134
|
+
|
127
135
|
def autocorrect(range)
|
136
|
+
return unless range
|
137
|
+
|
128
138
|
lambda do |corrector|
|
129
139
|
case range.source
|
130
140
|
when ',' then corrector.remove(range)
|
@@ -57,23 +57,17 @@ module RuboCop
|
|
57
57
|
MSG = 'Place `when` conditions with a splat ' \
|
58
58
|
'at the end of the `when` branches.'.freeze
|
59
59
|
ARRAY_MSG = 'Do not expand array literals in `when` conditions.'.freeze
|
60
|
-
OPEN_BRACKET = '['.freeze
|
61
60
|
PERCENT_W = '%w'.freeze
|
62
61
|
PERCENT_CAPITAL_W = '%W'.freeze
|
63
62
|
PERCENT_I = '%i'.freeze
|
64
63
|
PERCENT_CAPITAL_I = '%I'.freeze
|
65
64
|
|
66
|
-
def initialize(*)
|
67
|
-
super
|
68
|
-
@reordered_splat_condition = false
|
69
|
-
end
|
70
|
-
|
71
65
|
def on_case(node)
|
72
66
|
_case_branch, *when_branches, _else_branch = *node
|
73
67
|
when_conditions =
|
74
68
|
when_branches.each_with_object([]) do |branch, conditions|
|
75
|
-
condition, = *branch
|
76
|
-
conditions <<
|
69
|
+
*condition, _ = *branch
|
70
|
+
condition.each { |c| conditions << c }
|
77
71
|
end
|
78
72
|
|
79
73
|
splat_offenses(when_conditions).reverse_each do |condition|
|
@@ -85,19 +79,74 @@ module RuboCop
|
|
85
79
|
end
|
86
80
|
|
87
81
|
def autocorrect(node)
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
82
|
+
*conditions, _body = *node
|
83
|
+
|
84
|
+
new_condition =
|
85
|
+
conditions.each_with_object([]) do |condition, correction|
|
86
|
+
variable, = *condition
|
87
|
+
if variable.respond_to?(:array_type?) && variable.array_type?
|
88
|
+
correction << expand_percent_array(variable)
|
89
|
+
next
|
90
|
+
end
|
91
|
+
|
92
|
+
correction << condition.source
|
93
|
+
end
|
94
|
+
new_condition = new_condition.join(', ')
|
95
|
+
|
96
|
+
lambda do |corrector|
|
97
|
+
if needs_reorder?(conditions)
|
98
|
+
reorder_condition(corrector, node, new_condition)
|
99
|
+
else
|
100
|
+
inline_fix_branch(corrector, node, conditions, new_condition)
|
101
|
+
end
|
96
102
|
end
|
97
103
|
end
|
98
104
|
|
99
105
|
private
|
100
106
|
|
107
|
+
def inline_fix_branch(corrector, node, conditions, new_condition)
|
108
|
+
range =
|
109
|
+
Parser::Source::Range.new(node.loc.expression.source_buffer,
|
110
|
+
conditions[0].loc.expression.begin_pos,
|
111
|
+
conditions[-1].loc.expression.end_pos)
|
112
|
+
corrector.replace(range, new_condition)
|
113
|
+
end
|
114
|
+
|
115
|
+
def reorder_condition(corrector, node, new_condition)
|
116
|
+
*_conditions, body = *node
|
117
|
+
parent = node.parent
|
118
|
+
_case_branch, *when_branches, _else_branch = *parent
|
119
|
+
current_index = when_branches.index { |branch| branch == node }
|
120
|
+
next_branch = when_branches[current_index + 1]
|
121
|
+
range = Parser::Source::Range.new(parent,
|
122
|
+
node.source_range.begin_pos,
|
123
|
+
next_branch.source_range.begin_pos)
|
124
|
+
|
125
|
+
corrector.remove(range)
|
126
|
+
|
127
|
+
correction = if same_line?(node, body)
|
128
|
+
new_condition_with_then(node, new_condition)
|
129
|
+
else
|
130
|
+
new_branch_without_then(node, body, new_condition)
|
131
|
+
end
|
132
|
+
|
133
|
+
corrector.insert_after(when_branches.last.source_range, correction)
|
134
|
+
end
|
135
|
+
|
136
|
+
def same_line?(node, other)
|
137
|
+
node.loc.first_line == other.loc.first_line
|
138
|
+
end
|
139
|
+
|
140
|
+
def new_condition_with_then(node, new_condition)
|
141
|
+
"\n#{' ' * node.loc.column}when " \
|
142
|
+
"#{new_condition} then #{node.children.last.source}"
|
143
|
+
end
|
144
|
+
|
145
|
+
def new_branch_without_then(node, body, new_condition)
|
146
|
+
"\n#{' ' * node.loc.column}when #{new_condition}\n" \
|
147
|
+
"#{' ' * body.loc.column}#{node.children.last.source}"
|
148
|
+
end
|
149
|
+
|
101
150
|
def splat_offenses(when_conditions)
|
102
151
|
found_non_splat = false
|
103
152
|
when_conditions.reverse.each_with_object([]) do |condition, result|
|
@@ -115,34 +164,10 @@ module RuboCop
|
|
115
164
|
!condition.splat_type?
|
116
165
|
end
|
117
166
|
|
118
|
-
def
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
if array_start.start_with?(OPEN_BRACKET)
|
123
|
-
corrector.remove(condition.loc.operator)
|
124
|
-
corrector.remove(variable.loc.begin)
|
125
|
-
corrector.remove(variable.loc.end)
|
126
|
-
else
|
127
|
-
corrector.replace(condition.source_range,
|
128
|
-
expand_percent_array(variable))
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
def reorder_splat_condition(node)
|
134
|
-
_case_branch, *when_branches, _else_branch = *node.parent
|
135
|
-
current_index = when_branches.index { |branch| branch == node }
|
136
|
-
next_branch = when_branches[current_index + 1]
|
137
|
-
correction = "\n#{offset(node)}#{node.source}"
|
138
|
-
range =
|
139
|
-
Parser::Source::Range.new(node.parent,
|
140
|
-
node.source_range.begin_pos,
|
141
|
-
next_branch.source_range.begin_pos)
|
142
|
-
|
143
|
-
lambda do |corrector|
|
144
|
-
corrector.remove(range)
|
145
|
-
corrector.insert_after(when_branches.last.source_range, correction)
|
167
|
+
def needs_reorder?(conditions)
|
168
|
+
conditions.any? do |condition|
|
169
|
+
variable, = *condition
|
170
|
+
condition.splat_type? && !(variable && variable.array_type?)
|
146
171
|
end
|
147
172
|
end
|
148
173
|
|
@@ -159,6 +184,8 @@ module RuboCop
|
|
159
184
|
":#{elements.join(', :')}"
|
160
185
|
elsif array_start.start_with?(PERCENT_CAPITAL_I)
|
161
186
|
%(:"#{elements.join('", :"')}")
|
187
|
+
else
|
188
|
+
elements.join(', ')
|
162
189
|
end
|
163
190
|
end
|
164
191
|
end
|
@@ -33,23 +33,12 @@ module RuboCop
|
|
33
33
|
def on_send(node)
|
34
34
|
return unless should_run?
|
35
35
|
receiver, second_method, *args = *node
|
36
|
-
return
|
36
|
+
return if accept_second_call?(receiver, second_method, args)
|
37
37
|
|
38
38
|
receiver, _args, body = *receiver if receiver.block_type?
|
39
|
-
|
40
|
-
|
41
|
-
# check that we have usual block or block pass
|
42
|
-
return if body.nil? && (args.nil? || !args.block_pass_type?)
|
43
|
-
return unless SELECT_METHODS.include?(first_method)
|
44
|
-
return if lazy?(caller)
|
39
|
+
return if accept_first_call?(receiver, body)
|
45
40
|
|
46
|
-
|
47
|
-
|
48
|
-
message = second_method == :last ? REVERSE_MSG : MSG
|
49
|
-
add_offense(node, range, format(message,
|
50
|
-
preferred_method,
|
51
|
-
first_method,
|
52
|
-
second_method))
|
41
|
+
offense(node, receiver, second_method)
|
53
42
|
end
|
54
43
|
|
55
44
|
def autocorrect(node)
|
@@ -79,10 +68,31 @@ module RuboCop
|
|
79
68
|
config['Rails'.freeze]['Enabled'.freeze])
|
80
69
|
end
|
81
70
|
|
82
|
-
def
|
83
|
-
receiver
|
84
|
-
DANGEROUS_METHODS.include?(method)
|
85
|
-
args.empty?
|
71
|
+
def accept_second_call?(receiver, method, args)
|
72
|
+
!receiver ||
|
73
|
+
!DANGEROUS_METHODS.include?(method) ||
|
74
|
+
!args.empty?
|
75
|
+
end
|
76
|
+
|
77
|
+
def accept_first_call?(receiver, body)
|
78
|
+
caller, first_method, args = *receiver
|
79
|
+
|
80
|
+
# check that we have usual block or block pass
|
81
|
+
return true if body.nil? && (args.nil? || !args.block_pass_type?)
|
82
|
+
return true unless SELECT_METHODS.include?(first_method)
|
83
|
+
|
84
|
+
lazy?(caller)
|
85
|
+
end
|
86
|
+
|
87
|
+
def offense(node, receiver, second_method)
|
88
|
+
_caller, first_method, _args = *receiver
|
89
|
+
range = receiver.loc.selector.join(node.loc.selector)
|
90
|
+
|
91
|
+
message = second_method == :last ? REVERSE_MSG : MSG
|
92
|
+
add_offense(node, range, format(message,
|
93
|
+
preferred_method,
|
94
|
+
first_method,
|
95
|
+
second_method))
|
86
96
|
end
|
87
97
|
|
88
98
|
def preferred_method
|