reek 2.0.0 → 2.0.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/CHANGELOG +5 -0
- data/README.md +13 -2
- data/Rakefile +2 -1
- data/features/command_line_interface/options.feature +2 -3
- data/features/command_line_interface/smell_selection.feature +0 -1
- data/features/command_line_interface/smells_count.feature +0 -2
- data/features/command_line_interface/stdin.feature +3 -10
- data/features/configuration_files/masking_smells.feature +1 -5
- data/features/configuration_files/overrides_defaults.feature +0 -1
- data/features/rake_task/rake_task.feature +1 -4
- data/features/reports/json.feature +73 -0
- data/features/reports/reports.feature +0 -3
- data/features/reports/yaml.feature +0 -1
- data/features/ruby_api/api.feature +0 -1
- data/features/samples.feature +0 -4
- data/features/step_definitions/reek_steps.rb +14 -4
- data/features/support/env.rb +3 -0
- data/lib/reek/cli/option_interpreter.rb +2 -0
- data/lib/reek/cli/options.rb +3 -3
- data/lib/reek/cli/report/formatter.rb +1 -1
- data/lib/reek/cli/report/location_formatter.rb +11 -0
- data/lib/reek/cli/report/report.rb +11 -2
- data/lib/reek/core/code_context.rb +49 -10
- data/lib/reek/core/sniffer.rb +2 -2
- data/lib/reek/core/{code_parser.rb → tree_walker.rb} +16 -7
- data/lib/reek/examiner.rb +0 -39
- data/lib/reek/smells.rb +3 -25
- data/lib/reek/smells/feature_envy.rb +0 -2
- data/lib/reek/smells/smell_detector.rb +0 -6
- data/lib/reek/source/sexp_extensions.rb +17 -6
- data/lib/reek/source/sexp_node.rb +1 -1
- data/lib/reek/spec.rb +66 -0
- data/lib/reek/spec/should_reek.rb +0 -6
- data/lib/reek/spec/should_reek_of.rb +0 -49
- data/lib/reek/spec/should_reek_only_of.rb +0 -11
- data/lib/reek/version.rb +6 -1
- data/reek.gemspec +3 -2
- data/spec/reek/cli/json_report_spec.rb +20 -0
- data/spec/reek/core/code_context_spec.rb +6 -0
- data/spec/reek/core/smell_configuration_spec.rb +3 -3
- data/spec/reek/core/{code_parser_spec.rb → tree_walker_spec.rb} +4 -4
- data/spec/reek/examiner_spec.rb +0 -19
- data/spec/reek/smells/attribute_spec.rb +6 -9
- data/spec/reek/smells/boolean_parameter_spec.rb +13 -15
- data/spec/reek/smells/class_variable_spec.rb +17 -17
- data/spec/reek/smells/control_parameter_spec.rb +44 -46
- data/spec/reek/smells/data_clump_spec.rb +73 -70
- data/spec/reek/smells/duplicate_method_call_spec.rb +39 -37
- data/spec/reek/smells/feature_envy_spec.rb +53 -57
- data/spec/reek/smells/irresponsible_module_spec.rb +12 -11
- data/spec/reek/smells/long_parameter_list_spec.rb +33 -26
- data/spec/reek/smells/long_yield_list_spec.rb +15 -19
- data/spec/reek/smells/module_initialize_spec.rb +4 -6
- data/spec/reek/smells/nested_iterators_spec.rb +28 -28
- data/spec/reek/smells/nil_check_spec.rb +18 -20
- data/spec/reek/smells/prima_donna_method_spec.rb +6 -9
- data/spec/reek/smells/repeated_conditional_spec.rb +41 -43
- data/spec/reek/smells/too_many_instance_variables_spec.rb +6 -11
- data/spec/reek/smells/too_many_methods_spec.rb +44 -61
- data/spec/reek/smells/too_many_statements_spec.rb +14 -41
- data/spec/reek/smells/uncommunicative_method_name_spec.rb +6 -11
- data/spec/reek/smells/uncommunicative_module_name_spec.rb +10 -14
- data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +15 -16
- data/spec/reek/smells/uncommunicative_variable_name_spec.rb +33 -36
- data/spec/reek/smells/unused_parameters_spec.rb +16 -19
- data/spec/reek/smells/utility_function_spec.rb +7 -10
- metadata +22 -6
@@ -35,54 +35,5 @@ module Reek
|
|
35
35
|
smell_category_or_type.to_s.split(/::/)[-1]
|
36
36
|
end
|
37
37
|
end
|
38
|
-
|
39
|
-
#
|
40
|
-
# Checks the target source code for instances of "smell category"
|
41
|
-
# and returns true only if it can find one of them that matches.
|
42
|
-
#
|
43
|
-
# Remember that this includes our "smell types" as well. So it could be the
|
44
|
-
# "smell type" UtilityFunction, which is represented as a concrete class
|
45
|
-
# in reek but it could also be "Duplication" which is a "smell categgory".
|
46
|
-
#
|
47
|
-
# In theory you could pass many different types of input here:
|
48
|
-
# - :UtilityFunction
|
49
|
-
# - "UtilityFunction"
|
50
|
-
# - UtilityFunction (this works in our specs because we tend to do "include Reek:Smells")
|
51
|
-
# - Reek::Smells::UtilityFunction (the right way if you really want to pass a class)
|
52
|
-
# - "Duplication" or :Duplication which is an abstract "smell category"
|
53
|
-
#
|
54
|
-
# It is recommended to pass this as a symbol like :UtilityFunction. However we don't
|
55
|
-
# enforce this.
|
56
|
-
#
|
57
|
-
# Additionally you can be more specific and pass in "smell_details" you
|
58
|
-
# want to check for as well e.g. "name" or "count" (see the examples below).
|
59
|
-
# The parameters you can check for are depending on the smell you are checking for.
|
60
|
-
# For instance "count" doesn't make sense everywhere whereas "name" does in most cases.
|
61
|
-
# If you pass in a parameter that doesn't exist (e.g. you make a typo like "namme") reek will
|
62
|
-
# raise an ArgumentError to give you a hint that you passed something that doesn't make
|
63
|
-
# much sense.
|
64
|
-
#
|
65
|
-
# smell_category - The "smell category" or "smell_type" we check for.
|
66
|
-
# smells_details - A hash containing "smell warning" parameters
|
67
|
-
#
|
68
|
-
# Examples
|
69
|
-
#
|
70
|
-
# Without smell_details:
|
71
|
-
#
|
72
|
-
# reek_of(:FeatureEnvy)
|
73
|
-
# reek_of(Reek::Smells::UtilityFunction)
|
74
|
-
#
|
75
|
-
# With smell_details:
|
76
|
-
#
|
77
|
-
# reek_of(UncommunicativeParameterName, name: 'x2')
|
78
|
-
# reek_of(DataClump, count: 3)
|
79
|
-
#
|
80
|
-
# Examples from a real spec
|
81
|
-
#
|
82
|
-
# expect(src).to reek_of(Reek::Smells::DuplicateMethodCall, name: '@other.thing')
|
83
|
-
#
|
84
|
-
def reek_of(smell_category, smell_details = {})
|
85
|
-
ShouldReekOf.new(smell_category, smell_details)
|
86
|
-
end
|
87
38
|
end
|
88
39
|
end
|
@@ -28,16 +28,5 @@ module Reek
|
|
28
28
|
"Expected #{@examiner.description} not to reek only of #{@smell_category}, but it did"
|
29
29
|
end
|
30
30
|
end
|
31
|
-
|
32
|
-
#
|
33
|
-
# See the documentaton for "reek_of".
|
34
|
-
#
|
35
|
-
# Notable differences to reek_of:
|
36
|
-
# 1.) "reek_of" doesn't mind if there are other smells of a different category.
|
37
|
-
# "reek_only_of" will fail in that case.
|
38
|
-
# 2.) "reek_only_of" doesn't support the additional smell_details hash.
|
39
|
-
def reek_only_of(smell_category)
|
40
|
-
ShouldReekOnlyOf.new(smell_category)
|
41
|
-
end
|
42
31
|
end
|
43
32
|
end
|
data/lib/reek/version.rb
CHANGED
data/reek.gemspec
CHANGED
@@ -4,7 +4,7 @@ require 'reek/version'
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = 'reek'
|
7
|
-
s.version = Reek::
|
7
|
+
s.version = Reek::Version::STRING
|
8
8
|
|
9
9
|
s.authors = ['Kevin Rutherford', 'Timo Roessner', 'Matijs van Zuijlen']
|
10
10
|
s.default_executable = 'reek'
|
@@ -33,6 +33,7 @@ Gem::Specification.new do |s|
|
|
33
33
|
s.add_runtime_dependency('parser', ['~> 2.2'])
|
34
34
|
s.add_runtime_dependency('unparser', ['~> 0.2.2'])
|
35
35
|
s.add_runtime_dependency('rainbow', ['~> 2.0'])
|
36
|
+
s.add_runtime_dependency('require_all', ['~> 1.3'])
|
36
37
|
|
37
38
|
s.add_development_dependency('bundler', ['~> 1.1'])
|
38
39
|
s.add_development_dependency('rake', ['~> 10.0'])
|
@@ -40,5 +41,5 @@ Gem::Specification.new do |s|
|
|
40
41
|
s.add_development_dependency('rspec', ['~> 3.0'])
|
41
42
|
s.add_development_dependency('yard', ['>= 0.8.7', '< 0.9'])
|
42
43
|
s.add_development_dependency('factory_girl', ['~> 4.0'])
|
43
|
-
s.add_development_dependency('rubocop', ['~> 0.
|
44
|
+
s.add_development_dependency('rubocop', ['~> 0.29.0'])
|
44
45
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'reek/examiner'
|
3
|
+
require 'reek/cli/report/report'
|
4
|
+
require 'reek/cli/report/formatter'
|
5
|
+
|
6
|
+
describe Reek::Cli::Report::JsonReport do
|
7
|
+
let(:instance) { Reek::Cli::Report::JsonReport.new }
|
8
|
+
|
9
|
+
context 'empty source' do
|
10
|
+
let(:examiner) { Reek::Examiner.new('') }
|
11
|
+
|
12
|
+
before do
|
13
|
+
instance.add_examiner examiner
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'prints empty json' do
|
17
|
+
expect { instance.show }.to output(/^\[\]$/).to_stdout
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -25,12 +25,18 @@ describe CodeContext do
|
|
25
25
|
it 'does not match when its own short name is not given' do
|
26
26
|
expect(@ctx.matches?(['banana'])).to eq(false)
|
27
27
|
end
|
28
|
+
it 'does not let pipe-ended Strings make matching ignore the rest' do
|
29
|
+
expect(@ctx.matches?(['banana|'])).to eq(false)
|
30
|
+
end
|
28
31
|
it 'recognises its own short name' do
|
29
32
|
expect(@ctx.matches?(['banana', @exp_name])).to eq(true)
|
30
33
|
end
|
31
34
|
it 'recognises its short name as a regex' do
|
32
35
|
expect(@ctx.matches?([/banana/, /#{@exp_name}/])).to eq(true)
|
33
36
|
end
|
37
|
+
it 'does not blow up on []-ended Strings' do
|
38
|
+
expect(@ctx.matches?(['banana[]', @exp_name])).to eq(true)
|
39
|
+
end
|
34
40
|
|
35
41
|
context 'when there is an outer' do
|
36
42
|
let(:outer) { double('outer') }
|
@@ -47,9 +47,9 @@ describe SmellConfiguration do
|
|
47
47
|
|
48
48
|
it 'should override multiple values' do
|
49
49
|
expect(@smell_config.merge!('enabled' => false, 'accept' => [/[A-Z]$/])).to eq(
|
50
|
-
|
51
|
-
|
52
|
-
|
50
|
+
'enabled' => false, 'exclude' => [],
|
51
|
+
'reject' => [/^.$/, /[0-9]$/, /[A-Z]/],
|
52
|
+
'accept' => [/[A-Z]$/]
|
53
53
|
)
|
54
54
|
end
|
55
55
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'reek/core/
|
2
|
+
require 'reek/core/tree_walker'
|
3
3
|
|
4
4
|
include Reek::Core
|
5
5
|
|
6
|
-
describe
|
6
|
+
describe TreeWalker, 'with no method definitions' do
|
7
7
|
it 'reports no problems for empty source code' do
|
8
8
|
expect('').not_to reek
|
9
9
|
end
|
@@ -13,14 +13,14 @@ class Fred; end').not_to reek
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
describe
|
16
|
+
describe TreeWalker, 'with a global method definition' do
|
17
17
|
it 'reports no problems for simple method' do
|
18
18
|
src = 'def Outermost::fred() true; end'
|
19
19
|
expect(src).not_to reek
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
describe
|
23
|
+
describe TreeWalker, 'when a yield is the receiver' do
|
24
24
|
it 'reports no problems' do
|
25
25
|
src = <<EOS
|
26
26
|
def values(*args)
|
data/spec/reek/examiner_spec.rb
CHANGED
@@ -3,21 +3,6 @@ require 'reek/examiner'
|
|
3
3
|
|
4
4
|
include Reek
|
5
5
|
|
6
|
-
shared_examples_for 'supports the deprecated api' do
|
7
|
-
it 'returns all smells as active' do
|
8
|
-
expect(@examiner.all_active_smells).to eq(@examiner.smells)
|
9
|
-
end
|
10
|
-
it 'returns all smells as active' do
|
11
|
-
expect(@examiner.all_smells).to eq(@examiner.smells)
|
12
|
-
end
|
13
|
-
it 'counts all smells as active smells' do
|
14
|
-
expect(@examiner.num_active_smells).to eq(@examiner.smells.length)
|
15
|
-
end
|
16
|
-
it 'never reports masked smells' do
|
17
|
-
expect(@examiner.num_masked_smells).to eq(0)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
6
|
shared_examples_for 'no smells found' do
|
22
7
|
it 'is not smelly' do
|
23
8
|
expect(@examiner).not_to be_smelly
|
@@ -25,8 +10,6 @@ shared_examples_for 'no smells found' do
|
|
25
10
|
it 'finds no smells' do
|
26
11
|
expect(@examiner.smells.length).to eq(0)
|
27
12
|
end
|
28
|
-
|
29
|
-
it_should_behave_like 'supports the deprecated api'
|
30
13
|
end
|
31
14
|
|
32
15
|
shared_examples_for 'one smell found' do
|
@@ -39,8 +22,6 @@ shared_examples_for 'one smell found' do
|
|
39
22
|
it 'reports the correct smell' do
|
40
23
|
expect(@examiner.smells[0].smell_category).to eq(@expected_first_smell)
|
41
24
|
end
|
42
|
-
|
43
|
-
it_should_behave_like 'supports the deprecated api'
|
44
25
|
end
|
45
26
|
|
46
27
|
describe Examiner do
|
@@ -3,13 +3,10 @@ require 'reek/smells/attribute'
|
|
3
3
|
require 'reek/core/module_context'
|
4
4
|
require 'reek/smells/smell_detector_shared'
|
5
5
|
|
6
|
-
|
7
|
-
include Reek::Smells
|
8
|
-
|
9
|
-
describe Attribute do
|
6
|
+
describe Reek::Smells::Attribute do
|
10
7
|
before :each do
|
11
|
-
@source_name = '
|
12
|
-
@detector = Attribute
|
8
|
+
@source_name = 'dummy_source'
|
9
|
+
@detector = build(:smell_detector, smell_type: :Attribute, source: @source_name)
|
13
10
|
end
|
14
11
|
|
15
12
|
it_should_behave_like 'SmellDetector'
|
@@ -17,7 +14,7 @@ describe Attribute do
|
|
17
14
|
context 'with no attributes' do
|
18
15
|
it 'records nothing in the module' do
|
19
16
|
src = 'module Fred; end'
|
20
|
-
ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
|
17
|
+
ctx = Reek::Core::CodeContext.new(nil, src.to_reek_source.syntax_tree)
|
21
18
|
expect(@detector.examine_context(ctx)).to be_empty
|
22
19
|
end
|
23
20
|
end
|
@@ -29,7 +26,7 @@ describe Attribute do
|
|
29
26
|
|
30
27
|
shared_examples_for 'one attribute found' do
|
31
28
|
before :each do
|
32
|
-
ctx = CodeContext.new(nil, @src.to_reek_source.syntax_tree)
|
29
|
+
ctx = Reek::Core::CodeContext.new(nil, @src.to_reek_source.syntax_tree)
|
33
30
|
@smells = @detector.examine_context(ctx)
|
34
31
|
end
|
35
32
|
|
@@ -46,7 +43,7 @@ describe Attribute do
|
|
46
43
|
end
|
47
44
|
|
48
45
|
it 'reports the correct smell class' do
|
49
|
-
expect(@smells[0].smell_category).to eq(
|
46
|
+
expect(@smells[0].smell_category).to eq(described_class.smell_category)
|
50
47
|
end
|
51
48
|
|
52
49
|
it 'reports the context fq name' do
|
@@ -2,9 +2,7 @@ require 'spec_helper'
|
|
2
2
|
require 'reek/smells/boolean_parameter'
|
3
3
|
require 'reek/smells/smell_detector_shared'
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
describe BooleanParameter do
|
5
|
+
describe Reek::Smells::BooleanParameter do
|
8
6
|
context 'parameter defaulted with boolean' do
|
9
7
|
context 'in a method' do
|
10
8
|
it 'reports a parameter defaulted to true' do
|
@@ -14,51 +12,51 @@ describe BooleanParameter do
|
|
14
12
|
|
15
13
|
it 'reports a parameter defaulted to false' do
|
16
14
|
src = 'def cc(arga = false) end'
|
17
|
-
expect(src).to reek_of(BooleanParameter, name: 'arga')
|
15
|
+
expect(src).to reek_of(:BooleanParameter, name: 'arga')
|
18
16
|
end
|
19
17
|
|
20
18
|
it 'reports two parameters defaulted to booleans' do
|
21
19
|
src = 'def cc(nowt, arga = true, argb = false, &blk) end'
|
22
|
-
expect(src).to reek_of(BooleanParameter, name: 'arga')
|
23
|
-
expect(src).to reek_of(BooleanParameter, name: 'argb')
|
20
|
+
expect(src).to reek_of(:BooleanParameter, name: 'arga')
|
21
|
+
expect(src).to reek_of(:BooleanParameter, name: 'argb')
|
24
22
|
end
|
25
23
|
end
|
26
24
|
|
27
25
|
context 'in a singleton method' do
|
28
26
|
it 'reports a parameter defaulted to true' do
|
29
27
|
src = 'def self.cc(arga = true) end'
|
30
|
-
expect(src).to reek_of(BooleanParameter, name: 'arga')
|
28
|
+
expect(src).to reek_of(:BooleanParameter, name: 'arga')
|
31
29
|
end
|
32
30
|
it 'reports a parameter defaulted to false' do
|
33
31
|
src = 'def fred.cc(arga = false) end'
|
34
|
-
expect(src).to reek_of(BooleanParameter, name: 'arga')
|
32
|
+
expect(src).to reek_of(:BooleanParameter, name: 'arga')
|
35
33
|
end
|
36
34
|
it 'reports two parameters defaulted to booleans' do
|
37
35
|
src = 'def Module.cc(nowt, arga = true, argb = false, &blk) end'
|
38
|
-
expect(src).to reek_of(BooleanParameter, name: 'arga')
|
39
|
-
expect(src).to reek_of(BooleanParameter, name: 'argb')
|
36
|
+
expect(src).to reek_of(:BooleanParameter, name: 'arga')
|
37
|
+
expect(src).to reek_of(:BooleanParameter, name: 'argb')
|
40
38
|
end
|
41
39
|
end
|
42
40
|
end
|
43
41
|
|
44
42
|
context 'when a smell is reported' do
|
45
43
|
before(:each) do
|
46
|
-
@source_name = '
|
47
|
-
@detector = BooleanParameter
|
44
|
+
@source_name = 'dummy_source'
|
45
|
+
@detector = build(:smell_detector, smell_type: :BooleanParameter, source: @source_name)
|
48
46
|
end
|
49
47
|
|
50
48
|
it_should_behave_like 'SmellDetector'
|
51
49
|
|
52
50
|
it 'reports the fields correctly' do
|
53
51
|
src = 'def cc(arga = true) end'
|
54
|
-
ctx = MethodContext.new(nil, src.to_reek_source.syntax_tree)
|
52
|
+
ctx = Reek::Core::MethodContext.new(nil, src.to_reek_source.syntax_tree)
|
55
53
|
@detector.examine(ctx)
|
56
54
|
smells = @detector.smells_found.to_a
|
57
55
|
expect(smells.length).to eq(1)
|
58
|
-
expect(smells[0].smell_category).to eq(
|
56
|
+
expect(smells[0].smell_category).to eq(described_class.smell_category)
|
59
57
|
expect(smells[0].parameters[:name]).to eq('arga')
|
60
58
|
expect(smells[0].source).to eq(@source_name)
|
61
|
-
expect(smells[0].smell_type).to eq(
|
59
|
+
expect(smells[0].smell_type).to eq(described_class.smell_type)
|
62
60
|
expect(smells[0].lines).to eq([1])
|
63
61
|
end
|
64
62
|
end
|
@@ -3,13 +3,10 @@ require 'reek/smells/class_variable'
|
|
3
3
|
require 'reek/core/module_context'
|
4
4
|
require 'reek/smells/smell_detector_shared'
|
5
5
|
|
6
|
-
|
7
|
-
include Reek::Smells
|
8
|
-
|
9
|
-
describe ClassVariable do
|
6
|
+
describe Reek::Smells::ClassVariable do
|
10
7
|
before :each do
|
11
|
-
@source_name = '
|
12
|
-
@detector = ClassVariable
|
8
|
+
@source_name = 'dummy_source'
|
9
|
+
@detector = build(:smell_detector, smell_type: :ClassVariable, source: @source_name)
|
13
10
|
@class_variable = '@@things'
|
14
11
|
end
|
15
12
|
|
@@ -18,11 +15,12 @@ describe ClassVariable do
|
|
18
15
|
context 'with no class variables' do
|
19
16
|
it 'records nothing in the class' do
|
20
17
|
exp = ast(:class, :Fred)
|
21
|
-
expect(@detector.examine_context(CodeContext.new(nil, exp))).to be_empty
|
18
|
+
expect(@detector.examine_context(Reek::Core::CodeContext.new(nil, exp))).to be_empty
|
22
19
|
end
|
20
|
+
|
23
21
|
it 'records nothing in the module' do
|
24
22
|
exp = ast(:module, :Fred)
|
25
|
-
expect(@detector.examine_context(CodeContext.new(nil, exp))).to be_empty
|
23
|
+
expect(@detector.examine_context(Reek::Core::CodeContext.new(nil, exp))).to be_empty
|
26
24
|
end
|
27
25
|
end
|
28
26
|
|
@@ -30,11 +28,13 @@ describe ClassVariable do
|
|
30
28
|
shared_examples_for 'one variable found' do
|
31
29
|
before :each do
|
32
30
|
ast = @src.to_reek_source.syntax_tree
|
33
|
-
@smells = @detector.examine_context(CodeContext.new(nil, ast))
|
31
|
+
@smells = @detector.examine_context(Reek::Core::CodeContext.new(nil, ast))
|
34
32
|
end
|
33
|
+
|
35
34
|
it 'records only that class variable' do
|
36
35
|
expect(@smells.length).to eq(1)
|
37
36
|
end
|
37
|
+
|
38
38
|
it 'records the variable name' do
|
39
39
|
expect(@smells[0].parameters[:name]).to eq(@class_variable)
|
40
40
|
end
|
@@ -94,16 +94,16 @@ describe ClassVariable do
|
|
94
94
|
end
|
95
95
|
|
96
96
|
it 'reports the correct fields' do
|
97
|
-
src =
|
98
|
-
module Fred
|
99
|
-
|
100
|
-
end
|
101
|
-
EOS
|
102
|
-
ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
|
97
|
+
src = <<-EOS
|
98
|
+
module Fred
|
99
|
+
#{@class_variable} = {}
|
100
|
+
end
|
101
|
+
EOS
|
102
|
+
ctx = Reek::Core::CodeContext.new(nil, src.to_reek_source.syntax_tree)
|
103
103
|
@warning = @detector.examine_context(ctx)[0]
|
104
104
|
expect(@warning.source).to eq(@source_name)
|
105
|
-
expect(@warning.smell_category).to eq(
|
106
|
-
expect(@warning.smell_type).to eq(
|
105
|
+
expect(@warning.smell_category).to eq(described_class.smell_category)
|
106
|
+
expect(@warning.smell_type).to eq(described_class.smell_type)
|
107
107
|
expect(@warning.parameters[:name]).to eq(@class_variable)
|
108
108
|
expect(@warning.lines).to eq([2])
|
109
109
|
end
|
@@ -2,12 +2,10 @@ require 'spec_helper'
|
|
2
2
|
require 'reek/smells/control_parameter'
|
3
3
|
require 'reek/smells/smell_detector_shared'
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
describe ControlParameter do
|
5
|
+
describe Reek::Smells::ControlParameter do
|
8
6
|
before(:each) do
|
9
|
-
@source_name = '
|
10
|
-
@detector = ControlParameter
|
7
|
+
@source_name = 'dummy_source'
|
8
|
+
@detector = build(:smell_detector, smell_type: :ControlParameter, source: @source_name)
|
11
9
|
end
|
12
10
|
|
13
11
|
it_should_behave_like 'SmellDetector'
|
@@ -15,94 +13,94 @@ describe ControlParameter do
|
|
15
13
|
context 'parameter not used to determine code path' do
|
16
14
|
it 'does not report a ternary check on an ivar' do
|
17
15
|
src = 'def simple(arga) @ivar ? arga : 3 end'
|
18
|
-
expect(src).not_to reek_of(ControlParameter)
|
16
|
+
expect(src).not_to reek_of(:ControlParameter)
|
19
17
|
end
|
20
18
|
|
21
19
|
it 'does not report a ternary check on a lvar' do
|
22
20
|
src = 'def simple(arga) lvar = 27; lvar ? arga : @ivar end'
|
23
|
-
expect(src).not_to reek_of(ControlParameter)
|
21
|
+
expect(src).not_to reek_of(:ControlParameter)
|
24
22
|
end
|
25
23
|
|
26
24
|
it 'does not report when parameter is unused' do
|
27
25
|
src = 'def simple(arg) test = 1 end'
|
28
|
-
expect(src).not_to reek_of(ControlParameter)
|
26
|
+
expect(src).not_to reek_of(:ControlParameter)
|
29
27
|
end
|
30
28
|
|
31
29
|
it 'does not report when parameter is used inside conditional' do
|
32
30
|
src = 'def simple(arg) if true then puts arg end end'
|
33
|
-
expect(src).not_to reek_of(ControlParameter)
|
31
|
+
expect(src).not_to reek_of(:ControlParameter)
|
34
32
|
end
|
35
33
|
end
|
36
34
|
|
37
35
|
context 'parameter only used to determine code path' do
|
38
36
|
it 'reports a ternary check on a parameter' do
|
39
37
|
src = 'def simple(arga) arga ? @ivar : 3 end'
|
40
|
-
expect(src).to reek_of(ControlParameter, name: 'arga')
|
38
|
+
expect(src).to reek_of(:ControlParameter, name: 'arga')
|
41
39
|
end
|
42
40
|
|
43
41
|
it 'reports a couple inside a block' do
|
44
42
|
src = 'def blocks(arg) @text.map { |blk| arg ? blk : "#{blk}" } end'
|
45
|
-
expect(src).to reek_of(ControlParameter, name: 'arg')
|
43
|
+
expect(src).to reek_of(:ControlParameter, name: 'arg')
|
46
44
|
end
|
47
45
|
|
48
46
|
it 'reports on an if statement modifier' do
|
49
47
|
src = 'def simple(arg) args = {}; args.merge(\'a\' => \'A\') if arg end'
|
50
|
-
expect(src).to reek_of(ControlParameter, name: 'arg')
|
48
|
+
expect(src).to reek_of(:ControlParameter, name: 'arg')
|
51
49
|
end
|
52
50
|
|
53
51
|
it 'reports on an unless statement modifier' do
|
54
52
|
src = 'def simple(arg) args = {}; args.merge(\'a\' => \'A\') unless arg end'
|
55
|
-
expect(src).to reek_of(ControlParameter, name: 'arg')
|
53
|
+
expect(src).to reek_of(:ControlParameter, name: 'arg')
|
56
54
|
end
|
57
55
|
|
58
56
|
it 'reports on if control expression' do
|
59
57
|
src = 'def simple(arg) args = {}; if arg then args.merge(\'a\' => \'A\') end end'
|
60
|
-
expect(src).to reek_of(ControlParameter, name: 'arg')
|
58
|
+
expect(src).to reek_of(:ControlParameter, name: 'arg')
|
61
59
|
end
|
62
60
|
|
63
61
|
it 'reports on if control expression with &&' do
|
64
62
|
src = 'def simple(arg) if arg && true then puts "arg" end end'
|
65
|
-
expect(src).to reek_of(ControlParameter, name: 'arg')
|
63
|
+
expect(src).to reek_of(:ControlParameter, name: 'arg')
|
66
64
|
end
|
67
65
|
|
68
66
|
it 'reports on if control expression with preceding &&' do
|
69
67
|
src = 'def simple(arg) if true && arg then puts "arg" end end'
|
70
|
-
expect(src).to reek_of(ControlParameter, name: 'arg')
|
68
|
+
expect(src).to reek_of(:ControlParameter, name: 'arg')
|
71
69
|
end
|
72
70
|
|
73
71
|
it 'reports on if control expression with two && conditions' do
|
74
72
|
src = 'def simple(a) ag = {}; if a && true && true then puts "2" end end'
|
75
|
-
expect(src).to reek_of(ControlParameter, name: 'a')
|
73
|
+
expect(src).to reek_of(:ControlParameter, name: 'a')
|
76
74
|
end
|
77
75
|
|
78
76
|
it 'reports on if control expression with ||' do
|
79
77
|
src = 'def simple(arg) args = {}; if arg || true then puts "arg" end end'
|
80
|
-
expect(src).to reek_of(ControlParameter, name: 'arg')
|
78
|
+
expect(src).to reek_of(:ControlParameter, name: 'arg')
|
81
79
|
end
|
82
80
|
|
83
81
|
it 'reports on if control expression with or' do
|
84
82
|
src = 'def simple(arg) args = {}; if arg or true then puts "arg" end end'
|
85
|
-
expect(src).to reek_of(ControlParameter, name: 'arg')
|
83
|
+
expect(src).to reek_of(:ControlParameter, name: 'arg')
|
86
84
|
end
|
87
85
|
|
88
86
|
it 'reports on if control expression with if' do
|
89
87
|
src = 'def simple(arg) args = {}; if (arg if true) then puts "arg" end end'
|
90
|
-
expect(src).to reek_of(ControlParameter, name: 'arg')
|
88
|
+
expect(src).to reek_of(:ControlParameter, name: 'arg')
|
91
89
|
end
|
92
90
|
|
93
91
|
it 'reports on && notation' do
|
94
92
|
src = 'def simple(arg) args = {}; arg && args.merge(\'a\' => \'A\') end'
|
95
|
-
expect(src).to reek_of(ControlParameter, name: 'arg')
|
93
|
+
expect(src).to reek_of(:ControlParameter, name: 'arg')
|
96
94
|
end
|
97
95
|
|
98
96
|
it 'reports on || notation' do
|
99
97
|
src = 'def simple(arg) args = {}; arg || args.merge(\'a\' => \'A\') end'
|
100
|
-
expect(src).to reek_of(ControlParameter, name: 'arg')
|
98
|
+
expect(src).to reek_of(:ControlParameter, name: 'arg')
|
101
99
|
end
|
102
100
|
|
103
101
|
it 'reports on case statement' do
|
104
102
|
src = 'def simple(arg) case arg when nil; nil when false; nil else nil end end'
|
105
|
-
expect(src).to reek_of(ControlParameter, name: 'arg')
|
103
|
+
expect(src).to reek_of(:ControlParameter, name: 'arg')
|
106
104
|
end
|
107
105
|
|
108
106
|
it 'reports on nested if statements that are both control parameters' do
|
@@ -114,7 +112,7 @@ describe ControlParameter do
|
|
114
112
|
end
|
115
113
|
end
|
116
114
|
EOS
|
117
|
-
expect(src).to reek_of(ControlParameter, name: 'arg')
|
115
|
+
expect(src).to reek_of(:ControlParameter, name: 'arg')
|
118
116
|
end
|
119
117
|
|
120
118
|
it 'reports on nested if statements where the inner if is a control parameter' do
|
@@ -126,32 +124,32 @@ describe ControlParameter do
|
|
126
124
|
end
|
127
125
|
end
|
128
126
|
EOS
|
129
|
-
expect(src).to reek_of(ControlParameter, name: 'arg')
|
127
|
+
expect(src).to reek_of(:ControlParameter, name: 'arg')
|
130
128
|
end
|
131
129
|
|
132
130
|
it 'reports on explicit comparison in the condition' do
|
133
131
|
src = 'def simple(arg) if arg == :foo then :foo else :bar end end'
|
134
|
-
expect(src).to reek_of(ControlParameter)
|
132
|
+
expect(src).to reek_of(:ControlParameter)
|
135
133
|
end
|
136
134
|
|
137
135
|
it 'reports on explicit negative comparison in the condition' do
|
138
136
|
src = 'def simple(arg) if arg != :foo then :bar else :foo end end'
|
139
|
-
expect(src).to reek_of(ControlParameter)
|
137
|
+
expect(src).to reek_of(:ControlParameter)
|
140
138
|
end
|
141
139
|
|
142
140
|
it 'reports when the argument is compared to a regexp' do
|
143
141
|
src = 'def simple(arg) if arg =~ /foo/ then :foo else :bar end end'
|
144
|
-
expect(src).to reek_of(ControlParameter)
|
142
|
+
expect(src).to reek_of(:ControlParameter)
|
145
143
|
end
|
146
144
|
|
147
145
|
it 'reports when the argument is reverse-compared to a regexp' do
|
148
146
|
src = 'def simple(arg) if /foo/ =~ arg then :foo else :bar end end'
|
149
|
-
expect(src).to reek_of(ControlParameter)
|
147
|
+
expect(src).to reek_of(:ControlParameter)
|
150
148
|
end
|
151
149
|
|
152
150
|
it 'reports when the argument is used in a complex regexp' do
|
153
151
|
src = 'def simple(arg) if /foo#{arg}/ =~ bar then :foo else :bar end end'
|
154
|
-
expect(src).to reek_of(ControlParameter)
|
152
|
+
expect(src).to reek_of(:ControlParameter)
|
155
153
|
end
|
156
154
|
|
157
155
|
it 'reports when the argument is a block parameter' do
|
@@ -160,64 +158,64 @@ describe ControlParameter do
|
|
160
158
|
bar(blk || proc {})
|
161
159
|
end
|
162
160
|
EOS
|
163
|
-
expect(src).to reek_of(ControlParameter)
|
161
|
+
expect(src).to reek_of(:ControlParameter)
|
164
162
|
end
|
165
163
|
end
|
166
164
|
|
167
165
|
context 'parameter used besides determining code path' do
|
168
166
|
it 'does not report on if conditional expression' do
|
169
167
|
src = 'def simple(arg) if arg then use(arg) else use(@other) end end'
|
170
|
-
expect(src).not_to reek_of(ControlParameter)
|
168
|
+
expect(src).not_to reek_of(:ControlParameter)
|
171
169
|
end
|
172
170
|
|
173
171
|
it 'does not report on an if statement modifier' do
|
174
172
|
src = 'def simple(arg) args = {}; args.merge(\'a\' => arg) if arg end'
|
175
|
-
expect(src).not_to reek_of(ControlParameter)
|
173
|
+
expect(src).not_to reek_of(:ControlParameter)
|
176
174
|
end
|
177
175
|
|
178
176
|
it 'does not report on an unless statement modifier' do
|
179
177
|
src = 'def simple(arg) args = {}; args.merge(\'a\' => arg) unless arg end'
|
180
|
-
expect(src).not_to reek_of(ControlParameter)
|
178
|
+
expect(src).not_to reek_of(:ControlParameter)
|
181
179
|
end
|
182
180
|
|
183
181
|
it 'does not report on if control expression' do
|
184
182
|
src = 'def simple(arg) args = {}; if arg then args.merge(\'a\' => arg) end end'
|
185
|
-
expect(src).not_to reek_of(ControlParameter)
|
183
|
+
expect(src).not_to reek_of(:ControlParameter)
|
186
184
|
end
|
187
185
|
|
188
186
|
it 'does not report on if control expression with &&' do
|
189
187
|
src = 'def simple(arg) if arg && true then puts arg end end'
|
190
|
-
expect(src).not_to reek_of(ControlParameter)
|
188
|
+
expect(src).not_to reek_of(:ControlParameter)
|
191
189
|
end
|
192
190
|
|
193
191
|
it 'does not report on && notation' do
|
194
192
|
src = 'def simple(arg) args = {}; arg && args.merge(\'a\' => arg) end'
|
195
|
-
expect(src).not_to reek_of(ControlParameter)
|
193
|
+
expect(src).not_to reek_of(:ControlParameter)
|
196
194
|
end
|
197
195
|
|
198
196
|
it 'does not report on || notation' do
|
199
197
|
src = 'def simple(arg) args = {}; arg || args.merge(\'a\' => arg) end'
|
200
|
-
expect(src).not_to reek_of(ControlParameter)
|
198
|
+
expect(src).not_to reek_of(:ControlParameter)
|
201
199
|
end
|
202
200
|
|
203
201
|
it 'does not report when parameter is used outside conditional' do
|
204
202
|
src = 'def simple(arg) puts arg; if arg then @a = 1 end end'
|
205
|
-
expect(src).not_to reek_of(ControlParameter)
|
203
|
+
expect(src).not_to reek_of(:ControlParameter)
|
206
204
|
end
|
207
205
|
|
208
206
|
it 'does not report when parameter is used as a method call argument in a condition' do
|
209
207
|
src = 'def simple(arg) if foo(arg) then @a = 1 end end'
|
210
|
-
expect(src).not_to reek_of(ControlParameter)
|
208
|
+
expect(src).not_to reek_of(:ControlParameter)
|
211
209
|
end
|
212
210
|
|
213
211
|
it 'does not report when parameter is used as a method call receiver in a condition' do
|
214
212
|
src = 'def simple(arg) if arg.foo? then @a = 1 end end'
|
215
|
-
expect(src).not_to reek_of(ControlParameter)
|
213
|
+
expect(src).not_to reek_of(:ControlParameter)
|
216
214
|
end
|
217
215
|
|
218
216
|
it 'does not report when the argument is a hash on which we access a key' do
|
219
217
|
src = 'def simple(arg) if arg[\'a\'] then puts \'a\' else puts \'b\' end end'
|
220
|
-
expect(src).not_to reek_of ControlParameter
|
218
|
+
expect(src).not_to reek_of :ControlParameter
|
221
219
|
end
|
222
220
|
|
223
221
|
it 'does not report when used in first conditional but not second' do
|
@@ -231,7 +229,7 @@ describe ControlParameter do
|
|
231
229
|
end
|
232
230
|
end
|
233
231
|
EOS
|
234
|
-
expect(src).not_to reek_of(ControlParameter)
|
232
|
+
expect(src).not_to reek_of(:ControlParameter)
|
235
233
|
end
|
236
234
|
|
237
235
|
it 'does not report when used in second conditional but not first' do
|
@@ -245,7 +243,7 @@ describe ControlParameter do
|
|
245
243
|
end
|
246
244
|
end
|
247
245
|
EOS
|
248
|
-
expect(src).not_to reek_of(ControlParameter)
|
246
|
+
expect(src).not_to reek_of(:ControlParameter)
|
249
247
|
end
|
250
248
|
|
251
249
|
it 'does not report when used in body of control flow operator' do
|
@@ -260,7 +258,7 @@ describe ControlParameter do
|
|
260
258
|
qux or quuz(arg)
|
261
259
|
end
|
262
260
|
EOS
|
263
|
-
expect(src).not_to reek_of(ControlParameter)
|
261
|
+
expect(src).not_to reek_of(:ControlParameter)
|
264
262
|
end
|
265
263
|
end
|
266
264
|
|
@@ -274,7 +272,7 @@ describe ControlParameter do
|
|
274
272
|
puts "hello" if arg
|
275
273
|
end
|
276
274
|
EOS
|
277
|
-
ctx = MethodContext.new(nil, src.to_reek_source.syntax_tree)
|
275
|
+
ctx = Reek::Core::MethodContext.new(nil, src.to_reek_source.syntax_tree)
|
278
276
|
smells = @detector.examine(ctx)
|
279
277
|
expect(smells.length).to eq(1)
|
280
278
|
@warning = smells[0]
|