reek 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/History.txt +11 -1
  2. data/README.txt +1 -0
  3. data/lib/reek.rb +8 -9
  4. data/lib/reek/checker.rb +10 -2
  5. data/lib/reek/class_checker.rb +4 -7
  6. data/lib/reek/file_checker.rb +0 -6
  7. data/lib/reek/method_checker.rb +56 -30
  8. data/lib/reek/object_refs.rb +5 -2
  9. data/lib/reek/printer.rb +45 -7
  10. data/lib/reek/rake_task.rb +5 -3
  11. data/lib/reek/smells/control_couple.rb +53 -0
  12. data/lib/reek/smells/duplication.rb +54 -0
  13. data/lib/reek/smells/feature_envy.rb +65 -0
  14. data/lib/reek/smells/large_class.rb +35 -0
  15. data/lib/reek/smells/long_method.rb +35 -0
  16. data/lib/reek/smells/long_parameter_list.rb +36 -0
  17. data/lib/reek/smells/long_yield_list.rb +20 -0
  18. data/lib/reek/smells/nested_iterators.rb +24 -0
  19. data/lib/reek/smells/smell.rb +56 -0
  20. data/lib/reek/smells/smells.rb +24 -0
  21. data/lib/reek/smells/uncommunicative_name.rb +72 -0
  22. data/lib/reek/smells/utility_function.rb +34 -0
  23. data/lib/reek/version.rb +1 -1
  24. data/spec/integration_spec.rb +6 -6
  25. data/spec/reek/printer_spec.rb +21 -21
  26. data/spec/reek/report_spec.rb +5 -5
  27. data/spec/reek/{control_couple_spec.rb → smells/control_couple_spec.rb} +1 -1
  28. data/spec/reek/smells/duplication_spec.rb +60 -0
  29. data/spec/reek/smells/feature_envy_spec.rb +91 -0
  30. data/spec/reek/{large_class_spec.rb → smells/large_class_spec.rb} +8 -8
  31. data/spec/reek/{long_method_spec.rb → smells/long_method_spec.rb} +1 -1
  32. data/spec/reek/{long_parameter_list_spec.rb → smells/long_parameter_list_spec.rb} +1 -1
  33. data/spec/reek/smells/nested_iterators_spec.rb +43 -0
  34. data/spec/reek/{smell_spec.rb → smells/smell_spec.rb} +2 -2
  35. data/spec/reek/smells/uncommunicative_name_spec.rb +83 -0
  36. data/spec/reek/{utility_function_spec.rb → smells/utility_function_spec.rb} +1 -1
  37. data/spec/samples/inline.reek +13 -5
  38. data/spec/samples/optparse.reek +32 -10
  39. data/spec/samples/redcloth.reek +24 -6
  40. data/spec/script_spec.rb +1 -1
  41. data/tasks/reek.rake +9 -0
  42. data/website/index.html +3 -2
  43. data/website/index.txt +3 -1
  44. metadata +24 -12
  45. data/lib/reek/smells.rb +0 -192
  46. data/spec/reek/feature_envy_spec.rb +0 -222
  47. data/spec/reek/nested_iterators_spec.rb +0 -42
  48. data/spec/reek/uncommunicative_name_spec.rb +0 -106
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/../spec_helper.rb'
1
+ require File.dirname(__FILE__) + '/../../spec_helper.rb'
2
2
 
3
3
  require 'reek/method_checker'
4
4
  require 'reek/report'
@@ -1,19 +1,27 @@
1
+ [Duplication] C#build calls $?.==(0) more than once
2
+ [Duplication] C#build calls Inline.directory more than once
3
+ [Duplication] C#build calls io.puts more than once
4
+ [Duplication] C#build calls io.puts(#endif) more than once
5
+ [Duplication] C#build calls io.puts(#ifdef __cplusplus) more than once
1
6
  [Long Method] C#build has approx 61 statements
2
7
  [Nested Iterators] C#build has nested iterators
3
- [Feature Envy] C#build uses io more than self
4
8
  [Uncommunicative Name] C#build uses the local variable name 't'
5
9
  [Uncommunicative Name] C#c uses the method name 'c'
