kevinrutherford-reek 1.1.3.4 → 1.1.3.5

Sign up to get free protection for your applications and to get access to all the features.
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