reek 3.3.0 → 3.3.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/.gitignore +1 -0
- data/.rubocop.yml +2 -2
- data/.travis.yml +3 -2
- data/CHANGELOG.md +7 -1
- data/config/defaults.reek +2 -1
- data/docs/API.md +102 -25
- data/docs/Code-Smells.md +2 -2
- data/docs/Nested-Iterators.md +1 -0
- data/docs/Too-Many-Methods.md +1 -1
- data/lib/reek/ast/object_refs.rb +1 -0
- data/lib/reek/cli/option_interpreter.rb +1 -1
- data/lib/reek/code_comment.rb +3 -0
- data/lib/reek/context/code_context.rb +1 -1
- data/lib/reek/examiner.rb +2 -0
- data/lib/reek/rake/task.rb +10 -1
- data/lib/reek/report/formatter.rb +2 -2
- data/lib/reek/report/report.rb +10 -13
- data/lib/reek/smells/attribute.rb +1 -1
- data/lib/reek/smells/nested_iterators.rb +1 -1
- data/lib/reek/smells/nil_check.rb +1 -1
- data/lib/reek/smells/smell_detector.rb +1 -1
- data/lib/reek/smells/smell_warning.rb +7 -5
- data/lib/reek/source/source_code.rb +1 -1
- data/lib/reek/spec.rb +1 -1
- data/lib/reek/spec/should_reek.rb +1 -1
- data/lib/reek/tree_dresser.rb +19 -4
- data/lib/reek/version.rb +1 -1
- data/spec/reek/ast/node_spec.rb +5 -5
- data/spec/reek/ast/sexp_extensions_spec.rb +41 -41
- data/spec/reek/ast/sexp_formatter_spec.rb +9 -9
- data/spec/reek/context/code_context_spec.rb +7 -7
- data/spec/reek/context/method_context_spec.rb +9 -9
- data/spec/reek/context/singleton_method_context_spec.rb +2 -2
- data/spec/reek/report/html_report_spec.rb +2 -1
- data/spec/reek/smells/class_variable_spec.rb +2 -2
- data/spec/reek/smells/nested_iterators_spec.rb +5 -0
- data/spec/reek/source/source_code_spec.rb +1 -1
- data/spec/reek/spec/should_reek_spec.rb +1 -1
- data/spec/reek/tree_dresser_spec.rb +41 -7
- data/spec/spec_helper.rb +1 -7
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 18055c0f9c08fb0e795cb4417885156291c9f5b7
|
4
|
+
data.tar.gz: b2d41cb4510dd092450c82bae4664bbbb7a10d50
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 92722d3bdd09267e2c5858414b6f91cf066a6f9c3596033a3845d1c2d7cd768d17eb29e932af6d7ea8a432081f77b6f77092051288903b0377f11f6137c292ff
|
7
|
+
data.tar.gz: 0124c0f5b7d1c4f0f580b545757d1f94d51c2f93310b2dfe922abaa9ef241fc91a4ddadbad07832d6d5e92e99b0d4186b70f194f54f68f995693fbc70afc15e5
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -14,9 +14,9 @@ Metrics/ClassLength:
|
|
14
14
|
Metrics/MethodLength:
|
15
15
|
Max: 15
|
16
16
|
|
17
|
-
# Be
|
17
|
+
# Be rather lenient with line length
|
18
18
|
Metrics/LineLength:
|
19
|
-
Max:
|
19
|
+
Max: 120
|
20
20
|
|
21
21
|
# Indent one level for follow-up lines
|
22
22
|
Style/MultilineOperationIndentation:
|
data/.travis.yml
CHANGED
@@ -20,11 +20,12 @@ matrix:
|
|
20
20
|
allow_failures:
|
21
21
|
- rvm: jruby
|
22
22
|
- rvm: jruby-head
|
23
|
+
- rvm: rbx-2
|
23
24
|
- rvm: ruby-head
|
24
25
|
fast_finish: true
|
25
26
|
notifications:
|
26
|
-
|
27
|
+
email:
|
27
28
|
- timo.roessner@googlemail.com
|
28
29
|
- matijs@matijs.net
|
29
30
|
- chastell@chastell.net
|
30
|
-
irc:
|
31
|
+
irc: irc.freenode.org#reek
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,12 @@
|
|
2
2
|
|
3
3
|
## Unreleased
|
4
4
|
|
5
|
+
## 3.3.1 (2015-09-03)
|
6
|
+
|
7
|
+
* (troessner) Fix file list as argument in rake task
|
8
|
+
* (troessner) Ignore `Object#tap` for NestedIterators
|
9
|
+
* (mvz) Ensure all YAML methods are loaded (workaround for #653)
|
10
|
+
|
5
11
|
## 3.3.0 (2015-08-23)
|
6
12
|
|
7
13
|
* (HParker / Adam Hess) add support for or-assign constants
|
@@ -9,7 +15,7 @@
|
|
9
15
|
|
10
16
|
## 3.2.1 (2015-08-17)
|
11
17
|
|
12
|
-
* Revert 864f0a9 to hotfix
|
18
|
+
* (troessner) Revert 864f0a9 to hotfix #642
|
13
19
|
|
14
20
|
## 3.2.0 (2015-08-17)
|
15
21
|
|
data/config/defaults.reek
CHANGED
data/docs/API.md
CHANGED
@@ -1,29 +1,35 @@
|
|
1
1
|
# Using `reek` inside your Ruby application
|
2
2
|
|
3
|
-
|
3
|
+
## Installation
|
4
|
+
|
5
|
+
Either standalone via
|
4
6
|
|
5
7
|
```bash
|
6
8
|
gem install reek
|
7
9
|
```
|
8
10
|
|
9
|
-
|
11
|
+
or by adding
|
12
|
+
|
13
|
+
```
|
14
|
+
gem 'reek'
|
15
|
+
```
|
16
|
+
|
17
|
+
to your Gemfile.
|
18
|
+
|
19
|
+
## Quick start
|
10
20
|
|
11
|
-
|
21
|
+
Code says more than a thousand words:
|
12
22
|
|
13
23
|
```ruby
|
14
24
|
require 'reek'
|
15
25
|
|
16
|
-
source = <<-
|
26
|
+
source = <<-EOS
|
17
27
|
class Dirty
|
18
|
-
|
19
|
-
|
20
|
-
puts @screen.title
|
21
|
-
@screen = widgets.map { |w| w.each { |key| key += 3 * x } }
|
22
|
-
puts @screen.contents
|
23
|
-
fail
|
28
|
+
def m(a,b,c)
|
29
|
+
puts a,b
|
24
30
|
end
|
25
31
|
end
|
26
|
-
|
32
|
+
EOS
|
27
33
|
|
28
34
|
reporter = Reek::Report::TextReport.new
|
29
35
|
examiner = Reek::Examiner.new(source)
|
@@ -31,16 +37,22 @@ reporter.add_examiner examiner
|
|
31
37
|
reporter.show
|
32
38
|
```
|
33
39
|
|
34
|
-
This
|
35
|
-
|
36
|
-
`Reek::Examiner.new` can take `source` as `String`, `File` or `IO`.
|
40
|
+
This would output the following on STDOUT:
|
37
41
|
|
38
42
|
```
|
39
|
-
|
40
|
-
|
43
|
+
string -- 5 warnings:
|
44
|
+
Dirty has no descriptive comment (IrresponsibleModule)
|
45
|
+
Dirty#m has the name 'm' (UncommunicativeMethodName)
|
46
|
+
Dirty#m has the parameter name 'a' (UncommunicativeParameterName)
|
47
|
+
Dirty#m has the parameter name 'b' (UncommunicativeParameterName)
|
48
|
+
Dirty#m has unused parameter 'c' (UnusedParameters)
|
41
49
|
```
|
42
50
|
|
43
|
-
|
51
|
+
Note that `Reek::Examiner.new` can take `source` as `String`, `Pathname`, `File` or `IO`.
|
52
|
+
|
53
|
+
## Choosing your output format
|
54
|
+
|
55
|
+
Besides normal text output, `reek` can generate output in YAML,
|
44
56
|
JSON, HTML and XML by using the following Report types:
|
45
57
|
|
46
58
|
```
|
@@ -51,6 +63,78 @@ HTMLReport
|
|
51
63
|
XMLReport
|
52
64
|
```
|
53
65
|
|
66
|
+
## Configuration
|
67
|
+
|
68
|
+
Given you have the following configuration file called `config.reek` in your root directory:
|
69
|
+
|
70
|
+
```Yaml
|
71
|
+
---
|
72
|
+
IrresponsibleModule:
|
73
|
+
enabled: false
|
74
|
+
```
|
75
|
+
|
76
|
+
You can now use either
|
77
|
+
|
78
|
+
```Ruby
|
79
|
+
Reek::Configuration::AppConfiguration.from_path Pathname.new('config.reek`)
|
80
|
+
```
|
81
|
+
|
82
|
+
but you can also pass a hash via `Reek::Configuration::AppConfiguration.from_map`.
|
83
|
+
|
84
|
+
This hash can have the following 3 keys:
|
85
|
+
|
86
|
+
1.) directory_directives [Hash] for instance:
|
87
|
+
|
88
|
+
```Ruby
|
89
|
+
{ Pathname("spec/samples/three_clean_files/") =>
|
90
|
+
{ Reek::Smells::UtilityFunction => { "enabled" => false } } }
|
91
|
+
```
|
92
|
+
|
93
|
+
2.) default_directive [Hash] for instance:
|
94
|
+
|
95
|
+
```Ruby
|
96
|
+
{ Reek::Smells::IrresponsibleModule => { "enabled" => false } }
|
97
|
+
```
|
98
|
+
|
99
|
+
3.) excluded_paths [Array] for instance:
|
100
|
+
|
101
|
+
```Ruby
|
102
|
+
[ Pathname('spec/samples/two_smelly_files') ]
|
103
|
+
```
|
104
|
+
|
105
|
+
Given the example above you should load that as "default directive" which means that it will
|
106
|
+
be the default configuration for smell types for which there is
|
107
|
+
no "directory directive" (so a directory-specific configuration):
|
108
|
+
|
109
|
+
```Ruby
|
110
|
+
require 'reek'
|
111
|
+
|
112
|
+
default_directive = { Reek::Smells::IrresponsibleModule => { 'enabled' => false } }
|
113
|
+
configuration = Reek::Configuration::AppConfiguration.from_map default_directive: default_directive
|
114
|
+
|
115
|
+
source = <<-EOS
|
116
|
+
class Dirty
|
117
|
+
def call_me(a,b)
|
118
|
+
puts a,b
|
119
|
+
end
|
120
|
+
end
|
121
|
+
EOS
|
122
|
+
|
123
|
+
reporter = Reek::Report::TextReport.new
|
124
|
+
examiner = Reek::Examiner.new(source, configuration: configuration); nil
|
125
|
+
reporter.add_examiner examiner; nil
|
126
|
+
reporter.show
|
127
|
+
```
|
128
|
+
|
129
|
+
This would now only report the `UncommunicativeParameterName` but not the `IrresponsibleModule`
|
130
|
+
for the `Dirty` class:
|
131
|
+
|
132
|
+
```
|
133
|
+
string -- 2 warnings:
|
134
|
+
Dirty#call_me has the parameter name 'a' (UncommunicativeParameterName)
|
135
|
+
Dirty#call_me has the parameter name 'b' (UncommunicativeParameterName)
|
136
|
+
```
|
137
|
+
|
54
138
|
## Accessing the smell warnings directly
|
55
139
|
|
56
140
|
You can also access the smells detected by an examiner directly:
|
@@ -59,14 +143,7 @@ You can also access the smells detected by an examiner directly:
|
|
59
143
|
require 'reek'
|
60
144
|
|
61
145
|
source = <<-END
|
62
|
-
class
|
63
|
-
# This method smells of :reek:NestedIterators but ignores them
|
64
|
-
def awful(x, y, offset = 0, log = false)
|
65
|
-
puts @screen.title
|
66
|
-
@screen = widgets.map { |w| w.each { |key| key += 3 * x } }
|
67
|
-
puts @screen.contents
|
68
|
-
fail
|
69
|
-
end
|
146
|
+
class C
|
70
147
|
end
|
71
148
|
END
|
72
149
|
|
data/docs/Code-Smells.md
CHANGED
@@ -4,7 +4,7 @@ Smells are indicators of where your code might be hard to read, maintain or evol
|
|
4
4
|
|
5
5
|
Reek currently includes checks for the following smells:
|
6
6
|
|
7
|
-
* [Attribute](Attribute.md)
|
7
|
+
* [Attribute](Attribute.md)
|
8
8
|
* [Class Variable](Class-Variable.md)
|
9
9
|
* [Control Couple](Control-Couple.md), including
|
10
10
|
* [Boolean Parameter](Boolean-Parameter.md)
|
@@ -31,4 +31,4 @@ Reek currently includes checks for the following smells:
|
|
31
31
|
* [Uncommunicative Module Name](Uncommunicative-Module-Name.md)
|
32
32
|
* [Uncommunicative Parameter Name](Uncommunicative-Parameter-Name.md)
|
33
33
|
* [Uncommunicative Variable Name](Uncommunicative-Variable-Name.md)
|
34
|
-
* [Unused Parameters](Unused-Parameters.md)
|
34
|
+
* [Unused Parameters](Unused-Parameters.md)
|
data/docs/Nested-Iterators.md
CHANGED
data/docs/Too-Many-Methods.md
CHANGED
@@ -52,4 +52,4 @@ would cause reek to emit the same warning as in the example above.
|
|
52
52
|
|
53
53
|
| Option | Value | Effect |
|
54
54
|
| ---------------|-------------|---------|
|
55
|
-
| max_methods | integer | The maximum number of methods that are permitted. Defaults to
|
55
|
+
| max_methods | integer | The maximum number of methods that are permitted. Defaults to 15 |
|
data/lib/reek/ast/object_refs.rb
CHANGED
data/lib/reek/code_comment.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
require 'yaml'
|
2
2
|
require 'private_attr/everywhere'
|
3
3
|
|
4
|
+
# NOTE: Work-around for https://github.com/tenderlove/psych/issues/223
|
5
|
+
require 'psych.rb' if Object.const_defined?(:Psych)
|
6
|
+
|
4
7
|
module Reek
|
5
8
|
#
|
6
9
|
# A comment header from an abstract syntax tree; found directly above
|
@@ -137,7 +137,7 @@ module Reek
|
|
137
137
|
#
|
138
138
|
# @param visibility [Symbol]
|
139
139
|
# @param names [Array<Symbol>]
|
140
|
-
def track_visibility(visibility, names
|
140
|
+
def track_visibility(visibility, names)
|
141
141
|
if names.any?
|
142
142
|
children.each do |child|
|
143
143
|
child.visibility = visibility if names.include? child.name
|
data/lib/reek/examiner.rb
CHANGED
@@ -24,6 +24,8 @@ module Reek
|
|
24
24
|
# @param filter_by_smells [Array<String>]
|
25
25
|
# List of smell types to filter by.
|
26
26
|
#
|
27
|
+
# @param configuration [Configuration::AppConfiguration]
|
28
|
+
# The configuration for this Examiner.
|
27
29
|
def initialize(source,
|
28
30
|
filter_by_smells = [],
|
29
31
|
configuration: Configuration::AppConfiguration.default)
|
data/lib/reek/rake/task.rb
CHANGED
@@ -44,7 +44,7 @@ module Reek
|
|
44
44
|
# Glob pattern to match source files.
|
45
45
|
# Setting the REEK_SRC environment variable overrides this.
|
46
46
|
# Defaults to 'lib/**/*.rb'.
|
47
|
-
|
47
|
+
attr_reader :source_files
|
48
48
|
|
49
49
|
# String containing commandline options to be passed to Reek.
|
50
50
|
# Setting the REEK_OPTS environment variable overrides this value.
|
@@ -71,10 +71,19 @@ module Reek
|
|
71
71
|
define_task
|
72
72
|
end
|
73
73
|
|
74
|
+
def source_files=(files)
|
75
|
+
raise ArgumentError, no_string_given_for_file_list_warning unless files.is_a?(String)
|
76
|
+
@source_files = FileList[files]
|
77
|
+
end
|
78
|
+
|
74
79
|
private
|
75
80
|
|
76
81
|
private_attr_reader :fail_on_error, :name, :verbose
|
77
82
|
|
83
|
+
def no_string_given_for_file_list_warning
|
84
|
+
"File list should be a String that can contain a glob pattern, e.g. '{app,lib,spec}/**/*.rb'"
|
85
|
+
end
|
86
|
+
|
78
87
|
def define_task
|
79
88
|
desc 'Check for code smells'
|
80
89
|
task(name) { run_task }
|
@@ -10,7 +10,7 @@ module Reek
|
|
10
10
|
#
|
11
11
|
# @api private
|
12
12
|
module Formatter
|
13
|
-
def self.format_list(warnings, formatter
|
13
|
+
def self.format_list(warnings, formatter: SimpleWarningFormatter.new)
|
14
14
|
warnings.map do |warning|
|
15
15
|
" #{formatter.format warning}"
|
16
16
|
end.join("\n")
|
@@ -31,7 +31,7 @@ module Reek
|
|
31
31
|
#
|
32
32
|
# @api private
|
33
33
|
class SimpleWarningFormatter
|
34
|
-
def initialize(location_formatter
|
34
|
+
def initialize(location_formatter: BlankLocationFormatter)
|
35
35
|
@location_formatter = location_formatter
|
36
36
|
end
|
37
37
|
|
data/lib/reek/report/report.rb
CHANGED
@@ -16,13 +16,15 @@ module Reek
|
|
16
16
|
# @api private
|
17
17
|
WARNINGS_COLOR = :red
|
18
18
|
|
19
|
-
def initialize(
|
19
|
+
def initialize(heading_formatter: HeadingFormatter::Quiet,
|
20
|
+
report_formatter: Formatter, sort_by_issue_count: false,
|
21
|
+
warning_formatter: SimpleWarningFormatter.new)
|
20
22
|
@examiners = []
|
23
|
+
@heading_formatter = heading_formatter.new(report_formatter)
|
24
|
+
@report_formatter = report_formatter
|
25
|
+
@sort_by_issue_count = sort_by_issue_count
|
21
26
|
@total_smell_count = 0
|
22
|
-
@
|
23
|
-
@warning_formatter = options.fetch :warning_formatter, SimpleWarningFormatter.new
|
24
|
-
@report_formatter = options.fetch :report_formatter, Formatter
|
25
|
-
@sort_by_issue_count = options.fetch :sort_by_issue_count, false
|
27
|
+
@warning_formatter = warning_formatter
|
26
28
|
end
|
27
29
|
|
28
30
|
# Add Examiner to report on. The report will output results for all
|
@@ -56,7 +58,7 @@ module Reek
|
|
56
58
|
|
57
59
|
private
|
58
60
|
|
59
|
-
private_attr_reader :examiners, :
|
61
|
+
private_attr_reader :examiners, :heading_formatter, :report_formatter,
|
60
62
|
:sort_by_issue_count, :warning_formatter
|
61
63
|
end
|
62
64
|
|
@@ -89,7 +91,7 @@ module Reek
|
|
89
91
|
result = heading_formatter.header(examiner)
|
90
92
|
if examiner.smelly?
|
91
93
|
formatted_list = report_formatter.format_list(examiner.smells,
|
92
|
-
warning_formatter)
|
94
|
+
formatter: warning_formatter)
|
93
95
|
result += ":\n#{formatted_list}"
|
94
96
|
end
|
95
97
|
result
|
@@ -104,11 +106,6 @@ module Reek
|
|
104
106
|
s = total_smell_count == 1 ? '' : 's'
|
105
107
|
Rainbow("#{total_smell_count} total warning#{s}\n").color(colour)
|
106
108
|
end
|
107
|
-
|
108
|
-
def heading_formatter
|
109
|
-
@heading_formatter ||=
|
110
|
-
options.fetch(:heading_formatter, HeadingFormatter::Quiet).new(report_formatter)
|
111
|
-
end
|
112
109
|
end
|
113
110
|
|
114
111
|
#
|
@@ -139,7 +136,7 @@ module Reek
|
|
139
136
|
class HTMLReport < Base
|
140
137
|
require 'erb'
|
141
138
|
|
142
|
-
def show(target_path
|
139
|
+
def show(target_path: Pathname.new('reek.html'))
|
143
140
|
template_path = Pathname.new("#{__dir__}/html_report.html.erb")
|
144
141
|
File.write target_path, ERB.new(template_path.read).result(binding)
|
145
142
|
puts 'HTML file saved'
|
@@ -19,7 +19,7 @@ module Reek
|
|
19
19
|
# The name of the config field that sets the names of any
|
20
20
|
# methods for which nesting should not be considered
|
21
21
|
IGNORE_ITERATORS_KEY = 'ignore_iterators'
|
22
|
-
DEFAULT_IGNORE_ITERATORS = []
|
22
|
+
DEFAULT_IGNORE_ITERATORS = ['tap']
|
23
23
|
|
24
24
|
def self.default_config
|
25
25
|
super.merge(
|
@@ -11,12 +11,14 @@ module Reek
|
|
11
11
|
attr_reader :context, :lines, :message, :parameters, :smell_detector
|
12
12
|
def_delegators :smell_detector, :smell_category, :smell_type, :source
|
13
13
|
|
14
|
-
|
14
|
+
# FIXME: switch to required kwargs when dropping Ruby 2.0 compatibility
|
15
|
+
def initialize(smell_detector, context: '', lines: raise, message: raise,
|
16
|
+
parameters: {})
|
15
17
|
@smell_detector = smell_detector
|
16
|
-
@context =
|
17
|
-
@lines =
|
18
|
-
@message =
|
19
|
-
@parameters =
|
18
|
+
@context = context.to_s
|
19
|
+
@lines = lines
|
20
|
+
@message = message
|
21
|
+
@parameters = parameters
|
20
22
|
end
|
21
23
|
|
22
24
|
def hash
|
@@ -23,7 +23,7 @@ module Reek
|
|
23
23
|
# code - Ruby code as String
|
24
24
|
# description - 'STDIN', 'string' or a filepath as String
|
25
25
|
# parser - the parser to use for generating AST's out of the given source
|
26
|
-
def initialize(code, description, parser
|
26
|
+
def initialize(code, description, parser: Parser::Ruby22)
|
27
27
|
@source = code
|
28
28
|
@description = description
|
29
29
|
@parser = parser
|
data/lib/reek/spec.rb
CHANGED
@@ -106,7 +106,7 @@ module Reek
|
|
106
106
|
# Returns +true+ if and only if the target source code contains smells.
|
107
107
|
#
|
108
108
|
def reek(configuration = Configuration::AppConfiguration.default)
|
109
|
-
ShouldReek.new configuration
|
109
|
+
ShouldReek.new(configuration: configuration)
|
110
110
|
end
|
111
111
|
end
|
112
112
|
end
|
data/lib/reek/tree_dresser.rb
CHANGED
@@ -7,23 +7,38 @@ module Reek
|
|
7
7
|
#
|
8
8
|
# @api private
|
9
9
|
class TreeDresser
|
10
|
-
def initialize(klass_map
|
10
|
+
def initialize(klass_map: AST::ASTNodeClassMap.new)
|
11
11
|
@klass_map = klass_map
|
12
12
|
end
|
13
13
|
|
14
14
|
# Recursively enhance an AST with type-dependent mixins, and comments.
|
15
15
|
#
|
16
16
|
# See {file:docs/How-reek-works-internally.md} for the big picture of how this works.
|
17
|
-
#
|
17
|
+
# Example:
|
18
|
+
# This
|
19
|
+
# class Klazz; def meth(argument); argument.call_me; end; end
|
20
|
+
# corresponds to this sexp:
|
21
|
+
# (class
|
22
|
+
# (const nil :Klazz) nil
|
23
|
+
# (def :meth
|
24
|
+
# (args
|
25
|
+
# (arg :argument))
|
26
|
+
# (send
|
27
|
+
# (lvar :argument) :call_me)))
|
28
|
+
# where every node is of type Parser::AST::Node.
|
29
|
+
# Passing this into `dress` will return the exact same structure, but this
|
30
|
+
# time the nodes will contain type-dependent mixins, e.g. this:
|
31
|
+
# (const nil :Klazz)
|
32
|
+
# will be of type Reek::AST::Node with Reek::AST::SexpExtensions::ConstNode mixed in.
|
18
33
|
# @param sexp [Parser::AST::Node] - the given sexp
|
19
34
|
# @param comment_map [Hash] - see the documentation for SourceCode#syntax_tree
|
20
35
|
# @param parent [Parser::AST::Node] - the parent sexp
|
21
36
|
#
|
22
37
|
# @return an instance of Reek::AST::Node with type-dependent sexp extensions mixed in.
|
23
|
-
def dress(sexp, comment_map, parent
|
38
|
+
def dress(sexp, comment_map, parent: nil)
|
24
39
|
return sexp unless sexp.is_a? ::Parser::AST::Node
|
25
40
|
type = sexp.type
|
26
|
-
children = sexp.children.map { |child| dress(child, comment_map, sexp) }
|
41
|
+
children = sexp.children.map { |child| dress(child, comment_map, parent: sexp) }
|
27
42
|
comments = comment_map[sexp]
|
28
43
|
klass_map.klass_for(type).new(type, children,
|
29
44
|
location: sexp.loc, comments: comments, parent: parent)
|
data/lib/reek/version.rb
CHANGED
data/spec/reek/ast/node_spec.rb
CHANGED
@@ -4,20 +4,20 @@ require_relative '../../../lib/reek/ast/node'
|
|
4
4
|
RSpec.describe Reek::AST::Node do
|
5
5
|
context 'format' do
|
6
6
|
it 'formats self' do
|
7
|
-
expect(
|
7
|
+
expect(sexp(:self).format_to_ruby).to eq('self')
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
11
|
context 'hash' do
|
12
12
|
it 'hashes equal for equal sexps' do
|
13
|
-
node1 =
|
14
|
-
node2 =
|
13
|
+
node1 = sexp(:def, :jim, sexp(:args), sexp(:send, sexp(:int, 4), :+, sexp(:send, nil, :fred)))
|
14
|
+
node2 = sexp(:def, :jim, sexp(:args), sexp(:send, sexp(:int, 4), :+, sexp(:send, nil, :fred)))
|
15
15
|
expect(node1.hash).to eq(node2.hash)
|
16
16
|
end
|
17
17
|
|
18
18
|
it 'hashes diferent for diferent sexps' do
|
19
|
-
node1 =
|
20
|
-
node2 =
|
19
|
+
node1 = sexp(:def, :jim, sexp(:args), sexp(:send, sexp(:int, 4), :+, sexp(:send, nil, :fred)))
|
20
|
+
node2 = sexp(:def, :jim, sexp(:args), sexp(:send, sexp(:int, 3), :+, sexp(:send, nil, :fred)))
|
21
21
|
expect(node1.hash).not_to eq(node2.hash)
|
22
22
|
end
|
23
23
|
end
|
@@ -3,7 +3,7 @@ require_relative '../../../lib/reek/ast/sexp_extensions'
|
|
3
3
|
|
4
4
|
RSpec.describe Reek::AST::SexpExtensions::DefNode do
|
5
5
|
context 'with no parameters' do
|
6
|
-
let(:node) {
|
6
|
+
let(:node) { sexp(:def, :hello, sexp(:args)) }
|
7
7
|
|
8
8
|
it 'has no arg names' do
|
9
9
|
expect(node.arg_names).to eq []
|
@@ -24,8 +24,8 @@ RSpec.describe Reek::AST::SexpExtensions::DefNode do
|
|
24
24
|
|
25
25
|
context 'with 1 parameter' do
|
26
26
|
let(:node) do
|
27
|
-
|
28
|
-
|
27
|
+
sexp(:def, :hello,
|
28
|
+
sexp(:args, sexp(:arg, :param)))
|
29
29
|
end
|
30
30
|
|
31
31
|
it 'has 1 arg name' do
|
@@ -47,10 +47,10 @@ RSpec.describe Reek::AST::SexpExtensions::DefNode do
|
|
47
47
|
|
48
48
|
context 'with a block parameter' do
|
49
49
|
let(:node) do
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
50
|
+
sexp(:def, :hello,
|
51
|
+
sexp(:args,
|
52
|
+
sexp(:arg, :param),
|
53
|
+
sexp(:blockarg, :blk)))
|
54
54
|
end
|
55
55
|
|
56
56
|
it 'has 1 arg name' do
|
@@ -72,9 +72,9 @@ RSpec.describe Reek::AST::SexpExtensions::DefNode do
|
|
72
72
|
|
73
73
|
context 'with 1 defaulted parameter' do
|
74
74
|
let(:node) do
|
75
|
-
|
76
|
-
|
77
|
-
|
75
|
+
sexp(:def, :hello,
|
76
|
+
sexp(:args,
|
77
|
+
sexp(:optarg, :param, sexp(:array))))
|
78
78
|
end
|
79
79
|
|
80
80
|
it 'has 1 arg name' do
|
@@ -96,23 +96,23 @@ RSpec.describe Reek::AST::SexpExtensions::DefNode do
|
|
96
96
|
|
97
97
|
context 'with a body with 2 statements' do
|
98
98
|
let(:node) do
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
99
|
+
sexp(:def, :hello, sexp(:args),
|
100
|
+
sexp(:begin,
|
101
|
+
sexp(:first),
|
102
|
+
sexp(:second)))
|
103
103
|
end
|
104
104
|
|
105
105
|
it 'has 2 body statements' do
|
106
|
-
expect(node.body).to eq
|
106
|
+
expect(node.body).to eq sexp(:begin, sexp(:first), sexp(:second))
|
107
107
|
end
|
108
108
|
|
109
109
|
it 'finds nodes in the body with #body_nodes' do
|
110
|
-
expect(node.body_nodes([:first])).to eq [
|
110
|
+
expect(node.body_nodes([:first])).to eq [sexp(:first)]
|
111
111
|
end
|
112
112
|
end
|
113
113
|
|
114
114
|
context 'with no body' do
|
115
|
-
let(:node) {
|
115
|
+
let(:node) { sexp(:def, :hello, sexp(:args), nil) }
|
116
116
|
|
117
117
|
it 'has a body that is nil' do
|
118
118
|
expect(node.body).to be_nil
|
@@ -126,7 +126,7 @@ end
|
|
126
126
|
|
127
127
|
RSpec.describe Reek::AST::SexpExtensions::DefsNode do
|
128
128
|
context 'with no parameters' do
|
129
|
-
let(:node) {
|
129
|
+
let(:node) { sexp(:defs, sexp(:lvar, :obj), :hello, sexp(:args)) }
|
130
130
|
|
131
131
|
it 'has no arg names' do
|
132
132
|
expect(node.arg_names).to eq []
|
@@ -147,8 +147,8 @@ RSpec.describe Reek::AST::SexpExtensions::DefsNode do
|
|
147
147
|
|
148
148
|
context 'with 1 parameter' do
|
149
149
|
let(:node) do
|
150
|
-
|
151
|
-
|
150
|
+
sexp(:defs, sexp(:lvar, :obj), :hello,
|
151
|
+
sexp(:args, sexp(:arg, :param)))
|
152
152
|
end
|
153
153
|
|
154
154
|
it 'has 1 arg name' do
|
@@ -170,10 +170,10 @@ RSpec.describe Reek::AST::SexpExtensions::DefsNode do
|
|
170
170
|
|
171
171
|
context 'with a block' do
|
172
172
|
let(:node) do
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
173
|
+
sexp(:defs, sexp(:lvar, :obj), :hello,
|
174
|
+
sexp(:args,
|
175
|
+
sexp(:arg, :param),
|
176
|
+
sexp(:blockarg, :blk)))
|
177
177
|
end
|
178
178
|
|
179
179
|
it 'has 1 arg name' do
|
@@ -195,9 +195,9 @@ RSpec.describe Reek::AST::SexpExtensions::DefsNode do
|
|
195
195
|
|
196
196
|
context 'with 1 defaulted parameter' do
|
197
197
|
let(:node) do
|
198
|
-
|
199
|
-
|
200
|
-
|
198
|
+
sexp(:defs, sexp(:lvar, :obj), :hello,
|
199
|
+
sexp(:args,
|
200
|
+
sexp(:optarg, :param, sexp(:array))))
|
201
201
|
end
|
202
202
|
|
203
203
|
it 'has 1 arg name' do
|
@@ -219,21 +219,21 @@ RSpec.describe Reek::AST::SexpExtensions::DefsNode do
|
|
219
219
|
|
220
220
|
context 'with a body with 2 statements' do
|
221
221
|
let(:node) do
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
222
|
+
sexp(:defs, sexp(:self), :hello, sexp(:args),
|
223
|
+
sexp(:begin,
|
224
|
+
sexp(:first),
|
225
|
+
sexp(:second)))
|
226
226
|
end
|
227
227
|
|
228
228
|
it 'has 2 body statements' do
|
229
|
-
expect(node.body).to eq
|
229
|
+
expect(node.body).to eq sexp(:begin, sexp(:first), sexp(:second))
|
230
230
|
end
|
231
231
|
end
|
232
232
|
end
|
233
233
|
|
234
234
|
RSpec.describe Reek::AST::SexpExtensions::SendNode do
|
235
235
|
context 'with no parameters' do
|
236
|
-
let(:node) {
|
236
|
+
let(:node) { sexp(:send, nil, :hello) }
|
237
237
|
|
238
238
|
it 'has no argument names' do
|
239
239
|
expect(node.arg_names).to eq []
|
@@ -241,7 +241,7 @@ RSpec.describe Reek::AST::SexpExtensions::SendNode do
|
|
241
241
|
end
|
242
242
|
|
243
243
|
context 'with 1 literal parameter' do
|
244
|
-
let(:node) {
|
244
|
+
let(:node) { sexp(:send, nil, :hello, sexp(:lit, :param)) }
|
245
245
|
|
246
246
|
it 'has 1 argument name' do
|
247
247
|
expect(node.arg_names).to eq [:param]
|
@@ -249,7 +249,7 @@ RSpec.describe Reek::AST::SexpExtensions::SendNode do
|
|
249
249
|
end
|
250
250
|
|
251
251
|
context 'with 2 literal parameters' do
|
252
|
-
let(:node) {
|
252
|
+
let(:node) { sexp(:send, nil, :hello, sexp(:lit, :x), sexp(:lit, :y)) }
|
253
253
|
|
254
254
|
it 'has 2 argument names' do
|
255
255
|
expect(node.arg_names).to eq [:x, :y]
|
@@ -259,7 +259,7 @@ end
|
|
259
259
|
|
260
260
|
RSpec.describe Reek::AST::SexpExtensions::BlockNode do
|
261
261
|
context 'with no parameters' do
|
262
|
-
let(:node) {
|
262
|
+
let(:node) { sexp(:block, sexp(:send, nil, :map), sexp(:args), nil) }
|
263
263
|
|
264
264
|
it 'has no parameter names' do
|
265
265
|
expect(node.parameter_names).to eq []
|
@@ -267,7 +267,7 @@ RSpec.describe Reek::AST::SexpExtensions::BlockNode do
|
|
267
267
|
end
|
268
268
|
|
269
269
|
context 'with 1 parameter' do
|
270
|
-
let(:node) {
|
270
|
+
let(:node) { sexp(:block, sexp(:send, nil, :map), sexp(:args, :param), nil) }
|
271
271
|
|
272
272
|
it 'has 1 parameter name' do
|
273
273
|
expect(node.parameter_names).to eq [:param]
|
@@ -275,7 +275,7 @@ RSpec.describe Reek::AST::SexpExtensions::BlockNode do
|
|
275
275
|
end
|
276
276
|
|
277
277
|
context 'with 2 parameters' do
|
278
|
-
let(:node) {
|
278
|
+
let(:node) { sexp(:block, sexp(:send, nil, :map), sexp(:args, :x, :y), nil) }
|
279
279
|
|
280
280
|
it 'has 2 parameter names' do
|
281
281
|
expect(node.parameter_names).to eq [:x, :y]
|
@@ -286,7 +286,7 @@ end
|
|
286
286
|
RSpec.describe Reek::AST::SexpExtensions::ModuleNode do
|
287
287
|
context 'with a simple name' do
|
288
288
|
subject do
|
289
|
-
mod =
|
289
|
+
mod = sexp(:module, :Fred, nil)
|
290
290
|
mod
|
291
291
|
end
|
292
292
|
|
@@ -309,7 +309,7 @@ RSpec.describe Reek::AST::SexpExtensions::ModuleNode do
|
|
309
309
|
|
310
310
|
context 'with a scoped name' do
|
311
311
|
subject do
|
312
|
-
|
312
|
+
sexp(:module, sexp(:const, sexp(:const, nil, :Foo), :Bar), nil)
|
313
313
|
end
|
314
314
|
|
315
315
|
it 'has the correct #name' do
|
@@ -333,7 +333,7 @@ end
|
|
333
333
|
RSpec.describe Reek::AST::SexpExtensions::CasgnNode do
|
334
334
|
context 'with single assignment' do
|
335
335
|
subject do
|
336
|
-
|
336
|
+
sexp(:casgn, nil, :Foo)
|
337
337
|
end
|
338
338
|
|
339
339
|
it 'does not define a module' do
|
@@ -4,30 +4,30 @@ require_relative '../../../lib/reek/ast/sexp_formatter'
|
|
4
4
|
RSpec.describe Reek::AST::SexpFormatter do
|
5
5
|
describe '::format' do
|
6
6
|
it 'formats a simple s-expression' do
|
7
|
-
result = described_class.format
|
7
|
+
result = described_class.format sexp(:lvar, :foo)
|
8
8
|
expect(result).to eq('foo')
|
9
9
|
end
|
10
10
|
|
11
11
|
it 'formats a more complex s-expression' do
|
12
|
-
ast =
|
12
|
+
ast = sexp(:send, nil, :foo, sexp(:lvar, :bar))
|
13
13
|
result = described_class.format(ast)
|
14
14
|
expect(result).to eq('foo(bar)')
|
15
15
|
end
|
16
16
|
|
17
17
|
it 'reduces very large ASTs to a single line' do
|
18
|
-
ast =
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
18
|
+
ast = sexp(:if,
|
19
|
+
sexp(:send, nil, :foo),
|
20
|
+
sexp(:send, nil, :bar),
|
21
|
+
sexp(:begin,
|
22
|
+
sexp(:send, nil, :baz),
|
23
|
+
sexp(:send, nil, :qux)))
|
24
24
|
result = described_class.format ast
|
25
25
|
|
26
26
|
expect(result).to eq 'if foo ... end'
|
27
27
|
end
|
28
28
|
|
29
29
|
it "doesn't reduce two-line ASTs" do
|
30
|
-
ast =
|
30
|
+
ast = sexp(:def, 'my_method', sexp(:args))
|
31
31
|
result = described_class.format ast
|
32
32
|
expect(result).to eq 'def my_method; end'
|
33
33
|
end
|
@@ -78,7 +78,7 @@ RSpec.describe Reek::Context::CodeContext do
|
|
78
78
|
|
79
79
|
it "yields the module's full AST" do
|
80
80
|
ctx.each_node(:module, []) do |exp|
|
81
|
-
expect(exp).to eq(
|
81
|
+
expect(exp).to eq(sexp(:module, sexp(:const, nil, :Emptiness), nil))
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
@@ -105,11 +105,11 @@ RSpec.describe Reek::Context::CodeContext do
|
|
105
105
|
|
106
106
|
it "yields the module's full AST" do
|
107
107
|
ctx.each_node(:module, []) do |exp|
|
108
|
-
expect(exp).to eq
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
108
|
+
expect(exp).to eq sexp(:module,
|
109
|
+
sexp(:const, nil, :Loneliness),
|
110
|
+
sexp(:def, :calloo,
|
111
|
+
sexp(:args),
|
112
|
+
sexp(:send, nil, :puts, sexp(:str, 'hello'))))
|
113
113
|
end
|
114
114
|
end
|
115
115
|
|
@@ -209,7 +209,7 @@ RSpec.describe Reek::Context::CodeContext do
|
|
209
209
|
|
210
210
|
it 'sets visibility on subsequent child contexts' do
|
211
211
|
context.append_child_context first_child
|
212
|
-
context.track_visibility :private
|
212
|
+
context.track_visibility :private, []
|
213
213
|
context.append_child_context second_child
|
214
214
|
expect(first_child.visibility).to eq :public
|
215
215
|
expect(second_child.visibility).to eq :private
|
@@ -23,27 +23,27 @@ RSpec.describe Reek::Context::MethodContext do
|
|
23
23
|
end
|
24
24
|
|
25
25
|
describe '#envious_receivers' do
|
26
|
-
let(:exp) {
|
26
|
+
let(:exp) { sexp(:def, :foo, sexp(:args, sexp(:arg, :bar)), nil) }
|
27
27
|
|
28
28
|
it 'should ignore ivars as refs to self' do
|
29
|
-
method_context.record_call_to
|
29
|
+
method_context.record_call_to sexp(:send, sexp(:ivar, :@cow), :feed_to)
|
30
30
|
expect(method_context.envious_receivers).to be_empty
|
31
31
|
end
|
32
32
|
|
33
33
|
it 'should ignore explicit calls to self' do
|
34
34
|
method_context.refs.record_reference_to :other
|
35
|
-
method_context.record_call_to
|
35
|
+
method_context.record_call_to sexp(:send, sexp(:self), :thing)
|
36
36
|
expect(method_context.envious_receivers).to be_empty
|
37
37
|
end
|
38
38
|
|
39
39
|
it 'should ignore implicit calls to self' do
|
40
|
-
method_context.record_call_to
|
41
|
-
method_context.record_call_to
|
40
|
+
method_context.record_call_to sexp(:send, sexp(:lvar, :text), :each, sexp(:arglist))
|
41
|
+
method_context.record_call_to sexp(:send, nil, :shelve, sexp(:arglist))
|
42
42
|
expect(method_context.envious_receivers).to be_empty
|
43
43
|
end
|
44
44
|
|
45
45
|
it 'should record envious calls' do
|
46
|
-
method_context.record_call_to
|
46
|
+
method_context.record_call_to sexp(:send, sexp(:lvar, :bar), :baz)
|
47
47
|
expect(method_context.envious_receivers).to include(:bar)
|
48
48
|
end
|
49
49
|
end
|
@@ -66,7 +66,7 @@ RSpec.describe Reek::Context::MethodContext do
|
|
66
66
|
let(:defaults) { assignments_from('def meth(arga, argb=456, &blk) end') }
|
67
67
|
|
68
68
|
it 'returns the param-value pair' do
|
69
|
-
expect(defaults[0]).to eq [:argb,
|
69
|
+
expect(defaults[0]).to eq [:argb, sexp(:int, 456)]
|
70
70
|
end
|
71
71
|
|
72
72
|
it 'returns the nothing else' do
|
@@ -80,8 +80,8 @@ RSpec.describe Reek::Context::MethodContext do
|
|
80
80
|
end
|
81
81
|
|
82
82
|
it 'returns both param-value pairs' do
|
83
|
-
expect(defaults[0]).to eq [:arga,
|
84
|
-
expect(defaults[1]).to eq [:argb,
|
83
|
+
expect(defaults[0]).to eq [:arga, sexp(:int, 123)]
|
84
|
+
expect(defaults[1]).to eq [:argb, sexp(:int, 456)]
|
85
85
|
end
|
86
86
|
|
87
87
|
it 'returns nothing else' do
|
@@ -3,13 +3,13 @@ require_relative '../../../lib/reek/context/singleton_method_context'
|
|
3
3
|
|
4
4
|
RSpec.describe Reek::Context::SingletonMethodContext do
|
5
5
|
let(:smc) do
|
6
|
-
sexp =
|
6
|
+
sexp = sexp(:def, :foo, sexp(:args, sexp(:arg, :bar)), nil)
|
7
7
|
Reek::Context::SingletonMethodContext.new(nil, sexp)
|
8
8
|
end
|
9
9
|
|
10
10
|
describe '#envious_receivers' do
|
11
11
|
it 'should not record envious calls' do
|
12
|
-
smc.record_call_to
|
12
|
+
smc.record_call_to sexp(:send, sexp(:lvar, :bar), :baz)
|
13
13
|
expect(smc.envious_receivers).to be_empty
|
14
14
|
end
|
15
15
|
end
|
@@ -16,7 +16,8 @@ RSpec.describe Reek::Report::HTMLReport do
|
|
16
16
|
it 'has the text 0 total warnings' do
|
17
17
|
tempfile = Tempfile.new(['Reek::Report::HTMLReport.', '.html'])
|
18
18
|
response = "HTML file saved\n"
|
19
|
-
expect { instance.show tempfile.path }.
|
19
|
+
expect { instance.show(target_path: tempfile.path) }.
|
20
|
+
to output(response).to_stdout
|
20
21
|
expect(tempfile.read).to include('0 total warnings')
|
21
22
|
end
|
22
23
|
end
|
@@ -12,12 +12,12 @@ RSpec.describe Reek::Smells::ClassVariable do
|
|
12
12
|
|
13
13
|
context 'with no class variables' do
|
14
14
|
it 'records nothing in the class' do
|
15
|
-
exp =
|
15
|
+
exp = sexp(:class, :Fred)
|
16
16
|
expect(detector.examine_context(Reek::Context::CodeContext.new(nil, exp))).to be_empty
|
17
17
|
end
|
18
18
|
|
19
19
|
it 'records nothing in the module' do
|
20
|
-
exp =
|
20
|
+
exp = sexp(:module, :Fred)
|
21
21
|
expect(detector.examine_context(Reek::Context::CodeContext.new(nil, exp))).to be_empty
|
22
22
|
end
|
23
23
|
end
|
@@ -22,6 +22,11 @@ RSpec.describe Reek::Smells::NestedIterators do
|
|
22
22
|
expect(src).to reek_of(:NestedIterators)
|
23
23
|
end
|
24
24
|
|
25
|
+
it 'should not report nested iterators for Object#tap' do
|
26
|
+
src = 'def do_stuff(*params); [].tap {|list| params.map {|param| list << (param + param)} } end'
|
27
|
+
expect(src).not_to reek_of(:NestedIterators)
|
28
|
+
end
|
29
|
+
|
25
30
|
it 'should not report method with successive iterators' do
|
26
31
|
src = <<-EOS
|
27
32
|
def bad(fred)
|
@@ -30,7 +30,7 @@ RSpec.describe Reek::Source::SourceCode do
|
|
30
30
|
let(:source_name) { 'Test source' }
|
31
31
|
let(:error_message) { 'Error message' }
|
32
32
|
let(:parser) { double('parser') }
|
33
|
-
let(:src) { Reek::Source::SourceCode.new('', source_name, parser) }
|
33
|
+
let(:src) { Reek::Source::SourceCode.new('', source_name, parser: parser) }
|
34
34
|
|
35
35
|
before { $stderr = catcher }
|
36
36
|
|
@@ -46,7 +46,7 @@ RSpec.describe Reek::Spec::ShouldReek do
|
|
46
46
|
context 'matcher without masking' do
|
47
47
|
let(:path) { SAMPLES_PATH.join('clean_due_to_masking/masked.reek') }
|
48
48
|
let(:configuration) { test_configuration_for(path) }
|
49
|
-
let(:matcher) { Reek::Spec::ShouldReek.new configuration }
|
49
|
+
let(:matcher) { Reek::Spec::ShouldReek.new(configuration: configuration) }
|
50
50
|
let(:masked_file) { SAMPLES_PATH.join('clean_due_to_masking/dirty_one.rb') }
|
51
51
|
|
52
52
|
it 'masks smells using the relevant configuration' do
|
@@ -1,16 +1,50 @@
|
|
1
|
+
require_relative '../../lib/reek/cli/silencer'
|
2
|
+
Reek::CLI::Silencer.silently do
|
3
|
+
require 'parser/ruby22'
|
4
|
+
end
|
5
|
+
|
1
6
|
require_relative '../spec_helper'
|
2
7
|
require_relative '../../lib/reek/tree_dresser'
|
3
8
|
|
4
9
|
RSpec.describe Reek::TreeDresser do
|
5
|
-
let(:ifnode) { ::Parser::AST::Node.new(:if) }
|
6
|
-
let(:sendnode) { ::Parser::AST::Node.new(:send) }
|
7
10
|
let(:dresser) { described_class.new }
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
+
let(:sexp) do
|
12
|
+
Parser::Ruby22.parse('class Klazz; def meth(argument); argument.call_me; end; end')
|
13
|
+
end
|
14
|
+
let(:dressed_ast) do
|
15
|
+
# The dressed AST looks like this:
|
16
|
+
# (class
|
17
|
+
# (const nil :Klazz) nil
|
18
|
+
# (def :meth
|
19
|
+
# (args
|
20
|
+
# (arg :argument))
|
21
|
+
# (send
|
22
|
+
# (lvar :argument) :call_me)))
|
23
|
+
dresser.dress(sexp, {})
|
11
24
|
end
|
25
|
+
let(:const_node) { dressed_ast.children.first }
|
26
|
+
let(:def_node) { dressed_ast.children.last }
|
27
|
+
let(:args_node) { def_node.children[1] }
|
28
|
+
let(:send_node) { def_node.children[2] }
|
29
|
+
|
30
|
+
context 'dresses the given sexp' do
|
31
|
+
it 'dresses `const` nodes properly' do
|
32
|
+
expect(const_node).to be_a Reek::AST::SexpExtensions::ConstNode
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'dresses `def` nodes properly' do
|
36
|
+
expect(def_node).to be_a Reek::AST::SexpExtensions::DefNode
|
37
|
+
expect(def_node).to be_a Reek::AST::SexpExtensions::SingletonMethod
|
38
|
+
expect(def_node).to be_a Reek::AST::SexpExtensions::MethodNodeBase
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'dresses `args` nodes properly' do
|
42
|
+
expect(args_node).to be_a Reek::AST::SexpExtensions::ArgsNode
|
43
|
+
expect(args_node).to be_a Reek::AST::SexpExtensions::NestedAssignables
|
44
|
+
end
|
12
45
|
|
13
|
-
|
14
|
-
|
46
|
+
it 'dresses `send` nodes properly' do
|
47
|
+
expect(send_node).to be_a Reek::AST::SexpExtensions::SendNode
|
48
|
+
end
|
15
49
|
end
|
16
50
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -3,7 +3,6 @@ require_relative '../lib/reek'
|
|
3
3
|
require_relative '../lib/reek/spec'
|
4
4
|
require_relative '../lib/reek/ast/ast_node_class_map'
|
5
5
|
require_relative '../lib/reek/configuration/app_configuration'
|
6
|
-
require 'ostruct'
|
7
6
|
|
8
7
|
Reek::CLI::Silencer.silently do
|
9
8
|
require 'factory_girl'
|
@@ -35,17 +34,12 @@ module Helpers
|
|
35
34
|
end
|
36
35
|
|
37
36
|
# :reek:UncommunicativeMethodName
|
38
|
-
def
|
37
|
+
def sexp(type, *children)
|
39
38
|
@klass_map ||= Reek::AST::ASTNodeClassMap.new
|
40
39
|
@klass_map.klass_for(type).new(type, children)
|
41
40
|
end
|
42
|
-
|
43
|
-
def ast(*args)
|
44
|
-
s(*args)
|
45
|
-
end
|
46
41
|
end
|
47
42
|
|
48
|
-
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
49
43
|
RSpec.configure do |config|
|
50
44
|
config.filter_run :focus
|
51
45
|
config.run_all_when_everything_filtered = true
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: reek
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.3.
|
4
|
+
version: 3.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kevin Rutherford
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2015-
|
14
|
+
date: 2015-09-03 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: parser
|