| OLD | NEW |
| (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 } | |
| OLD | NEW |