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,234 +1,144 @@
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::TooManyConstants do
6
- context 'counting constants' do
7
- it 'should not report for non-excessive constants' do
8
- src = <<-EOS
9
- class Dummy
10
- A = B = C = D = E = 1
11
- end
12
- EOS
13
-
14
- expect(src).not_to reek_of(:TooManyConstants)
15
- end
16
-
17
- it 'should not report when increasing default' do
18
- src = <<-EOS
19
- # :reek:TooManyConstants: { max_constants: 6 }
20
- class Dummy
21
- A = B = C = D = E = 1
22
- F = 1
23
- end
24
- EOS
5
+ let(:config) do
6
+ { Reek::Smells::TooManyConstants::MAX_ALLOWED_CONSTANTS_KEY => 2 }
7
+ end
25
8
 
26
- expect(src).not_to reek_of(:TooManyConstants)
27
- end
9
+ it 'reports the right values' do
10
+ src = <<-EOS
11
+ class Alfa
12
+ Bravo = Charlie = Delta = 1
13
+ end
14
+ EOS
15
+
16
+ expect(src).to reek_of(:TooManyConstants,
17
+ lines: [1],
18
+ context: 'Alfa',
19
+ message: 'has 3 constants',
20
+ source: 'string',
21
+ count: 3).with_config(config)
22
+ end
28
23
 
29
- it 'should not report when disabled' do
30
- src = <<-EOS
31
- # :reek:TooManyConstants: { enabled: false }
32
- class Dummy
33
- A = B = C = D = E = 1
34
- F = 1
35
- end
36
- EOS
24
+ it 'should not report for non-excessive constants' do
25
+ src = <<-EOS
26
+ class Alfa
27
+ Bravo = Charlie = 1
28
+ end
29
+ EOS
37
30
 
38
- expect(src).not_to reek_of(:TooManyConstants)
39
- end
31
+ expect(src).not_to reek_of(:TooManyConstants).with_config(config)
32
+ end
40
33
 
41
- it 'should not account class definition' do
42
- src = <<-EOS
43
- module Dummiest
44
- class Dummy
45
- A = B = C = D = E = 1
34
+ it 'should not report when increasing default' do
35
+ src = <<-EOS
36
+ # :reek:TooManyConstants: { max_constants: 3 }
37
+ class Alfa
38
+ Bravo = Charlie = Delta = 1
39
+ end
40
+ EOS
46
41
 
47
- Error = Class.new(StandardError)
48
- end
49
- end
50
- EOS
42
+ expect(src).not_to reek_of(:TooManyConstants).with_config(config)
43
+ end
51
44
 
52
- expect(src).not_to reek_of(:TooManyConstants)
53
- end
45
+ it 'should not report when disabled' do
46
+ src = <<-EOS
47
+ # :reek:TooManyConstants: { enabled: false }
48
+ class Alfa
49
+ Bravo = Charlie = Delta = 1
50
+ end
51
+ EOS
54
52
 
55
- it 'should not account struct definition' do
56
- src = <<-EOS
57
- module Dummiest
58
- class Dummy
59
- A = B = C = D = E = 1
53
+ expect(src).not_to reek_of(:TooManyConstants).with_config(config)
54
+ end
60
55
 
61
- Struct = Struct.new
62
- end
63
- end
64
- EOS
56
+ it 'should not account class definition' do
57
+ src = <<-EOS
58
+ class Alfa
59
+ Bravo = Charlie = 1
60
+ Delta = Class.new(StandardError)
61
+ end
62
+ EOS
65
63
 
66
- expect(src).to_not reek_of(:TooManyConstants)
67
- end
64
+ expect(src).not_to reek_of(:TooManyConstants).with_config(config)
65
+ end
68
66
 
69
- it 'should count each constant only once' do
70
- src = <<-EOS
71
- class Good
72
- A = B = C = D = E = 1
73
- end
67
+ it 'should not account struct definition' do
68
+ src = <<-EOS
69
+ class Alfa
70
+ Bravo = Charlie = 1
71
+ Delta = Struct.new
72
+ end
73
+ EOS
74
74
 
75
- class Bad
76
- A = B = C = D = E = 1
77
- end
75
+ expect(src).to_not reek_of(:TooManyConstants).with_config(config)
76
+ end
78
77
 
