reek 3.5.0 → 3.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +6 -0
  3. data/CHANGELOG.md +19 -12
  4. data/CONTRIBUTING.md +7 -7
  5. data/README.md +91 -28
  6. data/ataru_setup.rb +13 -0
  7. data/{config/defaults.reek → defaults.reek} +0 -0
  8. data/docs/API.md +32 -31
  9. data/docs/Attribute.md +1 -1
  10. data/docs/Basic-Smell-Options.md +2 -1
  11. data/docs/Boolean-Parameter.md +1 -1
  12. data/docs/Class-Variable.md +2 -2
  13. data/docs/Command-Line-Options.md +2 -2
  14. data/docs/Control-Couple.md +3 -3
  15. data/docs/Control-Parameter.md +2 -2
  16. data/docs/Data-Clump.md +2 -2
  17. data/docs/Duplicate-Method-Call.md +4 -4
  18. data/docs/Feature-Envy.md +2 -2
  19. data/docs/How-reek-works-internally.md +2 -2
  20. data/docs/Irresponsible-Module.md +2 -2
  21. data/docs/Large-Class.md +2 -2
  22. data/docs/Long-Parameter-List.md +1 -1
  23. data/docs/Long-Yield-List.md +2 -2
  24. data/docs/Module-Initialize.md +3 -3
  25. data/docs/Nested-Iterators.md +1 -1
  26. data/docs/Nil-Check.md +2 -2
  27. data/docs/Prima-Donna-Method.md +4 -4
  28. data/docs/RSpec-matchers.md +7 -7
  29. data/docs/Rake-Task.md +2 -2
  30. data/docs/Reek-Driven-Development.md +4 -4
  31. data/docs/Repeated-Conditional.md +2 -2
  32. data/docs/Simulated-Polymorphism.md +2 -2
  33. data/docs/Smell-Suppression.md +3 -3
  34. data/docs/Too-Many-Instance-Variables.md +4 -4
  35. data/docs/Too-Many-Methods.md +5 -5
  36. data/docs/Too-Many-Statements.md +2 -2
  37. data/docs/Uncommunicative-Method-Name.md +4 -4
  38. data/docs/Uncommunicative-Module-Name.md +4 -4
  39. data/docs/Uncommunicative-Name.md +2 -2
  40. data/docs/Uncommunicative-Parameter-Name.md +4 -4
  41. data/docs/Uncommunicative-Variable-Name.md +3 -3
  42. data/docs/Unused-Parameters.md +2 -2
  43. data/docs/Utility-Function.md +4 -4
  44. data/docs/Versioning-Policy.md +2 -2
  45. data/features/command_line_interface/options.feature +1 -1
  46. data/features/configuration_files/directory_specific_directives.feature +4 -4
  47. data/features/configuration_loading.feature +10 -24
  48. data/features/programmatic_access.feature +3 -3
  49. data/features/reports/json.feature +1 -1
  50. data/features/reports/reports.feature +2 -2
  51. data/features/reports/yaml.feature +1 -1
  52. data/lib/reek/ast/sexp_extensions.rb +17 -498
  53. data/lib/reek/ast/sexp_extensions/arguments.rb +101 -0
  54. data/lib/reek/ast/sexp_extensions/attribute_assignments.rb +12 -0
  55. data/lib/reek/ast/sexp_extensions/block.rb +36 -0
  56. data/lib/reek/ast/sexp_extensions/case.rb +20 -0
  57. data/lib/reek/ast/sexp_extensions/constant.rb +12 -0
  58. data/lib/reek/ast/sexp_extensions/if.rb +16 -0
  59. data/lib/reek/ast/sexp_extensions/literal.rb +12 -0
  60. data/lib/reek/ast/sexp_extensions/logical_operators.rb +26 -0
  61. data/lib/reek/ast/sexp_extensions/methods.rb +114 -0
  62. data/lib/reek/ast/sexp_extensions/module.rb +85 -0
  63. data/lib/reek/ast/sexp_extensions/nested_assignables.rb +23 -0
  64. data/lib/reek/ast/sexp_extensions/send.rb +60 -0
  65. data/lib/reek/ast/sexp_extensions/super.rb +14 -0
  66. data/lib/reek/ast/sexp_extensions/symbols.rb +16 -0
  67. data/lib/reek/ast/sexp_extensions/variables.rb +38 -0
  68. data/lib/reek/ast/sexp_extensions/when.rb +16 -0
  69. data/lib/reek/ast/sexp_extensions/yield.rb +16 -0
  70. data/lib/reek/cli/application.rb +0 -4
  71. data/lib/reek/cli/options.rb +2 -4
  72. data/lib/reek/configuration/app_configuration.rb +37 -9
  73. data/lib/reek/configuration/configuration_file_finder.rb +8 -5
  74. data/lib/reek/configuration/directory_directives.rb +2 -2
  75. data/lib/reek/context/attribute_context.rb +21 -0
  76. data/lib/reek/context/code_context.rb +5 -9
  77. data/lib/reek/rake/task.rb +5 -5
  78. data/lib/reek/smells/nested_iterators.rb +73 -26
  79. data/lib/reek/smells/smell_warning.rb +1 -38
  80. data/lib/reek/source/source_code.rb +1 -1
  81. data/lib/reek/spec.rb +2 -2
  82. data/lib/reek/spec/should_reek_of.rb +8 -3
  83. data/lib/reek/spec/should_reek_only_of.rb +2 -1
  84. data/lib/reek/spec/smell_matcher.rb +59 -0
  85. data/lib/reek/tree_walker.rb +4 -3
  86. data/lib/reek/version.rb +1 -1
  87. data/logo/reek.bw.png +0 -0
  88. data/logo/reek.bw.svg +77 -0
  89. data/logo/reek.png +0 -0
  90. data/logo/reek.svg +621 -0
  91. data/logo/reek.text.png +0 -0
  92. data/logo/reek.text.svg +628 -0
  93. data/reek.gemspec +1 -1
  94. data/spec/factories/factories.rb +0 -1
  95. data/spec/reek/ast/sexp_extensions_spec.rb +0 -7
  96. data/spec/reek/cli/options_spec.rb +1 -2
  97. data/spec/reek/configuration/app_configuration_spec.rb +30 -14
  98. data/spec/reek/configuration/configuration_file_finder_spec.rb +23 -5
  99. data/spec/reek/smells/attribute_spec.rb +11 -2
  100. data/spec/reek/smells/boolean_parameter_spec.rb +14 -12
  101. data/spec/reek/smells/class_variable_spec.rb +18 -15
  102. data/spec/reek/smells/control_parameter_spec.rb +1 -2
  103. data/spec/reek/smells/duplicate_method_call_spec.rb +1 -2
  104. data/spec/reek/smells/feature_envy_spec.rb +8 -29
  105. data/spec/reek/smells/irresponsible_module_spec.rb +1 -2
  106. data/spec/reek/smells/long_parameter_list_spec.rb +1 -2
  107. data/spec/reek/smells/long_yield_list_spec.rb +1 -2
  108. data/spec/reek/smells/nested_iterators_spec.rb +1 -2
  109. data/spec/reek/smells/nil_check_spec.rb +1 -1
  110. data/spec/reek/smells/prima_donna_method_spec.rb +1 -1
  111. data/spec/reek/smells/repeated_conditional_spec.rb +1 -2
  112. data/spec/reek/smells/smell_detector_shared.rb +1 -1
  113. data/spec/reek/smells/smell_warning_spec.rb +2 -4
  114. data/spec/reek/smells/too_many_instance_variables_spec.rb +20 -19
  115. data/spec/reek/smells/too_many_statements_spec.rb +1 -1
  116. data/spec/reek/smells/uncommunicative_method_name_spec.rb +1 -4
  117. data/spec/reek/smells/uncommunicative_module_name_spec.rb +1 -4
  118. data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +1 -4
  119. data/spec/reek/smells/uncommunicative_variable_name_spec.rb +3 -3
  120. data/spec/reek/smells/utility_function_spec.rb +1 -3
  121. data/spec/reek/spec/should_reek_of_spec.rb +5 -5
  122. data/spec/reek/spec/smell_matcher_spec.rb +92 -0
  123. data/tasks/configuration.rake +15 -0
  124. metadata +37 -5
  125. data/config/cucumber.yml +0 -3
  126. data/tasks/develop.rake +0 -21
