Skip to content

Commit 69dfe14

Browse files
Dan Rubelcommit-bot@chromium.org
Dan Rubel
authored andcommitted
Improve local modifier recovery
In addition to inlining and improving local modifier recovery, this CL also cleans up several tests and addresses comments in https://dart-review.googlesource.com/c/sdk/+/35300 Change-Id: Icf0ad8afdb923e52f43e4d8fa91b1731ab99089c Reviewed-on: https://dart-review.googlesource.com/35500 Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Dan Rubel <[email protected]>
1 parent 188cee8 commit 69dfe14

File tree

5 files changed

+74
-120
lines changed

5 files changed

+74
-120
lines changed

pkg/analyzer/test/generated/parser_fasta_test.dart

Lines changed: 0 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -387,26 +387,6 @@ class ErrorParserTest_Fasta extends FastaParserTestCase
387387
super.test_fieldInitializerOutsideConstructor();
388388
}
389389

390-
@override
391-
@failingTest
392-
void test_functionTypedParameter_incomplete1() {
393-
// TODO(brianwilkerson) Does not recover.
394-
// type 'FormalParameterListImpl' is not a subtype of type 'TypeParameterList' of 'typeParameters' where
395-
// FormalParameterListImpl is from package:analyzer/src/dart/ast/ast.dart
396-
// TypeParameterList is from package:analyzer/dart/ast/ast.dart
397-
//
398-
// package:analyzer/src/fasta/ast_builder.dart 1122:40 AstBuilder.endTopLevelMethod
399-
// package:front_end/src/fasta/parser/parser.dart 1741:14 Parser.parseTopLevelMethod
400-
// package:front_end/src/fasta/parser/parser.dart 1646:11 Parser.parseTopLevelMember
401-
// package:front_end/src/fasta/parser/parser.dart 298:14 Parser._parseTopLevelDeclaration
402-
// package:front_end/src/fasta/parser/parser.dart 263:13 Parser.parseTopLevelDeclaration
403-
// package:front_end/src/fasta/parser/parser.dart 252:15 Parser.parseUnit
404-
// package:analyzer/src/generated/parser_fasta.dart 77:33 _Parser2.parseCompilationUnit2
405-
// package:analyzer/src/generated/parser_fasta.dart 72:12 _Parser2.parseCompilationUnit
406-
// test/generated/parser_fasta_test.dart 2543:35 FastaParserTestCase.parseCompilationUnit
407-
super.test_functionTypedParameter_incomplete1();
408-
}
409-
410390
@override
411391
@failingTest
412392
void test_getterInFunction_block_noReturnType() {
@@ -1447,18 +1427,6 @@ class ErrorParserTest_Fasta extends FastaParserTestCase
14471427
super.test_unexpectedToken_returnInExpressionFunctionBody();
14481428
}
14491429

1450-
@override
1451-
void test_varAndType_local() {
1452-
// The inherited test is marked as failing.
1453-
super.test_varAndType_local();
1454-
}
1455-
1456-
@override
1457-
void test_varAndType_parameter() {
1458-
// The inherited test is marked as failing.
1459-
super.test_varAndType_parameter();
1460-
}
1461-
14621430
@override
14631431
// @failingTest
14641432
void test_voidVariable_parseClassMember_initializer() {
@@ -2127,36 +2095,6 @@ class FormalParameterParserTest_Fasta extends FastaParserTestCase
21272095
void test_parseNormalFormalParameter_function_void_typeParameterComments() {
21282096
// Ignored: Fasta does not support the generic comment syntax.
21292097
}
2130-
2131-
@override
2132-
@failingTest
2133-
void test_parseNormalFormalParameter_simple_const_noType() {
2134-
// TODO(brianwilkerson) Wrong errors:
2135-
// Expected 0 errors of type ParserErrorCode.EXTRANEOUS_MODIFIER, found 1 (1)
2136-
super.test_parseNormalFormalParameter_simple_const_noType();
2137-
}
2138-
2139-
@failingTest
2140-
void test_parseNormalFormalParameter_simple_const_noType2() {
2141-
// TODO(danrubel): should not be generating an error
2142-
super.test_parseNormalFormalParameter_simple_const_noType();
2143-
assertNoErrors();
2144-
}
2145-
2146-
@override
2147-
@failingTest
2148-
void test_parseNormalFormalParameter_simple_const_type() {
2149-
// TODO(brianwilkerson) Wrong errors:
2150-
// Expected 0 errors of type ParserErrorCode.EXTRANEOUS_MODIFIER, found 1 (1)
2151-
super.test_parseNormalFormalParameter_simple_const_type();
2152-
}
2153-
2154-
@failingTest
2155-
void test_parseNormalFormalParameter_simple_const_type2() {
2156-
// TODO(danrubel): should not be generating an error
2157-
super.test_parseNormalFormalParameter_simple_const_type();
2158-
assertNoErrors();
2159-
}
21602098
}
21612099

