reek 0.3.1 → 1.0.0

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 (96) hide show
  1. data/History.txt +20 -0
  2. data/README.txt +4 -80
  3. data/Rakefile +15 -4
  4. data/bin/reek +10 -16
  5. data/config/defaults.reek +53 -0
  6. data/lib/reek.rb +1 -21
  7. data/lib/reek/block_context.rb +37 -0
  8. data/lib/reek/class_context.rb +73 -0
  9. data/lib/reek/code_context.rb +47 -0
  10. data/lib/reek/code_parser.rb +204 -0
  11. data/lib/reek/exceptions.reek +13 -0
  12. data/lib/reek/if_context.rb +25 -0
  13. data/lib/reek/method_context.rb +85 -0
  14. data/lib/reek/module_context.rb +34 -0
  15. data/lib/reek/name.rb +42 -0
  16. data/lib/reek/object_refs.rb +3 -6
  17. data/lib/reek/options.rb +60 -40
  18. data/lib/reek/rake_task.rb +20 -29
  19. data/lib/reek/report.rb +16 -27
  20. data/lib/reek/sexp_formatter.rb +52 -0
  21. data/lib/reek/singleton_method_context.rb +27 -0
  22. data/lib/reek/smell_warning.rb +49 -0
  23. data/lib/reek/smells/control_couple.rb +21 -13
  24. data/lib/reek/smells/duplication.rb +23 -27
  25. data/lib/reek/smells/feature_envy.rb +18 -25
  26. data/lib/reek/smells/large_class.rb +32 -17
  27. data/lib/reek/smells/long_method.rb +24 -16
  28. data/lib/reek/smells/long_parameter_list.rb +25 -18
  29. data/lib/reek/smells/long_yield_list.rb +7 -9
  30. data/lib/reek/smells/nested_iterators.rb +13 -9
  31. data/lib/reek/smells/smell_detector.rb +66 -0
  32. data/lib/reek/smells/smells.rb +71 -10
  33. data/lib/reek/smells/uncommunicative_name.rb +49 -41
  34. data/lib/reek/smells/utility_function.rb +18 -18
  35. data/lib/reek/source.rb +116 -0
  36. data/lib/reek/spec.rb +146 -0
  37. data/lib/reek/stop_context.rb +62 -0
  38. data/lib/reek/yield_call_context.rb +14 -0
  39. data/reek.gemspec +42 -0
  40. data/spec/integration/reek_source_spec.rb +20 -0
  41. data/spec/{script_spec.rb → integration/script_spec.rb} +11 -24
  42. data/spec/reek/class_context_spec.rb +198 -0
  43. data/spec/reek/code_context_spec.rb +92 -0
  44. data/spec/reek/code_parser_spec.rb +44 -0
  45. data/spec/reek/config_spec.rb +42 -0
  46. data/spec/reek/if_context_spec.rb +17 -0
  47. data/spec/reek/method_context_spec.rb +52 -0
  48. data/spec/reek/module_context_spec.rb +38 -0
  49. data/spec/reek/options_spec.rb +2 -28
  50. data/spec/reek/report_spec.rb +6 -40
  51. data/spec/reek/sexp_formatter_spec.rb +31 -0
  52. data/spec/reek/singleton_method_context_spec.rb +17 -0
  53. data/spec/reek/smells/control_couple_spec.rb +10 -18
  54. data/spec/reek/smells/duplication_spec.rb +53 -32
  55. data/spec/reek/smells/feature_envy_spec.rb +87 -49
  56. data/spec/reek/smells/large_class_spec.rb +45 -4
  57. data/spec/reek/smells/long_method_spec.rb +25 -41
  58. data/spec/reek/smells/long_parameter_list_spec.rb +30 -76
  59. data/spec/reek/smells/nested_iterators_spec.rb +19 -29
  60. data/spec/reek/smells/smell_spec.rb +9 -18
  61. data/spec/reek/smells/uncommunicative_name_spec.rb +88 -53
  62. data/spec/reek/smells/utility_function_spec.rb +45 -44
  63. data/spec/samples/inline_spec.rb +40 -0
  64. data/spec/samples/optparse_spec.rb +100 -0
  65. data/spec/samples/redcloth_spec.rb +93 -0
  66. data/spec/spec_helper.rb +3 -1
  67. data/tasks/reek.rake +1 -10
  68. data/tasks/rspec.rake +16 -35
  69. metadata +43 -46
  70. data/lib/reek/checker.rb +0 -66
  71. data/lib/reek/class_checker.rb +0 -25
  72. data/lib/reek/file_checker.rb +0 -20
  73. data/lib/reek/method_checker.rb +0 -198
  74. data/lib/reek/printer.rb +0 -154
  75. data/lib/reek/smells/smell.rb +0 -56
  76. data/lib/reek/version.rb +0 -9
  77. data/setup.rb +0 -1585
  78. data/spec/integration_spec.rb +0 -30
  79. data/spec/reek/class_checker_spec.rb +0 -48
  80. data/spec/reek/method_checker_spec.rb +0 -67
  81. data/spec/reek/printer_spec.rb +0 -30
  82. data/spec/reek_source_spec.rb +0 -12
  83. data/spec/samples/inline.reek +0 -27
  84. data/spec/samples/optparse.reek +0 -79
  85. data/spec/samples/optparse/date.rb +0 -17
  86. data/spec/samples/optparse/shellwords.rb +0 -6
  87. data/spec/samples/optparse/time.rb +0 -10
  88. data/spec/samples/optparse/uri.rb +0 -6
  89. data/spec/samples/optparse/version.rb +0 -70
  90. data/spec/samples/redcloth.reek +0 -65
  91. data/tasks/samples.rake +0 -17
  92. data/website/index.html +0 -71
  93. data/website/index.txt +0 -40
  94. data/website/javascripts/rounded_corners_lite.inc.js +0 -285
  95. data/website/stylesheets/screen.css +0 -138
  96. data/website/template.rhtml +0 -48