@@ -24,19 +24,19 @@ class TooManyInstanceVariables
24
24
  end
25
25
  ```
26
26
 
27
- `reek` would emit the following warning:
27
+ Reek would emit the following warning:
28
28
 
29
29
  ```
30
30
  test.rb -- 5 warnings:
31
31
  [1]:TooManyInstanceVariables has at least 4 instance variables (TooManyInstanceVariables)
32
32
  ```
33
- ## Current Support in `reek`
33
+ ## Current Support in Reek
34
34
 
35
- `reek` only counts the instance variables you use explicitly like in the example above. Class macros like `attr_accessor` are disregarded.
35
+ Reek only counts the instance variables you use explicitly like in the example above. Class macros like `attr_accessor` are disregarded.
36
36
 
37
37
  ## Configuration
38
38
 
39
- `reek`'s `Too Many Instance Variables` detector offers the [Basic Smell Options](Basic-Smell-Options.md), plus:
39
+ Reek's `Too Many Instance Variables` detector offers the [Basic Smell Options](Basic-Smell-Options.md), plus:
40
40
 
41
41
  | Option | Value | Effect |
42
42
  | ---------------|-------------|---------|
@@ -22,15 +22,15 @@ class TooManyMethods
22
22
  end
23
23
  ```
24
24
 
25
- `reek` would emit the following warning:
25
+ Reek would emit the following warning:
26
26
 
27
27
  ```
28
28
  test.rb -- 1 warning:
29
29
  [1]:TooManyMethods has at least 4 methods (TooManyMethods)
30
30
  ```
31
- ## Current Support in `reek`
31
+ ## Current Support in Reek
32
32
 
33
- `reek` counts all the methods it can find in a `class` - instance *and* class methods. So given `max_methods` from above is 4, this:
33
+ Reek counts all the methods it can find in a `class` - instance *and* class methods. So given `max_methods` from above is 4, this:
34
34
 
