kevinrutherford-reek 1.1.3.10 → 1.1.3.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/History.txt +5 -1
  2. data/bin/reek +2 -17
  3. data/features/masking_smells.feature +22 -8
  4. data/features/options.feature +12 -5
  5. data/features/reports.feature +22 -12
  6. data/features/samples.feature +66 -66
  7. data/lib/reek/adapters/application.rb +47 -0
  8. data/lib/reek/{config_file.rb → adapters/config_file.rb} +0 -0
  9. data/lib/reek/adapters/core_extras.rb +72 -0
  10. data/lib/reek/{object_source.rb → adapters/object_source.rb} +7 -6
  11. data/lib/reek/{rake_task.rb → adapters/rake_task.rb} +2 -2
  12. data/lib/reek/adapters/report.rb +91 -0
  13. data/lib/reek/adapters/source.rb +49 -0
  14. data/lib/reek/{spec.rb → adapters/spec.rb} +20 -9
  15. data/lib/reek/block_context.rb +1 -1
  16. data/lib/reek/class_context.rb +3 -2
  17. data/lib/reek/code_parser.rb +4 -0
  18. data/lib/reek/command_line.rb +85 -0
  19. data/lib/reek/detector_stack.rb +23 -6
  20. data/lib/reek/exceptions.reek +5 -1
  21. data/lib/reek/smell_warning.rb +5 -1
  22. data/lib/reek/smells/duplication.rb +5 -3
  23. data/lib/reek/smells/smell_detector.rb +15 -1
  24. data/lib/reek/smells/uncommunicative_name.rb +1 -1
  25. data/lib/reek/sniffer.rb +34 -66
  26. data/lib/reek.rb +1 -1
  27. data/reek.gemspec +3 -3
  28. data/spec/quality/reek_source_spec.rb +15 -0
  29. data/spec/reek/adapters/report_spec.rb +48 -0
  30. data/spec/reek/{should_reek_of_spec.rb → adapters/should_reek_of_spec.rb} +14 -11
  31. data/spec/reek/{should_reek_only_of_spec.rb → adapters/should_reek_only_of_spec.rb} +6 -4
  32. data/spec/reek/{should_reek_spec.rb → adapters/should_reek_spec.rb} +13 -10
  33. data/spec/reek/block_context_spec.rb +6 -0
  34. data/spec/reek/code_parser_spec.rb +6 -1
  35. data/spec/reek/config_spec.rb +3 -3
  36. data/spec/reek/smell_warning_spec.rb +2 -1
  37. data/spec/reek/smells/duplication_spec.rb +1 -1
  38. data/spec/reek/smells/large_class_spec.rb +3 -2
  39. data/spec/reek/smells/long_method_spec.rb +4 -3
  40. data/spec/reek/smells/long_parameter_list_spec.rb +0 -2
  41. data/spec/reek/smells/smell_detector_spec.rb +2 -16
  42. data/spec/reek/smells/uncommunicative_name_spec.rb +1 -2
  43. data/spec/reek/smells/utility_function_spec.rb +4 -0
  44. data/spec/samples/not_quite_masked/dirty.rb +8 -0
  45. data/spec/samples/not_quite_masked/masked.reek +5 -0
  46. data/spec/spec_helper.rb +1 -1
  47. data/tasks/reek.rake +2 -2
  48. data/tasks/test.rake +8 -8
  49. metadata +18 -20
  50. data/features/rake_task.feature +0 -9
  51. data/lib/reek/core_extras.rb +0 -50
  52. data/lib/reek/options.rb +0 -103
  53. data/lib/reek/report.rb +0 -115
  54. data/lib/reek/source.rb +0 -36
  55. data/spec/reek/options_spec.rb +0 -13
  56. data/spec/reek/report_spec.rb +0 -49
  57. data/spec/slow/inline_spec.rb +0 -44
  58. data/spec/slow/optparse_spec.rb +0 -112
  59. data/spec/slow/redcloth_spec.rb +0 -105
  60. data/spec/slow/reek_source_spec.rb +0 -13
data/History.txt CHANGED
@@ -6,18 +6,22 @@
6
6
  ** Output now reports on all files examined, even if they have no smells
