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
@@ -0,0 +1,57 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe InlineCommentSpaceWarning do
|
4
|
+
SETTINGS = {InlineCommentSpaceWarning::OPTION_KEY => 2, :indent_size => 2}
|
5
|
+
it 'is a line-based warning' do
|
6
|
+
InlineCommentSpaceWarning.new('(stdin)', 'hello').should be_a(LineWarning)
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'matches when there are less than 2 spaces between code and comment' do
|
10
|
+
InlineCommentSpaceWarning.should warn('a + b#comment', SETTINGS)
|
11
|
+
InlineCommentSpaceWarning.should warn('a + b # comment', SETTINGS)
|
12
|
+
InlineCommentSpaceWarning.should_not warn('a + b # comment', SETTINGS)
|
13
|
+
InlineCommentSpaceWarning.should_not warn('a +b # wool: ignore OperatorSpacing', SETTINGS)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'has an option to specify the necessary spacing' do
|
17
|
+
InlineCommentSpaceWarning.options.size.should be > 0
|
18
|
+
InlineCommentSpaceWarning.options[0].first.should ==
|
19
|
+
InlineCommentSpaceWarning::OPTION_KEY
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'respects the option for specifying the necessary spacing' do
|
23
|
+
settings = {InlineCommentSpaceWarning::OPTION_KEY => 0}
|
24
|
+
InlineCommentSpaceWarning.should warn('a + b # comment', settings)
|
25
|
+
InlineCommentSpaceWarning.should_not warn('a + b# comment', settings)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'has a remotely useful description' do
|
29
|
+
InlineCommentSpaceWarning.new('(stdin)', 'hello #').desc.should =~ /inline.*comment/i
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'when fixing' do
|
33
|
+
before do
|
34
|
+
@settings = {InlineCommentSpaceWarning::OPTION_KEY => 2}
|
35
|
+
end
|
36
|
+
|
37
|
+
after do
|
38
|
+
InlineCommentSpaceWarning.should correct_to(@input, @output, @settings)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'adds spaces when necessary' do
|
42
|
+
@input = 'a + b#comment'
|
43
|
+
@output = 'a + b #comment'
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'removes spaces when necessary' do
|
47
|
+
@input = 'a + b #comment'
|
48
|
+
@output = 'a + b #comment'
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'respects the option for spacing' do
|
52
|
+
@settings = {InlineCommentSpaceWarning::OPTION_KEY => 0}
|
53
|
+
@input = 'a + b #comment'
|
54
|
+
@output = 'a + b#comment'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe ExtraBlankLinesWarning do
|
4
|
+
it 'is a file-based warning' do
|
5
|
+
ExtraBlankLinesWarning.new('(stdin)', 'hello').should be_a(FileWarning)
|
6
|
+
FileWarning.all_warnings.should include(ExtraBlankLinesWarning)
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'matches when there is a single empty blank line' do
|
10
|
+
ExtraBlankLinesWarning.should warn("a + b\n")
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'matches when there is a single blank line with spaces' do
|
14
|
+
ExtraBlankLinesWarning.should warn("a + b\n ")
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'matches when there is are multiple blank lines' do
|
18
|
+
ExtraBlankLinesWarning.should warn("a + b\n \n\t\n")
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'counts the number of blank lines' do
|
22
|
+
ExtraBlankLinesWarning.new('(stdin)', "a + b\n").count_extra_lines.should == 1
|
23
|
+
ExtraBlankLinesWarning.new('(stdin)', "a + b\n\t\n").count_extra_lines.should == 2
|
24
|
+
ExtraBlankLinesWarning.new('(stdin)', "a + b\n\n").count_extra_lines.should == 2
|
25
|
+
ExtraBlankLinesWarning.new('(stdin)', "a + b\n \n\n").count_extra_lines.should == 3
|
26
|
+
ExtraBlankLinesWarning.new('(stdin)', "a + b\n \n\t\n").count_extra_lines.should == 3
|
27
|
+
ExtraBlankLinesWarning.new('(stdin)', "a + b\n\n\n\n\n").count_extra_lines.should == 5
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'has a remotely useful description' do
|
31
|
+
ExtraBlankLinesWarning.new('(stdin)', 'hello ').desc.should =~ /blank line/
|
32
|
+
end
|
33
|
+
|
34
|
+
INPUTS = ["a + b\n\n\t \t\n\t ", "a + b\n \n\t\n", "a + b\n \n\n",
|
35
|
+
"a + b\n\n\n\n\n", "a + b\n", "a + b\n " ]
|
36
|
+
|
37
|
+
INPUTS.each do |input|
|
38
|
+
context "When fixing #{input.inspect}" do
|
39
|
+
it 'fixes by removing all extra whitespace' do
|
40
|
+
ExtraBlankLinesWarning.should correct_to(input, 'a + b')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'when fixing a realistic multiline block' do
|
46
|
+
before do
|
47
|
+
@original = <<-EOF
|
48
|
+
# Warning for using semicolons outside of class declarations.
|
49
|
+
class SemicolonWarning < LineWarning
|
50
|
+
|
51
|
+
def initialize(file, line)
|
52
|
+
severity = line =~ /['"]/ ? 2 : 4
|
53
|
+
super('Semicolon for multiple statements', file, line, 0, severity)
|
54
|
+
end
|
55
|
+
|
56
|
+
def desc
|
57
|
+
'The line uses a semicolon to separate multiple statements outside of a class declaration.'
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
EOF
|
62
|
+
@original.strip!
|
63
|
+
@invalid = @original + "\n \t\t\n \n\n"
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'only removes the trailing whitespace' do
|
67
|
+
ExtraBlankLinesWarning.should correct_to(@invalid, @original)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe ExtraWhitespaceWarning do
|
4
|
+
it 'is a line-based warning' do
|
5
|
+
ExtraWhitespaceWarning.new('(stdin)', 'hello').should be_a(LineWarning)
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'matches when there are spaces at the end of a line' do
|
9
|
+
ExtraWhitespaceWarning.should warn('a + b ')
|
10
|
+
ExtraWhitespaceWarning.should warn('a + b ')
|
11
|
+
ExtraWhitespaceWarning.should_not warn('a + b')
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'matches when there are tabs at the end of a line' do
|
15
|
+
ExtraWhitespaceWarning.should warn("a + b\t\t")
|
16
|
+
ExtraWhitespaceWarning.should warn("a + b\t")
|
17
|
+
ExtraWhitespaceWarning.should_not warn('a + b')
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'has a remotely useful description' do
|
21
|
+
ExtraWhitespaceWarning.new('(stdin)', 'hello ').desc.should =~ /whitespace/
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'when fixing' do
|
25
|
+
it 'fixes by removing extra spaces' do
|
26
|
+
ExtraWhitespaceWarning.should correct_to('a + b ', 'a + b')
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'fixes by removing extra tabs' do
|
30
|
+
ExtraWhitespaceWarning.should correct_to("a + b\t\t", 'a + b')
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe GenericLineLengthWarning do
|
4
|
+
before do
|
5
|
+
@eighty_cap = LineLengthCustomSeverity(80, 2)
|
6
|
+
@eighty_cap.line_length_limit = 80
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'is a line-based warning' do
|
10
|
+
GenericLineLengthWarning.new('(stdin)', 'hello').should be_a(LineWarning)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'initializes to a file and line' do
|
14
|
+
warning = @eighty_cap.new('(stdin)', 'x' * 81)
|
15
|
+
warning.severity.should == @eighty_cap.severity
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'has a remotely useful description' do
|
19
|
+
@eighty_cap.new('(stdin)', 'x' * 80).desc.should =~ /line length/i
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'matches lines longer than the specified number of characters' do
|
23
|
+
@eighty_cap.should warn('x' * 82)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'does not match lines shorter than the specified number of characters' do
|
27
|
+
@eighty_cap.should_not warn('x' * 78)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'does not match lines equal to the specified number of characters' do
|
31
|
+
@eighty_cap.should_not warn('x' * 80)
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'when fixing' do
|
35
|
+
before do
|
36
|
+
@twenty_cap = Class.new(GenericLineLengthWarning)
|
37
|
+
@twenty_cap.line_length_limit = 20
|
38
|
+
@settings = {}
|
39
|
+
end
|
40
|
+
|
41
|
+
after do
|
42
|
+
@twenty_cap.should correct_to(@input, @output, @settings)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'takes a line with just a comment on it and breaks it into many lines' do
|
46
|
+
@input = '# my comment is this and that and another thing'
|
47
|
+
@output = "# my comment is this\n# and that and\n# another thing"
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'creates new lines with the same indentation as the input' do
|
51
|
+
@input = ' # my comment is this and that and another thing'
|
52
|
+
@output = " # my comment is\n # this and that\n # and another\n # thing"
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'uses the same number of hashes to denote the comment' do
|
56
|
+
@input = ' ## my comment is this and that and another thing'
|
57
|
+
@output = " ## my comment is\n ## this and that\n ## and another\n ## thing"
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'splits up code with an overly long comment at the end' do
|
61
|
+
@input = ' a + b # this is a stupidly long comment lol'
|
62
|
+
@output = " # this is a\n # stupidly long\n # comment lol\n a + b"
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'uses the same indentation and hashes for the new comment' do
|
66
|
+
@input = ' a + b ### this is a stupidly long comment lol'
|
67
|
+
@output = " ### this is a\n ### stupidly long\n ### comment lol\n a + b"
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'fails to fix when if/unless are in a symbol' do
|
71
|
+
# This came from an actual bug from running wool on wool's source.
|
72
|
+
@input = " left, right = @class.new('').split_on_keyword('x = 5 unless y == 2', :unless)"
|
73
|
+
@output = @input
|
74
|
+
end
|
75
|
+
|
76
|
+
context 'with an indent size of 2' do
|
77
|
+
before { @settings = {:indent_size => 2} }
|
78
|
+
it "doesn't try to convert the 'end if foobar' technique" do
|
79
|
+
@input = ' end if should_run_block?'
|
80
|
+
@output = ' end if should_run_block?'
|
81
|
+
end
|
82
|
+
|
83
|
+
it "doesn't try to convert the 'end unless foobar' technique" do
|
84
|
+
@input = ' end unless should_run_block?'
|
85
|
+
@output = ' end unless should_run_block?'
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'converts lines with guarded ifs into 3 liners' do
|
89
|
+
@input = 'puts x if x > y && y.call'
|
90
|
+
@output = "if x > y && y.call\n puts x\nend"
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'converts lines with guarded unlesses into 3 liners' do
|
94
|
+
@input = 'puts x unless x > number'
|
95
|
+
@output = "unless x > number\n puts x\nend"
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'converts lines with guarded ifs while maintaining indentation' do
|
99
|
+
@input = ' puts x unless x > number'
|
100
|
+
@output = " unless x > number\n puts x\n end"
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'only converts when it finds a guard on the top level expression' do
|
104
|
+
@input = %Q[syms.each { |sym| raise ArgumentError, "unknown option '\#{sym}'" unless @specs[sym] }]
|
105
|
+
@output = %Q[syms.each { |sym| raise ArgumentError, "unknown option '\#{sym}'" unless @specs[sym] }]
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'only converts when it finds a guard on the real-world top level expression' do
|
109
|
+
@input = 'x.select { |x| x if 5 }'
|
110
|
+
@output = 'x.select { |x| x if 5 }'
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'converts nested if/unless as guards' do
|
114
|
+
@input = 'puts x if foo.bar unless baz.boo'
|
115
|
+
@output = "unless baz.boo\n if foo.bar\n puts x\n end\nend"
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'converts nested three if/unless as guards' do
|
119
|
+
@input = 'puts x if foo.bar unless baz.boo if alpha.beta'
|
120
|
+
@output = "if alpha.beta\n unless baz.boo\n if foo.bar\n puts x\n end\n end\nend"
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'converts nested three if/unless as guards maintaining indentation' do
|
124
|
+
@input = ' puts x if foo.bar unless baz.boo if alpha.beta'
|
125
|
+
@output = " if alpha.beta\n unless baz.boo\n if foo.bar\n puts x\n end\n end\n end"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe 'LineLengthMaximum' do
|
132
|
+
before do
|
133
|
+
@hundred_cap = LineLengthMaximum(100)
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'matches lines longer than the specified maximum' do
|
137
|
+
@hundred_cap.should warn('x' * 101)
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'has a high severity' do
|
141
|
+
@hundred_cap.severity.should >= 7.5
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'does not match lines smaller than the specified maximum' do
|
145
|
+
@hundred_cap.should_not warn('x' * 100)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe 'LineLengthWarning' do
|
150
|
+
before do
|
151
|
+
@hundred_cap = LineLengthWarning(80)
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'matches lines longer than the specified maximum' do
|
155
|
+
@hundred_cap.should warn('x' * 81)
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'has a lower severity' do
|
159
|
+
@hundred_cap.severity.should <= 4
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'does not match lines smaller than the specified maximum' do
|
163
|
+
@hundred_cap.should_not warn('x' * 80)
|
164
|
+
end
|
165
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe MisalignedUnindentationWarning do
|
4
|
+
context 'when fixing' do
|
5
|
+
it 'is a line-based warning' do
|
6
|
+
MisalignedUnindentationWarning.new('(stdin)', 'hello', 80).should be_a(LineWarning)
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'matches nothing' do
|
10
|
+
MisalignedUnindentationWarning.should_not warn(' a + b', 2)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'fixes by removing more spaces than expected' do
|
14
|
+
MisalignedUnindentationWarning.should correct_to(' a + b', ' a + b', 2)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'fixes by adding a second space' do
|
18
|
+
MisalignedUnindentationWarning.should correct_to(' a + b', ' a + b', 2)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'fixes by adding indentation' do
|
22
|
+
MisalignedUnindentationWarning.should correct_to('a + b', ' a + b', 4)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'describes the incorrect indentation values' do
|
26
|
+
warning = MisalignedUnindentationWarning.new('(stdin)', ' a + b', 2)
|
27
|
+
other_warning = MisalignedUnindentationWarning.new('(stdin)', ' a + b', 2)
|
28
|
+
warning_3 = MisalignedUnindentationWarning.new('(stdin)', 'a + b', 4)
|
29
|
+
warning.desc.should =~ /Expected 2/
|
30
|
+
warning.desc.should =~ /found 3/
|
31
|
+
other_warning.desc.should =~ /Expected 2/
|
32
|
+
other_warning.desc.should =~ /found 1/
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe OperatorSpacing do
|
4
|
+
it 'is a line-based warning' do
|
5
|
+
OperatorSpacing.new('(stdin)', 'hello').should be_a(LineWarning)
|
6
|
+
end
|
7
|
+
|
8
|
+
it "doesn't match block declarations" do
|
9
|
+
OperatorSpacing.should_not warn('[1, 2].each { |x| p x }')
|
10
|
+
OperatorSpacing.should_not warn('[1, 2].each {| y | p x }')
|
11
|
+
OperatorSpacing.should_not warn("[1, 2].each do |x|\n p x\nend")
|
12
|
+
OperatorSpacing.should_not warn("[1, 2].each do|x|\n p x\nend")
|
13
|
+
end
|
14
|
+
|
15
|
+
it "doesn't match in a comment" do
|
16
|
+
OperatorSpacing.should_not warn('hello # a+b')
|
17
|
+
end
|
18
|
+
|
19
|
+
it "doesn't match a <<- heredoc" do
|
20
|
+
OperatorSpacing.should_not warn('@original = <<-EOF')
|
21
|
+
end
|
22
|
+
|
23
|
+
it "doesn't match a << heredoc" do
|
24
|
+
OperatorSpacing.should_not warn('@original = <<EOF')
|
25
|
+
end
|
26
|
+
|
27
|
+
it "doesn't match adjacent negative numbers" do
|
28
|
+
OperatorSpacing.should_not warn(' exit(-1)')
|
29
|
+
end
|
30
|
+
|
31
|
+
it "doesn't match *args in block parameters" do
|
32
|
+
OperatorSpacing.should_not warn('list.each do |*args|')
|
33
|
+
OperatorSpacing.should_not warn('list.each { |*args| }')
|
34
|
+
end
|
35
|
+
|
36
|
+
it "doesn't match splat arguments" do
|
37
|
+
OperatorSpacing.should_not warn('x.call(*args)')
|
38
|
+
OperatorSpacing.should_not warn('x.call(a, *args)')
|
39
|
+
OperatorSpacing.should_not warn('x.call(*args, b)')
|
40
|
+
OperatorSpacing.should_not warn('x.call(a, *args, b)')
|
41
|
+
end
|
42
|
+
|
43
|
+
it "does match multiplication in an argument list" do
|
44
|
+
OperatorSpacing.should warn('x.call(a *b)')
|
45
|
+
OperatorSpacing.should warn('x.call(x, a *b)')
|
46
|
+
OperatorSpacing.should warn('x.call(a *b, z)')
|
47
|
+
end
|
48
|
+
|
49
|
+
it "doesn't match block arguments" do
|
50
|
+
OperatorSpacing.should_not warn('x.call(&b)')
|
51
|
+
OperatorSpacing.should_not warn('x.call(a, &b)')
|
52
|
+
OperatorSpacing.should_not warn('x.call(&b, b)')
|
53
|
+
OperatorSpacing.should_not warn('x.call(a, &b, b)')
|
54
|
+
end
|
55
|
+
|
56
|
+
it "doesn't match the [*item] idiom" do
|
57
|
+
OperatorSpacing.should_not warn('[*args]')
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'has a reasonable description' do
|
61
|
+
OperatorSpacing.new('(stdin)', 'a+ b').desc.should =~ /spacing/
|
62
|
+
end
|
63
|
+
|
64
|
+
OperatorSpacing::OPERATORS.each do |operator|
|
65
|
+
context "with #{operator}" do
|
66
|
+
it "matches when there is no space on the left side" do
|
67
|
+
OperatorSpacing.should warn("a#{operator} b")
|
68
|
+
end
|
69
|
+
|
70
|
+
it "matches when there is no space on the right side" do
|
71
|
+
OperatorSpacing.should warn("a #{operator}b")
|
72
|
+
end unless operator == '/' # This confuses the shit out of the lexer
|
73
|
+
|
74
|
+
it "matches when there is no space on both sides" do
|
75
|
+
OperatorSpacing.should warn("a#{operator}b")
|
76
|
+
end
|
77
|
+
|
78
|
+
it "doesn't match when there is exactly one space on both sides" do
|
79
|
+
OperatorSpacing.should_not warn("a #{operator} b")
|
80
|
+
end
|
81
|
+
|
82
|
+
context 'when fixing' do
|
83
|
+
it 'changes nothing when there is one space on both sides' do
|
84
|
+
OperatorSpacing.should correct_to("a #{operator} b", "a #{operator} b")
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'fixes by inserting an extra space on the left' do
|
88
|
+
OperatorSpacing.should correct_to("a#{operator} b", "a #{operator} b")
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'fixes by inserting an extra space on the right' do
|
92
|
+
OperatorSpacing.should correct_to("a #{operator}b", "a #{operator} b")
|
93
|
+
end unless operator == '/' # This confuses the shit out of the lexer
|
94
|
+
|
95
|
+
it 'fixes by inserting an extra space on both sides' do
|
96
|
+
OperatorSpacing.should correct_to("a#{operator}b", "a #{operator} b")
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|