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.

Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +32 -1
  3. data/README.md +28 -3
  4. data/config/default.yml +14 -12
  5. data/config/disabled.yml +1 -1
  6. data/config/enabled.yml +190 -118
  7. data/lib/rubocop.rb +9 -1
  8. data/lib/rubocop/cli.rb +49 -13
  9. data/lib/rubocop/config.rb +5 -5
  10. data/lib/rubocop/cop/cop.rb +34 -1
  11. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +47 -0
  12. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -4
  13. data/lib/rubocop/cop/lint/useless_assignment.rb +39 -11
  14. data/lib/rubocop/cop/lint/useless_comparison.rb +2 -4
  15. data/lib/rubocop/cop/rails/has_and_belongs_to_many.rb +20 -0
  16. data/lib/rubocop/cop/rails/read_attribute.rb +28 -0
  17. data/lib/rubocop/cop/style/access_control.rb +12 -1
  18. data/lib/rubocop/cop/style/attr.rb +7 -0
  19. data/lib/rubocop/cop/style/collection_methods.rb +13 -1
  20. data/lib/rubocop/cop/style/constant_name.rb +1 -1
  21. data/lib/rubocop/cop/style/def_parentheses.rb +18 -0
  22. data/lib/rubocop/cop/style/documentation.rb +1 -1
  23. data/lib/rubocop/cop/style/empty_literal.rb +14 -0
  24. data/lib/rubocop/cop/style/even_odd.rb +56 -0
  25. data/lib/rubocop/cop/style/favor_modifier.rb +2 -2
  26. data/lib/rubocop/cop/style/hash_methods.rb +40 -0
  27. data/lib/rubocop/cop/style/indentation_width.rb +148 -0
  28. data/lib/rubocop/cop/style/method_and_variable_snake_case.rb +40 -25
  29. data/lib/rubocop/cop/style/method_call_parentheses.rb +8 -0
  30. data/lib/rubocop/cop/style/multiline_if_then.rb +1 -1
  31. data/lib/rubocop/cop/style/nil_comparison.rb +38 -0
  32. data/lib/rubocop/cop/style/signal_exception.rb +11 -0
  33. data/lib/rubocop/cop/style/space_after_method_name.rb +34 -0
  34. data/lib/rubocop/cop/util.rb +17 -0
  35. data/lib/rubocop/formatter/emacs_style_formatter.rb +2 -2
  36. data/lib/rubocop/formatter/file_list_formatter.rb +3 -2
  37. data/lib/rubocop/formatter/formatter_set.rb +3 -11
  38. data/lib/rubocop/formatter/offence_count_formatter.rb +50 -0
  39. data/lib/rubocop/formatter/progress_formatter.rb +0 -2
  40. data/lib/rubocop/formatter/simple_text_formatter.rb +1 -6
  41. data/lib/rubocop/version.rb +1 -1
  42. data/spec/project_spec.rb +7 -0
  43. data/spec/rubocop/cli_spec.rb +119 -57
  44. data/spec/rubocop/config_spec.rb +23 -17
  45. data/spec/rubocop/cop/commissioner_spec.rb +8 -8
  46. data/spec/rubocop/cop/cop_spec.rb +80 -0
  47. data/spec/rubocop/cop/lint/parentheses_as_grouped_expression_spec.rb +63 -0
  48. data/spec/rubocop/cop/lint/useless_assignment_spec.rb +59 -0
  49. data/spec/rubocop/cop/rails/has_and_belongs_to_many_spec.rb +19 -0
  50. data/spec/rubocop/cop/rails/read_attribute_spec.rb +19 -0
  51. data/spec/rubocop/cop/rails/validation_spec.rb +5 -5
  52. data/spec/rubocop/cop/style/access_control_spec.rb +28 -0
  53. data/spec/rubocop/cop/style/attr_spec.rb +6 -1
  54. data/spec/rubocop/cop/style/collection_methods_spec.rb +5 -0
  55. data/spec/rubocop/cop/style/constant_name_spec.rb +9 -0
  56. data/spec/rubocop/cop/style/def_with_parentheses_spec.rb +14 -9
  57. data/spec/rubocop/cop/style/def_without_parentheses_spec.rb +12 -7
  58. data/spec/rubocop/cop/style/empty_literal_spec.rb +42 -27
  59. data/spec/rubocop/cop/style/even_odd_spec.rb +47 -0
  60. data/spec/rubocop/cop/style/favor_modifier_spec.rb +15 -14
  61. data/spec/rubocop/cop/style/hash_methods_spec.rb +51 -0
  62. data/spec/rubocop/cop/style/indentation_width_spec.rb +390 -0
  63. data/spec/rubocop/cop/style/method_and_variable_snake_case_spec.rb +58 -50
  64. data/spec/rubocop/cop/style/method_call_parentheses_spec.rb +6 -1
  65. data/spec/rubocop/cop/style/nil_comparison_spec.rb +31 -0
  66. data/spec/rubocop/cop/style/signal_exception_spec.rb +28 -0
  67. data/spec/rubocop/cop/style/space_after_method_name_spec.rb +61 -0
  68. data/spec/rubocop/formatter/emacs_style_formatter_spec.rb +9 -2
  69. data/spec/rubocop/formatter/file_list_formatter_spec.rb +3 -3
  70. data/spec/rubocop/formatter/offence_count_formatter_spec.rb +52 -0
  71. data/spec/rubocop/formatter/progress_formatter_spec.rb +70 -84
  72. data/spec/rubocop/source_parser_spec.rb +1 -1
  73. metadata +29 -5
  74. data/lib/rubocop/cop/style/line_continuation.rb +0 -27
  75. 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
