reek 4.3.0 → 4.4.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/CONTRIBUTING.md +3 -0
- data/README.md +2 -0
- data/defaults.reek +3 -0
- data/features/configuration_files/directory_specific_directives.feature +11 -6
- data/features/samples.feature +14 -4
- data/lib/reek/context/code_context.rb +3 -2
- data/lib/reek/smells.rb +1 -0
- data/lib/reek/smells/instance_variable_assumption.rb +71 -0
- data/lib/reek/smells/too_many_instance_variables.rb +2 -1
- data/lib/reek/version.rb +1 -1
- data/spec/reek/smells/instance_variable_assumption_spec.rb +195 -0
- data/spec/reek/smells/too_many_instance_variables_spec.rb +100 -43
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9e0d256e7194e6839716a3817b6fe951985f4fc8
|
4
|
+
data.tar.gz: ec2e207fe63cd0c8cd5b48071e660bd83ccb1cc6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6a2f747bdbded9c2610d934c23b07a72b001a93a9a9ed99d20b9e2bdea7c6ed5e7e667c8e05713b1e77e148294fb8e4cd34d606e197829744491db395a0c964b
|
7
|
+
data.tar.gz: 16d71aee67557e3f4d78cba1d45c8452032ccf76148c57b0c50650d0bff4f8fbcb4ecc9020df33a88746a80cce65235231e5b9a4f610e187a47a43baba27b1bf
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# Change log
|
2
2
|
|
3
|
+
## 4.4.0 (2016-08-24)
|
4
|
+
|
5
|
+
* (waldyr) Add ignored nodes parameter to local_nodes
|
6
|
+
* (waldyr) Add Instance Variable Assumption smell detector
|
7
|
+
* (waldyr) Remove memoized instance variables from accounting of TooManyInstanceVariables smell
|
8
|
+
|
3
9
|
## 4.3.0 (2016-08-23)
|
4
10
|
|
5
11
|
* (backus) Add ManualDispatch smell.
|
data/CONTRIBUTING.md
CHANGED
@@ -105,6 +105,9 @@ git rebase -i master
|
|
105
105
|
# squash squash squash
|
106
106
|
git push -f origin
|
107
107
|
```
|
108
|
+
## Failing Cucumber Scenarios
|
109
|
+
|
110
|
+
If there is a failing scenario and you can not figure out why it is failing, just run the failing scenario: `bundle exec cucumber features/failing_scenario.feature:line`. By doing so Aruba will leave its set up in the `tmp/aruba` directory. You can then `cd` into this directory and run Reek the same way the cucumber scenario actually ran it. This way you can debug scenario failures that can be very opaque sometimes.
|
108
111
|
|
109
112
|
## Versioning policy
|
110
113
|
|
data/README.md
CHANGED
data/defaults.reek
CHANGED
@@ -49,10 +49,12 @@ Feature: Directory directives
|
|
49
49
|
When I run `reek -c web_app/config.reek web_app/`
|
50
50
|
Then it reports:
|
51
51
|
"""
|
52
|
+
web_app/app/controllers/users_controller.rb -- 1 warning:
|
53
|
+
[1]:InstanceVariableAssumption: UsersController assumes too much for instance variable @user [https://github.com/troessner/reek/blob/master/docs/Instance-Variable-Assumption.md]
|
52
54
|
web_app/app/models/user.rb -- 2 warnings:
|
53
55
|
[1]:IrresponsibleModule: User has no descriptive comment [https://github.com/troessner/reek/blob/master/docs/Irresponsible-Module.md]
|
54
56
|
[2]:UnusedParameters: User#logged_in_with_role has unused parameter 'r' [https://github.com/troessner/reek/blob/master/docs/Unused-Parameters.md]
|
55
|
-
|
57
|
+
3 total warnings
|
56
58
|
"""
|
57
59
|
|
58
60
|
Scenario: Ignore trailing slashes
|
@@ -118,12 +120,13 @@ Feature: Directory directives
|
|
118
120
|
When I run `reek -c web_app/config.reek web_app/`
|
119
121
|
Then it reports:
|
120
122
|
"""
|
121
|
-
web_app/app/controllers/users_controller.rb --
|
123
|
+
web_app/app/controllers/users_controller.rb -- 3 warnings:
|
124
|
+
[1]:InstanceVariableAssumption: UsersController assumes too much for instance variable @user [https://github.com/troessner/reek/blob/master/docs/Instance-Variable-Assumption.md]
|
122
125
|
[1]:IrresponsibleModule: UsersController has no descriptive comment [https://github.com/troessner/reek/blob/master/docs/Irresponsible-Module.md]
|
123
126
|
[4]:NestedIterators: UsersController#show contains iterators nested 2 deep [https://github.com/troessner/reek/blob/master/docs/Nested-Iterators.md]
|
124
127
|
web_app/app/models/user.rb -- 1 warning:
|
125
128
|
[2]:UnusedParameters: User#logged_in_with_role has unused parameter 'r' [https://github.com/troessner/reek/blob/master/docs/Unused-Parameters.md]
|
126
|
-
|
129
|
+
4 total warnings
|
127
130
|
"""
|
128
131
|
|
129
132
|
Scenario: Use the default directive if there is no directory directive
|
@@ -163,11 +166,13 @@ Feature: Directory directives
|
|
163
166
|
When I run `reek -c config.reek other/ web_app/`
|
164
167
|
Then it reports:
|
165
168
|
"""
|
166
|
-
other/projects_controller.rb --
|
169
|
+
other/projects_controller.rb -- 2 warnings:
|
170
|
+
[1]:InstanceVariableAssumption: ProjectController assumes too much for instance variable @project [https://github.com/troessner/reek/blob/master/docs/Instance-Variable-Assumption.md]
|
167
171
|
[4]:NestedIterators: ProjectController#show contains iterators nested 2 deep [https://github.com/troessner/reek/blob/master/docs/Nested-Iterators.md]
|
168
|
-
web_app/app/controllers/users_controller.rb --
|
172
|
+
web_app/app/controllers/users_controller.rb -- 2 warnings:
|
173
|
+
[1]:InstanceVariableAssumption: UsersController assumes too much for instance variable @user [https://github.com/troessner/reek/blob/master/docs/Instance-Variable-Assumption.md]
|
169
174
|
[1]:IrresponsibleModule: UsersController has no descriptive comment [https://github.com/troessner/reek/blob/master/docs/Irresponsible-Module.md]
|
170
|
-
|
175
|
+
4 total warnings
|
171
176
|
"""
|
172
177
|
|
173
178
|
Scenario: Abort on non-existent smell type in directory directive
|
data/features/samples.feature
CHANGED
@@ -11,7 +11,7 @@ Feature: Basic smell detection
|
|
11
11
|
Then the exit status indicates smells
|
12
12
|
And it reports:
|
13
13
|
"""
|
14
|
-
inline.rb --
|
14
|
+
inline.rb -- 51 warnings:
|
15
15
|
BooleanParameter: Inline::C#parse_signature has boolean parameter 'raw' [https://github.com/troessner/reek/blob/master/docs/Boolean-Parameter.md]
|
16
16
|
ClassVariable: Inline declares the class variable @@directory [https://github.com/troessner/reek/blob/master/docs/Class-Variable.md]
|
17
17
|
ClassVariable: Inline declares the class variable @@rootdir [https://github.com/troessner/reek/blob/master/docs/Class-Variable.md]
|
@@ -32,6 +32,9 @@ Feature: Basic smell detection
|
|
32
32
|
DuplicateMethodCall: Inline::C#initialize calls stack.empty? 2 times [https://github.com/troessner/reek/blob/master/docs/Duplicate-Method-Call.md]
|
33
33
|
DuplicateMethodCall: Module#inline calls Inline.const_get(lang) 2 times [https://github.com/troessner/reek/blob/master/docs/Duplicate-Method-Call.md]
|
34
34
|
DuplicateMethodCall: Module#inline calls options[:testing] 2 times [https://github.com/troessner/reek/blob/master/docs/Duplicate-Method-Call.md]
|
35
|
+
InstanceVariableAssumption: Inline::C assumes too much for instance variable @module_name [https://github.com/troessner/reek/blob/master/docs/Instance-Variable-Assumption.md]
|
36
|
+
InstanceVariableAssumption: Inline::C assumes too much for instance variable @so_name [https://github.com/troessner/reek/blob/master/docs/Instance-Variable-Assumption.md]
|
37
|
+
InstanceVariableAssumption: Inline::C assumes too much for instance variable @types [https://github.com/troessner/reek/blob/master/docs/Instance-Variable-Assumption.md]
|
35
38
|
IrresponsibleModule: CompilationError has no descriptive comment [https://github.com/troessner/reek/blob/master/docs/Irresponsible-Module.md]
|
36
39
|
IrresponsibleModule: Dir has no descriptive comment [https://github.com/troessner/reek/blob/master/docs/Irresponsible-Module.md]
|
37
40
|
IrresponsibleModule: File has no descriptive comment [https://github.com/troessner/reek/blob/master/docs/Irresponsible-Module.md]
|
@@ -60,7 +63,7 @@ Feature: Basic smell detection
|
|
60
63
|
UncommunicativeVariableName: Inline::C#module_name has the variable name 'x' [https://github.com/troessner/reek/blob/master/docs/Uncommunicative-Variable-Name.md]
|
61
64
|
UncommunicativeVariableName: Inline::C#parse_signature has the variable name 'x' [https://github.com/troessner/reek/blob/master/docs/Uncommunicative-Variable-Name.md]
|
62
65
|
UtilityFunction: Inline::C#strip_comments doesn't depend on instance state (maybe move it to another class?) [https://github.com/troessner/reek/blob/master/docs/Utility-Function.md]
|
63
|
-
optparse.rb --
|
66
|
+
optparse.rb -- 126 warnings:
|
64
67
|
Attribute: OptionParser#banner is a writable attribute [https://github.com/troessner/reek/blob/master/docs/Attribute.md]
|
65
68
|
Attribute: OptionParser#default_argv is a writable attribute [https://github.com/troessner/reek/blob/master/docs/Attribute.md]
|
66
69
|
Attribute: OptionParser#program_name is a writable attribute [https://github.com/troessner/reek/blob/master/docs/Attribute.md]
|
@@ -115,6 +118,8 @@ Feature: Basic smell detection
|
|
115
118
|
FeatureEnvy: OptionParser::List#accept refers to pat more than self (maybe move it to another class?) [https://github.com/troessner/reek/blob/master/docs/Feature-Envy.md]
|
116
119
|
FeatureEnvy: OptionParser::List#add_banner refers to opt more than self (maybe move it to another class?) [https://github.com/troessner/reek/blob/master/docs/Feature-Envy.md]
|
117
120
|
FeatureEnvy: OptionParser::List#summarize refers to opt more than self (maybe move it to another class?) [https://github.com/troessner/reek/blob/master/docs/Feature-Envy.md]
|
121
|
+
InstanceVariableAssumption: OptionParser assumes too much for instance variable @release [https://github.com/troessner/reek/blob/master/docs/Instance-Variable-Assumption.md]
|
122
|
+
InstanceVariableAssumption: OptionParser assumes too much for instance variable @version [https://github.com/troessner/reek/blob/master/docs/Instance-Variable-Assumption.md]
|
118
123
|
LongParameterList: OptionParser#complete has 4 parameters [https://github.com/troessner/reek/blob/master/docs/Long-Parameter-List.md]
|
119
124
|
LongParameterList: OptionParser#summarize has 4 parameters [https://github.com/troessner/reek/blob/master/docs/Long-Parameter-List.md]
|
120
125
|
LongParameterList: OptionParser::List#complete has 4 parameters [https://github.com/troessner/reek/blob/master/docs/Long-Parameter-List.md]
|
@@ -185,7 +190,7 @@ Feature: Basic smell detection
|
|
185
190
|
UnusedParameters: OptionParser::Completion#convert has unused parameter 'opt' [https://github.com/troessner/reek/blob/master/docs/Unused-Parameters.md]
|
186
191
|
UnusedParameters: OptionParser::Switch::NoArgument#parse has unused parameter 'argv' [https://github.com/troessner/reek/blob/master/docs/Unused-Parameters.md]
|
187
192
|
UnusedParameters: OptionParser::Switch::OptionalArgument#parse has unused parameter 'argv' [https://github.com/troessner/reek/blob/master/docs/Unused-Parameters.md]
|
188
|
-
redcloth.rb --
|
193
|
+
redcloth.rb -- 110 warnings:
|
189
194
|
Attribute: RedCloth#filter_html is a writable attribute [https://github.com/troessner/reek/blob/master/docs/Attribute.md]
|
190
195
|
Attribute: RedCloth#filter_styles is a writable attribute [https://github.com/troessner/reek/blob/master/docs/Attribute.md]
|
191
196
|
Attribute: RedCloth#hard_breaks is a writable attribute [https://github.com/troessner/reek/blob/master/docs/Attribute.md]
|
@@ -220,6 +225,11 @@ Feature: Basic smell detection
|
|
220
225
|
FeatureEnvy: RedCloth#blocks refers to blk more than self (maybe move it to another class?) [https://github.com/troessner/reek/blob/master/docs/Feature-Envy.md]
|
221
226
|
FeatureEnvy: RedCloth#clean_white_space refers to text more than self (maybe move it to another class?) [https://github.com/troessner/reek/blob/master/docs/Feature-Envy.md]
|
222
227
|
FeatureEnvy: RedCloth#pba refers to text more than self (maybe move it to another class?) [https://github.com/troessner/reek/blob/master/docs/Feature-Envy.md]
|
228
|
+
InstanceVariableAssumption: RedCloth assumes too much for instance variable @lite_mode [https://github.com/troessner/reek/blob/master/docs/Instance-Variable-Assumption.md]
|
229
|
+
InstanceVariableAssumption: RedCloth assumes too much for instance variable @pre_list [https://github.com/troessner/reek/blob/master/docs/Instance-Variable-Assumption.md]
|
230
|
+
InstanceVariableAssumption: RedCloth assumes too much for instance variable @rules [https://github.com/troessner/reek/blob/master/docs/Instance-Variable-Assumption.md]
|
231
|
+
InstanceVariableAssumption: RedCloth assumes too much for instance variable @shelf [https://github.com/troessner/reek/blob/master/docs/Instance-Variable-Assumption.md]
|
232
|
+
InstanceVariableAssumption: RedCloth assumes too much for instance variable @urlrefs [https://github.com/troessner/reek/blob/master/docs/Instance-Variable-Assumption.md]
|
223
233
|
LongParameterList: RedCloth#textile_bq has 4 parameters [https://github.com/troessner/reek/blob/master/docs/Long-Parameter-List.md]
|
224
234
|
LongParameterList: RedCloth#textile_fn_ has 5 parameters [https://github.com/troessner/reek/blob/master/docs/Long-Parameter-List.md]
|
225
235
|
LongParameterList: RedCloth#textile_p has 4 parameters [https://github.com/troessner/reek/blob/master/docs/Long-Parameter-List.md]
|
@@ -291,5 +301,5 @@ Feature: Basic smell detection
|
|
291
301
|
UtilityFunction: RedCloth#lT doesn't depend on instance state (maybe move it to another class?) [https://github.com/troessner/reek/blob/master/docs/Utility-Function.md]
|
292
302
|
UtilityFunction: RedCloth#no_textile doesn't depend on instance state (maybe move it to another class?) [https://github.com/troessner/reek/blob/master/docs/Utility-Function.md]
|
293
303
|
UtilityFunction: RedCloth#v_align doesn't depend on instance state (maybe move it to another class?) [https://github.com/troessner/reek/blob/master/docs/Utility-Function.md]
|
294
|
-
|
304
|
+
287 total warnings
|
295
305
|
"""
|
@@ -68,8 +68,9 @@ module Reek
|
|
68
68
|
# @param type [Symbol] the type of the nodes we are looking for, e.g. :defs.
|
69
69
|
# @yield block that is executed for every node.
|
70
70
|
#
|
71
|
-
def local_nodes(type, &blk)
|
72
|
-
|
71
|
+
def local_nodes(type, ignored = [], &blk)
|
72
|
+
ignored += [:casgn, :class, :module]
|
73
|
+
each_node(type, ignored, &blk)
|
73
74
|
end
|
74
75
|
|
75
76
|
# Iterate over `self` and child contexts.
|
data/lib/reek/smells.rb
CHANGED
@@ -7,6 +7,7 @@ require_relative 'smells/data_clump'
|
|
7
7
|
require_relative 'smells/duplicate_method_call'
|
8
8
|
require_relative 'smells/feature_envy'
|
9
9
|
require_relative 'smells/irresponsible_module'
|
10
|
+
require_relative 'smells/instance_variable_assumption'
|
10
11
|
require_relative 'smells/long_parameter_list'
|
11
12
|
require_relative 'smells/long_yield_list'
|
12
13
|
require_relative 'smells/manual_dispatch'
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative 'smell_detector'
|
3
|
+
require_relative 'smell_warning'
|
4
|
+
|
5
|
+
module Reek
|
6
|
+
module Smells
|
7
|
+
#
|
8
|
+
# The +InstanceVariableAssumption+ class is responsible for
|
9
|
+
# detecting directly access of instance variables in a class
|
10
|
+
# that does not define them in its initialize method.
|
11
|
+
#
|
12
|
+
class InstanceVariableAssumption < SmellDetector
|
13
|
+
def self.contexts
|
14
|
+
[:class]
|
15
|
+
end
|
16
|
+
|
17
|
+
# Checks +klass+ for instance
|
18
|
+
# variables assumptions.
|
19
|
+
#
|
20
|
+
# @return [Array<SmellWarning>]
|
21
|
+
#
|
22
|
+
def sniff(ctx)
|
23
|
+
method_expressions = ctx.node_instance_methods
|
24
|
+
|
25
|
+
assumptions = (variables_from_context(method_expressions) -
|
26
|
+
variables_from_initialize(method_expressions)).uniq
|
27
|
+
|
28
|
+
assumptions.map do |assumption|
|
29
|
+
build_smell_warning(ctx, assumption)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def build_smell_warning(ctx, assumption)
|
36
|
+
message = "assumes too much for instance variable #{assumption}"
|
37
|
+
|
38
|
+
smell_warning(
|
39
|
+
context: ctx,
|
40
|
+
lines: [ctx.exp.line],
|
41
|
+
message: message,
|
42
|
+
parameters: { assumption: assumption })
|
43
|
+
end
|
44
|
+
|
45
|
+
# :reek:UtilityFunction
|
46
|
+
def variables_from_initialize(instance_methods)
|
47
|
+
initialize_exp = instance_methods.detect do |method|
|
48
|
+
method.name == :initialize
|
49
|
+
end
|
50
|
+
|
51
|
+
return [] unless initialize_exp
|
52
|
+
|
53
|
+
initialize_exp.each_node(:ivasgn).map(&:name)
|
54
|
+
end
|
55
|
+
|
56
|
+
def variables_from_context(instance_methods)
|
57
|
+
instance_methods.map do |method|
|
58
|
+
method.find_nodes(assumption_nodes, ignored_nodes).map(&:name)
|
59
|
+
end.flatten
|
60
|
+
end
|
61
|
+
|
62
|
+
def assumption_nodes
|
63
|
+
[:ivar]
|
64
|
+
end
|
65
|
+
|
66
|
+
def ignored_nodes
|
67
|
+
[:or_asgn]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -35,7 +35,8 @@ module Reek
|
|
35
35
|
#
|
36
36
|
def sniff(ctx)
|
37
37
|
max_allowed_ivars = value(MAX_ALLOWED_IVARS_KEY, ctx)
|
38
|
-
|
38
|
+
variables = ctx.local_nodes(:ivasgn, [:or_asgn]).map(&:name)
|
39
|
+
count = variables.uniq.size
|
39
40
|
return [] if count <= max_allowed_ivars
|
40
41
|
[smell_warning(
|
41
42
|
context: ctx,
|
data/lib/reek/version.rb
CHANGED
@@ -0,0 +1,195 @@
|
|
1
|
+
require_relative '../../spec_helper'
|
2
|
+
|
3
|
+
require_lib 'reek/smells/instance_variable_assumption'
|
4
|
+
|
5
|
+
RSpec.describe Reek::Smells::InstanceVariableAssumption do
|
6
|
+
describe 'warning' do
|
7
|
+
context 'smell line' do
|
8
|
+
it 'should report the lines' do
|
9
|
+
src = <<-EOS
|
10
|
+
class Dummy
|
11
|
+
def test
|
12
|
+
@a
|
13
|
+
end
|
14
|
+
end
|
15
|
+
EOS
|
16
|
+
|
17
|
+
expect(src).to reek_of(:InstanceVariableAssumption, lines: [1])
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'smell parameters' do
|
22
|
+
it 'should report the lines' do
|
23
|
+
src = <<-EOS
|
24
|
+
class Dummy
|
25
|
+
def test
|
26
|
+
@a
|
27
|
+
end
|
28
|
+
end
|
29
|
+
EOS
|
30
|
+
|
31
|
+
expect(src).to reek_of(:InstanceVariableAssumption, assumption: :@a)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'smell context' do
|
36
|
+
it 'should report the context' do
|
37
|
+
src = <<-EOS
|
38
|
+
class Dummy
|
39
|
+
def test
|
40
|
+
@a
|
41
|
+
end
|
42
|
+
end
|
43
|
+
EOS
|
44
|
+
|
45
|
+
expect(src).to reek_of(:InstanceVariableAssumption, context: 'Dummy')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'smell message' do
|
50
|
+
it 'should report the ivars in the message' do
|
51
|
+
message_a = 'assumes too much for instance variable @a'
|
52
|
+
message_b = 'assumes too much for instance variable @b'
|
53
|
+
|
54
|
+
src = <<-EOS
|
55
|
+
class Dummy
|
56
|
+
def test
|
57
|
+
[@a, @b]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
EOS
|
61
|
+
|
62
|
+
expect(src).to reek_of(:InstanceVariableAssumption, message: message_a)
|
63
|
+
expect(src).to reek_of(:InstanceVariableAssumption, message: message_b)
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should report each ivar once' do
|
67
|
+
message_a = 'assumes too much for instance variable @a'
|
68
|
+
message_b = 'assumes too much for instance variable @b'
|
69
|
+
message_c = 'assumes too much for instance variable @c'
|
70
|
+
|
71
|
+
src = <<-EOS
|
72
|
+
class Dummy
|
73
|
+
def test
|
74
|
+
[@a, @a, @b, @c]
|
75
|
+
end
|
76
|
+
|
77
|
+
def retest
|
78
|
+
@c
|
79
|
+
end
|
80
|
+
end
|
81
|
+
EOS
|
82
|
+
|
83
|
+
expect(src).to reek_of(:InstanceVariableAssumption, message: message_a)
|
84
|
+
expect(src).to reek_of(:InstanceVariableAssumption, message: message_b)
|
85
|
+
expect(src).to reek_of(:InstanceVariableAssumption, message: message_c)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'should not report an empty class' do
|
91
|
+
src = <<-EOS
|
92
|
+
class Dummy
|
93
|
+
end
|
94
|
+
EOS
|
95
|
+
|
96
|
+
expect(src).not_to reek_of(:InstanceVariableAssumption)
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'should not report when lazy initializing' do
|
100
|
+
src = <<-EOS
|
101
|
+
class Dummy
|
102
|
+
def test
|
103
|
+
@a ||= 1
|
104
|
+
end
|
105
|
+
end
|
106
|
+
EOS
|
107
|
+
|
108
|
+
expect(src).not_to reek_of(:InstanceVariableAssumption)
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'should report when making instance variable assumption' do
|
112
|
+
src = <<-EOS
|
113
|
+
class Dummy
|
114
|
+
def test
|
115
|
+
@a
|
116
|
+
end
|
117
|
+
end
|
118
|
+
EOS
|
119
|
+
|
120
|
+
expect(src).to reek_of(:InstanceVariableAssumption)
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'reports variable even if others are initialized' do
|
124
|
+
src = <<-EOS
|
125
|
+
class Dummy
|
126
|
+
def initialize
|
127
|
+
@a = 1
|
128
|
+
end
|
129
|
+
|
130
|
+
def test
|
131
|
+
[@a, @b]
|
132
|
+
end
|
133
|
+
end
|
134
|
+
EOS
|
135
|
+
|
136
|
+
expect(src).to reek_of(:InstanceVariableAssumption)
|
137
|
+
end
|
138
|
+
|
139
|
+
context 'inner classes' do
|
140
|
+
it 'should report outter class' do
|
141
|
+
src = <<-EOS
|
142
|
+
class Dummy
|
143
|
+
def test
|
144
|
+
@a
|
145
|
+
end
|
146
|
+
|
147
|
+
class Dummiest
|
148
|
+
end
|
149
|
+
end
|
150
|
+
EOS
|
151
|
+
|
152
|
+
expect(src).to reek_of(:InstanceVariableAssumption, context: 'Dummy')
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'should report even if outer class initialize the variable' do
|
156
|
+
src = <<-EOS
|
157
|
+
class Dummy
|
158
|
+
def initialize
|
159
|
+
@a = 1
|
160
|
+
end
|
161
|
+
|
162
|
+
class Dummiest
|
163
|
+
def test
|
164
|
+
@a
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
EOS
|
169
|
+
|
170
|
+
expect(src).to reek_of(:InstanceVariableAssumption, context: 'Dummy::Dummiest')
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'should report inner classes' do
|
174
|
+
src = <<-EOS
|
175
|
+
class Dummy
|
176
|
+
def initialize
|
177
|
+
@a = 1
|
178
|
+
end
|
179
|
+
|
180
|
+
class Dummiest
|
181
|
+
def initialize
|
182
|
+
@b = 1
|
183
|
+
end
|
184
|
+
|
185
|
+
def test
|
186
|
+
@c
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
EOS
|
191
|
+
|
192
|
+
expect(src).to reek_of(:InstanceVariableAssumption, context: 'Dummy::Dummiest')
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
@@ -1,24 +1,24 @@
|
|
1
1
|
require_relative '../../spec_helper'
|
2
2
|
require_lib 'reek/smells/too_many_instance_variables'
|
3
|
-
require_relative 'smell_detector_shared'
|
4
3
|
|
5
4
|
RSpec.describe Reek::Smells::TooManyInstanceVariables do
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
end
|
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
|
13
|
+
end
|
14
|
+
EOS
|
17
15
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
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
|
22
22
|
end
|
23
23
|
|
24
24
|
context 'counting instance variables' do
|
@@ -26,73 +26,130 @@ RSpec.describe Reek::Smells::TooManyInstanceVariables do
|
|
26
26
|
src = <<-EOS
|
27
27
|
class Empty
|
28
28
|
def ivars
|
29
|
-
|
29
|
+
@a = @b = @c = @d = 1
|
30
30
|
end
|
31
31
|
end
|
32
32
|
EOS
|
33
|
-
expect(src).not_to reek_of(
|
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
|
44
|
+
end
|
45
|
+
EOS
|
46
|
+
expect(src).not_to reek_of(described_class)
|
34
47
|
end
|
35
48
|
|
36
49
|
it 'counts each ivar only once' do
|
37
50
|
src = <<-EOS
|
38
51
|
class Empty
|
39
52
|
def ivars
|
40
|
-
|
41
|
-
|
53
|
+
@a = @b = @c = @d = 1
|
54
|
+
@a = @b = @c = @d = 1
|
42
55
|
end
|
43
56
|
end
|
44
57
|
EOS
|
45
|
-
expect(src).not_to reek_of(
|
58
|
+
expect(src).not_to reek_of(described_class)
|
46
59
|
end
|
47
60
|
|
48
|
-
it 'should report
|
61
|
+
it 'should not report memoized ivars' do
|
49
62
|
src = <<-EOS
|
50
63
|
class Empty
|
51
64
|
def ivars
|
52
|
-
|
65
|
+
@a = @b = @c = @d = 1
|
66
|
+
@e ||= 1
|
53
67
|
end
|
54
68
|
end
|
55
69
|
EOS
|
56
|
-
expect(src).
|
70
|
+
expect(src).not_to reek_of(described_class)
|
57
71
|
end
|
58
72
|
|
59
|
-
it 'should not
|
73
|
+
it 'should not count ivars on inner classes altogether' do
|
60
74
|
src = <<-EOS
|
61
|
-
class
|
62
|
-
|
63
|
-
|
75
|
+
class Empty
|
76
|
+
class InnerA
|
77
|
+
def ivars
|
78
|
+
@a = @b = @c = @d = 1
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class InnerB
|
83
|
+
def ivars
|
84
|
+
@e = 1
|
85
|
+
end
|
64
86
|
end
|
65
87
|
end
|
88
|
+
EOS
|
89
|
+
expect(src).not_to reek_of(described_class)
|
90
|
+
end
|
66
91
|
|
67
|
-
|
68
|
-
|
69
|
-
|
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
|
+
|
101
|
+
module InnerB
|
102
|
+
def ivars
|
103
|
+
@e = 1
|
104
|
+
end
|
70
105
|
end
|
71
106
|
end
|
72
107
|
EOS
|
73
|
-
expect(src).not_to reek_of(
|
108
|
+
expect(src).not_to reek_of(described_class)
|
74
109
|
end
|
75
|
-
end
|
76
110
|
|
77
|
-
|
78
|
-
let(:warning) do
|
111
|
+
it 'reports excessive ivars' do
|
79
112
|
src = <<-EOS
|
80
|
-
# Comment
|
81
113
|
class Empty
|
82
114
|
def ivars
|
83
|
-
|
115
|
+
@a = @b = @c = @d = 1
|
116
|
+
@e = 1
|
117
|
+
end
|
118
|
+
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
|
+
|
130
|
+
def ivars_b
|
131
|
+
@e = 1
|
84
132
|
end
|
85
133
|
end
|
86
134
|
EOS
|
87
|
-
|
88
|
-
detector.sniff(ctx).first
|
135
|
+
expect(src).to reek_of(described_class)
|
89
136
|
end
|
90
137
|
|
91
|
-
|
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
|
144
|
+
end
|
92
145
|
|
93
|
-
|
94
|
-
|
95
|
-
|
146
|
+
class Full
|
147
|
+
def ivars_b
|
148
|
+
@a = @b = @c = @d = 1
|
149
|
+
end
|
150
|
+
end
|
151
|
+
EOS
|
152
|
+
expect(src).not_to reek_of(described_class)
|
96
153
|
end
|
97
154
|
end
|
98
155
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: reek
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kevin Rutherford
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2016-08-
|
14
|
+
date: 2016-08-24 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: codeclimate-engine-rb
|
@@ -236,6 +236,7 @@ files:
|
|
236
236
|
- lib/reek/smells/data_clump.rb
|
237
237
|
- lib/reek/smells/duplicate_method_call.rb
|
238
238
|
- lib/reek/smells/feature_envy.rb
|
239
|
+
- lib/reek/smells/instance_variable_assumption.rb
|
239
240
|
- lib/reek/smells/irresponsible_module.rb
|
240
241
|
- lib/reek/smells/long_parameter_list.rb
|
241
242
|
- lib/reek/smells/long_yield_list.rb
|
@@ -345,6 +346,7 @@ files:
|
|
345
346
|
- spec/reek/smells/data_clump_spec.rb
|
346
347
|
- spec/reek/smells/duplicate_method_call_spec.rb
|
347
348
|
- spec/reek/smells/feature_envy_spec.rb
|
349
|
+
- spec/reek/smells/instance_variable_assumption_spec.rb
|
348
350
|
- spec/reek/smells/irresponsible_module_spec.rb
|
349
351
|
- spec/reek/smells/long_parameter_list_spec.rb
|
350
352
|
- spec/reek/smells/long_yield_list_spec.rb
|
@@ -410,7 +412,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
410
412
|
version: '0'
|
411
413
|
requirements: []
|
412
414
|
rubyforge_project:
|
413
|
-
rubygems_version: 2.
|
415
|
+
rubygems_version: 2.6.4
|
414
416
|
signing_key:
|
415
417
|
specification_version: 4
|
416
418
|
summary: Code smell detector for Ruby
|