reek 4.4.0 → 4.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -0
  3. data/CONTRIBUTING.md +41 -4
  4. data/README.md +15 -3
  5. data/defaults.reek +1 -1
  6. data/docs/Basic-Smell-Options.md +2 -2
  7. data/docs/Code-Smells.md +4 -0
  8. data/docs/How-To-Write-New-Detectors.md +116 -0
  9. data/docs/How-reek-works-internally.md +3 -4
  10. data/docs/Instance-Variable-Assumption.md +134 -0
  11. data/docs/Simulated-Polymorphism.md +1 -1
  12. data/docs/Smell-Suppression.md +6 -6
  13. data/docs/{style-guide.md → Style-Guide.md} +0 -0
  14. data/docs/Unused-Private-Method.md +1 -1
  15. data/docs/YAML-Reports.md +0 -18
  16. data/features/configuration_files/directory_specific_directives.feature +4 -4
  17. data/features/configuration_files/unused_private_method.feature +2 -2
  18. data/features/samples.feature +122 -117
  19. data/features/smells/subclassed_from_core_class.feature +1 -1
  20. data/lib/reek/code_comment.rb +13 -4
  21. data/lib/reek/context/code_context.rb +1 -0
  22. data/lib/reek/examiner.rb +24 -27
  23. data/lib/reek/smells/class_variable.rb +1 -1
  24. data/lib/reek/smells/control_parameter.rb +1 -1
  25. data/lib/reek/smells/data_clump.rb +1 -1
  26. data/lib/reek/smells/duplicate_method_call.rb +1 -1
  27. data/lib/reek/smells/feature_envy.rb +1 -1
  28. data/lib/reek/smells/instance_variable_assumption.rb +1 -1
  29. data/lib/reek/smells/prima_donna_method.rb +1 -1
  30. data/lib/reek/smells/repeated_conditional.rb +1 -1
  31. data/lib/reek/smells/smell_detector.rb +5 -14
  32. data/lib/reek/smells/smell_repository.rb +1 -5
  33. data/lib/reek/smells/smell_warning.rb +6 -8
  34. data/lib/reek/smells/subclassed_from_core_class.rb +1 -1
  35. data/lib/reek/smells/uncommunicative_variable_name.rb +22 -12
  36. data/lib/reek/smells/unused_private_method.rb +1 -1
  37. data/lib/reek/spec.rb +2 -2
  38. data/lib/reek/spec/should_reek_of.rb +12 -8
  39. data/lib/reek/version.rb +1 -1
  40. data/spec/reek/code_comment_spec.rb +13 -5
  41. data/spec/reek/examiner_spec.rb +2 -2
  42. data/spec/reek/smells/attribute_spec.rb +91 -78
  43. data/spec/reek/smells/boolean_parameter_spec.rb +72 -64
  44. data/spec/reek/smells/class_variable_spec.rb +81 -68
  45. data/spec/reek/smells/control_parameter_spec.rb +101 -141
  46. data/spec/reek/smells/data_clump_spec.rb +94 -149
  47. data/spec/reek/smells/duplicate_method_call_spec.rb +98 -85
  48. data/spec/reek/smells/feature_envy_spec.rb +164 -183
  49. data/spec/reek/smells/instance_variable_assumption_spec.rb +51 -147
  50. data/spec/reek/smells/irresponsible_module_spec.rb +153 -170
  51. data/spec/reek/smells/long_parameter_list_spec.rb +44 -88
  52. data/spec/reek/smells/long_yield_list_spec.rb +41 -41
  53. data/spec/reek/smells/manual_dispatch_spec.rb +36 -18
  54. data/spec/reek/smells/module_initialize_spec.rb +31 -33
  55. data/spec/reek/smells/nested_iterators_spec.rb +189 -183
  56. data/spec/reek/smells/nil_check_spec.rb +48 -37
  57. data/spec/reek/smells/prima_donna_method_spec.rb +41 -26
  58. data/spec/reek/smells/repeated_conditional_spec.rb +75 -87
  59. data/spec/reek/smells/smell_warning_spec.rb +7 -0
  60. data/spec/reek/smells/subclassed_from_core_class_spec.rb +37 -112
  61. data/spec/reek/smells/too_many_constants_spec.rb +109 -199
  62. data/spec/reek/smells/too_many_instance_variables_spec.rb +105 -128
  63. data/spec/reek/smells/too_many_methods_spec.rb +38 -62
  64. data/spec/reek/smells/too_many_statements_spec.rb +69 -45
  65. data/spec/reek/smells/uncommunicative_method_name_spec.rb +16 -29
  66. data/spec/reek/smells/uncommunicative_module_name_spec.rb +24 -37
  67. data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +55 -60
  68. data/spec/reek/smells/uncommunicative_variable_name_spec.rb +108 -95
  69. data/spec/reek/smells/unused_parameters_spec.rb +73 -49
  70. data/spec/reek/smells/unused_private_method_spec.rb +97 -50
  71. data/spec/reek/smells/utility_function_spec.rb +130 -188
  72. data/spec/reek/spec/should_reek_of_spec.rb +2 -2
  73. metadata +6 -7
  74. data/lib/reek/cli/warning_collector.rb +0 -27
  75. data/spec/reek/cli/warning_collector_spec.rb +0 -25
  76. data/spec/reek/smells/smell_detector_shared.rb +0 -29