79
- class Ugly
80
- A = B = C = D = E = 1
81
- end
82
- EOS
78
+ it 'should count each constant only once' do
79
+ src = <<-EOS
80
+ class Alfa
81
+ Bravo = Charlie = 1
82
+ end
83
83
 
84
- expect(src).not_to reek_of(:TooManyConstants)
85
- end
84
+ class Delta
85
+ Echo = Foxtrot = 1
86
+ end
86
87
 
87
- it 'should count each constant only once for each class' do
88
- src = <<-EOS
89
- module Movie
90
- class Good
91
- A = B = C = D = E = 1
92
- end
88
+ class Golf
89
+ Hotel = India = 1
90
+ end
91
+ EOS
93
92
 
94
- class Bad
95
- F = G = H = I = J = 1
96
- end
93
+ expect(src).not_to reek_of(:TooManyConstants).with_config(config)
94
+ end
97
95
 
98
- class Ugly
99
- K = L = M = N = O = 1
100
- end
101
- end
102
- EOS
103
-
104
- expect(src).not_to reek_of(:TooManyConstants)
105
- end
106
-
107
- it 'should not report outer module when inner module suppressed' do
108
- src = <<-EOS
109
- module Foo
110
- # ignore :reek:TooManyConstants:
111
- module Bar
112
- A = 1
113
- B = 2
114
- C = 3
115
- D = 4
116
- E = 5
117
- F = 6
118
- end
96
+ it 'should not report outer module when inner module suppressed' do
97
+ src = <<-EOS
98
+ module Alfa
99
+ # ignore :reek:TooManyConstants:
100
+ module Bravo
101
+ Charlie = Delta = Echo = 1
119
102
  end
120
- EOS
121
-
122
- expect(src).not_to reek_of(:TooManyConstants, context: 'Foo')
123
- end
124
-
125
- it 'should count each constant only once for each namespace' do
126
- src = <<-EOS
127
- module Movie
128
- A = B = C = D = E = 1
103
+ end
104
+ EOS
129
105
 
130
- class Good
131
- F = 1
132
- end
133
- end
134
- EOS
106
+ expect(src).not_to reek_of(:TooManyConstants).with_config(config)
107
+ end
135
108
 
136
- expect(src).not_to reek_of(:TooManyConstants)
137
- end
109
+ it 'should count each constant only once for each namespace' do
110
+ src = <<-EOS
111
+ module Alfa
112
+ Bravo = Charlie = 1
138
113
 
139
- it 'should report for excessive constants inside a class' do
140
- src = <<-EOS
141
- class Dummy
142
- A = B = C = D = E = 1
143
- F = 1
114
+ class Delta
115
+ Echo = 1
144
116
  end
145
- EOS
146
-
147
- expect(src).to reek_of(:TooManyConstants)
148
- end
117
+ end
118
+ EOS
149
119
 
150
- it 'should report for excessive constants inside a module' do
151
- src = <<-EOS
152
- module Dummiest
153
- A = B = C = D = E = 1
154
- F = 1
120
+ expect(src).not_to reek_of(:TooManyConstants).with_config(config)
121
+ end
155
122
 
156
- class Dummy
157
- end
158
- end
159
- EOS
123
+ it 'should report for excessive constants inside a module' do
124
+ src = <<-EOS
125
+ module Alfa
126
+ Bravo = Charlie = Delta = 1
127
+ end
128
+ EOS
160
129
 
161
- expect(src).to reek_of(:TooManyConstants, context: 'Dummiest')
162
- end
130
+ expect(src).to reek_of(:TooManyConstants, context: 'Alfa').with_config(config)
163
131
  end
164
132
 
165
- context 'smell report' do
166
- it 'reports the number of constants' do
167
- src = <<-EOS
168
- module Moduly
169
- class Klass
170
- A = B = C = D = E = 1
171
- F = 1
172
- end
133
+ it 'reports the full class name' do
134
+ src = <<-EOS
135
+ module Alfa
136
+ class Bravo
137
+ Charlie = Delta = Echo = 1
173
138
  end
