OLD | NEW |
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 import 'dart:convert' show UTF8; | 5 import 'dart:convert' show UTF8; |
6 | 6 |
7 import 'package:front_end/src/fasta/scanner/recover.dart' | 7 import 'package:front_end/src/fasta/scanner/recover.dart' |
8 show defaultRecoveryStrategy; | 8 show defaultRecoveryStrategy; |
9 import 'package:front_end/src/fasta/scanner.dart' as fasta; | 9 import 'package:front_end/src/fasta/scanner.dart' as fasta; |
10 import 'package:front_end/src/fasta/scanner/token.dart' as fasta; | 10 import 'package:front_end/src/fasta/scanner/token.dart' as fasta; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
70 | 70 |
71 void _assertOpenClosePair(String source) { | 71 void _assertOpenClosePair(String source) { |
72 analyzer.BeginToken open = _scan(source); | 72 analyzer.BeginToken open = _scan(source); |
73 fasta.Token close = open.next; | 73 fasta.Token close = open.next; |
74 expect(close.next.isEof, isTrue); | 74 expect(close.next.isEof, isTrue); |
75 expect(open.endGroup, close); | 75 expect(open.endGroup, close); |
76 expect(open.isSynthetic, isFalse); | 76 expect(open.isSynthetic, isFalse); |
77 expect(close.isSynthetic, isFalse); | 77 expect(close.isSynthetic, isFalse); |
78 } | 78 } |
79 | 79 |
80 void _assertOpenOnly(String source) { | 80 void _assertOpenOnly(String source, String expectedCloser) { |
81 analyzer.BeginToken open = _scan(source); | 81 ErrorListener listener = new ErrorListener(); |
| 82 analyzer.BeginToken open = scanWithListener(source, listener); |
82 fasta.Token close = open.next; | 83 fasta.Token close = open.next; |
83 expect(close.next.isEof, isTrue); | 84 expect(close.next.isEof, isTrue); |
84 expect(open.endGroup, close); | 85 expect(open.endGroup, close); |
85 expect(open.isSynthetic, isFalse); | 86 expect(open.isSynthetic, isFalse); |
86 expect(close.isSynthetic, isTrue); | 87 expect(close.isSynthetic, isTrue); |
| 88 listener.assertErrors([ |
| 89 new TestError(0, ScannerErrorCode.EXPECTED_TOKEN, [expectedCloser]), |
| 90 ]); |
87 } | 91 } |
88 | 92 |
89 void test_lt() { | 93 void test_lt() { |
90 // fasta does not automatically insert a closer for '<' | 94 // fasta does not automatically insert a closer for '<' |
91 // because it could be part of an expression rather than an opener | 95 // because it could be part of an expression rather than an opener |
92 analyzer.BeginToken lt = _scan('<'); | 96 analyzer.BeginToken lt = _scan('<'); |
93 expect(lt.next.isEof, isTrue); | 97 expect(lt.next.isEof, isTrue); |
94 expect(lt.isSynthetic, isFalse); | 98 expect(lt.isSynthetic, isFalse); |
95 } | 99 } |
96 | 100 |
97 void test_lt_gt() { | 101 void test_lt_gt() { |
98 _assertOpenClosePair('< >'); | 102 _assertOpenClosePair('< >'); |
99 } | 103 } |
100 | 104 |
101 @override | 105 @override |
102 void test_open_curly_bracket() { | 106 void test_open_curly_bracket() { |
103 _assertOpenOnly('{'); | 107 _assertOpenOnly('{', '}'); |
104 } | 108 } |
105 | 109 |
106 void test_open_curly_bracket_with_close() { | 110 void test_open_curly_bracket_with_close() { |
107 _assertOpenClosePair('{ }'); | 111 _assertOpenClosePair('{ }'); |
108 } | 112 } |
109 | 113 |
110 void test_open_paren() { | 114 void test_open_paren() { |
111 _assertOpenOnly('('); | 115 _assertOpenOnly('(', ')'); |
112 } | 116 } |
113 | 117 |
114 void test_open_paren_with_close() { | 118 void test_open_paren_with_close() { |
115 _assertOpenClosePair('( )'); | 119 _assertOpenClosePair('( )'); |
116 } | 120 } |
117 | 121 |
118 void test_open_square_bracket() { | 122 void test_open_square_bracket() { |
119 _assertOpenOnly('['); | 123 _assertOpenOnly('[', ']'); |
120 } | 124 } |
121 | 125 |
122 void test_open_square_bracket_with_close() { | 126 void test_open_square_bracket_with_close() { |
123 _assertOpenClosePair('[ ]'); | 127 _assertOpenClosePair('[ ]'); |
124 } | 128 } |
125 | 129 |
126 @override | 130 @override |
127 void test_mismatched_opener_in_interpolation() { | 131 void test_mismatched_opener_in_interpolation() { |
128 // When openers and closers are mismatched, | 132 // When openers and closers are mismatched, |
129 // fasta favors considering the opener to be mismatched | 133 // fasta favors considering the opener to be mismatched |
130 // and inserts synthetic closers as needed. | 134 // and inserts synthetic closers as needed. |
131 // r'"${({(}}"' is parsed as r'"${({()})}"' | 135 // r'"${({(}}"' is parsed as r'"${({()})}"' |
132 // where both ')' are synthetic | 136 // where both ')' are synthetic |
133 var stringStart = _scan(r'"${({(}}"'); | 137 ErrorListener listener = new ErrorListener(); |
134 var interpolationStart = stringStart.next as analyzer.BeginToken; | 138 var stringStart = scanWithListener(r'"${({(}}"', listener); |
135 var openParen1 = interpolationStart.next as analyzer.BeginToken; | 139 analyzer.BeginToken interpolationStart = stringStart.next; |
136 var openBrace = openParen1.next as analyzer.BeginToken; | 140 analyzer.BeginToken openParen1 = interpolationStart.next; |
137 var openParen2 = openBrace.next as analyzer.BeginToken; | 141 analyzer.BeginToken openBrace = openParen1.next; |
| 142 analyzer.BeginToken openParen2 = openBrace.next; |
138 var closeParen2 = openParen2.next; | 143 var closeParen2 = openParen2.next; |
139 var closeBrace = closeParen2.next; | 144 var closeBrace = closeParen2.next; |
140 var closeParen1 = closeBrace.next; | 145 var closeParen1 = closeBrace.next; |
141 var interpolationEnd = closeParen1.next; | 146 var interpolationEnd = closeParen1.next; |
142 var stringEnd = interpolationEnd.next; | 147 var stringEnd = interpolationEnd.next; |
143 var eof = stringEnd.next; | 148 var eof = stringEnd.next; |
144 | 149 |
145 expect(interpolationStart.endToken, same(interpolationEnd)); | 150 expect(interpolationStart.endToken, same(interpolationEnd)); |
146 expect(interpolationEnd.isSynthetic, isFalse); | 151 expect(interpolationEnd.isSynthetic, isFalse); |
147 expect(openParen1.endToken, same(closeParen1)); | 152 expect(openParen1.endToken, same(closeParen1)); |
148 expect(closeParen1.isSynthetic, isTrue); | 153 expect(closeParen1.isSynthetic, isTrue); |
149 expect(openBrace.endToken, same(closeBrace)); | 154 expect(openBrace.endToken, same(closeBrace)); |
150 expect(closeBrace.isSynthetic, isFalse); | 155 expect(closeBrace.isSynthetic, isFalse); |
151 expect(openParen2.endToken, same(closeParen2)); | 156 expect(openParen2.endToken, same(closeParen2)); |
152 expect(closeParen2.isSynthetic, isTrue); | 157 expect(closeParen2.isSynthetic, isTrue); |
153 expect(eof.isEof, isTrue); | 158 expect(eof.isEof, isTrue); |
| 159 listener.assertErrors([ |
| 160 new TestError(3, ScannerErrorCode.EXPECTED_TOKEN, [')']), |
| 161 new TestError(5, ScannerErrorCode.EXPECTED_TOKEN, [')']), |
| 162 ]); |
154 } | 163 } |
155 | 164 |
156 @override | 165 @override |
157 void test_unmatched_openers() { | 166 void test_unmatched_openers() { |
| 167 ErrorListener listener = new ErrorListener(); |
158 // fasta inserts missing closers except for '<' | 168 // fasta inserts missing closers except for '<' |
159 var openBrace = _scan('{[(<') as analyzer.BeginToken; | 169 analyzer.BeginToken openBrace = scanWithListener('{[(<', listener); |
160 var openBracket = openBrace.next as analyzer.BeginToken; | 170 analyzer.BeginToken openBracket = openBrace.next; |
161 var openParen = openBracket.next as analyzer.BeginToken; | 171 analyzer.BeginToken openParen = openBracket.next; |
162 var openLT = openParen.next as analyzer.BeginToken; | 172 analyzer.BeginToken openLT = openParen.next; |
163 var closeParen = openLT.next; | 173 var closeParen = openLT.next; |
164 var closeBracket = closeParen.next; | 174 var closeBracket = closeParen.next; |
165 var closeBrace = closeBracket.next; | 175 var closeBrace = closeBracket.next; |
166 var eof = closeBrace.next; | 176 var eof = closeBrace.next; |
167 | 177 |
168 expect(openBrace.endGroup, same(closeBrace)); | 178 expect(openBrace.endGroup, same(closeBrace)); |
169 expect(openBracket.endGroup, same(closeBracket)); | 179 expect(openBracket.endGroup, same(closeBracket)); |
170 expect(openParen.endGroup, same(closeParen)); | 180 expect(openParen.endGroup, same(closeParen)); |
171 expect(eof.isEof, true); | 181 expect(eof.isEof, true); |
| 182 |
| 183 listener.assertErrors([ |
| 184 new TestError(2, ScannerErrorCode.EXPECTED_TOKEN, [')']), |
| 185 new TestError(1, ScannerErrorCode.EXPECTED_TOKEN, [']']), |
| 186 new TestError(0, ScannerErrorCode.EXPECTED_TOKEN, ['}']), |
| 187 ]); |
172 } | 188 } |
173 | 189 |
174 analyzer.Token _scan(String source, | 190 analyzer.Token _scan(String source, |
175 {bool genericMethodComments: false, | 191 {bool genericMethodComments: false, |
176 bool lazyAssignmentOperators: false}) { | 192 bool lazyAssignmentOperators: false}) { |
177 ErrorListener listener = new ErrorListener(); | 193 ErrorListener listener = new ErrorListener(); |
178 analyzer.Token token = scanWithListener(source, listener, | 194 analyzer.Token token = scanWithListener(source, listener, |
179 genericMethodComments: genericMethodComments, | 195 genericMethodComments: genericMethodComments, |
180 lazyAssignmentOperators: lazyAssignmentOperators); | 196 lazyAssignmentOperators: lazyAssignmentOperators); |
181 listener.assertNoErrors(); | 197 listener.assertNoErrors(); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
244 } else if (token is fasta.UnmatchedToken) { | 260 } else if (token is fasta.UnmatchedToken) { |
245 expect(lastClosedGroup?.endGroup?.next, same(token), | 261 expect(lastClosedGroup?.endGroup?.next, same(token), |
246 reason: 'Unexpected error token for group: $lastClosedGroup'); | 262 reason: 'Unexpected error token for group: $lastClosedGroup'); |
247 expect(token.begin, lastClosedGroup); | 263 expect(token.begin, lastClosedGroup); |
248 } | 264 } |
249 token = token.next; | 265 token = token.next; |
250 } | 266 } |
251 expect(openerStack, isEmpty, reason: 'Missing closers'); | 267 expect(openerStack, isEmpty, reason: 'Missing closers'); |
252 } | 268 } |
253 } | 269 } |
OLD | NEW |