@@ -1,52 +1,52 @@
1
1
  require_relative '../../spec_helper'
2
- require_lib 'reek/context/code_context'
3
2
  require_lib 'reek/smells/long_yield_list'
4
- require_relative 'smell_detector_shared'
5
3
 
6
4
  RSpec.describe Reek::Smells::LongYieldList do
7
- let(:detector) { build(:smell_detector, smell_type: :LongYieldList) }
8
-
9
- it_should_behave_like 'SmellDetector'
10
-
11
- context 'yield' do
12
- it 'should not report yield with no parameters' do
13
- src = 'def simple(arga, argb, &blk) f(3);yield; end'
14
- expect(src).not_to reek_of(:LongYieldList)
15
- end
16
-
17
- it 'should not report yield with few parameters' do
18
- src = 'def simple(arga, argb, &blk) f(3);yield a,b; end'
19
- expect(src).not_to reek_of(:LongYieldList)
20
- end
21
-
22
- it 'should report yield with many parameters' do
23
- src = 'def simple(arga, argb, &blk) f(3);yield arga,argb,arga,argb; end'
24
- expect(src).to reek_of(:LongYieldList, count: 4)
25
- end
26
-
27
- it 'should not report yield of a long expression' do
28
- src = 'def simple(arga, argb, &blk) f(3);yield(if @dec then argb else 5+3 end); end'
29
- expect(src).not_to reek_of(:LongYieldList)
30
- end
5
+ it 'reports the right values' do
6
+ src = <<-EOS
7
+ class Alfa
8
+ def bravo(charlie, delta, echo, foxtrot)
9
+ yield charlie, delta, echo, foxtrot
10
+ end
11
+ end
12
+ EOS
13
+
14
+ expect(src).to reek_of(:LongYieldList,
15
+ lines: [3],
16
+ context: 'Alfa#bravo',
17
+ message: 'yields 4 parameters',
18
+ source: 'string',
19
+ count: 4)
31
20
  end
32
21
 
33
- context 'when a smells is reported' do
34
- let(:warning) do
35
- src = <<-EOS
36
- def simple(arga, argb, &blk)
37
- f(3)
38
- yield(arga,argb,arga,argb)
22
+ it 'does count all occurences' do
23
+ src = <<-EOS
24
+ class Alfa
25
+ def bravo(charlie, delta, echo, foxtrot)
26
+ yield charlie, delta, echo, foxtrot
27
+ end
28
+
29
+ def golf(hotel, india, juliett, kilo)
30
+ yield hotel, india, juliett, kilo
39
31
  end