35
35
  ```Ruby
36
36
  class TooManyMethods
@@ -44,11 +44,11 @@ class TooManyMethods
44
44
  end
45
45
  ```
46
46
 
47
- would cause reek to emit the same warning as in the example above.
47
+ would cause Reek to emit the same warning as in the example above.
48
48
 
49
49
  ## Configuration
50
50
 
51
- `reek`'s `Too Many Methods` detector offers the [Basic Smell Options](Basic-Smell-Options.md), plus:
51
+ Reek's `Too Many Methods` detector offers the [Basic Smell Options](Basic-Smell-Options.md), plus:
52
52
 
53
53
  | Option | Value | Effect |
54
54
  | ---------------|-------------|---------|
@@ -6,7 +6,7 @@ A method with `Too Many Statements` is any method that has a large number of lin
6
6
 
7
7
  ## Current Support in Reek
8
8
 
9
- `Too Many Statements` warns about any method that has more than 5 statements. `reek`'s smell detector for `Too Many Statements` counts +1 for every simple statement in a method and +1 for every statement within a control structure (`if`, `else`, `case`, `when`, `for`, `while`, `until`, `begin`, `rescue`) but it doesn't count the control structure itself.
9
+ `Too Many Statements` warns about any method that has more than 5 statements. Reek's smell detector for `Too Many Statements` counts +1 for every simple statement in a method and +1 for every statement within a control structure (`if`, `else`, `case`, `when`, `for`, `while`, `until`, `begin`, `rescue`) but it doesn't count the control structure itself.
10
10
 
11
11
  So the following method would score +6 in Reek's statement-counting algorithm:
12
12
 
@@ -30,7 +30,7 @@ end
30
30
 
31
31
  ## Configuration
32
32
 
33
- `reek`'s `Too Many Statements` detector supports the [Basic Smell Options](Basic-Smell-Options.md), plus:
33
+ Reek's `Too Many Statements` detector supports the [Basic Smell Options](Basic-Smell-Options.md), plus:
34
34
 
35
35
  | Option | Value | Effect |
36
36
  | ---------------|-------------|---------|
@@ -6,7 +6,7 @@ An `Uncommunicative Method Name` is a method name that doesn't communicate its i
6
6
 
7
7
  Poor names make it hard for the reader to build a mental picture of what's going on in the code. They can also be mis-interpreted; and they hurt the flow of reading, because the reader must slow down to interpret the names.
8
8
 
9
- ## Current Support in reek
9
+ ## Current Support in Reek
10
10
 
11
11
  `Uncommunicative Method Name` checks for:
12
12
 
@@ -16,9 +16,9 @@ Poor names make it hard for the reader to build a mental picture of what's going
16
16
 
17
17
  ## Configuration
18
18
 
19
- `reek`'s Uncommunicative Method Name detector supports the [Basic Smell Options](Basic-Smell-Options.md), plus:
19
+ Reek's Uncommunicative Method Name detector supports the [Basic Smell Options](Basic-Smell-Options.md), plus:
20
20
 
21
21
  | Option | Value | Effect |
22
22
  | ---------------|-------------|---------|
23
- | `reject` | array of regular expressions | The set of regular expressions that `reek` uses to check for bad names. Defaults to `[/^[a-z]$/, /[0-9]$/, /[A-Z]/]`. |
24
- | `accept` | array of strings or regular expressions | Name that will be accepted (not reported) even if they match one of the `reject` expressions. |
23
+ | `reject` | array of regular expressions | The set of regular expressions that Reek uses to check for bad names. Defaults to `[/^[a-z]$/, /[0-9]$/, /[A-Z]/]`. |
24
+ | `accept` | array of strings or regular expressions | Name that will be accepted (not reported) even if they match one of the `reject` expressions. |
@@ -6,7 +6,7 @@ An `Uncommunicative Module Name` is a module name that doesn't communicate its i
6
6
 
7
7
  Poor names make it hard for the reader to build a mental picture of what's going on in the code. They can also be mis-interpreted; and they hurt the flow of reading, because the reader must slow down to interpret the names.
8
8
 
9
- ## Current Support in reek
9
+ ## Current Support in Reek
10
10
 
11
11
  `Uncommunicative Module Name` checks for:
12
12
 
@@ -15,9 +15,9 @@ Poor names make it hard for the reader to build a mental picture of what's going
15
15
 
16
16
  ## Configuration
17
17
 
18
- `reek`'s `Uncommunicative Module Name` detector supports the [Basic Smell Options](Basic-Smell-Options.md), plus:
18
+ Reek's `Uncommunicative Module Name` detector supports the [Basic Smell Options](Basic-Smell-Options.md), plus:
19
19
 
20
20
  | Option | Value | Effect |
21
21
  | ---------------|-------------|---------|
22
- | `reject` | array of regular expressions | The set of regular expressions that `reek` uses to check for bad names. Defaults to `[/^.$/, /[0-9]$/]`. |
23
- | `accept` | array of names as strings | List of names that will be accepted (not reported) even if they match one of the `reject` expressions. Empty by default.|
22
+ | `reject` | array of regular expressions | The set of regular expressions that Reek uses to check for bad names. Defaults to `[/^.$/, /[0-9]$/]`. |
23
+ | `accept` | array of names as strings | List of names that will be accepted (not reported) even if they match one of the `reject` expressions. Empty by default.|
@@ -8,9 +8,9 @@ Poor names make it hard for the reader to build a mental picture of what's going
8
8
 