6
- [Feature Envy] C#crap_for_windoze uses Config::CONFIG more than self
10
+ [Duplication] C#crap_for_windoze calls Config::CONFIG[libdir] more than once
11
+ [Duplication] C#generate calls result.sub!((?-mix:\A\n), ) more than once
12
+ [Duplication] C#generate calls signature[args] more than once
13
+ [Duplication] C#generate calls signature[args].map more than once
7
14
  [Long Method] C#generate has approx 33 statements
8
- [Feature Envy] C#initialize uses stack more than self
15
+ [Duplication] C#initialize calls stack.empty? more than once
9
16
  [Long Method] C#load_cache has approx 7 statements
10
17
  [Long Method] C#module_name has approx 6 statements
11
- [Nested Iterators] C#module_name has nested iterators
12
- [Feature Envy] C#module_name uses md5 more than self
18
+ [Feature Envy] C#module_name refers to md5 more than self
13
19
  [Long Method] C#parse_signature has approx 15 statements
14
20
  [Control Couple] C#parse_signature is controlled by argument raw
15
21
  [Utility Function] C#strip_comments doesn't depend on instance state
22
+ [Feature Envy] C#strip_comments refers to src more than self
16
23
  [Large Class] Dir has 31 methods
17
24
  [Large Class] Module has 34 methods
25
+ [Duplication] Module#inline calls Inline.const_get(lang) more than once
18
26
  [Long Method] Module#inline has approx 12 statements
19
27
  [Control Couple] Module#inline is controlled by argument options
@@ -2,6 +2,13 @@
2
2
  [Long Parameter List] CompletingHash#complete has 4 parameters
3
3
  [Nested Iterators] CompletingHash#complete has nested iterators
4
4
  [Long Method] CompletingHash#getopts has approx 17 statements
5
+ [Duplication] CompletingHash#make_switch calls default_style.guess(arg=a) more than once
6
+ [Duplication] CompletingHash#make_switch calls long.<<(o=q.downcase) more than once
7
+ [Duplication] CompletingHash#make_switch calls pattern.method(convert) more than once
8
+ [Duplication] CompletingHash#make_switch calls pattern.method(convert).to_proc more than once
9
+ [Duplication] CompletingHash#make_switch calls pattern.respond_to?(convert) more than once
10
+ [Duplication] CompletingHash#make_switch calls q.downcase more than once
11
+ [Duplication] CompletingHash#make_switch calls sdesc.<<("-#{q}") more than once
5
12
  [Long Method] CompletingHash#make_switch has approx 69 statements
6
13
  [Nested Iterators] CompletingHash#make_switch has nested iterators
7
14
  [Uncommunicative Name] CompletingHash#make_switch uses the local variable name 'a'
@@ -10,30 +17,37 @@
10
17
  [Uncommunicative Name] CompletingHash#make_switch uses the local variable name 'q'
11
18
  [Uncommunicative Name] CompletingHash#make_switch uses the local variable name 's'
12
19
  [Nested Iterators] CompletingHash#match has nested iterators
13
- [Feature Envy] CompletingHash#order uses argv more than self
14
- [Feature Envy] CompletingHash#parse uses argv more than self
20
+ [Duplication] CompletingHash#order calls argv[0] more than once
21
+ [Feature Envy] CompletingHash#order refers to argv more than self
22
+ [Duplication] CompletingHash#parse calls argv[0] more than once
23
+ [Feature Envy] CompletingHash#parse refers to argv more than self
24
+ [Duplication] CompletingHash#parse_in_order calls $!.set_option(arg, true) more than once
25
+ [Duplication] CompletingHash#parse_in_order calls cb.call(val) more than once
26
+ [Duplication] CompletingHash#parse_in_order calls setter.call(sw.switch_name, val) more than once
27
+ [Duplication] CompletingHash#parse_in_order calls sw.block more than once
28
+ [Duplication] CompletingHash#parse_in_order calls sw.switch_name more than once
15
29
  [Long Method] CompletingHash#parse_in_order has approx 30 statements
16
30
  [Nested Iterators] CompletingHash#parse_in_order has nested iterators
