Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2017, 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 import 'package:front_end/src/fasta/errors.dart'; | |
| 6 import 'package:front_end/src/fasta/parser/identifier_context.dart'; | |
| 7 import 'package:front_end/src/fasta/parser/parser.dart'; | |
| 8 import 'package:front_end/src/fasta/scanner/token.dart'; | |
| 9 import 'package:front_end/src/fasta/source/stack_listener.dart'; | |
| 10 | |
| 11 /// "Mini AST" representation of a declaration which can accept annotations. | |
| 12 class AnnotatedNode { | |
| 13 final Comment documentationComment; | |
| 14 | |
| 15 final List<Annotation> metadata; | |
| 16 | |
| 17 AnnotatedNode(this.documentationComment, List<Annotation> metadata) | |
| 18 : metadata = metadata ?? const []; | |
| 19 } | |
| 20 | |
| 21 /// "Mini AST" representation of an annotation. | |
| 22 class Annotation { | |
| 23 final String name; | |
| 24 | |
| 25 final String constructorName; | |
| 26 | |
| 27 final List<Expression> arguments; | |
| 28 | |
| 29 Annotation(this.name, this.constructorName, this.arguments); | |
| 30 } | |
| 31 | |
| 32 /// "Mini AST" representation of a class declaration. | |
| 33 class ClassDeclaration extends CompilationUnitMember { | |
| 34 final String name; | |
| 35 | |
| 36 final TypeName superclass; | |
| 37 | |
| 38 final List<ClassMember> members; | |
| 39 | |
| 40 ClassDeclaration(Comment documentationComment, List<Annotation> metadata, | |
| 41 this.name, this.superclass, this.members) | |
| 42 : super(documentationComment, metadata); | |
| 43 } | |
| 44 | |
| 45 /// "Mini AST" representation of a class member. | |
| 46 class ClassMember extends AnnotatedNode { | |
| 47 ClassMember(Comment documentationComment, List<Annotation> metadata) | |
| 48 : super(documentationComment, metadata); | |
| 49 } | |
| 50 | |
| 51 /// "Mini AST" representation of a comment. | |
| 52 class Comment { | |
| 53 final bool isDocumentation; | |
| 54 | |
| 55 final List<Token> tokens; | |
| 56 | |
| 57 factory Comment(Token commentToken) { | |
| 58 var tokens = <Token>[]; | |
| 59 bool isDocumentation = false; | |
| 60 while (commentToken != null) { | |
| 61 if (commentToken.lexeme.startsWith('/**') || | |
| 62 commentToken.lexeme.startsWith('///')) { | |
| 63 isDocumentation = true; | |
| 64 } | |
| 65 tokens.add(commentToken); | |
| 66 commentToken = commentToken.next; | |
| 67 } | |
| 68 return new Comment._(isDocumentation, tokens); | |
| 69 } | |
| 70 | |
| 71 Comment._(this.isDocumentation, this.tokens); | |
| 72 } | |
| 73 | |
| 74 /// "Mini AST" representation of a CompilationUnit. | |
| 75 class CompilationUnit { | |
| 76 final declarations = <CompilationUnitMember>[]; | |
| 77 } | |
| 78 | |
| 79 /// "Mini AST" representation of a top level member of a compilation unit. | |
| 80 class CompilationUnitMember extends AnnotatedNode { | |
| 81 CompilationUnitMember(Comment documentationComment, List<Annotation> metadata) | |
| 82 : super(documentationComment, metadata); | |
| 83 } | |
| 84 | |
| 85 /// "Mini AST" representation of a constructor declaration. | |
| 86 class ConstructorDeclaration extends ClassMember { | |
| 87 final ConstructorReference name; | |
| 88 | |
| 89 ConstructorDeclaration( | |
| 90 Comment documentationComment, List<Annotation> metadata, this.name) | |
| 91 : super(documentationComment, metadata); | |
| 92 } | |
| 93 | |
| 94 /// "Mini AST" representation of a constructor reference. | |
| 95 class ConstructorReference { | |
| 96 final String name; | |
| 97 | |
| 98 final String constructorName; | |
| 99 | |
| 100 ConstructorReference(this.name, this.constructorName); | |
| 101 } | |
| 102 | |
| 103 /// "Mini AST" representation of an individual enum constant in an enum | |
| 104 /// declaration. | |
| 105 class EnumConstantDeclaration extends AnnotatedNode { | |
| 106 final String name; | |
| 107 | |
| 108 EnumConstantDeclaration( | |
| 109 Comment documentationComment, List<Annotation> metadata, this.name) | |
| 110 : super(documentationComment, metadata); | |
| 111 } | |
| 112 | |
| 113 /// "Mini AST" representation of an enum declaration. | |
| 114 class EnumDeclaration extends CompilationUnitMember { | |
| 115 final String name; | |
| 116 | |
| 117 final List<EnumConstantDeclaration> constants; | |
| 118 | |
| 119 EnumDeclaration(Comment documentationComment, List<Annotation> metadata, | |
| 120 this.name, this.constants) | |
| 121 : super(documentationComment, metadata); | |
| 122 } | |
| 123 | |
| 124 /// "Mini AST" representation of an expression. | |
| 125 class Expression {} | |
| 126 | |
| 127 /// "Mini AST" representation of an integer literal. | |
| 128 class IntegerLiteral extends Expression { | |
| 129 final int value; | |
| 130 | |
| 131 IntegerLiteral(this.value); | |
| 132 } | |
| 133 | |
| 134 /// "Mini AST" representation of a method declaration. | |
| 135 class MethodDeclaration extends ClassMember { | |
| 136 final bool isGetter; | |
| 137 | |
| 138 final String name; | |
| 139 | |
| 140 final TypeName returnType; | |
| 141 | |
| 142 MethodDeclaration(Comment documentationComment, List<Annotation> metadata, | |
| 143 this.isGetter, this.name, this.returnType) | |
| 144 : super(documentationComment, metadata); | |
| 145 } | |
| 146 | |
| 147 /// Parser listener which generates a "mini AST" representation of the source | |
| 148 /// code. This representation is just sufficient for summary code generation. | |
| 149 class MiniAstBuilder extends StackListener { | |
| 150 bool inMetadata = false; | |
| 151 | |
| 152 final compilationUnit = new CompilationUnit(); | |
| 153 | |
| 154 @override | |
| 155 Uri get uri => null; | |
| 156 | |
| 157 @override | |
| 158 void beginMetadata(Token token) { | |
| 159 inMetadata = true; | |
| 160 } | |
| 161 | |
| 162 @override | |
| 163 void beginMetadataStar(Token token) { | |
| 164 debugEvent("beginMetadataStar"); | |
| 165 if (token.precedingComments != null) { | |
| 166 push(new Comment(token.precedingComments)); | |
| 167 } else { | |
| 168 push(NullValue.Comments); | |
| 169 } | |
| 170 } | |
| 171 | |
| 172 @override | |
| 173 void endArguments(int count, Token beginToken, Token endToken) { | |
| 174 debugEvent("Arguments"); | |
| 175 push(popList(count)); | |
| 176 } | |
| 177 | |
| 178 @override | |
| 179 void endClassBody(int memberCount, Token beginToken, Token endToken) { | |
| 180 debugEvent("ClassBody"); | |
| 181 push(popList(memberCount)); | |
| 182 } | |
| 183 | |
| 184 void endClassDeclaration( | |
| 185 int interfacesCount, | |
| 186 Token beginToken, | |
| 187 Token classKeyword, | |
| 188 Token extendsKeyword, | |
| 189 Token implementsKeyword, | |
| 190 Token endToken) { | |
| 191 debugEvent("ClassDeclaration"); | |
| 192 // ignore: strong_mode_down_cast_composite | |
| 193 List<ClassMember> members = pop(); | |
|
scheglov
2017/03/14 17:22:40
Would this be better?
var members = pop() as List<
Paul Berry
2017/03/14 17:31:36
Personally, I like it better. But IIRC, Peter has
scheglov
2017/03/14 17:35:37
OK
Probably performance is not a concern for gener
| |
| 194 TypeName superclass = pop(); | |
| 195 pop(); // Type variables | |
| 196 String name = pop(); | |
| 197 // ignore: strong_mode_down_cast_composite | |
| 198 List<Annotation> metadata = pop(); | |
| 199 Comment comment = pop(); | |
| 200 compilationUnit.declarations.add( | |
| 201 new ClassDeclaration(comment, metadata, name, superclass, members)); | |
| 202 } | |
| 203 | |
| 204 @override | |
| 205 void endCombinators(int count) { | |
| 206 debugEvent("Combinators"); | |
| 207 } | |
| 208 | |
| 209 @override | |
| 210 void endConditionalUris(int count) { | |
| 211 debugEvent("ConditionalUris"); | |
| 212 if (count != 0) { | |
| 213 internalError('Conditional URIs are not supported by summary codegen'); | |
| 214 } | |
| 215 } | |
| 216 | |
| 217 @override | |
| 218 void endConstructorReference( | |
| 219 Token start, Token periodBeforeName, Token endToken) { | |
| 220 debugEvent("ConstructorReference"); | |
| 221 String constructorName = popIfNotNull(periodBeforeName); | |
| 222 pop(); // Type arguments | |
| 223 String name = pop(); | |
| 224 push(new ConstructorReference(name, constructorName)); | |
| 225 } | |
| 226 | |
| 227 void endEnum(Token enumKeyword, Token endBrace, int count) { | |
| 228 debugEvent("Enum"); | |
| 229 // ignore: strong_mode_down_cast_composite | |
| 230 List<EnumConstantDeclaration> constants = popList(count); | |
| 231 String name = pop(); | |
| 232 // ignore: strong_mode_down_cast_composite | |
| 233 List<Annotation> metadata = pop(); | |
| 234 Comment comment = pop(); | |
| 235 compilationUnit.declarations | |
| 236 .add(new EnumDeclaration(comment, metadata, name, constants)); | |
| 237 } | |
| 238 | |
| 239 @override | |
| 240 void endFactoryMethod( | |
| 241 Token beginToken, Token factoryKeyword, Token endToken) { | |
| 242 debugEvent("FactoryMethod"); | |
| 243 pop(); // Body | |
| 244 ConstructorReference name = pop(); | |
| 245 // ignore: strong_mode_down_cast_composite | |
| 246 List<Annotation> metadata = pop(); | |
| 247 Comment comment = pop(); | |
| 248 push(new ConstructorDeclaration(comment, metadata, name)); | |
| 249 } | |
| 250 | |
| 251 @override | |
| 252 void endFieldInitializer(Token assignment) { | |
| 253 debugEvent("FieldInitializer"); | |
| 254 pop(); // Expression | |
| 255 } | |
| 256 | |
| 257 @override | |
| 258 void endFormalParameter( | |
| 259 Token covariantKeyword, Token thisKeyword, FormalParameterType kind) { | |
| 260 debugEvent("FormalParameter"); | |
| 261 pop(); // Name | |
| 262 pop(); // Type | |
| 263 pop(); // Metadata | |
| 264 pop(); // Comment | |
| 265 } | |
| 266 | |
| 267 @override | |
| 268 void endFormalParameters(int count, Token beginToken, Token endToken) { | |
| 269 debugEvent("FormalParameters"); | |
| 270 } | |
| 271 | |
| 272 @override | |
| 273 void endIdentifierList(int count) { | |
| 274 debugEvent("IdentifierList"); | |
| 275 push(popList(count)); | |
| 276 } | |
| 277 | |
| 278 @override | |
| 279 void endImport(Token importKeyword, Token deferredKeyword, Token asKeyword, | |
| 280 Token semicolon) { | |
| 281 debugEvent("Import"); | |
| 282 popIfNotNull(asKeyword); // Prefix identifier | |
| 283 pop(); // URI | |
| 284 pop(); // Metadata | |
| 285 pop(); // Comment | |
| 286 } | |
| 287 | |
| 288 @override | |
| 289 void endLibraryName(Token libraryKeyword, Token semicolon) { | |
| 290 debugEvent("LibraryName"); | |
| 291 pop(); // Library name | |
| 292 pop(); // Metadata | |
| 293 pop(); // Comment | |
| 294 } | |
| 295 | |
| 296 @override | |
| 297 void endLiteralString(int interpolationCount, Token endToken) { | |
| 298 super.endLiteralString(interpolationCount, endToken); | |
| 299 String value = pop(); | |
| 300 push(new StringLiteral(value)); | |
| 301 } | |
| 302 | |
| 303 @override | |
| 304 void endMember() { | |
| 305 debugEvent("Member"); | |
| 306 } | |
| 307 | |
| 308 @override | |
| 309 void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) { | |
| 310 debugEvent("Metadata"); | |
| 311 inMetadata = false; | |
| 312 // ignore: strong_mode_down_cast_composite | |
| 313 List<Expression> arguments = pop(); | |
| 314 String constructorName = popIfNotNull(periodBeforeName); | |
| 315 pop(); // Type arguments | |
| 316 String name = pop(); | |
| 317 push(new Annotation(name, constructorName, arguments)); | |
| 318 } | |
| 319 | |
| 320 @override | |
| 321 void endMetadataStar(int count, bool forParameter) { | |
| 322 debugEvent("MetadataStar"); | |
| 323 push(popList(count) ?? NullValue.Metadata); | |
| 324 } | |
| 325 | |
| 326 void endMethod(Token getOrSet, Token beginToken, Token endToken) { | |
| 327 debugEvent("Method"); | |
| 328 pop(); // Body | |
| 329 pop(); // Initializers | |
| 330 pop(); // Formal parameters | |
| 331 pop(); // Type variables | |
| 332 String name = pop(); | |
| 333 TypeName returnType = pop(); | |
| 334 // ignore: strong_mode_down_cast_composite | |
| 335 List<Annotation> metadata = pop(); | |
| 336 Comment comment = pop(); | |
| 337 push(new MethodDeclaration( | |
| 338 comment, metadata, getOrSet?.lexeme == 'get', name, returnType)); | |
| 339 } | |
| 340 | |
| 341 @override | |
| 342 void endSend(Token beginToken, Token endToken) { | |
| 343 debugEvent("Send"); | |
| 344 // ignore: strong_mode_down_cast_composite | |
| 345 pop(); // Arguments | |
| 346 pop(); // Type arguments | |
| 347 pop(); // Receiver | |
| 348 push(new UnknownExpression()); | |
| 349 } | |
| 350 | |
| 351 @override | |
| 352 void endShow(Token showKeyword) { | |
| 353 debugEvent("Show"); | |
| 354 pop(); // Shown names | |
| 355 } | |
| 356 | |
| 357 @override | |
| 358 void endTopLevelFields(int count, Token beginToken, Token endToken) { | |
| 359 // We ignore top level variable declarations; they are present just to make | |
| 360 // the IDL analyze without warnings. | |
| 361 debugEvent("TopLevelFields"); | |
| 362 popList(count); // Fields | |
| 363 pop(); // Type | |
| 364 pop(); // Metadata | |
| 365 pop(); // Comment | |
| 366 } | |
| 367 | |
| 368 @override | |
| 369 void endTypeArguments(int count, Token beginToken, Token endToken) { | |
| 370 debugEvent("TypeArguments"); | |
| 371 push(popList(count)); | |
| 372 } | |
| 373 | |
| 374 @override | |
| 375 void handleAsyncModifier(Token asyncToken, Token starToken) { | |
| 376 debugEvent("AsyncModifier"); | |
| 377 } | |
| 378 | |
| 379 @override | |
| 380 void handleBinaryExpression(Token token) { | |
| 381 debugEvent("BinaryExpression"); | |
| 382 pop(); // RHS | |
| 383 pop(); // LHS | |
| 384 push(new UnknownExpression()); | |
| 385 } | |
| 386 | |
| 387 @override | |
| 388 void handleFormalParameterWithoutValue(Token token) { | |
| 389 debugEvent("FormalParameterWithoutValue"); | |
| 390 } | |
| 391 | |
| 392 @override | |
| 393 void handleFunctionBodySkipped(Token token, bool isExpressionBody) { | |
| 394 if (isExpressionBody) pop(); | |
| 395 push(NullValue.FunctionBody); | |
| 396 } | |
| 397 | |
| 398 void handleIdentifier(Token token, IdentifierContext context) { | |
| 399 if (context == IdentifierContext.enumValueDeclaration) { | |
| 400 var comment = new Comment(token.precedingComments); | |
| 401 push(new EnumConstantDeclaration(comment, null, token.lexeme)); | |
| 402 } else { | |
| 403 push(token.lexeme); | |
| 404 } | |
| 405 } | |
| 406 | |
| 407 void handleLiteralInt(Token token) { | |
| 408 debugEvent("LiteralInt"); | |
| 409 push(new IntegerLiteral(int.parse(token.lexeme))); | |
| 410 } | |
| 411 | |
| 412 void handleLiteralNull(Token token) { | |
| 413 debugEvent("LiteralNull"); | |
| 414 push(new UnknownExpression()); | |
| 415 } | |
| 416 | |
| 417 @override | |
| 418 void handleModifier(Token token) { | |
| 419 debugEvent("Modifier"); | |
| 420 } | |
| 421 | |
| 422 @override | |
| 423 void handleModifiers(int count) { | |
| 424 debugEvent("Modifiers"); | |
| 425 } | |
| 426 | |
| 427 @override | |
| 428 void handleQualified(Token period) { | |
| 429 debugEvent("Qualified"); | |
| 430 String suffix = pop(); | |
| 431 String prefix = pop(); | |
| 432 push('$prefix.$suffix'); | |
| 433 } | |
| 434 | |
| 435 @override | |
| 436 void handleType(Token beginToken, Token endToken) { | |
| 437 debugEvent("Type"); | |
| 438 // ignore: strong_mode_down_cast_composite | |
| 439 List<TypeName> typeArguments = pop(); | |
| 440 String name = pop(); | |
| 441 push(new TypeName(name, typeArguments)); | |
| 442 } | |
| 443 } | |
| 444 | |
| 445 /// Parser intended for use with [MiniAstBuilder]. | |
| 446 class MiniAstParser extends Parser { | |
| 447 MiniAstParser(MiniAstBuilder listener) : super(listener); | |
| 448 | |
| 449 Token parseArgumentsOpt(Token token) { | |
| 450 MiniAstBuilder listener = this.listener; | |
| 451 if (listener.inMetadata) { | |
| 452 return super.parseArgumentsOpt(token); | |
| 453 } else { | |
| 454 return skipArgumentsOpt(token); | |
| 455 } | |
| 456 } | |
| 457 | |
| 458 Token parseFunctionBody(Token token, bool isExpression, bool allowAbstract) { | |
| 459 return skipFunctionBody(token, isExpression, allowAbstract); | |
| 460 } | |
| 461 } | |
| 462 | |
| 463 /// "Mini AST" representation of a string literal. | |
| 464 class StringLiteral extends Expression { | |
| 465 final String stringValue; | |
| 466 | |
| 467 StringLiteral(this.stringValue); | |
| 468 } | |
| 469 | |
| 470 /// "Mini AST" representation of a type name. | |
| 471 class TypeName { | |
| 472 final String name; | |
| 473 | |
| 474 final List<TypeName> typeArguments; | |
| 475 | |
| 476 TypeName(this.name, this.typeArguments); | |
| 477 } | |
| 478 | |
| 479 /// "Mini AST" representation of an expression which summary code generation | |
| 480 /// need not be concerned about. | |
| 481 class UnknownExpression extends Expression {} | |
| OLD | NEW |