40
- EOS
41
- ctx = Reek::Context::CodeContext.new(nil, Reek::Source::SourceCode.from(src).syntax_tree)
42
- detector.sniff(ctx).first
43
- end
32
+ end
33
+ EOS
34
+
35
+ expect(src).to reek_of(:LongYieldList,
36
+ lines: [3],
37
+ context: 'Alfa#bravo')
38
+ expect(src).to reek_of(:LongYieldList,
39
+ lines: [7],
40
+ context: 'Alfa#golf')
41
+ end
44
42
 
45
- it_should_behave_like 'common fields set correctly'
43
+ it 'does not report yield with 3 parameters' do
44
+ src = <<-EOS
45
+ def alfa(bravo, charlie, delta)
46
+ yield bravo, charlie, delta
47
+ end
48
+ EOS
46
49
 
47
- it 'reports the correct values' do
48
- expect(warning.parameters[:count]).to eq(4)
49
- expect(warning.lines).to eq([3])
50
- end
50
+ expect(src).not_to reek_of(:LongYieldList)
51
51
  end
52
52
  end
@@ -1,31 +1,49 @@
1
1
  require_relative '../../spec_helper'
2
2
  require_lib 'reek/smells/too_many_constants'
3
- require_relative 'smell_detector_shared'
4
3
 
5
4
  RSpec.describe Reek::Smells::ManualDispatch do
6
- it 'reports manual dispatch smell when using #respond_to?' do
5
+ it 'reports the right values' do
7
6
  src = <<-EOS
8
- class Dummy
9
- def call
10
- fail if unrelated_guard_clause?
11
-
12
- if foo.respond_to?(:bar, true)
13
- hello
14
- foo.baz
15
- foo.bar
16
- end
7
+ class Alfa
8
+ def bravo(charlie)
9
+ true if charlie.respond_to?(:to_a)
17
10
  end
18
11
  end
19
12
  EOS
20
13
 
21
- expect(src).to reek_of(:ManualDispatch, message: 'manually dispatches method call', lines: [5])
14
+ expect(src).to reek_of(:ManualDispatch,
15
+ lines: [3],
16
+ context: 'Alfa#bravo',
17
+ message: 'manually dispatches method call',
18
+ source: 'string')
19
+ end
20
+
21
+ it 'does count all occurences' do
22
+ src = <<-EOS
23
+ class Alfa
24
+ def bravo(charlie)
25
+ true if charlie.respond_to?(:to_a)
26
+ end
27
+
28
+ def delta(echo)
29
+ true if echo.respond_to?(:to_a)
30
+ end
31
+ end
32
+ EOS
33
+
34
+ expect(src).to reek_of(:ManualDispatch,
35
+ lines: [3],
36
+ context: 'Alfa#bravo')
37
+ expect(src).to reek_of(:ManualDispatch,
38
+ lines: [7],
39
+ context: 'Alfa#delta')
22
40
  end
23
41
 
24
42
  it 'reports manual dispatch smell when using #respond_to? on implicit self' do
25
43
  src = <<-EOS
26
- class Dummy
27
- def call
28
- bar if respond_to?(:bar)
44
+ class Alfa
45
+ def bravo
46
+ charlie if respond_to?(:delta)
29
47
  end
30
48
  end
31
49
  EOS
@@ -35,9 +53,9 @@ RSpec.describe Reek::Smells::ManualDispatch do
35
53
 
36
54
  it 'reports manual dispatch within a conditional' do
37
55
  src = <<-EOS
38
- class Dummy
39
- def call
40
- foo.respond_to?(:bar) && foo.bar
56
+ class Alfa
57
+ def bravo
58
+ charlie.respond_to?(:delta) && charlie.echo
41
59
  end
42
60
  end
43
61
  EOS
@@ -1,44 +1,42 @@
1
1
  require_relative '../../spec_helper'
2
2
  require_lib 'reek/smells/module_initialize'
3
- require_relative 'smell_detector_shared'
4
3
 
5
4
  RSpec.describe Reek::Smells::ModuleInitialize do
