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
@@ -1,82 +0,0 @@
1
- module Reek
2
-
3
- #
4
- # Extensions to +Sexp+ to allow +CodeParser+ to navigate the abstract
5
- # syntax tree more easily.
6
- #
7
- module SexpNode
8
- def is_language_node?
9
- first.class == Symbol
10
- end
11
-
12
- def has_type?(type)
13
- is_language_node? and first == type
14
- end
15
-
16
- #
17
- # Carries out a depth-first traversal of this syntax tree, yielding
18
- # every Sexp of type +target_type+. The traversal ignores any node
19
- # whose type is listed in the Array +ignoring+.
20
- #
21
- def look_for(target_type, ignoring, &blk)
22
- each do |elem|
23
- if Sexp === elem then
24
- elem.look_for(target_type, ignoring, &blk) unless ignoring.include?(elem.first)
25
- end
26
- end
27
- blk.call(self) if first == target_type
28
- end
29
- end
30
-
31
- module SexpExtensions
32
- module CaseNode
33
- def condition
34
- self[1]
35
- end
36
- end
37
-
38
- module CallNode
39
- def receiver() self[1] end
40
- def method_name() self[2] end
41
- def args() self[3] end
42
- def arg_names
43
- args[1..-1].map {|arg| arg[1]}
44
- end
45
- end
46
-
47
- module CvarNode
48
- def name() self[1] end
49
- end
50
-
51
- CvasgnNode = CvarNode
52
- CvdeclNode = CvarNode
53
-
54
- module DefnNode
55
- def method_name() self[1] end
56
- def parameters() self[2] end
57
- end
58
-
59
- module IfNode
60
- def condition
61
- self[1]
62
- end
63
- end
64
- end
65
-
66
- class TreeDresser
67
-
68
- def dress(sexp)
69
- sexp.extend(SexpNode)
70
- module_name = extensions_for(sexp.sexp_type)
71
- if Reek::SexpExtensions.const_defined?(module_name)
72
- sexp.extend(Reek::SexpExtensions.const_get(module_name))
73
- end
74
- sexp[0..-1].each { |sub| dress(sub) if Array === sub }
75
- sexp
76
- end
77
-
78
- def extensions_for(node_type)
79
- "#{node_type.to_s.capitalize}Node"
80
- end
81
- end
82
- end
@@ -1,14 +0,0 @@
1
-
2
- module Reek
3
-
4
- class VersionCommand
5
- def initialize(progname)
6
- @progname = progname
7
- end
8
- def execute(view)
9
- view.output("#{@progname} #{Reek::VERSION}")
10
- view.report_success
11
- end
12
- end
13
-
14
- end
@@ -1,12 +0,0 @@
1
- require 'reek/code_context'
2
-
3
- module Reek
4
- class YieldCallContext < CodeContext
5
- attr_reader :parameters
6
-
7
- def initialize(outer, exp)
8
- super
9
- @parameters = exp[1..-1]
10
- end
11
- end
12
- end
@@ -1,31 +0,0 @@
1
- require File.dirname(__FILE__) + '/../../spec_helper.rb'
2
-
3
- require 'reek/adapters/core_extras'
4
- require 'reek/adapters/report'
5
- require 'reek/adapters/source'
6
- require 'reek/smells/feature_envy'
7
-
8
- include Reek
9
-
10
- describe ReportSection, " when empty" do
11
- before(:each) do
12
- @rpt = ReportSection.new(''.sniff, false)
13
- end
14
-
15
- it 'has an empty quiet_report' do
16
- @rpt.quiet_report.should == ''
17
- end
18
- end
19
-
20
- describe ReportSection, "smell_list" do
21
- before(:each) do
22
- rpt = ReportSection.new('def simple(a) a[3] end'.sniff, false)
23
- @lines = rpt.smell_list.split("\n")
24
- end
25
-
26
- it 'should mention every smell name' do
27
- @lines.should have_at_least(2).lines
28
- @lines[0].should match(/[Utility Function]/)
29
- @lines[1].should match(/[Feature Envy]/)
30
- end
31
- end
@@ -1,138 +0,0 @@
1
- require File.dirname(__FILE__) + '/../../spec_helper.rb'
2
-
3
- require 'reek/adapters/report'
4
- require 'reek/adapters/spec'
5
-
6
- include Reek
7
- include Reek::Spec
8
-
9
- # belongs in its own spec file
10
- describe ReekMatcher do
11
- before :each do
12
- smelly_code = Dir['spec/samples/two_smelly_files/*.rb']
13
- @sniffers = smelly_code.sniff.sniffers
14
- @full = VerboseReport.new(@sniffers, false).report
15
- end
16
-
17
- it 'reports quietly' do
18
- ReekMatcher.create_reporter(@sniffers).should_not == @full
19
- end
20
- end
21
-
22
- describe ShouldReekOf do
23
- context 'rdoc demo example' do
24
- before :each do
25
- @ruby = 'def double_thing() @other.thing.foo + @other.thing.foo end'
26
- end
27
-
28
- shared_examples_for 'reek as documented' do
29
- it 'reports duplicate calls to @other.thing' do
30
- @ruby.should reek_of(:Duplication, /@other.thing[^\.]/)
31
- end
32
- it 'reports duplicate calls to @other.thing.foo' do
33
- @ruby.should reek_of(:Duplication, /@other.thing.foo/)
34
- end
35
- it 'does not report any feature envy' do
36
- @ruby.should_not reek_of(:FeatureEnvy)
37
- end
38
- end
39
-
40
- context 'using source code' do
41
- it_should_behave_like 'reek as documented'
42
- end
43
-
44
- context 'using a sniffer' do
45
- before :each do
46
- @ruby = @ruby.sniff
47
- end
48
-
49
- it_should_behave_like 'reek as documented'
50
- end
51
- end
52
-
53
- context 'checking code in a string' do
54
- before :each do
55
- @clean_code = 'def good() true; end'
56
- @smelly_code = 'def x() y = 4; end'
57
- @expected_report = Reek::Spec::ReekMatcher::create_reporter(@smelly_code.sniff).report
58
- @matcher = ShouldReekOf.new(:UncommunicativeName, [/x/, /y/])
59
- end
60
-
61
- it 'matches a smelly String' do
62
- @matcher.matches?(@smelly_code).should be_true
63
- end
64
-
65
- it 'doesnt match a fragrant String' do
66
- @matcher.matches?(@clean_code).should be_false
67
- end
68
-
69
- it 'reports the smells when should_not fails' do
70
- @matcher.matches?(@smelly_code).should be_true
71
- @matcher.failure_message_for_should_not.should include(@expected_report)
72
- end
73
- end
74
-
75
- context 'checking code in a Dir' do
76
- before :each do
77
- @clean_dir = Dir['spec/samples/three_clean_files/*.rb']
78
- @smelly_dir = Dir['spec/samples/two_smelly_files/*.rb']
79
- @matcher = ShouldReekOf.new(:UncommunicativeName, [/Dirty/, /@s/])
80
- end
81
-
82
- it 'matches a smelly String' do
83
- @matcher.matches?(@smelly_dir).should be_true
84
- end
85
-
86
- it 'doesnt match a fragrant String' do
87
- @matcher.matches?(@clean_dir).should be_false
88
- end
89
-
90
- it 'reports the smells when should_not fails' do
91
- @matcher.matches?(@smelly_dir).should be_true
92
- @matcher.failure_message_for_should_not.should include(QuietReport.new(@smelly_dir.sniff.sniffers, '%m%c %w (%s)').report)
93
- end
94
- end
95
-
96
- context 'checking code in a File' do
97
- before :each do
98
- @clean_file = File.new(Dir['spec/samples/three_clean_files/*.rb'][0])
99
- @smelly_file = File.new(Dir['spec/samples/two_smelly_files/*.rb'][0])
100
- @matcher = ShouldReekOf.new(:UncommunicativeName, [/Dirty/, /@s/])
101
- end
102
-
103
- it 'matches a smelly String' do
104
- @matcher.matches?(@smelly_file).should be_true
105
- end
106
-
107
- it 'doesnt match a fragrant String' do
108
- @matcher.matches?(@clean_file).should be_false
109
- end
110
-
111
- it 'reports the smells when should_not fails' do
112
- @matcher.matches?(@smelly_file).should be_true
113
- @matcher.failure_message_for_should_not.should include(QuietReport.new(@smelly_file.sniff, '%m%c %w (%s)').report)
114
- end
115
- end
116
-
117
- context 'report formatting' do
118
- before :each do
119
- sn_clean = 'def clean() @thing = 4; end'.sniff
120
- sn_dirty = 'def dirty() thing.cool + thing.cool; end'.sniff
121
- sniffers = SnifferSet.new([sn_clean, sn_dirty], '')
122
- @matcher = ShouldReekOf.new(:UncommunicativeName, [/Dirty/, /@s/])
123
- @matcher.matches?(sniffers)
124
- @lines = @matcher.failure_message_for_should_not.split("\n").map {|str| str.chomp}
125
- @error_message = @lines.shift
126
- @smells = @lines.grep(/^ /)
127
- @headers = (@lines - @smells)
128
- end
129
-
130
- it 'mentions every smell in the report' do
131
- @smells.should have(2).warnings
132
- end
133
-
134
- it 'doesnt mention the clean source' do
135
- @headers.should have(1).headers
136
- end
137
- end
138
- end
@@ -1,87 +0,0 @@
1
- require File.dirname(__FILE__) + '/../../spec_helper.rb'
2
-
3
- require 'reek/adapters/report'
4
- require 'reek/adapters/spec'
5
-
6
- include Reek
7
- include Reek::Spec
8
-
9
- describe ShouldReekOnlyOf, 'checking code in a string' do
10
- before :each do
11
- @clean_code = 'def good() true; end'
12
- @smelly_code = 'def fine() y = 4; end'
13
- @matcher = ShouldReekOnlyOf.new(:UncommunicativeName, [/y/])
14
- end
15
-
16
- it 'matches a smelly String' do
17
- @matcher.matches?(@smelly_code).should be_true
18
- end
19
-
20
- it 'doesnt match a fragrant String' do
21
- @matcher.matches?(@clean_code).should be_false
22
- end
23
-
24
- it 'reports the smells when should_not fails' do
25
- @matcher.matches?(@smelly_code).should be_true
26
- @matcher.failure_message_for_should_not.should include('UncommunicativeName')
27
- end
28
- end
29
-
30
- describe ShouldReekOnlyOf, 'checking code in a Dir' do
31
- before :each do
32
- @clean_dir = Dir['spec/samples/three_clean_files/*.rb']
33
- @smelly_dir = Dir['spec/samples/all_but_one_masked/*.rb']
34
- @matcher = ShouldReekOnlyOf.new(:NestedIterators, [/Dirty\#a/])
35
- end
36
-
37
- it 'matches a smelly String' do
38
- @matcher.matches?(@smelly_dir).should be_true
39
- end
40
-
41
- it 'doesnt match a fragrant String' do
42
- @matcher.matches?(@clean_dir).should be_false
43
- end
44
-
45
- it 'reports the smells when should_not fails' do
46
- @matcher.matches?(@smelly_dir).should be_true
47
- @matcher.failure_message_for_should.should include(QuietReport.new(@smelly_dir.sniff.sniffers).report)
48
- end
49
- end
50
-
51
- describe ShouldReekOnlyOf, 'checking code in a File' do
52
- before :each do
53
- @clean_file = File.new(Dir['spec/samples/three_clean_files/*.rb'][0])
54
- @smelly_file = File.new(Dir['spec/samples/all_but_one_masked/d*.rb'][0])
55
- @matcher = ShouldReekOnlyOf.new(:NestedIterators, [/Dirty\#a/])
56
- end
57
-
58
- it 'matches a smelly String' do
59
- @matcher.matches?(@smelly_file).should be_true
60
- end
61
-
62
- it 'doesnt match a fragrant String' do
63
- @matcher.matches?(@clean_file).should be_false
64
- end
65
-
66
- it 'reports the smells when should_not fails' do
67
- @matcher.matches?(@smelly_file).should be_true
68
- @matcher.failure_message_for_should.should include(QuietReport.new(@smelly_file.sniff).report)
69
- end
70
- end
71
-
72
- describe ShouldReekOnlyOf, 'report formatting' do
73
- before :each do
74
- @smelly_dir = Dir['spec/samples/all_but_one_masked/*.rb']
75
- @matcher = ShouldReekOnlyOf.new(:NestedIterators, [/Dirty\#a/])
76
- @matcher.matches?(@smelly_dir)
77
- @lines = @matcher.failure_message_for_should.split("\n").map {|str| str.chomp}
78
- @error_message = @lines.shift
79
- @smells = @lines.grep(/^ /)
80
- @headers = (@lines - @smells)
81
- end
82
-
83
- it 'doesnt mention the clean files' do
84
- @headers.should have(1).header
85
- @headers.should_not include('clean')
86
- end
87
- end
@@ -1,65 +0,0 @@
1
- require File.dirname(__FILE__) + '/../spec_helper.rb'
2
-
3
- require 'reek/block_context'
4
- require 'reek/method_context'
5
-
6
- include Reek
7
-
8
- describe BlockContext do
9
-
10
- it "should record single parameter" do
11
- element = StopContext.new
12
- element = BlockContext.new(element, s(:iter, nil, s(:lasgn, :x), nil))
13
- element.variable_names.should == [Name.new(:x)]
14
- end
15
-
16
- it "should record single parameter within a method" do
17
- element = StopContext.new
18
- element = MethodContext.new(element, s(:defn, :help))
19
- element = BlockContext.new(element, s(:iter, nil, s(:lasgn, :x), nil))
20
- element.variable_names.should == [Name.new(:x)]
21
- end
22
-
23
- it "records multiple parameters" do
24
- element = StopContext.new
25
- element = BlockContext.new(element, s(:iter, nil, s(:masgn, s(:array, s(:lasgn, :x), s(:lasgn, :y))), nil))
26
- element.variable_names.should == [Name.new(:x), Name.new(:y)]
27
- end
28
-
29
- it "should not pass parameters upward" do
30
- mc = MethodContext.new(StopContext.new, s(:defn, :help, s(:args)))
31
- element = BlockContext.new(mc, s(:iter, nil, s(:lasgn, :x)))
32
- mc.variable_names.should be_empty
33
- end
34
-
35
- it 'records local variables' do
36
- bctx = BlockContext.new(StopContext.new, s(nil, nil))
37
- bctx.record_local_variable(:q2)
38
- bctx.variable_names.should include(Name.new(:q2))
39
- end
40
-
41
- it 'copes with a yield to an ivar' do
42
- scope = BlockContext.new(StopContext.new, s(:iter, nil, s(:iasgn, :@list), s(:self)))
43
- scope.record_instance_variable(:@list)
44
- scope.variable_names.should == [:@list]
45
- end
46
-
47
- context 'full_name' do
48
- it "reports full context" do
49
- bctx = BlockContext.new(StopContext.new, s(nil, nil))
50
- bctx.full_name.should == 'block'
51
- end
52
- it 'uses / to connect to the class name' do
53
- element = StopContext.new
54
- element = ClassContext.new(element, :Fred, s(:class, :Fred))
55
- element = BlockContext.new(element, s(:iter, nil, s(:lasgn, :x), nil))
56
- element.full_name.should == 'Fred/block'
57
- end
58
- it 'uses / to connect to the module name' do
59
- element = StopContext.new
60
- element = ModuleContext.new(element, :Fred, s(:module, :Fred))
61
- element = BlockContext.new(element, s(:iter, nil, s(:lasgn, :x), nil))
62
- element.full_name.should == 'Fred/block'
63
- end
64
- end
65
- end
@@ -1,161 +0,0 @@
1
- require File.dirname(__FILE__) + '/../spec_helper.rb'
2
-
3
- require 'reek/class_context'
4
- require 'reek/stop_context'
5
- require 'reek/smells/feature_envy'
6
-
7
- include Reek
8
- include Reek::Smells
9
-
10
- describe ClassContext do
11
- it 'should report Long Parameter List' do
12
- ruby = 'class Inner; def simple(arga, argb, argc, argd) f(3);true end end'
13
- ruby.should reek_of(:LongParameterList, /Inner/, /simple/, /4 parameters/)
14
- end
15
-
16
- it 'should report two different methods' do
17
- src = <<EOEX
18
- class Fred
19
- def simple(arga, argb, argc, argd) f(3);true end
20
- def simply(arga, argb, argc, argd) f(3);false end
21
- end
22
- EOEX
23
-
24
- src.should reek_of(:LongParameterList, /Fred/, /simple/)
25
- src.should reek_of(:LongParameterList, /Fred/, /simply/)
26
- end
27
-
28
- it 'should report many different methods' do
29
- src = <<EOEX
30
- class Fred
31
- def textile_bq(tag, atts, cite, content) f(3);end
32
- def textile_p(tag, atts, cite, content) f(3);end
33
- def textile_fn_(tag, num, atts, cite, content) f(3);end
34
- def textile_popup_help(name, windowW, windowH) f(3);end
35
- end
36
- EOEX
37
-
38
- src.should reek_of(:LongParameterList, /Fred/, /textile_bq/)
39
- src.should reek_of(:LongParameterList, /Fred/, /textile_fn_/)
40
- src.should reek_of(:LongParameterList, /Fred/, /textile_p/)
41
- end
42
- end
43
-
44
- class Above
45
- def above() end
46
- def both() end
47
- end
48
-
49
- class Below < Above
50
- def both() end
51
- def below() end
52
- end
53
-
54
- describe ClassContext, 'overridden methods' do
55
- describe 'of loaded class' do
56
- before :each do
57
- @ctx = ClassContext.create(StopContext.new, [0, :Below])
58
- end
59
-
60
- it 'should recognise non-overridden method' do
61
- @ctx.is_overriding_method?('below').should == false
62
- @ctx.is_overriding_method?('above').should == false
63
- end
64
-
65
- it 'should recognise overridden method' do
66
- @ctx.is_overriding_method?('both').should == true
67
- end
68
-
69
- it 'should recognise methods in current codebase' do
70
- ctx = ClassContext.create(StopContext.new, [0, :FeatureEnvy])
71
- ctx.is_overriding_method?('examine_context').should == true
72
- end
73
- end
74
-
75
- describe 'of non-loaded class' do
76
- before :each do
77
- @ctx = ClassContext.create(StopContext.new, [0, :Missing])
78
- end
79
-
80
- it 'should recognise non-overridden method' do
81
- @ctx.is_overriding_method?('below').should == false
82
- @ctx.is_overriding_method?('above').should == false
83
- end
84
-
85
- it 'should recognise overridden method' do
86
- @ctx.is_overriding_method?('both').should == false
87
- end
88
- end
89
- end
90
-
91
- describe 'Integration defect:' do
92
- it 'should not report UtilityFunction for FeatureEnvy#examine_context' do
93
- kelement = ClassContext.create(StopContext.new, [0, :FeatureEnvy, s(:const, :SmellDetector)])
94
- meth = Name.new(:examine_context)
95
- kelement.is_overriding_method?(meth).should == true
96
- melement = MethodContext.new(kelement, [0, :examine_context])
97
- melement.is_overriding_method?(meth).should == true
98
- melement.depends_on_instance?.should == true
99
- end
100
- end
101
-
102
- module Mod1
103
- class Klass1
104
- module Mod2
105
- class Klass2
106
- end
107
- end
108
- end
109
- end
110
-
111
- describe CodeContext, 'find class' do
112
- before :each do
113
- @stop = StopContext.new
114
- @mod1 = ModuleContext.create(@stop, [0, :Mod1])
115
- @klass1 = ClassContext.create(@mod1, [0, :Klass1])
116
- @mod2 = ModuleContext.create(@klass1, [0, :Mod2])
117
- @klass2 = ClassContext.create(@mod2, [0, :Klass2])
118
- end
119
-
120
- describe ModuleContext do
121
- it 'should find local name' do
122
- @mod1.find_module('Klass1').name.should == 'Mod1::Klass1'
123
- @mod2.find_module('Klass2').name.should == 'Mod1::Klass1::Mod2::Klass2'
124
- end
125
-
126
- it 'should not find deeper class' do
127
- @mod1.find_module('Klass2').should == nil
128
- end
129
-
130
- it 'should find own Module' do
131
- @mod1.myself.name.should == 'Mod1'
132
- @mod2.myself.name.should == 'Mod1::Klass1::Mod2'
133
- end
134
- end
135
-
136
- describe ClassContext do
137
- it 'should find local module' do
138
- @klass1.find_module('Mod2').name.should == 'Mod1::Klass1::Mod2'
139
- end
140
-
141
- it 'should not find deeper module' do
142
- @klass1.find_module('Klass2').should == nil
143
- end
144
-
145
- it 'should find own Class' do
146
- @klass1.myself.name.should == 'Mod1::Klass1'
147
- @klass2.myself.name.should == 'Mod1::Klass1::Mod2::Klass2'
148
- end
149
- end
150
- end
151
-
152
- describe ClassContext do
153
- it 'does not report empty class in another module' do
154
- 'class Treetop::Runtime::SyntaxNode; end'.should_not reek
155
- end
156
-
157
- it 'deals with :: scoped names' do
158
- element = ClassContext.create(StopContext.new, [:colon2, [:colon2, [:const, :Treetop], :Runtime], :SyntaxNode])
159
- element.num_methods.should == 0
160
- end
161
- end