9
9
  ## Current Support in Reek
10
10
 
11
- `reek` offers four related checks:
11
+ Reek offers four related checks:
12
12
 
13
13
  * [Uncommunicative Method Name](Uncommunicative-Method-Name.md)
14
14
  * [Uncommunicative Module Name](Uncommunicative-Module-Name.md)
15
15
  * [Uncommunicative Parameter Name](Uncommunicative-Parameter-Name.md)
16
- * [Uncommunicative Variable Name](Uncommunicative-Variable-Name.md)
16
+ * [Uncommunicative Variable Name](Uncommunicative-Variable-Name.md)
@@ -6,7 +6,7 @@ An `Uncommunicative Parameter Name` is a parameter name that doesn't communicate
6
6
 
7
7
  Poor names make it hard for the reader to build a mental picture of what's going on in the code. They can also be mis-interpreted; and they hurt the flow of reading, because the reader must slow down to interpret the names.
8
8
 
9
- ## Current Support in reek
9
+ ## Current Support in Reek
10
10
 
11
11
  `Uncommunicative Parameter Name` checks for:
12
12
 
@@ -16,9 +16,9 @@ Poor names make it hard for the reader to build a mental picture of what's going
16
16
 
17
17
  ## Configuration
18
18
 
19
- `reek`'s Uncommunicative Parameter Name detector supports the [Basic Smell Options](Basic-Smell-Options.md), plus:
19
+ Reek's Uncommunicative Parameter Name detector supports the [Basic Smell Options](Basic-Smell-Options.md), plus:
20
20
 
21
21
  | Option | Value | Effect |
22
22
  | ---------------|-------------|---------|
23
- | `reject` | array of regular expressions | The set of regular expressions that `reek` uses to check for bad names. Defaults to `[/^.$/, /[0-9]$/, /[A-Z]/]@. |
24
- | `accept` | array of strings or regular expressions | Name that will be accepted (not reported) even if they match one of the `reject` expressions. |
23
+ | `reject` | array of regular expressions | The set of regular expressions that Reek uses to check for bad names. Defaults to `[/^.$/, /[0-9]$/, /[A-Z]/]@. |
24
+ | `accept` | array of strings or regular expressions | Name that will be accepted (not reported) even if they match one of the `reject` expressions. |
@@ -16,9 +16,9 @@ Poor names make it hard for the reader to build a mental picture of what's going
16
16
 
17
17
  ## Configuration
18
18
 
19
- `reek`'s `Uncommunicative Variable Name` detector supports the [Basic Smell Options](Basic-Smell-Options.md), plus:
19
+ Reek's `Uncommunicative Variable Name` detector supports the [Basic Smell Options](Basic-Smell-Options.md), plus:
20
20
 
21
21
  | Option | Value | Effect |
22
22
  | ---------------|-------------|---------|
23
- | `reject` | array of regular expressions | The set of regular expressions that `reek` uses to check for bad names. Defaults to `[/^.$/, /[0-9]$/, /[A-Z]/]`. |
24
- | `accept` | array of strings or regular expressions | Name that will be accepted (not reported) even if they match one of the `reject` expressions. Defaults to @['_']@.|
23
+ | `reject` | array of regular expressions | The set of regular expressions that Reek uses to check for bad names. Defaults to `[/^.$/, /[0-9]$/, /[A-Z]/]`. |
24
+ | `accept` | array of strings or regular expressions | Name that will be accepted (not reported) even if they match one of the `reject` expressions. Defaults to @['_']@.|
@@ -16,7 +16,7 @@ class Klass
16
16
  end
17
17
  ```
18
18
 
19
- `reek` would emit the following warning:
19
+ Reek would emit the following warning:
20
20
 
21
21
  ```
22
22
  [2]:Klass#unused_parameters has unused parameter 'z' (UnusedParameters)
@@ -24,4 +24,4 @@ end
24
24
 
25
25
  ## Configuration
26
26
 
27
- `Unused Parameter` offers the [Basic Smell Options](Basic-Smell-Options.md).
27
+ `Unused Parameter` offers the [Basic Smell Options](Basic-Smell-Options.md).
@@ -18,14 +18,14 @@ class UtilityFunction
18
18
  end
19
19
  ```
20
20
 
21
- `reek` would report:
21
+ Reek would report:
22
22
 
23
23
  ```
24
24
  test.rb -- 2 warnings:
25
25
  [2]:UtilityFunction#showcase doesn't depend on instance state (UtilityFunction)
