reek 1.1.3 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. data/History.txt +44 -4
  2. data/License.txt +20 -0
  3. data/README.rdoc +83 -0
  4. data/Rakefile +0 -1
  5. data/bin/reek +3 -11
  6. data/config/defaults.reek +20 -1
  7. data/features/masking_smells.feature +111 -0
  8. data/features/options.feature +49 -0
  9. data/features/reports.feature +90 -0
  10. data/features/samples.feature +284 -0
  11. data/features/stdin.feature +43 -0
  12. data/features/step_definitions/reek_steps.rb +35 -0
  13. data/features/support/env.rb +38 -0
  14. data/lib/reek.rb +1 -1
  15. data/lib/reek/adapters/application.rb +47 -0
  16. data/lib/reek/adapters/config_file.rb +31 -0
  17. data/lib/reek/adapters/core_extras.rb +72 -0
  18. data/lib/reek/{object_source.rb → adapters/object_source.rb} +15 -19
  19. data/lib/reek/{rake_task.rb → adapters/rake_task.rb} +2 -2
  20. data/lib/reek/adapters/report.rb +91 -0
  21. data/lib/reek/adapters/source.rb +53 -0
  22. data/lib/reek/{spec.rb → adapters/spec.rb} +45 -60
  23. data/lib/reek/block_context.rb +1 -1
  24. data/lib/reek/class_context.rb +26 -6
  25. data/lib/reek/code_context.rb +8 -0
  26. data/lib/reek/code_parser.rb +82 -39
  27. data/lib/reek/command_line.rb +85 -0
  28. data/lib/reek/configuration.rb +51 -0
  29. data/lib/reek/detector_stack.rb +39 -0
  30. data/lib/reek/exceptions.reek +8 -1
  31. data/lib/reek/method_context.rb +53 -11
  32. data/lib/reek/module_context.rb +1 -2
  33. data/lib/reek/name.rb +8 -2
  34. data/lib/reek/sexp_formatter.rb +2 -0
  35. data/lib/reek/smell_warning.rb +26 -8
  36. data/lib/reek/smells/control_couple.rb +8 -4
  37. data/lib/reek/smells/data_clump.rb +88 -0
  38. data/lib/reek/smells/duplication.rb +11 -9
  39. data/lib/reek/smells/feature_envy.rb +3 -4
  40. data/lib/reek/smells/large_class.rb +17 -17
  41. data/lib/reek/smells/long_method.rb +10 -8
  42. data/lib/reek/smells/long_parameter_list.rb +16 -10
  43. data/lib/reek/smells/long_yield_list.rb +1 -1
  44. data/lib/reek/smells/nested_iterators.rb +3 -3
  45. data/lib/reek/smells/simulated_polymorphism.rb +58 -0
  46. data/lib/reek/smells/smell_detector.rb +94 -27
  47. data/lib/reek/smells/uncommunicative_name.rb +23 -23
  48. data/lib/reek/smells/utility_function.rb +27 -11
  49. data/lib/reek/sniffer.rb +183 -0
  50. data/reek.gemspec +5 -5
  51. data/spec/quality/reek_source_spec.rb +15 -0
  52. data/spec/reek/adapters/report_spec.rb +49 -0
  53. data/spec/reek/adapters/should_reek_of_spec.rb +108 -0
  54. data/spec/reek/adapters/should_reek_only_of_spec.rb +87 -0
  55. data/spec/reek/adapters/should_reek_spec.rb +92 -0
  56. data/spec/reek/block_context_spec.rb +7 -1
  57. data/spec/reek/class_context_spec.rb +39 -16
  58. data/spec/reek/code_context_spec.rb +7 -7
  59. data/spec/reek/code_parser_spec.rb +6 -1
  60. data/spec/reek/config_spec.rb +3 -3
  61. data/spec/reek/configuration_spec.rb +12 -0
  62. data/spec/reek/method_context_spec.rb +2 -2
  63. data/spec/reek/name_spec.rb +24 -0
  64. data/spec/reek/object_source_spec.rb +23 -0
  65. data/spec/reek/singleton_method_context_spec.rb +2 -2
  66. data/spec/reek/smell_warning_spec.rb +53 -0
  67. data/spec/reek/smells/data_clump_spec.rb +87 -0
  68. data/spec/reek/smells/duplication_spec.rb +13 -17
  69. data/spec/reek/smells/feature_envy_spec.rb +23 -28
  70. data/spec/reek/smells/large_class_spec.rb +109 -34
  71. data/spec/reek/smells/long_method_spec.rb +140 -3
  72. data/spec/reek/smells/long_parameter_list_spec.rb +1 -2
  73. data/spec/reek/smells/simulated_polymorphism_spec.rb +50 -0
  74. data/spec/reek/smells/smell_detector_spec.rb +53 -0
  75. data/spec/reek/smells/uncommunicative_name_spec.rb +20 -7
  76. data/spec/reek/smells/utility_function_spec.rb +76 -67
  77. data/spec/reek/sniffer_spec.rb +10 -0
  78. data/spec/samples/all_but_one_masked/clean_one.rb +6 -0
  79. data/spec/samples/all_but_one_masked/dirty.rb +7 -0
  80. data/spec/samples/all_but_one_masked/masked.reek +5 -0
  81. data/spec/samples/clean_due_to_masking/clean_one.rb +6 -0
  82. data/spec/samples/clean_due_to_masking/clean_three.rb +6 -0
  83. data/spec/samples/clean_due_to_masking/clean_two.rb +6 -0
  84. data/spec/samples/clean_due_to_masking/dirty_one.rb +7 -0
  85. data/spec/samples/clean_due_to_masking/dirty_two.rb +7 -0
  86. data/spec/samples/clean_due_to_masking/masked.reek +7 -0
  87. data/spec/samples/corrupt_config_file/corrupt.reek +1 -0
  88. data/spec/samples/corrupt_config_file/dirty.rb +7 -0
  89. data/spec/samples/empty_config_file/dirty.rb +7 -0
  90. data/spec/samples/empty_config_file/empty.reek +0 -0
  91. data/spec/samples/exceptions.reek +4 -0
  92. data/spec/{slow/samples → samples}/inline.rb +0 -0
  93. data/spec/samples/masked/dirty.rb +7 -0
  94. data/spec/samples/masked/masked.reek +3 -0
  95. data/spec/samples/mixed_results/clean_one.rb +6 -0
  96. data/spec/samples/mixed_results/clean_three.rb +6 -0
  97. data/spec/samples/mixed_results/clean_two.rb +6 -0
  98. data/spec/samples/mixed_results/dirty_one.rb +7 -0
  99. data/spec/samples/mixed_results/dirty_two.rb +7 -0
  100. data/spec/samples/not_quite_masked/dirty.rb +8 -0
  101. data/spec/samples/not_quite_masked/masked.reek +5 -0
  102. data/spec/{slow/samples → samples}/optparse.rb +0 -0
  103. data/spec/samples/overrides/masked/dirty.rb +7 -0
  104. data/spec/samples/overrides/masked/lower.reek +5 -0
  105. data/spec/samples/overrides/upper.reek +5 -0
  106. data/spec/{slow/samples → samples}/redcloth.rb +0 -0
  107. data/spec/samples/three_clean_files/clean_one.rb +6 -0
  108. data/spec/samples/three_clean_files/clean_three.rb +6 -0
  109. data/spec/samples/three_clean_files/clean_two.rb +6 -0
  110. data/spec/samples/two_smelly_files/dirty_one.rb +7 -0
  111. data/spec/samples/two_smelly_files/dirty_two.rb +7 -0
  112. data/spec/spec.opts +1 -1
  113. data/spec/spec_helper.rb +4 -4
  114. data/tasks/reek.rake +8 -5
  115. data/tasks/test.rake +51 -0
  116. metadata +75 -25
  117. data/README.txt +0 -6
  118. data/lib/reek/options.rb +0 -92
  119. data/lib/reek/report.rb +0 -81
  120. data/lib/reek/smells/smells.rb +0 -81
  121. data/lib/reek/source.rb +0 -127
  122. data/spec/reek/options_spec.rb +0 -13
  123. data/spec/reek/report_spec.rb +0 -48
  124. data/spec/reek/smells/smell_spec.rb +0 -24
  125. data/spec/slow/inline_spec.rb +0 -43
  126. data/spec/slow/optparse_spec.rb +0 -108
  127. data/spec/slow/redcloth_spec.rb +0 -101
  128. data/spec/slow/reek_source_spec.rb +0 -20
  129. data/spec/slow/script_spec.rb +0 -55
  130. data/spec/slow/source_list_spec.rb +0 -40
  131. data/tasks/rspec.rake +0 -21
