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.
Files changed (209) hide show
  1. data/.yardopts +10 -0
  2. data/History.txt +62 -0
  3. data/README.md +74 -0
  4. data/bin/reek +2 -2
  5. data/config/defaults.reek +44 -5
  6. data/features/api.feature +20 -0
  7. data/features/masking_smells.feature +60 -42
  8. data/features/options.feature +7 -2
  9. data/features/rake_task.feature +29 -22
  10. data/features/reports.feature +9 -41
  11. data/features/samples.feature +184 -196
  12. data/features/stdin.feature +5 -8
  13. data/features/step_definitions/reek_steps.rb +8 -4
  14. data/features/support/env.rb +2 -3
  15. data/features/yaml.feature +85 -0
  16. data/lib/reek/cli/application.rb +46 -0
  17. data/lib/reek/cli/command_line.rb +108 -0
  18. data/lib/reek/cli/help_command.rb +18 -0
  19. data/lib/reek/cli/reek_command.rb +37 -0
  20. data/lib/reek/cli/report.rb +58 -0
  21. data/lib/reek/cli/version_command.rb +19 -0
  22. data/lib/reek/cli/yaml_command.rb +32 -0
  23. data/lib/reek/core/code_context.rb +64 -0
  24. data/lib/reek/core/code_parser.rb +166 -0
  25. data/lib/reek/core/method_context.rb +84 -0
  26. data/lib/reek/core/module_context.rb +20 -0
  27. data/lib/reek/core/object_refs.rb +51 -0
  28. data/lib/reek/core/singleton_method_context.rb +20 -0
  29. data/lib/reek/core/smell_configuration.rb +62 -0
  30. data/lib/reek/core/sniffer.rb +105 -0
  31. data/lib/reek/core/stop_context.rb +30 -0
  32. data/lib/reek/core/warning_collector.rb +27 -0
  33. data/lib/reek/examiner.rb +104 -0
  34. data/lib/reek/rake/task.rb +142 -0
  35. data/lib/reek/smell_warning.rb +73 -23
  36. data/lib/reek/smells/attribute.rb +26 -21
  37. data/lib/reek/smells/boolean_parameter.rb +38 -0
  38. data/lib/reek/smells/class_variable.rb +22 -9
  39. data/lib/reek/smells/control_couple.rb +40 -16
  40. data/lib/reek/smells/data_clump.rb +114 -23
  41. data/lib/reek/smells/duplication.rb +55 -15
  42. data/lib/reek/smells/feature_envy.rb +16 -7
  43. data/lib/reek/smells/irresponsible_module.rb +37 -0
  44. data/lib/reek/smells/large_class.rb +37 -19
  45. data/lib/reek/smells/long_method.rb +20 -9
  46. data/lib/reek/smells/long_parameter_list.rb +22 -10
  47. data/lib/reek/smells/long_yield_list.rb +43 -7
  48. data/lib/reek/smells/nested_iterators.rb +68 -8
  49. data/lib/reek/smells/simulated_polymorphism.rb +26 -15
  50. data/lib/reek/smells/smell_detector.rb +29 -51
  51. data/lib/reek/smells/uncommunicative_method_name.rb +74 -0
  52. data/lib/reek/smells/uncommunicative_module_name.rb +74 -0
  53. data/lib/reek/smells/uncommunicative_parameter_name.rb +79 -0
  54. data/lib/reek/smells/uncommunicative_variable_name.rb +89 -0
  55. data/lib/reek/smells/utility_function.rb +51 -12
  56. data/lib/reek/smells.rb +29 -0
  57. data/lib/reek/source/code_comment.rb +37 -0
  58. data/lib/reek/source/config_file.rb +72 -0
  59. data/lib/reek/source/core_extras.rb +46 -0
  60. data/lib/reek/source/reference_collector.rb +28 -0
  61. data/lib/reek/source/sexp_formatter.rb +17 -0
  62. data/lib/reek/source/source_code.rb +44 -0
  63. data/lib/reek/source/source_file.rb +32 -0
  64. data/lib/reek/source/source_locator.rb +42 -0
  65. data/lib/reek/source/tree_dresser.rb +204 -0
  66. data/lib/reek/source.rb +18 -0
  67. data/lib/reek/spec/should_reek.rb +31 -0
  68. data/lib/reek/spec/should_reek_of.rb +37 -0
  69. data/lib/reek/spec/should_reek_only_of.rb +37 -0
  70. data/lib/reek/spec.rb +51 -0
  71. data/lib/reek.rb +8 -4
  72. data/reek.gemspec +9 -7
  73. data/spec/matchers/smell_of_matcher.rb +58 -0
  74. data/spec/reek/{help_command_spec.rb → cli/help_command_spec.rb} +3 -4
  75. data/spec/reek/cli/reek_command_spec.rb +46 -0
  76. data/spec/reek/cli/report_spec.rb +30 -0
  77. data/spec/reek/{version_command_spec.rb → cli/version_command_spec.rb} +3 -3
  78. data/spec/reek/cli/yaml_command_spec.rb +47 -0
  79. data/spec/reek/core/code_context_spec.rb +145 -0
  80. data/spec/reek/{code_parser_spec.rb → core/code_parser_spec.rb} +7 -6
  81. data/spec/reek/{config_spec.rb → core/config_spec.rb} +2 -6
  82. data/spec/reek/{method_context_spec.rb → core/method_context_spec.rb} +16 -36
  83. data/spec/reek/core/module_context_spec.rb +27 -0
  84. data/spec/reek/{object_refs_spec.rb → core/object_refs_spec.rb} +5 -6
  85. data/spec/reek/core/singleton_method_context_spec.rb +9 -0
  86. data/spec/reek/core/smell_configuration_spec.rb +11 -0
  87. data/spec/reek/core/stop_context_spec.rb +17 -0
  88. data/spec/reek/core/warning_collector_spec.rb +27 -0
  89. data/spec/reek/examiner_spec.rb +103 -0
  90. data/spec/reek/smell_warning_spec.rb +74 -82
  91. data/spec/reek/smells/attribute_spec.rb +42 -23
  92. data/spec/reek/smells/behaves_like_variable_detector.rb +2 -2
  93. data/spec/reek/smells/boolean_parameter_spec.rb +66 -0
  94. data/spec/reek/smells/class_variable_spec.rb +60 -75
  95. data/spec/reek/smells/control_couple_spec.rb +37 -32
  96. data/spec/reek/smells/data_clump_spec.rb +63 -24
  97. data/spec/reek/smells/duplication_spec.rb +106 -57
  98. data/spec/reek/smells/feature_envy_spec.rb +113 -92
  99. data/spec/reek/smells/irresponsible_module_spec.rb +58 -0
  100. data/spec/reek/smells/large_class_spec.rb +67 -57
  101. data/spec/reek/smells/long_method_spec.rb +40 -10
  102. data/spec/reek/smells/long_parameter_list_spec.rb +50 -28
  103. data/spec/reek/smells/long_yield_list_spec.rb +57 -0
  104. data/spec/reek/smells/nested_iterators_spec.rb +115 -7
  105. data/spec/reek/smells/simulated_polymorphism_spec.rb +56 -20
  106. data/spec/reek/smells/smell_detector_shared.rb +42 -0
  107. data/spec/reek/smells/uncommunicative_method_name_spec.rb +42 -0
  108. data/spec/reek/smells/uncommunicative_module_name_spec.rb +66 -0
  109. data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +71 -0
  110. data/spec/reek/smells/uncommunicative_variable_name_spec.rb +120 -0
  111. data/spec/reek/smells/utility_function_spec.rb +50 -4
  112. data/spec/reek/source/code_comment_spec.rb +82 -0
  113. data/spec/reek/source/object_source_spec.rb +20 -0
  114. data/spec/reek/source/reference_collector_spec.rb +53 -0
  115. data/spec/reek/{adapters/source_spec.rb → source/source_code_spec.rb} +7 -8
  116. data/spec/reek/source/tree_dresser_spec.rb +270 -0
  117. data/spec/reek/spec/should_reek_of_spec.rb +76 -0
  118. data/spec/reek/spec/should_reek_only_of_spec.rb +89 -0
  119. data/spec/reek/{adapters → spec}/should_reek_spec.rb +8 -32
  120. data/spec/samples/all_but_one_masked/clean_one.rb +1 -0
  121. data/spec/samples/all_but_one_masked/dirty.rb +1 -0
  122. data/spec/samples/all_but_one_masked/masked.reek +5 -1
  123. data/spec/samples/clean_due_to_masking/clean_one.rb +1 -0
  124. data/spec/samples/clean_due_to_masking/clean_three.rb +1 -0
  125. data/spec/samples/clean_due_to_masking/clean_two.rb +1 -0
  126. data/spec/samples/clean_due_to_masking/dirty_one.rb +1 -1
  127. data/spec/samples/clean_due_to_masking/dirty_two.rb +1 -1
  128. data/spec/samples/clean_due_to_masking/masked.reek +5 -1
  129. data/spec/samples/config/allow_duplication.reek +3 -0
  130. data/spec/samples/config/deeper_nested_iterators.reek +3 -0
  131. data/spec/samples/corrupt_config_file/dirty.rb +1 -1
  132. data/spec/samples/demo/demo.rb +8 -0
  133. data/spec/samples/empty_config_file/dirty.rb +2 -1
  134. data/spec/samples/exceptions.reek +1 -1
  135. data/spec/samples/inline_config/dirty.rb +16 -0
  136. data/spec/samples/inline_config/masked.reek +7 -0
  137. data/spec/samples/mask_some/dirty.rb +8 -0
  138. data/spec/samples/mask_some/some.reek +8 -0
  139. data/spec/samples/masked/dirty.rb +2 -1
  140. data/spec/samples/masked/masked.reek +3 -1
  141. data/spec/samples/mixed_results/clean_one.rb +1 -0
  142. data/spec/samples/mixed_results/clean_three.rb +1 -0
  143. data/spec/samples/mixed_results/clean_two.rb +1 -0
  144. data/spec/samples/mixed_results/dirty_one.rb +1 -0
  145. data/spec/samples/mixed_results/dirty_two.rb +1 -0
  146. data/spec/samples/not_quite_masked/dirty.rb +2 -1
  147. data/spec/samples/not_quite_masked/masked.reek +1 -1
  148. data/spec/samples/overrides/masked/dirty.rb +2 -1
  149. data/spec/samples/overrides/masked/lower.reek +3 -1
  150. data/spec/samples/three_clean_files/clean_one.rb +1 -0
  151. data/spec/samples/three_clean_files/clean_three.rb +1 -0
  152. data/spec/samples/three_clean_files/clean_two.rb +1 -0
  153. data/spec/samples/two_smelly_files/dirty_one.rb +2 -1
  154. data/spec/samples/two_smelly_files/dirty_two.rb +2 -1
  155. data/spec/spec_helper.rb +10 -2
  156. data/tasks/reek.rake +2 -2
  157. data/tasks/test.rake +12 -3
  158. metadata +121 -79
  159. data/README.rdoc +0 -84
  160. data/features/profile.feature +0 -34
  161. data/lib/reek/adapters/application.rb +0 -46
  162. data/lib/reek/adapters/command_line.rb +0 -77
  163. data/lib/reek/adapters/config_file.rb +0 -31
  164. data/lib/reek/adapters/core_extras.rb +0 -64
  165. data/lib/reek/adapters/rake_task.rb +0 -121
  166. data/lib/reek/adapters/report.rb +0 -86
  167. data/lib/reek/adapters/source.rb +0 -72
  168. data/lib/reek/adapters/spec.rb +0 -133
  169. data/lib/reek/block_context.rb +0 -62
  170. data/lib/reek/class_context.rb +0 -41
  171. data/lib/reek/code_context.rb +0 -68
  172. data/lib/reek/code_parser.rb +0 -203
  173. data/lib/reek/configuration.rb +0 -57
  174. data/lib/reek/detector_stack.rb +0 -37
  175. data/lib/reek/help_command.rb +0 -14
  176. data/lib/reek/if_context.rb +0 -18
  177. data/lib/reek/masking_collection.rb +0 -33
  178. data/lib/reek/method_context.rb +0 -138
  179. data/lib/reek/module_context.rb +0 -49
  180. data/lib/reek/name.rb +0 -57
  181. data/lib/reek/object_refs.rb +0 -49
  182. data/lib/reek/reek_command.rb +0 -28
  183. data/lib/reek/sexp_formatter.rb +0 -10
  184. data/lib/reek/singleton_method_context.rb +0 -26
  185. data/lib/reek/smells/uncommunicative_name.rb +0 -84
  186. data/lib/reek/sniffer.rb +0 -177
  187. data/lib/reek/stop_context.rb +0 -35
  188. data/lib/reek/tree_dresser.rb +0 -82
  189. data/lib/reek/version_command.rb +0 -14
  190. data/lib/reek/yield_call_context.rb +0 -12
  191. data/spec/reek/adapters/report_spec.rb +0 -31
  192. data/spec/reek/adapters/should_reek_of_spec.rb +0 -138
  193. data/spec/reek/adapters/should_reek_only_of_spec.rb +0 -87
  194. data/spec/reek/block_context_spec.rb +0 -65
  195. data/spec/reek/class_context_spec.rb +0 -161
  196. data/spec/reek/code_context_spec.rb +0 -182
  197. data/spec/reek/configuration_spec.rb +0 -12
  198. data/spec/reek/if_context_spec.rb +0 -17
  199. data/spec/reek/masking_collection_spec.rb +0 -236
  200. data/spec/reek/module_context_spec.rb +0 -46
  201. data/spec/reek/name_spec.rb +0 -37
  202. data/spec/reek/object_source_spec.rb +0 -23
  203. data/spec/reek/reek_command_spec.rb +0 -45
  204. data/spec/reek/singleton_method_context_spec.rb +0 -16
  205. data/spec/reek/smells/smell_detector_spec.rb +0 -36
  206. data/spec/reek/smells/uncommunicative_name_spec.rb +0 -146
  207. data/spec/reek/sniffer_spec.rb +0 -11
  208. data/spec/reek/stop_context_spec.rb +0 -33
  209. data/spec/reek/tree_dresser_spec.rb +0 -20