@@ -1,11 +1,12 @@
1
1
  require File.dirname(__FILE__) + '/../../spec_helper.rb'
2
-
3
- require 'reek/class_checker'
2
+ require 'reek/code_parser'
4
3
  require 'reek/report'
4
+ require 'reek/smells/large_class'
5
5
 
6
6
  include Reek
7
+ include Reek::Smells
7
8
 
8
- describe ClassChecker, "(Large Class)" do
9
+ describe LargeClass do
9
10
 
10
11
  class BigOne
11
12
  26.times do |i|
@@ -17,7 +18,7 @@ describe ClassChecker, "(Large Class)" do
17
18
 
18
19
  before(:each) do
19
20
  @rpt = Report.new
20
- @cchk = ClassChecker.new(@rpt)
21
+ @cchk = CodeParser.new(@rpt, SmellConfig.new.smell_listeners)
21
22
  end
22
23
 
23
24
  it 'should not report short class' do
@@ -42,4 +43,44 @@ describe ClassChecker, "(Large Class)" do
42
43
  @cchk.check_object(BigOne)
43
44
  @rpt[0].report.should match(/BigOne/)
44
45
  end
46
+
47
+ describe 'when exceptions are listed' do
48
+ before :each do
49
+ @ctx = ClassContext.create(StopContext.new, [0, :Humungous])
50
+ 30.times { |num| @ctx.record_method("method#{num}") }
51
+ @config = LargeClass.default_config
52
+ end
53
+
54
+ it 'should ignore first excepted name' do
55
+ @config[LargeClass::EXCLUDE_KEY] = ['Humungous']
56
+ lc = LargeClass.new(@config)
57
+ lc.examine(@ctx, @rpt).should == false
58
+ @rpt.length.should == 0
59
+ end
60
+
61
+ it 'should ignore second excepted name' do
62
+ @config[LargeClass::EXCLUDE_KEY] = ['Oversized', 'Humungous']
63
+ lc = LargeClass.new(@config)
64
+ lc.examine(@ctx, @rpt).should == false
65
+ @rpt.length.should == 0
66
+ end
67
+
68
+ it 'should report non-excepted name' do
69
+ @config[LargeClass::EXCLUDE_KEY] = ['SmellMe']
70
+ lc = LargeClass.new(@config)
71
+ lc.examine(@ctx, @rpt).should == true
72
+ @rpt.length.should == 1
73
+ end
74
+ end
75
+ end
76
+
77
+ describe LargeClass do
78
+ it 'should not report empty class in another module' do
79
+ 'class Treetop::Runtime::SyntaxNode; end'.should_not reek
80
+ end
81
+
82
+ it 'should deal with :: scoped names' do
83
+ element = ClassContext.create(StopContext.new, [:colon2, [:colon2, [:const, :Treetop], :Runtime], :SyntaxNode])
84
+ element.num_methods.should == 0
85
+ end
45
86
  end
