rubocop 0.14.1 → 0.15.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 (109) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +5 -3
  3. data/CHANGELOG.md +245 -198
  4. data/README.md +7 -0
  5. data/Rakefile +5 -1
  6. data/config/default.yml +27 -4
  7. data/config/enabled.yml +18 -4
  8. data/lib/rubocop.rb +13 -1
  9. data/lib/rubocop/cli.rb +83 -23
  10. data/lib/rubocop/config.rb +1 -1
  11. data/lib/rubocop/cop/cop.rb +31 -6
  12. data/lib/rubocop/cop/lint/block_alignment.rb +11 -8
  13. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +21 -14
  14. data/lib/rubocop/cop/lint/useless_setter_call.rb +1 -1
  15. data/lib/rubocop/cop/rails/output.rb +35 -0
  16. data/lib/rubocop/cop/style/{access_control.rb → access_modifier_indentation.rb} +18 -15
  17. data/lib/rubocop/cop/style/alias.rb +14 -2
  18. data/lib/rubocop/cop/style/align_hash.rb +174 -109
  19. data/lib/rubocop/cop/style/autocorrect_alignment.rb +38 -18
  20. data/lib/rubocop/cop/style/blocks.rb +4 -6
  21. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +3 -3
  22. data/lib/rubocop/cop/style/cyclomatic_complexity.rb +46 -0
  23. data/lib/rubocop/cop/style/empty_lines_around_access_modifier.rb +48 -0
  24. data/lib/rubocop/cop/style/empty_lines_around_body.rb +62 -0
  25. data/lib/rubocop/cop/style/end_of_line.rb +6 -2
  26. data/lib/rubocop/cop/style/favor_modifier.rb +11 -1
  27. data/lib/rubocop/cop/style/final_newline.rb +10 -4
  28. data/lib/rubocop/cop/style/hash_syntax.rb +32 -21
  29. data/lib/rubocop/cop/style/leading_comment_space.rb +9 -0
  30. data/lib/rubocop/cop/style/method_call_parentheses.rb +11 -1
  31. data/lib/rubocop/cop/style/numeric_literals.rb +11 -15
  32. data/lib/rubocop/cop/style/redundant_return.rb +7 -4
  33. data/lib/rubocop/cop/style/redundant_self.rb +3 -3
  34. data/lib/rubocop/cop/style/signal_exception.rb +4 -2
  35. data/lib/rubocop/cop/style/space_after_comma_etc.rb +7 -1
  36. data/lib/rubocop/cop/style/space_after_control_keyword.rb +6 -0
  37. data/lib/rubocop/cop/style/space_after_method_name.rb +7 -1
  38. data/lib/rubocop/cop/style/space_after_not.rb +6 -2
  39. data/lib/rubocop/cop/style/space_around_block_braces.rb +149 -0
  40. data/lib/rubocop/cop/style/space_around_equals_in_parameter_default.rb +33 -0
  41. data/lib/rubocop/cop/style/space_around_operators.rb +169 -0
  42. data/lib/rubocop/cop/style/space_before_modifier_keyword.rb +6 -0
  43. data/lib/rubocop/cop/style/space_inside.rb +35 -0
  44. data/lib/rubocop/cop/style/space_inside_brackets.rb +18 -0
  45. data/lib/rubocop/cop/style/space_inside_hash_literal_braces.rb +99 -0
  46. data/lib/rubocop/cop/style/space_inside_parens.rb +18 -0
  47. data/lib/rubocop/cop/style/special_global_vars.rb +52 -25
  48. data/lib/rubocop/cop/style/string_literals.rb +1 -1
  49. data/lib/rubocop/cop/style/surrounding_space.rb +1 -344
  50. data/lib/rubocop/cop/style/trailing_blank_lines.rb +17 -5
  51. data/lib/rubocop/cop/style/trailing_whitespace.rb +9 -5
  52. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -2
  53. data/lib/rubocop/cop/style/word_array.rb +16 -1
  54. data/lib/rubocop/cop/team.rb +5 -5
  55. data/lib/rubocop/cop/util.rb +1 -0
  56. data/lib/rubocop/formatter/offence_count_formatter.rb +0 -1
  57. data/lib/rubocop/options.rb +76 -111
  58. data/lib/rubocop/rake_task.rb +4 -2
  59. data/lib/rubocop/target_finder.rb +3 -3
  60. data/lib/rubocop/version.rb +1 -1
  61. data/spec/rubocop/cli_spec.rb +123 -13
  62. data/spec/rubocop/config_spec.rb +2 -2
  63. data/spec/rubocop/cop/lint/rescue_exception_spec.rb +10 -0
  64. data/spec/rubocop/cop/lint/useless_setter_call_spec.rb +13 -0
  65. data/spec/rubocop/cop/offence_spec.rb +2 -0
  66. data/spec/rubocop/cop/rails/output_spec.rb +40 -0
  67. data/spec/rubocop/cop/style/access_modifier_indentation_spec.rb +243 -0
  68. data/spec/rubocop/cop/style/alias_spec.rb +8 -0
  69. data/spec/rubocop/cop/style/align_array_spec.rb +12 -0
  70. data/spec/rubocop/cop/style/align_hash_spec.rb +15 -0
  71. data/spec/rubocop/cop/style/braces_around_hash_parameters_spec.rb +7 -4
  72. data/spec/rubocop/cop/style/cyclomatic_complexity_spec.rb +203 -0
  73. data/spec/rubocop/cop/style/empty_lines_around_access_modifier_spec.rb +56 -0
  74. data/spec/rubocop/cop/style/empty_lines_around_body_spec.rb +87 -0
  75. data/spec/rubocop/cop/style/end_of_line_spec.rb +17 -8
  76. data/spec/rubocop/cop/style/favor_modifier_spec.rb +34 -0
  77. data/spec/rubocop/cop/style/final_newline_spec.rb +5 -0
  78. data/spec/rubocop/cop/style/hash_syntax_spec.rb +22 -2
  79. data/spec/rubocop/cop/style/leading_comment_space_spec.rb +5 -0
  80. data/spec/rubocop/cop/style/method_call_parentheses_spec.rb +39 -4
  81. data/spec/rubocop/cop/style/numeric_literals_spec.rb +5 -0
  82. data/spec/rubocop/cop/style/signal_exception_spec.rb +11 -0
  83. data/spec/rubocop/cop/style/space_after_colon_spec.rb +7 -0
  84. data/spec/rubocop/cop/style/space_after_comma_spec.rb +5 -0
  85. data/spec/rubocop/cop/style/space_after_control_keyword_spec.rb +29 -8
  86. data/spec/rubocop/cop/style/space_after_method_name_spec.rb +15 -0
  87. data/spec/rubocop/cop/style/space_after_semicolon_spec.rb +5 -0
  88. data/spec/rubocop/cop/style/space_around_block_braces_spec.rb +68 -0
  89. data/spec/rubocop/cop/style/space_around_equals_in_default_parameter_spec.rb +5 -0
  90. data/spec/rubocop/cop/style/space_around_operators_spec.rb +43 -0
  91. data/spec/rubocop/cop/style/space_before_modifier_keyword_spec.rb +23 -0
  92. data/spec/rubocop/cop/style/space_inside_brackets_spec.rb +7 -0
  93. data/spec/rubocop/cop/style/space_inside_hash_literal_braces_spec.rb +65 -23
  94. data/spec/rubocop/cop/style/space_inside_parens_spec.rb +7 -0
  95. data/spec/rubocop/cop/style/special_global_vars_spec.rb +12 -2
  96. data/spec/rubocop/cop/style/string_literals_spec.rb +6 -0
  97. data/spec/rubocop/cop/style/symbol_array_spec.rb +5 -7
  98. data/spec/rubocop/cop/style/trailing_blank_lines_spec.rb +26 -1
  99. data/spec/rubocop/cop/style/trailing_whitespace_spec.rb +7 -0
  100. data/spec/rubocop/cop/style/trivial_accessors_spec.rb +8 -0
  101. data/spec/rubocop/cop/style/word_array_spec.rb +33 -2
  102. data/spec/rubocop/cop/team_spec.rb +4 -4
  103. data/spec/rubocop/formatter/json_formatter_spec.rb +1 -1
  104. data/spec/rubocop/options_spec.rb +5 -96
  105. data/spec/rubocop/processed_source_spec.rb +3 -3
  106. data/spec/spec_helper.rb +28 -23
  107. data/spec/support/mri_syntax_checker.rb +20 -16
  108. metadata +24 -5
  109. data/spec/rubocop/cop/style/access_control_spec.rb +0 -164
