reek 1.6.6 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +6 -9
  3. data/features/command_line_interface/options.feature +20 -16
  4. data/features/command_line_interface/stdin.feature +1 -1
  5. data/features/rake_task/rake_task.feature +0 -12
  6. data/features/reports/reports.feature +63 -23
  7. data/features/reports/yaml.feature +3 -3
  8. data/features/samples.feature +3 -3
  9. data/lib/reek/cli/application.rb +5 -5
  10. data/lib/reek/cli/input.rb +1 -1
  11. data/lib/reek/cli/option_interpreter.rb +77 -0
  12. data/lib/reek/cli/options.rb +89 -82
  13. data/lib/reek/cli/report/formatter.rb +33 -24
  14. data/lib/reek/cli/report/heading_formatter.rb +45 -0
  15. data/lib/reek/cli/report/location_formatter.rb +23 -0
  16. data/lib/reek/cli/report/report.rb +32 -17
  17. data/lib/reek/configuration/app_configuration.rb +2 -2
  18. data/lib/reek/configuration/configuration_file_finder.rb +10 -10
  19. data/lib/reek/core/smell_repository.rb +3 -28
  20. data/lib/reek/rake/task.rb +35 -76
  21. data/lib/reek/smell_warning.rb +31 -16
  22. data/lib/reek/smells/nested_iterators.rb +1 -1
  23. data/lib/reek/smells/smell_detector.rb +9 -0
  24. data/lib/reek/smells/utility_function.rb +2 -1
  25. data/lib/reek/spec/should_reek.rb +0 -3
  26. data/lib/reek/spec/should_reek_of.rb +61 -12
  27. data/lib/reek/spec/should_reek_only_of.rb +12 -10
  28. data/lib/reek/version.rb +1 -1
  29. data/reek.gemspec +2 -2
  30. data/spec/factories/factories.rb +2 -5
  31. data/spec/reek/cli/html_report_spec.rb +28 -0
  32. data/spec/reek/cli/option_interperter_spec.rb +14 -0
  33. data/spec/reek/cli/text_report_spec.rb +95 -0
  34. data/spec/reek/cli/yaml_report_spec.rb +23 -0
  35. data/spec/reek/configuration/configuration_file_finder_spec.rb +5 -6
  36. data/spec/reek/core/module_context_spec.rb +1 -1
  37. data/spec/reek/core/smell_repository_spec.rb +17 -0
  38. data/spec/reek/smell_warning_spec.rb +9 -11
  39. data/spec/reek/smells/boolean_parameter_spec.rb +11 -11
  40. data/spec/reek/smells/control_parameter_spec.rb +40 -40
  41. data/spec/reek/smells/data_clump_spec.rb +17 -17
  42. data/spec/reek/smells/duplicate_method_call_spec.rb +56 -33
  43. data/spec/reek/smells/feature_envy_spec.rb +44 -40
  44. data/spec/reek/smells/irresponsible_module_spec.rb +1 -1
  45. data/spec/reek/smells/long_parameter_list_spec.rb +12 -12
  46. data/spec/reek/smells/long_yield_list_spec.rb +4 -4
  47. data/spec/reek/smells/module_initialize_spec.rb +3 -3
  48. data/spec/reek/smells/nested_iterators_spec.rb +71 -52
  49. data/spec/reek/smells/nil_check_spec.rb +6 -6
  50. data/spec/reek/smells/prima_donna_method_spec.rb +2 -2
  51. data/spec/reek/smells/too_many_statements_spec.rb +34 -34
  52. data/spec/reek/smells/uncommunicative_method_name_spec.rb +1 -1
  53. data/spec/reek/smells/uncommunicative_module_name_spec.rb +7 -3
  54. data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +12 -12
  55. data/spec/reek/smells/uncommunicative_variable_name_spec.rb +28 -38
  56. data/spec/reek/smells/unused_parameters_spec.rb +16 -17
  57. data/spec/reek/smells/utility_function_spec.rb +21 -8
  58. data/spec/reek/spec/should_reek_of_spec.rb +18 -5
  59. data/spec/reek/spec/should_reek_only_of_spec.rb +7 -1
  60. data/spec/spec_helper.rb +22 -14
  61. metadata +15 -20
  62. data/lib/reek/cli/help_command.rb +0 -15
  63. data/lib/reek/cli/report/strategy.rb +0 -64
  64. data/lib/reek/cli/version_command.rb +0 -16
  65. data/spec/matchers/smell_of_matcher.rb +0 -95
  66. data/spec/reek/cli/help_command_spec.rb +0 -25
  67. data/spec/reek/cli/report_spec.rb +0 -132
  68. data/spec/reek/cli/version_command_spec.rb +0 -31
