Skip to content

Commit

Permalink
Rework parsing of local function declarations
Browse files Browse the repository at this point in the history
This CL reworks parsing local variable and local function
declarations to improve recovery and error messages.
In addition, the fasta parser properly parses metadata
before a local function declaration.

Change-Id: Ia43c8bab3f3ce3b824390a4aa36d50b85f1ea9af
Reviewed-on: https://dart-review.googlesource.com/46952
Commit-Queue: Dan Rubel <[email protected]>
Reviewed-by: Brian Wilkerson <[email protected]>
  • Loading branch information
Dan Rubel authored and [email protected] committed Mar 20, 2018
1 parent 8eb749e commit fd005e1
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 215 deletions.
53 changes: 7 additions & 46 deletions pkg/analyzer/test/generated/parser_fasta_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,13 @@ class ErrorParserTest_Fasta extends FastaParserTestCase
super.test_invalidUnicodeEscape_tooManyDigits_variable();
}

@override
@failingTest
void test_localFunction_annotation() {
// TODO(danrubel): Update fasta to allow metadata before local function.
super.test_localFunction_annotation();
}

@override
@failingTest
void test_method_invalidTypeParameterComments() {
Expand Down Expand Up @@ -679,38 +686,6 @@ class ErrorParserTest_Fasta extends FastaParserTestCase
super.test_missingFunctionBody_invalid();
}

@override
@failingTest
void test_missingFunctionParameters_local_nonVoid_block() {
// TODO(brianwilkerson) Wrong errors:
// Expected 1 errors of type ParserErrorCode.MISSING_FUNCTION_PARAMETERS, found 0
super.test_missingFunctionParameters_local_nonVoid_block();
}

@override
@failingTest
void test_missingFunctionParameters_local_nonVoid_expression() {
// TODO(brianwilkerson) Wrong errors:
// Expected 1 errors of type ParserErrorCode.MISSING_FUNCTION_PARAMETERS, found 0
super.test_missingFunctionParameters_local_nonVoid_expression();
}

@override
@failingTest
void test_missingFunctionParameters_local_void_block() {
// TODO(brianwilkerson) Wrong errors:
// Expected 1 errors of type ParserErrorCode.MISSING_FUNCTION_PARAMETERS, found 0
super.test_missingFunctionParameters_local_void_block();
}

@override
@failingTest
void test_missingFunctionParameters_local_void_expression() {
// TODO(brianwilkerson) Wrong errors:
// Expected 1 errors of type ParserErrorCode.MISSING_FUNCTION_PARAMETERS, found 0
super.test_missingFunctionParameters_local_void_expression();
}

@override
@failingTest
void test_missingFunctionParameters_topLevel_void_block() {
Expand Down Expand Up @@ -1790,20 +1765,6 @@ class RecoveryParserTest_Fasta extends FastaParserTestCase
super.test_functionExpression_named();
}

@override
@failingTest
void test_incompleteLocalVariable_beforeIdentifier() {
// TODO(brianwilkerson) reportUnrecoverableErrorWithToken
super.test_incompleteLocalVariable_beforeIdentifier();
}

@override
@failingTest
void test_incompleteLocalVariable_beforeKeyword() {
// TODO(brianwilkerson) reportUnrecoverableErrorWithToken
super.test_incompleteLocalVariable_beforeKeyword();
}

@override
@failingTest
void test_incompleteTypeArguments_field() {
Expand Down
69 changes: 46 additions & 23 deletions pkg/analyzer/test/generated/parser_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3130,15 +3130,10 @@ class Foo {

void test_expectedToken_parseStatement_afterVoid() {
parseStatement("void}", expectedEndOffset: 4);
listener.assertErrors(usingFastaParser
? [
expectedError(ParserErrorCode.MISSING_STATEMENT, 0, 4),
expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 1)
]
: [
expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 1),
expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 1)
]);
listener.assertErrors([
expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 1),
expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 1)
]);
}

void test_expectedToken_semicolonMissingAfterExport() {
Expand Down Expand Up @@ -3832,7 +3827,8 @@ class Wrong<T> {
expectNotNullIfNoErrors(statement);
listener.assertErrors(usingFastaParser
? [
expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1),
expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1),
expectedError(ParserErrorCode.MISSING_IDENTIFIER, 9, 1),
expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 1)
]
: [
Expand Down Expand Up @@ -4161,6 +4157,23 @@ class Wrong<T> {
]);
}