21622100
/**

pkg/analyzer/test/generated/parser_test.dart

Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2686,6 +2686,15 @@ abstract class ErrorParserTestMixin implements AbstractParserTestCase {
26862686
]);
26872687
}
26882688

2689+
void test_covariantAndType_local() {
2690+
// This is currently reporting EXPECTED_TOKEN for a missing semicolon, but
2691+
// this would be a better error message.
2692+
parseStatement("covariant int x;");
2693+
listener.assertErrors(usingFastaParser
2694+
? [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 0, 9)]
2695+
: [expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 9)]);
2696+
}
2697+
26892698
void test_covariantMember_getter_noReturnType() {
26902699
createParser('static covariant get x => 0;');
26912700
ClassMember member = parser.parseClassMember('C');
@@ -3498,24 +3507,20 @@ class Foo {
34983507
}
34993508

35003509
void test_functionTypedParameter_incomplete1() {
3501-
// This caused an exception at one point.
3502-
if (fe.Scanner.useFasta) {
3503-
parseCompilationUnit("void f(int Function(", errors: [
3504-
expectedError(ScannerErrorCode.EXPECTED_TOKEN, 20, 0),
3505-
expectedError(ScannerErrorCode.EXPECTED_TOKEN, 20, 0),
3506-
expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 20, 0),
3507-
expectedError(ParserErrorCode.MISSING_IDENTIFIER, 20, 0),
3508-
]);
3509-
} else {
3510-
parseCompilationUnit("void f(int Function(", codes: [
3511-
ParserErrorCode.MISSING_FUNCTION_BODY,
3512-
ParserErrorCode.MISSING_CLOSING_PARENTHESIS,
3513-
ParserErrorCode.EXPECTED_EXECUTABLE,
3514-
ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE,
3515-
ParserErrorCode.EXPECTED_TOKEN,
3516-
ParserErrorCode.EXPECTED_TOKEN
3517-
]);
3518-
}
3510+
parseCompilationUnit("void f(int Function(",
3511+
errors: usingFastaParser
3512+
? [
3513+
expectedError(ScannerErrorCode.EXPECTED_TOKEN, 6, 1),
3514+
expectedError(ScannerErrorCode.EXPECTED_TOKEN, 19, 1),
3515+
expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 8),
3516+
expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 20, 0),
3517+
]
3518+
: [
3519+
expectedError(ScannerErrorCode.EXPECTED_TOKEN, 20, 0),
3520+
expectedError(ScannerErrorCode.EXPECTED_TOKEN, 20, 0),
3521+
expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 20, 0),
3522+
expectedError(ParserErrorCode.MISSING_IDENTIFIER, 20, 0),
3523+
]);
35193524
}
35203525

35213526
void test_functionTypedParameter_var() {
@@ -5246,22 +5251,24 @@ void main() {
52465251
errors: [expectedError(ParserErrorCode.VAR_AND_TYPE, 14, 3)]);
52475252
}
52485253

5249-
@failingTest
52505254
void test_varAndType_local() {
52515255
// This is currently reporting EXPECTED_TOKEN for a missing semicolon, but
52525256
// this would be a better error message.
52535257
parseStatement("var int x;");
5254-
listener.assertErrors([expectedError(ParserErrorCode.VAR_AND_TYPE, 4, 3)]);
5258+
listener.assertErrors(usingFastaParser
5259+
? [expectedError(ParserErrorCode.VAR_AND_TYPE, 4, 3)]
5260+
: [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 8, 1)]);
52555261
}
52565262

5257-
@failingTest
52585263
void test_varAndType_parameter() {
52595264
// This is currently reporting EXPECTED_TOKEN for a missing semicolon, but
52605265
// this would be a better error message.
52615266
createParser('(var int x)');
52625267
FormalParameterList list = parser.parseFormalParameterList();
52635268
expectNotNullIfNoErrors(list);
5264-
listener.assertErrors([expectedError(ParserErrorCode.VAR_AND_TYPE, 5, 3)]);
5269+
listener.assertErrors(usingFastaParser
5270+
? [expectedError(ParserErrorCode.VAR_AND_TYPE, 5, 3)]
5271+
: [expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1)]);
52655272
}
52665273

52675274
void test_varAndType_topLevelVariable() {
@@ -9117,14 +9124,10 @@ abstract class FormalParameterParserTestMixin
91179124
}
91189125

91199126
void test_parseNormalFormalParameter_simple_const_noType() {
9120-
NormalFormalParameter parameter = parseNormalFormalParameter('const a');
9127+
NormalFormalParameter parameter = parseNormalFormalParameter('const a',
9128+
errorCodes:
9129+
usingFastaParser ? [ParserErrorCode.EXTRANEOUS_MODIFIER] : []);
91219130
expect(parameter, isNotNull);
9122-
if (usingFastaParser) {
9123-
// TODO(danrubel): should not be generating an error
9124-
assertErrorsWithCodes([ParserErrorCode.EXTRANEOUS_MODIFIER]);
9125-
} else {
9126-
assertNoErrors();
9127-
}
91289131
expect(parameter, new isInstanceOf<SimpleFormalParameter>());
91299132
SimpleFormalParameter simpleParameter = parameter;
91309133
expect(simpleParameter.keyword, isNotNull);
@@ -9133,14 +9136,10 @@ abstract class FormalParameterParserTestMixin
91339136
}
91349137

91359138
void test_parseNormalFormalParameter_simple_const_type() {
9136-
NormalFormalParameter parameter = parseNormalFormalParameter('const A a');
9139+
NormalFormalParameter parameter = parseNormalFormalParameter('const A a',
9140+
errorCodes:
9141+
usingFastaParser ? [ParserErrorCode.EXTRANEOUS_MODIFIER] : []);
91379142
expect(parameter, isNotNull);
9138-
if (usingFastaParser) {
9139-
// TODO(danrubel): should not be generating an error
9140-
assertErrorsWithCodes([ParserErrorCode.EXTRANEOUS_MODIFIER]);
9141-
} else {
9142-
assertNoErrors();
9143-
}
91449143
expect(parameter, new isInstanceOf<SimpleFormalParameter>());
91459144
SimpleFormalParameter simpleParameter = parameter;
91469145
expect(simpleParameter.keyword, isNotNull);

pkg/analyzer/test/src/fasta/recovery/paired_tokens_test.dart

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -136,12 +136,10 @@ int y = 0;
136136
*/
137137
@reflectiveTest
138138
class BracketsTest extends AbstractRecoveryTest {
139-
@failingTest
140139
void test_indexOperator() {
141-
// Parser crashes
142140
testRecovery('''
143141
f(x) => l[x
144-
''', [ScannerErrorCode.EXPECTED_TOKEN, ScannerErrorCode.EXPECTED_TOKEN], '''
142+
''', [ScannerErrorCode.EXPECTED_TOKEN, ParserErrorCode.EXPECTED_TOKEN], '''
145143
f(x) => l[x];
146144
''');
147145
}
@@ -166,12 +164,10 @@ var x = [[0], [1], [2]];
166164
''');
167165
}
168166

169-
@failingTest
170167
void test_listLiteral_outer_last() {
171-
// Parser crashes
172168
testRecovery('''
173169
var x = [0, 1
174-
''', [ScannerErrorCode.EXPECTED_TOKEN, ScannerErrorCode.EXPECTED_TOKEN], '''
170+
''', [ScannerErrorCode.EXPECTED_TOKEN, ParserErrorCode.EXPECTED_TOKEN], '''
175171
var x = [0, 1];
176172
''');
177173
}
@@ -224,12 +220,11 @@ class C {}
224220
''');
225221
}
226222

