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,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