6
- context 'module' do
7
- context 'with method named initialize' do
8
- it 'smells' do
9
- src = <<-EOF
10
- module A
11
- def initialize; end
12
- end
13
- EOF
14
- expect(src).to reek_of(:ModuleInitialize)
5
+ it 'reports the right values' do
6
+ src = <<-EOS
7
+ module Alfa
8
+ def initialize; end
15
9
  end
16
- end
10
+ EOS
17
11
 
18
- context 'with method named initialize in a nested class' do
19
- it 'does not smell' do
20
- src = <<-EOF
21
- module A
22
- class B
23
- def initialize; end
24
- end
25
- end
26
- EOF
27
- expect(src).not_to reek_of(:ModuleInitialize)
12
+ expect(src).to reek_of(:ModuleInitialize,
13
+ lines: [1],
14
+ context: 'Alfa',
15
+ message: 'has initialize method',
16
+ source: 'string')
17
+ end
18
+
19
+ it 'does not report with method named initialize in a nested class' do
20
+ src = <<-EOF
21
+ module Alfa
22
+ class Bravo
23
+ def initialize; end
24
+ end
28
25
  end
29
- end
26
+ EOF
30
27
 
31
- context 'with method named initialize in a nested struct' do
32
- it 'does not smell' do
33
- src = <<-EOF
34
- module A
35
- B = Struct.new(:c) do
36
- def initialize; end
37
- end
38
- end
39
- EOF
40
- expect(src).not_to reek_of(:ModuleInitialize)
28
+ expect(src).not_to reek_of(:ModuleInitialize)
29
+ end
30
+
31
+ it 'does not smell with method named initialize in a nested struct' do
32
+ src = <<-EOF
33
+ module Alfa
34
+ Bravo = Struct.new(:charlie) do
35
+ def initialize; end
36
+ end
41
37
  end
42
- end
38
+ EOF
39
+
40
+ expect(src).not_to reek_of(:ModuleInitialize)
43
41
  end
44
42
  end
@@ -1,96 +1,148 @@
1
1
  require_relative '../../spec_helper'
2
2
  require_lib 'reek/smells/nested_iterators'
3
- require_relative 'smell_detector_shared'
4
3
 
5
4
  RSpec.describe Reek::Smells::NestedIterators do
6
- context 'with no iterators' do
7
- it 'reports no smells' do
8
- src = 'def fred() nothing = true; end'
9
- expect(src).not_to reek_of(:NestedIterators)
10
- end
5
+ it 'reports the right values' do
6
+ src = <<-EOS
7
+ def alfa(bravo)
8
+ bravo.each do |charlie|
9
+ charlie.each { |delta| delta }
10
+ end
11
+ end
12
+ EOS
13
+
14
+ expect(src).to reek_of(:NestedIterators,
15
+ lines: [3],
16
+ context: 'alfa',
17
+ message: 'contains iterators nested 2 deep',
18
+ source: 'string',
19
+ depth: 2)
11
20
  end
12
21
 
13
- context 'with one iterator' do
14
- it 'reports no smells' do
15
- src = 'def fred() nothing.each {|item| item}; end'
16
- expect(src).not_to reek_of(:NestedIterators)
17
- end
22
+ it 'does count all occurences' do
23
+ src = <<-EOS
24
+ def alfa
25
+ bravo.each do |charlie|
26
+ charlie.each { |delta| delta }
27
+ end
28
+
29
+ echo.each do |foxtrot|
30
+ foxtrot.each do |golf|
31
+ golf.each { |hotel| hotel }
32
+ end
33
+ end
34
+ end
35
+ EOS
36
+
37
+ expect(src).to reek_of(:NestedIterators, lines: [3], depth: 2)
38
+ expect(src).to reek_of(:NestedIterators, lines: [8], depth: 3)
18
39
  end
19
40
 
