reek 1.3.6 → 1.3.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +6 -0
  3. data/README.md +11 -1
  4. data/config/defaults.reek +1 -0
  5. data/features/command_line_interface/options.feature +1 -0
  6. data/features/rake_task/rake_task.feature +3 -0
  7. data/features/ruby_api/api.feature +1 -3
  8. data/features/samples.feature +27 -20
  9. data/features/support/env.rb +2 -2
  10. data/lib/reek/cli/application.rb +0 -4
  11. data/lib/reek/cli/command_line.rb +10 -12
  12. data/lib/reek/cli/reek_command.rb +1 -1
  13. data/lib/reek/cli/report.rb +36 -8
  14. data/lib/reek/config_file_exception.rb +3 -0
  15. data/lib/reek/core/code_context.rb +18 -8
  16. data/lib/reek/core/code_parser.rb +65 -61
  17. data/lib/reek/core/method_context.rb +4 -0
  18. data/lib/reek/core/module_context.rb +2 -2
  19. data/lib/reek/core/smell_repository.rb +3 -0
  20. data/lib/reek/core/sniffer.rb +0 -1
  21. data/lib/reek/core/stop_context.rb +1 -1
  22. data/lib/reek/smells/attribute.rb +1 -1
  23. data/lib/reek/smells/control_parameter.rb +79 -45
  24. data/lib/reek/smells/data_clump.rb +1 -1
  25. data/lib/reek/smells/duplicate_method_call.rb +1 -1
  26. data/lib/reek/smells/long_parameter_list.rb +1 -1
  27. data/lib/reek/smells/long_yield_list.rb +1 -1
  28. data/lib/reek/smells/nested_iterators.rb +1 -1
  29. data/lib/reek/smells/nil_check.rb +10 -5
  30. data/lib/reek/smells/repeated_conditional.rb +1 -1
  31. data/lib/reek/smells/smell_detector.rb +2 -3
  32. data/lib/reek/smells/too_many_instance_variables.rb +1 -1
  33. data/lib/reek/smells/too_many_methods.rb +1 -1
  34. data/lib/reek/smells/too_many_statements.rb +1 -1
  35. data/lib/reek/smells/uncommunicative_method_name.rb +4 -4
  36. data/lib/reek/smells/uncommunicative_module_name.rb +4 -4
  37. data/lib/reek/smells/uncommunicative_parameter_name.rb +9 -9
  38. data/lib/reek/smells/uncommunicative_variable_name.rb +1 -1
  39. data/lib/reek/smells/unused_parameters.rb +2 -6
  40. data/lib/reek/smells/utility_function.rb +1 -1
  41. data/lib/reek/source/code_comment.rb +1 -1
  42. data/lib/reek/source/config_file.rb +9 -8
  43. data/lib/reek/source/sexp_extensions.rb +2 -2
  44. data/lib/reek/source/sexp_node.rb +8 -5
  45. data/lib/reek/source/source_repository.rb +5 -0
  46. data/lib/reek/version.rb +1 -1
  47. data/reek.gemspec +3 -2
  48. data/spec/reek/cli/report_spec.rb +38 -8
  49. data/spec/reek/core/code_context_spec.rb +35 -3
  50. data/spec/reek/core/module_context_spec.rb +1 -1
  51. data/spec/reek/smells/repeated_conditional_spec.rb +1 -1
  52. data/spec/reek/smells/smell_detector_shared.rb +1 -2
  53. data/spec/reek/smells/too_many_statements_spec.rb +39 -25
  54. data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +44 -30
  55. data/spec/reek/smells/unused_parameters_spec.rb +15 -11
  56. data/spec/reek/source/sexp_extensions_spec.rb +2 -2
  57. data/spec/reek/source/sexp_node_spec.rb +0 -1
  58. data/spec/samples/ruby20_syntax.rb +1 -5
  59. metadata +172 -162
  60. data/lib/reek/cli/yaml_command.rb +0 -32
  61. data/lib/reek/core/hash_extensions.rb +0 -29
  62. data/spec/reek/cli/yaml_command_spec.rb +0 -47
  63. data/spec/reek/core/config_spec.rb +0 -38
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cd6196b99429388642049ac970d159ca81066a08
4
- data.tar.gz: 45ec008b56f8a42ca8edeaa9951ecc8b03fd5d7c
3
+ metadata.gz: a655ae03def5604c059ac663e271eecc1a18d461
4
+ data.tar.gz: 6f6c21e7d712a339e649ad91eabefea90c5a6d13
5
5
  SHA512:
