rubocop 0.11.1 → 0.12.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/CHANGELOG.md +32 -1
- data/README.md +28 -3
- data/config/default.yml +14 -12
- data/config/disabled.yml +1 -1
- data/config/enabled.yml +190 -118
- data/lib/rubocop.rb +9 -1
- data/lib/rubocop/cli.rb +49 -13
- data/lib/rubocop/config.rb +5 -5
- data/lib/rubocop/cop/cop.rb +34 -1
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +47 -0
- data/lib/rubocop/cop/lint/rescue_exception.rb +1 -4
- data/lib/rubocop/cop/lint/useless_assignment.rb +39 -11
- data/lib/rubocop/cop/lint/useless_comparison.rb +2 -4
- data/lib/rubocop/cop/rails/has_and_belongs_to_many.rb +20 -0
- data/lib/rubocop/cop/rails/read_attribute.rb +28 -0
- data/lib/rubocop/cop/style/access_control.rb +12 -1
- data/lib/rubocop/cop/style/attr.rb +7 -0
- data/lib/rubocop/cop/style/collection_methods.rb +13 -1
- data/lib/rubocop/cop/style/constant_name.rb +1 -1
- data/lib/rubocop/cop/style/def_parentheses.rb +18 -0
- data/lib/rubocop/cop/style/documentation.rb +1 -1
- data/lib/rubocop/cop/style/empty_literal.rb +14 -0
- data/lib/rubocop/cop/style/even_odd.rb +56 -0
- data/lib/rubocop/cop/style/favor_modifier.rb +2 -2
- data/lib/rubocop/cop/style/hash_methods.rb +40 -0
- data/lib/rubocop/cop/style/indentation_width.rb +148 -0
- data/lib/rubocop/cop/style/method_and_variable_snake_case.rb +40 -25
- data/lib/rubocop/cop/style/method_call_parentheses.rb +8 -0
- data/lib/rubocop/cop/style/multiline_if_then.rb +1 -1
- data/lib/rubocop/cop/style/nil_comparison.rb +38 -0
- data/lib/rubocop/cop/style/signal_exception.rb +11 -0
- data/lib/rubocop/cop/style/space_after_method_name.rb +34 -0
- data/lib/rubocop/cop/util.rb +17 -0
- data/lib/rubocop/formatter/emacs_style_formatter.rb +2 -2
- data/lib/rubocop/formatter/file_list_formatter.rb +3 -2
- data/lib/rubocop/formatter/formatter_set.rb +3 -11
- data/lib/rubocop/formatter/offence_count_formatter.rb +50 -0
- data/lib/rubocop/formatter/progress_formatter.rb +0 -2
- data/lib/rubocop/formatter/simple_text_formatter.rb +1 -6
- data/lib/rubocop/version.rb +1 -1
- data/spec/project_spec.rb +7 -0
- data/spec/rubocop/cli_spec.rb +119 -57
- data/spec/rubocop/config_spec.rb +23 -17
- data/spec/rubocop/cop/commissioner_spec.rb +8 -8
- data/spec/rubocop/cop/cop_spec.rb +80 -0
- data/spec/rubocop/cop/lint/parentheses_as_grouped_expression_spec.rb +63 -0
- data/spec/rubocop/cop/lint/useless_assignment_spec.rb +59 -0
- data/spec/rubocop/cop/rails/has_and_belongs_to_many_spec.rb +19 -0
- data/spec/rubocop/cop/rails/read_attribute_spec.rb +19 -0
- data/spec/rubocop/cop/rails/validation_spec.rb +5 -5
- data/spec/rubocop/cop/style/access_control_spec.rb +28 -0
- data/spec/rubocop/cop/style/attr_spec.rb +6 -1
- data/spec/rubocop/cop/style/collection_methods_spec.rb +5 -0
- data/spec/rubocop/cop/style/constant_name_spec.rb +9 -0
- data/spec/rubocop/cop/style/def_with_parentheses_spec.rb +14 -9
- data/spec/rubocop/cop/style/def_without_parentheses_spec.rb +12 -7
- data/spec/rubocop/cop/style/empty_literal_spec.rb +42 -27
- data/spec/rubocop/cop/style/even_odd_spec.rb +47 -0
- data/spec/rubocop/cop/style/favor_modifier_spec.rb +15 -14
- data/spec/rubocop/cop/style/hash_methods_spec.rb +51 -0
- data/spec/rubocop/cop/style/indentation_width_spec.rb +390 -0
- data/spec/rubocop/cop/style/method_and_variable_snake_case_spec.rb +58 -50
- data/spec/rubocop/cop/style/method_call_parentheses_spec.rb +6 -1
- data/spec/rubocop/cop/style/nil_comparison_spec.rb +31 -0
- data/spec/rubocop/cop/style/signal_exception_spec.rb +28 -0
- data/spec/rubocop/cop/style/space_after_method_name_spec.rb +61 -0
- data/spec/rubocop/formatter/emacs_style_formatter_spec.rb +9 -2
- data/spec/rubocop/formatter/file_list_formatter_spec.rb +3 -3
- data/spec/rubocop/formatter/offence_count_formatter_spec.rb +52 -0
- data/spec/rubocop/formatter/progress_formatter_spec.rb +70 -84
- data/spec/rubocop/source_parser_spec.rb +1 -1
- metadata +29 -5
- data/lib/rubocop/cop/style/line_continuation.rb +0 -27
- data/spec/rubocop/cop/style/line_continuation_spec.rb +0 -26
@@ -10,51 +10,66 @@ module Rubocop
|
|
10
10
|
MSG = 'Use snake_case for methods and variables.'
|
11
11
|
SNAKE_CASE = /^@?[\da-z_]+[!?=]?$/
|
12
12
|
|
13
|
-
# http://phrogz.net/programmingruby/language.html#table_18.4
|
14
|
-
OPERATOR_METHODS = %w(
|
15
|
-
| ^ & <=> == === =~ > >= < <= << >>
|
16
|
-
+ - * / % ** ~ +@ -@ [] []= ` ! != !~
|
17
|
-
).map(&:to_sym)
|
18
|
-
|
19
13
|
def investigate(processed_source)
|
20
14
|
ast = processed_source.ast
|
21
15
|
return unless ast
|
22
16
|
on_node([:def, :defs, :lvasgn, :ivasgn, :send], ast) do |n|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
end
|
33
|
-
|
34
|
-
next unless name
|
17
|
+
range = case n.type
|
18
|
+
when :def then name_of_instance_method(n)
|
19
|
+
when :defs then name_of_singleton_method(n)
|
20
|
+
when :lvasgn, :ivasgn then name_of_variable(n)
|
21
|
+
when :send then name_of_setter(n)
|
22
|
+
end
|
23
|
+
|
24
|
+
next unless range
|
25
|
+
name = range.source.to_sym
|
35
26
|
next if name =~ SNAKE_CASE || OPERATOR_METHODS.include?(name)
|
36
27
|
|
37
|
-
add_offence(:convention,
|
28
|
+
add_offence(:convention, range, MSG)
|
38
29
|
end
|
39
30
|
end
|
40
31
|
|
41
32
|
def name_of_instance_method(def_node)
|
42
|
-
def_node.
|
33
|
+
expr = def_node.loc.expression
|
34
|
+
match = /^def(\s+)([\w]+[!?=]?\b)/.match(expr.source)
|
35
|
+
return unless match
|
36
|
+
space, method_name = match.captures
|
37
|
+
begin_pos = expr.begin_pos + 'def'.length + space.length
|
38
|
+
Parser::Source::Range.new(expr.source_buffer, begin_pos,
|
39
|
+
begin_pos + method_name.length)
|
43
40
|
end
|
44
41
|
|
45
42
|
def name_of_singleton_method(defs_node)
|
46
|
-
defs_node
|
43
|
+
scope, method_name, _args, _body = *defs_node
|
44
|
+
after_dot(defs_node, method_name.length,
|
45
|
+
"def\s+" + Regexp.escape(scope.loc.expression.source))
|
47
46
|
end
|
48
47
|
|
49
48
|
def name_of_variable(vasgn_node)
|
50
|
-
vasgn_node.
|
49
|
+
expr = vasgn_node.loc.expression
|
50
|
+
name = vasgn_node.children.first
|
51
|
+
Parser::Source::Range.new(expr.source_buffer, expr.begin_pos,
|
52
|
+
expr.begin_pos + name.length)
|
51
53
|
end
|
52
54
|
|
53
55
|
def name_of_setter(send_node)
|
54
56
|
receiver, method_name = *send_node
|
55
|
-
return
|
56
|
-
return
|
57
|
-
method_name
|
57
|
+
return unless receiver && receiver.type == :self
|
58
|
+
return unless method_name.to_s.end_with?('=')
|
59
|
+
after_dot(send_node, method_name.length - '='.length,
|
60
|
+
Regexp.escape(receiver.loc.expression.source))
|
61
|
+
end
|
62
|
+
|
63
|
+
# Returns a range containing the method name after the given regexp and
|
64
|
+
# a dot.
|
65
|
+
def after_dot(node, method_name_length, regexp)
|
66
|
+
expr = node.loc.expression
|
67
|
+
match = /\A#{regexp}\s*\.\s*/.match(expr.source)
|
68
|
+
return unless match
|
69
|
+
offset = match[0].length
|
70
|
+
begin_pos = expr.begin_pos + offset
|
71
|
+
Parser::Source::Range.new(expr.source_buffer, begin_pos,
|
72
|
+
begin_pos + method_name_length)
|
58
73
|
end
|
59
74
|
end
|
60
75
|
end
|
@@ -12,6 +12,14 @@ module Rubocop
|
|
12
12
|
|
13
13
|
if args.empty? && node.loc.begin
|
14
14
|
add_offence(:convention, node.loc.begin, MSG)
|
15
|
+
do_autocorrect(node)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def autocorrect_action(node)
|
20
|
+
@corrections << lambda do |corrector|
|
21
|
+
corrector.remove(node.loc.begin)
|
22
|
+
corrector.remove(node.loc.end)
|
15
23
|
end
|
16
24
|
end
|
17
25
|
end
|
@@ -23,7 +23,7 @@ module Rubocop
|
|
23
23
|
next_thing = if body && body.loc.expression
|
24
24
|
body.loc.expression.begin
|
25
25
|
elsif else_clause && else_clause.loc.expression
|
26
|
-
|
26
|
+
else_clause.loc.expression.begin
|
27
27
|
else
|
28
28
|
node.loc.end # No body, use "end".
|
29
29
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Rubocop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# This cop checks for comparison of something with nil using ==.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
#
|
10
|
+
# # bad
|
11
|
+
# if x == nil
|
12
|
+
# if x != nil
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# if x.nil?
|
16
|
+
# if !x.nil?
|
17
|
+
class NilComparison < Cop
|
18
|
+
MSG = 'Prefer the use of the nil? predicate.'
|
19
|
+
|
20
|
+
OPS = %w(== === !=)
|
21
|
+
|
22
|
+
NIL_NODE = s(:nil)
|
23
|
+
|
24
|
+
def on_send(node)
|
25
|
+
op = node.loc.selector.source
|
26
|
+
|
27
|
+
if OPS.include?(op)
|
28
|
+
_receiver, _method, args = *node
|
29
|
+
|
30
|
+
if args == NIL_NODE
|
31
|
+
add_offence(:convention, node.loc.selector, MSG)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -15,12 +15,22 @@ module Rubocop
|
|
15
15
|
check_for_fail(rescue_node)
|
16
16
|
end
|
17
17
|
|
18
|
+
def autocorrect_action(node)
|
19
|
+
@corrections << lambda do |corrector|
|
20
|
+
name = command?(:raise, node) ? 'fail' : 'raise'
|
21
|
+
corrector.replace(node.loc.selector, name)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
18
27
|
def check_for_raise(node)
|
19
28
|
return unless node
|
20
29
|
|
21
30
|
on_node(:send, node, :rescue) do |send_node|
|
22
31
|
if command?(:raise, send_node)
|
23
32
|
add_offence(:convention, send_node.loc.selector, FAIL_MSG)
|
33
|
+
do_autocorrect(send_node)
|
24
34
|
end
|
25
35
|
end
|
26
36
|
end
|
@@ -31,6 +41,7 @@ module Rubocop
|
|
31
41
|
on_node(:send, node, :rescue) do |send_node|
|
32
42
|
if command?(:fail, send_node)
|
33
43
|
add_offence(:convention, send_node.loc.selector, RAISE_MSG)
|
44
|
+
do_autocorrect(send_node)
|
34
45
|
end
|
35
46
|
end
|
36
47
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Rubocop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Checks for space between a method name and a left parenthesis.
|
7
|
+
class SpaceAfterMethodName < Cop
|
8
|
+
MSG = 'Never put a space between a method name and the opening ' +
|
9
|
+
'parenthesis.'
|
10
|
+
|
11
|
+
def on_def(node)
|
12
|
+
_method_name, args, _body = *node
|
13
|
+
check(args)
|
14
|
+
end
|
15
|
+
|
16
|
+
def on_defs(node)
|
17
|
+
_scope, _method_name, args, _body = *node
|
18
|
+
check(args)
|
19
|
+
end
|
20
|
+
|
21
|
+
def check(args)
|
22
|
+
return unless args.loc.begin && args.loc.begin.is?('(')
|
23
|
+
expr = args.loc.expression
|
24
|
+
pos_before_left_paren = Parser::Source::Range.new(expr.source_buffer,
|
25
|
+
expr.begin_pos - 1,
|
26
|
+
expr.begin_pos)
|
27
|
+
if pos_before_left_paren.source =~ /\s/
|
28
|
+
add_offence(:convention, pos_before_left_paren, MSG)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/rubocop/cop/util.rb
CHANGED
@@ -22,6 +22,23 @@ module Rubocop
|
|
22
22
|
def block_length(block_node)
|
23
23
|
block_node.loc.end.line - block_node.loc.begin.line
|
24
24
|
end
|
25
|
+
|
26
|
+
def const_name(node)
|
27
|
+
return nil if node.nil? || node.type != :const
|
28
|
+
|
29
|
+
const_names = []
|
30
|
+
const_node = node
|
31
|
+
|
32
|
+
loop do
|
33
|
+
namespace_node, name = *const_node
|
34
|
+
const_names << name
|
35
|
+
break unless namespace_node
|
36
|
+
break if namespace_node.type == :cbase
|
37
|
+
const_node = namespace_node
|
38
|
+
end
|
39
|
+
|
40
|
+
const_names.reverse.join('::')
|
41
|
+
end
|
25
42
|
end
|
26
43
|
end
|
27
44
|
end
|
@@ -4,8 +4,8 @@ module Rubocop
|
|
4
4
|
module Formatter
|
5
5
|
# This formatter displays the report data in format that's
|
6
6
|
# easy to process in the Emacs text editor.
|
7
|
-
class EmacsStyleFormatter <
|
8
|
-
def
|
7
|
+
class EmacsStyleFormatter < BaseFormatter
|
8
|
+
def file_finished(file, offences)
|
9
9
|
offences.each do |o|
|
10
10
|
output.printf("%s:%d:%d: %s: %s\n",
|
11
11
|
file, o.line, o.real_column, o.encode_severity,
|
@@ -9,8 +9,9 @@ module Rubocop
|
|
9
9
|
#
|
10
10
|
# /some/file
|
11
11
|
# /some/other/file
|
12
|
-
class FileListFormatter <
|
13
|
-
def
|
12
|
+
class FileListFormatter < BaseFormatter
|
13
|
+
def file_finished(file, offences)
|
14
|
+
return if offences.empty?
|
14
15
|
output.printf("%s\n", file)
|
15
16
|
end
|
16
17
|
end
|
@@ -12,15 +12,12 @@ module Rubocop
|
|
12
12
|
'clang' => ClangStyleFormatter,
|
13
13
|
'emacs' => EmacsStyleFormatter,
|
14
14
|
'json' => JSONFormatter,
|
15
|
-
'files' => FileListFormatter
|
15
|
+
'files' => FileListFormatter,
|
16
|
+
'offences' => OffenceCountFormatter
|
16
17
|
}
|
17
18
|
|
18
19
|
FORMATTER_APIS = [:started, :file_started, :file_finished, :finished]
|
19
20
|
|
20
|
-
def initialize(report_summary = true)
|
21
|
-
@reports_summary = report_summary
|
22
|
-
end
|
23
|
-
|
24
21
|
FORMATTER_APIS.each do |method_name|
|
25
22
|
define_method(method_name) do |*args|
|
26
23
|
each { |f| f.send(method_name, *args) }
|
@@ -39,12 +36,7 @@ module Rubocop
|
|
39
36
|
|
40
37
|
output = output_path ? File.open(output_path, 'w') : $stdout
|
41
38
|
|
42
|
-
|
43
|
-
if formatter.respond_to?(:reports_summary=)
|
44
|
-
# TODO: Consider dropping -s/--silent option
|
45
|
-
formatter.reports_summary = @reports_summary
|
46
|
-
end
|
47
|
-
self << formatter
|
39
|
+
self << formatter_class.new(output)
|
48
40
|
end
|
49
41
|
|
50
42
|
def close_output_files
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Rubocop
|
4
|
+
module Formatter
|
5
|
+
# This formatter displays the list of offended cops with a count of how
|
6
|
+
# many offences of their kind were found. Ordered by desc offence count
|
7
|
+
#
|
8
|
+
# Here's the format:
|
9
|
+
#
|
10
|
+
# (26) LineLength
|
11
|
+
# (3) OneLineConditional
|
12
|
+
class OffenceCountFormatter < BaseFormatter
|
13
|
+
|
14
|
+
attr_reader :offence_counts
|
15
|
+
|
16
|
+
def started(target_files)
|
17
|
+
super
|
18
|
+
@offence_counts = Hash.new(0)
|
19
|
+
end
|
20
|
+
|
21
|
+
def file_finished(file, offences)
|
22
|
+
offences.each { |o| @offence_counts[o.cop_name] += 1 }
|
23
|
+
end
|
24
|
+
|
25
|
+
def finished(inspected_files)
|
26
|
+
report_summary(inspected_files.count,
|
27
|
+
ordered_offence_counts(@offence_counts))
|
28
|
+
end
|
29
|
+
|
30
|
+
def report_summary(file_count, offence_counts)
|
31
|
+
output.puts
|
32
|
+
|
33
|
+
offence_count = total_offence_count(offence_counts)
|
34
|
+
offence_counts.each do |cop_name, count|
|
35
|
+
output.puts "#{count.to_s.ljust(offence_count.to_s.length + 2)}" +
|
36
|
+
"#{cop_name}\n"
|
37
|
+
end
|
38
|
+
output.puts
|
39
|
+
end
|
40
|
+
|
41
|
+
def ordered_offence_counts(offence_counts)
|
42
|
+
Hash[offence_counts.sort_by { |k, v| v }.reverse]
|
43
|
+
end
|
44
|
+
|
45
|
+
def total_offence_count(offence_counts = {})
|
46
|
+
offence_counts.values.inject(0, :+)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -6,9 +6,6 @@ module Rubocop
|
|
6
6
|
# Offences are displayed at compact form - just the
|
7
7
|
# location of the problem and the associated message.
|
8
8
|
class SimpleTextFormatter < BaseFormatter
|
9
|
-
attr_accessor :reports_summary
|
10
|
-
alias_method :reports_summary?, :reports_summary
|
11
|
-
|
12
9
|
def started(target_files)
|
13
10
|
@total_offence_count = 0
|
14
11
|
end
|
@@ -20,9 +17,7 @@ module Rubocop
|
|
20
17
|
end
|
21
18
|
|
22
19
|
def finished(inspected_files)
|
23
|
-
|
24
|
-
report_summary(inspected_files.count, @total_offence_count)
|
25
|
-
end
|
20
|
+
report_summary(inspected_files.count, @total_offence_count)
|
26
21
|
end
|
27
22
|
|
28
23
|
def report_file(file, offences)
|
data/lib/rubocop/version.rb
CHANGED
data/spec/project_spec.rb
CHANGED
@@ -9,5 +9,12 @@ describe 'RuboCop Project' do
|
|
9
9
|
expect(Rubocop::Config.load_file('config/default.yml').keys.sort)
|
10
10
|
.to eq((['AllCops'] + cop_names).sort)
|
11
11
|
end
|
12
|
+
it 'has a description for all cops' do
|
13
|
+
cop_names = Rubocop::Cop::Cop.all.map(&:cop_name)
|
14
|
+
conf = Rubocop::Config.load_file('config/default.yml')
|
15
|
+
cop_names.each do |name|
|
16
|
+
expect(conf[name]['Description']).not_to be_nil
|
17
|
+
end
|
18
|
+
end
|
12
19
|
end
|
13
20
|
end
|
data/spec/rubocop/cli_spec.rb
CHANGED
@@ -44,6 +44,8 @@ Usage: rubocop [options] [file1, file2, ...]
|
|
44
44
|
--only COP Run just one cop.
|
45
45
|
--auto-gen-config Generate a configuration file acting as a
|
46
46
|
TODO list.
|
47
|
+
--show-cops Shows cops and their config for the
|
48
|
+
current directory.
|
47
49
|
-f, --format FORMATTER Choose an output formatter. This option
|
48
50
|
can be specified multiple times to enable
|
49
51
|
multiple formatters at the same time.
|
@@ -53,6 +55,7 @@ Usage: rubocop [options] [file1, file2, ...]
|
|
53
55
|
[e]macs
|
54
56
|
[j]son
|
55
57
|
[f]iles
|
58
|
+
[o]ffences
|
56
59
|
custom formatter class name
|
57
60
|
-o, --out FILE Write output to a file instead of STDOUT.
|
58
61
|
This option applies to the previously
|
@@ -62,7 +65,6 @@ Usage: rubocop [options] [file1, file2, ...]
|
|
62
65
|
-R, --rails Run extra Rails cops.
|
63
66
|
-l, --lint Run only lint cops.
|
64
67
|
-a, --auto-correct Auto-correct offences.
|
65
|
-
-s, --silent Silence summary.
|
66
68
|
-n, --no-color Disable color output.
|
67
69
|
-v, --version Display version.
|
68
70
|
-V, --verbose-version Display verbose version.
|
@@ -207,8 +209,6 @@ Usage: rubocop [options] [file1, file2, ...]
|
|
207
209
|
"#{abs('example1.rb')}:2:2: C: Trailing whitespace detected.",
|
208
210
|
"#{abs('example2.rb')}:1:1: C: Missing utf-8 encoding comment.",
|
209
211
|
"#{abs('example2.rb')}:1:1: C: Tab detected.",
|
210
|
-
'',
|
211
|
-
'2 files inspected, 6 offences detected',
|
212
212
|
''].join("\n"))
|
213
213
|
end
|
214
214
|
|
@@ -231,8 +231,6 @@ Usage: rubocop [options] [file1, file2, ...]
|
|
231
231
|
"#{abs('example1.rb')}:1:5: C: Trailing whitespace detected.",
|
232
232
|
"#{abs('example1.rb')}:2:2: C: Trailing whitespace detected.",
|
233
233
|
"#{abs('example2.rb')}:1:1: C: Tab detected.",
|
234
|
-
'',
|
235
|
-
'2 files inspected, 4 offences detected',
|
236
234
|
''].join("\n"))
|
237
235
|
end
|
238
236
|
|
@@ -243,9 +241,18 @@ Usage: rubocop [options] [file1, file2, ...]
|
|
243
241
|
'y ',
|
244
242
|
'puts x'])
|
245
243
|
create_file('example2.rb', ['# encoding: utf-8',
|
246
|
-
"\tx
|
247
|
-
'
|
248
|
-
|
244
|
+
"\tx",
|
245
|
+
'def a',
|
246
|
+
' puts',
|
247
|
+
'end'])
|
248
|
+
create_file('example3.rb', ['# encoding: utf-8',
|
249
|
+
'def badName',
|
250
|
+
' if something',
|
251
|
+
' test',
|
252
|
+
' end',
|
253
|
+
'end'])
|
254
|
+
expect(cli.run(['--format', 'clang', 'example1.rb', 'example2.rb',
|
255
|
+
'example3.rb']))
|
249
256
|
.to eq(1)
|
250
257
|
expect($stdout.string)
|
251
258
|
.to eq(['example1.rb:2:2: C: Surrounding space missing for operator ' +
|
@@ -264,10 +271,26 @@ Usage: rubocop [options] [file1, file2, ...]
|
|
264
271
|
'y ',
|
265
272
|
' ^',
|
266
273
|
'example2.rb:2:1: C: Tab detected.',
|
267
|
-
"\tx
|
268
|
-
'
|
274
|
+
"\tx",
|
275
|
+
'^^^^^',
|
276
|
+
'example2.rb:4:1: C: Use 2 (not 3) spaces for indentation.',
|
277
|
+
' puts',
|
278
|
+
'^^^',
|
279
|
+
'example3.rb:2:5: C: Use snake_case for methods and ' +
|
280
|
+
'variables.',
|
281
|
+
'def badName',
|
282
|
+
' ^^^^^^^',
|
283
|
+
'example3.rb:3:3: C: Favor modifier if/unless usage when ' +
|
284
|
+
'you have a single-line body. Another good alternative is ' +
|
285
|
+
'the usage of control flow &&/||.',
|
286
|
+
' if something',
|
287
|
+
' ^^',
|
288
|
+
'example3.rb:5:5: W: end at 5, 4 is not aligned with if at ' +
|
289
|
+
'3, 2',
|
290
|
+
' end',
|
291
|
+
' ^^^',
|
269
292
|
'',
|
270
|
-
'
|
293
|
+
'3 files inspected, 9 offences detected',
|
271
294
|
''].join("\n"))
|
272
295
|
end
|
273
296
|
|
@@ -387,34 +410,80 @@ Usage: rubocop [options] [file1, file2, ...]
|
|
387
410
|
expect($stderr.string).to eq("Unrecognized cop name: 123.\n")
|
388
411
|
end
|
389
412
|
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
"#{abs('example2.rb')}:1:1: C: Missing utf-8 encoding comment.",
|
402
|
-
"#{abs('example2.rb')}:1:1: C: Tab detected.",
|
403
|
-
''].join("\n"))
|
404
|
-
end
|
413
|
+
context '--show-cops' do
|
414
|
+
let(:cops) { Cop::Cop.all }
|
415
|
+
let(:global_conf) do
|
416
|
+
config_path = Rubocop::Config.configuration_file_for(Dir.pwd.to_s)
|
417
|
+
Rubocop::Config.configuration_from_file(config_path)
|
418
|
+
end
|
419
|
+
before do
|
420
|
+
cops.each do |cop_class|
|
421
|
+
cop_class.config = global_conf.for_cop(cop_class.cop_name)
|
422
|
+
end
|
423
|
+
end
|
405
424
|
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
425
|
+
subject do
|
426
|
+
expect { cli.run ['--show-cops'] }.to exit_with_code(0)
|
427
|
+
@stdout = $stdout.string
|
428
|
+
end
|
429
|
+
it 'prints all available cops and their description' do
|
430
|
+
subject
|
431
|
+
cops.each do |cop|
|
432
|
+
expect(@stdout).to include cop.cop_name
|
433
|
+
expect(@stdout).to include cop.short_description
|
434
|
+
end
|
435
|
+
end
|
436
|
+
|
437
|
+
it 'prints all types' do
|
438
|
+
subject
|
439
|
+
cops
|
440
|
+
.types
|
441
|
+
.dup
|
442
|
+
.map!(&:to_s)
|
443
|
+
.map!(&:capitalize)
|
444
|
+
.each { |type| expect(@stdout).to include(type) }
|
445
|
+
end
|
446
|
+
|
447
|
+
it 'prints all cops in their right type listing' do
|
448
|
+
subject
|
449
|
+
lines = @stdout.lines
|
450
|
+
lines.slice_before(/Type /).each do |slice|
|
451
|
+
types = cops.types.dup.map!(&:to_s).map!(&:capitalize)
|
452
|
+
current = types.delete(slice.shift[/Type '(?<c>[^'']+)'/, 'c'])
|
453
|
+
# all cops in their type listing
|
454
|
+
cops.with_type(current).each do |cop|
|
455
|
+
expect(slice.any? { |l| l.include? cop.cop_name }).to be_true
|
456
|
+
end
|
457
|
+
|
458
|
+
# no cop in wrong type listing
|
459
|
+
types.each do |type|
|
460
|
+
cops.with_type(type).each do |cop|
|
461
|
+
expect(slice.any? { |l| l.include? cop.cop_name }).to be_false
|
462
|
+
end
|
463
|
+
end
|
464
|
+
end
|
465
|
+
end
|
466
|
+
|
467
|
+
it 'prints the current configuration' do
|
468
|
+
subject
|
469
|
+
out = @stdout.lines.to_a
|
470
|
+
cops.each do |cop|
|
471
|
+
conf = global_conf[cop.cop_name].dup
|
472
|
+
confstrt = out.find_index { |i| i.include?("- #{cop.cop_name}") } + 1
|
473
|
+
c = out[confstrt, conf.keys.size].to_s
|
474
|
+
conf.delete('Description')
|
475
|
+
expect(c).to include(cop.short_description)
|
476
|
+
conf.each do |k, v|
|
477
|
+
# ugly hack to get hash/array content tested
|
478
|
+
if v.kind_of?(Hash) || v.kind_of?(Array)
|
479
|
+
expect(c).to include "#{k}: #{v.to_s.dump[2, -2]}"
|
480
|
+
else
|
481
|
+
expect(c).to include "#{k}: #{v}"
|
482
|
+
end
|
483
|
+
|
484
|
+
end
|
485
|
+
end
|
486
|
+
end
|
418
487
|
end
|
419
488
|
|
420
489
|
it 'shows config files when --debug is passed', ruby: 2.0 do
|
@@ -437,7 +506,6 @@ Usage: rubocop [options] [file1, file2, ...]
|
|
437
506
|
create_file('example1.rb', "\tputs 0")
|
438
507
|
expect(cli.run(['--format',
|
439
508
|
'emacs',
|
440
|
-
'--silent',
|
441
509
|
'--debug',
|
442
510
|
'example1.rb'])).to eq(1)
|
443
511
|
expect($stdout.string.lines[-1]).to eq(
|
@@ -718,8 +786,6 @@ Usage: rubocop [options] [file1, file2, ...]
|
|
718
786
|
expect($stdout.string)
|
719
787
|
.to eq(["#{abs('example.rb')}:3:3: E: unexpected " +
|
720
788
|
'token $end',
|
721
|
-
'',
|
722
|
-
'1 file inspected, 1 offence detected',
|
723
789
|
''].join("\n"))
|
724
790
|
end
|
725
791
|
|
@@ -732,8 +798,6 @@ Usage: rubocop [options] [file1, file2, ...]
|
|
732
798
|
expect($stdout.string)
|
733
799
|
.to eq(["#{abs('example.rb')}:2:6: W: " +
|
734
800
|
"`*' interpreted as argument prefix",
|
735
|
-
'',
|
736
|
-
'1 file inspected, 1 offence detected',
|
737
801
|
''].join("\n"))
|
738
802
|
end
|
739
803
|
|
@@ -766,8 +830,6 @@ Usage: rubocop [options] [file1, file2, ...]
|
|
766
830
|
["#{abs('example.rb')}:8:80: C: Line is too long. [95/79]",
|
767
831
|
"#{abs('example.rb')}:10:5: C: Prefer single-quoted strings when " +
|
768
832
|
"you don't need string interpolation or special symbols.",
|
769
|
-
'',
|
770
|
-
'1 file inspected, 2 offences detected',
|
771
833
|
''].join("\n"))
|
772
834
|
end
|
773
835
|
|
@@ -792,8 +854,6 @@ Usage: rubocop [options] [file1, file2, ...]
|
|
792
854
|
["#{abs('example.rb')}:8:80: C: Line is too long. [95/79]",
|
793
855
|
"#{abs('example.rb')}:10:5: C: Prefer single-quoted strings when " +
|
794
856
|
"you don't need string interpolation or special symbols.",
|
795
|
-
'',
|
796
|
-
'1 file inspected, 2 offences detected',
|
797
857
|
''].join("\n"))
|
798
858
|
end
|
799
859
|
|
@@ -803,10 +863,7 @@ Usage: rubocop [options] [file1, file2, ...]
|
|
803
863
|
'y("123", 123456) # rubocop:disable all'
|
804
864
|
])
|
805
865
|
expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(0)
|
806
|
-
expect($stdout.string).to
|
807
|
-
['',
|
808
|
-
'1 file inspected, no offences detected',
|
809
|
-
''].join("\n"))
|
866
|
+
expect($stdout.string).to be_empty
|
810
867
|
end
|
811
868
|
|
812
869
|
it 'can have selected cops disabled on a single line' do
|
@@ -819,8 +876,6 @@ Usage: rubocop [options] [file1, file2, ...]
|
|
819
876
|
expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(1)
|
820
877
|
expect($stdout.string).to eq(
|
821
878
|
["#{abs('example.rb')}:3:80: C: Line is too long. [95/79]",
|
822
|
-
'',
|
823
|
-
'1 file inspected, 1 offence detected',
|
824
879
|
''].join("\n"))
|
825
880
|
end
|
826
881
|
|
@@ -1033,6 +1088,15 @@ Usage: rubocop [options] [file1, file2, ...]
|
|
1033
1088
|
expect($stderr.string).to include('invalid option: --emacs')
|
1034
1089
|
end
|
1035
1090
|
end
|
1091
|
+
|
1092
|
+
describe '-s/--silent option' do
|
1093
|
+
it 'raises error in RuboCop 1.0.0' do
|
1094
|
+
# This spec can be removed
|
1095
|
+
# once CLI#ignore_dropped_options is removed.
|
1096
|
+
expect(cli.run(['--silent'])).to eq(1)
|
1097
|
+
expect($stderr.string).to include('invalid option: --silent')
|
1098
|
+
end
|
1099
|
+
end
|
1036
1100
|
end
|
1037
1101
|
|
1038
1102
|
describe '-o/--out option' do
|
@@ -1067,18 +1131,16 @@ Usage: rubocop [options] [file1, file2, ...]
|
|
1067
1131
|
|
1068
1132
|
expect(File.read('emacs_output.txt')).to eq([
|
1069
1133
|
"#{abs(target_file)}:2:80: C: Line is too long. [90/79]",
|
1070
|
-
'',
|
1071
|
-
'1 file inspected, 1 offence detected',
|
1072
1134
|
''
|
1073
1135
|
].join("\n"))
|
1074
1136
|
end
|
1075
1137
|
end
|
1076
1138
|
|
1077
1139
|
describe '#display_error_summary' do
|
1078
|
-
it 'displays an error message when errors are present' do
|
1140
|
+
it 'displays an error message to stderr when errors are present' do
|
1079
1141
|
msg = 'An error occurred while Encoding cop was inspecting file.rb.'
|
1080
1142
|
cli.display_error_summary([msg])
|
1081
|
-
expect($
|
1143
|
+
expect($stderr.string.lines.to_a[-6..-5])
|
1082
1144
|
.to eq(["1 error occurred:\n", "#{msg}\n"])
|
1083
1145
|
end
|
1084
1146
|
end
|