reek 4.4.0 → 4.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/CONTRIBUTING.md +41 -4
- data/README.md +15 -3
- data/defaults.reek +1 -1
- data/docs/Basic-Smell-Options.md +2 -2
- data/docs/Code-Smells.md +4 -0
- data/docs/How-To-Write-New-Detectors.md +116 -0
- data/docs/How-reek-works-internally.md +3 -4
- data/docs/Instance-Variable-Assumption.md +134 -0
- data/docs/Simulated-Polymorphism.md +1 -1
- data/docs/Smell-Suppression.md +6 -6
- data/docs/{style-guide.md → Style-Guide.md} +0 -0
- data/docs/Unused-Private-Method.md +1 -1
- data/docs/YAML-Reports.md +0 -18
- data/features/configuration_files/directory_specific_directives.feature +4 -4
- data/features/configuration_files/unused_private_method.feature +2 -2
- data/features/samples.feature +122 -117
- data/features/smells/subclassed_from_core_class.feature +1 -1
- data/lib/reek/code_comment.rb +13 -4
- data/lib/reek/context/code_context.rb +1 -0
- data/lib/reek/examiner.rb +24 -27
- data/lib/reek/smells/class_variable.rb +1 -1
- data/lib/reek/smells/control_parameter.rb +1 -1
- data/lib/reek/smells/data_clump.rb +1 -1
- data/lib/reek/smells/duplicate_method_call.rb +1 -1
- data/lib/reek/smells/feature_envy.rb +1 -1
- data/lib/reek/smells/instance_variable_assumption.rb +1 -1
- data/lib/reek/smells/prima_donna_method.rb +1 -1
- data/lib/reek/smells/repeated_conditional.rb +1 -1
- data/lib/reek/smells/smell_detector.rb +5 -14
- data/lib/reek/smells/smell_repository.rb +1 -5
- data/lib/reek/smells/smell_warning.rb +6 -8
- data/lib/reek/smells/subclassed_from_core_class.rb +1 -1
- data/lib/reek/smells/uncommunicative_variable_name.rb +22 -12
- data/lib/reek/smells/unused_private_method.rb +1 -1
- data/lib/reek/spec.rb +2 -2
- data/lib/reek/spec/should_reek_of.rb +12 -8
- data/lib/reek/version.rb +1 -1
- data/spec/reek/code_comment_spec.rb +13 -5
- data/spec/reek/examiner_spec.rb +2 -2
- data/spec/reek/smells/attribute_spec.rb +91 -78
- data/spec/reek/smells/boolean_parameter_spec.rb +72 -64
- data/spec/reek/smells/class_variable_spec.rb +81 -68
- data/spec/reek/smells/control_parameter_spec.rb +101 -141
- data/spec/reek/smells/data_clump_spec.rb +94 -149
- data/spec/reek/smells/duplicate_method_call_spec.rb +98 -85
- data/spec/reek/smells/feature_envy_spec.rb +164 -183
- data/spec/reek/smells/instance_variable_assumption_spec.rb +51 -147
- data/spec/reek/smells/irresponsible_module_spec.rb +153 -170
- data/spec/reek/smells/long_parameter_list_spec.rb +44 -88
- data/spec/reek/smells/long_yield_list_spec.rb +41 -41
- data/spec/reek/smells/manual_dispatch_spec.rb +36 -18
- data/spec/reek/smells/module_initialize_spec.rb +31 -33
- data/spec/reek/smells/nested_iterators_spec.rb +189 -183
- data/spec/reek/smells/nil_check_spec.rb +48 -37
- data/spec/reek/smells/prima_donna_method_spec.rb +41 -26
- data/spec/reek/smells/repeated_conditional_spec.rb +75 -87
- data/spec/reek/smells/smell_warning_spec.rb +7 -0
- data/spec/reek/smells/subclassed_from_core_class_spec.rb +37 -112
- data/spec/reek/smells/too_many_constants_spec.rb +109 -199
- data/spec/reek/smells/too_many_instance_variables_spec.rb +105 -128
- data/spec/reek/smells/too_many_methods_spec.rb +38 -62
- data/spec/reek/smells/too_many_statements_spec.rb +69 -45
- data/spec/reek/smells/uncommunicative_method_name_spec.rb +16 -29
- data/spec/reek/smells/uncommunicative_module_name_spec.rb +24 -37
- data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +55 -60
- data/spec/reek/smells/uncommunicative_variable_name_spec.rb +108 -95
- data/spec/reek/smells/unused_parameters_spec.rb +73 -49
- data/spec/reek/smells/unused_private_method_spec.rb +97 -50
- data/spec/reek/smells/utility_function_spec.rb +130 -188
- data/spec/reek/spec/should_reek_of_spec.rb +2 -2
- metadata +6 -7
- data/lib/reek/cli/warning_collector.rb +0 -27
- data/spec/reek/cli/warning_collector_spec.rb +0 -25
- data/spec/reek/smells/smell_detector_shared.rb +0 -29
@@ -1,140 +1,148 @@
|
|
1
1
|
require_relative '../../spec_helper'
|
2
2
|
require_lib 'reek/smells/uncommunicative_variable_name'
|
3
|
-
require_relative 'smell_detector_shared'
|
4
3
|
|
5
4
|
RSpec.describe Reek::Smells::UncommunicativeVariableName do
|
6
|
-
|
7
|
-
|
5
|
+
it 'reports the right values' do
|
6
|
+
src = <<-EOS
|
7
|
+
def alfa
|
8
|
+
x = 5
|
9
|
+
end
|
10
|
+
EOS
|
11
|
+
|
12
|
+
expect(src).to reek_of(:UncommunicativeVariableName,
|
13
|
+
lines: [2],
|
14
|
+
context: 'alfa',
|
15
|
+
message: "has the variable name 'x'",
|
16
|
+
source: 'string',
|
17
|
+
name: 'x')
|
8
18
|
end
|
9
19
|
|
10
|
-
|
20
|
+
it 'does count all occurences' do
|
21
|
+
src = <<-EOS
|
22
|
+
def alfa
|
23
|
+
x = 3
|
24
|
+
y = 7
|
25
|
+
end
|
26
|
+
EOS
|
27
|
+
|
28
|
+
expect(src).to reek_of(:UncommunicativeVariableName,
|
29
|
+
lines: [2],
|
30
|
+
name: 'x')
|
31
|
+
expect(src).to reek_of(:UncommunicativeVariableName,
|
32
|
+
lines: [3],
|
33
|
+
name: 'y')
|
34
|
+
end
|
11
35
|
|
12
|
-
context '
|
13
|
-
it 'does not report use of one-letter
|
14
|
-
src = 'class
|
36
|
+
context 'instance variables' do
|
37
|
+
it 'does not report use of one-letter names' do
|
38
|
+
src = 'class Alfa; def bravo; @x; end; end'
|
15
39
|
expect(src).not_to reek_of(:UncommunicativeVariableName)
|
16
40
|
end
|
17
|
-
|
18
|
-
|
41
|
+
|
42
|
+
it 'reports one-letter names in assignment' do
|
43
|
+
src = 'class Alfa; def bravo(charlie) @x = charlie; end; end'
|
19
44
|
expect(src).to reek_of(:UncommunicativeVariableName, name: '@x')
|
20
45
|
end
|
21
46
|
end
|
22
47
|
|
23
|
-
context 'local
|
24
|
-
it 'does not report one-word variable name' do
|
25
|
-
expect('def help(fred) simple = jim(45) end').
|
26
|
-
not_to reek_of(:UncommunicativeVariableName)
|
27
|
-
end
|
28
|
-
|
48
|
+
context 'local variables' do
|
29
49
|
it 'does not report single underscore as a variable name' do
|
30
|
-
|
50
|
+
src = 'def alfa; _ = bravo(); end'
|
51
|
+
expect(src).not_to reek_of(:UncommunicativeVariableName)
|
31
52
|
end
|
32
53
|
|
33
|
-
it 'reports one-letter
|
34
|
-
src = 'def
|
54
|
+
it 'reports one-letter names' do
|
55
|
+
src = 'def alfa; x = bravo(); end'
|
35
56
|
expect(src).to reek_of(:UncommunicativeVariableName, name: 'x')
|
36
57
|
end
|
37
58
|
|
38
|
-
it 'reports
|
39
|
-
src = 'def
|
40
|
-
expect(src).to reek_of(:UncommunicativeVariableName, name: '
|
59
|
+
it 'reports names ending with a digit' do
|
60
|
+
src = 'def alfa; var123 = bravo(); end'
|
61
|
+
expect(src).to reek_of(:UncommunicativeVariableName, name: 'var123')
|
41
62
|
end
|
42
63
|
|
43
|
-
it 'reports
|
44
|
-
|
45
|
-
src
|
46
|
-
expect(src).to reek_of(:UncommunicativeVariableName,
|
47
|
-
name: bad_var)
|
48
|
-
end
|
49
|
-
|
50
|
-
it 'reports variable name only once' do
|
51
|
-
src = 'def simple(fred) x = jim(45); x = y end'
|
52
|
-
syntax_tree = Reek::Source::SourceCode.from(src).syntax_tree
|
53
|
-
ctx = Reek::Context::CodeContext.new(nil, syntax_tree)
|
54
|
-
smells = detector.sniff(ctx)
|
55
|
-
expect(smells.length).to eq(1)
|
56
|
-
expect(smells[0].smell_type).to eq(described_class.smell_type)
|
57
|
-
expect(smells[0].parameters[:name]).to eq('x')
|
58
|
-
expect(smells[0].lines).to eq([1, 1])
|
64
|
+
it 'reports camelcased names' do
|
65
|
+
src = 'def alfa; bravoCharlie = delta(); end'
|
66
|
+
expect(src).to reek_of(:UncommunicativeVariableName, name: 'bravoCharlie')
|
59
67
|
end
|
60
68
|
|
61
69
|
it 'reports a bad name inside a block' do
|
62
|
-
src = 'def
|
63
|
-
expect(src).to reek_of(:UncommunicativeVariableName, name: '
|
70
|
+
src = 'def alfa; bravo.each { x = 42 }; end'
|
71
|
+
expect(src).to reek_of(:UncommunicativeVariableName, name: 'x')
|
64
72
|
end
|
65
73
|
|
66
74
|
it 'reports variable name outside any method' do
|
67
|
-
|
68
|
-
|
75
|
+
src = 'class Alfa; x = bravo(); end'
|
76
|
+
expect(src).to reek_of(:UncommunicativeVariableName, name: 'x')
|
69
77
|
end
|
70
|
-
end
|
71
78
|
|
72
|
-
|
73
|
-
|
74
|
-
src
|
75
|
-
def bad
|
76
|
-
unless @mod then
|
77
|
-
@sig.each { |x| x.to_s }
|
78
|
-
end
|
79
|
-
end
|
80
|
-
EOS
|
81
|
-
expect(src).to reek_of(:UncommunicativeVariableName, name: 'x')
|
79
|
+
it "reports bad names starting with '_'" do
|
80
|
+
src = 'def alfa; _bravoCharlie_42 = delta(); end'
|
81
|
+
expect(src).to reek_of(:UncommunicativeVariableName, name: '_bravoCharlie_42')
|
82
82
|
end
|
83
|
+
end
|
83
84
|
|
85
|
+
context 'block parameters' do
|
84
86
|
it 'reports all relevant block parameters' do
|
85
87
|
src = <<-EOS
|
86
|
-
def
|
87
|
-
@
|
88
|
+
def alfa
|
89
|
+
@bravo.map { |x, y| x + y }
|
88
90
|
end
|
89
91
|
EOS
|
92
|
+
|
90
93
|
expect(src).to reek_of(:UncommunicativeVariableName, name: 'x')
|
91
94
|
expect(src).to reek_of(:UncommunicativeVariableName, name: 'y')
|
92
95
|
end
|
93
96
|
|
94
97
|
it 'reports block parameters used outside of methods' do
|
95
98
|
src = <<-EOS
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
+
class Alfa
|
100
|
+
@bravo.map { |x| x * 2 }
|
101
|
+
end
|
99
102
|
EOS
|
103
|
+
|
100
104
|
expect(src).to reek_of(:UncommunicativeVariableName, name: 'x')
|
101
105
|
end
|
102
106
|
|
103
107
|
it 'reports splatted block parameters correctly' do
|
104
108
|
src = <<-EOS
|
105
|
-
def
|
106
|
-
@
|
109
|
+
def alfa
|
110
|
+
@bravo.map { |*y| y << 1 }
|
107
111
|
end
|
108
112
|
EOS
|
113
|
+
|
109
114
|
expect(src).to reek_of(:UncommunicativeVariableName, name: 'y')
|
110
115
|
end
|
111
116
|
|
112
117
|
it 'reports nested block parameters' do
|
113
118
|
src = <<-EOS
|
114
|
-
def
|
115
|
-
@
|
119
|
+
def alfa
|
120
|
+
@bravo.map { |(x, y)| x + y }
|
116
121
|
end
|
117
122
|
EOS
|
123
|
+
|
118
124
|
expect(src).to reek_of(:UncommunicativeVariableName, name: 'x')
|
119
125
|
expect(src).to reek_of(:UncommunicativeVariableName, name: 'y')
|
120
126
|
end
|
121
127
|
|
122
128
|
it 'reports splatted nested block parameters' do
|
123
129
|
src = <<-EOS
|
124
|
-
def
|
125
|
-
@
|
130
|
+
def def alfa
|
131
|
+
@bravo.map { |(x, *y)| x + y }
|
126
132
|
end
|
127
133
|
EOS
|
134
|
+
|
128
135
|
expect(src).to reek_of(:UncommunicativeVariableName, name: 'x')
|
129
136
|
expect(src).to reek_of(:UncommunicativeVariableName, name: 'y')
|
130
137
|
end
|
131
138
|
|
132
139
|
it 'reports deeply nested block parameters' do
|
133
140
|
src = <<-EOS
|
134
|
-
def
|
135
|
-
@
|
141
|
+
def alfa
|
142
|
+
@bravo.map { |(x, (y, z))| x + y + z }
|
136
143
|
end
|
137
144
|
EOS
|
145
|
+
|
138
146
|
expect(src).to reek_of(:UncommunicativeVariableName, name: 'x')
|
139
147
|
expect(src).to reek_of(:UncommunicativeVariableName, name: 'y')
|
140
148
|
expect(src).to reek_of(:UncommunicativeVariableName, name: 'z')
|
@@ -142,51 +150,56 @@ RSpec.describe Reek::Smells::UncommunicativeVariableName do
|
|
142
150
|
|
143
151
|
it 'reports shadowed block parameters' do
|
144
152
|
src = <<-EOS
|
145
|
-
def
|
146
|
-
@
|
153
|
+
def alfa
|
154
|
+
@bravo.map { |x; y| y = x * 2 }
|
147
155
|
end
|
148
156
|
EOS
|
157
|
+
|
149
158
|
expect(src).to reek_of(:UncommunicativeVariableName, name: 'x')
|
150
159
|
expect(src).to reek_of(:UncommunicativeVariableName, name: 'y')
|
151
160
|
end
|
152
161
|
end
|
153
162
|
|
154
|
-
|
155
|
-
let(:
|
156
|
-
src = <<-EOS
|
157
|
-
def bad
|
158
|
-
unless @mod then
|
159
|
-
x2 = xy.to_s
|
160
|
-
x2
|
161
|
-
x2 = 56
|
162
|
-
end
|
163
|
-
end
|
164
|
-
EOS
|
165
|
-
syntax_tree = Reek::Source::SourceCode.from(src).syntax_tree
|
166
|
-
ctx = Reek::Context::CodeContext.new(nil, syntax_tree)
|
167
|
-
detector.sniff(ctx).first
|
168
|
-
end
|
163
|
+
describe '`accept` patterns' do
|
164
|
+
let(:src) { 'def alfa; bravo2 = 42; end' }
|
169
165
|
|
170
|
-
|
166
|
+
it 'make smelly names pass via regex / strings given by list / literal' do
|
167
|
+
expect(src).to reek_of(:UncommunicativeVariableName)
|
171
168
|
|
172
|
-
|
173
|
-
|
174
|
-
|
169
|
+
[[/bravo2/], /bravo2/, ['bravo2'], 'bravo2'].each do |pattern|
|
170
|
+
expect(src).to_not reek_of(:UncommunicativeVariableName).with_config('accept' => pattern)
|
171
|
+
end
|
175
172
|
end
|
176
173
|
end
|
177
174
|
|
178
|
-
|
179
|
-
let(:
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
175
|
+
describe '`reject` patterns' do
|
176
|
+
let(:src) { 'def alfa; foobar = 42; end' }
|
177
|
+
|
178
|
+
it 'reject smelly names via regex / strings given by list / literal' do
|
179
|
+
expect(src).not_to reek_of(:UncommunicativeVariableName)
|
180
|
+
|
181
|
+
[[/foobar/], /foobar/, ['foobar'], 'foobar'].each do |pattern|
|
182
|
+
expect(src).to reek_of(:UncommunicativeVariableName).with_config('reject' => pattern)
|
183
|
+
end
|
184
184
|
end
|
185
|
+
end
|
186
|
+
|
187
|
+
describe '.default_config' do
|
188
|
+
it 'should merge in the default accept and reject patterns' do
|
189
|
+
expected = {
|
190
|
+
'enabled' => true,
|
191
|
+
'exclude' => [],
|
192
|
+
'reject' => [/^.$/, /[0-9]$/, /[A-Z]/],
|
193
|
+
'accept' => [/^_$/]
|
194
|
+
}
|
185
195
|
|
186
|
-
|
196
|
+
expect(described_class.default_config).to eq(expected)
|
197
|
+
end
|
198
|
+
end
|
187
199
|
|
188
|
-
|
189
|
-
|
200
|
+
describe '.contexts' do
|
201
|
+
it 'are scoped to classes, modules, instance and singleton methods' do
|
202
|
+
expect(described_class.contexts).to eq([:module, :class, :def, :defs])
|
190
203
|
end
|
191
204
|
end
|
192
205
|
end
|
@@ -1,79 +1,103 @@
|
|
1
1
|
require_relative '../../spec_helper'
|
2
2
|
require_lib 'reek/smells/unused_parameters'
|
3
|
-
require_relative 'smell_detector_shared'
|
4
3
|
|
5
4
|
RSpec.describe Reek::Smells::UnusedParameters do
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
it 'reports the right values' do
|
6
|
+
src = <<-EOS
|
7
|
+
def alfa(bravo)
|
8
|
+
end
|
9
|
+
EOS
|
10
|
+
|
11
|
+
expect(src).to reek_of(:UnusedParameters,
|
12
|
+
lines: [1],
|
13
|
+
context: 'alfa',
|
14
|
+
message: "has unused parameter 'bravo'",
|
15
|
+
source: 'string',
|
16
|
+
name: 'bravo')
|
17
|
+
end
|
10
18
|
|
11
|
-
|
12
|
-
|
13
|
-
|
19
|
+
it 'does count all occurences' do
|
20
|
+
src = <<-EOS
|
21
|
+
def alfa(bravo, charlie)
|
22
|
+
end
|
23
|
+
EOS
|
24
|
+
|
25
|
+
expect(src).to reek_of(:UnusedParameters,
|
26
|
+
lines: [1],
|
27
|
+
name: 'bravo')
|
28
|
+
expect(src).to reek_of(:UnusedParameters,
|
29
|
+
lines: [1],
|
30
|
+
name: 'charlie')
|
31
|
+
end
|
14
32
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
expect(src).to reek_of(:UnusedParameters, name: 'denum')
|
19
|
-
end
|
33
|
+
it 'reports nothing for no parameters' do
|
34
|
+
expect('def alfa; end').not_to reek_of(:UnusedParameters)
|
35
|
+
end
|
20
36
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
name: 'quotient')
|
25
|
-
end
|
37
|
+
it 'reports nothing for used parameter' do
|
38
|
+
expect('def alfa(bravo); bravo; end').not_to reek_of(:UnusedParameters)
|
39
|
+
end
|
26
40
|
|
27
|
-
|
28
|
-
|
29
|
-
end
|
41
|
+
it 'reports for 1 used and 2 unused parameter' do
|
42
|
+
src = 'def alfa(bravo, charlie, delta); bravo end'
|
30
43
|
|
31
|
-
|
32
|
-
|
33
|
-
|
44
|
+
expect(src).not_to reek_of(:UnusedParameters, name: 'bravo')
|
45
|
+
expect(src).to reek_of(:UnusedParameters, name: 'charlie')
|
46
|
+
expect(src).to reek_of(:UnusedParameters, name: 'delta')
|
47
|
+
end
|
34
48
|
|
35
|
-
|
36
|
-
|
37
|
-
|
49
|
+
it 'reports nothing for named parameters prefixed with _' do
|
50
|
+
expect('def alfa(_bravo); end').not_to reek_of(:UnusedParameters)
|
51
|
+
end
|
38
52
|
|
39
|
-
|
40
|
-
|
53
|
+
it 'reports nothing when using a parameter via self assignment' do
|
54
|
+
expect('def alfa(bravo); bravo += 1; end').not_to reek_of(:UnusedParameters)
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'reports nothing when using a parameter on a rescue' do
|
58
|
+
expect('def alfa(bravo = 3); puts "nothing"; rescue; retry if bravo -= 1 > 0; raise; end').
|
59
|
+
not_to reek_of(:UnusedParameters)
|
60
|
+
end
|
61
|
+
|
62
|
+
context 'using super' do
|
63
|
+
it 'reports nothing with implicit arguments' do
|
64
|
+
expect('def alfa(*bravo); super; end').not_to reek_of(:UnusedParameters)
|
41
65
|
end
|
42
66
|
|
43
|
-
it 'reports
|
44
|
-
expect('def
|
67
|
+
it 'reports something when explicitely passing no arguments' do
|
68
|
+
expect('def alfa(*bravo); super(); end').to reek_of(:UnusedParameters)
|
45
69
|
end
|
46
70
|
|
47
|
-
it 'reports
|
48
|
-
expect('def
|
71
|
+
it 'reports nothing when explicitely passing all arguments' do
|
72
|
+
expect('def alfa(*bravo); super(*bravo); end').not_to reek_of(:UnusedParameters)
|
49
73
|
end
|
50
74
|
|
51
|
-
it 'reports nothing
|
52
|
-
expect('def
|
75
|
+
it 'reports nothing in a nested context' do
|
76
|
+
expect('def alfa(*bravo); charlie(super); end').not_to reek_of(:UnusedParameters)
|
53
77
|
end
|
78
|
+
end
|
54
79
|
|
55
|
-
|
56
|
-
|
57
|
-
|
80
|
+
context 'anonymous parameters' do
|
81
|
+
it 'reports nothing for unused anonymous parameter' do
|
82
|
+
expect('def alfa(_); end').not_to reek_of(:UnusedParameters)
|
58
83
|
end
|
59
84
|
|
60
|
-
it 'reports
|
61
|
-
expect('def
|
62
|
-
to reek_of(:UnusedParameters)
|
85
|
+
it 'reports nothing for unused anonymous splatted parameter' do
|
86
|
+
expect('def alfa(*); end').not_to reek_of(:UnusedParameters)
|
63
87
|
end
|
88
|
+
end
|
64
89
|
|
65
|
-
|
66
|
-
|
67
|
-
|
90
|
+
context 'splatted parameters' do
|
91
|
+
it 'reports nothing for used splatted parameter' do
|
92
|
+
expect('def alfa(*bravo); bravo; end').not_to reek_of(:UnusedParameters)
|
68
93
|
end
|
69
94
|
|
70
|
-
it 'reports
|
71
|
-
expect('def
|
95
|
+
it 'reports something when not using a keyword argument with splat' do
|
96
|
+
expect('def alfa(**bravo); end').to reek_of(:UnusedParameters)
|
72
97
|
end
|
73
98
|
|
74
|
-
it 'reports nothing when using a
|
75
|
-
expect('def
|
76
|
-
not_to reek_of(:UnusedParameters)
|
99
|
+
it 'reports nothing when using a keyword argument with splat' do
|
100
|
+
expect('def alfa(**bravo); bravo; end').not_to reek_of(:UnusedParameters)
|
77
101
|
end
|
78
102
|
end
|
79
103
|
end
|