reek 3.2.1 → 3.3.0
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/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
@@ -63,33 +63,29 @@ RSpec.describe Reek::Context::MethodContext do
|
|
63
63
|
end
|
64
64
|
|
65
65
|
context 'with 1 default' do
|
66
|
-
|
67
|
-
src = 'def meth(arga, argb=456, &blk) end'
|
68
|
-
@defaults = assignments_from(src)
|
69
|
-
end
|
66
|
+
let(:defaults) { assignments_from('def meth(arga, argb=456, &blk) end') }
|
70
67
|
|
71
68
|
it 'returns the param-value pair' do
|
72
|
-
expect(
|
69
|
+
expect(defaults[0]).to eq [:argb, s(:int, 456)]
|
73
70
|
end
|
74
71
|
|
75
72
|
it 'returns the nothing else' do
|
76
|
-
expect(
|
73
|
+
expect(defaults.length).to eq(1)
|
77
74
|
end
|
78
75
|
end
|
79
76
|
|
80
77
|
context 'with 2 defaults' do
|
81
|
-
|
82
|
-
|
83
|
-
@defaults = assignments_from(src)
|
78
|
+
let(:defaults) do
|
79
|
+
assignments_from('def meth(arga=123, argb=456, &blk) end')
|
84
80
|
end
|
85
81
|
|
86
82
|
it 'returns both param-value pairs' do
|
87
|
-
expect(
|
88
|
-
expect(
|
83
|
+
expect(defaults[0]).to eq [:arga, s(:int, 123)]
|
84
|
+
expect(defaults[1]).to eq [:argb, s(:int, 456)]
|
89
85
|
end
|
90
86
|
|
91
87
|
it 'returns nothing else' do
|
92
|
-
expect(
|
88
|
+
expect(defaults.length).to eq(2)
|
93
89
|
end
|
94
90
|
end
|
95
91
|
end
|
@@ -8,7 +8,7 @@ RSpec.describe Reek::Context::ModuleContext do
|
|
8
8
|
module Fred
|
9
9
|
def simple(x) x + 1; end
|
10
10
|
end
|
11
|
-
').to reek_of(:UncommunicativeParameterName,
|
11
|
+
').to reek_of(:UncommunicativeParameterName, name: 'x')
|
12
12
|
end
|
13
13
|
|
14
14
|
it 'should not report module with empty class' do
|
@@ -2,15 +2,11 @@ require_relative '../../spec_helper'
|
|
2
2
|
require_relative '../../../lib/reek/context/root_context'
|
3
3
|
|
4
4
|
RSpec.describe Reek::Context::RootContext do
|
5
|
-
before :each do
|
6
|
-
src = 'foo = 1'
|
7
|
-
ast = Reek::Source::SourceCode.from(src).syntax_tree
|
8
|
-
@root = Reek::Context::RootContext.new(ast)
|
9
|
-
end
|
10
|
-
|
11
5
|
context 'full_name' do
|
12
6
|
it 'reports full context' do
|
13
|
-
|
7
|
+
ast = Reek::Source::SourceCode.from('foo = 1').syntax_tree
|
8
|
+
root = Reek::Context::RootContext.new(ast)
|
9
|
+
expect(root.full_name).to eq('')
|
14
10
|
end
|
15
11
|
end
|
16
12
|
end
|
data/spec/reek/examiner_spec.rb
CHANGED
@@ -3,64 +3,53 @@ require_relative '../../lib/reek/examiner'
|
|
3
3
|
|
4
4
|
RSpec.shared_examples_for 'no smells found' do
|
5
5
|
it 'is not smelly' do
|
6
|
-
expect(
|
6
|
+
expect(examiner).not_to be_smelly
|
7
7
|
end
|
8
8
|
it 'finds no smells' do
|
9
|
-
expect(
|
9
|
+
expect(examiner.smells.length).to eq(0)
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
13
|
RSpec.shared_examples_for 'one smell found' do
|
14
14
|
it 'is smelly' do
|
15
|
-
expect(
|
15
|
+
expect(examiner).to be_smelly
|
16
16
|
end
|
17
17
|
it 'reports the smell' do
|
18
|
-
expect(
|
18
|
+
expect(examiner.smells.length).to eq(1)
|
19
19
|
end
|
20
20
|
it 'reports the correct smell' do
|
21
|
-
expect(
|
21
|
+
expect(examiner.smells[0].smell_category).to eq(expected_first_smell)
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
25
|
RSpec.describe Reek::Examiner do
|
26
|
-
|
27
|
-
@expected_first_smell = 'NestedIterators'
|
28
|
-
end
|
26
|
+
let(:expected_first_smell) { 'NestedIterators' }
|
29
27
|
|
30
28
|
context 'with a fragrant String' do
|
31
|
-
|
32
|
-
@examiner = described_class.new('def good() true; end')
|
33
|
-
end
|
29
|
+
let(:examiner) { described_class.new('def good() true; end') }
|
34
30
|
|
35
31
|
it_should_behave_like 'no smells found'
|
36
32
|
end
|
37
33
|
|
38
34
|
context 'with a smelly String' do
|
39
|
-
|
40
|
-
|
41
|
-
@expected_first_smell = 'UncommunicativeName'
|
42
|
-
end
|
35
|
+
let(:examiner) { described_class.new('def fine() y = 4; end') }
|
36
|
+
let(:expected_first_smell) { 'UncommunicativeName' }
|
43
37
|
|
44
38
|
it_should_behave_like 'one smell found'
|
45
39
|
end
|
46
40
|
|
47
41
|
context 'with a partially masked smelly File' do
|
48
|
-
let(:path) { SAMPLES_PATH.join('all_but_one_masked/masked.reek') }
|
49
42
|
let(:configuration) { test_configuration_for(path) }
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
@examiner = described_class.new(smelly_file, [], configuration: configuration)
|
54
|
-
end
|
43
|
+
let(:examiner) { described_class.new(smelly_file, [], configuration: configuration) }
|
44
|
+
let(:path) { SAMPLES_PATH.join('all_but_one_masked/masked.reek') }
|
45
|
+
let(:smelly_file) { Pathname.glob(SAMPLES_PATH.join('all_but_one_masked/d*.rb')).first }
|
55
46
|
|
56
47
|
it_should_behave_like 'one smell found'
|
57
48
|
end
|
58
49
|
|
59
50
|
context 'with a fragrant File' do
|
60
|
-
|
61
|
-
|
62
|
-
@examiner = described_class.new(clean_file)
|
63
|
-
end
|
51
|
+
let(:clean_file) { Pathname.glob(SAMPLES_PATH.join('three_clean_files/*.rb')).first }
|
52
|
+
let(:examiner) { described_class.new(clean_file) }
|
64
53
|
|
65
54
|
it_should_behave_like 'no smells found'
|
66
55
|
end
|
@@ -3,10 +3,8 @@ require_relative '../../../lib/reek/smells/attribute'
|
|
3
3
|
require_relative 'smell_detector_shared'
|
4
4
|
|
5
5
|
RSpec.describe Reek::Smells::Attribute do
|
6
|
-
|
7
|
-
|
8
|
-
@detector = build(:smell_detector, smell_type: :Attribute, source: @source_name)
|
9
|
-
end
|
6
|
+
let(:detector) { build(:smell_detector, smell_type: :Attribute, source: source_name) }
|
7
|
+
let(:source_name) { 'dummy_source' }
|
10
8
|
|
11
9
|
it_should_behave_like 'SmellDetector'
|
12
10
|
|
@@ -66,22 +66,20 @@ RSpec.describe Reek::Smells::BooleanParameter do
|
|
66
66
|
end
|
67
67
|
|
68
68
|
context 'when a smell is reported' do
|
69
|
-
|
70
|
-
|
71
|
-
@detector = build(:smell_detector, smell_type: :BooleanParameter, source: @source_name)
|
72
|
-
end
|
69
|
+
let(:detector) { build(:smell_detector, smell_type: :BooleanParameter, source: source_name) }
|
70
|
+
let(:source_name) { 'dummy_source' }
|
73
71
|
|
74
72
|
it_should_behave_like 'SmellDetector'
|
75
73
|
|
76
74
|
it 'reports the fields correctly' do
|
77
75
|
src = 'def cc(arga = true) end'
|
78
76
|
ctx = Reek::Context::MethodContext.new(nil, Reek::Source::SourceCode.from(src).syntax_tree)
|
79
|
-
|
80
|
-
smells =
|
77
|
+
detector.examine(ctx)
|
78
|
+
smells = detector.smells_found.to_a
|
81
79
|
expect(smells.length).to eq(1)
|
82
80
|
expect(smells[0].smell_category).to eq(described_class.smell_category)
|
83
81
|
expect(smells[0].parameters[:name]).to eq('arga')
|
84
|
-
expect(smells[0].source).to eq(
|
82
|
+
expect(smells[0].source).to eq(source_name)
|
85
83
|
expect(smells[0].smell_type).to eq(described_class.smell_type)
|
86
84
|
expect(smells[0].lines).to eq([1])
|
87
85
|
end
|
@@ -4,90 +4,75 @@ require_relative '../../../lib/reek/context/module_context'
|
|
4
4
|
require_relative 'smell_detector_shared'
|
5
5
|
|
6
6
|
RSpec.describe Reek::Smells::ClassVariable do
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
@class_variable = '@@things'
|
11
|
-
end
|
7
|
+
let(:class_variable) { '@@things' }
|
8
|
+
let(:detector) { build(:smell_detector, smell_type: :ClassVariable, source: source_name) }
|
9
|
+
let(:source_name) { 'dummy_source' }
|
12
10
|
|
13
11
|
it_should_behave_like 'SmellDetector'
|
14
12
|
|
15
13
|
context 'with no class variables' do
|
16
14
|
it 'records nothing in the class' do
|
17
15
|
exp = ast(:class, :Fred)
|
18
|
-
expect(
|
16
|
+
expect(detector.examine_context(Reek::Context::CodeContext.new(nil, exp))).to be_empty
|
19
17
|
end
|
20
18
|
|
21
19
|
it 'records nothing in the module' do
|
22
20
|
exp = ast(:module, :Fred)
|
23
|
-
expect(
|
21
|
+
expect(detector.examine_context(Reek::Context::CodeContext.new(nil, exp))).to be_empty
|
24
22
|
end
|
25
23
|
end
|
26
24
|
|
27
25
|
context 'with one class variable' do
|
28
26
|
shared_examples_for 'one variable found' do
|
29
|
-
|
30
|
-
|
31
|
-
@smells = @detector.examine_context(Reek::Context::CodeContext.new(nil, ast))
|
32
|
-
end
|
27
|
+
let(:ast) { Reek::Source::SourceCode.from(src).syntax_tree }
|
28
|
+
let(:smells) { detector.examine_context(Reek::Context::CodeContext.new(nil, ast)) }
|
33
29
|
|
34
30
|
it 'records only that class variable' do
|
35
|
-
expect(
|
31
|
+
expect(smells.length).to eq(1)
|
36
32
|
end
|
37
33
|
|
38
34
|
it 'records the variable name' do
|
39
|
-
expect(
|
35
|
+
expect(smells[0].parameters[:name]).to eq(class_variable)
|
40
36
|
end
|
41
37
|
end
|
42
38
|
|
43
39
|
['class', 'module'].each do |scope|
|
44
40
|
context "declared in a #{scope}" do
|
45
|
-
|
46
|
-
@src = "#{scope} Fred; #{@class_variable} = {}; end"
|
47
|
-
end
|
48
|
-
|
41
|
+
let(:src) { "#{scope} Fred; #{class_variable} = {}; end" }
|
49
42
|
it_should_behave_like 'one variable found'
|
50
43
|
end
|
51
44
|
|
52
45
|
context "used in a #{scope}" do
|
53
|
-
|
54
|
-
@src = "#{scope} Fred; def jim() #{@class_variable} = {}; end; end"
|
55
|
-
end
|
56
|
-
|
46
|
+
let(:src) { "#{scope} Fred; def jim() #{class_variable} = {}; end; end" }
|
57
47
|
it_should_behave_like 'one variable found'
|
58
48
|
end
|
59
49
|
|
60
50
|
context "indexed in a #{scope}" do
|
61
|
-
|
62
|
-
@src = "#{scope} Fred; def jim() #{@class_variable}[mash] = {}; end; end"
|
63
|
-
end
|
64
|
-
|
51
|
+
let(:src) { "#{scope} Fred; def jim() #{class_variable}[mash] = {}; end; end" }
|
65
52
|
it_should_behave_like 'one variable found'
|
66
53
|
end
|
67
54
|
|
68
55
|
context "declared and used in a #{scope}" do
|
69
|
-
|
70
|
-
|
56
|
+
let(:src) do
|
57
|
+
<<-EOS
|
71
58
|
#{scope} Fred
|
72
|
-
#{
|
73
|
-
def jim() #{
|
59
|
+
#{class_variable} = {}
|
60
|
+
def jim() #{class_variable} = {}; end
|
74
61
|
end
|
75
|
-
|
62
|
+
EOS
|
76
63
|
end
|
77
|
-
|
78
64
|
it_should_behave_like 'one variable found'
|
79
65
|
end
|
80
66
|
|
81
67
|
context "used twice in a #{scope}" do
|
82
|
-
|
83
|
-
|
68
|
+
let(:src) do
|
69
|
+
<<-EOS
|
84
70
|
#{scope} Fred
|
85
|
-
def jeff() #{
|
86
|
-
def jim() #{
|
71
|
+
def jeff() #{class_variable} = {}; end
|
72
|
+
def jim() #{class_variable} = {}; end
|
87
73
|
end
|
88
|
-
|
74
|
+
EOS
|
89
75
|
end
|
90
|
-
|
91
76
|
it_should_behave_like 'one variable found'
|
92
77
|
end
|
93
78
|
end
|
@@ -96,15 +81,15 @@ RSpec.describe Reek::Smells::ClassVariable do
|
|
96
81
|
it 'reports the correct fields' do
|
97
82
|
src = <<-EOS
|
98
83
|
module Fred
|
99
|
-
#{
|
84
|
+
#{class_variable} = {}
|
100
85
|
end
|
101
86
|
EOS
|
102
87
|
ctx = Reek::Context::CodeContext.new(nil, Reek::Source::SourceCode.from(src).syntax_tree)
|
103
|
-
|
104
|
-
expect(
|
105
|
-
expect(
|
106
|
-
expect(
|
107
|
-
expect(
|
108
|
-
expect(
|
88
|
+
warning = detector.examine_context(ctx)[0]
|
89
|
+
expect(warning.source).to eq(source_name)
|
90
|
+
expect(warning.smell_category).to eq(described_class.smell_category)
|
91
|
+
expect(warning.smell_type).to eq(described_class.smell_type)
|
92
|
+
expect(warning.parameters[:name]).to eq(class_variable)
|
93
|
+
expect(warning.lines).to eq([2])
|
109
94
|
end
|
110
95
|
end
|
@@ -3,10 +3,8 @@ require_relative '../../../lib/reek/smells/control_parameter'
|
|
3
3
|
require_relative 'smell_detector_shared'
|
4
4
|
|
5
5
|
RSpec.describe Reek::Smells::ControlParameter do
|
6
|
-
|
7
|
-
|
8
|
-
@detector = build(:smell_detector, smell_type: :ControlParameter, source: @source_name)
|
9
|
-
end
|
6
|
+
let(:detector) { build(:smell_detector, smell_type: :ControlParameter, source: source_name) }
|
7
|
+
let(:source_name) { 'dummy_source' }
|
10
8
|
|
11
9
|
it_should_behave_like 'SmellDetector'
|
12
10
|
|
@@ -263,7 +261,7 @@ RSpec.describe Reek::Smells::ControlParameter do
|
|
263
261
|
end
|
264
262
|
|
265
263
|
context 'when a smell is reported' do
|
266
|
-
|
264
|
+
let(:warning) do
|
267
265
|
src = <<-EOS
|
268
266
|
def things(arg)
|
269
267
|
@text.map do |blk|
|
@@ -273,16 +271,16 @@ RSpec.describe Reek::Smells::ControlParameter do
|
|
273
271
|
end
|
274
272
|
EOS
|
275
273
|
ctx = Reek::Context::MethodContext.new(nil, Reek::Source::SourceCode.from(src).syntax_tree)
|
276
|
-
smells =
|
274
|
+
smells = detector.examine(ctx)
|
277
275
|
expect(smells.length).to eq(1)
|
278
|
-
|
276
|
+
smells.first
|
279
277
|
end
|
280
278
|
|
281
279
|
it_should_behave_like 'common fields set correctly'
|
282
280
|
|
283
281
|
it 'has the correct fields' do
|
284
|
-
expect(
|
285
|
-
expect(
|
282
|
+
expect(warning.parameters[:name]).to eq('arg')
|
283
|
+
expect(warning.lines).to eq([3, 5])
|
286
284
|
end
|
287
285
|
end
|
288
286
|
end
|
@@ -6,7 +6,7 @@ RSpec.shared_examples_for 'a data clump detector' do
|
|
6
6
|
it 'does not report small parameter sets' do
|
7
7
|
src = <<-EOS
|
8
8
|
# test module
|
9
|
-
#{
|
9
|
+
#{context} Scrunch
|
10
10
|
def first(pa) @field == :sym ? 0 : 3; end
|
11
11
|
def second(pa) @field == :sym; end
|
12
12
|
def third(pa) pa - pb + @fred; end
|
@@ -16,52 +16,51 @@ RSpec.shared_examples_for 'a data clump detector' do
|
|
16
16
|
end
|
17
17
|
|
18
18
|
context 'with 3 identical pairs' do
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
#{
|
19
|
+
let(:module_name) { 'Scrunch' }
|
20
|
+
let(:smells) do
|
21
|
+
src = <<-EOS
|
22
|
+
#{context} #{module_name}
|
23
23
|
def first(pa, pb) @field == :sym ? 0 : 3; end
|
24
24
|
def second(pa, pb) @field == :sym; end
|
25
25
|
def third(pa, pb) pa - pb + @fred; end
|
26
26
|
end
|
27
27
|
EOS
|
28
|
-
ctx = Reek::Context::ModuleContext.new(nil, Reek::Source::SourceCode.from(
|
29
|
-
|
30
|
-
@smells = detector.examine_context(ctx)
|
28
|
+
ctx = Reek::Context::ModuleContext.new(nil, Reek::Source::SourceCode.from(src).syntax_tree)
|
29
|
+
build(:smell_detector, smell_type: :DataClump).examine_context(ctx)
|
31
30
|
end
|
32
31
|
|
33
32
|
it 'records only the one smell' do
|
34
|
-
expect(
|
33
|
+
expect(smells.length).to eq(1)
|
35
34
|
end
|
36
35
|
|
37
36
|
it 'reports all parameters' do
|
38
|
-
expect(
|
37
|
+
expect(smells[0].parameters[:parameters]).to eq(['pa', 'pb'])
|
39
38
|
end
|
40
39
|
|
41
40
|
it 'reports the number of occurrences' do
|
42
|
-
expect(
|
41
|
+
expect(smells[0].parameters[:count]).to eq(3)
|
43
42
|
end
|
44
43
|
|
45
44
|
it 'reports all methods' do
|
46
|
-
expect(
|
45
|
+
expect(smells[0].parameters[:methods]).to eq(['first', 'second', 'third'])
|
47
46
|
end
|
48
47
|
|
49
48
|
it 'reports the declaration line numbers' do
|
50
|
-
expect(
|
49
|
+
expect(smells[0].lines).to eq([2, 3, 4])
|
51
50
|
end
|
52
51
|
|
53
52
|
it 'reports the correct smell class' do
|
54
|
-
expect(
|
53
|
+
expect(smells[0].smell_category).to eq(Reek::Smells::DataClump.smell_category)
|
55
54
|
end
|
56
55
|
|
57
56
|
it 'reports the context fq name' do
|
58
|
-
expect(
|
57
|
+
expect(smells[0].context).to eq(module_name)
|
59
58
|
end
|
60
59
|
end
|
61
60
|
|
62
61
|
it 'reports 3 swapped pairs' do
|
63
62
|
src = <<-EOS
|
64
|
-
#{
|
63
|
+
#{context} Scrunch
|
65
64
|
def one(pa, pb) @field == :sym ? 0 : 3; end
|
66
65
|
def two(pb, pa) @field == :sym; end
|
67
66
|
def tri(pa, pb) pa - pb + @fred; end
|
@@ -74,7 +73,7 @@ RSpec.shared_examples_for 'a data clump detector' do
|
|
74
73
|
|
75
74
|
it 'reports 3 identical parameter sets' do
|
76
75
|
src = <<-EOS
|
77
|
-
#{
|
76
|
+
#{context} Scrunch
|
78
77
|
def first(pa, pb, pc) @field == :sym ? 0 : 3; end
|
79
78
|
def second(pa, pb, pc) @field == :sym; end
|
80
79
|
def third(pa, pb, pc) pa - pb + @fred; end
|
@@ -87,7 +86,7 @@ RSpec.shared_examples_for 'a data clump detector' do
|
|
87
86
|
|
88
87
|
it 'reports re-ordered identical parameter sets' do
|
89
88
|
src = <<-EOS
|
90
|
-
#{
|
89
|
+
#{context} Scrunch
|
91
90
|
def first(pb, pa, pc) @field == :sym ? 0 : 3; end
|
92
91
|
def second(pc, pb, pa) @field == :sym; end
|
93
92
|
def third(pa, pb, pc) pa - pb + @fred; end
|
@@ -100,7 +99,7 @@ RSpec.shared_examples_for 'a data clump detector' do
|
|
100
99
|
|
101
100
|
it 'counts only identical parameter sets' do
|
102
101
|
src = <<-EOS
|
103
|
-
#{
|
102
|
+
#{context} RedCloth
|
104
103
|
def fa(p1, p2, p3, conten) end
|
105
104
|
def fb(p1, p2, p3, conten) end
|
106
105
|
def fc(name, windowW, windowH) end
|
@@ -111,7 +110,7 @@ RSpec.shared_examples_for 'a data clump detector' do
|
|
111
110
|
|
112
111
|
it 'gets a real example right' do
|
113
112
|
src = <<-EOS
|
114
|
-
#{
|
113
|
+
#{context} Inline
|
115
114
|
def generate(src, options) end
|
116
115
|
def c (src, options) end
|
117
116
|
def c_singleton (src, options) end
|
@@ -124,7 +123,7 @@ RSpec.shared_examples_for 'a data clump detector' do
|
|
124
123
|
|
125
124
|
it 'correctly checks number of occurences' do
|
126
125
|
src = <<-EOS
|
127
|
-
#{
|
126
|
+
#{context} Smelly
|
128
127
|
def fa(p1, p2, p3) end
|
129
128
|
def fb(p2, p3, p4) end
|
130
129
|
def fc(p3, p4, p5) end
|
@@ -137,7 +136,7 @@ RSpec.shared_examples_for 'a data clump detector' do
|
|
137
136
|
|
138
137
|
it 'detects clumps smaller than the total number of arguments' do
|
139
138
|
src = <<-EOS
|
140
|
-
#{
|
139
|
+
#{context} Smelly
|
141
140
|
def fa(p1, p2, p3) end
|
142
141
|
def fb(p1, p3, p2) end
|
143
142
|
def fc(p4, p1, p2) end
|
@@ -149,7 +148,7 @@ RSpec.shared_examples_for 'a data clump detector' do
|
|
149
148
|
|
150
149
|
it 'ignores anonymous parameters' do
|
151
150
|
src = <<-EOS
|
152
|
-
#{
|
151
|
+
#{context} Smelly
|
153
152
|
def fa(p1, p2, *) end
|
154
153
|
def fb(p1, p2, *) end
|
155
154
|
def fc(p1, p2, *) end
|
@@ -161,24 +160,18 @@ RSpec.shared_examples_for 'a data clump detector' do
|
|
161
160
|
end
|
162
161
|
|
163
162
|
RSpec.describe Reek::Smells::DataClump do
|
164
|
-
|
165
|
-
@detector = build(:smell_detector, smell_type: :DataClump)
|
166
|
-
end
|
163
|
+
let(:detector) { build(:smell_detector, smell_type: :DataClump) }
|
167
164
|
|
168
165
|
it_should_behave_like 'SmellDetector'
|
169
166
|
|
170
167
|
context 'in a class' do
|
171
|
-
|
172
|
-
@context = 'class'
|
173
|
-
end
|
168
|
+
let(:context) { 'class' }
|
174
169
|
|
175
170
|
it_should_behave_like 'a data clump detector'
|
176
171
|
end
|
177
172
|
|
178
173
|
context 'in a module' do
|
179
|
-
|
180
|
-
@context = 'module'
|
181
|
-
end
|
174
|
+
let(:context) { 'module' }
|
182
175
|
|
183
176
|
it_should_behave_like 'a data clump detector'
|
184
177
|
end
|