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
@@ -75,10 +75,11 @@ describe Rubocop::Config do
75
75
  create_file(file_path, ['Encoding:',
76
76
  ' Enabled: false'])
77
77
  end
78
-
79
78
  it 'returns a configuration inheriting from default.yml' do
79
+ config = DEFAULT_CONFIG['Encoding'].dup
80
+ config['Enabled'] = false
80
81
  expect(configuration_from_file)
81
- .to eq(DEFAULT_CONFIG.merge('Encoding' => { 'Enabled' => false }))
82
+ .to eql(DEFAULT_CONFIG.merge('Encoding' => config))
82
83
  end
83
84
  end
84
85
 
@@ -175,16 +176,21 @@ describe Rubocop::Config do
175
176
  end
176
177
 
177
178
  it 'returns the ancestor configuration plus local overrides' do
178
- expect(configuration_from_file)
179
- .to eq(DEFAULT_CONFIG.merge('LineLength' => {
180
- 'Enabled' => true,
181
- 'Max' => 77
182
- },
183
- 'MethodLength' => {
184
- 'Enabled' => true,
185
- 'CountComments' => false,
186
- 'Max' => 5
187
- }))
179
+ config = DEFAULT_CONFIG
180
+ .merge('LineLength' => {
181
+ 'Description' =>
182
+ DEFAULT_CONFIG['LineLength']['Description'],
183
+ 'Enabled' => true,
184
+ 'Max' => 77
185
+ },
186
+ 'MethodLength' => {
187
+ 'Description' =>
188
+ DEFAULT_CONFIG['MethodLength']['Description'],
189
+ 'Enabled' => true,
190
+ 'CountComments' => false,
191
+ 'Max' => 5
192
+ })
193
+ expect(configuration_from_file).to eq(config)
188
194
  end
189
195
  end
190
196
 
@@ -216,11 +222,11 @@ describe Rubocop::Config do
216
222
  end
217
223
 
218
224
  it 'returns values from the last one when possible' do
219
- expect(configuration_from_file['MethodLength'])
220
- .to eq('Enabled' => true, # overridden in .rubocop.yml
221
- 'CountComments' => true, # only defined in normal.yml
222
- 'Max' => 200 # special.yml takes precedence
223
- )
225
+ expected = { 'Enabled' => true, # overridden in .rubocop.yml
226
+ 'CountComments' => true, # only defined in normal.yml
227
+ 'Max' => 200 } # special.yml takes precedence
228
+ expect(configuration_from_file['MethodLength'].to_set)
229
+ .to be_superset(expected.to_set)
224
230
  end
225
231
  end
226
232
  end
@@ -54,16 +54,16 @@ module Rubocop
54
54
 
55
55
  context 'when passed :raise_error option' do
56
56
  it 're-raises the exception received while processing' do
57
- cop = double(Cop, offences: [])
58
- cop.stub(:on_def) { raise RuntimeError }
57
+ cop = double(Cop, offences: [])
58
+ cop.stub(:on_def) { raise RuntimeError }
59
59
 
60
- commissioner = Commissioner.new([cop], raise_error: true)
61
- source = ['def method', '1', 'end']
62
- processed_source = parse_source(source)
60
+ commissioner = Commissioner.new([cop], raise_error: true)
61
+ source = ['def method', '1', 'end']
62
+ processed_source = parse_source(source)
63
63
 
64
- expect do
65
- commissioner.investigate(processed_source)
66
- end.to raise_error(RuntimeError)
64
+ expect do
65
+ commissioner.investigate(processed_source)
66
+ end.to raise_error(RuntimeError)
67
67
  end
68
68
  end
69
69
  end
@@ -33,6 +33,86 @@ module Rubocop
33
33
  cop.add_offence(:convention, location, 'message')
34
34
  expect(cop.offences.first.cop_name).to eq('AvoidFor')
35
35
  end