@@ -14,7 +14,7 @@ shared_examples_for 'a data clump detector' do
14
14
  def third(pa) pa - pb + @fred; end
15
15
  end
16
16
  EOS
17
- expect(src).not_to smell_of(DataClump)
17
+ expect(src).not_to reek_of(DataClump)
18
18
  end
19
19
 
20
20
  context 'with 3 identical pairs' do
@@ -62,9 +62,9 @@ EOS
62
62
  def tri(pa, pb) pa - pb + @fred; end
63
63
  end
64
64
  EOS
65
- expect(src).to smell_of(DataClump,
66
- count: 3,
67
- parameters: ['pa', 'pb'])
65
+ expect(src).to reek_of(DataClump,
66
+ count: 3,
67
+ parameters: ['pa', 'pb'])
68
68
  end
69
69
 
70
70
  it 'reports 3 identical parameter sets' do
@@ -75,9 +75,9 @@ EOS
75
75
  def third(pa, pb, pc) pa - pb + @fred; end
76
76
  end
77
77
  EOS
78
- expect(src).to smell_of(DataClump,
79
- count: 3,
80
- parameters: ['pa', 'pb', 'pc'])
78
+ expect(src).to reek_of(DataClump,
79
+ count: 3,
80
+ parameters: ['pa', 'pb', 'pc'])
81
81
  end
82
82
 
83
83
  it 'reports re-ordered identical parameter sets' do
@@ -88,9 +88,9 @@ EOS
88
88
  def third(pa, pb, pc) pa - pb + @fred; end
89
89
  end
90
90
  EOS
91
- expect(src).to smell_of(DataClump,
92
- count: 3,
93
- parameters: ['pa', 'pb', 'pc'])
91
+ expect(src).to reek_of(DataClump,
92
+ count: 3,
93
+ parameters: ['pa', 'pb', 'pc'])
94
94
  end
95
95
 
96
96
  it 'counts only identical parameter sets' do
@@ -101,7 +101,7 @@ EOS
101
101
  def fc(name, windowW, windowH) end
102
102
  end
103
103
  EOS
104
- expect(src).not_to smell_of(DataClump)
104
+ expect(src).not_to reek_of(DataClump)
105
105
  end
106
106
 
107
107
  it 'gets a real example right' do
@@ -114,7 +114,7 @@ EOS
114
114
  def c_raw_singleton (src, options) end
115
115
  end
116
116
  EOS
117
- expect(src).to smell_of(DataClump, count: 5)
117
+ expect(src).to reek_of(DataClump, count: 5)
118
118
  end
119
119
 
120
120
  it 'correctly checks number of occurences' do
@@ -127,7 +127,7 @@ EOS
127
127
  def fe(p5, p1, p2) end
128
128
  end
129
129
  EOS
130
- expect(src).not_to smell_of(DataClump)
130
+ expect(src).not_to reek_of(DataClump)
131
131
  end
132
132
 
133
133
  it 'detects clumps smaller than the total number of arguments' do
@@ -138,8 +138,8 @@ EOS
138
138
  def fc(p4, p1, p2) end
139
139
  end
140
140
  EOS
