wool 0.5.1
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.
- data/.document +5 -0
- data/.gitignore +23 -0
- data/LICENSE +45 -0
- data/README.rdoc +17 -0
- data/Rakefile +77 -0
- data/TODO.md +17 -0
- data/VERSION +1 -0
- data/bin/wool +4 -0
- data/features/step_definitions/wool_steps.rb +39 -0
- data/features/support/env.rb +14 -0
- data/features/support/testdata/1_input +1 -0
- data/features/support/testdata/1_output +1 -0
- data/features/support/testdata/2_input +4 -0
- data/features/support/testdata/2_output +4 -0
- data/features/support/testdata/3_input +8 -0
- data/features/support/testdata/3_output +11 -0
- data/features/support/testdata/4_input +5 -0
- data/features/support/testdata/4_output +5 -0
- data/features/wool.feature +24 -0
- data/lib/wool.rb +40 -0
- data/lib/wool/advice/advice.rb +42 -0
- data/lib/wool/advice/comment_advice.rb +37 -0
- data/lib/wool/analysis/annotations.rb +34 -0
- data/lib/wool/analysis/annotations/next_annotation.rb +26 -0
- data/lib/wool/analysis/annotations/parent_annotation.rb +20 -0
- data/lib/wool/analysis/annotations/scope_annotation.rb +37 -0
- data/lib/wool/analysis/lexical_analysis.rb +165 -0
- data/lib/wool/analysis/protocol_registry.rb +32 -0
- data/lib/wool/analysis/protocols.rb +82 -0
- data/lib/wool/analysis/scope.rb +13 -0
- data/lib/wool/analysis/sexp_analysis.rb +98 -0
- data/lib/wool/analysis/signature.rb +16 -0
- data/lib/wool/analysis/symbol.rb +10 -0
- data/lib/wool/analysis/visitor.rb +36 -0
- data/lib/wool/analysis/wool_class.rb +47 -0
- data/lib/wool/rake/task.rb +42 -0
- data/lib/wool/runner.rb +156 -0
- data/lib/wool/scanner.rb +160 -0
- data/lib/wool/support/module_extensions.rb +84 -0
- data/lib/wool/third_party/trollop.rb +845 -0
- data/lib/wool/warning.rb +145 -0
- data/lib/wool/warnings/comment_spacing.rb +30 -0
- data/lib/wool/warnings/extra_blank_lines.rb +29 -0
- data/lib/wool/warnings/extra_whitespace.rb +15 -0
- data/lib/wool/warnings/line_length.rb +113 -0
- data/lib/wool/warnings/misaligned_unindentation.rb +16 -0
- data/lib/wool/warnings/operator_spacing.rb +63 -0
- data/lib/wool/warnings/rescue_exception.rb +41 -0
- data/lib/wool/warnings/semicolon.rb +24 -0
- data/lib/wool/warnings/useless_double_quotes.rb +37 -0
- data/spec/advice_specs/advice_spec.rb +69 -0
- data/spec/advice_specs/comment_advice_spec.rb +38 -0
- data/spec/advice_specs/spec_helper.rb +1 -0
- data/spec/analysis_specs/annotations_specs/next_prev_annotation_spec.rb +47 -0
- data/spec/analysis_specs/annotations_specs/parent_annotation_spec.rb +41 -0
- data/spec/analysis_specs/annotations_specs/spec_helper.rb +5 -0
- data/spec/analysis_specs/lexical_analysis_spec.rb +179 -0
- data/spec/analysis_specs/protocol_registry_spec.rb +58 -0
- data/spec/analysis_specs/protocols_spec.rb +49 -0
- data/spec/analysis_specs/scope_spec.rb +20 -0
- data/spec/analysis_specs/sexp_analysis_spec.rb +134 -0
- data/spec/analysis_specs/spec_helper.rb +2 -0
- data/spec/analysis_specs/visitor_spec.rb +53 -0
- data/spec/analysis_specs/wool_class_spec.rb +54 -0
- data/spec/rake_specs/spec_helper.rb +1 -0
- data/spec/rake_specs/task_spec.rb +67 -0
- data/spec/runner_spec.rb +171 -0
- data/spec/scanner_spec.rb +75 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +93 -0
- data/spec/support_specs/module_extensions_spec.rb +91 -0
- data/spec/support_specs/spec_helper.rb +1 -0
- data/spec/warning_spec.rb +95 -0
- data/spec/warning_specs/comment_spacing_spec.rb +57 -0
- data/spec/warning_specs/extra_blank_lines_spec.rb +70 -0
- data/spec/warning_specs/extra_whitespace_spec.rb +33 -0
- data/spec/warning_specs/line_length_spec.rb +165 -0
- data/spec/warning_specs/misaligned_unindentation_spec.rb +35 -0
- data/spec/warning_specs/operator_spacing_spec.rb +101 -0
- data/spec/warning_specs/rescue_exception_spec.rb +105 -0
- data/spec/warning_specs/semicolon_spec.rb +58 -0
- data/spec/warning_specs/spec_helper.rb +1 -0
- data/spec/warning_specs/useless_double_quotes_spec.rb +62 -0
- data/spec/wool_spec.rb +8 -0
- data/status_reports/2010/12/2010-12-14.md +163 -0
- data/test/third_party_tests/test_trollop.rb +1181 -0
- data/wool.gemspec +173 -0
- metadata +235 -0
data/spec/runner_spec.rb
ADDED
@@ -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
|
data/spec/spec_helper.rb
ADDED
@@ -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
|