36
+
37
+ describe 'description' do
38
+ let(:short_desc) { 'abc' }
39
+ let(:long_desc) { short_desc + "\n" + short_desc + 'def' }
40
+ before { Cop.config['Description'] = long_desc }
41
+ context '#full_description' do
42
+ it 'contains whole text' do
43
+ expect(Cop.full_description).to eq(long_desc)
44
+ expect(Cop.full_description.lines.to_a.size).to be > 1
45
+ end
46
+ end
47
+ context '#short_description' do
48
+ it 'contains first line' do
49
+ expect(Cop.short_description).to eq(short_desc)
50
+ expect(Cop.short_description.lines.to_a.size).to eq(1)
51
+ end
52
+ end
53
+ end
54
+
55
+ context 'with no submodule' do
56
+ subject(:cop) { Cop }
57
+ it('has right name') { expect(cop.cop_name).to eq('Cop') }
58
+ it('has right type') { expect(cop.cop_type).to eq(:cop) }
59
+ end
60
+
61
+ context 'with style cops' do
62
+ subject(:cop) { Style::AvoidFor }
63
+ it('has right name') { expect(cop.cop_name).to eq('AvoidFor') }
64
+ it('has right type') { expect(cop.cop_type).to eq(:style) }
65
+ end
66
+
67
+ context 'with lint cops' do
68
+ subject(:cop) { Lint::Loop }
69
+ it('has right name') { expect(cop.cop_name).to eq('Loop') }
70
+ it('has right type') { expect(cop.cop_type).to eq(:lint) }
71
+ end
72
+
73
+ context 'with rails cops' do
74
+ subject(:cop) { Rails::Validation }
75
+ it('has right name') { expect(cop.cop_name).to eq('Validation') }
76
+ it('has right type') { expect(cop.cop_type).to eq(:rails) }
77
+ end
78
+
79
+ describe 'CopStore' do
80
+ context '#types' do
81
+ subject { Rubocop::Cop::Cop.all.types }
82
+ it('has types') { expect(subject.length).not_to eq(0) }
83
+ it { should include :lint }
84
+ it do
85
+ pending 'Rails cops are usually removed after CLI start, ' +
86
+ 'so CLI spec impacts this one'
87
+ should include :rails
88
+ end
89
+ it { should include :style }
90
+ it 'contains every value only once' do
91
+ expect(subject.length).to eq(subject.uniq.length)
92
+ end
93
+ end
94
+ context '#with_type' do
95
+ let(:types) { Rubocop::Cop::Cop.all.types }
96
+ it 'has at least one cop per type' do
97
+ types.each do |c|
98
+ expect(Rubocop::Cop::Cop.all.with_type(c).length).to be > 0
99
+ end
100
+ end
101
+
102
+ it 'has each cop in exactly one type' do
103
+ sum = 0
104
+ types.each do |c|
105
+ sum = sum + Rubocop::Cop::Cop.all.with_type(c).length
106
+ end
107
+ expect(sum).to be Rubocop::Cop::Cop.all.length
108
+ end
109
+
110
+ it 'returns 0 for an invalid type' do
111
+ expect(Rubocop::Cop::Cop.all.with_type('x').length).to be 0
112
+ end
113
+ end
114
+ end
115
+
36
116
  end
37
117
  end
38
118
  end
