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.
- data/History.txt +2 -1
- data/License.txt +20 -0
- data/bin/reek +5 -5
- data/features/options.feature +1 -0
- data/features/reports.feature +40 -0
- data/features/stdin.feature +10 -1
- data/features/step_definitions/reek_steps.rb +2 -2
- data/features/support/env.rb +2 -2
- data/lib/reek/class_context.rb +2 -2
- data/lib/reek/code_parser.rb +4 -0
- data/lib/reek/core_extras.rb +50 -0
- data/lib/reek/object_source.rb +7 -18
- data/lib/reek/options.rb +13 -3
- data/lib/reek/report.rb +27 -28
- data/lib/reek/sexp_formatter.rb +2 -0
- data/lib/reek/smells/control_couple.rb +5 -0
- data/lib/reek/sniffer.rb +98 -3
- data/lib/reek/source.rb +9 -112
- data/lib/reek/spec.rb +29 -55
- data/lib/reek.rb +1 -1
- data/reek.gemspec +4 -4
- data/spec/reek/object_source_spec.rb +3 -3
- data/spec/reek/report_spec.rb +9 -5
- data/spec/reek/should_reek_of_spec.rb +105 -0
- data/spec/reek/should_reek_only_of_spec.rb +85 -0
- data/spec/reek/{spec_spec.rb → should_reek_spec.rb} +24 -3
- data/spec/reek/smells/duplication_spec.rb +1 -1
- data/spec/reek/smells/large_class_spec.rb +1 -0
- data/spec/reek/smells/long_method_spec.rb +4 -4
- data/spec/reek/smells/long_parameter_list_spec.rb +1 -1
- data/spec/reek/smells/smell_detector_spec.rb +1 -1
- data/spec/reek/smells/uncommunicative_name_spec.rb +2 -1
- data/spec/reek/sniffer_spec.rb +10 -0
- data/spec/samples/all_but_one_masked/clean_one.rb +6 -0
- data/spec/samples/all_but_one_masked/dirty.rb +7 -0
- data/spec/samples/all_but_one_masked/masked.reek +5 -0
- data/spec/samples/clean_due_to_masking/clean_one.rb +6 -0
- data/spec/samples/clean_due_to_masking/clean_three.rb +6 -0
- data/spec/samples/clean_due_to_masking/clean_two.rb +6 -0
- data/spec/samples/clean_due_to_masking/dirty_one.rb +7 -0
- data/spec/samples/clean_due_to_masking/dirty_two.rb +7 -0
- data/spec/samples/clean_due_to_masking/masked.reek +7 -0
- data/spec/samples/mixed_results/clean_one.rb +6 -0
- data/spec/samples/mixed_results/clean_three.rb +6 -0
- data/spec/samples/mixed_results/clean_two.rb +6 -0
- data/spec/samples/mixed_results/dirty_one.rb +7 -0
- data/spec/samples/mixed_results/dirty_two.rb +7 -0
- data/spec/slow/inline_spec.rb +6 -2
- data/spec/slow/optparse_spec.rb +6 -2
- data/spec/slow/redcloth_spec.rb +6 -2
- data/tasks/test.rake +2 -0
- metadata +23 -4
- 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
|
-
|
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
|
-
|
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
|
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
|
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/
|
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'.
|
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
|
-
@
|
46
|
-
@
|
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#{@
|
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
|
-
@
|
70
|
-
@
|
62
|
+
@sniffer = actual.sniff
|
63
|
+
@sniffer.has_smell?(@klass, @patterns)
|
71
64
|
end
|
72
65
|
def failure_message_for_should
|
73
|
-
"Expected #{@
|
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 #{@
|
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
|
-
@
|
96
|
-
@
|
79
|
+
@sniffer = actual.sniff
|
80
|
+
@sniffer.smells_only_of?(@klass, @patterns)
|
97
81
|
end
|
98
82
|
def failure_message_for_should
|
99
|
-
"Expected
|
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
|
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
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.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-
|
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/
|
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
|
12
|
-
|
13
|
-
|
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
|
data/spec/reek/report_spec.rb
CHANGED
@@ -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, "
|
28
|
+
describe Report, "smell_list" do
|
25
29
|
before(:each) do
|
26
|
-
rpt =
|
27
|
-
@report = rpt.
|
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.
|
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.
|
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.
|
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'.
|
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
|
@@ -8,8 +8,8 @@ include Reek
|
|
8
8
|
include Reek::Smells
|
9
9
|
|
10
10
|
def process_method(src)
|
11
|
-
|
12
|
-
CodeParser.new(
|
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
|
-
|
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
|
-
|
47
|
+
src.should reek_only_of(:LongMethod)
|
48
48
|
end
|
49
49
|
|
50
50
|
it 'should report long inner block' do
|