rubocop 0.93.1 → 1.0.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 +1 -1
- data/config/default.yml +59 -54
- data/lib/rubocop.rb +0 -2
- data/lib/rubocop/cli/command/version.rb +1 -1
- data/lib/rubocop/config.rb +4 -0
- data/lib/rubocop/config_loader.rb +19 -2
- data/lib/rubocop/config_loader_resolver.rb +7 -5
- data/lib/rubocop/config_validator.rb +7 -6
- data/lib/rubocop/cop/badge.rb +9 -24
- data/lib/rubocop/cop/base.rb +16 -1
- data/lib/rubocop/cop/commissioner.rb +34 -20
- data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +1 -1
- data/lib/rubocop/cop/layout/class_structure.rb +7 -0
- data/lib/rubocop/cop/layout/space_around_operators.rb +4 -1
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +37 -13
- data/lib/rubocop/cop/lint/to_json.rb +1 -1
- data/lib/rubocop/cop/metrics/parameter_lists.rb +4 -1
- data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +1 -1
- data/lib/rubocop/cop/security/open.rb +12 -10
- data/lib/rubocop/cop/style/accessor_grouping.rb +1 -1
- data/lib/rubocop/cop/style/format_string_token.rb +47 -2
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +10 -13
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +6 -11
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +7 -11
- data/lib/rubocop/cop/style/redundant_parentheses.rb +4 -0
- data/lib/rubocop/cop/style/redundant_self.rb +3 -0
- data/lib/rubocop/cop/style/safe_navigation.rb +16 -4
- data/lib/rubocop/cop/style/string_concatenation.rb +13 -1
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +3 -1
- data/lib/rubocop/formatter/offense_count_formatter.rb +1 -1
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -1
- data/lib/rubocop/options.rb +4 -1
- data/lib/rubocop/version.rb +56 -6
- metadata +4 -4
data/lib/rubocop.rb
CHANGED
@@ -471,8 +471,6 @@ require_relative 'rubocop/cop/style/redundant_fetch_block'
|
|
471
471
|
require_relative 'rubocop/cop/style/redundant_file_extension_in_require'
|
472
472
|
require_relative 'rubocop/cop/style/redundant_self_assignment'
|
473
473
|
require_relative 'rubocop/cop/style/sole_nested_conditional'
|
474
|
-
require_relative 'rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses'
|
475
|
-
require_relative 'rubocop/cop/style/method_call_with_args_parentheses/require_parentheses'
|
476
474
|
require_relative 'rubocop/cop/style/method_called_on_do_end_block'
|
477
475
|
require_relative 'rubocop/cop/style/method_def_parentheses'
|
478
476
|
require_relative 'rubocop/cop/style/min_max'
|
@@ -10,7 +10,7 @@ module RuboCop
|
|
10
10
|
|
11
11
|
def run
|
12
12
|
puts RuboCop::Version.version(debug: false) if @options[:version]
|
13
|
-
puts RuboCop::Version.version(debug: true) if @options[:verbose_version]
|
13
|
+
puts RuboCop::Version.version(debug: true, env: env) if @options[:verbose_version]
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
data/lib/rubocop/config.rb
CHANGED
@@ -35,12 +35,13 @@ module RuboCop
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def load_file(file)
|
38
|
-
path =
|
38
|
+
path = file_path(file)
|
39
39
|
|
40
40
|
hash = load_yaml_configuration(path)
|
41
41
|
|
42
42
|
# Resolve requires first in case they define additional cops
|
43
|
-
resolver.resolve_requires(path, hash)
|
43
|
+
loaded_features = resolver.resolve_requires(path, hash)
|
44
|
+
add_loaded_features(loaded_features)
|
44
45
|
|
45
46
|
add_missing_namespaces(path, hash)
|
46
47
|
|
@@ -172,8 +173,24 @@ module RuboCop
|
|
172
173
|
resolver.merge_with_default(config, config_file, unset_nil: unset_nil)
|
173
174
|
end
|
174
175
|
|
176
|
+
def loaded_features
|
177
|
+
@loaded_features.flatten.compact
|
178
|
+
end
|
179
|
+
|
175
180
|
private
|
176
181
|
|
182
|
+
def file_path(file)
|
183
|
+
File.absolute_path(file.is_a?(RemoteConfig) ? file.file : file)
|
184
|
+
end
|
185
|
+
|
186
|
+
def add_loaded_features(loaded_features)
|
187
|
+
if instance_variable_defined?(:@loaded_features)
|
188
|
+
instance_variable_get(:@loaded_features) << loaded_features
|
189
|
+
else
|
190
|
+
instance_variable_set(:@loaded_features, [loaded_features])
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
177
194
|
def find_project_dotfile(target_dir)
|
178
195
|
find_file_upwards(DOTFILE, target_dir, project_root)
|
179
196
|
end
|
@@ -9,11 +9,13 @@ module RuboCop
|
|
9
9
|
class ConfigLoaderResolver
|
10
10
|
def resolve_requires(path, hash)
|
11
11
|
config_dir = File.dirname(path)
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
hash.delete('require').tap do |loaded_features|
|
13
|
+
Array(loaded_features).each do |feature|
|
14
|
+
if feature.start_with?('.')
|
15
|
+
require(File.join(config_dir, feature))
|
16
|
+
else
|
17
|
+
require(feature)
|
18
|
+
end
|
17
19
|
end
|
18
20
|
end
|
19
21
|
end
|
@@ -18,6 +18,11 @@ module RuboCop
|
|
18
18
|
# @api private
|
19
19
|
NEW_COPS_VALUES = %w[pending disable enable].freeze
|
20
20
|
|
21
|
+
# @api private
|
22
|
+
CONFIG_CHECK_KEYS = %w[Enabled Safe SafeAutoCorrect AutoCorrect].to_set.freeze
|
23
|
+
CONFIG_CHECK_DEPARTMENTS = %w[pending override_department].freeze
|
24
|
+
private_constant :CONFIG_CHECK_KEYS, :CONFIG_CHECK_DEPARTMENTS
|
25
|
+
|
21
26
|
def_delegators :@config, :smart_loaded_path, :for_all_cops
|
22
27
|
|
23
28
|
def initialize(config)
|
@@ -202,13 +207,9 @@ module RuboCop
|
|
202
207
|
hash.each do |key, value|
|
203
208
|
check_cop_config_value(value, key) if value.is_a?(Hash)
|
204
209
|
|
205
|
-
next unless
|
206
|
-
Safe
|
207
|
-
SafeAutoCorrect
|
208
|
-
AutoCorrect].include?(key) && value.is_a?(String)
|
210
|
+
next unless CONFIG_CHECK_KEYS.include?(key) && value.is_a?(String)
|
209
211
|
|
210
|
-
next if key == 'Enabled' &&
|
211
|
-
%w[pending override_department].include?(value)
|
212
|
+
next if key == 'Enabled' && CONFIG_CHECK_DEPARTMENTS.include?(value)
|
212
213
|
|
213
214
|
raise ValidationError, msg_not_boolean(parent, key, value)
|
214
215
|
end
|
data/lib/rubocop/cop/badge.rb
CHANGED
@@ -10,37 +10,22 @@ module RuboCop
|
|
10
10
|
# allow for badge references in source files that omit the department for
|
11
11
|
# RuboCop to infer.
|
12
12
|
class Badge
|
13
|
-
# Error raised when a badge parse fails.
|
14
|
-
class InvalidBadge < Error
|
15
|
-
MSG = 'Invalid badge %<badge>p. ' \
|
16
|
-
'Expected `Department/CopName` or `CopName`.'
|
17
|
-
|
18
|
-
def initialize(token)
|
19
|
-
super(format(MSG, badge: token))
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
13
|
attr_reader :department, :cop_name
|
24
14
|
|
25
15
|
def self.for(class_name)
|
26
|
-
|
16
|
+
parts = class_name.split('::')
|
17
|
+
name_deep_enough = parts.length >= 4
|
18
|
+
new(name_deep_enough ? parts[2..-1] : parts.last(2))
|
27
19
|
end
|
28
20
|
|
29
21
|
def self.parse(identifier)
|
30
|
-
|
31
|
-
|
32
|
-
raise InvalidBadge, identifier if parts.size > 2
|
33
|
-
|
34
|
-
if parts.one?
|
35
|
-
new(nil, *parts)
|
36
|
-
else
|
37
|
-
new(*parts)
|
38
|
-
end
|
22
|
+
new(identifier.split('/'))
|
39
23
|
end
|
40
24
|
|
41
|
-
def initialize(
|
42
|
-
|
43
|
-
@
|
25
|
+
def initialize(class_name_parts)
|
26
|
+
department_parts = class_name_parts[0...-1]
|
27
|
+
@department = (department_parts.join('/').to_sym unless department_parts.empty?)
|
28
|
+
@cop_name = class_name_parts.last
|
44
29
|
end
|
45
30
|
|
46
31
|
def ==(other)
|
@@ -66,7 +51,7 @@ module RuboCop
|
|
66
51
|
end
|
67
52
|
|
68
53
|
def with_department(department)
|
69
|
-
self.class.new(department, cop_name)
|
54
|
+
self.class.new([department.to_s.split('/'), cop_name].flatten)
|
70
55
|
end
|
71
56
|
end
|
72
57
|
end
|
data/lib/rubocop/cop/base.rb
CHANGED
@@ -261,6 +261,21 @@ module RuboCop
|
|
261
261
|
'they are returned as the result of the investigation'
|
262
262
|
end
|
263
263
|
|
264
|
+
### Reserved for Commissioner
|
265
|
+
|
266
|
+
# @api private
|
267
|
+
def callbacks_needed
|
268
|
+
self.class.callbacks_needed
|
269
|
+
end
|
270
|
+
|
271
|
+
# @api private
|
272
|
+
def self.callbacks_needed
|
273
|
+
@callbacks_needed ||= public_instance_methods.select do |m|
|
274
|
+
m.match?(/^on_|^after_/) &&
|
275
|
+
!Base.method_defined?(m) # exclude standard "callbacks" like 'on_begin_investigation'
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
264
279
|
private
|
265
280
|
|
266
281
|
### Reserved for Cop::Cop
|
@@ -291,7 +306,7 @@ module RuboCop
|
|
291
306
|
end
|
292
307
|
|
293
308
|
private_class_method def self.restrict_on_send
|
294
|
-
@restrict_on_send ||= self::RESTRICT_ON_SEND.
|
309
|
+
@restrict_on_send ||= self::RESTRICT_ON_SEND.to_a.freeze
|
295
310
|
end
|
296
311
|
|
297
312
|
# Called before any investigation
|
@@ -7,7 +7,7 @@ module RuboCop
|
|
7
7
|
class Commissioner
|
8
8
|
include RuboCop::AST::Traversal
|
9
9
|
|
10
|
-
RESTRICTED_CALLBACKS = %i[on_send on_csend].freeze
|
10
|
+
RESTRICTED_CALLBACKS = %i[on_send on_csend after_send after_csend].freeze
|
11
11
|
private_constant :RESTRICTED_CALLBACKS
|
12
12
|
|
13
13
|
# How a Commissioner returns the results of the investigation
|
@@ -45,8 +45,7 @@ module RuboCop
|
|
45
45
|
@cops = cops
|
46
46
|
@forces = forces
|
47
47
|
@options = options
|
48
|
-
|
49
|
-
@restricted_map = {}
|
48
|
+
initialize_callbacks
|
50
49
|
|
51
50
|
reset
|
52
51
|
end
|
@@ -61,16 +60,18 @@ module RuboCop
|
|
61
60
|
method_name = :"on_#{node_type}"
|
62
61
|
next unless method_defined?(method_name)
|
63
62
|
|
64
|
-
|
65
|
-
|
66
|
-
|
63
|
+
# Hacky: Comment-out code as needed
|
64
|
+
r = '#' unless RESTRICTED_CALLBACKS.include?(method_name) # has Restricted?
|
65
|
+
c = '#' if NO_CHILD_NODES.include?(node_type) # has Children?
|
67
66
|
|
68
67
|
class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
68
|
+
def on_#{node_type}(node)
|
69
|
+
trigger_responding_cops(:on_#{node_type}, node)
|
70
|
+
#{r} trigger_restricted_cops(:on_#{node_type}, node)
|
71
|
+
#{c} super(node)
|
72
|
+
#{c} trigger_responding_cops(:after_#{node_type}, node)
|
73
|
+
#{c}#{r} trigger_restricted_cops(:after_#{node_type}, node)
|
74
|
+
end
|
74
75
|
RUBY
|
75
76
|
end
|
76
77
|
|
@@ -94,7 +95,7 @@ module RuboCop
|
|
94
95
|
private
|
95
96
|
|
96
97
|
def trigger_responding_cops(callback, node)
|
97
|
-
@callbacks[callback]
|
98
|
+
@callbacks[callback]&.each do |cop|
|
98
99
|
with_cop_error_handling(cop, node) do
|
99
100
|
cop.send(callback, node)
|
100
101
|
end
|
@@ -105,19 +106,32 @@ module RuboCop
|
|
105
106
|
@errors = []
|
106
107
|
end
|
107
108
|
|
108
|
-
def
|
109
|
-
callbacks = @cops
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
109
|
+
def initialize_callbacks
|
110
|
+
@callbacks = build_callbacks(@cops)
|
111
|
+
@restricted_map = restrict_callbacks(@callbacks)
|
112
|
+
end
|
113
|
+
|
114
|
+
def build_callbacks(cops)
|
115
|
+
callbacks = {}
|
116
|
+
cops.each do |cop|
|
117
|
+
cop.callbacks_needed.each do |callback|
|
118
|
+
(callbacks[callback] ||= []) << cop
|
119
|
+
end
|
114
120
|
end
|
115
121
|
callbacks
|
116
122
|
end
|
117
123
|
|
124
|
+
def restrict_callbacks(callbacks)
|
125
|
+
restricted = {}
|
126
|
+
RESTRICTED_CALLBACKS.each do |callback|
|
127
|
+
restricted[callback] = restricted_map(callbacks[callback])
|
128
|
+
end
|
129
|
+
restricted
|
130
|
+
end
|
131
|
+
|
118
132
|
def trigger_restricted_cops(event, node)
|
119
133
|
name = node.method_name
|
120
|
-
@restricted_map
|
134
|
+
@restricted_map[event][name]&.each do |cop|
|
121
135
|
with_cop_error_handling(cop, node) do
|
122
136
|
cop.send(event, node)
|
123
137
|
end
|
@@ -127,7 +141,7 @@ module RuboCop
|
|
127
141
|
# Note: mutates `callbacks` in place
|
128
142
|
def restricted_map(callbacks)
|
129
143
|
map = {}
|
130
|
-
callbacks
|
144
|
+
callbacks&.select! do |cop|
|
131
145
|
restrictions = cop.class.send :restrict_on_send
|
132
146
|
restrictions.each do |name|
|
133
147
|
(map[name] ||= []) << cop
|
@@ -89,7 +89,7 @@ module RuboCop
|
|
89
89
|
begin_line_num = previous_line_num - base_line_num + 1
|
90
90
|
end_line_num = node.first_line - base_line_num + 1
|
91
91
|
lines = source_in_lines[begin_line_num...end_line_num]
|
92
|
-
"\n#{
|
92
|
+
"\n#{lines.join("\n").split(node.source).first || ''}"
|
93
93
|
end
|
94
94
|
|
95
95
|
def fix_escaped_content(word_node, escape, delimiters)
|
@@ -265,6 +265,9 @@ module RuboCop
|
|
265
265
|
end
|
266
266
|
|
267
267
|
def end_position_for(node)
|
268
|
+
heredoc = find_heredoc(node)
|
269
|
+
return heredoc.location.heredoc_end.end_pos + 1 if heredoc
|
270
|
+
|
268
271
|
end_line = buffer.line_for_position(node.loc.expression.end_pos)
|
269
272
|
buffer.line_range(end_line).end_pos
|
270
273
|
end
|
@@ -284,6 +287,10 @@ module RuboCop
|
|
284
287
|
buffer.line_range(node.loc.line).begin_pos - 1
|
285
288
|
end
|
286
289
|
|
290
|
+
def find_heredoc(node)
|
291
|
+
node.each_node(:str, :dstr, :xstr).find(&:heredoc?)
|
292
|
+
end
|
293
|
+
|
287
294
|
def buffer
|
288
295
|
processed_source.buffer
|
289
296
|
end
|
@@ -5,6 +5,8 @@ module RuboCop
|
|
5
5
|
module Layout
|
6
6
|
# Checks that operators have space around them, except for ** which
|
7
7
|
# should or shouldn't have surrounding space depending on configuration.
|
8
|
+
# It allows vertical alignment consisting of one or more whitespace
|
9
|
+
# around operators.
|
8
10
|
#
|
9
11
|
# This cop has `AllowForAlignment` option. When `true`, allows most
|
10
12
|
# uses of extra spacing if the intent is to align with an operator on
|
@@ -207,7 +209,8 @@ module RuboCop
|
|
207
209
|
token = Token.new(operator, nil, operator.source)
|
208
210
|
align_preceding = aligned_with_preceding_assignment(token)
|
209
211
|
|
210
|
-
return
|
212
|
+
return false if align_preceding == :yes ||
|
213
|
+
aligned_with_subsequent_assignment(token) == :none
|
211
214
|
|
212
215
|
aligned_with_subsequent_assignment(token) != :yes
|
213
216
|
end
|
@@ -14,14 +14,25 @@ module RuboCop
|
|
14
14
|
# # good
|
15
15
|
# x = 0
|
16
16
|
#
|
17
|
-
# @example AllowInHeredoc: false
|
17
|
+
# @example AllowInHeredoc: false (default)
|
18
18
|
# # The line in this example contains spaces after the 0.
|
19
19
|
# # bad
|
20
20
|
# code = <<~RUBY
|
21
21
|
# x = 0
|
22
22
|
# RUBY
|
23
23
|
#
|
24
|
-
#
|
24
|
+
# # ok
|
25
|
+
# code = <<~RUBY
|
26
|
+
# x = 0 #{}
|
27
|
+
# RUBY
|
28
|
+
#
|
29
|
+
# # good
|
30
|
+
# trailing_whitespace = ' '
|
31
|
+
# code = <<~RUBY
|
32
|
+
# x = 0#{trailing_whitespace}
|
33
|
+
# RUBY
|
34
|
+
#
|
35
|
+
# @example AllowInHeredoc: true
|
25
36
|
# # The line in this example contains spaces after the 0.
|
26
37
|
# # good
|
27
38
|
# code = <<~RUBY
|
@@ -35,36 +46,49 @@ module RuboCop
|
|
35
46
|
MSG = 'Trailing whitespace detected.'
|
36
47
|
|
37
48
|
def on_new_investigation
|
38
|
-
|
49
|
+
@heredocs = extract_heredocs(processed_source.ast)
|
39
50
|
processed_source.lines.each_with_index do |line, index|
|
40
|
-
lineno = index + 1
|
41
|
-
|
42
51
|
next unless line.end_with?(' ', "\t")
|
43
|
-
next if skip_heredoc? && inside_heredoc?(heredoc_ranges, lineno)
|
44
52
|
|
45
|
-
|
46
|
-
|
53
|
+
process_line(line, index + 1)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def process_line(line, lineno)
|
60
|
+
heredoc = find_heredoc(lineno)
|
61
|
+
return if skip_heredoc? && heredoc
|
62
|
+
|
63
|
+
range = offense_range(lineno, line)
|
64
|
+
add_offense(range) do |corrector|
|
65
|
+
if heredoc
|
66
|
+
corrector.insert_after(range, '#{}') unless static?(heredoc) # rubocop:disable Lint/InterpolationCheck
|
67
|
+
else
|
47
68
|
corrector.remove(range)
|
48
69
|
end
|
49
70
|
end
|
50
71
|
end
|
51
72
|
|
52
|
-
|
73
|
+
def static?(heredoc)
|
74
|
+
heredoc.loc.expression.source.end_with? "'"
|
75
|
+
end
|
53
76
|
|
54
77
|
def skip_heredoc?
|
55
78
|
cop_config.fetch('AllowInHeredoc', false)
|
56
79
|
end
|
57
80
|
|
58
|
-
def
|
59
|
-
|
81
|
+
def find_heredoc(line_number)
|
82
|
+
@heredocs.each { |node, r| return node if r.include?(line_number) }
|
83
|
+
nil
|
60
84
|
end
|
61
85
|
|
62
|
-
def
|
86
|
+
def extract_heredocs(ast)
|
63
87
|
return [] unless ast
|
64
88
|
|
65
89
|
ast.each_node(:str, :dstr, :xstr).select(&:heredoc?).map do |node|
|
66
90
|
body = node.location.heredoc_body
|
67
|
-
|
91
|
+
[node, body.first_line...body.last_line]
|
68
92
|
end
|
69
93
|
end
|
70
94
|
|