rubocop 0.55.0 → 0.56.0
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 +45 -0
- data/config/disabled.yml +4 -4
- data/config/enabled.yml +32 -16
- data/lib/rubocop.rb +8 -2
- data/lib/rubocop/cli.rb +4 -0
- data/lib/rubocop/comment_config.rb +36 -9
- data/lib/rubocop/config.rb +8 -1
- data/lib/rubocop/cop/generator.rb +4 -3
- data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +101 -29
- data/lib/rubocop/cop/{style → layout}/empty_line_after_guard_clause.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +5 -5
- data/lib/rubocop/cop/layout/first_parameter_indentation.rb +112 -2
- data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +8 -4
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +107 -0
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +4 -0
- data/lib/rubocop/cop/lint/nested_percent_literal.rb +0 -8
- data/lib/rubocop/cop/lint/percent_string_array.rb +1 -1
- data/lib/rubocop/cop/lint/percent_symbol_array.rb +1 -1
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +3 -0
- data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +16 -3
- data/lib/rubocop/cop/lint/splat_keyword_arguments.rb +36 -0
- data/lib/rubocop/cop/lint/unneeded_cop_enable_directive.rb +20 -2
- data/lib/rubocop/cop/performance/inefficient_hash_search.rb +95 -0
- data/lib/rubocop/cop/performance/unneeded_sort.rb +41 -6
- data/lib/rubocop/cop/rails/assert_not.rb +44 -0
- data/lib/rubocop/cop/rails/blank.rb +34 -28
- data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +1 -1
- data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +12 -2
- data/lib/rubocop/cop/rails/http_positional_arguments.rb +7 -7
- data/lib/rubocop/cop/rails/present.rb +31 -25
- data/lib/rubocop/cop/rails/refute_methods.rb +76 -0
- data/lib/rubocop/cop/rails/reversible_migration.rb +6 -4
- data/lib/rubocop/cop/rails/save_bang.rb +4 -1
- data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +1 -10
- data/lib/rubocop/cop/style/command_literal.rb +15 -3
- data/lib/rubocop/cop/style/comment_annotation.rb +6 -1
- data/lib/rubocop/cop/style/empty_method.rb +6 -3
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +12 -2
- data/lib/rubocop/cop/style/method_missing_super.rb +34 -0
- data/lib/rubocop/cop/style/{method_missing.rb → missing_respond_to_missing.rb} +7 -29
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +28 -2
- data/lib/rubocop/node_pattern.rb +1 -1
- data/lib/rubocop/processed_source.rb +12 -6
- data/lib/rubocop/result_cache.rb +9 -4
- data/lib/rubocop/rspec/shared_contexts.rb +4 -0
- data/lib/rubocop/runner.rb +8 -2
- data/lib/rubocop/target_finder.rb +40 -60
- data/lib/rubocop/version.rb +1 -1
- metadata +10 -4
@@ -6,12 +6,12 @@ module RuboCop
|
|
6
6
|
# This cop checks whether method definitions are
|
7
7
|
# separated by one empty line.
|
8
8
|
#
|
9
|
-
# `NumberOfEmptyLines` can be
|
10
|
-
# an array (e.g. [1, 2]) to
|
11
|
-
# empty lines.
|
9
|
+
# `NumberOfEmptyLines` can be an integer (default is 1) or
|
10
|
+
# an array (e.g. [1, 2]) to specify a minimum and maximum
|
11
|
+
# number of empty lines permitted.
|
12
12
|
#
|
13
|
-
# `AllowAdjacentOneLineDefs`
|
14
|
-
# one
|
13
|
+
# `AllowAdjacentOneLineDefs` configures whether adjacent
|
14
|
+
# one-line method definitions are considered an offense.
|
15
15
|
#
|
16
16
|
# @example
|
17
17
|
#
|
@@ -4,8 +4,8 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module Layout
|
6
6
|
# This cop checks the indentation of the first parameter in a method call.
|
7
|
-
# Parameters after the first one are checked by
|
8
|
-
# by this cop.
|
7
|
+
# Parameters after the first one are checked by Layout/AlignParameters,
|
8
|
+
# not by this cop.
|
9
9
|
#
|
10
10
|
# @example
|
11
11
|
#
|
@@ -14,10 +14,119 @@ module RuboCop
|
|
14
14
|
# first_param,
|
15
15
|
# second_param)
|
16
16
|
#
|
17
|
+
# foo = some_method(
|
18
|
+
# first_param,
|
19
|
+
# second_param)
|
20
|
+
#
|
21
|
+
# foo = some_method(nested_call(
|
22
|
+
# nested_first_param),
|
23
|
+
# second_param)
|
24
|
+
#
|
25
|
+
# foo = some_method(
|
26
|
+
# nested_call(
|
27
|
+
# nested_first_param),
|
28
|
+
# second_param)
|
29
|
+
#
|
30
|
+
# some_method nested_call(
|
31
|
+
# nested_first_param),
|
32
|
+
# second_param
|
33
|
+
#
|
34
|
+
# # Style: consistent
|
35
|
+
#
|
36
|
+
# # good
|
37
|
+
# some_method(
|
38
|
+
# first_param,
|
39
|
+
# second_param)
|
40
|
+
#
|
41
|
+
# foo = some_method(
|
42
|
+
# first_param,
|
43
|
+
# second_param)
|
44
|
+
#
|
45
|
+
# foo = some_method(nested_call(
|
46
|
+
# nested_first_param),
|
47
|
+
# second_param)
|
48
|
+
#
|
49
|
+
# foo = some_method(
|
50
|
+
# nested_call(
|
51
|
+
# nested_first_param),
|
52
|
+
# second_param)
|
53
|
+
#
|
54
|
+
# some_method nested_call(
|
55
|
+
# nested_first_param),
|
56
|
+
# second_param
|
57
|
+
#
|
58
|
+
# # Style: consistent_relative_to_receiver
|
59
|
+
#
|
17
60
|
# # good
|
18
61
|
# some_method(
|
19
62
|
# first_param,
|
20
63
|
# second_param)
|
64
|
+
#
|
65
|
+
# foo = some_method(
|
66
|
+
# first_param,
|
67
|
+
# second_param)
|
68
|
+
#
|
69
|
+
# foo = some_method(nested_call(
|
70
|
+
# nested_first_param),
|
71
|
+
# second_param)
|
72
|
+
#
|
73
|
+
# foo = some_method(
|
74
|
+
# nested_call(
|
75
|
+
# nested_first_param),
|
76
|
+
# second_param)
|
77
|
+
#
|
78
|
+
# some_method nested_call(
|
79
|
+
# nested_first_param),
|
80
|
+
# second_params
|
81
|
+
#
|
82
|
+
# # Style: special_for_inner_method_call
|
83
|
+
#
|
84
|
+
# # good
|
85
|
+
# some_method(
|
86
|
+
# first_param,
|
87
|
+
# second_param)
|
88
|
+
#
|
89
|
+
# foo = some_method(
|
90
|
+
# first_param,
|
91
|
+
# second_param)
|
92
|
+
#
|
93
|
+
# foo = some_method(nested_call(
|
94
|
+
# nested_first_param),
|
95
|
+
# second_param)
|
96
|
+
#
|
97
|
+
# foo = some_method(
|
98
|
+
# nested_call(
|
99
|
+
# nested_first_param),
|
100
|
+
# second_param)
|
101
|
+
#
|
102
|
+
# some_method nested_call(
|
103
|
+
# nested_first_param),
|
104
|
+
# second_param
|
105
|
+
#
|
106
|
+
# # Style: special_for_inner_method_call_in_parentheses
|
107
|
+
#
|
108
|
+
# # good
|
109
|
+
# some_method(
|
110
|
+
# first_param,
|
111
|
+
# second_param)
|
112
|
+
#
|
113
|
+
# foo = some_method(
|
114
|
+
# first_param,
|
115
|
+
# second_param)
|
116
|
+
#
|
117
|
+
# foo = some_method(nested_call(
|
118
|
+
# nested_first_param),
|
119
|
+
# second_param)
|
120
|
+
#
|
121
|
+
# foo = some_method(
|
122
|
+
# nested_call(
|
123
|
+
# nested_first_param),
|
124
|
+
# second_param)
|
125
|
+
#
|
126
|
+
# some_method nested_call(
|
127
|
+
# nested_first_param),
|
128
|
+
# second_param
|
129
|
+
#
|
21
130
|
class FirstParameterIndentation < Cop
|
22
131
|
include Alignment
|
23
132
|
include ConfigurableEnforcedStyle
|
@@ -65,6 +174,7 @@ module RuboCop
|
|
65
174
|
|
66
175
|
def special_inner_call_indentation?(node)
|
67
176
|
return false if style == :consistent
|
177
|
+
return true if style == :consistent_relative_to_receiver
|
68
178
|
|
69
179
|
parent = node.parent
|
70
180
|
|
@@ -66,7 +66,7 @@ module RuboCop
|
|
66
66
|
return if node.multiline?
|
67
67
|
return unless bracket_method?(node)
|
68
68
|
tokens = tokens(node)
|
69
|
-
left_token = left_ref_bracket(tokens)
|
69
|
+
left_token = left_ref_bracket(node, tokens)
|
70
70
|
return unless left_token
|
71
71
|
right_token = closing_bracket(tokens, left_token)
|
72
72
|
|
@@ -101,7 +101,7 @@ module RuboCop
|
|
101
101
|
|
102
102
|
def reference_brackets(node)
|
103
103
|
tokens = tokens(node)
|
104
|
-
left = left_ref_bracket(tokens)
|
104
|
+
left = left_ref_bracket(node, tokens)
|
105
105
|
[left, closing_bracket(tokens, left)]
|
106
106
|
end
|
107
107
|
|
@@ -110,8 +110,12 @@ module RuboCop
|
|
110
110
|
BRACKET_METHODS.include?(method)
|
111
111
|
end
|
112
112
|
|
113
|
-
def left_ref_bracket(tokens)
|
114
|
-
|
113
|
+
def left_ref_bracket(node, tokens)
|
114
|
+
if node.method?(:[]=)
|
115
|
+
tokens.find(&:left_ref_bracket?)
|
116
|
+
else
|
117
|
+
tokens.reverse.find(&:left_ref_bracket?)
|
118
|
+
end
|
115
119
|
end
|
116
120
|
|
117
121
|
def closing_bracket(tokens, opening_bracket)
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
#
|
7
|
+
# This cop emulates the following Ruby warnings in Ruby 2.6.
|
8
|
+
#
|
9
|
+
# % cat example.rb
|
10
|
+
# ERB.new('hi', nil, '-', '@output_buffer')
|
11
|
+
# % ruby -rerb example.rb
|
12
|
+
# example.rb:1: warning: Passing safe_level with the 2nd argument of
|
13
|
+
# ERB.new is deprecated. Do not use it, and specify other arguments as
|
14
|
+
# keyword arguments.
|
15
|
+
# example.rb:1: warning: Passing trim_mode with the 3rd argument of
|
16
|
+
# ERB.new is deprecated. Use keyword argument like
|
17
|
+
# ERB.new(str, trim_mode:...) instead.
|
18
|
+
# example.rb:1: warning: Passing eoutvar with the 4th argument of ERB.new
|
19
|
+
# is deprecated. Use keyword argument like ERB.new(str, eoutvar: ...)
|
20
|
+
# instead.
|
21
|
+
#
|
22
|
+
# Now non-keyword arguments other than first one are softly deprecated
|
23
|
+
# and will be removed when Ruby 2.5 becomes EOL.
|
24
|
+
# `ERB.new` with non-keyword arguments is deprecated since ERB 2.2.0.
|
25
|
+
# Use `:trim_mode` and `:eoutvar` keyword arguments to `ERB.new`.
|
26
|
+
# This cop identifies places where `ERB.new(str, trim_mode, eoutvar)` can
|
27
|
+
# be replaced by `ERB.new(str, :trim_mode: trim_mode, eoutvar: eoutvar)`.
|
28
|
+
#
|
29
|
+
# @example
|
30
|
+
# # Target codes supports Ruby 2.6 and higher only
|
31
|
+
# # bad
|
32
|
+
# ERB.new(str, nil, '-', '@output_buffer')
|
33
|
+
#
|
34
|
+
# # good
|
35
|
+
# ERB.new(str, trim_mode: '-', eoutvar: '@output_buffer')
|
36
|
+
#
|
37
|
+
# # Target codes supports Ruby 2.5 and lower only
|
38
|
+
# # good
|
39
|
+
# ERB.new(str, nil, '-', '@output_buffer')
|
40
|
+
#
|
41
|
+
# # Target codes supports Ruby 2.6, 2.5 and lower
|
42
|
+
# # bad
|
43
|
+
# ERB.new(str, nil, '-', '@output_buffer')
|
44
|
+
#
|
45
|
+
# # good
|
46
|
+
# # Ruby standard library style
|
47
|
+
# # https://github.com/ruby/ruby/commit/3406c5d
|
48
|
+
# if ERB.instance_method(:initialize).parameters.assoc(:key) # Ruby 2.6+
|
49
|
+
# ERB.new(str, trim_mode: '-', eoutvar: '@output_buffer')
|
50
|
+
# else
|
51
|
+
# ERB.new(str, nil, '-', '@output_buffer')
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
# # good
|
55
|
+
# # Use `RUBY_VERSION` style
|
56
|
+
# if RUBY_VERSION >= '2.6'
|
57
|
+
# ERB.new(str, trim_mode: '-', eoutvar: '@output_buffer')
|
58
|
+
# else
|
59
|
+
# ERB.new(str, nil, '-', '@output_buffer')
|
60
|
+
# end
|
61
|
+
#
|
62
|
+
class ErbNewArguments < Cop
|
63
|
+
extend TargetRubyVersion
|
64
|
+
|
65
|
+
minimum_target_ruby_version 2.6
|
66
|
+
|
67
|
+
MESSAGES = [
|
68
|
+
'Passing safe_level with the 2nd argument of `ERB.new` is ' \
|
69
|
+
'deprecated. Do not use it, and specify other arguments as ' \
|
70
|
+
'keyword arguments.',
|
71
|
+
'Passing trim_mode with the 3rd argument of `ERB.new` is ' \
|
72
|
+
'deprecated. Use keyword argument like ' \
|
73
|
+
'`ERB.new(str, trim_mode: %<arg_value>s)` instead.',
|
74
|
+
'Passing eoutvar with the 4th argument of `ERB.new` is ' \
|
75
|
+
'deprecated. Use keyword argument like ' \
|
76
|
+
'`ERB.new(str, eoutvar: %<arg_value>s)` instead.'
|
77
|
+
].freeze
|
78
|
+
|
79
|
+
def_node_matcher :erb_new_with_non_keyword_arguments, <<-PATTERN
|
80
|
+
(send
|
81
|
+
(const {nil? cbase} :ERB) :new $...)
|
82
|
+
PATTERN
|
83
|
+
|
84
|
+
def on_send(node)
|
85
|
+
erb_new_with_non_keyword_arguments(node) do |arguments|
|
86
|
+
return if correct_arguments?(arguments)
|
87
|
+
|
88
|
+
1.upto(3) do |i|
|
89
|
+
next if !arguments[i] || arguments[i].hash_type?
|
90
|
+
|
91
|
+
message = format(MESSAGES[i - 1], arg_value: arguments[i].source)
|
92
|
+
|
93
|
+
add_offense(
|
94
|
+
node, location: arguments[i].source_range, message: message
|
95
|
+
)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def correct_arguments?(arguments)
|
101
|
+
arguments.size == 1 ||
|
102
|
+
arguments.size == 2 && arguments[1].hash_type?
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -38,14 +38,6 @@ module RuboCop
|
|
38
38
|
|
39
39
|
private
|
40
40
|
|
41
|
-
def str_content(node)
|
42
|
-
if node.str_type?
|
43
|
-
node.children[0]
|
44
|
-
else
|
45
|
-
node.children.map { |c| str_content(c) }.join
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
41
|
def contains_percent_literals?(node)
|
50
42
|
node.each_child_node.any? do |child|
|
51
43
|
literal = child.children.first.to_s.scrub
|
@@ -62,7 +62,7 @@ module RuboCop
|
|
62
62
|
literal = value.children.first.to_s.scrub
|
63
63
|
|
64
64
|
# To avoid likely false positives (e.g. a single ' or ")
|
65
|
-
next if literal.gsub(/[
|
65
|
+
next if literal.gsub(/[^[[:alnum:]]]/, '').empty?
|
66
66
|
|
67
67
|
QUOTES_AND_COMMAS.any? { |pat| literal =~ pat }
|
68
68
|
end
|
@@ -55,7 +55,7 @@ module RuboCop
|
|
55
55
|
literal = child.children.first
|
56
56
|
|
57
57
|
# To avoid likely false positives (e.g. a single ' or ")
|
58
|
-
next if literal.to_s.gsub(/[
|
58
|
+
next if literal.to_s.gsub(/[^[[:alnum:]]]/, '').empty?
|
59
59
|
|
60
60
|
patterns.any? { |pat| literal =~ pat }
|
61
61
|
end
|
@@ -27,6 +27,9 @@ module RuboCop
|
|
27
27
|
# foo&.bar && (foobar.baz || foo&.baz)
|
28
28
|
#
|
29
29
|
class SafeNavigationConsistency < Cop
|
30
|
+
include IgnoredNode
|
31
|
+
include NilMethods
|
32
|
+
|
30
33
|
MSG = 'Ensure that safe navigation is used consistently ' \
|
31
34
|
'inside of `&&` and `||`.'.freeze
|
32
35
|
|
@@ -42,15 +45,16 @@ module RuboCop
|
|
42
45
|
safe_nav_receiver = node.receiver
|
43
46
|
|
44
47
|
method_calls = conditions.select(&:send_type?)
|
45
|
-
unsafe_method_calls =
|
46
|
-
safe_nav_receiver
|
47
|
-
end
|
48
|
+
unsafe_method_calls =
|
49
|
+
unsafe_method_calls(method_calls, safe_nav_receiver)
|
48
50
|
|
49
51
|
unsafe_method_calls.each do |unsafe_method_call|
|
50
52
|
location =
|
51
53
|
node.loc.expression.join(unsafe_method_call.loc.expression)
|
52
54
|
add_offense(unsafe_method_call,
|
53
55
|
location: location)
|
56
|
+
|
57
|
+
ignore_node(unsafe_method_call)
|
54
58
|
end
|
55
59
|
end
|
56
60
|
|
@@ -69,11 +73,20 @@ module RuboCop
|
|
69
73
|
unless parent &&
|
70
74
|
(AST::Node::OPERATOR_KEYWORDS.include?(parent.type) ||
|
71
75
|
(parent.begin_type? &&
|
76
|
+
parent.parent &&
|
72
77
|
AST::Node::OPERATOR_KEYWORDS.include?(parent.parent.type)))
|
73
78
|
return node
|
74
79
|
end
|
75
80
|
top_conditional_ancestor(parent)
|
76
81
|
end
|
82
|
+
|
83
|
+
def unsafe_method_calls(method_calls, safe_nav_receiver)
|
84
|
+
method_calls.select do |method_call|
|
85
|
+
safe_nav_receiver == method_call.receiver &&
|
86
|
+
!nil_methods.include?(method_call.method_name) &&
|
87
|
+
!ignored_node?(method_call)
|
88
|
+
end
|
89
|
+
end
|
77
90
|
end
|
78
91
|
end
|
79
92
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
#
|
7
|
+
# This cop emulates the following Ruby warnings in Ruby 2.6.
|
8
|
+
#
|
9
|
+
# % ruby -we "def m(a) end; h = {foo: 1}; m(**h)"
|
10
|
+
# -e:1: warning: passing splat keyword arguments as a single Hash to `m'
|
11
|
+
#
|
12
|
+
# It checks for use of splat keyword arguments as a single Hash.
|
13
|
+
#
|
14
|
+
# @example
|
15
|
+
# # bad
|
16
|
+
# do_something(**arguments)
|
17
|
+
#
|
18
|
+
# # good
|
19
|
+
# do_something(arguments)
|
20
|
+
#
|
21
|
+
class SplatKeywordArguments < Cop
|
22
|
+
MSG = 'Do not use splat keyword arguments as a single Hash.'.freeze
|
23
|
+
|
24
|
+
def on_send(node)
|
25
|
+
node.arguments.each do |argument|
|
26
|
+
next unless argument.hash_type?
|
27
|
+
|
28
|
+
argument.children.each do |element|
|
29
|
+
add_offense(element) if element.kwsplat_type?
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|