reek 2.1.0 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +2 -21
- data/.travis.yml +1 -0
- data/.yardopts +3 -6
- data/CHANGELOG +6 -0
- data/CONTRIBUTING.md +8 -3
- data/README.md +94 -42
- data/config/defaults.reek +0 -1
- data/docs/API.md +50 -0
- data/docs/Attribute.md +43 -0
- data/docs/Basic-Smell-Options.md +44 -0
- data/docs/Boolean-Parameter.md +52 -0
- data/docs/Class-Variable.md +40 -0
- data/docs/Code-Smells.md +34 -0
- data/docs/Command-Line-Options.md +84 -0
- data/docs/Configuration-Files.md +38 -0
- data/docs/Control-Couple.md +22 -0
- data/docs/Control-Parameter.md +29 -0
- data/docs/Data-Clump.md +44 -0
- data/docs/Duplicate-Method-Call.md +49 -0
- data/docs/Feature-Envy.md +29 -0
- data/docs/How-reek-works-internally.md +44 -0
- data/docs/Irresponsible-Module.md +39 -0
- data/docs/Large-Class.md +20 -0
- data/docs/Long-Parameter-List.md +38 -0
- data/docs/Long-Yield-List.md +36 -0
- data/docs/Module-Initialize.md +62 -0
- data/docs/Nested-Iterators.md +38 -0
- data/docs/Nil-Check.md +39 -0
- data/docs/Prima-Donna-Method.md +53 -0
- data/docs/RSpec-matchers.md +133 -0
- data/docs/Rake-Task.md +58 -0
- data/docs/Reek-Driven-Development.md +45 -0
- data/docs/Repeated-Conditional.md +44 -0
- data/docs/Simulated-Polymorphism.md +16 -0
- data/docs/Smell-Suppression.md +32 -0
- data/docs/Too-Many-Instance-Variables.md +43 -0
- data/docs/Too-Many-Methods.md +55 -0
- data/docs/Too-Many-Statements.md +50 -0
- data/docs/Uncommunicative-Method-Name.md +24 -0
- data/docs/Uncommunicative-Module-Name.md +23 -0
- data/docs/Uncommunicative-Name.md +16 -0
- data/docs/Uncommunicative-Parameter-Name.md +24 -0
- data/docs/Uncommunicative-Variable-Name.md +24 -0
- data/docs/Unused-Parameters.md +27 -0
- data/docs/Utility-Function.md +46 -0
- data/docs/Versioning-Policy.md +7 -0
- data/docs/YAML-Reports.md +111 -0
- data/docs/yard_plugin.rb +14 -0
- data/features/command_line_interface/options.feature +1 -0
- data/features/programmatic_access.feature +1 -1
- data/features/samples.feature +3 -3
- data/lib/reek.rb +2 -2
- data/lib/reek/cli/input.rb +2 -2
- data/lib/reek/cli/option_interpreter.rb +2 -0
- data/lib/reek/cli/options.rb +10 -4
- data/lib/reek/cli/reek_command.rb +2 -2
- data/lib/reek/cli/report/report.rb +60 -0
- data/lib/reek/cli/silencer.rb +13 -0
- data/lib/reek/{source → core}/ast_node.rb +1 -1
- data/lib/reek/{source → core}/ast_node_class_map.rb +10 -11
- data/lib/reek/{source → core}/code_comment.rb +1 -1
- data/lib/reek/core/code_context.rb +1 -1
- data/lib/reek/core/examiner.rb +85 -0
- data/lib/reek/core/method_context.rb +1 -1
- data/lib/reek/core/module_context.rb +2 -2
- data/lib/reek/core/reference_collector.rb +31 -0
- data/lib/reek/core/singleton_method_context.rb +0 -4
- data/lib/reek/core/smell_repository.rb +4 -2
- data/lib/reek/{source → core}/tree_dresser.rb +1 -1
- data/lib/reek/{source → sexp}/sexp_extensions.rb +5 -5
- data/lib/reek/sexp/sexp_formatter.rb +29 -0
- data/lib/reek/sexp/sexp_node.rb +91 -0
- data/lib/reek/smells.rb +4 -2
- data/lib/reek/smells/attribute.rb +35 -7
- data/lib/reek/smells/boolean_parameter.rb +1 -1
- 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 +12 -4
- data/lib/reek/smells/feature_envy.rb +1 -1
- data/lib/reek/smells/irresponsible_module.rb +3 -3
- data/lib/reek/smells/long_parameter_list.rb +1 -1
- data/lib/reek/smells/long_yield_list.rb +1 -1
- data/lib/reek/smells/module_initialize.rb +1 -1
- data/lib/reek/smells/nested_iterators.rb +1 -1
- data/lib/reek/smells/nil_check.rb +3 -2
- data/lib/reek/smells/prima_donna_method.rb +18 -11
- data/lib/reek/smells/repeated_conditional.rb +3 -3
- data/lib/reek/smells/smell_detector.rb +5 -1
- data/lib/reek/smells/smell_warning.rb +99 -0
- data/lib/reek/smells/too_many_instance_variables.rb +1 -1
- data/lib/reek/smells/too_many_methods.rb +1 -1
- data/lib/reek/smells/too_many_statements.rb +1 -1
- data/lib/reek/smells/uncommunicative_method_name.rb +1 -1
- data/lib/reek/smells/uncommunicative_module_name.rb +1 -1
- data/lib/reek/smells/uncommunicative_parameter_name.rb +1 -1
- data/lib/reek/smells/uncommunicative_variable_name.rb +1 -1
- data/lib/reek/smells/unused_parameters.rb +1 -1
- data/lib/reek/smells/utility_function.rb +3 -16
- data/lib/reek/source/source_code.rb +31 -13
- data/lib/reek/source/source_locator.rb +16 -17
- data/lib/reek/source/source_repository.rb +10 -11
- data/lib/reek/spec/should_reek.rb +2 -2
- data/lib/reek/spec/should_reek_of.rb +2 -2
- data/lib/reek/spec/should_reek_only_of.rb +2 -2
- data/lib/reek/version.rb +1 -1
- data/reek.gemspec +3 -4
- data/spec/factories/factories.rb +1 -1
- data/spec/gem/yard_spec.rb +1 -1
- data/spec/quality/reek_source_spec.rb +2 -2
- data/spec/reek/cli/html_report_spec.rb +3 -3
- data/spec/reek/cli/json_report_spec.rb +3 -3
- data/spec/reek/cli/{option_interperter_spec.rb → option_interpreter_spec.rb} +1 -1
- data/spec/reek/cli/options_spec.rb +19 -0
- data/spec/reek/cli/text_report_spec.rb +7 -7
- data/spec/reek/cli/xml_report_spec.rb +34 -0
- data/spec/reek/cli/yaml_report_spec.rb +3 -3
- data/spec/reek/configuration/app_configuration_spec.rb +1 -1
- data/spec/reek/configuration/configuration_file_finder_spec.rb +22 -1
- data/spec/reek/{source → core}/code_comment_spec.rb +14 -14
- data/spec/reek/core/code_context_spec.rb +1 -1
- data/spec/reek/{examiner_spec.rb → core/examiner_spec.rb} +12 -12
- data/spec/reek/core/method_context_spec.rb +27 -22
- data/spec/reek/core/module_context_spec.rb +2 -2
- data/spec/reek/core/object_refs_spec.rb +1 -1
- data/spec/reek/{source → core}/object_source_spec.rb +1 -1
- data/spec/reek/{source → core}/reference_collector_spec.rb +25 -16
- data/spec/reek/core/singleton_method_context_spec.rb +12 -2
- data/spec/reek/core/smell_configuration_spec.rb +1 -1
- data/spec/reek/core/smell_repository_spec.rb +12 -1
- data/spec/reek/core/stop_context_spec.rb +1 -1
- data/spec/reek/core/tree_dresser_spec.rb +16 -0
- data/spec/reek/core/tree_walker_spec.rb +3 -3
- data/spec/reek/core/warning_collector_spec.rb +6 -6
- data/spec/reek/{source → sexp}/sexp_extensions_spec.rb +8 -8
- data/spec/reek/{source → sexp}/sexp_formatter_spec.rb +11 -5
- data/spec/reek/{source → sexp}/sexp_node_spec.rb +3 -3
- data/spec/reek/smells/attribute_spec.rb +89 -85
- data/spec/reek/smells/behaves_like_variable_detector.rb +1 -1
- data/spec/reek/smells/boolean_parameter_spec.rb +1 -1
- data/spec/reek/smells/class_variable_spec.rb +1 -1
- data/spec/reek/smells/control_parameter_spec.rb +1 -1
- data/spec/reek/smells/data_clump_spec.rb +2 -2
- data/spec/reek/smells/duplicate_method_call_spec.rb +1 -1
- data/spec/reek/smells/feature_envy_spec.rb +2 -2
- data/spec/reek/smells/irresponsible_module_spec.rb +1 -1
- data/spec/reek/smells/long_parameter_list_spec.rb +2 -2
- data/spec/reek/smells/long_yield_list_spec.rb +1 -1
- data/spec/reek/smells/module_initialize_spec.rb +1 -1
- data/spec/reek/smells/nested_iterators_spec.rb +2 -2
- data/spec/reek/smells/nil_check_spec.rb +1 -1
- data/spec/reek/smells/prima_donna_method_spec.rb +1 -1
- data/spec/reek/smells/repeated_conditional_spec.rb +1 -1
- data/spec/reek/smells/smell_detector_shared.rb +2 -2
- data/spec/reek/{smell_warning_spec.rb → smells/smell_warning_spec.rb} +7 -7
- data/spec/reek/smells/too_many_instance_variables_spec.rb +1 -1
- data/spec/reek/smells/too_many_methods_spec.rb +1 -1
- data/spec/reek/smells/too_many_statements_spec.rb +4 -4
- data/spec/reek/smells/uncommunicative_method_name_spec.rb +1 -1
- data/spec/reek/smells/uncommunicative_module_name_spec.rb +1 -1
- data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +1 -1
- data/spec/reek/smells/uncommunicative_variable_name_spec.rb +1 -1
- data/spec/reek/smells/unused_parameters_spec.rb +1 -1
- data/spec/reek/smells/utility_function_spec.rb +1 -1
- data/spec/reek/source/source_code_spec.rb +1 -1
- data/spec/reek/spec/should_reek_of_spec.rb +1 -1
- data/spec/reek/spec/should_reek_only_of_spec.rb +1 -1
- data/spec/reek/spec/should_reek_spec.rb +1 -1
- data/spec/samples/checkstyle.xml +2 -0
- data/spec/spec_helper.rb +15 -3
- metadata +68 -38
- data/.ruby-gemset +0 -1
- data/lib/reek/examiner.rb +0 -79
- data/lib/reek/smell_warning.rb +0 -87
- data/lib/reek/source/reference_collector.rb +0 -27
- data/lib/reek/source/sexp_formatter.rb +0 -22
- data/lib/reek/source/sexp_node.rb +0 -79
- data/spec/reek/source/tree_dresser_spec.rb +0 -16
@@ -0,0 +1,49 @@
|
|
1
|
+
# Duplicate Method Call
|
2
|
+
|
3
|
+
## Introduction
|
4
|
+
|
5
|
+
Duplication occurs when two fragments of code look nearly identical, or when two fragments of code have nearly identical effects at some conceptual level.
|
6
|
+
`reek` implements a check for _Duplicate Method Call_.
|
7
|
+
|
8
|
+
## Example
|
9
|
+
|
10
|
+
Here's a very much simplified and contrived example. The following method will report a warning:
|
11
|
+
|
12
|
+
```Ruby
|
13
|
+
def double_thing()
|
14
|
+
@other.thing + @other.thing
|
15
|
+
end
|
16
|
+
```
|
17
|
+
|
18
|
+
One quick approach to silence Reek would be to refactor the code thus:
|
19
|
+
|
20
|
+
```Ruby
|
21
|
+
def double_thing()
|
22
|
+
thing = @other.thing
|
23
|
+
thing + thing
|
24
|
+
end
|
25
|
+
```
|
26
|
+
|
27
|
+
A slightly different approach would be to replace all calls of `double_thing` by calls to `@other.double_thing`:
|
28
|
+
|
29
|
+
```Ruby
|
30
|
+
class Other
|
31
|
+
def double_thing()
|
32
|
+
thing + thing
|
33
|
+
end
|
34
|
+
end
|
35
|
+
```
|
36
|
+
|
37
|
+
The approach you take will depend on balancing other factors in your code.
|
38
|
+
|
39
|
+
## Current support in reek
|
40
|
+
|
41
|
+
`reek`'s Duplicate Method Call detector checks for repeated identical method calls within any one method definition. This is intended to complement the checks performed by tools such as [Flay](http://ruby.sadi.st/Flay.html) and [Simian](http://www.redhillconsulting.com.au/products/simian/).
|
42
|
+
|
43
|
+
## Configuration
|
44
|
+
|
45
|
+
Reek's Duplication detector currently offers the [Basic Smell Options](Basic-Smell-Options.md), plus:
|
46
|
+
|
47
|
+
Option | Value | Effect
|
48
|
+
-------|-------|-------
|
49
|
+
`max_calls` | integer | The maximum number of duplicate calls allowed within a method. Defaults to 1.
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Feature Envy
|
2
|
+
|
3
|
+
## Introduction
|
4
|
+
|
5
|
+
Feature Envy occurs when a code fragment references another object more often than it references itself, or when several clients do the same series of manipulations on a particular type of object.
|
6
|
+
|
7
|
+
A simple example would be the following method, which "belongs" on the Item class and not on the Cart class:
|
8
|
+
|
9
|
+
```Ruby
|
10
|
+
class Cart
|
11
|
+
def price
|
12
|
+
@item.price + @item.tax
|
13
|
+
end
|
14
|
+
end
|
15
|
+
```
|
16
|
+
|
17
|
+
`Feature Envy` reduces the code's ability to communicate intent: code that "belongs" on one class but which is located in another can be hard to find, and may upset the "System of Names" in the host class.
|
18
|
+
|
19
|
+
`Feature Envy` also affects the design's flexibility: A code fragment that is in the wrong class creates couplings that may not be natural within the application's domain, and creates a loss of cohesion in the unwilling host class.
|
20
|
+
|
21
|
+
`Feature Envy` often arises because it must manipulate other objects (usually its arguments) to get them into a useful form, and one force preventing them (the arguments) doing this themselves is that the common knowledge lives outside the arguments, or the arguments are of too basic a type to justify extending that type. Therefore there must be something which 'knows' about the contents or purposes of the arguments. That thing would have to be more than just a basic type, because the basic types are either containers which don't know about their contents, or they are single objects which can't capture their relationship with their fellows of the same type. So, this thing with the extra knowledge should be reified into a class, and the utility method will most likely belong there.
|
22
|
+
|
23
|
+
## Current Support in reek
|
24
|
+
|
25
|
+
`Feature Envy` reports any method that refers to self less often than it refers to (ie. send messages to) some other object.
|
26
|
+
|
27
|
+
## Configuration
|
28
|
+
|
29
|
+
Feature Envy supports the [Basic Smell Options](Basic-Smell-Options.md).
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# How reek works internally
|
2
|
+
|
3
|
+
**Using reek via bin/reek:**
|
4
|
+
|
5
|
+
```
|
6
|
+
[bin/reek]
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
Application (cli/application.rb) +
|
11
|
+
Options (cli/options)
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
ReekCommand (cli/reek_command)
|
16
|
+
with Reporter (cli/report/report)
|
17
|
+
/ | \
|
18
|
+
/ | \
|
19
|
+
/ | \
|
20
|
+
Source Source Source (source/source_code)
|
21
|
+
| | |
|
22
|
+
| | |
|
23
|
+
| | |
|
24
|
+
Examiner Examiner Examiner (examiner)
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
Examiner sets up a:
|
29
|
+
- SourceRepository (source/source_repository)
|
30
|
+
- a WarningCollector (core/warning_collector)
|
31
|
+
|
32
|
+
The Examiner then goes through each source:
|
33
|
+
- Initializing a SmellRepository (core/smell_repository)
|
34
|
+
- getting the AST from the source
|
35
|
+
- applying a TreeWalker(core/tree_walker) to process this syntax tree given the SmellRepository
|
36
|
+
- finally have that SmellRepository reporting back on the WarningCollector mentioned above
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
In the last step, the reporter from the ReekCommand:
|
41
|
+
- gathers all the warnings from the collectors of all Examiners (as you can see here https://github.com/troessner/reek/blob/master/lib/reek/cli/report/report.rb#L30)
|
42
|
+
- outputs them with whatever output format we have chose via the cli options
|
43
|
+
```
|
44
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# Irresponsible Module
|
2
|
+
|
3
|
+
## Introduction
|
4
|
+
|
5
|
+
Classes and modules are the units of reuse and release. It is therefore considered good practice to annotate every class and module with a brief comment outlining its responsibilities.
|
6
|
+
|
7
|
+
## Example
|
8
|
+
|
9
|
+
Given
|
10
|
+
|
11
|
+
```Ruby
|
12
|
+
class Dummy
|
13
|
+
# Do things...
|
14
|
+
end
|
15
|
+
```
|
16
|
+
|
17
|
+
`reek` would emit the following warning:
|
18
|
+
|
19
|
+
```
|
20
|
+
test.rb -- 1 warning:
|
21
|
+
[1]:Dummy has no descriptive comment (IrresponsibleModule)
|
22
|
+
```
|
23
|
+
|
24
|
+
Fixing this is simple - just an explaining comment:
|
25
|
+
|
26
|
+
```Ruby
|
27
|
+
# The Dummy class is responsible for ...
|
28
|
+
class Dummy
|
29
|
+
# Do things...
|
30
|
+
end
|
31
|
+
```
|
32
|
+
|
33
|
+
## Current Support in reek
|
34
|
+
|
35
|
+
`Irresponsible Module` currently checks classes, but not modules.
|
36
|
+
|
37
|
+
## Configuration
|
38
|
+
|
39
|
+
`Irresponsible Module` supports only the [Basic Smell Options](Basic-Smell-Options.md).
|
data/docs/Large-Class.md
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# Large Class
|
2
|
+
|
3
|
+
## Introduction
|
4
|
+
|
5
|
+
A `Large Class` is a class or module that has a large number of instance variables, methods or lines of code in any one piece of its specification. (That is, this smell relates to pieces of the class's specification, not to the size of the corresponding instance of `Class`.)
|
6
|
+
|
7
|
+
## Current Support in Reek
|
8
|
+
|
9
|
+
`Large Class` reports classes having more than a configurable number of methods or instance variables. The method count includes public, protected and private methods, and excludes methods inherited from superclasses or included modules.
|
10
|
+
|
11
|
+
## Configuration
|
12
|
+
|
13
|
+
`reek`'s Large Class detector supports the [Basic Smell Options](Basic-Smell-Options.md), plus:
|
14
|
+
|
15
|
+
| Option | Value | Effect |
|
16
|
+
| ---------------|-------------|---------|
|
17
|
+
| max_methods | integer | The maximum number of methods allowed in a class before a warning is issued. Defaults to 25. |
|
18
|
+
| max_instance_variables | integer | The maximum number of instance variables allowed in a class before a warning is issued. Defaults to 9. |
|
19
|
+
|
20
|
+
The `Large Class` detector is enabled whenever `reek` is asked to check an instance of `Class` or `Module`.
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# Long Parameter List
|
2
|
+
|
3
|
+
## Introduction
|
4
|
+
|
5
|
+
A `Long Parameter List` occurs when a method has a lot of parameters.
|
6
|
+
|
7
|
+
## Example
|
8
|
+
|
9
|
+
Given
|
10
|
+
|
11
|
+
```Ruby
|
12
|
+
class Dummy
|
13
|
+
def long_list(foo,bar,baz,fling,flung)
|
14
|
+
puts foo,bar,baz,fling,flung
|
15
|
+
end
|
16
|
+
end
|
17
|
+
```
|
18
|
+
|
19
|
+
`reek` would report the following warning:
|
20
|
+
|
21
|
+
```
|
22
|
+
test.rb -- 1 warning:
|
23
|
+
[2]:Dummy#long_list has 5 parameters (LongParameterList)
|
24
|
+
```
|
25
|
+
|
26
|
+
A common solution to this problem would be the introduction of parameter objects.
|
27
|
+
|
28
|
+
## Current Support in Reek
|
29
|
+
|
30
|
+
`Long Parameter List` reports any method or block with more than 3 parameters.
|
31
|
+
|
32
|
+
## Configuration
|
33
|
+
|
34
|
+
Reek's Long Parameter List detector supports the [Basic Smell Options](Basic-Smell-Options.md), plus:
|
35
|
+
|
36
|
+
| Option | Value | Effect |
|
37
|
+
| ---------------|-------------|---------|
|
38
|
+
| max_params | integer | The maximum number of parameters allowed in a method or block before a warning is issued. Defaults to 3. |
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# Long Yield List
|
2
|
+
|
3
|
+
## Introduction
|
4
|
+
|
5
|
+
A _Long Yield List_ occurs when a method yields a lot of arguments to the block it gets passed.
|
6
|
+
|
7
|
+
## Example
|
8
|
+
|
9
|
+
```Ruby
|
10
|
+
class Dummy
|
11
|
+
def yields_a_lot(foo,bar,baz,fling,flung)
|
12
|
+
yield foo,bar,baz,fling,flung
|
13
|
+
end
|
14
|
+
end
|
15
|
+
```
|
16
|
+
|
17
|
+
`reek` would report the following warning:
|
18
|
+
|
19
|
+
```
|
20
|
+
test.rb -- 1 warning:
|
21
|
+
[4]:Dummy#yields_a_lot yields 5 parameters (LongYieldList)
|
22
|
+
```
|
23
|
+
|
24
|
+
A common solution to this problem would be the introduction of parameter objects.
|
25
|
+
|
26
|
+
## Current Support in Reek
|
27
|
+
|
28
|
+
Currently Long Parameter List reports any method or block with more than 3 parameters.
|
29
|
+
|
30
|
+
## Configuration
|
31
|
+
|
32
|
+
Reek's Long Parameter List detector supports the [Basic Smell Options](Basic-Smell-Options.md), plus:
|
33
|
+
|
34
|
+
| Option | Value | Effect |
|
35
|
+
| ---------------|-------------|---------|
|
36
|
+
| max_params | integer | The maximum number of parameters allowed in a method or block before a warning is issued. Defaults to 3. |
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# Module Initialize
|
2
|
+
|
3
|
+
## Introduction
|
4
|
+
|
5
|
+
A module is usually a mixin, so when an `#initialize` method is present it is
|
6
|
+
hard to tell initialization order and parameters so having `#initialize`
|
7
|
+
in a module is usually a bad idea.
|
8
|
+
|
9
|
+
## Example
|
10
|
+
|
11
|
+
The `Foo` module below contains a method `initialize`. Although class `B` inherits from `A`, the inclusion of `Foo` stops `A#initialize` from being called.
|
12
|
+
|
13
|
+
```Ruby
|
14
|
+
class A
|
15
|
+
def initialize(a)
|
16
|
+
@a = a
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module Foo
|
21
|
+
def initialize(foo)
|
22
|
+
@foo = foo
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class B < A
|
27
|
+
include Foo
|
28
|
+
|
29
|
+
def initialize(b)
|
30
|
+
super('bar')
|
31
|
+
@b = b
|
32
|
+
end
|
33
|
+
end
|
34
|
+
```
|
35
|
+
|
36
|
+
A simple solution is to rename `Foo#initialize` and call that method by name:
|
37
|
+
|
38
|
+
```Ruby
|
39
|
+
module Foo
|
40
|
+
def setup_foo_module(foo)
|
41
|
+
@foo = foo
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class B < A
|
46
|
+
include Foo
|
47
|
+
|
48
|
+
def initialize(b)
|
49
|
+
super 'bar'
|
50
|
+
setup_foo_module('foo')
|
51
|
+
@b = b
|
52
|
+
end
|
53
|
+
end
|
54
|
+
```
|
55
|
+
|
56
|
+
## Current Support in reek
|
57
|
+
|
58
|
+
`reek` warns about module initialize when an instance method named `initialize` is present in a module.
|
59
|
+
|
60
|
+
## Configuration
|
61
|
+
|
62
|
+
Module Initialize supports the [Basic Smell Options](Basic-Smell-Options.md).
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# Nested Iterators
|
2
|
+
|
3
|
+
## Introduction
|
4
|
+
|
5
|
+
A `Nested Iterator` occurs when a block contains another block.
|
6
|
+
|
7
|
+
## Example
|
8
|
+
|
9
|
+
Given
|
10
|
+
|
11
|
+
```Ruby
|
12
|
+
class Duck
|
13
|
+
class << self
|
14
|
+
def duck_names
|
15
|
+
%i!tick trick track!.each do |surname|
|
16
|
+
%i!duck!.each do |last_name|
|
17
|
+
puts "full name is #{surname} #{last_name}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
```
|
24
|
+
|
25
|
+
`reek` would report the following warning:
|
26
|
+
|
27
|
+
```
|
28
|
+
test.rb -- 1 warning:
|
29
|
+
[5]:Duck#duck_names contains iterators nested 2 deep (NestedIterators)
|
30
|
+
```
|
31
|
+
|
32
|
+
## Current Support in Reek
|
33
|
+
|
34
|
+
Nested Iterators reports failing methods only once.
|
35
|
+
|
36
|
+
## Configuration
|
37
|
+
|
38
|
+
`Nested Iterators` offers the [Basic Smell Options](Basic-Smell-Options.md).
|
data/docs/Nil-Check.md
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# Nil Check
|
2
|
+
|
3
|
+
## Introduction
|
4
|
+
|
5
|
+
A `NilCheck` is a type check. Failures of `NilCheck` violate the ["tell, don't ask"](http://robots.thoughtbot.com/tell-dont-ask) principle.
|
6
|
+
Additionally to that, type checks often mask bigger problems in your source code like not using OOP and / or polymorphism when you should.
|
7
|
+
|
8
|
+
## Example
|
9
|
+
|
10
|
+
Given
|
11
|
+
|
12
|
+
```Ruby
|
13
|
+
class Klass
|
14
|
+
def nil_checker(argument)
|
15
|
+
if argument.nil?
|
16
|
+
puts "argument isn't nil!"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
```
|
21
|
+
|
22
|
+
`reek` would emit the following warning:
|
23
|
+
|
24
|
+
```
|
25
|
+
test.rb -- 1 warning:
|
26
|
+
[3]:Klass#nil_checker performs a nil-check. (NilCheck)
|
27
|
+
```
|
28
|
+
|
29
|
+
## Current Support in Reek
|
30
|
+
|
31
|
+
`NilCheck` reports use of
|
32
|
+
|
33
|
+
* <code>.nil?</code> method
|
34
|
+
* <code>==</code> and <code>===</code> operators when checking vs. <code>nil</code>
|
35
|
+
* case statements that use syntax like <code>when nil</code>
|
36
|
+
|
37
|
+
## Configuration
|
38
|
+
|
39
|
+
`Nil Check` offers the [Basic Smell Options](Basic-Smell-Options.md).
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# Prima Donna Method
|
2
|
+
|
3
|
+
## Introduction
|
4
|
+
|
5
|
+
A candidate method for the `Prima Donna Method` smell are methods whose names end with an exclamation mark.
|
6
|
+
|
7
|
+
An exclamation mark in method names means (the explanation below is taken from [here](http://dablog.rubypal.com/2007/8/15/bang-methods-or-danger-will-rubyist) ):
|
8
|
+
|
9
|
+
>>
|
10
|
+
The ! in method names that end with ! means, “This method is dangerous”—or, more precisely, this method is the “dangerous” version of an otherwise equivalent method, with the same name minus the !. “Danger” is relative; the ! doesn’t mean anything at all unless the method name it’s in corresponds to a similar but bang-less method name.
|
11
|
+
So, for example, gsub! is the dangerous version of gsub. exit! is the dangerous version of exit. flatten! is the dangerous version of flatten. And so forth.
|
12
|
+
|
13
|
+
Such a method is called `Prima Donna Method` if and only if her non-bang version does not exist and this method is reported as a smell.
|
14
|
+
|
15
|
+
## Example
|
16
|
+
|
17
|
+
Given
|
18
|
+
|
19
|
+
```Ruby
|
20
|
+
class C
|
21
|
+
def foo; end
|
22
|
+
def foo!; end
|
23
|
+
def bar!; end
|
24
|
+
end
|
25
|
+
```
|
26
|
+
|
27
|
+
`reek` would report `bar!` as `prima donna method` smell but not `foo!`.
|
28
|
+
|
29
|
+
`reek` reports this smell only in a class context, not in a module context in order to allow perfectly legit code like this:
|
30
|
+
|
31
|
+
|
32
|
+
```Ruby
|
33
|
+
class Parent
|
34
|
+
def foo; end
|
35
|
+
end
|
36
|
+
|
37
|
+
module Dangerous
|
38
|
+
def foo!; end
|
39
|
+
end
|
40
|
+
|
41
|
+
class Son < Parent
|
42
|
+
include Dangerous
|
43
|
+
end
|
44
|
+
|
45
|
+
class Daughter < Parent
|
46
|
+
end
|
47
|
+
```
|
48
|
+
|
49
|
+
In this example, `reek` would not report the `prima donna method` smell for the method `foo` of the `Dangerous` module.
|
50
|
+
|
51
|
+
## Configuration
|
52
|
+
|
53
|
+
`Prima Donna Method` offers the [Basic Smell Options](Basic-Smell-Options.md).
|