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

Unified Diff: pkg/front_end/test/scanner_test.dart

Issue 2676083002: Connect fasta's scanner to the analyzer-derived scanner tests in front_end. (Closed)
Patch Set: Created 3 years, 10 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/front_end/test/scanner_test.dart
diff --git a/pkg/front_end/test/scanner_test.dart b/pkg/front_end/test/scanner_test.dart
index 69e802d3008e3b898096106cdaafabf806b56901..10c2ad11350fe9350ef35bce7663c4bbfecfb45e 100644
--- a/pkg/front_end/test/scanner_test.dart
+++ b/pkg/front_end/test/scanner_test.dart
@@ -4,6 +4,11 @@
import 'package:front_end/src/base/errors.dart';
import 'package:front_end/src/base/jenkins_smi_hash.dart';
+import 'package:front_end/src/fasta/scanner/error_token.dart' as fasta;
+import 'package:front_end/src/fasta/scanner/keyword.dart' as fasta;
+import 'package:front_end/src/fasta/scanner/string_scanner.dart' as fasta;
+import 'package:front_end/src/fasta/scanner/token.dart' as fasta;
+import 'package:front_end/src/fasta/scanner/token_constants.dart' as fasta;
import 'package:front_end/src/scanner/errors.dart';
import 'package:front_end/src/scanner/reader.dart';
import 'package:front_end/src/scanner/scanner.dart';
@@ -16,6 +21,7 @@ main() {
defineReflectiveTests(CharSequenceReaderTest);
defineReflectiveTests(KeywordStateTest);
defineReflectiveTests(ScannerTest);
Paul Berry 2017/02/03 23:10:36 Note that this test file now tests both the analyz
+ defineReflectiveTests(ScannerTest_Fasta);
defineReflectiveTests(TokenTypeTest);
});
}
@@ -113,7 +119,556 @@ class KeywordStateTest {
}
@reflectiveTest
-class ScannerTest {
+class ScannerTest extends ScannerTestBase {
+ @override
+ Token _scanWithListener(String source, _ErrorListener listener,
+ {bool genericMethodComments: false,
+ bool lazyAssignmentOperators: false}) {
+ Scanner scanner =
+ new _TestScanner(new CharSequenceReader(source), listener);
+ scanner.scanGenericMethodComments = genericMethodComments;
+ scanner.scanLazyAssignmentOperators = lazyAssignmentOperators;
+ return scanner.tokenize();
+ }
+}
+
+@reflectiveTest
+class ScannerTest_Fasta extends ScannerTestBase {
+ final _keywordMap = {
+ "assert": Keyword.ASSERT,
+ "break": Keyword.BREAK,
+ "case": Keyword.CASE,
+ "catch": Keyword.CATCH,
+ "class": Keyword.CLASS,
+ "const": Keyword.CONST,
+ "continue": Keyword.CONTINUE,
+ "default": Keyword.DEFAULT,
+ "do": Keyword.DO,
+ "else": Keyword.ELSE,
+ "enum": Keyword.ENUM,
+ "extends": Keyword.EXTENDS,
+ "false": Keyword.FALSE,
+ "final": Keyword.FINAL,
+ "finally": Keyword.FINALLY,
+ "for": Keyword.FOR,
+ "if": Keyword.IF,
+ "in": Keyword.IN,
+ "new": Keyword.NEW,
+ "null": Keyword.NULL,
+ "rethrow": Keyword.RETHROW,
+ "return": Keyword.RETURN,
+ "super": Keyword.SUPER,
+ "switch": Keyword.SWITCH,
+ "this": Keyword.THIS,
+ "throw": Keyword.THROW,
+ "true": Keyword.TRUE,
+ "try": Keyword.TRY,
+ "var": Keyword.VAR,
+ "void": Keyword.VOID,
+ "while": Keyword.WHILE,
+ "with": Keyword.WITH,
+ "is": Keyword.IS,
+ "abstract": Keyword.ABSTRACT,
+ "as": Keyword.AS,
+ "covariant": Keyword.COVARIANT,
+ "dynamic": Keyword.DYNAMIC,
+ "export": Keyword.EXPORT,
+ "external": Keyword.EXTERNAL,
+ "factory": Keyword.FACTORY,
+ "get": Keyword.GET,
+ "implements": Keyword.IMPLEMENTS,
+ "import": Keyword.IMPORT,
+ "library": Keyword.LIBRARY,
+ "operator": Keyword.OPERATOR,
+ "part": Keyword.PART,
+ "set": Keyword.SET,
+ "static": Keyword.STATIC,
+ "typedef": Keyword.TYPEDEF,
+ "deferred": Keyword.DEFERRED,
+ };
+
+ @override
+ @failingTest
Paul Berry 2017/02/03 23:10:36 Note: these overrides indicate to the test_reflect
+ void test_ampersand_ampersand_eq() {
+ // TODO(paulberry,ahe): Fasta doesn't support `&&=` yet
+ super.test_ampersand_ampersand_eq();
+ }
+
+ @override
+ @failingTest
+ void test_bar_bar_eq() {
+ // TODO(paulberry,ahe): Fasta doesn't support `||=` yet
+ super.test_bar_bar_eq();
+ }
+
+ @override
+ @failingTest
+ void test_comment_generic_method_type_assign() {
+ // TODO(paulberry,ahe): Fasta doesn't support generic method comment syntax.
ahe 2017/02/06 11:01:20 Do you think that would be necessary to support in
Paul Berry 2017/02/06 13:46:54 It's not clear at this point. I asked Dan Grove a
+ super.test_comment_generic_method_type_assign();
+ }
+
+ @override
+ @failingTest
+ void test_comment_generic_method_type_list() {
+ // TODO(paulberry,ahe): Fasta doesn't support generic method comment syntax.
+ super.test_comment_generic_method_type_list();
+ }
+
+ @override
+ @failingTest
+ void test_comment_multi_unterminated() {
+ // TODO(paulberry,ahe): see UnimplementedError("distinguish unterminated errors")
ahe 2017/02/06 11:01:20 Long line here and a few below.
Paul Berry 2017/02/06 13:46:54 Done.
+ super.test_comment_multi_unterminated();
+ }
+
+ @override
+ @failingTest
+ void test_comment_single() {
+ // TODO(paulberry,ahe): See TODO comment below in _translateTokenInfoKind().
+ super.test_comment_single();
+ }
+
+ @override
+ @failingTest
+ void test_double_missingDigitInExponent() {
+ // TODO(paulberry,ahe): see UnimplementedError("distinguish unterminated errors")
+ super.test_double_missingDigitInExponent();
+ }
+
+ @override
+ @failingTest
+ void test_hexidecimal_missingDigit() {
+ // TODO(paulberry,ahe): see UnimplementedError("distinguish unterminated errors")
+ super.test_hexidecimal_missingDigit();
+ }
+
+ @override
+ @failingTest
+ void test_index() {
+ // TODO(paulberry,ahe): "[]" should be parsed as a single token.
ahe 2017/02/04 09:48:19 Note: [] and []= are tokenized as a single token o
Paul Berry 2017/02/04 14:57:55 Interesting. The behavior of the analyzer scanner
ahe 2017/02/06 11:01:20 I agree. A corner case with the dart2js/fasta appr
Paul Berry 2017/02/06 13:46:54 SGTM.
Siggi Cherem (dart-lang) 2017/02/06 23:51:29 A small question: could we annotate somehow these
Paul Berry 2017/02/07 13:56:11 I've filed an issue: https://github.com/dart-lang/
+ super.test_index();
+ }
+
+ @override
+ @failingTest
+ void test_index_eq() {
+ // TODO(paulberry,ahe): "[]=" should be parsed as a single token.
+ super.test_index_eq();
+ }
+
+ @override
+ @failingTest
+ void test_scriptTag_withArgs() {
+ // TODO(paulberry,ahe): script tags are needed by analyzer.
+ super.test_scriptTag_withArgs();
+ }
+
+ @override
+ @failingTest
+ void test_scriptTag_withoutSpace() {
+ // TODO(paulberry,ahe): script tags are needed by analyzer.
+ super.test_scriptTag_withoutSpace();
+ }
+
+ @override
+ @failingTest
+ void test_scriptTag_withSpace() {
+ // TODO(paulberry,ahe): script tags are needed by analyzer.
+ super.test_scriptTag_withSpace();
+ }
+
+ @override
+ @failingTest
+ void test_string_multi_unterminated() {
+ // TODO(paulberry,ahe): bad error recovery.
+ super.test_string_multi_unterminated();
+ }
+
+ @override
+ @failingTest
+ void test_string_multi_unterminated_interpolation_block() {
+ // TODO(paulberry,ahe): bad error recovery.
+ super.test_string_multi_unterminated_interpolation_block();
+ }
+
+ @override
+ @failingTest
+ void test_string_multi_unterminated_interpolation_identifier() {
+ // TODO(paulberry,ahe): bad error recovery.
+ super.test_string_multi_unterminated_interpolation_identifier();
+ }
+
+ @override
+ @failingTest
+ void test_string_raw_multi_unterminated() {
+ // TODO(paulberry,ahe): bad error recovery.
+ super.test_string_raw_multi_unterminated();
+ }
+
+ @override
+ @failingTest
+ void test_string_raw_simple_unterminated_eof() {
+ // TODO(paulberry,ahe): bad error recovery.
+ super.test_string_raw_simple_unterminated_eof();
+ }
+
+ @override
+ @failingTest
+ void test_string_raw_simple_unterminated_eol() {
+ // TODO(paulberry,ahe): bad error recovery.
+ super.test_string_raw_simple_unterminated_eol();
+ }
+
+ @override
+ @failingTest
+ void test_string_simple_interpolation_missingIdentifier() {
+ // TODO(paulberry,ahe): bad error recovery.
+ super.test_string_simple_interpolation_missingIdentifier();
+ }
+
+ @override
+ @failingTest
+ void test_string_simple_interpolation_nonIdentifier() {
+ // TODO(paulberry,ahe): bad error recovery.
+ super.test_string_simple_interpolation_nonIdentifier();
+ }
+
+ @override
+ @failingTest
+ void test_string_simple_unterminated_eof() {
+ // TODO(paulberry,ahe): bad error recovery.
+ super.test_string_simple_unterminated_eof();
+ }
+
+ @override
+ @failingTest
+ void test_string_simple_unterminated_eol() {
+ // TODO(paulberry,ahe): bad error recovery.
+ super.test_string_simple_unterminated_eol();
+ }
+
+ @override
+ @failingTest
+ void test_string_simple_unterminated_interpolation_block() {
+ // TODO(paulberry,ahe): bad error recovery.
+ super.test_string_simple_unterminated_interpolation_block();
+ }
+
+ @override
+ @failingTest
+ void test_string_simple_unterminated_interpolation_identifier() {
+ // TODO(paulberry,ahe): bad error recovery.
+ super.test_string_simple_unterminated_interpolation_identifier();
+ }
+
+ @override
+ Token _scanWithListener(String source, _ErrorListener listener,
+ {bool genericMethodComments: false,
+ bool lazyAssignmentOperators: false}) {
+ if (genericMethodComments) {
+ // Fasta doesn't support generic method comments.
+ // TODO(paulberry): once the analyzer toolchain no longer needs generic
+ // method comments, remove tests that exercise them.
+ fail('No generic method comment support in Fasta');
+ }
+ // Note: Fasta always supports lazy assignment operators (`&&=` and `||=`),
+ // so we can ignore the `lazyAssignmentOperators` flag.
+ // TODO(paulberry): once lazyAssignmentOperators are fully supported by
+ // Dart, remove this flag.
+ var scanner = new fasta.StringScanner(source, includeComments: true);
+ var token = scanner.tokenize();
+ var analyzerTokenHead = new Token(null, 0);
+ analyzerTokenHead.previous = analyzerTokenHead;
+ var analyzerTokenTail = analyzerTokenHead;
+ // TODO(paulberry,ahe): Fasta includes comments directly in the token
+ // stream, rather than pointing to them via a "precedingComment" pointer, as
+ // analyzer does. This seems like it will complicate parsing and other
+ // operations.
+ CommentToken currentCommentHead;
+ CommentToken currentCommentTail;
+ while (true) {
+ if (token is fasta.ErrorToken) {
+ var error = _translateErrorToken(token, source.length);
+ if (error != null) {
+ listener.errors.add(error);
+ }
+ } else if (token is fasta.StringToken &&
+ token.info.kind == fasta.COMMENT_TOKEN) {
+ var translatedToken = _translateToken(token, null) as CommentToken;
+ if (currentCommentHead == null) {
+ currentCommentHead = currentCommentTail = translatedToken;
+ } else {
+ currentCommentTail.setNext(translatedToken);
+ currentCommentTail = translatedToken;
+ }
+ } else {
+ var translatedToken = _translateToken(token, currentCommentHead);
+ translatedToken.setNext(translatedToken);
+ currentCommentHead = currentCommentTail = null;
+ analyzerTokenTail.setNext(translatedToken);
+ translatedToken.previous = analyzerTokenTail;
+ analyzerTokenTail = translatedToken;
+ }
+ if (token.isEof) {
+ return analyzerTokenHead.next;
+ }
+ token = token.next;
+ }
+ }
+
+ _TestError _translateErrorToken(fasta.ErrorToken token, int inputLength) {
+ int charOffset = token.charOffset;
+ // TODO(paulberry,ahe): why is endOffset sometimes null?
+ int endOffset = token.endOffset ?? charOffset;
+ _TestError _makeError(ScannerErrorCode errorCode, List<Object> arguments) {
+ int errorLength = endOffset - charOffset;
+ if (charOffset == inputLength) {
+ // Analyzer never generates an error message past the end of the input,
+ // since such an error would not be visible in an editor.
+ // TODO(paulberry,ahe): would it make sense to replicate this behavior
+ // in fasta, or move it elsewhere in analyzer?
+ charOffset--;
+ }
+ if (errorLength == 0) {
+ // Analyzer never generates an error message of length zero,
+ // since such an error would not be visible in an editor.
+ // TODO(paulberry,ahe): would it make sense to replicate this behavior
+ // in fasta, or move it elsewhere in analyzer?
+ errorLength = 1;
+ }
+ return new _TestError(charOffset, errorLength, errorCode, arguments);
+ }
+
+ if (token is fasta.UnterminatedToken) {
+ // TODO(paulberry,ahe): How to tell what kind of error to
+ // report? It could be ScannerErrorCode.UNTERMINATED_STRING_LITERAL,
+ // ScannerErrorCode.MISSING_HEX_DIGIT, or
+ // ScannerErrorCode.UNTERMINATED_MULTI_LINE_COMMENT
ahe 2017/02/04 09:48:19 Absolutely. Just this week, I was thinking about c
Paul Berry 2017/02/04 14:57:55 Aha, thank you. I failed to notice the presence o
ahe 2017/02/06 11:01:20 We should be careful about polymorphism, but in th
Paul Berry 2017/02/06 13:46:54 Aha, nice. When I do my rework of this code (whic
+ return _makeError(
+ throw new UnimplementedError("distinguish unterminated errors"),
+ null);
+ } else if (token is fasta.UnmatchedToken) {
+ return null;
+ } else if (token is fasta.NonAsciiIdentifierToken) {
+ return _makeError(ScannerErrorCode.ILLEGAL_CHARACTER, [token.character]);
+ } else if (token is fasta.NonAsciiWhitespaceToken) {
+ return _makeError(ScannerErrorCode.ILLEGAL_CHARACTER, [token.character]);
+ }
+ throw new UnimplementedError('${token.runtimeType}');
+ }
+
+ Keyword _translateKeyword(String syntax) =>
+ _keywordMap[syntax] ?? (throw new UnimplementedError('$syntax'));
+
+ Token _translateToken(fasta.Token token, CommentToken comment) {
+ var type = _translateTokenInfoKind(token.info.kind);
+ int offset = token.charOffset;
+ Token makeStringToken(String value) {
+ if (comment == null) {
+ return new StringToken(type, value, offset);
+ } else {
+ return new StringTokenWithComment(type, value, offset, comment);
+ }
+ }
+
+ Token makeKeywordToken(Keyword keyword) {
+ if (comment == null) {
+ return new KeywordToken(keyword, offset);
+ } else {
+ return new KeywordTokenWithComment(keyword, offset, comment);
+ }
+ }
+
+ Token makeBeginToken() {
+ if (comment == null) {
+ return new BeginToken(type, offset);
+ } else {
+ return new BeginTokenWithComment(type, offset, comment);
+ }
+ }
+
+ Token makeCommentToken() {
+ return new CommentToken(type, token.value, offset);
+ }
+
+ if (token is fasta.StringToken) {
+ if (token.info.kind == fasta.COMMENT_TOKEN) {
+ return makeCommentToken();
+ } else {
+ return makeStringToken(token.value);
+ }
+ } else if (token is fasta.KeywordToken) {
+ return makeKeywordToken(_translateKeyword(token.keyword.syntax));
+ } else if (token is fasta.SymbolToken) {
+ if (token is fasta.BeginGroupToken) {
+ if (type == TokenType.LT) {
+ return makeStringToken(token.value);
+ } else {
+ return makeBeginToken();
+ }
+ } else {
+ return makeStringToken(token.value);
+ }
+ }
+ throw new UnimplementedError('${token.runtimeType}');
+ }
+
+ TokenType _translateTokenInfoKind(int kind) {
+ switch (kind) {
+ case fasta.EOF_TOKEN:
+ return TokenType.EOF;
+ case fasta.KEYWORD_TOKEN:
+ return TokenType.KEYWORD;
+ case fasta.IDENTIFIER_TOKEN:
+ return TokenType.IDENTIFIER;
+ case fasta.BAD_INPUT_TOKEN:
+ return TokenType.STRING;
+ case fasta.DOUBLE_TOKEN:
+ return TokenType.DOUBLE;
+ case fasta.INT_TOKEN:
+ return TokenType.INT;
+ case fasta.HEXADECIMAL_TOKEN:
+ return TokenType.HEXADECIMAL;
+ case fasta.STRING_TOKEN:
+ return TokenType.STRING;
+ case fasta.AMPERSAND_TOKEN:
+ return TokenType.AMPERSAND;
+ case fasta.BACKPING_TOKEN:
+ return TokenType.BACKPING;
+ case fasta.BACKSLASH_TOKEN:
+ return TokenType.BACKSLASH;
+ case fasta.BANG_TOKEN:
+ return TokenType.BANG;
+ case fasta.BAR_TOKEN:
+ return TokenType.BAR;
+ case fasta.COLON_TOKEN:
+ return TokenType.COLON;
+ case fasta.COMMA_TOKEN:
+ return TokenType.COMMA;
+ case fasta.EQ_TOKEN:
+ return TokenType.EQ;
+ case fasta.GT_TOKEN:
+ return TokenType.GT;
+ case fasta.HASH_TOKEN:
+ return TokenType.HASH;
+ case fasta.OPEN_CURLY_BRACKET_TOKEN:
+ return TokenType.OPEN_CURLY_BRACKET;
+ case fasta.OPEN_SQUARE_BRACKET_TOKEN:
+ return TokenType.OPEN_SQUARE_BRACKET;
+ case fasta.OPEN_PAREN_TOKEN:
+ return TokenType.OPEN_PAREN;
+ case fasta.LT_TOKEN:
+ return TokenType.LT;
+ case fasta.MINUS_TOKEN:
+ return TokenType.MINUS;
+ case fasta.PERIOD_TOKEN:
+ return TokenType.PERIOD;
+ case fasta.PLUS_TOKEN:
+ return TokenType.PLUS;
+ case fasta.QUESTION_TOKEN:
+ return TokenType.QUESTION;
+ case fasta.AT_TOKEN:
+ return TokenType.AT;
+ case fasta.CLOSE_CURLY_BRACKET_TOKEN:
+ return TokenType.CLOSE_CURLY_BRACKET;
+ case fasta.CLOSE_SQUARE_BRACKET_TOKEN:
+ return TokenType.CLOSE_SQUARE_BRACKET;
+ case fasta.CLOSE_PAREN_TOKEN:
+ return TokenType.CLOSE_PAREN;
+ case fasta.SEMICOLON_TOKEN:
+ return TokenType.SEMICOLON;
+ case fasta.SLASH_TOKEN:
+ return TokenType.SLASH;
+ case fasta.TILDE_TOKEN:
+ return TokenType.TILDE;
+ case fasta.STAR_TOKEN:
+ return TokenType.STAR;
+ case fasta.PERCENT_TOKEN:
+ return TokenType.PERCENT;
+ case fasta.CARET_TOKEN:
+ return TokenType.CARET;
+ case fasta.STRING_INTERPOLATION_TOKEN:
+ return TokenType.STRING_INTERPOLATION_EXPRESSION;
+ case fasta.LT_EQ_TOKEN:
+ return TokenType.LT_EQ;
+ case fasta.FUNCTION_TOKEN:
+ return TokenType.FUNCTION;
+ case fasta.SLASH_EQ_TOKEN:
+ return TokenType.SLASH_EQ;
+ case fasta.PERIOD_PERIOD_PERIOD_TOKEN:
+ return TokenType.PERIOD_PERIOD_PERIOD;
+ case fasta.PERIOD_PERIOD_TOKEN:
+ return TokenType.PERIOD_PERIOD;
+ case fasta.EQ_EQ_EQ_TOKEN:
+ // TODO(paulberry,ahe): what is this?
+ throw new UnimplementedError();
+ case fasta.EQ_EQ_TOKEN:
+ return TokenType.EQ_EQ;
+ case fasta.LT_LT_EQ_TOKEN:
+ return TokenType.LT_LT_EQ;
+ case fasta.LT_LT_TOKEN:
+ return TokenType.LT_LT;
+ case fasta.GT_EQ_TOKEN:
+ return TokenType.GT_EQ;
+ case fasta.GT_GT_EQ_TOKEN:
+ return TokenType.GT_GT_EQ;
+ case fasta.INDEX_EQ_TOKEN:
+ return TokenType.INDEX_EQ;
+ case fasta.INDEX_TOKEN:
+ return TokenType.INDEX;
+ case fasta.BANG_EQ_EQ_TOKEN:
+ // TODO(paulberry,ahe): what is this?
+ throw new UnimplementedError();
+ case fasta.BANG_EQ_TOKEN:
+ return TokenType.BANG_EQ;
+ case fasta.AMPERSAND_AMPERSAND_TOKEN:
+ return TokenType.AMPERSAND_AMPERSAND;
+ case fasta.AMPERSAND_EQ_TOKEN:
+ return TokenType.AMPERSAND_EQ;
+ case fasta.BAR_BAR_TOKEN:
+ return TokenType.BAR_BAR;
+ case fasta.BAR_EQ_TOKEN:
+ return TokenType.BAR_EQ;
+ case fasta.STAR_EQ_TOKEN:
+ return TokenType.STAR_EQ;
+ case fasta.PLUS_PLUS_TOKEN:
+ return TokenType.PLUS_PLUS;
+ case fasta.PLUS_EQ_TOKEN:
+ return TokenType.PLUS_EQ;
+ case fasta.MINUS_MINUS_TOKEN:
+ return TokenType.MINUS_MINUS;
+ case fasta.MINUS_EQ_TOKEN:
+ return TokenType.MINUS_EQ;
+ case fasta.TILDE_SLASH_EQ_TOKEN:
+ return TokenType.TILDE_SLASH_EQ;
+ case fasta.TILDE_SLASH_TOKEN:
+ return TokenType.TILDE_SLASH;
+ case fasta.PERCENT_EQ_TOKEN:
+ return TokenType.PERCENT_EQ;
+ case fasta.GT_GT_TOKEN:
+ return TokenType.GT_GT;
+ case fasta.CARET_EQ_TOKEN:
+ return TokenType.CARET_EQ;
+ case fasta.COMMENT_TOKEN:
+ // TODO(paulberry,ahe): how to distinguish multi-line from
+ // single-line comments? Causes a failure in test_comment_single().
ahe 2017/02/06 11:01:20 I'd just look at the first two characters of the c
Paul Berry 2017/02/06 13:46:54 Ok. I'll make a follow-up CL that adjusts this co
+ return TokenType.MULTI_LINE_COMMENT;
+ case fasta.STRING_INTERPOLATION_IDENTIFIER_TOKEN:
+ return TokenType.STRING_INTERPOLATION_IDENTIFIER;
+ case fasta.QUESTION_PERIOD_TOKEN:
+ return TokenType.QUESTION_PERIOD;
+ case fasta.QUESTION_QUESTION_TOKEN:
+ return TokenType.QUESTION_QUESTION;
+ case fasta.QUESTION_QUESTION_EQ_TOKEN:
+ return TokenType.QUESTION_QUESTION_EQ;
+ default:
+ throw new UnimplementedError('$kind');
+ }
+ }
+}
+
+abstract class ScannerTestBase {
void fail_incomplete_string_interpolation() {
// https://code.google.com/p/dart/issues/detail?id=18073
_assertErrorAndTokens(
@@ -230,6 +785,36 @@ class ScannerTest {
_assertComment(TokenType.MULTI_LINE_COMMENT, "/* comment */");
}
+ void test_comment_multi_consecutive_2() {
Paul Berry 2017/02/03 23:10:36 Note: during this process I discovered that consec
+ Token token = _scan("/* x */ /* y */ z");
+ expect(token.type, TokenType.IDENTIFIER);
+ expect(token.precedingComments, isNotNull);
+ expect(token.precedingComments.value(), "/* x */");
+ expect(token.precedingComments.previous, isNull);
+ expect(token.precedingComments.next, isNotNull);
+ expect(token.precedingComments.next.value(), "/* y */");
+ expect(
+ token.precedingComments.next.previous, same(token.precedingComments));
+ expect(token.precedingComments.next.next, isNull);
+ }
+
+ void test_comment_multi_consecutive_3() {
+ Token token = _scan("/* x */ /* y */ /* z */ a");
+ expect(token.type, TokenType.IDENTIFIER);
+ expect(token.precedingComments, isNotNull);
+ expect(token.precedingComments.value(), "/* x */");
+ expect(token.precedingComments.previous, isNull);
+ expect(token.precedingComments.next, isNotNull);
+ expect(token.precedingComments.next.value(), "/* y */");
+ expect(
+ token.precedingComments.next.previous, same(token.precedingComments));
+ expect(token.precedingComments.next.next, isNotNull);
+ expect(token.precedingComments.next.next.value(), "/* z */");
+ expect(token.precedingComments.next.next.previous,
+ same(token.precedingComments.next));
+ expect(token.precedingComments.next.next.next, isNull);
+ }
+
void test_comment_multi_lineEnds() {
String code = r'''
/**
@@ -1149,14 +1734,7 @@ class ScannerTest {
}
Token _scanWithListener(String source, _ErrorListener listener,
- {bool genericMethodComments: false,
- bool lazyAssignmentOperators: false}) {
- Scanner scanner =
- new _TestScanner(new CharSequenceReader(source), listener);
- scanner.scanGenericMethodComments = genericMethodComments;
- scanner.scanLazyAssignmentOperators = lazyAssignmentOperators;
- return scanner.tokenize();
- }
+ {bool genericMethodComments: false, bool lazyAssignmentOperators: false});
}
@reflectiveTest
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698