20
- it 'should report nested iterators in a method' do
21
- src = 'def bad(fred) @fred.each {|item| item.each {|ting| ting.ting} } end'
22
- expect(src).to reek_of(:NestedIterators)
41
+ it 'reports no smells with no iterators' do
42
+ src = 'def alfa; end'
43
+ expect(src).not_to reek_of(:NestedIterators)
44
+ end
45
+
46
+ it 'reports no smells with one iterator' do
47
+ src = <<-EOS
48
+ def alfa(bravo)
49
+ bravo.each { |charlie| charlie }
50
+ end
51
+ EOS
52
+
53
+ expect(src).not_to reek_of(:NestedIterators)
23
54
  end
24
55
 
25
56
  it 'should not report nested iterators for Object#tap' do
26
- src = 'def do_stuff(*params); [].tap {|list| params.map {|param| list << (param + param)} } end'
57
+ src = <<-EOS
58
+ def alfa(bravo)
59
+ bravo.tap do |charlie|
60
+ charlie.each { |delta| delta }
61
+ end
62
+ end
63
+ EOS
64
+
27
65
  expect(src).not_to reek_of(:NestedIterators)
28
66
  end
29
67
 
30
68
  it 'should not report method with successive iterators' do
31
69
  src = <<-EOS
32
- def bad(fred)
33
- @fred.each {|item| item.each }
34
- @jim.each {|ting| ting.each }
70
+ def alfa
71
+ @bravo.each { |charlie| charlie }
72
+ @charlie.each { |delta| delta }
35
73
  end
36
74
  EOS
75
+
37
76
  expect(src).not_to reek_of(:NestedIterators)
38
77
  end
39
78
 
40
79
  it 'should not report method with chained iterators' do
41
80
  src = <<-EOS
42
- def chained
43
- @sig.keys.sort_by { |xray| xray.to_s }.each { |min| md5 << min.to_s }
81
+ def alfa
82
+ bravo.sort_by { |charlie| charlie }.each { |delta| delta }
44
83
  end
45
84
  EOS
85
+
46
86
  expect(src).not_to reek_of(:NestedIterators)
47
87
  end
48
88
 
49
89
  it 'detects an iterator with an empty block' do
50
90
  src = <<-EOS
51
- def foo
52
- bar do |bar|
53
- baz {|baz| }
91
+ def alfa
92
+ bravo do |charlie|
93
+ charlie { |delta| }
54
94
  end
55
95
  end
56
96
  EOS
97
+
57
98
  expect(src).to reek_of(:NestedIterators)
58
99
  end
59
100
 
60
101
  it 'reports nesting inside iterator arguments' do
61
102
  src = <<-EOS
62
- def bad(fred, ted)
63
- fred.foo(
64
- ted.each {|item|
65
- item.each {|part|
66
- part.baz
67
- }
68
- }
69
- ) { |qux| qux.quuz }
103
+ def alfa(bravo)
104
+ bravo(
105
+ charlie.each do |delta|
106
+ delta.each { |echo| echo }
107
+ end
108
+ )
70
109
  end
71
110
  EOS
111
+
72
112
  expect(src).to reek_of(:NestedIterators, depth: 2)
73
113
  end
74
114
 
75
115
  it 'reports the deepest level of nesting only' do
76
116
  src = <<-EOS
77
- def bad(fred)
78
- fred.each {|item|
79
- item.each {|part|
80
- part.each {|sub| sub.foobar}
81
- }
82
- }
117
+ def alfa(bravo)
118
+ bravo.each do |charlie|
119
+ charlie.each do |delta|
120
+ delta.each { |echo| echo }
121
+ end
122
+ end
83
123
  end
84
124
  EOS
125
+
85
126
  expect(src).not_to reek_of(:NestedIterators, depth: 2)
86
- expect(src).to reek_of(:NestedIterators, depth: 3)
127
+ expect(src).to reek_of(:NestedIterators, depth: 3, lines: [4])
128
+ end
129
+
130
+ it 'reports all lines on which nested iterators occur' do
131
+ source = <<-EOS
132
+ def alfa
133
+ @bravo.each { |charlie| charlie.each { |delta| @echo.send } }
134
+ @foxtrot.each { |golf| golf.each { |hotel| @india.send } }
135
+ end
136
+ EOS
137
+
138
+ expect(source).to reek_of(:NestedIterators, lines: [2, 3])
87
139
  end
