rubocop 0.60.0 → 0.61.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 +4 -4
- data/config/default.yml +573 -560
- data/lib/rubocop.rb +5 -0
- data/lib/rubocop/ast/node.rb +1 -1
- data/lib/rubocop/ast/sexp.rb +1 -1
- data/lib/rubocop/cli.rb +9 -14
- data/lib/rubocop/config.rb +4 -3
- data/lib/rubocop/config_loader.rb +25 -22
- data/lib/rubocop/config_loader_resolver.rb +3 -2
- data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +53 -0
- data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +73 -0
- data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +138 -0
- data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +52 -46
- data/lib/rubocop/cop/generator.rb +13 -17
- data/lib/rubocop/cop/generator/configuration_injector.rb +60 -0
- data/lib/rubocop/cop/layout/align_hash.rb +3 -0
- data/lib/rubocop/cop/layout/comment_indentation.rb +32 -2
- data/lib/rubocop/cop/layout/indent_heredoc.rb +11 -5
- data/lib/rubocop/cop/layout/indentation_width.rb +7 -1
- data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +11 -11
- data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +1 -1
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +16 -3
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +30 -17
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +11 -0
- data/lib/rubocop/cop/lint/shadowed_exception.rb +2 -5
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +1 -1
- data/lib/rubocop/cop/metrics/line_length.rb +2 -2
- data/lib/rubocop/cop/mixin/trailing_comma.rb +11 -15
- data/lib/rubocop/cop/offense.rb +1 -1
- data/lib/rubocop/cop/performance/open_struct.rb +46 -0
- data/lib/rubocop/cop/performance/redundant_merge.rb +18 -4
- data/lib/rubocop/cop/rails/bulk_change_table.rb +2 -2
- data/lib/rubocop/cop/rails/dynamic_find_by.rb +15 -8
- data/lib/rubocop/cop/rails/http_positional_arguments.rb +17 -14
- data/lib/rubocop/cop/rails/http_status.rb +4 -4
- data/lib/rubocop/cop/rails/inverse_of.rb +2 -2
- data/lib/rubocop/cop/rails/reversible_migration.rb +1 -1
- data/lib/rubocop/cop/rails/skips_model_validations.rb +1 -1
- data/lib/rubocop/cop/rails/validation.rb +4 -4
- data/lib/rubocop/cop/security/open.rb +31 -11
- data/lib/rubocop/cop/style/begin_block.rb +6 -0
- data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +1 -1
- data/lib/rubocop/cop/style/empty_case_condition.rb +13 -7
- data/lib/rubocop/cop/style/for.rb +9 -78
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +6 -4
- data/lib/rubocop/cop/style/global_vars.rb +1 -1
- data/lib/rubocop/cop/style/infinite_loop.rb +42 -6
- data/lib/rubocop/cop/style/lambda.rb +4 -87
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +221 -16
- data/lib/rubocop/cop/style/raise_args.rb +1 -1
- data/lib/rubocop/cop/style/regexp_literal.rb +62 -10
- data/lib/rubocop/cop/style/unneeded_condition.rb +2 -2
- data/lib/rubocop/cop/variable_force.rb +4 -2
- data/lib/rubocop/cop/variable_force/variable.rb +2 -0
- data/lib/rubocop/magic_comment.rb +1 -1
- data/lib/rubocop/remote_config.rb +13 -4
- data/lib/rubocop/rspec/expect_offense.rb +1 -1
- data/lib/rubocop/runner.rb +15 -4
- data/lib/rubocop/version.rb +1 -1
- metadata +7 -2
@@ -5,58 +5,64 @@ module RuboCop
|
|
5
5
|
# Autocorrection logic for the closing brace of a literal either
|
6
6
|
# on the same line as the last contained elements, or a new line.
|
7
7
|
class MultilineLiteralBraceCorrector
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
def correct(processed_source, node)
|
16
|
-
@processed_source = processed_source
|
17
|
-
if closing_brace_on_same_line?(node)
|
18
|
-
lambda do |corrector|
|
19
|
-
corrector.insert_before(node.loc.end, "\n".freeze)
|
20
|
-
end
|
21
|
-
else
|
22
|
-
# When a comment immediately before the closing brace gets in the
|
23
|
-
# way of an easy correction, the offense is reported but not auto-
|
24
|
-
# corrected. The user must handle the delicate decision of where to
|
25
|
-
# put the comment.
|
26
|
-
return if new_line_needed_before_closing_brace?(node)
|
27
|
-
|
28
|
-
lambda do |corrector|
|
29
|
-
corrector.remove(range_with_surrounding_space(range: node.loc.end,
|
30
|
-
side: :left))
|
31
|
-
|
32
|
-
corrector.insert_after(
|
33
|
-
last_element_range_with_trailing_comma(node),
|
34
|
-
node.loc.end.source
|
35
|
-
)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
# rubocop:enable Metrics/MethodLength
|
8
|
+
include MultilineLiteralBraceLayout
|
9
|
+
include RangeHelp
|
10
|
+
|
11
|
+
def initialize(node, processed_source)
|
12
|
+
@node = node
|
13
|
+
@processed_source = processed_source
|
14
|
+
end
|
40
15
|
|
41
|
-
|
16
|
+
def call(corrector)
|
17
|
+
if closing_brace_on_same_line?(node)
|
18
|
+
correct_same_line_brace(corrector)
|
19
|
+
else
|
20
|
+
# When a comment immediately before the closing brace gets in the
|
21
|
+
# way of an easy correction, the offense is reported but not auto-
|
22
|
+
# corrected. The user must handle the delicate decision of where to
|
23
|
+
# put the comment.
|
24
|
+
return if new_line_needed_before_closing_brace?(node)
|
42
25
|
|
43
|
-
|
44
|
-
trailing_comma_range = last_element_trailing_comma_range(node)
|
45
|
-
if trailing_comma_range
|
46
|
-
children(node).last.source_range.join(trailing_comma_range)
|
47
|
-
else
|
48
|
-
children(node).last.source_range
|
49
|
-
end
|
26
|
+
correct_next_line_brace(corrector)
|
50
27
|
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
attr_reader :node, :processed_source
|
33
|
+
|
34
|
+
def correct_same_line_brace(corrector)
|
35
|
+
corrector.insert_before(node.loc.end, "\n".freeze)
|
36
|
+
end
|
37
|
+
|
38
|
+
def correct_next_line_brace(corrector)
|
39
|
+
corrector.remove(
|
40
|
+
range_with_surrounding_space(range: node.loc.end, side: :left)
|
41
|
+
)
|
42
|
+
|
43
|
+
corrector.insert_after(
|
44
|
+
last_element_range_with_trailing_comma(node),
|
45
|
+
node.loc.end.source
|
46
|
+
)
|
47
|
+
end
|
51
48
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
49
|
+
def last_element_range_with_trailing_comma(node)
|
50
|
+
trailing_comma_range = last_element_trailing_comma_range(node)
|
51
|
+
if trailing_comma_range
|
52
|
+
children(node).last.source_range.join(trailing_comma_range)
|
53
|
+
else
|
54
|
+
children(node).last.source_range
|
58
55
|
end
|
59
56
|
end
|
57
|
+
|
58
|
+
def last_element_trailing_comma_range(node)
|
59
|
+
range = range_with_surrounding_space(
|
60
|
+
range: children(node).last.source_range,
|
61
|
+
side: :right
|
62
|
+
).end.resize(1)
|
63
|
+
|
64
|
+
range.source == ',' ? range : nil
|
65
|
+
end
|
60
66
|
end
|
61
67
|
end
|
62
68
|
end
|
@@ -98,6 +98,11 @@ module RuboCop
|
|
98
98
|
end
|
99
99
|
SPEC
|
100
100
|
|
101
|
+
CONFIGURATION_ADDED_MESSAGE = <<-MESSAGE.strip_indent
|
102
|
+
[modify] A configuration for the cop is added into %<configuration_file_path>s.
|
103
|
+
If you want to disable the cop by default, set `Enabled` option to false.
|
104
|
+
MESSAGE
|
105
|
+
|
101
106
|
def initialize(name, github_user, output: $stdout)
|
102
107
|
@badge = Badge.parse(name)
|
103
108
|
@github_user = github_user
|
@@ -123,24 +128,15 @@ module RuboCop
|
|
123
128
|
end
|
124
129
|
|
125
130
|
def inject_config(config_file_path: 'config/default.yml')
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
target_line = config.find.with_index(1) do |line, index|
|
135
|
-
next if line =~ /^[\s#]/
|
136
|
-
break index - 1 if badge.to_s < line
|
131
|
+
injector =
|
132
|
+
ConfigurationInjector.new(configuration_file_path: config_file_path,
|
133
|
+
badge: badge,
|
134
|
+
version_added: bump_minor_version)
|
135
|
+
|
136
|
+
injector.inject do
|
137
|
+
output.puts(format(CONFIGURATION_ADDED_MESSAGE,
|
138
|
+
configuration_file_path: config_file_path))
|
137
139
|
end
|
138
|
-
config.insert(target_line, content)
|
139
|
-
File.write(config_file_path, config.join)
|
140
|
-
output.puts <<-MESSAGE.strip_indent
|
141
|
-
[modify] A configuration for the cop is added into #{config_file_path}.
|
142
|
-
If you want to disable the cop by default, set `Enabled` option to false.
|
143
|
-
MESSAGE
|
144
140
|
end
|
145
141
|
|
146
142
|
def todo
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
class Generator
|
6
|
+
# A class that injects a require directive into the root RuboCop file.
|
7
|
+
# It looks for other directives that require files in the same (cop)
|
8
|
+
# namespace and injects the provided one in alpha
|
9
|
+
class ConfigurationInjector
|
10
|
+
TEMPLATE = <<-YAML.strip_indent
|
11
|
+
%<badge>s:
|
12
|
+
Description: 'TODO: Write a description of the cop.'
|
13
|
+
Enabled: true
|
14
|
+
VersionAdded: '%<version_added>s'
|
15
|
+
|
16
|
+
YAML
|
17
|
+
|
18
|
+
def initialize(configuration_file_path:, badge:, version_added:)
|
19
|
+
@configuration_file_path = configuration_file_path
|
20
|
+
@badge = badge
|
21
|
+
@version_added = version_added
|
22
|
+
@output = output
|
23
|
+
end
|
24
|
+
|
25
|
+
def inject
|
26
|
+
configuration_entries.insert(find_target_line,
|
27
|
+
new_configuration_entry)
|
28
|
+
|
29
|
+
File.write(configuration_file_path, configuration_entries.join)
|
30
|
+
|
31
|
+
yield if block_given?
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
attr_reader :configuration_file_path, :badge, :version_added, :output
|
37
|
+
|
38
|
+
def configuration_entries
|
39
|
+
@configuration_entries ||= File.readlines(configuration_file_path)
|
40
|
+
end
|
41
|
+
|
42
|
+
def new_configuration_entry
|
43
|
+
format(TEMPLATE, badge: badge, version_added: version_added)
|
44
|
+
end
|
45
|
+
|
46
|
+
def find_target_line
|
47
|
+
configuration_entries.find.with_index do |line, index|
|
48
|
+
next if comment?(line)
|
49
|
+
|
50
|
+
break index if badge.to_s < line
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def comment?(yaml)
|
55
|
+
yaml =~ /^[\s#]/
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -182,6 +182,7 @@ module RuboCop
|
|
182
182
|
|
183
183
|
def on_send(node)
|
184
184
|
return if double_splat?(node)
|
185
|
+
return unless node.arguments?
|
185
186
|
|
186
187
|
last_argument = node.last_argument
|
187
188
|
|
@@ -190,6 +191,8 @@ module RuboCop
|
|
190
191
|
|
191
192
|
ignore_node(last_argument)
|
192
193
|
end
|
194
|
+
alias on_super on_send
|
195
|
+
alias on_yield on_send
|
193
196
|
|
194
197
|
def on_hash(node)
|
195
198
|
return if ignored_node?(node)
|
@@ -42,12 +42,42 @@ module RuboCop
|
|
42
42
|
processed_source.each_comment { |comment| check(comment) }
|
43
43
|
end
|
44
44
|
|
45
|
-
def autocorrect(
|
46
|
-
|
45
|
+
def autocorrect(comment)
|
46
|
+
corrections = autocorrect_preceding_comments(comment) <<
|
47
|
+
autocorrect_one(comment)
|
48
|
+
->(corrector) { corrections.each { |corr| corr.call(corrector) } }
|
47
49
|
end
|
48
50
|
|
49
51
|
private
|
50
52
|
|
53
|
+
# Corrects all comment lines that occur immediately before the given
|
54
|
+
# comment and have the same indentation. This is to avoid a long chain
|
55
|
+
# of correcting, saving the file, parsing and inspecting again, and
|
56
|
+
# then correcting one more line, and so on.
|
57
|
+
def autocorrect_preceding_comments(comment)
|
58
|
+
corrections = []
|
59
|
+
line_no = comment.loc.line
|
60
|
+
column = comment.loc.column
|
61
|
+
comments = processed_source.comments
|
62
|
+
(comments.index(comment) - 1).downto(0) do |ix|
|
63
|
+
previous_comment = comments[ix]
|
64
|
+
break unless should_correct?(previous_comment, column, line_no - 1)
|
65
|
+
|
66
|
+
corrections << autocorrect_one(previous_comment)
|
67
|
+
line_no -= 1
|
68
|
+
end
|
69
|
+
corrections
|
70
|
+
end
|
71
|
+
|
72
|
+
def should_correct?(comment, column, line_no)
|
73
|
+
loc = comment.loc
|
74
|
+
loc.line == line_no && loc.column == column
|
75
|
+
end
|
76
|
+
|
77
|
+
def autocorrect_one(comment)
|
78
|
+
AlignmentCorrector.correct(processed_source, comment, @column_delta)
|
79
|
+
end
|
80
|
+
|
51
81
|
def check(comment)
|
52
82
|
return unless own_line_comment?(comment)
|
53
83
|
|
@@ -99,7 +99,7 @@ module RuboCop
|
|
99
99
|
return unless body_indent_level.zero?
|
100
100
|
end
|
101
101
|
|
102
|
-
return if
|
102
|
+
return if line_too_long?(node)
|
103
103
|
|
104
104
|
add_offense(node, location: :heredoc_body)
|
105
105
|
end
|
@@ -173,8 +173,8 @@ module RuboCop
|
|
173
173
|
)
|
174
174
|
end
|
175
175
|
|
176
|
-
def
|
177
|
-
return false if
|
176
|
+
def line_too_long?(node)
|
177
|
+
return false if unlimited_heredoc_length?
|
178
178
|
|
179
179
|
body = heredoc_body(node)
|
180
180
|
|
@@ -182,9 +182,15 @@ module RuboCop
|
|
182
182
|
actual_indent = indent_level(body)
|
183
183
|
increase_indent_level = expected_indent - actual_indent
|
184
184
|
|
185
|
-
|
185
|
+
longest_line(body).size + increase_indent_level >= max_line_length
|
186
|
+
end
|
187
|
+
|
188
|
+
def longest_line(lines)
|
189
|
+
lines.each_line.max_by { |line| line.chomp.size }.chomp
|
190
|
+
end
|
186
191
|
|
187
|
-
|
192
|
+
def unlimited_heredoc_length?
|
193
|
+
config.for_cop('Metrics/LineLength')['AllowHeredoc']
|
188
194
|
end
|
189
195
|
|
190
196
|
def max_line_length
|
@@ -96,6 +96,12 @@ module RuboCop
|
|
96
96
|
check_members(node.loc.keyword, members)
|
97
97
|
end
|
98
98
|
|
99
|
+
def on_sclass(node)
|
100
|
+
_class_name, *members = *node
|
101
|
+
|
102
|
+
check_members(node.loc.keyword, members)
|
103
|
+
end
|
104
|
+
|
99
105
|
def on_send(node)
|
100
106
|
super
|
101
107
|
return unless node.adjacent_def_modifier?
|
@@ -141,7 +147,7 @@ module RuboCop
|
|
141
147
|
end
|
142
148
|
|
143
149
|
def on_if(node, base = node)
|
144
|
-
return if ignored_node?(node)
|
150
|
+
return if ignored_node?(node)
|
145
151
|
return if node.ternary? || node.modifier_form?
|
146
152
|
|
147
153
|
check_if(node, node.body, node.else_branch, base.loc)
|
@@ -91,26 +91,26 @@ module RuboCop
|
|
91
91
|
class MultilineArrayBraceLayout < Cop
|
92
92
|
include MultilineLiteralBraceLayout
|
93
93
|
|
94
|
-
SAME_LINE_MESSAGE = '
|
95
|
-
'the last array element when opening brace is on the
|
96
|
-
'the first array element.'.freeze
|
94
|
+
SAME_LINE_MESSAGE = 'The closing array brace must be on the same ' \
|
95
|
+
'line as the last array element when the opening brace is on the ' \
|
96
|
+
'same line as the first array element.'.freeze
|
97
97
|
|
98
|
-
NEW_LINE_MESSAGE = '
|
99
|
-
'the last array element when opening brace is on a
|
100
|
-
'from the first array element.'.freeze
|
98
|
+
NEW_LINE_MESSAGE = 'The closing array brace must be on the line ' \
|
99
|
+
'after the last array element when the opening brace is on a ' \
|
100
|
+
'separate line from the first array element.'.freeze
|
101
101
|
|
102
|
-
ALWAYS_NEW_LINE_MESSAGE = '
|
103
|
-
'after the last array element.'.freeze
|
102
|
+
ALWAYS_NEW_LINE_MESSAGE = 'The closing array brace must be on the ' \
|
103
|
+
'line after the last array element.'.freeze
|
104
104
|
|
105
|
-
ALWAYS_SAME_LINE_MESSAGE = '
|
106
|
-
'line as the last array element.'.freeze
|
105
|
+
ALWAYS_SAME_LINE_MESSAGE = 'The closing array brace must be on the ' \
|
106
|
+
'same line as the last array element.'.freeze
|
107
107
|
|
108
108
|
def on_array(node)
|
109
109
|
check_brace_layout(node)
|
110
110
|
end
|
111
111
|
|
112
112
|
def autocorrect(node)
|
113
|
-
MultilineLiteralBraceCorrector.
|
113
|
+
MultilineLiteralBraceCorrector.new(node, processed_source)
|
114
114
|
end
|
115
115
|
end
|
116
116
|
end
|
@@ -28,8 +28,9 @@ module RuboCop
|
|
28
28
|
'aligned with `%<beginning>s` at ' \
|
29
29
|
'%<begin_loc_line>d, %<begin_loc_column>d.'.freeze
|
30
30
|
ANCESTOR_TYPES = %i[kwbegin def defs class module].freeze
|
31
|
-
RUBY_2_5_ANCESTOR_TYPES = (ANCESTOR_TYPES + [
|
31
|
+
RUBY_2_5_ANCESTOR_TYPES = (ANCESTOR_TYPES + %i[block]).freeze
|
32
32
|
ANCESTOR_TYPES_WITH_ACCESS_MODIFIERS = %i[def defs].freeze
|
33
|
+
ASSIGNMENT_TYPES = %i[lvasgn].freeze
|
33
34
|
|
34
35
|
def on_resbody(node)
|
35
36
|
check(node) unless modifier?(node)
|
@@ -115,10 +116,13 @@ module RuboCop
|
|
115
116
|
ancestor_node = ancestor_node(node)
|
116
117
|
return nil if ancestor_node.nil?
|
117
118
|
|
119
|
+
assignment_node = assignment_node(ancestor_node)
|
120
|
+
return assignment_node unless assignment_node.nil?
|
121
|
+
|
118
122
|
access_modifier_node = access_modifier_node(ancestor_node)
|
119
|
-
return
|
123
|
+
return access_modifier_node unless access_modifier_node.nil?
|
120
124
|
|
121
|
-
|
125
|
+
ancestor_node
|
122
126
|
end
|
123
127
|
|
124
128
|
def ancestor_node(node)
|
@@ -132,6 +136,15 @@ module RuboCop
|
|
132
136
|
node.each_ancestor(*ancestor_types).first
|
133
137
|
end
|
134
138
|
|
139
|
+
def assignment_node(node)
|
140
|
+
assignment_node = node.ancestors.first
|
141
|
+
return nil unless
|
142
|
+
assignment_node &&
|
143
|
+
ASSIGNMENT_TYPES.include?(assignment_node.type)
|
144
|
+
|
145
|
+
assignment_node
|
146
|
+
end
|
147
|
+
|
135
148
|
def access_modifier_node(node)
|
136
149
|
return nil unless
|
137
150
|
ANCESTOR_TYPES_WITH_ACCESS_MODIFIERS.include?(node.type)
|