174
- EOS
175
-
176
- expect(src).to reek_of(:TooManyConstants, count: 6)
177
- end
178
-
179
- it 'reports the line where it occurs' do
180
- src = <<-EOS
181
- module Moduly
182
- class Klass
183
- A = B = C = D = E = 1
184
- F = 1
185
- end
186
- end
187
- EOS
188
-
189
- expect(src).to reek_of(:TooManyConstants, lines: [2])
190
- end
191
-
192
- it 'reports a readable message' do
193
- src = <<-EOS
194
- module Moduly
195
- class Klass
196
- A = B = C = D = E = 1
197
- F = 1
198
- end
199
- end
200
- EOS
201
-
202
- expect(src).to reek_of(:TooManyConstants, message: 'has 6 constants')
203
- end
204
-
205
- context 'context' do
206
- it 'reports the full class name' do
207
- src = <<-EOS
208
- module Moduly
209
- class Klass
210
- A = B = C = D = E = 1
211
- F = 1
212
- end
213
- end
214
- EOS
215
-
216
- expect(src).to reek_of(:TooManyConstants, context: 'Moduly::Klass')
217
139
  end
140
+ EOS
218
141
 
219
- it 'reports the module name' do
220
- src = <<-EOS
221
- module Moduly
222
- A = B = C = D = E = 1
223
- F = 1
224
-
225
- class Klass
226
- end
227
- end
228
- EOS
229
-
230
- expect(src).to reek_of(:TooManyConstants, context: 'Moduly')
231
- end
232
- end
142
+ expect(src).to reek_of(:TooManyConstants, context: 'Alfa::Bravo').with_config(config)
233
143
  end
234
144
  end
@@ -2,154 +2,131 @@ require_relative '../../spec_helper'
2
2
  require_lib 'reek/smells/too_many_instance_variables'
3
3
 
4
4
  RSpec.describe Reek::Smells::TooManyInstanceVariables do
5
- context 'reporting smell' do
6
- it 'reports the smell parameters' do
7
- src = <<-EOS
8
- class Empty
9
- def ivars
10
- @a = @b = @c = @d = 1
11
- @e = 1
12
- end
5
+ let(:config) do
6
+ { Reek::Smells::TooManyInstanceVariables::MAX_ALLOWED_IVARS_KEY => 2 }
7
+ end
8
+
9
+ it 'reports the right values' do
10
+ src = <<-EOS
11
+ class Alfa
12
+ def bravo
13
+ @charlie = @delta = @echo = 1
13
14
  end
14
- EOS
15
-
16
- expect(src).to reek_of(described_class,
17
- lines: [1],
18
- count: 5,
19
- message: 'has at least 5 instance variables',
20
- context: 'Empty')
21
- end
15
+ end
16
+ EOS
17
+
18
+ expect(src).to reek_of(:TooManyInstanceVariables,
19
+ lines: [1],
20
+ context: 'Alfa',
21
+ message: 'has at least 3 instance variables',
22
+ source: 'string',
23
+ count: 3).with_config(config)
22
24
  end
23
25
 
24
- context 'counting instance variables' do
25
- it 'should not report for non-excessive ivars' do
26
- src = <<-EOS
27
- class Empty
28
- def ivars
29
- @a = @b = @c = @d = 1
30
- end
26
+ it 'should not report for non-excessive ivars' do
27
+ src = <<-EOS
28
+ class Alfa
29
+ def bravo
30
+ @charlie = @delta = 1
31
31
  end
32
- EOS
33
- expect(src).not_to reek_of(described_class)
34
- end
35
-
36
- it 'has a configurable maximum' do
37
- src = <<-EOS
38
- # :reek:TooManyInstanceVariables: { max_instance_variables: 5 }
39
- class Empty
40
- def ivars
41
- @a = @b = @c = @d = 1
42
- @e = 1
43
- end
32
+ end
33
+ EOS
34
+
35
+ expect(src).not_to reek_of(:TooManyInstanceVariables).with_config(config)
36
+ end
37
+
38
+ it 'has a configurable maximum' do
39
+ src = <<-EOS
40
+ # :reek:TooManyInstanceVariables: { max_instance_variables: 3 }
41
+ class Alfa
42
+ def bravo
43
+ @charlie = @delta = @echo = 1
44
44
  end
45
- EOS
46
- expect(src).not_to reek_of(described_class)
47
- end
48
-
49
- it 'counts each ivar only once' do
50
- src = <<-EOS
51
- class Empty
52
- def ivars
53
- @a = @b = @c = @d = 1
54
- @a = @b = @c = @d = 1
55
- end
45
+ end
46
+ EOS
47
+
48
+ expect(src).not_to reek_of(:TooManyInstanceVariables).with_config(config)
49
+ end
50
+
51
+ it 'counts each ivar only once' do
52
+ src = <<-EOS
53
+ class Alfa
54
+ def bravo
55
+ @charlie = @delta = 1
56
+ @charlie = @delta = 1
56
57
  end
