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,53 @@
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', 'source', 'reference_collector')
3
+
4
+ include Reek::Source
5
+
6
+ describe ReferenceCollector do
7
+
8
+ context 'counting refs to self' do
9
+ def refs_to_self(src)
10
+ ReferenceCollector.new(src.to_reek_source.syntax_tree).num_refs_to_self
11
+ end
12
+ it 'with no refs to self' do
13
+ refs_to_self('def no_envy(arga) arga.barg end').should == 0
14
+ end
15
+ it 'counts a call to super' do
16
+ refs_to_self('def simple() super; end').should == 1
17
+ end
18
+ it 'counts a local call' do
19
+ refs_to_self('def simple() to_s; end').should == 1
20
+ end
21
+ it 'counts a use of self' do
22
+ refs_to_self('def simple() lv = self; end').should == 1
23
+ end
24
+ it 'counts a call with self as receiver' do
25
+ refs_to_self('def simple() self.to_s; end').should == 1
26
+ end
27
+ it 'counts uses of an ivar' do
28
+ refs_to_self('def no_envy() @item.to_a; @item = 4; @item end').should == 3
29
+ end
30
+ it 'counts an ivar passed to a method' do
31
+ refs_to_self('def no_envy(arga) arga.barg(@item); arga end').should == 1
32
+ end
33
+ it 'ignores global variables' do
34
+ refs_to_self('def no_envy(arga) $s2.to_a; $s2[arga] end').should == 0
35
+ end
36
+ it 'ignores global variables' do
37
+ src = <<EOS
38
+ def accept(t, pat = /.*/nm, &block)
39
+ if pat
40
+ pat.respond_to?(:match) or raise TypeError, "has no `match'"
41
+ else
42
+ pat = t if t.respond_to?(:match)
43
+ end
44
+ unless block
45
+ block = pat.method(:convert).to_proc if pat.respond_to?(:convert)
46
+ end
47
+ @atype[t] = [pat, block]
48
+ end
49
+ EOS
50
+ refs_to_self(src).should == 2
51
+ end
52
+ end
53
+ end
@@ -1,20 +1,19 @@
1
- require File.dirname(__FILE__) + '/../../spec_helper.rb'
2
-
3
- require 'reek/adapters/source'
1
+ require File.join(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__)))), 'spec_helper')
4
2
  require 'stringio'
3
+ require File.join(File.dirname(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__))))), 'lib', 'reek', 'source', 'source_code')
5
4
 
6
- include Reek
5
+ include Reek::Source
7
6
 
8
- describe Source do
7
+ describe SourceCode do
9
8
  context 'when the parser fails' do
10
9
  before :each do
11
10
  @catcher = StringIO.new
12
- @old_err_io = (Source.err_io = @catcher)
11
+ @old_err_io = (SourceCode.err_io = @catcher)
13
12
  parser = mock('parser')
14
13
  @error_message = 'Error message'
15
14
  parser.should_receive(:parse).and_raise(SyntaxError.new(@error_message))
16
15
  @source_name = 'Test source'
17
- @src = Source.new('', @source_name, parser)
16
+ @src = SourceCode.new('', @source_name, parser)
18
17
  end
19
18
  it 'raises a SyntaxError' do
20
19
  @src.syntax_tree
@@ -35,7 +34,7 @@ describe Source do
35
34
  @catcher.string.should match(@error_message)
36
35
  end
37
36
  after :each do
38
- Source.err_io = @old_err_io
37
+ SourceCode.err_io = @old_err_io
39
38
  end
40
39
  end
41
40
  end
