reek 0.3.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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