rubocop 0.84.0 → 0.85.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +10 -14
- data/config/default.yml +33 -15
- data/lib/rubocop.rb +6 -0
- data/lib/rubocop/cli.rb +2 -2
- data/lib/rubocop/cli/command/auto_genenerate_config.rb +2 -2
- data/lib/rubocop/comment_config.rb +1 -1
- data/lib/rubocop/config.rb +3 -1
- data/lib/rubocop/config_loader.rb +1 -1
- data/lib/rubocop/config_loader_resolver.rb +18 -2
- data/lib/rubocop/config_store.rb +12 -2
- data/lib/rubocop/cop/bundler/gem_comment.rb +70 -1
- data/lib/rubocop/cop/commissioner.rb +0 -21
- data/lib/rubocop/cop/cop.rb +36 -21
- data/lib/rubocop/cop/corrector.rb +3 -1
- data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +3 -1
- data/lib/rubocop/cop/layout/case_indentation.rb +3 -3
- data/lib/rubocop/cop/layout/class_structure.rb +19 -16
- data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +2 -2
- data/lib/rubocop/cop/layout/end_of_line.rb +2 -2
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/first_array_element_line_break.rb +1 -1
- data/lib/rubocop/cop/layout/first_parameter_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/hash_alignment.rb +6 -6
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +1 -1
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +20 -103
- data/lib/rubocop/cop/layout/line_length.rb +17 -17
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +3 -1
- data/lib/rubocop/cop/layout/space_around_keyword.rb +2 -2
- data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +3 -1
- data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +3 -1
- data/lib/rubocop/cop/lint/ambiguous_operator.rb +2 -1
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +8 -4
- data/lib/rubocop/cop/lint/ensure_return.rb +1 -1
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +3 -1
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +33 -2
- data/lib/rubocop/cop/lint/loop.rb +1 -1
- data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +69 -0
- data/lib/rubocop/cop/lint/nested_percent_literal.rb +1 -1
- data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +7 -7
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +3 -1
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +3 -3
- data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
- data/lib/rubocop/cop/lint/suppressed_exception.rb +4 -2
- data/lib/rubocop/cop/lint/unreachable_code.rb +1 -1
- data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +1 -1
- data/lib/rubocop/cop/lint/useless_setter_call.rb +1 -1
- data/lib/rubocop/cop/migration/department_name.rb +9 -5
- data/lib/rubocop/cop/mixin/array_min_size.rb +3 -1
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +3 -1
- data/lib/rubocop/cop/mixin/configurable_formatting.rb +1 -1
- data/lib/rubocop/cop/mixin/ignored_pattern.rb +1 -1
- data/lib/rubocop/cop/mixin/line_length_help.rb +1 -1
- data/lib/rubocop/cop/mixin/multiline_element_indentation.rb +3 -1
- data/lib/rubocop/cop/mixin/regexp_literal_help.rb +16 -0
- data/lib/rubocop/cop/mixin/surrounding_space.rb +3 -1
- data/lib/rubocop/cop/mixin/uncommunicative_name.rb +1 -1
- data/lib/rubocop/cop/naming/class_and_module_camel_case.rb +11 -1
- data/lib/rubocop/cop/naming/file_name.rb +26 -11
- data/lib/rubocop/cop/naming/predicate_name.rb +1 -1
- data/lib/rubocop/cop/registry.rb +65 -8
- data/lib/rubocop/cop/style/array_join.rb +1 -1
- data/lib/rubocop/cop/style/bare_percent_literals.rb +1 -1
- data/lib/rubocop/cop/style/copyright.rb +2 -2
- data/lib/rubocop/cop/style/empty_method.rb +1 -1
- data/lib/rubocop/cop/style/exponential_notation.rb +3 -3
- data/lib/rubocop/cop/style/format_string_token.rb +2 -3
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -2
- data/lib/rubocop/cop/style/hash_each_methods.rb +1 -1
- data/lib/rubocop/cop/style/hash_syntax.rb +5 -3
- data/lib/rubocop/cop/style/inline_comment.rb +1 -1
- data/lib/rubocop/cop/style/multiline_memoization.rb +1 -1
- data/lib/rubocop/cop/style/negated_if.rb +3 -3
- data/lib/rubocop/cop/style/negated_unless.rb +3 -3
- data/lib/rubocop/cop/style/non_nil_check.rb +1 -1
- data/lib/rubocop/cop/style/redundant_conditional.rb +4 -3
- data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -1
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +89 -0
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +130 -0
- data/lib/rubocop/cop/style/symbol_array.rb +1 -1
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +3 -3
- data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +3 -3
- data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +13 -13
- data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +3 -3
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +3 -1
- data/lib/rubocop/cop/style/unless_else.rb +1 -1
- data/lib/rubocop/cop/style/when_then.rb +1 -1
- data/lib/rubocop/cop/team.rb +69 -25
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/cop/utils/format_string.rb +18 -0
- data/lib/rubocop/cop/variable_force/branch.rb +3 -1
- data/lib/rubocop/formatter/junit_formatter.rb +14 -4
- data/lib/rubocop/magic_comment.rb +1 -1
- data/lib/rubocop/options.rb +17 -3
- data/lib/rubocop/result_cache.rb +4 -4
- data/lib/rubocop/rspec/cop_helper.rb +2 -23
- data/lib/rubocop/rspec/expect_offense.rb +45 -6
- data/lib/rubocop/rspec/shared_contexts.rb +2 -2
- data/lib/rubocop/runner.rb +14 -10
- data/lib/rubocop/target_finder.rb +3 -1
- data/lib/rubocop/target_ruby.rb +4 -1
- data/lib/rubocop/version.rb +1 -1
- metadata +23 -5
@@ -122,7 +122,9 @@ module RuboCop
|
|
122
122
|
|
123
123
|
return unless first_offense
|
124
124
|
|
125
|
-
|
125
|
+
if unused_variables_only?(first_offense, variables)
|
126
|
+
return unused_range(node.type, mlhs_node, right)
|
127
|
+
end
|
126
128
|
|
127
129
|
return range_for_parentheses(first_offense, mlhs_node) if Util.parentheses?(mlhs_node)
|
128
130
|
|
data/lib/rubocop/cop/team.rb
CHANGED
@@ -2,7 +2,13 @@
|
|
2
2
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
|
-
#
|
5
|
+
# A group of cops, ready to be called on duty to inspect files.
|
6
|
+
# Team is responsible for selecting only relevant cops to be sent on duty,
|
7
|
+
# as well as insuring that the needed forces are sent along with them.
|
8
|
+
#
|
9
|
+
# For performance reasons, Team will first dispatch cops & forces in two groups,
|
10
|
+
# first the ones needed for autocorrection (if any), then the rest
|
11
|
+
# (unless autocorrections happened).
|
6
12
|
class Team
|
7
13
|
DEFAULT_OPTIONS = {
|
8
14
|
auto_correct: false,
|
@@ -11,12 +17,12 @@ module RuboCop
|
|
11
17
|
|
12
18
|
Investigation = Struct.new(:offenses, :errors)
|
13
19
|
|
14
|
-
attr_reader :errors, :warnings, :updated_source_file
|
20
|
+
attr_reader :errors, :warnings, :updated_source_file, :cops
|
15
21
|
|
16
22
|
alias updated_source_file? updated_source_file
|
17
23
|
|
18
|
-
def initialize(
|
19
|
-
@
|
24
|
+
def initialize(cops, config = nil, options = nil)
|
25
|
+
@cops = cops
|
20
26
|
@config = config
|
21
27
|
@options = options || DEFAULT_OPTIONS
|
22
28
|
@errors = []
|
@@ -25,6 +31,31 @@ module RuboCop
|
|
25
31
|
validate_config
|
26
32
|
end
|
27
33
|
|
34
|
+
# @return [Team]
|
35
|
+
def self.new(cop_or_classes, config, options = {})
|
36
|
+
# Support v0 api:
|
37
|
+
return mobilize(cop_or_classes, config, options) if cop_or_classes.first.is_a?(Class)
|
38
|
+
|
39
|
+
super
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return [Team] with cops assembled from the given `cop_classes`
|
43
|
+
def self.mobilize(cop_classes, config, options = nil)
|
44
|
+
options ||= DEFAULT_OPTIONS
|
45
|
+
cops = mobilize_cops(cop_classes, config, options)
|
46
|
+
new(cops, config, options)
|
47
|
+
end
|
48
|
+
|
49
|
+
# @return [Array<Cop::Cop>]
|
50
|
+
def self.mobilize_cops(cop_classes, config, options = nil)
|
51
|
+
options ||= DEFAULT_OPTIONS
|
52
|
+
only = options.fetch(:only, [])
|
53
|
+
safe = options.fetch(:safe, false)
|
54
|
+
cop_classes.enabled(config, only, safe).map do |cop_class|
|
55
|
+
cop_class.new(config, options)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
28
59
|
def autocorrect?
|
29
60
|
@options[:auto_correct]
|
30
61
|
end
|
@@ -44,14 +75,6 @@ module RuboCop
|
|
44
75
|
offenses(processed_source)
|
45
76
|
end
|
46
77
|
|
47
|
-
def cops
|
48
|
-
only = @options.fetch(:only, [])
|
49
|
-
safe = @options.fetch(:safe, false)
|
50
|
-
@cops ||= @cop_classes.enabled(@config, only, safe).map do |cop_class|
|
51
|
-
cop_class.new(@config, @options)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
78
|
def forces
|
56
79
|
@forces ||= forces_for(cops)
|
57
80
|
end
|
@@ -93,21 +116,23 @@ module RuboCop
|
|
93
116
|
|
94
117
|
private
|
95
118
|
|
96
|
-
def offenses(processed_source)
|
119
|
+
def offenses(processed_source) # rubocop:disable Metrics/AbcSize
|
97
120
|
# The autocorrection process may have to be repeated multiple times
|
98
121
|
# until there are no corrections left to perform
|
99
122
|
# To speed things up, run auto-correcting cops by themselves, and only
|
100
123
|
# run the other cops when no corrections are left
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
124
|
+
on_duty = roundup_relevant_cops(processed_source.file_path)
|
125
|
+
|
126
|
+
autocorrect_cops, other_cops = on_duty.partition(&:autocorrect?)
|
127
|
+
|
128
|
+
autocorrect = investigate(autocorrect_cops, processed_source)
|
129
|
+
|
130
|
+
if autocorrect(processed_source.buffer, autocorrect_cops)
|
131
|
+
# We corrected some errors. Another round of inspection will be
|
132
|
+
# done, and any other offenses will be caught then, so we don't
|
133
|
+
# need to continue.
|
134
|
+
return autocorrect.offenses
|
135
|
+
end
|
111
136
|
|
112
137
|
other = investigate(other_cops, processed_source)
|
113
138
|
|
@@ -120,13 +145,32 @@ module RuboCop
|
|
120
145
|
def investigate(cops, processed_source)
|
121
146
|
return Investigation.new([], {}) if cops.empty?
|
122
147
|
|
123
|
-
commissioner = Commissioner.new(cops, forces_for(cops))
|
148
|
+
commissioner = Commissioner.new(cops, forces_for(cops), @options)
|
124
149
|
offenses = commissioner.investigate(processed_source)
|
125
|
-
yield offenses if block_given?
|
126
150
|
|
127
151
|
Investigation.new(offenses, commissioner.errors)
|
128
152
|
end
|
129
153
|
|
154
|
+
def roundup_relevant_cops(filename)
|
155
|
+
cops.reject do |cop|
|
156
|
+
cop.excluded_file?(filename) ||
|
157
|
+
!support_target_ruby_version?(cop) ||
|
158
|
+
!support_target_rails_version?(cop)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def support_target_ruby_version?(cop)
|
163
|
+
return true unless cop.class.respond_to?(:support_target_ruby_version?)
|
164
|
+
|
165
|
+
cop.class.support_target_ruby_version?(cop.target_ruby_version)
|
166
|
+
end
|
167
|
+
|
168
|
+
def support_target_rails_version?(cop)
|
169
|
+
return true unless cop.class.respond_to?(:support_target_rails_version?)
|
170
|
+
|
171
|
+
cop.class.support_target_rails_version?(cop.target_rails_version)
|
172
|
+
end
|
173
|
+
|
130
174
|
def autocorrect_all_cops(buffer, cops)
|
131
175
|
corrector = Corrector.new(buffer)
|
132
176
|
|
data/lib/rubocop/cop/util.rb
CHANGED
@@ -108,7 +108,7 @@ module RuboCop
|
|
108
108
|
end
|
109
109
|
|
110
110
|
def trim_string_interporation_escape_character(str)
|
111
|
-
str.gsub(
|
111
|
+
str.gsub(/\\\#\{(.*?)\}/) { "\#{#{Regexp.last_match(1)}}" }
|
112
112
|
end
|
113
113
|
|
114
114
|
def interpret_string_escapes(string)
|
@@ -97,6 +97,10 @@ module RuboCop
|
|
97
97
|
@format_sequences ||= parse
|
98
98
|
end
|
99
99
|
|
100
|
+
def valid?
|
101
|
+
!mixed_formats?
|
102
|
+
end
|
103
|
+
|
100
104
|
def named_interpolation?
|
101
105
|
format_sequences.any?(&:name)
|
102
106
|
end
|
@@ -114,6 +118,20 @@ module RuboCop
|
|
114
118
|
)
|
115
119
|
end
|
116
120
|
end
|
121
|
+
|
122
|
+
def mixed_formats?
|
123
|
+
formats = format_sequences.map do |seq|
|
124
|
+
if seq.name
|
125
|
+
:named
|
126
|
+
elsif seq.max_digit_dollar_num
|
127
|
+
:numbered
|
128
|
+
else
|
129
|
+
:unnumbered
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
formats.uniq.size > 1
|
134
|
+
end
|
117
135
|
end
|
118
136
|
end
|
119
137
|
end
|
@@ -109,7 +109,9 @@ module RuboCop
|
|
109
109
|
return false if may_jump_to_other_branch?
|
110
110
|
|
111
111
|
other.each_ancestor(include_self: true) do |other_ancestor|
|
112
|
-
|
112
|
+
if control_node.equal?(other_ancestor.control_node)
|
113
|
+
return !child_node.equal?(other_ancestor.child_node)
|
114
|
+
end
|
113
115
|
end
|
114
116
|
|
115
117
|
if parent
|
@@ -35,19 +35,29 @@ module RuboCop
|
|
35
35
|
#
|
36
36
|
# In the future, it would be preferable to return only enabled cops.
|
37
37
|
Cop::Cop.all.each do |cop|
|
38
|
+
target_offenses = offenses_for_cop(offenses, cop)
|
39
|
+
|
40
|
+
next unless relevant_for_output?(options, target_offenses)
|
41
|
+
|
38
42
|
REXML::Element.new('testcase', @testsuite).tap do |testcase|
|
39
43
|
testcase.attributes['classname'] = classname_attribute_value(file)
|
40
44
|
testcase.attributes['name'] = cop.cop_name
|
41
45
|
|
42
|
-
target_offenses = offenses.select do |offense|
|
43
|
-
offense.cop_name == cop.cop_name
|
44
|
-
end
|
45
|
-
|
46
46
|
add_failure_to(testcase, target_offenses, cop.cop_name)
|
47
47
|
end
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
+
def relevant_for_output?(options, target_offenses)
|
52
|
+
!options[:display_only_failed] || target_offenses.any?
|
53
|
+
end
|
54
|
+
|
55
|
+
def offenses_for_cop(all_offenses, cop)
|
56
|
+
all_offenses.select do |offense|
|
57
|
+
offense.cop_name == cop.cop_name
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
51
61
|
def classname_attribute_value(file)
|
52
62
|
file.gsub(/\.rb\Z/, '').gsub("#{Dir.pwd}/", '').tr('/', '.')
|
53
63
|
end
|
@@ -133,7 +133,7 @@ module RuboCop
|
|
133
133
|
# @see https://www.gnu.org/software/emacs/manual/html_node/emacs/Specify-Coding.html
|
134
134
|
# @see https://git.io/vMCXh Emacs handling in Ruby's parse.y
|
135
135
|
class EmacsComment < EditorComment
|
136
|
-
FORMAT =
|
136
|
+
FORMAT = /-\*-(.+)-\*-/.freeze
|
137
137
|
SEPARATOR = ';'
|
138
138
|
OPERATOR = ':'
|
139
139
|
|
data/lib/rubocop/options.rb
CHANGED
@@ -143,6 +143,8 @@ module RuboCop
|
|
143
143
|
@options[:output_path] = path
|
144
144
|
end
|
145
145
|
end
|
146
|
+
|
147
|
+
option(opts, '--display-only-failed')
|
146
148
|
end
|
147
149
|
|
148
150
|
def add_severity_option(opts)
|
@@ -276,7 +278,9 @@ module RuboCop
|
|
276
278
|
'be used with --only.'
|
277
279
|
end
|
278
280
|
raise OptionArgumentError, 'Syntax checking cannot be turned off.' if except_syntax?
|
279
|
-
|
281
|
+
unless boolean_or_empty_cache?
|
282
|
+
raise OptionArgumentError, '-C/--cache argument must be true or false'
|
283
|
+
end
|
280
284
|
|
281
285
|
if display_only_fail_level_offenses_with_autocorrect?
|
282
286
|
raise OptionArgumentError, '--autocorrect cannot be used with ' \
|
@@ -284,6 +288,7 @@ module RuboCop
|
|
284
288
|
end
|
285
289
|
validate_auto_gen_config
|
286
290
|
validate_auto_correct
|
291
|
+
validate_display_only_failed
|
287
292
|
validate_parallel
|
288
293
|
|
289
294
|
return if incompatible_options.size <= 1
|
@@ -307,13 +312,20 @@ module RuboCop
|
|
307
312
|
end
|
308
313
|
end
|
309
314
|
|
315
|
+
def validate_display_only_failed
|
316
|
+
return unless @options.key?(:display_only_failed)
|
317
|
+
return if @options[:format] == 'junit'
|
318
|
+
|
319
|
+
raise OptionArgumentError,
|
320
|
+
format('--display-only-failed can only be used together with --format junit.')
|
321
|
+
end
|
322
|
+
|
310
323
|
def validate_auto_correct
|
311
324
|
return if @options.key?(:auto_correct)
|
312
325
|
return unless @options.key?(:disable_uncorrectable)
|
313
326
|
|
314
327
|
raise OptionArgumentError,
|
315
|
-
format('
|
316
|
-
flag: '--disable-uncorrectable')
|
328
|
+
format('--disable-uncorrectable can only be used together with --auto-correct.')
|
317
329
|
end
|
318
330
|
|
319
331
|
def validate_parallel
|
@@ -429,6 +441,8 @@ module RuboCop
|
|
429
441
|
'if no format is specified.'],
|
430
442
|
fail_level: ['Minimum severity (A/R/C/W/E/F) for exit',
|
431
443
|
'with error code.'],
|
444
|
+
display_only_failed: ['Only output offense messages. Omit passing',
|
445
|
+
'cops. Only valid for --format junit.'],
|
432
446
|
display_only_fail_level_offenses:
|
433
447
|
['Only output offense messages at',
|
434
448
|
'the specified --fail-level or above'],
|
data/lib/rubocop/result_cache.rb
CHANGED
@@ -33,7 +33,7 @@ module RuboCop
|
|
33
33
|
|
34
34
|
def requires_file_removal?(file_count, config_store)
|
35
35
|
file_count > 1 &&
|
36
|
-
file_count > config_store.
|
36
|
+
file_count > config_store.for_dir('.').for_all_cops['MaxFilesInCache']
|
37
37
|
end
|
38
38
|
|
39
39
|
def remove_oldest_files(files, dirs, cache_root, verbose)
|
@@ -60,7 +60,7 @@ module RuboCop
|
|
60
60
|
end
|
61
61
|
|
62
62
|
def self.cache_root(config_store)
|
63
|
-
root = config_store.
|
63
|
+
root = config_store.for_dir('.').for_all_cops['CacheRootDirectory']
|
64
64
|
root ||= if ENV.key?('XDG_CACHE_HOME')
|
65
65
|
# Include user ID in the path to make sure the user has write
|
66
66
|
# access.
|
@@ -72,7 +72,7 @@ module RuboCop
|
|
72
72
|
end
|
73
73
|
|
74
74
|
def self.allow_symlinks_in_cache_location?(config_store)
|
75
|
-
config_store.
|
75
|
+
config_store.for_dir('.').for_all_cops['AllowSymlinksInCacheRootDirectory']
|
76
76
|
end
|
77
77
|
|
78
78
|
def initialize(file, team, options, config_store, cache_root = nil)
|
@@ -143,7 +143,7 @@ module RuboCop
|
|
143
143
|
digester = Digest::SHA1.new
|
144
144
|
mode = File.stat(file).mode
|
145
145
|
digester.update(
|
146
|
-
"#{file}#{mode}#{config_store.
|
146
|
+
"#{file}#{mode}#{config_store.for_file(file).signature}"
|
147
147
|
)
|
148
148
|
digester.file(file)
|
149
149
|
digester.hexdigest
|
@@ -48,30 +48,9 @@ module CopHelper
|
|
48
48
|
corrector.rewrite
|
49
49
|
end
|
50
50
|
|
51
|
-
def autocorrect_source_with_loop(source, file = nil)
|
52
|
-
cnt = 0
|
53
|
-
loop do
|
54
|
-
cop.instance_variable_set(:@corrections, [])
|
55
|
-
new_source = autocorrect_source(source, file)
|
56
|
-
return new_source if new_source == source
|
57
|
-
|
58
|
-
source = new_source
|
59
|
-
cnt += 1
|
60
|
-
raise RuboCop::Runner::InfiniteCorrectionLoop.new(file, []) if cnt > RuboCop::Runner::MAX_ITERATIONS
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
51
|
def _investigate(cop, processed_source)
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
instances << klass.new([cop])
|
69
|
-
end
|
70
|
-
|
71
|
-
commissioner =
|
72
|
-
RuboCop::Cop::Commissioner.new([cop], forces, raise_error: true)
|
73
|
-
commissioner.investigate(processed_source)
|
74
|
-
commissioner
|
52
|
+
team = RuboCop::Cop::Team.new([cop], nil, raise_error: true)
|
53
|
+
team.inspect_file(processed_source)
|
75
54
|
end
|
76
55
|
end
|
77
56
|
|
@@ -71,9 +71,27 @@ module RuboCop
|
|
71
71
|
# RUBY
|
72
72
|
#
|
73
73
|
# expect_no_corrections
|
74
|
+
#
|
75
|
+
# If your code has variables of different lengths, you can use `%{foo}`
|
76
|
+
# and `^{foo}` to format your template:
|
77
|
+
#
|
78
|
+
# %w[raise fail].each do |keyword|
|
79
|
+
# expect_offense(<<~RUBY, keyword: keyword)
|
80
|
+
# %{keyword}(RuntimeError, msg)
|
81
|
+
# ^{keyword}^^^^^^^^^^^^^^^^^^^ Redundant `RuntimeError` argument can be removed.
|
82
|
+
# RUBY
|
74
83
|
module ExpectOffense
|
84
|
+
def format_offense(source, **replacements)
|
85
|
+
replacements.each do |keyword, value|
|
86
|
+
source = source.gsub("%{#{keyword}}", value)
|
87
|
+
.gsub("^{#{keyword}}", '^' * value.size)
|
88
|
+
end
|
89
|
+
source
|
90
|
+
end
|
91
|
+
|
75
92
|
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
76
|
-
def expect_offense(source, file = nil)
|
93
|
+
def expect_offense(source, file = nil, **replacements)
|
94
|
+
source = format_offense(source, **replacements)
|
77
95
|
RuboCop::Formatter::DisabledConfigFormatter
|
78
96
|
.config_to_allow_offenses = {}
|
79
97
|
RuboCop::Formatter::DisabledConfigFormatter.detected_styles = {}
|
@@ -96,17 +114,38 @@ module RuboCop
|
|
96
114
|
|
97
115
|
expect(actual_annotations.to_s).to eq(expected_annotations.to_s)
|
98
116
|
end
|
99
|
-
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
100
117
|
|
101
|
-
def expect_correction(correction)
|
118
|
+
def expect_correction(correction, loop: true)
|
102
119
|
raise '`expect_correction` must follow `expect_offense`' unless @processed_source
|
103
120
|
|
104
|
-
|
105
|
-
|
106
|
-
|
121
|
+
iteration = 0
|
122
|
+
new_source = loop do
|
123
|
+
iteration += 1
|
124
|
+
|
125
|
+
corrector =
|
126
|
+
RuboCop::Cop::Corrector.new(@processed_source.buffer, cop.corrections)
|
127
|
+
corrected_source = corrector.rewrite
|
128
|
+
|
129
|
+
break corrected_source unless loop
|
130
|
+
break corrected_source if cop.corrections.empty?
|
131
|
+
break corrected_source if corrected_source == @processed_source.buffer.source
|
132
|
+
|
133
|
+
if iteration > RuboCop::Runner::MAX_ITERATIONS
|
134
|
+
raise RuboCop::Runner::InfiniteCorrectionLoop.new(@processed_source.path, [])
|
135
|
+
end
|
136
|
+
|
137
|
+
# Prepare for next loop
|
138
|
+
cop.instance_variable_set(:@corrections, [])
|
139
|
+
# Cache invalidation. This is bad!
|
140
|
+
cop.instance_variable_set(:@token_table, nil)
|
141
|
+
@processed_source = parse_source(corrected_source,
|
142
|
+
@processed_source.path)
|
143
|
+
_investigate(cop, @processed_source)
|
144
|
+
end
|
107
145
|
|
108
146
|
expect(new_source).to eq(correction)
|
109
147
|
end
|
148
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
110
149
|
|
111
150
|
def expect_no_corrections
|
112
151
|
raise '`expect_no_corrections` must follow `expect_offense`' unless @processed_source
|