17
31
  [Control Couple] CompletingHash#parse_in_order is controlled by argument setter
18
- [Feature Envy] CompletingHash#permute uses argv more than self
32
+ [Duplication] CompletingHash#permute calls argv[0] more than once
33
+ [Feature Envy] CompletingHash#permute refers to argv more than self
19
34
  [Long Parameter List] CompletingHash#summarize has 4 parameters
20
35
  [Uncommunicative Name] CompletingHash#ver uses the local variable name 'v'
21
36
  [Control Couple] List#accept is controlled by argument pat
22
- [Feature Envy] List#accept uses pat more than self
37
+ [Feature Envy] List#accept refers to pat more than self
23
38
  [Uncommunicative Name] List#accept uses the parameter name 't'
24
- [Feature Envy] List#add_banner uses opt more than self
25
39
  [Long Parameter List] List#complete has 4 parameters
26
- [Feature Envy] List#initialize uses OptionMap more than self
27
40
  [Uncommunicative Name] List#reject uses the parameter name 't'
28
- [Feature Envy] List#summarize uses opt more than self
29
41
  [Long Parameter List] List#update has 5 parameters
30
42
  [Long Method] List#update has approx 6 statements
31
43
  [Control Couple] List#update is controlled by argument lopts
32
44
  [Control Couple] List#update is controlled by argument sopts
33
45
  [Uncommunicative Name] List#update uses the local variable name 'o'
34
46
  [Control Couple] NoArgument#parse is controlled by argument arg
47
+ [Duplication] OptionParser#complete calls candidates.size more than once
48
+ [Duplication] OptionParser#complete calls k.id2name more than once
35
49
  [Long Method] OptionParser#complete has approx 23 statements
36
- [Feature Envy] OptionParser#complete uses candidates more than self
50
+ [Feature Envy] OptionParser#complete refers to candidates more than self
37
51
  [Uncommunicative Name] OptionParser#complete uses the local variable name 'k'
38
52
  [Uncommunicative Name] OptionParser#complete uses the local variable name 'v'
39
53
  [Utility Function] OptionParser#convert doesn't depend on instance state
@@ -43,14 +57,22 @@
43
57
  [Control Couple] RequiredArgument#parse is controlled by argument arg
44
58
  [Uncommunicative Name] Switch#add_banner uses the local variable name 's'
45
59
  [Long Parameter List] Switch#initialize has 7 parameters
60
+ [Duplication] Switch#parse_arg calls s.length more than once
46
61
  [Long Method] Switch#parse_arg has approx 12 statements
47
- [Feature Envy] Switch#parse_arg uses arg more than self
62
+ [Feature Envy] Switch#parse_arg refers to arg more than self
48
63
  [Uncommunicative Name] Switch#parse_arg uses the local variable name 'm'
49
64
  [Uncommunicative Name] Switch#parse_arg uses the local variable name 's'
65
+ [Duplication] Switch#summarize calls block.max more than once
66
+ [Duplication] Switch#summarize calls block.max.to_i more than once
67
+ [Duplication] Switch#summarize calls indent.+(l) more than once
68
+ [Duplication] Switch#summarize calls left.collect more than once
69
+ [Duplication] Switch#summarize calls left.shift more than once
70
+ [Duplication] Switch#summarize calls left[-1] more than once
71
+ [Duplication] Switch#summarize calls s.length more than once
50
72
  [Long Parameter List] Switch#summarize has 5 parameters
51
73
  [Long Method] Switch#summarize has approx 27 statements
52
74
  [Nested Iterators] Switch#summarize has nested iterators
53
- [Feature Envy] Switch#summarize uses left more than self
75
+ [Feature Envy] Switch#summarize refers to left more than self
54
76
  [Uncommunicative Name] Switch#summarize uses the local variable name 'l'
55
77
  [Uncommunicative Name] Switch#summarize uses the local variable name 'r'
56
78
  [Uncommunicative Name] Switch#summarize uses the local variable name 's'
@@ -1,24 +1,34 @@
1
1
  [Long Method] RedCloth#block_markdown_bq has approx 6 statements