26
26
  ```
27
27
 
28
- ## Current Support in reek
28
+ ## Current Support in Reek
29
29
 
30
30
  _Utility Function_ will warn about any method that:
31
31
 
@@ -41,7 +41,7 @@ _[Feature Envy](Feature-Envy.md)_ is only triggered if there are some references
41
41
 
42
42
  ## Configuration
43
43
 
44
- `reek`'s _Utility Function_ detector supports the [Basic Smell Options](Basic-Smell-Options.md), plus:
44
+ Reek's _Utility Function_ detector supports the [Basic Smell Options](Basic-Smell-Options.md), plus:
45
45
 
46
46
  | Option | Value | Effect |
47
47
  | ---------------|-------------|---------|
@@ -53,4 +53,4 @@ A sample configuration file would look like this:
53
53
  ---
54
54
  UtilityFunction:
55
55
  public_methods_only: true
56
- ``
56
+ ```
@@ -1,7 +1,7 @@
1
1
  # Versioning Policy
2
2
 
3
- * CLI interface: Adding options is a non-breaking change, and would warrant an update of the minor version. Removing options is a breaking change and requires a major version update (we did this going to reek 2). Adding a report format probably also warrents a minor version upgrade.
4
- * API: We haven't really defined a 'public' API for using Reek programmatically, and we've only just started testing it. So, this is basically a blank slate at the moment. We will work on this as a part of the reek 3 release.
3
+ * CLI interface: Adding options is a non-breaking change, and would warrant an update of the minor version. Removing options is a breaking change and requires a major version update (we did this going to Reek 2). Adding a report format probably also warrents a minor version upgrade.
4
+ * API: We haven't really defined a 'public' API for using Reek programmatically, and we've only just started testing it. So, this is basically a blank slate at the moment. We will work on this as a part of the Reek 3 release.
5
5
  * List of detected smells: Adding a smell warrants a minor release, removing a smell is a breaking change. This makes sense if you consider that the CLI allows running a single smell detector.
6
6
  * Consistency of detected smells: This is very hard to guarantee. If we fix a bug in one of the detectors, some fragrant code may become smelly, or vice versa. Right now we don't bother with this.
7
7
  * Smell configuration: The detectors are quite tolerant regarding configuration options that they don't recognize, so we regard any change here as only requiring a minor release.
@@ -1,5 +1,5 @@
1
1
  Feature: Reek can be controlled using command-line options
2
- In order to change reek's default behaviour
2
+ In order to change Reek's default behaviour
3
3
  As a developer
4
4
  I want to supply options on the command line
5
5
 
@@ -1,8 +1,8 @@
1
1
  Feature: Directory directives
2
- In order to have a more fine-grained control over what reek reports
2
+ In order to have a more fine-grained control over what Reek reports
3
3
  And to enable domain specific modes (like a Ruby on Rails mode)
4
4
  As a user
5
- I want to be able to configure reek using directory directives
5
+ I want to be able to configure Reek using directory directives
6
6
 
7
7
  Scenario: Configure multiple directories
8
8
  Given a file named "web_app/config.reek" with:
@@ -206,8 +206,8 @@ Feature: Directory directives
206
206
  And stderr reports:
207
207
  """
208
208
  You are trying to configure smell type IteratorsNested but we can't find one with that name.
209
- Please make sure you spelled it right (see 'config/defaults.reek' in the reek
210
- repository for a list of all available smell types.
209
+ Please make sure you spelled it right. (See 'defaults.reek' in the Reek
210
+ repository for a list of all available smell types.)
211
211
 
212
212
  """
213
213
 
@@ -1,16 +1,16 @@
1
1
  Feature: Offer different ways how to load configuration
2
2
 
3
- There are 3 ways of passing reek a configuration file:
4
- - Using the cli "-c" switch
5
- - Having a file ending with .reek either in your current working directory or in a parent directory
6
- - Having a file ending with .reek in your HOME directory
7
- The order in which reek tries to find such a configuration file should exactly be like above:
8
- First reek should check if we have given it a configuration file explicitly via CLI.
9
- Then it should check the current working directory for a file and if it can't find one,
10
- it should traverse up the directories until it hits the root directory.
11
- And finally, it should check your HOME directory.
3
+ Reek can be configured in two ways:
4
+ - Using the cli "-c" switch to pass a configuration file on the command line.
5
+ - Having a Reek configuration file that is automatically found. Reek will
6
+ look for a file ending in .reek in the following places, in order:
7
+ - The current working directory
8
+ - The working directory's ancestor directories, traversing all the way up
9
+ to the root.
10
+ - Your HOME directory
11
+ Reek will check these in order and stop after the first file found.
12
12
 
13
- Scenario: No configuration
13
+ Scenario: Default configuration
14
14
  Given a smelly file called 'smelly.rb'
15
15
  When I run reek smelly.rb
16
16
  Then the exit status indicates smells
@@ -36,20 +36,6 @@ Feature: Offer different ways how to load configuration
36
36
  Then it reports no errors
37
37
  And it succeeds
38
38
 
39
- Scenario: Configuration file in the parent directory of the working directory
40
- Given a smelly file called 'smelly.rb' in a subdirectory
41
- And a masking configuration file called 'config.reek'
42
- When I run "reek smelly.rb" in the subdirectory
43
- Then it reports no errors
44
- And it succeeds
45
-
46
- Scenario: Configuration file in the HOME directory
47
- Given a smelly file called 'smelly.rb'
48
- And a masking configuration file in the HOME directory
49
- When I run reek smelly.rb
50
- Then it reports no errors
51
- And it succeeds
52
-
53
39
  Scenario: Two opposing configuration files and we stop after the first one
