| 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 import 'dart:convert'; | 
| 4 | 5 | 
| 5 import 'package:analyzer/src/fasta/token_utils.dart'; | 6 import 'package:analyzer/src/fasta/token_utils.dart'; | 
| 6 import 'package:front_end/src/fasta/fasta_codes.dart'; | 7 import 'package:front_end/src/fasta/fasta_codes.dart'; | 
| 7 import 'package:front_end/src/fasta/scanner/error_token.dart' as fasta; | 8 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; | 9 import 'package:front_end/src/fasta/scanner/string_scanner.dart' as fasta; | 
| 9 import 'package:front_end/src/fasta/scanner/token.dart' as fasta; | 10 import 'package:front_end/src/fasta/scanner/token.dart' as fasta; | 
| 10 import 'package:front_end/src/fasta/scanner/token_constants.dart' as fasta; | 11 import 'package:front_end/src/fasta/scanner/token_constants.dart' as fasta; | 
|  | 12 import 'package:front_end/src/fasta/scanner/utf8_bytes_scanner.dart' as fasta; | 
| 11 import 'package:front_end/src/scanner/errors.dart'; | 13 import 'package:front_end/src/scanner/errors.dart'; | 
| 12 import 'package:front_end/src/scanner/token.dart'; | 14 import 'package:front_end/src/scanner/token.dart'; | 
| 13 import 'package:test/test.dart'; | 15 import 'package:test/test.dart'; | 
| 14 import 'package:test_reflective_loader/test_reflective_loader.dart'; | 16 import 'package:test_reflective_loader/test_reflective_loader.dart'; | 
| 15 | 17 | 
| 16 import 'scanner_test.dart'; | 18 import 'scanner_test.dart'; | 
| 17 | 19 | 
| 18 main() { | 20 main() { | 
| 19   defineReflectiveSuite(() { | 21   defineReflectiveSuite(() { | 
| 20     defineReflectiveTests(ScannerTest_Fasta); | 22     defineReflectiveTests(ScannerTest_Fasta); | 
|  | 23     defineReflectiveTests(ScannerTest_Fasta_UTF8); | 
| 21     defineReflectiveTests(ScannerTest_Fasta_Direct); | 24     defineReflectiveTests(ScannerTest_Fasta_Direct); | 
|  | 25     defineReflectiveTests(ScannerTest_Fasta_Direct_UTF8); | 
| 22   }); | 26   }); | 
| 23 } | 27 } | 
| 24 | 28 | 
| 25 @reflectiveTest | 29 @reflectiveTest | 
|  | 30 class ScannerTest_Fasta_UTF8 extends ScannerTest_Fasta { | 
|  | 31   @override | 
|  | 32   createScanner(String source, {bool genericMethodComments: false}) { | 
|  | 33     List<int> encoded = UTF8.encode(source).toList(growable: true); | 
|  | 34     encoded.add(0); // Ensure 0 terminted bytes for UTF8 scanner | 
|  | 35     return new fasta.Utf8BytesScanner(encoded, | 
|  | 36         includeComments: true, | 
|  | 37         scanGenericMethodComments: genericMethodComments); | 
|  | 38   } | 
|  | 39 } | 
|  | 40 | 
|  | 41 @reflectiveTest | 
| 26 class ScannerTest_Fasta extends ScannerTestBase { | 42 class ScannerTest_Fasta extends ScannerTestBase { | 
| 27   ScannerTest_Fasta() { | 43   ScannerTest_Fasta() { | 
| 28     usingFasta = true; | 44     usingFasta = true; | 
| 29   } | 45   } | 
| 30 | 46 | 
|  | 47   createScanner(String source, {bool genericMethodComments: false}) => | 
|  | 48       new fasta.StringScanner(source, | 
|  | 49           includeComments: true, | 
|  | 50           scanGenericMethodComments: genericMethodComments); | 
|  | 51 | 
| 31   @override | 52   @override | 
| 32   Token scanWithListener(String source, ErrorListener listener, | 53   Token scanWithListener(String source, ErrorListener listener, | 
| 33       {bool genericMethodComments: false, | 54       {bool genericMethodComments: false, | 
| 34       bool lazyAssignmentOperators: false}) { | 55       bool lazyAssignmentOperators: false}) { | 
| 35     var scanner = new fasta.StringScanner(source, | 56     var scanner = | 
| 36         includeComments: true, | 57         createScanner(source, genericMethodComments: genericMethodComments); | 
| 37         scanGenericMethodComments: genericMethodComments); |  | 
| 38     var token = scanner.tokenize(); | 58     var token = scanner.tokenize(); | 
| 39     return new ToAnalyzerTokenStreamConverter_WithListener(listener) | 59     return new ToAnalyzerTokenStreamConverter_WithListener(listener) | 
| 40         .convertTokens(token); | 60         .convertTokens(token); | 
| 41   } | 61   } | 
| 42 | 62 | 
| 43   void test_comments() { | 63   void test_comments() { | 
| 44     const source = ''' | 64     const source = ''' | 
| 45        /// Doc comment before class | 65        /// Doc comment before class | 
| 46        /// second line | 66        /// second line | 
| 47        /// third | 67        /// third | 
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 233         if (commentToken.next != null) { | 253         if (commentToken.next != null) { | 
| 234           expect(commentToken.next.previous, commentToken); | 254           expect(commentToken.next.previous, commentToken); | 
| 235         } | 255         } | 
| 236         commentToken = commentToken.next; | 256         commentToken = commentToken.next; | 
| 237       } | 257       } | 
| 238       token = token.next; | 258       token = token.next; | 
| 239     } | 259     } | 
| 240   } | 260   } | 
| 241 | 261 | 
| 242   @override | 262   @override | 
| 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 |  | 
| 251   void test_string_multi_unterminated_interpolation_block() { |  | 
| 252     // TODO(paulberry,ahe): bad error recovery. |  | 
| 253     super.test_string_multi_unterminated_interpolation_block(); |  | 
| 254   } |  | 
| 255 |  | 
| 256   @override |  | 
| 257   @failingTest |  | 
| 258   void test_string_multi_unterminated_interpolation_identifier() { |  | 
| 259     // TODO(paulberry,ahe): bad error recovery. |  | 
| 260     super.test_string_multi_unterminated_interpolation_identifier(); |  | 
| 261   } |  | 
| 262 |  | 
| 263   @override |  | 
| 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 |  | 
| 300   void test_string_simple_unterminated_interpolation_block() { |  | 
| 301     // TODO(paulberry,ahe): bad error recovery. |  | 
| 302     super.test_string_simple_unterminated_interpolation_block(); |  | 
| 303   } |  | 
| 304 |  | 
| 305   @override |  | 
| 306   @failingTest |  | 
| 307   void test_string_simple_unterminated_interpolation_identifier() { |  | 
| 308     // TODO(paulberry,ahe): bad error recovery. |  | 
| 309     super.test_string_simple_unterminated_interpolation_identifier(); |  | 
| 310   } |  | 
| 311 |  | 
| 312   @override |  | 
| 313   void test_unmatched_openers() { | 263   void test_unmatched_openers() { | 
| 314     var openBrace = _scan('{[(') as BeginToken; | 264     var openBrace = _scan('{[(') as BeginToken; | 
| 315     var openBracket = openBrace.next as BeginToken; | 265     var openBracket = openBrace.next as BeginToken; | 
| 316     var openParen = openBracket.next as BeginToken; | 266     var openParen = openBracket.next as BeginToken; | 
| 317     var closeParen = openParen.next; | 267     var closeParen = openParen.next; | 
| 318     var closeBracket = closeParen.next; | 268     var closeBracket = closeParen.next; | 
| 319     var closeBrace = closeBracket.next; | 269     var closeBrace = closeBracket.next; | 
| 320     expect(closeBrace.next.type, TokenType.EOF); | 270     expect(closeBrace.next.type, TokenType.EOF); | 
| 321     expect(openBrace.endToken, same(closeBrace)); | 271     expect(openBrace.endToken, same(closeBrace)); | 
| 322     expect(openBracket.endToken, same(closeBracket)); | 272     expect(openBracket.endToken, same(closeBracket)); | 
| 323     expect(openParen.endToken, same(closeParen)); | 273     expect(openParen.endToken, same(closeParen)); | 
| 324   } | 274   } | 
| 325 | 275 | 
| 326   Token _scan(String source, | 276   Token _scan(String source, | 
| 327       {bool genericMethodComments: false, | 277       {bool genericMethodComments: false, | 
| 328       bool lazyAssignmentOperators: false}) { | 278       bool lazyAssignmentOperators: false}) { | 
| 329     ErrorListener listener = new ErrorListener(); | 279     ErrorListener listener = new ErrorListener(); | 
| 330     Token token = scanWithListener(source, listener, | 280     Token token = scanWithListener(source, listener, | 
| 331         genericMethodComments: genericMethodComments, | 281         genericMethodComments: genericMethodComments, | 
| 332         lazyAssignmentOperators: lazyAssignmentOperators); | 282         lazyAssignmentOperators: lazyAssignmentOperators); | 
| 333     listener.assertNoErrors(); | 283     listener.assertNoErrors(); | 
| 334     return token; | 284     return token; | 
| 335   } | 285   } | 
| 336 } | 286 } | 
| 337 | 287 | 
| 338 /// Base class for scanner tests that examine the token stream in Fasta format. | 288 /// Base class for scanner tests that examine the token stream in Fasta format. | 
| 339 abstract class ScannerTest_Fasta_Base { | 289 abstract class ScannerTest_Fasta_Base { | 
| 340   Token scan(String source); | 290   Token scan(String source); | 
| 341 | 291 | 
|  | 292   expectToken(Token token, TokenType type, int offset, int length, | 
|  | 293       {bool isSynthetic: false, String lexeme}) { | 
|  | 294     String description = '${token.type} $token'; | 
|  | 295     expect(token.type, type, reason: description); | 
|  | 296     expect(token.offset, offset, reason: description); | 
|  | 297     expect(token.length, length, reason: description); | 
|  | 298     expect(token.isSynthetic, isSynthetic, reason: description); | 
|  | 299     if (lexeme != null) { | 
|  | 300       expect(token.lexeme, lexeme, reason: description); | 
|  | 301     } | 
|  | 302   } | 
|  | 303 | 
|  | 304   void test_string_simple_unterminated_interpolation_block() { | 
|  | 305     Token token = scan(r'"foo ${bar'); | 
|  | 306     expectToken(token, TokenType.STRING, 0, 5, lexeme: '"foo '); | 
|  | 307 | 
|  | 308     token = token.next; | 
|  | 309     expectToken(token, TokenType.STRING_INTERPOLATION_EXPRESSION, 5, 2); | 
|  | 310     BeginToken interpolationStart = token; | 
|  | 311 | 
|  | 312     token = token.next; | 
|  | 313     expectToken(token, TokenType.IDENTIFIER, 7, 3, lexeme: 'bar'); | 
|  | 314 | 
|  | 315     // Expect interpolation to be terminated before string is closed | 
|  | 316     token = token.next; | 
|  | 317     expectToken(token, TokenType.CLOSE_CURLY_BRACKET, 10, 0, | 
|  | 318         isSynthetic: true, lexeme: '}'); | 
|  | 319     expect(interpolationStart.endToken, same(token)); | 
|  | 320 | 
|  | 321     token = token.next; | 
|  | 322     expect((token as fasta.ErrorToken).errorCode, same(codeUnmatchedToken)); | 
|  | 323     expect((token as fasta.UnmatchedToken).begin, same(interpolationStart)); | 
|  | 324 | 
|  | 325     token = token.next; | 
|  | 326     expectToken(token, TokenType.STRING, 10, 0, isSynthetic: true, lexeme: '"'); | 
|  | 327 | 
|  | 328     token = token.next; | 
|  | 329     expect((token as fasta.ErrorToken).errorCode, same(codeUnterminatedString)); | 
|  | 330   } | 
|  | 331 | 
|  | 332   void test_string_simple_missing_interpolation_identifier() { | 
|  | 333     Token token = scan(r'"foo $'); | 
|  | 334     expectToken(token, TokenType.STRING, 0, 5, lexeme: '"foo '); | 
|  | 335 | 
|  | 336     token = token.next; | 
|  | 337     expectToken(token, TokenType.STRING_INTERPOLATION_IDENTIFIER, 5, 1); | 
|  | 338 | 
|  | 339     token = token.next; | 
|  | 340     expect((token as fasta.ErrorToken).errorCode, | 
|  | 341         same(codeUnexpectedDollarInString)); | 
|  | 342     expect((token as fasta.UnterminatedToken).start, r'$'); | 
|  | 343 | 
|  | 344     token = token.next; | 
|  | 345     expectToken(token, TokenType.STRING, 6, 0, isSynthetic: true, lexeme: '"'); | 
|  | 346 | 
|  | 347     token = token.next; | 
|  | 348     expect((token as fasta.ErrorToken).errorCode, same(codeUnterminatedString)); | 
|  | 349   } | 
|  | 350 | 
|  | 351   void test_string_multi_unterminated() { | 
|  | 352     Token token = scan("'''string"); | 
|  | 353     expectToken(token, TokenType.STRING, 0, 9, | 
|  | 354         lexeme: "'''string'''", isSynthetic: true); | 
|  | 355 | 
|  | 356     token = token.next; | 
|  | 357     expect((token as fasta.ErrorToken).errorCode, same(codeUnterminatedString)); | 
|  | 358     expect((token as fasta.ErrorToken).start, "'''"); | 
|  | 359   } | 
|  | 360 | 
|  | 361   void test_string_raw_multi_unterminated() { | 
|  | 362     Token token = scan("r'''string"); | 
|  | 363     expectToken(token, TokenType.STRING, 0, 10, | 
|  | 364         lexeme: "r'''string'''", isSynthetic: true); | 
|  | 365 | 
|  | 366     token = token.next; | 
|  | 367     expect((token as fasta.ErrorToken).errorCode, same(codeUnterminatedString)); | 
|  | 368     expect((token as fasta.ErrorToken).start, "r'''"); | 
|  | 369   } | 
|  | 370 | 
|  | 371   void test_string_raw_simple_unterminated_eof() { | 
|  | 372     Token token = scan("r'string"); | 
|  | 373     expectToken(token, TokenType.STRING, 0, 8, | 
|  | 374         lexeme: "r'string'", isSynthetic: true); | 
|  | 375 | 
|  | 376     token = token.next; | 
|  | 377     expect((token as fasta.ErrorToken).errorCode, same(codeUnterminatedString)); | 
|  | 378     expect((token as fasta.ErrorToken).start, "r'"); | 
|  | 379   } | 
|  | 380 | 
|  | 381   void test_string_raw_simple_unterminated_eol() { | 
|  | 382     Token token = scan("r'string\n"); | 
|  | 383     expectToken(token, TokenType.STRING, 0, 8, | 
|  | 384         lexeme: "r'string'", isSynthetic: true); | 
|  | 385 | 
|  | 386     token = token.next; | 
|  | 387     expect((token as fasta.ErrorToken).errorCode, same(codeUnterminatedString)); | 
|  | 388     expect((token as fasta.ErrorToken).start, "r'"); | 
|  | 389   } | 
|  | 390 | 
|  | 391   void test_string_simple_unterminated_eof() { | 
|  | 392     Token token = scan("'string"); | 
|  | 393     expectToken(token, TokenType.STRING, 0, 7, | 
|  | 394         lexeme: "'string'", isSynthetic: true); | 
|  | 395 | 
|  | 396     token = token.next; | 
|  | 397     expect((token as fasta.ErrorToken).errorCode, same(codeUnterminatedString)); | 
|  | 398     expect((token as fasta.ErrorToken).start, "'"); | 
|  | 399   } | 
|  | 400 | 
|  | 401   void test_string_simple_unterminated_eol() { | 
|  | 402     Token token = scan("'string\n"); | 
|  | 403     expectToken(token, TokenType.STRING, 0, 7, | 
|  | 404         lexeme: "'string'", isSynthetic: true); | 
|  | 405 | 
|  | 406     token = token.next; | 
|  | 407     expect((token as fasta.ErrorToken).errorCode, same(codeUnterminatedString)); | 
|  | 408     expect((token as fasta.ErrorToken).start, "'"); | 
|  | 409   } | 
|  | 410 | 
| 342   void test_match_angle_brackets() { | 411   void test_match_angle_brackets() { | 
| 343     var x = scan('x<y>'); | 412     var x = scan('x<y>'); | 
| 344     var lessThan = x.next as BeginToken; | 413     var lessThan = x.next as BeginToken; | 
| 345     var y = lessThan.next; | 414     var y = lessThan.next; | 
| 346     var greaterThan = y.next; | 415     var greaterThan = y.next; | 
| 347     expect(greaterThan.next.isEof, isTrue); | 416     expect(greaterThan.next.isEof, isTrue); | 
| 348     expect(lessThan.endGroup, same(greaterThan)); | 417     expect(lessThan.endGroup, same(greaterThan)); | 
| 349   } | 418   } | 
| 350 | 419 | 
| 351   void test_match_angle_brackets_gt_gt() { | 420   void test_match_angle_brackets_gt_gt() { | 
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 487     var y = lessThan.next; | 556     var y = lessThan.next; | 
| 488     var greaterThans = y.next; | 557     var greaterThans = y.next; | 
| 489     var z = greaterThans.next; | 558     var z = greaterThans.next; | 
| 490     expect(z.next.isEof, isTrue); | 559     expect(z.next.isEof, isTrue); | 
| 491     expect(lessThan.endGroup, isNull); | 560     expect(lessThan.endGroup, isNull); | 
| 492   } | 561   } | 
| 493 } | 562 } | 
| 494 | 563 | 
| 495 /// Scanner tests that exercise the Fasta scanner directly. | 564 /// Scanner tests that exercise the Fasta scanner directly. | 
| 496 @reflectiveTest | 565 @reflectiveTest | 
|  | 566 class ScannerTest_Fasta_Direct_UTF8 extends ScannerTest_Fasta_Direct { | 
|  | 567   createScanner(String source, {bool includeComments}) { | 
|  | 568     List<int> encoded = UTF8.encode(source).toList(growable: true); | 
|  | 569     encoded.add(0); // Ensure 0 terminted bytes for UTF8 scanner | 
|  | 570     return new fasta.Utf8BytesScanner(encoded, | 
|  | 571         includeComments: includeComments); | 
|  | 572   } | 
|  | 573 } | 
|  | 574 | 
|  | 575 /// Scanner tests that exercise the Fasta scanner directly. | 
|  | 576 @reflectiveTest | 
| 497 class ScannerTest_Fasta_Direct extends ScannerTest_Fasta_Base { | 577 class ScannerTest_Fasta_Direct extends ScannerTest_Fasta_Base { | 
|  | 578   createScanner(String source, {bool includeComments}) => | 
|  | 579       new fasta.StringScanner(source, includeComments: includeComments); | 
|  | 580 | 
| 498   @override | 581   @override | 
| 499   Token scan(String source) { | 582   Token scan(String source) { | 
| 500     var scanner = new fasta.StringScanner(source, includeComments: true); | 583     return createScanner(source, includeComments: true).tokenize(); | 
| 501     return scanner.tokenize(); |  | 
| 502   } | 584   } | 
| 503 | 585 | 
| 504   void test_linestarts() { | 586   void test_linestarts() { | 
| 505     var scanner = new fasta.StringScanner("var\r\ni\n=\n1;\n"); | 587     var scanner = createScanner("var\r\ni\n=\n1;\n"); | 
| 506     var token = scanner.tokenize(); | 588     var token = scanner.tokenize(); | 
| 507     expect(token.lexeme, 'var'); | 589     expect(token.lexeme, 'var'); | 
| 508     var lineStarts = scanner.lineStarts; | 590     var lineStarts = scanner.lineStarts; | 
| 509     expect(lineStarts, orderedEquals([0, 5, 7, 9, 12, 13])); | 591     expect(lineStarts, orderedEquals([0, 5, 7, 9, 12, 13])); | 
| 510   } | 592   } | 
| 511 |  | 
| 512   test_unterminated_string_with_unterminated_interpolation() { |  | 
| 513     Token token = scan(r'"foo ${bar'); |  | 
| 514     BeginToken interpolationStart = token.next; |  | 
| 515 |  | 
| 516     Token previous; |  | 
| 517     while (token.kind != fasta.BAD_INPUT_TOKEN) { |  | 
| 518       expect(token.isEof, isFalse); |  | 
| 519       previous = token; |  | 
| 520       token = token.next; |  | 
| 521     } |  | 
| 522 |  | 
| 523     // Expect interpolation to be terminated before string is closed |  | 
| 524 |  | 
| 525     token = previous; |  | 
| 526     expect(token.isSynthetic, isTrue); |  | 
| 527     expect(token.length, 0); |  | 
| 528     expect(token.stringValue, '}'); |  | 
| 529 |  | 
| 530     token = token.next; |  | 
| 531     expect((token as fasta.ErrorToken).errorCode, same(codeUnmatchedToken)); |  | 
| 532     expect((token as fasta.UnmatchedToken).begin, same(interpolationStart)); |  | 
| 533 |  | 
| 534     token = token.next; |  | 
| 535     expect((token as fasta.ErrorToken).errorCode, same(codeUnterminatedString)); |  | 
| 536   } |  | 
| 537 } | 593 } | 
| 538 | 594 | 
| 539 /// Override of [ToAnalyzerTokenStreamConverter] that verifies that there are no | 595 /// Override of [ToAnalyzerTokenStreamConverter] that verifies that there are no | 
| 540 /// errors. | 596 /// errors. | 
| 541 class ToAnalyzerTokenStreamConverter_NoErrors | 597 class ToAnalyzerTokenStreamConverter_NoErrors | 
| 542     extends ToAnalyzerTokenStreamConverter { | 598     extends ToAnalyzerTokenStreamConverter { | 
| 543   @override | 599   @override | 
| 544   void reportError( | 600   void reportError( | 
| 545       ScannerErrorCode errorCode, int offset, List<Object> arguments) { | 601       ScannerErrorCode errorCode, int offset, List<Object> arguments) { | 
| 546     fail('Unexpected error: $errorCode, $offset, $arguments'); | 602     fail('Unexpected error: $errorCode, $offset, $arguments'); | 
| 547   } | 603   } | 
| 548 } | 604 } | 
| 549 | 605 | 
| 550 /// Override of [ToAnalyzerTokenStreamConverter] that records errors in an | 606 /// Override of [ToAnalyzerTokenStreamConverter] that records errors in an | 
| 551 /// [ErrorListener]. | 607 /// [ErrorListener]. | 
| 552 class ToAnalyzerTokenStreamConverter_WithListener | 608 class ToAnalyzerTokenStreamConverter_WithListener | 
| 553     extends ToAnalyzerTokenStreamConverter { | 609     extends ToAnalyzerTokenStreamConverter { | 
| 554   final ErrorListener _listener; | 610   final ErrorListener _listener; | 
| 555 | 611 | 
| 556   ToAnalyzerTokenStreamConverter_WithListener(this._listener); | 612   ToAnalyzerTokenStreamConverter_WithListener(this._listener); | 
| 557 | 613 | 
| 558   @override | 614   @override | 
| 559   void reportError( | 615   void reportError( | 
| 560       ScannerErrorCode errorCode, int offset, List<Object> arguments) { | 616       ScannerErrorCode errorCode, int offset, List<Object> arguments) { | 
| 561     _listener.errors.add(new TestError(offset, errorCode, arguments)); | 617     _listener.errors.add(new TestError(offset, errorCode, arguments)); | 
| 562   } | 618   } | 
| 563 } | 619 } | 
| OLD | NEW | 
|---|