2
2
  [Utility Function] RedCloth#block_markdown_rule doesn't depend on instance state
3
+ [Duplication] RedCloth#block_textile_lists calls depth.last more than once
4
+ [Duplication] RedCloth#block_textile_lists calls depth.last.length more than once
5
+ [Duplication] RedCloth#block_textile_lists calls depth[i] more than once
6
+ [Duplication] RedCloth#block_textile_lists calls line_id.-(1) more than once
7
+ [Duplication] RedCloth#block_textile_lists calls lines[line_id.-(1)] more than once
8
+ [Duplication] RedCloth#block_textile_lists calls tl.length more than once
3
9
  [Long Method] RedCloth#block_textile_lists has approx 21 statements
4
10
  [Nested Iterators] RedCloth#block_textile_lists has nested iterators
5
- [Feature Envy] RedCloth#block_textile_lists uses depth more than self
6
11
  [Long Method] RedCloth#block_textile_table has approx 19 statements
7
12
  [Nested Iterators] RedCloth#block_textile_table has nested iterators
8
13
  [Long Method] RedCloth#blocks has approx 17 statements
9
14
  [Nested Iterators] RedCloth#blocks has nested iterators
10
15
  [Control Couple] RedCloth#blocks is controlled by argument deep_code
11
16
  [Control Couple] RedCloth#check_refs is controlled by argument text
17
+ [Duplication] RedCloth#clean_html calls tags[tag] more than once
12
18
  [Utility Function] RedCloth#clean_html doesn't depend on instance state
13
19
  [Long Method] RedCloth#clean_html has approx 14 statements
14
20
  [Nested Iterators] RedCloth#clean_html has nested iterators
21
+ [Feature Envy] RedCloth#clean_html refers to tags more than self
15
22
  [Long Method] RedCloth#clean_white_space has approx 7 statements
16
- [Feature Envy] RedCloth#clean_white_space uses text more than self
23
+ [Feature Envy] RedCloth#clean_white_space refers to text more than self
17
24
  [Utility Function] RedCloth#flush_left doesn't depend on instance state
25
+ [Feature Envy] RedCloth#flush_left refers to indt more than self
26
+ [Feature Envy] RedCloth#flush_left refers to text more than self
18
27
  [Utility Function] RedCloth#footnote_ref doesn't depend on instance state
19
28
  [Long Method] RedCloth#glyphs_textile has approx 9 statements
20
29
  [Utility Function] RedCloth#h_align doesn't depend on instance state
21
30
  [Utility Function] RedCloth#htmlesc doesn't depend on instance state
31
+ [Feature Envy] RedCloth#htmlesc refers to str more than self
22
32
  [Utility Function] RedCloth#incoming_entities doesn't depend on instance state
23
33
  [Nested Iterators] RedCloth#inline has nested iterators
24
34
  [Long Method] RedCloth#inline_markdown_link has approx 6 statements
@@ -29,13 +39,21 @@
29
39
  [Nested Iterators] RedCloth#inline_textile_span has nested iterators
30
40
  [Utility Function] RedCloth#lT doesn't depend on instance state
31
41
  [Utility Function] RedCloth#no_textile doesn't depend on instance state
42
+ [Feature Envy] RedCloth#no_textile refers to text more than self
43
+ [Duplication] RedCloth#pba calls $1.length more than once
32
44
  [Long Method] RedCloth#pba has approx 22 statements
33
45
  [Control Couple] RedCloth#pba is controlled by argument text_in
34
- [Feature Envy] RedCloth#pba uses style and text more than self
46
+ [Feature Envy] RedCloth#pba refers to style more than self
47
+ [Feature Envy] RedCloth#pba refers to text more than self
48
+ [Duplication] RedCloth#rip_offtags calls @pre_list.last more than once
49
+ [Duplication] RedCloth#rip_offtags calls @pre_list.last.<<(line) more than once
50
+ [Duplication] RedCloth#rip_offtags calls codepre.-(used_offtags.length) more than once
51
+ [Duplication] RedCloth#rip_offtags calls codepre.-(used_offtags.length).>(0) more than once
52
+ [Duplication] RedCloth#rip_offtags calls codepre.zero? more than once
53
+ [Duplication] RedCloth#rip_offtags calls used_offtags.length more than once
54
+ [Duplication] RedCloth#rip_offtags calls used_offtags[notextile] more than once
35
55
  [Long Method] RedCloth#rip_offtags has approx 22 statements