6
- metadata.gz: a09c19c44892cd6d2b8cc82b0fa82c8563fbed0c8734b8f12dfbb5906c223b664ab15e95cdeea8d2270004e06a182968d161bd644a044b157236e69141b8be80
7
- data.tar.gz: a6ff074ebe7abd1a2029ffd6a3f04571ee75beb5709cef297a221bc37b3427fa84c5d53de767ccecf2f248e70a0cdf75fb8e363eb776ddec0b0aa9f1d2018c93
6
+ metadata.gz: 637e3a7af79aee3dd3d7e107d9de35ab2bac39b90f015b58ae8b21cd852a12613a7085d5217eb701ef0b78baa2f517566d21906006eba841dcc77e722ff6d171
7
+ data.tar.gz: 1f6f1923e86614fcb73d77e6a36e3c4f977db3bba059b785904042f27fa8fe7fecc5f568128597c432ee5ca42ea7b9c3ce5039b256f13bd87f46228136438d3d
data/CHANGELOG CHANGED
@@ -1,3 +1,9 @@
1
+ == 1.3.7
2
+
3
+ * (gilles-leblanc) Add color to reek's output
4
+ * (mvz) Ignore unused parameters if method calls super in nested context
5
+ * (mvz) Only mark parameters uncommunicative if used
6
+
1
7
  == 1.3.6
2
8
 
3
9
  * (troessner) Add `Prima Donna Method` smell
data/README.md CHANGED
@@ -1,9 +1,16 @@
1
1
  # Reek -- code smell detection for Ruby
2
2
 
3
- ##Overview
3
+
4
+ ### Overview
5
+
4
6
 
