| 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:front_end/src/fasta/analyzer/token_utils.dart'; | 5 import 'package:front_end/src/fasta/analyzer/token_utils.dart'; |
| 6 import 'package:front_end/src/fasta/scanner/error_token.dart' as fasta; | 6 import 'package:front_end/src/fasta/scanner/error_token.dart' as fasta; |
| 7 import 'package:front_end/src/fasta/scanner/keyword.dart' as fasta; | 7 import 'package:front_end/src/fasta/scanner/keyword.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 21 matching lines...) Expand all Loading... |
| 32 // TODO(paulberry): once the analyzer toolchain no longer needs generic | 32 // TODO(paulberry): once the analyzer toolchain no longer needs generic |
| 33 // method comments, remove tests that exercise them. | 33 // method comments, remove tests that exercise them. |
| 34 fail('No generic method comment support in Fasta'); | 34 fail('No generic method comment support in Fasta'); |
| 35 } | 35 } |
| 36 // Note: Fasta always supports lazy assignment operators (`&&=` and `||=`), | 36 // Note: Fasta always supports lazy assignment operators (`&&=` and `||=`), |
| 37 // so we can ignore the `lazyAssignmentOperators` flag. | 37 // so we can ignore the `lazyAssignmentOperators` flag. |
| 38 // TODO(paulberry): once lazyAssignmentOperators are fully supported by | 38 // TODO(paulberry): once lazyAssignmentOperators are fully supported by |
| 39 // Dart, remove this flag. | 39 // Dart, remove this flag. |
| 40 var scanner = new fasta.StringScanner(source, includeComments: true); | 40 var scanner = new fasta.StringScanner(source, includeComments: true); |
| 41 var token = scanner.tokenize(); | 41 var token = scanner.tokenize(); |
| 42 var analyzerTokenHead = new Token(null, 0); | 42 return toAnalyzerTokenStream(token, |
| 43 analyzerTokenHead.previous = analyzerTokenHead; | 43 (ScannerErrorCode errorCode, int offset, List<Object> arguments) { |
| 44 var analyzerTokenTail = analyzerTokenHead; | 44 listener.errors.add(new TestError(offset, errorCode, arguments)); |
| 45 // TODO(paulberry,ahe): Fasta includes comments directly in the token | 45 }); |
| 46 // stream, rather than pointing to them via a "precedingComment" pointer, as | |
| 47 // analyzer does. This seems like it will complicate parsing and other | |
| 48 // operations. | |
| 49 CommentToken currentCommentHead; | |
| 50 CommentToken currentCommentTail; | |
| 51 while (true) { | |
| 52 if (scanner.hasErrors && token is fasta.ErrorToken) { | |
| 53 var error = _translateErrorToken(token, source.length); | |
| 54 if (error != null) { | |
| 55 listener.errors.add(error); | |
| 56 } | |
| 57 } else if (token is fasta.StringToken && | |
| 58 token.info.kind == fasta.COMMENT_TOKEN) { | |
| 59 // TODO(paulberry,ahe): It would be nice if the scanner gave us an | |
| 60 // easier way to distinguish between the two types of comment. | |
| 61 var type = token.value.startsWith('/*') | |
| 62 ? TokenType.MULTI_LINE_COMMENT | |
| 63 : TokenType.SINGLE_LINE_COMMENT; | |
| 64 var translatedToken = | |
| 65 new CommentToken(type, token.value, token.charOffset); | |
| 66 if (currentCommentHead == null) { | |
| 67 currentCommentHead = currentCommentTail = translatedToken; | |
| 68 } else { | |
| 69 currentCommentTail.setNext(translatedToken); | |
| 70 currentCommentTail = translatedToken; | |
| 71 } | |
| 72 } else { | |
| 73 var translatedToken = toAnalyzerToken(token, currentCommentHead); | |
| 74 translatedToken.setNext(translatedToken); | |
| 75 currentCommentHead = currentCommentTail = null; | |
| 76 analyzerTokenTail.setNext(translatedToken); | |
| 77 translatedToken.previous = analyzerTokenTail; | |
| 78 analyzerTokenTail = translatedToken; | |
| 79 } | |
| 80 if (token.isEof) { | |
| 81 return analyzerTokenHead.next; | |
| 82 } | |
| 83 token = token.next; | |
| 84 } | |
| 85 } | 46 } |
| 86 | 47 |
| 87 @override | 48 @override |
| 88 @failingTest | 49 @failingTest |
| 89 void test_ampersand_ampersand_eq() { | 50 void test_ampersand_ampersand_eq() { |
| 90 // TODO(paulberry,ahe): Fasta doesn't support `&&=` yet | 51 // TODO(paulberry,ahe): Fasta doesn't support `&&=` yet |
| 91 super.test_ampersand_ampersand_eq(); | 52 super.test_ampersand_ampersand_eq(); |
| 92 } | 53 } |
| 93 | 54 |
| 94 @override | 55 @override |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 211 // TODO(paulberry,ahe): bad error recovery. | 172 // TODO(paulberry,ahe): bad error recovery. |
| 212 super.test_string_simple_unterminated_interpolation_block(); | 173 super.test_string_simple_unterminated_interpolation_block(); |
| 213 } | 174 } |
| 214 | 175 |
| 215 @override | 176 @override |
| 216 @failingTest | 177 @failingTest |
| 217 void test_string_simple_unterminated_interpolation_identifier() { | 178 void test_string_simple_unterminated_interpolation_identifier() { |
| 218 // TODO(paulberry,ahe): bad error recovery. | 179 // TODO(paulberry,ahe): bad error recovery. |
| 219 super.test_string_simple_unterminated_interpolation_identifier(); | 180 super.test_string_simple_unterminated_interpolation_identifier(); |
| 220 } | 181 } |
| 221 | |
| 222 TestError _translateErrorToken(fasta.ErrorToken token, int inputLength) { | |
| 223 int charOffset = token.charOffset; | |
| 224 // TODO(paulberry,ahe): why is endOffset sometimes null? | |
| 225 int endOffset = token.endOffset ?? charOffset; | |
| 226 TestError _makeError(ScannerErrorCode errorCode, List<Object> arguments) { | |
| 227 if (charOffset == inputLength) { | |
| 228 // Analyzer never generates an error message past the end of the input, | |
| 229 // since such an error would not be visible in an editor. | |
| 230 // TODO(paulberry,ahe): would it make sense to replicate this behavior | |
| 231 // in fasta, or move it elsewhere in analyzer? | |
| 232 charOffset--; | |
| 233 } | |
| 234 return new TestError(charOffset, errorCode, arguments); | |
| 235 } | |
| 236 | |
| 237 var errorCode = token.errorCode; | |
| 238 switch (errorCode) { | |
| 239 case fasta.ErrorKind.UnterminatedString: | |
| 240 // TODO(paulberry,ahe): Fasta reports the error location as the entire | |
| 241 // string; analyzer expects the end of the string. | |
| 242 charOffset = endOffset; | |
| 243 return _makeError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, null); | |
| 244 case fasta.ErrorKind.UnmatchedToken: | |
| 245 return null; | |
| 246 case fasta.ErrorKind.UnterminatedComment: | |
| 247 // TODO(paulberry,ahe): Fasta reports the error location as the entire | |
| 248 // comment; analyzer expects the end of the comment. | |
| 249 charOffset = endOffset; | |
| 250 return _makeError( | |
| 251 ScannerErrorCode.UNTERMINATED_MULTI_LINE_COMMENT, null); | |
| 252 case fasta.ErrorKind.MissingExponent: | |
| 253 // TODO(paulberry,ahe): Fasta reports the error location as the entire | |
| 254 // number; analyzer expects the end of the number. | |
| 255 charOffset = endOffset; | |
| 256 return _makeError(ScannerErrorCode.MISSING_DIGIT, null); | |
| 257 case fasta.ErrorKind.ExpectedHexDigit: | |
| 258 // TODO(paulberry,ahe): Fasta reports the error location as the entire | |
| 259 // number; analyzer expects the end of the number. | |
| 260 charOffset = endOffset; | |
| 261 return _makeError(ScannerErrorCode.MISSING_HEX_DIGIT, null); | |
| 262 case fasta.ErrorKind.NonAsciiIdentifier: | |
| 263 case fasta.ErrorKind.NonAsciiWhitespace: | |
| 264 return _makeError( | |
| 265 ScannerErrorCode.ILLEGAL_CHARACTER, [token.character]); | |
| 266 case fasta.ErrorKind.UnexpectedDollarInString: | |
| 267 return null; | |
| 268 default: | |
| 269 throw new UnimplementedError('$errorCode'); | |
| 270 } | |
| 271 } | |
| 272 } | 182 } |
| OLD | NEW |