@@ -1,58 +1,43 @@
1
1
  require File.dirname(__FILE__) + '/../../spec_helper.rb'
2
2
 
3
- require 'reek/method_checker'
3
+ require 'reek/code_parser'
4
4
  require 'reek/report'
5
5
 
6
6
  include Reek
7
7
 
8
- describe MethodChecker, "(Long Method)" do
9
-
10
- before(:each) do
11
- @rpt = Report.new
12
- @cchk = MethodChecker.new(@rpt, 'Thing')
13
- end
14
-
8
+ describe CodeParser, "(Long Method)" do
15
9
  it 'should not report short methods' do
16
- @cchk.check_source('def short(arga) alf = f(1);@bet = 2;@cut = 3;@dit = 4; @emp = 5;end')
17
- @rpt.should be_empty
10
+ 'def short(arga) alf = f(1);@bet = 2;@cut = 3;@dit = 4; @emp = 5;end'.should_not reek
18
11
  end
19
12
 
20
13
  it 'should report long methods' do
21
- @cchk.check_source('def long(arga) alf = f(1);@bet = 2;@cut = 3;@dit = 4; @emp = 5;@fry = 6;end')
22
- @rpt.length.should == 1
23
- @rpt[0].should be_instance_of(LongMethod)
14
+ 'def long(arga) alf = f(1);@bet = 2;@cut = 3;@dit = 4; @emp = 5;@fry = 6;end'.should reek_only_of(:LongMethod, /6 statements/)
15
+ end
16
+
17
+ it 'should not report initialize' do
18
+ 'def initialize(arga) alf = f(1);@bet = 2;@cut = 3;@dit = 4; @emp = 5;@fry = 6;end'.should_not reek
24
19
  end
25
20
 
26
21
  it 'should only report a long method once' do
27
22
  source =<<EOS
28
- def standard_entries(rbconfig)
29
- @abc = rbconfig
30
- rubypath = File.join(@abc['bindir'], @abcf['ruby_install_name'] + cff['EXEEXT'])
31
- major = yyy['MAJOR'].to_i
32
- minor = zzz['MINOR'].to_i
33
- teeny = ccc['TEENY'].to_i
34
- version = ""
35
- if c['rubylibdir']
36
- @libruby = "/lib/ruby"
37
- @librubyver = "/lib/ruby/"
38
- @librubyverarch = "/lib/ruby/"
39
- @siteruby = "lib/ruby/version/site_ruby"
40
- @siterubyver = siteruby
41
- @siterubyverarch = "$siterubyver/['arch']}"
42
- end
43
- end
44
- EOS
45
- @cchk.check_source(source)
46
- @rpt.length.should == 1
47
- @rpt[0].should be_instance_of(LongMethod)
23
+ def standard_entries(rbconfig)
24
+ @abc = rbconfig
25
+ rubypath = File.join(@abc['bindir'], @abcf['ruby_install_name'] + cff['EXEEXT'])
26
+ major = yyy['MAJOR'].to_i
27
+ minor = zzz['MINOR'].to_i
28
+ teeny = ccc['TEENY'].to_i
29
+ version = ""
30
+ if c['rubylibdir']
31
+ @libruby = "/lib/ruby"
32
+ @librubyver = "/lib/ruby/"
33
+ @librubyverarch = "/lib/ruby/"
34
+ @siteruby = "lib/ruby/version/site_ruby"
35
+ @siterubyver = siteruby
36
+ @siterubyverarch = "$siterubyver/['arch']}"
48
37
  end
49
38
  end
50
-
51
- describe MethodChecker, "(Long Block)" do
52
-
53
- before(:each) do
54
- @rpt = Report.new
55
- @cchk = MethodChecker.new(@rpt, 'Thing')
39
+ EOS
40
+ source.should reek_only_of(:LongMethod)
56
41
  end
57
42
 
58
43
  it 'should report long inner block' do
@@ -69,7 +54,6 @@ def long(arga)
69
54
  end