88
140
 
89
141
  it 'handles the case where super receives a block' do
90
142
  src = <<-EOS
91
- def super_call_with_block
92
- super do |k|
93
- nothing.each { |thing| item }
143
+ def alfa
144
+ super do |bravo|
145
+ bravo.each { |charlie| charlie }
94
146
  end
95
147
  end
96
148
  EOS
@@ -100,9 +152,9 @@ RSpec.describe Reek::Smells::NestedIterators do
100
152
 
101
153
  it 'handles the case where super receives a block and arguments' do
102
154
  src = <<-EOS
103
- def super_call_with_block
104
- super(foo) do |k|
105
- nothing.each { |thing| item }
155
+ def alfa
156
+ super do |bravo|
157
+ bravo.each { |charlie| charlie }
106
158
  end
107
159
  end
108
160
  EOS
@@ -110,142 +162,94 @@ RSpec.describe Reek::Smells::NestedIterators do
110
162
  expect(src).to reek_of(:NestedIterators)
111
163
  end
112
164
 
113
- describe 'sniff / warnings' do
114
- let(:detector) { build(:smell_detector, smell_type: :NestedIterators) }
115
-
116
- it 'reports a sensible warning message' do
117
- source = <<-EOS
118
- def foo
119
- bar do |bar|
120
- baz {|baz| }
121
- end
122
- end
123
- EOS
124
- expect(source).to reek_of(:NestedIterators, message: 'contains iterators nested 2 deep')
125
- end
126
-
127
- it 'reports the name of the method and line of the deepest iterator' do
128
- source = <<-EOS
129
- def foo
130
- bar do |bar|
131
- baz {|baz| }
132
- end
133
- end
134
- EOS
135
- expect(source).to reek_of(:NestedIterators, lines: [3])
136
- end
137
-
138
- it 'reports all lines on which nested iterators occur' do
139
- source = <<-EOS
140
- def bad
141
- @fred.each {|item| item.each {|part| @joe.send} }
142
- @jim.each {|ting| ting.each {|piece| @hal.send} }
143
- end
144
- EOS
145
-
146
- expect(source).to reek_of(:NestedIterators, lines: [2, 3])
147
- end
148
-
149
- it 'reports separete cases of nested iterators if levels are different' do
150
- source = <<-EOS
151
- def bad
152
- @fred.each {|item| item.each {|part| part.foo} }
153
- @jim.each {|ting| ting.each {|piece| piece.each {|atom| atom.foo } } }
165
+ it 'does not count iterators without block arguments' do
166
+ src = <<-EOS
167
+ def alfa
168
+ bravo do
169
+ charlie.each { |delta| delta }
154
170
  end
155
- EOS
156
- expect(source).to reek_of(:NestedIterators, lines: [2], depth: 2)
157
- expect(source).to reek_of(:NestedIterators, lines: [3], depth: 3)
158
- end
159
- end
171
+ end
172
+ EOS
160
173
 
161
- describe 'iterators without block arguments' do
162
- it 'does not count those iterators' do
163
- source = <<-EOS
164
- def foo
165
- before do
166
- item.each do |part|
167
- puts part
168
- end
169
- end
170
- end
171
- EOS
172
- expect(source).not_to reek_of(:NestedIterators)
173
- end
174
+ expect(src).not_to reek_of(:NestedIterators)
174
175
  end
175
176
 
176
177
  context 'when blocks are specified as lambdas' do
177
178
  it 'does not report blocks that are not nested' do
178
- source = <<-EOS
179
- def foo
180
- bar ->(x) { baz x }
179
+ src = <<-EOS
180
+ def alfa
181
+ bravo ->(charlie) { delta }
181
182
  end
182
183
  EOS
183
- expect(source).not_to reek_of(:NestedIterators)
184
+
185
+ expect(src).not_to reek_of(:NestedIterators)
184
186
  end
185
187
 
186
188
  it 'reports blocks that are nested' do