54
40
  Given a smelly file called 'smelly.rb' in a subdirectory
55
41
  And an enabling configuration file in the subdirectory
@@ -1,5 +1,5 @@
1
- Feature: Using reek programmatically
2
- In order to use reek from inside my program
1
+ Feature: Using Reek programmatically
2
+ In order to use Reek from inside my program
3
3
  As a developer
4
4
  I want to be able to use its classes
5
5
 
@@ -22,7 +22,7 @@ Feature: Using reek programmatically
22
22
  has the name 'm'
23
23
  """
24
24
 
25
- Scenario: Using reek's built-in report classes
25
+ Scenario: Using Reek's built-in report classes
26
26
  Given a smelly file called 'smelly.rb'
27
27
  And a file named "examine.rb" with:
28
28
  """
@@ -1,5 +1,5 @@
1
1
  Feature: Report smells using simple JSON layout
2
- In order to parse reek's output simply and consistently, simply
2
+ In order to parse Reek's output simply and consistently, simply
3
3
  output a list of smells in JSON.
4
4
 
5
5
  Scenario: output is empty when there are no smells
@@ -1,7 +1,7 @@
1
1
  Feature: Correctly formatted reports
2
- In order to get the most out of reek
2
+ In order to get the most out of Reek
3
3
  As a developer
4
- I want to be able to parse reek's output simply and consistently
4
+ I want to be able to parse Reek's output simply and consistently
5
5
 
6
6
  Scenario Outline: two reports run together with indented smells
7
7
  Given a directory called 'smelly' containing two smelly files
@@ -1,5 +1,5 @@
1
1
  Feature: Report smells using simple YAML layout
2
- In order to parse reek's output simply and consistently, simply
2
+ In order to parse Reek's output simply and consistently, simply
3
3
  output a list of smells in Yaml.
4
4
 
5
5
  Scenario: output is empty when there are no smells
@@ -1,500 +1,19 @@
1
1
  require_relative 'reference_collector'
2
2
 