@@ -0,0 +1,183 @@
1
+ require 'reek/detector_stack'
2
+
3
+ # SMELL: Duplication -- all these should be found automagically
4
+ require 'reek/smells/control_couple'
5
+ require 'reek/smells/data_clump'
6
+ require 'reek/smells/duplication'
7
+ require 'reek/smells/feature_envy'
8
+ require 'reek/smells/large_class'
9
+ require 'reek/smells/long_method'
10
+ require 'reek/smells/long_parameter_list'
11
+ require 'reek/smells/long_yield_list'
12
+ require 'reek/smells/nested_iterators'
13
+ require 'reek/smells/simulated_polymorphism'
14
+ require 'reek/smells/uncommunicative_name'
15
+ require 'reek/smells/utility_function'
16
+ require 'reek/code_parser'
17
+ require 'yaml'
18
+
19
+ class Hash
20
+ def push_keys(hash)
21
+ keys.each {|key| hash[key].adopt!(self[key]) }
22
+ end
23
+
24
+ def adopt!(other)
25
+ other.keys.each do |key|
26
+ ov = other[key]
27
+ if Array === ov and has_key?(key)
28
+ self[key] += ov
29
+ else
30
+ self[key] = ov
31
+ end
32
+ end
33
+ self
34
+ end
35
+
36
+ def adopt(other)
37
+ self.deep_copy.adopt!(other)
38
+ end
39
+
40
+ def deep_copy
41
+ YAML::load(YAML::dump(self))
42
+ end
43
+ end
44
+
45
+ module Reek
46
+ class Sniffer
47
+
48
+ def self.smell_classes
49
+ # SMELL: Duplication -- these should be loaded by listing the files
50
+ [
51
+ Smells::ControlCouple,
52
+ Smells::DataClump,
53
+ Smells::Duplication,
54
+ Smells::FeatureEnvy,
55
+ Smells::LargeClass,
56
+ Smells::LongMethod,
57
+ Smells::LongParameterList,
58
+ Smells::LongYieldList,
59
+ Smells::NestedIterators,
60
+ Smells::SimulatedPolymorphism,
61
+ Smells::UncommunicativeName,
62
+ Smells::UtilityFunction,
63
+ ]
64
+ end
65
+
66
+ def initialize(src)
67
+ @already_checked_for_smells = false
68
+ @typed_detectors = nil
69
+ @detectors = Hash.new
70
+ Sniffer.smell_classes.each { |klass| @detectors[klass] = DetectorStack.new(klass.new) }
71
+ @source = src
72
+ src.configure(self)
73
+ end
74
+
75
+ def check_for_smells
76
+ return if @already_checked_for_smells
77
+ CodeParser.new(self).process(@source.syntax_tree)
78
+ @already_checked_for_smells = true
79
+ end
80
+
81
+ def configure(klass, config)
82
+ @detectors[klass].push(config)
83
+ end
84
+
85
+ def report_on(report)
86
+ check_for_smells
87
+ @detectors.each_value { |stack| stack.report_on(report) }
88
+ end
89
+
90
+ def examine(scope, type)
91
+ listeners = smell_listeners[type]
92
+ listeners.each {|smell| smell.examine(scope) } if listeners
93
+ end
94
+
95
+ def smelly?
96
+ check_for_smells
97
+ @detectors.each_value { |stack| return true if stack.smelly? }
98
+ false
99
+ end
100
+
101
+ def num_smells
102
+ check_for_smells
103
+ total = 0
104
+ @detectors.each_value { |stack| total += stack.num_smells }
105
+ total
106
+ end
107
+
108
+ def desc
109
+ # SMELL: Special Case
110
+ # Only used in the Report tests, because they don't always create a Source.
111
+ @source ? @source.desc : "unknown"
112
+ end
113
+
114
+ #
115
+ # Checks for instances of +smell_class+, and returns +true+
116
+ # only if one of them has a report string matching all of the +patterns+.
117
+ #
118
+ def has_smell?(smell_class, patterns=[])
119
+ check_for_smells
120
+ stack = @detectors[Reek::Smells.const_get(smell_class)] # SMELL: Duplication of code in ConfigFile
121
+ stack.has_smell?(patterns)
122
+ end
123
+
124
+ def smells_only_of?(klass, patterns)
125
+ num_smells == 1 and has_smell?(klass, patterns)
126
+ end
127
+
128
+ def sniff
129
+ self
130
+ end
131
+
132
+ def sniffers
133
+ [self]
134
+ end
135
+
136
+ private
137
+
138
+ def smell_listeners()
139
+ unless @typed_detectors
140
+ @typed_detectors = Hash.new {|hash,key| hash[key] = [] }
141
+ @detectors.each_value { |stack| stack.listen_to(@typed_detectors) }
142
+ end
143
+ @typed_detectors
144
+ end
145
+ end
146
+
147
+ class SnifferSet
148
+
149
+ attr_reader :desc, :sniffers
150
+
151
+ def initialize(sniffers, desc)
152
+ @sniffers = sniffers
153
+ @desc = desc
154
+ end
155
+
156
+ def smelly?
157
+ @sniffers.any? {|sniffer| sniffer.smelly? }
158
+ end
159
+
160
+ #
161
+ # Checks for instances of +smell_class+, and returns +true+
162
+ # only if one of them has a report string matching all of the +patterns+.
163
+ #
164
+ def has_smell?(smell_class, patterns=[])
165
+ @sniffers.any? {|sniffer| sniffer.has_smell?(smell_class, patterns)}
166
+ end
167
+
168
+ def num_smells
169
+ total = 0
170
+ @sniffers.each {|sniffer| total += sniffer.num_smells}
171
+ total
172
+ end
173
+
174
+ def smells_only_of?(klass, patterns)
175
+ num_smells == 1 and has_smell?(klass, patterns)
176
+ end
177
+
178
+ def sniff
179
+ self
180
+ end
181
+
182
+ end
183
+ end
data/reek.gemspec CHANGED
@@ -2,17 +2,17 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{reek}
5
- s.version = "1.1.3"
5
+ s.version = "1.2.0"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Kevin Rutherford"]
9
- s.date = %q{2009-05-19}
9
+ s.date = %q{2009-09-20}
10
10
  s.default_executable = %q{reek}