void test_localFunction_annotation() {
CompilationUnit unit =
parseCompilationUnit("class C { m() { @Foo f() {} } }");
expect(unit.declarations, hasLength(1));
ClassDeclaration declaration = unit.declarations[0];
expect(declaration.members, hasLength(1));
MethodDeclaration member = declaration.members[0];
BlockFunctionBody body = member.body;
expect(body.block.statements, hasLength(1));
FunctionDeclarationStatement statement = body.block.statements[0];
if (usingFastaParser) {
expect(statement.functionDeclaration.metadata, hasLength(1));
Annotation metadata = statement.functionDeclaration.metadata[0];
expect(metadata.name.name, 'Foo');
}
}

void test_method_invalidTypeParameterComments() {
enableGenericMethodComments = true;
createParser('void m/*<E, hello!>*/() {}');
Expand Down Expand Up @@ -4388,36 +4401,36 @@ class Wrong<T> {
[expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 0, 6)]);
}

@failingTest
void test_missingFunctionParameters_local_nonVoid_block() {
// The parser does not recognize this as a function declaration, so it tries
// to parse it as an expression statement. It isn't clear what the best
// error message is in this case.
parseStatement("int f { return x;}");
listener.assertErrors(
[expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 4, 1)]);
parseStatement("int f { return x;}", expectedEndOffset: 6);
listener
.assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 1)]);
}

@failingTest
void test_missingFunctionParameters_local_nonVoid_expression() {
// The parser does not recognize this as a function declaration, so it tries
// to parse it as an expression statement. It isn't clear what the best
// error message is in this case.
parseStatement("int f => x;");
listener.assertErrors(
[expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 4, 1)]);
listener.assertErrors(usingFastaParser
? [expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 6, 2)]
: [expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 3)]);
}

void test_missingFunctionParameters_local_void_block() {
parseStatement("void f { return x;}");
listener.assertErrors(
[expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 5, 1)]);
parseStatement("void f { return x;}", expectedEndOffset: 7);
listener.assertErrors(usingFastaParser
? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]
: [expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 5, 1)]);
}

void test_missingFunctionParameters_local_void_expression() {
parseStatement("void f => x;");
listener.assertErrors(
[expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 5, 1)]);
[expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 7, 2)]);
}

void test_missingFunctionParameters_topLevel_nonVoid_block() {
Expand Down Expand Up @@ -4675,8 +4688,9 @@ class Wrong<T> {

void test_missingStatement_afterVoid() {
parseStatement("void;");
listener
.assertErrors([expectedError(ParserErrorCode.MISSING_STATEMENT, 0, 4)]);
listener.assertErrors(usingFastaParser
? [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 1)]
: [expectedError(ParserErrorCode.MISSING_STATEMENT, 4, 1)]);
}

void test_missingTerminatorForParameterGroup_named() {
Expand Down Expand Up @@ -15400,6 +15414,15 @@ abstract class StatementParserTestMixin implements AbstractParserTestCase {
expect(variableList.variables, hasLength(1));
}

void test_parseVariableDeclaration_equals_builtIn() {
VariableDeclarationStatement statement = parseStatement('int set = 0;');
assertNoErrors();
expect(statement.semicolon, isNotNull);
VariableDeclarationList variableList = statement.variables;
expect(variableList, isNotNull);
expect(variableList.variables, hasLength(1));
}

void test_parseWhileStatement() {
var statement = parseStatement('while (x) {}') as WhileStatement;
assertNoErrors();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,23 +157,7 @@ class LocalVariableTest extends PartialCodeTest {
"int _s_;",
allFailing: true),
new TestDescriptor(
'typeName', 'int a', [ParserErrorCode.EXPECTED_TOKEN], "int a;",
failing: [
'assert',
'break',
'continue',
'do',
'if',
'for',
'labeled',
'localFunctionNonVoid',
'localFunctionVoid',
'localVariable',
'switch',
'try',
'return',
'while'
]),
'typeName', 'int a', [ParserErrorCode.EXPECTED_TOKEN], "int a;"),
new TestDescriptor(
'var',
'var',
Expand Down
Loading

0 comments on commit fd005e1

Please sign in to comment.