reek 2.1.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (179) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +2 -21
  3. data/.travis.yml +1 -0
  4. data/.yardopts +3 -6
  5. data/CHANGELOG +6 -0
  6. data/CONTRIBUTING.md +8 -3
  7. data/README.md +94 -42
  8. data/config/defaults.reek +0 -1
  9. data/docs/API.md +50 -0
  10. data/docs/Attribute.md +43 -0
  11. data/docs/Basic-Smell-Options.md +44 -0
  12. data/docs/Boolean-Parameter.md +52 -0
  13. data/docs/Class-Variable.md +40 -0
  14. data/docs/Code-Smells.md +34 -0
  15. data/docs/Command-Line-Options.md +84 -0
  16. data/docs/Configuration-Files.md +38 -0
  17. data/docs/Control-Couple.md +22 -0
  18. data/docs/Control-Parameter.md +29 -0
  19. data/docs/Data-Clump.md +44 -0
  20. data/docs/Duplicate-Method-Call.md +49 -0
  21. data/docs/Feature-Envy.md +29 -0
  22. data/docs/How-reek-works-internally.md +44 -0
  23. data/docs/Irresponsible-Module.md +39 -0
  24. data/docs/Large-Class.md +20 -0
  25. data/docs/Long-Parameter-List.md +38 -0
  26. data/docs/Long-Yield-List.md +36 -0
  27. data/docs/Module-Initialize.md +62 -0
  28. data/docs/Nested-Iterators.md +38 -0
  29. data/docs/Nil-Check.md +39 -0
  30. data/docs/Prima-Donna-Method.md +53 -0
  31. data/docs/RSpec-matchers.md +133 -0
  32. data/docs/Rake-Task.md +58 -0
  33. data/docs/Reek-Driven-Development.md +45 -0
  34. data/docs/Repeated-Conditional.md +44 -0
  35. data/docs/Simulated-Polymorphism.md +16 -0
  36. data/docs/Smell-Suppression.md +32 -0
  37. data/docs/Too-Many-Instance-Variables.md +43 -0
  38. data/docs/Too-Many-Methods.md +55 -0
  39. data/docs/Too-Many-Statements.md +50 -0
  40. data/docs/Uncommunicative-Method-Name.md +24 -0
  41. data/docs/Uncommunicative-Module-Name.md +23 -0
  42. data/docs/Uncommunicative-Name.md +16 -0
  43. data/docs/Uncommunicative-Parameter-Name.md +24 -0
  44. data/docs/Uncommunicative-Variable-Name.md +24 -0
  45. data/docs/Unused-Parameters.md +27 -0
  46. data/docs/Utility-Function.md +46 -0
  47. data/docs/Versioning-Policy.md +7 -0
  48. data/docs/YAML-Reports.md +111 -0
  49. data/docs/yard_plugin.rb +14 -0
  50. data/features/command_line_interface/options.feature +1 -0
  51. data/features/programmatic_access.feature +1 -1
  52. data/features/samples.feature +3 -3
  53. data/lib/reek.rb +2 -2
  54. data/lib/reek/cli/input.rb +2 -2
  55. data/lib/reek/cli/option_interpreter.rb +2 -0
  56. data/lib/reek/cli/options.rb +10 -4
  57. data/lib/reek/cli/reek_command.rb +2 -2
  58. data/lib/reek/cli/report/report.rb +60 -0
  59. data/lib/reek/cli/silencer.rb +13 -0
  60. data/lib/reek/{source → core}/ast_node.rb +1 -1
  61. data/lib/reek/{source → core}/ast_node_class_map.rb +10 -11
  62. data/lib/reek/{source → core}/code_comment.rb +1 -1
  63. data/lib/reek/core/code_context.rb +1 -1
  64. data/lib/reek/core/examiner.rb +85 -0
  65. data/lib/reek/core/method_context.rb +1 -1
  66. data/lib/reek/core/module_context.rb +2 -2
  67. data/lib/reek/core/reference_collector.rb +31 -0
  68. data/lib/reek/core/singleton_method_context.rb +0 -4
  69. data/lib/reek/core/smell_repository.rb +4 -2
  70. data/lib/reek/{source → core}/tree_dresser.rb +1 -1
  71. data/lib/reek/{source → sexp}/sexp_extensions.rb +5 -5
  72. data/lib/reek/sexp/sexp_formatter.rb +29 -0
  73. data/lib/reek/sexp/sexp_node.rb +91 -0
  74. data/lib/reek/smells.rb +4 -2
  75. data/lib/reek/smells/attribute.rb +35 -7
  76. data/lib/reek/smells/boolean_parameter.rb +1 -1
  77. data/lib/reek/smells/class_variable.rb +1 -1
  78. data/lib/reek/smells/control_parameter.rb +1 -1
  79. data/lib/reek/smells/data_clump.rb +1 -1
  80. data/lib/reek/smells/duplicate_method_call.rb +12 -4
  81. data/lib/reek/smells/feature_envy.rb +1 -1
  82. data/lib/reek/smells/irresponsible_module.rb +3 -3
  83. data/lib/reek/smells/long_parameter_list.rb +1 -1
  84. data/lib/reek/smells/long_yield_list.rb +1 -1
  85. data/lib/reek/smells/module_initialize.rb +1 -1
  86. data/lib/reek/smells/nested_iterators.rb +1 -1
  87. data/lib/reek/smells/nil_check.rb +3 -2
  88. data/lib/reek/smells/prima_donna_method.rb +18 -11
  89. data/lib/reek/smells/repeated_conditional.rb +3 -3
  90. data/lib/reek/smells/smell_detector.rb +5 -1
  91. data/lib/reek/smells/smell_warning.rb +99 -0
  92. data/lib/reek/smells/too_many_instance_variables.rb +1 -1
  93. data/lib/reek/smells/too_many_methods.rb +1 -1
  94. data/lib/reek/smells/too_many_statements.rb +1 -1
  95. data/lib/reek/smells/uncommunicative_method_name.rb +1 -1
  96. data/lib/reek/smells/uncommunicative_module_name.rb +1 -1
  97. data/lib/reek/smells/uncommunicative_parameter_name.rb +1 -1
  98. data/lib/reek/smells/uncommunicative_variable_name.rb +1 -1
  99. data/lib/reek/smells/unused_parameters.rb +1 -1
  100. data/lib/reek/smells/utility_function.rb +3 -16
  101. data/lib/reek/source/source_code.rb +31 -13
  102. data/lib/reek/source/source_locator.rb +16 -17
  103. data/lib/reek/source/source_repository.rb +10 -11
  104. data/lib/reek/spec/should_reek.rb +2 -2
  105. data/lib/reek/spec/should_reek_of.rb +2 -2
  106. data/lib/reek/spec/should_reek_only_of.rb +2 -2
  107. data/lib/reek/version.rb +1 -1
  108. data/reek.gemspec +3 -4
  109. data/spec/factories/factories.rb +1 -1
  110. data/spec/gem/yard_spec.rb +1 -1
  111. data/spec/quality/reek_source_spec.rb +2 -2
  112. data/spec/reek/cli/html_report_spec.rb +3 -3
  113. data/spec/reek/cli/json_report_spec.rb +3 -3
  114. data/spec/reek/cli/{option_interperter_spec.rb → option_interpreter_spec.rb} +1 -1
  115. data/spec/reek/cli/options_spec.rb +19 -0
  116. data/spec/reek/cli/text_report_spec.rb +7 -7
  117. data/spec/reek/cli/xml_report_spec.rb +34 -0
  118. data/spec/reek/cli/yaml_report_spec.rb +3 -3
  119. data/spec/reek/configuration/app_configuration_spec.rb +1 -1
  120. data/spec/reek/configuration/configuration_file_finder_spec.rb +22 -1
  121. data/spec/reek/{source → core}/code_comment_spec.rb +14 -14
  122. data/spec/reek/core/code_context_spec.rb +1 -1
  123. data/spec/reek/{examiner_spec.rb → core/examiner_spec.rb} +12 -12
  124. data/spec/reek/core/method_context_spec.rb +27 -22
  125. data/spec/reek/core/module_context_spec.rb +2 -2
  126. data/spec/reek/core/object_refs_spec.rb +1 -1
  127. data/spec/reek/{source → core}/object_source_spec.rb +1 -1
  128. data/spec/reek/{source → core}/reference_collector_spec.rb +25 -16
  129. data/spec/reek/core/singleton_method_context_spec.rb +12 -2
  130. data/spec/reek/core/smell_configuration_spec.rb +1 -1
  131. data/spec/reek/core/smell_repository_spec.rb +12 -1
  132. data/spec/reek/core/stop_context_spec.rb +1 -1
  133. data/spec/reek/core/tree_dresser_spec.rb +16 -0
  134. data/spec/reek/core/tree_walker_spec.rb +3 -3
  135. data/spec/reek/core/warning_collector_spec.rb +6 -6
  136. data/spec/reek/{source → sexp}/sexp_extensions_spec.rb +8 -8
  137. data/spec/reek/{source → sexp}/sexp_formatter_spec.rb +11 -5
  138. data/spec/reek/{source → sexp}/sexp_node_spec.rb +3 -3
  139. data/spec/reek/smells/attribute_spec.rb +89 -85
  140. data/spec/reek/smells/behaves_like_variable_detector.rb +1 -1
  141. data/spec/reek/smells/boolean_parameter_spec.rb +1 -1
  142. data/spec/reek/smells/class_variable_spec.rb +1 -1
  143. data/spec/reek/smells/control_parameter_spec.rb +1 -1
  144. data/spec/reek/smells/data_clump_spec.rb +2 -2
  145. data/spec/reek/smells/duplicate_method_call_spec.rb +1 -1
  146. data/spec/reek/smells/feature_envy_spec.rb +2 -2
  147. data/spec/reek/smells/irresponsible_module_spec.rb +1 -1
  148. data/spec/reek/smells/long_parameter_list_spec.rb +2 -2
  149. data/spec/reek/smells/long_yield_list_spec.rb +1 -1
  150. data/spec/reek/smells/module_initialize_spec.rb +1 -1
  151. data/spec/reek/smells/nested_iterators_spec.rb +2 -2
  152. data/spec/reek/smells/nil_check_spec.rb +1 -1
  153. data/spec/reek/smells/prima_donna_method_spec.rb +1 -1
  154. data/spec/reek/smells/repeated_conditional_spec.rb +1 -1
  155. data/spec/reek/smells/smell_detector_shared.rb +2 -2
  156. data/spec/reek/{smell_warning_spec.rb → smells/smell_warning_spec.rb} +7 -7
  157. data/spec/reek/smells/too_many_instance_variables_spec.rb +1 -1
  158. data/spec/reek/smells/too_many_methods_spec.rb +1 -1
  159. data/spec/reek/smells/too_many_statements_spec.rb +4 -4
  160. data/spec/reek/smells/uncommunicative_method_name_spec.rb +1 -1
  161. data/spec/reek/smells/uncommunicative_module_name_spec.rb +1 -1
  162. data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +1 -1
  163. data/spec/reek/smells/uncommunicative_variable_name_spec.rb +1 -1
  164. data/spec/reek/smells/unused_parameters_spec.rb +1 -1
  165. data/spec/reek/smells/utility_function_spec.rb +1 -1
  166. data/spec/reek/source/source_code_spec.rb +1 -1
  167. data/spec/reek/spec/should_reek_of_spec.rb +1 -1
  168. data/spec/reek/spec/should_reek_only_of_spec.rb +1 -1
  169. data/spec/reek/spec/should_reek_spec.rb +1 -1
  170. data/spec/samples/checkstyle.xml +2 -0
  171. data/spec/spec_helper.rb +15 -3
  172. metadata +68 -38
  173. data/.ruby-gemset +0 -1
  174. data/lib/reek/examiner.rb +0 -79
  175. data/lib/reek/smell_warning.rb +0 -87
  176. data/lib/reek/source/reference_collector.rb +0 -27
  177. data/lib/reek/source/sexp_formatter.rb +0 -22
  178. data/lib/reek/source/sexp_node.rb +0 -79
  179. 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).
@@ -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).