187
- source = <<-EOS
188
- def foo
189
- bar ->(x) { baz x, ->(y) { quux y } }
189
+ src = <<-EOS
190
+ def alfa
191
+ bravo ->(charlie) do
192
+ delta ->(echo) { echo }
193
+ end
190
194
  end
191
195
  EOS
192
- expect(source).to reek_of(:NestedIterators)
196
+
197
+ expect(src).to reek_of(:NestedIterators)
193
198
  end
194
199
  end
195
200
 
196
201
  it 'reports nested iterators called via safe navigation' do
197
- source = <<-EOS
198
- def show_bottles(bars)
199
- bars&.each do |bar|
200
- bar&.each do |bottle|
201
- puts bottle
202
- end
202
+ src = <<-EOS
203
+ def alfa(bravo)
204
+ bravo&.each do |charlie|
205
+ charlie&.each { |delta| delta }
203
206
  end
204
207
  end
205
208
  EOS
206
- expect(source).to reek_of(:NestedIterators)
209
+
210
+ expect(src).to reek_of(:NestedIterators)
207
211
  end
208
212
 
209
213
  it 'does not report unnested iterators called via safe navigation' do
210
- source = <<-EOS
211
- def show_bottles(bar)
212
- bar&.each do |bottle|
213
- puts bottle
214
- end
214
+ src = <<-EOS
215
+ def alfa(bravo)
216
+ bravo&.each { |charlie| charlie }
217
+ delta&.each { |echo| echo }
215
218
  end
216
219
  EOS
217
- expect(source).not_to reek_of(:NestedIterators)
220
+
221
+ expect(src).not_to reek_of(:NestedIterators)
218
222
  end
219
223
 
220
- context 'when the allowed nesting depth is 3' do
224
+ context 'setting the allowed nesting depth to 3' do
221
225
  let(:config) do
222
226
  { Reek::Smells::NestedIterators::MAX_ALLOWED_NESTING_KEY => 3 }
223
227
  end
224
228
 
225
- it 'should not report nested iterators 2 levels deep' do
226
- src = <<-EOS
227
- def bad(fred)
228
- @fred.each {|one| one.each {|two| two.two} }
229
- end
230
- EOS
231
-
232
- expect(src).not_to reek_of(:NestedIterators).with_config(config)
233
- end
234
-
235
- it 'should not report nested iterators 3 levels deep' do
229
+ it 'does not report nested iterators 3 levels deep' do
236
230
  src = <<-EOS
237
- def bad(fred)
238
- @fred.each {|one| one.each {|two| two.each {|three| three.three} } }
231
+ def alfa(bravo)
232
+ bravo.each do |charlie|
233
+ charlie.each do |delta|
234
+ delta.each { |echo| echo }
235
+ end
236
+ end
239
237
  end
240
238
  EOS
241
239
 
242
240
  expect(src).not_to reek_of(:NestedIterators).with_config(config)
243
241
  end
244
242
 
245
- it 'should report nested iterators 4 levels deep' do
243
+ it 'reports nested iterators 4 levels deep' do
246
244
  src = <<-EOS
247
- def bad(fred)
248
- @fred.each {|one| one.each {|two| two.each {|three| three.each {|four| four.four} } } }
245
+ def alfa(bravo)
246
+ bravo.each do |charlie|
247
+ charlie.each do |delta|
248
+ delta.each do |echo|
249
+ echo.each { |foxtrot| foxtrot }
250
+ end
251
+ end
252
+ end
249
253
  end
250
254
  EOS
251
255
 
@@ -258,68 +262,70 @@ RSpec.describe Reek::Smells::NestedIterators do
258
262
  { Reek::Smells::NestedIterators::IGNORE_ITERATORS_KEY => ['ignore_me'] }
259
263
  end
260
264
 