- name = case n.type
24
- when :def
25
- name_of_instance_method(n)
26
- when :defs
27
- name_of_singleton_method(n)
28
- when :lvasgn, :ivasgn
29
- name_of_variable(n)
30
- when :send
31
- name_of_setter(n)
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, n.location.expression, MSG)
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.children.first
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.children[1]
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.children.first
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 nil unless receiver && receiver.type == :self
56
- return nil unless method_name.to_s.end_with?('=')
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
- else_clause.loc.expression.begin
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
@@ -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 < SimpleTextFormatter
8
- def report_file(file, offences)
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 < SimpleTextFormatter
13
- def report_file(file, offences)
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
- formatter = formatter_class.new(output)
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
@@ -30,8 +30,6 @@ module Rubocop
30
30
  def finished(inspected_files)
31
31
  output.puts
32
32
 
33
- return unless reports_summary?
34
-
35
33
  unless @offences_for_files.empty?
36
34
  output.puts
37
35
  output.puts 'Offences:'
@@ -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
- if reports_summary?
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)
@@ -3,7 +3,7 @@
3
3
  module Rubocop
4
4
  # This module holds the RuboCop version information.
5
5
  module Version
6
- STRING = '0.11.1'
6
+ STRING = '0.12.0'
7
7
 
8
8
  MSG = '%s (using Parser %s, running on %s %s %s)'
9
9
 
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
@@ -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 = 0",
247
- 'puts x'])
248
- expect(cli.run(['--format', 'clang', 'example1.rb', 'example2.rb']))
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 = 0",
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
- '2 files inspected, 5 offences detected',
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
- it 'ommits summary when --silent passed', ruby: 1.9 do
391
- create_file('example1.rb', 'puts 0 ')
392
- create_file('example2.rb', "\tputs 0")
393
- expect(cli.run(['--format',
394
- 'emacs',
395
- '--silent',
396
- 'example1.rb',
397
- 'example2.rb'])).to eq(1)
398
- expect($stdout.string).to eq(
399
- ["#{abs('example1.rb')}:1:1: C: Missing utf-8 encoding comment.",
400
- "#{abs('example1.rb')}:1:7: C: Trailing whitespace detected.",
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
- it 'ommits summary when --silent passed', ruby: 2.0 do
407
- create_file('example1.rb', 'puts 0 ')
408
- create_file('example2.rb', "\tputs 0")
409
- expect(cli.run(['--format',
410
- 'emacs',
411
- '--silent',
412
- 'example1.rb',
413
- 'example2.rb'])).to eq(1)
414
- expect($stdout.string).to eq(
415
- ["#{abs('example1.rb')}:1:7: C: Trailing whitespace detected.",
416
- "#{abs('example2.rb')}:1:1: C: Tab detected.",
417
- ''].join("\n"))
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 eq(
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($stdout.string.lines.to_a[-6..-5])
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