@@ -19,13 +19,25 @@ module Rubocop
19
19
  end
20
20
 
21
21
  if blank_lines > 0
22
- convention(nil,
23
- source_range(processed_source.buffer,
24
- processed_source[0...-blank_lines],
25
- 0, 1),
26
- format(MSG, blank_lines))
22
+ range_size =
23
+ processed_source.raw_lines.to_a[-blank_lines..-1].join.length
24
+ range = source_range(processed_source.buffer,
25
+ processed_source[0...-blank_lines],
26
+ 0, range_size)
27
+ convention(range, range, format(MSG, blank_lines))
27
28
  end
28
29
  end
30
+
31
+ def autocorrect(range)
32
+ # Bail out if there's also trailing whitespace, because
33
+ # auto-correction in the two cops would result in clobbering.
34
+ if range.source =~ / / &&
35
+ config.for_cop('TrailingWhitespace')['Enabled']
36
+ fail CorrectionNotPossible
37
+ end
38
+
39
+ @corrections << ->(corrector) { corrector.remove(range) }
40
+ end
29
41
  end
30
42
  end
31
43
  end
@@ -10,14 +10,18 @@ module Rubocop
10
10
  def investigate(processed_source)
11
11
  processed_source.lines.each_with_index do |line, index|
12
12
  if line =~ /.*[ \t]+$/
