kevinrutherford-reek 1.1.3.9 → 1.1.3.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/History.txt +2 -1
  2. data/License.txt +20 -0
  3. data/bin/reek +5 -5
  4. data/features/options.feature +1 -0
  5. data/features/reports.feature +40 -0
  6. data/features/stdin.feature +10 -1
  7. data/features/step_definitions/reek_steps.rb +2 -2
  8. data/features/support/env.rb +2 -2
  9. data/lib/reek/class_context.rb +2 -2
  10. data/lib/reek/code_parser.rb +4 -0
  11. data/lib/reek/core_extras.rb +50 -0
  12. data/lib/reek/object_source.rb +7 -18
  13. data/lib/reek/options.rb +13 -3
  14. data/lib/reek/report.rb +27 -28
  15. data/lib/reek/sexp_formatter.rb +2 -0
  16. data/lib/reek/smells/control_couple.rb +5 -0
  17. data/lib/reek/sniffer.rb +98 -3
  18. data/lib/reek/source.rb +9 -112
  19. data/lib/reek/spec.rb +29 -55
  20. data/lib/reek.rb +1 -1
  21. data/reek.gemspec +4 -4
  22. data/spec/reek/object_source_spec.rb +3 -3
  23. data/spec/reek/report_spec.rb +9 -5
  24. data/spec/reek/should_reek_of_spec.rb +105 -0
  25. data/spec/reek/should_reek_only_of_spec.rb +85 -0
  26. data/spec/reek/{spec_spec.rb → should_reek_spec.rb} +24 -3
  27. data/spec/reek/smells/duplication_spec.rb +1 -1
  28. data/spec/reek/smells/large_class_spec.rb +1 -0
  29. data/spec/reek/smells/long_method_spec.rb +4 -4
  30. data/spec/reek/smells/long_parameter_list_spec.rb +1 -1
  31. data/spec/reek/smells/smell_detector_spec.rb +1 -1
  32. data/spec/reek/smells/uncommunicative_name_spec.rb +2 -1
  33. data/spec/reek/sniffer_spec.rb +10 -0
  34. data/spec/samples/all_but_one_masked/clean_one.rb +6 -0
  35. data/spec/samples/all_but_one_masked/dirty.rb +7 -0
  36. data/spec/samples/all_but_one_masked/masked.reek +5 -0
  37. data/spec/samples/clean_due_to_masking/clean_one.rb +6 -0
  38. data/spec/samples/clean_due_to_masking/clean_three.rb +6 -0
  39. data/spec/samples/clean_due_to_masking/clean_two.rb +6 -0
  40. data/spec/samples/clean_due_to_masking/dirty_one.rb +7 -0
  41. data/spec/samples/clean_due_to_masking/dirty_two.rb +7 -0
  42. data/spec/samples/clean_due_to_masking/masked.reek +7 -0
  43. data/spec/samples/mixed_results/clean_one.rb +6 -0
  44. data/spec/samples/mixed_results/clean_three.rb +6 -0
  45. data/spec/samples/mixed_results/clean_two.rb +6 -0
  46. data/spec/samples/mixed_results/dirty_one.rb +7 -0
  47. data/spec/samples/mixed_results/dirty_two.rb +7 -0
  48. data/spec/slow/inline_spec.rb +6 -2
  49. data/spec/slow/optparse_spec.rb +6 -2
  50. data/spec/slow/redcloth_spec.rb +6 -2
  51. data/tasks/test.rake +2 -0
  52. metadata +23 -4
  53. data/spec/slow/source_list_spec.rb +0 -40
data/lib/reek/source.rb CHANGED
@@ -1,139 +1,36 @@
1
- require 'reek/code_parser'
2
- require 'reek/report'
3
1
  require 'reek/sniffer'
4
- require 'ruby_parser'
5
2
 
6
3
  module Reek
7
4
 
8
5
  #
