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.outline_builder; |
| 6 |
| 7 import 'package:kernel/ast.dart' show |
| 8 AsyncMarker, |
| 9 ProcedureKind; |
| 10 |
| 11 import 'package:dart_parser/src/parser.dart' show |
| 12 FormalParameterType, |
| 13 optional; |
| 14 |
| 15 import 'package:dart_scanner/src/token.dart' show |
| 16 Token; |
| 17 |
| 18 import '../combinator.dart' show |
| 19 Combinator; |
| 20 |
| 21 import '../errors.dart' show |
| 22 internalError; |
| 23 |
| 24 import '../builder/builder.dart'; |
| 25 |
| 26 import '../modifier.dart' show |
| 27 Modifier; |
| 28 |
| 29 import 'source_library_builder.dart' show |
| 30 SourceLibraryBuilder; |
| 31 |
| 32 import 'unhandled_listener.dart' show |
| 33 NullValue, |
| 34 Unhandled, |
| 35 UnhandledListener; |
| 36 |
| 37 enum MethodBody { |
| 38 Abstract, |
| 39 Regular, |
| 40 RedirectingFactoryBody, |
| 41 } |
| 42 |
| 43 AsyncMarker asyncMarkerFromTokens(Token asyncToken, Token starToken) { |
| 44 if (asyncToken == null || identical(asyncToken.stringValue, "sync")) { |
| 45 if (starToken == null) { |
| 46 return AsyncMarker.Sync; |
| 47 } else { |
| 48 assert(identical(starToken.stringValue, "*")); |
| 49 return AsyncMarker.SyncStar; |
| 50 } |
| 51 } else if (identical(asyncToken.stringValue, "async")) { |
| 52 if (starToken == null) { |
| 53 return AsyncMarker.Async; |
| 54 } else { |
| 55 assert(identical(starToken.stringValue, "*")); |
| 56 return AsyncMarker.AsyncStar; |
| 57 } |
| 58 } else { |
| 59 return internalError("Unknown async modifier: $asyncToken"); |
| 60 } |
| 61 } |
| 62 |
| 63 class OutlineBuilder extends UnhandledListener { |
| 64 final SourceLibraryBuilder library; |
| 65 |
| 66 OutlineBuilder(this.library); |
| 67 |
| 68 Uri get uri => library.uri; |
| 69 |
| 70 void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) { |
| 71 debugEvent("Metadata"); |
| 72 List arguments = pop(); |
| 73 String postfix = popIfNotNull(periodBeforeName); |
| 74 List<TypeBuilder> typeArguments = pop(); |
| 75 if (arguments == null) { |
| 76 String expression = pop(); |
| 77 push(new MetadataBuilder.fromExpression(expression, postfix)); |
| 78 } else { |
| 79 String typeName = pop(); |
| 80 push(new MetadataBuilder.fromConstructor( |
| 81 library.addConstructorReference( |
| 82 typeName, typeArguments, postfix), arguments)); |
| 83 } |
| 84 } |
| 85 |
| 86 void endHide(Token hideKeyword) { |
| 87 debugEvent("Hide"); |
| 88 List<String> names = pop(); |
| 89 push(new Combinator.hide(names)); |
| 90 } |
| 91 |
| 92 void endShow(Token showKeyword) { |
| 93 debugEvent("Show"); |
| 94 List<String> names = pop(); |
| 95 push(new Combinator.show(names)); |
| 96 } |
| 97 |
| 98 void endCombinators(int count) { |
| 99 debugEvent("Combinators"); |
| 100 push(popList(count) ?? NullValue.Combinators); |
| 101 } |
| 102 |
| 103 void endExport(Token exportKeyword, Token semicolon) { |
| 104 debugEvent("Export"); |
| 105 List<Combinator> combinators = pop(); |
| 106 Unhandled conditionalUris = pop(); |
| 107 String uri = pop(); |
| 108 List<MetadataBuilder> metadata = pop(); |
| 109 library.addExport(metadata, uri, conditionalUris, combinators); |
| 110 checkEmpty(); |
| 111 } |
| 112 |
| 113 void endImport(Token importKeyword, Token deferredKeyword, Token asKeyword, |
| 114 Token semicolon) { |
| 115 debugEvent("endImport"); |
| 116 List<Combinator> combinators = pop(); |
| 117 String prefix = popIfNotNull(asKeyword); |
| 118 Unhandled conditionalUris = pop(); |
| 119 String uri = pop(); |
| 120 List<MetadataBuilder> metadata = pop(); |
| 121 library.addImport(metadata, uri, conditionalUris, prefix, combinators, |
| 122 deferredKeyword != null); |
| 123 checkEmpty(); |
| 124 } |
| 125 |
| 126 void endPart(Token partKeyword, Token semicolon) { |
| 127 debugEvent("Part"); |
| 128 String uri = pop(); |
| 129 List<MetadataBuilder> metadata = pop(); |
| 130 library.addPart(metadata, uri); |
| 131 checkEmpty(); |
| 132 } |
| 133 |
| 134 void handleOperatorName(Token operatorKeyword, Token token) { |
| 135 debugEvent("OperatorName"); |
| 136 push(token.stringValue); |
| 137 } |
| 138 |
| 139 void endIdentifierList(int count) { |
| 140 debugEvent("endIdentifierList"); |
| 141 push(popList(count) ?? NullValue.IdentifierList); |
| 142 } |
| 143 |
| 144 void handleQualified(Token period) { |
| 145 debugEvent("handleQualified"); |
| 146 String name = pop(); |
| 147 String receiver = pop(); |
| 148 push("$receiver.$name"); |
| 149 } |
| 150 |
| 151 void endLibraryName(Token libraryKeyword, Token semicolon) { |
| 152 debugEvent("endLibraryName"); |
| 153 String name = pop(); |
| 154 List<MetadataBuilder> metadata = pop(); |
| 155 library.name = name; |
| 156 library.metadata = metadata; |
| 157 } |
| 158 |
| 159 void beginClassDeclaration(Token token) { |
| 160 library.beginNestedScope(); |
| 161 } |
| 162 |
| 163 void endClassDeclaration(int interfacesCount, Token beginToken, |
| 164 Token extendsKeyword, Token implementsKeyword, Token endToken) { |
| 165 debugEvent("endClassDeclaration"); |
| 166 List<TypeBuilder> interfaces = popList(interfacesCount); |
| 167 TypeBuilder supertype = pop(); |
| 168 List<TypeVariableBuilder> typeVariables = pop(); |
| 169 String name = pop(); |
| 170 int modifiers = Modifier.validate(pop()); |
| 171 List<MetadataBuilder> metadata = pop(); |
| 172 library.addClass( |
| 173 metadata, modifiers, name, typeVariables, supertype, interfaces); |
| 174 checkEmpty(); |
| 175 } |
| 176 |
| 177 ProcedureKind computeProcedureKind(Token token) { |
| 178 if (token == null) return ProcedureKind.Method; |
| 179 if (optional("get", token)) return ProcedureKind.Getter; |
| 180 if (optional("set", token)) return ProcedureKind.Setter; |
| 181 return internalError("Unhandled: ${token.value}"); |
| 182 } |
| 183 |
| 184 ProcedureBuilder endTopLevelMethod( |
| 185 Token beginToken, Token getOrSet, Token endToken) { |
| 186 debugEvent("endTopLevelMethod"); |
| 187 MethodBody kind = pop(); |
| 188 AsyncMarker asyncModifier = pop(); |
| 189 List<FormalParameterBuilder> formals = pop(); |
| 190 List<TypeVariableBuilder> typeVariables = pop(); |
| 191 String name = pop(); |
| 192 TypeBuilder returnType = pop(); |
| 193 int modifiers = Modifier.validate(pop(), |
| 194 isAbstract: kind == MethodBody.Abstract); |
| 195 List<MetadataBuilder> metadata = pop(); |
| 196 checkEmpty(); |
| 197 return library.addProcedure(metadata, modifiers, returnType, name, |
| 198 typeVariables, formals, asyncModifier, computeProcedureKind(getOrSet)); |
| 199 } |
| 200 |
| 201 void handleNoFunctionBody(Token token) { |
| 202 debugEvent("NoFunctionBody"); |
| 203 push(MethodBody.Abstract); |
| 204 } |
| 205 |
| 206 void skippedFunctionBody(Token token) { |
| 207 debugEvent("skippedFunctionBody"); |
| 208 push(MethodBody.Regular); |
| 209 } |
| 210 |
| 211 void endMethod(Token getOrSet, Token beginToken, Token endToken) { |
| 212 debugEvent("Method"); |
| 213 MethodBody kind = pop(); |
| 214 if (kind == MethodBody.RedirectingFactoryBody) { |
| 215 // This will cause an error later. |
| 216 pop(); |
| 217 } |
| 218 AsyncMarker asyncModifier = pop(); |
| 219 List<FormalParameterBuilder> formals = pop(); |
| 220 List<TypeVariableBuilder> typeVariables = pop(); |
| 221 String name = pop(); |
| 222 if (identical("-", name) && formals == null) { |
| 223 name = "unary-"; |
| 224 } |
| 225 TypeBuilder returnType = pop(); |
| 226 int modifiers = Modifier.validate(pop(), |
| 227 isAbstract: kind == MethodBody.Abstract); |
| 228 List<MetadataBuilder> metadata = pop(); |
| 229 library.addProcedure(metadata, modifiers, returnType, name, typeVariables, |
| 230 formals, asyncModifier, computeProcedureKind(getOrSet)); |
| 231 } |
| 232 |
| 233 void endMixinApplication() { |
| 234 debugEvent("MixinApplication"); |
| 235 List<TypeBuilder> mixins = pop(); |
| 236 TypeBuilder supertype = pop(); |
| 237 push(library.addMixinApplication(supertype, mixins)); |
| 238 } |
| 239 |
| 240 void beginNamedMixinApplication(Token token) { |
| 241 library.beginNestedScope(); |
| 242 } |
| 243 |
| 244 void endNamedMixinApplication( |
| 245 Token classKeyword, Token implementsKeyword, Token endToken) { |
| 246 debugEvent("endNamedMixinApplication"); |
| 247 List<TypeBuilder> interfaces = popIfNotNull(implementsKeyword); |
| 248 TypeBuilder mixinApplication = pop(); |
| 249 int modifiers = Modifier.validate(pop()); |
| 250 List<TypeVariableBuilder> typeVariables = pop(); |
| 251 String name = pop(); |
| 252 List<MetadataBuilder> metadata = pop(); |
| 253 library.addNamedMixinApplication( |
| 254 metadata, name, typeVariables, modifiers, mixinApplication, interfaces); |
| 255 checkEmpty(); |
| 256 } |
| 257 |
| 258 void endTypeArguments(int count, Token beginToken, Token endToken) { |
| 259 debugEvent("TypeArguments"); |
| 260 push(popList(count) ?? NullValue.TypeArguments); |
| 261 } |
| 262 |
| 263 void endType(Token beginToken, Token endToken) { |
| 264 debugEvent("Type"); |
| 265 List<TypeBuilder> arguments = pop(); |
| 266 String name = pop(); |
| 267 push(library.addInterfaceType(name, arguments)); |
| 268 } |
| 269 |
| 270 void endTypeList(int count) { |
| 271 debugEvent("TypeList"); |
| 272 push(popList(count) ?? NullValue.TypeList); |
| 273 } |
| 274 |
| 275 void endTypeVariables(int count, Token beginToken, Token endToken) { |
| 276 debugEvent("TypeVariables"); |
| 277 push(popList(count) ?? NullValue.TypeVariables); |
| 278 } |
| 279 |
| 280 void handleVoidKeyword(Token token) { |
| 281 debugEvent("VoidKeyword"); |
| 282 push(library.addVoidType()); |
| 283 } |
| 284 |
| 285 void endFormalParameter(Token thisKeyword) { |
| 286 debugEvent("FormalParameter"); |
| 287 String name = pop(); |
| 288 TypeBuilder type = pop(); |
| 289 int modifiers = Modifier.validate(pop()); |
| 290 List<MetadataBuilder> metadata = pop(); |
| 291 push(library.addFormalParameter(metadata, modifiers, type, name, |
| 292 thisKeyword != null)); |
| 293 } |
| 294 |
| 295 void handleValuedFormalParameter(Token equals, Token token) { |
| 296 debugEvent("ValuedFormalParameter"); |
| 297 // Ignored for now. |
| 298 } |
| 299 |
| 300 void handleFunctionTypedFormalParameter(Token token) { |
| 301 debugEvent("FunctionTypedFormalParameter"); |
| 302 pop(); // Function type parameters. |
| 303 pop(); // Type variables. |
| 304 String name = pop(); |
| 305 pop(); // Return type. |
| 306 push(NullValue.Type); |
| 307 push(name); |
| 308 } |
| 309 |
| 310 void endOptionalFormalParameters( |
| 311 int count, Token beginToken, Token endToken) { |
| 312 debugEvent("OptionalFormalParameters"); |
| 313 FormalParameterType kind = optional("{", beginToken) |
| 314 ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL; |
| 315 List parameters = popList(count); |
| 316 for (FormalParameterBuilder parameter in parameters) { |
| 317 parameter.kind = kind; |
| 318 } |
| 319 push(parameters); |
| 320 } |
| 321 |
| 322 void endFormalParameters(int count, Token beginToken, Token endToken) { |
| 323 debugEvent("FormalParameters"); |
| 324 List formals = popList(count); |
| 325 if (formals != null && formals.isNotEmpty) { |
| 326 var last = formals.last; |
| 327 if (last is List) { |
| 328 var newList = |
| 329 new List<FormalParameterBuilder>(formals.length - 1 + last.length); |
| 330 newList.setRange(0, formals.length - 1, formals); |
| 331 newList.setRange(formals.length - 1, newList.length, last); |
| 332 for (int i = 0; i < last.length; i++) { |
| 333 newList[i + formals.length - 1] = last[i]; |
| 334 } |
| 335 formals = newList; |
| 336 } |
| 337 } |
| 338 if (formals != null) { |
| 339 for (var formal in formals) { |
| 340 if (formal is! FormalParameterBuilder) { |
| 341 internalError(formals); |
| 342 } |
| 343 } |
| 344 formals = new List<FormalParameterBuilder>.from(formals); |
| 345 } |
| 346 push(formals ?? NullValue.FormalParameters); |
| 347 } |
| 348 |
| 349 void endEnum(Token enumKeyword, Token endBrace, int count) { |
| 350 List<String> constants = popList(count); |
| 351 String name = pop(); |
| 352 List<MetadataBuilder> metadata = pop(); |
| 353 library.addEnum(metadata, name, constants); |
| 354 checkEmpty(); |
| 355 } |
| 356 |
| 357 void beginFunctionTypeAlias(Token token) { |
| 358 library.beginNestedScope(); |
| 359 } |
| 360 |
| 361 void endFunctionTypeAlias(Token typedefKeyword, Token endToken) { |
| 362 debugEvent("endFunctionTypeAlias"); |
| 363 List<FormalParameterBuilder> formals = pop(); |
| 364 List<TypeVariableBuilder> typeVariables = pop(); |
| 365 String name = pop(); |
| 366 TypeBuilder returnType = pop(); |
| 367 List<MetadataBuilder> metadata = pop(); |
| 368 library.addFunctionTypeAlias( |
| 369 metadata, returnType, name, typeVariables, formals); |
| 370 checkEmpty(); |
| 371 } |
| 372 |
| 373 void endTopLevelFields(int count, Token beginToken, Token endToken) { |
| 374 debugEvent("endTopLevelFields"); |
| 375 List<String> names = popList(count); |
| 376 TypeBuilder type = pop(); |
| 377 int modifiers = Modifier.validate(pop()); |
| 378 List<MetadataBuilder> metadata = pop(); |
| 379 library.addFields(metadata, modifiers, type, names); |
| 380 checkEmpty(); |
| 381 } |
| 382 |
| 383 void endFields(int count, Token beginToken, Token endToken) { |
| 384 debugEvent("Fields"); |
| 385 List<String> names = popList(count); |
| 386 TypeBuilder type = pop(); |
| 387 int modifiers = Modifier.validate(pop()); |
| 388 List<MetadataBuilder> metadata = pop(); |
| 389 library.addFields(metadata, modifiers, type, names); |
| 390 } |
| 391 |
| 392 void endTypeVariable(Token token, Token extendsOrSuper) { |
| 393 debugEvent("endTypeVariable"); |
| 394 TypeBuilder bound = pop(); |
| 395 String name = pop(); |
| 396 push(library.addTypeVariable(name, bound)); |
| 397 } |
| 398 |
| 399 void endPartOf(Token partKeyword, Token semicolon) { |
| 400 debugEvent("endPartOf"); |
| 401 String name = pop(); |
| 402 List<MetadataBuilder> metadata = pop(); |
| 403 library.addPartOf(metadata, name); |
| 404 } |
| 405 |
| 406 void endConstructorReference( |
| 407 Token start, Token periodBeforeName, Token endToken) { |
| 408 debugEvent("ConstructorReference"); |
| 409 String suffix = popIfNotNull(periodBeforeName); |
| 410 List<TypeBuilder> typeArguments = pop(); |
| 411 String name = pop(); |
| 412 push(library.addConstructorReference(name, typeArguments, suffix)); |
| 413 } |
| 414 |
| 415 void endFactoryMethod(Token beginToken, Token endToken) { |
| 416 debugEvent("FactoryMethod"); |
| 417 MethodBody kind = pop(); |
| 418 ConstructorReferenceBuilder redirectionTarget; |
| 419 if (kind == MethodBody.RedirectingFactoryBody) { |
| 420 redirectionTarget = pop(); |
| 421 } |
| 422 AsyncMarker asyncModifier = pop(); |
| 423 List<FormalParameterBuilder> formals = pop(); |
| 424 var name = pop(); |
| 425 List<MetadataBuilder> metadata = pop(); |
| 426 library.addFactoryMethod(metadata, name, formals, asyncModifier, |
| 427 redirectionTarget); |
| 428 } |
| 429 |
| 430 void endRedirectingFactoryBody(Token beginToken, Token endToken) { |
| 431 debugEvent("RedirectingFactoryBody"); |
| 432 push(MethodBody.RedirectingFactoryBody); |
| 433 } |
| 434 |
| 435 void endInitializer(Token assignmentOperator) { |
| 436 debugEvent("Initializer"); |
| 437 // This is a variable initializer and it's ignored for now. May also be |
| 438 // constructor initializer. |
| 439 } |
| 440 |
| 441 void endInitializers(int count, Token beginToken, Token endToken) { |
| 442 debugEvent("Initializers"); |
| 443 // Ignored for now. |
| 444 } |
| 445 |
| 446 void handleNoInitializers() { |
| 447 debugEvent("NoInitializers"); |
| 448 // This is a constructor initializer and it's ignored for now. |
| 449 } |
| 450 |
| 451 void endMember() { |
| 452 debugEvent("Member"); |
| 453 } |
| 454 |
| 455 void endClassBody(int memberCount, Token beginToken, Token endToken) { |
| 456 debugEvent("ClassBody"); |
| 457 } |
| 458 |
| 459 void handleAsyncModifier(Token asyncToken, Token starToken) { |
| 460 debugEvent("AsyncModifier"); |
| 461 push(asyncMarkerFromTokens(asyncToken, starToken)); |
| 462 } |
| 463 |
| 464 void handleModifier(Token token) { |
| 465 debugEvent("Modifier"); |
| 466 push(new Modifier.fromString(token.stringValue)); |
| 467 } |
| 468 |
| 469 void handleModifiers(int count) { |
| 470 debugEvent("Modifiers"); |
| 471 push(popList(count) ?? NullValue.Modifiers); |
| 472 } |
| 473 |
| 474 void debugEvent(String name) { |
| 475 // printEvent(name); |
| 476 } |
| 477 } |
OLD | NEW |