Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(671)

Side by Side Diff: pkg/front_end/test/scanner_replacement_test.dart

Issue 2777153002: move synthetic fasta closers into the token stream (Closed)
Patch Set: rebase Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « pkg/front_end/test/scanner_fasta_test.dart ('k') | pkg/front_end/test/scanner_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/precedence.dart' 7 import 'package:front_end/src/fasta/scanner/precedence.dart'
8 show BAD_INPUT_INFO, EOF_INFO; 8 show BAD_INPUT_INFO, EOF_INFO;
9 import 'package:front_end/src/fasta/scanner/recover.dart' 9 import 'package:front_end/src/fasta/scanner/recover.dart'
10 show defaultRecoveryStrategy; 10 show defaultRecoveryStrategy;
11 import 'package:front_end/src/fasta/scanner.dart' as fasta; 11 import 'package:front_end/src/fasta/scanner.dart' as fasta;
12 import 'package:front_end/src/fasta/scanner/token.dart' as fasta;
13 import 'package:front_end/src/fasta/scanner/error_token.dart' as fasta;
12 import 'package:front_end/src/scanner/token.dart' as analyzer; 14 import 'package:front_end/src/scanner/token.dart' as analyzer;
13 import 'package:front_end/src/scanner/errors.dart' 15 import 'package:front_end/src/scanner/errors.dart'
14 show ScannerErrorCode, translateErrorToken; 16 show ScannerErrorCode, translateErrorToken;
15 import 'package:test/test.dart'; 17 import 'package:test/test.dart';
16 import 'package:test_reflective_loader/test_reflective_loader.dart'; 18 import 'package:test_reflective_loader/test_reflective_loader.dart';
17 19
18 import 'scanner_test.dart'; 20 import 'scanner_test.dart';
19 21
20 main() { 22 main() {
21 defineReflectiveSuite(() { 23 defineReflectiveSuite(() {
(...skipping 25 matching lines...) Expand all
47 // Dart, remove this flag. 49 // Dart, remove this flag.
48 fasta.ScannerResult result = fasta.scanString(source, 50 fasta.ScannerResult result = fasta.scanString(source,
49 includeComments: true, 51 includeComments: true,
50 recover: ((List<int> bytes, fasta.Token tokens, List<int> lineStarts) { 52 recover: ((List<int> bytes, fasta.Token tokens, List<int> lineStarts) {
51 // perform recovery as a separate step 53 // perform recovery as a separate step
52 // so that the token stream can be validated before and after recovery 54 // so that the token stream can be validated before and after recovery
53 return tokens; 55 return tokens;
54 })); 56 }));
55 fasta.Token tokens = result.tokens; 57 fasta.Token tokens = result.tokens;
56 assertValidTokenStream(tokens); 58 assertValidTokenStream(tokens);
59 assertValidBeginTokens(tokens);
57 if (result.hasErrors) { 60 if (result.hasErrors) {
58 List<int> bytes = UTF8.encode(source); 61 List<int> bytes = UTF8.encode(source);
59 tokens = defaultRecoveryStrategy(bytes, tokens, result.lineStarts); 62 tokens = defaultRecoveryStrategy(bytes, tokens, result.lineStarts);
60 assertValidTokenStream(tokens); 63 assertValidTokenStream(tokens, errorsFirst: true);
61 } 64 }
62 return extractErrors(tokens, listener); 65 return extractErrors(tokens, listener);
63 } 66 }
64 67
65 @override 68 @override
66 @failingTest 69 @failingTest
67 void test_ampersand_ampersand_eq() { 70 void test_ampersand_ampersand_eq() {
68 // TODO(paulberry,ahe): Fasta scanner doesn't support lazy assignment 71 // TODO(paulberry,ahe): Fasta scanner doesn't support lazy assignment
69 // operators. 72 // operators.
70 super.test_ampersand_ampersand_eq(); 73 super.test_ampersand_ampersand_eq();
(...skipping 16 matching lines...) Expand all
87 } 90 }
88 91
89 @override 92 @override
90 @failingTest 93 @failingTest
91 void test_comment_generic_method_type_list() { 94 void test_comment_generic_method_type_list() {
92 // TODO(paulberry,ahe): Fasta scanner doesn't support generic comment 95 // TODO(paulberry,ahe): Fasta scanner doesn't support generic comment
93 // syntax. 96 // syntax.
94 super.test_comment_generic_method_type_list(); 97 super.test_comment_generic_method_type_list();
95 } 98 }
96 99
97 @override 100 void _assertOpenClosePair(String source) {
98 @failingTest 101 fasta.BeginGroupToken open = _scan(source);
99 void test_mismatched_closer() { 102 fasta.Token close = open.next;
100 // TODO(danrubel): investigate and fix 103 expect(close.next.isEof, isTrue);
101 super.test_mismatched_closer(); 104 expect(open.endGroup, close);
105 expect(open.isSynthetic, isFalse);
106 expect(close.isSynthetic, isFalse);
107 }
108
109 void _assertOpenOnly(String source) {
110 fasta.BeginGroupToken open = _scan(source);
111 fasta.Token close = open.next;
112 expect(close.next.isEof, isTrue);
113 expect(open.endGroup, close);
114 expect(open.isSynthetic, isFalse);
115 expect(close.isSynthetic, isTrue);
116 }
117
118 void test_lt() {
119 // fasta does not automatically insert a closer for '<'
120 // because it could be part of an expression rather than an opener
121 fasta.BeginGroupToken lt = _scan('<');
122 expect(lt.next.isEof, isTrue);
123 expect(lt.isSynthetic, isFalse);
124 }
125
126 void test_lt_gt() {
127 _assertOpenClosePair('< >');
102 } 128 }
103 129
104 @override 130 @override
105 @failingTest 131 void test_open_curly_bracket() {
106 void test_mismatched_opener() { 132 _assertOpenOnly('{');
107 // TODO(danrubel): investigate and fix 133 }
108 super.test_mismatched_opener(); 134
135 void test_open_curly_bracket_with_close() {
136 _assertOpenClosePair('{ }');
137 }
138
139 void test_open_paren() {
140 _assertOpenOnly('(');
141 }
142
143 void test_open_paren_with_close() {
144 _assertOpenClosePair('( )');
145 }
146
147 void test_open_square_bracket() {
148 _assertOpenOnly('[');
149 }
150
151 void test_open_square_bracket_with_close() {
152 _assertOpenClosePair('[ ]');
109 } 153 }
110 154
111 @override 155 @override
112 @failingTest 156 void test_mismatched_closer() {
113 void test_mismatched_opener_in_interpolation() { 157 // When openers and closers are mismatched,
114 // TODO(danrubel): investigate and fix 158 // fasta favors considering the opener to be mismatched,
115 super.test_mismatched_opener_in_interpolation(); 159 // and inserts synthetic closers as needed.
160 // `(])` is parsed as `()])` where the first `)` is synthetic
161 // and the trailing `])` are unmatched.
162 fasta.BeginGroupToken openParen = _scan('(])');
163 fasta.Token closeParen = openParen.next;
164 fasta.Token closeBracket = closeParen.next;
165 fasta.Token closeParen2 = closeBracket.next;
166 fasta.Token eof = closeParen2.next;
167
168 expect(openParen.endToken, same(closeParen));
169 expect(closeParen.isSynthetic, isTrue);
170 expect(eof.isEof, isTrue);
116 } 171 }
117 172
118 @override 173 @override
174 void test_mismatched_opener() {
175 // When openers and closers are mismatched,
176 // fasta favors considering the opener to be mismatched
177 // and inserts synthetic closers as needed.
178 // `([)` is parsed as `([])` where `]` is synthetic.
179 fasta.BeginGroupToken openParen = _scan('([)');
180 fasta.BeginGroupToken openBracket = openParen.next;
181 fasta.Token closeBracket = openBracket.next; // <-- synthetic
182 fasta.Token closeParen = closeBracket.next;
183 fasta.Token eof = closeParen.next;
184
185 expect(openParen.endToken, same(closeParen));
186 expect(closeParen.isSynthetic, isFalse);
187 expect(openBracket.endToken, same(closeBracket));
188 expect(closeBracket.isSynthetic, isTrue);
189 expect(eof.isEof, isTrue);
190 }
191
192 @override
193 void test_mismatched_opener_in_interpolation() {
194 // When openers and closers are mismatched,
195 // fasta favors considering the opener to be mismatched
196 // and inserts synthetic closers as needed.
197 // r'"${({(}}"' is parsed as r'"${({()})}"'
198 // where both ')' are synthetic
199 var stringStart = _scan(r'"${({(}}"');
200 var interpolationStart = stringStart.next as fasta.BeginGroupToken;
201 var openParen1 = interpolationStart.next as fasta.BeginGroupToken;
202 var openBrace = openParen1.next as fasta.BeginGroupToken;
203 var openParen2 = openBrace.next as fasta.BeginGroupToken;
204 var closeParen2 = openParen2.next;
205 var closeBrace = closeParen2.next;
206 var closeParen1 = closeBrace.next;
207 var interpolationEnd = closeParen1.next;
208 var stringEnd = interpolationEnd.next;
209 var eof = stringEnd.next;
210
211 expect(interpolationStart.endToken, same(interpolationEnd));
212 expect(interpolationEnd.isSynthetic, isFalse);
213 expect(openParen1.endToken, same(closeParen1));
214 expect(closeParen1.isSynthetic, isTrue);
215 expect(openBrace.endToken, same(closeBrace));
216 expect(closeBrace.isSynthetic, isFalse);
217 expect(openParen2.endToken, same(closeParen2));
218 expect(closeParen2.isSynthetic, isTrue);
219 expect(eof.isEof, isTrue);
220 }
221
222 @override
119 @failingTest 223 @failingTest
120 void test_string_multi_unterminated() { 224 void test_string_multi_unterminated() {
121 // See defaultRecoveryStrategy recoverString 225 // See defaultRecoveryStrategy recoverString
122 super.test_string_multi_unterminated(); 226 super.test_string_multi_unterminated();
123 } 227 }
124 228
125 @override 229 @override
126 @failingTest 230 @failingTest
127 void test_string_multi_unterminated_interpolation_block() { 231 void test_string_multi_unterminated_interpolation_block() {
128 // See defaultRecoveryStrategy recoverString 232 // See defaultRecoveryStrategy recoverString
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 super.test_string_simple_unterminated_interpolation_block(); 296 super.test_string_simple_unterminated_interpolation_block();
193 } 297 }
194 298
195 @override 299 @override
196 @failingTest 300 @failingTest
197 void test_string_simple_unterminated_interpolation_identifier() { 301 void test_string_simple_unterminated_interpolation_identifier() {
198 // See defaultRecoveryStrategy recoverString 302 // See defaultRecoveryStrategy recoverString
199 super.test_string_simple_unterminated_interpolation_identifier(); 303 super.test_string_simple_unterminated_interpolation_identifier();
200 } 304 }
201 305
202 @failingTest
203 @override 306 @override
204 void test_unmatched_openers() { 307 void test_unmatched_openers() {
205 // fasta recovery inserts closers 308 // fasta inserts missing closers except for '<'
206 var openBrace = _scan('{[(<') as analyzer.BeginToken; 309 var openBrace = _scan('{[(<') as fasta.BeginGroupToken;
207 var openBracket = openBrace.next as analyzer.BeginToken; 310 var openBracket = openBrace.next as fasta.BeginGroupToken;
208 var openParen = openBracket.next as analyzer.BeginToken; 311 var openParen = openBracket.next as fasta.BeginGroupToken;
209 var openLT = openParen.next as analyzer.BeginToken; 312 var openLT = openParen.next as fasta.BeginGroupToken;
210 var closeGT = openLT.next; 313 var closeParen = openLT.next;
211 var closeParen = closeGT.next;
212 var closeBracket = closeParen.next; 314 var closeBracket = closeParen.next;
213 var closeBrace = closeBracket.next; 315 var closeBrace = closeBracket.next;
214 expect(closeBrace.next.type, analyzer.TokenType.EOF); 316 var eof = closeBrace.next;
215 317
216 expect(openBrace.endToken, closeBrace); 318 expect(openBrace.endGroup, same(closeBrace));
217 expect(openBracket.endToken, closeBracket); 319 expect(openBracket.endGroup, same(closeBracket));
218 expect(openParen.endToken, closeParen); 320 expect(openParen.endGroup, same(closeParen));
219 expect(openLT.endToken, closeGT); 321 expect(eof.isEof, true);
220 } 322 }
221 323
222 analyzer.Token _scan(String source, 324 analyzer.Token _scan(String source,
223 {bool genericMethodComments: false, 325 {bool genericMethodComments: false,
224 bool lazyAssignmentOperators: false}) { 326 bool lazyAssignmentOperators: false}) {
225 ErrorListener listener = new ErrorListener(); 327 ErrorListener listener = new ErrorListener();
226 analyzer.Token token = scanWithListener(source, listener, 328 analyzer.Token token = scanWithListener(source, listener,
227 genericMethodComments: genericMethodComments, 329 genericMethodComments: genericMethodComments,
228 lazyAssignmentOperators: lazyAssignmentOperators); 330 lazyAssignmentOperators: lazyAssignmentOperators);
229 listener.assertNoErrors(); 331 listener.assertNoErrors();
(...skipping 13 matching lines...) Expand all
243 } 345 }
244 if (!token.previousToken.isEof) { 346 if (!token.previousToken.isEof) {
245 var head = new fasta.SymbolToken(EOF_INFO, -1); 347 var head = new fasta.SymbolToken(EOF_INFO, -1);
246 token.previous = head; 348 token.previous = head;
247 head.next = token; 349 head.next = token;
248 } 350 }
249 return token; 351 return token;
250 } 352 }
251 353
252 /// Assert that the tokens in the stream are correctly connected prev/next. 354 /// Assert that the tokens in the stream are correctly connected prev/next.
253 void assertValidTokenStream(fasta.Token firstToken) { 355 void assertValidTokenStream(fasta.Token firstToken,
356 {bool errorsFirst: false}) {
254 fasta.Token token = firstToken; 357 fasta.Token token = firstToken;
255 fasta.Token previous = token.previousToken; 358 fasta.Token previous = token.previousToken;
256 expect(previous.isEof, isTrue, reason: 'Missing leading EOF'); 359 expect(previous.isEof, isTrue, reason: 'Missing leading EOF');
257 expect(previous.next, token, reason: 'Invalid leading EOF'); 360 expect(previous.next, token, reason: 'Invalid leading EOF');
258 expect(previous.previous, previous, reason: 'Invalid leading EOF'); 361 expect(previous.previous, previous, reason: 'Invalid leading EOF');
362 if (errorsFirst) {
363 while (!token.isEof && token is fasta.ErrorToken) {
364 token = token.next;
365 }
366 }
367 var isNotErrorToken = isNot(new isInstanceOf<fasta.ErrorToken>());
259 while (!token.isEof) { 368 while (!token.isEof) {
369 if (errorsFirst) expect(token, isNotErrorToken);
260 previous = token; 370 previous = token;
261 token = token.next; 371 token = token.next;
262 expect(token, isNotNull, reason: previous.toString()); 372 expect(token, isNotNull, reason: previous.toString());
263 expect(token.previous, previous, reason: token.toString()); 373 expect(token.previous, previous, reason: token.toString());
264 } 374 }
265 expect(token.next, token, reason: 'Invalid trailing EOF'); 375 expect(token.next, token, reason: 'Invalid trailing EOF');
266 } 376 }
377
378 /// Assert that all [fasta.BeginGroupToken] has a valid `endGroup`
379 /// that is in the stream.
380 void assertValidBeginTokens(fasta.Token firstToken) {
381 var openerStack = <fasta.BeginGroupToken>[];
382 fasta.BeginGroupToken lastClosedGroup;
383 fasta.Token token = firstToken;
384 while (!token.isEof) {
385 if (token is fasta.BeginGroupToken) {
386 if (token.lexeme != '<')
387 expect(token.endGroup, isNotNull, reason: token.lexeme);
388 if (token.endGroup != null) openerStack.add(token);
389 } else if (openerStack.isNotEmpty && openerStack.last.endGroup == token) {
390 lastClosedGroup = openerStack.removeLast();
391 expect(token.isSynthetic, token.next is fasta.UnmatchedToken,
392 reason: 'Expect synthetic closer then error token');
393 } else if (token is fasta.UnmatchedToken) {
394 expect(lastClosedGroup?.endGroup?.next, same(token),
395 reason: 'Unexpected error token for group: $lastClosedGroup');
396 expect(token.begin, lastClosedGroup);
397 }
398 token = token.next;
399 }
400 expect(openerStack, isEmpty, reason: 'Missing closers');
401 }
267 } 402 }
OLDNEW
« no previous file with comments | « pkg/front_end/test/scanner_fasta_test.dart ('k') | pkg/front_end/test/scanner_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698