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