Skip to content

Commit 2be7b95

Browse files
Dan Rubelcommit-bot@chromium.org
Dan Rubel
authored andcommitted
Refactor fasta parse top level modifiers
This CL moves modifier parsing out of parseTopLevelMethod and parseFields into parseTopLevelMember and before findMemberName. This is the next step in evenally removing findMemberName and improving top level declaration recovery. * New ModifierRecoveryContext2 which will soon replace both ModifierContext and ModifierContext2 * Remove now unused TopLevelModifierRecoveryContext * Remove unused beginTopLevelMethod event arguments * Remove unused handleNoType event arguments * Address comment in https://dart-review.googlesource.com/c/sdk/+/36500 Change-Id: I6842a83d9604cdcca611d7209e3ebcc78de469d3 Reviewed-on: https://dart-review.googlesource.com/36680 Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Dan Rubel <[email protected]>
1 parent 04e91a3 commit 2be7b95

File tree

10 files changed

+413
-119
lines changed

10 files changed

+413
-119
lines changed

pkg/analyzer/test/generated/parser_fasta_listener.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -478,8 +478,8 @@ class ForwardingTestListener extends ForwardingListener {
478478
}
479479

480480
@override
481-
void beginTopLevelMethod(Token token, Token name) {
482-
super.beginTopLevelMethod(token, name);
481+
void beginTopLevelMethod() {
482+
super.beginTopLevelMethod();
483483
begin('TopLevelMethod');
484484
}
485485

pkg/analyzer/test/src/fasta/recovery/partial_code/top_level_variable_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ class TopLevelVariableTest extends PartialCodeTest {
103103
failing: allExceptEof),
104104
new TestDescriptor(
105105
'varName', 'var a', [ParserErrorCode.EXPECTED_TOKEN], "var a;",
106-
allFailing: true),
106+
failing: allExceptEof),
107107
new TestDescriptor(
108108
'varNameEquals',
109109
'var a =',

pkg/compiler/lib/src/parser/element_listener.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ class ElementListener extends Listener {
461461
Token token) {}
462462

463463
@override
464-
void handleNoType(Token token) {
464+
void handleNoType() {
465465
pushNode(null);
466466
}
467467

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -365,8 +365,8 @@ class ForwardingListener implements Listener {
365365
}
366366

367367
@override
368-
void beginTopLevelMethod(Token token, Token name) {
369-
listener?.beginTopLevelMethod(token, name);
368+
void beginTopLevelMethod() {
369+
listener?.beginTopLevelMethod();
370370
}
371371

372372
@override
@@ -1150,8 +1150,8 @@ class ForwardingListener implements Listener {
11501150
}
11511151

11521152
@override
1153-
void handleNoType(Token token) {
1154-
listener?.handleNoType(token);
1153+
void handleNoType() {
1154+
listener?.handleNoType();
11551155
}
11561156

11571157
@override

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -809,7 +809,7 @@ class Listener {
809809
logEvent("TopLevelFields");
810810
}
811811

812-
void beginTopLevelMethod(Token token, Token name) {}
812+
void beginTopLevelMethod() {}
813813

814814
/// Handle the end of a top level method. Substructures:
815815
/// - metadata
@@ -1071,7 +1071,7 @@ class Listener {
10711071
logEvent("NoConstructorReferenceContinuationAfterTypeArguments");
10721072
}
10731073

1074-
void handleNoType(Token token) {
1074+
void handleNoType() {
10751075
logEvent("NoType");
10761076
}
10771077

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

Lines changed: 265 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,271 @@ class ModifierContext {
218218
}
219219
}
220220

221+
/// This class parses modifiers in recovery situations,
222+
/// but does not call handleModifier or handleModifiers.
223+
class ModifierRecoveryContext2 {
224+
final Parser parser;
225+
TypeContinuation typeContinuation;
226+
int modifierCount = 0;
227+
Token abstractToken;
228+
Token constToken;
229+
Token covariantToken;
230+
Token externalToken;
231+
Token finalToken;
232+
Token staticOrCovariant;
233+
Token staticToken;
234+
Token varFinalOrConst;
235+
Token varToken;
236+
237+
// TODO(danrubel): Replace [ModifierRecoveryContext] and [ModifierContext]
238+
// with this class.
239+
240+
ModifierRecoveryContext2(this.parser);
241+
242+
/// Parse modifiers for top level functions and fields.
243+
Token parseTopLevelModifiers(Token token, TypeContinuation typeContinuation,
244+
{Token externalToken, Token varFinalOrConst}) {
245+
token = parseModifiers(token, typeContinuation,
246+
externalToken: externalToken, varFinalOrConst: varFinalOrConst);
247+
248+
if (abstractToken != null) {
249+
parser.reportRecoverableErrorWithToken(
250+
abstractToken, fasta.templateExtraneousModifier);
251+
}
252+
if (staticOrCovariant != null) {
253+
parser.reportRecoverableErrorWithToken(
254+
staticOrCovariant, fasta.templateExtraneousModifier);
255+
covariantToken = null;
256+
staticOrCovariant = null;
257+
staticToken = null;
258+
--modifierCount;
259+
}
260+
return token;
261+
}
262+
263+
Token parseModifiers(Token token, TypeContinuation typeContinuation,
264+
{Token externalToken, Token staticOrCovariant, Token varFinalOrConst}) {
265+
this.typeContinuation = typeContinuation;
266+
if (externalToken != null) {
267+
this.externalToken = externalToken;
268+
++modifierCount;
269+
}
270+
if (staticOrCovariant != null) {
271+
this.staticOrCovariant = staticOrCovariant;
272+
++modifierCount;
273+
if (optional('static', staticOrCovariant)) {
274+
staticToken = staticOrCovariant;
275+
} else if (optional('covariant', staticOrCovariant)) {
276+
covariantToken = staticOrCovariant;
277+
} else {
278+
throw "Internal error: Unexpected staticOrCovariant"
279+
" '$staticOrCovariant'.";
280+
}
281+
}
282+
if (varFinalOrConst != null) {
283+
this.varFinalOrConst = varFinalOrConst;
284+
++modifierCount;
285+
if (optional('var', varFinalOrConst)) {
286+
varToken = varFinalOrConst;
287+
} else if (optional('final', varFinalOrConst)) {
288+
finalToken = varFinalOrConst;
289+
} else if (optional('const', varFinalOrConst)) {
290+
constToken = varFinalOrConst;
291+
} else {
292+
throw "Internal error: Unexpected varFinalOrConst '$varFinalOrConst'.";
293+
}
294+
}
295+
296+
// Process invalid and out-of-order modifiers
297+
Token next = token.next;
298+
while (isModifier(next)) {
299+
final value = next.stringValue;
300+
if (identical('abstract', value)) {
301+
token = parseAbstract(token);
302+
} else if (identical('const', value)) {
303+
token = parseConst(token);
304+
} else if (identical('covariant', value)) {
305+
token = parseCovariant(token);
306+
} else if (identical('external', value)) {
307+
token = parseExternal(token);
308+
} else if (identical('final', value)) {
309+
token = parseFinal(token);
310+
} else if (identical('static', value)) {
311+
token = parseStatic(token);
312+
} else if (identical('var', value)) {
313+
token = parseVar(token);
314+
} else {
315+
throw 'Internal Error: Unhandled modifier: $value';
316+
}
317+
next = token.next;
318+
}
319+
320+
return token;
321+
}
322+
323+
Token parseAbstract(Token token) {
324+
Token next = token.next;
325+
assert(optional('abstract', next));
326+
if (abstractToken == null) {
327+
abstractToken = next;
328+
++modifierCount;
329+
return next;
330+
}
331+
332+
// Recovery
333+
parser.reportRecoverableErrorWithToken(
334+
next, fasta.templateDuplicatedModifier);
335+
return next;
336+
}
337+
338+
Token parseConst(Token token) {
339+
Token next = token.next;
340+
assert(optional('const', next));
341+
if (varFinalOrConst == null && covariantToken == null) {
342+
typeContinuation ??= TypeContinuation.Optional;
343+
varFinalOrConst = constToken = next;
344+
++modifierCount;
345+
return next;
346+
}
347+
348+
// Recovery
349+
if (constToken != null) {
350+
parser.reportRecoverableErrorWithToken(
351+
next, fasta.templateDuplicatedModifier);
352+
} else if (covariantToken != null) {
353+
parser.reportRecoverableError(next, fasta.messageConstAndCovariant);
354+
} else if (finalToken != null) {
355+
parser.reportRecoverableError(next, fasta.messageConstAndFinal);
356+
} else if (varToken != null) {
357+
parser.reportRecoverableError(next, fasta.messageConstAndVar);
358+
} else {
359+
throw 'Internal Error: Unexpected varFinalOrConst: $varFinalOrConst';
360+
}
361+
return next;
362+
}
363+
364+
Token parseCovariant(Token token) {
365+
Token next = token.next;
366+
assert(optional('covariant', next));
367+
if (staticOrCovariant == null && constToken == null) {
368+
staticOrCovariant = covariantToken = next;
369+
++modifierCount;
370+
371+
if (varToken != null) {
372+
parser.reportRecoverableError(next, fasta.messageCovariantAfterVar);
373+
} else if (finalToken != null) {
374+
parser.reportRecoverableError(next, fasta.messageCovariantAfterFinal);
375+
}
376+
return next;
377+
}
378+
379+
// Recovery
380+
if (constToken != null) {
381+
parser.reportRecoverableError(next, fasta.messageConstAndCovariant);
382+
} else if (covariantToken != null) {
383+
parser.reportRecoverableErrorWithToken(
384+
next, fasta.templateDuplicatedModifier);
385+
} else if (staticToken != null) {
386+
parser.reportRecoverableError(next, fasta.messageCovariantAndStatic);
387+
} else {
388+
throw 'Internal Error: Unexpected staticOrCovariant: $staticOrCovariant';
389+
}
390+
return next;
391+
}
392+
393+
Token parseExternal(Token token) {
394+
Token next = token.next;
395+
assert(optional('external', next));
396+
if (externalToken == null) {
397+
externalToken = next;
398+
++modifierCount;
399+
return next;
400+
}
401+
402+
// Recovery
403+
parser.reportRecoverableErrorWithToken(
404+
next, fasta.templateExtraneousModifier);
405+
return next;
406+
}
407+
408+
Token parseFinal(Token token) {
409+
Token next = token.next;
410+
assert(optional('final', next));
411+
if (varFinalOrConst == null) {
412+
typeContinuation ??= TypeContinuation.Optional;
413+
varFinalOrConst = finalToken = next;
414+
++modifierCount;
415+
return next;
416+
}
417+
418+
// Recovery
419+
if (constToken != null) {
420+
parser.reportRecoverableError(next, fasta.messageConstAndFinal);
421+
} else if (finalToken != null) {
422+
parser.reportRecoverableErrorWithToken(
423+
next, fasta.templateDuplicatedModifier);
424+
} else if (varToken != null) {
425+
parser.reportRecoverableError(next, fasta.messageFinalAndVar);
426+
} else {
427+
throw 'Internal Error: Unexpected varFinalOrConst: $varFinalOrConst';
428+
}
429+
return next;
430+
}
431+
432+
Token parseStatic(Token token) {
433+
Token next = token.next;
434+
assert(optional('static', next));
435+
if (staticOrCovariant == null) {
436+
staticOrCovariant = staticToken = next;
437+
++modifierCount;
438+
439+
if (constToken != null) {
440+
parser.reportRecoverableError(next, fasta.messageStaticAfterConst);
441+
} else if (finalToken != null) {
442+
parser.reportRecoverableError(next, fasta.messageStaticAfterFinal);
443+
} else if (varToken != null) {
444+
parser.reportRecoverableError(next, fasta.messageStaticAfterVar);
445+
}
446+
return next;
447+
}
448+
449+
// Recovery
450+
if (covariantToken != null) {
451+
parser.reportRecoverableError(next, fasta.messageCovariantAndStatic);
452+
} else if (staticToken != null) {
453+
parser.reportRecoverableErrorWithToken(
454+
next, fasta.templateDuplicatedModifier);
455+
} else {
456+
throw 'Internal Error: Unexpected staticOrCovariant: $staticOrCovariant';
457+
}
458+
return next;
459+
}
460+
461+
Token parseVar(Token token) {
462+
Token next = token.next;
463+
assert(optional('var', next));
464+
if (varFinalOrConst == null) {
465+
typeContinuation = typeContinuationAfterVar(typeContinuation);
466+
varFinalOrConst = varToken = next;
467+
++modifierCount;
468+
return next;
469+
}
470+
471+
// Recovery
472+
if (constToken != null) {
473+
parser.reportRecoverableError(next, fasta.messageConstAndVar);
474+
} else if (finalToken != null) {
475+
parser.reportRecoverableError(next, fasta.messageFinalAndVar);
476+
} else if (varToken != null) {
477+
parser.reportRecoverableErrorWithToken(
478+
next, fasta.templateDuplicatedModifier);
479+
} else {
480+
throw 'Internal Error: Unexpected varFinalOrConst: $varFinalOrConst';
481+
}
482+
return next;
483+
}
484+
}
485+
221486
class ModifierRecoveryContext extends ModifierContext {
222487
Token constToken;
223488
Token covariantToken;
@@ -685,32 +950,3 @@ class FactoryModifierContext {
685950
}
686951
}
687952
}
688-
689-
class TopLevelMethodModifierContext {
690-
final Parser parser;
691-
Token externalToken;
692-
693-
TopLevelMethodModifierContext(this.parser);
694-
695-
/// Parse modifiers from the tokens following [token].
696-
Token parseRecovery(Token token) {
697-
Token beforeToken = token;
698-
while (isModifier(token.next)) {
699-
beforeToken = token;
700-
token = token.next;
701-
if (optional('external', token)) {
702-
if (externalToken == null) {
703-
externalToken = token;
704-
} else {
705-
parser.reportRecoverableErrorWithToken(
706-
token, fasta.templateDuplicatedModifier);
707-
}
708-
} else {
709-
// TODO(danrubel): report more specific analyzer error codes
710-
parser.reportRecoverableErrorWithToken(
711-
token, fasta.templateExtraneousModifier);
712-
}
713-
}
714-
return beforeToken;
715-
}
716-
}

0 commit comments

Comments
 (0)