70
55
  end
71
56
  EOS
72
- @cchk.check_source(src)
73
- @rpt.length.should == 1
57
+ src.should reek_only_of(:LongMethod)
74
58
  end
75
59
  end
@@ -1,89 +1,67 @@
1
1
  require File.dirname(__FILE__) + '/../../spec_helper.rb'
2
2
 
3
- require 'reek/method_checker'
3
+ require 'reek/code_parser'
4
+ require 'reek/smells/long_parameter_list'
4
5
  require 'reek/report'
5
6
 
6
7
  include Reek
8
+ include Reek::Smells
7
9
 
8
- describe MethodChecker, "(Long Parameter List)" do
9
-
10
- before(:each) do
11
- @rpt = Report.new
12
- @cchk = MethodChecker.new(@rpt, 'Thing')
13
- end
10
+ describe CodeParser, "(Long Parameter List)" do
14
11
 
15
12
  describe 'for methods with few parameters' do
16
13
  it 'should report nothing for no parameters' do
17
- @cchk.check_source('def simple; f(3);true; end')
18
- @rpt.should be_empty
14
+ 'def simple; f(3);true; end'.should_not reek
19
15
  end
20
-
21
16
  it 'should report nothing for 1 parameter' do
22
- @cchk.check_source('def simple(yep) f(3);true end')
23
- @rpt.should be_empty
17
+ 'def simple(yep) f(3);true end'.should_not reek
24
18
  end
25
-
26
19
  it 'should report nothing for 2 parameters' do
27
- @cchk.check_source('def simple(yep,zero) f(3);true end')
28
- @rpt.should be_empty
20
+ 'def simple(yep,zero) f(3);true end'.should_not reek
29
21
  end
30
-
31
22
  it 'should not count an optional block' do
32
- @cchk.check_source('def simple(alpha, yep, zero, &opt) f(3);true end')
33
- @rpt.should be_empty
23
+ 'def simple(alpha, yep, zero, &opt) f(3);true end'.should_not reek
34
24
  end
35
-
36
25
  it 'should not report inner block with too many parameters' do
37
- @cchk.check_source('def simple(yep,zero); m[3]; rand(34); f.each { |arga, argb, argc, argd| true}; end')
38
- @rpt.should be_empty
26
+ 'def simple(yep,zero); m[3]; rand(34); f.each { |arga, argb, argc, argd| true}; end'.should_not reek
39
27
  end
40
28
 
41
29
  describe 'and default values' do
42
30
  it 'should report nothing for 1 parameter' do
43
- @cchk.check_source('def simple(zero=nil) f(3);false end')
44
- @rpt.should be_empty
31
+ 'def simple(zero=nil) f(3);false end'.should_not reek
45
32
  end
46
-
47
33
  it 'should report nothing for 2 parameters with 1 default' do
48
- @cchk.check_source('def simple(yep, zero=nil) f(3);false end')
49
- @rpt.should be_empty
34
+ 'def simple(yep, zero=nil) f(3);false end'.should_not reek
50
35
  end
51
-
52
36
  it 'should report nothing for 2 defaulted parameters' do
53
- @cchk.check_source('def simple(yep=4, zero=nil) f(3);false end')
54
- @rpt.should be_empty
37
+ 'def simple(yep=4, zero=nil) f(3);false end'.should_not reek
55
38
  end
56
39
  end
57
40
  end
58
41
 
59
42
  describe 'for methods with too many parameters' do
60
43
  it 'should report 4 parameters' do
61
- @cchk.check_source('def simple(arga, argb, argc, argd) f(3);true end')
62
- @rpt.length.should == 1
63
- @rpt[0].should be_instance_of(LongParameterList)
44
+ 'def simple(arga, argb, argc, argd) f(3);true end'.should reek_only_of(:LongParameterList, /4 parameters/)
64
45
  end
65
-
66
46
  it 'should report 8 parameters' do
67
- @cchk.check_source('def simple(arga, argb, argc, argd,arge, argf, argg, argh) f(3);true end')
68
- @rpt.length.should == 1
69
- @rpt[0].should be_instance_of(LongParameterList)
47
+ 'def simple(arga, argb, argc, argd,arge, argf, argg, argh) f(3);true end'.should reek_only_of(:LongParameterList, /8 parameters/)
70
48
  end