261
- it 'should not report nesting the ignored iterator inside another' do
262
- src = 'def bad(fred) @fred.each {|item| item.ignore_me {|ting| ting.ting} } end'
263
- expect(src).not_to reek_of(:NestedIterators).with_config(config)
264
- end
265
+ it 'does not report when nesting the ignored iterator inside another' do
266
+ src = <<-EOS
267
+ def alfa(bravo)
268
+ bravo.each do |charlie|
269
+ charlie.ignore_me { |delta| delta }
270
+ end
271
+ end
272
+ EOS
265
273
 
266
- it 'should not report nesting inside the ignored iterator' do
267
- src = 'def bad(fred) @fred.ignore_me {|item| item.each {|ting| ting.ting} } end'
268
274
  expect(src).not_to reek_of(:NestedIterators).with_config(config)
269
275
  end
270
276
 
271
- it 'should report nested iterators inside the ignored iterator' do
272
- src = '
273
- def bad(fred)
274
- @fred.ignore_me {|item| item.each {|ting| ting.each {|other| other.other} } }
277
+ it 'does not report a nested iterator inside the ignored iterator' do
278
+ src = <<-EOS
279
+ def alfa(bravo)
280
+ bravo.ignore_me do |charlie|
281
+ charlie.each { |delta| delta }
282
+ end
275
283
  end
276
- '
277
- expect(src).to reek_of(:NestedIterators, depth: 2).with_config(config)
284
+ EOS
285
+
286
+ expect(src).not_to reek_of(:NestedIterators).with_config(config)
278
287
  end
279
288
 
280
- it 'should report nested iterators outside the ignored iterator' do
281
- src = '
282
- def bad(fred)
283
- @fred.each {|item| item.each {|ting| ting.ignore_me {|other| other.other} } }
289
+ it 'reports nested iterators inside the ignored iterator' do
290
+ src = <<-EOS
291
+ def alfa(bravo)
292
+ bravo.ignore_me do |charlie|
293
+ charlie.each do |delta|
294
+ delta.each { |echo| echo }
295
+ end
296
+ end
284
297
  end
285
- '
298
+ EOS
299
+
286
300
  expect(src).to reek_of(:NestedIterators, depth: 2).with_config(config)
287
301
  end
288
302
 
289
- it 'should report nested iterators with the ignored iterator between them' do
290
- src = '
291
- def bad(fred)
292
- @fred.each {|item| item.ignore_me {|ting| ting.ting {|other| other.other} } }
303
+ it 'reports nested iterators outside the ignored iterator' do
304
+ src = <<-EOS
305
+ def alfa(bravo)
306
+ bravo.each do |charlie|
307
+ charlie.each do |delta|
308
+ delta.ignore_me { |echo| echo }
309
+ end
310
+ end
293
311
  end
294
- '
312
+ EOS
313
+
295
314
  expect(src).to reek_of(:NestedIterators, depth: 2).with_config(config)
296
315
  end
297
- end
298
- end
299
316
 
300
- RSpec.describe Reek::Smells::NestedIterators do
301
- let(:detector) { build(:smell_detector, smell_type: :NestedIterators) }
302
-
303
- it_should_behave_like 'SmellDetector'
304
-
305
- context 'when a smell is reported' do
306
- let(:warning) do
317
+ it 'should report nested iterators with the ignored iterator between them' do
307
318
  src = <<-EOS
308
- def fred()
309
- nothing.each do |item|
310
- again.each {|thing| item }
319
+ def alfa(bravo)
320
+ bravo.each do |charlie|
321
+ charlie.ignore_me do |delta|
322
+ delta.each { |echo| echo }
323
+ end
311
324
  end
312
325
  end
313
326
  EOS
314
- ctx = Reek::Context::CodeContext.new(nil, Reek::Source::SourceCode.from(src).syntax_tree)
315
- detector.sniff(ctx).first
316
- end
317
327
 
318
- it_should_behave_like 'common fields set correctly'
319
-
320
- it 'reports correct values' do
321
- expect(warning.parameters[:depth]).to eq(2)
322
- expect(warning.lines).to eq([3])
328
+ expect(src).to reek_of(:NestedIterators, depth: 2).with_config(config)
323
329
  end
324
330
  end
325
331
  end