| 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 'package:analyzer/src/fasta/token_utils.dart'; | 5 import 'package:analyzer/src/fasta/token_utils.dart'; |
| 6 import 'package:front_end/src/fasta/fasta_codes.dart'; | 6 import 'package:front_end/src/fasta/fasta_codes.dart'; |
| 7 import 'package:front_end/src/fasta/scanner/error_token.dart' as fasta; | 7 import 'package:front_end/src/fasta/scanner/error_token.dart' as fasta; |
| 8 import 'package:front_end/src/fasta/scanner/string_scanner.dart' as fasta; | 8 import 'package:front_end/src/fasta/scanner/string_scanner.dart' as fasta; |
| 9 import 'package:front_end/src/fasta/scanner/token.dart' as fasta; | 9 import 'package:front_end/src/fasta/scanner/token.dart' as fasta; |
| 10 import 'package:front_end/src/fasta/scanner/token_constants.dart' as fasta; | 10 import 'package:front_end/src/fasta/scanner/token_constants.dart' as fasta; |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 234 expect(commentToken.next.previous, commentToken); | 234 expect(commentToken.next.previous, commentToken); |
| 235 } | 235 } |
| 236 commentToken = commentToken.next; | 236 commentToken = commentToken.next; |
| 237 } | 237 } |
| 238 token = token.next; | 238 token = token.next; |
| 239 } | 239 } |
| 240 } | 240 } |
| 241 | 241 |
| 242 @override | 242 @override |
| 243 @failingTest | 243 @failingTest |
| 244 void test_string_multi_unterminated() { |
| 245 // TODO(paulberry,ahe): bad error recovery. |
| 246 super.test_string_multi_unterminated(); |
| 247 } |
| 248 |
| 249 @override |
| 250 @failingTest |
| 244 void test_string_multi_unterminated_interpolation_block() { | 251 void test_string_multi_unterminated_interpolation_block() { |
| 245 // TODO(paulberry,ahe): bad error recovery. | 252 // TODO(paulberry,ahe): bad error recovery. |
| 246 super.test_string_multi_unterminated_interpolation_block(); | 253 super.test_string_multi_unterminated_interpolation_block(); |
| 247 } | 254 } |
| 248 | 255 |
| 249 @override | 256 @override |
| 250 @failingTest | 257 @failingTest |
| 251 void test_string_multi_unterminated_interpolation_identifier() { | 258 void test_string_multi_unterminated_interpolation_identifier() { |
| 252 // TODO(paulberry,ahe): bad error recovery. | 259 // TODO(paulberry,ahe): bad error recovery. |
| 253 super.test_string_multi_unterminated_interpolation_identifier(); | 260 super.test_string_multi_unterminated_interpolation_identifier(); |
| 254 } | 261 } |
| 255 | 262 |
| 256 @override | 263 @override |
| 257 @failingTest | 264 @failingTest |
| 265 void test_string_raw_multi_unterminated() { |
| 266 // TODO(paulberry,ahe): bad error recovery. |
| 267 super.test_string_raw_multi_unterminated(); |
| 268 } |
| 269 |
| 270 @override |
| 271 @failingTest |
| 272 void test_string_raw_simple_unterminated_eof() { |
| 273 // TODO(paulberry,ahe): bad error recovery. |
| 274 super.test_string_raw_simple_unterminated_eof(); |
| 275 } |
| 276 |
| 277 @override |
| 278 @failingTest |
| 279 void test_string_raw_simple_unterminated_eol() { |
| 280 // TODO(paulberry,ahe): bad error recovery. |
| 281 super.test_string_raw_simple_unterminated_eol(); |
| 282 } |
| 283 |
| 284 @override |
| 285 @failingTest |
| 286 void test_string_simple_unterminated_eof() { |
| 287 // TODO(paulberry,ahe): bad error recovery. |
| 288 super.test_string_simple_unterminated_eof(); |
| 289 } |
| 290 |
| 291 @override |
| 292 @failingTest |
| 293 void test_string_simple_unterminated_eol() { |
| 294 // TODO(paulberry,ahe): bad error recovery. |
| 295 super.test_string_simple_unterminated_eol(); |
| 296 } |
| 297 |
| 298 @override |
| 299 @failingTest |
| 258 void test_string_simple_unterminated_interpolation_block() { | 300 void test_string_simple_unterminated_interpolation_block() { |
| 259 // TODO(paulberry,ahe): bad error recovery. | 301 // TODO(paulberry,ahe): bad error recovery. |
| 260 super.test_string_simple_unterminated_interpolation_block(); | 302 super.test_string_simple_unterminated_interpolation_block(); |
| 261 } | 303 } |
| 262 | 304 |
| 263 @override | 305 @override |
| 264 @failingTest | 306 @failingTest |
| 265 void test_string_simple_unterminated_interpolation_identifier() { | 307 void test_string_simple_unterminated_interpolation_identifier() { |
| 266 // TODO(paulberry,ahe): bad error recovery. | 308 // TODO(paulberry,ahe): bad error recovery. |
| 267 super.test_string_simple_unterminated_interpolation_identifier(); | 309 super.test_string_simple_unterminated_interpolation_identifier(); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 290 lazyAssignmentOperators: lazyAssignmentOperators); | 332 lazyAssignmentOperators: lazyAssignmentOperators); |
| 291 listener.assertNoErrors(); | 333 listener.assertNoErrors(); |
| 292 return token; | 334 return token; |
| 293 } | 335 } |
| 294 } | 336 } |
| 295 | 337 |
| 296 /// Base class for scanner tests that examine the token stream in Fasta format. | 338 /// Base class for scanner tests that examine the token stream in Fasta format. |
| 297 abstract class ScannerTest_Fasta_Base { | 339 abstract class ScannerTest_Fasta_Base { |
| 298 Token scan(String source); | 340 Token scan(String source); |
| 299 | 341 |
| 300 expectToken(Token token, TokenType type, int offset, int length, | |
| 301 {bool isSynthetic: false, String lexeme}) { | |
| 302 String description = '${token.type} $token'; | |
| 303 expect(token.type, type, reason: description); | |
| 304 expect(token.offset, offset, reason: description); | |
| 305 expect(token.length, length, reason: description); | |
| 306 expect(token.isSynthetic, isSynthetic, reason: description); | |
| 307 if (lexeme != null) { | |
| 308 expect(token.lexeme, lexeme, reason: description); | |
| 309 } | |
| 310 } | |
| 311 | |
| 312 void test_incomplete_string_interpolation() { | |
| 313 Token token = scan(r'"foo ${bar'); | |
| 314 expectToken(token, TokenType.STRING, 0, 5, lexeme: '"foo '); | |
| 315 | |
| 316 token = token.next; | |
| 317 expectToken(token, TokenType.STRING_INTERPOLATION_EXPRESSION, 5, 2); | |
| 318 BeginToken interpolationStart = token; | |
| 319 | |
| 320 token = token.next; | |
| 321 expectToken(token, TokenType.IDENTIFIER, 7, 3, lexeme: 'bar'); | |
| 322 | |
| 323 // Expect interpolation to be terminated before string is closed | |
| 324 token = token.next; | |
| 325 expectToken(token, TokenType.CLOSE_CURLY_BRACKET, 10, 0, | |
| 326 isSynthetic: true, lexeme: '}'); | |
| 327 expect(interpolationStart.endToken, same(token)); | |
| 328 | |
| 329 token = token.next; | |
| 330 expect((token as fasta.ErrorToken).errorCode, same(codeUnmatchedToken)); | |
| 331 expect((token as fasta.UnmatchedToken).begin, same(interpolationStart)); | |
| 332 | |
| 333 token = token.next; | |
| 334 expectToken(token, TokenType.STRING, 10, 0, isSynthetic: true, lexeme: '"'); | |
| 335 | |
| 336 token = token.next; | |
| 337 expect((token as fasta.ErrorToken).errorCode, same(codeUnterminatedString)); | |
| 338 } | |
| 339 | |
| 340 void test_string_multi_unterminated() { | |
| 341 Token token = scan("'''string"); | |
| 342 expectToken(token, TokenType.STRING, 0, 9, lexeme: "'''string"); | |
| 343 | |
| 344 token = token.next; | |
| 345 expectToken(token, TokenType.STRING, 9, 0, | |
| 346 isSynthetic: true, lexeme: "'''"); | |
| 347 | |
| 348 token = token.next; | |
| 349 expect((token as fasta.ErrorToken).errorCode, same(codeUnterminatedString)); | |
| 350 expect((token as fasta.ErrorToken).start, "'''"); | |
| 351 } | |
| 352 | |
| 353 void test_string_raw_multi_unterminated() { | |
| 354 Token token = scan("r'''string"); | |
| 355 expectToken(token, TokenType.STRING, 0, 10, lexeme: "r'''string"); | |
| 356 | |
| 357 token = token.next; | |
| 358 expectToken(token, TokenType.STRING, 10, 0, | |
| 359 isSynthetic: true, lexeme: "'''"); | |
| 360 | |
| 361 token = token.next; | |
| 362 expect((token as fasta.ErrorToken).errorCode, same(codeUnterminatedString)); | |
| 363 expect((token as fasta.ErrorToken).start, "r'''"); | |
| 364 } | |
| 365 | |
| 366 void test_string_raw_simple_unterminated_eof() { | |
| 367 Token token = scan("r'string"); | |
| 368 expectToken(token, TokenType.STRING, 0, 8, lexeme: "r'string"); | |
| 369 | |
| 370 token = token.next; | |
| 371 expectToken(token, TokenType.STRING, 8, 0, isSynthetic: true, lexeme: "'"); | |
| 372 | |
| 373 token = token.next; | |
| 374 expect((token as fasta.ErrorToken).errorCode, same(codeUnterminatedString)); | |
| 375 expect((token as fasta.ErrorToken).start, "r'"); | |
| 376 } | |
| 377 | |
| 378 void test_string_raw_simple_unterminated_eol() { | |
| 379 Token token = scan("r'string\n"); | |
| 380 expectToken(token, TokenType.STRING, 0, 8, lexeme: "r'string"); | |
| 381 | |
| 382 token = token.next; | |
| 383 expectToken(token, TokenType.STRING, 8, 0, isSynthetic: true, lexeme: "'"); | |
| 384 | |
| 385 token = token.next; | |
| 386 expect((token as fasta.ErrorToken).errorCode, same(codeUnterminatedString)); | |
| 387 expect((token as fasta.ErrorToken).start, "r'"); | |
| 388 } | |
| 389 | |
| 390 void test_string_simple_unterminated_eof() { | |
| 391 Token token = scan("'string"); | |
| 392 expectToken(token, TokenType.STRING, 0, 7, lexeme: "'string"); | |
| 393 | |
| 394 token = token.next; | |
| 395 expectToken(token, TokenType.STRING, 7, 0, isSynthetic: true, lexeme: "'"); | |
| 396 | |
| 397 token = token.next; | |
| 398 expect((token as fasta.ErrorToken).errorCode, same(codeUnterminatedString)); | |
| 399 expect((token as fasta.ErrorToken).start, "'"); | |
| 400 } | |
| 401 | |
| 402 void test_string_simple_unterminated_eol() { | |
| 403 Token token = scan("'string\n"); | |
| 404 expectToken(token, TokenType.STRING, 0, 7, lexeme: "'string"); | |
| 405 | |
| 406 token = token.next; | |
| 407 expectToken(token, TokenType.STRING, 7, 0, isSynthetic: true, lexeme: "'"); | |
| 408 | |
| 409 token = token.next; | |
| 410 expect((token as fasta.ErrorToken).errorCode, same(codeUnterminatedString)); | |
| 411 expect((token as fasta.ErrorToken).start, "'"); | |
| 412 } | |
| 413 | |
| 414 void test_match_angle_brackets() { | 342 void test_match_angle_brackets() { |
| 415 var x = scan('x<y>'); | 343 var x = scan('x<y>'); |
| 416 var lessThan = x.next as BeginToken; | 344 var lessThan = x.next as BeginToken; |
| 417 var y = lessThan.next; | 345 var y = lessThan.next; |
| 418 var greaterThan = y.next; | 346 var greaterThan = y.next; |
| 419 expect(greaterThan.next.isEof, isTrue); | 347 expect(greaterThan.next.isEof, isTrue); |
| 420 expect(lessThan.endGroup, same(greaterThan)); | 348 expect(lessThan.endGroup, same(greaterThan)); |
| 421 } | 349 } |
| 422 | 350 |
| 423 void test_match_angle_brackets_gt_gt() { | 351 void test_match_angle_brackets_gt_gt() { |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 565 } | 493 } |
| 566 | 494 |
| 567 /// Scanner tests that exercise the Fasta scanner directly. | 495 /// Scanner tests that exercise the Fasta scanner directly. |
| 568 @reflectiveTest | 496 @reflectiveTest |
| 569 class ScannerTest_Fasta_Direct extends ScannerTest_Fasta_Base { | 497 class ScannerTest_Fasta_Direct extends ScannerTest_Fasta_Base { |
| 570 @override | 498 @override |
| 571 Token scan(String source) { | 499 Token scan(String source) { |
| 572 var scanner = new fasta.StringScanner(source, includeComments: true); | 500 var scanner = new fasta.StringScanner(source, includeComments: true); |
| 573 return scanner.tokenize(); | 501 return scanner.tokenize(); |
| 574 } | 502 } |
| 503 |
| 504 test_unterminated_string_with_unterminated_interpolation() { |
| 505 Token token = scan(r'"foo ${bar'); |
| 506 BeginToken interpolationStart = token.next; |
| 507 |
| 508 Token previous; |
| 509 while (token.kind != fasta.BAD_INPUT_TOKEN) { |
| 510 expect(token.isEof, isFalse); |
| 511 previous = token; |
| 512 token = token.next; |
| 513 } |
| 514 |
| 515 // Expect interpolation to be terminated before string is closed |
| 516 |
| 517 token = previous; |
| 518 expect(token.isSynthetic, isTrue); |
| 519 expect(token.length, 0); |
| 520 expect(token.stringValue, '}'); |
| 521 |
| 522 token = token.next; |
| 523 expect((token as fasta.ErrorToken).errorCode, same(codeUnmatchedToken)); |
| 524 expect((token as fasta.UnmatchedToken).begin, same(interpolationStart)); |
| 525 |
| 526 token = token.next; |
| 527 expect((token as fasta.ErrorToken).errorCode, same(codeUnterminatedString)); |
| 528 } |
| 575 } | 529 } |
| 576 | 530 |
| 577 /// Override of [ToAnalyzerTokenStreamConverter] that verifies that there are no | 531 /// Override of [ToAnalyzerTokenStreamConverter] that verifies that there are no |
| 578 /// errors. | 532 /// errors. |
| 579 class ToAnalyzerTokenStreamConverter_NoErrors | 533 class ToAnalyzerTokenStreamConverter_NoErrors |
| 580 extends ToAnalyzerTokenStreamConverter { | 534 extends ToAnalyzerTokenStreamConverter { |
| 581 @override | 535 @override |
| 582 void reportError( | 536 void reportError( |
| 583 ScannerErrorCode errorCode, int offset, List<Object> arguments) { | 537 ScannerErrorCode errorCode, int offset, List<Object> arguments) { |
| 584 fail('Unexpected error: $errorCode, $offset, $arguments'); | 538 fail('Unexpected error: $errorCode, $offset, $arguments'); |
| 585 } | 539 } |
| 586 } | 540 } |
| 587 | 541 |
| 588 /// Override of [ToAnalyzerTokenStreamConverter] that records errors in an | 542 /// Override of [ToAnalyzerTokenStreamConverter] that records errors in an |
| 589 /// [ErrorListener]. | 543 /// [ErrorListener]. |
| 590 class ToAnalyzerTokenStreamConverter_WithListener | 544 class ToAnalyzerTokenStreamConverter_WithListener |
| 591 extends ToAnalyzerTokenStreamConverter { | 545 extends ToAnalyzerTokenStreamConverter { |
| 592 final ErrorListener _listener; | 546 final ErrorListener _listener; |
| 593 | 547 |
| 594 ToAnalyzerTokenStreamConverter_WithListener(this._listener); | 548 ToAnalyzerTokenStreamConverter_WithListener(this._listener); |
| 595 | 549 |
| 596 @override | 550 @override |
| 597 void reportError( | 551 void reportError( |
| 598 ScannerErrorCode errorCode, int offset, List<Object> arguments) { | 552 ScannerErrorCode errorCode, int offset, List<Object> arguments) { |
| 599 _listener.errors.add(new TestError(offset, errorCode, arguments)); | 553 _listener.errors.add(new TestError(offset, errorCode, arguments)); |
| 600 } | 554 } |
| 601 } | 555 } |
| OLD | NEW |