141
- expect(src).to smell_of(DataClump,
142
- parameters: %w(p1 p2))
141
+ expect(src).to reek_of(DataClump,
142
+ parameters: %w(p1 p2))
143
143
  end
144
144
 
145
145
  it 'ignores anonymous parameters' do
@@ -150,8 +150,8 @@ EOS
150
150
  def fc(p1, p2, *) end
151
151
  end
152
152
  EOS
153
- expect(src).to smell_of(DataClump,
154
- parameters: %w(p1 p2))
153
+ expect(src).to reek_of(DataClump,
154
+ parameters: %w(p1 p2))
155
155
  end
156
156
  end
157
157
 
@@ -12,13 +12,13 @@ describe DuplicateMethodCall do
12
12
  before :each do
13
13
  @source_name = 'copy-cat'
14
14
  @detector = DuplicateMethodCall.new(@source_name)
15
- src = <<EOS
16
- def double_thing(other)
17
- other[@thing]
18
- not_the_sam(at = all)
19
- other[@thing]
20
- end
21
- EOS
15
+ src = <<-EOS
16
+ def double_thing(other)
17
+ other[@thing]
18
+ not_the_sam(at = all)
19
+ other[@thing]
20
+ end
21
+ EOS
22
22
  ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
23
23
  smells = @detector.examine_context(ctx)
24
24
  expect(smells.length).to eq(1)
@@ -39,24 +39,28 @@ EOS
39
39
  context 'with repeated method calls' do
40
40
  it 'reports repeated call' do
41
41
  src = 'def double_thing() @other.thing + @other.thing end'
42
- expect(src).to smell_of(DuplicateMethodCall, name: '@other.thing')
42
+ expect(src).to reek_of(DuplicateMethodCall, name: '@other.thing')
43
43
  end
44
+
44
45
  it 'reports repeated call to lvar' do
45
46
  src = 'def double_thing(other) other[@thing] + other[@thing] end'
46
- expect(src).to smell_of(DuplicateMethodCall, name: 'other[@thing]')
47
+ expect(src).to reek_of(DuplicateMethodCall, name: 'other[@thing]')
47
48
  end
49
+
48
50
  it 'reports call parameters' do
49
51
  src = 'def double_thing() @other.thing(2,3) + @other.thing(2,3) end'
50
- expect(src).to smell_of(DuplicateMethodCall, name: '@other.thing(2, 3)')
52
+ expect(src).to reek_of(DuplicateMethodCall, name: '@other.thing(2, 3)')
51
53
  end
54
+
52
55
  it 'should report nested calls' do
53
56
  src = 'def double_thing() @other.thing.foo + @other.thing.foo end'
54
- expect(src).to smell_of(DuplicateMethodCall, { name: '@other.thing' },
55
- { name: '@other.thing.foo' })
57
+ expect(src).to reek_of(DuplicateMethodCall, name: '@other.thing')
58
+ expect(src).to reek_of(DuplicateMethodCall, name: '@other.thing.foo')
56
59
  end
60
+
57
61
  it 'should ignore calls to new' do
58
62
  src = 'def double_thing() @other.new + @other.new end'
59
- expect(src).not_to smell_of(DuplicateMethodCall)
63
+ expect(src).not_to reek_of(DuplicateMethodCall)
60
64
  end
61
65
  end
62
66
 
@@ -72,7 +76,7 @@ EOS
72
76
  end
73
77
  end
74
78
  EOS
75
- expect(src).not_to smell_of(DuplicateMethodCall)
79
+ expect(src).not_to reek_of(DuplicateMethodCall)
76
80
  end
77
81
  end
78
82
 
@@ -84,7 +88,7 @@ EOS
84
88
  bar { baz }
85
89
  end
86
90
  EOS
87
- expect(src).to smell_of(DuplicateMethodCall)
91
+ expect(src).to reek_of(DuplicateMethodCall)
88
92
  end
89
93
 
90
94
  it 'reports no smell if the blocks are different' do