13
- convention(nil,
14
- source_range(processed_source.buffer,
15
- processed_source[0...index],
16
- line.rstrip.length,
17
- line.length - line.rstrip.length))
13
+ range = source_range(processed_source.buffer,
14
+ processed_source[0...index],
15
+ line.rstrip.length,
16
+ line.length - line.rstrip.length)
17
+ convention(range, range)
18
18
  end
19
19
  end
20
20
  end
21
+
22
+ def autocorrect(range)
23
+ @corrections << ->(corrector) { corrector.remove(range) }
24
+ end
21
25
  end
22
26
  end
23
27
  end
@@ -32,7 +32,6 @@ module Rubocop
32
32
  convention(node, :keyword,
33
33
  sprintf(MSG, kind, kind))
34
34
  end
35
-
36
35
  end
37
36
 
38
37
  def exact_name_match?
@@ -67,7 +66,7 @@ module Rubocop
67
66
  end
68
67
 
69
68
  def looks_like_trivial_writer?(args, body)
70
- args.children.size == 1 &&
69
+ args.children.size == 1 && args.children[0].type != :restarg &&
71
70
  body && body.type == :ivasgn &&
72
71
  body.children[1] && body.children[1].type == :lvar
73
72
  end
@@ -18,13 +18,24 @@ module Rubocop
18
18
 
19
19
  string_array = array_elems.all? { |e| e.type == :str }
20
20
 
21
- if string_array && !complex_content?(array_elems)
21
+ if string_array && !complex_content?(array_elems) &&
22
+ array_elems.size > min_size && !comments_in_array?(node)
22
23
  convention(node, :expression)
23
24
  end
24
25
  end
25
26
 
26
27
  private
27
28
 
29
+ def comments_in_array?(node)
30
+ comments = processed_source.comments
31
+
32
+ array_range = node.loc.expression.to_a
33
+
34
+ comments.any? do |comment|
35
+ !(comment.loc.expression.to_a & array_range).empty?
36
+ end
37
+ end
38
+
28
39
  def complex_content?(arr_sexp)
29
40
  arr_sexp.each do |s|
30
41
  source = s.loc.expression.source
@@ -36,6 +47,10 @@ module Rubocop
36
47
 
37
48
  false
38
49
  end
50
+
51
+ def min_size
52
+ cop_config['MinSize']
53
+ end
39
54
  end
40
55
  end
41
56
  end