36
- [Feature Envy] RedCloth#rip_offtags uses codepre more than self
37
- [Feature Envy] RedCloth#shelve uses @shelf more than self
38
- [Feature Envy] RedCloth#smooth_offtags uses @pre_list more than self
56
+ [Feature Envy] RedCloth#rip_offtags refers to codepre more than self
39
57
  [Long Parameter List] RedCloth#textile_bq has 4 parameters
40
58
  [Control Couple] RedCloth#textile_bq is controlled by argument atts
41
59
  [Control Couple] RedCloth#textile_bq is controlled by argument cite
data/spec/script_spec.rb CHANGED
@@ -62,7 +62,7 @@ describe 'report format', 'with one source' do
62
62
 
63
63
  it 'should not adorn the list of warnings' do
64
64
  report = `ruby -Ilib bin/reek "def y() @x = 3; end"`
65
- report.split(/\n/).length.should == 1
65
+ report.split(/\n/).length.should == 2
66
66
  report.should_not match(/\n\n/)
67
67
  end
68
68
  end
data/tasks/reek.rake CHANGED
@@ -1,7 +1,16 @@
1
1
  require 'reek/rake_task'
2
+ require 'flay'
2
3
 
3
4
  Reek::RakeTask.new do |t|
4
5
  t.fail_on_error = true
5
6
  t.verbose = false
6
7
  # t.sort = 'smell'
7
8
  end
9
+
10
+ desc 'Check for code duplication'
11
+ task 'flay' do
12
+ files = FileList['lib/**/*.rb']
13
+ flayer = Flay.new(16)
14
+ flayer.process(*files)
15
+ flayer.report
16
+ end
data/website/index.html CHANGED
@@ -39,7 +39,7 @@
39
39
  <h2>Installing</h2>
40
40
  <code>$ gem install reek</code>
41
41
  <h2>The basics</h2>
42
- <code>$ reek [options] [source_files]</code>
42
+ <code>$ reek [options] sources</code>
43
43
  <p>(See <code>reek --help</code> for details.)</p>
44
44
  <h2>Code Smells</h2>
45
45
  <p>reek currently includes very naive checks for the following code smells:</p>
@@ -51,6 +51,7 @@
51
51
  <li>Long Parameter List</li>
52
52
  <li>Utility Function</li>
53
53
  <li>Nested Iterators</li>
54
+ <li>Control Couple</li>
54
55
  </ul>
55
56
  <h2>How to access the source code</h2>
56
57
  <p>The source is hosted on both <a href="http://github.com/kevinrutherford/reek/tree/master">github</a> and <a href="http://rubyforge.org/projects/reek/">rubyforge</a></p>
@@ -59,7 +60,7 @@
59
60
  <h2>Contact</h2>
60
61
  <p>Comments are welcome. Send an email to <a href="mailto:kevin@rutherford-software.com">Kevin Rutherford</a></p>
61
62
  <p class="coda">
62
- <a href="http://www.kevinrutherford.co.uk">Kevin Rutherford</a>, 15th September 2008<br>
63
+ <a href="http://www.kevinrutherford.co.uk">Kevin Rutherford</a>, 2nd November 2008<br>
63
64
  Theme extended from <a href="http://rb2js.rubyforge.org/">Paul Battley</a>
64
65
  </p>
65
66
  </div>
data/website/index.txt CHANGED
@@ -8,7 +8,7 @@ h2. Installing
8
8
 
9
9
  h2. The basics
10
10
 
11
- @$ reek [options] [source_files]@
11
+ @$ reek [options] sources@
12
12
 
13
13
  (See @reek --help@ for details.)
14
14
 
@@ -23,6 +23,8 @@ reek currently includes very naive checks for the following code smells:
23
23
  * Long Parameter List
24
24
  * Utility Function
