Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(175)

Side by Side Diff: pkg/front_end/lib/src/fasta/analyzer/ast_builder.dart

Issue 2756593004: Start unraveling circularities between analyzer and front_end/kernel. (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 library fasta.analyzer.ast_builder;
6
7 import 'package:analyzer/analyzer.dart';
8 import 'package:analyzer/dart/ast/ast_factory.dart' show AstFactory;
9 import 'package:analyzer/dart/ast/standard_ast_factory.dart' as standard;
10 import 'package:analyzer/dart/ast/token.dart' as analyzer show Token;
11 import 'package:analyzer/dart/element/element.dart' show Element;
12 import '../parser/parser.dart' show FormalParameterType;
13 import '../scanner/token.dart' show BeginGroupToken, Token;
14
15 import '../errors.dart' show internalError;
16 import '../kernel/kernel_builder.dart'
17 show Builder, KernelLibraryBuilder, ProcedureBuilder;
18 import '../parser/identifier_context.dart' show IdentifierContext;
19 import '../quote.dart';
20 import '../source/scope_listener.dart'
21 show JumpTargetKind, NullValue, Scope, ScopeListener;
22 import 'analyzer.dart' show toKernel;
23 import 'element_store.dart'
24 show
25 AnalyzerLocalVariableElemment,
26 AnalyzerParameterElement,
27 ElementStore,
28 KernelClassElement;
29 import 'token_utils.dart' show toAnalyzerToken, toAnalyzerCommentToken;
30
31 class AstBuilder extends ScopeListener {
32 final AstFactory ast = standard.astFactory;
33
34 final KernelLibraryBuilder library;
35
36 final Builder member;
37
38 final ElementStore elementStore;
39
40 @override
41 final Uri uri;
42
43 /// The name of the class currently being parsed, or `null` if no class is
44 /// being parsed.
45 String className;
46
47 AstBuilder(this.library, this.member, this.elementStore, Scope scope,
48 [Uri uri])
49 : uri = uri ?? library.fileUri,
50 super(scope);
51
52 createJumpTarget(JumpTargetKind kind, int charOffset) {
53 // TODO(ahe): Implement jump targets.
54 return null;
55 }
56
57 void beginLiteralString(Token token) {
58 debugEvent("beginLiteralString");
59 push(token);
60 }
61
62 @override
63 void handleNoConstructorReferenceContinuationAfterTypeArguments(Token token) {
64 debugEvent("NoConstructorReferenceContinuationAfterTypeArguments");
65 push(NullValue.ConstructorReferenceContinuationAfterTypeArguments);
66 }
67
68 @override
69 void endConstructorReference(
70 Token start, Token periodBeforeName, Token endToken) {
71 debugEvent("ConstructorReference");
72 SimpleIdentifier constructorName = pop();
73 TypeArgumentList typeArguments = pop();
74 Identifier typeNameIdentifier = pop();
75 push(ast.constructorName(ast.typeName(typeNameIdentifier, typeArguments),
76 toAnalyzerToken(periodBeforeName), constructorName));
77 }
78
79 @override
80 void handleConstExpression(Token token) {
81 debugEvent("ConstExpression");
82 _handleInstanceCreation(token);
83 }
84
85 void _handleInstanceCreation(Token token) {
86 MethodInvocation arguments = pop();
87 ConstructorName constructorName = pop();
88 push(ast.instanceCreationExpression(
89 toAnalyzerToken(token), constructorName, arguments.argumentList));
90 }
91
92 @override
93 void handleNewExpression(Token token) {
94 debugEvent("NewExpression");
95 _handleInstanceCreation(token);
96 }
97
98 @override
99 void handleParenthesizedExpression(BeginGroupToken token) {
100 debugEvent("ParenthesizedExpression");
101 Expression expression = pop();
102 push(ast.parenthesizedExpression(
103 toAnalyzerToken(token), expression, toAnalyzerToken(token.endGroup)));
104 }
105
106 void handleStringPart(Token token) {
107 debugEvent("StringPart");
108 push(token);
109 }
110
111 void doStringPart(Token token) {
112 push(ast.simpleStringLiteral(toAnalyzerToken(token), token.lexeme));
113 }
114
115 void endLiteralString(int interpolationCount, Token endToken) {
116 debugEvent("endLiteralString");
117 if (interpolationCount == 0) {
118 Token token = pop();
119 String value = unescapeString(token.lexeme);
120 push(ast.simpleStringLiteral(toAnalyzerToken(token), value));
121 } else {
122 List parts = popList(1 + interpolationCount * 2);
123 Token first = parts.first;
124 Token last = parts.last;
125 Quote quote = analyzeQuote(first.lexeme);
126 List<InterpolationElement> elements = <InterpolationElement>[];
127 elements.add(ast.interpolationString(toAnalyzerToken(first),
128 unescapeFirstStringPart(first.lexeme, quote)));
129 for (int i = 1; i < parts.length - 1; i++) {
130 var part = parts[i];
131 if (part is Token) {
132 elements
133 .add(ast.interpolationString(toAnalyzerToken(part), part.lexeme));
134 } else if (part is Expression) {
135 elements.add(ast.interpolationExpression(null, part, null));
136 } else {
137 internalError(
138 "Unexpected part in string interpolation: ${part.runtimeType}");
139 }
140 }
141 elements.add(ast.interpolationString(
142 toAnalyzerToken(last), unescapeLastStringPart(last.lexeme, quote)));
143 push(ast.stringInterpolation(elements));
144 }
145 }
146
147 void handleScript(Token token) {
148 debugEvent("Script");
149 push(ast.scriptTag(toAnalyzerToken(token)));
150 }
151
152 void handleStringJuxtaposition(int literalCount) {
153 debugEvent("StringJuxtaposition");
154 push(ast.adjacentStrings(popList(literalCount)));
155 }
156
157 void endArguments(int count, Token beginToken, Token endToken) {
158 debugEvent("Arguments");
159 List expressions = popList(count);
160 ArgumentList arguments = ast.argumentList(
161 toAnalyzerToken(beginToken), expressions, toAnalyzerToken(endToken));
162 push(ast.methodInvocation(null, null, null, null, arguments));
163 }
164
165 void handleIdentifier(Token token, IdentifierContext context) {
166 debugEvent("handleIdentifier");
167 analyzer.Token analyzerToken = toAnalyzerToken(token);
168
169 if (context.inSymbol) {
170 push(analyzerToken);
171 return;
172 }
173
174 SimpleIdentifier identifier = ast.simpleIdentifier(analyzerToken,
175 isDeclaration: context.inDeclaration);
176 if (context.inLibraryOrPartOfDeclaration) {
177 if (!context.isContinuation) {
178 push([identifier]);
179 } else {
180 push(identifier);
181 }
182 } else if (context == IdentifierContext.enumValueDeclaration) {
183 // TODO(paulberry): analyzer's ASTs allow for enumerated values to have
184 // metadata, but the spec doesn't permit it.
185 List<Annotation> metadata;
186 Comment comment = _toAnalyzerComment(token.precedingComments);
187 push(ast.enumConstantDeclaration(comment, metadata, identifier));
188 } else {
189 if (context.isScopeReference) {
190 String name = token.lexeme;
191 Builder builder = scope.lookup(name, token.charOffset, uri);
192 if (builder != null) {
193 Element element = elementStore[builder];
194 assert(element != null);
195 identifier.staticElement = element;
196 }
197 } else if (context == IdentifierContext.classDeclaration) {
198 className = identifier.name;
199 }
200 push(identifier);
201 }
202 }
203
204 void endSend(Token beginToken, Token endToken) {
205 debugEvent("Send");
206 MethodInvocation arguments = pop();
207 TypeArgumentList typeArguments = pop();
208 if (arguments != null) {
209 doInvocation(endToken, typeArguments, arguments);
210 } else {
211 doPropertyGet(endToken);
212 }
213 }
214
215 void doInvocation(
216 Token token, TypeArgumentList typeArguments, MethodInvocation arguments) {
217 Expression receiver = pop();
218 if (receiver is SimpleIdentifier) {
219 arguments.methodName = receiver;
220 if (typeArguments != null) {
221 arguments.typeArguments = typeArguments;
222 }
223 push(arguments);
224 } else {
225 push(ast.functionExpressionInvocation(
226 receiver, typeArguments, arguments.argumentList));
227 }
228 }
229
230 void doPropertyGet(Token token) {}
231
232 void endExpressionStatement(Token token) {
233 debugEvent("ExpressionStatement");
234 push(ast.expressionStatement(pop(), toAnalyzerToken(token)));
235 }
236
237 @override
238 void handleEmptyFunctionBody(Token semicolon) {
239 debugEvent("EmptyFunctionBody");
240 // TODO(scheglov) Change the parser to not produce these modifiers.
241 pop(); // star
242 pop(); // async
243 push(ast.emptyFunctionBody(toAnalyzerToken(semicolon)));
244 }
245
246 @override
247 void handleEmptyStatement(Token token) {
248 debugEvent("EmptyStatement");
249 push(ast.emptyStatement(toAnalyzerToken(token)));
250 }
251
252 void endBlockFunctionBody(int count, Token beginToken, Token endToken) {
253 debugEvent("BlockFunctionBody");
254 List statements = popList(count);
255 if (beginToken != null) {
256 exitLocalScope();
257 }
258 Block block = ast.block(
259 toAnalyzerToken(beginToken), statements, toAnalyzerToken(endToken));
260 analyzer.Token star = pop();
261 analyzer.Token asyncKeyword = pop();
262 push(ast.blockFunctionBody(asyncKeyword, star, block));
263 }
264
265 void finishFunction(formals, asyncModifier, FunctionBody body) {
266 debugEvent("finishFunction");
267 Statement bodyStatement;
268 if (body is EmptyFunctionBody) {
269 bodyStatement = ast.emptyStatement(body.semicolon);
270 } else if (body is ExpressionFunctionBody) {
271 bodyStatement = ast.returnStatement(null, body.expression, null);
272 } else {
273 bodyStatement = (body as BlockFunctionBody).block;
274 }
275 var kernel = toKernel(bodyStatement, elementStore, library.library, scope);
276 if (member is ProcedureBuilder) {
277 ProcedureBuilder builder = member;
278 builder.body = kernel;
279 } else {
280 internalError("Internal error: expected procedure, but got: $member");
281 }
282 }
283
284 void beginCascade(Token token) {
285 debugEvent("beginCascade");
286 Expression expression = pop();
287 push(token);
288 if (expression is CascadeExpression) {
289 push(expression);
290 } else {
291 push(ast.cascadeExpression(expression, <Expression>[]));
292 }
293 push(NullValue.CascadeReceiver);
294 }
295
296 void endCascade() {
297 debugEvent("Cascade");
298 Expression expression = pop();
299 CascadeExpression receiver = pop();
300 pop(); // Token.
301 receiver.cascadeSections.add(expression);
302 push(receiver);
303 }
304
305 void handleOperator(Token token) {
306 debugEvent("Operator");
307 push(toAnalyzerToken(token));
308 }
309
310 void handleSymbolVoid(Token token) {
311 debugEvent("SymbolVoid");
312 push(toAnalyzerToken(token));
313 }
314
315 void handleBinaryExpression(Token token) {
316 debugEvent("BinaryExpression");
317 if (identical(".", token.stringValue) ||
318 identical("?.", token.stringValue) ||
319 identical("..", token.stringValue)) {
320 doDotExpression(token);
321 } else {
322 Expression right = pop();
323 Expression left = pop();
324 push(ast.binaryExpression(left, toAnalyzerToken(token), right));
325 }
326 }
327
328 void doDotExpression(Token token) {
329 Expression identifierOrInvoke = pop();
330 Expression receiver = pop();
331 if (identifierOrInvoke is SimpleIdentifier) {
332 if (receiver is SimpleIdentifier && identical('.', token.stringValue)) {
333 push(ast.prefixedIdentifier(
334 receiver, toAnalyzerToken(token), identifierOrInvoke));
335 } else {
336 push(ast.propertyAccess(
337 receiver, toAnalyzerToken(token), identifierOrInvoke));
338 }
339 } else if (identifierOrInvoke is MethodInvocation) {
340 assert(identifierOrInvoke.target == null);
341 identifierOrInvoke
342 ..target = receiver
343 ..operator = toAnalyzerToken(token);
344 push(identifierOrInvoke);
345 } else {
346 internalError(
347 "Unhandled property access: ${identifierOrInvoke.runtimeType}");
348 }
349 }
350
351 void handleLiteralInt(Token token) {
352 debugEvent("LiteralInt");
353 push(ast.integerLiteral(toAnalyzerToken(token), int.parse(token.lexeme)));
354 }
355
356 void handleExpressionFunctionBody(Token arrowToken, Token endToken) {
357 debugEvent("ExpressionFunctionBody");
358 Expression expression = pop();
359 analyzer.Token star = pop();
360 analyzer.Token asyncKeyword = pop();
361 assert(star == null);
362 push(ast.expressionFunctionBody(asyncKeyword, toAnalyzerToken(arrowToken),
363 expression, toAnalyzerToken(endToken)));
364 }
365
366 void endReturnStatement(
367 bool hasExpression, Token beginToken, Token endToken) {
368 debugEvent("ReturnStatement");
369 Expression expression = hasExpression ? pop() : null;
370 push(ast.returnStatement(
371 toAnalyzerToken(beginToken), expression, toAnalyzerToken(endToken)));
372 }
373
374 void endIfStatement(Token ifToken, Token elseToken) {
375 Statement elsePart = popIfNotNull(elseToken);
376 Statement thenPart = pop();
377 Expression condition = pop();
378 BeginGroupToken leftParenthesis = ifToken.next;
379 push(ast.ifStatement(
380 toAnalyzerToken(ifToken),
381 toAnalyzerToken(ifToken.next),
382 condition,
383 toAnalyzerToken(leftParenthesis.endGroup),
384 thenPart,
385 toAnalyzerToken(elseToken),
386 elsePart));
387 }
388
389 void prepareInitializers() {
390 debugEvent("prepareInitializers");
391 }
392
393 void handleNoInitializers() {
394 debugEvent("NoInitializers");
395 push(NullValue.ConstructorInitializers);
396 }
397
398 void endInitializers(int count, Token beginToken, Token endToken) {
399 debugEvent("Initializers");
400 push(popList(count));
401 }
402
403 void endVariableInitializer(Token assignmentOperator) {
404 debugEvent("VariableInitializer");
405 assert(assignmentOperator.stringValue == "=");
406 Expression initializer = pop();
407 Identifier identifier = pop();
408 // TODO(ahe): Don't push initializers, instead install them.
409 push(ast.variableDeclaration(
410 identifier, toAnalyzerToken(assignmentOperator), initializer));
411 }
412
413 @override
414 void endWhileStatement(Token whileKeyword, Token endToken) {
415 debugEvent("WhileStatement");
416 Statement body = pop();
417 ParenthesizedExpression condition = pop();
418 exitContinueTarget();
419 exitBreakTarget();
420 push(ast.whileStatement(
421 toAnalyzerToken(whileKeyword),
422 condition.leftParenthesis,
423 condition.expression,
424 condition.rightParenthesis,
425 body));
426 }
427
428 @override
429 void handleNoVariableInitializer(Token token) {
430 debugEvent("NoVariableInitializer");
431 }
432
433 void endInitializedIdentifier(Token nameToken) {
434 debugEvent("InitializedIdentifier");
435 AstNode node = pop();
436 VariableDeclaration variable;
437 // TODO(paulberry): This seems kludgy. It would be preferable if we
438 // could respond to a "handleNoVariableInitializer" event by converting a
439 // SimpleIdentifier into a VariableDeclaration, and then when this code was
440 // reached, node would always be a VariableDeclaration.
441 if (node is VariableDeclaration) {
442 variable = node;
443 } else if (node is SimpleIdentifier) {
444 variable = ast.variableDeclaration(node, null, null);
445 } else {
446 internalError("unhandled identifier: ${node.runtimeType}");
447 }
448 push(variable);
449 scope[variable.name.name] = variable.name.staticElement =
450 new AnalyzerLocalVariableElemment(variable);
451 }
452
453 void endVariablesDeclaration(int count, Token endToken) {
454 debugEvent("VariablesDeclaration");
455 List<VariableDeclaration> variables = popList(count);
456 TypeAnnotation type = pop();
457 pop(); // TODO(paulberry): Modifiers.
458 push(ast.variableDeclarationStatement(
459 ast.variableDeclarationList(null, null, null, type, variables),
460 toAnalyzerToken(endToken)));
461 }
462
463 void handleAssignmentExpression(Token token) {
464 debugEvent("AssignmentExpression");
465 Expression rhs = pop();
466 Expression lhs = pop();
467 push(ast.assignmentExpression(lhs, toAnalyzerToken(token), rhs));
468 }
469
470 void endBlock(int count, Token beginToken, Token endToken) {
471 debugEvent("Block");
472 List<Statement> statements = popList(count) ?? <Statement>[];
473 exitLocalScope();
474 push(ast.block(
475 toAnalyzerToken(beginToken), statements, toAnalyzerToken(endToken)));
476 }
477
478 void endForStatement(Token forKeyword, Token leftSeparator,
479 int updateExpressionCount, Token endToken) {
480 debugEvent("ForStatement");
481 Statement body = pop();
482 List<Expression> updates = popList(updateExpressionCount);
483 Statement conditionStatement = pop();
484 Object initializerPart = pop();
485 exitLocalScope();
486 exitContinueTarget();
487 exitBreakTarget();
488 BeginGroupToken leftParenthesis = forKeyword.next;
489
490 VariableDeclarationList variableList;
491 Expression initializer;
492 if (initializerPart is VariableDeclarationStatement) {
493 variableList = initializerPart.variables;
494 } else {
495 initializer = initializerPart as Expression;
496 }
497
498 Expression condition;
499 analyzer.Token rightSeparator;
500 if (conditionStatement is ExpressionStatement) {
501 condition = conditionStatement.expression;
502 rightSeparator = conditionStatement.semicolon;
503 } else {
504 rightSeparator = (conditionStatement as EmptyStatement).semicolon;
505 }
506
507 push(ast.forStatement(
508 toAnalyzerToken(forKeyword),
509 toAnalyzerToken(leftParenthesis),
510 variableList,
511 initializer,
512 toAnalyzerToken(leftSeparator),
513 condition,
514 rightSeparator,
515 updates,
516 toAnalyzerToken(leftParenthesis.endGroup),
517 body));
518 }
519
520 void handleLiteralList(
521 int count, Token beginToken, Token constKeyword, Token endToken) {
522 debugEvent("LiteralList");
523 List<Expression> expressions = popList(count);
524 TypeArgumentList typeArguments = pop();
525 push(ast.listLiteral(toAnalyzerToken(constKeyword), typeArguments,
526 toAnalyzerToken(beginToken), expressions, toAnalyzerToken(endToken)));
527 }
528
529 void handleAsyncModifier(Token asyncToken, Token starToken) {
530 debugEvent("AsyncModifier");
531 push(toAnalyzerToken(asyncToken) ?? NullValue.FunctionBodyAsyncToken);
532 push(toAnalyzerToken(starToken) ?? NullValue.FunctionBodyStarToken);
533 }
534
535 void endAwaitExpression(Token beginToken, Token endToken) {
536 debugEvent("AwaitExpression");
537 push(ast.awaitExpression(toAnalyzerToken(beginToken), pop()));
538 }
539
540 void handleLiteralBool(Token token) {
541 debugEvent("LiteralBool");
542 bool value = identical(token.stringValue, "true");
543 assert(value || identical(token.stringValue, "false"));
544 push(ast.booleanLiteral(toAnalyzerToken(token), value));
545 }
546
547 void handleLiteralDouble(Token token) {
548 debugEvent("LiteralDouble");
549 push(ast.doubleLiteral(toAnalyzerToken(token), double.parse(token.lexeme)));
550 }
551
552 void handleLiteralNull(Token token) {
553 debugEvent("LiteralNull");
554 push(ast.nullLiteral(toAnalyzerToken(token)));
555 }
556
557 void handleLiteralMap(
558 int count, Token beginToken, Token constKeyword, Token endToken) {
559 debugEvent("LiteralMap");
560 List<MapLiteralEntry> entries = popList(count) ?? <MapLiteralEntry>[];
561 TypeArgumentList typeArguments = pop();
562 push(ast.mapLiteral(toAnalyzerToken(constKeyword), typeArguments,
563 toAnalyzerToken(beginToken), entries, toAnalyzerToken(endToken)));
564 }
565
566 void endLiteralMapEntry(Token colon, Token endToken) {
567 debugEvent("LiteralMapEntry");
568 Expression value = pop();
569 Expression key = pop();
570 push(ast.mapLiteralEntry(key, toAnalyzerToken(colon), value));
571 }
572
573 void endLiteralSymbol(Token hashToken, int tokenCount) {
574 debugEvent("LiteralSymbol");
575 List<analyzer.Token> components = popList(tokenCount);
576 push(ast.symbolLiteral(toAnalyzerToken(hashToken), components));
577 }
578
579 @override
580 void handleSuperExpression(Token token) {
581 debugEvent("SuperExpression");
582 push(ast.superExpression(toAnalyzerToken(token)));
583 }
584
585 @override
586 void handleThisExpression(Token token) {
587 debugEvent("ThisExpression");
588 push(ast.thisExpression(toAnalyzerToken(token)));
589 }
590
591 void handleType(Token beginToken, Token endToken) {
592 debugEvent("Type");
593 TypeArgumentList arguments = pop();
594 Identifier name = pop();
595 // TODO(paulberry,ahe): what if the type doesn't resolve to a class
596 // element? Try to share code with BodyBuilder.builderToFirstExpression.
597 KernelClassElement cls = name.staticElement;
598 push(ast.typeName(name, arguments)..type = cls?.rawType);
599 }
600
601 @override
602 void handleAssertStatement(Token assertKeyword, Token leftParenthesis,
603 Token comma, Token rightParenthesis, Token semicolon) {
604 debugEvent("AssertStatement");
605 Expression message = popIfNotNull(comma);
606 Expression condition = pop();
607 push(ast.assertStatement(
608 toAnalyzerToken(assertKeyword),
609 toAnalyzerToken(leftParenthesis),
610 condition,
611 toAnalyzerToken(comma),
612 message,
613 toAnalyzerToken(rightParenthesis),
614 toAnalyzerToken(semicolon)));
615 }
616
617 void handleAsOperator(Token operator, Token endToken) {
618 debugEvent("AsOperator");
619 TypeAnnotation type = pop();
620 Expression expression = pop();
621 push(ast.asExpression(expression, toAnalyzerToken(operator), type));
622 }
623
624 @override
625 void handleBreakStatement(
626 bool hasTarget, Token breakKeyword, Token semicolon) {
627 debugEvent("BreakStatement");
628 SimpleIdentifier label = hasTarget ? pop() : null;
629 push(ast.breakStatement(
630 toAnalyzerToken(breakKeyword), label, toAnalyzerToken(semicolon)));
631 }
632
633 @override
634 void handleContinueStatement(
635 bool hasTarget, Token continueKeyword, Token semicolon) {
636 debugEvent("ContinueStatement");
637 SimpleIdentifier label = hasTarget ? pop() : null;
638 push(ast.continueStatement(
639 toAnalyzerToken(continueKeyword), label, toAnalyzerToken(semicolon)));
640 }
641
642 void handleIsOperator(Token operator, Token not, Token endToken) {
643 debugEvent("IsOperator");
644 TypeAnnotation type = pop();
645 Expression expression = pop();
646 push(ast.isExpression(
647 expression, toAnalyzerToken(operator), toAnalyzerToken(not), type));
648 }
649
650 void handleConditionalExpression(Token question, Token colon) {
651 debugEvent("ConditionalExpression");
652 Expression elseExpression = pop();
653 Expression thenExpression = pop();
654 Expression condition = pop();
655 push(ast.conditionalExpression(condition, toAnalyzerToken(question),
656 thenExpression, toAnalyzerToken(colon), elseExpression));
657 }
658
659 @override
660 void endRedirectingFactoryBody(Token equalToken, Token endToken) {
661 debugEvent("RedirectingFactoryBody");
662 ConstructorName constructorName = pop();
663 Token starToken = pop();
664 Token asyncToken = pop();
665 push(new _RedirectingFactoryBody(
666 asyncToken, starToken, equalToken, constructorName));
667 }
668
669 @override
670 void endRethrowStatement(Token rethrowToken, Token endToken) {
671 debugEvent("RethrowStatement");
672 RethrowExpression expression =
673 ast.rethrowExpression(toAnalyzerToken(rethrowToken));
674 // TODO(scheglov) According to the specification, 'rethrow' is a statement.
675 push(ast.expressionStatement(expression, toAnalyzerToken(endToken)));
676 }
677
678 void endThrowExpression(Token throwToken, Token endToken) {
679 debugEvent("ThrowExpression");
680 push(ast.throwExpression(toAnalyzerToken(throwToken), pop()));
681 }
682
683 @override
684 void endOptionalFormalParameters(
685 int count, Token beginToken, Token endToken) {
686 debugEvent("OptionalFormalParameters");
687 push(new _OptionalFormalParameters(popList(count), beginToken, endToken));
688 }
689
690 void handleValuedFormalParameter(Token equals, Token token) {
691 debugEvent("ValuedFormalParameter");
692 Expression value = pop();
693 push(new _ParameterDefaultValue(equals, value));
694 }
695
696 void handleFunctionType(Token functionToken, Token semicolon) {
697 debugEvent("FunctionType");
698 FormalParameterList parameters = pop();
699 TypeParameterList typeParameters = pop();
700 TypeAnnotation returnType = pop();
701 push(ast.genericFunctionType(returnType, toAnalyzerToken(functionToken),
702 typeParameters, parameters));
703 }
704
705 void handleFormalParameterWithoutValue(Token token) {
706 debugEvent("FormalParameterWithoutValue");
707 push(NullValue.ParameterDefaultValue);
708 }
709
710 @override
711 void endForInExpression(Token token) {
712 debugEvent("ForInExpression");
713 }
714
715 @override
716 void endForIn(Token awaitToken, Token forToken, Token leftParenthesis,
717 Token inKeyword, Token rightParenthesis, Token endToken) {
718 debugEvent("ForInExpression");
719 Statement body = pop();
720 Expression iterator = pop();
721 Object variableOrDeclaration = pop();
722 exitLocalScope();
723 exitContinueTarget();
724 exitBreakTarget();
725 if (variableOrDeclaration is SimpleIdentifier) {
726 push(ast.forEachStatementWithReference(
727 toAnalyzerToken(awaitToken),
728 toAnalyzerToken(forToken),
729 toAnalyzerToken(leftParenthesis),
730 variableOrDeclaration,
731 toAnalyzerToken(inKeyword),
732 iterator,
733 toAnalyzerToken(rightParenthesis),
734 body));
735 } else {
736 var statement = variableOrDeclaration as VariableDeclarationStatement;
737 VariableDeclarationList variableList = statement.variables;
738 push(ast.forEachStatementWithDeclaration(
739 toAnalyzerToken(awaitToken),
740 toAnalyzerToken(forToken),
741 toAnalyzerToken(leftParenthesis),
742 ast.declaredIdentifier(
743 variableList.documentationComment,
744 variableList.metadata,
745 variableList.keyword,
746 variableList.type,
747 variableList.variables.single.name),
748 toAnalyzerToken(inKeyword),
749 iterator,
750 toAnalyzerToken(rightParenthesis),
751 body));
752 }
753 }
754
755 void endFormalParameter(
756 Token covariantKeyword, Token thisKeyword, FormalParameterType kind) {
757 debugEvent("FormalParameter");
758 _ParameterDefaultValue defaultValue = pop();
759
760 AstNode nameOrFunctionTypedParameter = pop();
761
762 FormalParameter node;
763 SimpleIdentifier name;
764 if (nameOrFunctionTypedParameter is FormalParameter) {
765 node = nameOrFunctionTypedParameter;
766 name = nameOrFunctionTypedParameter.identifier;
767 } else {
768 name = nameOrFunctionTypedParameter;
769 TypeAnnotation type = pop();
770 _Modifiers modifiers = pop();
771 Token keyword = modifiers?.finalConstOrVarKeyword;
772 pop(); // TODO(paulberry): Metadata.
773 Comment comment = pop();
774 if (thisKeyword == null) {
775 node = ast.simpleFormalParameter2(
776 comment: comment,
777 covariantKeyword: toAnalyzerToken(covariantKeyword),
778 keyword: toAnalyzerToken(keyword),
779 type: type,
780 identifier: name);
781 } else {
782 // TODO(scheglov): Ideally the period token should be passed in.
783 Token period = identical('.', thisKeyword.next?.stringValue)
784 ? thisKeyword.next
785 : null;
786 node = ast.fieldFormalParameter2(
787 comment: comment,
788 covariantKeyword: toAnalyzerToken(covariantKeyword),
789 keyword: toAnalyzerToken(keyword),
790 type: type,
791 thisKeyword: toAnalyzerToken(thisKeyword),
792 period: toAnalyzerToken(period),
793 identifier: name);
794 }
795 }
796
797 ParameterKind analyzerKind = _toAnalyzerParameterKind(kind);
798 if (analyzerKind != ParameterKind.REQUIRED) {
799 node = ast.defaultFormalParameter(node, analyzerKind,
800 toAnalyzerToken(defaultValue?.separator), defaultValue?.value);
801 }
802
803 if (name != null) {
804 scope[name.name] =
805 name.staticElement = new AnalyzerParameterElement(node);
806 }
807 push(node);
808 }
809
810 @override
811 void endFunctionTypedFormalParameter(
812 Token covariantKeyword, Token thisKeyword, FormalParameterType kind) {
813 debugEvent("FunctionTypedFormalParameter");
814
815 FormalParameterList formalParameters = pop();
816 TypeParameterList typeParameters = pop();
817 SimpleIdentifier name = pop();
818 TypeAnnotation returnType = pop();
819
820 {
821 _Modifiers modifiers = pop();
822 if (modifiers != null) {
823 // TODO(scheglov): Report error.
824 internalError('Unexpected modifier. Report an error.');
825 }
826 }
827
828 pop(); // TODO(paulberry): Metadata.
829 Comment comment = pop();
830
831 FormalParameter node;
832 if (thisKeyword == null) {
833 node = ast.functionTypedFormalParameter2(
834 comment: comment,
835 covariantKeyword: toAnalyzerToken(covariantKeyword),
836 returnType: returnType,
837 identifier: name,
838 typeParameters: typeParameters,
839 parameters: formalParameters);
840 } else {
841 // TODO(scheglov): Ideally the period token should be passed in.
842 Token period = identical('.', thisKeyword?.next?.stringValue)
843 ? thisKeyword.next
844 : null;
845 node = ast.fieldFormalParameter2(
846 comment: comment,
847 covariantKeyword: toAnalyzerToken(covariantKeyword),
848 type: returnType,
849 thisKeyword: toAnalyzerToken(thisKeyword),
850 period: toAnalyzerToken(period),
851 identifier: name,
852 typeParameters: typeParameters,
853 parameters: formalParameters);
854 }
855
856 scope[name.name] = name.staticElement = new AnalyzerParameterElement(node);
857 push(node);
858 }
859
860 void endFormalParameters(int count, Token beginToken, Token endToken) {
861 debugEvent("FormalParameters");
862 List rawParameters = popList(count) ?? const <Object>[];
863 List<FormalParameter> parameters = <FormalParameter>[];
864 Token leftDelimiter;
865 Token rightDelimiter;
866 for (Object raw in rawParameters) {
867 if (raw is _OptionalFormalParameters) {
868 parameters.addAll(raw.parameters);
869 leftDelimiter = raw.leftDelimiter;
870 rightDelimiter = raw.rightDelimiter;
871 } else {
872 parameters.add(raw as FormalParameter);
873 }
874 }
875 push(ast.formalParameterList(
876 toAnalyzerToken(beginToken),
877 parameters,
878 toAnalyzerToken(leftDelimiter),
879 toAnalyzerToken(rightDelimiter),
880 toAnalyzerToken(endToken)));
881 }
882
883 void handleCatchBlock(Token onKeyword, Token catchKeyword) {
884 debugEvent("CatchBlock");
885 Block body = pop();
886 FormalParameterList catchParameterList = popIfNotNull(catchKeyword);
887 TypeAnnotation type = popIfNotNull(onKeyword);
888 SimpleIdentifier exception;
889 SimpleIdentifier stackTrace;
890 if (catchParameterList != null) {
891 List<FormalParameter> catchParameters = catchParameterList.parameters;
892 if (catchParameters.length > 0) {
893 exception = catchParameters[0].identifier;
894 }
895 if (catchParameters.length > 1) {
896 stackTrace = catchParameters[1].identifier;
897 }
898 }
899 push(ast.catchClause(
900 toAnalyzerToken(onKeyword),
901 type,
902 toAnalyzerToken(catchKeyword),
903 catchParameterList?.leftParenthesis,
904 exception,
905 null,
906 stackTrace,
907 catchParameterList?.rightParenthesis,
908 body));
909 }
910
911 @override
912 void handleFinallyBlock(Token finallyKeyword) {
913 debugEvent("FinallyBlock");
914 // The finally block is popped in "endTryStatement".
915 }
916
917 void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) {
918 Block finallyBlock = popIfNotNull(finallyKeyword);
919 List<CatchClause> catchClauses = popList(catchCount);
920 Block body = pop();
921 push(ast.tryStatement(toAnalyzerToken(tryKeyword), body, catchClauses,
922 toAnalyzerToken(finallyKeyword), finallyBlock));
923 }
924
925 void handleNoExpression(Token token) {
926 debugEvent("NoExpression");
927 push(NullValue.Expression);
928 }
929
930 void handleIndexedExpression(
931 Token openCurlyBracket, Token closeCurlyBracket) {
932 debugEvent("IndexedExpression");
933 Expression index = pop();
934 Expression target = pop();
935 if (target == null) {
936 CascadeExpression receiver = pop();
937 Token token = peek();
938 push(receiver);
939 IndexExpression expression = ast.indexExpressionForCascade(
940 toAnalyzerToken(token),
941 toAnalyzerToken(openCurlyBracket),
942 index,
943 toAnalyzerToken(closeCurlyBracket));
944 assert(expression.isCascaded);
945 push(expression);
946 } else {
947 push(ast.indexExpressionForTarget(
948 target,
949 toAnalyzerToken(openCurlyBracket),
950 index,
951 toAnalyzerToken(closeCurlyBracket)));
952 }
953 }
954
955 void handleUnaryPrefixExpression(Token token) {
956 debugEvent("UnaryPrefixExpression");
957 push(ast.prefixExpression(toAnalyzerToken(token), pop()));
958 }
959
960 void handleUnaryPrefixAssignmentExpression(Token token) {
961 debugEvent("UnaryPrefixAssignmentExpression");
962 push(ast.prefixExpression(toAnalyzerToken(token), pop()));
963 }
964
965 void handleUnaryPostfixAssignmentExpression(Token token) {
966 debugEvent("UnaryPostfixAssignmentExpression");
967 push(ast.postfixExpression(pop(), toAnalyzerToken(token)));
968 }
969
970 void handleModifier(Token token) {
971 debugEvent("Modifier");
972 push(token);
973 }
974
975 void handleModifiers(int count) {
976 debugEvent("Modifiers");
977 if (count == 0) {
978 push(NullValue.Modifiers);
979 } else {
980 push(new _Modifiers(popList(count)));
981 }
982 }
983
984 void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) {
985 // TODO(paulberry): set up scopes properly to resolve parameters and type
986 // variables.
987 debugEvent("TopLevelMethod");
988 FunctionBody body = pop();
989 FormalParameterList parameters = pop();
990 TypeParameterList typeParameters = pop();
991 SimpleIdentifier name = pop();
992 analyzer.Token propertyKeyword = toAnalyzerToken(getOrSet);
993 TypeAnnotation returnType = pop();
994 _Modifiers modifiers = pop();
995 Token externalKeyword = modifiers?.externalKeyword;
996 List<Annotation> metadata = pop();
997 Comment comment = pop();
998 push(ast.functionDeclaration(
999 comment,
1000 metadata,
1001 toAnalyzerToken(externalKeyword),
1002 returnType,
1003 propertyKeyword,
1004 name,
1005 ast.functionExpression(typeParameters, parameters, body)));
1006 }
1007
1008 @override
1009 void endTopLevelDeclaration(Token token) {
1010 debugEvent("TopLevelDeclaration");
1011 }
1012
1013 @override
1014 void endCompilationUnit(int count, Token token) {
1015 debugEvent("CompilationUnit");
1016 analyzer.Token beginToken = null; // TODO(paulberry)
1017 ScriptTag scriptTag = null;
1018 var directives = <Directive>[];
1019 var declarations = <CompilationUnitMember>[];
1020 analyzer.Token endToken = null; // TODO(paulberry)
1021 List<Object> elements = popList(count);
1022 if (elements != null) {
1023 for (AstNode node in elements) {
1024 if (node is ScriptTag) {
1025 scriptTag = node;
1026 } else if (node is Directive) {
1027 directives.add(node);
1028 } else if (node is CompilationUnitMember) {
1029 declarations.add(node);
1030 } else {
1031 internalError(
1032 'Unrecognized compilation unit member: ${node.runtimeType}');
1033 }
1034 }
1035 }
1036 push(ast.compilationUnit(
1037 beginToken, scriptTag, directives, declarations, endToken));
1038 }
1039
1040 void endImport(Token importKeyword, Token deferredKeyword, Token asKeyword,
1041 Token semicolon) {
1042 debugEvent("Import");
1043 List<Combinator> combinators = pop();
1044 SimpleIdentifier prefix;
1045 if (asKeyword != null) prefix = pop();
1046 List<Configuration> configurations = pop();
1047 StringLiteral uri = pop();
1048 List<Annotation> metadata = pop();
1049 assert(metadata == null); // TODO(paulberry): fix.
1050 Comment comment = pop();
1051 push(ast.importDirective(
1052 comment,
1053 metadata,
1054 toAnalyzerToken(importKeyword),
1055 uri,
1056 configurations,
1057 toAnalyzerToken(deferredKeyword),
1058 toAnalyzerToken(asKeyword),
1059 prefix,
1060 combinators,
1061 toAnalyzerToken(semicolon)));
1062 }
1063
1064 void endExport(Token exportKeyword, Token semicolon) {
1065 debugEvent("Export");
1066 List<Combinator> combinators = pop();
1067 List<Configuration> configurations = pop();
1068 StringLiteral uri = pop();
1069 List<Annotation> metadata = pop();
1070 assert(metadata == null);
1071 Comment comment = pop();
1072 push(ast.exportDirective(comment, metadata, toAnalyzerToken(exportKeyword),
1073 uri, configurations, combinators, toAnalyzerToken(semicolon)));
1074 }
1075
1076 @override
1077 void endDottedName(int count, Token firstIdentifier) {
1078 debugEvent("DottedName");
1079 List<SimpleIdentifier> components = popList(count);
1080 push(ast.dottedName(components));
1081 }
1082
1083 @override
1084 void endDoWhileStatement(
1085 Token doKeyword, Token whileKeyword, Token semicolon) {
1086 debugEvent("DoWhileStatement");
1087 ParenthesizedExpression condition = pop();
1088 Statement body = pop();
1089 exitContinueTarget();
1090 exitBreakTarget();
1091 push(ast.doStatement(
1092 toAnalyzerToken(doKeyword),
1093 body,
1094 toAnalyzerToken(whileKeyword),
1095 condition.leftParenthesis,
1096 condition.expression,
1097 condition.rightParenthesis,
1098 toAnalyzerToken(semicolon)));
1099 }
1100
1101 void endConditionalUri(Token ifKeyword, Token equalitySign) {
1102 debugEvent("ConditionalUri");
1103 StringLiteral libraryUri = pop();
1104 // TODO(paulberry,ahe): the parser should report the right paren token to
1105 // the listener.
1106 Token rightParen = null;
1107 StringLiteral value;
1108 if (equalitySign != null) {
1109 value = pop();
1110 }
1111 DottedName name = pop();
1112 // TODO(paulberry,ahe): what if there is no `(` token due to an error in the
1113 // file being parsed? It seems like we need the parser to do adequate error
1114 // recovery and then report both the ifKeyword and leftParen tokens to the
1115 // listener.
1116 Token leftParen = ifKeyword.next;
1117 push(ast.configuration(
1118 toAnalyzerToken(ifKeyword),
1119 toAnalyzerToken(leftParen),
1120 name,
1121 toAnalyzerToken(equalitySign),
1122 value,
1123 toAnalyzerToken(rightParen),
1124 libraryUri));
1125 }
1126
1127 @override
1128 void endConditionalUris(int count) {
1129 debugEvent("ConditionalUris");
1130 push(popList(count) ?? NullValue.ConditionalUris);
1131 }
1132
1133 @override
1134 void endIdentifierList(int count) {
1135 debugEvent("IdentifierList");
1136 push(popList(count) ?? NullValue.IdentifierList);
1137 }
1138
1139 @override
1140 void endShow(Token showKeyword) {
1141 debugEvent("Show");
1142 List<SimpleIdentifier> shownNames = pop();
1143 push(ast.showCombinator(toAnalyzerToken(showKeyword), shownNames));
1144 }
1145
1146 @override
1147 void endHide(Token hideKeyword) {
1148 debugEvent("Hide");
1149 List<SimpleIdentifier> hiddenNames = pop();
1150 push(ast.hideCombinator(toAnalyzerToken(hideKeyword), hiddenNames));
1151 }
1152
1153 @override
1154 void endTypeList(int count) {
1155 debugEvent("TypeList");
1156 push(popList(count) ?? NullValue.TypeList);
1157 }
1158
1159 @override
1160 void endClassBody(int memberCount, Token beginToken, Token endToken) {
1161 debugEvent("ClassBody");
1162 push(new _ClassBody(
1163 beginToken, popList(memberCount) ?? <ClassMember>[], endToken));
1164 }
1165
1166 @override
1167 void endClassDeclaration(
1168 int interfacesCount,
1169 Token beginToken,
1170 Token classKeyword,
1171 Token extendsKeyword,
1172 Token implementsKeyword,
1173 Token endToken) {
1174 debugEvent("ClassDeclaration");
1175 _ClassBody body = pop();
1176 ImplementsClause implementsClause;
1177 if (implementsKeyword != null) {
1178 List<TypeName> interfaces = popList(interfacesCount);
1179 implementsClause =
1180 ast.implementsClause(toAnalyzerToken(implementsKeyword), interfaces);
1181 }
1182 ExtendsClause extendsClause;
1183 WithClause withClause;
1184 var supertype = pop();
1185 if (supertype == null) {
1186 // No extends clause
1187 } else if (supertype is TypeName) {
1188 extendsClause =
1189 ast.extendsClause(toAnalyzerToken(extendsKeyword), supertype);
1190 } else if (supertype is _MixinApplication) {
1191 extendsClause = ast.extendsClause(
1192 toAnalyzerToken(extendsKeyword), supertype.supertype);
1193 withClause = ast.withClause(
1194 toAnalyzerToken(supertype.withKeyword), supertype.mixinTypes);
1195 } else {
1196 internalError('Unexpected kind of supertype ${supertype.runtimeType}');
1197 }
1198 TypeParameterList typeParameters = pop();
1199 SimpleIdentifier name = pop();
1200 assert(className == name.name);
1201 className = null;
1202 _Modifiers modifiers = pop();
1203 Token abstractKeyword = modifiers?.abstractKeyword;
1204 List<Annotation> metadata = pop();
1205 Comment comment = pop();
1206 push(ast.classDeclaration(
1207 comment,
1208 metadata,
1209 toAnalyzerToken(abstractKeyword),
1210 toAnalyzerToken(classKeyword),
1211 name,
1212 typeParameters,
1213 extendsClause,
1214 withClause,
1215 implementsClause,
1216 toAnalyzerToken(body.beginToken),
1217 body.members,
1218 toAnalyzerToken(body.endToken)));
1219 }
1220
1221 @override
1222 void endMixinApplication(Token withKeyword) {
1223 debugEvent("MixinApplication");
1224 List<TypeName> mixinTypes = pop();
1225 TypeName supertype = pop();
1226 push(new _MixinApplication(supertype, withKeyword, mixinTypes));
1227 }
1228
1229 @override
1230 void endNamedMixinApplication(Token beginToken, Token classKeyword,
1231 Token equalsToken, Token implementsKeyword, Token endToken) {
1232 debugEvent("NamedMixinApplication");
1233 ImplementsClause implementsClause;
1234 if (implementsKeyword != null) {
1235 List<TypeName> interfaces = pop();
1236 implementsClause =
1237 ast.implementsClause(toAnalyzerToken(implementsKeyword), interfaces);
1238 }
1239 _MixinApplication mixinApplication = pop();
1240 var superclass = mixinApplication.supertype;
1241 var withClause = ast.withClause(
1242 toAnalyzerToken(mixinApplication.withKeyword),
1243 mixinApplication.mixinTypes);
1244 analyzer.Token equals = toAnalyzerToken(equalsToken);
1245 TypeParameterList typeParameters = pop();
1246 SimpleIdentifier name = pop();
1247 _Modifiers modifiers = pop();
1248 Token abstractKeyword = modifiers?.abstractKeyword;
1249 List<Annotation> metadata = pop();
1250 Comment comment = pop();
1251 push(ast.classTypeAlias(
1252 comment,
1253 metadata,
1254 toAnalyzerToken(classKeyword),
1255 name,
1256 typeParameters,
1257 equals,
1258 toAnalyzerToken(abstractKeyword),
1259 superclass,
1260 withClause,
1261 implementsClause,
1262 toAnalyzerToken(endToken)));
1263 }
1264
1265 @override
1266 void endLibraryName(Token libraryKeyword, Token semicolon) {
1267 debugEvent("LibraryName");
1268 List<SimpleIdentifier> libraryName = pop();
1269 var name = ast.libraryIdentifier(libraryName);
1270 List<Annotation> metadata = pop();
1271 Comment comment = pop();
1272 push(ast.libraryDirective(comment, metadata,
1273 toAnalyzerToken(libraryKeyword), name, toAnalyzerToken(semicolon)));
1274 }
1275
1276 @override
1277 void handleQualified(Token period) {
1278 SimpleIdentifier identifier = pop();
1279 var prefix = pop();
1280 if (prefix is List) {
1281 // We're just accumulating components into a list.
1282 prefix.add(identifier);
1283 push(prefix);
1284 } else if (prefix is SimpleIdentifier) {
1285 // TODO(paulberry): resolve [identifier]. Note that BodyBuilder handles
1286 // this situation using SendAccessor.
1287 push(ast.prefixedIdentifier(prefix, toAnalyzerToken(period), identifier));
1288 } else {
1289 // TODO(paulberry): implement.
1290 logEvent('Qualified with >1 dot');
1291 }
1292 }
1293
1294 @override
1295 void endPart(Token partKeyword, Token semicolon) {
1296 debugEvent("Part");
1297 StringLiteral uri = pop();
1298 List<Annotation> metadata = pop();
1299 Comment comment = pop();
1300 push(ast.partDirective(comment, metadata, toAnalyzerToken(partKeyword), uri,
1301 toAnalyzerToken(semicolon)));
1302 }
1303
1304 @override
1305 void endPartOf(Token partKeyword, Token semicolon, bool hasName) {
1306 debugEvent("PartOf");
1307 List<SimpleIdentifier> libraryName = pop();
1308 var name = ast.libraryIdentifier(libraryName);
1309 StringLiteral uri = null; // TODO(paulberry)
1310 // TODO(paulberry,ahe): seems hacky. It would be nice if the parser passed
1311 // in a reference to the "of" keyword.
1312 var ofKeyword = partKeyword.next;
1313 List<Annotation> metadata = pop();
1314 Comment comment = pop();
1315 push(ast.partOfDirective(comment, metadata, toAnalyzerToken(partKeyword),
1316 toAnalyzerToken(ofKeyword), uri, name, toAnalyzerToken(semicolon)));
1317 }
1318
1319 void endUnnamedFunction(Token token) {
1320 // TODO(paulberry): set up scopes properly to resolve parameters and type
1321 // variables. Note that this is tricky due to the handling of initializers
1322 // in constructors, so the logic should be shared with BodyBuilder as much
1323 // as possible.
1324 debugEvent("UnnamedFunction");
1325 FunctionBody body = pop();
1326 FormalParameterList parameters = pop();
1327 TypeParameterList typeParameters = pop();
1328 push(ast.functionExpression(typeParameters, parameters, body));
1329 }
1330
1331 @override
1332 void handleNoFieldInitializer(Token token) {
1333 debugEvent("NoFieldInitializer");
1334 SimpleIdentifier name = pop();
1335 push(ast.variableDeclaration(name, null, null));
1336 }
1337
1338 @override
1339 void endFactoryMethod(
1340 Token beginToken, Token factoryKeyword, Token semicolon) {
1341 debugEvent("FactoryMethod");
1342
1343 FunctionBody body;
1344 Token separator;
1345 ConstructorName redirectedConstructor;
1346 Object bodyObject = pop();
1347 if (bodyObject is FunctionBody) {
1348 body = bodyObject;
1349 } else if (bodyObject is _RedirectingFactoryBody) {
1350 separator = bodyObject.equalToken;
1351 redirectedConstructor = bodyObject.constructorName;
1352 body = ast.emptyFunctionBody(toAnalyzerToken(semicolon));
1353 } else {
1354 internalError('Unexpected body object: ${bodyObject.runtimeType}');
1355 }
1356
1357 FormalParameterList parameters = pop();
1358 ConstructorName constructorName = pop();
1359 _Modifiers modifiers = pop();
1360 List<Annotation> metadata = pop();
1361 Comment comment = pop();
1362 push(ast.constructorDeclaration(
1363 comment,
1364 metadata,
1365 toAnalyzerToken(modifiers?.externalKeyword),
1366 toAnalyzerToken(modifiers?.finalConstOrVarKeyword),
1367 toAnalyzerToken(factoryKeyword),
1368 constructorName.type.name,
1369 constructorName.period,
1370 constructorName.name,
1371 parameters,
1372 toAnalyzerToken(separator),
1373 null,
1374 redirectedConstructor,
1375 body));
1376 }
1377
1378 void endFieldInitializer(Token assignment) {
1379 debugEvent("FieldInitializer");
1380 Expression initializer = pop();
1381 SimpleIdentifier name = pop();
1382 push(ast.variableDeclaration(
1383 name, toAnalyzerToken(assignment), initializer));
1384 }
1385
1386 void endTopLevelFields(int count, Token beginToken, Token endToken) {
1387 debugEvent("TopLevelFields");
1388 List<VariableDeclaration> variables = popList(count);
1389 TypeAnnotation type = pop();
1390 _Modifiers modifiers = pop();
1391 Token keyword = modifiers?.finalConstOrVarKeyword;
1392 var variableList = ast.variableDeclarationList(
1393 null, null, toAnalyzerToken(keyword), type, variables);
1394 List<Annotation> metadata = pop();
1395 Comment comment = pop();
1396 push(ast.topLevelVariableDeclaration(
1397 comment, metadata, variableList, toAnalyzerToken(endToken)));
1398 }
1399
1400 @override
1401 void endTypeVariable(Token token, Token extendsOrSuper) {
1402 // TODO(paulberry): set up scopes properly to resolve parameters and type
1403 // variables. Note that this is tricky due to the handling of initializers
1404 // in constructors, so the logic should be shared with BodyBuilder as much
1405 // as possible.
1406 debugEvent("TypeVariable");
1407 TypeAnnotation bound = pop();
1408 SimpleIdentifier name = pop();
1409 List<Annotation> metadata = pop();
1410 Comment comment = pop();
1411 push(ast.typeParameter(
1412 comment, metadata, name, toAnalyzerToken(extendsOrSuper), bound));
1413 }
1414
1415 @override
1416 void endTypeVariables(int count, Token beginToken, Token endToken) {
1417 debugEvent("TypeVariables");
1418 List<TypeParameter> typeParameters = popList(count);
1419 push(ast.typeParameterList(toAnalyzerToken(beginToken), typeParameters,
1420 toAnalyzerToken(endToken)));
1421 }
1422
1423 @override
1424 void endMethod(Token getOrSet, Token beginToken, Token endToken) {
1425 debugEvent("Method");
1426 FunctionBody body = pop();
1427 ConstructorName redirectedConstructor = null; // TODO(paulberry)
1428 List<Object> initializerObjects = pop() ?? const [];
1429 Token separator = null; // TODO(paulberry)
1430 FormalParameterList parameters = pop();
1431 TypeParameterList typeParameters = pop(); // TODO(paulberry)
1432 var name = pop();
1433 TypeAnnotation returnType = pop(); // TODO(paulberry)
1434 _Modifiers modifiers = pop();
1435 List<Annotation> metadata = pop();
1436 Comment comment = pop();
1437
1438 var initializers = <ConstructorInitializer>[];
1439 for (Object initializerObject in initializerObjects) {
1440 if (initializerObject is AssignmentExpression) {
1441 analyzer.Token thisKeyword;
1442 analyzer.Token period;
1443 SimpleIdentifier fieldName;
1444 Expression left = initializerObject.leftHandSide;
1445 if (left is PropertyAccess) {
1446 var thisExpression = left.target as ThisExpression;
1447 thisKeyword = thisExpression.thisKeyword;
1448 period = left.operator;
1449 fieldName = left.propertyName;
1450 } else {
1451 fieldName = left as SimpleIdentifier;
1452 }
1453 initializers.add(ast.constructorFieldInitializer(
1454 thisKeyword,
1455 period,
1456 fieldName,
1457 initializerObject.operator,
1458 initializerObject.rightHandSide));
1459 }
1460 }
1461
1462 void constructor(SimpleIdentifier returnType, analyzer.Token period,
1463 SimpleIdentifier name) {
1464 push(ast.constructorDeclaration(
1465 comment,
1466 metadata,
1467 toAnalyzerToken(modifiers?.externalKeyword),
1468 toAnalyzerToken(modifiers?.finalConstOrVarKeyword),
1469 null, // TODO(paulberry): factoryKeyword
1470 ast.simpleIdentifier(returnType.token),
1471 period,
1472 name,
1473 parameters,
1474 toAnalyzerToken(separator),
1475 initializers,
1476 redirectedConstructor,
1477 body));
1478 }
1479
1480 void method(Token operatorKeyword, SimpleIdentifier name) {
1481 push(ast.methodDeclaration(
1482 comment,
1483 metadata,
1484 toAnalyzerToken(modifiers?.externalKeyword),
1485 toAnalyzerToken(
1486 modifiers?.abstractKeyword ?? modifiers?.staticKeyword),
1487 returnType,
1488 toAnalyzerToken(getOrSet),
1489 toAnalyzerToken(operatorKeyword),
1490 name,
1491 typeParameters,
1492 parameters,
1493 body));
1494 }
1495
1496 if (name is SimpleIdentifier) {
1497 if (name.name == className) {
1498 constructor(name, null, null);
1499 } else {
1500 method(null, name);
1501 }
1502 } else if (name is _OperatorName) {
1503 method(name.operatorKeyword, name.name);
1504 } else if (name is PrefixedIdentifier) {
1505 constructor(name.prefix, name.period, name.identifier);
1506 } else {
1507 throw new UnimplementedError();
1508 }
1509 }
1510
1511 @override
1512 void endMember() {
1513 debugEvent("Member");
1514 }
1515
1516 @override
1517 void handleVoidKeyword(Token token) {
1518 debugEvent("VoidKeyword");
1519 // TODO(paulberry): is this sufficient, or do we need to hook the "void"
1520 // keyword up to an element?
1521 handleIdentifier(token, IdentifierContext.typeReference);
1522 handleNoTypeArguments(token);
1523 handleType(token, token);
1524 }
1525
1526 @override
1527 void endFunctionTypeAlias(
1528 Token typedefKeyword, Token equals, Token endToken) {
1529 debugEvent("FunctionTypeAlias");
1530 if (equals == null) {
1531 FormalParameterList parameters = pop();
1532 TypeParameterList typeParameters = pop();
1533 SimpleIdentifier name = pop();
1534 TypeAnnotation returnType = pop();
1535 List<Annotation> metadata = pop();
1536 Comment comment = pop();
1537 push(ast.functionTypeAlias(
1538 comment,
1539 metadata,
1540 toAnalyzerToken(typedefKeyword),
1541 returnType,
1542 name,
1543 typeParameters,
1544 parameters,
1545 toAnalyzerToken(endToken)));
1546 } else {
1547 TypeAnnotation type = pop();
1548 TypeParameterList templateParameters = pop();
1549 SimpleIdentifier name = pop();
1550 List<Annotation> metadata = pop();
1551 Comment comment = pop();
1552 if (type is! GenericFunctionType) {
1553 // TODO(paulberry) Generate an error and recover (better than
1554 // this).
1555 type = null;
1556 }
1557 push(ast.genericTypeAlias(
1558 comment,
1559 metadata,
1560 toAnalyzerToken(typedefKeyword),
1561 name,
1562 templateParameters,
1563 toAnalyzerToken(equals),
1564 type,
1565 toAnalyzerToken(endToken)));
1566 }
1567 }
1568
1569 @override
1570 void endEnum(Token enumKeyword, Token endBrace, int count) {
1571 debugEvent("Enum");
1572 List<EnumConstantDeclaration> constants = popList(count);
1573 // TODO(paulberry,ahe): the parser should pass in the openBrace token.
1574 var openBrace = enumKeyword.next.next as BeginGroupToken;
1575 // TODO(paulberry): what if the '}' is missing and the parser has performed
1576 // error recovery?
1577 Token closeBrace = openBrace.endGroup;
1578 SimpleIdentifier name = pop();
1579 List<Annotation> metadata = pop();
1580 Comment comment = pop();
1581 push(ast.enumDeclaration(
1582 comment,
1583 metadata,
1584 toAnalyzerToken(enumKeyword),
1585 name,
1586 toAnalyzerToken(openBrace),
1587 constants,
1588 toAnalyzerToken(closeBrace)));
1589 }
1590
1591 @override
1592 void endTypeArguments(int count, Token beginToken, Token endToken) {
1593 debugEvent("TypeArguments");
1594 List<TypeAnnotation> arguments = popList(count);
1595 push(ast.typeArgumentList(
1596 toAnalyzerToken(beginToken), arguments, toAnalyzerToken(endToken)));
1597 }
1598
1599 @override
1600 void endFields(
1601 int count, Token covariantKeyword, Token beginToken, Token endToken) {
1602 debugEvent("Fields");
1603 List<VariableDeclaration> variables = popList(count);
1604 TypeAnnotation type = pop();
1605 _Modifiers modifiers = pop();
1606 var variableList = ast.variableDeclarationList(null, null,
1607 toAnalyzerToken(modifiers?.finalConstOrVarKeyword), type, variables);
1608 List<Annotation> metadata = pop();
1609 Comment comment = pop();
1610 push(ast.fieldDeclaration2(
1611 comment: comment,
1612 metadata: metadata,
1613 covariantKeyword: toAnalyzerToken(covariantKeyword),
1614 staticKeyword: toAnalyzerToken(modifiers?.staticKeyword),
1615 fieldList: variableList,
1616 semicolon: toAnalyzerToken(endToken)));
1617 }
1618
1619 @override
1620 void handleOperatorName(Token operatorKeyword, Token token) {
1621 debugEvent("OperatorName");
1622 push(new _OperatorName(operatorKeyword,
1623 ast.simpleIdentifier(toAnalyzerToken(token), isDeclaration: true)));
1624 }
1625
1626 @override
1627 void beginMetadataStar(Token token) {
1628 debugEvent("beginMetadataStar");
1629 if (token.precedingComments != null) {
1630 push(_toAnalyzerComment(token.precedingComments));
1631 } else {
1632 push(NullValue.Comments);
1633 }
1634 }
1635
1636 @override
1637 void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
1638 debugEvent("Metadata");
1639 MethodInvocation invocation = pop();
1640 SimpleIdentifier constructorName = periodBeforeName != null ? pop() : null;
1641 pop(); // Type arguments, not allowed.
1642 Identifier name = pop();
1643 push(ast.annotation(
1644 toAnalyzerToken(beginToken),
1645 name,
1646 toAnalyzerToken(periodBeforeName),
1647 constructorName,
1648 invocation?.argumentList));
1649 }
1650
1651 ParameterKind _toAnalyzerParameterKind(FormalParameterType type) {
1652 if (type == FormalParameterType.POSITIONAL) {
1653 return ParameterKind.POSITIONAL;
1654 } else if (type == FormalParameterType.NAMED) {
1655 return ParameterKind.NAMED;
1656 } else {
1657 return ParameterKind.REQUIRED;
1658 }
1659 }
1660
1661 Comment _toAnalyzerComment(Token comments) {
1662 if (comments == null) return null;
1663
1664 // This is temporary placeholder code to get tests to pass.
1665 // TODO(paulberry): after analyzer and fasta token representations are
1666 // unified, refactor the code in analyzer's parser that handles
1667 // documentation comments so that it is reusable, and reuse it here.
1668 // See Parser.parseCommentAndMetadata
1669 var tokens = <analyzer.Token>[toAnalyzerCommentToken(comments)];
1670 var references = <CommentReference>[];
1671 return ast.documentationComment(tokens, references);
1672 }
1673 }
1674
1675 /// Data structure placed on the stack to represent a class body.
1676 ///
1677 /// This is needed because analyzer has no separate AST representation of a
1678 /// class body; it simply stores all of the relevant data in the
1679 /// [ClassDeclaration] object.
1680 class _ClassBody {
1681 final Token beginToken;
1682
1683 final List<ClassMember> members;
1684
1685 final Token endToken;
1686
1687 _ClassBody(this.beginToken, this.members, this.endToken);
1688 }
1689
1690 /// Data structure placed on the stack to represent a mixin application (a
1691 /// structure of the form "A with B, C").
1692 ///
1693 /// This is needed because analyzer has no separate AST representation of a
1694 /// mixin application; it simply stores all of the relevant data in the
1695 /// [ClassDeclaration] or [ClassTypeAlias] object.
1696 class _MixinApplication {
1697 final TypeName supertype;
1698
1699 final Token withKeyword;
1700
1701 final List<TypeName> mixinTypes;
1702
1703 _MixinApplication(this.supertype, this.withKeyword, this.mixinTypes);
1704 }
1705
1706 /// Data structure placed on the stack to represent the default parameter
1707 /// value with the separator token.
1708 class _ParameterDefaultValue {
1709 final Token separator;
1710 final Expression value;
1711
1712 _ParameterDefaultValue(this.separator, this.value);
1713 }
1714
1715 /// Data structure placed on stack to represent the redirected constructor.
1716 class _RedirectingFactoryBody {
1717 final Token asyncKeyword;
1718 final Token starKeyword;
1719 final Token equalToken;
1720 final ConstructorName constructorName;
1721
1722 _RedirectingFactoryBody(this.asyncKeyword, this.starKeyword, this.equalToken,
1723 this.constructorName);
1724 }
1725
1726 /// Data structure placed on the stack as a container for optional parameters.
1727 class _OptionalFormalParameters {
1728 final List<FormalParameter> parameters;
1729 final Token leftDelimiter;
1730 final Token rightDelimiter;
1731
1732 _OptionalFormalParameters(
1733 this.parameters, this.leftDelimiter, this.rightDelimiter);
1734 }
1735
1736 /// Data structure placed on the stack to represent the keyword "operator"
1737 /// followed by a token.
1738 class _OperatorName {
1739 final Token operatorKeyword;
1740 final SimpleIdentifier name;
1741
1742 _OperatorName(this.operatorKeyword, this.name);
1743 }
1744
1745 /// Data structure placed on the stack to represent a non-empty sequence
1746 /// of modifiers.
1747 class _Modifiers {
1748 Token abstractKeyword;
1749 Token externalKeyword;
1750 Token finalConstOrVarKeyword;
1751 Token staticKeyword;
1752
1753 _Modifiers(List<Token> modifierTokens) {
1754 // No need to check the order and uniqueness of the modifiers, or that
1755 // disallowed modifiers are not used; the parser should do that.
1756 // TODO(paulberry,ahe): implement the necessary logic in the parser.
1757 for (var token in modifierTokens) {
1758 var s = token.lexeme;
1759 if (identical('abstract', s)) {
1760 abstractKeyword = token;
1761 } else if (identical('const', s)) {
1762 finalConstOrVarKeyword = token;
1763 } else if (identical('external', s)) {
1764 externalKeyword = token;
1765 } else if (identical('final', s)) {
1766 finalConstOrVarKeyword = token;
1767 } else if (identical('static', s)) {
1768 staticKeyword = token;
1769 } else if (identical('var', s)) {
1770 finalConstOrVarKeyword = token;
1771 } else {
1772 internalError('Unhandled modifier: $s');
1773 }
1774 }
1775 }
1776 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698