227-
@failingTest
228223
void test_parameterList_eof() {
229-
// Parser crashes
230224
testRecovery('''
231225
f(x
232-
''', [ScannerErrorCode.EXPECTED_TOKEN], '''
226+
''', [ScannerErrorCode.EXPECTED_TOKEN, ParserErrorCode.MISSING_FUNCTION_BODY],
227+
'''
233228
f(x) {}
234229
''');
235230
}

pkg/front_end/lib/src/fasta/parser/modifier_context.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ Token skipToLastModifier(Token token) {
7575
}
7676

7777
TypeContinuation typeContinuationAfterVar(TypeContinuation typeContinuation) {
78-
switch (typeContinuation ?? TypeContinuation.Required) {
78+
switch (typeContinuation) {
7979
case TypeContinuation.NormalFormalParameter:
8080
return TypeContinuation.NormalFormalParameterAfterVar;
8181

@@ -190,6 +190,7 @@ class ModifierContext {
190190
return token;
191191
}
192192
switch (memberKind) {
193+
case MemberKind.Local:
193194
case MemberKind.StaticField:
194195
case MemberKind.StaticMethod:
195196
case MemberKind.TopLevelField:

pkg/front_end/lib/src/fasta/parser/parser.dart

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,7 @@ import 'modifier_context.dart'
8383
TopLevelMethodModifierContext,
8484
isModifier,
8585
parseModifiersOpt,
86-
skipToLastModifier,
87-
typeContinuationAfterVar,
88-
typeContinuationFromMemberKind;
86+
typeContinuationAfterVar;
8987

9088
import 'recovery_listeners.dart'
9189
show ClassHeaderRecoveryListener, ImportRecoveryListener;
@@ -4225,6 +4223,8 @@ class Parser {
42254223
throw "Internal error: Unknown asyncState: '$asyncState'.";
42264224
} else if (identical(value, 'const')) {
42274225
return parseExpressionStatementOrConstDeclaration(token);
4226+
} else if (isModifier(token.next)) {
4227+
return parseVariablesDeclaration(token);
42284228
} else if (token.next.isIdentifier) {
42294229
return parseExpressionStatementOrDeclaration(token);
42304230
} else if (identical(value, '@')) {
@@ -5399,22 +5399,43 @@ class Parser {
53995399
Token parseVariablesDeclarationMaybeSemicolon(
54005400
Token token, bool endWithSemicolon) {
54015401
token = parseMetadataStar(token);
5402+
Token next = token.next;
54025403

54035404
MemberKind memberKind = MemberKind.Local;
54045405
TypeContinuation typeContinuation;
5405-
if (isModifier(token.next)) {
5406-
ModifierContext modifierContext = parseModifiersOpt(
5407-
this, token, skipToLastModifier(token), memberKind, null, true, null);
5408-
token = modifierContext.lastModifier;
5409-
typeContinuation = modifierContext.typeContinuation;
5410-
memberKind = modifierContext.memberKind;
5411-
modifierContext = null;
5406+
Token varFinalOrConst;
5407+
if (isModifier(next)) {
5408+
if (optional('var', next)) {
5409+
typeContinuation = TypeContinuation.OptionalAfterVar;
5410+
varFinalOrConst = token = parseModifier(token);
5411+
next = token.next;
5412+
} else if (optional('final', next) || optional('const', next)) {
5413+
typeContinuation = TypeContinuation.Optional;
5414+
varFinalOrConst = token = parseModifier(token);
5415+
next = token.next;
5416+
}
5417+
5418+
if (isModifier(next)) {
5419+
// Recovery
5420+
ModifierRecoveryContext modifierContext = new ModifierRecoveryContext(
5421+
this, memberKind, null, true, typeContinuation);
5422+
token = modifierContext.parseRecovery(token,
5423+
varFinalOrConst: varFinalOrConst);
5424+
5425+
memberKind = modifierContext.memberKind;
5426+
typeContinuation = modifierContext.typeContinuation;
5427+
varFinalOrConst = modifierContext.varFinalOrConst;
5428+
listener.handleModifiers(modifierContext.modifierCount);
5429+
modifierContext = null;
5430+
} else {
5431+
listener.handleModifiers(1);
5432+
}
54125433
} else {
54135434
listener.handleModifiers(0);
5414-
typeContinuation = typeContinuationFromMemberKind(true, memberKind);
54155435
}
54165436

5417-
token = parseType(token, typeContinuation, null, memberKind);
5437+
token = parseType(
5438+
token, typeContinuation ?? TypeContinuation.Required, null, memberKind);
54185439
return parseVariablesDeclarationMaybeSemicolonRest(token, endWithSemicolon);
54195440
}
54205441

0 commit comments

Comments
 (0)