3
- module Reek
4
- module AST
5
- #
6
- # Extension modules providing utility methods to ASTNode objects, depending
7
- # on their type.
8
- #
9
- module SexpExtensions
10
- # Base module for utility methods for argument nodes.
11
- module ArgNodeBase
12
- def name
13
- children.first
14
- end
15
-
16
- # Other is a symbol?
17
- def ==(other)
18
- name == other
19
- end
20
-
21
- def marked_unused?
22
- plain_name.start_with?('_')
23
- end
24
-
25
- def plain_name
26
- name.to_s
27
- end
28
-
29
- def block?
30
- false
31
- end
32
-
33
- def optional_argument?
34
- false
35
- end
36
-
37
- def anonymous_splat?
38
- false
39
- end
40
-
41
- def components
42
- [self]
43
- end
44
- end
45
-
46
- # Utility methods for :arg nodes.
47
- module ArgNode
48
- include ArgNodeBase
49
- end
50
-
51
- # Utility methods for :kwarg nodes.
52
- module KwargNode
53
- include ArgNodeBase
54
- end
55
-
56
- # Utility methods for :optarg nodes.
57
- module OptargNode
58
- include ArgNodeBase
59
-
60
- def optional_argument?
61
- true
62
- end
63
- end
64
-
65
- # Utility methods for :kwoptarg nodes.
66
- module KwoptargNode
67
- include ArgNodeBase
68
-
69
- def optional_argument?
70
- true
71
- end
72
- end
73
-
74
- # Utility methods for :blockarg nodes.
75
- module BlockargNode
76
- include ArgNodeBase
77
- def block?
78
- true
79
- end
80
- end
81
-
82
- # Utility methods for :restarg nodes.
83
- module RestargNode
84
- include ArgNodeBase
85
- def anonymous_splat?
86
- !name
87
- end
88
- end
89
-
90
- # Utility methods for :kwrestarg nodes.
91
- module KwrestargNode
92
- include ArgNodeBase
93
- def anonymous_splat?
94
- !name
95
- end
96
- end
97
-
98
- # Utility methods for :shadowarg nodes.
99
- module ShadowargNode
100
- include ArgNodeBase
101
- end
102
-
103
- # Base module for utility methods for nodes that can contain argument
104
- # nodes nested through :mlhs nodes.
105
- module NestedAssignables
106
- def components
107
- children.flat_map(&:components)
108
- end
109
- end
110
-
111
- # Utility methods for :args nodes.
112
- module ArgsNode
113
- include NestedAssignables
114
- end
115
-
116
- # Utility methods for :mlhs nodes.
117
- module MlhsNode
118
- include NestedAssignables
119
- end
120
-
121
- # Base module for utility methods for :and and :or nodes.
122
- module LogicOperatorBase
123
- def condition() children.first end
124
-
125
- def body_nodes(type, ignoring = [])
126
- children[1].find_nodes type, ignoring
127
- end
128
- end
129
-
130
- # Utility methods for :and nodes.
131
- module AndNode
132
- include LogicOperatorBase
133
- end
134
-
135
- # Utility methods for :or nodes.
136
- module OrNode
137
- include LogicOperatorBase
138
- end
139
-
140
- # Utility methods for :attrasgn nodes.
141
- module AttrasgnNode
142
- def args() children[2] end
143
- end
144
-
145
- # Utility methods for :case nodes.
146
- module CaseNode
147
- def condition() children.first end
148
-
149
- def body_nodes(type, ignoring = [])
150
- children[1..-1].compact.flat_map { |child| child.find_nodes(type, ignoring) }
151
- end
152
-
153
- def else_body
154
- children.last
155
- end
156
- end
157
-
158
- # Utility methods for :when nodes.
159
- module WhenNode
160
- def condition_list
161
- children[0..-2]
162
- end
163
-
164
- def body
165
- children.last
166
- end
167
- end
168
-
169
- # Utility methods for :send nodes.
170
- module SendNode
171
- def receiver; children.first; end
172
- def method_name() children[1]; end
173
- def args() children[2..-1] end
174
-
175
- def participants
176
- ([receiver] + args).compact
177
- end
178
-
179
- def arg_names
180
- args.map { |arg| arg.children.first }
181
- end
182
-
183
- def module_creation_call?
184
- object_creation_call? && module_creation_receiver?
185
- end
186
-
187
- def module_creation_receiver?
188
- receiver && [:Class, :Struct].include?(receiver.simple_name)
189
- end
190
-
191
- def object_creation_call?
192
- method_name == :new
193
- end
194
-
195
- def visibility_modifier?
196
- VISIBILITY_MODIFIERS.include?(method_name)
197
- end
198
-
199
- def attribute_writer?
200
- ATTR_DEFN_METHODS.include?(method_name) ||
201
- attr_with_writable_flag?
202
- end
203
-
204
- # Handles the case where we create an attribute writer via:
205
- # attr :foo, true
206
- def attr_with_writable_flag?
207
- method_name == :attr && args.any? && args.last.type == :true
208
- end
209
-
210
- VISIBILITY_MODIFIERS = [:private, :public, :protected, :module_function]
211
- ATTR_DEFN_METHODS = [:attr_writer, :attr_accessor]
212
- end
213
-
214
- Op_AsgnNode = SendNode
215
-
216
- # Base module for utility methods for nodes representing variables.
217
- module VariableBase
218
- def name() children.first end
219
- end
220
-
221
- # Utility methods for :cvar nodes.
222
- module CvarNode
223
- include VariableBase
224
- end
225
-
226
- CvasgnNode = CvarNode
227
- CvdeclNode = CvarNode
228
-
229
- # Utility methods for :ivar nodes.
230
- module IvarNode
231
- include VariableBase
232
- end
233
-
234
- # Utility methods for :ivasgn nodes.
235
- module IvasgnNode
236
- include VariableBase
237
- end
238
-
239
- # Utility methods for :lvar nodes.
240
- module LvarNode
241
- include VariableBase
242
-
243
- alias_method :simple_name, :name
244
- alias_method :var_name, :name
245
- end
246
-
247
- LvasgnNode = LvarNode
248
-
249
- # Base module for utility methods for :def and :defs nodes.
250
- module MethodNodeBase
251
- def arguments
252
- parameters.reject(&:block?)
253
- end
254
-
255
- def arg_names
256
- arguments.map(&:name)
257
- end
258
-
259
- def parameters
260
- argslist.components
261
- end
262
-
263
- def parameter_names
264
- parameters.map(&:name)
265
- end
266
-
267
- def name_without_bang
268
- name.to_s.chop
269
- end
270
-
271
- def ends_with_bang?
272
- name[-1] == '!'
273
- end
274
-
275
- def body_nodes(types, ignoring = [])
276
- if body
277
- body.find_nodes(types, ignoring)
278
- else
279
- []
280
- end
281
- end
282
- end
283
-
284
- # Checking if a method is a singleton method.
285
- module SingletonMethod
286
- def singleton_method?
287
- singleton_method_via_class_self_notation?
288
- end
289
-
290
- # Ruby allows us to make a method a singleton_method using the
291
- # class << self syntax.
292
- #
293
- # To check for this we check if the parent node is of type :sclass.
294
- #
295
- # @return [Boolean]
296
- def singleton_method_via_class_self_notation?
297
- return unless parent
298
- parent.type == :sclass
299
- end
300
- end
301
-
302
- # Utility methods for :def nodes.
303
- module DefNode
304
- def name() children.first end
305
- def argslist() children[1] end
306
-
307
- def body
308
- children[2]
309
- end
310
-
311
- def full_name(outer)
312
- prefix = outer == '' ? '' : "#{outer}#"
313
- "#{prefix}#{name}"
314
- end
315
-
316
- def depends_on_instance?
317
- ReferenceCollector.new(self).num_refs_to_self > 0
318
- end
319
-
320
- include MethodNodeBase
321
- include SingletonMethod
322
- end
323
-
324
- # Utility methods for :defs nodes.
325
- module DefsNode
326
- def receiver() children.first end
327
- def name() children[1] end
328
- def argslist() children[2] end
329
-
330
- def body
331
- children[3]
332
- end
333
-
334
- include MethodNodeBase
335
-
336
- def full_name(outer)
337
- prefix = outer == '' ? '' : "#{outer}#"
338
- "#{prefix}#{SexpFormatter.format(receiver)}.#{name}"
339
- end
340
-
341
- def depends_on_instance?
342
- false
343
- end
344
- end
345
-
346
- # Utility methods for :if nodes.
347
- module IfNode
348
- def condition() children.first end
349
-
350
- def body_nodes(type, ignoring = [])
351
- children[1..-1].compact.flat_map { |child| child.find_nodes(type, ignoring) }
352
- end
353
- end
354
-
355
- # Utility methods for :block nodes.
356
- module BlockNode
357
- def call() children.first end
358
- def args() children[1] end
359
- def block() children[2] end
360
- def parameters() children[1] || [] end
361
-
362
- def parameter_names
363
- parameters.children
364
- end
365
-
366
- def simple_name
367
- :block
368
- end
369
-
370
- def without_block_arguments?
371
- args.components.empty?
372
- end
373
- end
374
-
375
- # Utility methods for :lit nodes.
376
- module LitNode
377
- def value() children.first end
378
- end
379
-
380
- # Utility methods for :const nodes.
381
- module ConstNode
382
- def simple_name
383
- children.last
384
- end
385
- end
386
-
387
- # Base module for utility methods for module nodes.
388
- module ModuleNodeBase
389
- # The full name of the module or class, including the name of any
390
- # module or class it is nested inside of.
391
- #
392
- # For example, given code like this:
393
- #
394
- # module Foo
395
- # class Bar::Baz
396
- # end
397
- # end
398
- #
399
- # The full name for the inner class will be 'Foo::Bar::Baz'. To return
400
- # the correct name, the name of the outer context has to be passed into this method.
401
- #
402
- # @param outer [String] full name of the wrapping module or class
403
- # @return the module's full name
404
- def full_name(outer)
405
- prefix = outer == '' ? '' : "#{outer}::"
406
- "#{prefix}#{name}"
407
- end
408
-
409
- # The final section of the module or class name. For example, for a
410
- # module with name 'Foo::Bar' this will return 'Bar'; for a module with
411
- # name 'Foo' this will return 'Foo'.
412
- #
413
- # @return [String] the final section of the name
414
- def simple_name
415
- name.split('::').last
416
- end
417
- end
418
-
419
- # Utility methods for :module nodes.
420
- module ModuleNode
421
- include ModuleNodeBase
422
-
423
- # @return [String] name as given in the module statement
424
- def name
425
- SexpFormatter.format(children.first)
426
- end
427
- end
428
-
429
- # Utility methods for :class nodes.
430
- module ClassNode
431
- include ModuleNode
432
- def superclass() children[1] end
433
- end
434
-
435
- # Utility methods for :casgn nodes.
436
- module CasgnNode
437
- include ModuleNodeBase
438
-
439
- def defines_module?
440
- return false unless value
441
- call = case value.type
442
- when :block
443
- value.call
444
- when :send
445
- value
446
- end
447
- call && call.module_creation_call?
448
- end
449
-
450
- def name
451
- SexpFormatter.format(children[1])
452
- end
453
-
454
- # there are two valid forms of the casgn sexp
455
- # (casgn <namespace> <name> <value>) and
456
- # (casgn <namespace> <name>) used in or-asgn and mlhs
457
- #
458
- # source = "class Hi; THIS ||= 3; end"
459
- # (class
460
- # (const nil :Hi) nil
461
- # (or-asgn
462
- # (casgn nil :THIS)
463
- # (int 3)))
464
- def value
465
- children[2]
466
- end
467
- end
468
-
469
- # Utility methods for :yield nodes.
470
- module YieldNode
471
- def args() children end
472
-
473
- def arg_names
474
- args.map { |arg| arg[1] }
475
- end
476
- end
477
-
478
- # Utility methods for :super nodes.
479
- module SuperNode
480
- def method_name
481
- :super
482
- end
483
- end
484
-
485
- ZsuperNode = SuperNode
486
-
487
- # Utility methods for :sym nodes.
488
- module SymNode
489
- def name
490
- children.first
491
- end
492
-
493
- def full_name(outer)
494
- prefix = outer == '' ? '' : "#{outer}#"
495
- "#{prefix}#{name}"
496
- end
497
- end
498
- end
499
- end
500
- end
3
+ require_relative 'sexp_extensions/arguments'
4
+ require_relative 'sexp_extensions/attribute_assignments'
5
+ require_relative 'sexp_extensions/block'
6
+ require_relative 'sexp_extensions/case'
7
+ require_relative 'sexp_extensions/constant'
8
+ require_relative 'sexp_extensions/if'
9
+ require_relative 'sexp_extensions/literal'
10
+ require_relative 'sexp_extensions/logical_operators'
11
+ require_relative 'sexp_extensions/methods'
12
+ require_relative 'sexp_extensions/module'
13
+ require_relative 'sexp_extensions/nested_assignables'
14
+ require_relative 'sexp_extensions/send'
15
+ require_relative 'sexp_extensions/super'
16
+ require_relative 'sexp_extensions/symbols'
17
+ require_relative 'sexp_extensions/variables'
18
+ require_relative 'sexp_extensions/when'
19
+ require_relative 'sexp_extensions/yield'