reek 1.2.6 → 1.2.8
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.
- data/.yardopts +10 -0
- data/History.txt +62 -0
- data/README.md +74 -0
- data/bin/reek +2 -2
- data/config/defaults.reek +44 -5
- data/features/api.feature +20 -0
- data/features/masking_smells.feature +60 -42
- data/features/options.feature +7 -2
- data/features/rake_task.feature +29 -22
- data/features/reports.feature +9 -41
- data/features/samples.feature +184 -196
- data/features/stdin.feature +5 -8
- data/features/step_definitions/reek_steps.rb +8 -4
- data/features/support/env.rb +2 -3
- data/features/yaml.feature +85 -0
- data/lib/reek/cli/application.rb +46 -0
- data/lib/reek/cli/command_line.rb +108 -0
- data/lib/reek/cli/help_command.rb +18 -0
- data/lib/reek/cli/reek_command.rb +37 -0
- data/lib/reek/cli/report.rb +58 -0
- data/lib/reek/cli/version_command.rb +19 -0
- data/lib/reek/cli/yaml_command.rb +32 -0
- data/lib/reek/core/code_context.rb +64 -0
- data/lib/reek/core/code_parser.rb +166 -0
- data/lib/reek/core/method_context.rb +84 -0
- data/lib/reek/core/module_context.rb +20 -0
- data/lib/reek/core/object_refs.rb +51 -0
- data/lib/reek/core/singleton_method_context.rb +20 -0
- data/lib/reek/core/smell_configuration.rb +62 -0
- data/lib/reek/core/sniffer.rb +105 -0
- data/lib/reek/core/stop_context.rb +30 -0
- data/lib/reek/core/warning_collector.rb +27 -0
- data/lib/reek/examiner.rb +104 -0
- data/lib/reek/rake/task.rb +142 -0
- data/lib/reek/smell_warning.rb +73 -23
- data/lib/reek/smells/attribute.rb +26 -21
- data/lib/reek/smells/boolean_parameter.rb +38 -0
- data/lib/reek/smells/class_variable.rb +22 -9
- data/lib/reek/smells/control_couple.rb +40 -16
- data/lib/reek/smells/data_clump.rb +114 -23
- data/lib/reek/smells/duplication.rb +55 -15
- data/lib/reek/smells/feature_envy.rb +16 -7
- data/lib/reek/smells/irresponsible_module.rb +37 -0
- data/lib/reek/smells/large_class.rb +37 -19
- data/lib/reek/smells/long_method.rb +20 -9
- data/lib/reek/smells/long_parameter_list.rb +22 -10
- data/lib/reek/smells/long_yield_list.rb +43 -7
- data/lib/reek/smells/nested_iterators.rb +68 -8
- data/lib/reek/smells/simulated_polymorphism.rb +26 -15
- data/lib/reek/smells/smell_detector.rb +29 -51
- data/lib/reek/smells/uncommunicative_method_name.rb +74 -0
- data/lib/reek/smells/uncommunicative_module_name.rb +74 -0
- data/lib/reek/smells/uncommunicative_parameter_name.rb +79 -0
- data/lib/reek/smells/uncommunicative_variable_name.rb +89 -0
- data/lib/reek/smells/utility_function.rb +51 -12
- data/lib/reek/smells.rb +29 -0
- data/lib/reek/source/code_comment.rb +37 -0
- data/lib/reek/source/config_file.rb +72 -0
- data/lib/reek/source/core_extras.rb +46 -0
- data/lib/reek/source/reference_collector.rb +28 -0
- data/lib/reek/source/sexp_formatter.rb +17 -0
- data/lib/reek/source/source_code.rb +44 -0
- data/lib/reek/source/source_file.rb +32 -0
- data/lib/reek/source/source_locator.rb +42 -0
- data/lib/reek/source/tree_dresser.rb +204 -0
- data/lib/reek/source.rb +18 -0
- data/lib/reek/spec/should_reek.rb +31 -0
- data/lib/reek/spec/should_reek_of.rb +37 -0
- data/lib/reek/spec/should_reek_only_of.rb +37 -0
- data/lib/reek/spec.rb +51 -0
- data/lib/reek.rb +8 -4
- data/reek.gemspec +9 -7
- data/spec/matchers/smell_of_matcher.rb +58 -0
- data/spec/reek/{help_command_spec.rb → cli/help_command_spec.rb} +3 -4
- data/spec/reek/cli/reek_command_spec.rb +46 -0
- data/spec/reek/cli/report_spec.rb +30 -0
- data/spec/reek/{version_command_spec.rb → cli/version_command_spec.rb} +3 -3
- data/spec/reek/cli/yaml_command_spec.rb +47 -0
- data/spec/reek/core/code_context_spec.rb +145 -0
- data/spec/reek/{code_parser_spec.rb → core/code_parser_spec.rb} +7 -6
- data/spec/reek/{config_spec.rb → core/config_spec.rb} +2 -6
- data/spec/reek/{method_context_spec.rb → core/method_context_spec.rb} +16 -36
- data/spec/reek/core/module_context_spec.rb +27 -0
- data/spec/reek/{object_refs_spec.rb → core/object_refs_spec.rb} +5 -6
- data/spec/reek/core/singleton_method_context_spec.rb +9 -0
- data/spec/reek/core/smell_configuration_spec.rb +11 -0
- data/spec/reek/core/stop_context_spec.rb +17 -0
- data/spec/reek/core/warning_collector_spec.rb +27 -0
- data/spec/reek/examiner_spec.rb +103 -0
- data/spec/reek/smell_warning_spec.rb +74 -82
- data/spec/reek/smells/attribute_spec.rb +42 -23
- data/spec/reek/smells/behaves_like_variable_detector.rb +2 -2
- data/spec/reek/smells/boolean_parameter_spec.rb +66 -0
- data/spec/reek/smells/class_variable_spec.rb +60 -75
- data/spec/reek/smells/control_couple_spec.rb +37 -32
- data/spec/reek/smells/data_clump_spec.rb +63 -24
- data/spec/reek/smells/duplication_spec.rb +106 -57
- data/spec/reek/smells/feature_envy_spec.rb +113 -92
- data/spec/reek/smells/irresponsible_module_spec.rb +58 -0
- data/spec/reek/smells/large_class_spec.rb +67 -57
- data/spec/reek/smells/long_method_spec.rb +40 -10
- data/spec/reek/smells/long_parameter_list_spec.rb +50 -28
- data/spec/reek/smells/long_yield_list_spec.rb +57 -0
- data/spec/reek/smells/nested_iterators_spec.rb +115 -7
- data/spec/reek/smells/simulated_polymorphism_spec.rb +56 -20
- data/spec/reek/smells/smell_detector_shared.rb +42 -0
- data/spec/reek/smells/uncommunicative_method_name_spec.rb +42 -0
- data/spec/reek/smells/uncommunicative_module_name_spec.rb +66 -0
- data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +71 -0
- data/spec/reek/smells/uncommunicative_variable_name_spec.rb +120 -0
- data/spec/reek/smells/utility_function_spec.rb +50 -4
- data/spec/reek/source/code_comment_spec.rb +82 -0
- data/spec/reek/source/object_source_spec.rb +20 -0
- data/spec/reek/source/reference_collector_spec.rb +53 -0
- data/spec/reek/{adapters/source_spec.rb → source/source_code_spec.rb} +7 -8
- data/spec/reek/source/tree_dresser_spec.rb +270 -0
- data/spec/reek/spec/should_reek_of_spec.rb +76 -0
- data/spec/reek/spec/should_reek_only_of_spec.rb +89 -0
- data/spec/reek/{adapters → spec}/should_reek_spec.rb +8 -32
- data/spec/samples/all_but_one_masked/clean_one.rb +1 -0
- data/spec/samples/all_but_one_masked/dirty.rb +1 -0
- data/spec/samples/all_but_one_masked/masked.reek +5 -1
- data/spec/samples/clean_due_to_masking/clean_one.rb +1 -0
- data/spec/samples/clean_due_to_masking/clean_three.rb +1 -0
- data/spec/samples/clean_due_to_masking/clean_two.rb +1 -0
- data/spec/samples/clean_due_to_masking/dirty_one.rb +1 -1
- data/spec/samples/clean_due_to_masking/dirty_two.rb +1 -1
- data/spec/samples/clean_due_to_masking/masked.reek +5 -1
- data/spec/samples/config/allow_duplication.reek +3 -0
- data/spec/samples/config/deeper_nested_iterators.reek +3 -0
- data/spec/samples/corrupt_config_file/dirty.rb +1 -1
- data/spec/samples/demo/demo.rb +8 -0
- data/spec/samples/empty_config_file/dirty.rb +2 -1
- data/spec/samples/exceptions.reek +1 -1
- data/spec/samples/inline_config/dirty.rb +16 -0
- data/spec/samples/inline_config/masked.reek +7 -0
- data/spec/samples/mask_some/dirty.rb +8 -0
- data/spec/samples/mask_some/some.reek +8 -0
- data/spec/samples/masked/dirty.rb +2 -1
- data/spec/samples/masked/masked.reek +3 -1
- data/spec/samples/mixed_results/clean_one.rb +1 -0
- data/spec/samples/mixed_results/clean_three.rb +1 -0
- data/spec/samples/mixed_results/clean_two.rb +1 -0
- data/spec/samples/mixed_results/dirty_one.rb +1 -0
- data/spec/samples/mixed_results/dirty_two.rb +1 -0
- data/spec/samples/not_quite_masked/dirty.rb +2 -1
- data/spec/samples/not_quite_masked/masked.reek +1 -1
- data/spec/samples/overrides/masked/dirty.rb +2 -1
- data/spec/samples/overrides/masked/lower.reek +3 -1
- data/spec/samples/three_clean_files/clean_one.rb +1 -0
- data/spec/samples/three_clean_files/clean_three.rb +1 -0
- data/spec/samples/three_clean_files/clean_two.rb +1 -0
- data/spec/samples/two_smelly_files/dirty_one.rb +2 -1
- data/spec/samples/two_smelly_files/dirty_two.rb +2 -1
- data/spec/spec_helper.rb +10 -2
- data/tasks/reek.rake +2 -2
- data/tasks/test.rake +12 -3
- metadata +121 -79
- data/README.rdoc +0 -84
- data/features/profile.feature +0 -34
- data/lib/reek/adapters/application.rb +0 -46
- data/lib/reek/adapters/command_line.rb +0 -77
- data/lib/reek/adapters/config_file.rb +0 -31
- data/lib/reek/adapters/core_extras.rb +0 -64
- data/lib/reek/adapters/rake_task.rb +0 -121
- data/lib/reek/adapters/report.rb +0 -86
- data/lib/reek/adapters/source.rb +0 -72
- data/lib/reek/adapters/spec.rb +0 -133
- data/lib/reek/block_context.rb +0 -62
- data/lib/reek/class_context.rb +0 -41
- data/lib/reek/code_context.rb +0 -68
- data/lib/reek/code_parser.rb +0 -203
- data/lib/reek/configuration.rb +0 -57
- data/lib/reek/detector_stack.rb +0 -37
- data/lib/reek/help_command.rb +0 -14
- data/lib/reek/if_context.rb +0 -18
- data/lib/reek/masking_collection.rb +0 -33
- data/lib/reek/method_context.rb +0 -138
- data/lib/reek/module_context.rb +0 -49
- data/lib/reek/name.rb +0 -57
- data/lib/reek/object_refs.rb +0 -49
- data/lib/reek/reek_command.rb +0 -28
- data/lib/reek/sexp_formatter.rb +0 -10
- data/lib/reek/singleton_method_context.rb +0 -26
- data/lib/reek/smells/uncommunicative_name.rb +0 -84
- data/lib/reek/sniffer.rb +0 -177
- data/lib/reek/stop_context.rb +0 -35
- data/lib/reek/tree_dresser.rb +0 -82
- data/lib/reek/version_command.rb +0 -14
- data/lib/reek/yield_call_context.rb +0 -12
- data/spec/reek/adapters/report_spec.rb +0 -31
- data/spec/reek/adapters/should_reek_of_spec.rb +0 -138
- data/spec/reek/adapters/should_reek_only_of_spec.rb +0 -87
- data/spec/reek/block_context_spec.rb +0 -65
- data/spec/reek/class_context_spec.rb +0 -161
- data/spec/reek/code_context_spec.rb +0 -182
- data/spec/reek/configuration_spec.rb +0 -12
- data/spec/reek/if_context_spec.rb +0 -17
- data/spec/reek/masking_collection_spec.rb +0 -236
- data/spec/reek/module_context_spec.rb +0 -46
- data/spec/reek/name_spec.rb +0 -37
- data/spec/reek/object_source_spec.rb +0 -23
- data/spec/reek/reek_command_spec.rb +0 -45
- data/spec/reek/singleton_method_context_spec.rb +0 -16
- data/spec/reek/smells/smell_detector_spec.rb +0 -36
- data/spec/reek/smells/uncommunicative_name_spec.rb +0 -146
- data/spec/reek/sniffer_spec.rb +0 -11
- data/spec/reek/stop_context_spec.rb +0 -33
- data/spec/reek/tree_dresser_spec.rb +0 -20
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
require File.join(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__)))), 'spec_helper')
|
|
2
|
+
require File.join(File.dirname(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__))))), 'lib', 'reek', 'smells', 'irresponsible_module')
|
|
3
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'smell_detector_shared')
|
|
4
|
+
|
|
5
|
+
include Reek::Smells
|
|
6
|
+
|
|
7
|
+
describe IrresponsibleModule do
|
|
8
|
+
before(:each) do
|
|
9
|
+
@bad_module_name = 'WrongUn'
|
|
10
|
+
@detector = IrresponsibleModule.new('yoof')
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it_should_behave_like 'SmellDetector'
|
|
14
|
+
|
|
15
|
+
it "does not report a class having a comment" do
|
|
16
|
+
src = <<EOS
|
|
17
|
+
# test class
|
|
18
|
+
class Responsible; end
|
|
19
|
+
EOS
|
|
20
|
+
ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
|
|
21
|
+
@detector.examine_context(ctx).should be_empty
|
|
22
|
+
end
|
|
23
|
+
it "reports a class without a comment" do
|
|
24
|
+
src = "class #{@bad_module_name}; end"
|
|
25
|
+
ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
|
|
26
|
+
smells = @detector.examine_context(ctx)
|
|
27
|
+
smells.length.should == 1
|
|
28
|
+
smells[0].smell_class.should == IrresponsibleModule::SMELL_CLASS
|
|
29
|
+
smells[0].subclass.should == IrresponsibleModule::SMELL_SUBCLASS
|
|
30
|
+
smells[0].lines.should == [1]
|
|
31
|
+
smells[0].smell[IrresponsibleModule::MODULE_NAME_KEY].should == @bad_module_name
|
|
32
|
+
end
|
|
33
|
+
it "reports a class with an empty comment" do
|
|
34
|
+
src = <<EOS
|
|
35
|
+
#
|
|
36
|
+
#
|
|
37
|
+
#
|
|
38
|
+
class #{@bad_module_name}; end
|
|
39
|
+
EOS
|
|
40
|
+
ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
|
|
41
|
+
smells = @detector.examine_context(ctx)
|
|
42
|
+
smells.length.should == 1
|
|
43
|
+
smells[0].smell_class.should == IrresponsibleModule::SMELL_CLASS
|
|
44
|
+
smells[0].subclass.should == IrresponsibleModule::SMELL_SUBCLASS
|
|
45
|
+
smells[0].lines.should == [4]
|
|
46
|
+
smells[0].smell[IrresponsibleModule::MODULE_NAME_KEY].should == @bad_module_name
|
|
47
|
+
end
|
|
48
|
+
it 'reports a fq module name correctly' do
|
|
49
|
+
src = 'class Foo::Bar; end'
|
|
50
|
+
ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
|
|
51
|
+
smells = @detector.examine_context(ctx)
|
|
52
|
+
smells.length.should == 1
|
|
53
|
+
smells[0].smell_class.should == IrresponsibleModule::SMELL_CLASS
|
|
54
|
+
smells[0].subclass.should == IrresponsibleModule::SMELL_SUBCLASS
|
|
55
|
+
smells[0].smell[IrresponsibleModule::MODULE_NAME_KEY].should == 'Foo::Bar'
|
|
56
|
+
smells[0].context.should match(/#{smells[0].smell[IrresponsibleModule::MODULE_NAME_KEY]}/)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -1,78 +1,43 @@
|
|
|
1
|
-
require File.dirname(__FILE__)
|
|
2
|
-
|
|
3
|
-
require 'reek
|
|
4
|
-
require 'reek
|
|
5
|
-
require '
|
|
6
|
-
require 'reek/smells/large_class'
|
|
1
|
+
require File.join(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__)))), 'spec_helper')
|
|
2
|
+
require File.join(File.dirname(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__))))), 'lib', 'reek', 'smells', 'large_class')
|
|
3
|
+
require File.join(File.dirname(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__))))), 'lib', 'reek', 'examiner')
|
|
4
|
+
require File.join(File.dirname(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__))))), 'lib', 'reek', 'core', 'code_parser')
|
|
5
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'smell_detector_shared')
|
|
7
6
|
|
|
8
7
|
include Reek
|
|
9
8
|
include Reek::Smells
|
|
10
9
|
|
|
11
|
-
describe LargeClass
|
|
10
|
+
describe LargeClass do
|
|
12
11
|
before(:each) do
|
|
13
|
-
@
|
|
14
|
-
|
|
15
|
-
class #{@class_name}
|
|
16
|
-
def me01x()3 end;def me02x()3 end;def me03x()3 end;def me04x()3 end;def me05x()3 end
|
|
17
|
-
def me11x()3 end;def me12x()3 end;def me13x()3 end;def me14x()3 end;def me15x()3 end
|
|
18
|
-
def me21x()3 end;def me22x()3 end;def me23x()3 end;def me24x()3 end;def me25x()3 end
|
|
19
|
-
def me31x()3 end;def me32x()3 end;def me33x()3 end;def me34x()3 end;def me35x()3 end
|
|
20
|
-
def me41x()3 end;def me42x()3 end;def me43x()3 end;def me44x()3 end;def me45x()3 end
|
|
21
|
-
def me51x()3 end
|
|
22
|
-
end
|
|
23
|
-
EOS
|
|
24
|
-
@ctx = ClassContext.from_s(src)
|
|
25
|
-
@config = LargeClass.default_config
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
it 'should ignore first excepted name' do
|
|
29
|
-
@config[LargeClass::EXCLUDE_KEY] = [@class_name]
|
|
30
|
-
lc = LargeClass.new(@config)
|
|
31
|
-
lc.examine(@ctx).should == false
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
it 'should ignore second excepted name' do
|
|
35
|
-
@config[LargeClass::EXCLUDE_KEY] = ['Oversized', @class_name]
|
|
36
|
-
lc = LargeClass.new(@config)
|
|
37
|
-
lc.examine(@ctx).should == false
|
|
12
|
+
@source_name = 'elephant'
|
|
13
|
+
@detector = LargeClass.new(@source_name)
|
|
38
14
|
end
|
|
39
15
|
|
|
40
|
-
|
|
41
|
-
@config[LargeClass::EXCLUDE_KEY] = ['SmellMe']
|
|
42
|
-
lc = LargeClass.new(@config)
|
|
43
|
-
lc.examine(@ctx).should == true
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
describe LargeClass, 'checking source code' do
|
|
16
|
+
it_should_behave_like 'SmellDetector'
|
|
48
17
|
|
|
49
18
|
context 'counting instance variables' do
|
|
50
|
-
it 'should not report
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
it 'should count ivars in one method' do
|
|
55
|
-
ClassContext.from_s('class Empty;def ivars() @aa=@ab=@ac=@ad; end;end').should have(4).variable_names
|
|
19
|
+
it 'should not report 9 ivars' do
|
|
20
|
+
'# clean class for testing purposes
|
|
21
|
+
class Empty;def ivars() @aa=@ab=@ac=@ad=@ae=@af=@ag=@ah=@ai=4; end;end'.should_not reek
|
|
56
22
|
end
|
|
57
23
|
|
|
58
|
-
it '
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
it 'should not report 9 ivars' do
|
|
63
|
-
'class Empty;def ivars() @aa=@ab=@ac=@ad=@ae=@af=@ag=@ah=@ai; end;end'.should_not reek
|
|
24
|
+
it 'counts each ivar only once' do
|
|
25
|
+
'# clean class for testing purposes
|
|
26
|
+
class Empty;def ivars() @aa=@ab=@ac=@ad=@ae=@af=@ag=@ah=@ai=4;@aa=3; end;end'.should_not reek
|
|
64
27
|
end
|
|
65
28
|
|
|
66
29
|
it 'should report 10 ivars' do
|
|
67
|
-
'
|
|
30
|
+
'# smelly class for testing purposes
|
|
31
|
+
class Empty;def ivars() @aa=@ab=@ac=@ad=@ae=@af=@ag=@ah=@ai=@aj=4; end;end'.should reek_only_of(:LargeClass)
|
|
68
32
|
end
|
|
69
33
|
|
|
70
34
|
it 'should not report 10 ivars in 2 extensions' do
|
|
71
35
|
src = <<EOS
|
|
36
|
+
# clean class for testing purposes
|
|
72
37
|
class Full;def ivars_a() @aa=@ab=@ac=@ad=@ae; end;end
|
|
38
|
+
# clean class for testing purposes
|
|
73
39
|
class Full;def ivars_b() @af=@ag=@ah=@ai=@aj; end;end
|
|
74
40
|
EOS
|
|
75
|
-
|
|
76
41
|
src.should_not reek
|
|
77
42
|
end
|
|
78
43
|
end
|
|
@@ -81,6 +46,7 @@ EOS
|
|
|
81
46
|
|
|
82
47
|
it 'should not report 25 methods' do
|
|
83
48
|
src = <<EOS
|
|
49
|
+
# smelly class for testing purposes
|
|
84
50
|
class Full
|
|
85
51
|
def me01x()3 end;def me02x()3 end;def me03x()3 end;def me04x()3 end;def me05x()3 end
|
|
86
52
|
def me11x()3 end;def me12x()3 end;def me13x()3 end;def me14x()3 end;def me15x()3 end
|
|
@@ -89,7 +55,8 @@ class Full
|
|
|
89
55
|
def me41x()3 end;def me42x()3 end;def me43x()3 end;def me44x()3 end;def me45x()3 end
|
|
90
56
|
end
|
|
91
57
|
EOS
|
|
92
|
-
src.
|
|
58
|
+
ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
|
|
59
|
+
@detector.examine_context(ctx).should be_empty
|
|
93
60
|
end
|
|
94
61
|
|
|
95
62
|
it 'should report 26 methods' do
|
|
@@ -103,7 +70,11 @@ class Full
|
|
|
103
70
|
def me51x()3 end
|
|
104
71
|
end
|
|
105
72
|
EOS
|
|
106
|
-
src.
|
|
73
|
+
ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
|
|
74
|
+
smells = @detector.examine_context(ctx)
|
|
75
|
+
smells.length.should == 1
|
|
76
|
+
smells[0].subclass.should == LargeClass::SUBCLASS_TOO_MANY_METHODS
|
|
77
|
+
smells[0].smell[LargeClass::METHOD_COUNT_KEY].should == 26
|
|
107
78
|
end
|
|
108
79
|
end
|
|
109
80
|
|
|
@@ -119,7 +90,46 @@ class Full
|
|
|
119
90
|
def me51x()3 end
|
|
120
91
|
end
|
|
121
92
|
EOS
|
|
122
|
-
src.
|
|
93
|
+
ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
|
|
94
|
+
@detector.examine_context(ctx).should be_empty
|
|
123
95
|
end
|
|
124
96
|
end
|
|
97
|
+
|
|
98
|
+
it 'reports correctly when the class has many methods' do
|
|
99
|
+
src = <<EOS
|
|
100
|
+
class Full
|
|
101
|
+
def me01x()3 end;def me02x()3 end;def me03x()3 end;def me04x()3 end;def me05x()3 end
|
|
102
|
+
def me11x()3 end;def me12x()3 end;def me13x()3 end;def me14x()3 end;def me15x()3 end
|
|
103
|
+
def me21x()3 end;def me22x()3 end;def me23x()3 end;def me24x()3 end;def me25x()3 end
|
|
104
|
+
def me31x()3 end;def me32x()3 end;def me33x()3 end;def me34x()3 end;def me35x()3 end
|
|
105
|
+
def me41x()3 end;def me42x()3 end;def me43x()3 end;def me44x()3 end;def me45x()3 end
|
|
106
|
+
def me51x()3 end
|
|
107
|
+
end
|
|
108
|
+
EOS
|
|
109
|
+
ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
|
|
110
|
+
@warning = @detector.examine_context(ctx)[0]
|
|
111
|
+
@warning.source.should == @source_name
|
|
112
|
+
@warning.smell_class.should == 'LargeClass'
|
|
113
|
+
@warning.subclass.should == LargeClass::SUBCLASS_TOO_MANY_METHODS
|
|
114
|
+
@warning.smell[LargeClass::METHOD_COUNT_KEY].should == 26
|
|
115
|
+
@warning.lines.should == [1]
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it 'reports correctly when the class has 30 instance variables' do
|
|
119
|
+
src = <<EOS
|
|
120
|
+
# smelly class for testing purposes
|
|
121
|
+
class Empty
|
|
122
|
+
def ivars
|
|
123
|
+
@aa=@ab=@ac=@ad=@ae=@af=@ag=@ah=@ai=@aj=4
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
EOS
|
|
127
|
+
ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
|
|
128
|
+
@warning = @detector.examine_context(ctx)[0]
|
|
129
|
+
@warning.source.should == @source_name
|
|
130
|
+
@warning.smell_class.should == 'LargeClass'
|
|
131
|
+
@warning.subclass.should == LargeClass::SUBCLASS_TOO_MANY_IVARS
|
|
132
|
+
@warning.smell[LargeClass::IVAR_COUNT_KEY].should == 10
|
|
133
|
+
@warning.lines.should == [2]
|
|
134
|
+
end
|
|
125
135
|
end
|
|
@@ -1,29 +1,32 @@
|
|
|
1
|
-
require File.dirname(__FILE__)
|
|
2
|
-
|
|
3
|
-
require 'reek
|
|
4
|
-
require 'reek
|
|
5
|
-
require '
|
|
1
|
+
require File.join(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__)))), 'spec_helper')
|
|
2
|
+
require File.join(File.dirname(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__))))), 'lib', 'reek', 'smells', 'long_method')
|
|
3
|
+
require File.join(File.dirname(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__))))), 'lib', 'reek', 'core', 'code_parser')
|
|
4
|
+
require File.join(File.dirname(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__))))), 'lib', 'reek', 'core', 'sniffer')
|
|
5
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'smell_detector_shared')
|
|
6
6
|
|
|
7
7
|
include Reek
|
|
8
8
|
include Reek::Smells
|
|
9
9
|
|
|
10
10
|
def process_method(src)
|
|
11
11
|
source = src.to_reek_source
|
|
12
|
-
sniffer = Sniffer.new(source)
|
|
13
|
-
CodeParser.new(sniffer).process_defn(source.syntax_tree)
|
|
12
|
+
sniffer = Core::Sniffer.new(source)
|
|
13
|
+
Core::CodeParser.new(sniffer).process_defn(source.syntax_tree)
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
describe LongMethod do
|
|
17
17
|
it 'should not report short methods' do
|
|
18
|
-
'def short(arga) alf = f(1);@bet = 2;@cut = 3;@dit = 4; @emp = 5;end'
|
|
18
|
+
src = 'def short(arga) alf = f(1);@bet = 2;@cut = 3;@dit = 4; @emp = 5;end'
|
|
19
|
+
src.should_not smell_of(LongMethod)
|
|
19
20
|
end
|
|
20
21
|
|
|
21
22
|
it 'should report long methods' do
|
|
22
|
-
'def long(arga) alf = f(1);@bet = 2;@cut = 3;@dit = 4; @emp = 5;@fry = 6;end'
|
|
23
|
+
src = 'def long(arga) alf = f(1);@bet = 2;@cut = 3;@dit = 4; @emp = 5;@fry = 6;end'
|
|
24
|
+
src.should reek_only_of(:LongMethod, /6 statements/)
|
|
23
25
|
end
|
|
24
26
|
|
|
25
27
|
it 'should not report initialize' do
|
|
26
|
-
'def initialize(arga) alf = f(1);@bet = 2;@cut = 3;@dit = 4; @emp = 5;@fry = 6;end'
|
|
28
|
+
src = 'def initialize(arga) alf = f(1);@bet = 2;@cut = 3;@dit = 4; @emp = 5;@fry = 6;end'
|
|
29
|
+
src.should_not smell_of(LongMethod)
|
|
27
30
|
end
|
|
28
31
|
|
|
29
32
|
it 'should only report a long method once' do
|
|
@@ -194,3 +197,30 @@ EOS
|
|
|
194
197
|
method.num_statements.should == 6
|
|
195
198
|
end
|
|
196
199
|
end
|
|
200
|
+
|
|
201
|
+
describe LongMethod do
|
|
202
|
+
before(:each) do
|
|
203
|
+
@detector = LongMethod.new('silver')
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
it_should_behave_like 'SmellDetector'
|
|
207
|
+
|
|
208
|
+
context 'when the method has 30 statements' do
|
|
209
|
+
before :each do
|
|
210
|
+
@num_statements = 30
|
|
211
|
+
ctx = mock('method_context', :null_object => true)
|
|
212
|
+
ctx.should_receive(:num_statements).and_return(@num_statements)
|
|
213
|
+
ctx.should_receive(:config).and_return({})
|
|
214
|
+
@smells = @detector.examine_context(ctx)
|
|
215
|
+
end
|
|
216
|
+
it 'reports only 1 smell' do
|
|
217
|
+
@smells.length.should == 1
|
|
218
|
+
end
|
|
219
|
+
it 'reports the number of statements' do
|
|
220
|
+
@smells[0].smell[LongMethod::STATEMENT_COUNT_KEY].should == @num_statements
|
|
221
|
+
end
|
|
222
|
+
it 'reports the correct subclass' do
|
|
223
|
+
@smells[0].subclass.should == LongMethod::SUBCLASS_TOO_MANY_STATEMENTS
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
end
|
|
@@ -1,72 +1,94 @@
|
|
|
1
|
-
require File.dirname(__FILE__)
|
|
2
|
-
|
|
3
|
-
require '
|
|
1
|
+
require File.join(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__)))), 'spec_helper')
|
|
2
|
+
require File.join(File.dirname(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__))))), 'lib', 'reek', 'smells', 'long_parameter_list')
|
|
3
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'smell_detector_shared')
|
|
4
4
|
|
|
5
5
|
include Reek
|
|
6
6
|
include Reek::Smells
|
|
7
7
|
|
|
8
8
|
describe LongParameterList do
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
|
|
10
|
+
context 'for methods with few parameters' do
|
|
11
11
|
it 'should report nothing for no parameters' do
|
|
12
|
-
'def simple; f(3);true; end'.should_not
|
|
12
|
+
'def simple; f(3);true; end'.should_not smell_of(LongParameterList)
|
|
13
13
|
end
|
|
14
14
|
it 'should report nothing for 1 parameter' do
|
|
15
|
-
'def simple(yep) f(3);true end'.should_not
|
|
15
|
+
'def simple(yep) f(3);true end'.should_not smell_of(LongParameterList)
|
|
16
16
|
end
|
|
17
17
|
it 'should report nothing for 2 parameters' do
|
|
18
|
-
'def simple(yep,zero) f(3);true end'.should_not
|
|
18
|
+
'def simple(yep,zero) f(3);true end'.should_not smell_of(LongParameterList)
|
|
19
19
|
end
|
|
20
20
|
it 'should not count an optional block' do
|
|
21
|
-
'def simple(alpha, yep, zero, &opt) f(3);true end'.should_not
|
|
21
|
+
'def simple(alpha, yep, zero, &opt) f(3);true end'.should_not smell_of(LongParameterList)
|
|
22
22
|
end
|
|
23
23
|
it 'should not report inner block with too many parameters' do
|
|
24
|
-
'def simple(yep,zero); m[3]; rand(34); f.each { |arga, argb, argc, argd| true}; end'
|
|
24
|
+
src = 'def simple(yep,zero); m[3]; rand(34); f.each { |arga, argb, argc, argd| true}; end'
|
|
25
|
+
src.should_not smell_of(LongParameterList)
|
|
25
26
|
end
|
|
26
27
|
|
|
27
28
|
describe 'and default values' do
|
|
28
29
|
it 'should report nothing for 1 parameter' do
|
|
29
|
-
'def simple(zero=nil) f(3);false end'.should_not
|
|
30
|
+
'def simple(zero=nil) f(3);false end'.should_not smell_of(LongParameterList)
|
|
30
31
|
end
|
|
31
32
|
it 'should report nothing for 2 parameters with 1 default' do
|
|
32
|
-
'def simple(yep, zero=nil) f(3);false end'.should_not
|
|
33
|
+
'def simple(yep, zero=nil) f(3);false end'.should_not smell_of(LongParameterList)
|
|
33
34
|
end
|
|
34
35
|
it 'should report nothing for 2 defaulted parameters' do
|
|
35
|
-
'def simple(yep=4, zero=nil) f(3);false end'.should_not
|
|
36
|
+
'def simple(yep=4, zero=nil) f(3);false end'.should_not smell_of(LongParameterList)
|
|
36
37
|
end
|
|
37
38
|
end
|
|
38
39
|
end
|
|
39
40
|
|
|
40
41
|
describe 'for methods with too many parameters' do
|
|
41
42
|
it 'should report 4 parameters' do
|
|
42
|
-
'def simple(arga, argb, argc, argd) f(3);true end'
|
|
43
|
+
src = 'def simple(arga, argb, argc, argd) f(3);true end'
|
|
44
|
+
src.should smell_of(LongParameterList, LongParameterList::PARAMETER_COUNT_KEY => 4)
|
|
43
45
|
end
|
|
44
46
|
it 'should report 8 parameters' do
|
|
45
|
-
'def simple(arga, argb, argc, argd,arge, argf, argg, argh) f(3);true end'
|
|
47
|
+
src = 'def simple(arga, argb, argc, argd,arge, argf, argg, argh) f(3);true end'
|
|
48
|
+
src.should smell_of(LongParameterList, LongParameterList::PARAMETER_COUNT_KEY => 8)
|
|
46
49
|
end
|
|
47
50
|
|
|
48
51
|
describe 'and default values' do
|
|
49
52
|
it 'should report 3 with 1 defaulted' do
|
|
50
|
-
'def simple(polly, queue, yep, zero=nil) f(3);false end'
|
|
53
|
+
src = 'def simple(polly, queue, yep, zero=nil) f(3);false end'
|
|
54
|
+
src.should smell_of(LongParameterList, LongParameterList::PARAMETER_COUNT_KEY => 4)
|
|
51
55
|
end
|
|
52
56
|
it 'should report with 3 defaulted' do
|
|
53
|
-
'def simple(aarg, polly=2, yep=:truth, zero=nil) f(3);false end'
|
|
57
|
+
src = 'def simple(aarg, polly=2, yep=:truth, zero=nil) f(3);false end'
|
|
58
|
+
src.should smell_of(LongParameterList, LongParameterList::PARAMETER_COUNT_KEY => 4)
|
|
54
59
|
end
|
|
55
60
|
end
|
|
56
61
|
end
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
describe LongParameterList do
|
|
65
|
+
before(:each) do
|
|
66
|
+
@source_name = 'smokin'
|
|
67
|
+
@detector = LongParameterList.new(@source_name)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it_should_behave_like 'SmellDetector'
|
|
71
|
+
|
|
72
|
+
context 'when a smell is reported' do
|
|
73
|
+
before :each do
|
|
74
|
+
src = <<EOS
|
|
75
|
+
def badguy(arga, argb, argc, argd)
|
|
76
|
+
f(3)
|
|
77
|
+
true
|
|
78
|
+
end
|
|
79
|
+
EOS
|
|
80
|
+
ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
|
|
81
|
+
@smells = @detector.examine_context(ctx)
|
|
82
|
+
@warning = @smells[0]
|
|
64
83
|
end
|
|
65
|
-
|
|
66
|
-
|
|
84
|
+
|
|
85
|
+
it_should_behave_like 'common fields set correctly'
|
|
86
|
+
|
|
87
|
+
it 'reports the number of parameters' do
|
|
88
|
+
@warning.smell[LongParameterList::PARAMETER_COUNT_KEY].should == 4
|
|
67
89
|
end
|
|
68
|
-
it '
|
|
69
|
-
|
|
90
|
+
it 'reports the line number of the method' do
|
|
91
|
+
@warning.lines.should == [1]
|
|
70
92
|
end
|
|
71
93
|
end
|
|
72
94
|
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
require File.join(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__)))), 'spec_helper')
|
|
2
|
+
require File.join(File.dirname(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__))))), 'lib', 'reek', 'smells', 'long_yield_list')
|
|
3
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'smell_detector_shared')
|
|
4
|
+
|
|
5
|
+
include Reek
|
|
6
|
+
include Reek::Smells
|
|
7
|
+
|
|
8
|
+
describe LongYieldList do
|
|
9
|
+
before(:each) do
|
|
10
|
+
@source_name = 'oo la la'
|
|
11
|
+
@detector = LongYieldList.new(@source_name)
|
|
12
|
+
# SMELL: can't use the default config, because that contains an override,
|
|
13
|
+
# which causes the mocked matches?() method to be called twice!!
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it_should_behave_like 'SmellDetector'
|
|
17
|
+
|
|
18
|
+
context 'yield' do
|
|
19
|
+
it 'should not report yield with no parameters' do
|
|
20
|
+
src = 'def simple(arga, argb, &blk) f(3);yield; end'
|
|
21
|
+
src.should_not smell_of(LongYieldList)
|
|
22
|
+
end
|
|
23
|
+
it 'should not report yield with few parameters' do
|
|
24
|
+
src = 'def simple(arga, argb, &blk) f(3);yield a,b; end'
|
|
25
|
+
src.should_not smell_of(LongYieldList)
|
|
26
|
+
end
|
|
27
|
+
it 'should report yield with many parameters' do
|
|
28
|
+
src = 'def simple(arga, argb, &blk) f(3);yield arga,argb,arga,argb; end'
|
|
29
|
+
src.should smell_of(LongYieldList, LongYieldList::PARAMETER_COUNT_KEY => 4)
|
|
30
|
+
end
|
|
31
|
+
it 'should not report yield of a long expression' do
|
|
32
|
+
src = 'def simple(arga, argb, &blk) f(3);yield(if @dec then argb else 5+3 end); end'
|
|
33
|
+
src.should_not smell_of(LongYieldList)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
context 'when a smells is reported' do
|
|
38
|
+
before :each do
|
|
39
|
+
src = <<EOS
|
|
40
|
+
def simple(arga, argb, &blk)
|
|
41
|
+
f(3)
|
|
42
|
+
yield(arga,argb,arga,argb)
|
|
43
|
+
end
|
|
44
|
+
EOS
|
|
45
|
+
ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
|
|
46
|
+
@smells = @detector.examine_context(ctx)
|
|
47
|
+
@warning = @smells[0]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it_should_behave_like 'common fields set correctly'
|
|
51
|
+
|
|
52
|
+
it 'reports the correct values' do
|
|
53
|
+
@warning.smell['parameter_count'].should == 4
|
|
54
|
+
@warning.lines.should == [3]
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -1,13 +1,28 @@
|
|
|
1
|
-
require File.dirname(__FILE__)
|
|
2
|
-
|
|
3
|
-
require '
|
|
1
|
+
require File.join(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__)))), 'spec_helper')
|
|
2
|
+
require File.join(File.dirname(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__))))), 'lib', 'reek', 'smells', 'nested_iterators')
|
|
3
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'smell_detector_shared')
|
|
4
4
|
|
|
5
5
|
include Reek::Smells
|
|
6
6
|
|
|
7
7
|
describe NestedIterators do
|
|
8
8
|
|
|
9
|
+
context 'with no iterators' do
|
|
10
|
+
it 'reports no smells' do
|
|
11
|
+
src = 'def fred() nothing = true; end'
|
|
12
|
+
src.should_not smell_of(NestedIterators)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
context 'with one iterator' do
|
|
17
|
+
it 'reports no smells' do
|
|
18
|
+
src = 'def fred() nothing.each {|item| item}; end'
|
|
19
|
+
src.should_not smell_of(NestedIterators)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
9
23
|
it 'should report nested iterators in a method' do
|
|
10
|
-
'def bad(fred) @fred.each {|item| item.each {|ting| ting.ting} } end'
|
|
24
|
+
src = 'def bad(fred) @fred.each {|item| item.each {|ting| ting.ting} } end'
|
|
25
|
+
src.should smell_of(NestedIterators)
|
|
11
26
|
end
|
|
12
27
|
|
|
13
28
|
it 'should not report method with successive iterators' do
|
|
@@ -17,7 +32,7 @@ def bad(fred)
|
|
|
17
32
|
@jim.each {|ting| ting.each }
|
|
18
33
|
end
|
|
19
34
|
EOS
|
|
20
|
-
src.should_not
|
|
35
|
+
src.should_not smell_of(NestedIterators)
|
|
21
36
|
end
|
|
22
37
|
|
|
23
38
|
it 'should not report method with chained iterators' do
|
|
@@ -26,7 +41,7 @@ def chained
|
|
|
26
41
|
@sig.keys.sort_by { |xray| xray.to_s }.each { |min| md5 << min.to_s }
|
|
27
42
|
end
|
|
28
43
|
EOS
|
|
29
|
-
src.should_not
|
|
44
|
+
src.should_not smell_of(NestedIterators)
|
|
30
45
|
end
|
|
31
46
|
|
|
32
47
|
it 'should report nested iterators only once per method' do
|
|
@@ -36,7 +51,100 @@ def bad(fred)
|
|
|
36
51
|
@jim.each {|ting| ting.each {|piece| @hal.send} }
|
|
37
52
|
end
|
|
38
53
|
EOS
|
|
39
|
-
src.should
|
|
54
|
+
src.should smell_of(NestedIterators, {}, {})
|
|
40
55
|
end
|
|
56
|
+
|
|
57
|
+
context 'when the allowed nesting depth is 3' do
|
|
58
|
+
before :each do
|
|
59
|
+
@config = {NestedIterators::MAX_ALLOWED_NESTING_KEY => 3}
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it 'should not report nested iterators 2 levels deep' do
|
|
63
|
+
src = <<EOS
|
|
64
|
+
def bad(fred)
|
|
65
|
+
@fred.each {|one| one.each {|two| two.two} }
|
|
41
66
|
end
|
|
67
|
+
EOS
|
|
68
|
+
src.should_not smell_of(NestedIterators).with_config(@config)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it 'should not report nested iterators 3 levels deep' do
|
|
72
|
+
src = <<EOS
|
|
73
|
+
def bad(fred)
|
|
74
|
+
@fred.each {|one| one.each {|two| two.each {|three| three.three} } }
|
|
75
|
+
end
|
|
76
|
+
EOS
|
|
77
|
+
src.should_not smell_of(NestedIterators).with_config(@config)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it 'should report nested iterators 4 levels deep' do
|
|
81
|
+
src = <<EOS
|
|
82
|
+
def bad(fred)
|
|
83
|
+
@fred.each {|one| one.each {|two| two.each {|three| three.each {|four| four.four} } } }
|
|
84
|
+
end
|
|
85
|
+
EOS
|
|
86
|
+
src.should smell_of(NestedIterators).with_config(@config)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
context 'when ignoring iterators' do
|
|
91
|
+
before :each do
|
|
92
|
+
@config = {NestedIterators::IGNORE_ITERATORS_KEY => ['ignore_me']}
|
|
93
|
+
end
|
|
42
94
|
|
|
95
|
+
it 'should not report nesting the ignored iterator inside another' do
|
|
96
|
+
src = 'def bad(fred) @fred.each {|item| item.ignore_me {|ting| ting.ting} } end'
|
|
97
|
+
src.should_not smell_of(NestedIterators).with_config(@config)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it 'should not report nesting inside the ignored iterator' do
|
|
101
|
+
src = 'def bad(fred) @fred.ignore_me {|item| item.each {|ting| ting.ting} } end'
|
|
102
|
+
src.should_not smell_of(NestedIterators).with_config(@config)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
it 'should report nested iterators inside the ignored iterator' do
|
|
106
|
+
src = 'def bad(fred) @fred.ignore_me {|item| item.each {|ting| ting.each {|other| other.other} } } end'
|
|
107
|
+
src.should smell_of(NestedIterators, NestedIterators::NESTING_DEPTH_KEY => 2).with_config(@config)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it 'should report nested iterators outside the ignored iterator' do
|
|
111
|
+
src = 'def bad(fred) @fred.each {|item| item.each {|ting| ting.ignore_me {|other| other.other} } } end'
|
|
112
|
+
src.should smell_of(NestedIterators, NestedIterators::NESTING_DEPTH_KEY => 2).with_config(@config)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it 'should report nested iterators with the ignored iterator between them' do
|
|
116
|
+
src = 'def bad(fred) @fred.each {|item| item.ignore_me {|ting| ting.ting {|other| other.other} } } end'
|
|
117
|
+
src.should smell_of(NestedIterators, NestedIterators::NESTING_DEPTH_KEY => 2).with_config(@config)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
describe NestedIterators do
|
|
123
|
+
before(:each) do
|
|
124
|
+
@source_name = 'cuckoo'
|
|
125
|
+
@detector = NestedIterators.new(@source_name)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it_should_behave_like 'SmellDetector'
|
|
129
|
+
|
|
130
|
+
context 'when a smell is reported' do
|
|
131
|
+
before :each do
|
|
132
|
+
src = <<EOS
|
|
133
|
+
def fred()
|
|
134
|
+
nothing.each do |item|
|
|
135
|
+
again.each {|thing| item }
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
EOS
|
|
139
|
+
ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
|
|
140
|
+
@warning = @detector.examine_context(ctx)[0]
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
it_should_behave_like 'common fields set correctly'
|
|
144
|
+
|
|
145
|
+
it 'reports correct values' do
|
|
146
|
+
@warning.smell[NestedIterators::NESTING_DEPTH_KEY].should == 2
|
|
147
|
+
@warning.lines.should == [3]
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|