wool 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. data/.document +5 -0
  2. data/.gitignore +23 -0
  3. data/LICENSE +45 -0
  4. data/README.rdoc +17 -0
  5. data/Rakefile +77 -0
  6. data/TODO.md +17 -0
  7. data/VERSION +1 -0
  8. data/bin/wool +4 -0
  9. data/features/step_definitions/wool_steps.rb +39 -0
  10. data/features/support/env.rb +14 -0
  11. data/features/support/testdata/1_input +1 -0
  12. data/features/support/testdata/1_output +1 -0
  13. data/features/support/testdata/2_input +4 -0
  14. data/features/support/testdata/2_output +4 -0
  15. data/features/support/testdata/3_input +8 -0
  16. data/features/support/testdata/3_output +11 -0
  17. data/features/support/testdata/4_input +5 -0
  18. data/features/support/testdata/4_output +5 -0
  19. data/features/wool.feature +24 -0
  20. data/lib/wool.rb +40 -0
  21. data/lib/wool/advice/advice.rb +42 -0
  22. data/lib/wool/advice/comment_advice.rb +37 -0
  23. data/lib/wool/analysis/annotations.rb +34 -0
  24. data/lib/wool/analysis/annotations/next_annotation.rb +26 -0
  25. data/lib/wool/analysis/annotations/parent_annotation.rb +20 -0
  26. data/lib/wool/analysis/annotations/scope_annotation.rb +37 -0
  27. data/lib/wool/analysis/lexical_analysis.rb +165 -0
  28. data/lib/wool/analysis/protocol_registry.rb +32 -0
  29. data/lib/wool/analysis/protocols.rb +82 -0
  30. data/lib/wool/analysis/scope.rb +13 -0
  31. data/lib/wool/analysis/sexp_analysis.rb +98 -0
  32. data/lib/wool/analysis/signature.rb +16 -0
  33. data/lib/wool/analysis/symbol.rb +10 -0
  34. data/lib/wool/analysis/visitor.rb +36 -0
  35. data/lib/wool/analysis/wool_class.rb +47 -0
  36. data/lib/wool/rake/task.rb +42 -0
  37. data/lib/wool/runner.rb +156 -0
  38. data/lib/wool/scanner.rb +160 -0
  39. data/lib/wool/support/module_extensions.rb +84 -0
  40. data/lib/wool/third_party/trollop.rb +845 -0
  41. data/lib/wool/warning.rb +145 -0
  42. data/lib/wool/warnings/comment_spacing.rb +30 -0
  43. data/lib/wool/warnings/extra_blank_lines.rb +29 -0
  44. data/lib/wool/warnings/extra_whitespace.rb +15 -0
  45. data/lib/wool/warnings/line_length.rb +113 -0
  46. data/lib/wool/warnings/misaligned_unindentation.rb +16 -0
  47. data/lib/wool/warnings/operator_spacing.rb +63 -0
  48. data/lib/wool/warnings/rescue_exception.rb +41 -0
  49. data/lib/wool/warnings/semicolon.rb +24 -0
  50. data/lib/wool/warnings/useless_double_quotes.rb +37 -0
  51. data/spec/advice_specs/advice_spec.rb +69 -0
  52. data/spec/advice_specs/comment_advice_spec.rb +38 -0
  53. data/spec/advice_specs/spec_helper.rb +1 -0
  54. data/spec/analysis_specs/annotations_specs/next_prev_annotation_spec.rb +47 -0
  55. data/spec/analysis_specs/annotations_specs/parent_annotation_spec.rb +41 -0
  56. data/spec/analysis_specs/annotations_specs/spec_helper.rb +5 -0
  57. data/spec/analysis_specs/lexical_analysis_spec.rb +179 -0
  58. data/spec/analysis_specs/protocol_registry_spec.rb +58 -0
  59. data/spec/analysis_specs/protocols_spec.rb +49 -0
  60. data/spec/analysis_specs/scope_spec.rb +20 -0
  61. data/spec/analysis_specs/sexp_analysis_spec.rb +134 -0
  62. data/spec/analysis_specs/spec_helper.rb +2 -0
  63. data/spec/analysis_specs/visitor_spec.rb +53 -0
  64. data/spec/analysis_specs/wool_class_spec.rb +54 -0
  65. data/spec/rake_specs/spec_helper.rb +1 -0
  66. data/spec/rake_specs/task_spec.rb +67 -0
  67. data/spec/runner_spec.rb +171 -0
  68. data/spec/scanner_spec.rb +75 -0
  69. data/spec/spec.opts +1 -0
  70. data/spec/spec_helper.rb +93 -0
  71. data/spec/support_specs/module_extensions_spec.rb +91 -0
  72. data/spec/support_specs/spec_helper.rb +1 -0
  73. data/spec/warning_spec.rb +95 -0
  74. data/spec/warning_specs/comment_spacing_spec.rb +57 -0
  75. data/spec/warning_specs/extra_blank_lines_spec.rb +70 -0
  76. data/spec/warning_specs/extra_whitespace_spec.rb +33 -0
  77. data/spec/warning_specs/line_length_spec.rb +165 -0
  78. data/spec/warning_specs/misaligned_unindentation_spec.rb +35 -0
  79. data/spec/warning_specs/operator_spacing_spec.rb +101 -0
  80. data/spec/warning_specs/rescue_exception_spec.rb +105 -0
  81. data/spec/warning_specs/semicolon_spec.rb +58 -0
  82. data/spec/warning_specs/spec_helper.rb +1 -0
  83. data/spec/warning_specs/useless_double_quotes_spec.rb +62 -0
  84. data/spec/wool_spec.rb +8 -0
  85. data/status_reports/2010/12/2010-12-14.md +163 -0
  86. data/test/third_party_tests/test_trollop.rb +1181 -0
  87. data/wool.gemspec +173 -0
  88. metadata +235 -0