@@ -94,7 +98,7 @@ EOS
94
98
  bar { qux }
95
99
  end
96
100
  EOS
97
- expect(src).not_to smell_of(DuplicateMethodCall)
101
+ expect(src).not_to reek_of(DuplicateMethodCall)
98
102
  end
99
103
  end
100
104
 
@@ -106,7 +110,7 @@ EOS
106
110
  bar.qux { baz }
107
111
  end
108
112
  EOS
109
- expect(src).to smell_of(DuplicateMethodCall)
113
+ expect(src).to reek_of(DuplicateMethodCall)
110
114
  end
111
115
 
112
116
  it 'reports a smell if the blocks are different' do
@@ -116,14 +120,14 @@ EOS
116
120
  bar.qux { qux }
117
121
  end
118
122
  EOS
119
- expect(src).to smell_of(DuplicateMethodCall)
123
+ expect(src).to reek_of(DuplicateMethodCall)
120
124
  end
121
125
  end
122
126
 
123
127
  context 'with repeated attribute assignment' do
124
128
  it 'reports repeated assignment' do
125
129
  src = 'def double_thing(thing) @other[thing] = true; @other[thing] = true; end'
126
- expect(src).to smell_of(DuplicateMethodCall, name: '@other[thing] = true')
130
+ expect(src).to reek_of(DuplicateMethodCall, name: '@other[thing] = true')
127
131
  end
128
132
  it 'does not report multi-assignments' do
129
133
  src = <<EOS
@@ -132,61 +136,80 @@ def _parse ctxt
132
136
  error, ctxt.index = @err, @err_ind
133
137
  end
134
138
  EOS
135
- expect(src).not_to smell_of(DuplicateMethodCall)
139
+ expect(src).not_to reek_of(DuplicateMethodCall)
136
140
  end
137
141
  end
138
142
 
139
143
  context 'non-repeated method calls' do
140
144
  it 'should not report similar calls' do
141
145
  src = 'def equals(other) other.thing == self.thing end'
142
- expect(src).not_to smell_of(DuplicateMethodCall)
146
+ expect(src).not_to reek_of(DuplicateMethodCall)
143
147
  end
144
148
  it 'should respect call parameters' do
145
149
  src = 'def double_thing() @other.thing(3) + @other.thing(2) end'
146
- expect(src).not_to smell_of(DuplicateMethodCall)
150
+ expect(src).not_to reek_of(DuplicateMethodCall)
147
151
  end
148
152
  end
149
153
 
150
154
  context 'allowing up to 3 calls' do
151
155
  before :each do
152
- @config = { DuplicateMethodCall::MAX_ALLOWED_CALLS_KEY => 3 }
156
+ @config = { DuplicateMethodCall: { DuplicateMethodCall::MAX_ALLOWED_CALLS_KEY => 3 } }
153
157
  end
158
+
154
159
  it 'does not report double calls' do
155
160
  src = 'def double_thing() @other.thing + @other.thing end'
156
- expect(src).not_to smell_of(DuplicateMethodCall).with_config(@config)
161
+ with_test_config(@config) do
162
+ expect(src).not_to reek_of(DuplicateMethodCall)
163
+ end
157
164
  end
165
+
158
166
  it 'does not report triple calls' do
159
167
  src = 'def double_thing() @other.thing + @other.thing + @other.thing end'
160
- expect(src).not_to smell_of(DuplicateMethodCall).with_config(@config)
168
+ with_test_config(@config) do
169
+ expect(src).not_to reek_of(DuplicateMethodCall)
170
+ end
161
171
  end
172
+
162
173
  it 'reports quadruple calls' do
163
174
  src = '
164
175
  def double_thing()
165
176
  @other.thing + @other.thing + @other.thing + @other.thing
166
177
  end
167
178
  '
168
- expect(src).to smell_of(DuplicateMethodCall, name: '@other.thing', count: 4).
169
- with_config(@config)
179
+ with_test_config(@config) do
180
+ expect(src).to reek_of(DuplicateMethodCall, name: '@other.thing', count: 4)
181
+ end
170
182
  end