@@ -0,0 +1,30 @@
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', 'examiner')
3
+ require File.join(File.dirname(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__))))), 'lib', 'reek', 'cli', 'report')
4
+
5
+ include Reek
6
+ include Reek::Cli
7
+
8
+ describe QuietReport, " when empty" do
9
+ context 'empty source' do
10
+ it 'has an empty quiet_report' do
11
+ examiner = Examiner.new('')
12
+ QuietReport.new(examiner).report.should == ''
13
+ end
14
+ end
15
+
16
+ context 'with a couple of smells' do
17
+ before :each do
18
+ examiner = Examiner.new('def simple(a) a[3] end')
19
+ rpt = QuietReport.new(examiner)
20
+ @lines = rpt.report.split("\n")
21
+ end
22
+ it 'has a header and a list of smells' do
23
+ @lines.should have_at_least(3).lines
24
+ end
25
+ it 'should mention every smell name' do
26
+ @lines[0].should match('[Utility Function]')
27
+ @lines[1].should match('[Feature Envy]')
28
+ end
29
+ end
30
+ end
@@ -1,8 +1,8 @@
1
- require File.dirname(__FILE__) + '/../spec_helper.rb'
2
-
3
- require 'reek/version_command'
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', 'cli', 'version_command')
4
3
 
