reek 3.2.1 → 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/Rakefile +0 -1
- data/config/defaults.reek +1 -1
- data/features/samples.feature +17 -16
- data/lib/reek.rb +0 -1
- data/lib/reek/ast/ast_node_class_map.rb +5 -1
- data/lib/reek/ast/node.rb +10 -3
- data/lib/reek/ast/object_refs.rb +11 -5
- data/lib/reek/ast/reference_collector.rb +6 -2
- data/lib/reek/ast/sexp_extensions.rb +42 -1
- data/lib/reek/ast/sexp_formatter.rb +2 -1
- data/lib/reek/cli/application.rb +12 -9
- data/lib/reek/cli/command.rb +6 -0
- data/lib/reek/cli/input.rb +4 -4
- data/lib/reek/cli/option_interpreter.rb +11 -7
- data/lib/reek/cli/options.rb +42 -40
- data/lib/reek/cli/reek_command.rb +3 -3
- data/lib/reek/cli/silencer.rb +12 -3
- data/lib/reek/cli/warning_collector.rb +8 -3
- data/lib/reek/code_comment.rb +6 -1
- data/lib/reek/configuration/app_configuration.rb +65 -100
- data/lib/reek/configuration/configuration_file_finder.rb +4 -13
- data/lib/reek/configuration/configuration_validator.rb +35 -0
- data/lib/reek/configuration/default_directive.rb +12 -0
- data/lib/reek/configuration/directory_directives.rb +54 -0
- data/lib/reek/configuration/excluded_paths.rb +18 -0
- data/lib/reek/context/code_context.rb +19 -17
- data/lib/reek/examiner.rb +9 -7
- data/lib/reek/rake/task.rb +12 -22
- data/lib/reek/report/formatter.rb +6 -1
- data/lib/reek/report/report.rb +22 -13
- data/lib/reek/smells/attribute.rb +6 -53
- data/lib/reek/smells/control_parameter.rb +21 -13
- data/lib/reek/smells/data_clump.rb +17 -9
- data/lib/reek/smells/duplicate_method_call.rb +12 -6
- data/lib/reek/smells/long_parameter_list.rb +2 -2
- data/lib/reek/smells/long_yield_list.rb +4 -4
- data/lib/reek/smells/nested_iterators.rb +4 -2
- data/lib/reek/smells/nil_check.rb +6 -2
- data/lib/reek/smells/repeated_conditional.rb +3 -3
- data/lib/reek/smells/smell_configuration.rb +17 -7
- data/lib/reek/smells/smell_detector.rb +24 -11
- data/lib/reek/smells/smell_repository.rb +1 -1
- data/lib/reek/smells/smell_warning.rb +6 -6
- data/lib/reek/smells/too_many_instance_variables.rb +2 -2
- data/lib/reek/smells/too_many_methods.rb +4 -4
- data/lib/reek/smells/too_many_statements.rb +4 -4
- data/lib/reek/smells/uncommunicative_method_name.rb +5 -5
- data/lib/reek/smells/uncommunicative_module_name.rb +6 -6
- data/lib/reek/smells/uncommunicative_parameter_name.rb +8 -4
- data/lib/reek/smells/uncommunicative_variable_name.rb +9 -5
- data/lib/reek/smells/utility_function.rb +1 -1
- data/lib/reek/source/source_code.rb +5 -1
- data/lib/reek/source/source_locator.rb +3 -2
- data/lib/reek/spec.rb +3 -3
- data/lib/reek/spec/should_reek.rb +10 -5
- data/lib/reek/spec/should_reek_of.rb +9 -6
- data/lib/reek/spec/should_reek_only_of.rb +13 -8
- data/lib/reek/tree_dresser.rb +6 -2
- data/lib/reek/tree_walker.rb +40 -32
- data/lib/reek/version.rb +1 -1
- data/reek.gemspec +1 -1
- data/spec/reek/ast/node_spec.rb +1 -2
- data/spec/reek/ast/object_refs_spec.rb +40 -42
- data/spec/reek/ast/sexp_extensions_spec.rb +98 -104
- data/spec/reek/cli/warning_collector_spec.rb +8 -12
- data/spec/reek/code_comment_spec.rb +3 -5
- data/spec/reek/configuration/app_configuration_spec.rb +43 -57
- data/spec/reek/configuration/configuration_file_finder_spec.rb +5 -7
- data/spec/reek/configuration/default_directive_spec.rb +13 -0
- data/spec/reek/configuration/directory_directives_spec.rb +89 -0
- data/spec/reek/configuration/excluded_paths_spec.rb +30 -0
- data/spec/reek/context/code_context_spec.rb +63 -62
- data/spec/reek/context/method_context_spec.rb +8 -12
- data/spec/reek/context/module_context_spec.rb +1 -1
- data/spec/reek/context/root_context_spec.rb +3 -7
- data/spec/reek/examiner_spec.rb +14 -25
- data/spec/reek/smells/attribute_spec.rb +2 -4
- data/spec/reek/smells/boolean_parameter_spec.rb +5 -7
- data/spec/reek/smells/class_variable_spec.rb +29 -44
- data/spec/reek/smells/control_parameter_spec.rb +7 -9
- data/spec/reek/smells/data_clump_spec.rb +25 -32
- data/spec/reek/smells/duplicate_method_call_spec.rb +8 -7
- data/spec/reek/smells/feature_envy_spec.rb +16 -17
- data/spec/reek/smells/irresponsible_module_spec.rb +2 -4
- data/spec/reek/smells/long_parameter_list_spec.rb +6 -9
- data/spec/reek/smells/long_yield_list_spec.rb +6 -9
- data/spec/reek/smells/nested_iterators_spec.rb +14 -16
- data/spec/reek/smells/repeated_conditional_spec.rb +25 -25
- data/spec/reek/smells/smell_configuration_spec.rb +32 -27
- data/spec/reek/smells/smell_detector_shared.rb +12 -13
- data/spec/reek/smells/smell_warning_spec.rb +54 -58
- data/spec/reek/smells/too_many_instance_variables_spec.rb +9 -9
- data/spec/reek/smells/too_many_methods_spec.rb +13 -14
- data/spec/reek/smells/too_many_statements_spec.rb +8 -10
- data/spec/reek/smells/uncommunicative_method_name_spec.rb +8 -9
- data/spec/reek/smells/uncommunicative_module_name_spec.rb +12 -13
- data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +7 -10
- data/spec/reek/smells/uncommunicative_variable_name_spec.rb +16 -20
- data/spec/reek/smells/utility_function_spec.rb +11 -15
- data/spec/reek/source/source_code_spec.rb +6 -11
- data/spec/reek/spec/should_reek_of_spec.rb +19 -30
- data/spec/reek/spec/should_reek_only_of_spec.rb +28 -34
- data/spec/reek/tree_walker_spec.rb +14 -2
- data/spec/spec_helper.rb +2 -3
- data/tasks/test.rake +0 -5
- metadata +10 -6
- data/docs/Configuration-Files.md +0 -49
- data/spec/gem/updates_spec.rb +0 -25
- data/spec/gem/yard_spec.rb +0 -11
- data/spec/reek/smells/behaves_like_variable_detector.rb +0 -39
@@ -3,26 +3,22 @@ require_relative '../../../lib/reek/cli/warning_collector'
|
|
3
3
|
require_relative '../../../lib/reek/smells/smell_warning'
|
4
4
|
|
5
5
|
RSpec.describe Reek::CLI::WarningCollector do
|
6
|
-
|
7
|
-
@collector = described_class.new
|
8
|
-
end
|
6
|
+
let(:collector) { described_class.new }
|
9
7
|
|
10
8
|
context 'when empty' do
|
11
9
|
it 'reports no warnings' do
|
12
|
-
expect(
|
10
|
+
expect(collector.warnings).to eq([])
|
13
11
|
end
|
14
12
|
end
|
15
13
|
|
16
14
|
context 'with one warning' do
|
17
|
-
before :each do
|
18
|
-
@warning = Reek::Smells::SmellWarning.new(Reek::Smells::FeatureEnvy.new(''),
|
19
|
-
context: 'fred',
|
20
|
-
lines: [1, 2, 3],
|
21
|
-
message: 'hello')
|
22
|
-
@collector.found_smell(@warning)
|
23
|
-
end
|
24
15
|
it 'reports that warning' do
|
25
|
-
|
16
|
+
warning = Reek::Smells::SmellWarning.new(Reek::Smells::FeatureEnvy.new(''),
|
17
|
+
context: 'fred',
|
18
|
+
lines: [1, 2, 3],
|
19
|
+
message: 'hello')
|
20
|
+
collector.found_smell(warning)
|
21
|
+
expect(collector.warnings).to eq([warning])
|
26
22
|
end
|
27
23
|
end
|
28
24
|
end
|
@@ -3,14 +3,12 @@ require_relative '../../lib/reek/code_comment'
|
|
3
3
|
|
4
4
|
RSpec.describe Reek::CodeComment do
|
5
5
|
context 'with an empty comment' do
|
6
|
-
|
7
|
-
@comment = described_class.new('')
|
8
|
-
end
|
6
|
+
let(:comment) { described_class.new('') }
|
9
7
|
it 'is not descriptive' do
|
10
|
-
expect(
|
8
|
+
expect(comment).not_to be_descriptive
|
11
9
|
end
|
12
10
|
it 'has an empty config' do
|
13
|
-
expect(
|
11
|
+
expect(comment.config).to be_empty
|
14
12
|
end
|
15
13
|
end
|
16
14
|
|
@@ -1,13 +1,19 @@
|
|
1
1
|
require 'pathname'
|
2
2
|
require_relative '../../spec_helper'
|
3
3
|
require_relative '../../../lib/reek/configuration/app_configuration'
|
4
|
-
require_relative '../../../lib/reek/
|
5
|
-
require_relative '../../../lib/reek/
|
4
|
+
require_relative '../../../lib/reek/configuration/directory_directives'
|
5
|
+
require_relative '../../../lib/reek/configuration/default_directive'
|
6
|
+
require_relative '../../../lib/reek/configuration/excluded_paths'
|
6
7
|
|
7
8
|
RSpec.describe Reek::Configuration::AppConfiguration do
|
8
|
-
describe '#
|
9
|
-
|
10
|
-
|
9
|
+
describe '#new' do
|
10
|
+
it 'raises NotImplementedError' do
|
11
|
+
expect { subject }.to raise_error(NotImplementedError)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'factory methods' do
|
16
|
+
let(:expected_excluded_paths) do
|
11
17
|
[SAMPLES_PATH.join('two_smelly_files'),
|
12
18
|
SAMPLES_PATH.join('source_with_non_ruby_files')]
|
13
19
|
end
|
@@ -19,13 +25,28 @@ RSpec.describe Reek::Configuration::AppConfiguration do
|
|
19
25
|
{ Reek::Smells::UtilityFunction => { 'enabled' => false } } }
|
20
26
|
end
|
21
27
|
|
22
|
-
|
23
|
-
|
24
|
-
|
28
|
+
describe '#from_path' do
|
29
|
+
let(:full_configuration_path) { SAMPLES_PATH.join('configuration/full_configuration.reek') }
|
30
|
+
|
31
|
+
it 'properly loads configuration and processes it' do
|
32
|
+
config = described_class.from_path full_configuration_path
|
33
|
+
|
34
|
+
expect(config.send(:excluded_paths)).to eq(expected_excluded_paths)
|
35
|
+
expect(config.send(:default_directive)).to eq(expected_default_directive)
|
36
|
+
expect(config.send(:directory_directives)).to eq(expected_directory_directives)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#from_map' do
|
41
|
+
it 'properly sets the configuration' do
|
42
|
+
config = described_class.from_map(directory_directives: expected_directory_directives,
|
43
|
+
default_directive: expected_default_directive,
|
44
|
+
excluded_paths: expected_excluded_paths)
|
25
45
|
|
26
|
-
|
27
|
-
|
28
|
-
|
46
|
+
expect(config.send(:excluded_paths)).to eq(expected_excluded_paths)
|
47
|
+
expect(config.send(:default_directive)).to eq(expected_default_directive)
|
48
|
+
expect(config.send(:directory_directives)).to eq(expected_directory_directives)
|
49
|
+
end
|
29
50
|
end
|
30
51
|
end
|
31
52
|
|
@@ -43,64 +64,29 @@ RSpec.describe Reek::Configuration::AppConfiguration do
|
|
43
64
|
let(:source_via) { 'foo/bar/bang/dummy.rb' }
|
44
65
|
|
45
66
|
it 'returns the corresponding directive' do
|
46
|
-
|
47
|
-
expect(
|
67
|
+
configuration = described_class.from_map directory_directives: directory_directives
|
68
|
+
expect(configuration.directive_for(source_via)).to eq(bang_config)
|
48
69
|
end
|
49
70
|
end
|
50
71
|
|
51
72
|
context 'our source is not in a directory for which we have a directive' do
|
52
|
-
let(:
|
73
|
+
let(:irresponsible_module_config) do
|
74
|
+
{ Reek::Smells::IrresponsibleModule => { enabled: false } }
|
75
|
+
end
|
76
|
+
let(:attribute_config) { { Reek::Smells::Attribute => { enabled: false } } }
|
53
77
|
let(:default_directive) do
|
54
|
-
|
78
|
+
irresponsible_module_config
|
55
79
|
end
|
56
80
|
let(:directory_directives) do
|
57
|
-
{ Pathname.new('foo/bar/baz')
|
81
|
+
{ Pathname.new('foo/bar/baz') => attribute_config }
|
58
82
|
end
|
59
83
|
let(:source_via) { 'foo/bar/bang/dummy.rb' }
|
60
84
|
|
61
85
|
it 'returns the default directive' do
|
62
|
-
|
63
|
-
|
64
|
-
expect(
|
86
|
+
configuration = described_class.from_map directory_directives: directory_directives,
|
87
|
+
default_directive: default_directive
|
88
|
+
expect(configuration.directive_for(source_via)).to eq(irresponsible_module_config)
|
65
89
|
end
|
66
90
|
end
|
67
91
|
end
|
68
|
-
|
69
|
-
describe '#best_directory_match_for' do
|
70
|
-
let(:directory_directives) do
|
71
|
-
{
|
72
|
-
Pathname.new('foo/bar/baz') => {},
|
73
|
-
Pathname.new('foo/bar') => {},
|
74
|
-
Pathname.new('bar/boo') => {}
|
75
|
-
}
|
76
|
-
end
|
77
|
-
|
78
|
-
before do
|
79
|
-
allow(subject).to receive(:directory_directives).and_return directory_directives
|
80
|
-
end
|
81
|
-
|
82
|
-
it 'returns the corresponding directory when source_base_dir is a leaf' do
|
83
|
-
source_base_dir = 'foo/bar/baz/bang'
|
84
|
-
hit = subject.send :best_directory_match_for, source_base_dir
|
85
|
-
expect(hit.to_s).to eq('foo/bar/baz')
|
86
|
-
end
|
87
|
-
|
88
|
-
it 'returns the corresponding directory when source_base_dir is in the middle of the tree' do
|
89
|
-
source_base_dir = 'foo/bar'
|
90
|
-
hit = subject.send :best_directory_match_for, source_base_dir
|
91
|
-
expect(hit.to_s).to eq('foo/bar')
|
92
|
-
end
|
93
|
-
|
94
|
-
it 'returns nil we are on top at the top of the and all other directories are below' do
|
95
|
-
source_base_dir = 'foo'
|
96
|
-
hit = subject.send :best_directory_match_for, source_base_dir
|
97
|
-
expect(hit).to be_nil
|
98
|
-
end
|
99
|
-
|
100
|
-
it 'returns nil when there source_base_dir is not part of any directory directive at all' do
|
101
|
-
source_base_dir = 'non/existent'
|
102
|
-
hit = subject.send :best_directory_match_for, source_base_dir
|
103
|
-
expect(hit).to be_nil
|
104
|
-
end
|
105
|
-
end
|
106
92
|
end
|
@@ -7,16 +7,14 @@ require_relative '../../spec_helper'
|
|
7
7
|
|
8
8
|
RSpec.describe Reek::Configuration::ConfigurationFileFinder do
|
9
9
|
describe '.find' do
|
10
|
-
it 'returns the
|
11
|
-
|
12
|
-
|
13
|
-
found
|
14
|
-
expect(found).to eq(config_file)
|
10
|
+
it 'returns the path if it’s set' do
|
11
|
+
path = Pathname.new 'foo/bar'
|
12
|
+
found = described_class.find(path: path)
|
13
|
+
expect(found).to eq(path)
|
15
14
|
end
|
16
15
|
|
17
16
|
it 'returns the file in current dir if config_file is nil' do
|
18
|
-
|
19
|
-
found = described_class.find(options: options, current: SAMPLES_PATH)
|
17
|
+
found = described_class.find(current: SAMPLES_PATH)
|
20
18
|
expect(found).to eq(SAMPLES_PATH.join('exceptions.reek'))
|
21
19
|
end
|
22
20
|
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require_relative '../../spec_helper'
|
2
|
+
require_relative '../../../lib/reek/configuration/default_directive'
|
3
|
+
|
4
|
+
RSpec.describe Reek::Configuration::DefaultDirective do
|
5
|
+
describe '#add' do
|
6
|
+
subject { {}.extend(described_class) }
|
7
|
+
|
8
|
+
it 'adds a smell configuration' do
|
9
|
+
subject.add :UncommunicativeVariableName, enabled: false
|
10
|
+
expect(subject).to eq(Reek::Smells::UncommunicativeVariableName => { enabled: false })
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require_relative '../../spec_helper'
|
2
|
+
require_relative '../../../lib/reek/configuration/directory_directives'
|
3
|
+
|
4
|
+
RSpec.describe Reek::Configuration::DirectoryDirectives do
|
5
|
+
describe '#directive_for' do
|
6
|
+
let(:baz_config) { { Reek::Smells::IrresponsibleModule => { enabled: false } } }
|
7
|
+
let(:bang_config) { { Reek::Smells::Attribute => { enabled: true } } }
|
8
|
+
subject do
|
9
|
+
{
|
10
|
+
Pathname.new('foo/bar/baz') => baz_config,
|
11
|
+
Pathname.new('foo/bar/bang') => bang_config
|
12
|
+
}.extend(described_class)
|
13
|
+
end
|
14
|
+
let(:source_via) { 'foo/bar/bang/dummy.rb' }
|
15
|
+
|
16
|
+
context 'our source is in a directory for which we have a directive' do
|
17
|
+
it 'returns the corresponding directive' do
|
18
|
+
expect(subject.directive_for(source_via)).to eq(bang_config)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'our source is not in a directory for which we have a directive' do
|
23
|
+
it 'returns nil' do
|
24
|
+
expect(subject.directive_for('does/not/exist')).to eq(nil)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#add' do
|
30
|
+
subject do
|
31
|
+
{}.extend(described_class)
|
32
|
+
end
|
33
|
+
let(:empty_config) { Hash.new }
|
34
|
+
|
35
|
+
context 'one of given paths does not exist' do
|
36
|
+
let(:bogus_path) { Pathname('does/not/exist') }
|
37
|
+
|
38
|
+
it 'raises an error' do
|
39
|
+
Reek::CLI::Silencer.silently(stderr: true) do
|
40
|
+
expect { subject.add(bogus_path, {}) }.to raise_error(SystemExit)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'one of given paths is a file' do
|
46
|
+
let(:file_as_path) { SAMPLES_PATH.join('inline.rb') }
|
47
|
+
|
48
|
+
it 'raises an error' do
|
49
|
+
Reek::CLI::Silencer.silently(stderr: true) do
|
50
|
+
expect { subject.add(file_as_path, {}) }.to raise_error(SystemExit)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe '#best_match_for' do
|
57
|
+
subject do
|
58
|
+
{
|
59
|
+
Pathname.new('foo/bar/baz') => {},
|
60
|
+
Pathname.new('foo/bar') => {},
|
61
|
+
Pathname.new('bar/boo') => {}
|
62
|
+
}.extend(described_class)
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'returns the corresponding directory when source_base_dir is a leaf' do
|
66
|
+
source_base_dir = 'foo/bar/baz/bang'
|
67
|
+
hit = subject.send :best_match_for, source_base_dir
|
68
|
+
expect(hit.to_s).to eq('foo/bar/baz')
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'returns the corresponding directory when source_base_dir is in the middle of the tree' do
|
72
|
+
source_base_dir = 'foo/bar'
|
73
|
+
hit = subject.send :best_match_for, source_base_dir
|
74
|
+
expect(hit.to_s).to eq('foo/bar')
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'returns nil we are on top of the tree and all other directories are below' do
|
78
|
+
source_base_dir = 'foo'
|
79
|
+
hit = subject.send :best_match_for, source_base_dir
|
80
|
+
expect(hit).to be_nil
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'returns nil when source_base_dir is not part of any directory directive at all' do
|
84
|
+
source_base_dir = 'non/existent'
|
85
|
+
hit = subject.send :best_match_for, source_base_dir
|
86
|
+
expect(hit).to be_nil
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require_relative '../../spec_helper'
|
2
|
+
require_relative '../../../lib/reek/configuration/excluded_paths'
|
3
|
+
|
4
|
+
RSpec.describe Reek::Configuration::ExcludedPaths do
|
5
|
+
describe '#add' do
|
6
|
+
subject { [].extend(described_class) }
|
7
|
+
|
8
|
+
context 'one of the given paths does not exist' do
|
9
|
+
let(:bogus_path) { Pathname('does/not/exist') }
|
10
|
+
let(:paths) { [SAMPLES_PATH, bogus_path] }
|
11
|
+
|
12
|
+
it 'raises an error' do
|
13
|
+
Reek::CLI::Silencer.silently(stderr: true) do
|
14
|
+
expect { subject.add(paths) }.to raise_error(SystemExit)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'one of given paths is a file' do
|
20
|
+
let(:file_as_path) { SAMPLES_PATH.join('inline.rb') }
|
21
|
+
let(:paths) { [SAMPLES_PATH, file_as_path] }
|
22
|
+
|
23
|
+
it 'raises an error if one of the given paths is a file' do
|
24
|
+
Reek::CLI::Silencer.silently(stderr: true) do
|
25
|
+
expect { subject.add(paths) }.to raise_error(SystemExit)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -4,107 +4,109 @@ require_relative '../../../lib/reek/context/module_context'
|
|
4
4
|
|
5
5
|
RSpec.describe Reek::Context::CodeContext do
|
6
6
|
context 'name recognition' do
|
7
|
+
let(:ctx) { Reek::Context::CodeContext.new(nil, exp) }
|
8
|
+
let(:exp) { double('exp') }
|
9
|
+
let(:exp_name) { 'random_name' }
|
10
|
+
let(:full_name) { "::::::::::::::::::::#{exp_name}" }
|
11
|
+
|
7
12
|
before :each do
|
8
|
-
|
9
|
-
|
10
|
-
@exp = double('exp')
|
11
|
-
allow(@exp).to receive(:name).and_return(@exp_name)
|
12
|
-
allow(@exp).to receive(:full_name).and_return(@full_name)
|
13
|
-
@ctx = Reek::Context::CodeContext.new(nil, @exp)
|
13
|
+
allow(exp).to receive(:name).and_return(exp_name)
|
14
|
+
allow(exp).to receive(:full_name).and_return(full_name)
|
14
15
|
end
|
16
|
+
|
15
17
|
it 'gets its short name from the exp' do
|
16
|
-
expect(
|
18
|
+
expect(ctx.name).to eq(exp_name)
|
17
19
|
end
|
18
20
|
it 'does not match an empty list' do
|
19
|
-
expect(
|
21
|
+
expect(ctx.matches?([])).to eq(false)
|
20
22
|
end
|
21
23
|
it 'does not match when its own short name is not given' do
|
22
|
-
expect(
|
24
|
+
expect(ctx.matches?(['banana'])).to eq(false)
|
23
25
|
end
|
24
26
|
it 'does not let pipe-ended Strings make matching ignore the rest' do
|
25
|
-
expect(
|
27
|
+
expect(ctx.matches?(['banana|'])).to eq(false)
|
26
28
|
end
|
27
29
|
it 'recognises its own short name' do
|
28
|
-
expect(
|
30
|
+
expect(ctx.matches?(['banana', exp_name])).to eq(true)
|
29
31
|
end
|
30
32
|
it 'recognises its short name as a regex' do
|
31
|
-
expect(
|
33
|
+
expect(ctx.matches?([/banana/, /#{exp_name}/])).to eq(true)
|
32
34
|
end
|
33
35
|
it 'does not blow up on []-ended Strings' do
|
34
|
-
expect(
|
36
|
+
expect(ctx.matches?(['banana[]', exp_name])).to eq(true)
|
35
37
|
end
|
36
38
|
|
37
39
|
context 'when there is an outer' do
|
38
|
-
let(:
|
40
|
+
let(:ctx) { Reek::Context::CodeContext.new(outer, exp) }
|
41
|
+
let(:outer_name) { 'another_random sting' }
|
42
|
+
let(:outer) { double('outer') }
|
43
|
+
|
39
44
|
before :each do
|
40
|
-
|
41
|
-
allow(outer).to receive(:full_name).at_least(:once).and_return(@outer_name)
|
45
|
+
allow(outer).to receive(:full_name).at_least(:once).and_return(outer_name)
|
42
46
|
allow(outer).to receive(:config).and_return({})
|
43
|
-
@ctx = Reek::Context::CodeContext.new(outer, @exp)
|
44
47
|
end
|
48
|
+
|
45
49
|
it 'creates the correct full name' do
|
46
|
-
expect(
|
50
|
+
expect(ctx.full_name).to eq(full_name)
|
47
51
|
end
|
48
52
|
it 'recognises its own full name' do
|
49
|
-
expect(
|
53
|
+
expect(ctx.matches?(['banana', full_name])).to eq(true)
|
50
54
|
end
|
51
55
|
it 'recognises its full name as a regex' do
|
52
|
-
expect(
|
56
|
+
expect(ctx.matches?([/banana/, /#{full_name}/])).to eq(true)
|
53
57
|
end
|
54
58
|
end
|
55
59
|
end
|
56
60
|
|
57
61
|
context 'enumerating syntax elements' do
|
58
62
|
context 'in an empty module' do
|
59
|
-
|
60
|
-
|
61
|
-
src = "module #{@module_name}; end"
|
63
|
+
let(:ctx) do
|
64
|
+
src = 'module Emptiness; end'
|
62
65
|
ast = Reek::Source::SourceCode.from(src).syntax_tree
|
63
|
-
|
66
|
+
Reek::Context::CodeContext.new(nil, ast)
|
64
67
|
end
|
65
68
|
|
66
69
|
it 'yields no calls' do
|
67
|
-
|
70
|
+
ctx.each_node(:send, []) { |exp| raise "#{exp} yielded by empty module!" }
|
68
71
|
end
|
69
72
|
|
70
73
|
it 'yields one module' do
|
71
74
|
mods = 0
|
72
|
-
|
75
|
+
ctx.each_node(:module, []) { |_exp| mods += 1 }
|
73
76
|
expect(mods).to eq(1)
|
74
77
|
end
|
75
78
|
|
76
79
|
it "yields the module's full AST" do
|
77
|
-
|
78
|
-
expect(exp).to eq(s(:module, s(:const, nil,
|
80
|
+
ctx.each_node(:module, []) do |exp|
|
81
|
+
expect(exp).to eq(s(:module, s(:const, nil, :Emptiness), nil))
|
79
82
|
end
|
80
83
|
end
|
81
84
|
|
82
85
|
context 'with no block' do
|
83
86
|
it 'returns an empty array of ifs' do
|
84
|
-
expect(
|
87
|
+
expect(ctx.each_node(:if, [])).to be_empty
|
85
88
|
end
|
86
89
|
end
|
87
90
|
end
|
88
91
|
|
89
92
|
context 'with a nested element' do
|
90
|
-
|
91
|
-
|
92
|
-
@method_name = 'calloo'
|
93
|
-
src = "module #{@module_name}; def #{@method_name}; puts('hello') end; end"
|
93
|
+
let(:ctx) do
|
94
|
+
src = "module Loneliness; def calloo; puts('hello') end; end"
|
94
95
|
ast = Reek::Source::SourceCode.from(src).syntax_tree
|
95
|
-
|
96
|
+
Reek::Context::CodeContext.new(nil, ast)
|
96
97
|
end
|
98
|
+
|
97
99
|
it 'yields no ifs' do
|
98
|
-
|
100
|
+
ctx.each_node(:if, []) { |exp| raise "#{exp} yielded by empty module!" }
|
99
101
|
end
|
100
102
|
it 'yields one module' do
|
101
|
-
expect(
|
103
|
+
expect(ctx.each_node(:module, []).length).to eq(1)
|
102
104
|
end
|
103
105
|
|
104
106
|
it "yields the module's full AST" do
|
105
|
-
|
107
|
+
ctx.each_node(:module, []) do |exp|
|
106
108
|
expect(exp).to eq s(:module,
|
107
|
-
s(:const, nil,
|
109
|
+
s(:const, nil, :Loneliness),
|
108
110
|
s(:def, :calloo,
|
109
111
|
s(:args),
|
110
112
|
s(:send, nil, :puts, s(:str, 'hello'))))
|
@@ -112,37 +114,36 @@ RSpec.describe Reek::Context::CodeContext do
|
|
112
114
|
end
|
113
115
|
|
114
116
|
it 'yields one method' do
|
115
|
-
expect(
|
117
|
+
expect(ctx.each_node(:def, []).length).to eq(1)
|
116
118
|
end
|
117
119
|
|
118
120
|
it "yields the method's full AST" do
|
119
|
-
|
121
|
+
ctx.each_node(:def, []) { |exp| expect(exp[1]).to eq(:calloo) }
|
120
122
|
end
|
121
123
|
|
122
124
|
context 'pruning the traversal' do
|
123
125
|
it 'ignores the call inside the method' do
|
124
|
-
expect(
|
126
|
+
expect(ctx.each_node(:send, [:def])).to be_empty
|
125
127
|
end
|
126
128
|
end
|
127
129
|
end
|
128
130
|
|
129
131
|
it 'finds 3 ifs in a class' do
|
130
|
-
src =
|
131
|
-
class Scrunch
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
end
|
144
|
-
EOS
|
145
|
-
|
132
|
+
src = <<-EOS
|
133
|
+
class Scrunch
|
134
|
+
def first
|
135
|
+
return @field == :sym ? 0 : 3;
|
136
|
+
end
|
137
|
+
def second
|
138
|
+
if @field == :sym
|
139
|
+
@other += " quarts"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
def third
|
143
|
+
raise 'flu!' unless @field == :sym
|
144
|
+
end
|
145
|
+
end
|
146
|
+
EOS
|
146
147
|
ast = Reek::Source::SourceCode.from(src).syntax_tree
|
147
148
|
ctx = Reek::Context::CodeContext.new(nil, ast)
|
148
149
|
expect(ctx.each_node(:if, []).length).to eq(3)
|
@@ -152,11 +153,11 @@ EOS
|
|
152
153
|
describe '#config_for' do
|
153
154
|
let(:src) do
|
154
155
|
<<-EOS
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
156
|
+
# :reek:DuplicateMethodCall: { allow_calls: [ puts ] }')
|
157
|
+
def repeated_greeting
|
158
|
+
puts 'Hello!'
|
159
|
+
puts 'Hello!'
|
160
|
+
end
|
160
161
|
EOS
|
161
162
|
end
|
162
163
|
let(:expression) { Reek::Source::SourceCode.from(src).syntax_tree }
|