rubocop 0.41.2 → 0.42.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.
Potentially problematic release.
This version of rubocop might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +2 -3
- data/config/default.yml +13 -0
- data/config/disabled.yml +5 -0
- data/config/enabled.yml +20 -0
- data/lib/rubocop.rb +4 -0
- data/lib/rubocop/ast_node.rb +4 -3
- data/lib/rubocop/config.rb +1 -1
- data/lib/rubocop/config_loader.rb +2 -7
- data/lib/rubocop/cop/cop.rb +3 -3
- data/lib/rubocop/cop/lint/block_alignment.rb +18 -16
- data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +34 -19
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +9 -1
- data/lib/rubocop/cop/lint/shadowed_exception.rb +23 -3
- data/lib/rubocop/cop/lint/unneeded_disable.rb +1 -1
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +41 -4
- data/lib/rubocop/cop/mixin/array_hash_indentation.rb +1 -1
- data/lib/rubocop/cop/mixin/autocorrect_alignment.rb +1 -1
- data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +3 -5
- data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +4 -4
- data/lib/rubocop/cop/mixin/space_inside.rb +23 -8
- data/lib/rubocop/cop/mixin/statement_modifier.rb +1 -1
- data/lib/rubocop/cop/offense.rb +33 -10
- data/lib/rubocop/cop/performance/case_when_splat.rb +16 -14
- data/lib/rubocop/cop/performance/sample.rb +0 -1
- data/lib/rubocop/cop/rails/save_bang.rb +77 -0
- data/lib/rubocop/cop/rails/validation.rb +15 -15
- data/lib/rubocop/cop/style/access_modifier_indentation.rb +1 -1
- data/lib/rubocop/cop/style/align_hash.rb +1 -1
- data/lib/rubocop/cop/style/block_comments.rb +1 -3
- data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +19 -10
- data/lib/rubocop/cop/style/closing_parenthesis_indentation.rb +1 -1
- data/lib/rubocop/cop/style/comment_annotation.rb +14 -14
- data/lib/rubocop/cop/style/comment_indentation.rb +1 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +25 -26
- data/lib/rubocop/cop/style/dot_position.rb +24 -19
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +22 -8
- data/lib/rubocop/cop/style/each_with_object.rb +11 -1
- data/lib/rubocop/cop/style/else_alignment.rb +1 -1
- data/lib/rubocop/cop/style/empty_lines.rb +22 -11
- data/lib/rubocop/cop/style/empty_lines_around_access_modifier.rb +9 -6
- data/lib/rubocop/cop/style/empty_lines_around_block_body.rb +14 -14
- data/lib/rubocop/cop/style/empty_lines_around_class_body.rb +8 -5
- data/lib/rubocop/cop/style/empty_lines_around_method_body.rb +12 -8
- data/lib/rubocop/cop/style/empty_lines_around_module_body.rb +17 -4
- data/lib/rubocop/cop/style/empty_literal.rb +12 -7
- data/lib/rubocop/cop/style/for.rb +1 -1
- data/lib/rubocop/cop/style/indent_array.rb +1 -1
- data/lib/rubocop/cop/style/indent_hash.rb +1 -1
- data/lib/rubocop/cop/style/indentation_width.rb +1 -1
- data/lib/rubocop/cop/style/initial_indentation.rb +1 -1
- data/lib/rubocop/cop/style/lambda.rb +2 -3
- data/lib/rubocop/cop/style/method_call_parentheses.rb +6 -4
- data/lib/rubocop/cop/style/method_missing.rb +74 -0
- data/lib/rubocop/cop/style/multiline_method_call_indentation.rb +1 -1
- data/lib/rubocop/cop/style/multiline_operation_indentation.rb +1 -1
- data/lib/rubocop/cop/style/nested_modifier.rb +23 -13
- data/lib/rubocop/cop/style/next.rb +1 -1
- data/lib/rubocop/cop/style/numeric_predicate.rb +142 -0
- data/lib/rubocop/cop/style/op_method.rb +12 -4
- data/lib/rubocop/cop/style/parallel_assignment.rb +11 -3
- data/lib/rubocop/cop/style/rescue_ensure_alignment.rb +9 -6
- data/lib/rubocop/cop/style/single_line_block_params.rb +3 -2
- data/lib/rubocop/cop/style/space_inside_block_braces.rb +1 -1
- data/lib/rubocop/cop/style/space_inside_string_interpolation.rb +1 -1
- data/lib/rubocop/cop/style/symbol_array.rb +18 -10
- data/lib/rubocop/cop/style/ternary_parentheses.rb +94 -0
- data/lib/rubocop/cop/style/trailing_blank_lines.rb +1 -1
- data/lib/rubocop/cop/style/unneeded_percent_q.rb +12 -6
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/cop/variable_force/assignment.rb +1 -1
- data/lib/rubocop/cop/variable_force/locatable.rb +1 -1
- data/lib/rubocop/formatter/disabled_config_formatter.rb +18 -7
- data/lib/rubocop/formatter/html_formatter.rb +25 -11
- data/lib/rubocop/formatter/text_util.rb +1 -1
- data/lib/rubocop/node_pattern.rb +2 -0
- data/lib/rubocop/processed_source.rb +3 -0
- data/lib/rubocop/rake_task.rb +1 -1
- data/lib/rubocop/rspec/shared_contexts.rb +4 -0
- data/lib/rubocop/runner.rb +18 -7
- data/lib/rubocop/string_util.rb +2 -5
- data/lib/rubocop/version.rb +1 -1
- metadata +7 -3
@@ -4,15 +4,23 @@
|
|
4
4
|
module RuboCop
|
5
5
|
module Cop
|
6
6
|
module Style
|
7
|
-
# This cop makes sure that certain operator methods have their
|
8
|
-
# parameter named `other`.
|
7
|
+
# This cop makes sure that certain binary operator methods have their
|
8
|
+
# sole parameter named `other`.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
#
|
12
|
+
# # bad
|
13
|
+
# def +(amount); end
|
14
|
+
#
|
15
|
+
# # good
|
16
|
+
# def +(other); end
|
9
17
|
class OpMethod < Cop
|
10
18
|
MSG = 'When defining the `%s` operator, ' \
|
11
19
|
'name its argument `other`.'.freeze
|
12
20
|
|
13
21
|
OP_LIKE_METHODS = [:eql?, :equal?].freeze
|
14
22
|
|
15
|
-
BLACKLISTED = [:+@, :-@, :[], :[]=,
|
23
|
+
BLACKLISTED = [:+@, :-@, :[], :[]=, :<<, :`].freeze
|
16
24
|
|
17
25
|
TARGET_ARGS = [s(:args, s(:arg, :other)),
|
18
26
|
s(:args, s(:arg, :_other))].freeze
|
@@ -20,7 +28,7 @@ module RuboCop
|
|
20
28
|
def on_def(node)
|
21
29
|
name, args, _body = *node
|
22
30
|
return unless op_method?(name) &&
|
23
|
-
args.children.
|
31
|
+
args.children.one? &&
|
24
32
|
!TARGET_ARGS.include?(args)
|
25
33
|
|
26
34
|
add_offense(args.children[0], :expression, format(MSG, name))
|
@@ -179,13 +179,21 @@ module RuboCop
|
|
179
179
|
protected
|
180
180
|
|
181
181
|
def assignment
|
182
|
-
@new_elements.map
|
183
|
-
"#{lhs.source} = #{rhs.source}"
|
184
|
-
end
|
182
|
+
@new_elements.map { |lhs, rhs| "#{lhs.source} = #{source(rhs)}" }
|
185
183
|
end
|
186
184
|
|
187
185
|
private
|
188
186
|
|
187
|
+
def source(node)
|
188
|
+
if node.str_type? && node.loc.begin.nil?
|
189
|
+
"'#{node.source}'"
|
190
|
+
elsif node.sym_type? && node.loc.begin.nil?
|
191
|
+
":#{node.source}"
|
192
|
+
else
|
193
|
+
node.source
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
189
197
|
def extract_sources(node)
|
190
198
|
node.children.map(&:source)
|
191
199
|
end
|
@@ -58,14 +58,17 @@ module RuboCop
|
|
58
58
|
|
59
59
|
def check(node)
|
60
60
|
end_loc = ancestor_node(node).loc.end
|
61
|
-
return if end_loc.column == node.loc.keyword.column
|
62
|
-
return if end_loc.line == node.loc.keyword.line
|
63
|
-
|
64
61
|
kw_loc = node.loc.keyword
|
65
62
|
|
66
|
-
|
67
|
-
|
68
|
-
|
63
|
+
return if end_loc.column == kw_loc.column
|
64
|
+
return if end_loc.line == kw_loc.line
|
65
|
+
|
66
|
+
add_offense(node, kw_loc, format_message(kw_loc, end_loc))
|
67
|
+
end
|
68
|
+
|
69
|
+
def format_message(kw_loc, end_loc)
|
70
|
+
format(MSG, kw_loc.source, kw_loc.line, kw_loc.column, end_loc.line,
|
71
|
+
end_loc.column)
|
69
72
|
end
|
70
73
|
|
71
74
|
def modifier?(node)
|
@@ -12,7 +12,7 @@ module RuboCop
|
|
12
12
|
class SingleLineBlockParams < Cop
|
13
13
|
def on_block(node)
|
14
14
|
# we care only for single line blocks
|
15
|
-
return unless block_length(node)
|
15
|
+
return unless block_length(node).zero?
|
16
16
|
|
17
17
|
method_node, args_node, _body_node = *node
|
18
18
|
receiver, method_name, _method_args = *method_node
|
@@ -21,9 +21,10 @@ module RuboCop
|
|
21
21
|
return unless receiver
|
22
22
|
return unless method_names.include?(method_name)
|
23
23
|
|
24
|
-
# discard cases with argument destructuring
|
25
24
|
args = *args_node
|
26
25
|
|
26
|
+
return if args.empty?
|
27
|
+
# discard cases with argument destructuring
|
27
28
|
return true unless args.all? { |n| n.type == :arg }
|
28
29
|
return if args_match?(method_name, args)
|
29
30
|
|
@@ -70,7 +70,7 @@ module RuboCop
|
|
70
70
|
space_inside_left_brace(left_brace, args_delimiter, sb)
|
71
71
|
end
|
72
72
|
|
73
|
-
if inner =~ /\S$/ && block_length(node)
|
73
|
+
if inner =~ /\S$/ && block_length(node).zero?
|
74
74
|
no_space(sb, right_brace.begin_pos, right_brace.end_pos,
|
75
75
|
'Space missing inside }.')
|
76
76
|
else
|
@@ -40,7 +40,7 @@ module RuboCop
|
|
40
40
|
private
|
41
41
|
|
42
42
|
def autocorrect(node)
|
43
|
-
new_source =
|
43
|
+
new_source = style == :no_space ? node.source : " #{node.source} "
|
44
44
|
lambda do |corrector|
|
45
45
|
corrector.replace(range_with_surrounding_space(node.source_range),
|
46
46
|
new_source)
|
@@ -76,23 +76,31 @@ module RuboCop
|
|
76
76
|
def autocorrect(node)
|
77
77
|
syms = node.children.map { |c| c.children[0].to_s }
|
78
78
|
corrected = if style == :percent
|
79
|
-
|
80
|
-
syms = syms.map { |s| escape_string(s) } if escape
|
81
|
-
syms = syms.map { |s| s.gsub(/\)/, '\\)') }
|
82
|
-
if escape
|
83
|
-
"%I(#{syms.join(' ')})"
|
84
|
-
else
|
85
|
-
"%i(#{syms.join(' ')})"
|
86
|
-
end
|
79
|
+
percent_replacement(syms)
|
87
80
|
else
|
88
|
-
syms
|
89
|
-
"[#{syms.join(', ')}]"
|
81
|
+
bracket_replacement(syms)
|
90
82
|
end
|
91
83
|
|
92
84
|
lambda do |corrector|
|
93
85
|
corrector.replace(node.source_range, corrected)
|
94
86
|
end
|
95
87
|
end
|
88
|
+
|
89
|
+
def percent_replacement(syms)
|
90
|
+
escape = syms.any? { |s| needs_escaping?(s) }
|
91
|
+
syms = syms.map { |s| escape_string(s) } if escape
|
92
|
+
syms = syms.map { |s| s.gsub(/\)/, '\\)') }
|
93
|
+
if escape
|
94
|
+
"%I(#{syms.join(' ')})"
|
95
|
+
else
|
96
|
+
"%i(#{syms.join(' ')})"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def bracket_replacement(syms)
|
101
|
+
syms = syms.map { |s| to_symbol_literal(s) }
|
102
|
+
"[#{syms.join(', ')}]"
|
103
|
+
end
|
96
104
|
end
|
97
105
|
end
|
98
106
|
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RuboCop
|
5
|
+
module Cop
|
6
|
+
module Style
|
7
|
+
# This cop checks for the presence of arentheses around ternary
|
8
|
+
# conditions. It is configurable to enforce inclusion or omission of
|
9
|
+
# parentheses using `EnforcedStyle`.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
#
|
13
|
+
# EnforcedStyle: require_no_parentheses (deafault)
|
14
|
+
#
|
15
|
+
# @bad
|
16
|
+
# foo = (bar?) ? a : b
|
17
|
+
# foo = (bar.baz) ? a : b
|
18
|
+
# foo = (bar && baz) ? a : b
|
19
|
+
#
|
20
|
+
# @good
|
21
|
+
# foo = bar? ? a : b
|
22
|
+
# foo = bar.baz? ? a : b
|
23
|
+
# foo = bar && baz ? a : b
|
24
|
+
#
|
25
|
+
# @example
|
26
|
+
#
|
27
|
+
# EnforcedStyle: require_parentheses
|
28
|
+
#
|
29
|
+
# @bad
|
30
|
+
# foo = bar? ? a : b
|
31
|
+
# foo = bar.baz? ? a : b
|
32
|
+
# foo = bar && baz ? a : b
|
33
|
+
#
|
34
|
+
# @good
|
35
|
+
# foo = (bar?) ? a : b
|
36
|
+
# foo = (bar.baz) ? a : b
|
37
|
+
# foo = (bar && baz) ? a : b
|
38
|
+
class TernaryParentheses < Cop
|
39
|
+
include IfNode
|
40
|
+
include SafeAssignment
|
41
|
+
include ConfigurableEnforcedStyle
|
42
|
+
|
43
|
+
MSG = '%s parentheses for ternary conditions.'.freeze
|
44
|
+
|
45
|
+
def on_if(node)
|
46
|
+
return unless ternary?(node)
|
47
|
+
|
48
|
+
add_offense(node, node.source_range, message) if offense?(node)
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def offense?(node)
|
54
|
+
condition, = *node
|
55
|
+
|
56
|
+
(require_parentheses? && !parenthesized?(condition) ||
|
57
|
+
!require_parentheses? && parenthesized?(condition)) &&
|
58
|
+
!(safe_assignment?(condition) && safe_assignment_allowed?)
|
59
|
+
end
|
60
|
+
|
61
|
+
def autocorrect(node)
|
62
|
+
condition, = *node
|
63
|
+
|
64
|
+
lambda do |corrector|
|
65
|
+
if require_parentheses?
|
66
|
+
corrector.insert_before(condition.source_range, '(')
|
67
|
+
corrector.insert_after(condition.source_range, ')')
|
68
|
+
else
|
69
|
+
# Don't correct if it's a safe assignment
|
70
|
+
unless safe_assignment?(condition)
|
71
|
+
corrector.remove(condition.loc.begin)
|
72
|
+
corrector.remove(condition.loc.end)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def message
|
79
|
+
verb = require_parentheses? ? 'Use' : 'Omit'
|
80
|
+
|
81
|
+
format(MSG, verb)
|
82
|
+
end
|
83
|
+
|
84
|
+
def require_parentheses?
|
85
|
+
style == :require_parentheses
|
86
|
+
end
|
87
|
+
|
88
|
+
def parenthesized?(node)
|
89
|
+
node.source =~ /^\(.*\)$/
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -16,6 +16,7 @@ module RuboCop
|
|
16
16
|
PERCENT_Q = '%q'.freeze
|
17
17
|
PERCENT_CAPITAL_Q = '%Q'.freeze
|
18
18
|
STRING_INTERPOLATION_REGEXP = /#\{.+}/
|
19
|
+
ESCAPED_NON_BACKSLASH = /\\[^\\]/
|
19
20
|
|
20
21
|
def on_dstr(node)
|
21
22
|
check(node)
|
@@ -35,12 +36,9 @@ module RuboCop
|
|
35
36
|
src = node.source
|
36
37
|
return unless start_with_percent_q_variant?(src)
|
37
38
|
return if src.include?(SINGLE_QUOTE) && src.include?(QUOTE)
|
38
|
-
if src.start_with?(PERCENT_Q) &&
|
39
|
-
|
40
|
-
|
41
|
-
if src.start_with?(PERCENT_CAPITAL_Q) && acceptable_capital_q?(node)
|
42
|
-
return
|
43
|
-
end
|
39
|
+
return if src.start_with?(PERCENT_Q) && acceptable_q?(node)
|
40
|
+
return if src.start_with?(PERCENT_CAPITAL_Q) &&
|
41
|
+
acceptable_capital_q?(node)
|
44
42
|
|
45
43
|
add_offense(node, :expression)
|
46
44
|
end
|
@@ -73,6 +71,14 @@ module RuboCop
|
|
73
71
|
string.start_with?(PERCENT_Q, PERCENT_CAPITAL_Q)
|
74
72
|
end
|
75
73
|
|
74
|
+
def acceptable_q?(node)
|
75
|
+
src = node.source
|
76
|
+
|
77
|
+
return true if src =~ STRING_INTERPOLATION_REGEXP
|
78
|
+
|
79
|
+
src.scan(/\\./).any? { |s| s =~ ESCAPED_NON_BACKSLASH }
|
80
|
+
end
|
81
|
+
|
76
82
|
def acceptable_capital_q?(node)
|
77
83
|
src = node.source
|
78
84
|
src.include?(QUOTE) &&
|
data/lib/rubocop/cop/util.rb
CHANGED
@@ -79,7 +79,7 @@ module RuboCop
|
|
79
79
|
def operator_assignment_node
|
80
80
|
return nil unless node.parent
|
81
81
|
return nil unless OPERATOR_ASSIGNMENT_TYPES.include?(node.parent.type)
|
82
|
-
return nil unless node.
|
82
|
+
return nil unless node.sibling_index.zero?
|
83
83
|
node.parent
|
84
84
|
end
|
85
85
|
|
@@ -60,6 +60,8 @@ module RuboCop
|
|
60
60
|
"#{output.path}` in a .rubocop.yml file."
|
61
61
|
end
|
62
62
|
|
63
|
+
private
|
64
|
+
|
63
65
|
def command
|
64
66
|
command = 'rubocop --auto-gen-config'
|
65
67
|
if @exclude_limit_option
|
@@ -89,14 +91,22 @@ module RuboCop
|
|
89
91
|
output.puts '# Cop supports --auto-correct.'
|
90
92
|
end
|
91
93
|
|
92
|
-
default_cfg =
|
94
|
+
default_cfg = default_config(cop_name)
|
93
95
|
return unless default_cfg
|
94
96
|
|
95
|
-
params = default_cfg
|
96
|
-
%w(Description StyleGuide Reference Enabled Exclude) -
|
97
|
-
cfg.keys
|
97
|
+
params = cop_config_params(default_cfg, cfg)
|
98
98
|
return if params.empty?
|
99
99
|
|
100
|
+
output_cop_param_comments(params, default_cfg)
|
101
|
+
end
|
102
|
+
|
103
|
+
def cop_config_params(default_cfg, cfg)
|
104
|
+
default_cfg.keys -
|
105
|
+
%w(Description StyleGuide Reference Enabled Exclude) -
|
106
|
+
cfg.keys
|
107
|
+
end
|
108
|
+
|
109
|
+
def output_cop_param_comments(params, default_cfg)
|
100
110
|
output.puts "# Configuration parameters: #{params.join(', ')}."
|
101
111
|
|
102
112
|
params.each do |param|
|
@@ -108,6 +118,10 @@ module RuboCop
|
|
108
118
|
end
|
109
119
|
end
|
110
120
|
|
121
|
+
def default_config(cop_name)
|
122
|
+
RuboCop::ConfigLoader.default_configuration[cop_name]
|
123
|
+
end
|
124
|
+
|
111
125
|
def output_cop_config(output, cfg, cop_name)
|
112
126
|
# 'Enabled' option will be put into file only if exclude
|
113
127
|
# limit is exceeded.
|
@@ -156,9 +170,6 @@ module RuboCop
|
|
156
170
|
output.puts " - '#{file}'"
|
157
171
|
end
|
158
172
|
end
|
159
|
-
rescue LoadError
|
160
|
-
# Fallback to Enabled: false for Ruby < 1.9.3
|
161
|
-
output.puts ' Enabled: false'
|
162
173
|
end
|
163
174
|
end
|
164
175
|
end
|
@@ -94,20 +94,34 @@ module RuboCop
|
|
94
94
|
end
|
95
95
|
|
96
96
|
def highlighted_source_line(offense)
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
(
|
97
|
+
source_before_highlight(offense) +
|
98
|
+
hightlight_source_tag(offense) +
|
99
|
+
source_after_highlight(offense) +
|
100
|
+
possible_ellipses(offense.location)
|
101
|
+
end
|
102
|
+
|
103
|
+
def hightlight_source_tag(offense)
|
104
|
+
"<span class=\"highlight #{offense.severity}\">" \
|
105
|
+
"#{escape(offense.highlighted_area.source)}" \
|
106
|
+
'</span>'
|
107
|
+
end
|
108
|
+
|
109
|
+
def source_before_highlight(offense)
|
110
|
+
source_line = offense.location.source_line
|
111
|
+
escape(source_line[0...offense.highlighted_area.begin_pos])
|
112
|
+
end
|
113
|
+
|
114
|
+
def source_after_highlight(offense)
|
115
|
+
source_line = offense.location.source_line
|
116
|
+
escape(source_line[offense.highlighted_area.end_pos..-1])
|
117
|
+
end
|
118
|
+
|
119
|
+
def possible_ellipses(location)
|
120
|
+
location.first_line == location.last_line ? '' : " #{ELLIPSES}"
|
106
121
|
end
|
107
122
|
|
108
123
|
def escape(s)
|
109
|
-
|
110
|
-
CGI.escapeHTML(s).gsub(/'/, ''')
|
124
|
+
CGI.escapeHTML(s)
|
111
125
|
end
|
112
126
|
|
113
127
|
def base64_encoded_logo_image
|