9
6
  # A +Source+ object represents a chunk of Ruby source code.
10
7
  #
11
- # The various class methods are factories that will create +Source+
12
- # instances from various types of input.
13
- #
14
8
  class Source
15
9
 
16
- #
17
- # Factory method: creates a +Source+ object by reading Ruby code from
18
- # the +IO+ stream. The stream is consumed upto end-of-file, but the
19
- # source code is not parsed until +report+ is called. +desc+ provides
20
- # a string description to be used in the header of formatted reports.
21
- #
22
- def self.from_io(ios, desc)
23
- code = ios.readlines.join
24
- return new(code, desc)
25
- end
26
-
27
- #
28
- # Factory method: creates a +Source+ object by reading Ruby code from
29
- # the +code+ string. The code is not parsed until +report+ is called.
30
- #
31
- def self.from_s(code)
32
- return new(code, 'string')
33
- end
34
-
35
- #
36
- # Factory method: creates a +Source+ object by reading Ruby code from
37
- # File +file+. The source code is not parsed until +report+ is called.
38
- #
39
- def self.from_f(file)
40
- from_path(file.path)
41
- end
42
-
43
10
  #
44
11
  # Factory method: creates a +Source+ object by reading Ruby code from
45
12
  # the named file. The source code is not parsed until +report+ is called.
46
13
  #
47
- def self.from_path(filename)
14
+ def self.from_path(filename, sniffer)
48
15
  code = IO.readlines(filename).join
49
- sniffer = Sniffer.new.configure_along_path(filename)
16
+ # SMELL: Greedy Method
17
+ # The Sniffer should ask this source to configure it.
18
+ sniffer.configure_along_path(filename)
50
19
  return new(code, filename, sniffer)
51
20
  end
52
21
 
53
- #
54
- # Factory method: creates a +Source+ object from an array of file paths.
55
- # No source code is actually parsed until the report is accessed.
56
- #
57
- def self.from_pathlist(paths)
58
- sources = paths.map {|path| Source.from_path(path) }
59
- SourceList.new(sources)
60
- end
22
+ attr_reader :desc
23
+ attr_reader :sniffer # SMELL -- bidirectional link
61
24
 
62
- def initialize(code, desc, sniffer = Sniffer.new) # :nodoc:
25
+ def initialize(code, desc, sniffer) # :nodoc:
63
26
  @source = code
64
27
  @desc = desc
65
28
  @sniffer = sniffer
29
+ @sniffer.source = self
66
30
  end
67
31
 
68
- def generate_syntax_tree
32
+ def syntax_tree
69
33
  RubyParser.new.parse(@source, @desc) || s()
70
34
  end
71
-
72
- #
73
- # Returns a +Report+ listing the smells found in this source. The first
74
- # call to +report+ parses the source code and constructs a list of
75
- # +SmellWarning+s found; subsequent calls simply return this same list.
76
- #
77
- def report
78
- unless @report
79
- parser = CodeParser.new(@sniffer)
80
- parser.process(generate_syntax_tree)
81
- @report = Report.new(@sniffer)
82
- end
83
- @report
84
- end
85
-
86
- def smelly?
87
- report.length > 0
88
- end
89
-
90
- #
91
- # Checks this source for instances of +smell_class+, and returns +true+
92
- # only if one of them has a report string matching all of the +patterns+.
93
- #
94
- def has_smell?(smell_class, patterns)
95
- report.has_smell?(smell_class, patterns)
96
- end
97
-
98
- # Creates a formatted report of all the +Smells::SmellWarning+ objects recorded in
99
- # this report, with a heading.
100
- def full_report
101
- report.full_report(@desc)
102
- end
103
-
104
- def to_s
105
- @desc
106
- end
107
- end
108
-
109
- #
110
- # Represents a list of Sources as if they were a single source.
111
- #
112
- class SourceList
113
- def initialize(sources)
114
- @sources = sources
115
- end
116
-
117
- #
118
- # Checks this source for instances of +smell_class+, and returns +true+
119
- # only if one of them has a report string matching all of the +patterns+.
120
- #
121
- def has_smell?(smell_class, patterns=[])
122
- report.has_smell?(smell_class, patterns)
123
- end
124
-
125
- def smelly?
126
- @sources.any? {|source| source.smelly? }
127
- end
128
-
129
- def full_report
130
- ReportList.new(@sources).full_report
131
- end
132
-
133
- def report
134
- ReportList.new(@sources)
135
- end
136
35
  end
