| // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| import 'package:front_end/src/fasta/analyzer/token_utils.dart'; |
| import 'package:front_end/src/fasta/scanner/precedence.dart'; |
| import 'package:front_end/src/scanner/token.dart'; |
| import 'package:front_end/src/fasta/scanner/string_scanner.dart'; |
| import 'package:test/test.dart'; |
| import 'package:test_reflective_loader/test_reflective_loader.dart'; |
| |
| import 'scanner_fasta_test.dart'; |
| import 'scanner_test.dart'; |
| |
| main() { |
| defineReflectiveSuite(() { |
| defineReflectiveTests(ScannerTest_RoundTrip); |
| }); |
| } |
| |
| /// Scanner tests that use the analyzer scanner, then convert the resulting |
| /// token stream into a Fasta token stream, then convert back to an analyzer |
| /// token stream before verifying assertions. |
| /// |
| /// These tests help to validate the correctness of the analyzer->Fasta token |
| /// stream conversion. |
| @reflectiveTest |
| class ScannerTest_RoundTrip extends ScannerTest { |
| @override |
| Token scanWithListener(String source, ErrorListener listener, |
| {bool genericMethodComments: false, |
| bool lazyAssignmentOperators: false}) { |
| var analyzerToken = super.scanWithListener(source, listener, |
| genericMethodComments: genericMethodComments, |
| lazyAssignmentOperators: lazyAssignmentOperators); |
| var fastaToken = fromAnalyzerTokenStream(analyzerToken); |
| // Since [scanWithListener] reports errors to the listener, we don't |
| // expect any error tokens in the Fasta token stream, so we convert using |
| // ToAnalyzerTokenStreamConverter_NoErrors. |
| return new ToAnalyzerTokenStreamConverter_NoErrors() |
| .convertTokens(fastaToken); |
| } |
| |
| @override |
| @failingTest |
| void test_ampersand_ampersand_eq() { |
| // TODO(paulberry,ahe): Fasta scanner doesn't support lazy assignment |
| // operators. |
| super.test_ampersand_ampersand_eq(); |
| } |
| |
| @override |
| @failingTest |
| void test_bar_bar_eq() { |
| // TODO(paulberry,ahe): Fasta scanner doesn't support lazy assignment |
| // operators. |
| super.test_bar_bar_eq(); |
| } |
| |
| @override |
| @failingTest |
| void test_comment_generic_method_type_assign() { |
| // TODO(paulberry,ahe): Fasta scanner doesn't support generic comment |
| // syntax. |
| super.test_comment_generic_method_type_assign(); |
| } |
| |
| @override |
| @failingTest |
| void test_comment_generic_method_type_list() { |
| // TODO(paulberry,ahe): Fasta scanner doesn't support generic comment |
| // syntax. |
| super.test_comment_generic_method_type_list(); |
| } |
| |
| @override |
| @failingTest |
| void test_scriptTag_withArgs() { |
| // TODO(paulberry,ahe): Fasta scanner doesn't support script tag |
| super.test_scriptTag_withArgs(); |
| } |
| |
| @override |
| @failingTest |
| void test_scriptTag_withoutSpace() { |
| // TODO(paulberry,ahe): Fasta scanner doesn't support script tag |
| super.test_scriptTag_withoutSpace(); |
| } |
| |
| @override |
| @failingTest |
| void test_scriptTag_withSpace() { |
| // TODO(paulberry,ahe): Fasta scanner doesn't support script tag |
| super.test_scriptTag_withSpace(); |
| } |
| |
| void test_pseudo_keywords() { |
| var pseudoAnalyzerKeywords = new Set<Keyword>.from([ |
| Keyword.ABSTRACT, |
| Keyword.AS, |
| Keyword.COVARIANT, |
| Keyword.DEFERRED, |
| Keyword.DYNAMIC, |
| Keyword.EXPORT, |
| Keyword.EXTERNAL, |
| Keyword.FACTORY, |
| Keyword.GET, |
| Keyword.IMPLEMENTS, |
| Keyword.IMPORT, |
| Keyword.LIBRARY, |
| Keyword.OPERATOR, |
| Keyword.PART, |
| Keyword.SET, |
| Keyword.STATIC, |
| Keyword.TYPEDEF, |
| ]); |
| for (Keyword keyword in Keyword.values) { |
| expect(keyword.isPseudoKeyword, pseudoAnalyzerKeywords.contains(keyword), |
| reason: keyword.name); |
| } |
| } |
| |
| var allTokenTypes = new Set<TokenType>.from([ |
| TokenType.EOF, |
| TokenType.DOUBLE, |
| TokenType.HEXADECIMAL, |
| TokenType.IDENTIFIER, |
| TokenType.INT, |
| TokenType.KEYWORD, |
| TokenType.MULTI_LINE_COMMENT, |
| TokenType.SCRIPT_TAG, |
| TokenType.SINGLE_LINE_COMMENT, |
| TokenType.STRING, |
| TokenType.AMPERSAND, |
| TokenType.AMPERSAND_AMPERSAND, |
| TokenType.AMPERSAND_AMPERSAND_EQ, |
| TokenType.AMPERSAND_EQ, |
| TokenType.AT, |
| TokenType.BANG, |
| TokenType.BANG_EQ, |
| TokenType.BAR, |
| TokenType.BAR_BAR, |
| TokenType.BAR_BAR_EQ, |
| TokenType.BAR_EQ, |
| TokenType.COLON, |
| TokenType.COMMA, |
| TokenType.CARET, |
| TokenType.CARET_EQ, |
| TokenType.CLOSE_CURLY_BRACKET, |
| TokenType.CLOSE_PAREN, |
| TokenType.CLOSE_SQUARE_BRACKET, |
| TokenType.EQ, |
| TokenType.EQ_EQ, |
| TokenType.FUNCTION, |
| TokenType.GT, |
| TokenType.GT_EQ, |
| TokenType.GT_GT, |
| TokenType.GT_GT_EQ, |
| TokenType.HASH, |
| TokenType.INDEX, |
| TokenType.INDEX_EQ, |
| TokenType.LT, |
| TokenType.LT_EQ, |
| TokenType.LT_LT, |
| TokenType.LT_LT_EQ, |
| TokenType.MINUS, |
| TokenType.MINUS_EQ, |
| TokenType.MINUS_MINUS, |
| TokenType.OPEN_CURLY_BRACKET, |
| TokenType.OPEN_PAREN, |
| TokenType.OPEN_SQUARE_BRACKET, |
| TokenType.PERCENT, |
| TokenType.PERCENT_EQ, |
| TokenType.PERIOD, |
| TokenType.PERIOD_PERIOD, |
| TokenType.PLUS, |
| TokenType.PLUS_EQ, |
| TokenType.PLUS_PLUS, |
| TokenType.QUESTION, |
| TokenType.QUESTION_PERIOD, |
| TokenType.QUESTION_QUESTION, |
| TokenType.QUESTION_QUESTION_EQ, |
| TokenType.SEMICOLON, |
| TokenType.SLASH, |
| TokenType.SLASH_EQ, |
| TokenType.STAR, |
| TokenType.STAR_EQ, |
| TokenType.STRING_INTERPOLATION_EXPRESSION, |
| TokenType.STRING_INTERPOLATION_IDENTIFIER, |
| TokenType.TILDE, |
| TokenType.TILDE_SLASH, |
| TokenType.TILDE_SLASH_EQ, |
| TokenType.BACKPING, |
| TokenType.BACKSLASH, |
| TokenType.PERIOD_PERIOD_PERIOD, |
| TokenType.GENERIC_METHOD_TYPE_LIST, |
| TokenType.GENERIC_METHOD_TYPE_ASSIGN, |
| ]); |
| |
| void test_isOperator() { |
| var operatorTokenTypes = new Set<TokenType>.from([ |
| TokenType.AMPERSAND, |
| TokenType.AMPERSAND_AMPERSAND, |
| TokenType.AMPERSAND_AMPERSAND_EQ, |
| TokenType.AMPERSAND_EQ, |
| TokenType.BANG, |
| TokenType.BANG_EQ, |
| TokenType.BAR, |
| TokenType.BAR_BAR, |
| TokenType.BAR_BAR_EQ, |
| TokenType.BAR_EQ, |
| TokenType.CARET, |
| TokenType.CARET_EQ, |
| TokenType.EQ, |
| TokenType.EQ_EQ, |
| TokenType.GT, |
| TokenType.GT_EQ, |
| TokenType.GT_GT, |
| TokenType.GT_GT_EQ, |
| TokenType.INDEX, |
| TokenType.INDEX_EQ, |
| TokenType.LT, |
| TokenType.LT_EQ, |
| TokenType.LT_LT, |
| TokenType.LT_LT_EQ, |
| TokenType.MINUS, |
| TokenType.MINUS_EQ, |
| TokenType.MINUS_MINUS, |
| TokenType.PERCENT, |
| TokenType.PERCENT_EQ, |
| TokenType.PERIOD_PERIOD, |
| TokenType.PLUS, |
| TokenType.PLUS_EQ, |
| TokenType.PLUS_PLUS, |
| TokenType.QUESTION, |
| TokenType.QUESTION_PERIOD, |
| TokenType.QUESTION_QUESTION, |
| TokenType.QUESTION_QUESTION_EQ, |
| TokenType.SLASH, |
| TokenType.SLASH_EQ, |
| TokenType.STAR, |
| TokenType.STAR_EQ, |
| TokenType.TILDE, |
| TokenType.TILDE_SLASH, |
| TokenType.TILDE_SLASH_EQ, |
| ]); |
| |
| void assertIsOperator(String source, bool isOperator) { |
| if (source == null || source.isEmpty) return; |
| var scanner = new StringScanner(source, includeComments: true); |
| var token = scanner.tokenize(); |
| expect(token.isOperator, isOperator, reason: source); |
| } |
| |
| var operatorLexemes = |
| new Set.from(operatorTokenTypes.map((tt) => tt.lexeme)); |
| |
| for (PrecedenceInfo info in PrecedenceInfo.all) { |
| assertIsOperator(info.value, operatorLexemes.contains(info.value)); |
| } |
| |
| for (TokenType tt in new List.from(allTokenTypes)) { |
| assertIsOperator(tt.lexeme, operatorTokenTypes.contains(tt)); |
| } |
| } |
| } |