@@ -0,0 +1,63 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ module Rubocop
6
+ module Cop
7
+ module Lint
8
+ describe ParenthesesAsGroupedExpression do
9
+ let(:cop) { ParenthesesAsGroupedExpression.new }
10
+
11
+ it 'registers an offence for method call with space before the ' +
12
+ 'parenthesis' do
13
+ inspect_source(cop, ['a.func (x)'])
14
+ expect(cop.offences).to have(1).item
15
+ end
16
+
17
+ it 'registers an offence for predicate method call with space ' +
18
+ 'before the parenthesis' do
19
+ inspect_source(cop, ['is? (x)'])
20
+ expect(cop.offences).to have(1).item
21
+ end
22
+
23
+ it 'registers an offence for math expression' do
24
+ inspect_source(cop, ['puts (2 + 3) * 4'])
25
+ expect(cop.offences).to have(1).item
26
+ end
27
+
28
+ it 'accepts a method call without arguments' do
29
+ inspect_source(cop, ['func'])
30
+ expect(cop.offences).to be_empty
31
+ end
32
+
33
+ it 'accepts a method call with arguments but no parentheses' do
34
+ inspect_source(cop, ['puts x'])
35
+ expect(cop.offences).to be_empty
36
+ end
37
+
38
+ it 'accepts a chain of method calls' do
39
+ inspect_source(cop, ['a.b',
40
+ 'a.b 1',
41
+ 'a.b(1)'])
42
+ expect(cop.offences).to be_empty
43
+ end
44
+
45
+ it 'accepts method with parens as arg to method without' do
46
+ inspect_source(cop, ['a b(c)'])
47
+ expect(cop.offences).to be_empty
48
+ end
49
+
50
+ it 'accepts an operator call with argument in parentheses' do
51
+ inspect_source(cop, ['a % (b + c)',
52
+ 'a.b = (c == d)'])
53
+ expect(cop.offences).to be_empty
54
+ end
55
+
56
+ it 'accepts a space inside opening paren followed by left paren' do
57
+ inspect_source(cop, ['a( (b) )'])
58
+ expect(cop.offences).to be_empty
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -48,6 +48,65 @@ module Rubocop
48
48
  expect(cop.offences.size).to eq(1)
49
49
  end
50
50
 
51
+ it 'accepts def ending with ivar assignment' do
52
+ inspect_source(cop,
53
+ ['def test',
54
+ ' something',
55
+ ' @top = 5',
56
+ 'end'
57
+ ])
58
+ expect(cop.offences).to be_empty
59
+ end
60
+
61
+ it 'accepts def ending ivar attr assignment' do
62
+ inspect_source(cop,
63
+ ['def test',
64
+ ' something',
65
+ ' @top.attr = 5',
66
+ 'end'
67
+ ])
68
+ expect(cop.offences).to be_empty
69
+ end
70
+
71
+ it 'accepts def ending with argument attr assignment' do
72
+ inspect_source(cop,
73
+ ['def test(some_arg)',
74
+ ' unrelated_local_variable = Top.new',
75
+ ' some_arg.attr = 5',
76
+ 'end'
77
+ ])
78
+ expect(cop.offences).to be_empty
79
+ end
80
+
81
+ context 'when a lvar has an object passed as argument ' +
82
+ 'at the end of the method' do
83
+ it 'accepts the lvar attr assignment' do
84
+ inspect_source(cop,
85
+ ['def test(some_arg)',
86
+ ' @some_ivar = some_arg',
87
+ ' @some_ivar.do_something',
88
+ ' some_lvar = @some_ivar',
89
+ ' some_lvar.do_something',
90
+ ' some_lvar.attr = 5',
91
+ 'end'
92
+ ])
93
+ expect(cop.offences).to be_empty
94
+ end
95
+ end
96
+
97
+ context 'when a lvar declared as an argument ' +
98
+ 'is no longer the passed object at the end of the method' do
99
+ it 'registers an offence for the lvar attr assignment' do
100
+ inspect_source(cop,
101
+ ['def test(some_arg)',
102
+ ' some_arg = Top.new',
103
+ ' some_arg.attr = 5',
104
+ 'end'
105
+ ])
106
+ expect(cop.offences.size).to eq(1)
107
+ end
108
+ end
109
+
51
110
  it 'is not confused by operators ending with =' do