137
36
  end
138
-
139
- require 'reek/object_source'
data/lib/reek/spec.rb CHANGED
@@ -1,4 +1,4 @@
1
- require 'reek/source'
1
+ require 'reek/sniffer'
2
2
 
3
3
  module Reek
4
4
 
@@ -34,7 +34,7 @@ module Reek
34
34
  # And a more complex example, making use of one of the factory methods for
35
35
  # +Source+ so that the code is parsed and analysed only once:
36
36
  #
37
- # ruby = 'def double_thing() @other.thing.foo + @other.thing.foo end'.to_source
37
+ # ruby = 'def double_thing() @other.thing.foo + @other.thing.foo end'.sniff
38
38
  # ruby.should reek_of(:Duplication, /@other.thing[^\.]/)
39
39
  # ruby.should reek_of(:Duplication, /@other.thing.foo/)
40
40
  # ruby.should_not reek_of(:FeatureEnvy)
@@ -42,67 +42,67 @@ module Reek
42
42
  module Spec
43
43
  class ShouldReek # :nodoc:
44
44
  def matches?(actual)
45
- @source = actual.to_source
46
- @source.smelly?
45
+ @sniffer = actual.sniff
46
+ @sniffer.smelly?
47
47
  end
48
48
  def failure_message_for_should
49
49
  "Expected source to reek, but it didn't"
50
50
  end
51
51
  def failure_message_for_should_not
52
- "Expected no smells, but got:\n#{@source.full_report}"
52
+ "Expected no smells, but got:\n#{@sniffer.quiet_report}"
53
53
  end
54
54
  end
55
55
 
56
- #
57
- # Returns +true+ if and only if the target source code contains smells.
58
- #
59
- def reek
60
- ShouldReek.new
61
- end
62
-
63
56
  class ShouldReekOf # :nodoc:
64
57
  def initialize(klass, patterns)
65
58
  @klass = klass
66
59
  @patterns = patterns
67
60
  end
68
61
  def matches?(actual)
69
- @source = actual.to_source
70
- @source.has_smell?(@klass, @patterns)
62
+ @sniffer = actual.sniff
63
+ @sniffer.has_smell?(@klass, @patterns)
71
64
  end
72
65
  def failure_message_for_should
73
- "Expected #{@source} to reek of #{@klass}, but it didn't"
66
+ "Expected #{@sniffer.desc} to reek of #{@klass}, but it didn't"
74
67
  end
75
68
  def failure_message_for_should_not
76
- "Expected #{@source} not to reek of #{@klass}, but got:\n#{@source.full_report}"
69
+ "Expected #{@sniffer.desc} not to reek of #{@klass}, but got:\n#{@sniffer.quiet_report}"
77
70
  end
78
71
  end
79
72
 
80
- #
81
- # Checks the target source code for instances of +smell_class+,
82
- # and returns +true+ only if one of them has a report string matching
83
- # all of the +patterns+.
84
- #
85
- def reek_of(smell_class, *patterns)
86
- ShouldReekOf.new(smell_class, patterns)
87
- end
88
-
89
73
  class ShouldReekOnlyOf # :nodoc:
90
74
  def initialize(klass, patterns)
91
75
  @klass = klass
92
76
  @patterns = patterns
93
77
  end
94
78
  def matches?(actual)
