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
|
@@ -1,33 +1,10 @@
|
|
|
1
|
-
require File.dirname(__FILE__)
|
|
2
|
-
|
|
3
|
-
require 'reek/smell_warning'
|
|
4
|
-
require 'reek/smells/feature_envy'
|
|
1
|
+
require File.join(File.dirname(File.dirname(File.expand_path(__FILE__))), 'spec_helper')
|
|
2
|
+
require File.join(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__)))), 'lib', 'reek', 'smell_warning')
|
|
5
3
|
|
|
6
4
|
include Reek
|
|
7
5
|
|
|
8
6
|
describe SmellWarning do
|
|
9
7
|
context 'sort order' do
|
|
10
|
-
context 'smells differing only by masking' do
|
|
11
|
-
before :each do
|
|
12
|
-
@first = SmellWarning.new(Smells::FeatureEnvy.new, "self", 27, "self", true)
|
|
13
|
-
@second = SmellWarning.new(Smells::FeatureEnvy.new, "self", 27, "self", false)
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
it 'should hash equal when the smell is the same' do
|
|
17
|
-
@first.hash.should == @second.hash
|
|
18
|
-
end
|
|
19
|
-
it 'should compare equal when the smell is the same' do
|
|
20
|
-
@first.should == @second
|
|
21
|
-
end
|
|
22
|
-
it 'should compare equal when using <=>' do
|
|
23
|
-
(@first <=> @second).should == 0
|
|
24
|
-
end
|
|
25
|
-
it 'matches using eql?' do
|
|
26
|
-
@first.should eql(@second)
|
|
27
|
-
@second.should eql(@first)
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
|
|
31
8
|
shared_examples_for 'first sorts ahead of second' do
|
|
32
9
|
it 'hash differently' do
|
|
33
10
|
@first.hash.should_not == @second.hash
|
|
@@ -46,8 +23,8 @@ describe SmellWarning do
|
|
|
46
23
|
|
|
47
24
|
context 'smells differing only by detector' do
|
|
48
25
|
before :each do
|
|
49
|
-
@first = SmellWarning.new(
|
|
50
|
-
@second = SmellWarning.new(
|
|
26
|
+
@first = SmellWarning.new('Duplication', "self", 27, "self", false)
|
|
27
|
+
@second = SmellWarning.new('FeatureEnvy', "self", 27, "self", true)
|
|
51
28
|
end
|
|
52
29
|
|
|
53
30
|
it_should_behave_like 'first sorts ahead of second'
|
|
@@ -55,8 +32,8 @@ describe SmellWarning do
|
|
|
55
32
|
|
|
56
33
|
context 'smells differing only by context' do
|
|
57
34
|
before :each do
|
|
58
|
-
@first = SmellWarning.new(
|
|
59
|
-
@second = SmellWarning.new(
|
|
35
|
+
@first = SmellWarning.new('FeatureEnvy', "first", 27, "self", true)
|
|
36
|
+
@second = SmellWarning.new('FeatureEnvy', "second", 27, "self", false)
|
|
60
37
|
end
|
|
61
38
|
|
|
62
39
|
it_should_behave_like 'first sorts ahead of second'
|
|
@@ -64,8 +41,8 @@ describe SmellWarning do
|
|
|
64
41
|
|
|
65
42
|
context 'smells differing only by message' do
|
|
66
43
|
before :each do
|
|
67
|
-
@first = SmellWarning.new(
|
|
68
|
-
@second = SmellWarning.new(
|
|
44
|
+
@first = SmellWarning.new('FeatureEnvy', "context", 27, "first", true)
|
|
45
|
+
@second = SmellWarning.new('FeatureEnvy', "context", 27, "second", false)
|
|
69
46
|
end
|
|
70
47
|
|
|
71
48
|
it_should_behave_like 'first sorts ahead of second'
|
|
@@ -73,8 +50,8 @@ describe SmellWarning do
|
|
|
73
50
|
|
|
74
51
|
context 'message takes precedence over smell name' do
|
|
75
52
|
before :each do
|
|
76
|
-
@first = SmellWarning.new(
|
|
77
|
-
@second = SmellWarning.new(
|
|
53
|
+
@first = SmellWarning.new('UtilityFunction', "context", 27, "first", true)
|
|
54
|
+
@second = SmellWarning.new('FeatureEnvy', "context", 27, "second", false)
|
|
78
55
|
end
|
|
79
56
|
|
|
80
57
|
it_should_behave_like 'first sorts ahead of second'
|
|
@@ -82,70 +59,85 @@ describe SmellWarning do
|
|
|
82
59
|
|
|
83
60
|
context 'smells differing everywhere' do
|
|
84
61
|
before :each do
|
|
85
|
-
@first = SmellWarning.new(
|
|
86
|
-
@second = SmellWarning.new(
|
|
62
|
+
@first = SmellWarning.new('UncommunicativeName', "Dirty", 27, "has the variable name '@s'", true)
|
|
63
|
+
@second = SmellWarning.new('Duplication', 'Dirty#a', 27, "calls @s.title twice", false)
|
|
87
64
|
end
|
|
88
65
|
|
|
89
66
|
it_should_behave_like 'first sorts ahead of second'
|
|
90
67
|
end
|
|
91
68
|
end
|
|
92
69
|
|
|
93
|
-
context '
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
70
|
+
context 'YAML representation' do
|
|
71
|
+
before :each do
|
|
72
|
+
@message = 'test message'
|
|
73
|
+
@lines = [24, 513]
|
|
74
|
+
@class = 'FeatureEnvy'
|
|
75
|
+
@context_name = 'Module::Class#method/block'
|
|
76
|
+
# Use a random string and a random bool
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
shared_examples_for 'common fields' do
|
|
80
|
+
it 'includes the smell class' do
|
|
81
|
+
@yaml.should match(/class:\s*FeatureEnvy/)
|
|
98
82
|
end
|
|
99
|
-
|
|
100
|
-
@
|
|
83
|
+
it 'includes the context' do
|
|
84
|
+
@yaml.should match(/context:\s*#{@context_name}/)
|
|
101
85
|
end
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
86
|
+
it 'includes the message' do
|
|
87
|
+
@yaml.should match(/message:\s*#{@message}/)
|
|
88
|
+
end
|
|
89
|
+
it 'indicates the masking' do
|
|
90
|
+
@yaml.should match(/is_active:\s*true/)
|
|
91
|
+
end
|
|
92
|
+
it 'includes the line numbers' do
|
|
93
|
+
@lines.each do |line|
|
|
94
|
+
@yaml.should match(/lines:[\s\d-]*- #{line}/)
|
|
95
|
+
end
|
|
105
96
|
end
|
|
106
97
|
end
|
|
107
98
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
99
|
+
context 'with all details specified' do
|
|
100
|
+
before :each do
|
|
101
|
+
@source = 'a/ruby/source/file.rb'
|
|
102
|
+
@subclass = 'TooManyParties'
|
|
103
|
+
@parameters = {'one' => 34, 'two' => 'second'}
|
|
104
|
+
@warning = SmellWarning.new(@class, @context_name, @lines, @message,
|
|
105
|
+
@source, @subclass, @parameters)
|
|
106
|
+
@yaml = @warning.to_yaml
|
|
107
|
+
end
|
|
112
108
|
|
|
113
|
-
|
|
114
|
-
rpt = CountingReport.new
|
|
115
|
-
@masked.report_on(rpt)
|
|
116
|
-
rpt.masked.should == 1
|
|
117
|
-
rpt.non_masked.should == 0
|
|
118
|
-
end
|
|
109
|
+
it_should_behave_like 'common fields'
|
|
119
110
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
111
|
+
it 'includes the subclass' do
|
|
112
|
+
@yaml.should match(/subclass:\s*#{@subclass}/)
|
|
113
|
+
end
|
|
114
|
+
it 'includes the source' do
|
|
115
|
+
@yaml.should match(/source:\s*#{@source}/)
|
|
116
|
+
end
|
|
117
|
+
it 'includes the parameters' do
|
|
118
|
+
@parameters.each do |key,value|
|
|
119
|
+
@yaml.should match(/#{key}:\s*#{value}/)
|
|
120
|
+
end
|
|
121
|
+
end
|
|
125
122
|
end
|
|
126
|
-
end
|
|
127
123
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
@yaml.should match(/is_masked:\s*true/)
|
|
146
|
-
end
|
|
147
|
-
it 'includes the line number' do
|
|
148
|
-
@yaml.should match(/line:\s*27/)
|
|
124
|
+
context 'with all defaults used' do
|
|
125
|
+
before :each do
|
|
126
|
+
warning = SmellWarning.new(@class, @context_name, @lines, @message)
|
|
127
|
+
@yaml = warning.to_yaml
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
it_should_behave_like 'common fields'
|
|
131
|
+
|
|
132
|
+
it 'includes no subclass' do
|
|
133
|
+
@yaml.should match(/subclass:\s*""/)
|
|
134
|
+
end
|
|
135
|
+
it 'includes no source' do
|
|
136
|
+
@yaml.should match(/source:\s*""/)
|
|
137
|
+
end
|
|
138
|
+
it 'includes empty parameters' do
|
|
139
|
+
@yaml.should_not match(/parameter/)
|
|
140
|
+
end
|
|
149
141
|
end
|
|
150
142
|
end
|
|
151
143
|
end
|
|
@@ -1,39 +1,58 @@
|
|
|
1
|
-
require File.dirname(__FILE__)
|
|
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', 'attribute')
|
|
3
|
+
require File.join(File.dirname(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__))))), 'lib', 'reek', 'core', 'module_context')
|
|
4
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'smell_detector_shared')
|
|
2
5
|
|
|
3
|
-
|
|
4
|
-
require 'reek/class_context'
|
|
5
|
-
|
|
6
|
-
include Reek
|
|
6
|
+
include Reek::Core
|
|
7
7
|
include Reek::Smells
|
|
8
8
|
|
|
9
9
|
describe Attribute do
|
|
10
10
|
before :each do
|
|
11
|
-
@
|
|
11
|
+
@source_name = 'ticker'
|
|
12
|
+
@detector = Attribute.new(@source_name)
|
|
12
13
|
end
|
|
14
|
+
|
|
15
|
+
it_should_behave_like 'SmellDetector'
|
|
16
|
+
|
|
13
17
|
context 'with no attributes' do
|
|
14
|
-
it 'records nothing in the class' do
|
|
15
|
-
ctx = ClassContext.from_s('class Fred; end')
|
|
16
|
-
@detector.attributes_in(ctx).should be_empty
|
|
17
|
-
end
|
|
18
18
|
it 'records nothing in the module' do
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
src = 'module Fred; end'
|
|
20
|
+
ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
|
|
21
|
+
@detector.examine_context(ctx).should be_empty
|
|
21
22
|
end
|
|
22
23
|
end
|
|
23
24
|
|
|
24
25
|
context 'with one attribute' do
|
|
26
|
+
before :each do
|
|
27
|
+
@attr_name = 'super_thing'
|
|
28
|
+
end
|
|
29
|
+
|
|
25
30
|
shared_examples_for 'one attribute found' do
|
|
26
|
-
|
|
27
|
-
|
|
31
|
+
before :each do
|
|
32
|
+
ctx = CodeContext.new(nil, @src.to_reek_source.syntax_tree)
|
|
33
|
+
@smells = @detector.examine_context(ctx)
|
|
28
34
|
end
|
|
35
|
+
|
|
29
36
|
it 'records only that attribute' do
|
|
30
|
-
@
|
|
37
|
+
@smells.length.should == 1
|
|
38
|
+
end
|
|
39
|
+
it 'reports the attribute name' do
|
|
40
|
+
@smells[0].smell[Attribute::ATTRIBUTE_KEY].should == @attr_name
|
|
41
|
+
end
|
|
42
|
+
it 'reports the declaration line number' do
|
|
43
|
+
@smells[0].lines.should == [1]
|
|
44
|
+
end
|
|
45
|
+
it 'reports the correct smell class' do
|
|
46
|
+
@smells[0].smell_class.should == Attribute::SMELL_CLASS
|
|
47
|
+
end
|
|
48
|
+
it 'reports the context fq name' do
|
|
49
|
+
@smells[0].context.should == 'Fred'
|
|
31
50
|
end
|
|
32
51
|
end
|
|
33
52
|
|
|
34
53
|
context 'declared in a class' do
|
|
35
54
|
before :each do
|
|
36
|
-
@
|
|
55
|
+
@src = "class Fred; attr :#{@attr_name}; end"
|
|
37
56
|
end
|
|
38
57
|
|
|
39
58
|
it_should_behave_like 'one attribute found'
|
|
@@ -41,7 +60,7 @@ describe Attribute do
|
|
|
41
60
|
|
|
42
61
|
context 'reader in a class' do
|
|
43
62
|
before :each do
|
|
44
|
-
@
|
|
63
|
+
@src = "class Fred; attr_reader :#{@attr_name}; end"
|
|
45
64
|
end
|
|
46
65
|
|
|
47
66
|
it_should_behave_like 'one attribute found'
|
|
@@ -49,7 +68,7 @@ describe Attribute do
|
|
|
49
68
|
|
|
50
69
|
context 'writer in a class' do
|
|
51
70
|
before :each do
|
|
52
|
-
@
|
|
71
|
+
@src = "class Fred; attr_writer :#{@attr_name}; end"
|
|
53
72
|
end
|
|
54
73
|
|
|
55
74
|
it_should_behave_like 'one attribute found'
|
|
@@ -57,7 +76,7 @@ describe Attribute do
|
|
|
57
76
|
|
|
58
77
|
context 'accessor in a class' do
|
|
59
78
|
before :each do
|
|
60
|
-
@
|
|
79
|
+
@src = "class Fred; attr_accessor :#{@attr_name}; end"
|
|
61
80
|
end
|
|
62
81
|
|
|
63
82
|
it_should_behave_like 'one attribute found'
|
|
@@ -65,7 +84,7 @@ describe Attribute do
|
|
|
65
84
|
|
|
66
85
|
context 'declared in a module' do
|
|
67
86
|
before :each do
|
|
68
|
-
@
|
|
87
|
+
@src = "module Fred; attr :#{@attr_name}; end"
|
|
69
88
|
end
|
|
70
89
|
|
|
71
90
|
it_should_behave_like 'one attribute found'
|
|
@@ -73,7 +92,7 @@ describe Attribute do
|
|
|
73
92
|
|
|
74
93
|
context 'reader in a module' do
|
|
75
94
|
before :each do
|
|
76
|
-
@
|
|
95
|
+
@src = "module Fred; attr_reader :#{@attr_name}; end"
|
|
77
96
|
end
|
|
78
97
|
|
|
79
98
|
it_should_behave_like 'one attribute found'
|
|
@@ -81,7 +100,7 @@ describe Attribute do
|
|
|
81
100
|
|
|
82
101
|
context 'writer in a module' do
|
|
83
102
|
before :each do
|
|
84
|
-
@
|
|
103
|
+
@src = "module Fred; attr_writer :#{@attr_name}; end"
|
|
85
104
|
end
|
|
86
105
|
|
|
87
106
|
it_should_behave_like 'one attribute found'
|
|
@@ -89,7 +108,7 @@ describe Attribute do
|
|
|
89
108
|
|
|
90
109
|
context 'accessor in a module' do
|
|
91
110
|
before :each do
|
|
92
|
-
@
|
|
111
|
+
@src = "module Fred; attr_accessor :#{@attr_name}; end"
|
|
93
112
|
end
|
|
94
113
|
|
|
95
114
|
it_should_behave_like 'one attribute found'
|
|
@@ -2,7 +2,7 @@ shared_examples_for 'a variable detector' do
|
|
|
2
2
|
context 'with no variables' do
|
|
3
3
|
it "doesn't record a smell" do
|
|
4
4
|
@detector.examine_context(@ctx)
|
|
5
|
-
@detector.
|
|
5
|
+
@detector.smells_found.length.should == 0
|
|
6
6
|
end
|
|
7
7
|
end
|
|
8
8
|
|
|
@@ -14,7 +14,7 @@ shared_examples_for 'a variable detector' do
|
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
it 'records only one smell' do
|
|
17
|
-
@detector.
|
|
17
|
+
@detector.smells_found.length.should == 1
|
|
18
18
|
end
|
|
19
19
|
it 'mentions the variable name in the report' do
|
|
20
20
|
@detector.should have_smell([/something/])
|
|
@@ -0,0 +1,66 @@
|
|
|
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', 'boolean_parameter')
|
|
3
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'smell_detector_shared')
|
|
4
|
+
|
|
5
|
+
include Reek::Smells
|
|
6
|
+
|
|
7
|
+
describe BooleanParameter do
|
|
8
|
+
context 'parameter defaulted with boolean' do
|
|
9
|
+
context 'in a method' do
|
|
10
|
+
it 'reports a parameter defaulted to true' do
|
|
11
|
+
src = 'def cc(arga = true) end'
|
|
12
|
+
src.should smell_of(BooleanParameter, BooleanParameter::PARAMETER_KEY => 'arga')
|
|
13
|
+
end
|
|
14
|
+
it 'reports a parameter defaulted to false' do
|
|
15
|
+
src = 'def cc(arga = false) end'
|
|
16
|
+
src.should smell_of(BooleanParameter, BooleanParameter::PARAMETER_KEY => 'arga')
|
|
17
|
+
end
|
|
18
|
+
it 'reports two parameters defaulted to booleans' do
|
|
19
|
+
src = 'def cc(nowt, arga = true, argb = false, &blk) end'
|
|
20
|
+
src.should smell_of(BooleanParameter,
|
|
21
|
+
{BooleanParameter::PARAMETER_KEY => 'arga'},
|
|
22
|
+
{BooleanParameter::PARAMETER_KEY => 'argb'})
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
context 'in a singleton method' do
|
|
27
|
+
it 'reports a parameter defaulted to true' do
|
|
28
|
+
src = 'def self.cc(arga = true) end'
|
|
29
|
+
src.should smell_of(BooleanParameter, BooleanParameter::PARAMETER_KEY => 'arga')
|
|
30
|
+
end
|
|
31
|
+
it 'reports a parameter defaulted to false' do
|
|
32
|
+
src = 'def fred.cc(arga = false) end'
|
|
33
|
+
src.should smell_of(BooleanParameter, BooleanParameter::PARAMETER_KEY => 'arga')
|
|
34
|
+
end
|
|
35
|
+
it 'reports two parameters defaulted to booleans' do
|
|
36
|
+
src = 'def Module.cc(nowt, arga = true, argb = false, &blk) end'
|
|
37
|
+
src.should smell_of(BooleanParameter,
|
|
38
|
+
{BooleanParameter::PARAMETER_KEY => 'arga'},
|
|
39
|
+
{BooleanParameter::PARAMETER_KEY => 'argb'})
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
context 'when a smell is reported' do
|
|
45
|
+
before(:each) do
|
|
46
|
+
@source_name = 'smokin'
|
|
47
|
+
@detector = BooleanParameter.new(@source_name)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it_should_behave_like 'SmellDetector'
|
|
51
|
+
|
|
52
|
+
it 'reports the fields correctly' do
|
|
53
|
+
src = 'def cc(arga = true) end'
|
|
54
|
+
ctx = MethodContext.new(nil, src.to_reek_source.syntax_tree)
|
|
55
|
+
@detector.examine(ctx)
|
|
56
|
+
smells = @detector.smells_found.to_a
|
|
57
|
+
smells.length.should == 1
|
|
58
|
+
smells[0].smell_class.should == BooleanParameter::SMELL_CLASS
|
|
59
|
+
smells[0].smell[BooleanParameter::PARAMETER_KEY].should == 'arga'
|
|
60
|
+
smells[0].source.should == @source_name
|
|
61
|
+
smells[0].smell_class.should == BooleanParameter::SMELL_CLASS
|
|
62
|
+
smells[0].subclass.should == BooleanParameter::SMELL_SUBCLASS
|
|
63
|
+
smells[0].lines.should == [1]
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -1,115 +1,100 @@
|
|
|
1
|
-
require File.dirname(__FILE__)
|
|
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', 'class_variable')
|
|
3
|
+
require File.join(File.dirname(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__))))), 'lib', 'reek', 'core', 'module_context')
|
|
4
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'smell_detector_shared')
|
|
2
5
|
|
|
3
|
-
|
|
4
|
-
require 'reek/class_context'
|
|
5
|
-
|
|
6
|
-
include Reek
|
|
6
|
+
include Reek::Core
|
|
7
7
|
include Reek::Smells
|
|
8
8
|
|
|
9
9
|
describe ClassVariable do
|
|
10
10
|
before :each do
|
|
11
|
-
@
|
|
11
|
+
@source_name = 'raffles'
|
|
12
|
+
@detector = ClassVariable.new(@source_name)
|
|
13
|
+
@class_variable = '@@things'
|
|
12
14
|
end
|
|
13
15
|
|
|
16
|
+
it_should_behave_like 'SmellDetector'
|
|
17
|
+
|
|
14
18
|
context 'with no class variables' do
|
|
15
19
|
it 'records nothing in the class' do
|
|
16
|
-
|
|
17
|
-
@detector.
|
|
20
|
+
exp = ast(:class, :Fred)
|
|
21
|
+
@detector.examine_context(CodeContext.new(nil, exp)).should be_empty
|
|
18
22
|
end
|
|
19
23
|
it 'records nothing in the module' do
|
|
20
|
-
|
|
21
|
-
@detector.
|
|
24
|
+
exp = ast(:module, :Fred)
|
|
25
|
+
@detector.examine_context(CodeContext.new(nil, exp)).should be_empty
|
|
22
26
|
end
|
|
23
27
|
end
|
|
24
28
|
|
|
25
29
|
context 'with one class variable' do
|
|
26
30
|
shared_examples_for 'one variable found' do
|
|
27
|
-
|
|
28
|
-
@
|
|
31
|
+
before :each do
|
|
32
|
+
ast = @src.to_reek_source.syntax_tree
|
|
33
|
+
@smells = @detector.examine_context(CodeContext.new(nil, ast))
|
|
29
34
|
end
|
|
30
35
|
it 'records only that class variable' do
|
|
31
|
-
@
|
|
36
|
+
@smells.length.should == 1
|
|
32
37
|
end
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
context 'declared in a class' do
|
|
36
|
-
before :each do
|
|
37
|
-
@ctx = ClassContext.from_s('class Fred; @@tools = {}; end')
|
|
38
|
+
it 'records the variable name' do
|
|
39
|
+
@smells[0].smell[ClassVariable::VARIABLE_KEY].should == @class_variable
|
|
38
40
|
end
|
|
39
|
-
|
|
40
|
-
it_should_behave_like 'one variable found'
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
['class', 'module'].each do |scope|
|
|
44
|
+
context "declared in a #{scope}" do
|
|
45
|
+
before :each do
|
|
46
|
+
@src = "#{scope} Fred; #{@class_variable} = {}; end"
|
|
47
|
+
end
|
|
47
48
|
|
|
48
|
-
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
context 'indexed in a class' do
|
|
52
|
-
before :each do
|
|
53
|
-
@ctx = ClassContext.from_s('class Fred; def jim() @@tools[mash] = {}; end; end')
|
|
49
|
+
it_should_behave_like 'one variable found'
|
|
54
50
|
end
|
|
55
51
|
|
|
56
|
-
|
|
57
|
-
|
|
52
|
+
context "used in a #{scope}" do
|
|
53
|
+
before :each do
|
|
54
|
+
@src = "#{scope} Fred; def jim() #{@class_variable} = {}; end; end"
|
|
55
|
+
end
|
|
58
56
|
|
|
59
|
-
|
|
60
|
-
before :each do
|
|
61
|
-
@ctx = ClassContext.from_s('class Fred; @@tools = {}; def jim() @@tools = {}; end; end')
|
|
57
|
+
it_should_behave_like 'one variable found'
|
|
62
58
|
end
|
|
63
59
|
|
|
64
|
-
|
|
65
|
-
|
|
60
|
+
context "indexed in a #{scope}" do
|
|
61
|
+
before :each do
|
|
62
|
+
@src = "#{scope} Fred; def jim() #{@class_variable}[mash] = {}; end; end"
|
|
63
|
+
end
|
|
66
64
|
|
|
67
|
-
|
|
68
|
-
before :each do
|
|
69
|
-
@ctx = ClassContext.from_s('class Fred; def jeff() @@tools = {}; end; def jim() @@tools = {}; end; end')
|
|
65
|
+
it_should_behave_like 'one variable found'
|
|
70
66
|
end
|
|
71
67
|
|
|
72
|
-
|
|
73
|
-
|
|
68
|
+
context "declared and used in a #{scope}" do
|
|
69
|
+
before :each do
|
|
70
|
+
@src = "#{scope} Fred; #{@class_variable} = {}; def jim() #{@class_variable} = {}; end; end"
|
|
71
|
+
end
|
|
74
72
|
|
|
75
|
-
|
|
76
|
-
before :each do
|
|
77
|
-
@ctx = ClassContext.from_s('module Fred; @@tools = {}; end')
|
|
73
|
+
it_should_behave_like 'one variable found'
|
|
78
74
|
end
|
|
79
75
|
|
|
80
|
-
|
|
81
|
-
|
|
76
|
+
context "used twice in a #{scope}" do
|
|
77
|
+
before :each do
|
|
78
|
+
@src = "#{scope} Fred; def jeff() #{@class_variable} = {}; end; def jim() #{@class_variable} = {}; end; end"
|
|
79
|
+
end
|
|
82
80
|
|
|
83
|
-
|
|
84
|
-
before :each do
|
|
85
|
-
@ctx = ClassContext.from_s('module Fred; def jim() @@tools = {}; end; end')
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
it_should_behave_like 'one variable found'
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
context 'indexed in a module' do
|
|
92
|
-
before :each do
|
|
93
|
-
@ctx = ClassContext.from_s('module Fred; def jim() @@tools[mash] = {}; end; end')
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
it_should_behave_like 'one variable found'
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
context 'declared and used in a module' do
|
|
100
|
-
before :each do
|
|
101
|
-
@ctx = ClassContext.from_s('module Fred; @@tools = {}; def jim() @@tools = {}; end; end')
|
|
81
|
+
it_should_behave_like 'one variable found'
|
|
102
82
|
end
|
|
103
|
-
|
|
104
|
-
it_should_behave_like 'one variable found'
|
|
105
83
|
end
|
|
84
|
+
end
|
|
106
85
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
86
|
+
it 'reports the correct fields' do
|
|
87
|
+
src = <<EOS
|
|
88
|
+
module Fred
|
|
89
|
+
#{@class_variable} = {}
|
|
90
|
+
end
|
|
91
|
+
EOS
|
|
92
|
+
ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
|
|
93
|
+
@warning = @detector.examine_context(ctx)[0]
|
|
94
|
+
@warning.source.should == @source_name
|
|
95
|
+
@warning.smell_class.should == ClassVariable::SMELL_CLASS
|
|
96
|
+
@warning.subclass.should == ClassVariable::SMELL_SUBCLASS
|
|
97
|
+
@warning.smell[ClassVariable::VARIABLE_KEY].should == @class_variable
|
|
98
|
+
@warning.lines.should == [2]
|
|
114
99
|
end
|
|
115
100
|
end
|