rubocop 0.91.1 → 1.1.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 +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)
|