95
- @source = actual.to_source
96
- @source.report.length == 1 and @source.has_smell?(@klass, @patterns)
79
+ @sniffer = actual.sniff
80
+ @sniffer.smells_only_of?(@klass, @patterns)
97
81
  end
98
82
  def failure_message_for_should
99
- "Expected source to reek only of #{@klass}, but got:\n#{@source.full_report}"
83
+ "Expected #{@sniffer.desc} to reek only of #{@klass}, but got:\n#{@sniffer.quiet_report}"
100
84
  end
101
85
  def failure_message_for_should_not
102
- "Expected source not to reek only of #{@klass}, but it did"
86
+ "Expected #{@sniffer.desc} not to reek only of #{@klass}, but it did"
103
87
  end
104
88
  end
105
89
 
90
+ #
91
+ # Returns +true+ if and only if the target source code contains smells.
92
+ #
93
+ def reek
94
+ ShouldReek.new
95
+ end
96
+
97
+ #
98
+ # Checks the target source code for instances of +smell_class+,
99
+ # and returns +true+ only if one of them has a report string matching
100
+ # all of the +patterns+.
101
+ #
102
+ def reek_of(smell_class, *patterns)
103
+ ShouldReekOf.new(smell_class, patterns)
104
+ end
105
+
106
106
  #
107
107
  # As for reek_of, but the matched smell warning must be the only warning of
108
108
  # any kind in the target source code's Reek report.
@@ -113,32 +113,6 @@ module Reek
113
113
  end
114
114
  end
115
115
 
116
- class File
117
- def to_source
118
- Reek::Source.from_f(self)
119
- end
120
- end
121
-
122
- class String
123
- def to_source
124
- Reek::Source.from_s(self)
125
- end
126
- end
127
-
128
- class Array
129
- def to_source
130
- Reek::Source.from_pathlist(self)
131
- end
132
- end
133
-
134
- module Reek
135
- class Source
136
- def to_source
137
- self
138
- end
139
- end
140
- end
141
-
142
116
  if Object.const_defined?(:Spec)
143
117
  Spec::Runner.configure do |config|
144
118
  config.include(Reek::Spec)
data/lib/reek.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  $:.unshift File.dirname(__FILE__)
2
2
 
3
3
  module Reek # :doc:
4
- VERSION = '1.1.3.9'
4
+ VERSION = '1.1.3.10'
5
5
  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.9"