71
49
 
72
50
  describe 'and default values' do
73
51
  it 'should report 3 with 1 defaulted' do
74
- @cchk.check_source('def simple(polly, queue, yep, zero=nil) f(3);false end')
75
- @rpt.length.should == 1
76
- @rpt[0].should be_instance_of(LongParameterList)
52
+ 'def simple(polly, queue, yep, zero=nil) f(3);false end'.should reek_only_of(:LongParameterList, /4 parameters/)
77
53
  end
78
-
79
54
  it 'should report with 3 defaulted' do
80
- @cchk.check_source('def simple(aarg, polly=2, yep=true, zero=nil) f(3);false end')
81
- @rpt.length.should == 1
82
- @rpt[0].should be_instance_of(LongParameterList)
55
+ 'def simple(aarg, polly=2, yep=true, zero=nil) f(3);false end'.should reek_only_of(:LongParameterList, /4 parameters/)
83
56
  end
84
57
  end
85
58
 
86
59
  describe 'in a class' do
60
+ before(:each) do
61
+ @rpt = Report.new
62
+ @cchk = CodeParser.new(@rpt, SmellConfig.new.smell_listeners)
63
+ end
64
+
87
65
  class InnerTest
88
66
  def xyzero(arga,argb) f(3);true end
89
67
  def abc(argx,yep,zero,argm) f(3);false end
@@ -92,47 +70,23 @@ describe MethodChecker, "(Long Parameter List)" do
92
70
  it 'should only report long param list' do
93
71
  @cchk.check_object(InnerTest)
94
72
  @rpt.length.should == 1
95
- @rpt[0].should be_instance_of(LongParameterList)
73
+ @rpt[0].report.should match(/Long Parameter List/)
96
74
  end
97
75
  end
98
76
  end
99
77
 
100
78
  describe 'yield' do
79
+ it 'should not report yield with no parameters' do
80
+ 'def simple(arga, argb, &blk) f(3);yield; end'.should_not reek
81
+ end
101
82
  it 'should not report yield with few parameters' do
102
- @cchk.check_source('def simple(arga, argb, &blk) f(3);yield a,b; end')
103
- @rpt.should be_empty
83
+ 'def simple(arga, argb, &blk) f(3);yield a,b; end'.should_not reek
104
84
  end
105
-
106
85
  it 'should report yield with many parameters' do
107
- @cchk.check_source('def simple(arga, argb, &blk) f(3);yield a,b,a,b; end')
108
- @rpt.length.should == 1
109
- @rpt[0].should be_instance_of(LongYieldList)
86
+ 'def simple(arga, argb, &blk) f(3);yield a,b,a,b; end'.should reek_only_of(:LongYieldList, /simple/, /yields/, /4/)
87
+ end
88
+ it 'should not report yield of a long expression' do
89
+ 'def simple(arga, argb, &blk) f(3);yield(if @dec then argb else 5+3 end); end'.should_not reek
110
90
  end
