kevinrutherford-reek 1.1.3.10 → 1.1.3.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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