kevinrutherford-reek 1.1.3.4 → 1.1.3.5

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.
data/History.txt CHANGED
@@ -1,11 +1,20 @@
1
- == 1.1.4 (in git)
1
+ == 1.2 (in git)
2
+
3
+ === Major Changes
4
+ * Reek's output reports are now formatted differently:
5
+ ** Reek is no longer silent about smell-free source code
6
+ ** Output now reports on all files examined, even if they have no smells
7
+ ** Smell warnings are indented in the report; file summary headers are not
8
+ ** Reports for multiple sources are run together; no more blank lines
2
9
 
3
10
  === Minor Changes
4
- * LongMethod now counts statements deeper into each method (fixed #25)
5
- * LongMethod no longer counts control structures, only their contained stmts
11
+ * Several changes to the LongMethod counting algorithm:
12
+ ** LongMethod now counts statements deeper into each method (fixed #25)
13
+ ** LongMethod no longer counts control structures, only their contained stmts
14
+ ** See http://wiki.github.com/kevinrutherford/reek/long-method for details
6
15
  * LargeClass is disabled when checking in-memory classes (fixed #28)
7
- * Output now reports on all files examined, even if they have no smells
8
- * Smell warnings are indented in the report to distinguish them from file headers
16
+ * Now reports an error for corrupt config files
17
+ * Empty config files are ignored
9
18
 
10
19
  == 1.1.3 2009-05-19
11
20
 
data/bin/reek CHANGED
@@ -10,10 +10,17 @@ require 'reek'
10
10
  require 'reek/source'
11
11
  require 'reek/options'
12
12
 
13
- exitstatus = 0
14
- source = Reek::Options.parse(ARGV)
15
- if source.smelly?
16
- puts source.report
17
- exitstatus = 2
13
+ def reek(args)
14
+ begin
15
+ source = Reek::Options.parse(args)
16
+ puts source.full_report
17
+ return source.smelly? ? 2 : 0
18
+ rescue SystemExit => ex
19
+ return ex.status
20
+ rescue Exception => error
21
+ $stderr.puts "Error: #{error}"
22
+ return 1
23
+ end
18
24
  end
19
- exit(exitstatus)
25
+
26
+ exit reek(ARGV)
@@ -0,0 +1,42 @@
1
+ @masking
2
+ Feature: Masking smells using config files
3
+ In order to keep my reports meaningful
4
+ As a developer
5
+ I want to mask some smells using config files
6
+
7
+ Scenario: empty config file is ignored
8
+ When I run reek spec/samples/empty_config_file/dirty.rb
9
+ Then it fails with exit status 2
10
+ And it reports:
11
+ """
12
+ spec/samples/empty_config_file/dirty.rb -- 6 warnings:
13
+ Dirty has the variable name '@s' (Uncommunicative Name)
14
+ Dirty#a calls @s.title multiple times (Duplication)
15
+ Dirty#a calls puts(@s.title) multiple times (Duplication)
16
+ Dirty#a has the name 'a' (Uncommunicative Name)
17
+ Dirty#a/block has the variable name 'x' (Uncommunicative Name)
18
+ Dirty#a/block/block is nested (Nested Iterators)
19
+
20
+ """
21
+
22
+ Scenario: corrupt config file prevents normal output
23
+ When I run reek spec/samples/corrupt_config_file/dirty.rb
24
+ Then it fails with exit status 1
25
+ And it reports the error 'Error: invalid configuration file "corrupt.reek"'
26
+
27
+ Scenario: missing source file is an error
28
+ When I run reek no_such_file.rb
29
+ Then it fails with exit status 1
30
+ And it reports the error "Error: No such file or directory - no_such_file.rb"
31
+
32
+ Scenario: switch off one smell
33
+ When I run reek spec/samples/masked/dirty.rb
34
+ Then it fails with exit status 2
35
+ And it reports:
36
+ """
37
+ spec/samples/masked/dirty.rb -- 3 warnings:
38
+ Dirty#a calls @s.title multiple times (Duplication)
39
+ Dirty#a calls puts(@s.title) multiple times (Duplication)
40
+ Dirty#a/block/block is nested (Nested Iterators)
41
+
42
+ """
@@ -0,0 +1,20 @@
1
+ @options
2
+ Feature: Reek can be controlled using command-line options
3
+ In order to change reek's default behaviour
4
+ As a developer
5
+ I want to supply options on the command line
6
+
7
+ Scenario: return non-zero status on bad option
8
+ When I run reek --no-such-option
9
+ Then it fails with exit status 1
10
+ And it reports the error "Error: invalid option: --no-such-option"
11
+
12
+ Scenario: return non-zero status on missing argument
13
+ When I run reek -f
14
+ Then it fails with exit status 1
15
+ And it reports the error "Error: missing argument: -f"
16
+
17
+ Scenario: display the current version number
18
+ When I run reek --version
19
+ Then it succeeds
20
+ And it reports the current version
@@ -0,0 +1,9 @@
1
+ @rake
2
+ Feature: RakeTask
3
+ In order to run reek as part of my CI process
4
+ As a developer
5
+ I want to create rake tasks to run reek
6
+
7
+ Scenario: reports no smells in reek's own source code
8
+ When I run rake reek
9
+ Then it succeeds
@@ -0,0 +1,28 @@
1
+ @reports
2
+ Feature: Correclty formatted reports
3
+ In order to get the most out of reek
4
+ As a developer
5
+ I want to be able to parse reek's output simply and consistently
6
+
7
+ Scenario: two reports run together with indented smells
8
+ When I run reek spec/samples/two_smelly_files/*.rb
9
+ Then it fails with exit status 2
10
+ And it reports:
11
+ """
12
+ spec/samples/two_smelly_files/dirty_one.rb -- 6 warnings:
13
+ Dirty has the variable name '@s' (Uncommunicative Name)
14
+ Dirty#a calls @s.title multiple times (Duplication)
15
+ Dirty#a calls puts(@s.title) multiple times (Duplication)
16
+ Dirty#a has the name 'a' (Uncommunicative Name)
17
+ Dirty#a/block has the variable name 'x' (Uncommunicative Name)
18
+ Dirty#a/block/block is nested (Nested Iterators)
19
+ spec/samples/two_smelly_files/dirty_two.rb -- 6 warnings:
20
+ Dirty has the variable name '@s' (Uncommunicative Name)
21
+ Dirty#a calls @s.title multiple times (Duplication)
22
+ Dirty#a calls puts(@s.title) multiple times (Duplication)
23
+ Dirty#a has the name 'a' (Uncommunicative Name)
24
+ Dirty#a/block has the variable name 'x' (Uncommunicative Name)
25
+ Dirty#a/block/block is nested (Nested Iterators)
26
+
27
+ """
28
+
@@ -0,0 +1,274 @@
1
+ @samples
2
+ Feature: Basic smell detection
3
+ In order to write better software
4
+ As a developer
5
+ I want to detect the smels in my Ruby code
6
+
7
+ Scenario: Correct smells from inline.rb
8
+ When I run reek spec/samples/inline.rb
9
+ Then it fails with exit status 2
10
+ And it reports:
11
+ """
12
+ spec/samples/inline.rb -- 32 warnings:
13
+ Inline::C has at least 13 instance variables (Large Class)
14
+ Inline::C#build calls ($? == 0) multiple times (Duplication)
15
+ Inline::C#build calls Inline.directory multiple times (Duplication)
16
+ Inline::C#build calls io.puts multiple times (Duplication)
17
+ Inline::C#build calls io.puts("#endif") multiple times (Duplication)
18
+ Inline::C#build calls io.puts("#ifdef __cplusplus") multiple times (Duplication)
19
+ Inline::C#build calls module_name multiple times (Duplication)
20
+ Inline::C#build calls warn("Output:\n#{result}") multiple times (Duplication)
21
+ Inline::C#build has approx 60 statements (Long Method)
22
+ Inline::C#build has the variable name 't' (Uncommunicative Name)
23
+ Inline::C#build/block/block has the variable name 'n' (Uncommunicative Name)
24
+ Inline::C#build/block/block is nested (Nested Iterators)
25
+ Inline::C#c has the name 'c' (Uncommunicative Name)
26
+ Inline::C#crap_for_windoze calls Config::CONFIG["libdir"] multiple times (Duplication)
27
+ Inline::C#generate calls result.sub!(/\A\n/, "") multiple times (Duplication)
28
+ Inline::C#generate calls signature["args"] multiple times (Duplication)
29
+ Inline::C#generate calls signature["args"].map multiple times (Duplication)
30
+ Inline::C#generate has approx 32 statements (Long Method)
31
+ Inline::C#initialize calls stack.empty? multiple times (Duplication)
32
+ Inline::C#load calls so_name multiple times (Duplication)
33
+ Inline::C#module_name/block has the variable name 'm' (Uncommunicative Name)
34
+ Inline::C#module_name/block has the variable name 'x' (Uncommunicative Name)
35
+ Inline::C#parse_signature has approx 15 statements (Long Method)
36
+ Inline::C#parse_signature is controlled by argument raw (Control Couple)
37
+ Inline::C#parse_signature/block has the variable name 'x' (Uncommunicative Name)
38
+ Inline::C#strip_comments doesn't depend on instance state (Utility Function)
39
+ Inline::C#strip_comments refers to src more than self (Feature Envy)
40
+ Inline::self.rootdir calls env.nil? multiple times (Duplication)
41
+ Inline::self.rootdir has approx 8 statements (Long Method)
42
+ Module#inline calls Inline.const_get(lang) multiple times (Duplication)
43
+ Module#inline has approx 11 statements (Long Method)
44
+ Module#inline is controlled by argument options (Control Couple)
45
+
46
+ """
47
+
48
+ Scenario: Correct smells from optparse.rb
49
+ When I run reek spec/samples/optparse.rb
50
+ Then it fails with exit status 2
51
+ And it reports:
52
+ """
53
+ spec/samples/optparse.rb -- 117 warnings:
54
+ OptionParser has at least 59 methods (Large Class)
55
+ OptionParser#CompletingHash#match/block/block is nested (Nested Iterators)
56
+ OptionParser#Completion::complete calls candidates.size multiple times (Duplication)
57
+ OptionParser#Completion::complete calls k.id2name multiple times (Duplication)
58
+ OptionParser#Completion::complete has approx 22 statements (Long Method)
59
+ OptionParser#Completion::complete has the variable name 'k' (Uncommunicative Name)
60
+ OptionParser#Completion::complete has the variable name 'v' (Uncommunicative Name)
61
+ OptionParser#Completion::complete refers to candidates more than self (Feature Envy)
62
+ OptionParser#Completion::complete/block has the variable name 'k' (Uncommunicative Name)
63
+ OptionParser#Completion::complete/block has the variable name 'v' (Uncommunicative Name)
64
+ OptionParser#List#accept has the variable name 't' (Uncommunicative Name)
65
+ OptionParser#List#accept is controlled by argument pat (Control Couple)
66
+ OptionParser#List#accept refers to pat more than self (Feature Envy)
67
+ OptionParser#List#add_banner refers to opt more than self (Feature Envy)
68
+ OptionParser#List#complete has 4 parameters (Long Parameter List)
69
+ OptionParser#List#reject has the variable name 't' (Uncommunicative Name)
70
+ OptionParser#List#summarize refers to opt more than self (Feature Envy)
71
+ OptionParser#List#update has 5 parameters (Long Parameter List)
72
+ OptionParser#List#update has approx 6 statements (Long Method)
73
+ OptionParser#List#update has the variable name 'o' (Uncommunicative Name)
74
+ OptionParser#List#update is controlled by argument lopts (Control Couple)
75
+ OptionParser#List#update is controlled by argument sopts (Control Couple)
76
+ OptionParser#List#update/block has the variable name 'o' (Uncommunicative Name)
77
+ OptionParser#ParseError#set_option is controlled by argument eq (Control Couple)
78
+ OptionParser#Switch#NoArgument#parse is controlled by argument arg (Control Couple)
79
+ OptionParser#Switch#OptionalArgument#parse is controlled by argument arg (Control Couple)
80
+ OptionParser#Switch#PlacedArgument#parse has approx 6 statements (Long Method)
81
+ OptionParser#Switch#RequiredArgument#parse is controlled by argument arg (Control Couple)
82
+ OptionParser#Switch#add_banner has the variable name 's' (Uncommunicative Name)
83
+ OptionParser#Switch#conv_arg calls conv multiple times (Duplication)
84
+ OptionParser#Switch#initialize has 7 parameters (Long Parameter List)
85
+ OptionParser#Switch#parse_arg calls pattern multiple times (Duplication)
86
+ OptionParser#Switch#parse_arg calls s.length multiple times (Duplication)
87
+ OptionParser#Switch#parse_arg has approx 11 statements (Long Method)
88
+ OptionParser#Switch#parse_arg has the variable name 'm' (Uncommunicative Name)
89
+ OptionParser#Switch#parse_arg has the variable name 's' (Uncommunicative Name)
90
+ OptionParser#Switch#self.guess has the variable name 't' (Uncommunicative Name)
91
+ OptionParser#Switch#self.incompatible_argument_styles has the variable name 't' (Uncommunicative Name)
92
+ OptionParser#Switch#summarize calls (indent + l) multiple times (Duplication)
93
+ OptionParser#Switch#summarize calls arg multiple times (Duplication)
94
+ OptionParser#Switch#summarize calls left.collect multiple times (Duplication)
95
+ OptionParser#Switch#summarize calls left.collect { |s| s.length }.max multiple times (Duplication)
96
+ OptionParser#Switch#summarize calls left.collect { |s| s.length }.max.to_i multiple times (Duplication)
97
+ OptionParser#Switch#summarize calls left.shift multiple times (Duplication)
98
+ OptionParser#Switch#summarize calls left[-1] multiple times (Duplication)
99
+ OptionParser#Switch#summarize calls s.length multiple times (Duplication)
100
+ OptionParser#Switch#summarize has 5 parameters (Long Parameter List)
101
+ OptionParser#Switch#summarize has approx 25 statements (Long Method)
102
+ OptionParser#Switch#summarize has the variable name 'l' (Uncommunicative Name)
103
+ OptionParser#Switch#summarize has the variable name 'r' (Uncommunicative Name)
104
+ OptionParser#Switch#summarize has the variable name 's' (Uncommunicative Name)
105
+ OptionParser#Switch#summarize refers to left more than self (Feature Envy)
106
+ OptionParser#Switch#summarize/block has the variable name 's' (Uncommunicative Name)
107
+ OptionParser#Switch#summarize/block/block is nested (Nested Iterators)
108
+ OptionParser#block has the variable name 'f' (Uncommunicative Name)
109
+ OptionParser#block has the variable name 'k' (Uncommunicative Name)
110
+ OptionParser#block has the variable name 'o' (Uncommunicative Name)
111
+ OptionParser#block has the variable name 's' (Uncommunicative Name)
112
+ OptionParser#block is controlled by argument o (Control Couple)
113
+ OptionParser#block is controlled by argument s (Control Couple)
114
+ OptionParser#block/block has the variable name 's' (Uncommunicative Name)
115
+ OptionParser#block/block has the variable name 'v' (Uncommunicative Name)
116
+ OptionParser#block/block is controlled by argument pkg (Control Couple)
117
+ OptionParser#block/block is nested (Nested Iterators)
118
+ OptionParser#complete has 4 parameters (Long Parameter List)
119
+ OptionParser#complete/block/block is nested (Nested Iterators)
120
+ OptionParser#getopts calls result[opt] = false multiple times (Duplication)
121
+ OptionParser#getopts has approx 17 statements (Long Method)
122
+ OptionParser#getopts/block is controlled by argument val (Control Couple)
123
+ OptionParser#load/block has the variable name 's' (Uncommunicative Name)
124
+ OptionParser#make_switch calls (long << o = q.downcase) multiple times (Duplication)
125
+ OptionParser#make_switch calls (sdesc << "-#{q}") multiple times (Duplication)
126
+ OptionParser#make_switch calls default_style.guess(arg = a) multiple times (Duplication)
127
+ OptionParser#make_switch calls notwice(NilClass, klass, "type") multiple times (Duplication)
128
+ OptionParser#make_switch calls notwice(a ? (Object) : (TrueClass), klass, "type") multiple times (Duplication)
129
+ OptionParser#make_switch calls pattern.method(:convert) multiple times (Duplication)
130
+ OptionParser#make_switch calls pattern.method(:convert).to_proc multiple times (Duplication)
131
+ OptionParser#make_switch calls pattern.respond_to?(:convert) multiple times (Duplication)
132
+ OptionParser#make_switch calls q.downcase multiple times (Duplication)
133
+ OptionParser#make_switch calls search(:atype, FalseClass) multiple times (Duplication)
134
+ OptionParser#make_switch calls search(:atype, o) multiple times (Duplication)
135
+ OptionParser#make_switch has approx 68 statements (Long Method)
136
+ OptionParser#make_switch has the variable name 'a' (Uncommunicative Name)
137
+ OptionParser#make_switch has the variable name 'n' (Uncommunicative Name)
138
+ OptionParser#make_switch has the variable name 'o' (Uncommunicative Name)
139
+ OptionParser#make_switch has the variable name 'q' (Uncommunicative Name)
140
+ OptionParser#make_switch has the variable name 's' (Uncommunicative Name)
141
+ OptionParser#make_switch/block has the variable name 'a' (Uncommunicative Name)
142
+ OptionParser#make_switch/block has the variable name 'o' (Uncommunicative Name)
143
+ OptionParser#make_switch/block has the variable name 'q' (Uncommunicative Name)
144
+ OptionParser#make_switch/block/block has the variable name 'c' (Uncommunicative Name)
145
+ OptionParser#make_switch/block/block has the variable name 'o' (Uncommunicative Name)
146
+ OptionParser#make_switch/block/block has the variable name 'v' (Uncommunicative Name)
147
+ OptionParser#make_switch/block/block is nested (Nested Iterators)
148
+ OptionParser#make_switch/block/block/block is nested (Nested Iterators)
149
+ OptionParser#order calls argv[0] multiple times (Duplication)
150
+ OptionParser#order refers to argv more than self (Feature Envy)
151
+ OptionParser#parse calls argv[0] multiple times (Duplication)
152
+ OptionParser#parse refers to argv more than self (Feature Envy)
153
+ OptionParser#parse_in_order calls $!.set_option(arg, true) multiple times (Duplication)
154
+ OptionParser#parse_in_order calls cb.call(val) multiple times (Duplication)
155
+ OptionParser#parse_in_order calls raise($!.set_option(arg, true)) multiple times (Duplication)
156
+ OptionParser#parse_in_order calls raise(*exc) multiple times (Duplication)
157
+ OptionParser#parse_in_order calls setter.call(sw.switch_name, val) multiple times (Duplication)
158
+ OptionParser#parse_in_order calls sw.block multiple times (Duplication)
159
+ OptionParser#parse_in_order calls sw.switch_name multiple times (Duplication)
160
+ OptionParser#parse_in_order has approx 28 statements (Long Method)
161
+ OptionParser#parse_in_order/block is controlled by argument setter (Control Couple)
162
+ OptionParser#parse_in_order/block/block is nested (Nested Iterators)
163
+ OptionParser#parse_in_order/block/block/block is nested (Nested Iterators)
164
+ OptionParser#permute calls argv[0] multiple times (Duplication)
165
+ OptionParser#permute refers to argv more than self (Feature Envy)
166
+ OptionParser#search/block has the variable name 'k' (Uncommunicative Name)
167
+ OptionParser#summarize has 4 parameters (Long Parameter List)
168
+ OptionParser#summarize/block has the variable name 'l' (Uncommunicative Name)
169
+ OptionParser#ver has the variable name 'v' (Uncommunicative Name)
170
+ block has the variable name 'q' (Uncommunicative Name)
171
+
172
+ """
173
+
174
+ Scenario: Correct smells from redcloth.rb
175
+ When I run reek spec/samples/redcloth.rb
176
+ Then it fails with exit status 2
177
+ And it reports:
178
+ """
179
+ spec/samples/redcloth.rb -- 93 warnings:
180
+ RedCloth has at least 44 methods (Large Class)
181
+ RedCloth#block has the variable name 'a' (Uncommunicative Name)
182
+ RedCloth#block has the variable name 'b' (Uncommunicative Name)
183
+ RedCloth#block_markdown_atx refers to text more than self (Feature Envy)
184
+ RedCloth#block_markdown_bq has approx 6 statements (Long Method)
185
+ RedCloth#block_markdown_rule doesn't depend on instance state (Utility Function)
186
+ RedCloth#block_markdown_rule refers to text more than self (Feature Envy)
187
+ RedCloth#block_markdown_setext refers to text more than self (Feature Envy)
188
+ RedCloth#block_textile_lists calls (line_id - 1) multiple times (Duplication)
189
+ RedCloth#block_textile_lists calls depth.last multiple times (Duplication)
190
+ RedCloth#block_textile_lists calls depth.last.length multiple times (Duplication)
191
+ RedCloth#block_textile_lists calls depth[i] multiple times (Duplication)
192
+ RedCloth#block_textile_lists calls lines[(line_id - 1)] multiple times (Duplication)
193
+ RedCloth#block_textile_lists calls tl.length multiple times (Duplication)
194
+ RedCloth#block_textile_lists has approx 20 statements (Long Method)
195
+ RedCloth#block_textile_lists refers to depth more than self (Feature Envy)
196
+ RedCloth#block_textile_lists/block/block is nested (Nested Iterators)
197
+ RedCloth#block_textile_lists/block/block/block has the variable name 'i' (Uncommunicative Name)
198
+ RedCloth#block_textile_lists/block/block/block has the variable name 'v' (Uncommunicative Name)
199
+ RedCloth#block_textile_lists/block/block/block is nested (Nested Iterators)
200
+ RedCloth#block_textile_table has approx 18 statements (Long Method)
201
+ RedCloth#block_textile_table/block/block has the variable name 'x' (Uncommunicative Name)
202
+ RedCloth#block_textile_table/block/block is nested (Nested Iterators)
203
+ RedCloth#block_textile_table/block/block/block is nested (Nested Iterators)
204
+ RedCloth#blocks has approx 18 statements (Long Method)
205
+ RedCloth#blocks/block is controlled by argument deep_code (Control Couple)
206
+ RedCloth#blocks/block/block is nested (Nested Iterators)
207
+ RedCloth#check_refs is controlled by argument text (Control Couple)
208
+ RedCloth#clean_html calls tags[tag] multiple times (Duplication)
209
+ RedCloth#clean_html doesn't depend on instance state (Utility Function)
210
+ RedCloth#clean_html has approx 14 statements (Long Method)
211
+ RedCloth#clean_html refers to raw more than self (Feature Envy)
212
+ RedCloth#clean_html refers to tags more than self (Feature Envy)
213
+ RedCloth#clean_html/block/block is nested (Nested Iterators)
214
+ RedCloth#clean_html/block/block/block has the variable name 'q' (Uncommunicative Name)
215
+ RedCloth#clean_html/block/block/block has the variable name 'q2' (Uncommunicative Name)
216
+ RedCloth#clean_html/block/block/block is nested (Nested Iterators)
217
+ RedCloth#clean_white_space has approx 7 statements (Long Method)
218
+ RedCloth#clean_white_space refers to text more than self (Feature Envy)
219
+ RedCloth#flush_left doesn't depend on instance state (Utility Function)
220
+ RedCloth#flush_left refers to indt more than self (Feature Envy)
221
+ RedCloth#flush_left refers to text more than self (Feature Envy)
222
+ RedCloth#footnote_ref doesn't depend on instance state (Utility Function)
223
+ RedCloth#footnote_ref refers to text more than self (Feature Envy)
224
+ RedCloth#glyphs_textile has approx 10 statements (Long Method)
225
+ RedCloth#h_align doesn't depend on instance state (Utility Function)
226
+ RedCloth#htmlesc doesn't depend on instance state (Utility Function)
227
+ RedCloth#htmlesc refers to str more than self (Feature Envy)
228
+ RedCloth#incoming_entities doesn't depend on instance state (Utility Function)
229
+ RedCloth#incoming_entities refers to text more than self (Feature Envy)
230
+ RedCloth#initialize/block has the variable name 'r' (Uncommunicative Name)
231
+ RedCloth#inline/block/block is nested (Nested Iterators)
232
+ RedCloth#inline_markdown_link has approx 6 statements (Long Method)
233
+ RedCloth#inline_markdown_link/block has the variable name 'm' (Uncommunicative Name)
234
+ RedCloth#inline_markdown_reflink has approx 8 statements (Long Method)
235
+ RedCloth#inline_markdown_reflink/block has the variable name 'm' (Uncommunicative Name)
236
+ RedCloth#inline_textile_code/block has the variable name 'm' (Uncommunicative Name)
237
+ RedCloth#inline_textile_image has approx 17 statements (Long Method)
238
+ RedCloth#inline_textile_image/block has the variable name 'm' (Uncommunicative Name)
239
+ RedCloth#inline_textile_link has approx 9 statements (Long Method)
240
+ RedCloth#inline_textile_link/block has the variable name 'm' (Uncommunicative Name)
241
+ RedCloth#inline_textile_span has approx 8 statements (Long Method)
242
+ RedCloth#inline_textile_span/block/block has the variable name 'm' (Uncommunicative Name)
243
+ RedCloth#inline_textile_span/block/block is nested (Nested Iterators)
244
+ RedCloth#no_textile doesn't depend on instance state (Utility Function)
245
+ RedCloth#no_textile refers to text more than self (Feature Envy)
246
+ RedCloth#pba calls $1.length multiple times (Duplication)
247
+ RedCloth#pba has approx 21 statements (Long Method)
248
+ RedCloth#pba is controlled by argument text_in (Control Couple)
249
+ RedCloth#pba refers to style more than self (Feature Envy)
250
+ RedCloth#pba refers to text more than self (Feature Envy)
251
+ RedCloth#refs_markdown/block has the variable name 'm' (Uncommunicative Name)
252
+ RedCloth#refs_textile/block has the variable name 'm' (Uncommunicative Name)
253
+ RedCloth#retrieve/block has the variable name 'i' (Uncommunicative Name)
254
+ RedCloth#retrieve/block has the variable name 'r' (Uncommunicative Name)
255
+ RedCloth#rip_offtags calls ((codepre - used_offtags.length) > 0) multiple times (Duplication)
256
+ RedCloth#rip_offtags calls (@pre_list.last << line) multiple times (Duplication)
257
+ RedCloth#rip_offtags calls (codepre - used_offtags.length) multiple times (Duplication)
258
+ RedCloth#rip_offtags calls @pre_list.last multiple times (Duplication)
259
+ RedCloth#rip_offtags calls codepre.zero? multiple times (Duplication)
260
+ RedCloth#rip_offtags calls htmlesc(line, :NoQuotes) multiple times (Duplication)
261
+ RedCloth#rip_offtags calls used_offtags.length multiple times (Duplication)
262
+ RedCloth#rip_offtags calls used_offtags["notextile"] multiple times (Duplication)
263
+ RedCloth#rip_offtags has approx 18 statements (Long Method)
264
+ RedCloth#textile_bq has 4 parameters (Long Parameter List)
265
+ RedCloth#textile_bq is controlled by argument atts (Control Couple)
266
+ RedCloth#textile_bq is controlled by argument cite (Control Couple)
267
+ RedCloth#textile_fn_ has 5 parameters (Long Parameter List)
268
+ RedCloth#textile_fn_ is controlled by argument atts (Control Couple)
269
+ RedCloth#textile_p has 4 parameters (Long Parameter List)
270
+ RedCloth#textile_p is controlled by argument atts (Control Couple)
271
+ RedCloth#to_html has approx 24 statements (Long Method)
272
+ RedCloth#v_align doesn't depend on instance state (Utility Function)
273
+
274
+ """
@@ -0,0 +1,34 @@
1
+ @stdin
2
+ Feature: Reek reads from $stdin when no files are given
3
+ In order to use reek with pipelines
4
+ As a developer
5
+ I want to pipe source code on stdin
6
+
7
+ Scenario: return zero status with no smells
8
+ When I pass "def simple() @fred = 3 end" to reek
9
+ Then it succeeds
10
+ And it reports:
11
+ """
12
+ $stdin -- 0 warnings
13
+
14
+ """
15
+
16
+ Scenario: outputs nothing on empty stdin
17
+ When I pass "" to reek
18
+ Then it succeeds
19
+ And it reports:
20
+ """
21
+ $stdin -- 0 warnings
22
+
23
+ """
24
+
25
+ Scenario: return non-zero status when there are smells
26
+ When I pass "class Turn; def y() @x = 3; end end" to reek
27
+ Then it fails with exit status 2
28
+ And it reports:
29
+ """
30
+ $stdin -- 2 warnings:
31
+ Turn has the variable name '@x' (Uncommunicative Name)
32
+ Turn#y has the name 'y' (Uncommunicative Name)
33
+
34
+ """
@@ -0,0 +1,35 @@
1
+ When /^I run reek (.*)$/ do |args|
2
+ run args
3
+ end
4
+
5
+ When /^I pass "([^\"]*)" to reek$/ do |stdin|
6
+ run_with_pipe stdin
7
+ end
8
+
9
+ When /^I run rake reek$/ do
10
+ rake
11
+ end
12
+
13
+ Then /^stdout equals "([^\"]*)"$/ do |report|
14
+ @last_stdout.should == report
15
+ end
16
+
17
+ Then /^it succeeds$/ do
18
+ @last_exit_status.should == 0
19
+ end
20
+
21
+ Then /^it fails with exit status (\d+)$/ do |status|
22
+ @last_exit_status.should == status.to_i
23
+ end
24
+
25
+ Then /^it reports:$/ do |report|
26
+ @last_stdout.should == report
27
+ end
28
+
29
+ Then /^it reports the error ['"](.*)['"]$/ do |string|
30
+ @last_stderr.chomp.should == string
31
+ end
32
+
33
+ Then /^it reports the current version$/ do
34
+ @last_stdout.chomp.should == "reek #{Reek::VERSION}"
35
+ end
@@ -0,0 +1,38 @@
1
+ $:.unshift 'lib'
2
+
3
+ require 'rubygems'
4
+ require 'tempfile'
5
+ require 'spec/expectations'
6
+ require 'fileutils'
7
+ require 'reek'
8
+
9
+ class CucumberWorld
10
+
11
+ def run(args)
12
+ stderr_file = Tempfile.new('cucumber')
13
+ stderr_file.close
14
+ @last_stdout = `ruby -Ilib bin/reek #{args} 2> #{stderr_file.path}`
15
+ @last_exit_status = $?.exitstatus
16
+ @last_stderr = IO.read(stderr_file.path)
17
+ end
18
+
19
+ def run_with_pipe(stdin)
20
+ stderr_file = Tempfile.new('cucumber')
21
+ stderr_file.close
22
+ @last_stdout = `echo \"#{stdin}\" | ruby -Ilib bin/reek 2> #{stderr_file.path}`
23
+ @last_exit_status = $?.exitstatus
24
+ @last_stderr = IO.read(stderr_file.path)
25
+ end
26
+
27
+ def rake
28
+ stderr_file = Tempfile.new('cucumber')
29
+ stderr_file.close
30
+ @last_stdout = `rake reek 2> #{stderr_file.path}`
31
+ @last_exit_status = $?.exitstatus
32
+ @last_stderr = IO.read(stderr_file.path)
33
+ end
34
+ end
35
+
36
+ World do
37
+ CucumberWorld.new
38
+ end
data/lib/reek/options.rb CHANGED
@@ -42,15 +42,11 @@ EOB
42
42
  end
43
43
 
44
44
  def self.parse(args)
45
- begin
46
- @@opts = parse_args(args)
47
- if args.length > 0
48
- return Source.from_pathlist(args)
49
- else
50
- return Source.from_io($stdin, 'stdin')
51
- end
52
- rescue OptionParser::ParseError, SystemCallError => err
53
- fatal_error(err)
45
+ @@opts = parse_args(args)
46
+ if args.length > 0
47
+ return Source.from_pathlist(args)
48
+ else
49
+ return Source.from_io($stdin, '$stdin')
54
50
  end
55
51
  end
56
52
 
@@ -81,12 +77,5 @@ EOB
81
77
  config[:format] = SMELL_SORT
82
78
  end
83
79
  end
84
-
85
- def self.fatal_error(err) # :nodoc:
86
- puts "Error: #{err}"
87
- puts "Use '-h' for help."
88
- exit(1)
89
- end
90
-
91
80
  end
92
81
  end
data/lib/reek/report.rb CHANGED
@@ -55,7 +55,7 @@ module Reek
55
55
  end
56
56
 
57
57
  def header(desc, num_smells)
58
- result = "\"#{desc}\" -- #{num_smells} warning"
58
+ result = "#{desc} -- #{num_smells} warning"
59
59
  result += 's' unless num_smells == 1
60
60
  result += " (+#{@masked_smells.length} masked)" unless @masked_smells.empty?
61
61
  result
@@ -94,8 +94,8 @@ module Reek
94
94
  @sources.select {|src| src.smelly? }
95
95
  end
96
96
 
97
- def to_s
98
- @sources.map { |src| src.full_report }.join("\n")
97
+ def full_report
98
+ @sources.map { |src| src.full_report }.join
99
99
  end
100
100
  end
101
101
  end
data/lib/reek/sniffer.rb CHANGED
@@ -76,7 +76,10 @@ module Reek
76
76
  # +config_file+.
77
77
  #
78
78
  def configure_with(config_file)
79
- YAML.load_file(config_file).push_keys(@config)
79
+ hash = YAML.load_file(config_file)
80
+ return unless hash
81
+ raise "invalid configuration file \"#{File.basename(config_file)}\"" unless Hash === hash
82
+ hash.push_keys(@config)
80
83
  end
81
84
 
82
85
  def disable(smell)
data/lib/reek/source.rb CHANGED
@@ -118,6 +118,10 @@ module Reek
118
118
  @sources.any? {|source| source.smelly? }
119
119
  end
120
120
 
121
+ def full_report
122
+ ReportList.new(@sources).full_report
123
+ end
124
+
121
125
  def report
122
126
  ReportList.new(@sources)
123
127
  end
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.4'
4
+ VERSION = '1.1.3.5'
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.4"
5
+ s.version = "1.1.3.5"
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-06-19}
9
+ s.date = %q{2009-06-29}
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
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/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/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/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"]
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/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/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/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/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/rspec.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
@@ -0,0 +1 @@
1
+ This is not a config file
@@ -0,0 +1,7 @@
1
+ class Dirty
2
+ def a
3
+ puts @s.title
4
+ @s.map {|x| x.each {|key| key += 3}}
5
+ puts @s.title
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ class Dirty
2
+ def a
3
+ puts @s.title
4
+ @s.map {|x| x.each {|key| key += 3}}
5
+ puts @s.title
6
+ end
7
+ end
File without changes
File without changes
@@ -0,0 +1,7 @@
1
+ class Dirty
2
+ def a
3
+ puts @s.title
4
+ @s.map {|x| x.each {|key| key += 3}}
5
+ puts @s.title
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ ---
2
+ UncommunicativeName:
3
+ enabled: false
File without changes
File without changes
@@ -0,0 +1,7 @@
1
+ class Dirty
2
+ def a
3
+ puts @s.title
4
+ @s.map {|x| x.each {|key| key += 3}}
5
+ puts @s.title
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ class Dirty
2
+ def a
3
+ puts @s.title
4
+ @s.map {|x| x.each {|key| key += 3}}
5
+ puts @s.title
6
+ end
7
+ end
@@ -11,10 +11,3 @@ describe 'Reek source code:' do
11
11
  Dir['lib/**/*.rb'].should_not reek
12
12
  end
13
13
  end
14
-
15
- describe 'RakeTask' do
16
- it 'should report no duplication' do
17
- report = `rake reek`.split("\n")
18
- report.length.should == 1
19
- end
20
- end
data/spec/spec_helper.rb CHANGED
@@ -10,4 +10,4 @@ end
10
10
 
11
11
  require 'reek/spec'
12
12
 
13
- SAMPLES_DIR = 'spec/slow/samples' unless Object.const_defined?('SAMPLES_DIR')
13
+ SAMPLES_DIR = 'spec/samples' unless Object.const_defined?('SAMPLES_DIR')
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kevinrutherford-reek
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.3.4
4
+ version: 1.1.3.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Rutherford
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-06-19 00:00:00 -07:00
12
+ date: 2009-06-29 00:00:00 -07:00
13
13
  default_executable: reek
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -58,6 +58,14 @@ files:
58
58
  - Rakefile
59
59
  - bin/reek
60
60
  - config/defaults.reek
61
+ - features/masking_smells.feature
62
+ - features/options.feature
63
+ - features/rake_task.feature
64
+ - features/reports.feature
65
+ - features/samples.feature
66
+ - features/stdin.feature
67
+ - features/step_definitions/reek_steps.rb
68
+ - features/support/env.rb
61
69
  - lib/reek.rb
62
70
  - lib/reek/block_context.rb
63
71
  - lib/reek/class_context.rb
@@ -117,14 +125,21 @@ files:
117
125
  - spec/reek/smells/smell_detector_spec.rb
118
126
  - spec/reek/smells/uncommunicative_name_spec.rb
119
127
  - spec/reek/smells/utility_function_spec.rb
128
+ - spec/samples/corrupt_config_file/corrupt.reek
129
+ - spec/samples/corrupt_config_file/dirty.rb
130
+ - spec/samples/empty_config_file/dirty.rb
131
+ - spec/samples/empty_config_file/empty.reek
132
+ - spec/samples/inline.rb
133
+ - spec/samples/masked/dirty.rb
134
+ - spec/samples/masked/masked.reek
135
+ - spec/samples/optparse.rb
136
+ - spec/samples/redcloth.rb
137
+ - spec/samples/two_smelly_files/dirty_one.rb
138
+ - spec/samples/two_smelly_files/dirty_two.rb
120
139
  - spec/slow/inline_spec.rb
121
140
  - spec/slow/optparse_spec.rb
122
141
  - spec/slow/redcloth_spec.rb
123
142
  - spec/slow/reek_source_spec.rb
124
- - spec/slow/samples/inline.rb
125
- - spec/slow/samples/optparse.rb
126
- - spec/slow/samples/redcloth.rb
127
- - spec/slow/script_spec.rb
128
143
  - spec/slow/source_list_spec.rb
129
144
  - spec/spec.opts
130
145
  - spec/spec_helper.rb
@@ -1,55 +0,0 @@
1
- require 'reek'
2
-
3
- describe 'version number' do
4
- it 'should report the correct value' do
5
- actual = `ruby -Ilib bin/reek --version`.split
6
- $?.exitstatus.should == 0
7
- actual[0].should == 'reek'
8
- actual[1].should == Reek::VERSION
9
- end
10
- end
11
-
12
- describe 'exit status', 'when reek is used incorrectly' do
13
- it 'should return non-zero status on bad option' do
14
- `ruby -Ilib bin/reek --no-such-option`
15
- $?.exitstatus.should == 1
16
- end
17
-
18
- it 'should complain about missing file' do
19
- `ruby -Ilib bin/reek nosuchfile.rb`
20
- $?.exitstatus.should == 1
21
- end
22
-
23
- it 'should return non-zero status on missing argument' do
24
- `ruby -Ilib bin/reek -f 2>/dev/null`
25
- $?.exitstatus.should == 1
26
- end
27
- end
28
-
29
- describe 'exit status', 'when reek is used correctly' do
30
- it 'should return non-zero status when smells are reported' do
31
- `echo "def x() 3; end" | ruby -Ilib bin/reek`
32
- $?.exitstatus.should == 2
33
- end
34
-
35
- it 'should return zero status with no smells' do
36
- `echo "def simple() @fred = 3 end" | ruby -Ilib bin/reek`
37
- $?.exitstatus.should == 0
38
- end
39
- end
40
-
41
- describe 'report format', 'with one source' do
42
- it 'should output nothing with empty source' do
43
- `echo "" | ruby -Ilib bin/reek`.should be_empty
44
- end
45
-
46
- it 'should output nothing when no smells' do
47
- `echo "def simple() @fred = 3; end" | ruby -Ilib bin/reek`.should be_empty
48
- end
49
-
50
- it 'should not adorn the list of warnings' do
51
- report = `echo "class Turn; def y() @x = 3; end end" | ruby -Ilib bin/reek`
52
- report.split(/\n/).length.should == 2
53
- report.should_not match(/\n\n/)
54
- end
55
- end