rubocop 0.1.0 → 0.2.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 (50) hide show
  1. data/.rbenv-version +1 -0
  2. data/.travis.yml +4 -0
  3. data/Gemfile +8 -8
  4. data/README.md +17 -1
  5. data/VERSION +1 -1
  6. data/bin/rubocop +1 -1
  7. data/features/step_definitions/rubocop_steps.rb +1 -0
  8. data/features/support/env.rb +2 -0
  9. data/lib/rubocop.rb +6 -0
  10. data/lib/rubocop/cli.rb +37 -17
  11. data/lib/rubocop/cop/align_parameters.rb +112 -0
  12. data/lib/rubocop/cop/cop.rb +43 -21
  13. data/lib/rubocop/cop/def_parentheses.rb +38 -0
  14. data/lib/rubocop/cop/empty_lines.rb +7 -6
  15. data/lib/rubocop/cop/encoding.rb +1 -1
  16. data/lib/rubocop/cop/end_of_line.rb +17 -0
  17. data/lib/rubocop/cop/grammar.rb +69 -9
  18. data/lib/rubocop/cop/hash_syntax.rb +26 -0
  19. data/lib/rubocop/cop/if_then_else.rb +49 -0
  20. data/lib/rubocop/cop/indentation.rb +16 -27
  21. data/lib/rubocop/cop/line_length.rb +2 -2
  22. data/lib/rubocop/cop/numeric_literals.rb +19 -0
  23. data/lib/rubocop/cop/offence.rb +2 -3
  24. data/lib/rubocop/cop/space_after_comma_etc.rb +10 -9
  25. data/lib/rubocop/cop/surrounding_space.rb +66 -17
  26. data/lib/rubocop/cop/tab.rb +2 -2
  27. data/lib/rubocop/cop/trailing_whitespace.rb +2 -2
  28. data/lib/rubocop/report/emacs_style.rb +4 -3
  29. data/rubocop.gemspec +16 -2
  30. data/spec/rubocop/cli_spec.rb +20 -5
  31. data/spec/rubocop/cops/align_parameters_spec.rb +201 -0
  32. data/spec/rubocop/cops/cop_spec.rb +4 -2
  33. data/spec/rubocop/cops/def_parentheses_spec.rb +48 -0
  34. data/spec/rubocop/cops/empty_lines_spec.rb +9 -8
  35. data/spec/rubocop/cops/end_of_line_spec.rb +17 -0
  36. data/spec/rubocop/cops/grammar_spec.rb +51 -11
  37. data/spec/rubocop/cops/hash_syntax_spec.rb +44 -0
  38. data/spec/rubocop/cops/if_then_else_spec.rb +74 -0
  39. data/spec/rubocop/cops/indentation_spec.rb +29 -4
  40. data/spec/rubocop/cops/line_length_spec.rb +4 -2
  41. data/spec/rubocop/cops/numeric_literals_spec.rb +49 -0
  42. data/spec/rubocop/cops/offence_spec.rb +4 -3
  43. data/spec/rubocop/cops/space_after_comma_etc_spec.rb +7 -5
  44. data/spec/rubocop/cops/surrounding_space_spec.rb +89 -26
  45. data/spec/rubocop/cops/tab_spec.rb +4 -2
  46. data/spec/rubocop/cops/trailing_whitespace_spec.rb +5 -3
  47. data/spec/rubocop/reports/emacs_style_spec.rb +4 -2
  48. data/spec/rubocop/reports/report_spec.rb +3 -1
  49. data/spec/spec_helper.rb +9 -1
  50. metadata +17 -3
@@ -5,10 +5,10 @@ module Rubocop
5
5
  class Tab < Cop
6
6
  ERROR_MESSAGE = 'Tab detected.'
7
7
 
8
- def inspect(file, source)
8
+ def inspect(file, source, tokens, sexp)
9
9
  source.each_with_index do |line, index|
10
10
  if line =~ /^ *\t/
11
- add_offence(:convention, index, line, ERROR_MESSAGE)
11
+ add_offence(:convention, index + 1, ERROR_MESSAGE)
12
12
  end
13
13
  end
14
14
  end
@@ -5,10 +5,10 @@ module Rubocop
5
5
  class TrailingWhitespace < Cop
6
6
  ERROR_MESSAGE = 'Trailing whitespace detected.'
7
7
 
8
- def inspect(file, source)
8
+ def inspect(file, source, tokens, sexp)
9
9
  source.each_with_index do |line, index|
10
10
  if line =~ /.*[ \t]+$/