@@ -9,12 +9,12 @@ module Rubocop
9
9
  def initialize(cop_classes, config, options = nil)
10
10
  @cop_classes = cop_classes
11
11
  @config = config
12
- @options = options || { autocorrect: false, debug: false }
12
+ @options = options || { auto_correct: false, debug: false }
13
13
  @errors = []
14
14
  end
15
15
 
16
16
  def autocorrect?
17
- @options[:autocorrect]
17
+ @options[:auto_correct]
18
18
  end
19
19
 
20
20
  def debug?
@@ -25,9 +25,9 @@ module Rubocop
25
25
  begin
26
26
  processed_source = SourceParser.parse_file(file)
27
27
  rescue Encoding::UndefinedConversionError, ArgumentError => e
28
- handle_error(e,
29
- "An error occurred while parsing #{file}.".color(:red))
30
- return []
28
+ range = Struct.new(:line, :column, :source_line).new(1, 0, '')
29
+ return [Offence.new(:fatal, range, e.message.capitalize + '.',
30
+ 'Parser')]
31
31
  end
32
32
 
33
33
  # If we got any syntax errors, return only the syntax offences.
@@ -62,6 +62,7 @@ module Rubocop
62
62
  namespace_node, name = *const_node
63
63
  const_names << name
64
64
  break unless namespace_node
65
+ break unless namespace_node.is_a?(Parser::AST::Node)
65
66
  break if namespace_node.type == :cbase
66
67
  const_node = namespace_node
67
68
  end
@@ -10,7 +10,6 @@ module Rubocop
10
10
  # (26) LineLength
11
11
  # (3) OneLineConditional
12
12
  class OffenceCountFormatter < BaseFormatter
13
-
14
13
  attr_reader :offence_counts
15
14
 
16
15
  def started(target_files)
@@ -7,12 +7,10 @@ module Rubocop
7
7
  class Options
8
8
  DEFAULT_FORMATTER = 'progress'
9
9
 
10
- def initialize(config_store)
11
- @config_store = config_store
10
+ def initialize
12
11
  @options = {}
13
12
  end
14
13
 
15
- # rubocop:disable MethodLength
16
14
  def parse(args)
17
15
  ignore_dropped_options(args)
18
16
  convert_deprecated_options(args)
@@ -20,89 +18,91 @@ module Rubocop
20
18
  OptionParser.new do |opts|
21
19
  opts.banner = 'Usage: rubocop [options] [file1, file2, ...]'
22
20
 
23
- opts.on('-d', '--debug', 'Display debug info.') do |d|
24
- @options[:debug] = d
25
- end
26
- opts.on('-c', '--config FILE', 'Specify configuration file.') do |f|
27
- @options[:config] = f
28
- @config_store.set_options_config(@options[:config])
29
- end
30
- opts.on('--only COP', 'Run just one cop.') do |s|
31
- @options[:only] = s
21
+ option(opts, '--only COP', 'Run just one cop.') do
32
22
  validate_only_option
33
23
  end
34
- opts.on('--auto-gen-config',
35
- 'Generate a configuration file acting as a',
36
- 'TODO list.') do
37
- @options[:auto_gen_config] = true
38
- @options[:formatters] = [
39
- [DEFAULT_FORMATTER],
40
- [Formatter::DisabledConfigFormatter,
41
- ConfigLoader::AUTO_GENERATED_FILE]
42
- ]
43
- validate_auto_gen_config_option(args)
44
- end
45
- opts.on('--show-cops',
46
- 'Shows cops and their config for the',
47
- 'current directory.') do
48
- print_available_cops
49
- exit(0)
50
- end
51
- opts.on('-f', '--format FORMATTER',
52
- 'Choose an output formatter. This option',
53
- 'can be specified multiple times to enable',
54
- 'multiple formatters at the same time.',
55
- ' [p]rogress (default)',
56
- ' [s]imple',
57
- ' [c]lang',
58
- ' [e]macs',
59
- ' [j]son',
60
- ' [f]iles',
61
- ' [o]ffences',
62
- ' custom formatter class name') do |key|
63
- @options[:formatters] ||= []
64
- @options[:formatters] << [key]
65
- end
66
- opts.on('-o', '--out FILE',
67
- 'Write output to a file instead of STDOUT.',
68
- 'This option applies to the previously',
69
- 'specified --format, or the default format',
70
- 'if no format is specified.') do |path|
71
- @options[:formatters] ||= [[DEFAULT_FORMATTER]]
72
- @options[:formatters].last << path
73
- end
74
- opts.on('-r', '--require FILE', 'Require Ruby file.') do |f|
24
+
25
+ option(opts, '-c', '--config FILE', 'Specify configuration file.')
26
+
27
+ add_formatting_options(opts, args)
28
+
29
+ option(opts, '-r', '--require FILE', 'Require Ruby file.') do |f|
75
30
  require f