5
+ s.version = "1.1.3.10"
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-07-06}
9
+ s.date = %q{2009-07-15}
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", "features/masking_smells.feature", "features/options.feature", "features/rake_task.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/block_context.rb", "lib/reek/class_context.rb", "lib/reek/code_context.rb", "lib/reek/code_parser.rb", "lib/reek/config_file.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/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/uncommunicative_name.rb", "lib/reek/smells/utility_function.rb", "lib/reek/sniffer.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/object_source_spec.rb", "spec/reek/options_spec.rb", "spec/reek/report_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/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_detector_spec.rb", "spec/reek/smells/uncommunicative_name_spec.rb", "spec/reek/smells/utility_function_spec.rb", "spec/reek/spec_spec.rb", "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/inline.rb", "spec/samples/masked/dirty.rb", "spec/samples/masked/masked.reek", "spec/samples/optparse.rb", "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/slow/inline_spec.rb", "spec/slow/optparse_spec.rb", "spec/slow/redcloth_spec.rb", "spec/slow/reek_source_spec.rb", "spec/slow/source_list_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "tasks/reek.rake", "tasks/test.rake"]
14
+ s.extra_rdoc_files = ["History.txt", "License.txt", "README.txt"]
15
+ s.files = ["History.txt", "License.txt", "README.txt", "Rakefile", "bin/reek", "config/defaults.reek", "features/masking_smells.feature", "features/options.feature", "features/rake_task.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/block_context.rb", "lib/reek/class_context.rb", "lib/reek/code_context.rb", "lib/reek/code_parser.rb", "lib/reek/config_file.rb", "lib/reek/core_extras.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/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/uncommunicative_name.rb", "lib/reek/smells/utility_function.rb", "lib/reek/sniffer.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/object_source_spec.rb", "spec/reek/options_spec.rb", "spec/reek/report_spec.rb", "spec/reek/should_reek_of_spec.rb", "spec/reek/should_reek_only_of_spec.rb", "spec/reek/should_reek_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/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_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/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/optparse.rb", "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/slow/inline_spec.rb", "spec/slow/optparse_spec.rb", "spec/slow/redcloth_spec.rb", "spec/slow/reek_source_spec.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
@@ -8,9 +8,9 @@ describe Dir do
8
8
  Dir['spec/samples/two_smelly_files/*.rb'].should reek_of(:UncommunicativeName)
9
9
  end
10
10
 
11
- it 'reports correct smells via SourceList' do
12
- src = Dir['spec/samples/two_smelly_files/*.rb'].to_source
13
- src.has_smell?(:UncommunicativeName).should be_true
11
+ it 'reports correct smells via Dir' do
12
+ sniffer = Dir['spec/samples/two_smelly_files/*.rb'].sniff
13
+ sniffer.has_smell?(:UncommunicativeName).should be_true
14
14
  end
15
15
 
16
16
  it 'copes with daft file specs' do
@@ -9,7 +9,7 @@ include Reek
9
9
 
10
10
  describe Report, " when empty" do
11
11
  before(:each) do
12
- @rpt = Report.new
12
+ @rpt = Report.new(Sniffer.new)
13
13
  end
14
14
 
15
15
  it 'should have zero length' do
@@ -19,12 +19,16 @@ describe Report, " when empty" do
19
19
  it 'should claim to be empty' do
20
20
  @rpt.should be_empty
21
21
  end
22
+
23
+ it 'has an empty quiet_report' do
24
+ @rpt.quiet_report.should == ''
25
+ end
22
26
  end
23
27
 
24
- describe Report, "to_s" do
28
+ describe Report, "smell_list" do
25
29
  before(:each) do
26
- rpt = Source.from_s('def simple(a) a[3] end').report
27
- @report = rpt.to_s.split("\n")
30
+ rpt = 'def simple(a) a[3] end'.sniff.report
31
+ @report = rpt.smell_list.split("\n")
28
32
  end
29
33
 
30
34
  it 'should mention every smell name' do
@@ -36,7 +40,7 @@ end
36
40
 
37
41
  describe Report, " as a SortedSet" do
38
42
  it 'should only add a smell once' do
39
- rpt = Report.new
43
+ rpt = Report.new(Sniffer.new)
40
44
  rpt << SmellWarning.new(Smells::FeatureEnvy.new, "self", 'too many!')
41
45
  rpt.length.should == 1
42
46
  rpt << SmellWarning.new(Smells::FeatureEnvy.new, "self", 'too many!')
@@ -0,0 +1,105 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ require 'reek/spec'
4
+
5
+ include Reek::Spec
6
+
7
+ describe ShouldReekOf, 'rdoc demo example' do
8
+ it 'works on a common source' do
9
+ ruby = 'def double_thing() @other.thing.foo + @other.thing.foo end'
10
+ ruby.should reek_of(:Duplication, /@other.thing[^\.]/)
11
+ ruby.should reek_of(:Duplication, /@other.thing.foo/)
12
+ ruby.should_not reek_of(:FeatureEnvy)
13
+ end
14
+
15
+ it 'works on a common sniffer' do
16
+ ruby = 'def double_thing() @other.thing.foo + @other.thing.foo end'.sniff
17
+ ruby.should reek_of(:Duplication, /@other.thing[^\.]/)
18
+ ruby.should reek_of(:Duplication, /@other.thing.foo/)
19
+ ruby.should_not reek_of(:FeatureEnvy)
20
+ end
21
+ end
22
+
23
+ describe ShouldReekOf, 'checking code in a string' do
24
+ before :each do
25
+ @clean_code = 'def good() true; end'
26
+ @smelly_code = 'def x() y = 4; end'
27
+ @matcher = ShouldReekOf.new(:UncommunicativeName, [/x/, /y/])
28
+ end
29
+
30
+ it 'matches a smelly String' do
31
+ @matcher.matches?(@smelly_code).should be_true
32
+ end
33
+
34
+ it 'doesnt match a fragrant String' do
35
+ @matcher.matches?(@clean_code).should be_false
36
+ end
37
+
38
+ it 'reports the smells when should_not fails' do
39
+ @matcher.matches?(@smelly_code).should be_true
40
+ @matcher.failure_message_for_should_not.should include(@smelly_code.sniff.quiet_report)
41
+ end
42
+ end
43
+
44
+ describe ShouldReekOf, 'checking code in a Dir' do
45
+ before :each do
46
+ @clean_dir = Dir['spec/samples/three_clean_files/*.rb']
47
+ @smelly_dir = Dir['spec/samples/two_smelly_files/*.rb']
48
+ @matcher = ShouldReekOf.new(:UncommunicativeName, [/Dirty/, /@s/])
49
+ end
50
+
51
+ it 'matches a smelly String' do
52
+ @matcher.matches?(@smelly_dir).should be_true
53
+ end
54
+
55
+ it 'doesnt match a fragrant String' do
56
+ @matcher.matches?(@clean_dir).should be_false
57
+ end
58
+
59
+ it 'reports the smells when should_not fails' do
60
+ @matcher.matches?(@smelly_dir).should be_true
61
+ @matcher.failure_message_for_should_not.should include(@smelly_dir.sniff.quiet_report)
62
+ end
63
+ end
64
+
65
+ describe ShouldReekOf, 'checking code in a File' do
66
+ before :each do
67
+ @clean_file = File.new(Dir['spec/samples/three_clean_files/*.rb'][0])
68
+ @smelly_file = File.new(Dir['spec/samples/two_smelly_files/*.rb'][0])
69
+ @matcher = ShouldReekOf.new(:UncommunicativeName, [/Dirty/, /@s/])
70
+ end
71
+
72
+ it 'matches a smelly String' do
73
+ @matcher.matches?(@smelly_file).should be_true
74
+ end
75
+
76
+ it 'doesnt match a fragrant String' do
77
+ @matcher.matches?(@clean_file).should be_false
78
+ end
79
+
80
+ it 'reports the smells when should_not fails' do
81
+ @matcher.matches?(@smelly_file).should be_true
82
+ @matcher.failure_message_for_should_not.should include(@smelly_file.sniff.quiet_report)
83
+ end
84
+ end
85
+
86
+ describe ShouldReekOf, 'report formatting' do
87
+ before :each do
88
+ @smelly_dir = Dir['spec/samples/mixed_results/*.rb']
89
+ @matcher = ShouldReekOf.new(:UncommunicativeName, [/Dirty/, /@s/])
90
+ @matcher.matches?(@smelly_dir)
91
+ @lines = @matcher.failure_message_for_should_not.split("\n").map {|str| str.chomp}
92
+ @error_message = @lines.shift
93
+ @smells = @lines.grep(/^ /)
94
+ @headers = (@lines - @smells)
95
+ end
96
+
97
+ it 'mentions every smell in the report' do
98
+ @smells.should have(12).warnings
99
+ end
100
+
101
+ it 'doesnt mention the clean files' do
102
+ @headers.should have(2).headers
103
+ @headers.should_not include('clean')
104
+ end
105
+ end
@@ -0,0 +1,85 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ require 'reek/spec'
4
+
5
+ include Reek::Spec
6
+
7
+ describe ShouldReekOnlyOf, 'checking code in a string' do
8
+ before :each do
9
+ @clean_code = 'def good() true; end'
10
+ @smelly_code = 'def fine() y = 4; end'
11
+ @matcher = ShouldReekOnlyOf.new(:UncommunicativeName, [/y/])
12
+ end
13
+
14
+ it 'matches a smelly String' do
15
+ @matcher.matches?(@smelly_code).should be_true
16
+ end
17
+
18
+ it 'doesnt match a fragrant String' do
19
+ @matcher.matches?(@clean_code).should be_false
20
+ end
21
+
22
+ it 'reports the smells when should_not fails' do
23
+ @matcher.matches?(@smelly_code).should be_true
24
+ @matcher.failure_message_for_should_not.should include('UncommunicativeName')
25
+ end
26
+ end
27
+
28
+ describe ShouldReekOnlyOf, 'checking code in a Dir' do
29
+ before :each do
30
+ @clean_dir = Dir['spec/samples/three_clean_files/*.rb']
31
+ @smelly_dir = Dir['spec/samples/all_but_one_masked/*.rb']
32
+ @matcher = ShouldReekOnlyOf.new(:NestedIterators, [/Dirty\#a/])
33
+ end
34
+
35
+ it 'matches a smelly String' do
36
+ @matcher.matches?(@smelly_dir).should be_true
37
+ end
38
+
39
+ it 'doesnt match a fragrant String' do
40
+ @matcher.matches?(@clean_dir).should be_false
41
+ end
42
+
43
+ it 'reports the smells when should_not fails' do
44
+ @matcher.matches?(@smelly_dir).should be_true
45
+ @matcher.failure_message_for_should.should include(@smelly_dir.sniff.quiet_report)
46
+ end
47
+ end
48
+
49
+ describe ShouldReekOnlyOf, 'checking code in a File' do
50
+ before :each do
51
+ @clean_file = File.new(Dir['spec/samples/three_clean_files/*.rb'][0])
52
+ @smelly_file = File.new(Dir['spec/samples/all_but_one_masked/d*.rb'][0])
53
+ @matcher = ShouldReekOnlyOf.new(:NestedIterators, [/Dirty\#a/])
54
+ end
55
+
56
+ it 'matches a smelly String' do
57
+ @matcher.matches?(@smelly_file).should be_true
58
+ end
59
+
60
+ it 'doesnt match a fragrant String' do
61
+ @matcher.matches?(@clean_file).should be_false
62
+ end
63
+
64
+ it 'reports the smells when should_not fails' do
65
+ @matcher.matches?(@smelly_file).should be_true
66
+ @matcher.failure_message_for_should.should include(@smelly_file.sniff.quiet_report)
67
+ end
68
+ end
69
+
70
+ describe ShouldReekOnlyOf, 'report formatting' do
71
+ before :each do
72
+ @smelly_dir = Dir['spec/samples/all_but_one_masked/*.rb']
73
+ @matcher = ShouldReekOnlyOf.new(:NestedIterators, [/Dirty\#a/])
74
+ @matcher.matches?(@smelly_dir)
75
+ @lines = @matcher.failure_message_for_should.split("\n").map {|str| str.chomp}
76
+ @error_message = @lines.shift
77
+ @smells = @lines.grep(/^ /)
78
+ @headers = (@lines - @smells)
79
+ end
80
+
81
+ it 'doesnt mention the clean files' do
82
+ @headers.should have(1).header
83
+ @headers.should_not include('clean')
84
+ end
85
+ end
@@ -21,7 +21,7 @@ describe ShouldReek, 'checking code in a string' do
21
21
 
22
22
  it 'reports the smells when should_not fails' do
23
23
  @matcher.matches?(@smelly_code).should be_true
24
- @matcher.failure_message_for_should_not.should include(@smelly_code.to_source.full_report)
24
+ @matcher.failure_message_for_should_not.should include(@smelly_code.sniff.quiet_report)
25
25
  end
26
26
  end
27
27
 
@@ -42,7 +42,7 @@ describe ShouldReek, 'checking code in a Dir' do
42
42
 
43
43
  it 'reports the smells when should_not fails' do
44
44
  @matcher.matches?(@smelly_dir).should be_true
45
- @matcher.failure_message_for_should_not.should include(@smelly_dir.to_source.full_report)
45
+ @matcher.failure_message_for_should_not.should include(@smelly_dir.sniff.quiet_report)
46
46
  end
47
47
  end
48
48
 
@@ -63,6 +63,27 @@ describe ShouldReek, 'checking code in a File' do
63
63
 
64
64
  it 'reports the smells when should_not fails' do
65
65
  @matcher.matches?(@smelly_file).should be_true
66
- @matcher.failure_message_for_should_not.should include(@smelly_file.to_source.full_report)
66
+ @matcher.failure_message_for_should_not.should include(@smelly_file.sniff.quiet_report)
67
+ end
68
+ end
69
+
70
+ describe ShouldReek, 'report formatting' do
71
+ before :each do
72
+ @smelly_dir = Dir['spec/samples/mixed_results/*.rb']
73
+ @matcher = ShouldReek.new
74
+ @matcher.matches?(@smelly_dir)
75
+ @lines = @matcher.failure_message_for_should_not.split("\n").map {|str| str.chomp}
76
+ @error_message = @lines.shift
77
+ @smells = @lines.grep(/^ /)
78
+ @headers = (@lines - @smells)
79
+ end
80
+
81
+ it 'mentions every smell in the report' do
82
+ @smells.should have(12).warnings
83
+ end
84
+
85
+ it 'doesnt mention the clean files' do
86
+ @headers.should have(2).headers
87
+ @headers.should_not include('clean')
67
88
  end
68
89
  end
@@ -21,7 +21,7 @@ describe Duplication, "repeated method calls" do
21
21
  end
22
22
 
23
23
  it 'should report nested calls' do
24
- ruby = 'def double_thing() @other.thing.foo + @other.thing.foo end'.to_source
24
+ ruby = 'def double_thing() @other.thing.foo + @other.thing.foo end'.sniff
25
25
  ruby.should reek_of(:Duplication, /@other.thing[^\.]/)
26
26
  ruby.should reek_of(:Duplication, /@other.thing.foo/)
27
27
  end
@@ -1,6 +1,7 @@
1
1
  require File.dirname(__FILE__) + '/../../spec_helper.rb'
2
2
  require 'reek/code_parser'
3
3
  require 'reek/report'
4
+ require 'reek/object_source'
4
5
  require 'reek/smells/large_class'
5
6
 
6
7
  include Reek
@@ -8,8 +8,8 @@ include Reek
8
8
  include Reek::Smells
9
9
 
10
10
  def process_method(src)
11
- source = Source.from_s(src)
12
- CodeParser.new(Sniffer.new).process_defn(source.generate_syntax_tree)
11
+ sniffer = src.sniff
12
+ CodeParser.new(sniffer).process_defn(sniffer.source.syntax_tree)
13
13
  end
14
14
 
15
15
  describe LongMethod do
@@ -26,7 +26,7 @@ describe LongMethod do
26
26
  end
27
27
 
28
28
  it 'should only report a long method once' do
29
- source =<<EOS
29
+ src = <<EOS
30
30
  def standard_entries(rbconfig)
31
31
  @abc = rbconfig
32
32
  rubypath = File.join(@abc['bindir'], @abcf['ruby_install_name'] + cff['EXEEXT'])
@@ -44,7 +44,7 @@ def standard_entries(rbconfig)
44
44
  end
45
45
  end
46
46
  EOS
47
- source.should reek_only_of(:LongMethod)
47
+ src.should reek_only_of(:LongMethod)
48
48
  end
49
49
 
50
50
  it 'should report long inner block' do