52
111
  inspect_source(cop,
53
112
  ['def test',
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ module Rubocop
6
+ module Cop
7
+ module Rails
8
+ describe HasAndBelongsToMany do
9
+ let(:cop) { described_class.new }
10
+
11
+ it 'registers an offence for has_and_belongs_to_many' do
12
+ inspect_source(cop,
13
+ ['has_and_belongs_to_many :groups'])
14
+ expect(cop.offences.size).to eq(1)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ module Rubocop
6
+ module Cop
7
+ module Rails
8
+ describe ReadAttribute do
9
+ let(:cop) { described_class.new }
10
+
11
+ it 'registers an offence for read_attribute' do
12
+ inspect_source(cop,
13
+ ['res = read_attribute(:test)'])
14
+ expect(cop.offences.size).to eq(1)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -6,20 +6,20 @@ module Rubocop
6
6
  module Cop
7
7
  module Rails
8
8
  describe Validation do
9
- let(:val) { Validation.new }
9
+ let(:cop) { described_class.new }
10
10
 
11
11
  Validation::BLACKLIST.each do |validation|
12
12
  it "registers an offence for #{validation}" do
13
- inspect_source(val,
13
+ inspect_source(cop,
14
14
  ["#{validation} :name"])
15
- expect(val.offences.size).to eq(1)
15
+ expect(cop.offences.size).to eq(1)
16
16
  end
17
17
  end
18
18
 
19
19
  it 'accepts sexy validations' do
20
- inspect_source(val,
20
+ inspect_source(cop,
21
21
  ['validates :name'])
22
- expect(val.offences).to be_empty
22
+ expect(cop.offences).to be_empty
23
23
  end
24
24
  end
25
25
  end
@@ -47,6 +47,34 @@ module Rubocop
47
47
  .to eq([format(AccessControl::INDENT_MSG, 'private')])
48
48
  end
49
49
 
50
+ it 'registers an offence for misaligned private in class ' +
51
+ 'defined with Class.new' do
52
+ inspect_source(a,
53
+ ['Test = Class.new do',
54
+ '',
55
+ 'private',
56
+ '',
57
+ ' def test; end',
58
+ 'end'])
59
+ expect(a.offences.size).to eq(1)
60
+ expect(a.offences.map(&:message))
61
+ .to eq([format(AccessControl::INDENT_MSG, 'private')])
62
+ end
63
+
64
+ it 'registers an offence for misaligned private in module ' +
65
+ 'defined with Module.new' do
66
+ inspect_source(a,
67
+ ['Test = Module.new do',
68
+ '',
69
+ 'private',
70
+ '',
71
+ ' def test; end',
72
+ 'end'])
73
+ expect(a.offences.size).to eq(1)
74
+ expect(a.offences.map(&:message))
75
+ .to eq([format(AccessControl::INDENT_MSG, 'private')])
76
+ end
77
+
50
78
  it 'registers an offence for misaligned protected' do
51
79
  inspect_source(a,
52
80
  ['class Test',
@@ -6,7 +6,7 @@ module Rubocop
6
6
  module Cop
7
7
  module Style
8
8
  describe Attr do
9
- let(:cop) { Attr.new }
9
+ let(:cop) { described_class.new }
10
10
 
11
11
  it 'registers an offence attr' do
12
12
  inspect_source(cop, ['class SomeClass',
@@ -14,6 +14,11 @@ module Rubocop
14
14
  'end'])
15
15
  expect(cop.offences.size).to eq(1)
16
16
  end
17
+
18
+ it 'auto-corrects attr to attr_reader' do
19
+ new_source = autocorrect_source(cop, 'attr')
20
+ expect(new_source).to eq('attr_reader')
21
+ end
17
22
  end
18
23
  end
19
24
  end
@@ -43,6 +43,11 @@ module Rubocop
43
43
  inspect_source(cop, ["[1, 2, 3].#{method}"])
44
44
  expect(cop.offences).to be_empty
45
45
  end
46
+
47
+ it 'auto-corrects to preferred method' do
48
+ new_source = autocorrect_source(cop, 'some.collect(&:test)')
49
+ expect(new_source).to eq('some.map(&:test)')
50
+ end
46
51
  end
47
52
  end
48
53
  end
@@ -44,6 +44,15 @@ module Rubocop
44
44
  expect(const.offences).to be_empty
45
45
  end
46
46
 
47
+ it 'does not check names if rhs is a method call with block' do
48
+ inspect_source(const,
49
+ ['AnythingGoes = test do',
50
+ ' do_something',
51
+ 'end'
52
+ ])
53
+ expect(const.offences).to be_empty
54
+ end
55
+
47
56
  it 'checks qualified const names' do
48
57
  inspect_source(const,
49
58
  ['::AnythingGoes = 30',