5
4
  include Reek
5
+ include Reek::Cli
6
6
 
7
7
  describe VersionCommand do
8
8
  before :each do
@@ -0,0 +1,47 @@
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', 'cli', 'yaml_command')
3
+
4
+ include Reek
5
+ include Reek::Cli
6
+
7
+ describe YamlCommand do
8
+ before :each do
9
+ @view = mock('view', :null_object => true)
10
+ @examiner = mock('examiner')
11
+ end
12
+
13
+ context 'with no smells' do
14
+ before :each do
15
+ @examiner.should_receive(:smells).and_return([])
16
+ @cmd = YamlCommand.new([@examiner])
17
+ end
18
+
19
+ it 'displays nothing on the view' do
20
+ @view.should_not_receive(:output)
21
+ @cmd.execute(@view)
22
+ end
23
+
24
+ it 'tells the view it succeeded' do
25
+ @view.should_receive(:report_success)
26
+ @cmd.execute(@view)
27
+ end
28
+ end
29
+
30
+ context 'with smells' do
31
+ before :each do
32
+ @smell = SmellWarning.new('UncommunicativeName', "self", 27, "self")
33
+ @examiner.should_receive(:smells).and_return([@smell])
34
+ @cmd = YamlCommand.new([@examiner])
35
+ end
36
+
37
+ it 'displays the correct text on the view' do
38
+ @view.should_receive(:output).with(/UncommunicativeName/)
39
+ @cmd.execute(@view)
40
+ end
41
+
42
+ it 'tells the view it found smells' do
43
+ @view.should_receive(:report_smells)
44
+ @cmd.execute(@view)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,145 @@
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', 'core', 'method_context')
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.dirname(File.dirname(File.dirname(File.expand_path(__FILE__))))), 'lib', 'reek', 'core', 'stop_context')
5
+
6
+ include Reek::Core
7
+
8
+ describe CodeContext do
9
+ context 'name recognition' do
10
+ before :each do
11
+ @exp_name = 'random_name' # SMELL: could use a String.random here
12
+ @full_name = "::::::::::::::::::::#{@exp_name}"
13
+ @exp = mock('exp')
14
+ @exp.should_receive(:name).any_number_of_times.and_return(@exp_name)
15
+ @exp.should_receive(:full_name).any_number_of_times.and_return(@full_name)
16
+ @exp.should_receive(:comments).any_number_of_times.and_return('')
17
+ @ctx = CodeContext.new(nil, @exp)
18
+ end
19
+ it 'gets its short name from the exp' do
20
+ @ctx.name.should == @exp_name
21
+ end
22
+ it 'does not match an empty list' do
23
+ @ctx.matches?([]).should == false
24
+ end
25
+ it 'does not match when its own short name is not given' do
26
+ @ctx.matches?(['banana']).should == false
27
+ end
28
+ it 'recognises its own short name' do
29
+ @ctx.matches?(['banana', @exp_name]).should == true
30
+ end
31
+ it 'recognises its short name as a regex' do
32
+ @ctx.matches?([/banana/, /#{@exp_name}/]).should == true
33
+ end
34
+
35
+ context 'when there is an outer' do
36
+ before :each do
37
+ @outer_name = 'another_random sting'
38
+ outer = mock('outer')
39
+ outer.should_receive(:full_name).at_least(:once).and_return(@outer_name)
40
+ outer.should_receive(:config).and_return({})
41
+ @ctx = CodeContext.new(outer, @exp)
42
+ end
43
+ it 'creates the correct full name' do
44
+ @ctx.full_name.should == "#{@full_name}"
45
+ end
46
+ it 'recognises its own full name' do
47
+ @ctx.matches?(['banana', @full_name]).should == true
48
+ end
49
+ it 'recognises its full name as a regex' do
50
+ @ctx.matches?([/banana/, /#{@full_name}/]).should == true
51
+ end
52
+ end
53
+ end
54
+
55
+ context 'generics' do
56
+ it 'should pass unknown method calls down the stack' do
57
+ stop = StopContext.new
58
+ def stop.bananas(arg1, arg2) arg1 + arg2 + 43 end
59
+ element = ModuleContext.new(stop, 'mod', ast(:module, :mod, nil))
60
+ element = MethodContext.new(element, ast(:defn, :bad))
61
+ element.bananas(17, -5).should == 55
62
+ end
63
+ end
64
+
65
+ context 'enumerating syntax elements' do
66
+ context 'in an empty module' do
67
+ before :each do
68
+ @module_name = 'Emptiness'
69
+ src = "module #{@module_name}; end"
70
+ ast = src.to_reek_source.syntax_tree
71
+ @ctx = CodeContext.new(nil, ast)
72
+ end
73
+ it 'yields no calls' do
74
+ @ctx.each_node(:call, []) {|exp| raise "#{exp} yielded by empty module!"}
75
+ end
76
+ it 'yields one module' do
77
+ mods = 0
78
+ @ctx.each_node(:module, []) {|exp| mods += 1}
79
+ mods.should == 1
80
+ end
81
+ it "yields the module's full AST" do
82
+ @ctx.each_node(:module, []) {|exp| exp[1].should == @module_name.to_sym}
83
+ end
84
+
85
+ context 'with no block' do
86
+ it 'returns an empty array of ifs' do
87
+ @ctx.each_node(:if, []).should be_empty
88
+ end
89
+ end
90
+ end
91
+
92
+ context 'with a nested element' do
93
+ before :each do
94
+ @module_name = 'Loneliness'
95
+ @method_name = 'calloo'
96
+ src = "module #{@module_name}; def #{@method_name}; puts('hello') end; end"
97
+ ast = src.to_reek_source.syntax_tree
98
+ @ctx = CodeContext.new(nil, ast)
99
+ end
100
+ it 'yields no ifs' do
101
+ @ctx.each_node(:if, []) {|exp| raise "#{exp} yielded by empty module!"}
102
+ end
103
+ it 'yields one module' do
104
+ @ctx.each_node(:module, []).length.should == 1
105
+ end
106
+ it "yields the module's full AST" do
107
+ @ctx.each_node(:module, []) {|exp| exp[1].should == @module_name.to_sym}
108
+ end
109
+ it 'yields one method' do
110
+ @ctx.each_node(:defn, []).length.should == 1
111
+ end
112
+ it "yields the method's full AST" do
113
+ @ctx.each_node(:defn, []) {|exp| exp[1].should == @method_name.to_sym}
114
+ end
115
+
116
+ context 'pruning the traversal' do
117
+ it 'ignores the call inside the method' do
118
+ @ctx.each_node(:call, [:defn]).should be_empty
119
+ end
120
+ end
121
+ end
122
+
123
+ it 'finds 3 ifs in a class' do
124
+ src = <<EOS
125
+ class Scrunch
126
+ def first
127
+ return @field == :sym ? 0 : 3;
128
+ end
129
+ def second
130
+ if @field == :sym
131
+ @other += " quarts"
132
+ end
133
+ end
134
+ def third
135
+ raise 'flu!' unless @field == :sym
136
+ end
137
+ end
138
+ EOS
139
+
140
+ ast = src.to_reek_source.syntax_tree
141
+ ctx = CodeContext.new(nil, ast)
142
+ ctx.each_node(:if, []).length.should == 3
143
+ end
144
+ end
145
+ end
@@ -1,21 +1,22 @@
1
- require File.dirname(__FILE__) + '/../spec_helper.rb'
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', 'core', 'code_parser')
2
3
 
3
- require 'reek/code_parser'
4
-
5
- include Reek
4
+ include Reek::Core
6
5
 
7
6
  describe CodeParser, "with no method definitions" do
8
7
  it 'reports no problems for empty source code' do
9
8
  ''.should_not reek
10
9
  end
11
10
  it 'reports no problems for empty class' do
12
- 'class Fred; end'.should_not reek
11
+ '# clean class for testing purposes
12
+ class Fred; end'.should_not reek
13
13
  end
14
14
  end
15
15
 
16
16
  describe CodeParser, 'with a global method definition' do
17
17
  it 'reports no problems for simple method' do
18
- 'def Outermost::fred() true; end'.should_not reek
18
+ src = 'def Outermost::fred() true; end'
19
+ src.should_not reek
19
20
  end
20
21
  end
21
22
 
@@ -1,9 +1,5 @@
1
- require File.dirname(__FILE__) + '/../spec_helper.rb'
2
-
3
- require 'reek/sniffer'
4
- require 'yaml'
5
-
6
- include Reek
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', 'core', 'sniffer')
7
3
 
8
4
  describe Hash do
9
5
  before :each do
@@ -1,13 +1,14 @@
1
- require File.dirname(__FILE__) + '/../spec_helper.rb'
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', 'core', 'method_context')
3
+ require File.join(File.dirname(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__))))), 'lib', 'reek', 'core', 'stop_context')
2
4
 