171
183
  end
172
184
 
173
185
  context 'allowing calls to some methods' do
174
186
  before :each do
175
- @config = { DuplicateMethodCall::ALLOW_CALLS_KEY => ['@some.thing', /puts/] }
187
+ @config = { DuplicateMethodCall:
188
+ { DuplicateMethodCall::ALLOW_CALLS_KEY => ['@some.thing', /puts/] } }
176
189
  end
190
+
177
191
  it 'does not report calls to some methods' do
178
192
  src = 'def double_some_thing() @some.thing + @some.thing end'
179
- expect(src).not_to smell_of(DuplicateMethodCall).with_config(@config)
193
+
194
+ with_test_config(@config) do
195
+ expect(src).not_to reek_of(DuplicateMethodCall)
196
+ end
180
197
  end
198
+
181
199
  it 'reports calls to other methods' do
182
200
  src = 'def double_other_thing() @other.thing + @other.thing end'
183
- expect(src).to smell_of(DuplicateMethodCall, name: '@other.thing').
184
- with_config(@config)
201
+
202
+ with_test_config(@config) do
203
+ expect(src).to reek_of(DuplicateMethodCall, name: '@other.thing')
204
+ end
185
205
  end
206
+
186
207
  it 'does not report calls to methods specifed with a regular expression' do
187
208
  src = 'def double_puts() puts @other.thing; puts @other.thing end'
188
- expect(src).to smell_of(DuplicateMethodCall, name: '@other.thing').
189
- with_config(@config)
209
+
210
+ with_test_config(@config) do
211
+ expect(src).to reek_of(DuplicateMethodCall, name: '@other.thing')
212
+ end
190
213
  end
191
214
  end
192
215
  end
@@ -10,60 +10,64 @@ describe FeatureEnvy do
10
10
  it 'should not report use of self' do
11
11
  expect('def simple() self.to_s + self.to_i end').not_to reek_of(:FeatureEnvy)
12
12
  end
13
+
13
14
  it 'should not report vcall with no argument' do
14
15
  expect('def simple() func; end').not_to reek_of(:FeatureEnvy)
15
16
  end
17
+
16
18
  it 'should not report single use' do
17
19
  expect('def no_envy(arga) arga.barg(@item) end').not_to reek_of(:FeatureEnvy)
18
20
  end
21
+
19
22
  it 'should not report return value' do
20
23
  expect('def no_envy(arga) arga.barg(@item); arga end').not_to reek_of(:FeatureEnvy)
21
24
  end
25
+
22
26
  it 'should ignore global variables' do
23
27
  expect('def no_envy() $s2.to_a; $s2[@item] end').not_to reek_of(:FeatureEnvy)
24
28
  end
29
+
25
30
  it 'should not report class methods' do
26
31
  expect('def simple() self.class.new.flatten_merge(self) end').
27
32
  not_to reek_of(:FeatureEnvy)
28
33
  end
34
+
29
35
  it 'should not report single use of an ivar' do
30
36
  expect('def no_envy() @item.to_a end').not_to reek_of(:FeatureEnvy)
31
37
  end
38
+
32
39
  it 'should not report returning an ivar' do
33
40
  expect('def no_envy() @item.to_a; @item end').not_to reek_of(:FeatureEnvy)
34
41
  end
42
+
35
43
  it 'should not report ivar usage in a parameter' do
36
44
  expect('def no_envy() @item.price + tax(@item) - savings(@item) end').
37
45
  not_to reek_of(:FeatureEnvy)
38
46
  end
47
+
39
48
  it 'should not report single use of an lvar' do
40
49
  expect('def no_envy() lv = @item; lv.to_a end').not_to reek_of(:FeatureEnvy)
41
50
  end
51
+
42
52
  it 'should not report returning an lvar' do
