rubocop 0.60.0 → 0.61.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 +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)
|