11
- add_offence(:convention, index, line, ERROR_MESSAGE)
11
+ add_offence(:convention, index + 1, ERROR_MESSAGE)
12
12
  end
13
13
  end
14
14
  end
@@ -6,9 +6,10 @@ module Rubocop
6
6
  class EmacsStyle < PlainText
7
7
  # Generates a string representation of the report
8
8
  def generate
9
- entries.map { |e|
10
- "#@filename:#{e.line_number + 1}: #{e.encode_severity}: #{e.message}"
11
- }.join("\n")
9
+ report = entries.map do |e|
10
+ "#@filename:#{e.line_number}: #{e.encode_severity}: #{e.message}"
11
+ end
12
+ report.join("\n")
12
13
  end
13
14
  end
14
15
  end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "rubocop"
8
- s.version = "0.1.0"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Bozhidar Batsov"]
12
- s.date = "2012-12-20"
12
+ s.date = "2013-01-02"
13
13
  s.description = "Automatic Ruby code style checking tool. Aims to enforce the community-driven Ruby Style Guide."
14
14
  s.email = "bozhidar@batsov.com"
15
15
  s.executables = ["rubocop"]
@@ -19,8 +19,10 @@ Gem::Specification.new do |s|
19
19
  ]
20
20
  s.files = [
21
21
  ".document",
22
+ ".rbenv-version",
22
23
  ".rspec",
23
24
  ".rvmrc",
25
+ ".travis.yml",
24
26
  "Gemfile",
25
27
  "Gemfile.lock",
26
28
  "LICENSE.txt",
@@ -33,12 +35,18 @@ Gem::Specification.new do |s|
33
35
  "features/support/env.rb",
34
36
  "lib/rubocop.rb",
35
37
  "lib/rubocop/cli.rb",
38
+ "lib/rubocop/cop/align_parameters.rb",
36
39
  "lib/rubocop/cop/cop.rb",
40
+ "lib/rubocop/cop/def_parentheses.rb",
37
41
  "lib/rubocop/cop/empty_lines.rb",
38
42
  "lib/rubocop/cop/encoding.rb",
43
+ "lib/rubocop/cop/end_of_line.rb",
39
44
  "lib/rubocop/cop/grammar.rb",
45
+ "lib/rubocop/cop/hash_syntax.rb",
46
+ "lib/rubocop/cop/if_then_else.rb",
40
47
  "lib/rubocop/cop/indentation.rb",
41
48
  "lib/rubocop/cop/line_length.rb",
49
+ "lib/rubocop/cop/numeric_literals.rb",
42
50
  "lib/rubocop/cop/offence.rb",
43
51
  "lib/rubocop/cop/space_after_comma_etc.rb",
44
52
  "lib/rubocop/cop/surrounding_space.rb",
@@ -50,11 +58,17 @@ Gem::Specification.new do |s|
50
58
  "lib/rubocop/version.rb",
51
59
  "rubocop.gemspec",
52
60
  "spec/rubocop/cli_spec.rb",
61
+ "spec/rubocop/cops/align_parameters_spec.rb",
53
62
  "spec/rubocop/cops/cop_spec.rb",
63
+ "spec/rubocop/cops/def_parentheses_spec.rb",
54
64
  "spec/rubocop/cops/empty_lines_spec.rb",
65
+ "spec/rubocop/cops/end_of_line_spec.rb",
55
66
  "spec/rubocop/cops/grammar_spec.rb",
67
+ "spec/rubocop/cops/hash_syntax_spec.rb",
68
+ "spec/rubocop/cops/if_then_else_spec.rb",
56
69
  "spec/rubocop/cops/indentation_spec.rb",
57
70
  "spec/rubocop/cops/line_length_spec.rb",
71
+ "spec/rubocop/cops/numeric_literals_spec.rb",
58
72
  "spec/rubocop/cops/offence_spec.rb",
59
73
  "spec/rubocop/cops/space_after_comma_etc_spec.rb",
60
74
  "spec/rubocop/cops/surrounding_space_spec.rb",
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  module Rubocop
@@ -17,7 +19,10 @@ module Rubocop
17
19
  end
18
20
 
19
21
  it 'checks a given correct file and returns 0' do
20
- File.open('example.rb', 'w') { |f| f.puts 'x = 0' }
22
+ File.open('example.rb', 'w') do |f|
23
+ f.puts '# encoding: utf-8'
24
+ f.puts 'x = 0'
25
+ end
21
26
  begin
22
27
  cli.run(['example.rb']).should == 0
23
28
  $stdout.string.should == "\n1 files inspected, 0 offences detected\n"
@@ -27,11 +32,14 @@ module Rubocop
27
32
  end
28
33
 
29
34
  it 'checks a given file with faults and returns 1' do
30
- File.open('example.rb', 'w') { |f| f.puts 'x = 0 ' }
35
+ File.open('example.rb', 'w') do |f|
36
+ f.puts '# encoding: utf-8'
37
+ f.puts 'x = 0 '
38
+ end
31
39
  begin
32
40
  cli.run(['example.rb']).should == 1
33
41
  $stdout.string.should == ['== example.rb ==',
34
- 'C: 0: Trailing whitespace detected.',
42
+ 'C: 2: Trailing whitespace detected.',
35
43
  '',
36
44
  '1 files inspected, 1 offences detected',
37
45
  ''].join("\n")
@@ -46,16 +54,23 @@ module Rubocop
46
54
  begin
47
55
  cli.run(['--emacs', 'example1.rb', 'example2.rb']).should == 1
48
56
  $stdout.string.should ==
49
- ['example1.rb:1: C: Trailing whitespace detected.',
57
+ ['example1.rb:1: C: Missing encoding comment.',
58
+ 'example1.rb:1: C: Trailing whitespace detected.',
59
+ 'example2.rb:1: C: Missing encoding comment.',
50
60
  'example2.rb:1: C: Tab detected.',
51
61
  '',
52
- '2 files inspected, 2 offences detected',
62
+ '2 files inspected, 4 offences detected',
53
63
  ''].join("\n")
54
64
  ensure
55
65
  File.delete 'example1.rb'
56
66
  File.delete 'example2.rb'
57
67
  end
58
68
  end
69
+
70
+ it 'finds no violations when checking the rubocop source code' do
71
+ cli.run
72
+ $stdout.string.should =~ /files inspected, 0 offences detected\n/
73
+ end
59
74
  end
60
75
  end
61
76
  end
@@ -0,0 +1,201 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ module Rubocop
6
+ module Cop
7
+ describe AlignParameters do
8
+ let (:align) { AlignParameters.new }
9
+
10
+ it 'registers an offence for parameters with single indent' do
11
+ inspect_source(align, 'file.rb', ['function(a,',
12
+ ' if b then c else d end)'])
13
+ align.offences.map(&:message).should ==
14
+ ['Align the parameters of a method call if they span more than ' +
15
+ 'one line.']
16
+ end
17
+
18
+ it 'registers an offence for parameters with double indent' do
19
+ inspect_source(align, 'file.rb', ['function(a,',
20
+ ' if b then c else d end)'])
21
+ align.offences.map(&:message).should ==
22
+ ['Align the parameters of a method call if they span more than ' +
23
+ 'one line.']
24
+ end
25
+
26
+ it 'accepts correctly aligned parameters' do
27
+ inspect_source(align, 'file.rb', ['function(a,',
28
+ ' 0, 1,',
29
+ ' (x + y),',
30
+ ' if b then c else d end)'])
31
+ align.offences.map(&:message).should == []
32
+ end
33
+
34
+ it 'accepts calls that only span one line' do
35
+ inspect_source(align, 'file.rb', ['find(path, s, @special[sexp[0]])'])
36
+ align.offences.map(&:message).should == []
37
+ end
38
+
39
+ it "doesn't get confused by a symbol argument" do
40
+ inspect_source(align, '',
41
+ ['add_offence(:convention, index,',
42
+ ' ERROR_MESSAGE % kind)'])
43
+ align.offences.map(&:message).should == []
44
+ end
45
+
46
+ it "doesn't get confused by splat operator" do
47
+ inspect_source(align, '',
48
+ ['func1(*a,',
49
+ ' *b,',
50
+ ' c)',
51
+ 'func2(a,',
52
+ ' *b,',
53
+ ' c)',
54
+ 'func3(*a)',
55
+ ])
56
+ align.offences.map(&:to_s).should ==
57
+ ['C: 5: Align the parameters of a method call if they span more ' +
58
+ 'than one line.']
59
+ end
60
+
61
+ it 'can handle a correctly aligned string literal as first argument' do
62
+ inspect_source(align, '',
63
+ ['add_offence("", x,',
64
+ ' a)'])
65
+ align.offences.map(&:message).should == []
66
+ end
67
+
68
+ it 'can handle a string literal as other argument' do
69
+ inspect_source(align, '',
70
+ ['add_offence(x,',
71
+ ' "", a)'])
72
+ align.offences.map(&:message).should == []
73
+ end
74
+
75
+ it "doesn't get confused by a line break inside a parameter" do
76
+ inspect_source(align, '',
77
+ ['read(path, { headers: true,',
78
+ ' converters: :numeric })'])
79
+ align.offences.map(&:message).should == []
80
+ end
81
+
82
+ it "doesn't get confused by symbols with embedded expressions" do
83
+ inspect_source(align, '',
84
+ ['send(:"#{name}_comments_path")'])
85
+ align.offences.map(&:message).should == []
86
+ end
87
+
88
+ it "doesn't get confused by regexen with embedded expressions" do
89
+ inspect_source(align, '',
90
+ ['a(/#{name}/)'])
91
+ align.offences.map(&:message).should == []
92
+ end
93
+
94
+ it "accepts braceless hashes" do
95
+ inspect_source(align, '',
96
+ ['run(collection, :entry_name => label,',
97
+ ' :paginator => paginator)'])
98
+ align.offences.map(&:message).should == []
99
+ end
100
+
101
+ it 'accepts the first parameter being on a new row' do
102
+ inspect_source(align, '',
103
+ [' match(',
104
+ ' a,',
105
+ ' b',
106
+ ' )'])
107
+ align.offences.map(&:message).should == []
108
+ end
109
+
110
+ it 'can handle heredoc strings' do
111
+ src = ['class_eval(<<-EOS, __FILE__, __LINE__ + 1)',
112
+ ' def run_#{name}_callbacks(*args)',
113
+ ' a = 1',
114
+ ' return value',
115
+ ' end',
116
+ ' EOS']
117
+ inspect_source(align, '', src)
118
+ align.offences.map(&:message).should == []
119
+ end
120
+
121
+ it 'can handle a method call within a method call' do
122
+ inspect_source(align, '',
123
+ ['a(a1,',
124
+ ' b(b1,',
125
+ ' b2),',
126
+ ' a2)'])
127
+ align.offences.map(&:message).should == []
128
+ end
129
+
130
+ it 'can handle a call embedded in a string' do
131
+ inspect_source(align, '',
132
+ ['model("#{index(name)}", child)'])
133
+ align.offences.map(&:message).should == []
134
+ end
135
+
136
+ it 'can handle do-end' do
137
+ inspect_source(align, '',
138
+ [' run(lambda do |e|',
139
+ " w = e['warden']",
140
+ ' end)'])
141
+ align.offences.map(&:message).should == []
142
+ end
143
+
144
+ it 'can handle a call with a block inside another call' do
145
+ src = ['new(table_name,',
146
+ ' exec_query("info(\'#{row[\'name\']}\')").map { |col|',
147
+ " col['name']",
148
+ ' })']
149
+ inspect_source(align, '', src)
150
+ align.offences.map(&:message).should == []
151
+ end
152
+
153
+ it 'can handle a ternary condition with a block reference' do
154
+ src = ['cond ? a : func(&b)']
155
+ inspect_source(align, '', src)
156
+ align.offences.map(&:message).should == []
157
+ end
158
+
159
+ it 'can handle parentheses used with no parameters' do
160
+ src = ['func()']
161
+ inspect_source(align, '', src)
162
+ align.offences.map(&:message).should == []
163
+ end
164
+
165
+ it 'can handle a multiline hash as first parameter' do
166
+ src = ['assert_equal({',
167
+ ' :space_before => "",',
168
+ '}, state)']
169
+ inspect_source(align, '', src)
170
+ align.offences.map(&:message).should == []
171
+ end
172
+
173
+ it 'can handle a multiline hash as second parameter' do
174
+ src = ['tag(:input, {',
175
+ ' :value => value',
176
+ '})']
177
+ inspect_source(align, '', src)
178
+ align.offences.map(&:message).should == []
179
+ end
180
+
181
+ it 'can handle method calls without parentheses' do
182
+ src = ['a(b c, d)']
183
+ inspect_source(align, '', src)
184
+ align.offences.map(&:message).should == []
185
+ end
186
+
187
+ it 'can handle other method calls without parentheses' do
188
+ src = ['chars(Unicode.apply_mapping @wrapped_string, :uppercase)']
189
+ inspect_source(align, '', src)
190
+ align.offences.map(&:message).should == []
191
+ end
192
+
193
+ it "doesn't check alignment if tabs are used to indent" do
194
+ src = ['a(b,',
195
+ "\tc)"]
196
+ inspect_source(align, '', src)
197
+ align.offences.map(&:message).should == []
198
+ end
199
+ end
200
+ end
201
+ end
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  module Rubocop
@@ -14,13 +16,13 @@ module Rubocop
14
16
  end
15
17
 
16
18
  it 'keeps track of offences' do
17
- cop.add_offence('file', 0, 'line', 'message')
19
+ cop.add_offence('file', 1, 'message')
18
20
 
19
21
  cop.offences.size.should == 1
20
22
  end
21
23
 
22
24
  it 'will report registered offences' do
23
- cop.add_offence('file', 0, 'line', 'message')
25
+ cop.add_offence('file', 1, 'message')
24
26
 
25
27
  cop.has_report?.should be_true
26
28
  end
@@ -0,0 +1,48 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ module Rubocop
6
+ module Cop
7
+ describe DefParentheses do
8
+ let (:def_par) { DefParentheses.new }
9
+
10
+ it 'reports an offence for def with parameters but no parens' do
11
+ src = ['def func a, b',
12
+ 'end']
13
+ inspect_source(def_par, '', src)
14
+ def_par.offences.map(&:message).should ==
15
+ ['Use def with parentheses when there are arguments.']
16
+ end
17
+
18
+ it 'reports an offence for def with empty parens' do
19
+ src = ['def func()',
20
+ 'end']
21
+ inspect_source(def_par, '', src)
22
+ def_par.offences.map(&:message).should ==
23
+ ["Omit the parentheses in defs when the method doesn't accept any " +
24
+ "arguments."]
25
+ end
26
+
27
+ it 'accepts def with arg and parens' do
28
+ src = ['def func(a)',
29
+ 'end']
30
+ inspect_source(def_par, '', src)
31
+ def_par.offences.map(&:message).should == []
32
+ end
33
+
34
+ it 'accepts def with no args and no parens' do
35
+ src = ['def func',
36
+ 'end']
37
+ inspect_source(def_par, '', src)
38
+ def_par.offences.map(&:message).should == []
39
+ end
40
+
41
+ it 'accepts empty parentheses in one liners' do
42
+ src = ["def to_s() join '/' end"]
43
+ inspect_source(def_par, '', src)
44
+ def_par.offences.map(&:message).should == []
45
+ end
46
+ end
47
+ end
48
+ end
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  module Rubocop
@@ -6,7 +8,7 @@ module Rubocop
6
8
  let (:empty_lines) { EmptyLines.new }
7
9
 
8
10
  it 'finds offences in inner classes' do
9
- empty_lines.inspect_source('', ['class K',
11
+ inspect_source(empty_lines, '', ['class K',
10
12
  ' def m',
11
13
  ' end',
12
14
  ' class J',
@@ -20,14 +22,13 @@ module Rubocop
20
22
  ' end',
21
23
  'end'])
22
24
  empty_lines.offences.size.should == 2
23
- empty_lines.offences.map(&:line).sort.should == [' def o',
24
- ' def p']
25
+ empty_lines.offences.map(&:line_number).sort.should == [7, 11]
25
26
  end
26
27
 
27
28
  # Only one def, so rule about empty line *between* defs does not
28
29
  # apply.
29
30
  it 'accepts a def that follows a line with code' do
30
- empty_lines.inspect_source('', ['x = 0',
31
+ inspect_source(empty_lines, '', ['x = 0',
31
32
  'def m',
32
33
  'end'])
33
34
  empty_lines.offences.size.should == 0
@@ -36,7 +37,7 @@ module Rubocop
36
37
  # Only one def, so rule about empty line *between* defs does not
37
38
  # apply.
38
39
  it 'accepts a def that follows code and a comment' do
39
- empty_lines.inspect_source('', [' x = 0',
40
+ inspect_source(empty_lines, '', [' x = 0',
40
41
  ' # 123',
41
42
  ' def m',
42
43
  ' end'])
@@ -44,7 +45,7 @@ module Rubocop
44
45
  end
45
46
 
46
47
  it 'accepts the first def without leading empty line in a class' do
47
- empty_lines.inspect_source('', ['class K',
48
+ inspect_source(empty_lines, '', ['class K',
48
49
  ' def m',
49
50
  ' end',
50
51
  'end'])
@@ -52,7 +53,7 @@ module Rubocop
52
53
  end
53
54
 
54
55
  it 'accepts a def that follows an empty line and then a comment' do
55
- empty_lines.inspect_source('', ['class A',
56
+ inspect_source(empty_lines, '', ['class A',
56
57
  ' # calculates value',
57
58
  ' def m',
58
59
  ' end',
@@ -74,7 +75,7 @@ module Rubocop
74
75
  ' end',
75
76
  'end',
76
77
  ]
77
- empty_lines.inspect_source('', source)
78
+ inspect_source(empty_lines, '', source)
78
79
  empty_lines.offences.map(&:message).should == []
79
80
  end
80
81
  end