43
53
  expect('def no_envy() lv = @item; lv.to_a; lv end').not_to reek_of(:FeatureEnvy)
44
54
  end
55
+
45
56
  it 'ignores lvar usage in a parameter' do
46
57
  expect('def no_envy() lv = @item; lv.price + tax(lv) - savings(lv); end').
47
58
  not_to reek_of(:FeatureEnvy)
48
59
  end
60
+
49
61
  it 'ignores multiple ivars' do
50
- src = <<EOS
51
- def func
52
- @other.a
53
- @other.b
54
- @nother.c
55
- @nother.d
56
- end
57
- EOS
62
+ src = <<-EOS
63
+ def func
64
+ @other.a
65
+ @other.b
66
+ @nother.c
67
+ @nother.d
68
+ end
69
+ EOS
58
70
  expect(src).not_to reek_of(:FeatureEnvy)
59
- #
60
- # def other.func(me)
61
- # a
62
- # b
63
- # me.nother_c
64
- # me.nother_d
65
- # end
66
- #
67
71
  end
68
72
  end
69
73
 
@@ -73,34 +77,34 @@ EOS
73
77
  def envy(arga)
74
78
  arga.b(arga) + arga.c(@fred)
75
79
  end
76
- ').to reek_only_of(:FeatureEnvy, /arga/)
80
+ ').to reek_only_of(:FeatureEnvy)
77
81
  end
78
82
  end
79
83
 
80
84
  it 'should report highest affinity' do
81
- src = <<EOS
82
- def total_envy
83
- fred = @item
84
- total = 0
85
- total += fred.price
86
- total += fred.tax
87
- total *= 1.15
88
- end
89
- EOS
90
- expect(src).to reek_only_of(:FeatureEnvy, /total/)
85
+ src = <<-EOS
86
+ def total_envy
87
+ fred = @item
88
+ total = 0
89
+ total += fred.price
90
+ total += fred.tax
91
+ total *= 1.15
92
+ end
93
+ EOS
94
+ expect(src).to reek_only_of(:FeatureEnvy)
91
95
  end
92
96
 
93
97
  it 'should report multiple affinities' do
94
- src = <<EOS
95
- def total_envy
96
- fred = @item
97
- total = 0
98
- total += fred.price
99
- total += fred.tax
100
- end
101
- EOS
102
- expect(src).to reek_of(:FeatureEnvy, /total/)
103
- expect(src).to reek_of(:FeatureEnvy, /fred/)
98
+ src = <<-EOS
99
+ def total_envy
100
+ fred = @item
101
+ total = 0
102
+ total += fred.price
103
+ total += fred.tax
104
+ end
105
+ EOS
106
+ expect(src).to reek_of(:FeatureEnvy, name: 'total')
107
+ expect(src).to reek_of(:FeatureEnvy, name: 'fred')
104
108
  end
105
109
 
106
110
  it 'should not be fooled by duplication' do
@@ -109,7 +113,7 @@ EOS
109
113
  @cow.feed_to(thing.pig)
110
114
  @duck.feed_to(thing.pig)
111
115
  end
112
- ').to reek_only_of(:Duplication, /thing.pig/)
116
+ ').to reek_only_of(:Duplication)
113
117
  end
114
118
 
115
119
  it 'should count local calls' do
@@ -118,7 +122,7 @@ EOS
118
122
  cow.feed_to(thing.pig)
119
123
  duck.feed_to(thing.pig)
120
124
  end
121
- ').to reek_only_of(:Duplication, /thing.pig/)
125
+ ').to reek_only_of(:Duplication)
122
126
  end
123
127
 
124
128
  it 'should report many calls to lvar' do
@@ -127,7 +131,7 @@ EOS
127
131
  lv = @item
128
132
  lv.price + lv.tax
129
133
  end
130
- ').to reek_only_of(:FeatureEnvy, /lv/)
134
+ ').to reek_only_of(:FeatureEnvy)
131
135
  #
132
136
  # def moved_version
133
137
  # price + tax