reek 1.6.6 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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