76
31
  end
77
- opts.on('-R', '--rails', 'Run extra Rails cops.') do |r|
78
- @options[:rails] = r
79
- end
80
- opts.on('-l', '--lint', 'Run only lint cops.') do |l|
81
- @options[:lint] = l
82
- end
83
- opts.on('-a', '--auto-correct', 'Auto-correct offences.') do |a|
84
- @options[:autocorrect] = a
85
- end
86
- opts.on('-n', '--no-color', 'Disable color output.') do |s|
87
- Sickill::Rainbow.enabled = false
88
- end
89
- opts.on('-v', '--version', 'Display version.') do
90
- puts Rubocop::Version.version(false)
91
- exit(0)
92
- end
93
- opts.on('-V', '--verbose-version', 'Display verbose version.') do
94
- puts Rubocop::Version.version(true)
95
- exit(0)
96
- end
32
+
33
+ add_boolean_flags(opts)
97
34
  end.parse!(args)
98
35
 
99
- target_files = target_finder.find(args)
100
- [@options, target_files]
36
+ [@options, args]
101
37
  end
102
- # rubocop:enable MethodLength
103
38
 
104
39
  private
105
40
 
41
+ FORMAT_HELP = ['Choose an output formatter. This option',
42
+ 'can be specified multiple times to enable',
43
+ 'multiple formatters at the same time.',
44
+ ' [p]rogress (default)',
45
+ ' [s]imple',
46
+ ' [c]lang',
47
+ ' [e]macs',
48
+ ' [j]son',
49
+ ' [f]iles',
50
+ ' [o]ffences',
51
+ ' custom formatter class name']
52
+
53
+ def add_formatting_options(opts, args)
54
+ option(opts, '--auto-gen-config',
55
+ 'Generate a configuration file acting as a', 'TODO list.') do
56
+ validate_auto_gen_config_option(args)
57
+ @options[:formatters] = [[DEFAULT_FORMATTER],
58
+ [Formatter::DisabledConfigFormatter,
59
+ ConfigLoader::AUTO_GENERATED_FILE]]
60
+ end
61
+
62
+ option(opts, '-f', '--format FORMATTER', *FORMAT_HELP) do |key|
63
+ @options[:formatters] ||= []
64
+ @options[:formatters] << [key]
65
+ end
66
+
67
+ option(opts, '-o', '--out FILE',
68
+ 'Write output to a file instead of STDOUT.',
69
+ 'This option applies to the previously',
70
+ 'specified --format, or the default format',
71
+ 'if no format is specified.') do |path|
72
+ @options[:formatters] ||= [[DEFAULT_FORMATTER]]
73
+ @options[:formatters].last << path
74
+ end
75
+ end
76
+
77
+ def add_boolean_flags(opts)
78
+ option(opts, '--show-cops',
79
+ 'Shows cops and their config for the',
80
+ 'current directory.')
81
+ option(opts, '-d', '--debug', 'Display debug info.')
82
+ option(opts, '-R', '--rails', 'Run extra Rails cops.')
83
+ option(opts, '-l', '--lint', 'Run only lint cops.')
84
+ option(opts, '-a', '--auto-correct', 'Auto-correct offences.')
85
+ option(opts, '-n', '--no-color', 'Disable color output.')
86
+ option(opts, '-v', '--version', 'Display version.')
87
+ option(opts, '-V', '--verbose-version', 'Display verbose version.')
88
+ end
89
+
90
+ # Sets a value in the @options hash, based on the given long option and its
91
+ # value, in addition to calling the block if a block is given.
92
+ def option(opts, *args)
93
+ opts.on(*args) do |arg|
94
+ @options[long_opt_symbol(args)] = arg
95
+ yield arg if block_given?
96
+ end
97
+ end
98
+
99
+ # Finds the option in `args` starting with -- and converts it to a symbol,
100
+ # e.g. [..., '--auto-correct', ...] to :auto_correct.
101
+ def long_opt_symbol(args)
102
+ long_opt = args.find { |arg| arg.start_with?('--') }
103
+ long_opt[2..-1].sub(/ .*/, '').gsub(/-/, '_').to_sym
104
+ end
105
+
106
106
  def ignore_dropped_options(args)
