rubocop 0.80.1 → 0.81.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 +62 -15
- data/lib/rubocop.rb +4 -1
- data/lib/rubocop/ast/builder.rb +2 -0
- data/lib/rubocop/ast/node.rb +11 -6
- data/lib/rubocop/ast/node/block_node.rb +5 -1
- data/lib/rubocop/ast/node/case_match_node.rb +56 -0
- data/lib/rubocop/ast/traversal.rb +11 -9
- data/lib/rubocop/config_obsoletion.rb +1 -0
- data/lib/rubocop/cop/layout/array_alignment.rb +53 -10
- data/lib/rubocop/cop/layout/block_end_newline.rb +5 -3
- data/lib/rubocop/cop/layout/else_alignment.rb +8 -0
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +1 -1
- data/lib/rubocop/cop/lint/boolean_symbol.rb +12 -0
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -1
- data/lib/rubocop/cop/lint/loop.rb +6 -4
- data/lib/rubocop/cop/lint/nested_method_definition.rb +2 -2
- data/lib/rubocop/cop/lint/raise_exception.rb +39 -0
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +1 -1
- data/lib/rubocop/cop/lint/struct_new_override.rb +58 -0
- data/lib/rubocop/cop/lint/suppressed_exception.rb +12 -22
- data/lib/rubocop/cop/lint/unused_method_argument.rb +32 -6
- data/lib/rubocop/cop/migration/department_name.rb +22 -9
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +6 -1
- data/lib/rubocop/cop/mixin/method_complexity.rb +5 -0
- data/lib/rubocop/cop/naming/method_name.rb +30 -0
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +26 -6
- data/lib/rubocop/cop/style/collection_methods.rb +2 -0
- data/lib/rubocop/cop/style/documentation.rb +43 -5
- data/lib/rubocop/cop/style/end_block.rb +6 -0
- data/lib/rubocop/cop/style/hash_each_methods.rb +2 -0
- data/lib/rubocop/cop/style/hash_transform_keys.rb +6 -2
- data/lib/rubocop/cop/style/hash_transform_values.rb +6 -2
- data/lib/rubocop/cop/style/inverse_methods.rb +1 -1
- data/lib/rubocop/cop/style/lambda.rb +1 -0
- data/lib/rubocop/cop/style/module_function.rb +56 -10
- data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +2 -2
- data/lib/rubocop/cop/style/one_line_conditional.rb +3 -2
- data/lib/rubocop/cop/style/redundant_sort.rb +2 -2
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +34 -0
- data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +41 -0
- data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +85 -0
- data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +44 -0
- data/lib/rubocop/formatter/clang_style_formatter.rb +1 -1
- data/lib/rubocop/formatter/junit_formatter.rb +17 -6
- data/lib/rubocop/formatter/tap_formatter.rb +1 -1
- data/lib/rubocop/processed_source.rb +1 -1
- data/lib/rubocop/version.rb +1 -1
- metadata +8 -5
- data/lib/rubocop/cop/lint/end_in_method.rb +0 -40
@@ -19,6 +19,7 @@ module RuboCop
|
|
19
19
|
'Layout/LeadingBlankLines' => 'Layout/LeadingEmptyLines',
|
20
20
|
'Layout/TrailingBlankLines' => 'Layout/TrailingEmptyLines',
|
21
21
|
'Lint/DuplicatedKey' => 'Lint/DuplicateHashKey',
|
22
|
+
'Lint/EndInMethod' => 'Style/EndBlock',
|
22
23
|
'Lint/HandleExceptions' => 'Lint/SuppressedException',
|
23
24
|
'Lint/MultipleCompare' => 'Lint/MultipleComparison',
|
24
25
|
'Lint/StringConversionInInterpolation' => 'Lint/RedundantStringCoercion',
|
@@ -6,33 +6,76 @@ module RuboCop
|
|
6
6
|
# Here we check if the elements of a multi-line array literal are
|
7
7
|
# aligned.
|
8
8
|
#
|
9
|
-
# @example
|
9
|
+
# @example EnforcedStyle: with_first_element (default)
|
10
|
+
# # good
|
11
|
+
#
|
12
|
+
# array = [1, 2, 3,
|
13
|
+
# 4, 5, 6]
|
14
|
+
# array = ['run',
|
15
|
+
# 'forrest',
|
16
|
+
# 'run']
|
17
|
+
#
|
10
18
|
# # bad
|
11
|
-
#
|
19
|
+
#
|
20
|
+
# array = [1, 2, 3,
|
12
21
|
# 4, 5, 6]
|
13
22
|
# array = ['run',
|
14
23
|
# 'forrest',
|
15
24
|
# 'run']
|
16
25
|
#
|
26
|
+
# @example EnforcedStyle: with_fixed_indentation
|
17
27
|
# # good
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
28
|
+
#
|
29
|
+
# array = [1, 2, 3,
|
30
|
+
# 4, 5, 6]
|
31
|
+
#
|
32
|
+
# # bad
|
33
|
+
#
|
34
|
+
# array = [1, 2, 3,
|
35
|
+
# 4, 5, 6]
|
23
36
|
class ArrayAlignment < Cop
|
24
37
|
include Alignment
|
25
38
|
|
26
|
-
|
27
|
-
|
39
|
+
ALIGN_ELEMENTS_MSG = 'Align the elements of an array literal ' \
|
40
|
+
'if they span more than one line.'
|
41
|
+
|
42
|
+
FIXED_INDENT_MSG = 'Use one level of indentation for elements ' \
|
43
|
+
'following the first line of a multi-line array.'
|
28
44
|
|
29
45
|
def on_array(node)
|
30
|
-
|
46
|
+
return if node.children.size < 2
|
47
|
+
|
48
|
+
check_alignment(node.children, base_column(node, node.children))
|
31
49
|
end
|
32
50
|
|
33
51
|
def autocorrect(node)
|
34
52
|
AlignmentCorrector.correct(processed_source, node, column_delta)
|
35
53
|
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def message(_node)
|
58
|
+
fixed_indentation? ? FIXED_INDENT_MSG : ALIGN_ELEMENTS_MSG
|
59
|
+
end
|
60
|
+
|
61
|
+
def fixed_indentation?
|
62
|
+
cop_config['EnforcedStyle'] == 'with_fixed_indentation'
|
63
|
+
end
|
64
|
+
|
65
|
+
def base_column(node, args)
|
66
|
+
if fixed_indentation?
|
67
|
+
lineno = target_method_lineno(node)
|
68
|
+
line = node.source_range.source_buffer.source_line(lineno)
|
69
|
+
indentation_of_line = /\S.*/.match(line).begin(0)
|
70
|
+
indentation_of_line + configured_indentation_width
|
71
|
+
else
|
72
|
+
display_column(args.first.source_range)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def target_method_lineno(node)
|
77
|
+
node.loc.line
|
78
|
+
end
|
36
79
|
end
|
37
80
|
end
|
38
81
|
end
|
@@ -52,9 +52,11 @@ module RuboCop
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def delimiter_range(node)
|
55
|
-
Parser::Source::Range.new(
|
56
|
-
|
57
|
-
|
55
|
+
Parser::Source::Range.new(
|
56
|
+
node.loc.expression.source_buffer,
|
57
|
+
node.children.compact.last.loc.expression.end_pos,
|
58
|
+
node.loc.expression.end_pos
|
59
|
+
)
|
58
60
|
end
|
59
61
|
end
|
60
62
|
end
|
@@ -59,6 +59,14 @@ module RuboCop
|
|
59
59
|
check_alignment(node.when_branches.last.loc.keyword, node.loc.else)
|
60
60
|
end
|
61
61
|
|
62
|
+
def on_case_match(node)
|
63
|
+
return unless node.else?
|
64
|
+
|
65
|
+
check_alignment(
|
66
|
+
node.in_pattern_branches.last.loc.keyword, node.loc.else
|
67
|
+
)
|
68
|
+
end
|
69
|
+
|
62
70
|
def autocorrect(node)
|
63
71
|
AlignmentCorrector.correct(processed_source, node, column_delta)
|
64
72
|
end
|
@@ -193,7 +193,7 @@ module RuboCop
|
|
193
193
|
node = node.receiver while node.receiver
|
194
194
|
# ascend to first call which has a dot
|
195
195
|
node = node.parent
|
196
|
-
node = node.parent until node.loc.dot
|
196
|
+
node = node.parent until node.loc.respond_to?(:dot) && node.loc.dot
|
197
197
|
|
198
198
|
return if node.loc.dot.line != node.first_line
|
199
199
|
|
@@ -32,6 +32,18 @@ module RuboCop
|
|
32
32
|
|
33
33
|
add_offense(node, message: format(MSG, boolean: node.value))
|
34
34
|
end
|
35
|
+
|
36
|
+
def autocorrect(node)
|
37
|
+
lambda do |corrector|
|
38
|
+
boolean_literal = node.source.delete(':')
|
39
|
+
parent = node.parent
|
40
|
+
if parent&.pair_type?
|
41
|
+
corrector.remove(parent.loc.operator)
|
42
|
+
boolean_literal = "#{node.source} =>"
|
43
|
+
end
|
44
|
+
corrector.replace(node.loc.expression, boolean_literal)
|
45
|
+
end
|
46
|
+
end
|
35
47
|
end
|
36
48
|
end
|
37
49
|
end
|
@@ -84,7 +84,7 @@ module RuboCop
|
|
84
84
|
|
85
85
|
def on_send(node)
|
86
86
|
erb_new_with_non_keyword_arguments(node) do |arguments|
|
87
|
-
return if correct_arguments?(arguments)
|
87
|
+
return if arguments.empty? || correct_arguments?(arguments)
|
88
88
|
|
89
89
|
arguments[1..3].each_with_index do |argument, i|
|
90
90
|
next if !argument || argument.hash_type?
|
@@ -27,18 +27,20 @@ module RuboCop
|
|
27
27
|
#
|
28
28
|
# # good
|
29
29
|
#
|
30
|
-
# #
|
31
|
-
#
|
30
|
+
# # while replacement
|
31
|
+
# loop do
|
32
32
|
# do_something
|
33
|
+
# break unless some_condition
|
33
34
|
# end
|
34
35
|
#
|
35
36
|
# @example
|
36
37
|
#
|
37
38
|
# # good
|
38
39
|
#
|
39
|
-
# #
|
40
|
-
#
|
40
|
+
# # until replacement
|
41
|
+
# loop do
|
41
42
|
# do_something
|
43
|
+
# break if some_condition
|
42
44
|
# end
|
43
45
|
class Loop < Cop
|
44
46
|
MSG = 'Use `Kernel#loop` with `break` rather than ' \
|
@@ -31,14 +31,14 @@ module RuboCop
|
|
31
31
|
# # good
|
32
32
|
#
|
33
33
|
# def foo
|
34
|
-
# self.class_eval do
|
34
|
+
# self.class.class_eval do
|
35
35
|
# def bar
|
36
36
|
# end
|
37
37
|
# end
|
38
38
|
# end
|
39
39
|
#
|
40
40
|
# def foo
|
41
|
-
# self.module_exec do
|
41
|
+
# self.class.module_exec do
|
42
42
|
# def bar
|
43
43
|
# end
|
44
44
|
# end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
# This cop checks for `raise` or `fail` statements which are
|
7
|
+
# raising `Exception` class.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# raise Exception, 'Error message here'
|
12
|
+
#
|
13
|
+
# # good
|
14
|
+
# raise StandardError, 'Error message here'
|
15
|
+
class RaiseException < Cop
|
16
|
+
MSG = 'Use `StandardError` over `Exception`.'
|
17
|
+
|
18
|
+
def_node_matcher :exception?, <<~PATTERN
|
19
|
+
(send nil? ${:raise :fail} (const _ :Exception) ... )
|
20
|
+
PATTERN
|
21
|
+
|
22
|
+
def_node_matcher :exception_new_with_message?, <<~PATTERN
|
23
|
+
(send nil? ${:raise :fail}
|
24
|
+
(send (const _ :Exception) :new ... ))
|
25
|
+
PATTERN
|
26
|
+
|
27
|
+
def on_send(node)
|
28
|
+
add_offense(node) if raise_exception?(node)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def raise_exception?(node)
|
34
|
+
exception?(node) || exception_new_with_message?(node)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
# This cop checks unexpected overrides of the `Struct` built-in methods
|
7
|
+
# via `Struct.new`.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# Bad = Struct.new(:members, :clone, :count)
|
12
|
+
# b = Bad.new([], true, 1)
|
13
|
+
# b.members #=> [] (overriding `Struct#members`)
|
14
|
+
# b.clone #=> true (overriding `Object#clone`)
|
15
|
+
# b.count #=> 1 (overriding `Enumerable#count`)
|
16
|
+
#
|
17
|
+
# # good
|
18
|
+
# Good = Struct.new(:id, :name)
|
19
|
+
# g = Good.new(1, "foo")
|
20
|
+
# g.members #=> [:id, :name]
|
21
|
+
# g.clone #=> #<struct Good id=1, name="foo">
|
22
|
+
# g.count #=> 2
|
23
|
+
#
|
24
|
+
class StructNewOverride < Cop
|
25
|
+
MSG = '`%<member_name>s` member overrides `Struct#%<method_name>s`' \
|
26
|
+
' and it may be unexpected.'
|
27
|
+
|
28
|
+
STRUCT_METHOD_NAMES = Struct.instance_methods
|
29
|
+
STRUCT_MEMBER_NAME_TYPES = %i[sym str].freeze
|
30
|
+
|
31
|
+
def_node_matcher :struct_new, <<~PATTERN
|
32
|
+
(send
|
33
|
+
(const ${nil? cbase} :Struct) :new ...)
|
34
|
+
PATTERN
|
35
|
+
|
36
|
+
def on_send(node)
|
37
|
+
return unless struct_new(node) do
|
38
|
+
node.arguments.each_with_index do |arg, index|
|
39
|
+
# Ignore if the first argument is a class name
|
40
|
+
next if index.zero? && arg.str_type?
|
41
|
+
|
42
|
+
# Ignore if the argument is not a member name
|
43
|
+
next unless STRUCT_MEMBER_NAME_TYPES.include?(arg.type)
|
44
|
+
|
45
|
+
member_name = arg.value
|
46
|
+
|
47
|
+
next unless STRUCT_METHOD_NAMES.include?(member_name.to_sym)
|
48
|
+
|
49
|
+
message = format(MSG, member_name: member_name.inspect,
|
50
|
+
method_name: member_name.to_s)
|
51
|
+
add_offense(arg, message: message)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -5,7 +5,7 @@ module RuboCop
|
|
5
5
|
module Lint
|
6
6
|
# This cop checks for *rescue* blocks with no body.
|
7
7
|
#
|
8
|
-
# @example
|
8
|
+
# @example
|
9
9
|
#
|
10
10
|
# # bad
|
11
11
|
# def some_method
|
@@ -14,25 +14,11 @@ module RuboCop
|
|
14
14
|
# end
|
15
15
|
#
|
16
16
|
# # bad
|
17
|
-
# def some_method
|
18
|
-
# do_something
|
19
|
-
# rescue
|
20
|
-
# # do nothing
|
21
|
-
# end
|
22
|
-
#
|
23
|
-
# # bad
|
24
17
|
# begin
|
25
18
|
# do_something
|
26
19
|
# rescue
|
27
20
|
# end
|
28
21
|
#
|
29
|
-
# # bad
|
30
|
-
# begin
|
31
|
-
# do_something
|
32
|
-
# rescue
|
33
|
-
# # do nothing
|
34
|
-
# end
|
35
|
-
#
|
36
22
|
# # good
|
37
23
|
# def some_method
|
38
24
|
# do_something
|
@@ -47,32 +33,36 @@ module RuboCop
|
|
47
33
|
# handle_exception
|
48
34
|
# end
|
49
35
|
#
|
50
|
-
# @example AllowComments: true
|
36
|
+
# @example AllowComments: true (default)
|
51
37
|
#
|
52
|
-
# #
|
38
|
+
# # good
|
53
39
|
# def some_method
|
54
40
|
# do_something
|
55
41
|
# rescue
|
42
|
+
# # do nothing
|
56
43
|
# end
|
57
44
|
#
|
58
|
-
# #
|
45
|
+
# # good
|
59
46
|
# begin
|
60
47
|
# do_something
|
61
48
|
# rescue
|
49
|
+
# # do nothing
|
62
50
|
# end
|
63
51
|
#
|
64
|
-
#
|
52
|
+
# @example AllowComments: false
|
53
|
+
#
|
54
|
+
# # bad
|
65
55
|
# def some_method
|
66
56
|
# do_something
|
67
57
|
# rescue
|
68
|
-
# # do nothing
|
58
|
+
# # do nothing
|
69
59
|
# end
|
70
60
|
#
|
71
|
-
# #
|
61
|
+
# # bad
|
72
62
|
# begin
|
73
63
|
# do_something
|
74
64
|
# rescue
|
75
|
-
# # do nothing
|
65
|
+
# # do nothing
|
76
66
|
# end
|
77
67
|
class SuppressedException < Cop
|
78
68
|
MSG = 'Do not suppress exceptions.'
|
@@ -38,9 +38,34 @@ module RuboCop
|
|
38
38
|
# def do_something(unused)
|
39
39
|
# end
|
40
40
|
#
|
41
|
+
# @example IgnoreNotImplementedMethods: true (default)
|
42
|
+
# # good
|
43
|
+
# def do_something(unused)
|
44
|
+
# raise NotImplementedError
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# def do_something_else(unused)
|
48
|
+
# fail "TODO"
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# @example IgnoreNotImplementedMethods: false
|
52
|
+
# # bad
|
53
|
+
# def do_something(unused)
|
54
|
+
# raise NotImplementedError
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# def do_something_else(unused)
|
58
|
+
# fail "TODO"
|
59
|
+
# end
|
60
|
+
#
|
41
61
|
class UnusedMethodArgument < Cop
|
42
62
|
include UnusedArgument
|
43
63
|
|
64
|
+
def_node_matcher :not_implemented?, <<~PATTERN
|
65
|
+
{(send nil? :raise (const nil? :NotImplementedError))
|
66
|
+
(send nil? :fail ...)}
|
67
|
+
PATTERN
|
68
|
+
|
44
69
|
def autocorrect(node)
|
45
70
|
UnusedArgCorrector.correct(processed_source, node)
|
46
71
|
end
|
@@ -51,16 +76,17 @@ module RuboCop
|
|
51
76
|
return unless variable.method_argument?
|
52
77
|
return if variable.keyword_argument? &&
|
53
78
|
cop_config['AllowUnusedKeywordArguments']
|
54
|
-
|
55
|
-
if cop_config['IgnoreEmptyMethods']
|
56
|
-
body = variable.scope.node.body
|
57
|
-
|
58
|
-
return if body.nil?
|
59
|
-
end
|
79
|
+
return if ignored_method?(variable.scope.node.body)
|
60
80
|
|
61
81
|
super
|
62
82
|
end
|
63
83
|
|
84
|
+
def ignored_method?(body)
|
85
|
+
cop_config['IgnoreEmptyMethods'] && body.nil? ||
|
86
|
+
cop_config['IgnoreNotImplementedMethods'] &&
|
87
|
+
not_implemented?(body)
|
88
|
+
end
|
89
|
+
|
64
90
|
def message(variable)
|
65
91
|
message = +"Unused method argument - `#{variable.name}`."
|
66
92
|
|