111
-
112
- end
113
-
114
- end
115
-
116
- describe LongParameterList, 'when given the class name' do
117
-
118
- before(:each) do
119
- @rpt = Report.new
120
- @cchk = MethodChecker.new(@rpt, 'classname')
121
- end
122
-
123
- it 'should report the class name' do
124
- @cchk.check_source('def simple(arga, argb, argc, argd) f(3);true end')
125
- @rpt.length.should == 1
126
- @rpt[0].should be_instance_of(LongParameterList)
127
- @rpt[0].report.should match(/classname#simple/)
128
- end
129
- end
130
-
131
- describe LongParameterList, '#report' do
132
- it 'should report the method name and num params' do
133
- mchk = MethodChecker.new([], 'Class')
134
- smell = LongParameterList.new(mchk)
135
- smell.report.should match(/Class/)
136
91
  end
137
-
138
92
  end
@@ -1,43 +1,33 @@
1
1
  require File.dirname(__FILE__) + '/../../spec_helper.rb'
2
2
 
3
- require 'reek/method_checker'
4
- require 'reek/report'
5
-
6
- include Reek
7
-
8
- def check(desc, src, expected, pending_str = nil)
9
- it(desc) do
10
- pending(pending_str) unless pending_str.nil?
11
- rpt = Report.new
12
- cchk = MethodChecker.new(rpt, 'Thing')
13
- cchk.check_source(src)
14
- rpt.length.should == expected.length
15
- (0...rpt.length).each do |smell|
16
- expected[smell].each { |patt| rpt[smell].detailed_report.should match(patt) }
17
- end
18
- end
19
- end
3
+ require 'reek/smells/nested_iterators'
20
4
 
21
- describe MethodChecker, " nested iterators" do
5
+ include Reek::Smells
22
6
 
23
- check 'should report nested iterators in a method',
24
- 'def bad(fred) @fred.each {|item| item.each {|ting| ting.ting} } end', [[/nested iterators/]]
7
+ describe NestedIterators do
8
+
9
+ it 'should report nested iterators in a method' do
10
+ 'def bad(fred) @fred.each {|item| item.each {|ting| ting.ting} } end'.should reek_only_of(:NestedIterators)
11
+ end
25
12
 
26
- check 'should not report method with successive iterators',
13
+ it 'should not report method with successive iterators' do
27
14
  'def bad(fred)
28
15
  @fred.each {|item| item.each }
29
16
  @jim.each {|ting| ting.each }
30
- end', []
17
+ end'.should_not reek
18
+ end
31
19
 
32
- check 'should not report method with chained iterators',
20
+ it 'should not report method with chained iterators' do
33
21
  'def chained
34
- @sig.keys.sort_by { |x| x.to_s }.each { |m| md5 << m.to_s }
35
- end', []
22
+ @sig.keys.sort_by { |xray| xray.to_s }.each { |min| md5 << min.to_s }
23
+ end'.should_not reek
24
+ end
36
25
 
37
- check 'should report nested iterators only once per method',
26
+ it 'should report nested iterators only once per method' do
38
27
  'def bad(fred)
39
- @fred.each {|item| item.each {|part| @joe.send} }
40
- @jim.each {|ting| ting.each {|piece| @hal.send} }
41
- end', [[/nested iterators/]]
28
+ @fred.each {|item| item.each {|part| @joe.send} }
29
+ @jim.each {|ting| ting.each {|piece| @hal.send} }
30
+ end'.should reek_only_of(:NestedIterators)
31
+ end
42
32
  end
43
33
 
@@ -1,33 +1,24 @@
1
1
  require File.dirname(__FILE__) + '/../../spec_helper.rb'
2
2
 
3
- require 'reek/smells'
3
+ require 'reek/smells/smells'
4
4
 
5
5
  include Reek
6
6
 
7
- describe Smell, "camel case converter" do
8
- it "should convert camel case name" do
9
- Smell.convert_camel_case('LongParameterList').should == 'Long Parameter List'
7
+ describe SmellWarning, ' in comparisons' do
8
+ before :each do
9
+ @first = SmellWarning.new(Smells::FeatureEnvy.new, "self", "self")
10
+ @second = SmellWarning.new(Smells::FeatureEnvy.new, "self", "self")
10
11
  end
11
-
12
- it "should display correct name in report" do
13
- smell = LongMethod.new(self, 25)
14
- smell.report.should match(/[#{smell.name}]/)
15
- end
16
- end
17
12
 
18
- describe Smell, ' in comparisons' do
19
13
  it 'should hash equal when the smell is the same' do
20
- UtilityFunction.new(self, 2).hash.should == UtilityFunction.new(self, 2).hash
21
- NestedIterators.new(self).hash.should == NestedIterators.new(self).hash
14
+ @first.hash.should == @second.hash
22
15
  end
23
16
 
24
17
  it 'should compare equal when the smell is the same' do
25
- UtilityFunction.new(self, 2).should == UtilityFunction.new(self, 2)
26
- NestedIterators.new(self).should == NestedIterators.new(self)
18
+ @first.should == @second
27
19
  end
28
20
 
29
21
  it 'should compare equal when using <=>' do
30
- (UtilityFunction.new(self, 2) <=> UtilityFunction.new(self, 2)).should == 0
31
- (NestedIterators.new(self) <=> NestedIterators.new(self)).should == 0
22
+ (@first <=> @second).should == 0
32
23
  end
33
- end
24
+ end
@@ -1,83 +1,118 @@
1
1
  require File.dirname(__FILE__) + '/../../spec_helper.rb'
2
-
3
- require 'reek/method_checker'
4
- require 'reek/report'
2
+ require 'ostruct'
3
+ require 'reek/method_context'
4
+ require 'reek/smells/uncommunicative_name'
5
5
 
6
6
  include Reek
7
+ include Reek::Smells
7
8
 
8
- def check(desc, src, expected, pending_str = nil)
9
- it(desc) do
10
- pending(pending_str) unless pending_str.nil?
11
- rpt = Report.new
12
- cchk = MethodChecker.new(rpt, 'Thing')
13
- cchk.check_source(src)
14
- rpt.length.should == expected.length
15
- (0...rpt.length).each do |smell|
16
- expected[smell].each { |patt| rpt[smell].detailed_report.should match(patt) }
17
- end
9
+ describe UncommunicativeName, "method name" do
10
+ it 'should not report one-word method name' do
11
+ 'def help(fred) basics(17) end'.should_not reek
12
+ end
13
+ it 'should report one-letter method name' do
14
+ 'def x(fred) basics(17) end'.should reek_only_of(:UncommunicativeName, /x/)
15
+ end
16
+ it 'should report name of the form "x2"' do
17
+ 'def x2(fred) basics(17) end'.should reek_only_of(:UncommunicativeName, /x2/)
18
18
  end
19
19
  end
20
20
 
21
- describe MethodChecker, "uncommunicative method name" do
22
- check 'should not report one-word method name', 'def help(fred) basics(17) end', []
23
- check 'should report one-letter method name', 'def x(fred) basics(17) end', [[/x/, /method name/]]
24
- check 'should report name of the form "x2"', 'def x2(fred) basics(17) end', [[/x2/, /method name/]]
21
+ describe UncommunicativeName, "field name" do
22
+ it 'should not report one-word field name' do
23
+ 'class Thing; def help(fred) @simple end end'.should_not reek
24
+ end
25
+ it 'should report one-letter fieldname' do
26
+ 'class Thing; def simple(fred) @x end end'.should reek_only_of(:UncommunicativeName, /@x/, /Thing/, /variable name/)
27
+ end
28
+ it 'should report name of the form "x2"' do
29
+ 'class Thing; def simple(fred) @x2 end end'.should reek_only_of(:UncommunicativeName, /@x2/, /Thing/, /variable name/)
30
+ end
31
+ it 'should report one-letter fieldname in assignment' do
32
+ 'class Thing; def simple(fred) @x = fred end end'.should reek_only_of(:UncommunicativeName, /@x/, /Thing/, /variable name/)
33
+ end
25
34
  end
26
35
 
27
- describe MethodChecker, "uncommunicative field name" do
28
- check 'should not report one-word field name', 'def help(fred) @simple end', []
29
- check 'should report one-letter fieldname', 'def simple(fred) @x end', [[/@x/, /field name/]]
30
- check 'should report name of the form "x2"', 'def simple(fred) @x2 end', [[/@x2/, /field name/]]
31
- check 'should report one-letter fieldname in assignment', 'def simple(fred) @x = fred end', [[/@x/, /field name/]]
36
+ describe UncommunicativeName, "local variable name" do
37
+ it 'should not report one-word variable name' do
38
+ 'def help(fred) simple = jim(45) end'.should_not reek
39
+ end
40
+ it 'should report one-letter variable name' do
41
+ 'def simple(fred) x = jim(45) end'.should reek_only_of(:UncommunicativeName, /x/, /variable name/)
42
+ end
43
+ it 'should report name of the form "x2"' do
44
+ 'def simple(fred) x2 = jim(45) end'.should reek_only_of(:UncommunicativeName, /x2/, /variable name/)
45
+ end
46
+ it 'should report variable name only once' do
47
+ 'def simple(fred) x = jim(45); x = y end'.should reek_only_of(:UncommunicativeName, /x/)
48
+ end
32
49
  end
33
50
 
34
- describe MethodChecker, "uncommunicative local variable name" do
35
- check 'should not report one-word variable name', 'def help(fred) simple = jim(45) end', []
36
- check 'should report one-letter variable name', 'def simple(fred) x = jim(45) end', [[/x/, /local variable name/]]
37
- check 'should report name of the form "x2"', 'def simple(fred) x2 = jim(45) end', [[/x2/, /local variable name/]]
38
- check 'should report variable name only once', 'def simple(fred) x = jim(45); x = y end', [[]]
51
+ describe UncommunicativeName, "parameter name" do
52
+ it 'should not recognise *' do
53
+ 'def help(xray, *) basics(17) end'.should_not reek
54
+ end
55
+ it "should report parameter's name" do
56
+ 'def help(x) basics(17) end'.should reek_only_of(:UncommunicativeName, /x/, /variable name/)
57
+ end
58
+ it 'should report name of the form "x2"' do
59
+ 'def help(x2) basics(17) end'.should reek_only_of(:UncommunicativeName, /x2/, /variable name/)
60
+ end
39
61
  end
40
62
 
41
- describe MethodChecker, "uncommunicative parameter name" do
42
- check 'should recognise short parameter name', 'def help(x) basics(17) end', [[]]
43
- check 'should not recognise *', 'def help(xray, *) basics(17) end', []
44
- check "should report parameter's name", 'def help(x) basics(17) end', [[/x/, /parameter name/]]
45
- check 'should report name of the form "x2"', 'def help(x2) basics(17) end', [[/x2/, /parameter name/]]
63
+ describe UncommunicativeName, "block parameter name" do
64
+ it "should report parameter's name" do
65
+ 'def help() @stuff.each {|x|} end'.should reek_only_of(:UncommunicativeName, /x/, /block/, /variable name/)
66
+ end
67
+
68
+ it "should report method name via if context" do
69
+ src = <<EOS
70
+ def bad
71
+ unless @mod then
72
+ @sig.each { |x| x.to_s }
73
+ end
74
+ end
75
+ EOS
76
+ src.should reek_only_of(:UncommunicativeName, /'x'/)
77
+ end
46
78
  end
47
79
 
48
- describe MethodChecker, "several uncommunicative names" do
80
+ describe UncommunicativeName, "several names" do
49
81
 
50
- check 'should report all bad names', 'def y(x) @z = x end', [[/'@z'/], [/'y'/], [/'x'/]]
82
+ it 'should report all bad names' do
83
+ ruby = Source.from_s('class Oof; def y(x) @z = x end end')
84
+ ruby.should reek_of(:UncommunicativeName, /'x'/)
85
+ ruby.should reek_of(:UncommunicativeName, /'y'/)
86
+ ruby.should reek_of(:UncommunicativeName, /'@z'/)
87
+ end
51
88
 
52
- source =<<EOS
53
- def bad(fred)
54
- @fred.each {|x| 4 - x }
55
- @jim.each {|y| y - 4 }
89
+ it 'should report all bad block parameters' do
90
+ source =<<EOS
91
+ class Thing
92
+ def bad(fred)
93
+ @fred.each {|x| 4 - x }
94
+ @jim.each {|y| y - 4 }
95
+ end
56
96
  end
57
97
  EOS
58
- check 'should report all bad block parameters', source, [[/'x'/], [/'y'/]], 'bug'
98
+ source.should reek_of(:UncommunicativeName, /'x'/)
99
+ source.should reek_of(:UncommunicativeName, /'y'/)
100
+ end
59
101
  end
60
102
 
61
- require 'ostruct'
62
- require 'reek/smells/uncommunicative_name'
63
- include Reek::Smells
64
-
65
103
  describe UncommunicativeName, '#examine' do
66
-
67
104
  before :each do
68
- @mc = OpenStruct.new
69
- @mc.parameters = []
70
- @mc.local_variables = []
71
- @mc.instance_variables = []
105
+ @report = Report.new
106
+ @uc = UncommunicativeName.new
72
107
  end
73
-
108
+
74
109
  it 'should return true when reporting a smell' do
75
- @mc.name = 'x'
76
- UncommunicativeName.examine(@mc, []).should == true
110
+ mc = MethodContext.new(StopContext.new, [:defn, :x, nil])
111
+ @uc.examine(mc, @report).should == true
77
112
  end
78
113
 
79
114
  it 'should return false when not reporting a smell' do
80
- @mc.name = 'not_bad'
81
- UncommunicativeName.examine(@mc, []).should == false
115
+ mc = MethodContext.new(StopContext.new, [:defn, :not_bad, nil])
116
+ @uc.examine(mc, @report).should == false
82
117
  end
83
118
  end