107
107
  # Currently we don't make -s/--silent option raise error
108
108
  # since those are mostly used by external tools.
@@ -144,41 +144,6 @@ module Rubocop
144
144
  fail ArgumentError,
145
145
  '--auto-gen-config can not be combined with any other arguments.'
146
146
  end
147
-
148
- target_finder.find(args).each do |file|
149
- config = @config_store.for(file)
150
- if @options[:auto_gen_config] && config.contains_auto_generated_config
151
- fail "Remove #{ConfigLoader::AUTO_GENERATED_FILE} from the " +
152
- 'current configuration before generating it again.'
153
- end
154
- end
155
- end
156
-
157
- def target_finder
158
- @target_finder ||= TargetFinder.new(@config_store, @options[:debug])
159
- end
160
-
161
- def print_available_cops
162
- cops = Cop::Cop.all
163
- puts "Available cops (#{cops.length}) + config for #{Dir.pwd.to_s}: "
164
- dirconf = @config_store.for(Dir.pwd.to_s)
165
- cops.types.sort!.each do |type|
166
- coptypes = cops.with_type(type).sort_by!(&:cop_name)
167
- puts "Type '#{type.to_s.capitalize}' (#{coptypes.size}):"
168
- coptypes.each do |cop|
169
- puts " - #{cop.cop_name}"
170
- cnf = dirconf.for_cop(cop).dup
171
- print_conf_option('Description',
172
- cnf.delete('Description') { 'None' })
173
- cnf.each { |k, v| print_conf_option(k, v) }
174
- print_conf_option('SupportsAutoCorrection',
175
- cop.new.support_autocorrect?.to_s)
176
- end
177
- end
178
- end
179
-
180
- def print_conf_option(option, value)
181
- puts " - #{option}: #{value}"
182
147
  end
183
148
  end
184
149
  end
@@ -1,6 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'rubocop'
4
3
  require 'rake'
5
4
  require 'rake/tasklib'
6
5
 
@@ -10,7 +9,6 @@ module Rubocop
10
9
  # require 'rubocop/rake_task'
11
10
  # Rubocop::RakeTask.new
12
11
  class RakeTask < Rake::TaskLib
13
-
14
12
  attr_accessor :name
15
13
  attr_accessor :verbose
16
14
  attr_accessor :fail_on_error
@@ -32,6 +30,10 @@ module Rubocop
32
30
  end
33
31
 
34
32
  def run_task(verbose)
33
+ # We lazy-load rubocop so that the task doesn't dramatically impact the
34
+ # load time of your Rakefile.
35
+ require 'rubocop'
36
+
35
37
  cli = CLI.new
36
38
  puts 'Running RuboCop...' if verbose
37
39
  result = cli.run(patterns)
@@ -42,13 +42,13 @@ module Rubocop
42
42
  # @return [Array] Array of filenames
43
43
  def target_files_in_dir(base_dir = Dir.pwd)
44
44
  files = Dir["#{base_dir}/**/*"].select { |path| FileTest.file?(path) }
45
+ base_dir_config = @config_store.for("#{base_dir}/foobar.rb")
45
46
 
46
47
  target_files = files.select do |file|
47
- config = @config_store.for(file)
48
- next false if config.file_to_exclude?(file)
48
+ next false if base_dir_config.file_to_exclude?(file)
49
49
  next true if File.extname(file) == '.rb'
