rubocop 0.40.0 → 0.41.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rubocop might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +7 -1014
- data/config/default.yml +61 -5
- data/config/disabled.yml +6 -0
- data/config/enabled.yml +63 -4
- data/lib/rubocop.rb +17 -1
- data/lib/rubocop/ast_node.rb +56 -42
- data/lib/rubocop/ast_node/traversal.rb +3 -3
- data/lib/rubocop/cli.rb +14 -9
- data/lib/rubocop/comment_config.rb +85 -32
- data/lib/rubocop/config.rb +29 -8
- data/lib/rubocop/config_loader.rb +1 -1
- data/lib/rubocop/cop/cop.rb +1 -1
- data/lib/rubocop/cop/corrector.rb +13 -0
- data/lib/rubocop/cop/lint/block_alignment.rb +25 -11
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +5 -2
- data/lib/rubocop/cop/lint/inherit_exception.rb +69 -0
- data/lib/rubocop/cop/lint/percent_string_array.rb +60 -0
- data/lib/rubocop/cop/lint/percent_symbol_array.rb +57 -0
- data/lib/rubocop/cop/lint/shadowed_exception.rb +95 -0
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +28 -13
- data/lib/rubocop/cop/mixin/autocorrect_alignment.rb +25 -19
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +16 -8
- data/lib/rubocop/cop/mixin/if_node.rb +1 -2
- data/lib/rubocop/cop/mixin/integer_node.rb +13 -0
- data/lib/rubocop/cop/mixin/match_range.rb +26 -0
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +16 -7
- data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +18 -1
- data/lib/rubocop/cop/mixin/negative_conditional.rb +6 -4
- data/lib/rubocop/cop/mixin/percent_literal.rb +10 -0
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +24 -6
- data/lib/rubocop/cop/mixin/space_before_punctuation.rb +20 -7
- data/lib/rubocop/cop/mixin/string_literals_help.rb +2 -2
- data/lib/rubocop/cop/mixin/trailing_comma.rb +34 -20
- data/lib/rubocop/cop/performance/flat_map.rb +23 -10
- data/lib/rubocop/cop/performance/push_splat.rb +47 -0
- data/lib/rubocop/cop/performance/redundant_block_call.rb +24 -1
- data/lib/rubocop/cop/performance/redundant_merge.rb +3 -5
- data/lib/rubocop/cop/performance/sample.rb +15 -11
- data/lib/rubocop/cop/rails/exit.rb +62 -0
- data/lib/rubocop/cop/rails/output_safety.rb +45 -0
- data/lib/rubocop/cop/rails/pluralization_grammar.rb +12 -4
- data/lib/rubocop/cop/rails/request_referer.rb +40 -0
- data/lib/rubocop/cop/rails/uniq_before_pluck.rb +63 -28
- data/lib/rubocop/cop/rails/validation.rb +37 -23
- data/lib/rubocop/cop/style/alias.rb +10 -6
- data/lib/rubocop/cop/style/bare_percent_literals.rb +18 -7
- data/lib/rubocop/cop/style/block_delimiters.rb +15 -22
- data/lib/rubocop/cop/style/closing_parenthesis_indentation.rb +19 -8
- data/lib/rubocop/cop/style/comment_indentation.rb +13 -5
- data/lib/rubocop/cop/style/conditional_assignment.rb +111 -59
- data/lib/rubocop/cop/style/documentation.rb +7 -1
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +43 -0
- data/lib/rubocop/cop/style/each_with_object.rb +25 -14
- data/lib/rubocop/cop/style/empty_else.rb +6 -10
- data/lib/rubocop/cop/style/extra_spacing.rb +20 -3
- data/lib/rubocop/cop/style/file_name.rb +16 -4
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
- data/lib/rubocop/cop/style/hash_syntax.rb +9 -2
- data/lib/rubocop/cop/style/if_unless_modifier.rb +20 -13
- data/lib/rubocop/cop/style/implicit_runtime_error.rb +32 -0
- data/lib/rubocop/cop/style/infinite_loop.rb +42 -5
- data/lib/rubocop/cop/style/lambda.rb +22 -0
- data/lib/rubocop/cop/style/method_def_parentheses.rb +12 -4
- data/lib/rubocop/cop/style/module_function.rb +28 -6
- data/lib/rubocop/cop/style/multiline_method_call_indentation.rb +49 -12
- data/lib/rubocop/cop/style/mutable_constant.rb +8 -1
- data/lib/rubocop/cop/style/nested_modifier.rb +1 -1
- data/lib/rubocop/cop/style/next.rb +43 -31
- data/lib/rubocop/cop/style/not.rb +33 -13
- data/lib/rubocop/cop/style/numeric_literal_prefix.rb +92 -0
- data/lib/rubocop/cop/style/numeric_literals.rb +1 -4
- data/lib/rubocop/cop/style/parallel_assignment.rb +26 -8
- data/lib/rubocop/cop/style/{deprecated_hash_methods.rb → preferred_hash_methods.rb} +8 -8
- data/lib/rubocop/cop/style/redundant_parentheses.rb +29 -19
- data/lib/rubocop/cop/style/redundant_self.rb +13 -6
- data/lib/rubocop/cop/style/space_after_not.rb +7 -5
- data/lib/rubocop/cop/style/space_around_keyword.rb +6 -0
- data/lib/rubocop/cop/style/space_around_operators.rb +5 -1
- data/lib/rubocop/cop/style/space_before_first_arg.rb +21 -9
- data/lib/rubocop/cop/style/space_inside_array_percent_literal.rb +53 -0
- data/lib/rubocop/cop/style/space_inside_block_braces.rb +2 -2
- data/lib/rubocop/cop/style/space_inside_hash_literal_braces.rb +26 -6
- data/lib/rubocop/cop/style/space_inside_percent_literal_delimiters.rb +64 -0
- data/lib/rubocop/cop/style/string_literals.rb +37 -8
- data/lib/rubocop/cop/style/symbol_array.rb +21 -12
- data/lib/rubocop/cop/style/symbol_proc.rb +26 -19
- data/lib/rubocop/cop/style/word_array.rb +1 -5
- data/lib/rubocop/cop/style/zero_length_predicate.rb +6 -6
- data/lib/rubocop/cop/team.rb +40 -27
- data/lib/rubocop/cop/util.rb +13 -42
- data/lib/rubocop/formatter/disabled_config_formatter.rb +37 -14
- data/lib/rubocop/formatter/html_formatter.rb +3 -7
- data/lib/rubocop/result_cache.rb +18 -4
- data/{spec/support → lib/rubocop/rspec}/cop_helper.rb +3 -0
- data/lib/rubocop/rspec/host_environment_simulation_helper.rb +33 -0
- data/lib/rubocop/rspec/shared_contexts.rb +75 -0
- data/lib/rubocop/rspec/shared_examples.rb +101 -0
- data/lib/rubocop/rspec/support.rb +9 -0
- data/lib/rubocop/runner.rb +2 -2
- data/lib/rubocop/string_interpreter.rb +58 -0
- data/lib/rubocop/version.rb +1 -1
- metadata +27 -7
@@ -19,33 +19,18 @@ module RuboCop
|
|
19
19
|
|
20
20
|
def on_block(node)
|
21
21
|
block_send_or_super, block_args, block_body = *node
|
22
|
-
|
23
|
-
if super?(block_send_or_super)
|
24
|
-
bmethod_name = :super
|
25
|
-
else
|
26
|
-
_breceiver, bmethod_name, _bargs = *block_send_or_super
|
27
|
-
end
|
22
|
+
block_method_name = resolve_block_method_name(block_send_or_super)
|
28
23
|
|
29
24
|
# TODO: Rails-specific handling that we should probably make
|
30
25
|
# configurable - https://github.com/bbatsov/rubocop/issues/1485
|
31
26
|
# we should ignore lambdas & procs
|
32
27
|
return if block_send_or_super == PROC_NODE
|
33
|
-
return if [:lambda, :proc].include?(
|
34
|
-
return if ignored_method?(
|
28
|
+
return if [:lambda, :proc].include?(block_method_name)
|
29
|
+
return if ignored_method?(block_method_name)
|
35
30
|
return unless can_shorten?(block_args, block_body)
|
36
31
|
|
37
32
|
_receiver, method_name, _args = *block_body
|
38
|
-
|
39
|
-
sb = node.source_range.source_buffer
|
40
|
-
block_start = node.loc.begin.begin_pos
|
41
|
-
block_end = node.loc.end.end_pos
|
42
|
-
range = Parser::Source::Range.new(sb, block_start, block_end)
|
43
|
-
|
44
|
-
add_offense(node,
|
45
|
-
range,
|
46
|
-
format(MSG,
|
47
|
-
method_name,
|
48
|
-
bmethod_name))
|
33
|
+
offense(node, method_name, block_method_name)
|
49
34
|
end
|
50
35
|
|
51
36
|
def autocorrect(node)
|
@@ -62,6 +47,28 @@ module RuboCop
|
|
62
47
|
end
|
63
48
|
end
|
64
49
|
|
50
|
+
private
|
51
|
+
|
52
|
+
def resolve_block_method_name(block_send_or_super)
|
53
|
+
return :super if super?(block_send_or_super)
|
54
|
+
|
55
|
+
_receiver, method_name, _args = *block_send_or_super
|
56
|
+
method_name
|
57
|
+
end
|
58
|
+
|
59
|
+
def offense(node, method_name, block_method_name)
|
60
|
+
sb = node.source_range.source_buffer
|
61
|
+
block_start = node.loc.begin.begin_pos
|
62
|
+
block_end = node.loc.end.end_pos
|
63
|
+
range = Parser::Source::Range.new(sb, block_start, block_end)
|
64
|
+
|
65
|
+
add_offense(node,
|
66
|
+
range,
|
67
|
+
format(MSG,
|
68
|
+
method_name,
|
69
|
+
block_method_name))
|
70
|
+
end
|
71
|
+
|
65
72
|
def autocorrect_method(corrector, node, args, method_name)
|
66
73
|
if args.empty?
|
67
74
|
autocorrect_no_args(corrector, node, method_name)
|
@@ -27,7 +27,7 @@ module RuboCop
|
|
27
27
|
def autocorrect(node)
|
28
28
|
words = node.children
|
29
29
|
if style == :percent
|
30
|
-
escape = words.any? { |w|
|
30
|
+
escape = words.any? { |w| needs_escaping?(w.children[0]) }
|
31
31
|
char = escape ? 'W' : 'w'
|
32
32
|
contents = autocorrect_words(words, escape, node.loc.line)
|
33
33
|
lambda do |corrector|
|
@@ -107,10 +107,6 @@ module RuboCop
|
|
107
107
|
end.join(' ')
|
108
108
|
end
|
109
109
|
|
110
|
-
def escape_string(string)
|
111
|
-
string.inspect[1..-2].tap { |s| s.gsub!(/\\"/, '"') }
|
112
|
-
end
|
113
|
-
|
114
110
|
def style_detected(style, ary_size)
|
115
111
|
cfg = config_to_allow_offenses
|
116
112
|
return if cfg['Enabled'] == false
|
@@ -41,15 +41,15 @@ module RuboCop
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def_node_matcher :zero_length_predicate, <<-END
|
44
|
-
{(send (send
|
45
|
-
(send (int $0) $:== (send
|
46
|
-
(send (send
|
47
|
-
(send (int $1) $:> (send
|
44
|
+
{(send (send (...) ${:length :size}) $:== (int $0))
|
45
|
+
(send (int $0) $:== (send (...) ${:length :size}))
|
46
|
+
(send (send (...) ${:length :size}) $:< (int $1))
|
47
|
+
(send (int $1) $:> (send (...) ${:length :size}))}
|
48
48
|
END
|
49
49
|
|
50
50
|
def_node_matcher :nonzero_length_predicate, <<-END
|
51
|
-
{(send (send
|
52
|
-
(send (int $0) ${:< :!=} (send
|
51
|
+
{(send (send (...) ${:length :size}) ${:> :!=} (int $0))
|
52
|
+
(send (int $0) ${:< :!=} (send (...) ${:length :size}))}
|
53
53
|
END
|
54
54
|
|
55
55
|
def autocorrect(node)
|
data/lib/rubocop/cop/team.rb
CHANGED
@@ -9,7 +9,9 @@ module RuboCop
|
|
9
9
|
# bad things are liable to happen
|
10
10
|
INCOMPATIBLE_COPS = {
|
11
11
|
Style::SymbolProc => [Style::SpaceBeforeBlockBraces],
|
12
|
-
Style::SpaceBeforeBlockBraces => [Style::SymbolProc]
|
12
|
+
Style::SpaceBeforeBlockBraces => [Style::SymbolProc],
|
13
|
+
Style::LineEndConcatenation => [Style::UnneededInterpolation],
|
14
|
+
Style::UnneededInterpolation => [Style::LineEndConcatenation]
|
13
15
|
}.freeze
|
14
16
|
|
15
17
|
DEFAULT_OPTIONS = {
|
@@ -17,6 +19,8 @@ module RuboCop
|
|
17
19
|
debug: false
|
18
20
|
}.freeze
|
19
21
|
|
22
|
+
Investigation = Struct.new(:offenses, :errors)
|
23
|
+
|
20
24
|
attr_reader :errors, :warnings, :updated_source_file
|
21
25
|
|
22
26
|
alias updated_source_file? updated_source_file
|
@@ -45,32 +49,7 @@ module RuboCop
|
|
45
49
|
return Lint::Syntax.offenses_from_processed_source(processed_source)
|
46
50
|
end
|
47
51
|
|
48
|
-
|
49
|
-
# until there are no corrections left to perform
|
50
|
-
# To speed things up, run auto-correcting cops by themselves, and only
|
51
|
-
# run the other cops when no corrections are left
|
52
|
-
autocorrect_cops, other_cops = cops.partition(&:autocorrect?)
|
53
|
-
offenses = []
|
54
|
-
errors = {}
|
55
|
-
|
56
|
-
if autocorrect_cops.any?
|
57
|
-
commissioner = Commissioner.new(autocorrect_cops,
|
58
|
-
forces_for(autocorrect_cops))
|
59
|
-
offenses = commissioner.investigate(processed_source)
|
60
|
-
if autocorrect(processed_source.buffer, autocorrect_cops)
|
61
|
-
# We corrected some errors. Another round of inspection will be
|
62
|
-
# done, and any other offenses will be caught then, so we don't
|
63
|
-
# need to continue.
|
64
|
-
return offenses
|
65
|
-
end
|
66
|
-
errors = commissioner.errors
|
67
|
-
end
|
68
|
-
|
69
|
-
commissioner = Commissioner.new(other_cops, forces_for(other_cops))
|
70
|
-
offenses.concat(commissioner.investigate(processed_source))
|
71
|
-
errors.merge!(commissioner.errors)
|
72
|
-
process_commissioner_errors(processed_source.path, errors)
|
73
|
-
offenses
|
52
|
+
offenses(processed_source)
|
74
53
|
end
|
75
54
|
|
76
55
|
def cops
|
@@ -93,6 +72,40 @@ module RuboCop
|
|
93
72
|
|
94
73
|
private
|
95
74
|
|
75
|
+
def offenses(processed_source)
|
76
|
+
# The autocorrection process may have to be repeated multiple times
|
77
|
+
# until there are no corrections left to perform
|
78
|
+
# To speed things up, run auto-correcting cops by themselves, and only
|
79
|
+
# run the other cops when no corrections are left
|
80
|
+
autocorrect_cops, other_cops = cops.partition(&:autocorrect?)
|
81
|
+
|
82
|
+
autocorrect =
|
83
|
+
investigate(autocorrect_cops, processed_source) do |offenses|
|
84
|
+
# We corrected some errors. Another round of inspection will be
|
85
|
+
# done, and any other offenses will be caught then, so we don't
|
86
|
+
# need to continue.
|
87
|
+
return offenses if autocorrect(processed_source.buffer,
|
88
|
+
autocorrect_cops)
|
89
|
+
end
|
90
|
+
|
91
|
+
other = investigate(other_cops, processed_source)
|
92
|
+
|
93
|
+
errors = autocorrect.errors.merge(other.errors)
|
94
|
+
process_commissioner_errors(processed_source.path, errors)
|
95
|
+
|
96
|
+
autocorrect.offenses.concat(other.offenses)
|
97
|
+
end
|
98
|
+
|
99
|
+
def investigate(cops, processed_source)
|
100
|
+
return Investigation.new([], {}) if cops.empty?
|
101
|
+
|
102
|
+
commissioner = Commissioner.new(cops, forces_for(cops))
|
103
|
+
offenses = commissioner.investigate(processed_source)
|
104
|
+
yield offenses if block_given?
|
105
|
+
|
106
|
+
Investigation.new(offenses, commissioner.errors)
|
107
|
+
end
|
108
|
+
|
96
109
|
def cop_enabled?(cop_class)
|
97
110
|
@config.cop_enabled?(cop_class) ||
|
98
111
|
(@options[:only] || []).include?(cop_class.cop_name)
|
data/lib/rubocop/cop/util.rb
CHANGED
@@ -23,19 +23,6 @@ module RuboCop
|
|
23
23
|
+ - * / % ** ~ +@ -@ [] []= ! != !~
|
24
24
|
).map(&:to_sym).push(:'`').freeze
|
25
25
|
|
26
|
-
STRING_ESCAPES = {
|
27
|
-
'\a' => "\a", '\b' => "\b", '\e' => "\e", '\f' => "\f", '\n' => "\n",
|
28
|
-
'\r' => "\r", '\s' => ' ', '\t' => "\t", '\v' => "\v", "\\\n" => ''
|
29
|
-
}.freeze
|
30
|
-
STRING_ESCAPE_REGEX = /\\(?:
|
31
|
-
[abefnrstv\n] | # simple escapes (above)
|
32
|
-
\d{1,3} | # octal byte escape
|
33
|
-
x\d{1,2} | # hex byte escape
|
34
|
-
u[0-9a-fA-F]{4} | # unicode char escape
|
35
|
-
u\{[^}]*\} | # extended unicode escape
|
36
|
-
. # any other escaped char
|
37
|
-
)/x
|
38
|
-
|
39
26
|
# Match literal regex characters, not including anchors, character
|
40
27
|
# classes, alternatives, groups, repetitions, references, etc
|
41
28
|
LITERAL_REGEX = /[\w\s\-,"'!#%&<>=;:`~]|\\[^AbBdDgGkwWszZS0-9]/
|
@@ -225,7 +212,7 @@ module RuboCop
|
|
225
212
|
|
226
213
|
# Regex matches IF there is a ' or there is a \\ in the string that is
|
227
214
|
# not preceded/followed by another \\ (e.g. "\\x34") but not "\\\\".
|
228
|
-
string
|
215
|
+
string =~ /'|(?<! \\) \\{2}* \\ (?![\\"])/x
|
229
216
|
end
|
230
217
|
|
231
218
|
# If double quoted string literals are found in Ruby code, and they are
|
@@ -233,12 +220,20 @@ module RuboCop
|
|
233
220
|
def double_quotes_acceptable?(string)
|
234
221
|
# If a string literal contains hard-to-type characters which would
|
235
222
|
# not appear on a "normal" keyboard, then double-quotes are acceptable
|
236
|
-
|
223
|
+
needs_escaping?(string) ||
|
237
224
|
string.codepoints.any? { |cp| cp < 32 || cp > 126 }
|
238
225
|
end
|
239
226
|
|
227
|
+
def needs_escaping?(string)
|
228
|
+
double_quotes_required?(escape_string(string))
|
229
|
+
end
|
230
|
+
|
231
|
+
def escape_string(string)
|
232
|
+
string.inspect[1..-2].tap { |s| s.gsub!(/\\"/, '"') }
|
233
|
+
end
|
234
|
+
|
240
235
|
def to_string_literal(string)
|
241
|
-
if
|
236
|
+
if needs_escaping?(string)
|
242
237
|
string.inspect
|
243
238
|
else
|
244
239
|
"'#{string.gsub('\\') { '\\\\' }}'"
|
@@ -246,35 +241,11 @@ module RuboCop
|
|
246
241
|
end
|
247
242
|
|
248
243
|
def to_symbol_literal(string)
|
249
|
-
|
250
|
-
":#{to_string_literal(string)}"
|
251
|
-
else
|
252
|
-
":#{string}"
|
253
|
-
end
|
244
|
+
":#{string.to_sym}"
|
254
245
|
end
|
255
246
|
|
256
|
-
# Take a string with embedded escapes, and convert the escapes as the Ruby
|
257
|
-
# interpreter would when reading a double-quoted string literal.
|
258
|
-
# For example, "\\n" will be converted to "\n".
|
259
247
|
def interpret_string_escapes(string)
|
260
|
-
|
261
|
-
string.gsub(STRING_ESCAPE_REGEX) do |escape|
|
262
|
-
STRING_ESCAPES[escape] || begin
|
263
|
-
if escape[1] == 'x'
|
264
|
-
[escape[2..-1].hex].pack('C')
|
265
|
-
elsif escape[1] == 'u'
|
266
|
-
if escape[2] == '{'
|
267
|
-
escape[3..-1].split(/\s+/).map(&:hex).pack('U')
|
268
|
-
else
|
269
|
-
[escape[2..-1].hex].pack('U')
|
270
|
-
end
|
271
|
-
elsif escape[1] =~ /\d/ # octal escape
|
272
|
-
[escape[1..-1].to_i(8)].pack('C')
|
273
|
-
else
|
274
|
-
escape[1] # literal escaped char, like \\
|
275
|
-
end
|
276
|
-
end
|
277
|
-
end
|
248
|
+
StringInterpreter.interpret(string)
|
278
249
|
end
|
279
250
|
end
|
280
251
|
end
|
@@ -25,6 +25,12 @@ module RuboCop
|
|
25
25
|
attr_accessor :config_to_allow_offenses, :detected_styles
|
26
26
|
end
|
27
27
|
|
28
|
+
def initialize(output, options = {})
|
29
|
+
super
|
30
|
+
@cops_with_offenses ||= Hash.new(0)
|
31
|
+
@files_with_offenses ||= {}
|
32
|
+
end
|
33
|
+
|
28
34
|
def file_started(_file, _file_info)
|
29
35
|
@exclude_limit_option = @options[:exclude_limit]
|
30
36
|
@exclude_limit = (
|
@@ -34,8 +40,6 @@ module RuboCop
|
|
34
40
|
end
|
35
41
|
|
36
42
|
def file_finished(file, offenses)
|
37
|
-
@cops_with_offenses ||= Hash.new(0)
|
38
|
-
@files_with_offenses ||= {}
|
39
43
|
offenses.each do |o|
|
40
44
|
@cops_with_offenses[o.cop_name] += 1
|
41
45
|
@files_with_offenses[o.cop_name] ||= []
|
@@ -44,27 +48,41 @@ module RuboCop
|
|
44
48
|
end
|
45
49
|
|
46
50
|
def finished(_inspected_files)
|
47
|
-
command = 'rubocop --auto-gen-config'
|
48
|
-
if @exclude_limit_option
|
49
|
-
command += format(' --exclude-limit %d', @exclude_limit_option.to_i)
|
50
|
-
end
|
51
51
|
output.puts HEADING % command
|
52
52
|
|
53
53
|
# Syntax isn't a real cop and it can't be disabled.
|
54
54
|
@cops_with_offenses.delete('Syntax')
|
55
55
|
|
56
|
-
|
57
|
-
output.puts
|
58
|
-
cfg = self.class.config_to_allow_offenses[cop_name] || {}
|
56
|
+
output_offenses
|
59
57
|
|
60
|
-
output_cop_comments(output, cfg, cop_name, offense_count)
|
61
|
-
output_cop_config(output, cfg, cop_name)
|
62
|
-
end
|
63
58
|
puts "Created #{output.path}."
|
64
59
|
puts "Run `rubocop --config #{output.path}`, or add `inherit_from: " \
|
65
60
|
"#{output.path}` in a .rubocop.yml file."
|
66
61
|
end
|
67
62
|
|
63
|
+
def command
|
64
|
+
command = 'rubocop --auto-gen-config'
|
65
|
+
if @exclude_limit_option
|
66
|
+
command += format(' --exclude-limit %d', @exclude_limit_option.to_i)
|
67
|
+
end
|
68
|
+
|
69
|
+
command
|
70
|
+
end
|
71
|
+
|
72
|
+
def output_offenses
|
73
|
+
@cops_with_offenses.sort.each do |cop_name, offense_count|
|
74
|
+
output_cop(cop_name, offense_count)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def output_cop(cop_name, offense_count)
|
79
|
+
output.puts
|
80
|
+
cfg = self.class.config_to_allow_offenses[cop_name] || {}
|
81
|
+
|
82
|
+
output_cop_comments(output, cfg, cop_name, offense_count)
|
83
|
+
output_cop_config(output, cfg, cop_name)
|
84
|
+
end
|
85
|
+
|
68
86
|
def output_cop_comments(output, cfg, cop_name, offense_count)
|
69
87
|
output.puts "# Offense count: #{offense_count}" if @show_offense_counts
|
70
88
|
if COPS[cop_name] && COPS[cop_name].first.new.support_autocorrect?
|
@@ -91,12 +109,17 @@ module RuboCop
|
|
91
109
|
end
|
92
110
|
|
93
111
|
def output_cop_config(output, cfg, cop_name)
|
112
|
+
# 'Enabled' option will be put into file only if exclude
|
113
|
+
# limit is exceeded.
|
114
|
+
cfg_without_enabled = cfg.reject { |key| key == 'Enabled' }
|
115
|
+
|
94
116
|
output.puts "#{cop_name}:"
|
95
|
-
|
117
|
+
cfg_without_enabled.each do |key, value|
|
96
118
|
value = value[0] if value.is_a?(Array)
|
97
119
|
output.puts " #{key}: #{value}"
|
98
120
|
end
|
99
|
-
|
121
|
+
|
122
|
+
output_offending_files(output, cfg_without_enabled, cop_name)
|
100
123
|
end
|
101
124
|
|
102
125
|
def output_offending_files(output, cfg, cop_name)
|
@@ -95,18 +95,14 @@ module RuboCop
|
|
95
95
|
|
96
96
|
def highlighted_source_line(offense)
|
97
97
|
location = offense.location
|
98
|
-
|
99
|
-
source_line = if location.first_line == location.last_line
|
100
|
-
location.source_line
|
101
|
-
else
|
102
|
-
"#{location.source_line} #{ELLIPSES}"
|
103
|
-
end
|
98
|
+
source_line = location.source_line
|
104
99
|
|
105
100
|
escape(source_line[0...offense.highlighted_area.begin_pos]) +
|
106
101
|
"<span class=\"highlight #{offense.severity}\">" +
|
107
102
|
escape(offense.highlighted_area.source) +
|
108
103
|
'</span>' +
|
109
|
-
escape(source_line[offense.highlighted_area.end_pos..-1])
|
104
|
+
escape(source_line[offense.highlighted_area.end_pos..-1]) +
|
105
|
+
(location.first_line == location.last_line ? '' : " #{ELLIPSES}")
|
110
106
|
end
|
111
107
|
|
112
108
|
def escape(s)
|
data/lib/rubocop/result_cache.rb
CHANGED
@@ -41,7 +41,11 @@ module RuboCop
|
|
41
41
|
private
|
42
42
|
|
43
43
|
def remove_files(files, dirs, remove_count, verbose)
|
44
|
-
|
44
|
+
# Batch file deletions, deleting over 130,000+ files will crash
|
45
|
+
# File.delete.
|
46
|
+
files[0, remove_count].each_slice(10_000).each do |files_slice|
|
47
|
+
File.delete(*files_slice)
|
48
|
+
end
|
45
49
|
dirs.each { |dir| Dir.rmdir(dir) if Dir["#{dir}/*"].empty? }
|
46
50
|
rescue Errno::ENOENT
|
47
51
|
# This can happen if parallel RuboCop invocations try to remove the
|
@@ -60,8 +64,14 @@ module RuboCop
|
|
60
64
|
File.join(root, 'rubocop_cache')
|
61
65
|
end
|
62
66
|
|
67
|
+
def self.allow_symlinks_in_cache_location?(config_store)
|
68
|
+
config_store.for('.').for_all_cops['AllowSymlinksInCacheRootDirectory']
|
69
|
+
end
|
70
|
+
|
63
71
|
def initialize(file, options, config_store, cache_root = nil)
|
64
72
|
cache_root ||= ResultCache.cache_root(config_store)
|
73
|
+
@allow_symlinks_in_cache_location =
|
74
|
+
ResultCache.allow_symlinks_in_cache_location?(config_store)
|
65
75
|
@path = File.join(cache_root, rubocop_checksum,
|
66
76
|
relevant_options_digest(options),
|
67
77
|
file_checksum(file, config_store))
|
@@ -81,9 +91,9 @@ module RuboCop
|
|
81
91
|
FileUtils.mkdir_p(dir)
|
82
92
|
preliminary_path = "#{@path}_#{rand(1_000_000_000)}"
|
83
93
|
# RuboCop must be in control of where its cached data is stored. A
|
84
|
-
# symbolic link anywhere in the cache directory tree
|
85
|
-
# that a symlink attack is being waged.
|
86
|
-
return if
|
94
|
+
# symbolic link anywhere in the cache directory tree can be an
|
95
|
+
# indication that a symlink attack is being waged.
|
96
|
+
return if symlink_protection_triggered?(dir)
|
87
97
|
|
88
98
|
File.open(preliminary_path, 'wb') do |f|
|
89
99
|
f.write(@cached_data.to_json(offenses))
|
@@ -98,6 +108,10 @@ module RuboCop
|
|
98
108
|
|
99
109
|
private
|
100
110
|
|
111
|
+
def symlink_protection_triggered?(path)
|
112
|
+
!@allow_symlinks_in_cache_location && any_symlink?(path)
|
113
|
+
end
|
114
|
+
|
101
115
|
def any_symlink?(path)
|
102
116
|
while path != File.dirname(path)
|
103
117
|
if File.symlink?(path)
|