blob: 6f1430d7683d086c9e7dcd3f22a11c81791519c8 [file] [log] [blame]
// 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:analyzer/src/dart/error/syntactic_errors.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'recovery_test_support.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(AngleBracketsTest);
defineReflectiveTests(BracesTest);
defineReflectiveTests(BracketsTest);
defineReflectiveTests(ParenthesesTest);
});
}
/// Test how well the parser recovers when angle brackets (`<` and `>`) are
/// mismatched.
@reflectiveTest
class AngleBracketsTest extends AbstractRecoveryTest {
@failingTest
void test_typeArguments_inner_last() {
testRecovery(
'''
List<List<int>
''',
[ScannerErrorCode.expectedToken],
'''
List<List<int>> _s_;
''',
);
}
void test_typeArguments_inner_last2() {
testRecovery(
'''
List<List<int> f;
''',
[ParserErrorCode.expectedToken],
'''
List<List<int>> f;
''',
);
}
@failingTest
void test_typeArguments_inner_notLast() {
testRecovery(
'''
Map<List<int, List<String>>
''',
[ScannerErrorCode.expectedToken],
'''
Map<List<int>, List<String>> _s_;
''',
);
}
void test_typeArguments_inner_notLast2() {
// TODO(danrubel): Investigate better recovery.
testRecovery(
'''
Map<List<int, List<String>> f;
''',
[ParserErrorCode.expectedToken],
'''
Map<List<int, List<String>>> f;
''',
);
}
void test_typeArguments_missing_comma() {
testRecovery(
'''
List<int double> f;
''',
[ParserErrorCode.expectedToken],
'''
List<int, double> f;
''',
);
}
@failingTest
void test_typeArguments_outer_last() {
testRecovery(
'''
List<int
''',
[ScannerErrorCode.expectedToken],
'''
List<int> _s_;
''',
);
}
void test_typeArguments_outer_last2() {
testRecovery(
'''
List<int f;
''',
[ParserErrorCode.expectedToken],
'''
List<int> f;
''',
);
}
void test_typeParameters_extraGt() {
testRecovery(
'''
f<T>>() => null;
''',
[
ParserErrorCode.topLevelOperator,
ParserErrorCode.missingFunctionParameters,
ParserErrorCode.missingFunctionBody,
],
'''
f<T> > () => null;
''',
expectedDiagnosticsInValidCode: [
ParserErrorCode.topLevelOperator,
ParserErrorCode.missingFunctionParameters,
ParserErrorCode.missingFunctionBody,
],
);
}
void test_typeParameters_funct() {
testRecovery(
'''
f<T extends Function()() => null;
''',
[
ParserErrorCode.expectedToken,
ParserErrorCode.missingFunctionParameters,
],
'''
f<T extends Function()>() => null;
''',
);
}
void test_typeParameters_funct2() {
testRecovery(
'''
f<T extends Function<X>()() => null;
''',
[
ParserErrorCode.expectedToken,
ParserErrorCode.missingFunctionParameters,
],
'''
f<T extends Function<X>()>() => null;
''',
);
}
void test_typeParameters_gtEq() {
testRecovery(
'''
f<T>=() => null;
''',
[ParserErrorCode.unexpectedToken],
'''
f<T>() => null;
''',
);
}
void test_typeParameters_gtGtEq() {
testRecovery(
'''
f<T extends List<int>>=() => null;
''',
[ParserErrorCode.unexpectedToken],
'''
f<T extends List<int>>() => null;
''',
);
}
void test_typeParameters_last() {
testRecovery(
'''
f<T() => null;
''',
[
ParserErrorCode.expectedToken,
ParserErrorCode.missingFunctionParameters,
],
'''
f<T>() => null;
''',
);
}
void test_typeParameters_outer_last() {
testRecovery(
'''
f<T extends List<int>() => null;
''',
[
ParserErrorCode.expectedToken,
ParserErrorCode.missingFunctionParameters,
],
'''
f<T extends List<int>>() => null;
''',
);
}
}
/// Test how well the parser recovers when curly braces are mismatched.
@reflectiveTest
class BracesTest extends AbstractRecoveryTest {
void test_statement_if_last() {
testRecovery(
'''
f(x) {
if (x != null) {
}
''',
[ScannerErrorCode.expectedToken],
'''
f(x) {
if (x != null) {}
}
''',
);
}
@failingTest
void test_statement_if_while() {
// Expected a list of length 2; found a list of length 1
testRecovery(
'''
f(x) {
if (x != null) {
while (x == null) {}
}
''',
[ScannerErrorCode.expectedToken],
'''
f(x) {
if (x != null) {}
while (x == null) {}
}
''',
);
}
@failingTest
void test_unit_functionBody_class() {
// Parser crashes
testRecovery(
'''
f(x) {
class C {}
''',
[ScannerErrorCode.expectedToken],
'''
f(x) {}
class C {}
''',
);
}
@failingTest
void test_unit_functionBody_function() {
// Expected a list of length 2; found a list of length 1
testRecovery(
'''
f(x) {
g(y) => y;
''',
[ScannerErrorCode.expectedToken],
'''
f(x) {}
g(y) => y;
''',
);
}
void test_unit_functionBody_last() {
testRecovery(
'''
f(x) {
''',
[ScannerErrorCode.expectedToken],
'''
f(x) {}
''',
);
}
@failingTest
void test_unit_functionBody_variable() {
// Expected a list of length 2; found a list of length 1
testRecovery(
'''
f(x) {
int y = 0;
''',
[ScannerErrorCode.expectedToken],
'''
f(x) {}
int y = 0;
''',
);
}
}
/// Test how well the parser recovers when square brackets are mismatched.
@reflectiveTest
class BracketsTest extends AbstractRecoveryTest {
void test_indexOperator() {
testRecovery(
'''
f(x) => l[x
''',
[ScannerErrorCode.expectedToken, ParserErrorCode.expectedToken],
'''
f(x) => l[x];
''',
);
}
void test_indexOperator_nullAware() {
testRecovery(
'''
f(x) => l?[x
''',
[ScannerErrorCode.expectedToken, ParserErrorCode.expectedToken],
'''
f(x) => l?[x];
''',
);
}
void test_listLiteral_inner_last() {
testRecovery(
'''
var x = [[0], [1];
''',
[ScannerErrorCode.expectedToken],
'''
var x = [[0], [1]];
''',
);
}
void test_listLiteral_inner_notLast() {
testRecovery(
'''
var x = [[0], [1, [2]];
''',
[ScannerErrorCode.expectedToken],
'''
var x = [[0], [1, [2]]];
''',
);
}
void test_listLiteral_missing_comma() {
testRecovery(
'''
var x = [0 1];
''',
[ParserErrorCode.expectedToken],
'''
var x = [0, 1];
''',
);
}
void test_listLiteral_outer_last() {
testRecovery(
'''
var x = [0, 1
''',
[ScannerErrorCode.expectedToken, ParserErrorCode.expectedToken],
'''
var x = [0, 1];
''',
);
}
}
/// Test how well the parser recovers when parentheses are mismatched.
@reflectiveTest
class ParenthesesTest extends AbstractRecoveryTest {
@failingTest
void test_if_last() {
// Parser crashes
testRecovery(
'''
f(x) {
if (x
}
''',
[ScannerErrorCode.expectedToken],
'''
f(x) {
if (x);
}
''',
);
}
@failingTest
void test_if_while() {
// Parser crashes
testRecovery(
'''
f(x) {
if (x
while(x != null) {}
}
''',
[ScannerErrorCode.expectedToken],
'''
f(x) {
if (x);
while(x != null) {}
}
''',
);
}
void test_parameterList_class() {
// Parser crashes
testRecovery(
'''
f(x
class C {}
''',
[ScannerErrorCode.expectedToken, ParserErrorCode.missingFunctionBody],
'''
f(x) {}
class C {}
''',
);
}
void test_parameterList_eof() {
testRecovery(
'''
f(x
''',
[ScannerErrorCode.expectedToken, ParserErrorCode.missingFunctionBody],
'''
f(x) {}
''',
);
}
}