@@ -0,0 +1,270 @@
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', 'source', 'tree_dresser')
3
+
4
+ include Reek::Source
5
+
6
+ describe TreeDresser do
7
+ before(:each) do
8
+ @dresser = TreeDresser.new
9
+ end
10
+ it 'maps :if to IfNode' do
11
+ @dresser.extensions_for(:if).should == 'IfNode'
12
+ end
13
+ it 'maps :call to CallNode' do
14
+ @dresser.extensions_for(:call).should == 'CallNode'
15
+ end
16
+ end
17
+
18
+ describe SexpNode do
19
+ context 'format' do
20
+ it 'formats self' do
21
+ @node = s(:self)
22
+ @node.extend(SexpNode)
23
+ @node.format_ruby.should == 'self'
24
+ end
25
+ end
26
+
27
+ context 'hash' do
28
+ it 'hashes equal for equal sexps' do
29
+ node1 = ast(:defn, s(:const2, :Fred, :jim), s(:call, :+, s(:lit, 4), :fred))
30
+ node2 = ast(:defn, s(:const2, :Fred, :jim), s(:call, :+, s(:lit, 4), :fred))
31
+ node1.hash.should == node2.hash
32
+ end
33
+ it 'hashes diferent for diferent sexps' do
34
+ node1 = ast(:defn, s(:const2, :Fred, :jim), s(:call, :+, s(:lit, 4), :fred))
35
+ node2 = ast(:defn, s(:const2, :Fred, :jim), s(:call, :+, s(:lit, 3), :fred))
36
+ node1.hash.should_not == node2.hash
37
+ end
38
+ end
39
+ end
40
+
41
+ describe SexpExtensions::DefnNode do
42
+ context 'with no parameters' do
43
+ before :each do
44
+ @node = s(:defn, :hello, s(:args))
45
+ @node.extend(SexpExtensions::DefnNode)
46
+ end
47
+ it 'has no parameters' do
48
+ @node.parameters.should == s(:args)
49
+ end
50
+ it 'has no parameter names' do
51
+ @node.parameter_names.should == s()
52
+ end
53
+ it 'includes outer scope in its full name' do
54
+ @node.full_name('Fred').should == 'Fred#hello'
55
+ end
56
+ it 'includes no marker in its full name with empty outer scope' do
57
+ @node.full_name('').should == 'hello'
58
+ end
59
+ end
60
+
61
+ context 'with 1 parameter' do
62
+ before :each do
63
+ @node = s(:defn, :hello, s(:args, :param))
64
+ @node.extend(SexpExtensions::DefnNode)
65
+ end
66
+ it 'has 1 parameter' do
67
+ @node.parameters.should == s(:args, :param)
68
+ end
69
+ it 'has 1 parameter name' do
70
+ @node.parameter_names.should == s(:param)
71
+ end
72
+ it 'includes outer scope in its full name' do
73
+ @node.full_name('Fred').should == 'Fred#hello'
74
+ end
75
+ it 'includes no marker in its full name with empty outer scope' do
76
+ @node.full_name('').should == 'hello'
77
+ end
78
+ end
79
+
80
+ context 'with a block' do
81
+ before :each do
82
+ @node = s(:defn, :hello, s(:args, :param, :"&blk"))
83
+ @node.extend(SexpExtensions::DefnNode)
84
+ end
85
+ it 'has 1 parameter' do
86
+ @node.parameters.should == s(:args, :param, :"&blk")
87
+ end
88
+ it 'has 1 parameter name' do
89
+ @node.parameter_names.should == s(:param, :"&blk")
90
+ end
91
+ it 'includes outer scope in its full name' do
92
+ @node.full_name('Fred').should == 'Fred#hello'
93
+ end
94
+ it 'includes no marker in its full name with empty outer scope' do
95
+ @node.full_name('').should == 'hello'
96
+ end
97
+ end
98
+
99
+ context 'with 1 defaulted parameter' do
100
+ before :each do
101
+ @node = s(:defn, :hello, s(:args, :param, s(:block, s(:lasgn, :param, s(:array)))))
102
+ @node.extend(SexpExtensions::DefnNode)
103
+ end
104
+ it 'has 1 parameter' do
105
+ @node.parameters.should == s(:args, :param)
106
+ end
107
+ it 'has 1 parameter name' do
108
+ @node.parameter_names.should == s(:param)
109
+ end
110
+ it 'includes outer scope in its full name' do
111
+ @node.full_name('Fred').should == 'Fred#hello'
112
+ end
113
+ it 'includes no marker in its full name with empty outer scope' do
114
+ @node.full_name('').should == 'hello'
115
+ end
116
+ end
117
+ end
118
+
119
+ describe SexpExtensions::DefsNode do
120
+ context 'with no parameters' do
121
+ before :each do
122
+ @node = s(:defs, :obj, :hello, s(:args))
123
+ @node.extend(SexpExtensions::DefsNode)
124
+ end
125
+ it 'has no parameters' do
126
+ @node.parameters.should == s(:args)
127
+ end
128
+ it 'has no parameter names' do
129
+ @node.parameter_names.should == s()
130
+ end
131
+ it 'includes outer scope in its full name' do
132
+ @node.full_name('Fred').should == 'Fred#obj.hello'
133
+ end
134
+ it 'includes no marker in its full name with empty outer scope' do
135
+ @node.full_name('').should == 'obj.hello'
136
+ end
137
+ end
138
+
139
+ context 'with 1 parameter' do
140
+ before :each do
141
+ @node = s(:defs, :obj, :hello, s(:args, :param))
142
+ @node.extend(SexpExtensions::DefsNode)
143
+ end
144
+ it 'has 1 parameter' do
145
+ @node.parameters.should == s(:args, :param)
146
+ end
147
+ it 'has 1 parameter name' do
148
+ @node.parameter_names.should == s(:param)
149
+ end
150
+ it 'includes outer scope in its full name' do
151
+ @node.full_name('Fred').should == 'Fred#obj.hello'
152
+ end
153
+ it 'includes no marker in its full name with empty outer scope' do
154
+ @node.full_name('').should == 'obj.hello'
155
+ end
156
+ end
157
+
158
+ context 'with a block' do
159
+ before :each do
160
+ @node = s(:defs, :obj, :hello, s(:args, :param, :"&blk"))
161
+ @node.extend(SexpExtensions::DefsNode)
162
+ end
163
+ it 'has 1 parameter' do
164
+ @node.parameters.should == s(:args, :param, :"&blk")
165
+ end
166
+ it 'has 1 parameter name' do
167
+ @node.parameter_names.should == s(:param, :"&blk")
168
+ end
169
+ it 'includes outer scope in its full name' do
170
+ @node.full_name('Fred').should == 'Fred#obj.hello'
171
+ end
172
+ it 'includes no marker in its full name with empty outer scope' do
173
+ @node.full_name('').should == 'obj.hello'
174
+ end
175
+ end
176
+
177
+ context 'with 1 defaulted parameter' do
178
+ before :each do
179
+ @node = s(:defs, :obj, :hello, s(:args, :param, s(:block, s(:lasgn, :param, s(:array)))))
180
+ @node.extend(SexpExtensions::DefsNode)
181
+ end
182
+ it 'has 1 parameter' do
183
+ @node.parameters.should == s(:args, :param)
184
+ end
185
+ it 'has 1 parameter name' do
186
+ @node.parameter_names.should == s(:param)
187
+ end
188
+ it 'includes outer scope in its full name' do
189
+ @node.full_name('Fred').should == 'Fred#obj.hello'
190
+ end
191
+ it 'includes no marker in its full name with empty outer scope' do
192
+ @node.full_name('').should == 'obj.hello'
193
+ end
194
+ end
195
+ end
196
+
197
+ describe SexpExtensions::IterNode do
198
+ context 'with no parameters' do
199
+ before :each do
200
+ @node = s(:iter, s(), nil, s())
201
+ @node.extend(SexpExtensions::IterNode)
202
+ end
203
+ it 'has no parameters' do
204
+ @node.parameters.should == []
205
+ end
206
+ it 'has no parameter names' do
207
+ @node.parameter_names.should == []
208
+ end
209
+ end
210
+
211
+ context 'with 1 parameter' do
212
+ before :each do
213
+ @node = s(:iter, s(), s(:lasgn, :param), s())
214
+ @node.extend(SexpExtensions::IterNode)
215
+ end
216
+ it 'has 1 parameter' do
217
+ @node.parameters.should == s(:lasgn, :param)
218
+ end
219
+ it 'has 1 parameter name' do
220
+ @node.parameter_names.should == s(:param)
221
+ end
222
+ end
223
+
224
+ context 'with 2 parameters' do
225
+ before :each do
226
+ @node = s(:iter, s(), s(:masgn, s(:array, s(:lasgn, :x), s(:lasgn, :y))), s())
227
+ @node.extend(SexpExtensions::IterNode)
228
+ end
229
+ it 'has 1 parameter' do
230
+ @node.parameters.should == s(:masgn, s(:array, s(:lasgn, :x), s(:lasgn, :y)))
231
+ end
232
+ it 'has 1 parameter name' do
233
+ @node.parameter_names.should == [:x, :y]
234
+ end
235
+ end
236
+ end
237
+
238
+ describe SexpExtensions::ModuleNode do
239
+ context 'with a simple name' do
240
+ subject do
241
+ mod = ast(:module, :Fred, nil)
242
+ mod
243
+ end
244
+ its(:name) { should == :Fred }
245
+ its(:simple_name) { should == :Fred }
246
+ its(:text_name) { should == 'Fred' }
247
+ it 'has a simple full_name' do
248
+ subject.full_name('').should == 'Fred'
249
+ end
250
+ it 'has a fq full_name' do
251
+ subject.full_name('Blimey::O::Reilly').should == 'Blimey::O::Reilly::Fred'
252
+ end
253
+ end
254
+
255
+ context 'with a scoped name' do
256
+ subject do
257
+ mod = ast(:module, s(:colon2, s(:const, :Foo), :Bar), nil)
258
+ mod
259
+ end
260
+ its(:name) { should == s(:colon2, s(:const, :Foo), :Bar) }
261
+ its(:simple_name) { should == :Bar }
262
+ its(:text_name) { should == 'Foo::Bar' }
263
+ it 'has a simple full_name' do
264
+ subject.full_name('').should == 'Foo::Bar'
265
+ end
266
+ it 'has a fq full_name' do
267
+ subject.full_name('Blimey::O::Reilly').should == 'Blimey::O::Reilly::Foo::Bar'
268
+ end
269
+ end
270
+ end
@@ -0,0 +1,76 @@
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', 'spec')
3
+
4
+ include Reek
5
+ include Reek::Spec
6
+
7
+ describe ShouldReekOf do
8
+ context 'rdoc demo example' do
9
+ before :each do
10
+ @ruby = 'def double_thing() @other.thing.foo + @other.thing.foo end'
11
+ end
12
+
13
+ it 'reports duplicate calls to @other.thing' do
14
+ @ruby.should reek_of(:Duplication, /@other.thing[^\.]/)
15
+ end
16
+ it 'reports duplicate calls to @other.thing.foo' do
17
+ @ruby.should reek_of(:Duplication, /@other.thing.foo/)
18
+ end
19
+ it 'does not report any feature envy' do
20
+ @ruby.should_not reek_of(:FeatureEnvy)
21
+ end
22
+ end
23
+
24
+ context 'checking code in a string' do
25
+ before :each do
26
+ @clean_code = 'def good() true; end'
27
+ @smelly_code = 'def x() y = 4; end'
28
+ @matcher = ShouldReekOf.new(:UncommunicativeVariableName, [/x/, /y/])
29
+ end
30
+
31
+ it 'matches a smelly String' do
32
+ @matcher.matches?(@smelly_code).should be_true
33
+ end
34
+
35
+ it 'doesnt match a fragrant String' do
36
+ @matcher.matches?(@clean_code).should be_false
37
+ end
38
+
39
+ it 'reports the smells when should_not fails' do
40
+ @matcher.matches?(@smelly_code).should be_true
41
+ @matcher.failure_message_for_should_not.should match('UncommunicativeVariableName')
42
+ end
43
+ end
44
+
45
+ context 'checking code in a Dir' do
46
+ before :each do
47
+ @clean_dir = Dir['spec/samples/three_clean_files/*.rb']
48
+ @smelly_dir = Dir['spec/samples/two_smelly_files/*.rb']
49
+ @matcher = ShouldReekOf.new(:UncommunicativeVariableName, [/Dirty/, /@s/])
50
+ end
51
+
52
+ it 'matches a smelly String' do
53
+ @matcher.matches?(@smelly_dir).should be_true
54
+ end
55
+
56
+ it 'doesnt match a fragrant String' do
57
+ @matcher.matches?(@clean_dir).should be_false
58
+ end
59
+ end
60
+
61
+ context 'checking code in a File' do
62
+ before :each do
63
+ @clean_file = File.new(Dir['spec/samples/three_clean_files/*.rb'][0])
64
+ @smelly_file = File.new(Dir['spec/samples/two_smelly_files/*.rb'][0])
65
+ @matcher = ShouldReekOf.new(:UncommunicativeVariableName, [/Dirty/, /@s/])
66
+ end
67
+
68
+ it 'matches a smelly String' do
69
+ @matcher.matches?(@smelly_file).should be_true
70
+ end
71
+
72
+ it 'doesnt match a fragrant String' do
73
+ @matcher.matches?(@clean_file).should be_false
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,89 @@
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', 'spec')
3
+
4
+ include Reek
5
+ include Reek::Spec
6
+
7
+ describe ShouldReekOnlyOf do
8
+ before :each do
9
+ @expected_smell_class = :NestedIterators
10
+ @expected_context_name = 'SmellyClass#big_method'
11
+ @matcher = ShouldReekOnlyOf.new(@expected_smell_class, [/#{@expected_context_name}/])
12
+ @examiner = mock('examiner', :null_object => true)
13
+ @examiner.should_receive(:smells).and_return {smells}
14
+ @match = @matcher.matches_examiner?(@examiner)
15
+ end
16
+
17
+ shared_examples_for 'no match' do
18
+ it 'does not match' do
19
+ @match.should be_false
20
+ end
21
+ context 'when a match was expected' do
22
+ before :each do
23
+ @source = 'the_path/to_a/source_file.rb'
24
+ @examiner.should_receive(:description).and_return(@source)
25
+ end
26
+ it 'reports the source' do
27
+ @matcher.failure_message_for_should.should match(@source)
28
+ end
29
+ it 'reports the expected smell class' do
30
+ @matcher.failure_message_for_should.should match(@expected_smell_class.to_s)
31
+ end
32
+ end
33
+ end
34
+
35
+ context 'with no smells' do
36
+ def smells
37
+ []
38
+ end
39
+
40
+ it_should_behave_like 'no match'
41
+ end
42
+
43
+ context 'with 1 non-matching smell' do
44
+ def smells
45
+ [SmellWarning.new('ControlCouple', 'context', [1], 'any old message')]
46
+ end
47
+
48
+ it_should_behave_like 'no match'
49
+ end
50
+
51
+ context 'with 2 non-matching smells' do
52
+ def smells
53
+ [
54
+ SmellWarning.new('ControlCouple', 'context', [1], 'any old message'),
55
+ SmellWarning.new('FeatureEnvy', 'context', [1], 'any old message')
56
+ ]
57
+ end
58
+
59
+ it_should_behave_like 'no match'
60
+ end
61
+
62
+ context 'with 1 non-matching and 1 matching smell' do
63
+ def smells
64
+ [
65
+ SmellWarning.new('ControlCouple', 'context', [1], 'any old message'),
66
+ SmellWarning.new(@expected_smell_class.to_s, 'context', [1], "message mentioning #{@expected_context_name}")
67
+ ]
68
+ end
69
+
70
+ it_should_behave_like 'no match'
71
+ end
72
+
73
+ context 'with 1 matching smell' do
74
+ def smells
75
+ [SmellWarning.new(@expected_smell_class.to_s, nil, [1], "message mentioning #{@expected_context_name}")]
76
+ end
77
+ it 'matches' do
78
+ @match.should be_true
79
+ end
80
+ it 'reports the expected smell when no match was expected' do
81
+ @matcher.failure_message_for_should_not.should match(@expected_smell_class.to_s)
82
+ end
83
+ it 'reports the source when no match was expected' do
84
+ source = 'the_path/to_a/source_file.rb'
85
+ @examiner.should_receive(:description).and_return(source)
86
+ @matcher.failure_message_for_should_not.should match(source)
87
+ end
88
+ end
89
+ end
@@ -1,7 +1,5 @@
1
- require File.dirname(__FILE__) + '/../../spec_helper.rb'
2
-
3
- require 'reek/adapters/report'
4
- require 'reek/adapters/spec'
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', 'spec')
5
3
 
6
4
  include Reek
7
5
  include Reek::Spec
@@ -22,8 +20,8 @@ describe ShouldReek, 'checking code in a string' do
22
20
  end
23
21
 
24
22
  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(QuietReport.new(@smelly_code.sniff).report)
23
+ @matcher.matches?(@smelly_code)
24
+ @matcher.failure_message_for_should_not.should match('UncommunicativeName')
27
25
  end
28
26
  end
29
27
 
@@ -43,8 +41,8 @@ describe ShouldReek, 'checking code in a Dir' do
43
41
  end
44
42
 
45
43
  it 'reports the smells when should_not fails' do
46
- @matcher.matches?(@smelly_dir).should be_true
47
- @matcher.failure_message_for_should_not.should include(QuietReport.new(@smelly_dir.sniff.sniffers).report)
44
+ @matcher.matches?(@smelly_dir)
45
+ @matcher.failure_message_for_should_not.should match('UncommunicativeName')
48
46
  end
49
47
  end
50
48
 
@@ -64,29 +62,7 @@ describe ShouldReek, 'checking code in a File' do
64
62
  end
65
63
 
66
64
  it 'reports the smells when should_not fails' do
67
- @matcher.matches?(@smelly_file).should be_true
68
- @matcher.failure_message_for_should_not.should include(QuietReport.new(@smelly_file.sniff).report)
69
- end
70
- end
71
-
72
- describe ShouldReek, 'report formatting' do
73
- before :each do
74
- sn_clean = 'def clean() @thing = 4; end'.sniff
75
- sn_dirty = 'def dirty() thing.cool + thing.cool; end'.sniff
76
- sniffers = SnifferSet.new([sn_clean, sn_dirty], '')
77
- @matcher = ShouldReek.new
78
- @matcher.matches?(sniffers)
79
- @lines = @matcher.failure_message_for_should_not.split("\n").map {|str| str.chomp}
80
- @error_message = @lines.shift
81
- @smells = @lines.grep(/^ /)
82
- @headers = (@lines - @smells)
83
- end
84
-
85
- it 'mentions every smell in the report' do
86
- @smells.should have(2).warnings
87
- end
88
-
89
- it 'doesnt mention the clean files' do
90
- @headers.should have(1).headers
65
+ @matcher.matches?(@smelly_file)
66
+ @matcher.failure_message_for_should_not.should match('UncommunicativeName')
91
67
  end
92
68
  end
@@ -1,3 +1,4 @@
1
+ # clean class for testing purposes
1
2
  class Clean
2
3
  def assign
3
4
  puts @sub.title
@@ -1,3 +1,4 @@
1
+ # smelly class for testing purposes
1
2
  class Dirty
2
3
  def a
3
4
  puts @s.title
@@ -1,5 +1,9 @@
1
1
  ---
2
2
  Duplication:
3
3
  enabled: false
4
- UncommunicativeName:
4
+ UncommunicativeVariableName:
5
+ enabled: false
6
+ UncommunicativeMethodName:
7
+ enabled: false
8
+ UncommunicativeParameterName:
5
9
  enabled: false
@@ -1,3 +1,4 @@
1
+ # clean class for testing purposes
1
2
  class Clean
2
3
  def assign
3
4
  puts @sub.title
@@ -1,3 +1,4 @@
1
+ # clean class for testing purposes
1
2
  class Clean
2
3
  def assign
3
4
  puts @sub.title
@@ -1,3 +1,4 @@
1
+ # clean class for testing purposes
1
2
  class Clean
2
3
  def assign
3
4
  puts @sub.title
@@ -1,7 +1,7 @@
1
1
  class Dirty
2
2
  def a
3
3
  puts @s.title
4
- @s.map {|x| x.each {|key| key += 3}}
4
+ @s = fred.map {|x| x.each {|key| key += 3}}
5
5
  puts @s.title
6
6
  end
7
7
  end
@@ -1,7 +1,7 @@
1
1
  class Dirty
2
2
  def a
3
3
  puts @s.title
4
- @s.map {|x| x.each {|key| key += 3}}
4
+ @s = fred.map {|x| x.each {|key| key += 3}}
5
5
  puts @s.title
6
6
  end
7
7
  end
@@ -1,7 +1,11 @@
1
1
  ---
2
2
  Duplication:
3
3
  enabled: false
4
+ IrresponsibleModule:
5
+ enabled: false
4
6
  NestedIterators:
5
7
  enabled: false
6
- UncommunicativeName:
8
+ UncommunicativeVariableName:
9
+ enabled: false
10
+ UncommunicativeMethodName:
7
11
  enabled: false
@@ -0,0 +1,3 @@
1
+ ---
2
+ Duplication:
3
+ enabled: false
@@ -0,0 +1,3 @@
1
+ ---
2
+ NestedIterators:
3
+ max_allowed_nesting: 3
@@ -1,7 +1,7 @@
1
1
  class Dirty
2
2
  def a
3
3
  puts @s.title
4
- @s.map {|x| x.each {|key| key += 3}}
4
+ @s = fred.map {|x| x.each {|key| key += 3}}
5
5
  puts @s.title
6
6
  end
7
7
  end