@@ -0,0 +1,171 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Runner do
4
+ before do
5
+ @runner = Runner.new(['a', :b])
6
+ end
7
+
8
+ context '#run' do
9
+ it 'collects options and arguments, decides what to scan, scans, and displays' do
10
+ runner = Runner.new(['--report-fixed', 'hello', 'world'])
11
+ expected_settings = {:"report-fixed_given"=>true, :"report-fixed"=>true,
12
+ :fix => false, :help => false, :debug => false,
13
+ InlineCommentSpaceWarning::OPTION_KEY => 2,
14
+ :"line-length" => nil, :only => nil, :stdin => false,
15
+ :display => true,
16
+ :__using__ => Warning.all_warnings,
17
+ :__fix__ => Warning.all_warnings}
18
+ scanner = mock(:scanner)
19
+ Scanner.should_receive(:new, expected_settings).and_return(scanner)
20
+
21
+ data1, data2 = mock(:data1), mock(:data2)
22
+ warning1, warning2 = mock(:warning1), mock(:warning2)
23
+ file1, file2 = mock(:file1), mock(:file2)
24
+
25
+ scanner.should_receive(:settings).exactly(3).times.and_return({:"report-fixed" => true})
26
+ File.should_receive(:read).with('hello').and_return(data1)
27
+ scanner.should_receive(:scan).
28
+ with(data1, 'hello').
29
+ and_return([warning1])
30
+ warning1.should_receive(:to_ary)
31
+
32
+ scanner.should_receive(:settings).and_return({})
33
+ File.should_receive(:read).with('world').and_return(data2)
34
+ scanner.should_receive(:scan).
35
+ with(data2, 'world').
36
+ and_return([warning2])
37
+ warning2.should_receive(:to_ary)
38
+
39
+ runner.should_receive(:display_warnings).with([warning1, warning2], expected_settings)
40
+
41
+ runner.run
42
+ end
43
+
44
+ it 'works with :stdin => true' do
45
+ runner = Runner.new(['--stdin', '--only', 'UselessDoubleQuotesWarning'])
46
+ expected_settings = {:"report-fixed"=>false, :fix => false, :help => false,
47
+ :debug => false, InlineCommentSpaceWarning::OPTION_KEY => 2,
48
+ :"line-length" => nil, :only => 'UselessDoubleQuotesWarning',
49
+ :stdin => true, :stdin_given => true, :only_given => true,
50
+ :display => true,
51
+ :__using__ => [UselessDoubleQuotesWarning],
52
+ :__fix__ => [UselessDoubleQuotesWarning]}
53
+ scanner = mock(:scanner)
54
+ Scanner.should_receive(:new, expected_settings).and_return(scanner)
55
+
56
+ data1 = mock(:data1)
57
+ warning1 = mock(:warning1)
58
+
59
+ scanner.should_receive(:settings).twice.and_return({:"report-fixed" => true})
60
+ STDIN.should_receive(:read).and_return(data1)
61
+ scanner.should_receive(:scan).
62
+ with(data1, '(stdin)').
63
+ and_return([warning1])
64
+ warning1.should_receive(:to_ary)
65
+
66
+ runner.should_receive(:display_warnings).with([warning1], expected_settings)
67
+ runner.run
68
+ end
69
+ end
70
+
71
+ context '#collect_options_and_arguments' do
72
+ before do
73
+ @runner = Runner.new(['--fix', '--report-fixed', 'hello', 'there'])
74
+ @settings, @arguments = @runner.collect_options_and_arguments
75
+ end
76
+
77
+ it 'finds both flags' do
78
+ @settings[:fix].should be_true
79
+ @settings[:"report-fixed"].should be_true
80
+ end
81
+
82
+ it 'finds both stray arguments' do
83
+ @arguments.should == ['hello', 'there']
84
+ end
85
+ end
86
+
87
+ context '#swizzling_argv' do
88
+ it 'changes ARGV to the runner\'s argv value' do
89
+ @runner.swizzling_argv do
90
+ ARGV.should == ['a', :b]
91
+ end
92
+ end
93
+
94
+ it 'restores ARGV despite an exception' do
95
+ old_argv = ARGV.dup
96
+ proc {
97
+ @runner.swizzling_argv do
98
+ raise SystemExit.new('exiting')
99
+ end
100
+ }.should raise_error(SystemExit)
101
+ ARGV.should == old_argv
102
+ end
103
+ end
104
+
105
+ context '#get_settings' do
106
+ it 'has a --fix option' do
107
+ runner = Runner.new(['--fix'])
108
+ settings = runner.swizzling_argv { runner.get_settings }
109
+ settings[:fix].should be_true
110
+ settings[:fix_given].should be_true
111
+ end
112
+
113
+ it 'has a --report-fixed option' do
114
+ runner = Runner.new(['--report-fixed'])
115
+ settings = runner.swizzling_argv { runner.get_settings }
116
+ settings[:"report-fixed"].should be_true
117
+ settings[:"report-fixed_given"].should be_true
118
+ end
119
+ end
120
+
121
+ context '#handle_global_options' do
122
+ it 'specifies :using and :fix when :only is provided' do
123
+ runner = Runner.new([])
124
+ runner.handle_global_options(:only => 'UselessDoubleQuotesWarning')
125
+ runner.using.should == [UselessDoubleQuotesWarning]
126
+ runner.fix.should == [UselessDoubleQuotesWarning]
127
+ end
128
+
129
+ it 'works with multiple short names' do
130
+ runner = Runner.new([])
131
+ runner.handle_global_options(:only => 'ST1,ST3')
132
+ runner.using.size.should == 2
133
+ runner.using.each {|w| w.ancestors.should include(Warning) }
134
+ end
135
+ end
136
+
137
+ context '#display_warnings' do
138
+ it 'prints the lines and files where there are warnings' do
139
+ warning = Warning.new('hello', 'a+b')
140
+ warning.line_number = 4
141
+ warning.severity = 3
142
+ warnings = [warning]
143
+ runner = Runner.new(['temp', 'hello'])
144
+ output = swizzling_io do
145
+ runner.display_warnings(warnings, {})
146
+ end
147
+ output.should =~ /hello:4/
148
+ output.should =~ /(3)/
149
+ output.should =~ /Warning/
150
+ output.should =~ /1 warning/
151
+ output.should =~ /0 are fixable/
152
+ end
153
+ end
154
+
155
+ context '#collect_warnings' do
156
+ it 'scans each file provided' do
157
+ scanner = mock(:scanner)
158
+ data1, data2 = mock(:data1), mock(:data2)
159
+ warning_list1, warning_list2 = mock(:wl1), mock(:wl2)
160
+ File.should_receive(:read).with('abc').and_return(data1)
161
+ scanner.should_receive(:settings).exactly(4).times.and_return({})
162
+ scanner.should_receive(:scan).with(data1, 'abc').and_return(warning_list1)
163
+ warning_list1.should_receive(:to_ary)
164
+ File.should_receive(:read).with('def').and_return(data2)
165
+ scanner.should_receive(:scan).with(data2, 'def').and_return(warning_list2)
166
+ warning_list2.should_receive(:to_ary)
167
+
168
+ @runner.collect_warnings(['abc', 'def'], scanner).should == [warning_list1, warning_list2]
169
+ end
170
+ end
171
+ end
@@ -0,0 +1,75 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require 'stringio'
3
+
4
+ describe Scanner do
5
+ before do
6
+ @scanner = Scanner.new(InlineCommentSpaceWarning::OPTION_KEY => 2)
7
+
8
+ @fix_scanner_stdout = StringIO.new
9
+ @fix_scanner = Scanner.new(:fix => true, :output_file => @fix_scanner_stdout)
10
+ end
11
+
12
+ context '#scan' do
13
+ it 'takes an input and gathers warnings about it' do
14
+ warnings = @scanner.scan('a + b ', '(stdin)')
15
+ warnings.size.should == 1
16
+ warnings[0].should be_a(ExtraWhitespaceWarning)
17
+ end
18
+
19
+ it "ignores warnings specified in the line's comments by class name" do
20
+ warnings = @scanner.scan('a +b # wool: ignore OperatorSpacing')
21
+ warnings.size.should == 0
22
+ end
23
+
24
+ it "ignores warnings specified in the line's comments by short name" do
25
+ warnings = @scanner.scan("a +b # wool: ignore #{OperatorSpacing.short_name}")
26
+ warnings.size.should == 0
27
+ end
28
+
29
+ it "ignores multiple warnings that are marked in the line's comments" do
30
+ warnings = @scanner.scan(
31
+ 'a +b; c + d # wool: ignore OperatorSpacing SemicolonWarning')
32
+ warnings.size.should == 0
33
+ end
34
+
35
+ it "ignores multiple warnings in the line's comments as short name" do
36
+ warnings = @scanner.scan(
37
+ "a +b; c + d # wool: ignore #{OperatorSpacing.short_name} #{SemicolonWarning.short_name}")
38
+ warnings.size.should == 0
39
+ end
40
+
41
+ it 'fixes the input and writes it to :output_file' do
42
+ warnings = @fix_scanner.scan('a + b ', '(stdin)')
43
+ warnings.size.should == 1
44
+ warnings[0].should be_a(ExtraWhitespaceWarning)
45
+ @fix_scanner_stdout.string.should == "a + b"
46
+ end
47
+
48
+ it 'fixes multiple errors on one line' do
49
+ warnings = @fix_scanner.scan('a +b ', '(stdin)')
50
+ warnings.size.should == 2
51
+ @fix_scanner_stdout.string.should == "a + b"
52
+ end
53
+
54
+ it 'fixes multiline inputs' do
55
+ warnings = @fix_scanner.scan("def plus(a, b)\n a + b \nend", '(stdin)')
56
+ warnings.size.should == 1
57
+ warnings[0].should be_a(ExtraWhitespaceWarning)
58
+ @fix_scanner_stdout.string.should == "def plus(a, b)\n a + b\nend"
59
+ end
60
+
61
+ it 'fixes multiline mis-indented inputs' do
62
+ warnings = @fix_scanner.scan("def plus(a, b)\n a + b\n end", '(stdin)')
63
+ warnings.size.should == 1
64
+ warnings[0].should be_a(MisalignedUnindentationWarning)
65
+ @fix_scanner_stdout.string.should == "def plus(a, b)\n a + b\nend"
66
+ end
67
+
68
+ it 'fixes class definitions' do
69
+ warnings = @fix_scanner.scan("class Hello\n a+b\nend", '(stdin)')
70
+ warnings.size.should == 1
71
+ warnings[0].should be_a(OperatorSpacing)
72
+ @fix_scanner_stdout.string.should == "class Hello\n a + b\nend"
73
+ end
74
+ end
75
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ --color --backtrace
@@ -0,0 +1,93 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'simplecov'
4
+ require 'simplecov-gem-adapter'
5
+ SimpleCov.start 'gem'
6
+ require 'wool'
7
+ require 'spec'
8
+ require 'spec/autorun'
9
+ require 'stringio'
10
+
11
+
12
+ include Wool
13
+
14
+ module Wool
15
+ module RSpec
16
+ module Matchers
17
+ # Matcher for checking if #match? returns trues
18
+ class Warns
19
+ def initialize(input, *args)
20
+ @input, @args = input, args
21
+ end
22
+
23
+ def matches?(actual)
24
+ @class = actual
25
+ result = @class.new('(stdin)', @input, *@args).match?
26
+ result && result != [] # empty list is also failure to find any warnings
27
+ end
28
+
29
+ def failure_message
30
+ "expected '#{@actual}' to match #{@input.inspect}"
31
+ end
32
+
33
+ def negative_failure_message
34
+ "expected '#{@actual}' to not match #{@input.inspect}"
35
+ end
36
+ end
37
+
38
+ def warn(input, *args)
39
+ Warns.new(input, *args)
40
+ end
41
+
42
+ # Matcher for comparing input/output of #fix
43
+ class CorrectsTo
44
+ def initialize(input, output, *args)
45
+ @input, @output, @args = input, output, args
46
+ end
47
+
48
+ def matches?(actual)
49
+ @class = actual
50
+ @class.new('(stdin)', @input, *@args).fix == @output
51
+ end
52
+
53
+ def failure_message
54
+ "expected '#{@input}' to correct to #{@output.inspect}"
55
+ end
56
+
57
+ def negative_failure_message
58
+ "expected '#{@input}' to not correct to #{@output.inspect}"
59
+ end
60
+ end
61
+
62
+ def correct_to(input, output, *args)
63
+ CorrectsTo.new(input, output, *args)
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ Spec::Runner.configure do |config|
70
+ config.include(Wool::RSpec::Matchers)
71
+ end
72
+
73
+ def with_examples(*args)
74
+ args.each do |arg|
75
+ yield arg
76
+ end
77
+ end
78
+
79
+ def swizzling_io
80
+ old_stdout, $stdout = $stdout, StringIO.new
81
+ yield
82
+ return $stdout.string
83
+ ensure
84
+ $stdout = old_stdout
85
+ end
86
+
87
+ def swizzling_stdin
88
+ old_stdin, $stdin = $stdin, StringIO.new
89
+ yield $stdin
90
+ return $stdin.string
91
+ ensure
92
+ $stdin = old_stdin
93
+ end
@@ -0,0 +1,91 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe ModuleExtensions do
4
+ before do
5
+ @class = Class.new do
6
+ extend ModuleExtensions
7
+ cattr_reader :read1, :read2
8
+ cattr_writer :write1, :write2
9
+ cattr_accessor :both1, :both2
10
+ cattr_accessor_with_default :arr1, []
11
+ end
12
+ end
13
+
14
+ describe '#cattr_reader' do
15
+ it 'creates reading methods for the given variables' do
16
+ @class.__send__(:instance_variable_set, :@read1, 'hello')
17
+ @class.read1.should == 'hello'
18
+ @class.__send__(:instance_variable_set, :@read2, 5)
19
+ @class.read2.should == 5
20
+ end
21
+ end
22
+
23
+ describe '#cattr_writer' do
24
+ it 'creates writing methods for the given variables' do
25
+ @class.write1 = 'hello'
26
+ @class.__send__(:instance_variable_get, :@write1).should == 'hello'
27
+ @class.write2 = 5
28
+ @class.__send__(:instance_variable_get, :@write2).should == 5
29
+ end
30
+ end
31
+
32
+ describe '#cattr_accessor' do
33
+ it 'creates reading and writing methods for the given variables' do
34
+ @class.both1 = 'hello'
35
+ @class.both1.should == 'hello'
36
+ @class.__send__(:instance_variable_get, :@both1).should == 'hello'
37
+ @class.__send__(:instance_variable_set, :@both1, 'world')
38
+ @class.both1.should == 'world'
39
+ @class.both2 = 5
40
+ @class.both2.should == 5
41
+ @class.__send__(:instance_variable_get, :@both2).should == 5
42
+ @class.__send__(:instance_variable_set, :@both2, 10)
43
+ @class.both2.should == 10
44
+ end
45
+ end
46
+
47
+ describe '#cattr_accessor_with_default' do
48
+ it 'creates reading and writing methods, but defaults the ivar value' do
49
+ @class.arr1.should == []
50
+ @class.__send__(:instance_variable_get, :@arr1).should == []
51
+ @class.arr1.should == [] # second invocation, after default value set
52
+ @class.arr1 = [1, 2]
53
+ @class.arr1.should == [1, 2]
54
+ @class.__send__(:instance_variable_get, :@arr1).should == [1, 2]
55
+ end
56
+ end
57
+
58
+ describe '#cattr_get_and_setter' do
59
+ before do
60
+ @base = Class.new do
61
+ extend ModuleExtensions
62
+ cattr_get_and_setter :type
63
+ type :silly
64
+ end
65
+ end
66
+
67
+ it 'acts a setter and getter on the base class' do
68
+ @base.type.should == :silly
69
+ end
70
+
71
+ it 'is not inherited' do
72
+ @derived = Class.new(@base)
73
+ @derived.type.should_not == :silly
74
+ end
75
+
76
+ it 'can be used by inherited classes' do
77
+ @derived = Class.new(@base) do
78
+ type :laughable
79
+ end
80
+ @derived.type.should == :laughable
81
+ @base.type.should == :silly
82
+ end
83
+
84
+ it 'turns a block into a proc and sets it' do
85
+ @derived = Class.new(@base) do
86
+ type { 5 + 3 }
87
+ end
88
+ @derived.type.call.should == 8
89
+ end
90
+ end
91
+ end
@@ -0,0 +1 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
@@ -0,0 +1,95 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Warning do
4
+ context 'when subclassed' do
5
+ it 'registers the new class in all_warnings' do
6
+ klass = Class.new(Warning)
7
+ Warning.all_warnings.should include(klass)
8
+ end
9
+ end
10
+
11
+ it 'does not match anything' do
12
+ Warning.should_not warn('hello(world)')
13
+ Warning.should_not warn(' a +b ')
14
+ end
15
+
16
+ describe 'short names in warnings' do
17
+ before do
18
+ @real_warnings = Warning.all_warnings.select do |x|
19
+ x.name && x != Warning && x != FileWarning && x != LineWarning
20
+ end
21
+ end
22
+
23
+ it 'exist for every warning class' do
24
+ @real_warnings.select {|x| x.name && x.short_name == nil}.should be_empty
25
+ end
26
+
27
+ it 'do not conflict with each other' do
28
+ short_names = @real_warnings.map {|x| x.short_name}.uniq
29
+ short_names.size.should == @real_warnings.size
30
+ end
31
+ end
32
+
33
+ it 'does not change lines when it fixes them' do
34
+ Warning.should correct_to('a+b', 'a+b')
35
+ Warning.should correct_to(' b ** c+1 eval(string) ', ' b ** c+1 eval(string) ')
36
+ end
37
+
38
+ context '#concrete_warnings' do
39
+ before { @concrete = Warning.concrete_warnings }
40
+ it 'returns a list of classes that are subclasses of Warning' do
41
+ @concrete.should_not be_empty
42
+ @concrete.each {|w| w.ancestors.should include(Warning) }
43
+ end
44
+
45
+ it 'returns a list that does not contain Warning, FileWarning, or LineWarning' do
46
+ @concrete.should_not include(Warning)
47
+ @concrete.should_not include(FileWarning)
48
+ @concrete.should_not include(LineWarning)
49
+ end
50
+ end
51
+
52
+ context '#desc' do
53
+ it "defaults to the class's name with all info" do
54
+ warning = Warning.new('hello.rb', 'a+b')
55
+ warning.severity = 7
56
+ warning.line_number = 3
57
+ warning.desc.should == 'Wool::Warning hello.rb:3 (7)'
58
+ end
59
+
60
+ it 'when specified in a subclass as a string, just uses the string' do
61
+ subclass = Class.new(Warning) { desc 'hello' }
62
+ subclass.new('a', 'b').desc.should == 'hello'
63
+ end
64
+
65
+ it 'when specified in a subclass as a block, runs that proc as the instance' do
66
+ subclass = Class.new(Warning) do
67
+ severity 1024
68
+ desc { self.class.severity.to_s }
69
+ end
70
+ subclass.new('a', 'b').desc.should == '1024'
71
+ end
72
+ end
73
+
74
+ context '#type' do
75
+ it 'returns the current type when no args are provided' do
76
+ klass = Class.new(Warning) do
77
+ def self.set_type
78
+ @type = 'hai'
79
+ end
80
+ end
81
+ klass.set_type
82
+ klass.type.should == 'hai'
83
+ end
84
+
85
+ it 'sets the type when an argument is provided' do
86
+ klass = Class.new(Warning) { type :silly }
87
+ klass.type.should == 'silly'
88
+ end
89
+
90
+ it 'sets a short name based on the type provided' do
91
+ klass = Class.new(Warning) { type :silly }
92
+ klass.short_name.should =~ /SI\d/
93
+ end
94
+ end
95
+ end