3
- require 'reek/method_context'
4
- require 'reek/stop_context'
5
-
6
- include Reek
5
+ include Reek::Core
7
6
 
8
7
  describe MethodContext, 'matching' do
9
8
  before :each do
10
- @element = MethodContext.new(StopContext.new, s(0, :mod))
9
+ exp = mock('exp', :null_object => true)
10
+ exp.should_receive(:full_name).at_least(:once).and_return('mod')
11
+ @element = MethodContext.new(StopContext.new, exp)
11
12
  end
12
13
 
13
14
  it 'should recognise itself in a collection of names' do
@@ -21,46 +22,25 @@ describe MethodContext, 'matching' do
21
22
  end
22
23
  end
23
24
 
24
- describe MethodContext, 'matching fq names' do
25
- before :each do
26
- element = StopContext.new
27
- element = ModuleContext.new(element, Name.new(:mod), s(:module, :mod, nil))
28
- element = ClassContext.new(element, Name.new(:klass), s())
29
- @element = MethodContext.new(element, s(0, :meth))
30
- end
31
-
32
- it 'should recognise itself in a collection of names' do
33
- @element.matches?(['banana', 'meth']).should == true
34
- @element.matches?(['banana', 'klass#meth']).should == true
35
- @element.matches?(['banana']).should == false
36
- end
37
-
38
- it 'should recognise itself in a collection of names' do
39
- @element.matches?([/banana/, /meth/]).should == true
40
- @element.matches?([/banana/, /klass#meth/]).should == true
41
- @element.matches?([/banana/]).should == false
42
- end
43
- end
44
-
45
25
  describe MethodContext do
46
26
  it 'should record ivars as refs to self' do
47
- mctx = MethodContext.new(StopContext.new, [:defn, :feed])
27
+ mctx = MethodContext.new(StopContext.new, ast(:defn, :feed))
48
28
  mctx.envious_receivers.should == []
49
- mctx.record_call_to([:call, [:ivar, :@cow], :feed_to])
29
+ mctx.record_call_to(ast(:call, s(:ivar, :@cow), :feed_to))
50
30
  mctx.envious_receivers.should == []
51
31
  end
52
32
 
53
33
  it 'should count calls to self' do
54
- mctx = MethodContext.new(StopContext.new, [:defn, :equals])
34
+ mctx = MethodContext.new(StopContext.new, ast(:defn, :equals))
55
35
  mctx.refs.record_ref([:lvar, :other])
56
- mctx.record_call_to([:call, [:self], :thing])
36
+ mctx.record_call_to(ast(:call, s(:self), :thing))
57
37
  mctx.envious_receivers.should be_empty
58
38
  end
59
39
 
60
40
  it 'should recognise a call on self' do
61
41
  mc = MethodContext.new(StopContext.new, s(:defn, :deep))
62
- mc.record_call_to(s(:call, s(:lvar, :text), :each, s(:arglist)))
63
- mc.record_call_to(s(:call, nil, :shelve, s(:arglist)))
42
+ mc.record_call_to(ast(:call, s(:lvar, :text), :each, s(:arglist)))
43
+ mc.record_call_to(ast(:call, nil, :shelve, s(:arglist)))
64
44
  mc.envious_receivers.should be_empty
65
45
  end
66
46
  end
@@ -85,7 +65,7 @@ describe MethodParameters, 'default assignments' do
85
65
  @defaults = assignments_from(src)
86
66
  end
87
67
  it 'returns the param-value pair' do
88
- @defaults[:argb].should == s(:lit, 456)
68
+ @defaults[0].should == s(:argb, s(:lit, 456))
89
69
  end
90
70
  it 'returns the nothing else' do
91
71
  @defaults.length.should == 1
@@ -98,8 +78,8 @@ describe MethodParameters, 'default assignments' do
98
78
  @defaults = assignments_from(src)
99
79
  end
100
80
  it 'returns both param-value pairs' do
101
- @defaults[:arga].should == s(:lit, 123)
102
- @defaults[:argb].should == s(:lit, 456)
81
+ @defaults[0].should == s(:arga, s(:lit, 123))
82
+ @defaults[1].should == s(:argb, s(:lit, 456))
103
83
  end
104
84
  it 'returns nothing else' do
105
85
  @defaults.length.should == 2
@@ -0,0 +1,27 @@
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', 'core', 'module_context')
3
+ require File.join(File.dirname(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__))))), 'lib', 'reek', 'core', 'stop_context')
4
+
5
+ include Reek::Core
6
+
7
+ describe ModuleContext do
8
+ it 'should report module name for smell in method' do
9
+ 'module Fred; def simple(x) true; end; end'.should reek_of(:UncommunicativeParameterName, /x/, /simple/)
10
+ end
11
+
12
+ it 'should not report module with empty class' do
13
+ '# module for test
14
+ module Fred
15
+ # module for test
16
+ class Jim; end; end'.should_not reek
17
+ end
18
+ end
19
+
20
+ describe ModuleContext do
21
+ it 'should recognise global constant' do
22
+ '# module for test
23
+ module ::Global
24
+ # module for test
25
+ class Inside; end; end'.should_not reek
26
+ end
27
+ end
@@ -1,8 +1,7 @@
1
- require File.dirname(__FILE__) + '/../spec_helper.rb'
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', 'core', 'object_refs')
2
3
 