5
7
  [![Build Status](https://secure.travis-ci.org/troessner/reek.png?branch=master)](http://travis-ci.org/troessner/reek?branch=master)
6
8
  [![Gem Version](https://badge.fury.io/rb/reek.png)](http://badge.fury.io/rb/reek)
9
+ [![Dependency Status](https://gemnasium.com/troessner/reek.png)](https://gemnasium.com/troessner/reek)
10
+ [![Inline docs](http://inch-pages.github.io/github/troessner/reek.png)](http://inch-pages.github.io/github/troessner/reek)
11
+
12
+
13
+ ### Synopsis
7
14
 
8
15
 
9
16
  Reek is a tool that examines Ruby classes, modules and methods and
@@ -131,6 +138,8 @@ There's a vim plugin for `reek`: [https://github.com/rainerborene/vim-reek](http
131
138
 
132
139
  TextMate Bundle for `reek`: [https://github.com/peeyush1234/reek.tmbundle](https://github.com/peeyush1234/reek.tmbundle)
133
140
 
141
+ Colorful output for `reek`: [Preek](https://github.com/joenas/preek) (also with [Guard::Preek](https://github.com/joenas/guard-preek))
142
+
134
143
  ### Dependencies
135
144
 
136
145
  Reek makes use of the following other gems:
@@ -138,6 +147,7 @@ Reek makes use of the following other gems:
138
147
  * ruby_parser
139
148
  * sexp_processor
140
149
  * ruby2ruby
150
+ * rainbow
141
151
 
142
152
  ### Learn More
143
153
 
data/config/defaults.reek CHANGED
@@ -89,6 +89,7 @@ UncommunicativeParameterName:
89
89
  - !ruby/regexp /^.$/
90
90
  - !ruby/regexp /[0-9]$/
91
91
  - !ruby/regexp /[A-Z]/
92
+ - !ruby/regexp /^_/
92
93
  accept: []
93
94
  UncommunicativeVariableName:
94
95
  enabled: true
@@ -38,6 +38,7 @@ Feature: Reek can be controlled using command-line options
38
38
  -c, --config FILE Read configuration options from FILE
39
39
 
40
40
  Report formatting:
41
+ -o, --[no-]color Use colors for the output (this is the default)
41
42
  -q, --quiet Suppress headings for smell-free source files (this is the default)
42
43
  -V, --no-quiet, --verbose Show headings for smell-free source files
43
44
  -n, --no-line-numbers Suppress line numbers from the output
@@ -8,6 +8,7 @@ Feature: Reek can be driven through its Task
8
8
  """
9
9
  Reek::Rake::Task.new do |t|
10
10
  t.source_files = 'spec/samples/masked/dirty.rb'
11
+ t.reek_opts = '--no-color'
11
12
  end
12
13
  """
13
14
  Then the exit status indicates an error
@@ -24,6 +25,7 @@ Feature: Reek can be driven through its Task
24
25
  """
25
26
  Reek::Rake::Task.new('silky') do |t|
26
27
  t.source_files = 'spec/samples/masked/dirty.rb'
28
+ t.reek_opts = '--no-color'
27
29
  end
28
30
  """
29
31
  Then the exit status indicates an error
@@ -52,6 +54,7 @@ Feature: Reek can be driven through its Task
52
54
  Reek::Rake::Task.new do |t|
53
55
  t.fail_on_error = false
54
56
  t.source_files = 'spec/samples/no_config_file/dirty.rb'
57
+ t.reek_opts = '--no-color'
55
58
  end
56
59
  """
57
60
  Then it reports no errors
@@ -9,12 +9,10 @@ Feature: The Reek API maintains backwards compatibility
9
9
  Then the exit status indicates smells
10
10
  And it reports:
11
11
  """
12
- spec/samples/demo/demo.rb -- 10 warnings:
12
+ spec/samples/demo/demo.rb -- 8 warnings:
13
13
  [1]:Dirty has no descriptive comment (IrresponsibleModule)
14
14
  [3]:Dirty#awful has 4 parameters (LongParameterList)
15
15
  [3]:Dirty#awful has boolean parameter 'log' (BooleanParameter)
16
- [3]:Dirty#awful has the parameter name 'x' (UncommunicativeParameterName)
17
- [3]:Dirty#awful has the parameter name 'y' (UncommunicativeParameterName)
18
16
  [5]:Dirty#awful has the variable name 'w' (UncommunicativeVariableName)
19
17
  [3]:Dirty#awful has unused parameter 'log' (UnusedParameters)
20
18
  [3]:Dirty#awful has unused parameter 'offset' (UnusedParameters)
@@ -10,8 +10,9 @@ Feature: Basic smell detection
10
10
  Then the exit status indicates smells
11
11
  And it reports:
12
12
  """
13
- spec/samples/inline.rb -- 39 warnings:
13
+ spec/samples/inline.rb -- 41 warnings:
14
14
  File has no descriptive comment (IrresponsibleModule)
15
+ File#self.write_with_backup has approx 6 statements (TooManyStatements)
15
16
  Inline declares the class variable @@directory (ClassVariable)
16
17
  Inline declares the class variable @@rootdir (ClassVariable)
17
18
  Inline#self.rootdir calls env.nil? twice (DuplicateMethodCall)
@@ -30,7 +31,7 @@ Feature: Basic smell detection
30
31
  Inline::C#build calls io.puts("#ifdef __cplusplus") twice (DuplicateMethodCall)
31
32
  Inline::C#build calls warn("Output:\n#{result}") twice (DuplicateMethodCall)
32
33
  Inline::C#build contains iterators nested 2 deep (NestedIterators)
33
- Inline::C#build has approx 60 statements (TooManyStatements)
34
+ Inline::C#build has approx 63 statements (TooManyStatements)
34
35
  Inline::C#build has the variable name 'n' (UncommunicativeVariableName)
35
36
  Inline::C#build has the variable name 't' (UncommunicativeVariableName)
36
37
  Inline::C#c has the name 'c' (UncommunicativeMethodName)
@@ -38,18 +39,19 @@ Feature: Basic smell detection
38
39
  Inline::C#generate calls result.sub!(/\A\n/, "") twice (DuplicateMethodCall)
39
40
  Inline::C#generate calls signature["args"] twice (DuplicateMethodCall)
40
41
  Inline::C#generate calls signature["args"].map twice (DuplicateMethodCall)
41
- Inline::C#generate has approx 32 statements (TooManyStatements)
42
+ Inline::C#generate has approx 35 statements (TooManyStatements)
42
43
  Inline::C#initialize calls stack.empty? twice (DuplicateMethodCall)
44
+ Inline::C#module_name has approx 7 statements (TooManyStatements)
43
45
  Inline::C#module_name has the variable name 'm' (UncommunicativeVariableName)
44
46
  Inline::C#module_name has the variable name 'x' (UncommunicativeVariableName)
45
- Inline::C#parse_signature has approx 15 statements (TooManyStatements)
47
+ Inline::C#parse_signature has approx 16 statements (TooManyStatements)
46
48
  Inline::C#parse_signature has boolean parameter 'raw' (BooleanParameter)
47
49
  Inline::C#parse_signature has the variable name 'x' (UncommunicativeVariableName)
48
50
  Inline::C#parse_signature is controlled by argument raw (ControlParameter)
49
51
  Inline::C#strip_comments doesn't depend on instance state (UtilityFunction)
50
52
  Inline::C#strip_comments refers to src more than self (FeatureEnvy)
51
53
  Module#inline calls Inline.const_get(lang) twice (DuplicateMethodCall)
52
- Module#inline has approx 11 statements (TooManyStatements)
54
+ Module#inline has approx 12 statements (TooManyStatements)
53
55
  """
54
56
 
55
57
  Scenario: Correct smells from optparse.rb
@@ -57,7 +59,7 @@ Feature: Basic smell detection
57
59
  Then the exit status indicates smells
58
60
  And it reports:
59
61
  """
60
- spec/samples/optparse.rb -- 103 warnings:
62
+ spec/samples/optparse.rb -- 108 warnings:
61
63
  OptionParser has at least 42 methods (TooManyMethods)
62
64
  OptionParser has the variable name 'f' (UncommunicativeVariableName)
63
65
  OptionParser has the variable name 'k' (UncommunicativeVariableName)
@@ -71,9 +73,11 @@ Feature: Basic smell detection
71
73
  OptionParser tests s at least 7 times (RepeatedConditional)
72
74
  OptionParser#complete contains iterators nested 2 deep (NestedIterators)
73
75
  OptionParser#complete has 4 parameters (LongParameterList)
76
+ OptionParser#complete has approx 6 statements (TooManyStatements)
74
77
  OptionParser#complete has boolean parameter 'icase' (BooleanParameter)
75
78
  OptionParser#getopts calls result[opt] = false twice (DuplicateMethodCall)
76
- OptionParser#getopts has approx 17 statements (TooManyStatements)
79
+ OptionParser#getopts has approx 18 statements (TooManyStatements)
80
+ OptionParser#load has approx 6 statements (TooManyStatements)
77
81
  OptionParser#load has the variable name 's' (UncommunicativeVariableName)
78
82
  OptionParser#make_switch calls (long << (o = q.downcase)) twice (DuplicateMethodCall)
79
83
  OptionParser#make_switch calls (sdesc << "-#{q}") twice (DuplicateMethodCall)
@@ -87,7 +91,7 @@ Feature: Basic smell detection
87
91
  OptionParser#make_switch calls search(:atype, FalseClass) twice (DuplicateMethodCall)
88
92
  OptionParser#make_switch calls search(:atype, o) 6 times (DuplicateMethodCall)
89
93
  OptionParser#make_switch contains iterators nested 3 deep (NestedIterators)
90
- OptionParser#make_switch has approx 68 statements (TooManyStatements)
94
+ OptionParser#make_switch has approx 72 statements (TooManyStatements)
91
95
  OptionParser#make_switch has the variable name 'a' (UncommunicativeVariableName)
92
96
  OptionParser#make_switch has the variable name 'c' (UncommunicativeVariableName)
93
97
  OptionParser#make_switch has the variable name 'n' (UncommunicativeVariableName)
@@ -108,19 +112,21 @@ Feature: Basic smell detection
108
112
  OptionParser#parse_in_order calls sw.block twice (DuplicateMethodCall)
109
113
  OptionParser#parse_in_order calls sw.switch_name twice (DuplicateMethodCall)
110
114
  OptionParser#parse_in_order contains iterators nested 3 deep (NestedIterators)
111
- OptionParser#parse_in_order has approx 28 statements (TooManyStatements)
115
+ OptionParser#parse_in_order has approx 35 statements (TooManyStatements)
112
116
  OptionParser#permute calls argv[0] twice (DuplicateMethodCall)
113
117
  OptionParser#permute refers to argv more than self (FeatureEnvy)
118
+ OptionParser#permute! has approx 6 statements (TooManyStatements)
114
119
  OptionParser#search has the variable name 'k' (UncommunicativeVariableName)
115
120
  OptionParser#self.inc performs a nil-check. (NilCheck)
116
121
  OptionParser#summarize has 4 parameters (LongParameterList)
117
122
  OptionParser#summarize has the variable name 'l' (UncommunicativeVariableName)
118
123
  OptionParser#ver has the variable name 'v' (UncommunicativeVariableName)
124
+ OptionParser::Arguable#options has approx 6 statements (TooManyStatements)
119
125
  OptionParser::Arguable#options= is controlled by argument opt (ControlParameter)
120
126
  OptionParser::CompletingHash#match contains iterators nested 2 deep (NestedIterators)
121
127
  OptionParser::Completion#complete calls candidates.size twice (DuplicateMethodCall)
122
128
  OptionParser::Completion#complete calls k.id2name twice (DuplicateMethodCall)
123
- OptionParser::Completion#complete has approx 22 statements (TooManyStatements)
129
+ OptionParser::Completion#complete has approx 23 statements (TooManyStatements)
124
130
  OptionParser::Completion#complete has boolean parameter 'icase' (BooleanParameter)
125
131
  OptionParser::Completion#complete has the variable name 'k' (UncommunicativeVariableName)
126
132
  OptionParser::Completion#complete has the variable name 'v' (UncommunicativeVariableName)
@@ -134,7 +140,7 @@ Feature: Basic smell detection
134
140
  OptionParser::List#reject has the parameter name 't' (UncommunicativeParameterName)
135
141
  OptionParser::List#summarize refers to opt more than self (FeatureEnvy)
136
142
  OptionParser::List#update has 5 parameters (LongParameterList)
137
- OptionParser::List#update has approx 6 statements (TooManyStatements)
143
+ OptionParser::List#update has approx 10 statements (TooManyStatements)
138
144
  OptionParser::List#update has the variable name 'o' (UncommunicativeVariableName)
139
145
  OptionParser::ParseError#set_option is controlled by argument eq (ControlParameter)
140
146
  OptionParser::Switch#add_banner has the variable name 's' (UncommunicativeVariableName)
@@ -143,6 +149,7 @@ Feature: Basic smell detection
143
149
  OptionParser::Switch#parse_arg has approx 11 statements (TooManyStatements)
144
150
  OptionParser::Switch#parse_arg has the variable name 'm' (UncommunicativeVariableName)
145
151
  OptionParser::Switch#parse_arg has the variable name 's' (UncommunicativeVariableName)
152
+ OptionParser::Switch#self.guess has approx 6 statements (TooManyStatements)
146
153
  OptionParser::Switch#self.guess has the variable name 't' (UncommunicativeVariableName)
147
154
  OptionParser::Switch#self.incompatible_argument_styles has the parameter name 't' (UncommunicativeParameterName)
148
155
  OptionParser::Switch#summarize calls (indent + l) twice (DuplicateMethodCall)
@@ -154,7 +161,7 @@ Feature: Basic smell detection
154
161
  OptionParser::Switch#summarize calls s.length 3 times (DuplicateMethodCall)
155
162
  OptionParser::Switch#summarize contains iterators nested 2 deep (NestedIterators)
156
163
  OptionParser::Switch#summarize has 5 parameters (LongParameterList)
157
- OptionParser::Switch#summarize has approx 25 statements (TooManyStatements)
164
+ OptionParser::Switch#summarize has approx 28 statements (TooManyStatements)
158
165
  OptionParser::Switch#summarize has the variable name 'l' (UncommunicativeVariableName)
159
166
  OptionParser::Switch#summarize has the variable name 'r' (UncommunicativeVariableName)
160
167
  OptionParser::Switch#summarize has the variable name 's' (UncommunicativeVariableName)
@@ -189,21 +196,21 @@ Feature: Basic smell detection
189
196
  RedCloth#block_textile_lists calls lines[(line_id - 1)] twice (DuplicateMethodCall)
190
197
  RedCloth#block_textile_lists calls tl.length 3 times (DuplicateMethodCall)
191
198
  RedCloth#block_textile_lists contains iterators nested 3 deep (NestedIterators)
192
- RedCloth#block_textile_lists has approx 20 statements (TooManyStatements)
199
+ RedCloth#block_textile_lists has approx 21 statements (TooManyStatements)
193
200
  RedCloth#block_textile_lists has the variable name 'i' (UncommunicativeVariableName)
194
201
  RedCloth#block_textile_lists has the variable name 'v' (UncommunicativeVariableName)
195
202
  RedCloth#block_textile_lists refers to depth more than self (FeatureEnvy)
196
203
  RedCloth#block_textile_table contains iterators nested 3 deep (NestedIterators)
197
- RedCloth#block_textile_table has approx 18 statements (TooManyStatements)
204
+ RedCloth#block_textile_table has approx 19 statements (TooManyStatements)
198
205
  RedCloth#block_textile_table has the variable name 'x' (UncommunicativeVariableName)
199
206
  RedCloth#blocks contains iterators nested 2 deep (NestedIterators)
200
- RedCloth#blocks has approx 18 statements (TooManyStatements)
207
+ RedCloth#blocks has approx 19 statements (TooManyStatements)
201
208
  RedCloth#blocks has boolean parameter 'deep_code' (BooleanParameter)
202
209
  RedCloth#blocks is controlled by argument deep_code (ControlParameter)
203
210
  RedCloth#clean_html calls tags[tag] twice (DuplicateMethodCall)
204
211
  RedCloth#clean_html contains iterators nested 3 deep (NestedIterators)
205
212
  RedCloth#clean_html doesn't depend on instance state (UtilityFunction)
206
- RedCloth#clean_html has approx 14 statements (TooManyStatements)
213
+ RedCloth#clean_html has approx 15 statements (TooManyStatements)
207
214
  RedCloth#clean_html has the variable name 'q' (UncommunicativeVariableName)
208
215
  RedCloth#clean_html has the variable name 'q2' (UncommunicativeVariableName)
209
216
  RedCloth#clean_html refers to raw more than self (FeatureEnvy)
@@ -233,7 +240,7 @@ Feature: Basic smell detection
233
240
  RedCloth#inline_textile_link has approx 9 statements (TooManyStatements)
234
241
  RedCloth#inline_textile_link has the variable name 'm' (UncommunicativeVariableName)
235
242
  RedCloth#inline_textile_span contains iterators nested 2 deep (NestedIterators)
236
- RedCloth#inline_textile_span has approx 8 statements (TooManyStatements)
243
+ RedCloth#inline_textile_span has approx 9 statements (TooManyStatements)
237
244
  RedCloth#inline_textile_span has the variable name 'm' (UncommunicativeVariableName)
238
245
  RedCloth#lT has the name 'lT' (UncommunicativeMethodName)
239
246
  RedCloth#lT is controlled by argument text (ControlParameter)
@@ -266,15 +273,15 @@ Feature: Basic smell detection
266
273
  RedCloth#textile_p has unused parameter 'cite' (UnusedParameters)
267
274
  RedCloth#textile_popup_help has the parameter name 'windowH' (UncommunicativeParameterName)
268
275
  RedCloth#textile_popup_help has the parameter name 'windowW' (UncommunicativeParameterName)
269
- RedCloth#to_html has approx 24 statements (TooManyStatements)
276
+ RedCloth#to_html has approx 26 statements (TooManyStatements)
270
277
  """
271
278
 
279
+ @ruby20
272
280
  Scenario: Correct smells from a source file with Ruby 2.0 specific syntax
273
281
  When I run reek spec/samples/ruby20_syntax.rb
274
282
  Then the exit status indicates smells
275
283
  And it reports:
276
284
  """
277
- spec/samples/ruby20_syntax.rb -- 2 warnings:
285
+ spec/samples/ruby20_syntax.rb -- 1 warning:
278
286
  [1]:SomeClass has no descriptive comment (IrresponsibleModule)
279
- [2]:SomeClass#method_with_keyword_arguments has unused parameter 'foo' (UnusedParameters)
280
287
  """
@@ -15,11 +15,11 @@ class ReekWorld
15
15
  end
16
16
 
17
17
  def reek(args)
18
- run("ruby -Ilib -rubygems bin/reek #{args}")
18
+ run("ruby -Ilib -rubygems bin/reek --no-color #{args}")
19
19
  end
20
20
 
21
21
  def reek_with_pipe(stdin, args)
22
- run("echo \"#{stdin}\" | ruby -Ilib -rubygems bin/reek #{args}")
22
+ run("echo \"#{stdin}\" | ruby -Ilib -rubygems bin/reek --no-color #{args}")
23
23
  end
24
24
 
25
25
  def rake(name, task_def)
@@ -41,10 +41,6 @@ module Reek
41
41
  def report_smells
42
42
  @status = STATUS_SMELLS
43
43
  end
44
-
45
- def update_status(reporter)
46
- reporter.has_smells? ? report_smells : report_success
47
- end
48
44
  end
49
45
  end
50
46
  end
@@ -1,9 +1,9 @@
1
1
  require 'optparse'
2
+ require 'rainbow'
2
3
  require 'reek/cli/report'
3
4
  require 'reek/cli/reek_command'
4
5
  require 'reek/cli/help_command'
5
6
  require 'reek/cli/version_command'
6
- require 'reek/cli/yaml_command'
7
7
  require 'reek/source'
8
8
 
9
9
  module Reek
@@ -17,9 +17,11 @@ module Reek
17
17
  def initialize(argv)
18
18
  @argv = argv
19
19
  @parser = OptionParser.new
20
+ @colored = true
20
21
  @report_class = QuietReport
21
22
  @warning_formatter = WarningFormatterWithLineNumbers
22
23
  @command_class = ReekCommand
24
+ @format = Report::DefaultFormat
23
25
  @config_files = []
24
26
  @sort_by_issue_count = false
25
27
  set_options
@@ -73,6 +75,9 @@ EOB
73
75
  end
74
76
 
75
77
  @parser.separator "\nReport formatting:"
78
+ @parser.on("-o", "--[no-]color", "Use colors for the output (this is the default)") do |opt|
79
+ @colored = opt
80
+ end
76
81
  @parser.on("-q", "--quiet", "Suppress headings for smell-free source files (this is the default)") do |opt|
77
82
  @report_class = QuietReport
78
83
  end
@@ -92,10 +97,7 @@ EOB
92
97
  @sort_by_issue_count = true
93
98
  end
94
99
  @parser.on("-y", "--yaml", "Report smells in YAML format") do
95
- @command_class = YamlCommand
96
- # SMELL: the args passed to the command should be tested, because it may
97
- # turn out that they are passed too soon, ie. before the files have been
98
- # separated out from the options
100
+ @format = :yaml
99
101
  end
100
102
  end
101
103
 
@@ -106,13 +108,9 @@ EOB
106
108
  elsif @command_class == VersionCommand
107
109
  VersionCommand.new(@parser.program_name)
108
110
  else
109
- sources = get_sources
110
- if @command_class == YamlCommand
111
- YamlCommand.create(sources, @config_files)
112
- else
113
- reporter = @report_class.new(@warning_formatter, ReportFormatter, @sort_by_issue_count)
114
- ReekCommand.create(sources, reporter, @config_files)
115
- end
111
+ Rainbow.enabled = @colored
112
+ reporter = @report_class.new(@warning_formatter, ReportFormatter, @sort_by_issue_count, @format)
113
+ ReekCommand.create(get_sources, reporter, @config_files)
116
114
  end
117
115
  end
118
116
 
@@ -22,7 +22,7 @@ module Reek
22
22
  @sources.each do |source|
23
23
  @reporter.add_examiner(Examiner.new(source, @config_files))
24
24
  end
25
- app.update_status(@reporter)
25
+ @reporter.has_smells? ? app.report_smells : app.report_success
26
26
  @reporter.show
27
27
  end
28
28
  end
@@ -1,3 +1,5 @@
1
+ require 'rainbow'
2
+
1
3
  module Reek
2
4
  module Cli
3
5
  module ReportFormatter
@@ -9,8 +11,8 @@ module Reek
9
11
 
10
12
  def self.header(examiner)
11
13
  count = examiner.smells_count
12
- result = "#{examiner.description} -- #{count} warning"
13
- result += 's' unless count == 1
14
+ result = Rainbow("#{examiner.description} -- ").cyan + Rainbow("#{count} warning").yellow
15
+ result += Rainbow('s').yellow unless count == 1
14
16
  result
15
17
  end
16
18
  end
@@ -33,13 +35,19 @@ module Reek
33
35
  end
34
36
  end
35
37
 
38
+ #
39
+ # A report that contains the smells and smell counts following source code analysis.
40
+ #
36
41
  class Report
37
- def initialize(warning_formatter = SimpleWarningFormatter, report_formatter = ReportFormatter, sort_by_issue_count = false)
42
+ DefaultFormat = :text
43
+
44
+ def initialize(warning_formatter = SimpleWarningFormatter, report_formatter = ReportFormatter, sort_by_issue_count = false, format = DefaultFormat)
38
45
  @warning_formatter = warning_formatter
39
46
  @report_formatter = report_formatter
40
47
  @examiners = []
41
48
  @total_smell_count = 0
42
49
  @sort_by_issue_count = sort_by_issue_count
50
+ @format = format
43
51
  end
44
52
 
45
53
  def add_examiner(examiner)
@@ -49,9 +57,18 @@ module Reek
49
57
  end
50
58
 
51
59
  def show
52
- sort_examiners
53
- display_summary
54
- display_total_smell_count
60
+ case @format
61
+ when DefaultFormat
62
+ sort_examiners
63
+ display_summary
64
+ display_total_smell_count
65
+ when :yaml
66
+ if all_smells.size > 0
67
+ print(all_smells.to_yaml)
68
+ else
69
+ print ''
70
+ end
71
+ end
55
72
  end
56
73
 
57
74
  def has_smells?
@@ -60,8 +77,13 @@ module Reek
60
77
 
61
78
  private
62
79
 
80
+ def all_smells
81
+ @all_smells ||= @examiners.each_with_object([]) { |examiner, smells| smells << examiner.smells }
82
+ .flatten
83
+ end
84
+
63
85
  def sort_examiners
64
- @examiners.sort! {|a, b| b.smells_count <=> a.smells_count } if @sort_by_issue_count
86
+ @examiners.sort! {|first, second| second.smells_count <=> first.smells_count } if @sort_by_issue_count
65
87
  end
66
88
 
67
89
  def display_summary
@@ -76,7 +98,7 @@ module Reek
76
98
  end
77
99
 
78
100
  def total_smell_count_message
79
- "#{@total_smell_count} total warning#{'s' unless @total_smell_count == 1 }\n"
101
+ Rainbow("#{@total_smell_count} total warning#{'s' unless @total_smell_count == 1 }\n").red
80
102
  end
81
103
 
82
104
  def summarize_single_examiner(examiner)
@@ -89,6 +111,9 @@ module Reek
89
111
  end
90
112
  end
91
113
 
114
+ #
115
+ # A report that lists smell-free source files.
116
+ #
92
117
  class VerboseReport < Report
93
118
  def gather_results
94
119
  @examiners.each_with_object([]) do |examiner, result|
@@ -97,6 +122,9 @@ module Reek
97
122
  end
98
123
  end
99
124
 
125
+ #
126
+ # A report that does not list smell-free source files.
127
+ #
100
128
  class QuietReport < Report
101
129
  def gather_results
102
130
  @examiners.each_with_object([]) do |examiner, result|