25
25
  * Nested Iterators
26
+ * Control Couple
27
+ * Duplication
26
28
 
27
29
  h2. How to access the source code
28
30
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reek
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Rutherford
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-11-02 00:00:00 +00:00
12
+ date: 2008-11-17 00:00:00 +00:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -68,25 +68,37 @@ files:
68
68
  - lib/reek/printer.rb
69
69
  - lib/reek/rake_task.rb
70
70
  - lib/reek/report.rb
71
- - lib/reek/smells.rb
71
+ - lib/reek/smells/control_couple.rb
72
+ - lib/reek/smells/duplication.rb
73
+ - lib/reek/smells/feature_envy.rb
74
+ - lib/reek/smells/large_class.rb
75
+ - lib/reek/smells/long_method.rb
76
+ - lib/reek/smells/long_parameter_list.rb
77
+ - lib/reek/smells/long_yield_list.rb
78
+ - lib/reek/smells/nested_iterators.rb
79
+ - lib/reek/smells/smell.rb
80
+ - lib/reek/smells/smells.rb
81
+ - lib/reek/smells/uncommunicative_name.rb
82
+ - lib/reek/smells/utility_function.rb
72
83
  - lib/reek/version.rb
73
84
  - setup.rb
74
85
  - spec/integration_spec.rb
75
86
  - spec/reek/class_checker_spec.rb
76
- - spec/reek/control_couple_spec.rb
77
- - spec/reek/feature_envy_spec.rb
78
- - spec/reek/large_class_spec.rb
79
- - spec/reek/long_method_spec.rb
80
- - spec/reek/long_parameter_list_spec.rb
81
87
  - spec/reek/method_checker_spec.rb
82
- - spec/reek/nested_iterators_spec.rb
83
88
  - spec/reek/object_refs_spec.rb
84
89
  - spec/reek/options_spec.rb
85
90
  - spec/reek/printer_spec.rb
86
91
  - spec/reek/report_spec.rb
87
- - spec/reek/smell_spec.rb
88
- - spec/reek/uncommunicative_name_spec.rb
89
- - spec/reek/utility_function_spec.rb
92
+ - spec/reek/smells/control_couple_spec.rb
93
+ - spec/reek/smells/duplication_spec.rb
94
+ - spec/reek/smells/feature_envy_spec.rb
95
+ - spec/reek/smells/large_class_spec.rb
96
+ - spec/reek/smells/long_method_spec.rb
97
+ - spec/reek/smells/long_parameter_list_spec.rb
98
+ - spec/reek/smells/nested_iterators_spec.rb
99
+ - spec/reek/smells/smell_spec.rb
100
+ - spec/reek/smells/uncommunicative_name_spec.rb
101
+ - spec/reek/smells/utility_function_spec.rb
90
102
  - spec/reek_source_spec.rb
91
103
  - spec/samples/inline.rb
92
104
  - spec/samples/inline.reek