3
- require 'reek/object_refs'
4
-
5
- include Reek
4
+ include Reek::Core
6
5
 
7
6
  describe ObjectRefs, 'when empty' do
8
7
  before(:each) do
@@ -27,7 +26,7 @@ describe ObjectRefs, 'with no refs to self' do
27
26
  end
28
27
 
29
28
  it 'should report :a as the max' do
30
- @refs.max_keys.should == ['a']
29
+ @refs.max_keys.should == {'a' => 2}
31
30
  end
32
31
 
33
32
  it 'should not report self as the max' do
@@ -75,7 +74,7 @@ describe ObjectRefs, 'with many refs to self' do
75
74
  end
76
75
 
77
76
  it 'should report self among the max' do
78
- @refs.max_keys.should == [Sexp.from_array([:lit, :self])]
77
+ @refs.max_keys.should == {Sexp.from_array([:lit, :self]) => 4}
79
78
  end
80
79
 
81
80
  it 'should report self as the max' do
@@ -0,0 +1,9 @@
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', 'core', 'module_context')
3
+ require File.join(File.dirname(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__))))), 'lib', 'reek', 'core', 'singleton_method_context')
4
+ require File.join(File.dirname(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__))))), 'lib', 'reek', 'core', 'stop_context')
5
+
6
+ include Reek::Core
7
+
8
+ describe SingletonMethodContext do
9
+ end
@@ -0,0 +1,11 @@
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', 'core', 'smell_configuration')
3
+
4
+ include Reek::Core
5
+
6
+ describe SmellConfiguration do
7
+ it 'returns the default value when key not found' do
8
+ cf = SmellConfiguration.new({})
9
+ cf.value('fred', nil, 27).should == 27
10
+ end
11
+ end
@@ -0,0 +1,17 @@
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', 'core', 'stop_context')
3
+
4
+ include Reek
5
+ include Reek::Core
6
+
7
+ describe StopContext do
8
+ before :each do
9
+ @stop = StopContext.new
10
+ end
11
+
12
+ context 'full_name' do
13
+ it "reports full context" do
14
+ @stop.full_name.should == ''
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,27 @@
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', 'core', 'warning_collector')
3
+ require File.join(File.dirname(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__))))), 'lib', 'reek', 'smell_warning')
4
+
5
+ include Reek::Core
6
+
7
+ describe WarningCollector do
8
+ before(:each) do
9
+ @collector = WarningCollector.new
10
+ end
11
+
12
+ context 'when empty' do
13
+ it 'reports no warnings' do
14
+ @collector.warnings.should == []
15
+ end
16
+ end
17
+
18
+ context 'with one warning' do
19
+ before :each do
20
+ @warning = Reek::SmellWarning.new('ControlCouple', 'fred', [1,2,3], 'hello')
21
+ @collector.found_smell(@warning)
22
+ end
23
+ it 'reports that warning' do
24
+ @collector.warnings.should == [@warning]
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,103 @@
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', 'examiner')
3
+
4
+ include Reek
5
+
6
+ shared_examples_for 'supports the deprecated api' do
7
+ it 'returns all smells as active' do
8
+ @examiner.all_active_smells.should == @examiner.smells
9
+ end
10
+ it 'returns all smells as active' do
11
+ @examiner.all_smells.should == @examiner.smells
12
+ end
13
+ it 'counts all smells as active smells' do
14
+ @examiner.num_active_smells.should == @examiner.smells.length
15
+ end
16
+ it 'never reports masked smells' do
17
+ @examiner.num_masked_smells.should == 0
18
+ end
19
+ end
20
+
21
+ shared_examples_for 'no smells found' do
22
+ it 'is not smelly' do
23
+ @examiner.should_not be_smelly
24
+ end
25
+ it 'finds no smells' do
26
+ @examiner.smells.length.should == 0
27
+ end
28
+
29
+ it_should_behave_like 'supports the deprecated api'
30
+ end
31
+
32
+ shared_examples_for 'one smell found' do
33
+ it 'is smelly' do
34
+ @examiner.should be_smelly
35
+ end
36
+ it 'reports the smell' do
37
+ @examiner.smells.length.should == 1
38
+ end
39
+ it 'reports the correct smell' do
40
+ @examiner.smells[0].smell_class.should == @expected_first_smell
41
+ end
42
+
43
+ it_should_behave_like 'supports the deprecated api'
44
+ end
45
+
46
+ describe Examiner do
47
+ before :each do
48
+ @expected_first_smell = 'NestedIterators'
49
+ end
50
+
51
+ context 'with a fragrant String' do
52
+ before :each do
53
+ @examiner = Examiner.new('def good() true; end')
54
+ end
55
+
56
+ it_should_behave_like 'no smells found'
57
+ end
58
+
59
+ context 'with a smelly String' do
60
+ before :each do
61
+ @examiner = Examiner.new('def fine() y = 4; end')
62
+ @expected_first_smell = 'UncommunicativeName'
63
+ end
64
+
65
+ it_should_behave_like 'one smell found'
66
+ end
67
+
68
+ context 'with a smelly Dir' do
69
+ before :each do
70
+ smelly_dir = Dir['spec/samples/all_but_one_masked/*.rb']
71
+ @examiner = Examiner.new(smelly_dir)
72
+ end
73
+
74
+ it_should_behave_like 'one smell found'
75
+ end
76
+
77
+ context 'with a fragrant Dir' do
78
+ before :each do
79
+ clean_dir = Dir['spec/samples/three_clean_files/*.rb']
80
+ @examiner = Examiner.new(clean_dir)
81
+ end
82
+
83
+ it_should_behave_like 'no smells found'
84
+ end
85
+
86
+ context 'with a smelly File' do
87
+ before :each do
88
+ smelly_file = File.new(Dir['spec/samples/all_but_one_masked/d*.rb'][0])
89
+ @examiner = Examiner.new(smelly_file)
90
+ end
91
+
92
+ it_should_behave_like 'one smell found'
93
+ end
94
+
95
+ context 'with a fragrant File' do
96
+ before :each do
97
+ clean_file = File.new(Dir['spec/samples/three_clean_files/*.rb'][0])
98
+ @examiner = Examiner.new(clean_file)
99
+ end
100
+
101
+ it_should_behave_like 'no smells found'
102
+ end
103
+ end