50
50
  next true if ruby_executable?(file)
51
- config.file_to_include?(file)
51
+ @config_store.for(file).file_to_include?(file)
52
52
  end
53
53
 
54
54
  target_files.uniq
@@ -3,7 +3,7 @@
3
3
  module Rubocop
4
4
  # This module holds the RuboCop version information.
5
5
  module Version
6
- STRING = '0.14.1'
6
+ STRING = '0.15.0'
7
7
 
8
8
  MSG = '%s (using Parser %s, running on %s %s %s)'
9
9
 
@@ -25,6 +25,14 @@ describe Rubocop::CLI, :isolated_environment do
25
25
  end
26
26
 
27
27
  describe 'option' do
28
+ describe '--version' do
29
+ it 'exits cleanly' do
30
+ expect { cli.run ['-v'] }.to exit_with_code(0)
31
+ expect { cli.run ['--version'] }.to exit_with_code(0)
32
+ expect($stdout.string).to eq((Rubocop::Version::STRING + "\n") * 2)
33
+ end
34
+ end
35
+
28
36
  describe '--auto-gen-config' do
29
37
  it 'exits with error if asked to re-generate a todo list that is in ' +
30
38
  'use' do
@@ -171,6 +179,88 @@ describe Rubocop::CLI, :isolated_environment do
171
179
  end
172
180
  end
173
181
 
182
+ describe '--show-cops' do
183
+ let(:cops) { Rubocop::Cop::Cop.all }
184
+
185
+ let(:global_conf) do
186
+ config_path =
187
+ Rubocop::ConfigLoader.configuration_file_for(Dir.pwd.to_s)
188
+ Rubocop::ConfigLoader.configuration_from_file(config_path)
189
+ end
190
+
191
+ let(:stdout) { $stdout.string }
192
+
193
+ before do
194
+ expect { cli.run ['--show-cops'] }.to exit_with_code(0)
195
+ end
196
+
197
+ # Extracts the first line out of the description
198
+ def short_description_of_cop(cop)
199
+ desc = full_description_of_cop(cop)
200
+ desc ? desc.lines.first.strip : ''
201
+ end
202
+
203
+ # Gets the full description of the cop or nil if no description is set.
204
+ def full_description_of_cop(cop)
205
+ cop_config = global_conf.for_cop(cop)
206
+ cop_config['Description']
207
+ end
208
+
209
+ it 'prints all available cops and their description' do
210
+ cops.each do |cop|
211
+ expect(stdout).to include cop.cop_name
212
+ expect(stdout).to include short_description_of_cop(cop)
213
+ end
214
+ end
215
+
216
+ it 'prints all types' do
217
+ cops
218
+ .types
219
+ .map(&:to_s)
220
+ .map(&:capitalize)
221
+ .each { |type| expect(stdout).to include(type) }
222
+ end
223
+
224
+ it 'prints all cops in their right type listing' do
225
+ lines = stdout.lines
226
+ lines.slice_before(/Type /).each do |slice|
227
+ types = cops.types.map(&:to_s).map(&:capitalize)
228
+ current = types.delete(slice.shift[/Type '(?<c>[^'']+)'/, 'c'])
229
+ # all cops in their type listing
230
+ cops.with_type(current).each do |cop|
231
+ expect(slice.any? { |l| l.include? cop.cop_name }).to be_true
232
+ end
233
+
234
+ # no cop in wrong type listing
235
+ types.each do |type|
236
+ cops.with_type(type).each do |cop|
237
+ expect(slice.any? { |l| l.include? cop.cop_name }).to be_false
238
+ end
239
+ end
240
+ end
241
+ end
242
+
243
+ it 'prints the current configuration' do
244
+ out = stdout.lines.to_a
245
+ cops.each do |cop|
246
+ conf = global_conf[cop.cop_name].dup
247
+ confstrt =
248
+ out.find_index { |i| i.include?("- #{cop.cop_name}") } + 1
249
+ c = out[confstrt, conf.keys.size].to_s
250
+ conf.delete('Description')
251
+ expect(c).to include(short_description_of_cop(cop))
252
+ conf.each do |k, v|
253
+ # ugly hack to get hash/array content tested
254
+ if v.kind_of?(Hash) || v.kind_of?(Array)
255
+ expect(c).to include "#{k}: #{v.to_s.dump[2, -2]}"
256
+ else
257
+ expect(c).to include "#{k}: #{v}"
258
+ end
259
+ end
260
+ end
261
+ end
262
+ end
263
+
174
264
  describe '-f/--format' do