data/lib/reek/smells.rb DELETED
@@ -1,192 +0,0 @@
1
- $:.unshift File.dirname(__FILE__)
2
-
3
- require 'reek/printer'
4
- require 'reek/options'
5
-
6
- module Reek
7
-
8
- class Smell
9
- include Comparable
10
-
11
- def self.convert_camel_case(class_name)
12
- class_name.gsub(/([a-z])([A-Z])/) { |s| "#{$1} #{$2}"}
13
- end
14
-
15
- def initialize(context, arg=nil)
16
- @context = context
17
- end
18
-
19
- def self.check(exp, context, arg=nil)
20
- smell = new(context, arg)
21
- return false unless smell.recognise?(exp)
22
- context.report(smell)
23
- true
24
- end
25
-
26
- def recognise?(stuff)
27
- @context != nil
28
- end
29
-
30
- def hash # :nodoc:
31
- report.hash
32
- end
33
-
34
- def <=>(other) # :nodoc:
35
- Options[:sort_order].compare(self, other)
36
- end
37
-
38
- alias eql? <=>
39
-
40
- def name
41
- self.class.convert_camel_case(self.class.name.split(/::/)[1])
42
- end
43
-
44
- def report
45
- "[#{name}] #{detailed_report}"
46
- end
47
-
48
- alias inspect report
49
-
50
- def to_s
51
- report
52
- end
53
- end
54
-
55
- class LongParameterList < Smell
56
- MAX_ALLOWED = 3
57
-
58
- def self.count_parameters(exp)
59
- result = exp.length - 1
60
- result -= 1 if Array === exp[-1] and exp[-1][0] == :block
61
- result
62
- end
63
-
64
- def recognise?(args)
65
- @num_params = LongParameterList.count_parameters(args)
66
- @num_params > MAX_ALLOWED
67
- end
68
-
69
- def detailed_report
70
- "#{@context.to_s} has #{@num_params} parameters"
71
- end
72
- end
73
-
74
- class LongYieldList < LongParameterList
75
- def recognise?(args)
76
- @num_params = args.length
77
- Array === args and @num_params > MAX_ALLOWED
78
- end
79
-
80
- def detailed_report
81
- "#{@context} yields #{@num_params} parameters"
82
- end
83
- end
84
-
85
- class LongMethod < Smell
86
- MAX_ALLOWED = 5
87
-
88
- def recognise?(num_stmts)
89
- @num_stmts = num_stmts
90
- num_stmts > MAX_ALLOWED
91
- end
92
-
93
- def detailed_report
94
- "#{@context} has approx #{@num_stmts} statements"
95
- end
96
- end
97
-
98
- class FeatureEnvy < Smell
99
-
100
- def recognise?(refs)
101
- @refs = refs
102
- !refs.self_is_max?
103
- end
104
-
105
- def detailed_report
106
- receiver = @refs.max_keys.map {|r| Printer.print(r)}.sort.join(' and ')
107
- "#{@context} uses #{receiver} more than self"
108
- end
109
- end
110
-
111
- class UtilityFunction < Smell
112
- def initialize(context, num_stmts)
113
- super
114
- @num_stmts = num_stmts
115
- end
116
-
117
- def recognise?(depends_on_self)
118
- @num_stmts > 0 and !depends_on_self
119
- end
120
-
121
- def detailed_report
122
- "#{@context} doesn't depend on instance state"
123
- end
124
- end
125
-
126
- class LargeClass < Smell
127
- MAX_ALLOWED = 25
128
-
129
- def self.non_inherited_methods(klass)
130
- return klass.instance_methods if klass.superclass.nil?
131
- klass.instance_methods - klass.superclass.instance_methods
132
- end
133
-
134
- def recognise?(name)
135
- klass = Object.const_get(name) rescue return
136
- @num_methods = LargeClass.non_inherited_methods(klass).length
137
- @num_methods > MAX_ALLOWED
138
- end
139
-
140
- def detailed_report
141
- "#{@context} has #{@num_methods} methods"
142
- end
143
- end
144
-
145
- class UncommunicativeName < Smell
146
- def initialize(context, symbol_type)
147
- super
148
- @symbol_type = symbol_type
149
- end
150
-
151
- def self.effective_length(name)
152
- return 500 if name == '*'
153
- name = name[1..-1] while /^@/ === name
154
- name.length
155
- end
156
-
157
- def recognise?(symbol)
158
- @symbol = symbol.to_s
159
- UncommunicativeName.effective_length(@symbol) < 2
160
- end
161
-
162
- def detailed_report
163
- "#{@context} uses the #{@symbol_type} name '#{@symbol}'"
164
- end
165
- end
166
-
167
- class NestedIterators < Smell
168
- def recognise?(already_in_iter)
169
- already_in_iter
170
- end
171
-
172
- def detailed_report
173
- "#{@context} has nested iterators"
174
- end
175
- end
176
-
177
- class ControlCouple < Smell
178
- def initialize(context, args)
179
- super
180
- @args = args
181
- end
182
-
183
- def recognise?(cond)
184
- @couple = cond
185
- cond[0] == :lvar and @args.include?(@couple[1])
186
- end
187
-
188
- def detailed_report
189
- "#{@context} is controlled by argument #{Printer.print(@couple)}"
190
- end
191
- end
192
- end