| 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 'dart:convert' show UTF8; | 5 import 'dart:convert' show UTF8; |
| 6 | 6 |
| 7 import 'package:front_end/src/fasta/scanner/recover.dart' | 7 import 'package:front_end/src/fasta/scanner/recover.dart' |
| 8 show defaultRecoveryStrategy; | 8 show defaultRecoveryStrategy; |
| 9 import 'package:front_end/src/fasta/scanner.dart' as fasta; | 9 import 'package:front_end/src/fasta/scanner.dart' as fasta; |
| 10 import 'package:front_end/src/fasta/scanner/token.dart' as fasta; | 10 import 'package:front_end/src/fasta/scanner/token.dart' as fasta; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 | 70 |
| 71 void _assertOpenClosePair(String source) { | 71 void _assertOpenClosePair(String source) { |
| 72 analyzer.BeginToken open = _scan(source); | 72 analyzer.BeginToken open = _scan(source); |
| 73 fasta.Token close = open.next; | 73 fasta.Token close = open.next; |
| 74 expect(close.next.isEof, isTrue); | 74 expect(close.next.isEof, isTrue); |
| 75 expect(open.endGroup, close); | 75 expect(open.endGroup, close); |
| 76 expect(open.isSynthetic, isFalse); | 76 expect(open.isSynthetic, isFalse); |
| 77 expect(close.isSynthetic, isFalse); | 77 expect(close.isSynthetic, isFalse); |
| 78 } | 78 } |
| 79 | 79 |
| 80 void _assertOpenOnly(String source) { | 80 void _assertOpenOnly(String source, String expectedCloser) { |
| 81 analyzer.BeginToken open = _scan(source); | 81 ErrorListener listener = new ErrorListener(); |
| 82 analyzer.BeginToken open = scanWithListener(source, listener); |
| 82 fasta.Token close = open.next; | 83 fasta.Token close = open.next; |
| 83 expect(close.next.isEof, isTrue); | 84 expect(close.next.isEof, isTrue); |
| 84 expect(open.endGroup, close); | 85 expect(open.endGroup, close); |
| 85 expect(open.isSynthetic, isFalse); | 86 expect(open.isSynthetic, isFalse); |
| 86 expect(close.isSynthetic, isTrue); | 87 expect(close.isSynthetic, isTrue); |
| 88 listener.assertErrors([ |
| 89 new TestError(0, ScannerErrorCode.EXPECTED_TOKEN, [expectedCloser]), |
| 90 ]); |
| 87 } | 91 } |
| 88 | 92 |
| 89 void test_lt() { | 93 void test_lt() { |
| 90 // fasta does not automatically insert a closer for '<' | 94 // fasta does not automatically insert a closer for '<' |
| 91 // because it could be part of an expression rather than an opener | 95 // because it could be part of an expression rather than an opener |
| 92 analyzer.BeginToken lt = _scan('<'); | 96 analyzer.BeginToken lt = _scan('<'); |
| 93 expect(lt.next.isEof, isTrue); | 97 expect(lt.next.isEof, isTrue); |
| 94 expect(lt.isSynthetic, isFalse); | 98 expect(lt.isSynthetic, isFalse); |
| 95 } | 99 } |
| 96 | 100 |
| 97 void test_lt_gt() { | 101 void test_lt_gt() { |
| 98 _assertOpenClosePair('< >'); | 102 _assertOpenClosePair('< >'); |
| 99 } | 103 } |
| 100 | 104 |
| 101 @override | 105 @override |
| 102 void test_open_curly_bracket() { | 106 void test_open_curly_bracket() { |
| 103 _assertOpenOnly('{'); | 107 _assertOpenOnly('{', '}'); |
| 104 } | 108 } |
| 105 | 109 |
| 106 void test_open_curly_bracket_with_close() { | 110 void test_open_curly_bracket_with_close() { |
| 107 _assertOpenClosePair('{ }'); | 111 _assertOpenClosePair('{ }'); |
| 108 } | 112 } |
| 109 | 113 |
| 110 void test_open_paren() { | 114 void test_open_paren() { |
| 111 _assertOpenOnly('('); | 115 _assertOpenOnly('(', ')'); |
| 112 } | 116 } |
| 113 | 117 |
| 114 void test_open_paren_with_close() { | 118 void test_open_paren_with_close() { |
| 115 _assertOpenClosePair('( )'); | 119 _assertOpenClosePair('( )'); |
| 116 } | 120 } |
| 117 | 121 |
| 118 void test_open_square_bracket() { | 122 void test_open_square_bracket() { |
| 119 _assertOpenOnly('['); | 123 _assertOpenOnly('[', ']'); |
| 120 } | 124 } |
| 121 | 125 |
| 122 void test_open_square_bracket_with_close() { | 126 void test_open_square_bracket_with_close() { |
| 123 _assertOpenClosePair('[ ]'); | 127 _assertOpenClosePair('[ ]'); |
| 124 } | 128 } |
| 125 | 129 |
| 126 @override | 130 @override |
| 127 void test_mismatched_opener_in_interpolation() { | 131 void test_mismatched_opener_in_interpolation() { |
| 128 // When openers and closers are mismatched, | 132 // When openers and closers are mismatched, |
| 129 // fasta favors considering the opener to be mismatched | 133 // fasta favors considering the opener to be mismatched |
| 130 // and inserts synthetic closers as needed. | 134 // and inserts synthetic closers as needed. |
| 131 // r'"${({(}}"' is parsed as r'"${({()})}"' | 135 // r'"${({(}}"' is parsed as r'"${({()})}"' |
| 132 // where both ')' are synthetic | 136 // where both ')' are synthetic |
| 133 var stringStart = _scan(r'"${({(}}"'); | 137 ErrorListener listener = new ErrorListener(); |
| 134 var interpolationStart = stringStart.next as analyzer.BeginToken; | 138 var stringStart = scanWithListener(r'"${({(}}"', listener); |
| 135 var openParen1 = interpolationStart.next as analyzer.BeginToken; | 139 analyzer.BeginToken interpolationStart = stringStart.next; |
| 136 var openBrace = openParen1.next as analyzer.BeginToken; | 140 analyzer.BeginToken openParen1 = interpolationStart.next; |
| 137 var openParen2 = openBrace.next as analyzer.BeginToken; | 141 analyzer.BeginToken openBrace = openParen1.next; |
| 142 analyzer.BeginToken openParen2 = openBrace.next; |
| 138 var closeParen2 = openParen2.next; | 143 var closeParen2 = openParen2.next; |
| 139 var closeBrace = closeParen2.next; | 144 var closeBrace = closeParen2.next; |
| 140 var closeParen1 = closeBrace.next; | 145 var closeParen1 = closeBrace.next; |
| 141 var interpolationEnd = closeParen1.next; | 146 var interpolationEnd = closeParen1.next; |
| 142 var stringEnd = interpolationEnd.next; | 147 var stringEnd = interpolationEnd.next; |
| 143 var eof = stringEnd.next; | 148 var eof = stringEnd.next; |
| 144 | 149 |
| 145 expect(interpolationStart.endToken, same(interpolationEnd)); | 150 expect(interpolationStart.endToken, same(interpolationEnd)); |
| 146 expect(interpolationEnd.isSynthetic, isFalse); | 151 expect(interpolationEnd.isSynthetic, isFalse); |
| 147 expect(openParen1.endToken, same(closeParen1)); | 152 expect(openParen1.endToken, same(closeParen1)); |
| 148 expect(closeParen1.isSynthetic, isTrue); | 153 expect(closeParen1.isSynthetic, isTrue); |
| 149 expect(openBrace.endToken, same(closeBrace)); | 154 expect(openBrace.endToken, same(closeBrace)); |
| 150 expect(closeBrace.isSynthetic, isFalse); | 155 expect(closeBrace.isSynthetic, isFalse); |
| 151 expect(openParen2.endToken, same(closeParen2)); | 156 expect(openParen2.endToken, same(closeParen2)); |
| 152 expect(closeParen2.isSynthetic, isTrue); | 157 expect(closeParen2.isSynthetic, isTrue); |
| 153 expect(eof.isEof, isTrue); | 158 expect(eof.isEof, isTrue); |
| 159 listener.assertErrors([ |
| 160 new TestError(3, ScannerErrorCode.EXPECTED_TOKEN, [')']), |
| 161 new TestError(5, ScannerErrorCode.EXPECTED_TOKEN, [')']), |
| 162 ]); |
| 154 } | 163 } |
| 155 | 164 |
| 156 @override | 165 @override |
| 157 void test_unmatched_openers() { | 166 void test_unmatched_openers() { |
| 167 ErrorListener listener = new ErrorListener(); |
| 158 // fasta inserts missing closers except for '<' | 168 // fasta inserts missing closers except for '<' |
| 159 var openBrace = _scan('{[(<') as analyzer.BeginToken; | 169 analyzer.BeginToken openBrace = scanWithListener('{[(<', listener); |
| 160 var openBracket = openBrace.next as analyzer.BeginToken; | 170 analyzer.BeginToken openBracket = openBrace.next; |
| 161 var openParen = openBracket.next as analyzer.BeginToken; | 171 analyzer.BeginToken openParen = openBracket.next; |
| 162 var openLT = openParen.next as analyzer.BeginToken; | 172 analyzer.BeginToken openLT = openParen.next; |
| 163 var closeParen = openLT.next; | 173 var closeParen = openLT.next; |
| 164 var closeBracket = closeParen.next; | 174 var closeBracket = closeParen.next; |
| 165 var closeBrace = closeBracket.next; | 175 var closeBrace = closeBracket.next; |
| 166 var eof = closeBrace.next; | 176 var eof = closeBrace.next; |
| 167 | 177 |
| 168 expect(openBrace.endGroup, same(closeBrace)); | 178 expect(openBrace.endGroup, same(closeBrace)); |
| 169 expect(openBracket.endGroup, same(closeBracket)); | 179 expect(openBracket.endGroup, same(closeBracket)); |
| 170 expect(openParen.endGroup, same(closeParen)); | 180 expect(openParen.endGroup, same(closeParen)); |
| 171 expect(eof.isEof, true); | 181 expect(eof.isEof, true); |
| 182 |
| 183 listener.assertErrors([ |
| 184 new TestError(2, ScannerErrorCode.EXPECTED_TOKEN, [')']), |
| 185 new TestError(1, ScannerErrorCode.EXPECTED_TOKEN, [']']), |
| 186 new TestError(0, ScannerErrorCode.EXPECTED_TOKEN, ['}']), |
| 187 ]); |
| 172 } | 188 } |
| 173 | 189 |
| 174 analyzer.Token _scan(String source, | 190 analyzer.Token _scan(String source, |
| 175 {bool genericMethodComments: false, | 191 {bool genericMethodComments: false, |
| 176 bool lazyAssignmentOperators: false}) { | 192 bool lazyAssignmentOperators: false}) { |
| 177 ErrorListener listener = new ErrorListener(); | 193 ErrorListener listener = new ErrorListener(); |
| 178 analyzer.Token token = scanWithListener(source, listener, | 194 analyzer.Token token = scanWithListener(source, listener, |
| 179 genericMethodComments: genericMethodComments, | 195 genericMethodComments: genericMethodComments, |
| 180 lazyAssignmentOperators: lazyAssignmentOperators); | 196 lazyAssignmentOperators: lazyAssignmentOperators); |
| 181 listener.assertNoErrors(); | 197 listener.assertNoErrors(); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 } else if (token is fasta.UnmatchedToken) { | 260 } else if (token is fasta.UnmatchedToken) { |
| 245 expect(lastClosedGroup?.endGroup?.next, same(token), | 261 expect(lastClosedGroup?.endGroup?.next, same(token), |
| 246 reason: 'Unexpected error token for group: $lastClosedGroup'); | 262 reason: 'Unexpected error token for group: $lastClosedGroup'); |
| 247 expect(token.begin, lastClosedGroup); | 263 expect(token.begin, lastClosedGroup); |
| 248 } | 264 } |
| 249 token = token.next; | 265 token = token.next; |
| 250 } | 266 } |
| 251 expect(openerStack, isEmpty, reason: 'Missing closers'); | 267 expect(openerStack, isEmpty, reason: 'Missing closers'); |
| 252 } | 268 } |
| 253 } | 269 } |
| OLD | NEW |