reek 4.4.0 → 4.4.1
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 +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
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6f4239287ce5d453034915801d47bd07738e0a09
|
|
4
|
+
data.tar.gz: 717f8ac8b8a9e0093a4aaa2ee9c5f739fd27be57
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ccbb4be4cf7bb2d47ce72f5fd7d709ca3b3b4e49b95253aa549a14d62a7468a176c9b10cb1d21da9667963791c3f8eca66137e0f2dd03bd5507e65c94deb6953
|
|
7
|
+
data.tar.gz: 90eb9358f3f66271fa0a568e4582f9d473911723730a30e1b9de7771e5f79381832be59c3d511ddae81c614d772d67a6e49a07ddece6de756f482663976ee5ea
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Change log
|
|
2
2
|
|
|
3
|
+
## 4.4.1 (2016-09-13)
|
|
4
|
+
|
|
5
|
+
* (troessner) Quote names in smell detector messages
|
|
6
|
+
* (troessner) Make our CodeComment regex more lenient
|
|
7
|
+
* (troessner) Fix UncommunicativeVariableName does not take regex configuration into account
|
|
8
|
+
|
|
3
9
|
## 4.4.0 (2016-08-24)
|
|
4
10
|
|
|
5
11
|
* (waldyr) Add ignored nodes parameter to local_nodes
|
data/CONTRIBUTING.md
CHANGED
|
@@ -27,7 +27,9 @@ version, Ruby platform (MRI, JRuby, etc.), operating system.
|
|
|
27
27
|
Try to provide a minimal example that reproduces the issue.
|
|
28
28
|
Extra kudos if you can write it as a failing test. :)
|
|
29
29
|
|
|
30
|
-
##
|
|
30
|
+
## Contribute features, bugfixes, documentation
|
|
31
|
+
|
|
32
|
+
### Getting started
|
|
31
33
|
|
|
32
34
|
Fork Reek, then clone it, make sure you have
|
|
33
35
|
[Bundler](http://bundler.io) installed, install dependencies
|
|
@@ -47,17 +49,52 @@ Once you’re sure your copy of Reek works create your own feature branch from o
|
|
|
47
49
|
git checkout -b your_feature_or_fix_name
|
|
48
50
|
```
|
|
49
51
|
|
|
50
|
-
Make sure you have read our [style guide](docs/
|
|
52
|
+
Make sure you have read our [style guide](docs/Style-Guide.md) before you
|
|
51
53
|
start contributing.
|
|
52
54
|
|
|
53
55
|
Then start hacking and add new tests which make sure that your new feature works or
|
|
54
56
|
demonstrate that your fix was needed.
|
|
57
|
+
|
|
58
|
+
### Tests
|
|
59
|
+
|
|
55
60
|
Reek is using [Rspec](http://rspec.info/) for unit and functional testing and [cucumber]() for integration tests.
|
|
56
61
|
|
|
57
62
|
When it comes to Rspec we're trying to follow [betterspecs](http://betterspecs.org/).
|
|
58
|
-
|
|
63
|
+
We're not using Rspec's [shared examples](https://www.relishapp.com/rspec/rspec-core/docs/example-groups/shared-examples) because we find
|
|
64
|
+
them rather harming than helpful.
|
|
65
|
+
You can find an excellent cheat sheet on how to write idiomatic Rspec [here](http://www.rubypigeon.com/posts/rspec-core-cheat-sheet).
|
|
66
|
+
|
|
67
|
+
**Spec naming conventions**
|
|
68
|
+
|
|
69
|
+
We do not use the popular "foo" / "bar" naming when it comes to the question "how to come up with good example names?".
|
|
70
|
+
Instead, we use the [military alphabet](https://en.wikipedia.org/wiki/NATO_phonetic_alphabet) in ascending order
|
|
71
|
+
which means that we would write this
|
|
72
|
+
|
|
73
|
+
```Ruby
|
|
74
|
+
class Foo
|
|
75
|
+
def bar(baz)
|
|
76
|
+
baz.quux
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
rather like this:
|
|
82
|
+
|
|
83
|
+
```Ruby
|
|
84
|
+
class Alfa
|
|
85
|
+
def bravo(charlie)
|
|
86
|
+
charlie.delta
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### How to write new smell detectors
|
|
92
|
+
|
|
93
|
+
Please see [our separate guide](docs/How-To-Write-New-Detectors.md) for this.
|
|
94
|
+
|
|
95
|
+
### Finishing up
|
|
59
96
|
|
|
60
|
-
We
|
|
97
|
+
We care a lot about [good commit messages](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
|
|
61
98
|
|
|
62
99
|
Once you’re happy with your feature / fix – or want to
|
|
63
100
|
share it as a work-in-progress and request comments – once
|
data/README.md
CHANGED
|
@@ -210,15 +210,27 @@ Reek currently includes checks for some aspects of
|
|
|
210
210
|
and more. See the [Code Smells](docs/Code-Smells.md)
|
|
211
211
|
for up to date details of exactly what Reek will check in your code.
|
|
212
212
|
|
|
213
|
-
|
|
213
|
+
**Special configuration for controversial detectors:**
|
|
214
|
+
|
|
215
|
+
[Unused Private Method](docs/Unused-Private-Method.md) is disabled by default
|
|
214
216
|
because it is [kind of controversial](https://github.com/troessner/reek/issues/844) which means
|
|
215
|
-
you have to explicitly activate in your configuration via
|
|
217
|
+
you have to explicitly activate it in your configuration via
|
|
216
218
|
|
|
217
219
|
```Yaml
|
|
218
220
|
UnusedPrivateMethod:
|
|
219
221
|
enabled: true
|
|
220
222
|
```
|
|
221
223
|
|
|
224
|
+
[Utility Function](docs/Utility-Function.md) is a [controversial detector](https://github.com/troessner/reek/issues/681)
|
|
225
|
+
as well that can turn out to be really unforgiving.
|
|
226
|
+
As a consequence, we made it possible to disable it for non-public methods like this:
|
|
227
|
+
|
|
228
|
+
```Yaml
|
|
229
|
+
---
|
|
230
|
+
UtilityFunction:
|
|
231
|
+
public_methods_only: true
|
|
232
|
+
```
|
|
233
|
+
|
|
222
234
|
## Configuration
|
|
223
235
|
|
|
224
236
|
### Command-line interface
|
|
@@ -356,7 +368,7 @@ end
|
|
|
356
368
|
You can even pass in smell specific configuration settings:
|
|
357
369
|
|
|
358
370
|
```Ruby
|
|
359
|
-
# :reek:NestedIterators
|
|
371
|
+
# :reek:NestedIterators { max_allowed_nesting: 2 }
|
|
360
372
|
def smelly_method foo
|
|
361
373
|
foo.each {|bar| bar.each {|baz| baz.qux}}
|
|
362
374
|
end
|
data/defaults.reek
CHANGED
data/docs/Basic-Smell-Options.md
CHANGED
|
@@ -19,7 +19,7 @@ exclusions for each smell.
|
|
|
19
19
|
To stop Reek reporting smells in any method called `write` you might create a configuration file containing this:
|
|
20
20
|
|
|
21
21
|
```yaml
|
|
22
|
-
|
|
22
|
+
DuplicateMethodCall:
|
|
23
23
|
exclude:
|
|
24
24
|
- write
|
|
25
25
|
```
|
|
@@ -27,7 +27,7 @@ ControlCouple:
|
|
|
27
27
|
Or a little more sophisticated using a Ruby regex like this:
|
|
28
28
|
|
|
29
29
|
```yaml
|
|
30
|
-
|
|
30
|
+
DuplicateMethodCall:
|
|
31
31
|
exclude:
|
|
32
32
|
- !ruby/regexp /write/
|
|
33
33
|
```
|
data/docs/Code-Smells.md
CHANGED
|
@@ -11,8 +11,10 @@ Reek currently includes checks for the following smells:
|
|
|
11
11
|
* [Control Parameter](Control-Parameter.md)
|
|
12
12
|
* [Data Clump](Data-Clump.md)
|
|
13
13
|
* [Duplicate Method Call](Duplicate-Method-Call.md)
|
|
14
|
+
* [Instance Variable Assumption](Instance-Variable-Assumption.md)
|
|
14
15
|
* [Irresponsible Module](Irresponsible-Module.md)
|
|
15
16
|
* [Large Class](Large-Class.md), including
|
|
17
|
+
* [Too Many Constants](Too-Many-Constants.md)
|
|
16
18
|
* [Too Many Instance Variables](Too-Many-Instance-Variables.md)
|
|
17
19
|
* [Too Many Methods](Too-Many-Methods.md)
|
|
18
20
|
* [Long Parameter List](Long-Parameter-List.md), and its special case [Long Yield List](Long-Yield-List.md)
|
|
@@ -23,8 +25,10 @@ Reek currently includes checks for the following smells:
|
|
|
23
25
|
* [Nested Iterators](Nested-Iterators.md)
|
|
24
26
|
* [Prima-Donna-Method](Prima-Donna-Method.md)
|
|
25
27
|
* [Simulated Polymorphism](Simulated-Polymorphism.md), including
|
|
28
|
+
* [Manual Dispatch](Manual-Dispatch.md)
|
|
26
29
|
* [Nil Check](Nil-Check.md)
|
|
27
30
|
* [Repeated Conditional](Repeated-Conditional.md)
|
|
31
|
+
* [Subclassed From Core Class](Subclassed-From-Core-Class.md)
|
|
28
32
|
* [Too Many Statements](Too-Many-Statements.md)
|
|
29
33
|
* [Uncommunicative Name](Uncommunicative-Name.md), including
|
|
30
34
|
* [Uncommunicative Method Name](Uncommunicative-Method-Name.md)
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
## How to write new detectors
|
|
2
|
+
|
|
3
|
+
### Outline what you have in mind
|
|
4
|
+
|
|
5
|
+
Before starting to code you should discuss the overall idea for your new smell detector with
|
|
6
|
+
us in a corresponding github issue.
|
|
7
|
+
We all should have a solid understanding of what this detector actually reports, the edgecases
|
|
8
|
+
it covers and the overall rationale behind it.
|
|
9
|
+
|
|
10
|
+
### Structure
|
|
11
|
+
|
|
12
|
+
All smell detectors reside in `lib/reek/smells` and have the following base structure:
|
|
13
|
+
|
|
14
|
+
```Ruby
|
|
15
|
+
require_relative 'smell_detector'
|
|
16
|
+
require_relative 'smell_warning'
|
|
17
|
+
|
|
18
|
+
module Reek
|
|
19
|
+
module Smells
|
|
20
|
+
#
|
|
21
|
+
# Here goes your introduction for this detector.
|
|
22
|
+
#
|
|
23
|
+
# See {file:docs/Your-Detector.md} for details.
|
|
24
|
+
class YourDetector < SmellDetector
|
|
25
|
+
def self.contexts
|
|
26
|
+
[:class] # In case you're operating on class contexts only - just an example.
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
#
|
|
30
|
+
# Here you should document what you expect "ctx" to look like.
|
|
31
|
+
#
|
|
32
|
+
# @return [Array<SmellWarning>]
|
|
33
|
+
#
|
|
34
|
+
def sniff(ctx)
|
|
35
|
+
# "found_smells" below is just an abstraction for
|
|
36
|
+
# "find the smells in question" and iteratore over them.
|
|
37
|
+
# This can just be a method but it can also be a more sophisticated set up.
|
|
38
|
+
# Check out other smell detectors to get a feeling for what to do here.
|
|
39
|
+
found_smells(ctx).map do |smell|
|
|
40
|
+
# "smell_warning" is defined in SmellDetector and should be used by you
|
|
41
|
+
# to construct smell warnings
|
|
42
|
+
smell_warning(
|
|
43
|
+
context: ctx,
|
|
44
|
+
lines: [], # lines on which the smell was detected
|
|
45
|
+
message: "...", # the message that is printed on STDOUT
|
|
46
|
+
# whatever you interpolate into the "message" should go into
|
|
47
|
+
# parameters below - if you do not interpolate anything you
|
|
48
|
+
# can omit this
|
|
49
|
+
parameters: { })
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
# Here goes everything you need for finding smells.
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Documentation
|
|
63
|
+
|
|
64
|
+
* Above every `SmellDetector::sniff` method it should be documented what the expected AST is
|
|
65
|
+
* Every detector should have a separate documentation page in /docs. You can
|
|
66
|
+
take any arbitrary existing smell detector documentation page as template (since
|
|
67
|
+
they all have the same structure already)
|
|
68
|
+
* The detector should be listed under [Code Smells](docs/Code-Smells.md)
|
|
69
|
+
|
|
70
|
+
### Rspec examples
|
|
71
|
+
|
|
72
|
+
All smell detector specs start out with 2 generic examples like below - the second one
|
|
73
|
+
only if it makes sense.
|
|
74
|
+
Here's what it looks like for `UncommunicativeVariableName`:
|
|
75
|
+
|
|
76
|
+
```Ruby
|
|
77
|
+
it 'reports the right values' do
|
|
78
|
+
src = <<-EOS
|
|
79
|
+
def alfa
|
|
80
|
+
bravo = 5
|
|
81
|
+
end
|
|
82
|
+
EOS
|
|
83
|
+
|
|
84
|
+
expect(src).to reek_of(:UncommunicativeVariableName,
|
|
85
|
+
lines: [2],
|
|
86
|
+
context: 'alfa',
|
|
87
|
+
message: "has the variable name 'bravo'",
|
|
88
|
+
source: 'string',
|
|
89
|
+
name: 'bravo')
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it 'does count all occurences' do
|
|
93
|
+
src = <<-EOS
|
|
94
|
+
def alfa
|
|
95
|
+
bravo = 3
|
|
96
|
+
charlie = 7
|
|
97
|
+
end
|
|
98
|
+
EOS
|
|
99
|
+
|
|
100
|
+
expect(src).to reek_of(:UncommunicativeVariableName,
|
|
101
|
+
lines: [2],
|
|
102
|
+
name: 'bravo')
|
|
103
|
+
expect(src).to reek_of(:UncommunicativeVariableName,
|
|
104
|
+
lines: [3],
|
|
105
|
+
name: 'charlie')
|
|
106
|
+
end
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
The following examples should then cover the detector specific features.
|
|
110
|
+
|
|
111
|
+
### Cucumber features
|
|
112
|
+
|
|
113
|
+
We are trying to write as few Cucumber features as possible.
|
|
114
|
+
Normally, there should be no need to write a new feature for a new smell detector.
|
|
115
|
+
If you feel like this is necessary in this case, please discuss this with us via
|
|
116
|
+
github issue or in your work-in-progress pull request before doing anything.
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
| |
|
|
26
26
|
| |
|
|
27
27
|
ReekCommand (cli/reek_command) |
|
|
28
|
-
* uses a reporter (report/report)
|
|
28
|
+
* uses a reporter (report/report) |
|
|
29
29
|
* uses a SourceLocator (source/source_locator) |
|
|
30
30
|
/ | \ |
|
|
31
31
|
/ | \ |
|
|
@@ -41,9 +41,8 @@
|
|
|
41
41
|
* generates the AST out of the given source
|
|
42
42
|
* adorns the generated AST via a TreeDresser (core/tree_dresser)
|
|
43
43
|
* initializes a SmellRepository with all relevant smells (smells/smell_repository)
|
|
44
|
-
* initializes a WarningCollector (cli/warning_collector)
|
|
45
44
|
* builds a tree of Contexts using ContextBuilder
|
|
46
|
-
*
|
|
45
|
+
* tells the SmellRepository above to run each of its smell detectors above on each of the contexts
|
|
47
46
|
/ | \
|
|
48
47
|
/ | \
|
|
49
48
|
/ | \
|
|
@@ -51,7 +50,7 @@
|
|
|
51
50
|
\ | /
|
|
52
51
|
\ | /
|
|
53
52
|
\ | /
|
|
54
|
-
|
|
53
|
+
SmellRepository
|
|
55
54
|
|
|
|
56
55
|
|
|
|
57
56
|
|
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# Instance Variable Assumption
|
|
2
|
+
|
|
3
|
+
## Introduction
|
|
4
|
+
|
|
5
|
+
Classes should not assume that instance variables are set or present outside of the current class definition.
|
|
6
|
+
|
|
7
|
+
Good:
|
|
8
|
+
|
|
9
|
+
```Ruby
|
|
10
|
+
class Foo
|
|
11
|
+
def initialize
|
|
12
|
+
@bar = :foo
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def foo?
|
|
16
|
+
@bar == :foo
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Good as well:
|
|
22
|
+
|
|
23
|
+
```Ruby
|
|
24
|
+
class Foo
|
|
25
|
+
def foo?
|
|
26
|
+
bar == :foo
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def bar
|
|
30
|
+
@bar ||= :foo
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Bad:
|
|
36
|
+
|
|
37
|
+
```Ruby
|
|
38
|
+
class Foo
|
|
39
|
+
def go_foo!
|
|
40
|
+
@bar = :foo
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def foo?
|
|
44
|
+
@bar == :foo
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Example
|
|
50
|
+
|
|
51
|
+
Running Reek on:
|
|
52
|
+
|
|
53
|
+
```Ruby
|
|
54
|
+
class Dummy
|
|
55
|
+
def test
|
|
56
|
+
@ivar
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
would report:
|
|
62
|
+
|
|
63
|
+
```Bash
|
|
64
|
+
[1]:InstanceVariableAssumption: Dummy assumes too much for instance variable @ivar [https://github.com/troessner/reek/blob/master/docs/Instance-Variable-Assumption.md]
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Note that this example would trigger this smell warning as well:
|
|
68
|
+
|
|
69
|
+
```Ruby
|
|
70
|
+
class Parent
|
|
71
|
+
def initialize(omg)
|
|
72
|
+
@omg = omg
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
class Child < Parent
|
|
77
|
+
def foo
|
|
78
|
+
@omg
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
The way to address the smell warning is that you should create an `attr_reader` to use `@omg` in the subclass and not access `@omg` directly like this:
|
|
84
|
+
|
|
85
|
+
```Ruby
|
|
86
|
+
class Parent
|
|
87
|
+
attr_reader :omg
|
|
88
|
+
|
|
89
|
+
def initialize(omg)
|
|
90
|
+
@omg = omg
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
class Child < Parent
|
|
95
|
+
def foo
|
|
96
|
+
omg
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Directly accessing instance variables is considered a smell because it [breaks encapsulation](http://designisrefactoring.com/2015/03/29/organizing-data-self-encapsulation/) and makes it harder to reason about code.
|
|
102
|
+
|
|
103
|
+
If you don't want to expose those methods as public API just make them private like this:
|
|
104
|
+
|
|
105
|
+
```Ruby
|
|
106
|
+
class Parent
|
|
107
|
+
def initialize(omg)
|
|
108
|
+
@omg = omg
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
private
|
|
112
|
+
attr_reader :omg
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
class Child < Parent
|
|
116
|
+
def foo
|
|
117
|
+
omg
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
## Current Support in Reek
|
|
124
|
+
|
|
125
|
+
An instance variable must:
|
|
126
|
+
|
|
127
|
+
* be set in the constructor
|
|
128
|
+
* or be accessed through a method with lazy initialization / memoization.
|
|
129
|
+
|
|
130
|
+
If not, _Instance Variable Assumption_ will be reported.
|
|
131
|
+
|
|
132
|
+
## Configuration
|
|
133
|
+
|
|
134
|
+
_Instance Variable Assumption_ supports the [Basic Smell Options](Basic-Smell-Options.md).
|