175
265
  let(:target_file) { 'example.rb' }
176
266
 
@@ -498,7 +588,10 @@ describe Rubocop::CLI, :isolated_environment do
498
588
  '# encoding: utf-8',
499
589
  "# #{'f9'.hex.chr}#{'29'.hex.chr}"
500
590
  ])
501
- expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(0)
591
+ expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(1)
592
+ expect($stdout.string)
593
+ .to eq(["#{abs('example.rb')}:1:1: F: Invalid byte sequence in utf-8.",
594
+ ''].join("\n"))
502
595
  end
503
596
 
504
597
  describe 'rubocop:disable comment' do
@@ -927,6 +1020,31 @@ describe Rubocop::CLI, :isolated_environment do
927
1020
  ''].join("\n"))
928
1021
  end
929
1022
 
1023
+ # Being immune to bad configuration files in excluded directories has
1024
+ # become important due to a bug in rubygems
1025
+ # (https://github.com/rubygems/rubygems/issues/680) that makes
1026
+ # installations of, for example, rubocop lack their .rubocop.yml in the
1027
+ # root directory.
1028
+ it 'can exclude a vendor directory with an erroneous config file' do
1029
+ create_file('vendor/bundle/ruby/1.9.1/gems/parser-2.0.0/.rubocop.yml',
1030
+ ['inherit_from: non_existent.yml'])
1031
+
1032
+ create_file('vendor/bundle/ruby/1.9.1/gems/parser-2.0.0/lib/ex.rb',
1033
+ ['# encoding: utf-8',
1034
+ '#' * 90])
1035
+
1036
+ create_file('.rubocop.yml',
1037
+ ['AllCops:',
1038
+ ' Excludes:',
1039
+ ' - vendor/**'])
1040
+
1041
+ cli.run(%w(--format simple))
1042
+ expect($stderr.string).to eq('')
1043
+ expect($stdout.string)
1044
+ .to eq(['', '0 files inspected, no offences detected',
1045
+ ''].join("\n"))
1046
+ end
1047
+
930
1048
  # Relative exclude paths in .rubocop.yml files are relative to that file,
931
1049
  # but in configuration files with other names they will be relative to
932
1050
  # whatever file inherits from them.
@@ -967,14 +1085,10 @@ describe Rubocop::CLI, :isolated_environment do
967
1085
  ])
968
1086
 
969
1087
  expect(cli.run(%w(--format simple example))).to eq(1)
970
- expect($stdout.string)
1088
+ expect($stderr.string)
971
1089
  .to eq(
972
1090
  ['Warning: unrecognized cop LyneLenth found in ' +
973
- File.expand_path('example/.rubocop.yml'),
974
- '== example/example1.rb ==',
975
- 'C: 2: 80: Line is too long. [90/79]',
976
- '',
977
- '1 file inspected, 1 offence detected',
1091
+ abs('example/.rubocop.yml'),
978
1092
  ''].join("\n"))
979
1093
  end
980
1094
 
@@ -991,14 +1105,10 @@ describe Rubocop::CLI, :isolated_environment do
991
1105
  ])
992
1106
 
993
1107
  expect(cli.run(%w(--format simple example))).to eq(1)
994
- expect($stdout.string)
1108
+ expect($stderr.string)
995
1109
  .to eq(
996
1110
  ['Warning: unrecognized parameter LineLength:Min found in ' +
997
- File.expand_path('example/.rubocop.yml'),
998
- '== example/example1.rb ==',
999
- 'C: 2: 80: Line is too long. [90/79]',
1000
- '',
1001
- '1 file inspected, 1 offence detected',
1111
+ abs('example/.rubocop.yml'),
1002
1112
  ''].join("\n"))
1003
1113
  end
1004
1114
  end