rubocop 0.87.1 → 0.88.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/bin/rubocop-profile +31 -0
- data/config/default.yml +57 -6
- data/lib/rubocop.rb +6 -0
- data/lib/rubocop/cli.rb +2 -2
- data/lib/rubocop/cli/command/auto_genenerate_config.rb +2 -2
- data/lib/rubocop/config_loader.rb +20 -7
- data/lib/rubocop/config_store.rb +4 -0
- data/lib/rubocop/cop/autocorrect_logic.rb +1 -1
- data/lib/rubocop/cop/badge.rb +1 -1
- data/lib/rubocop/cop/base.rb +12 -4
- data/lib/rubocop/cop/cop.rb +1 -1
- data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +26 -0
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +6 -1
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +1 -0
- data/lib/rubocop/cop/layout/end_alignment.rb +3 -2
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +16 -5
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +3 -2
- data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +27 -68
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +3 -2
- data/lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb +8 -2
- data/lib/rubocop/cop/lint/duplicate_elsif_condition.rb +39 -0
- data/lib/rubocop/cop/lint/duplicate_methods.rb +2 -2
- data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +3 -2
- data/lib/rubocop/cop/lint/literal_as_condition.rb +11 -1
- data/lib/rubocop/cop/lint/nested_method_definition.rb +13 -19
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +67 -0
- data/lib/rubocop/cop/mixin/statement_modifier.rb +3 -3
- data/lib/rubocop/cop/style/accessor_grouping.rb +8 -1
- data/lib/rubocop/cop/style/array_coercion.rb +63 -0
- data/lib/rubocop/cop/style/auto_resource_cleanup.rb +3 -2
- data/lib/rubocop/cop/style/bisected_attr_accessor.rb +5 -4
- data/lib/rubocop/cop/style/case_like_if.rb +217 -0
- data/lib/rubocop/cop/style/commented_keyword.rb +5 -2
- data/lib/rubocop/cop/style/conditional_assignment.rb +1 -1
- data/lib/rubocop/cop/style/exponential_notation.rb +6 -8
- data/lib/rubocop/cop/style/float_division.rb +7 -10
- data/lib/rubocop/cop/style/format_string_token.rb +5 -5
- data/lib/rubocop/cop/style/hash_as_last_array_item.rb +62 -0
- data/lib/rubocop/cop/style/hash_like_case.rb +76 -0
- data/lib/rubocop/cop/style/if_unless_modifier.rb +11 -11
- data/lib/rubocop/cop/style/missing_else.rb +1 -11
- data/lib/rubocop/cop/style/numeric_predicate.rb +3 -4
- data/lib/rubocop/cop/style/parallel_assignment.rb +3 -3
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
- data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +50 -0
- data/lib/rubocop/cop/style/redundant_sort.rb +3 -2
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +3 -2
- data/lib/rubocop/cop/style/trailing_method_end_statement.rb +9 -32
- data/lib/rubocop/cop/variable_force/variable.rb +5 -3
- data/lib/rubocop/file_finder.rb +12 -12
- data/lib/rubocop/path_util.rb +2 -17
- data/lib/rubocop/result_cache.rb +12 -8
- data/lib/rubocop/rspec/expect_offense.rb +31 -5
- data/lib/rubocop/rspec/shared_contexts.rb +12 -9
- data/lib/rubocop/runner.rb +5 -6
- data/lib/rubocop/target_finder.rb +2 -2
- data/lib/rubocop/version.rb +1 -1
- metadata +9 -2
@@ -150,9 +150,10 @@ module RuboCop
|
|
150
150
|
end
|
151
151
|
|
152
152
|
def alignment_node(node)
|
153
|
-
|
153
|
+
case style
|
154
|
+
when :keyword
|
154
155
|
node
|
155
|
-
|
156
|
+
when :variable
|
156
157
|
alignment_node_for_variable_style(node)
|
157
158
|
else
|
158
159
|
start_line_range(node)
|
@@ -95,11 +95,22 @@ module RuboCop
|
|
95
95
|
end
|
96
96
|
|
97
97
|
def line_break_necessary_in_args?(node)
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
98
|
+
needed_length_for_args(node) > max_line_length
|
99
|
+
end
|
100
|
+
|
101
|
+
def needed_length_for_args(node)
|
102
|
+
node.source_range.column +
|
103
|
+
characters_needed_for_space_and_pipes(node) +
|
104
|
+
node.source.lines.first.chomp.length +
|
105
|
+
block_arg_string(node, node.arguments).length
|
106
|
+
end
|
107
|
+
|
108
|
+
def characters_needed_for_space_and_pipes(node)
|
109
|
+
if node.source.lines.first.end_with?("|\n")
|
110
|
+
PIPE_SIZE
|
111
|
+
else
|
112
|
+
1 + PIPE_SIZE * 2
|
113
|
+
end
|
103
114
|
end
|
104
115
|
|
105
116
|
def add_offense_for_expression(node, expr, msg)
|
@@ -56,11 +56,12 @@ module RuboCop
|
|
56
56
|
def check_inside_pipes(arguments)
|
57
57
|
opening_pipe, closing_pipe = pipes(arguments)
|
58
58
|
|
59
|
-
|
59
|
+
case style
|
60
|
+
when :no_space
|
60
61
|
check_no_space_style_inside_pipes(arguments.children,
|
61
62
|
opening_pipe,
|
62
63
|
closing_pipe)
|
63
|
-
|
64
|
+
when :space
|
64
65
|
check_space_style_inside_pipes(arguments.children,
|
65
66
|
opening_pipe,
|
66
67
|
closing_pipe)
|
@@ -34,96 +34,55 @@ module RuboCop
|
|
34
34
|
# RuboCop::Cop::Cop
|
35
35
|
# ::RuboCop::Cop
|
36
36
|
#
|
37
|
-
class SpaceAroundMethodCallOperator <
|
38
|
-
include
|
37
|
+
class SpaceAroundMethodCallOperator < Base
|
38
|
+
include RangeHelp
|
39
|
+
extend AutoCorrector
|
40
|
+
|
41
|
+
SPACES_REGEXP = /\A[ \t]+\z/.freeze
|
39
42
|
|
40
43
|
MSG = 'Avoid using spaces around a method call operator.'
|
41
44
|
|
42
45
|
def on_send(node)
|
43
|
-
return unless
|
46
|
+
return unless node.dot? || node.safe_navigation?
|
44
47
|
|
45
|
-
|
48
|
+
check_space_before_dot(node)
|
49
|
+
check_space_after_dot(node)
|
46
50
|
end
|
51
|
+
alias on_csend on_send
|
47
52
|
|
48
53
|
def on_const(node)
|
49
54
|
return unless node.loc.double_colon
|
50
55
|
|
51
|
-
|
52
|
-
end
|
53
|
-
|
54
|
-
def autocorrect(node)
|
55
|
-
operator = operator_token(node)
|
56
|
-
left = left_token_for_auto_correction(node, operator)
|
57
|
-
right = right_token_for_auto_correction(operator)
|
58
|
-
|
59
|
-
lambda do |corrector|
|
60
|
-
SpaceCorrector.remove_space(
|
61
|
-
processed_source, corrector, left, right
|
62
|
-
)
|
63
|
-
end
|
56
|
+
check_space_after_double_colon(node)
|
64
57
|
end
|
65
58
|
|
66
|
-
alias on_csend on_send
|
67
|
-
|
68
59
|
private
|
69
60
|
|
70
|
-
def
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
if !right.comment? && valid_right_token?(right, operator)
|
76
|
-
no_space_offenses(node, operator, right, MSG)
|
77
|
-
end
|
78
|
-
return unless valid_left_token?(left, operator)
|
79
|
-
|
80
|
-
no_space_offenses(node, left, operator, MSG) if add_left_offense
|
81
|
-
end
|
82
|
-
|
83
|
-
def operator_token(node)
|
84
|
-
operator_location =
|
85
|
-
node.const_type? ? node.loc.double_colon : node.loc.dot
|
86
|
-
|
87
|
-
processed_source.find_token do |token|
|
88
|
-
token.pos == operator_location
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def previous_token(current_token)
|
93
|
-
index = processed_source.tokens.index(current_token)
|
94
|
-
index.zero? ? nil : processed_source.tokens[index - 1]
|
95
|
-
end
|
96
|
-
|
97
|
-
def next_token(current_token)
|
98
|
-
index = processed_source.tokens.index(current_token)
|
99
|
-
processed_source.tokens[index + 1]
|
100
|
-
end
|
101
|
-
|
102
|
-
def dot_or_safe_navigation_operator?(node)
|
103
|
-
node.dot? || node.safe_navigation?
|
61
|
+
def check_space_before_dot(node)
|
62
|
+
receiver_pos = node.receiver.source_range.end_pos
|
63
|
+
dot_pos = node.loc.dot.begin_pos
|
64
|
+
check_space(receiver_pos, dot_pos)
|
104
65
|
end
|
105
66
|
|
106
|
-
def
|
107
|
-
|
67
|
+
def check_space_after_dot(node)
|
68
|
+
dot_pos = node.loc.dot.end_pos
|
69
|
+
selector_pos = node.loc.selector.begin_pos
|
70
|
+
check_space(dot_pos, selector_pos)
|
108
71
|
end
|
109
72
|
|
110
|
-
def
|
111
|
-
|
73
|
+
def check_space_after_double_colon(node)
|
74
|
+
double_colon_pos = node.loc.double_colon.end_pos
|
75
|
+
name_pos = node.loc.name.begin_pos
|
76
|
+
check_space(double_colon_pos, name_pos)
|
112
77
|
end
|
113
78
|
|
114
|
-
def
|
115
|
-
|
116
|
-
return operator if node.const_type?
|
117
|
-
return left_token if valid_left_token?(left_token, operator)
|
118
|
-
|
119
|
-
operator
|
120
|
-
end
|
79
|
+
def check_space(begin_pos, end_pos)
|
80
|
+
return if end_pos <= begin_pos
|
121
81
|
|
122
|
-
|
123
|
-
|
124
|
-
return right_token if !right_token.comment? && valid_right_token?(right_token, operator)
|
82
|
+
range = range_between(begin_pos, end_pos)
|
83
|
+
return unless range.source.match?(SPACES_REGEXP)
|
125
84
|
|
126
|
-
|
85
|
+
add_offense(range) { |corrector| corrector.remove(range) }
|
127
86
|
end
|
128
87
|
end
|
129
88
|
end
|
@@ -142,11 +142,12 @@ module RuboCop
|
|
142
142
|
end
|
143
143
|
|
144
144
|
def issue_offenses(node, left, right, start_ok, end_ok)
|
145
|
-
|
145
|
+
case style
|
146
|
+
when :no_space
|
146
147
|
start_ok = next_to_comment?(node, left)
|
147
148
|
no_space_offenses(node, left, right, MSG, start_ok: start_ok,
|
148
149
|
end_ok: end_ok)
|
149
|
-
|
150
|
+
when :space
|
150
151
|
space_offenses(node, left, right, MSG, start_ok: start_ok,
|
151
152
|
end_ok: end_ok)
|
152
153
|
else
|
@@ -22,7 +22,9 @@ module RuboCop
|
|
22
22
|
# def initialize
|
23
23
|
# @x = 1
|
24
24
|
# end
|
25
|
-
class DisjunctiveAssignmentInConstructor <
|
25
|
+
class DisjunctiveAssignmentInConstructor < Base
|
26
|
+
extend AutoCorrector
|
27
|
+
|
26
28
|
MSG = 'Unnecessary disjunctive assignment. Use plain assignment.'
|
27
29
|
|
28
30
|
def on_def(node)
|
@@ -73,7 +75,11 @@ module RuboCop
|
|
73
75
|
# @param [Node] node a disjunctive assignment
|
74
76
|
def check_disjunctive_assignment(node)
|
75
77
|
lhs = node.child_nodes.first
|
76
|
-
|
78
|
+
return unless lhs.ivasgn_type?
|
79
|
+
|
80
|
+
add_offense(node.loc.operator) do |corrector|
|
81
|
+
corrector.replace(node.loc.operator, '=')
|
82
|
+
end
|
77
83
|
end
|
78
84
|
end
|
79
85
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
# This cop checks that there are no repeated conditions used in if 'elsif'.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# if x == 1
|
11
|
+
# do_something
|
12
|
+
# elsif x == 1
|
13
|
+
# do_something_else
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# # good
|
17
|
+
# if x == 1
|
18
|
+
# do_something
|
19
|
+
# elsif x == 2
|
20
|
+
# do_something_else
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
class DuplicateElsifCondition < Base
|
24
|
+
MSG = 'Duplicate `elsif` condition detected.'
|
25
|
+
|
26
|
+
def on_if(node)
|
27
|
+
previous = []
|
28
|
+
while node.if? || node.elsif?
|
29
|
+
condition = node.condition
|
30
|
+
add_offense(condition) if previous.include?(condition)
|
31
|
+
previous << condition
|
32
|
+
node = node.else_branch
|
33
|
+
break unless node&.if_type?
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -126,7 +126,7 @@ module RuboCop
|
|
126
126
|
end
|
127
127
|
|
128
128
|
def message_for_dup(node, method_name)
|
129
|
-
format(MSG, method: method_name, defined: @definitions[method_name],
|
129
|
+
format(MSG, method: method_name, defined: source_location(@definitions[method_name]),
|
130
130
|
current: source_location(node))
|
131
131
|
end
|
132
132
|
|
@@ -152,7 +152,7 @@ module RuboCop
|
|
152
152
|
|
153
153
|
add_offense(node, location: loc, message: message)
|
154
154
|
else
|
155
|
-
@definitions[method_name] =
|
155
|
+
@definitions[method_name] = node
|
156
156
|
end
|
157
157
|
end
|
158
158
|
|
@@ -30,6 +30,8 @@ module RuboCop
|
|
30
30
|
# break if condition
|
31
31
|
# end
|
32
32
|
class LiteralAsCondition < Cop
|
33
|
+
include RangeHelp
|
34
|
+
|
33
35
|
MSG = 'Literal `%<literal>s` appeared as a condition.'
|
34
36
|
|
35
37
|
def on_if(node)
|
@@ -57,7 +59,8 @@ module RuboCop
|
|
57
59
|
case_node.each_when do |when_node|
|
58
60
|
next unless when_node.conditions.all?(&:literal?)
|
59
61
|
|
60
|
-
|
62
|
+
range = when_conditions_range(when_node)
|
63
|
+
add_offense(when_node, location: range, message: message(range))
|
61
64
|
end
|
62
65
|
end
|
63
66
|
end
|
@@ -129,6 +132,13 @@ module RuboCop
|
|
129
132
|
node.condition
|
130
133
|
end
|
131
134
|
end
|
135
|
+
|
136
|
+
def when_conditions_range(when_node)
|
137
|
+
range_between(
|
138
|
+
when_node.conditions.first.source_range.begin_pos,
|
139
|
+
when_node.conditions.last.source_range.end_pos
|
140
|
+
)
|
141
|
+
end
|
132
142
|
end
|
133
143
|
end
|
134
144
|
end
|
@@ -59,31 +59,25 @@ module RuboCop
|
|
59
59
|
'Use `lambda` instead.'
|
60
60
|
|
61
61
|
def on_def(node)
|
62
|
-
|
63
|
-
|
64
|
-
end
|
65
|
-
end
|
66
|
-
alias on_defs on_def
|
67
|
-
|
68
|
-
private
|
62
|
+
subject, = *node
|
63
|
+
return if node.defs_type? && subject.lvar_type?
|
69
64
|
|
70
|
-
|
71
|
-
|
72
|
-
if child.def_type?
|
73
|
-
yield child
|
74
|
-
elsif child.defs_type?
|
75
|
-
subject, = *child
|
76
|
-
next if subject.lvar_type?
|
65
|
+
def_ancestor = node.each_ancestor(:def, :defs).first
|
66
|
+
return unless def_ancestor
|
77
67
|
|
78
|
-
|
79
|
-
|
80
|
-
|
68
|
+
within_scoping_def =
|
69
|
+
node.each_ancestor(:block, :sclass).any? do |ancestor|
|
70
|
+
scoping_method_call?(ancestor)
|
81
71
|
end
|
82
|
-
|
72
|
+
|
73
|
+
add_offense(node) if def_ancestor && !within_scoping_def
|
83
74
|
end
|
75
|
+
alias on_defs on_def
|
76
|
+
|
77
|
+
private
|
84
78
|
|
85
79
|
def scoping_method_call?(child)
|
86
|
-
eval_call?(child) || exec_call?(child) ||
|
80
|
+
child.sclass_type? || eval_call?(child) || exec_call?(child) ||
|
87
81
|
class_or_module_or_struct_new_call?(child)
|
88
82
|
end
|
89
83
|
|
@@ -35,6 +35,22 @@ module RuboCop
|
|
35
35
|
# require file
|
36
36
|
# end
|
37
37
|
#
|
38
|
+
# @example
|
39
|
+
#
|
40
|
+
# # bad
|
41
|
+
# Dir['./lib/**/*.rb'].each(&method(:require))
|
42
|
+
#
|
43
|
+
# # good
|
44
|
+
# Dir['./lib/**/*.rb'].sort.each(&method(:require))
|
45
|
+
#
|
46
|
+
# @example
|
47
|
+
#
|
48
|
+
# # bad
|
49
|
+
# Dir.glob(Rails.root.join('test', '*.rb'), &method(:require))
|
50
|
+
#
|
51
|
+
# # good
|
52
|
+
# Dir.glob(Rails.root.join('test', '*.rb')).sort.each(&method(:require))
|
53
|
+
#
|
38
54
|
class NonDeterministicRequireOrder < Cop
|
39
55
|
MSG = 'Sort files before requiring them.'
|
40
56
|
|
@@ -49,7 +65,16 @@ module RuboCop
|
|
49
65
|
end
|
50
66
|
end
|
51
67
|
|
68
|
+
def on_block_pass(node)
|
69
|
+
return unless method_require?(node)
|
70
|
+
return unless unsorted_dir_pass?(node.parent)
|
71
|
+
|
72
|
+
add_offense(node.parent)
|
73
|
+
end
|
74
|
+
|
52
75
|
def autocorrect(node)
|
76
|
+
return correct_block_pass(node) if node.arguments.last&.block_pass_type?
|
77
|
+
|
53
78
|
if unsorted_dir_block?(node)
|
54
79
|
lambda do |corrector|
|
55
80
|
corrector.replace(node, "#{node.source}.sort.each")
|
@@ -64,10 +89,38 @@ module RuboCop
|
|
64
89
|
|
65
90
|
private
|
66
91
|
|
92
|
+
def correct_block_pass(node)
|
93
|
+
if unsorted_dir_glob_pass?(node)
|
94
|
+
lambda do |corrector|
|
95
|
+
block_arg = node.arguments.last
|
96
|
+
corrector.remove(last_arg_range(node))
|
97
|
+
corrector.insert_after(node, ".sort.each(#{block_arg.source})")
|
98
|
+
end
|
99
|
+
else
|
100
|
+
lambda do |corrector|
|
101
|
+
corrector.replace(node.loc.selector, 'sort.each')
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Returns range of last argument including comma and whitespace.
|
107
|
+
#
|
108
|
+
# @return [Parser::Source::Range]
|
109
|
+
#
|
110
|
+
def last_arg_range(node)
|
111
|
+
node.arguments.last.source_range.with(
|
112
|
+
begin_pos: node.arguments[-2].source_range.end_pos
|
113
|
+
)
|
114
|
+
end
|
115
|
+
|
67
116
|
def unsorted_dir_loop?(node)
|
68
117
|
unsorted_dir_block?(node) || unsorted_dir_each?(node)
|
69
118
|
end
|
70
119
|
|
120
|
+
def unsorted_dir_pass?(node)
|
121
|
+
unsorted_dir_glob_pass?(node) || unsorted_dir_each_pass?(node)
|
122
|
+
end
|
123
|
+
|
71
124
|
def_node_matcher :unsorted_dir_block?, <<~PATTERN
|
72
125
|
(send (const {nil? cbase} :Dir) :glob ...)
|
73
126
|
PATTERN
|
@@ -76,6 +129,20 @@ module RuboCop
|
|
76
129
|
(send (send (const {nil? cbase} :Dir) {:[] :glob} ...) :each)
|
77
130
|
PATTERN
|
78
131
|
|
132
|
+
def_node_matcher :method_require?, <<~PATTERN
|
133
|
+
(block-pass (send nil? :method (sym :require)))
|
134
|
+
PATTERN
|
135
|
+
|
136
|
+
def_node_matcher :unsorted_dir_glob_pass?, <<~PATTERN
|
137
|
+
(send (const {nil? cbase} :Dir) :glob ...
|
138
|
+
(block-pass (send nil? :method (sym :require))))
|
139
|
+
PATTERN
|
140
|
+
|
141
|
+
def_node_matcher :unsorted_dir_each_pass?, <<~PATTERN
|
142
|
+
(send (send (const {nil? cbase} :Dir) {:[] :glob} ...) :each
|
143
|
+
(block-pass (send nil? :method (sym :require))))
|
144
|
+
PATTERN
|
145
|
+
|
79
146
|
def_node_matcher :loop_variable, <<~PATTERN
|
80
147
|
(args (arg $_))
|
81
148
|
PATTERN
|