11
11
  s.description = %q{Code smell detector for Ruby}
12
12
  s.email = ["kevin@rutherford-software.com"]
13
13
  s.executables = ["reek"]
14
- s.extra_rdoc_files = ["History.txt", "README.txt"]
15
- s.files = ["History.txt", "README.txt", "Rakefile", "bin/reek", "config/defaults.reek", "lib/reek.rb", "lib/reek/block_context.rb", "lib/reek/class_context.rb", "lib/reek/code_context.rb", "lib/reek/code_parser.rb", "lib/reek/exceptions.reek", "lib/reek/if_context.rb", "lib/reek/method_context.rb", "lib/reek/module_context.rb", "lib/reek/name.rb", "lib/reek/object_refs.rb", "lib/reek/object_source.rb", "lib/reek/options.rb", "lib/reek/rake_task.rb", "lib/reek/report.rb", "lib/reek/sexp_formatter.rb", "lib/reek/singleton_method_context.rb", "lib/reek/smell_warning.rb", "lib/reek/smells/control_couple.rb", "lib/reek/smells/duplication.rb", "lib/reek/smells/feature_envy.rb", "lib/reek/smells/large_class.rb", "lib/reek/smells/long_method.rb", "lib/reek/smells/long_parameter_list.rb", "lib/reek/smells/long_yield_list.rb", "lib/reek/smells/nested_iterators.rb", "lib/reek/smells/smell_detector.rb", "lib/reek/smells/smells.rb", "lib/reek/smells/uncommunicative_name.rb", "lib/reek/smells/utility_function.rb", "lib/reek/source.rb", "lib/reek/spec.rb", "lib/reek/stop_context.rb", "lib/reek/yield_call_context.rb", "reek.gemspec", "spec/reek/block_context_spec.rb", "spec/reek/class_context_spec.rb", "spec/reek/code_context_spec.rb", "spec/reek/code_parser_spec.rb", "spec/reek/config_spec.rb", "spec/reek/if_context_spec.rb", "spec/reek/method_context_spec.rb", "spec/reek/module_context_spec.rb", "spec/reek/name_spec.rb", "spec/reek/object_refs_spec.rb", "spec/reek/options_spec.rb", "spec/reek/report_spec.rb", "spec/reek/singleton_method_context_spec.rb", "spec/reek/smells/control_couple_spec.rb", "spec/reek/smells/duplication_spec.rb", "spec/reek/smells/feature_envy_spec.rb", "spec/reek/smells/large_class_spec.rb", "spec/reek/smells/long_method_spec.rb", "spec/reek/smells/long_parameter_list_spec.rb", "spec/reek/smells/nested_iterators_spec.rb", "spec/reek/smells/smell_spec.rb", "spec/reek/smells/uncommunicative_name_spec.rb", "spec/reek/smells/utility_function_spec.rb", "spec/slow/inline_spec.rb", "spec/slow/optparse_spec.rb", "spec/slow/redcloth_spec.rb", "spec/slow/reek_source_spec.rb", "spec/slow/samples/inline.rb", "spec/slow/samples/optparse.rb", "spec/slow/samples/redcloth.rb", "spec/slow/script_spec.rb", "spec/slow/source_list_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "tasks/reek.rake", "tasks/rspec.rake"]
14
+ s.extra_rdoc_files = ["History.txt", "License.txt", "README.rdoc"]
15
+ s.files = ["History.txt", "License.txt", "README.rdoc", "Rakefile", "bin/reek", "config/defaults.reek", "features/masking_smells.feature", "features/options.feature", "features/reports.feature", "features/samples.feature", "features/stdin.feature", "features/step_definitions/reek_steps.rb", "features/support/env.rb", "lib/reek.rb", "lib/reek/adapters/application.rb", "lib/reek/adapters/config_file.rb", "lib/reek/adapters/core_extras.rb", "lib/reek/adapters/object_source.rb", "lib/reek/adapters/rake_task.rb", "lib/reek/adapters/report.rb", "lib/reek/adapters/source.rb", "lib/reek/adapters/spec.rb", "lib/reek/block_context.rb", "lib/reek/class_context.rb", "lib/reek/code_context.rb", "lib/reek/code_parser.rb", "lib/reek/command_line.rb", "lib/reek/configuration.rb", "lib/reek/detector_stack.rb", "lib/reek/exceptions.reek", "lib/reek/if_context.rb", "lib/reek/method_context.rb", "lib/reek/module_context.rb", "lib/reek/name.rb", "lib/reek/object_refs.rb", "lib/reek/sexp_formatter.rb", "lib/reek/singleton_method_context.rb", "lib/reek/smell_warning.rb", "lib/reek/smells/control_couple.rb", "lib/reek/smells/data_clump.rb", "lib/reek/smells/duplication.rb", "lib/reek/smells/feature_envy.rb", "lib/reek/smells/large_class.rb", "lib/reek/smells/long_method.rb", "lib/reek/smells/long_parameter_list.rb", "lib/reek/smells/long_yield_list.rb", "lib/reek/smells/nested_iterators.rb", "lib/reek/smells/simulated_polymorphism.rb", "lib/reek/smells/smell_detector.rb", "lib/reek/smells/uncommunicative_name.rb", "lib/reek/smells/utility_function.rb", "lib/reek/sniffer.rb", "lib/reek/stop_context.rb", "lib/reek/yield_call_context.rb", "reek.gemspec", "spec/quality/reek_source_spec.rb", "spec/reek/adapters/report_spec.rb", "spec/reek/adapters/should_reek_of_spec.rb", "spec/reek/adapters/should_reek_only_of_spec.rb", "spec/reek/adapters/should_reek_spec.rb", "spec/reek/block_context_spec.rb", "spec/reek/class_context_spec.rb", "spec/reek/code_context_spec.rb", "spec/reek/code_parser_spec.rb", "spec/reek/config_spec.rb", "spec/reek/configuration_spec.rb", "spec/reek/if_context_spec.rb", "spec/reek/method_context_spec.rb", "spec/reek/module_context_spec.rb", "spec/reek/name_spec.rb", "spec/reek/object_refs_spec.rb", "spec/reek/object_source_spec.rb", "spec/reek/singleton_method_context_spec.rb", "spec/reek/smell_warning_spec.rb", "spec/reek/smells/control_couple_spec.rb", "spec/reek/smells/data_clump_spec.rb", "spec/reek/smells/duplication_spec.rb", "spec/reek/smells/feature_envy_spec.rb", "spec/reek/smells/large_class_spec.rb", "spec/reek/smells/long_method_spec.rb", "spec/reek/smells/long_parameter_list_spec.rb", "spec/reek/smells/nested_iterators_spec.rb", "spec/reek/smells/simulated_polymorphism_spec.rb", "spec/reek/smells/smell_detector_spec.rb", "spec/reek/smells/uncommunicative_name_spec.rb", "spec/reek/smells/utility_function_spec.rb", "spec/reek/sniffer_spec.rb", "spec/samples/all_but_one_masked/clean_one.rb", "spec/samples/all_but_one_masked/dirty.rb", "spec/samples/all_but_one_masked/masked.reek", "spec/samples/clean_due_to_masking/clean_one.rb", "spec/samples/clean_due_to_masking/clean_three.rb", "spec/samples/clean_due_to_masking/clean_two.rb", "spec/samples/clean_due_to_masking/dirty_one.rb", "spec/samples/clean_due_to_masking/dirty_two.rb", "spec/samples/clean_due_to_masking/masked.reek", "spec/samples/corrupt_config_file/corrupt.reek", "spec/samples/corrupt_config_file/dirty.rb", "spec/samples/empty_config_file/dirty.rb", "spec/samples/empty_config_file/empty.reek", "spec/samples/exceptions.reek", "spec/samples/inline.rb", "spec/samples/masked/dirty.rb", "spec/samples/masked/masked.reek", "spec/samples/mixed_results/clean_one.rb", "spec/samples/mixed_results/clean_three.rb", "spec/samples/mixed_results/clean_two.rb", "spec/samples/mixed_results/dirty_one.rb", "spec/samples/mixed_results/dirty_two.rb", "spec/samples/not_quite_masked/dirty.rb", "spec/samples/not_quite_masked/masked.reek", "spec/samples/optparse.rb", "spec/samples/overrides/masked/dirty.rb", "spec/samples/overrides/masked/lower.reek", "spec/samples/overrides/upper.reek", "spec/samples/redcloth.rb", "spec/samples/three_clean_files/clean_one.rb", "spec/samples/three_clean_files/clean_three.rb", "spec/samples/three_clean_files/clean_two.rb", "spec/samples/two_smelly_files/dirty_one.rb", "spec/samples/two_smelly_files/dirty_two.rb", "spec/spec.opts", "spec/spec_helper.rb", "tasks/reek.rake", "tasks/test.rake"]
16
16
  s.homepage = %q{http://wiki.github.com/kevinrutherford/reek}
17
17
  s.post_install_message = %q{
18
18
  For more information on reek, see http://wiki.github.com/kevinrutherford/reek
@@ -20,7 +20,7 @@ For more information on reek, see http://wiki.github.com/kevinrutherford/reek
20
20
  s.rdoc_options = ["--main", "README.txt"]
21
21
  s.require_paths = ["lib"]
22
22
  s.rubyforge_project = %q{reek}
23
- s.rubygems_version = %q{1.3.3}
23
+ s.rubygems_version = %q{1.3.5}
24
24
  s.summary = %q{Code smell detector for Ruby}
25
25
 
26
26
  if s.respond_to? :specification_version then
@@ -0,0 +1,15 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ describe 'Reek source code' do
4
+ it 'has no smells' do
5
+ Dir['lib/**/*.rb'].should_not reek
6
+ end
7
+
8
+ nucleus = Dir['lib/reek/**.rb'] - Dir['lib/reek/adapters/**/*.rb']
9
+ nucleus.each do |src|
10
+ it "#{src} contains no references from the nucleus out to the adapters" do
11
+ IO.readlines(src).grep(/adapters/).should be_empty
12
+ end
13
+ end
14
+
15
+ end
@@ -0,0 +1,49 @@
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)
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)
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
32
+
33
+ describe ReportSection, " as a SortedSet" do
34
+ it 'should only add a smell once' do
35
+ rpt = ReportSection.new(''.sniff)
36
+ rpt << SmellWarning.new(Smells::FeatureEnvy.new, "self", 'too many!', false)
37
+ rpt << SmellWarning.new(Smells::FeatureEnvy.new, "self", 'too many!', false)
38
+ lines = rpt.smell_list.split("\n")
39
+ lines.should have(1).lines
40
+ end
41
+
42
+ it 'should not count an identical masked smell' do
43
+ rpt = ReportSection.new(''.sniff)
44
+ # SMELL: Duplication -- the SmellWarning knows whether to call << or record_masked_smell
45
+ rpt << SmellWarning.new(Smells::FeatureEnvy.new, "self", 'too many!', false)
46
+ rpt.record_masked_smell(SmellWarning.new(Smells::FeatureEnvy.new, "self", 'too many!', true))
47
+ rpt.header.should == 'string -- 1 warning'
48
+ end
49
+ end
@@ -0,0 +1,108 @@
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 ShouldReekOf, 'rdoc demo example' do
10
+ it 'works on a common source' do
11
+ ruby = 'def double_thing() @other.thing.foo + @other.thing.foo end'
12
+ ruby.should reek_of(:Duplication, /@other.thing[^\.]/)
13
+ ruby.should reek_of(:Duplication, /@other.thing.foo/)
14
+ ruby.should_not reek_of(:FeatureEnvy)
15
+ end
16
+
17
+ it 'works on a common sniffer' do
18
+ ruby = 'def double_thing() @other.thing.foo + @other.thing.foo end'.sniff
19
+ ruby.should reek_of(:Duplication, /@other.thing[^\.]/)
20
+ ruby.should reek_of(:Duplication, /@other.thing.foo/)
21
+ ruby.should_not reek_of(:FeatureEnvy)
22
+ end
23
+ end
24
+
25
+ describe ShouldReekOf, 'checking code in a string' do
26
+ before :each do
27
+ @clean_code = 'def good() true; end'
28
+ @smelly_code = 'def x() y = 4; end'
29
+ @matcher = ShouldReekOf.new(:UncommunicativeName, [/x/, /y/])
30
+ end
31
+
32
+ it 'matches a smelly String' do
33
+ @matcher.matches?(@smelly_code).should be_true
34
+ end
35
+
36
+ it 'doesnt match a fragrant String' do
37
+ @matcher.matches?(@clean_code).should be_false
38
+ end
39
+
40
+ it 'reports the smells when should_not fails' do
41
+ @matcher.matches?(@smelly_code).should be_true
42
+ @matcher.failure_message_for_should_not.should include(Report.new(@smelly_code.sniff).quiet_report)
43
+ end
44
+ end
45
+
46
+ describe ShouldReekOf, 'checking code in a Dir' do
47
+ before :each do
48
+ @clean_dir = Dir['spec/samples/three_clean_files/*.rb']
49
+ @smelly_dir = Dir['spec/samples/two_smelly_files/*.rb']
50
+ @matcher = ShouldReekOf.new(:UncommunicativeName, [/Dirty/, /@s/])
51
+ end
52
+
53
+ it 'matches a smelly String' do
54
+ @matcher.matches?(@smelly_dir).should be_true
55
+ end
56
+
57
+ it 'doesnt match a fragrant String' do
58
+ @matcher.matches?(@clean_dir).should be_false
59
+ end
60
+
61
+ it 'reports the smells when should_not fails' do
62
+ @matcher.matches?(@smelly_dir).should be_true
63
+ @matcher.failure_message_for_should_not.should include(Report.new(@smelly_dir.sniff.sniffers).quiet_report)
64
+ end
65
+ end
66
+
67
+ describe ShouldReekOf, 'checking code in a File' do
68
+ before :each do
69
+ @clean_file = File.new(Dir['spec/samples/three_clean_files/*.rb'][0])
70
+ @smelly_file = File.new(Dir['spec/samples/two_smelly_files/*.rb'][0])
71
+ @matcher = ShouldReekOf.new(:UncommunicativeName, [/Dirty/, /@s/])
72
+ end
73
+
74
+ it 'matches a smelly String' do
75
+ @matcher.matches?(@smelly_file).should be_true
76
+ end
77
+
78
+ it 'doesnt match a fragrant String' do
79
+ @matcher.matches?(@clean_file).should be_false
80
+ end
81
+
82
+ it 'reports the smells when should_not fails' do
83
+ @matcher.matches?(@smelly_file).should be_true
84
+ @matcher.failure_message_for_should_not.should include(Report.new(@smelly_file.sniff).quiet_report)
85
+ end
86
+ end
87
+
88
+ describe ShouldReekOf, 'report formatting' do
89
+ before :each do
90
+ sn_clean = 'def clean() @thing = 4; end'.sniff
91
+ sn_dirty = 'def dirty() thing.cool + thing.cool; end'.sniff
92
+ sniffers = SnifferSet.new([sn_clean, sn_dirty], '')
93
+ @matcher = ShouldReekOf.new(:UncommunicativeName, [/Dirty/, /@s/])
94
+ @matcher.matches?(sniffers)
95
+ @lines = @matcher.failure_message_for_should_not.split("\n").map {|str| str.chomp}
96
+ @error_message = @lines.shift
97
+ @smells = @lines.grep(/^ /)
98
+ @headers = (@lines - @smells)
99
+ end
100
+
101
+ it 'mentions every smell in the report' do
102
+ @smells.should have(2).warnings
103
+ end
104
+
105
+ it 'doesnt mention the clean source' do
106
+ @headers.should have(1).headers
107
+ end
108
+ end
@@ -0,0 +1,87 @@
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(Report.new(@smelly_dir.sniff.sniffers).quiet_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(Report.new(@smelly_file.sniff).quiet_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