57
- EOS
58
- expect(src).not_to reek_of(described_class)
59
- end
60
-
61
- it 'should not report memoized ivars' do
62
- src = <<-EOS
63
- class Empty
64
- def ivars
65
- @a = @b = @c = @d = 1
66
- @e ||= 1
67
- end
58
+ end
59
+ EOS
60
+
61
+ expect(src).not_to reek_of(:TooManyInstanceVariables).with_config(config)
62
+ end
63
+
64
+ it 'does not report memoized bravo' do
65
+ src = <<-EOS
66
+ class Alfa
67
+ def bravo
68
+ @charlie = @delta = 1
69
+ @echo ||= 1
68
70
  end
69
- EOS
70
- expect(src).not_to reek_of(described_class)
71
- end
72
-
73
- it 'should not count ivars on inner classes altogether' do
74
- src = <<-EOS
75
- class Empty
76
- class InnerA
77
- def ivars
78
- @a = @b = @c = @d = 1
79
- end
80
- end
71
+ end
72
+ EOS
73
+
74
+ expect(src).not_to reek_of(:TooManyInstanceVariables).with_config(config)
75
+ end
81
76
 
82
- class InnerB
83
- def ivars
84
- @e = 1
85
- end
77
+ it 'does not count ivars across inner classes' do
78
+ src = <<-EOS
79
+ class Alfa
80
+ class Bravo
81
+ def charlie
82
+ @delta = @echo = 1
86
83
  end
87
84
  end
88
- EOS
89
- expect(src).not_to reek_of(described_class)
90
- end
91
-
92
- it 'should not count ivars on modules altogether' do
93
- src = <<-EOS
94
- class Empty
95
- class InnerA
96
- def ivars
97
- @a = @b = @c = @d = 1
98
- end
99
- end
100
85
 
101
- module InnerB
102
- def ivars
103
- @e = 1
104
- end
86
+ class Hotel
87
+ def india
88
+ @juliett = 1
105
89
  end
106
90
  end
107
- EOS
108
- expect(src).not_to reek_of(described_class)
109
- end
110
-
111
- it 'reports excessive ivars' do
112
- src = <<-EOS
113
- class Empty
114
- def ivars
115
- @a = @b = @c = @d = 1
116
- @e = 1
91
+ end
92
+ EOS
93
+
94
+ expect(src).not_to reek_of(:TooManyInstanceVariables).with_config(config)
95
+ end
96
+
97
+ it 'does not count ivars across inner modules and classes' do
98
+ src = <<-EOS
99
+ class Alfa
100
+ class Bravo
101
+ def charlie
102
+ @delta = @echo = 1
117
103
  end
118
104
  end
119
- EOS
120
- expect(src).to reek_of(described_class)
121
- end
122
-
123
- it 'reports excessive ivars even in different methods' do
124
- src = <<-EOS
125
- class Empty
126
- def ivars_a
127
- @a = @b = @c = @d = 1
128
- end
129
105
 
130
- def ivars_b
131
- @e = 1
106
+ module Foxtrot
107
+ def golf
108
+ @hotel = 1
132
109
  end
133
110
  end
134
- EOS
135
- expect(src).to reek_of(described_class)
136
- end
137
-
138
- it 'should not report for ivars in 2 extensions' do
139
- src = <<-EOS
140
- class Full
141
- def ivars_a
142
- @a = @b = @c = @d = 1
143
- end
111
+ end
112
+ EOS
113
+
114
+ expect(src).not_to reek_of(:TooManyInstanceVariables).with_config(config)
115
+ end
116
+
117
+ it 'reports excessive ivars across different methods' do
118
+ src = <<-EOS
119
+ class Alfa
120
+ def bravo
121
+ @charlie = @delta = 1
144
122
  end
145
123
 
146
- class Full
147
- def ivars_b
148
- @a = @b = @c = @d = 1
149
- end
124
+ def golf
125
+ @hotel = 1
150
126
  end
151
- EOS
152
- expect(src).not_to reek_of(described_class)
153
- end
127
+ end
128
+ EOS
129
+
130
+ expect(src).to reek_of(:TooManyInstanceVariables).with_config(config)
154
131
  end
155
132
  end