Skip to content

Commit

Permalink
Fix recovery when parsing complex type variables
Browse files Browse the repository at this point in the history
This fixes parser recovery when the user has inserted a word before
a method declaration with a complex type arguments, such as

  foo Future<List<int>> bar() {}

Fix dart-lang/sdk#34850

Change-Id: Ic6d1767668bd34d75c6ab5f9973e5762bdd8f160
Reviewed-on: https://dart-review.googlesource.com/c/80780
Reviewed-by: Brian Wilkerson <[email protected]>
Commit-Queue: Dan Rubel <[email protected]>
  • Loading branch information
danrubel authored and [email protected] committed Oct 19, 2018
1 parent dcb665f commit 9f7ad8d
Show file tree
Hide file tree
Showing 7 changed files with 288 additions and 89 deletions.
51 changes: 50 additions & 1 deletion pkg/analyzer/test/generated/parser_fasta_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -927,7 +927,56 @@ class SimpleParserTest_Fasta extends FastaParserTestCase
*/
@reflectiveTest
class StatementParserTest_Fasta extends FastaParserTestCase
with StatementParserTestMixin {}
with StatementParserTestMixin {
void test_invalid_typeArg_34850() {
var unit = parseCompilationUnit('foo Future<List<int>> bar() {}', errors: [
expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 4),
expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 4, 6),
expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 22, 3),
]);
// Validate that recovery has properly updated the token stream.
analyzer.Token token = unit.beginToken;
while (!token.isEof) {
expect(token.type, isNot(TokenType.GT_GT));
analyzer.Token next = token.next;
expect(next.previous, token);
token = next;
}
}

void test_partial_typeArg1_34850() {
var unit = parseCompilationUnit('<bar<', errors: [
expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 0, 1),
expectedError(ParserErrorCode.MISSING_IDENTIFIER, 5, 0),
expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 1, 3),
expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 5, 0),
]);
// Validate that recovery has properly updated the token stream.
analyzer.Token token = unit.beginToken;
while (!token.isEof) {
expect(token.type, isNot(TokenType.GT_GT));
analyzer.Token next = token.next;
expect(next.previous, token);
token = next;
}
}

void test_partial_typeArg2_34850() {
var unit = parseCompilationUnit('foo <bar<', errors: [
expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 3),
expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 0, 3),
expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 9, 0),
]);
// Validate that recovery has properly updated the token stream.
analyzer.Token token = unit.beginToken;
while (!token.isEof) {
expect(token.type, isNot(TokenType.GT_GT));
analyzer.Token next = token.next;
expect(next.previous, token);
token = next;
}
}
}

/**
* Tests of the fasta parser based on [TopLevelParserTestMixin].
Expand Down
13 changes: 6 additions & 7 deletions pkg/analyzer/test/generated/parser_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4215,15 +4215,11 @@ class Wrong<T> {
}

void test_method_invalidTypeParameters() {
// TODO(jmesserly): ideally we'd be better at parser recovery here.
// It doesn't try to advance past the invalid token `!` to find the
// valid `>`. If it did we'd get less cascading errors, at least for this
// particular example.
createParser('void m<E, hello!>() {}');
ClassMember member = parser.parseClassMember('C');
expectNotNullIfNoErrors(member);
listener.assertErrors(usingFastaParser
? [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 15, 1)]
? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 5)]
: [
expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 0) /*>*/,
expectedError(ParserErrorCode.MISSING_IDENTIFIER, 0, 0),
Expand Down Expand Up @@ -6576,7 +6572,7 @@ abstract class ExpressionParserTestMixin implements AbstractParserTestCase {
void test_parseFunctionExpression_functionInPlaceOfTypeName() {
Expression expression = parseExpression('<test(' ', (){});>[0, 1, 2]',
codes: usingFastaParser
? [ParserErrorCode.UNEXPECTED_TOKEN]
? [ParserErrorCode.EXPECTED_TOKEN]
: [
ParserErrorCode.EXPECTED_TOKEN,
ParserErrorCode.MISSING_IDENTIFIER,
Expand Down Expand Up @@ -10632,7 +10628,10 @@ Map<Symbol, convertStringToSymbolMap(Map<String, dynamic> map) {
result[new Symbol(name)] = value;
});
return result;
}''', errors: [expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 24)]);
}''', errors: [
expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 24),
expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 0, 3)
]);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -758,7 +758,7 @@ foo
Future<List<int>> bar() {}
''', r'''
foo
Future<List<int>> bar() async {}
Future<List<int>> bar(int x) {}
''');
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/analyzer/test/src/fasta/recovery/invalid_code_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const default = const Object();
f() {
return <g('')>[0, 1, 2];
}
''', [ParserErrorCode.UNEXPECTED_TOKEN], '''
''', [ParserErrorCode.EXPECTED_TOKEN], '''
f() {
return <g>[0, 1, 2];
}
Expand All @@ -53,7 +53,7 @@ f() {
f() {
return <test('', (){})>[0, 1, 2];
}
''', [ParserErrorCode.UNEXPECTED_TOKEN], '''
''', [ParserErrorCode.EXPECTED_TOKEN], '''
f() {
return <test>[0, 1, 2];
}
Expand Down
20 changes: 16 additions & 4 deletions pkg/analyzer/test/src/fasta/recovery/paired_tokens_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,21 @@ f<T> > () => null;
void test_typeParameters_funct() {
testRecovery('''
f<T extends Function()() => null;
''', [ParserErrorCode.EXPECTED_TOKEN], '''
''', [
ParserErrorCode.EXPECTED_TOKEN,
ParserErrorCode.MISSING_FUNCTION_PARAMETERS
], '''
f<T extends Function()>() => null;
''');
}

void test_typeParameters_funct2() {
testRecovery('''
f<T extends Function<X>()() => null;
''', [ParserErrorCode.EXPECTED_TOKEN], '''
''', [
ParserErrorCode.EXPECTED_TOKEN,
ParserErrorCode.MISSING_FUNCTION_PARAMETERS
], '''
f<T extends Function<X>()>() => null;
''');
}
Expand Down Expand Up @@ -133,15 +139,21 @@ List<int, double> f;
void test_typeParameters_last() {
testRecovery('''
f<T() => null;
''', [ParserErrorCode.EXPECTED_TOKEN], '''
''', [
ParserErrorCode.EXPECTED_TOKEN,
ParserErrorCode.MISSING_FUNCTION_PARAMETERS
], '''
f<T>() => null;
''');
}

void test_typeParameters_outer_last() {
testRecovery('''
f<T extends List<int>() => null;
''', [ParserErrorCode.EXPECTED_TOKEN], '''
''', [
ParserErrorCode.EXPECTED_TOKEN,
ParserErrorCode.MISSING_FUNCTION_PARAMETERS
], '''
f<T extends List<int>>() => null;
''');
}
Expand Down
Loading

0 comments on commit 9f7ad8d

Please sign in to comment.