7
7
  ** Smell warnings are indented in the report; file summary headers are not
8
8
  ** Reports for multiple sources are run together; no more blank lines
9
- ** Reports in spec matcher failures are quiet
9
+ ** Reports in spec matcher failures are quiet (fixed #38)
10
10
  * The smells masked by *.reek config files can now be seen:
11
11
  ** The header for each source file now counts masked smells
12
12
  ** The --show-all (-a) option shows masked warnings in the report
13
+ * The spec matchers are now accessed by requiring 'reek/adapters/spec'
13
14
 
14
15
  === Minor Changes
15
16
  * Reek's RDoc is now hosted at http://rdoc.info/projects/kevinrutherford/reek
17
+ * If a dir is passed on the command-line all **/*.rb files below it are examined (fixed #41)
16
18
  * Several changes to the LongMethod counting algorithm:
17
19
  ** LongMethod now counts statements deeper into each method (fixed #25)
18
20
  ** LongMethod no longer counts control structures, only their contained stmts
19
21
  ** See http://wiki.github.com/kevinrutherford/reek/long-method for details
20
22
  * LargeClass is disabled when checking in-memory classes (fixed #28)
23
+ * UtilityFunction no longer reports methods that call 'super' (fixed #39)
24
+ * Duplication warnings now report the number of identical calls
21
25
  * Now reports an error for corrupt config files
22
26
  * Empty config files are ignored
23
27
 
data/bin/reek CHANGED
@@ -6,21 +6,6 @@
6
6
  # Author: Kevin Rutherford
7
7
  #
8
8
 
9
- require 'reek/options'
9
+ require 'reek/adapters/application'
10
10
 
11
- def reek(args)
12
- begin
13
- sniffer = Reek::Options.parse(args)
14
- # SMELL:
15
- # This should use the actual type of report selected by the user's options
16
- puts sniffer.full_report
17
- return sniffer.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
24
- end
25
-
26
- exit reek(ARGV)
11
+ exit Reek::Application.new(ARGV).execute
@@ -11,8 +11,8 @@ Feature: Masking smells using config files
11
11
  """
12
12
  spec/samples/empty_config_file/dirty.rb -- 6 warnings:
13
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)
14
+ Dirty#a calls @s.title twice (Duplication)
15
+ Dirty#a calls puts(@s.title) twice (Duplication)
16
16
  Dirty#a has the name 'a' (Uncommunicative Name)
17
17
  Dirty#a/block has the variable name 'x' (Uncommunicative Name)
18
18
  Dirty#a/block/block is nested (Nested Iterators)
@@ -35,8 +35,8 @@ Feature: Masking smells using config files
35
35
  And it reports:
36
36
  """
37
37
  spec/samples/masked/dirty.rb -- 3 warnings (+3 masked):
38
- Dirty#a calls @s.title multiple times (Duplication)
39
- Dirty#a calls puts(@s.title) multiple times (Duplication)
38
+ Dirty#a calls @s.title twice (Duplication)
39
+ Dirty#a calls puts(@s.title) twice (Duplication)
40
40
  Dirty#a/block/block is nested (Nested Iterators)
41
41
 
42
42
  """
@@ -48,8 +48,8 @@ Feature: Masking smells using config files
48
48
  """
49
49
  spec/samples/masked/dirty.rb -- 3 warnings (+3 masked):
50
50
  (masked) Dirty has the variable name '@s' (Uncommunicative Name)
51
- Dirty#a calls @s.title multiple times (Duplication)
52
- Dirty#a calls puts(@s.title) multiple times (Duplication)
51
+ Dirty#a calls @s.title twice (Duplication)
52
+ Dirty#a calls puts(@s.title) twice (Duplication)
53
53
  (masked) Dirty#a has the name 'a' (Uncommunicative Name)
54
54
  (masked) Dirty#a/block has the variable name 'x' (Uncommunicative Name)
55
55
  Dirty#a/block/block is nested (Nested Iterators)
@@ -62,8 +62,22 @@ Feature: Masking smells using config files
62
62
  And it reports:
63
63
  """
64
64
  spec/samples/masked/dirty.rb -- 3 warnings (+3 masked):
65
- Dirty#a calls @s.title multiple times (Duplication)
66
- Dirty#a calls puts(@s.title) multiple times (Duplication)
65
+ Dirty#a calls @s.title twice (Duplication)
66
+ Dirty#a calls puts(@s.title) twice (Duplication)
67
+ Dirty#a/block/block is nested (Nested Iterators)
68
+
69
+ """
70
+
71
+ Scenario: non-masked smells are only counted once
72
+ When I run reek spec/samples/not_quite_masked/dirty.rb
73
+ Then it fails with exit status 2
74
+ And it reports:
75
+ """
76
+ spec/samples/not_quite_masked/dirty.rb -- 5 warnings (+1 masked):
77
+ Dirty has the variable name '@s' (Uncommunicative Name)
78
+ Dirty#a calls @s.title twice (Duplication)
79
+ Dirty#a calls puts(@s.title) twice (Duplication)
80
+ Dirty#a has the name 'a' (Uncommunicative Name)
67
81
  Dirty#a/block/block is nested (Nested Iterators)
68
82
 
69
83
  """
@@ -24,19 +24,26 @@ Feature: Reek can be controlled using command-line options
24
24
  Then it succeeds
25
25
  And it reports:
26
26
  """
27
- Usage: reek [options] files...
27
+ Usage: reek [options] [files]
28
+
29
+ Examples:
30
+
31
+ reek lib/*.rb
32
+ reek -q -a lib
33
+ cat my_class.rb | reek
28
34
 
29
- If no files are given, Reek reads source code from standard input.
30
35
  See http://wiki.github.com/kevinrutherford/reek for detailed help.
31
36
 
37
+ Common options:
38
+ -h, --help Show this message
39
+ -v, --version Show version
32
40
 
33
- Options:
41
+
42
+ Report formatting:
34
43
  -a, --[no-]show-all Show all smells, including those masked by config settings
35
44
  -q, --quiet Suppress headings for smell-free source files
36
- -h, --help Show this message
37
45
  -f, --format FORMAT Specify the format of smell warnings
38
46
  -c, --context-first Sort by context; sets the format string to "%m%c %w (%s)"
39
47
  -s, --smell-first Sort by smell; sets the format string to "%m[%s] %c %w"
40
- -v, --version Show version
41
48
 
42
49
  """
@@ -4,30 +4,35 @@ Feature: Correctly formatted reports
4
4
  As a developer
5
5
  I want to be able to parse reek's output simply and consistently
6
6
 
7
- Scenario: two reports run together with indented smells
8
- When I run reek spec/samples/two_smelly_files/*.rb
7
+ Scenario Outline: two reports run together with indented smells
8
+ When I run reek <args>
9
9
  Then it fails with exit status 2
10
10
  And it reports:
11
11
  """
12
12
  spec/samples/two_smelly_files/dirty_one.rb -- 6 warnings:
13
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)
14
+ Dirty#a calls @s.title twice (Duplication)
15
+ Dirty#a calls puts(@s.title) twice (Duplication)
16
16
  Dirty#a has the name 'a' (Uncommunicative Name)
17
17
  Dirty#a/block has the variable name 'x' (Uncommunicative Name)
18
18
  Dirty#a/block/block is nested (Nested Iterators)
19
19
  spec/samples/two_smelly_files/dirty_two.rb -- 6 warnings:
20
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)
21
+ Dirty#a calls @s.title twice (Duplication)
22
+ Dirty#a calls puts(@s.title) twice (Duplication)
23
23
  Dirty#a has the name 'a' (Uncommunicative Name)
24
24
  Dirty#a/block has the variable name 'x' (Uncommunicative Name)
25
25
  Dirty#a/block/block is nested (Nested Iterators)
26
26
 
27
27
  """
28
28
 
29
- Scenario: good files show headers consecutively
30
- When I run reek spec/samples/three_clean_files/*.rb
29
+ Examples:
30
+ | args |
31
+ | spec/samples/two_smelly_files/*.rb |
32
+ | spec/samples/two_smelly_files |
33
+
34
+ Scenario Outline: good files show headers consecutively
35
+ When I run reek <args>
31
36
  Then it succeeds
32
37
  And it reports:
33
38
  """
@@ -37,6 +42,11 @@ Feature: Correctly formatted reports
37
42
 
38
43
  """
39
44
 
45
+ Examples:
46
+ | args |
47
+ | spec/samples/three_clean_files/*.rb |
48
+ | spec/samples/three_clean_files |
49
+
40
50
  Scenario Outline: --quiet turns off headers for fragrant files
41
51
  When I run reek <option> spec/samples/three_clean_files/*.rb
42
52
  Then it succeeds
@@ -59,15 +69,15 @@ Feature: Correctly formatted reports
59
69
  """
60
70
  spec/samples/clean_due_to_masking/dirty_one.rb -- 0 warnings (+6 masked):
61
71
  (masked) Dirty has the variable name '@s' (Uncommunicative Name)
62
- (masked) Dirty#a calls @s.title multiple times (Duplication)
63
- (masked) Dirty#a calls puts(@s.title) multiple times (Duplication)
72
+ (masked) Dirty#a calls @s.title twice (Duplication)
73
+ (masked) Dirty#a calls puts(@s.title) twice (Duplication)
64
74
  (masked) Dirty#a has the name 'a' (Uncommunicative Name)
65
75
  (masked) Dirty#a/block has the variable name 'x' (Uncommunicative Name)
66
76
  (masked) Dirty#a/block/block is nested (Nested Iterators)
67
77
  spec/samples/clean_due_to_masking/dirty_two.rb -- 0 warnings (+6 masked):
68
78
  (masked) Dirty has the variable name '@s' (Uncommunicative Name)
69
- (masked) Dirty#a calls @s.title multiple times (Duplication)
70
- (masked) Dirty#a calls puts(@s.title) multiple times (Duplication)
79
+ (masked) Dirty#a calls @s.title twice (Duplication)
80
+ (masked) Dirty#a calls puts(@s.title) twice (Duplication)
71
81
  (masked) Dirty#a has the name 'a' (Uncommunicative Name)
72
82
  (masked) Dirty#a/block has the variable name 'x' (Uncommunicative Name)
73
83
  (masked) Dirty#a/block/block is nested (Nested Iterators)
@@ -11,25 +11,25 @@ Feature: Basic smell detection
11
11
  """
12
12
  spec/samples/inline.rb -- 32 warnings:
13
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)
14
+ Inline::C#build calls ($? == 0) twice (Duplication)
15
+ Inline::C#build calls Inline.directory 5 times (Duplication)
16
+ Inline::C#build calls io.puts 6 times (Duplication)
17
+ Inline::C#build calls io.puts("#endif") twice (Duplication)
18
+ Inline::C#build calls io.puts("#ifdef __cplusplus") twice (Duplication)
19
+ Inline::C#build calls module_name twice (Duplication)
20
+ Inline::C#build calls warn("Output:\n#{result}") twice (Duplication)
21
21
  Inline::C#build has approx 60 statements (Long Method)
22
22
  Inline::C#build has the variable name 't' (Uncommunicative Name)
23
23
  Inline::C#build/block/block has the variable name 'n' (Uncommunicative Name)
24
24
  Inline::C#build/block/block is nested (Nested Iterators)
25
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)
26
+ Inline::C#crap_for_windoze calls Config::CONFIG["libdir"] twice (Duplication)
27
+ Inline::C#generate calls result.sub!(/\A\n/, "") twice (Duplication)
28
+ Inline::C#generate calls signature["args"] twice (Duplication)
29
+ Inline::C#generate calls signature["args"].map twice (Duplication)
30
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)
31
+ Inline::C#initialize calls stack.empty? twice (Duplication)
32
+ Inline::C#load calls so_name twice (Duplication)
33
33
  Inline::C#module_name/block has the variable name 'm' (Uncommunicative Name)
34
34
  Inline::C#module_name/block has the variable name 'x' (Uncommunicative Name)
35
35
  Inline::C#parse_signature has approx 15 statements (Long Method)
@@ -37,9 +37,9 @@ Feature: Basic smell detection
37
37
  Inline::C#parse_signature/block has the variable name 'x' (Uncommunicative Name)
38
38
  Inline::C#strip_comments doesn't depend on instance state (Utility Function)
39
39
  Inline::C#strip_comments refers to src more than self (Feature Envy)
40
- Inline::self.rootdir calls env.nil? multiple times (Duplication)
40
+ Inline::self.rootdir calls env.nil? twice (Duplication)
41
41
  Inline::self.rootdir has approx 8 statements (Long Method)
42
- Module#inline calls Inline.const_get(lang) multiple times (Duplication)
42
+ Module#inline calls Inline.const_get(lang) twice (Duplication)
43
43
  Module#inline has approx 11 statements (Long Method)
44
44
  Module#inline is controlled by argument options (Control Couple)
45
45
 
@@ -53,8 +53,8 @@ Feature: Basic smell detection
53
53
  spec/samples/optparse.rb -- 117 warnings:
54
54
  OptionParser has at least 59 methods (Large Class)
55
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)
56
+ OptionParser#Completion::complete calls candidates.size twice (Duplication)
57
+ OptionParser#Completion::complete calls k.id2name twice (Duplication)
58
58
  OptionParser#Completion::complete has approx 22 statements (Long Method)
59
59
  OptionParser#Completion::complete has the variable name 'k' (Uncommunicative Name)
60
60
  OptionParser#Completion::complete has the variable name 'v' (Uncommunicative Name)
@@ -80,23 +80,23 @@ Feature: Basic smell detection
80
80
  OptionParser#Switch#PlacedArgument#parse has approx 6 statements (Long Method)
81
81
  OptionParser#Switch#RequiredArgument#parse is controlled by argument arg (Control Couple)
82
82
  OptionParser#Switch#add_banner has the variable name 's' (Uncommunicative Name)
83
- OptionParser#Switch#conv_arg calls conv multiple times (Duplication)
83
+ OptionParser#Switch#conv_arg calls conv twice (Duplication)
84
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)
85
+ OptionParser#Switch#parse_arg calls pattern twice (Duplication)
86
+ OptionParser#Switch#parse_arg calls s.length twice (Duplication)
87
87
  OptionParser#Switch#parse_arg has approx 11 statements (Long Method)
88
88
  OptionParser#Switch#parse_arg has the variable name 'm' (Uncommunicative Name)
89
89
  OptionParser#Switch#parse_arg has the variable name 's' (Uncommunicative Name)
90
90
  OptionParser#Switch#self.guess has the variable name 't' (Uncommunicative Name)
91
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)
92
+ OptionParser#Switch#summarize calls (indent + l) twice (Duplication)
93
+ OptionParser#Switch#summarize calls arg 4 times (Duplication)
94
+ OptionParser#Switch#summarize calls left.collect twice (Duplication)
95
+ OptionParser#Switch#summarize calls left.collect { |s| s.length }.max twice (Duplication)
96
+ OptionParser#Switch#summarize calls left.collect { |s| s.length }.max.to_i twice (Duplication)
97
+ OptionParser#Switch#summarize calls left.shift twice (Duplication)
98
+ OptionParser#Switch#summarize calls left[-1] 3 times (Duplication)
99
+ OptionParser#Switch#summarize calls s.length 3 times (Duplication)
100
100
  OptionParser#Switch#summarize has 5 parameters (Long Parameter List)
101
101
  OptionParser#Switch#summarize has approx 25 statements (Long Method)
102
102
  OptionParser#Switch#summarize has the variable name 'l' (Uncommunicative Name)
@@ -117,21 +117,21 @@ Feature: Basic smell detection
117
117
  OptionParser#block/block is nested (Nested Iterators)
118
118
  OptionParser#complete has 4 parameters (Long Parameter List)
119
119
  OptionParser#complete/block/block is nested (Nested Iterators)
120
- OptionParser#getopts calls result[opt] = false multiple times (Duplication)
120
+ OptionParser#getopts calls result[opt] = false twice (Duplication)
121
121
  OptionParser#getopts has approx 17 statements (Long Method)
122
122
  OptionParser#getopts/block is controlled by argument val (Control Couple)
123
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)
124
+ OptionParser#make_switch calls (long << o = q.downcase) twice (Duplication)
125
+ OptionParser#make_switch calls (sdesc << "-#{q}") twice (Duplication)
126
+ OptionParser#make_switch calls default_style.guess(arg = a) 4 times (Duplication)
127
+ OptionParser#make_switch calls notwice(NilClass, klass, "type") twice (Duplication)
128
+ OptionParser#make_switch calls notwice(a ? (Object) : (TrueClass), klass, "type") twice (Duplication)
129
+ OptionParser#make_switch calls pattern.method(:convert) twice (Duplication)
130
+ OptionParser#make_switch calls pattern.method(:convert).to_proc twice (Duplication)
131
+ OptionParser#make_switch calls pattern.respond_to?(:convert) twice (Duplication)
132
+ OptionParser#make_switch calls q.downcase 3 times (Duplication)
133
+ OptionParser#make_switch calls search(:atype, FalseClass) twice (Duplication)
134
+ OptionParser#make_switch calls search(:atype, o) 6 times (Duplication)
135
135
  OptionParser#make_switch has approx 68 statements (Long Method)
136
136
  OptionParser#make_switch has the variable name 'a' (Uncommunicative Name)
137
137
  OptionParser#make_switch has the variable name 'n' (Uncommunicative Name)
@@ -146,22 +146,22 @@ Feature: Basic smell detection
146
146
  OptionParser#make_switch/block/block has the variable name 'v' (Uncommunicative Name)
147
147
  OptionParser#make_switch/block/block is nested (Nested Iterators)
148
148
  OptionParser#make_switch/block/block/block is nested (Nested Iterators)
149
- OptionParser#order calls argv[0] multiple times (Duplication)
149
+ OptionParser#order calls argv[0] twice (Duplication)
150
150
  OptionParser#order refers to argv more than self (Feature Envy)
151
- OptionParser#parse calls argv[0] multiple times (Duplication)
151
+ OptionParser#parse calls argv[0] twice (Duplication)
152
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)
153
+ OptionParser#parse_in_order calls $!.set_option(arg, true) twice (Duplication)
154
+ OptionParser#parse_in_order calls cb.call(val) twice (Duplication)
155
+ OptionParser#parse_in_order calls raise($!.set_option(arg, true)) twice (Duplication)
156
+ OptionParser#parse_in_order calls raise(*exc) twice (Duplication)
157
+ OptionParser#parse_in_order calls setter.call(sw.switch_name, val) twice (Duplication)
158
+ OptionParser#parse_in_order calls sw.block twice (Duplication)
159
+ OptionParser#parse_in_order calls sw.switch_name twice (Duplication)
160
160
  OptionParser#parse_in_order has approx 28 statements (Long Method)
161
161
  OptionParser#parse_in_order/block is controlled by argument setter (Control Couple)
162
162
  OptionParser#parse_in_order/block/block is nested (Nested Iterators)
163
163
  OptionParser#parse_in_order/block/block/block is nested (Nested Iterators)
164
- OptionParser#permute calls argv[0] multiple times (Duplication)
164
+ OptionParser#permute calls argv[0] twice (Duplication)
165
165
  OptionParser#permute refers to argv more than self (Feature Envy)
166
166
  OptionParser#search/block has the variable name 'k' (Uncommunicative Name)
167
167
  OptionParser#summarize has 4 parameters (Long Parameter List)
@@ -185,12 +185,12 @@ Feature: Basic smell detection
185
185
  RedCloth#block_markdown_rule doesn't depend on instance state (Utility Function)
186
186
  RedCloth#block_markdown_rule refers to text more than self (Feature Envy)
187
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)
188
+ RedCloth#block_textile_lists calls (line_id - 1) twice (Duplication)
189
+ RedCloth#block_textile_lists calls depth.last 5 times (Duplication)
190
+ RedCloth#block_textile_lists calls depth.last.length twice (Duplication)
191
+ RedCloth#block_textile_lists calls depth[i] twice (Duplication)
192
+ RedCloth#block_textile_lists calls lines[(line_id - 1)] twice (Duplication)
193
+ RedCloth#block_textile_lists calls tl.length 3 times (Duplication)
194
194
  RedCloth#block_textile_lists has approx 20 statements (Long Method)
195
195
  RedCloth#block_textile_lists refers to depth more than self (Feature Envy)
196
196
  RedCloth#block_textile_lists/block/block is nested (Nested Iterators)
@@ -205,7 +205,7 @@ Feature: Basic smell detection
205
205
  RedCloth#blocks/block is controlled by argument deep_code (Control Couple)
206
206
  RedCloth#blocks/block/block is nested (Nested Iterators)
207
207
  RedCloth#check_refs is controlled by argument text (Control Couple)
208
- RedCloth#clean_html calls tags[tag] multiple times (Duplication)
208
+ RedCloth#clean_html calls tags[tag] twice (Duplication)
209
209
  RedCloth#clean_html doesn't depend on instance state (Utility Function)
210
210
  RedCloth#clean_html has approx 14 statements (Long Method)
211
211
  RedCloth#clean_html refers to raw more than self (Feature Envy)
@@ -243,7 +243,7 @@ Feature: Basic smell detection
243
243
  RedCloth#inline_textile_span/block/block is nested (Nested Iterators)
244
244
  RedCloth#no_textile doesn't depend on instance state (Utility Function)
245
245
  RedCloth#no_textile refers to text more than self (Feature Envy)
246
- RedCloth#pba calls $1.length multiple times (Duplication)
246
+ RedCloth#pba calls $1.length twice (Duplication)
247
247
  RedCloth#pba has approx 21 statements (Long Method)
248
248
  RedCloth#pba is controlled by argument text_in (Control Couple)
249
249
  RedCloth#pba refers to style more than self (Feature Envy)
@@ -252,14 +252,14 @@ Feature: Basic smell detection
252
252
  RedCloth#refs_textile/block has the variable name 'm' (Uncommunicative Name)
253
253
  RedCloth#retrieve/block has the variable name 'i' (Uncommunicative Name)
254
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)
255
+ RedCloth#rip_offtags calls ((codepre - used_offtags.length) > 0) twice (Duplication)
256
+ RedCloth#rip_offtags calls (@pre_list.last << line) twice (Duplication)
257
+ RedCloth#rip_offtags calls (codepre - used_offtags.length) twice (Duplication)
258
+ RedCloth#rip_offtags calls @pre_list.last twice (Duplication)
259
+ RedCloth#rip_offtags calls codepre.zero? twice (Duplication)
260
+ RedCloth#rip_offtags calls htmlesc(line, :NoQuotes) twice (Duplication)
261
+ RedCloth#rip_offtags calls used_offtags.length twice (Duplication)
262
+ RedCloth#rip_offtags calls used_offtags["notextile"] 3 times (Duplication)
263
263
  RedCloth#rip_offtags has approx 18 statements (Long Method)
264
264
  RedCloth#textile_bq has 4 parameters (Long Parameter List)
265
265
  RedCloth#textile_bq is controlled by argument atts (Control Couple)
@@ -0,0 +1,47 @@
1
+ require 'reek/command_line'
2
+ require 'reek/adapters/source'
3
+ require 'reek/adapters/core_extras'
4
+ require 'reek/adapters/report'
5
+
6
+ module Reek
7
+ #
8
+ # Represents an instance of a Reek application.
9
+ # This is the entry point for all invocations of Reek from the
10
+ # command line.
11
+ #
12
+ class Application
13
+ def initialize(argv)
14
+ @argv = argv
15
+ end
16
+
17
+ def examine_sources
18
+ # SMELL: Greedy Method
19
+ # Options.parse executes the -v and -h commands and throws a SystemExit
20
+ args = Options.new(@argv).parse
21
+ if args.length > 0
22
+ @sniffer = args.sniff
23
+ else
24
+ @sniffer = Reek::Sniffer.new($stdin.to_reek_source('$stdin'))
25
+ end
26
+ end
27
+
28
+ def reek
29
+ examine_sources
30
+ # SMELL:
31
+ # This should use the actual type of report selected by the user's options
32
+ puts Report.new(@sniffer.sniffers).full_report
33
+ return @sniffer.smelly? ? 2 : 0
34
+ end
35
+
36
+ def execute
37
+ begin
38
+ return reek
39
+ rescue SystemExit => ex
40
+ return ex.status
41
+ rescue Exception => error
42
+ $stderr.puts "Error: #{error}"
43
+ return 1
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,72 @@
1
+ require 'reek/adapters/source'
2
+ require 'reek/sniffer'
3
+
4
+ class Object
5
+ #
6
+ # Creates a new +Sniffer+ that assumes this object contains Ruby source
7
+ # code and examines that code for smells. Calls +to_reek_source+ on self
8
+ # to obtain the +Source+ object wrapper.
9
+ #
10
+ def sniff
11
+ Reek::Sniffer.new(self.to_reek_source)
12
+ end
13
+
14
+ #
15
+ # Constructs a Sniffer which examines this object for code smells.
16
+ # (This feature is only enabled if you have the ParseTree gem installed.)
17
+ #
18
+ def to_reek_source
19
+ ObjectSource.new(self, self.to_s)
20
+ end
21
+ end
22
+
23
+ class File
24
+ #
25
+ # Creates a new +Source+ that assumes this File contains Ruby source
26
+ # code and prepares it to be examined for code smells.
27
+ #
28
+ def to_reek_source
29
+ Reek::SourceFile.new(self)
30
+ end
31
+ end
32
+
33
+ class IO
34
+ #
35
+ # Creates a new +Source+ that assumes this IO stream contains Ruby source
36
+ # code and prepares it to be examined for code smells.
37
+ #
38
+ def to_reek_source(description = 'io')
39
+ Reek::Source.new(self.readlines.join, description)
40
+ end
41
+ end
42
+
43
+ class String
44
+ #
45
+ # Creates a new +Source+ that assumes this string contains Ruby source
46
+ # code and prepares it to be examined for code smells.
47
+ #
48
+ def to_reek_source
49
+ Reek::Source.new(self, 'string')
50
+ end
51
+ end
52
+
53
+ class Array
54
+ def paths
55
+ self.map do |path|
56
+ if test 'd', path
57
+ Dir["#{path}/**/*.rb"].paths
58
+ else
59
+ path
60
+ end
61
+ end.flatten.sort
62
+ end
63
+
64
+ #
65
+ # Creates a new +Sniffer+ that assumes this Array contains the names
66
+ # of Ruby source files and examines those files for smells.
67
+ #
68
+ def sniff
69
+ sniffers = paths.map {|path| File.new(path).sniff}
70
+ Reek::SnifferSet.new(sniffers, 'dir')
71
+ end
72
+ end
@@ -1,3 +1,5 @@
1
+ require 'reek/adapters/source'
2
+
1
3
  module Reek
2
4
  class ObjectSource < Source # :nodoc:
3
5
 
@@ -9,9 +11,10 @@ module Reek
9
11
  return unifier.process(sexp[0])
10
12
  end
11
13
 
12
- def initialize(code, desc, sniffer) # :nodoc:
14
+ def configure(sniffer)
13
15
  super
14
- @sniffer.disable(LargeClass)
16
+ disabled_config = {Reek::Smells::SmellDetector::ENABLED_KEY => false}
17
+ sniffer.configure(LargeClass, disabled_config)
15
18
  end
16
19
 
17
20
  def can_parse_objects?
@@ -39,9 +42,7 @@ class Object
39
42
  # Constructs a Sniffer which examines this object for code smells.
40
43
  # (This feature is only enabled if you have the ParseTree gem installed.)
41
44
  #
42
- def sniff
43
- result = Sniffer.new
44
- ObjectSource.new(self, self.to_s, result)
45
- result
45
+ def to_reek_source
46
+ ObjectSource.new(self, self.to_s)
46
47
  end
47
48
  end
@@ -59,7 +59,7 @@ module Reek
59
59
  # Defines a new task, using the name +name+.
60
60
  def initialize(name = :reek)
61
61
  @name = name
62
- @libs = [File.expand_path(File.dirname(__FILE__) + '/../../lib')]
62
+ @libs = [File.expand_path(File.dirname(__FILE__) + '/../../../lib')]
63
63
  @source_files = nil
64
64
  @ruby_opts = []
65
65
  @reek_opts = ''
@@ -87,7 +87,7 @@ private
87
87
  end
88
88
 
89
89
  def self.reek_script
90
- File.expand_path(File.dirname(__FILE__) + '/../../bin/reek')
90
+ File.expand_path(File.dirname(__FILE__) + '/../../../bin/reek')
91
91
  end
92
92
 
93
93
  def self.ruby_exe