rubocop 0.91.1 → 1.1.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 +8 -5
- data/config/default.yml +143 -56
- data/lib/rubocop.rb +17 -5
- data/lib/rubocop/cached_data.rb +2 -1
- data/lib/rubocop/cli/command/auto_genenerate_config.rb +1 -1
- data/lib/rubocop/cli/command/version.rb +1 -1
- data/lib/rubocop/comment_config.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_regeneration.rb +33 -0
- 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/bundler/duplicated_gem.rb +23 -3
- data/lib/rubocop/cop/commissioner.rb +36 -22
- data/lib/rubocop/cop/corrector.rb +3 -1
- data/lib/rubocop/cop/correctors/line_break_corrector.rb +2 -2
- data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +1 -1
- data/lib/rubocop/cop/force.rb +1 -1
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +10 -10
- data/lib/rubocop/cop/layout/array_alignment.rb +1 -0
- data/lib/rubocop/cop/layout/class_structure.rb +7 -0
- data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/dot_position.rb +6 -9
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +7 -7
- data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -1
- data/lib/rubocop/cop/layout/extra_spacing.rb +1 -2
- data/lib/rubocop/cop/layout/space_around_equals_in_parameter_default.rb +2 -11
- data/lib/rubocop/cop/layout/space_around_operators.rb +4 -1
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +0 -4
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +37 -13
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +2 -0
- data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +18 -1
- data/lib/rubocop/cop/lint/boolean_symbol.rb +3 -0
- data/lib/rubocop/cop/lint/debugger.rb +2 -3
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +77 -0
- data/lib/rubocop/cop/lint/empty_block.rb +46 -0
- data/lib/rubocop/cop/lint/flip_flop.rb +8 -2
- data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +37 -0
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +17 -3
- data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -0
- data/lib/rubocop/cop/lint/number_conversion.rb +46 -13
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +27 -8
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +78 -0
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +95 -0
- data/lib/rubocop/cop/lint/to_json.rb +1 -1
- data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +185 -0
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +2 -2
- data/lib/rubocop/cop/metrics/block_length.rb +3 -1
- data/lib/rubocop/cop/metrics/class_length.rb +14 -6
- data/lib/rubocop/cop/metrics/parameter_lists.rb +4 -1
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +1 -1
- data/lib/rubocop/cop/mixin/line_length_help.rb +1 -1
- data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +1 -1
- data/lib/rubocop/cop/naming/predicate_name.rb +2 -1
- data/lib/rubocop/cop/offense.rb +18 -5
- data/lib/rubocop/cop/security/open.rb +12 -10
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +6 -2
- data/lib/rubocop/cop/style/accessor_grouping.rb +3 -0
- data/lib/rubocop/cop/style/arguments_forwarding.rb +142 -0
- data/lib/rubocop/cop/style/array_coercion.rb +4 -0
- data/lib/rubocop/cop/style/case_like_if.rb +20 -4
- data/lib/rubocop/cop/style/class_equality_comparison.rb +64 -0
- data/lib/rubocop/cop/style/combinable_loops.rb +8 -1
- data/lib/rubocop/cop/style/comment_annotation.rb +6 -0
- data/lib/rubocop/cop/style/date_time.rb +12 -1
- data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +67 -0
- data/lib/rubocop/cop/style/explicit_block_argument.rb +6 -2
- data/lib/rubocop/cop/style/for.rb +0 -4
- data/lib/rubocop/cop/style/format_string_token.rb +48 -3
- 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/method_def_parentheses.rb +0 -4
- data/lib/rubocop/cop/style/mixin_usage.rb +7 -27
- data/lib/rubocop/cop/style/multiple_comparison.rb +54 -7
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +2 -0
- data/lib/rubocop/cop/style/optional_boolean_parameter.rb +11 -3
- data/lib/rubocop/cop/style/raise_args.rb +0 -3
- data/lib/rubocop/cop/style/redundant_begin.rb +36 -8
- data/lib/rubocop/cop/style/redundant_condition.rb +5 -1
- data/lib/rubocop/cop/style/redundant_interpolation.rb +6 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +4 -0
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +45 -24
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -15
- 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/semicolon.rb +3 -0
- data/lib/rubocop/cop/style/string_concatenation.rb +14 -2
- data/lib/rubocop/cop/style/swap_values.rb +108 -0
- data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +3 -1
- data/lib/rubocop/cop/team.rb +6 -1
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/cop/variable_force/branch.rb +0 -4
- data/lib/rubocop/ext/regexp_node.rb +29 -10
- data/lib/rubocop/ext/regexp_parser.rb +77 -0
- data/lib/rubocop/formatter/disabled_config_formatter.rb +12 -5
- data/lib/rubocop/formatter/formatter_set.rb +1 -1
- data/lib/rubocop/formatter/offense_count_formatter.rb +1 -1
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -1
- data/lib/rubocop/magic_comment.rb +2 -2
- data/lib/rubocop/options.rb +22 -17
- data/lib/rubocop/result_cache.rb +8 -2
- data/lib/rubocop/rspec/cop_helper.rb +1 -1
- data/lib/rubocop/rspec/expect_offense.rb +5 -5
- data/lib/rubocop/rspec/shared_contexts.rb +4 -0
- data/lib/rubocop/runner.rb +9 -5
- data/lib/rubocop/target_finder.rb +27 -26
- data/lib/rubocop/target_ruby.rb +1 -1
- data/lib/rubocop/version.rb +61 -6
- metadata +21 -16
- data/lib/rubocop/cop/mixin/regexp_literal_help.rb +0 -43
@@ -20,8 +20,6 @@ module RuboCop
|
|
20
20
|
nil
|
21
21
|
end
|
22
22
|
|
23
|
-
# rubocop:disable Metrics/BlockLength
|
24
|
-
|
25
23
|
# Abstract base class for branch classes.
|
26
24
|
# A branch represents a conditional branch in a scope.
|
27
25
|
#
|
@@ -42,8 +40,6 @@ module RuboCop
|
|
42
40
|
# do_something # no branch
|
43
41
|
# end
|
44
42
|
Base = Struct.new(:child_node, :scope) do
|
45
|
-
# rubocop:enable Metrics/BlockLength
|
46
|
-
|
47
43
|
def self.classes
|
48
44
|
@classes ||= []
|
49
45
|
end
|
@@ -10,21 +10,22 @@ module RuboCop
|
|
10
10
|
end
|
11
11
|
private_constant :ANY
|
12
12
|
|
13
|
-
class << self
|
14
|
-
attr_reader :parsed_cache
|
15
|
-
end
|
16
|
-
@parsed_cache = {}
|
17
|
-
|
18
13
|
# @return [Regexp::Expression::Root, nil]
|
19
|
-
|
20
|
-
|
14
|
+
# Note: we extend Regexp nodes to provide `loc` and `expression`
|
15
|
+
# see `ext/regexp_parser`.
|
16
|
+
attr_reader :parsed_tree
|
21
17
|
|
22
|
-
|
23
|
-
|
24
|
-
|
18
|
+
def assign_properties(*)
|
19
|
+
super
|
20
|
+
|
21
|
+
str = with_interpolations_blanked
|
22
|
+
@parsed_tree = begin
|
23
|
+
Regexp::Parser.parse(str, options: options)
|
25
24
|
rescue StandardError
|
26
25
|
nil
|
27
26
|
end
|
27
|
+
origin = loc.begin.end
|
28
|
+
@parsed_tree&.each_expression(true) { |e| e.origin = origin }
|
28
29
|
end
|
29
30
|
|
30
31
|
def each_capture(named: ANY)
|
@@ -40,6 +41,24 @@ module RuboCop
|
|
40
41
|
self
|
41
42
|
end
|
42
43
|
|
44
|
+
private
|
45
|
+
|
46
|
+
def with_interpolations_blanked
|
47
|
+
# Ignore the trailing regopt node
|
48
|
+
children[0...-1].map do |child|
|
49
|
+
source = child.source
|
50
|
+
|
51
|
+
# We don't want to consider the contents of interpolations as part of the pattern source,
|
52
|
+
# but need to preserve their width, to allow offsets to correctly line up with the
|
53
|
+
# original source: spaces have no effect, and preserve width.
|
54
|
+
if child.begin_type?
|
55
|
+
' ' * source.length
|
56
|
+
else
|
57
|
+
source
|
58
|
+
end
|
59
|
+
end.join
|
60
|
+
end
|
61
|
+
|
43
62
|
AST::RegexpNode.include self
|
44
63
|
end
|
45
64
|
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Ext
|
5
|
+
# Extensions for `regexp_parser` gem
|
6
|
+
module RegexpParser
|
7
|
+
# Source map for RegexpParser nodes
|
8
|
+
class Map < ::Parser::Source::Map
|
9
|
+
attr_reader :body, :quantifier, :begin, :end
|
10
|
+
|
11
|
+
def initialize(expression, body:, quantifier: nil, begin_l: nil, end_l: nil)
|
12
|
+
@begin = begin_l
|
13
|
+
@end = end_l
|
14
|
+
@body = body
|
15
|
+
@quantifier = quantifier
|
16
|
+
super(expression)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module Expression
|
21
|
+
# Add `expression` and `loc` to all `regexp_parser` nodes
|
22
|
+
module Base
|
23
|
+
attr_accessor :origin
|
24
|
+
|
25
|
+
# Shortcut to `loc.expression`
|
26
|
+
def expression
|
27
|
+
@expression ||= origin.adjust(begin_pos: ts, end_pos: ts + full_length)
|
28
|
+
end
|
29
|
+
|
30
|
+
# @returns a location map like `parser` does, with:
|
31
|
+
# - expression: complete expression
|
32
|
+
# - quantifier: for `+`, `{1,2}`, etc.
|
33
|
+
# - begin/end: for `[` and `]` (only CharacterSet for now)
|
34
|
+
#
|
35
|
+
# E.g.
|
36
|
+
# [a-z]{2,}
|
37
|
+
# ^^^^^^^^^ expression
|
38
|
+
# ^^^^ quantifier
|
39
|
+
# ^^^^^ body
|
40
|
+
# ^ begin
|
41
|
+
# ^ end
|
42
|
+
#
|
43
|
+
# Please open issue if you need other locations
|
44
|
+
def loc
|
45
|
+
@loc ||= begin
|
46
|
+
Map.new(expression, **build_location)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def build_location
|
53
|
+
return { body: expression } unless (q = quantifier)
|
54
|
+
|
55
|
+
body = expression.adjust(end_pos: -q.text.length)
|
56
|
+
q_loc = expression.with(begin_pos: body.end_pos)
|
57
|
+
{ body: body, quantifier: q_loc }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Provide `CharacterSet` with `begin` and `end` locations.
|
62
|
+
module CharacterSet
|
63
|
+
def build_location
|
64
|
+
h = super
|
65
|
+
body = h[:body]
|
66
|
+
h.merge!(
|
67
|
+
begin_l: body.with(end_pos: body.begin_pos + 1),
|
68
|
+
end_l: body.with(begin_pos: body.end_pos - 1)
|
69
|
+
)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
::Regexp::Expression::Base.include Expression::Base
|
74
|
+
::Regexp::Expression::CharacterSet.include Expression::CharacterSet
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -32,7 +32,6 @@ module RuboCop
|
|
32
32
|
@exclude_limit_option = @options[:exclude_limit]
|
33
33
|
@exclude_limit = Integer(@exclude_limit_option ||
|
34
34
|
RuboCop::Options::DEFAULT_MAXIMUM_EXCLUSION_ITEMS)
|
35
|
-
@show_offense_counts = !@options[:no_offense_counts]
|
36
35
|
end
|
37
36
|
|
38
37
|
def file_finished(file, offenses)
|
@@ -56,6 +55,14 @@ module RuboCop
|
|
56
55
|
|
57
56
|
private
|
58
57
|
|
58
|
+
def show_timestamp?
|
59
|
+
@options.fetch(:auto_gen_timestamp, true)
|
60
|
+
end
|
61
|
+
|
62
|
+
def show_offense_counts?
|
63
|
+
@options.fetch(:offense_counts, true)
|
64
|
+
end
|
65
|
+
|
59
66
|
def command
|
60
67
|
command = 'rubocop --auto-gen-config'
|
61
68
|
|
@@ -66,15 +73,15 @@ module RuboCop
|
|
66
73
|
format(' --exclude-limit %<limit>d',
|
67
74
|
limit: Integer(@exclude_limit_option))
|
68
75
|
end
|
69
|
-
command += ' --no-offense-counts'
|
76
|
+
command += ' --no-offense-counts' unless show_offense_counts?
|
70
77
|
|
71
|
-
command += ' --no-auto-gen-timestamp'
|
78
|
+
command += ' --no-auto-gen-timestamp' unless show_timestamp?
|
72
79
|
|
73
80
|
command
|
74
81
|
end
|
75
82
|
|
76
83
|
def timestamp
|
77
|
-
|
84
|
+
show_timestamp? ? "on #{Time.now.utc} " : ''
|
78
85
|
end
|
79
86
|
|
80
87
|
def output_offenses
|
@@ -112,7 +119,7 @@ module RuboCop
|
|
112
119
|
end
|
113
120
|
|
114
121
|
def output_cop_comments(output_buffer, cfg, cop_name, offense_count)
|
115
|
-
output_buffer.puts "# Offense count: #{offense_count}" if
|
122
|
+
output_buffer.puts "# Offense count: #{offense_count}" if show_offense_counts?
|
116
123
|
|
117
124
|
cop_class = Cop::Registry.global.find_by_cop_name(cop_name)
|
118
125
|
output_buffer.puts '# Cop supports --auto-correct.' if cop_class&.support_autocorrect?
|
@@ -194,7 +194,7 @@ module RuboCop
|
|
194
194
|
class SimpleComment < MagicComment
|
195
195
|
# Match `encoding` or `coding`
|
196
196
|
def encoding
|
197
|
-
extract(/\A\s*\#.*\b(?:en)?coding: (#{TOKEN})/
|
197
|
+
extract(/\A\s*\#.*\b(?:en)?coding: (#{TOKEN})/io)
|
198
198
|
end
|
199
199
|
|
200
200
|
private
|
@@ -207,7 +207,7 @@ module RuboCop
|
|
207
207
|
# Case-insensitive and dashes/underscores are acceptable.
|
208
208
|
# @see https://git.io/vM7Mg
|
209
209
|
def extract_frozen_string_literal
|
210
|
-
extract(/\A\s*#\s*frozen[_-]string[_-]literal:\s*(#{TOKEN})\s*\z/
|
210
|
+
extract(/\A\s*#\s*frozen[_-]string[_-]literal:\s*(#{TOKEN})\s*\z/io)
|
211
211
|
end
|
212
212
|
end
|
213
213
|
end
|
data/lib/rubocop/options.rb
CHANGED
@@ -114,20 +114,19 @@ module RuboCop
|
|
114
114
|
def add_auto_gen_options(opts)
|
115
115
|
option(opts, '--auto-gen-config')
|
116
116
|
|
117
|
+
option(opts, '--regenerate-todo') do
|
118
|
+
@options.replace(ConfigRegeneration.new.options.merge(@options))
|
119
|
+
end
|
120
|
+
|
117
121
|
option(opts, '--exclude-limit COUNT') do
|
118
122
|
@validator.validate_exclude_limit_option
|
119
123
|
end
|
120
124
|
|
121
125
|
option(opts, '--disable-uncorrectable')
|
122
126
|
|
123
|
-
option(opts, '--no-offense-counts')
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
option(opts, '--auto-gen-only-exclude')
|
128
|
-
option(opts, '--no-auto-gen-timestamp') do
|
129
|
-
@options[:no_auto_gen_timestamp] = true
|
130
|
-
end
|
127
|
+
option(opts, '--[no-]offense-counts')
|
128
|
+
option(opts, '--[no-]auto-gen-only-exclude')
|
129
|
+
option(opts, '--[no-]auto-gen-timestamp')
|
131
130
|
|
132
131
|
option(opts, '--init')
|
133
132
|
end
|
@@ -243,6 +242,9 @@ module RuboCop
|
|
243
242
|
# @api private
|
244
243
|
class OptionsValidator
|
245
244
|
class << self
|
245
|
+
SYNTAX_DEPARTMENTS = %w[Syntax Lint/Syntax].freeze
|
246
|
+
private_constant :SYNTAX_DEPARTMENTS
|
247
|
+
|
246
248
|
# Cop name validation must be done later than option parsing, so it's not
|
247
249
|
# called from within Options.
|
248
250
|
def validate_cop_list(names)
|
@@ -254,7 +256,7 @@ module RuboCop
|
|
254
256
|
names.each do |name|
|
255
257
|
next if cop_names.include?(name)
|
256
258
|
next if departments.include?(name)
|
257
|
-
next if
|
259
|
+
next if SYNTAX_DEPARTMENTS.include?(name)
|
258
260
|
|
259
261
|
raise IncorrectCopNameError, format_message_from(name, cop_names)
|
260
262
|
end
|
@@ -318,7 +320,7 @@ module RuboCop
|
|
318
320
|
|
319
321
|
message = '--%<flag>s can only be used together with --auto-gen-config.'
|
320
322
|
|
321
|
-
%i[exclude_limit
|
323
|
+
%i[exclude_limit offense_counts auto_gen_timestamp
|
322
324
|
auto_gen_only_exclude].each do |option|
|
323
325
|
if @options.key?(option)
|
324
326
|
raise OptionArgumentError,
|
@@ -423,17 +425,20 @@ module RuboCop
|
|
423
425
|
config: 'Specify configuration file.',
|
424
426
|
auto_gen_config: ['Generate a configuration file acting as a',
|
425
427
|
'TODO list.'],
|
426
|
-
|
427
|
-
'
|
428
|
-
|
429
|
-
|
430
|
-
'
|
431
|
-
'
|
428
|
+
regenerate_todo: ['Regenerate the TODO configuration file using',
|
429
|
+
'the last configuration. If there is no existing',
|
430
|
+
'TODO file, acts like --auto-gen-config.'],
|
431
|
+
offense_counts: ['Include offense counts in configuration',
|
432
|
+
'file generated by --auto-gen-config.',
|
433
|
+
'Default is true.'],
|
434
|
+
auto_gen_timestamp:
|
435
|
+
['Include the date and time when the --auto-gen-config',
|
436
|
+
'was run in the file it generates. Default is true.'],
|
432
437
|
auto_gen_only_exclude:
|
433
438
|
['Generate only Exclude parameters and not Max',
|
434
439
|
'when running --auto-gen-config, except if the',
|
435
440
|
'number of files with offenses is bigger than',
|
436
|
-
'exclude-limit.'],
|
441
|
+
'exclude-limit. Default is false.'],
|
437
442
|
exclude_limit: ['Used together with --auto-gen-config to',
|
438
443
|
'set the limit for how many Exclude',
|
439
444
|
"properties to generate. Default is #{MAX_EXCL}."],
|
data/lib/rubocop/result_cache.rb
CHANGED
@@ -95,6 +95,11 @@ module RuboCop
|
|
95
95
|
context_checksum(team, options),
|
96
96
|
file_checksum(file, config_store))
|
97
97
|
@cached_data = CachedData.new(file)
|
98
|
+
@debug = options[:debug]
|
99
|
+
end
|
100
|
+
|
101
|
+
def debug?
|
102
|
+
@debug
|
98
103
|
end
|
99
104
|
|
100
105
|
def valid?
|
@@ -102,6 +107,7 @@ module RuboCop
|
|
102
107
|
end
|
103
108
|
|
104
109
|
def load
|
110
|
+
puts "Loading cache from #{@path}" if debug?
|
105
111
|
@cached_data.from_json(IO.read(@path, encoding: Encoding::UTF_8))
|
106
112
|
end
|
107
113
|
|
@@ -209,8 +215,8 @@ module RuboCop
|
|
209
215
|
# The external dependency checksums are cached per RuboCop team so that
|
210
216
|
# the checksums don't need to be recomputed for each file.
|
211
217
|
def team_checksum(team)
|
212
|
-
@checksum_by_team ||= {}
|
213
|
-
@checksum_by_team[team
|
218
|
+
@checksum_by_team ||= {}.compare_by_identity
|
219
|
+
@checksum_by_team[team] ||= team.external_dependency_checksum
|
214
220
|
end
|
215
221
|
|
216
222
|
# We combine team and options into a single "context" checksum to avoid
|
@@ -133,14 +133,14 @@ module RuboCop
|
|
133
133
|
"#{@processed_source.diagnostics.map(&:render).join("\n")}"
|
134
134
|
end
|
135
135
|
|
136
|
-
offenses = _investigate(cop, @processed_source)
|
136
|
+
@offenses = _investigate(cop, @processed_source)
|
137
137
|
actual_annotations =
|
138
|
-
expected_annotations.with_offense_annotations(offenses)
|
138
|
+
expected_annotations.with_offense_annotations(@offenses)
|
139
139
|
|
140
140
|
expect(actual_annotations).to eq(expected_annotations), ''
|
141
|
-
expect(offenses.map(&:severity).uniq).to eq([severity]) if severity
|
141
|
+
expect(@offenses.map(&:severity).uniq).to eq([severity]) if severity
|
142
142
|
|
143
|
-
offenses
|
143
|
+
@offenses
|
144
144
|
end
|
145
145
|
|
146
146
|
def expect_correction(correction, loop: true)
|
@@ -157,7 +157,7 @@ module RuboCop
|
|
157
157
|
break corrected_source if corrected_source == @processed_source.buffer.source
|
158
158
|
|
159
159
|
if iteration > RuboCop::Runner::MAX_ITERATIONS
|
160
|
-
raise RuboCop::Runner::InfiniteCorrectionLoop.new(@processed_source.path, [])
|
160
|
+
raise RuboCop::Runner::InfiniteCorrectionLoop.new(@processed_source.path, [@offenses])
|
161
161
|
end
|
162
162
|
|
163
163
|
# Prepare for next loop
|
data/lib/rubocop/runner.rb
CHANGED
@@ -16,7 +16,11 @@ module RuboCop
|
|
16
16
|
root_cause = offenses_by_iteration[loop_start..-1]
|
17
17
|
.map { |x| x.map(&:cop_name).uniq.join(', ') }
|
18
18
|
.join(' -> ')
|
19
|
-
|
19
|
+
|
20
|
+
message = 'Infinite loop detected'
|
21
|
+
message += " in #{path}" if path
|
22
|
+
message += " and caused by #{root_cause}" if root_cause
|
23
|
+
super message
|
20
24
|
end
|
21
25
|
end
|
22
26
|
|
@@ -320,8 +324,8 @@ module RuboCop
|
|
320
324
|
end
|
321
325
|
|
322
326
|
def mobilized_cop_classes(config)
|
323
|
-
@mobilized_cop_classes ||= {}
|
324
|
-
@mobilized_cop_classes[config
|
327
|
+
@mobilized_cop_classes ||= {}.compare_by_identity
|
328
|
+
@mobilized_cop_classes[config] ||= begin
|
325
329
|
cop_classes = Cop::Registry.all
|
326
330
|
|
327
331
|
OptionsValidator.new(@options).validate_cop_options
|
@@ -395,8 +399,8 @@ module RuboCop
|
|
395
399
|
# otherwise dormant team that can be used for config- and option-
|
396
400
|
# level caching in ResultCache.
|
397
401
|
def standby_team(config)
|
398
|
-
@team_by_config ||= {}
|
399
|
-
@team_by_config[config
|
402
|
+
@team_by_config ||= {}.compare_by_identity
|
403
|
+
@team_by_config[config] ||=
|
400
404
|
Cop::Team.mobilize(mobilized_cop_classes(config), config, @options)
|
401
405
|
end
|
402
406
|
end
|
@@ -5,6 +5,8 @@ module RuboCop
|
|
5
5
|
# and picking ruby files.
|
6
6
|
# @api private
|
7
7
|
class TargetFinder
|
8
|
+
HIDDEN_PATH_SUBSTRING = "#{File::SEPARATOR}."
|
9
|
+
|
8
10
|
def initialize(config_store, options = {})
|
9
11
|
@config_store = config_store
|
10
12
|
@options = options
|
@@ -55,7 +57,8 @@ module RuboCop
|
|
55
57
|
# Support Windows: Backslashes from command-line -> forward slashes
|
56
58
|
base_dir = base_dir.gsub(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
|
57
59
|
all_files = find_files(base_dir, File::FNM_DOTMATCH)
|
58
|
-
|
60
|
+
# use file.include? for performance optimization
|
61
|
+
hidden_files = all_files.select { |file| file.include?(HIDDEN_PATH_SUBSTRING) }
|
59
62
|
base_dir_config = @config_store.for(base_dir)
|
60
63
|
|
61
64
|
target_files = all_files.select do |file|
|
@@ -78,34 +81,32 @@ module RuboCop
|
|
78
81
|
# the top level directories that are excluded in configuration in the
|
79
82
|
# normal way (dir/**/*).
|
80
83
|
def find_files(base_dir, flags)
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
84
|
+
# get all wanted directories first to improve speed of finding all files
|
85
|
+
exclude_pattern = combined_exclude_glob_patterns(base_dir)
|
86
|
+
dir_flags = flags | File::FNM_PATHNAME | File::FNM_EXTGLOB
|
87
|
+
patterns = wanted_dir_patterns(base_dir, exclude_pattern, dir_flags)
|
88
|
+
patterns.map! { |dir| File.join(dir, '*') }
|
89
|
+
# We need this special case to avoid creating the pattern
|
90
|
+
# /**/* which searches the entire file system.
|
91
|
+
patterns = [File.join(dir, '**/*')] if patterns.empty?
|
92
|
+
|
93
|
+
Dir.glob(patterns, flags).select { |path| FileTest.file?(path) }
|
94
|
+
end
|
95
|
+
|
96
|
+
def wanted_dir_patterns(base_dir, exclude_pattern, flags)
|
97
|
+
dirs = Dir.glob(File.join(base_dir, '*/'), flags)
|
98
|
+
.reject do |dir|
|
99
|
+
dir.end_with?('/./', '/../') || File.fnmatch?(exclude_pattern, dir, flags)
|
93
100
|
end
|
94
|
-
|
101
|
+
dirs.flat_map { |dir| wanted_dir_patterns(dir, exclude_pattern, flags) }
|
102
|
+
.unshift(base_dir)
|
95
103
|
end
|
96
104
|
|
97
|
-
def
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
def excluded_dirs(base_dir)
|
104
|
-
all_cops_config = @config_store.for(base_dir).for_all_cops
|
105
|
-
dir_tree_excludes = all_cops_config['Exclude'].select do |pattern|
|
106
|
-
pattern.is_a?(String) && pattern.end_with?('/**/*')
|
107
|
-
end
|
108
|
-
dir_tree_excludes.map { |pattern| pattern.sub(%r{/\*\*/\*$}, '') }
|
105
|
+
def combined_exclude_glob_patterns(base_dir)
|
106
|
+
exclude = @config_store.for(base_dir).for_all_cops['Exclude']
|
107
|
+
patterns = exclude.select { |pattern| pattern.is_a?(String) && pattern.end_with?('/**/*') }
|
108
|
+
.map { |pattern| pattern.sub("#{base_dir}/", '') }
|
109
|
+
"#{base_dir}/{#{patterns.join(',')}}"
|
109
110
|
end
|
110
111
|
|
111
112
|
def ruby_extension?(file)
|